24.6.20 Computed Fields

A computed field declaration in a struct or union type has the form:

computed field_type field_name;

Where field_type is a type specifier denoting the type of the computed field, and field_name is an identifier. Note that, unlike regular fields, computed fields cannot have endianness annotations, constraints defined for them, cannot be optional, nor have initialization values.

Computed fields are not really stored in the corresponding struct values: their value is computed every time they are referred, by invoking a couple of methods that the user should define:

For example, consider the following struct denoting a RISC-V instruction where the immediate is distributed in several chunks:

type RV32_InsnFmt_J = struct uint<32>
  {
    uint<1>   imm20;
    uint<10>  imm10_1;
    uint<1>   imm11;
    uint<8>   imm19_12;
    RV_Reg    rd;
    RV_Opcode opcode : opcode in RV_OPCODES_J;

    computed int<32> imm;

    method get_imm = int<32>:
    {
      return imm20:::imm19_12:::imm11:::imm10_1:::(0 as int<1>) as int<21>;
    }

    method set_imm = (int<32> imm) void:
    {
      imm20 = (imm .>> 20) & 1;
      imm10_1 = (imm .>> 19) & 0x3ff;
      imm11 = (imm .>> 10) & 1;
      imm19_12 = (imm .>> 19) & 0xff;
    }
 };

When we create a value of type RV32_InsnFmt_J we can then externally access the computed field imm like any other normal field. However, computed fields are not accessible in other struct methods, functions, constraint expressions and the like.