verilogsimulationsystem-verilogverilator

Is it possible to access the member of a user-defined struct in SystemVerilog using VPI and verilator?


In SystemVerilog, we can use our own user-defined data structure, as the example below:

typedef struct packed {
    logic [riscv::VLEN-1:0]   pc;            
    logic [TRANS_ID_BITS-1:0] trans_id;     
    fu_t                      fu;            
    fu_op                     op;           
    logic [REG_ADDR_SIZE-1:0] rs1;           
    logic [REG_ADDR_SIZE-1:0] rs2;           
    logic [REG_ADDR_SIZE-1:0] rd;           
    riscv::xlen_t             result;        
    logic                     valid;         
    logic                     use_imm;      
    logic                     use_zimm;
    logic                     use_pc;       
    exception_t               ex;            
    branchpredict_sbe_t       bp;           
    logic                     is_compressed; 
} scoreboard_entry_t;

For now, we don't need to know what exactly these members represent. What we can see is a user-defined data strucuture in SystemVerilog. And later we instantiate this struct as an input port in a module:

input  scoreboard_entry_t        issue_instr_i/*verilator public_flat_rd*/,

As you see, issue_instr_i is of this data struct and it is exposed to verilator. When I try to access it via VPI:

vpiHandle issue_instr =vpi_handle_by_name((PLI_BYTE8*)"TOP.core.issue_instr_i", NULL);
s_vpi_value v1;
v1.format = vpiHexStrVal;
vpi_get_value(issue_instr, &v1);
printf("instruction: %s\n", v1.value.str);

Apparently it only gives me a long string of hexadecimal values. Could anyone let me know how to access a specific member in this struct? I tried setting the VPI handle as issue_instr_i.rs1 etc, nothing worked.


Solution

  • For packed struct, if you know bit sizes of its members, you can use 'vpiBinStrVal' to get a binary string. You can use returned bits to segment them, according to the size of your struct. For example for the following struct

       struct  packed {
          logic [3:0]a;
          logic [1:0]b;
       } v;
    

    it might return 101011 where first 4 bits (1010) belong to a and the last two (11) belong to b. With unpacked structs it will not work though.

    However, you should be able to access struct elements by names (if it is implemented in verilator). In vcs the following works ok:

    void testme() {
        vpiHandle stAll = vpi_handle_by_name("top.sram.v", 0);
    
        s_vpi_value v1;
        v1.format = vpiBinStrVal;
        vpi_get_value(stAll, &v1);
        vpi_printf("struct: %s\n", v1.value.str);
        
        vpiHandle va = vpi_handle_by_name("top.sram.v.a", 0);
        vpi_get_value(va, &v1);
        vpi_printf("struct.a: %s\n", v1.value.str);
    
        vpiHandle vb = vpi_handle_by_name("top.sram.v.b", 0);
        vpi_get_value(vb, &v1);
        vpi_printf("struct.b: %s\n", v1.value.str);
    }