Home > Community > Forums > Functional Verification > Passing struct as an argument

Email

* Required Fields

Recipients email * (separate multiple addresses with commas)

Your name *

Your email *

Message *

Contact Us

* Required Fields
First Name *

Last Name *

Email *

Company / Institution *

Comments: *

 Passing struct as an argument 

Last post Wed, Sep 20 2006 2:26 AM by archive. 8 replies.
Started by archive 20 Sep 2006 02:26 AM. Topic has 8 replies and 4095 views
Page 1 of 1 (10 items)
Sort Posts:
  • Wed, Sep 20 2006 2:26 AM

    • archive
    • Top 75 Contributor
    • Joined on Fri, Jul 4 2008
    • Posts 88
    • Points 4,930
    Passing struct as an argument Reply

    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
    • Post Points: 0
  • Thu, Sep 21 2006 6:28 PM

    • archive
    • Top 75 Contributor
    • Joined on Fri, Jul 4 2008
    • Posts 88
    • Points 4,930
    RE: Passing struct as an argument Reply

    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
    • Post Points: 0
  • Thu, Sep 21 2006 6:30 PM

    • archive
    • Top 75 Contributor
    • Joined on Fri, Jul 4 2008
    • Posts 88
    • Points 4,930
    RE: Passing struct as an argument Reply

    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
    • Post Points: 0
  • Thu, Sep 21 2006 10:29 PM

    • archive
    • Top 75 Contributor
    • Joined on Fri, Jul 4 2008
    • Posts 88
    • Points 4,930
    RE: Passing struct as an argument Reply

    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
    • Post Points: 0
  • Fri, Sep 22 2006 7:19 AM

    • archive
    • Top 75 Contributor
    • Joined on Fri, Jul 4 2008
    • Posts 88
    • Points 4,930
    RE: Passing struct as an argument Reply

    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
    • Post Points: 0
  • Tue, Jan 23 2007 2:47 PM

    • archive
    • Top 75 Contributor
    • Joined on Fri, Jul 4 2008
    • Posts 88
    • Points 4,930
    RE: Passing struct as an argument Reply

    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
    • Post Points: 0
  • Tue, Jan 23 2007 2:56 PM

    • archive
    • Top 75 Contributor
    • Joined on Fri, Jul 4 2008
    • Posts 88
    • Points 4,930
    RE: Passing struct as an argument Reply

    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
    • Post Points: 0
  • Mon, Jan 28 2008 12:31 AM

    • archive
    • Top 75 Contributor
    • Joined on Fri, Jul 4 2008
    • Posts 88
    • Points 4,930
    RE: Passing struct as an argument Reply

    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
    • Post Points: 0
  • Tue, Jan 29 2008 10:31 AM

    • archive
    • Top 75 Contributor
    • Joined on Fri, Jul 4 2008
    • Posts 88
    • Points 4,930
    RE: Passing struct as an argument Reply

    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
    • Post Points: 0
  • Tue, Jan 29 2008 10:38 AM

    • archive
    • Top 75 Contributor
    • Joined on Fri, Jul 4 2008
    • Posts 88
    • Points 4,930
    RE: Passing struct as an argument Reply

    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
    • Post Points: 0
Page 1 of 1 (10 items)
Sort Posts:
Started by archive at 20 Sep 2006 02:26 AM. Topic has 8 replies.