The idea is to simplify data copy from C side to SV side.
step 1: SV allocate a dynamic array (of int, for example). This dynamic array will be persistent. This dynamic array is passed to C side with DPI import function.
Step 2: C function save the svOpenArrayHandle or even the actual C pointer appropriately and return.
Step 3: another C function is called somehow. This will fetch the svOpenArrayHandle and memcpy some data into it. Finally, it calls dpi exports to just notify SV that the data is ready in the dynamic array.
Step 4: SV do some processing on the data in the dynamic array.
step 3 and 4 can happen many times after step 1 and 2.
Is this legal operation sequence ?
In reply to robert.liu:
I don’t think this is or should be legal. A dynamic array is SystemVerilog-only datatype and memory management occurs on the SystemVerilog side. If the size of the dynamic array gets changed, the location of the memory might get changed as well. Even if the size does not change the memory manager is free to move the array around to make room for other arrays that grow or shrink.
If the dynamic array is a C compatible type, the array is going to be passed by reference anyways. If there are no changes to the array between steps 1 & 3, it will probably just pass the same reference pointer again, so there would be no performance penalty.
In reply to dave_59:
I need to explain step 3 a bit more. In this step, this “another” C function is called by vpi value change callback (to mimic @(posedge clk)) and it will send some data to SV side.
The idea above is just to do memory copy in this C function to the memory pointed to by the svOpenArrayHandle. It is because DPI export doesn’t support open array.
Like what you said, even we allocate dynamic array once and keep using it, it’s still likely to be moved around then this will fail sooner or later.
If we change the dynamic array to fixed size array, let’s say the fixed size array is a member of object, looks its memory still can be moved.
In reply to robert.liu:
I think you are getting into an XY problem where you are describing problems with your solution to a problem, and not describing the original problem. Without a bigger picture of your situation, I can only throw out a few suggestions:
- Use the VPI to get a handle to the array and use VPI routines to access the array.
- Keep the array allocated on one side of the language barrier and create access routines to interact with the array.
- If you have larger blocks of memory that you need to interact with, create access routines with larger fixed size array blocks to do memcpy.
In reply to dave_59:
The original problem is simple:
unlike dpi import which support open array for variable amount of data, what is the generic way of sending variable amount of data from C to SV, if the C function is called by irrelevant caller, like VPI callback.
It seems I’m using the 2nd way you described:
-
send the C pointer to the data and size of the data to SV via a DPI export:
void callback()
{
…
send_data_to_sv(data_ptr, size);
…
}
-
send_data_to_sv allocated dynamic array using the size and call DPI import for final copy:
export "DPI-C" function send_data_to_SV(chandle ptr, int size);
import "DPI-C" function void copy_data(chandle ptr, inout int array[]);
function void send_data_to_sv(chandle ptr, int size);
int array[] = new[size];
copy_data(ptr, array);
endfunction
- in C side, define copy_data
void copy_data(void* data_ptr, svOpenArrayHandle h)
{
memcpy(svOpenArrayHandle(h), dsta_ptr, svSizeOfArray(h);
}
You can see in above solution there are two DPI calls. Would the performance be better if we get rid of the import? Instead, we copy data directly in the callback function and call a simple dpi export to get SV notified.
In reply to robert.liu:
You are still describing your solution to a problem, and not the problem. Why are you trying to mix VPI callbacks with DPI? Could whatever you are trying to accomplish be done all with VPI or all with DPI?
And I don’t think there is any way to get rid of the two DPI calls you have. The C side needs to have a call that allocates the dynamic array first before the actual copying of data.