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

时间:2014-07-16 22:11:44

标签: function struct verilog offset system-verilog

我想知道在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 个答案:

答案 0 :(得分:4)

这可能不是一个好方便的方式。但这是本地SV代码,用于找出field_1

中的偏移量struct_type
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

答案 1 :(得分:1)

感谢您的示例。下面是一些迂腐的检查和消息,以确认一些分层结构的所有字段的偏移量和大小。 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

答案 2 :(得分:0)

拥有一个以您呈现的形式返回此功能的函数并没有多大意义。原因是你没有任何变量。您只需将值传入该方法,编译器就无法确定您希望在field1中获得struct_type的偏移量。

使用 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代码执行更多操作,但您需要更改调用函数的方式。

答案 3 :(得分:0)

如果您对使用VPI感到满意,那么您可以通过一些类型的内省来做您想做的事情。这个问题是你不能以你喜欢的方式调用这个函数,因为据我所知,编译器失去了field1实际上是什么的上下文。我的意思是该函数会看到一个逻辑向量值,但不知道它来自一个结构。

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

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

然后在技术上可以确定the_structstruct_type类型并遍历其所有字段以查找名为"field1"的字段并返回其偏移量。

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