Reading array of regs using Verilator and VPI

1.3k Views Asked by At

So I have the following register defined in my verilog

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

My goal is from my verilator c++ code to read each of the 16 values stored in it.

I have found that the documentation for this VPI stuff is rather difficult to find. I still cannot figure out what a t_vpi_vecval is and what its parameters are or if it is even the right approach.

Here is my approach at reading the 5th value in the register

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;
}

No-matter what I do here the method returns 0 suggesting that I am not looking at the register_mem array.

What am I doing wrong?

1

There are 1 best solutions below

3
On

In order to get values of the array, you need to get values for every element of an array separately. VPI does not return values for the full array.

Actually the handle which you get for an array is a handle of the vpiRegArray type. It can be iterated to access every separate element.

Here is a simple code which does the iteration and prints values of every element in the array:


#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;
}

In this case I initialized the val with vpiDecStrVal. It instructs the compiler to prepare value results as a decimal string. The value is now accessible as val.value.str. You have multiple choices to get string or binary data in 2-state or 4-state representation.

For 2-state values up to 32 bit you can use an integer formatting. However, for longer values or 4-state, you need vpiVectorVal. It actually requests verilog to create 2 arrays of 32-bit integers, aval and bval. Both have sizes big enough to keep all bits of the value. Combination of bits in aval and bval represent the 4-state value of all bits in the vector.

All vpi information is available in LRM including relation diagrams and data structures. There are also some books, for example "the verilog pli handbook" by Sutherland.