• 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. Sharing memory between SV and DPI-C methods

Stats

  • Locked Locked
  • Replies 3
  • Subscribers 65
  • Views 22518
  • 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

Sharing memory between SV and DPI-C methods

StephenH
StephenH over 14 years ago

Someone just asked me how to malloc() memory in a DPI-C import task (his reference model) such that the memory could be shared with the calling SV code. Because SV has some extra gubbins to track the array's properties, you cannot just use malloc() in C; even if you pass the pointer as an open array handle to the SV caller, SV won't know that you changed the array size.
A simple solution to this is to create a DPI-C export task in SV, that does the malloc for you in the SV domain.
Your C code can then call this function and use the array just as though you'd use C's malloc(), with the benefit that SV is aware of the array.

Here's an example.
// dpi.c
#include "svdpi.h"
#include <stdio.h>
#include <stdlib.h>
#include "vpi_user.h"

extern void allocate_mem ( int size );

void ref_model ( svOpenArrayHandle p )
{
  int unsigned *pp;
  int i;
  vpi_printf("c: Ref model started\n");
  allocate_mem(10);
  pp = ( int unsigned * ) svGetArrayPtr(p);
  for(i=0;i<10;i++) {
    pp[i] = i+1;
    vpi_printf("c: pp[%0d]=%0d\n",i,i+1);
  }
  vpi_printf("c: Ref model finished\n");
}

// dpi.sv
module top;
  typedef int unsigned mem_t;
  mem_t mem[];

  import "DPI-C" context task ref_model ( inout mem_t m[] );
  export "DPI-C" task allocate_mem;

  task allocate_mem ( input int size );
    $display("SV: allocating new SV DA of size %0d", size);
    mem = new[size];
  endtask

  initial begin
    ref_model(mem);
    $display("SV: ref model finished, mem.size()=%0d", mem.size());
    foreach (mem[i]) $display("SV: mem[%0d]=%0d", i,mem[i]);
  end
endmodule

And here's the corresponding output from "irun dpi.c dpi.sv"

c: Ref model started
SV: allocating new SV DA of size 10
c: pp[0]=1
c: pp[1]=2
c: pp[2]=3
c: pp[3]=4
c: pp[4]=5
c: pp[5]=6
c: pp[6]=7
c: pp[7]=8
c: pp[8]=9
c: pp[9]=10
c: Ref model finished
SV: ref model finished, mem.size()=10
SV: mem[0]=1
SV: mem[1]=2
SV: mem[2]=3
SV: mem[3]=4
SV: mem[4]=5
SV: mem[5]=6
SV: mem[6]=7
SV: mem[7]=8
SV: mem[8]=9
SV: mem[9]=10


Enjoy!

  • Cancel
  • frukr
    frukr over 13 years ago

    Very interesting issue raised here. In IEEE Std 1800-2009 section "35.5.1.4 Memory management" literally says the following:

    "The memory spaces owned and allocated by the foreign code and SystemVerilog code are disjoined. Each
    side is responsible for its own allocated memory. Specifically, an imported function shall not free the
    memory allocated by SystemVerilog code (or the SystemVerilog compiler) nor expect SystemVerilog code
    to free the memory allocated by the foreign code (or the foreign compiler). ..."

    So there isn't a second doubt on the issue of memory used for SV objects and memory allocated by CRT in user DPI code - they are separate and one shouldn't mess with the other. OK here.

    However continuing with the quote of the above mentioned section we read:

    "... This does not exclude scenarios where foreign code allocates a block of memory and then passes a handle (i.e., a pointer) to that block to
    SystemVerilog code, which in turn calls an imported function (e.g., C standard function free) that directly
    or indirectly frees that block."

    Now this where I get confused. Does this mean something like this is legal?

    //user DPI library

    void* user_dpi_malloc(int _size)
    {
        void* block = malloc(_size);
        return block;
    }

    //SV code

    module top;    
        import "DPI-C" function chandle user_dpi_malloc(int);
        import "DPI-C" function void free(chandle);
        
        chandle hnd;
        
        initial
        begin
            hnd = user_dpi_malloc(100);
            free(hnd);
        end

    endmodule    

    Here we have code allocated by malloc inside user library and freed by imported system's free. How can this work if user DPI is linked statically with CRT (hence it will have it's own malloc) while free coming from SV code will use system's? What if user's library is linked to different version of CRT than currently used by the system?
    Or maybe the code above isn't legal after all?

    • Cancel
    • Vote Up 0 Vote Down
    • Cancel
  • TAM1
    TAM1 over 13 years ago

    It looks legal to me. The memory is being allocated on the C side of the language boundary. And the memory is being free'd on the C side of the language boundary. I suppose that it would feel better if you declared your own C function:

    void user_dpi_free(void * ptr)
    {
        free( ptr );
        return;
    }

    But I think your code is functionally the same.

     

    • Cancel
    • Vote Up 0 Vote Down
    • Cancel
  • EML1
    EML1 over 9 years ago

    Does this work, and is it portable? After fixing the '[' typo it just crashes in VCS.

    • 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