Home Articles

SystemVerilog / Verilog:有没有办法找到打包结构的字段的整数位偏移量?

Asked
Viewed 896 times
2

我想知道在verilog或systemverilog中是否存在标准函数,它将返回打包结构中某个字段的位偏移量 . 例如,请参阅下面使用假设函数$ find_field_offset:

typedef struct packed
{
    logic [31:0] field_1,
    logic [15:0] field_2,
    logic [63:0] field_3
} struct_type;

struct_type the_struct;
int field_1_offset;
assign field_1_offset = $find_field_offset(the_struct.field_1);

谢谢!

4 Answers

  • 4

    如果你按照自己喜欢的方式调用函数,因为据我所知,编译器失去了 field1 实际上是什么的上下文 . 我的意思是该函数会看到一个逻辑向量值,但不知道它来自一个结构 .

    如果您可以将函数调用更改为:

    $find_field_offset(the_struct, "field1"); // note "field1" in quotes
    

    那么从技术上讲,可能会发现 the_struct 的类型为 struct_type 并遍历其所有字段以查找名为 "field1" 的字段并返回其偏移量 .

    使用VPI代码的问题在于VPI对象模型的支持因供应商而异 . 您必须足够幸运地使用支持我们在此需要的功能的供应商 .

  • 1

    它没有任何变量 . 您只需将值传入该方法,编译器就无法确定您希望在 struct_type 中获得 field1 的偏移量 .

    使用 native SystemVerilog可以做的最好的事情是定义自己的函数,该函数根据枚举参数返回偏移量 . 脱离我的头顶:

    typedef enum { FIELD1, FIELD2, FIELD3 } struct_type_fields_e;
    
    function int unsigned get_offset(struct_type_fields_e field);
      case (field)
        FIELD1 : return 0;
        FIELD2 : return 32;
        FIELD3 : return 48;
      endcase
    endfunction
    

    您可以使用某些VPI代码执行更多操作,但您需要更改调用函数的方式 .

  • 0

    这可能不是一个好的方便的方式 . 但这是本机SV代码,找出 struct_type 内的偏移量 field_1

    function automatic int get_offset_struct_type_field_1;
      struct_type x = '0;
      x.field_1 = '1;
      for (integer i = 0; i < $bits(x); i=i+1) begin
        if (x[i] == 1) return i;
      end
    endfunction
    
  • 0

    谢谢你的例子 . 下面是一些迂腐的检查和消息,以确认某些层次结构的所有字段的偏移量和大小 . char_idx是结构中半字节的字符位置,如果从$ writememh或类似字符串中读取为字符串 . 在初始块内调用此taks以确认下游解析将能够正确解释十六进制表示 .

    task report_offsets(
    );
        phy_mon_info_s tr;
        integer char_idx;
    
        $display("tr is made of %0d bits",$bits(tr));
        for (integer idx = 0;idx< $bits(tr);idx++) begin
            char_idx = ($bits(tr) - idx - 1) >> 2;
            tr = 1'b1 << idx;
            if (|tr.inst > 0)                  $display("tr.inst claims bit %0d hex char %0d"                ,idx, char_idx);
            if (|tr.clock_count)               $display("tr.clock_count claims bit %0d hex char %0d"         ,idx, char_idx);
            if (|tr.phy_info.dir)              $display("tr.phy_info.dir claims bit %0d hex char %0d"        ,idx, char_idx);
            if (|tr.phy_info.data_type)        $display("tr.phy_info.data_type claims bit %0d hex char %0d"  ,idx, char_idx);
            for (int inner = 0;inner< PHY_MON_FRAME_DWS;inner++) begin
               if (|tr.phy_info.header[inner]) $display("tr.phy_info.header[%0d] claims bit %0d hex char %0d",inner,idx, char_idx);
            end
            if (|tr.phy_info.payload_dws)      $display("tr.phy_info.payload_dws claims bit %0d hex char %0d",idx, char_idx);
            if (|tr.phy_info.prim)             $display("tr.phy_info.prim claims bit %0d hex char %0d"       ,idx, char_idx);
            if (|tr.phy_info.num_prims)        $display("tr.phy_info.num_prims claims bit %0d hex char %0d"  ,idx, char_idx);
            if (|tr.phy_clock)                 $display("tr.phy_info.phy_clk claims bit %0d hex char %0d"    ,idx, char_idx);
        end
    
        assert($bits(tr.inst                 ) % 4 == 0) else $error("total bits in tr.inst                 %0d is not a multiple of 4!",$bits(tr.inst                 ));
        assert($bits(tr.clock_count          ) % 4 == 0) else $error("total bits in tr.clock_count          %0d is not a multiple of 4!",$bits(tr.clock_count          ));
        assert($bits(tr.phy_info.dir         ) % 4 == 0) else $error("total bits in tr.phy_info.dir         %0d is not a multiple of 4!",$bits(tr.phy_info.dir         ));
        assert($bits(tr.phy_info.data_type   ) % 4 == 0) else $error("total bits in tr.phy_info.data_type   %0d is not a multiple of 4!",$bits(tr.phy_info.data_type   ));
        assert($bits(tr.phy_info.header      ) % 4 == 0) else $error("total bits in tr.phy_info.header      %0d is not a multiple of 4!",$bits(tr.phy_info.header      ));
        assert($bits(tr.phy_info.payload_dws ) % 4 == 0) else $error("total bits in tr.phy_info.payload_dws %0d is not a multiple of 4!",$bits(tr.phy_info.payload_dws ));
        assert($bits(tr.phy_info.prim        ) % 4 == 0) else $error("total bits in tr.phy_info.prim        %0d is not a multiple of 4!",$bits(tr.phy_info.prim        ));
        assert($bits(tr.phy_info.num_prims   ) % 4 == 0) else $error("total bits in tr.phy_info.num_prims   %0d is not a multiple of 4!",$bits(tr.phy_info.num_prims   ));
        assert($bits(tr.phy_clock            ) % 4 == 0) else $error("total bits in tr.phy_clock            %0d is not a multiple of 4!",$bits(tr.phy_clock            ));
        assert($bits(tr                      ) % 4 == 0) else $error("total bits in tr                      %0d is not a multiple of 4!",$bits(tr                      ));
    endtask
    

Related