• Skip to main content
  • Skip to search
  • Skip to footer
Cadence Home
  • This search text may be transcribed, used, stored, or accessed by our third-party service providers per our Cookie Policy and Privacy Policy.

  1. Community Forums
  2. Functional Verification
  3. Passing struct as an argument

Stats

  • Locked Locked
  • Replies 9
  • Subscribers 65
  • Views 22607
  • Members are here 0
This discussion has been locked.
You can no longer post new replies to this discussion. If you have a question you can start a new discussion

Passing struct as an argument

archive
archive over 19 years ago

Hi,
I am trying my hand on DPI, and have an example in which i want to pass a struct as an argument to 'C'. however i am not getting any results.

**********************************

The code is:

// Program to pass struct data-type as an argument.
// Author: Vivek C. Prasad
// Date  : 20 september 2006

#include
#include "svdpi.h"

  typedef struct {
    char a;
    int b;
    } AB;

  AB sc;
  int str(const AB sc) {
       printf("the byte is: %c\n",sc.a);
       printf("the int is: %d\n",sc.b);
       return(-1);
       }

**********************************

// Program to pass struct data-type as an argument.
// Author: Vivek C. Prasad
// Date  : 20 september 2006

module structPass();
 
  int res;
  typedef struct packed {
    byte a;
    shortint b;
    } AB;

  AB dt_struct;
 
  import "DPI-C" context str = function int structFunction(input dt_struct);

  initial begin
    dt_struct.a = "V";
    dt_struct.b = 10;
    res = structFunction(dt_struct);
    $display("The struct is passed as an argument.\n");
    $display("Byte: %0d\n",dt_struct.a);
    $display("Int : %0d\n",dt_struct.b);
    $display("Return : %0d\n",res);
  end
endmodule

**********************************
The Result is:

the byte is:
the int is: 0
The struct is passed as an argument.

Byte: 86

Int : 10

Return : -1

**********************************

Vivek.


Originally posted in cdnusers.org by prasad_vc
  • Cancel
  • archive
    archive over 19 years ago

    Using example F9.3 in appendix F of the LRM, it looks like the syntax of the str function should be:

    int str(const AB *sc) {
    printf("the byte is: %c\n", sc->a);
    printf("the int is: %d\n", sc->b);
    return(-1);
    }

    Tim


    Originally posted in cdnusers.org by tpylant
    • Cancel
    • Vote Up 0 Vote Down
    • Cancel
  • archive
    archive over 19 years ago

    Also on the SV side, the import should be:

    import "DPI-C" context str = function int structFunction(input AB dt_struct);

    You were missing the data type for the input argument.

    Tim


    Originally posted in cdnusers.org by tpylant
    • Cancel
    • Vote Up 0 Vote Down
    • Cancel
  • archive
    archive over 19 years ago

    Hi Tim,

    I tried it with the same, but could not get the desired result. Also, when i say "(input AB dt_struct)", the compiler says unsupported data-type in formal argument.

    I am using ncsim 5.6s005. Is it the tool issue?

    Vivek


    Originally posted in cdnusers.org by prasad_vc
    • Cancel
    • Vote Up 0 Vote Down
    • Cancel
  • archive
    archive over 19 years ago

    Hi Tim,
    With the ncsim v5.81 i was able to come up those issues, however one more difficulty has arose, the struct i am passing as an argument, is giving me swapped results. I mean, the struct member 'int' of sv is assigned to struct member 'byte' of 'C' and vice-versa. In my previous output it becomes

    the byte is: 10
    the int is: 86
    The struct is passed as an argument.
    Byte: 86
    Int : 10

    Isn't there anything like packing.low and packing.high as like specman in SystemVerilog.

    Vivek.


    Originally posted in cdnusers.org by prasad_vc
    • Cancel
    • Vote Up 0 Vote Down
    • Cancel
  • archive
    archive over 18 years ago

    Here's a complete example of operating on a SystemVerilog packed struct from the DPI (C) side. It's important to look at the svdpi.h file in the /tools/inca/include directory to understand this.

    -----file top.v-------
    module top ();

    // import functions do a call from SV to C
    import "DPI-C" context addone_c= function int addone_sv(input int x);
    import "DPI-C" context function void show_vec_inC(input bit [31:0] some_vec);
    import "DPI-C" context function void show_logic_inC(input logic [31:0] some_vec);

    typedef struct packed {
    int a;
    bit [9:0] b;
    bit [5:0] c;
    } mydata_struct_s;
    import "DPI-C" context function void pass_struct(inout mydata_struct_s t );

    bit [31:0] some_vec = 32'h12345678;
    logic [31:0] some_logic = 32'h8765X32Z;

    mydata_struct_s mydata_struct_i;

    initial
    begin
    $display("Gimme_Int %d",addone_sv(5));
    show_vec_inC(some_vec); // pass reference per SV spec
    show_logic_inC(some_logic); // pass reference per SV spec

    // stuff the structure with data
    mydata_struct_i.a = 9;
    mydata_struct_i.b = 10'b10_1011_0110;
    mydata_struct_i.c = 6'b11_0101;

    pass_struct(mydata_struct_i); // pass reference to packed struct

    $display("Verilog a %d", mydata_struct_i.a);
    $display("Verilog b %h", mydata_struct_i.b);
    $display("Verilog c %h", mydata_struct_i.c); // in this example the DPI inverts this data

    end

    endmodule

    -----file: main_task.c-----
    #include
    #include

    // Copyright Cadence Design Systems, Todd Mackett 2007

    // This is an example of manipulating packed data structure in SystemVerilog
    // Use /tools/inca/include/svdpi.h as a reference

    int addone_c(int x) {
    return x +1;
    }

    void show_vec_inC(svBitVecVal* x) {
    printf("show_vec_inC\n");
    printf("a= %x\n", *x);
    }

    // svLogicVecVal can have 0,1,X,Z
    void show_logic_inC(svLogicVecVal* x) {
    printf("show_Logic_inC\n");
    printf("a= %x\n", *x);
    printf("aval %x\n", x->a);
    printf("bval %x\n", x->b);

    }


    void pass_struct( svBitVecVal* x) { // NOT const so that this can be modified
    // can use x[0] to reference raw array
    // printf("Struct = %x, %x\n", x[0], x[1] );
    svBitVecVal aa; // define a local svBitVecVal
    // extract field a of SV "struct packed {...} mydata_struct_s

    svGetPartselBit(&aa , x, 16, 32);
    printf("mydata_struct_s.a: %x \n", aa);

    svGetPartselBit(&aa , x, 6, 10);
    printf("mydata_struct_s.b: %x \n", aa);
    // everything above here works

    svGetPartselBit(&aa , x, 0, 6);
    printf("mydata_struct_s.c: %x \n", aa);

    // svPutBitselBit(aa, 0, sv_0);
    printf("AA %x \n", aa);
    // do some manipulation on the local svBitVecVal
    aa = ~aa; // invert the bits (some generic bit manipulation routine)

    // can do something like this too: just set the value of Verilog Structure
    // aa = 13;
    printf("AA %x \n", aa);

    svPutPartselBit(x, aa, 0, 6); // this will modify the Verilog structure

    }
    ------file: RUN_NC------(script)------------
    rm -r INCA_libs
    rm *.so
    rm *.log
    rm *.h

    # Create .h file for Exported tasks/functions only
    # (imported function do NOT need .h file):
    ncverilog +sv top.v +ncdpiheader+dpi.h +elaborate +ncelabargs+-messages

    # ncvlog -sv top.v -mess
    # ncelab top -sv -dpiheader dpi.h -mess

    gcc -fPIC -shared -o main_task.so main_task.c -I/`ncroot`/tools/inca/include

    ncverilog +sv top.v +sv_lib=main_task.so +ncsimargs+"-sv_root ./"

    -----screen results, with some comments inserted-----------

    ncsim> run
    Gimme_Int 6
    show_vec_inC
    a= 12345678
    show_Logic_inC
    a= 8765f320
    aval 8765f320
    bval f00f
    mydata_struct_s.a: 9
    mydata_struct_s.b: 2b6
    mydata_struct_s.c: 35
    AA 35
    AA ffffffca
    Verilog a 9
    Verilog b 2b6
    Verilog c 0a <--- notice the DPI inverted the bits in this case
    ncsim: *W,RNQUIE: Simulation is complete.
    ncsim> exit



    Originally posted in cdnusers.org by tmackett
    • Cancel
    • Vote Up 0 Vote Down
    • Cancel
  • archive
    archive over 18 years ago

    Hmmmm, the above example came out with some strange characters when I copied/pasted to this. Let me repost:


    ---file: top.v-------
    module top ();

    // import functions do a call from SV to C
    import "DPI-C" context addone_c= function int addone_sv(input int x);
    import "DPI-C" context function void show_vec_inC(input bit [ 31:0] some_vec);
    import "DPI-C" context function void show_logic_inC(input logic [ 31:0] some_vec);

    typedef struct packed {
    int a;
    bit [ 9:0] b;
    bit [ 5:0] c;
    } mydata_struct_s;
    import "DPI-C" context function void pass_struct(inout mydata_struct_s t );

    bit [31:0] some_vec = 32'h12345678;
    logic [31:0] some_logic = 32'h8765X32Z;

    mydata_struct_s mydata_struct_i;

    initial
    begin
    $display("Gimme_Int %d",addone_sv(5));
    show_vec_inC(some_vec); // pass reference per SV spec
    show_logic_inC(some_logic); // pass reference per SV spec

    // stuff the structure with data
    mydata_struct_i.a = 9;
    mydata_struct_i.b = 10'b10_1011_0110;
    mydata_struct_i.c = 6'b11_0101;

    pass_struct(mydata_struct_i); // pass reference to packed struct

    $display("Verilog a %d", mydata_struct_i.a);
    $display("Verilog b %h", mydata_struct_i.b);
    $display("Verilog c %h", mydata_struct_i.c);

    end

    endmodule

    -------file: main_task.c----------
    #include
    #include

    // Copyright Cadence Design Systems, Todd Mackett 2007

    // This is an example of manipulating packed data structure in SystemVerilog
    // Use /tools/inca/include/svdpi.h as a reference

    int addone_c(int x) {
    return x +1;
    }

    void show_vec_inC(svBitVecVal* x) {
    printf("show_vec_inC\n");
    printf("a= %x\n", *x);
    }

    // svLogicVecVal can have 0,1,X,Z
    void show_logic_inC(svLogicVecVal* x) {
    printf("show_Logic_inC\n");
    printf("a= %x\n", *x);
    printf("aval %x\n", x->a);
    printf("bval %x\n", x->b);

    }


    void pass_struct( svBitVecVal* x) { // NOT const so that this can be modified
    // can use x[0] to reference raw array
    // printf("Struct = %x, %x\n", x [0], x [1] );
    svBitVecVal aa; // define a local svBitVecVal
    // extract field a of SV "struct packed {...} mydata_struct_s

    svGetPartselBit(&aa , x, 16, 32);
    printf("mydata_struct_s.a: %x \n", aa);

    svGetPartselBit(&aa , x, 6, 10);
    printf("mydata_struct_s.b: %x \n", aa);
    // everything above here works

    svGetPartselBit(&aa , x, 0, 6);
    printf("mydata_struct_s.c: %x \n", aa);

    // svPutBitselBit(aa, 0, sv_0);
    printf("AA %x \n", aa);
    // do some manipulation on the local svBitVecVal
    aa = ~aa; // invert the bits (some generic bit manipulation routine)

    // can do something like this too: just set the value of Verilog Structure
    // aa = 13;
    printf("AA %x \n", aa);

    svPutPartselBit(x, aa, 0, 6); // this will modify the Verilog structure

    }


    Originally posted in cdnusers.org by tmackett
    • Cancel
    • Vote Up 0 Vote Down
    • Cancel
  • archive
    archive over 17 years ago

    Hi Tim, I am trying to run the system verilog example you have given here for passing structure as an argument to C function. even with the modifications you had suggested i still do not see the proper values being printed by the C Function. I am attaching the SV file and the C Function. System Verilog :- -------------------------------------- module structPass(); int res; typedef struct packed { byte a; shortint b; } AB; AB dt_struct; import "DPI-C" context str = function int structFunction(input AB dt_struct); initial begin dt_struct.a = "V"; dt_struct.b = 10; res = structFunction(dt_struct); $display("The struct is passed as an argument.\n"); $display("Byte: %0d\n",dt_struct.a); $display("Int : %0d\n",dt_struct.b); $display("Return : %0d\n",res); end endmodule C Function :- -------------------------------------------- #include #include "/tools/cadence/install/tools.lnx86/include/svdpi.h" #include "/tools/cadence/install/tools.lnx86/include/vpi_user.h" typedef struct { char a; int b; } AB; AB sc; int str(const AB *sc) { printf("the byte is: %c\n",sc->a); printf("the int is: %d\n",sc->b); return(-1); } --------------------------------------- Any help would be appreciated.


    Originally posted in cdnusers.org by n_prasanna
    • Cancel
    • Vote Up 0 Vote Down
    • Cancel
  • archive
    archive over 17 years ago

    The problem is that the fields are coming across reversed which I don't understand. Here is the code that demonstrates that:

    module structPass(); int res; typedef struct packed { byte a; int b; } AB; AB dt_struct; import "DPI-C" context str = function int structFunction(input AB dt_struct); initial begin dt_struct.a = "V"; dt_struct.b = 10; $display("\nThe struct is passed as an argument."); $display("SV Byte: %0s",dt_struct.a); $display("SV Int : %0d",dt_struct.b); res = structFunction(dt_struct); $display("\nReturn : %0d\n",res); end endmodule
    #include #include "svdpi.h" typedef struct { int b; char a; } AB; AB sc; int str(const AB *sc) { printf("\nThe struct is received as an argument.\n"); printf("C  Byte: %c\n",sc->a); printf("C  Int : %d\n",sc->b); return(-1); }
    I know Todd posted a way to do it by treating the struct as a vector, but maybe someone else could shed some light on the struct reversing problem. Tim


    Originally posted in cdnusers.org by tpylant
    • Cancel
    • Vote Up 0 Vote Down
    • Cancel
  • archive
    archive over 17 years ago

    The reversing of the struct is apparently deliberate and universal across all simulators, but I can't remember why it's meant to happen. The fun thing is that packed and unpacked structs behave differently - i.e. one reverses, the other doesn't.
    Hopefully one of the simulator gurus can explain.
    If I can find the original explanation from a couple of years ago, I'll post that too...


    Originally posted in cdnusers.org by stephenh
    • Cancel
    • Vote Up 0 Vote Down
    • Cancel

Community Guidelines

The Cadence Design Communities support Cadence users and technologists interacting to exchange ideas, news, technical information, and best practices to solve problems and get the most from Cadence technology. The community is open to everyone, and to provide the most value, we require participants to follow our Community Guidelines that facilitate a quality exchange of ideas and information. By accessing, contributing, using or downloading any materials from the site, you agree to be bound by the full Community Guidelines.

© 2025 Cadence Design Systems, Inc. All Rights Reserved.

  • Terms of Use
  • Privacy
  • Cookie Policy
  • US Trademarks
  • Do Not Sell or Share My Personal Information