简体   繁体   中英

Unpacking system verilog packed struct in DPI-C call

I have a very complicated packed struct, C , with nested packed structs, A and B , in SystemVerilog:

typedef struct packed {
    logic [31:0] ex1;
    logic [3:0] ex2;
} A;

typedef struct packed {
    logic  ex3;
    A [7:0] ex4;
} B;

typedef struct packed {
    logic ex5
    A  [5:0]ex6;
    B  ex7;
} C;

I need to send this struct via a DPI-C call and then access the different elements within the struct. Unfortunately the actual struct I'm working with is much more complicated than above and I'd like to achieve this without bit indexing into the array for every element. I have seen this post but my struct is so nested and complicated that just indexing would be largely infeasible.

So in the testbench.sv file, I have:

import "DPI-C" function void passC(input C c); 

And then in the my-dpi.cc file, I want a way to simply save the svLogicVecVal into a C++ equivalent struct

struct A {
    svLogicVecVal ex1; \\[31:0] 
    svLogicVecVal ex2; \\[3:0]
};

struct B {
    svBit  ex3;
    A ex4[8];
};

struct C {
    svBit ex5
    A  ex6[6];
    B  ex7;
};

extern "C" function void passC(svLogicVecVal* c){
   C = c; 
} 

I know this is an extremely complicated issue so I would appreciate any advice on the best way to go about it. Unfortunately, I cannot change the SystemVerilog struct itself. I could try to convert it to C compatible types in SystemVerilog but I'd prefer to just go whatever the cleanest solution is. Thanks in advance.

I came up with an example which allows you to use vpi calls to traverse fields of the structure. It is pure vpi example involved from a dpi function. You can use something similar.

Here is verilog code

typedef struct packed {
    logic [3:0] f1;
    logic f2;
} s1_t;


typedef struct packed {
   logic  f3;
   s1_t s1;
} s2_t;

import "DPI-C" function void xploreStruct(string instName, string varName);

module test;
   s2_t s2 = '{1, '{2, 0}};
   
   initial begin
      xploreStruct("test", "s2");
   end
endmodule // test

The function gets called with two args: module instance, and variable name. You can probably come up with a different scheme. You might need to use a pure vpi system function instead of dpi if you want to pass the variable itself. Anyway, 'C' code for this example:

#include "stdio.h"
#include "svdpi.h"

#include "sv_vpi_user.h"

static void xploreStructUnionMembers(vpiHandle var, int offset);

void xploreStruct(const char *instName, const char *varName){
    vpiHandle module = vpi_handle_by_name(instName, 0);
    vpiHandle tdVar = vpi_handle_by_name(varName, module);
    
    printf("%s %s\n", vpi_get_str(vpiType, tdVar), vpi_get_str(vpiName, tdVar));

    xploreStructUnionMembers(tdVar, 1);
}

static void xploreStructUnionMembers(vpiHandle var, int offset){
    vpiHandle members = vpi_iterate(vpiMember, var);
    vpiHandle member;
    while (( member = vpi_scan(members) )) {
        printf("%*s %s %s\n", offset*4, "", vpi_get_str(vpiType, member), vpi_get_str(vpiName, member));
        
        int vType = vpi_get(vpiType, member);
        if (vType == vpiStructVar || vType == vpiUnionVar) {
            xploreStructUnionMembers(member, offset+1);
        }
        else {
            s_vpi_value value = {vpiIntVal};
            vpi_get_value(member, &value);
            printf("%*s = %d\n", offset*4, " ", value.value.integer);
        }
    }
    return;
}

and the output

vpiStructVar s2
     vpiLogicVar f3
     = 1
     vpiStructVar s1
         vpiLogicVar f1
         = 2
         vpiLogicVar f2
         = 0

This worked with vcs.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM