使用 Verilator 和 VPI 读取 regs 数组

Posted

技术标签:

【中文标题】使用 Verilator 和 VPI 读取 regs 数组【英文标题】:Reading array of regs using Verilator and VPI 【发布时间】:2020-02-19 18:43:04 【问题描述】:

所以我在我的 verilog 中定义了以下寄存器

reg [31:0] register_mem [0:15]/* verilator public */;

我的目标是从我的验证器 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 数组。

我做错了什么?

【问题讨论】:

【参考方案1】:

为了获取数组的值,您需要分别获取数组中每个元素的值。 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 位的 2 状态值,您可以使用整数格式。但是,对于更长的值或 4 状态,您需要 vpiVectorVal。它实际上要求 verilog 创建 2 个 32 位整数数组,aval 和 bval。两者都具有足够大的大小以保留值的所有位。 aval 和 bval 中的位组合表示向量中所有位的 4 状态值。

所有 vpi 信息都在 LRM 中可用,包括关系图和数据结构。还有一些书籍,例如 Sutherland 的“the verilog pli handbook”。

【讨论】:

不幸的是,这对我不起作用。有几处偏离。类型打印行报告它是vpiMemory (如果这意味着它合成为brams 而不是触发器,那么这很好,因为我将它写成可以同步访问,所以它会是一个Bram)。但是迭代器对我来说总是空的,所以它永远不会进入循环。这个值是否可能在主模块的子模块中很重要? 尝试使用vpiMemoryWord作为迭代器,而不是vipReg 宾果游戏!这就对了!非常感谢!

以上是关于使用 Verilator 和 VPI 读取 regs 数组的主要内容,如果未能解决你的问题,请参考以下文章

如何修复 Verilator 的凿子测试错误(应该与 verilator 一起使用 *** FAILED ***)?

Verilator 可以创建类层次结构吗?

如何知道 cocotb 测试台使用的是哪个模拟器?

chisel printf 失败(使用 chisel3 然后 Verilator 到 C++ 构建)

NVIDIA VPI架构解析

由于verilog与verilator中的无符号算术错误,比较是恒定的