'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 指令就是这种格式。如果我只使用一个简单的约束来将 ADDRRR 格式联系起来,比如 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 来涵盖各种情况。