我想知道在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);
谢谢!
答案 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_struct
是struct_type
类型并遍历其所有字段以查找名为"field1"
的字段并返回其偏移量。
使用VPI代码的问题在于VPI对象模型的支持因供应商而异。您必须足够幸运地使用支持我们在此需要的功能的供应商。