pysv
pysv copied to clipboard
IntArray error
Hi,
I use IntArray as funtion parameter in python side and compile passed. But a error occurs when I simulate by vcs:
Error-[DPI-ASSERT] Assertion failure in DPI call Assertion failure in DPI function/task call: dimension 0 query is not supported. (svSize) Please check the parameter passing in a DPI function/task call
And I find that the svSize is used in c file, which generated by compile_lib:
py::memoryview to_buffer(const svOpenArrayHandle array_handle) {
ssize_t element_size = sizeof(int32_t);
void *base_ptr = nullptr;
std::vector<ssize_t> sizes = {};
std::vector<ssize_t> strides = {};
// we try to query the underlying representation
base_ptr = svGetArrayPtr(array_handle);
if (!base_ptr) {
throw std::runtime_error("Array type does not have native C representation");
}
auto dim = svDimensions(array_handle);
for (auto i = 0; i < dim; i++) {
auto s = svSize(array_handle, i);
sizes.emplace_back(s);
}
// assumes row major ordering
ssize_t stride = element_size;
strides = std::vector<ssize_t>(dim, element_size);
for (int i = 0; i < dim - 1; i++) {
stride *= sizes[i];
strides[i] = stride;
}
return py::memoryview::from_buffer(
base_ptr, /* Pointer to buffer */
element_size, /* Size of one scalar */
py::format_descriptor<int32_t>::value, /* Python struct-style format descriptor */
sizes, /* Buffer dimensions */
strides /* Strides (in bytes) for each index */
);
}
Maybe this (dim in for loop begins from 0 ) causes the error?
Can you show me the code where you call the DPI function? Especially the array definition.
Can you show me the code where you call the DPI function? Especially the array definition.
Ok, in python side:
class Img2colVerificationTools:
@sv()
def __init__(self):
self.fea = None
self.fea_2d = None
self.counter = 0
@sv(fea_array=DataType.IntArray)
def get_fea(self, fea_array):
self.fea = np.array(fea_array).reshape(3,8,8)
self.fea_2d = self.fea.reshape(-1,4)
@sv(return_type=Reference(a=DataType.UInt, b=DataType.UInt, c=DataType.UInt,d=DataType.UInt))
def gen_stimulus(self):
out = self.fea_2d[self.counter,:]
self.counter += 1
return out
In sv side:
class fea_transaction;
rand int fea[][][];
int fea_queue[$];
constraint c_fea{
$size(fea) == 3;
foreach(fea[i]){
$size(fea[i]) == 8;
}
foreach(fea[i,j]){
$size(fea[i][j]) == 8;
}
foreach(fea[i,j,k]){
fea[i][j][k] >= 0;
fea[i][j][k] < 256;
}
}
function void flatten();
foreach(fea[i,j,k]) begin
fea_queue.push_back(fea[i][j][k]);
end
endfunction
endclass
module top_tb;
fea_transaction fea_tr;
initial begin
int a,b,c,d, cycle;
Img2colVerificationTools m_gen=new();
fea_tr = new();
fea_tr.randomize();
fea_tr.flatten();
m_gen.get_fea(fea_tr.fea_queue);
cycle = 48;
for(int i=0;i<cycle;i++) begin
m_gen.gen_stimulus(a,b,c,d);
$display("%d th cycle: a is %d",i+1,a);
$display("%d th cycle: b is %d",i+1,b);
$display("%d th cycle: c is %d",i+1,c);
$display("%d th cycle: d is %d",i+1,d);
end
pysv_finalize();
end
endmodule
int fea_queue[$];
defines a queue. SystemVerilog LRM does not specify how it can be translated to a DPI interface type. It should work once you convert it to an open/dynamic array.
int fea_queue[$];
defines a queue. SystemVerilog LRM does not specify how it can be translated to a DPI interface type. It should work once you convert it to an open/dynamic array.
Thanks, the queue can not be used here. But the same error occurs when I use dynamic array or static array:
class fea_transaction;
rand int fea[][][];
int fea_queue[$];
int fea_darray[];
int fea_sarray[3*8*8];
constraint c_fea{
$size(fea) == 3;
foreach(fea[i]){
$size(fea[i]) == 8;
}
foreach(fea[i,j]){
$size(fea[i][j]) == 8;
}
foreach(fea[i,j,k]){
fea[i][j][k] >= 0;
fea[i][j][k] < 256;
}
}
function void flatten();
foreach(fea[i,j,k]) begin
fea_queue.push_back(fea[i][j][k]);
end
fea_darray = fea_queue;
fea_sarray = fea_queue;
endfunction
endclass
module top_tb;
fea_transaction fea_tr;
initial begin
int a,b,c,d, cycle;
Img2colVerificationTools m_gen=new();
fea_tr = new();
fea_tr.randomize();
fea_tr.flatten();
m_gen.get_fea(fea_tr.fea_sarray);
cycle = 48;
for(int i=0;i<cycle;i++) begin
m_gen.gen_stimulus(a,b,c,d);
$display("%d th cycle: a is %d",i+1,a);
$display("%d th cycle: b is %d",i+1,b);
$display("%d th cycle: c is %d",i+1,c);
$display("%d th cycle: d is %d",i+1,d);
end
pysv_finalize();
end
endmodule
And i still think the reason of this error is usage of svSize function in c file. The similar error occurs when I take another experiment that I try to use svLow(h,0) function to get the lower bound of the first dimension of the array passed from sv to c:
Error-[DPI-ASSERT] Assertion failure in DPI call Source info: ./test_c.sv:35 Assertion failure in DPI function/task call: dimension 0 query is not supported. (svLow) Please check the parameter passing in a DPI function/task call.
Maybe the dimension parameter of these functions(likes svLow,svHigh,svSize) should start from 1 rather than 0?
In addition, i want to know what the code looks like if i pass a 3d array to python from sv. Here i was going to pass an array(3x8x8) to python. If i know how to do, i will do not use flatten in sv and reshape in python.
Maybe the dimension parameter of these functions(likes svLow,svHigh,svSize) should start from 1 rather than 0?
That's a good point. I will double check the spec. In the meantime, can you try to modify the generated C++ code and see if it works?
In addition, i want to know what the code looks like if i pass a 3d array to python from sv. Here i was going to pass an array(3x8x8) to python. If i know how to do, i will do not use flatten in sv and reshape in python.
Once the bug is fixed, the C++ you posted should produce a 3d Python array to the binding, at least that's the intention. I haven't extensively tested it thought.
That's a good point. I will double check the spec. In the meantime, can you try to modify the generated C++ code and see if it works?
Only modifying the generated c++ code doesn't work, and maybe the shared library need to be recompiled. But i do not know how to recompile due to dependency issues.
Once the bug is fixed, the C++ you posted should produce a 3d Python array to the binding, at least that's the intention. I haven't extensively tested it thought.
Actually, I want to know what the code looks like in python side, and just using IntArray as parameter type maybe can't generate sv binding as:
import "DPI-C" void function sv_fun(input int data[][][]);
just generate:
import "DPI-C" void function sv_fun(input int data[]);
I don't know if my understanding is correct.
Ok, i modify the code in pysv package installed and it works. The code modified is in file snippets/buffer_impl.cc:
auto dim = svDimensions(array_handle);
for (auto i = 1; i < dim + 1; i++) {
auto s = svSize(array_handle, i);
sizes.emplace_back(s);
}
// assumes row major ordering
ssize_t stride = element_size;
strides = std::vector<ssize_t>(dim, element_size);
for (int i = 0; i < dim; i++) {
stride *= sizes[i];
strides[i] = stride;
}
But the 3x8x8 array data is not correct. The data printed in sv is:
'{126, 99, 120, 153, 229, 203, 121, 53, 202, 178, 172, 25, 106, 179, 187, 133, 55, 41, 168, 119, 200, 132, 47, 146, 215, 42, 70, 22, 118, 58, 60, 201, 7, 185, 65, 42, 201, 144, 100, 97, 233, 82, 227, 232, 255, 104, 176, 39, 70, 122, 94, 29, 154, 240, 54, 127, 185, 160, 23, 6, 36, 237, 230, 115, 232, 31, 95, 24, 68, 170, 197, 31, 31, 162, 168, 38, 97, 58, 241, 206, 27, 203, 7, 63, 39, 105, 172, 200, 229, 59, 71, 46, 182, 161, 68, 37, 195, 239, 198, 81, 99, 227, 100, 96, 188, 39, 173, 235, 61, 146, 242, 196, 136, 150, 39, 13, 52, 210, 206, 208, 165, 0, 205, 208, 9, 199, 63, 221, 193, 29, 40, 29, 1, 124, 146, 173, 101, 204, 108, 244, 149, 233, 220, 38, 29, 137, 182, 251, 53, 137, 189, 242, 241, 206, 254, 7, 247, 76, 132, 193, 192, 45, 96, 83, 216, 158, 156, 109, 126, 13, 40, 36, 180, 149, 46, 67, 132, 81, 223, 103, 168, 116, 209, 178, 191, 229, 71, 157, 9, 56, 84, 229}
The data printed in python is:
126,0,0,0,0,0,0,0,0,0,1272250368,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,65535,0,0,0,0,0,0,0,0,0,0,0,0,0,0,355991751,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1146307414,543515759,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1272067408,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
Maybe the code in to_buffer function is not correct?
Actually, I want to know what the code looks like in python side, and just using IntArray as parameter type maybe can't generate sv binding as: import "DPI-C" void function sv_fun(input int data[][][]); just generate: import "DPI-C" void function sv_fun(input int data[]); I don't know if my understanding is correct.
You're right about this. The type info is not properly encoded and thus only 1D array is generated. I have some ideas on how to add type annotation on the multi-d array. and I will work on that next.
Maybe the code in to_buffer function is not correct?
It might be. I only tested the code with Verilator (the one I have access to on my laptop) and using 0
seems to work without crashing. I will investigate more.
Thanks again for finding the issues.
Looking forward to improvements in future
Should be fixed in the latest commit/release. Please reopen this issue if it doesn't work for you (I only tested it with Verilator). Example usage for a 3D array:
DataType.IntArray[3]
Should be fixed in the latest commit/release. Please reopen this issue if it doesn't work for you (I only tested it with Verilator). Example usage for a 3D array:
DataType.IntArray[3]
Emmm, maybe i have not access to reopen this issue.
A new problem is the static multi-dimensional array defined can't be passed to function in sv binding(maybe it doesn't has the conception of multi-dimensional dynamic array). As follows:
Incompatible complex type usage in task or function call. The following expression is incompatible with the formal parameter of the function. The type of the actual is 'int$[0:2][0:7][0:7]', while the type of the formal is 'int$[][][]'. Expression: data Source info: m_gen.get_fea(data)
If i define a multi-dimensional dynamic array (maybe called open array, likes data[][][]) and pass it to function in sv binding, a new error occurs:
Incompatible complex type usage in task or function call. The following expression is incompatible with the formal parameter of the function. The type of the actual is 'int$[][][]', while the type of the formal is 'int$[:][:][:]'. Expression: fea_array Source info: gen::Img2colVerificationTools_get_fea(this.pysv_ptr, fea_array)
Finally, after i modify parameter type to static array in sv binding function and define a static array to pass it, everything works. the example code is:
// my array
int data[3][8][8];
Img2colVerificationTools m_gen=new();
m_gen.get_fea(data);
//import c functoin, dosn't modify
import "DPI-C" function void Img2colVerificationTools_get_fea(input chandle self,
input int fea_array[][][]);
//modify to static array
class Img2colVerificationTools extends PySVObject;
......
function void get_fea(input int fea_array[3][8][8]);
Img2colVerificationTools_get_fea(pysv_ptr, fea_array);
endfunction
endclass
What simulator are you using? I tested the open array DPI interface with all big three simulators (VCS, Xcelium, and Questa), and Verilator. They all work with static-sized array. See the EDA playground example here: https://www.edaplayground.com/x/jrga
module dpi_tb;
import "DPI-C" context function void test_array(input int array[][]);
int value[2][4];
initial
begin
test_array(value);
end
endmodule
#include <stdio.h>
#include <iostream>
#include <svdpi.h>
using namespace std;
extern "C" {
void test_array(svOpenArrayHandle array) {
printf("works\n");
}
}
What simulator are you using? I tested the open array DPI interface with all big three simulators (VCS, Xcelium, and Questa), and Verilator. They all work with static-sized array. See the EDA playground example here: https://www.edaplayground.com/x/jrga
module dpi_tb; import "DPI-C" context function void test_array(input int array[][]); int value[2][4]; initial begin test_array(value); end endmodule
#include <stdio.h> #include <iostream> #include <svdpi.h> using namespace std; extern "C" { void test_array(svOpenArrayHandle array) { printf("works\n"); } }
I use the vcs to run. And i mean that static-sized array actually works, but error occurs in systemverilog binding. When a class is used in python, c++ file uses many static functions to map this class and systemverilog binding wraps these static functions into a sv class. Finally, we call this sv class for using as like calling python class.
A this class example in sv binding generated is:
class Img2colVerificationTools extends PySVObject;
function new();
pysv_ptr = Img2colVerificationTools_pysv_init();
endfunction
function void get_fea(input int fea_array[][][]);
Img2colVerificationTools_get_fea(pysv_ptr, fea_array);
endfunction
endclass
As like the above code, the formal parameter of get_fea
function is fea_array[][][]
so that i can not call this function by passing a static-sized array unless i modify fea_array[][][]
to fea_array[3][8][8](the same as the size of static-sized array passed). If i directly call the Img2colVerificationTools_get_fea
by passing a static-sized array, it will not a problem. It is the class wrapper that is causing the error.
As like the above code, the formal parameter of get_fea function is fea_array[][][] so that i can not call this function by passing a static-sized array unless i modify fea_array[][][] to fea_array[3][8][8](the same as the size of static-sized array passed). If i directly call the Img2colVerificationTools_get_fea by passing a static-sized array, it will not a problem. It is the class wrapper that is causing the error.
Got it. Thanks for the explanation. I am able to reproduce the error. I didn't realize that the class method is causing the issue. I don't know a quick workaround at the moment so unfortunately you have to use top-level functions instead of a python class. I will see if there is any workaround.
Reopen this issue for tracking.