所以我在我的 verilog 中定义了以下寄存器
reg [31:0] register_mem [0:15]/* verilator public */;
我的目标是从我的 verilator c++ 代码中读取存储在其中的 16 个值中的每一个。
我发现这个 VPI 东西的文档很难找到。我仍然无法弄清楚 t_vpi_vecval
是什么,它的参数是什么,或者它是否是正确的方法。
这是我读取寄存器中第 5 个值的方法
unsigned int read_regs() {
const std::string path = "TOP.TOP.cpu.reg_file.register_mem";
vpiHandle vh1 = vpi_handle_by_name((PLI_BYTE8*)path.c_str(), NULL);
if (!vh1) {
printf("Name %s", path.c_str());
vl_fatal(__FILE__, __LINE__, "sim_main", "No handle found: ");
}
const char* name = vpi_get_str(vpiName, vh1);
s_vpi_value v;
v.format = vpiVectorVal;
vpi_get_value(vh1, &v);
return v.value.vector[4].aval;
}
无论我在这里做什么,该方法都会返回 0,表明我没有查看 register_mem 数组。
我做错了什么?
最佳答案
为了获取数组的值,您需要分别获取数组中每个元素的值。 VPI 不返回完整数组的值。
实际上,您获得的数组句柄是 vpiRegArray
类型的句柄。它可以迭代以访问每个单独的元素。
这是一个简单的代码,它执行迭代并打印数组中每个元素的值:
#include "vpi_user.h"
PLI_INT32 preg_calltf( char *txt ) {
vpiHandle hreg = vpi_handle_by_name("rarr.register_mem", 0);
vpi_printf("reg type: %s\n", vpi_get_str(vpiType, hreg)); // vpiRegArray
s_vpi_value val = {vpiDecStrVal}; // struct t_vpi_value
vpiHandle arrayIterator = vpi_iterate( vpiReg, hreg);
if( arrayIterator != NULL ) {
vpiHandle item = NULL;
while( NULL != ( item = vpi_scan( arrayIterator ) ) ) {
vpi_get_value(item, &val);
vpi_printf("item type: %s = %s\n", vpi_get_str(vpiType, item), val.value.str); // vpiReg
vpi_free_object( item );
}
}
return 0;
}
在这种情况下,我使用 vpiDecStrVal
初始化了 val
。它指示编译器将值结果准备为十进制字符串。该值现在可以作为 val.value.str
访问。您有多种选择来获取 2 态或 4 态表示形式的字符串或二进制数据。
对于高达 32 位的二态值,您可以使用整数格式。但是,对于更长的值或 4 态,您需要 vpiVectorVal
。它实际上请求 verilog 创建 2 个 32 位整数数组 aval 和 bval。两者的大小都足够大,可以保留值的所有位。 aval 和 bval 中的位组合表示向量中所有位的 4 态值。
LRM 中提供了所有 vpi 信息,包括关系图和数据结构。还有一些书,例如 Sutherland 的“the verilog pli handbook”。
关于verilog - 使用 Verilator 和 VPI 读取 regs 数组,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/60307212/