System verilog 如何定义跨两个寄存器的字段的后门访问?

System verilog 如何定义跨两个寄存器的字段的后门访问?,system-verilog,uvm,System Verilog,Uvm,我有一个寄存器映射,它有16位宽的寄存器。我有一个大于16位宽的字段,因此它必须跨越两个地址。如何定义此字段的后门访问权限 这就是我为我的字段测试模式[23:0]所做的尝试: register_a.add_hdl_path_slice("path.to.regmap.test_pattern[15:0]", 0, 16); register_b.add_hdl_path_slice("path.to.regmap.test_pattern[23:16]", 0, 8); 此操作失败,出现以下错

我有一个寄存器映射,它有16位宽的寄存器。我有一个大于16位宽的字段,因此它必须跨越两个地址。如何定义此字段的后门访问权限

这就是我为我的字段
测试模式[23:0]
所做的尝试:

register_a.add_hdl_path_slice("path.to.regmap.test_pattern[15:0]", 0, 16);
register_b.add_hdl_path_slice("path.to.regmap.test_pattern[23:16]", 0, 8);
此操作失败,出现以下错误:

错误:VPI TYPERR vpi_handle_by_name()无法获取零件选择的句柄

不清楚这是否是我的工具的约束,或者是UVM代码如何使用VPI的约束。在探索UVM代码之后,我看到了应该处理零件选择的代码,但是它在
#ifdef QUESTA
指令中,所以我认为这是一个工具约束

是否有一个很好的解决方法?

根据:


可能的替代方案是,在for循环中选择位:

for (int i=0; i<16; i++) begin
  string tmp_path_s;
  tmp_path_s = $sformatf("path.to.regmap.test_pattern[%0d]", i);
  register_a.add_hdl_path_slice(tmp_path_s, i, 1);
end
for (int i=0; i<8; i++) begin
  string tmp_path_s;
  tmp_path_s = $sformatf("path.to.regmap.test_pattern[%0d]", i+16);
  register_a.add_hdl_path_slice(tmp_path_s, i, 1);
end

for(int i=0;i很遗憾,不管是谁贡献了这段代码(大概是Mentor?)都觉得有必要在
ifdefs
中包装的通用库中添加一个有用的功能。事实上,在
UVM_1_2
分支中,整个DPI/PLI接口文件被拆分为特定于模拟器的实现,情况更糟

查看git://git.code.sf.net/p/uvm/code 看起来唯一的QUESTA特定代码是此函数:

static int uvm_hdl_set_vlog_partsel(char *path, p_vpi_vecval value, PLI_INT32 flag);
static int uvm_hdl_get_vlog_partsel(char *path, p_vpi_vecval value, PLI_INT32 flag);
它使用以下DPI定义的值:

svLogic logic_bit;
svGetBitselLogic(&bit_value,0);
svLogicVecVal bit_value;
svGetPartselLogic(&bit_value,value,i,1);
svPutPartselLogic(value,bit_value,i,1);
理论上,如果您的模拟器和导师代码都符合标准,您可以删除
ifdef
,它应该仍然可以工作

您还可以通过检测路径中的部件选择并使用
vpi\u handle\u by\u index
来读取各个位,这在任何模拟器中都应该得到支持


注意:我最初的回答是错误的,因为代码是特定于Mentor的-感谢@dave_59让我直截了当,并向Mentor道歉。

你为什么不将其拆分为2个寄存器?因为你的寄存器大小是16位,所以声明一个大于此值的寄存器是没有意义的

我看到这样定义的大型字段的方式是声明两个寄存器,每个寄存器中有一个单独的字段。例如,如果您需要一个32位指针,您可以:

地址高,带16位字段 添加16位字段的低电平


为方便起见,您可以添加一个按顺序访问两者的任务。

不幸的是,我认为偏移量指的是寄存器中的偏移量,而不是字段。您可能希望让UVM开发人员了解这个问题:这些都是在IEEE 1800-2012 LRM的DPI部分中定义的,比使用PLI更有效。请确保你的手指指向了正确的方向。@dave_59关于DPI的观点很正确-但我的主要观点仍然站得住脚-添加功能(这不仅仅是特定于模拟器的解决方法)用
ifdef包装的我的u模拟器
不是构建UVM的好方法,在uvm1.2中它只会变得更糟。如果它符合标准,为什么要使用
ifdef
?如果DPI更有效,为什么还要使用PLI?@dave_59道歉,感谢你指出我的错误。我现在更新了我的答案。因为你参与了UVM公司委员会是否可以建议其他模拟器供应商实现相同的功能(可能是通过将代码复制粘贴到他们的文件中)-或者更好的方法是恢复到通用实现,这样就不需要复制粘贴了?该软件包的全部要点是SystemVerilog没有通过字符串名称查找变量所需的内省功能。DPI也没有。因此,您需要PLI/VPI来查找对象。然而,PLI的设计非常安全h使其速度非常慢。DPI使您可以使用C型指针访问SV变量,使其速度更快,但更容易错误地破坏模拟。@dave_59很抱歉,我们的评论发生冲突。我承认,由于供应商之间的细微差异,始终需要
#ifdef VENDOR
,但这是一个全新的功能,而不是vendor特定的解决方法。将文件拆分为完全独立的文件是一种倒退,当然这些标准足够标准,可以在需要时使用几个
ifdef
s实现一个公共的基本实现?在内部,这是一个24位总线,驱动一些逻辑。仅仅因为egister宽度为16位。我可以通过串联将这两部分粘合在一起,但没有技术原因说明总线不能跨越两个地址。我们用来生成寄存器RTL的工具支持跨越多个地址的大位字段,所以不这样做的唯一原因是因为这个UVM限制。您尝试过declari吗将这个寄存器的宽度设置为24位?我前面没有uvm引用,但我认为寄存器的宽度是uvm_reg的一个属性,而不是uvm_block。所以我认为您应该能够拥有不同宽度的寄存器。这样您就不需要添加片,您只需在uvm_reg::configure中直接传递hdl路径即可可以,但SPI接口在16位边界上工作,因此一个地址只能映射到16位。不管怎样,我的Cadence AE已经将此作为增强请求,但我还没有机会看到它是否有效。正如您从上面的评论中看到的,Mentor已经支持该功能。Synopsys不太确定。我认为它会工作不好,只是有一个16位地址无法映射到寄存器,因为32位寄存器正在使用它。
static int uvm_hdl_set_vlog_partsel(char *path, p_vpi_vecval value, PLI_INT32 flag);
static int uvm_hdl_get_vlog_partsel(char *path, p_vpi_vecval value, PLI_INT32 flag);
svLogic logic_bit;
svGetBitselLogic(&bit_value,0);
svLogicVecVal bit_value;
svGetPartselLogic(&bit_value,value,i,1);
svPutPartselLogic(value,bit_value,i,1);