Verilog 在设计中获取信号名称(使用VPI调用)

Verilog 在设计中获取信号名称(使用VPI调用),verilog,vpi,Verilog,Vpi,我想从使用vpi的Verilog设计中获得给定设计层次结构中的信号名称列表。这是我的自定义工具中的一个简单的网络名浏览器界面,它是用C和Python编写的 如何从Verilog设计中获得信号名称列表,以及在设计过程中应该使用哪些VPI调用 任何信息都将不胜感激。除了本代码已经给出的答案之外,请仔细查看您的层次结构并存储vpiLogic类型的设计对象,您可以根据需要对其进行调整。 它将寄存器的全名存储在一个无序的映射中,该映射在模拟过程中具有很好的O(1)访问时间 这段代码是为同时使用verilo

我想从使用vpi的Verilog设计中获得给定设计层次结构中的信号名称列表。这是我的自定义工具中的一个简单的网络名浏览器界面,它是用C和Python编写的

如何从Verilog设计中获得信号名称列表,以及在设计过程中应该使用哪些VPI调用


任何信息都将不胜感激。

除了本代码已经给出的答案之外,请仔细查看您的层次结构并存储
vpiLogic
类型的设计对象,您可以根据需要对其进行调整。 它将寄存器的全名存储在一个
无序的
映射中,该映射在模拟过程中具有很好的O(1)访问时间

这段代码是为同时使用verilog和VHDL的项目开发的

您还将发现,有时一些IP受到保护,处理起来很优雅,此外,使用作用域(
vpiInternalScope
)而不是
vpiModule
允许在
generate
语句中递归

是C++代码,但使用<代码>外“C”<代码>使它可以从EDA工具(使用IUS测试)调用。

#包括“vhpi_user.h”
#包括“vpi_user.h”
#包括“vpi_用户_cds.h”
#包括“sv_vpi_user.h”
#包括
#包括
#包括
#包括
外部“C”{
静态std::无序的\u-map reg\u-map;
#定义check_verilog(scopeH)(vpi_get(vpiLanguage,scopeH)=vpiVerilog)
#定义检查受保护(范围H)(vpi获取(vpiIsProtected,范围H))
#定义检查保护(范围H)(vpi获取(vpi保护,范围H))
#定义check_vhdl(scopeH)(vpi_get(vpiLanguage,scopeH)=vpiVHDL)
bool受保护(vpi处理范围){
开关(vpi_get(vpiType,scopeH)){
案例vpiClockingBlock:
案例vpiNamedBegin:
案例vpiTask:
返回检查受保护(范围h);
默认值:{
返回检查受保护(scopeH);
}
}
}
bool是有效的范围(vpiHandle范围){
开关(vpi_get(vpiType,scopeH)){
案例VPI实例:
案例vpiModule:
案例vpiGenScope:
案例vpiGenScopeArray:
案例vpiInstanceArray:
返回true;
违约:
返回false;
}
}
无效vpi_get_reg(vpi处理模块){
vpiHandle itr_reg,reg;
if((itr_reg=vpi_iterate(vpiReg,module))){
而((reg=vpi\U扫描(itr\U reg))){
std::string reg_name(vpi_get_str(vpiFullLSName,reg));
vpi_printf(“**Verilog寄存器全名:\t%s[%d]\n”,reg_Name.c_str(),vpi_get(vpiSize,reg));
注册表映射[(int)注册表映射.size()+1]=注册表名称;
}
}
}
无效vhpi_get_reg(VPI处理模块){
vhpiHandleT itr_reg,reg;
如果(vhpi_get(vhpiKindP,模块)=vhpicompinstmtk){
if((itr_reg=vhpi_迭代器(vhpiSigDecls,模块))){
而(reg=vhpi\U扫描(itr\U reg)){
字符串注册名(vhpi get str(vhpiFullLSNameP,reg));
vhpi_printf(“**VHDL寄存器完整LS名称:\t%s[%d]\n”,reg_Name.c_str(),vhpi_get(vhpiSizeP,reg));
注册表映射[(int)注册表映射.size()+1]=注册表名称;
}
}
}
}
无效向下行走(VPI手柄家长镜){
vpiHandle子范围,子范围;
if(检查verilog(parentScope)和&is(有效的)范围(parentScope)){
vpi_get_reg(父镜);
如果((子范围=vpi_迭代(vpi内部范围,父范围))){
而((子范围=vpi_扫描(子范围))){
如果(vpi受保护(子范围)){
if(vpi_get(vpiType,parentScope)!=vpiGenScope)
vpi_printf(“**Verilog作用域%s在%s中受保护\n”)、vpi_get_str(vpiFullLSName,子作用域)、vpi_get_str(vpiDefFile,父作用域));
其他的
vpi_printf(“**Verilog作用域%s在%s中受保护\n”)、vpi_get_str(vpiFullLSName,子作用域)、vpi_get_str(vpiFile,子作用域));
}
否则{
向下走(子范围);
}
}
}
}
else if(检查vhdl(父范围)){
vhpi_get_reg(父镜);
subScopeI=vhpi_迭代器(vhpi内部区域,父范围);
if(子范围i){
而((子范围=vhpi_扫描(子范围)))
向下走(子范围);
}
}
}
无效导航\u混合(常量字符*范围){
注册表映射清除();
vpiHandle Topscope,Topscope;
vpi_printf(“开始寄存器发现”);
if((topScopeH=vpi_handle_by_name((PLI_BYTE8*)作用域,NULL))){
TOPSCOPE=vpi_迭代(vpiModule,TOPSCOPE);
而((TOPSCOPE=vpi_扫描(TOPSCOPE)))
向下走(顶镜);
}
if((topScopeH=vhpi_handle_by_name((PLI_BYTE8*)作用域,NULL)))
向下走(顶镜);
vpi_printf(“已完成的寄存器发现……。\n”);
}
}

有端口,模块中有局部变量,总是块、函数、任务中有局部变量。你对哪些感兴趣?vpi中有多个扫描功能,可以扫描不同的实体。我认为获取端口名列表(w/层次结构)是一个很好的起点。一旦我理解了这个概念,我可以在必要时扩展它。您可以像这里一样遍历端口。然后,您可以使用vpi_get_str()Serge获取端口名,谢谢您的回复。是的,您的示例代码为我提供了足够的信息。谢谢