I've read up on the topic of 'type' constraints in e. I saw that it's possible to constrain the types of struct fields, like in this example:
extend DATA packet {
keep type header is a COP header;
};
This means that whenever I'm dealing with a DATA packet, I don't need to cast header to COP header as the compiler assumes this for me.
I've tried to use a 'type' constraint to tie two different determinant fields. For example, let's say that we have an instruction struct that contains a kind field that encodes the opcode and a format field that determines what arguments the instruction takes:
type instruction_kind : [ ADD, SUB, JMP, BE ] (bits:4);
type format_e : [ RRR, RI, RRI ];
struct instruction {
const kind : instruction_kind;
const format : format_e;
};
For example, the RRR format requires the following arguments:
type register_e : [ R0, R1, R2, R3 ] (bits:4);
extend RRR instruction {
rd : register_e;
rs1 : register_e;
rs2 : register_e;
};
An ADD instruction would be of this format. If I only use a simple constraint to tie the ADD with the RRR format, like keep kind == ADD => format == RRR
, then to constrain the arguments of an ADD, I'd need to do the following:
extend sys {
run() is also {
var instr : instruction;
gen instr keeping {
it is a ADD RRR instruction (add) and all of {
add.rd == R3;
add.rs1 == R1;
add.rs2 == R2;
};
};
print instr;
};
};
Because the arguments are defined under the RRR sub-type, I need to cast to it explicitly. This is rather annoying, because I always need to look up what format each instruction is. It would have been more natural to only have to cast to ADD instruction.
I've tried to use 'type' constraints for this purpose, but without success. If I write the following:
extend ADD instruction {
keep type me is a RRR instruction;
};
I get the following error message:
*** Error: Type constraints may only be put on fields of this struct
If I write it like this:
extend ADD instruction {
keep type format == RRR;
};
I get a different error message:
*** Error: Type constraints may only equate a property (enum field) of
the context struct with that of an associated struct
The second error expressly forbids what I'm trying to do, but the first one allows room for interpretation.
I can just extract the arguments into an own struct:
struct instruction_args {
const format : format_e;
};
extend RRR instruction_args {
rd : register_e;
rs1 : register_e;
rs2 : register_e;
};
and set 'type' constraints as shown in the documentation:
extend instruction {
when ADD { keep type args is a RRR instruction_args };
};
but now when constraining I always need to prefix every argument with .args:
extend sys {
run() is also {
var instr : instruction;
gen instr keeping {
it is a ADD instruction (add) and all of {
add.args.rd == R3;
add.args.rs1 == R1;
add.args.rs2 == R2;
};
};
print instr;
};
};
This isn't a big deal when writing the constraints, but when printing, the contents of args
don't get printed. It's an acceptable work-around, but I'm still interested in the initial idea.
Would correlating the when subtypes in the same struct be possible, but I just didn't use the proper syntax?