'type' 两个不同行列式字段之间的约束
'type' constraint between two different determinant fields
我在 e 中阅读了有关 'type' 约束的主题。我看到可以限制结构字段的类型,如本例所示:
extend DATA packet {
keep type header is a COP header;
};
这意味着每当我处理 DATA 数据包 时,我不需要将 header 转换为 COP header 因为编译器为我假设了这个。
我尝试使用 'type' 约束来绑定两个不同的行列式字段。例如,假设我们有一个 instruction struct,其中包含一个 kind 字段,该字段对操作码进行编码和一个 format 字段,用于确定指令采用的参数:
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;
};
例如,RRR 格式需要以下参数:
type register_e : [ R0, R1, R2, R3 ] (bits:4);
extend RRR instruction {
rd : register_e;
rs1 : register_e;
rs2 : register_e;
};
ADD 指令就是这种格式。如果我只使用一个简单的约束来将 ADD 与 RRR 格式联系起来,比如 keep kind == ADD => format == RRR
,那么要约束一个参数ADD,我需要执行以下操作:
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;
};
};
因为参数是在 RRR 子类型下定义的,所以我需要明确地转换为它。这很烦人,因为我总是需要查找每条指令的格式。只需要强制转换为 ADD 指令.
会更自然
我曾尝试为此目的使用 'type' 约束,但没有成功。如果我写以下内容:
extend ADD instruction {
keep type me is a RRR instruction;
};
我收到以下错误消息:
*** Error: Type constraints may only be put on fields of this struct
如果我这样写:
extend ADD instruction {
keep type format == RRR;
};
我收到不同的错误消息:
*** Error: Type constraints may only equate a property (enum field) of
the context struct with that of an associated struct
第二个错误明确禁止我尝试做的事情,但第一个错误允许解释空间。
我可以将参数提取到自己的结构中:
struct instruction_args {
const format : format_e;
};
extend RRR instruction_args {
rd : register_e;
rs1 : register_e;
rs2 : register_e;
};
并设置 'type' 约束,如文档中所示:
extend instruction {
when ADD { keep type args is a RRR instruction_args };
};
但现在在约束时我总是需要在每个参数前加上 .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;
};
};
这在编写约束时没什么大不了的,但是在打印时,args
的内容不会被打印出来。这是一个可以接受的解决方法,但我仍然对最初的想法感兴趣。
是否可以关联同一 struct 中的 when 子类型,但我只是没有使用正确的语法?
原则上,当事先知道every ADD instruction
实际上是一个ADD RRR instruction
,希望编译器自动处理每一个声明的类型的变量或表达式更具体(允许访问更具体类型的成员而无需强制转换),那么您可以简单地首先使用更具体的类型进行任何此类声明。
当这不是先验知识时,不幸的是我没有看到任何更好的通用方法来实现这一点。部分解决方法可能是定义一个 <type>
宏,它将 ADD instruction
转换为 ADD RRR instruction
,但您需要非常仔细地定义此宏,因为它应该捕获确切使用的语法(例如例如,如果你想让它同时捕获短的和完整的when-qualifiers,你需要相应地定义它)。您可以尝试制作宏 define as computed
并在其代码中使用反射 API 来涵盖各种情况。
我在 e 中阅读了有关 'type' 约束的主题。我看到可以限制结构字段的类型,如本例所示:
extend DATA packet {
keep type header is a COP header;
};
这意味着每当我处理 DATA 数据包 时,我不需要将 header 转换为 COP header 因为编译器为我假设了这个。
我尝试使用 'type' 约束来绑定两个不同的行列式字段。例如,假设我们有一个 instruction struct,其中包含一个 kind 字段,该字段对操作码进行编码和一个 format 字段,用于确定指令采用的参数:
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;
};
例如,RRR 格式需要以下参数:
type register_e : [ R0, R1, R2, R3 ] (bits:4);
extend RRR instruction {
rd : register_e;
rs1 : register_e;
rs2 : register_e;
};
ADD 指令就是这种格式。如果我只使用一个简单的约束来将 ADD 与 RRR 格式联系起来,比如 keep kind == ADD => format == RRR
,那么要约束一个参数ADD,我需要执行以下操作:
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;
};
};
因为参数是在 RRR 子类型下定义的,所以我需要明确地转换为它。这很烦人,因为我总是需要查找每条指令的格式。只需要强制转换为 ADD 指令.
会更自然我曾尝试为此目的使用 'type' 约束,但没有成功。如果我写以下内容:
extend ADD instruction {
keep type me is a RRR instruction;
};
我收到以下错误消息:
*** Error: Type constraints may only be put on fields of this struct
如果我这样写:
extend ADD instruction {
keep type format == RRR;
};
我收到不同的错误消息:
*** Error: Type constraints may only equate a property (enum field) of
the context struct with that of an associated struct
第二个错误明确禁止我尝试做的事情,但第一个错误允许解释空间。
我可以将参数提取到自己的结构中:
struct instruction_args {
const format : format_e;
};
extend RRR instruction_args {
rd : register_e;
rs1 : register_e;
rs2 : register_e;
};
并设置 'type' 约束,如文档中所示:
extend instruction {
when ADD { keep type args is a RRR instruction_args };
};
但现在在约束时我总是需要在每个参数前加上 .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;
};
};
这在编写约束时没什么大不了的,但是在打印时,args
的内容不会被打印出来。这是一个可以接受的解决方法,但我仍然对最初的想法感兴趣。
是否可以关联同一 struct 中的 when 子类型,但我只是没有使用正确的语法?
原则上,当事先知道every ADD instruction
实际上是一个ADD RRR instruction
,希望编译器自动处理每一个声明的类型的变量或表达式更具体(允许访问更具体类型的成员而无需强制转换),那么您可以简单地首先使用更具体的类型进行任何此类声明。
当这不是先验知识时,不幸的是我没有看到任何更好的通用方法来实现这一点。部分解决方法可能是定义一个 <type>
宏,它将 ADD instruction
转换为 ADD RRR instruction
,但您需要非常仔细地定义此宏,因为它应该捕获确切使用的语法(例如例如,如果你想让它同时捕获短的和完整的when-qualifiers,你需要相应地定义它)。您可以尝试制作宏 define as computed
并在其代码中使用反射 API 来涵盖各种情况。