2

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

如何从 Verilog 设计中获取信号名称列表以及应该使用哪些 VPI 调用来遍历设计?

任何信息,将不胜感激。

4

1 回答 1

0

除了已经给出的答案之外,此代码将遍历您的层次结构并存储类型的设计对象,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");
}

}
于 2018-05-18T01:40:23.330 回答