我想从使用 vpi 的 Verilog 设计中获取给定设计层次结构中的信号名称列表。这是一个简单的网络名称浏览器界面,来自我用 C 和 Python 编写的自定义工具。
如何从 Verilog 设计中获取信号名称列表以及应该使用哪些 VPI 调用来遍历设计?
任何信息,将不胜感激。
除了已经给出的答案之外,此代码将遍历您的层次结构并存储类型的设计对象,vpiLogic
您可以根据需要对其进行调整。它将寄存器的全名存储unordered_map
在模拟期间具有良好 O(1) 访问时间的寄存器中。
此代码是为同时使用 verilog 和 VHDL 的项目开发的。
您还会发现,有时某些 IP 受到保护,处理得当,此外还使用范围 ( vpiInternalScope
) 而不是允许在语句中vpiModule
递归。generate
它是 c++ 代码,但使用extern "C"
使得它可以从您的 EDA 工具中调用(使用 IUS 测试)。
#include "vhpi_user.h"
#include "vpi_user.h"
#include "vpi_user_cds.h"
#include "sv_vpi_user.h"
#include <string.h>
#include <stdlib.h>
#include <stdio.h>
#include <unordered_map>
extern "C" {
static std::unordered_map<int , std::string> reg_map;
#define check_verilog(scopeH) (vpi_get(vpiLanguage,scopeH) == vpiVerilog)
#define check_is_protected(scopeH) (vpi_get(vpiIsProtected,scopeH))
#define check_protected(scopeH) (vpi_get(vpiProtected,scopeH))
#define check_vhdl(scopeH) (vpi_get(vpiLanguage,scopeH) == vpiVHDL)
bool is_vpi_protected(vpiHandle scopeH) {
switch(vpi_get(vpiType, scopeH)) {
case vpiClockingBlock:
case vpiNamedBegin:
case vpiTask:
return check_is_protected(scopeH);
default: {
return check_protected(scopeH);
}
}
}
bool is_valid_scope(vpiHandle scopeH) {
switch (vpi_get(vpiType, scopeH)) {
case vpiInstance:
case vpiModule:
case vpiGenScope:
case vpiGenScopeArray:
case vpiInstanceArray:
return true;
default:
return false;
}
}
void vpi_get_reg(vpiHandle module) {
vpiHandle itr_reg, reg;
if ((itr_reg = vpi_iterate(vpiReg,module))) {
while ((reg = vpi_scan(itr_reg))) {
std::string reg_name(vpi_get_str(vpiFullLSName, reg));
vpi_printf("** Verilog register Full Name:\t%s[%d]\n",reg_name.c_str(),vpi_get(vpiSize, reg));
reg_map[(int)reg_map.size()+1] = reg_name;
}
}
}
void vhpi_get_reg(vpiHandle module) {
vhpiHandleT itr_reg, reg;
if (vhpi_get(vhpiKindP,module) == vhpiCompInstStmtK) {
if ((itr_reg = vhpi_iterator(vhpiSigDecls,module))) {
while (reg = vhpi_scan(itr_reg)) {
std::string reg_name(vhpi_get_str(vhpiFullLSNameP, reg));
vhpi_printf("** VHDL register Full LS Name:\t%s[%d]\n",reg_name.c_str(),vhpi_get(vhpiSizeP, reg));
reg_map[(int)reg_map.size()+1] = reg_name;
}
}
}
}
void walk_down(vpiHandle parentScope) {
vpiHandle subScopeI, subScopeH;
if (check_verilog(parentScope) && is_valid_scope(parentScope)) {
vpi_get_reg(parentScope);
if ((subScopeI = vpi_iterate(vpiInternalScope, parentScope))) {
while ((subScopeH = vpi_scan(subScopeI))) {
if (is_vpi_protected(subScopeH)) {
if (vpi_get(vpiType, parentScope)!= vpiGenScope)
vpi_printf("** Verilog scope %s in %s is protected \n",vpi_get_str(vpiFullLSName, subScopeH),vpi_get_str(vpiDefFile,parentScope));
else
vpi_printf("** Verilog scope %s in %s is protected \n",vpi_get_str(vpiFullLSName, subScopeH),vpi_get_str(vpiFile,subScopeH));
}
else {
walk_down(subScopeH);
}
}
}
}
else if(check_vhdl(parentScope)) {
vhpi_get_reg(parentScope);
subScopeI = vhpi_iterator(vhpiInternalRegions, parentScope);
if (subScopeI) {
while ((subScopeH = vhpi_scan(subScopeI)))
walk_down(subScopeH);
}
}
}
void navigate_mixed(const char * scope) {
reg_map.clear();
vpiHandle topScopeI, topScopeH;
vpi_printf(".........Starting register discovery \n");
if ((topScopeH = vpi_handle_by_name((PLI_BYTE8 *)scope, NULL))) {
topScopeI = vpi_iterate(vpiModule, topScopeH);
while ((topScopeH = vpi_scan(topScopeI)))
walk_down(topScopeH);
}
if ((topScopeH = vhpi_handle_by_name((PLI_BYTE8 *)scope, NULL)))
walk_down(topScopeH);
vpi_printf("Completed register discovery........\n");
}
}