diff --git a/Changes b/Changes index 0aa1a1586..5ad6ae118 100644 --- a/Changes +++ b/Changes @@ -15,6 +15,8 @@ The contributors that suggested a given feature are shown in []. Thanks! **** Fix passing parameter type instantiations by position number. +**** Fix DPI open array handling issues. + * Verilator 4.106 2020-12-02 diff --git a/include/verilated_dpi.cpp b/include/verilated_dpi.cpp index c1cc63f10..eecffa3c3 100644 --- a/include/verilated_dpi.cpp +++ b/include/verilated_dpi.cpp @@ -37,11 +37,6 @@ //====================================================================== // Internal macros -// Not supported yet -#define _VL_SVDPI_UNIMP() \ - VL_FATAL_MT(__FILE__, __LINE__, "", \ - (std::string("%%Error: Unsupported DPI function: ") + VL_FUNC).c_str()) - #define _VL_SVDPI_WARN(...) VL_PRINTF_MT(__VA_ARGS__) // Function requires a "context" in the import declaration @@ -258,16 +253,6 @@ static void* _vl_sv_adjusted_datap(const VerilatedDpiOpenVar* varp, int nargs, i return datap; } -static int _vl_sv_adjusted_bit(const VerilatedDpiOpenVar* varp, int indx) { - if (VL_UNLIKELY(indx < varp->low(0) || indx > varp->high(0))) { - _VL_SVDPI_WARN("%%Warning: DPI svOpenArrayHandle function packed index out of bounds; %d " - "outside [%d:%d].\n", - indx, varp->left(0), varp->right(0)); - return 0; - } - return indx - varp->low(0); -} - /// Return pointer to simulator open array element, or nullptr if outside range static void* _vl_svGetArrElemPtr(const svOpenArrayHandle h, int nargs, int indx1, int indx2, int indx3) VL_MT_SAFE { @@ -299,10 +284,10 @@ static void _vl_svGetBitArrElemVecVal(svBitVecVal* d, const svOpenArrayHandle s, for (int i = 0; i < VL_WORDS_I(varp->packed().elements()); ++i) d[i] = wdatap[i]; return; } - default: + default: // LCOV_EXCL_START // Errored earlier _VL_SVDPI_WARN("%%Warning: DPI svOpenArrayHandle function unsupported datatype (%d).\n", varp->vltype()); - return; + return; // LCOV_EXCL_STOP } } /// Copy to user logic array from simulator open array @@ -330,7 +315,7 @@ static void _vl_svGetLogicArrElemVecVal(svLogicVecVal* d, const svOpenArrayHandl d[0].aval = lwp[0]; d[0].bval = 0; d[1].aval = lwp[1]; - d[0].bval = 0; + d[1].bval = 0; break; } case VLVT_WDATA: { @@ -341,10 +326,10 @@ static void _vl_svGetLogicArrElemVecVal(svLogicVecVal* d, const svOpenArrayHandl } return; } - default: + default: // LCOV_EXCL_START // Errored earlier _VL_SVDPI_WARN("%%Warning: DPI svOpenArrayHandle function unsupported datatype (%d).\n", varp->vltype()); - return; + return; // LCOV_EXCL_STOP } } @@ -364,10 +349,10 @@ static void _vl_svPutBitArrElemVecVal(const svOpenArrayHandle d, const svBitVecV for (int i = 0; i < VL_WORDS_I(varp->packed().elements()); ++i) wdatap[i] = s[i]; return; } - default: + default: // LCOV_EXCL_START // Errored earlier _VL_SVDPI_WARN("%%Warning: DPI svOpenArrayHandle function unsupported datatype (%d).\n", varp->vltype()); - return; + return; // LCOV_EXCL_STOP } } /// Copy to simulator open array from from user logic array @@ -388,10 +373,10 @@ static void _vl_svPutLogicArrElemVecVal(const svOpenArrayHandle d, const svLogic for (int i = 0; i < VL_WORDS_I(varp->packed().elements()); ++i) wdatap[i] = s[i].aval; return; } - default: + default: // LCOV_EXCL_START // Errored earlier _VL_SVDPI_WARN("%%Warning: DPI svOpenArrayHandle function unsupported datatype (%d).\n", varp->vltype()); - return; + return; // LCOV_EXCL_STOP } } @@ -400,31 +385,14 @@ static svBit _vl_svGetBitArrElem(const svOpenArrayHandle s, int nargs, int indx1 int indx3, int indx4) VL_MT_SAFE { // One extra index supported, as need bit number const VerilatedDpiOpenVar* varp = _vl_openhandle_varp(s); - void* datap; - int lsb; - if (varp->packed().elements()) { - datap = _vl_sv_adjusted_datap(varp, nargs - 1, indx1, indx2, indx3); - lsb = _vl_sv_adjusted_bit( - varp, ((nargs == 1) ? indx1 : (nargs == 2) ? indx2 : (nargs == 3) ? indx3 : indx4)); - } else { - datap = _vl_sv_adjusted_datap(varp, nargs, indx1, indx2, indx3); - lsb = 0; - } + void* datap = _vl_sv_adjusted_datap(varp, nargs, indx1, indx2, indx3); if (VL_UNLIKELY(!datap)) return 0; switch (varp->vltype()) { - case VLVT_UINT8: return (*(reinterpret_cast(datap)) >> lsb) & 1; - case VLVT_UINT16: return (*(reinterpret_cast(datap)) >> lsb) & 1; - case VLVT_UINT32: return (*(reinterpret_cast(datap)) >> lsb) & 1; - case VLVT_UINT64: - return (*(reinterpret_cast(datap)) >> static_cast(lsb)) & 1ULL; - case VLVT_WDATA: { - WDataOutP wdatap = (reinterpret_cast(datap)); - return VL_BITRSHIFT_W(wdatap, lsb) & 1; - } - default: + case VLVT_UINT8: return (*(reinterpret_cast(datap))) & 1; + default: // LCOV_EXCL_START // Errored earlier _VL_SVDPI_WARN("%%Warning: DPI svOpenArrayHandle function unsupported datatype (%d).\n", varp->vltype()); - return 0; + return 0; // LCOV_EXCL_STOP } } /// Update simulator open array from bit @@ -433,27 +401,14 @@ static void _vl_svPutBitArrElem(const svOpenArrayHandle d, svBit value, int narg // One extra index supported, as need bit number value &= 1; // Make sure clean const VerilatedDpiOpenVar* varp = _vl_openhandle_varp(d); - void* datap; - int lsb; - if (varp->packed().elements()) { - datap = _vl_sv_adjusted_datap(varp, nargs - 1, indx1, indx2, indx3); - lsb = _vl_sv_adjusted_bit( - varp, ((nargs == 1) ? indx1 : (nargs == 2) ? indx2 : (nargs == 3) ? indx3 : indx4)); - } else { - datap = _vl_sv_adjusted_datap(varp, nargs, indx1, indx2, indx3); - lsb = 0; - } + void* datap = _vl_sv_adjusted_datap(varp, nargs, indx1, indx2, indx3); if (VL_UNLIKELY(!datap)) return; switch (varp->vltype()) { - case VLVT_UINT8: VL_ASSIGNBIT_II(-1, lsb, *(reinterpret_cast(datap)), value); return; - case VLVT_UINT16: VL_ASSIGNBIT_II(-1, lsb, *(reinterpret_cast(datap)), value); return; - case VLVT_UINT32: VL_ASSIGNBIT_II(-1, lsb, *(reinterpret_cast(datap)), value); return; - case VLVT_UINT64: VL_ASSIGNBIT_QI(-1, lsb, *(reinterpret_cast(datap)), value); return; - case VLVT_WDATA: VL_ASSIGNBIT_WI(-1, lsb, (reinterpret_cast(datap)), value); return; - default: + case VLVT_UINT8: *(reinterpret_cast(datap)) = value; return; + default: // LCOV_EXCL_START // Errored earlier _VL_SVDPI_WARN("%%Warning: DPI svOpenArrayHandle function unsupported datatype (%d).\n", varp->vltype()); - return; + return; // LCOV_EXCL_STOP } } @@ -643,13 +598,6 @@ svBit svGetBitArrElem(const svOpenArrayHandle s, int indx1, ...) { out = _vl_svGetBitArrElem(s, 3, indx1, indx2, indx3, 0); break; } - case 4: { - int indx2 = va_arg(ap, int); - int indx3 = va_arg(ap, int); - int indx4 = va_arg(ap, int); - out = _vl_svGetBitArrElem(s, 4, indx1, indx2, indx3, indx4); - break; - } default: out = _vl_svGetBitArrElem(s, -1, 0, 0, 0, 0); break; // Will error } va_end(ap); @@ -683,13 +631,6 @@ svLogic svGetLogicArrElem(const svOpenArrayHandle s, int indx1, ...) { out = _vl_svGetBitArrElem(s, 3, indx1, indx2, indx3, 0); break; } - case 4: { - int indx2 = va_arg(ap, int); - int indx3 = va_arg(ap, int); - int indx4 = va_arg(ap, int); - out = _vl_svGetBitArrElem(s, 4, indx1, indx2, indx3, indx4); - break; - } default: out = _vl_svGetBitArrElem(s, -1, 0, 0, 0, 0); break; // Will error } va_end(ap); @@ -725,13 +666,6 @@ void svPutBitArrElem(const svOpenArrayHandle d, svBit value, int indx1, ...) { _vl_svPutBitArrElem(d, value, 3, indx1, indx2, indx3, 0); break; } - case 4: { - int indx2 = va_arg(ap, int); - int indx3 = va_arg(ap, int); - int indx4 = va_arg(ap, int); - _vl_svPutBitArrElem(d, value, 4, indx1, indx2, indx3, indx4); - break; - } default: _vl_svPutBitArrElem(d, value, -1, 0, 0, 0, 0); break; // Will error } va_end(ap); @@ -763,13 +697,6 @@ void svPutLogicArrElem(const svOpenArrayHandle d, svLogic value, int indx1, ...) _vl_svPutBitArrElem(d, value, 3, indx1, indx2, indx3, 0); break; } - case 4: { - int indx2 = va_arg(ap, int); - int indx3 = va_arg(ap, int); - int indx4 = va_arg(ap, int); - _vl_svPutBitArrElem(d, value, 4, indx1, indx2, indx3, indx4); - break; - } default: _vl_svPutBitArrElem(d, value, -1, 0, 0, 0, 0); break; // Will error } va_end(ap); diff --git a/include/vltstd/svdpi.h b/include/vltstd/svdpi.h index f77630af7..6b560e2cf 100644 --- a/include/vltstd/svdpi.h +++ b/include/vltstd/svdpi.h @@ -102,7 +102,7 @@ typedef uint32_t svBitVecVal; * Because the contents of the unused bits is undetermined, * the following macros can be handy. */ -#define SV_MASK(N) (~(-1 << (N))) +#define SV_MASK(N) (~(0xffffffffU << (N))) #define SV_GET_UNSIGNED_BITS(VALUE, N) \ ((N) == 32 ? (VALUE) : ((VALUE) & SV_MASK(N))) diff --git a/test_regress/t/t_dpi_open.v b/test_regress/t/t_dpi_open.v index 09bce4338..e78d01b3b 100644 --- a/test_regress/t/t_dpi_open.v +++ b/test_regress/t/t_dpi_open.v @@ -6,11 +6,11 @@ // Version 2.0. // SPDX-License-Identifier: LGPL-3.0-only OR Artistic-2.0 -`ifdef VERILATOR +//`ifdef VERILATOR `define checkh(gotv,expv) do if ((gotv) !== (expv)) begin $write("%%Error: %s:%0d: got='h%x exp='h%x\n", `__FILE__,`__LINE__, (gotv), (expv)); $stop; end while(0) -`else - `define checkh(gotv,expv) do if ((gotv) !== (expv)) begin $write("%%Error: %s:%0d: got='h%x exp='h%x\n", `__FILE__,`__LINE__, (gotv), (expv)); end while(0) -`endif +//`else +// `define checkh(gotv,expv) do if ((gotv) !== (expv)) begin $write("%%Error: %s:%0d: got='h%x exp='h%x\n", `__FILE__,`__LINE__, (gotv), (expv)); end while(0) +//`endif module t (/*AUTOARG*/); @@ -48,11 +48,8 @@ module t (/*AUTOARG*/); logic o_logic [1:0]; byte i_byte [1:0]; byte o_byte [1:0]; - int i_int [1:0]; - int o_int [1:0]; integer i_integer [1:0]; integer o_integer [1:0]; - // verilator lint_on UNUSED import "DPI-C" function int dpii_failure(); @@ -60,6 +57,7 @@ module t (/*AUTOARG*/); // [] on packed arrays is unsupported in VCS & NC, so not supporting this + // p is number of packed dimensions, u is number of unpacked dimensions import "DPI-C" function void dpii_open_p0_u1(input int c,p,u, input reg i [], output reg o []); import "DPI-C" function void dpii_open_p1_u1(input int c,p,u, input reg [1:-1] i [], output reg [1:-1] o []); import "DPI-C" function void dpii_open_p1_u2(input int c,p,u, input reg [1:-1] i [] [], output reg [1:-1] o [] []); @@ -72,10 +70,19 @@ module t (/*AUTOARG*/); import "DPI-C" function void dpii_open_bit(input bit i [], output bit o []); import "DPI-C" function void dpii_open_logic(input logic i [], output logic o []); import "DPI-C" function void dpii_open_byte(input byte i [], output byte o []); - import "DPI-C" function void dpii_open_int(input int i [], output int o []); import "DPI-C" function void dpii_open_integer(input integer i [], output integer o []); - import "DPI-C" function int dpii_failed(); + int i_int_u1 [2:-2]; + int o_int_u1 [2:-2]; + int i_int_u2 [2:-2] [-3:3]; + int o_int_u2 [2:-2] [-3:3]; + int i_int_u3 [2:-2] [-3:3] [4:-4]; + int o_int_u3 [2:-2] [-3:3] [4:-4]; + import "DPI-C" function void dpii_open_int_u1(int u, input int i [], output int o []); + import "DPI-C" function void dpii_open_int_u2(int u, input int i [] [], output int o [] []); + import "DPI-C" function void dpii_open_int_u3(int u, input int i [] [] [], output int o [] [] []); + + // verilator lint_on UNUSED reg [95:0] crc; @@ -86,7 +93,6 @@ module t (/*AUTOARG*/); i_bit[a] = crc[0]; i_logic[a] = crc[0]; i_byte[a] = crc[7:0]; - i_int[a] = crc[31:0]; i_integer[a] = crc[31:0]; crc = {crc[94:0], crc[95]^crc[2]^crc[0]}; end @@ -94,7 +100,6 @@ module t (/*AUTOARG*/); dpii_open_bit(i_bit, o_bit); dpii_open_logic(i_logic, o_logic); dpii_open_byte(i_byte, o_byte); - dpii_open_int(i_int, o_int); dpii_open_integer(i_integer, o_integer); for (int a=-2; a<=2; a=a+1) begin @@ -104,14 +109,17 @@ module t (/*AUTOARG*/); i_rl_p1_u1[a] = crc[2:0]; i_rb_p1_u1[a] = crc[2:0]; i_rw_p1_u1[a] = crc[94:0]; + i_int_u1[a] = crc[31:0]; for (int b=-3; b<=3; b=b+1) begin i_rl_p1_u2[a][b] = crc[2:0]; i_rb_p1_u2[a][b] = crc[2:0]; i_rw_p1_u2[a][b] = crc[94:0]; + i_int_u2[a][b] = crc[31:0]; for (int c=-4; c<=4; c=c+1) begin i_rl_p1_u3[a][b][c] = crc[2:0]; i_rb_p1_u3[a][b][c] = crc[2:0]; i_rw_p1_u3[a][b][c] = crc[94:0]; + i_int_u3[a][b][c] = crc[31:0]; crc = {crc[94:0], crc[95]^crc[2]^crc[0]}; end end @@ -138,6 +146,19 @@ module t (/*AUTOARG*/); end end + dpii_open_int_u1(1, i_int_u1, o_int_u1); + dpii_open_int_u2(2, i_int_u2, o_int_u2); + dpii_open_int_u3(3, i_int_u3, o_int_u3); + for (int a=-2; a<=2; a=a+1) begin + `checkh(o_int_u1[a], ~i_int_u1[a]); + for (int b=-3; b<=3; b=b+1) begin + `checkh(o_int_u2[a][b], ~i_int_u2[a][b]); + for (int c=-4; c<=4; c=c+1) begin + `checkh(o_int_u3[a][b][c], ~i_int_u3[a][b][c]); + end + end + end + if (dpii_failure()!=0) begin $write("%%Error: Failure in DPI tests\n"); $stop; diff --git a/test_regress/t/t_dpi_open_c.cpp b/test_regress/t/t_dpi_open_c.cpp index b4aa42c56..cff5d506a 100644 --- a/test_regress/t/t_dpi_open_c.cpp +++ b/test_regress/t/t_dpi_open_c.cpp @@ -62,44 +62,17 @@ extern void dpii_open_int(const svOpenArrayHandle i, const svOpenArrayHandle o); extern void dpii_open_integer(const svOpenArrayHandle i, const svOpenArrayHandle o); extern void dpii_open_logic(const svOpenArrayHandle i, const svOpenArrayHandle o); +extern void dpii_open_int_u1(int u, const svOpenArrayHandle i, const svOpenArrayHandle o); +extern void dpii_open_int_u2(int u, const svOpenArrayHandle i, const svOpenArrayHandle o); +extern void dpii_open_int_u3(int u, const svOpenArrayHandle i, const svOpenArrayHandle o); + extern int dpii_failure(); } #endif -//====================================================================== - -// Untested: -// void *svGetArrElemPtr(const svOpenArrayHandle, int indx1, ...); -// void svPutBitArrElemVecVal(const svOpenArrayHandle d, const svBitVecVal* s, int indx1, ...); -// void svPutBitArrElem1VecVal(const svOpenArrayHandle d, const svBitVecVal* s, int indx1); -// void svPutLogicArrElemVecVal(const svOpenArrayHandle d, const svLogicVecVal* s, int indx1, ...); -// void svPutLogicArrElem1VecVal(const svOpenArrayHandle d, const svLogicVecVal* s, int indx1); -// void svGetBitArrElemVecVal(svBitVecVal* d, const svOpenArrayHandle s, int indx1, ...); -// void svGetBitArrElem1VecVal(svBitVecVal* d, const svOpenArrayHandle s, int indx1); -// void svGetLogicArrElemVecVal(svLogicVecVal* d, const svOpenArrayHandle s, int indx1, ...); -// void svGetLogicArrElem1VecVal(svLogicVecVal* d, const svOpenArrayHandle s, int indx1); -// svBit svGetBitArrElem(const svOpenArrayHandle s, int indx1, ...); -// svBit svGetBitArrElem1(const svOpenArrayHandle s, int indx1); -// svLogic svGetLogicArrElem(const svOpenArrayHandle s, int indx1, ...); -// svLogic svGetLogicArrElem1(const svOpenArrayHandle s, int indx1); -// void svPutBitArrElem(const svOpenArrayHandle d, svBit value, int indx1, ...); -// void svPutBitArrElem1(const svOpenArrayHandle d, svBit value, int indx1); -// void svPutLogicArrElem(const svOpenArrayHandle d, svLogic value, int indx1, ...); -// void svPutLogicArrElem1(const svOpenArrayHandle d, svLogic value, int indx1); - -//====================================================================== - int failure = 0; int dpii_failure() { return failure; } -// clang-format off -#ifdef _WIN32 -# define T_PRI64 "I64" -#else // Linux or compliant Unix flavors -# define T_PRI64 "ll" -#endif -// clang-format on - #define CHECK_RESULT_HEX(got, exp) \ do { \ if ((got) != (exp)) { \ @@ -122,8 +95,8 @@ void dpii_unused(const svOpenArrayHandle u) {} void _dpii_all(int c, int p, int u, const svOpenArrayHandle i, const svOpenArrayHandle o) { #ifdef TEST_VERBOSE - printf("-:%s:%d: For case c=%d p=%d u=%d data=%p\n", // - __FILE__, __LINE__, c, p, u, svGetArrayPtr(i)); + fprintf(stderr, "-:%s:%d: For case c=%d p=%d u=%d data=%p\n", // + __FILE__, __LINE__, c, p, u, svGetArrayPtr(i)); #endif (void)svGetArrayPtr(i); #ifndef NC @@ -260,18 +233,63 @@ void dpii_open_byte(const svOpenArrayHandle i, const svOpenArrayHandle o) { #endif } -void dpii_open_int(const svOpenArrayHandle i, const svOpenArrayHandle o) { +void dpii_open_integer(const svOpenArrayHandle i, const svOpenArrayHandle o) {} +void dpii_open_logic(const svOpenArrayHandle i, const svOpenArrayHandle o) {} + +static void _dpii_open_int_ux(int u, const svOpenArrayHandle i, const svOpenArrayHandle o) { intptr_t arrPtr = (intptr_t)svGetArrayPtr(i); CHECK_RESULT_HEX_NE(arrPtr, 0); // All the arrays should actually exist #ifndef NC // NC always returns zero and warns int sizeInputOfArray = svSizeOfArray(i); CHECK_RESULT_HEX_NE(sizeInputOfArray, 0); // None of the test cases have zero size - CHECK_RESULT_HEX_NE(svDimensions(i), 0); // All the test cases are unpacked arrays + CHECK_RESULT_HEX(svDimensions(i), u); #endif + + int dim = svDimensions(i); + + for (int a = svLow(i, 1); a <= svHigh(i, 1); ++a) { + if (dim == 1) { + intptr_t ip = (intptr_t)svGetArrElemPtr(i, a); + intptr_t i2p = (intptr_t)svGetArrElemPtr1(i, a); + CHECK_RESULT_HEX(ip, i2p); + CHECK_RESULT_HEX_NE(ip, 0); + intptr_t op = (intptr_t)svGetArrElemPtr(o, a); + CHECK_RESULT_HEX_NE(op, 0); + *reinterpret_cast(op) = ~*reinterpret_cast(ip); + } else { + for (int b = svLow(i, 2); b <= svHigh(i, 2); ++b) { + if (dim == 2) { + intptr_t ip = (intptr_t)svGetArrElemPtr(i, a, b); + intptr_t i2p = (intptr_t)svGetArrElemPtr2(i, a, b); + CHECK_RESULT_HEX(ip, i2p); + CHECK_RESULT_HEX_NE(ip, 0); + intptr_t op = (intptr_t)svGetArrElemPtr(o, a, b); + CHECK_RESULT_HEX_NE(op, 0); + *reinterpret_cast(op) = ~*reinterpret_cast(ip); + } else { + for (int c = svLow(i, 3); c <= svHigh(i, 3); ++c) { + if (dim == 3) { + intptr_t ip = (intptr_t)svGetArrElemPtr(i, a, b, c); + intptr_t i2p = (intptr_t)svGetArrElemPtr3(i, a, b, c); + CHECK_RESULT_HEX(ip, i2p); + CHECK_RESULT_HEX_NE(ip, 0); + intptr_t op = (intptr_t)svGetArrElemPtr(o, a, b, c); + CHECK_RESULT_HEX_NE(op, 0); + *reinterpret_cast(op) = ~*reinterpret_cast(ip); + } + } + } + } + } + } +} +void dpii_open_int_u1(int u, const svOpenArrayHandle i, const svOpenArrayHandle o) { + _dpii_open_int_ux(u, i, o); +} +void dpii_open_int_u2(int u, const svOpenArrayHandle i, const svOpenArrayHandle o) { + _dpii_open_int_ux(u, i, o); +} +void dpii_open_int_u3(int u, const svOpenArrayHandle i, const svOpenArrayHandle o) { + _dpii_open_int_ux(u, i, o); } - -void dpii_open_integer(const svOpenArrayHandle i, const svOpenArrayHandle o) {} -void dpii_open_logic(const svOpenArrayHandle i, const svOpenArrayHandle o) {} - -int dpii_failed() { return failure; } diff --git a/test_regress/t/t_dpi_open_elem.pl b/test_regress/t/t_dpi_open_elem.pl new file mode 100755 index 000000000..ab9367bf0 --- /dev/null +++ b/test_regress/t/t_dpi_open_elem.pl @@ -0,0 +1,23 @@ +#!/usr/bin/env perl +if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); die; } +# DESCRIPTION: Verilator: Verilog Test driver/expect definition +# +# Copyright 2003 by Wilson Snyder. This program is free software; you +# can redistribute it and/or modify it under the terms of either the GNU +# Lesser General Public License Version 3 or the Perl Artistic License +# Version 2.0. +# SPDX-License-Identifier: LGPL-3.0-only OR Artistic-2.0 + +scenarios(simulator => 1); + +compile( + v_flags2 => ["t/t_dpi_open_elem_c.cpp"], + verilator_flags2 => ["-Wall -Wno-DECLFILENAME -unroll-count 1"], + ); + +execute( + check_finished => 1, + ); + +ok(1); +1; diff --git a/test_regress/t/t_dpi_open_elem.v b/test_regress/t/t_dpi_open_elem.v new file mode 100644 index 000000000..c2b38f00a --- /dev/null +++ b/test_regress/t/t_dpi_open_elem.v @@ -0,0 +1,118 @@ +// DESCRIPTION: Verilator: Verilog Test module +// +// Copyright 2017 by Wilson Snyder. This program is free software; you can +// redistribute it and/or modify it under the terms of either the GNU +// Lesser General Public License Version 3 or the Perl Artistic License +// Version 2.0. +// SPDX-License-Identifier: LGPL-3.0-only OR Artistic-2.0 + + `define checkh(gotv,expv) do if ((gotv) !== (expv)) begin $write("%%Error: %s:%0d: got='h%x exp='h%x\n", `__FILE__,`__LINE__, (gotv), (expv)); $stop; end while(0) + +module t (/*AUTOARG*/); + + bit i_bit_p0_u1 [2:-2]; + bit o_bit_p0_u1 [2:-2]; + bit q_bit_p0_u1 [2:-2]; + bit i_bit_p0_u2 [2:-2] [-3:3]; + bit o_bit_p0_u2 [2:-2] [-3:3]; + bit q_bit_p0_u2 [2:-2] [-3:3]; + bit i_bit_p0_u3 [2:-2] [-3:3] [4:-4]; + bit o_bit_p0_u3 [2:-2] [-3:3] [4:-4]; + bit q_bit_p0_u3 [2:-2] [-3:3] [4:-4]; + import "DPI-C" function void dpii_bit_elem_p0_u1 + (int p, int u, input bit i [], output bit o [], output bit q []); + import "DPI-C" function void dpii_bit_elem_p0_u2 + (int p, int u, input bit i [] [], output bit o [] [], output bit q [] []); + import "DPI-C" function void dpii_bit_elem_p0_u3 + (int p, int u, input bit i [] [] [], output bit o [] [] [], output bit q [] [] []); + + logic i_logic_p0_u1 [2:-2]; + logic o_logic_p0_u1 [2:-2]; + logic q_logic_p0_u1 [2:-2]; + logic i_logic_p0_u2 [2:-2] [-3:3]; + logic o_logic_p0_u2 [2:-2] [-3:3]; + logic q_logic_p0_u2 [2:-2] [-3:3]; + logic i_logic_p0_u3 [2:-2] [-3:3] [4:-4]; + logic o_logic_p0_u3 [2:-2] [-3:3] [4:-4]; + logic q_logic_p0_u3 [2:-2] [-3:3] [4:-4]; + import "DPI-C" function void dpii_logic_elem_p0_u1(int p, int u, input logic i [], + output logic o [], output logic q []); + import "DPI-C" function void dpii_logic_elem_p0_u2(int p, int u, input logic i [] [], + output logic o [] [], output logic q [] []); + import "DPI-C" function void dpii_logic_elem_p0_u3(int p, int u, input logic i [] [] [], + output logic o [] [] [], output logic q [] [] []); + + import "DPI-C" function int dpii_failure(); + + reg [95:0] crc; + + initial begin + crc = 96'h8a10a572_5aef0c8d_d70a4497; + + begin + for (int a=-2; a<=2; a=a+1) begin + i_bit_p0_u1[a] = crc[0]; + for (int b=-3; b<=3; b=b+1) begin + i_bit_p0_u2[a][b] = crc[0]; + for (int c=-4; c<=4; c=c+1) begin + i_bit_p0_u3[a][b][c] = crc[0]; + crc = {crc[94:0], crc[95]^crc[2]^crc[0]}; + end + end + end + dpii_bit_elem_p0_u1(0, 1, i_bit_p0_u1, o_bit_p0_u1, q_bit_p0_u1); + dpii_bit_elem_p0_u2(0, 2, i_bit_p0_u2, o_bit_p0_u2, q_bit_p0_u2); + dpii_bit_elem_p0_u3(0, 3, i_bit_p0_u3, o_bit_p0_u3, q_bit_p0_u3); + for (int a=-2; a<=2; a=a+1) begin + `checkh(o_bit_p0_u1[a], ~i_bit_p0_u1[a]); + `checkh(q_bit_p0_u1[a], ~i_bit_p0_u1[a]); + for (int b=-3; b<=3; b=b+1) begin + `checkh(o_bit_p0_u2[a][b], ~i_bit_p0_u2[a][b]); + `checkh(q_bit_p0_u2[a][b], ~i_bit_p0_u2[a][b]); + for (int c=-4; c<=4; c=c+1) begin + `checkh(o_bit_p0_u3[a][b][c], ~i_bit_p0_u3[a][b][c]); + `checkh(q_bit_p0_u3[a][b][c], ~i_bit_p0_u3[a][b][c]); + end + end + end + end + + begin + for (int a=-2; a<=2; a=a+1) begin + i_logic_p0_u1[a] = crc[0]; + for (int b=-3; b<=3; b=b+1) begin + i_logic_p0_u2[a][b] = crc[0]; + for (int c=-4; c<=4; c=c+1) begin + i_logic_p0_u3[a][b][c] = crc[0]; + crc = {crc[94:0], crc[95]^crc[2]^crc[0]}; + end + end + end + dpii_logic_elem_p0_u1(0, 1, i_logic_p0_u1, o_logic_p0_u1, q_logic_p0_u1); + dpii_logic_elem_p0_u2(0, 2, i_logic_p0_u2, o_logic_p0_u2, q_logic_p0_u2); + dpii_logic_elem_p0_u3(0, 3, i_logic_p0_u3, o_logic_p0_u3, q_logic_p0_u3); + for (int a=-2; a<=2; a=a+1) begin + `checkh(o_logic_p0_u1[a], ~i_logic_p0_u1[a]); + `checkh(q_logic_p0_u1[a], ~i_logic_p0_u1[a]); + for (int b=-3; b<=3; b=b+1) begin + `checkh(o_logic_p0_u2[a][b], ~i_logic_p0_u2[a][b]); + `checkh(q_logic_p0_u2[a][b], ~i_logic_p0_u2[a][b]); + for (int c=-4; c<=4; c=c+1) begin + `checkh(o_logic_p0_u3[a][b][c], ~i_logic_p0_u3[a][b][c]); + `checkh(q_logic_p0_u3[a][b][c], ~i_logic_p0_u3[a][b][c]); + end + end + end + end + + if (dpii_failure()!=0) begin + $write("%%Error: Failure in DPI tests\n"); + $stop; + end + else begin + $write("*-* All Finished *-*\n"); + $finish; + end + end + +endmodule diff --git a/test_regress/t/t_dpi_open_elem_c.cpp b/test_regress/t/t_dpi_open_elem_c.cpp new file mode 100644 index 000000000..72a8793a4 --- /dev/null +++ b/test_regress/t/t_dpi_open_elem_c.cpp @@ -0,0 +1,188 @@ +// -*- mode: C++; c-file-style: "cc-mode" -*- +//************************************************************************* +// +// Copyright 2009-2017 by Wilson Snyder. This program is free software; you can +// redistribute it and/or modify it under the terms of either the GNU +// Lesser General Public License Version 3 or the Perl Artistic License +// Version 2.0. +// SPDX-License-Identifier: LGPL-3.0-only OR Artistic-2.0 +// +//************************************************************************* + +#include +#include +#include +#include "svdpi.h" + +//====================================================================== + +// clang-format off +#if defined(VERILATOR) +# include "Vt_dpi_open_elem__Dpi.h" +#elif defined(VCS) +# include "../vc_hdrs.h" +#elif defined(NC) +# define NEED_EXTERNS +// #elif defined(MS) +// # define NEED_EXTERNS +#else +# error "Unknown simulator for DPI test" +#endif +// clang-format on + +#ifdef NEED_EXTERNS +extern "C" { +// If get ncsim: *F,NOFDPI: Function {foo} not found in default libdpi. +// Then probably forgot to list a function here. + +void dpii_bit_elem_p0_u1(int p, int u, const svOpenArrayHandle i, const svOpenArrayHandle o, + const svOpenArrayHandle q); +void dpii_bit_elem_p0_u2(int p, int u, const svOpenArrayHandle i, const svOpenArrayHandle o, + const svOpenArrayHandle q); +void dpii_bit_elem_p0_u3(int p, int u, const svOpenArrayHandle i, const svOpenArrayHandle o, + const svOpenArrayHandle q); +void dpii_logic_elem_p0_u1(int p, int u, const svOpenArrayHandle i, const svOpenArrayHandle o, + const svOpenArrayHandle q); +void dpii_logic_elem_p0_u2(int p, int u, const svOpenArrayHandle i, const svOpenArrayHandle o, + const svOpenArrayHandle q); +void dpii_logic_elem_p0_u3(int p, int u, const svOpenArrayHandle i, const svOpenArrayHandle o, + const svOpenArrayHandle q); + +extern int dpii_failure(); +} +#endif + +int failure = 0; +int dpii_failure() { return failure; } + +#define CHECK_RESULT_HEX(got, exp) \ + do { \ + if ((got) != (exp)) { \ + std::cout << std::dec << "%Error: " << __FILE__ << ":" << __LINE__ << std::hex \ + << ": GOT=" << (got) << " EXP=" << (exp) << std::endl; \ + failure = __LINE__; \ + } \ + } while (0) + +#define CHECK_RESULT_HEX_NE(got, exp) \ + do { \ + if ((got) == (exp)) { \ + std::cout << std::dec << "%Error: " << __FILE__ << ":" << __LINE__ << std::hex \ + << ": GOT=" << (got) << " EXP!=" << (exp) << std::endl; \ + failure = __LINE__; \ + } \ + } while (0) + +void dpii_unused(const svOpenArrayHandle u) {} + +//====================================================================== + +static void _dpii_bit_elem_ux(int p, int u, const svOpenArrayHandle i, const svOpenArrayHandle o, + const svOpenArrayHandle q) { + int dim = svDimensions(i); +#ifndef NC + // NC always returns zero and warns + CHECK_RESULT_HEX(dim, u); + // svSizeOfArray(i) undeterministic as not in C representation +#endif + + for (int a = svLow(i, 1); a <= svHigh(i, 1); ++a) { + fflush(stdout); + if (dim == 1) { + svBit v = svGetBitArrElem(i, a); + svBit v2 = svGetBitArrElem1(i, a); + CHECK_RESULT_HEX(v, v2); + svPutBitArrElem(o, v ? 0 : 1, a); + svPutBitArrElem1(q, v ? 0 : 1, a); + } else { + for (int b = svLow(i, 2); b <= svHigh(i, 2); ++b) { + if (dim == 2) { + svBit v = svGetBitArrElem(i, a, b); + svBit v2 = svGetBitArrElem2(i, a, b); + CHECK_RESULT_HEX(v, v2); + svPutBitArrElem(o, v ? 0 : 1, a, b); + svPutBitArrElem2(q, v ? 0 : 1, a, b); + } else { + for (int c = svLow(i, 3); c <= svHigh(i, 3); ++c) { + if (dim == 3) { + svBit v = svGetBitArrElem(i, a, b, c); + svBit v2 = svGetBitArrElem3(i, a, b, c); + CHECK_RESULT_HEX(v, v2); + svPutBitArrElem(o, v ? 0 : 1, a, b, c); + svPutBitArrElem3(q, v ? 0 : 1, a, b, c); + } + } + } + } + } + } + fflush(stdout); +} +void dpii_bit_elem_p0_u1(int p, int u, const svOpenArrayHandle i, const svOpenArrayHandle o, + const svOpenArrayHandle q) { + _dpii_bit_elem_ux(p, u, i, o, q); +} +void dpii_bit_elem_p0_u2(int p, int u, const svOpenArrayHandle i, const svOpenArrayHandle o, + const svOpenArrayHandle q) { + _dpii_bit_elem_ux(p, u, i, o, q); +} +void dpii_bit_elem_p0_u3(int p, int u, const svOpenArrayHandle i, const svOpenArrayHandle o, + const svOpenArrayHandle q) { + _dpii_bit_elem_ux(p, u, i, o, q); +} + +//====================================================================== + +static void _dpii_logic_elem_ux(int p, int u, const svOpenArrayHandle i, const svOpenArrayHandle o, + const svOpenArrayHandle q) { + int sizeInputOfArray = svSizeOfArray(i); + int dim = svDimensions(i); +#ifndef NC + // NC always returns zero and warns + CHECK_RESULT_HEX(dim, u); + // svSizeOfArray(i) undeterministic as not in C representation +#endif + + for (int a = svLow(i, 1); a <= svHigh(i, 1); ++a) { + if (dim == 1) { + svLogic v = svGetLogicArrElem(i, a); + svLogic v2 = svGetLogicArrElem1(i, a); + CHECK_RESULT_HEX(v, v2); + svPutLogicArrElem(o, v ? 0 : 1, a); + svPutLogicArrElem1(q, v ? 0 : 1, a); + } else { + for (int b = svLow(i, 2); b <= svHigh(i, 2); ++b) { + if (dim == 2) { + svLogic v = svGetLogicArrElem(i, a, b); + svLogic v2 = svGetLogicArrElem2(i, a, b); + CHECK_RESULT_HEX(v, v2); + svPutLogicArrElem(o, v ? 0 : 1, a, b); + svPutLogicArrElem2(q, v ? 0 : 1, a, b); + } else { + for (int c = svLow(i, 3); c <= svHigh(i, 3); ++c) { + if (dim == 3) { + svLogic v = svGetLogicArrElem(i, a, b, c); + svLogic v2 = svGetLogicArrElem3(i, a, b, c); + CHECK_RESULT_HEX(v, v2); + svPutLogicArrElem(o, v ? 0 : 1, a, b, c); + svPutLogicArrElem3(q, v ? 0 : 1, a, b, c); + } + } + } + } + } + } + fflush(stdout); +} +void dpii_logic_elem_p0_u1(int p, int u, const svOpenArrayHandle i, const svOpenArrayHandle o, + const svOpenArrayHandle q) { + _dpii_logic_elem_ux(p, u, i, o, q); +} +void dpii_logic_elem_p0_u2(int p, int u, const svOpenArrayHandle i, const svOpenArrayHandle o, + const svOpenArrayHandle q) { + _dpii_logic_elem_ux(p, u, i, o, q); +} +void dpii_logic_elem_p0_u3(int p, int u, const svOpenArrayHandle i, const svOpenArrayHandle o, + const svOpenArrayHandle q) { + _dpii_logic_elem_ux(p, u, i, o, q); +} diff --git a/test_regress/t/t_dpi_open_oob_bad.out b/test_regress/t/t_dpi_open_oob_bad.out new file mode 100644 index 000000000..a40343874 --- /dev/null +++ b/test_regress/t/t_dpi_open_oob_bad.out @@ -0,0 +1,27 @@ +dpii_nullptr: +dpii_int_u3: +%Warning: DPI svOpenArrayHandle function index 3 out of bounds; 1 outside [4:-4]. +%Warning: DPI svOpenArrayHandle function index 2 out of bounds; 20 outside [-3:3]. +%Warning: DPI svOpenArrayHandle function index 1 out of bounds; 10 outside [2:-2]. +%Warning: DPI svOpenArrayHandle function called on 3 dimensional array using 1 dimensional function. +dpii_real_u1: +%Warning: DPI svOpenArrayHandle function unsupported datatype (5). +%Warning: DPI svOpenArrayHandle function unsupported datatype (5). +%Warning: DPI svOpenArrayHandle function unsupported datatype (5). +%Warning: DPI svOpenArrayHandle function unsupported datatype (5). +%Warning: DPI svOpenArrayHandle function unsupported datatype (5). +%Warning: DPI svOpenArrayHandle function unsupported datatype (5). +%Warning: DPI svOpenArrayHandle function unsupported datatype (5). +%Warning: DPI svOpenArrayHandle function unsupported datatype (5). +dpii_bit_u6: +%Warning: DPI svOpenArrayHandle function called on 6 dimensional array using -1 dimensional function. +%Warning: DPI svOpenArrayHandle function called on 6 dimensional array using -1 dimensional function. +%Warning: DPI svOpenArrayHandle function called on 6 dimensional array using -1 dimensional function. +%Warning: DPI svOpenArrayHandle function called on 6 dimensional array using -1 dimensional function. +%Warning: DPI svOpenArrayHandle function called on 6 dimensional array using -1 dimensional function. +%Warning: DPI svOpenArrayHandle function called on 6 dimensional array using -1 dimensional function. +%Warning: DPI svOpenArrayHandle function called on 6 dimensional array using -1 dimensional function. +%Warning: DPI svOpenArrayHandle function called on 6 dimensional array using -1 dimensional function. +dpii_real_u6: +%Warning: DPI svOpenArrayHandle function called on 6 dimensional array using -1 dimensional function. +*-* All Finished *-* diff --git a/test_regress/t/t_dpi_open_oob_bad.pl b/test_regress/t/t_dpi_open_oob_bad.pl new file mode 100755 index 000000000..8f02d74a8 --- /dev/null +++ b/test_regress/t/t_dpi_open_oob_bad.pl @@ -0,0 +1,24 @@ +#!/usr/bin/env perl +if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); die; } +# DESCRIPTION: Verilator: Verilog Test driver/expect definition +# +# Copyright 2003 by Wilson Snyder. This program is free software; you +# can redistribute it and/or modify it under the terms of either the GNU +# Lesser General Public License Version 3 or the Perl Artistic License +# Version 2.0. +# SPDX-License-Identifier: LGPL-3.0-only OR Artistic-2.0 + +scenarios(vlt => 1); + +compile( + v_flags2 => ["t/t_dpi_open_oob_bad_c.cpp"], + verilator_flags2 => ["-Wall -Wno-DECLFILENAME -unroll-count 1"], + ); + +execute( + fails => 0, # DPI warnings are not errors + expect_filename => $Self->{golden_filename}, + ); + +ok(1); +1; diff --git a/test_regress/t/t_dpi_open_oob_bad.v b/test_regress/t/t_dpi_open_oob_bad.v new file mode 100644 index 000000000..579ac523e --- /dev/null +++ b/test_regress/t/t_dpi_open_oob_bad.v @@ -0,0 +1,40 @@ +// DESCRIPTION: Verilator: Verilog Test module +// +// Copyright 2020 by Wilson Snyder. This program is free software; you can +// redistribute it and/or modify it under the terms of either the GNU +// Lesser General Public License Version 3 or the Perl Artistic License +// Version 2.0. +// SPDX-License-Identifier: LGPL-3.0-only OR Artistic-2.0 + +module t (/*AUTOARG*/); + + import "DPI-C" function void dpii_nullptr(); + + // verilator lint_off UNDRIVEN + int i_int_u3 [2:-2] [-3:3] [4:-4]; + import "DPI-C" function void dpii_int_u3(input int i [] [] []); + + real i_real_u1 [1:0]; + import "DPI-C" function void dpii_real_u1(input real i []); + + bit i_u6 [2][2][2][2][2][2]; + import "DPI-C" function void dpii_bit_u6(input bit i [][][][][][]); + + real i_real_u6 [2][2][2][2][2][2]; + import "DPI-C" function void dpii_real_u6(input real i [][][][][][]); + + initial begin + i_int_u3[0][0][0] = 32'hbad; + i_real_u1[0] = 1.1; + i_u6[0][0][0][0][0][0] = 1'b1; + + dpii_nullptr(); + dpii_int_u3(i_int_u3); + dpii_real_u1(i_real_u1); + dpii_bit_u6(i_u6); + dpii_real_u6(i_real_u6); + $write("*-* All Finished *-*\n"); + $finish; + end + +endmodule diff --git a/test_regress/t/t_dpi_open_oob_bad_c.cpp b/test_regress/t/t_dpi_open_oob_bad_c.cpp new file mode 100644 index 000000000..5ed9853c0 --- /dev/null +++ b/test_regress/t/t_dpi_open_oob_bad_c.cpp @@ -0,0 +1,156 @@ +// -*- mode: C++; c-file-style: "cc-mode" -*- +//************************************************************************* +// +// Copyright 2009-2020 by Wilson Snyder. This program is free software; you can +// redistribute it and/or modify it under the terms of either the GNU +// Lesser General Public License Version 3 or the Perl Artistic License +// Version 2.0. +// SPDX-License-Identifier: LGPL-3.0-only OR Artistic-2.0 +// +//************************************************************************* + +#include +#include +#include +#include "svdpi.h" + +//====================================================================== + +// clang-format off +#if defined(VERILATOR) +# include "Vt_dpi_open_oob_bad__Dpi.h" +#else +# error "Unknown simulator for DPI test" +#endif +// clang-format on + +#define CHECK_RESULT_HEX(got, exp) \ + do { \ + if ((got) != (exp)) { \ + std::cout << std::dec << "%Error: " << __FILE__ << ":" << __LINE__ << std::hex \ + << ": GOT=" << (got) << " EXP=" << (exp) << std::endl; \ + failure = __LINE__; \ + } \ + } while (0) + +#define CHECK_RESULT_HEX_NE(got, exp) \ + do { \ + if ((got) == (exp)) { \ + std::cout << std::dec << "%Error: " << __FILE__ << ":" << __LINE__ << std::hex \ + << ": GOT=" << (got) << " EXP!=" << (exp) << std::endl; \ + failure = __LINE__; \ + } \ + } while (0) + +//====================================================================== + +int failure = 0; + +void dpii_nullptr() { + printf("%s:\n", __func__); + // These cause fatal errors, so each would need a separate run + // svOpenArrayHandle h = nullptr; + // svBitVecVal bit_vec_val[2]; + // svLogicVecVal logic_vec_val[2]; + // svDimensions(h); + // svGetArrayPtr(h); + // svHigh(h, 0); + // svIncrement(h, 0); + // svLeft(h, 0); + // svLow(h, 0); + // svRight(h, 0); + // svSize(h, 0); + // svSizeOfArray(h); + // + // svGetArrElemPtr(h, 0); + // svGetArrElemPtr1(h, 0); + // svGetArrElemPtr2(h, 0, 0); + // svGetArrElemPtr3(h, 0, 0, 0); + // svGetBitArrElem(h, 0); + // svGetBitArrElem1(h, 0); + // svGetBitArrElem1VecVal(bit_vec_val, h, 0); + // svGetBitArrElem2(h, 0, 0); + // svGetBitArrElem2VecVal(bit_vec_val, h, 0, 0); + // svGetBitArrElem3(h, 0, 0, 0); + // svGetBitArrElem3VecVal(bit_vec_val, h, 0, 0, 0); + // svGetBitArrElemVecVal(bit_vec_val, h, 0); + // svGetLogicArrElem(h, 0); + // svGetLogicArrElem1(h, 0); + // svGetLogicArrElem1VecVal(logic_vec_val, h, 0); + // svGetLogicArrElem2(h, 0, 0); + // svGetLogicArrElem2VecVal(logic_vec_val, h, 0, 0); + // svGetLogicArrElem3(h, 0, 0, 0); + // svGetLogicArrElem3VecVal(logic_vec_val, h, 0, 0, 0); + // svGetLogicArrElemVecVal(logic_vec_val, h, 0); + // svPutBitArrElem(h, 0, 0); + // svPutBitArrElem1(h, 0, 0); + // svPutBitArrElem1VecVal(h, bit_vec_val, 0); + // svPutBitArrElem2(h, 0, 0, 0); + // svPutBitArrElem2VecVal(h, bit_vec_val, 0, 0); + // svPutBitArrElem3(h, 0, 0, 0, 0); + // svPutBitArrElem3VecVal(h, bit_vec_val, 0, 0, 0); + // svPutBitArrElemVecVal(h, bit_vec_val, 0); + // svPutLogicArrElem(h, 0, 0); + // svPutLogicArrElem1(h, 0, 0); + // svPutLogicArrElem1VecVal(h, logic_vec_val, 0); + // svPutLogicArrElem2(h, 0, 0, 0); + // svPutLogicArrElem2VecVal(h, logic_vec_val, 0, 0); + // svPutLogicArrElem3(h, 0, 0, 0, 0); + // svPutLogicArrElem3VecVal(h, logic_vec_val, 0, 0, 0); + // svPutLogicArrElemVecVal(h, logic_vec_val, 0); +} + +void dpii_int_u3(const svOpenArrayHandle i) { + printf("%s:\n", __func__); + // Correct usage + intptr_t ip = (intptr_t)svGetArrElemPtr3(i, 1, 2, 3); + CHECK_RESULT_HEX_NE(ip, 0); + // Out of bounds + ip = (intptr_t)svGetArrElemPtr3(i, 1, 2, 30); + ip = (intptr_t)svGetArrElemPtr3(i, 1, 20, 3); + ip = (intptr_t)svGetArrElemPtr3(i, 10, 2, 3); + ip = (intptr_t)svGetArrElemPtr1(i, 30); +} + +void dpii_real_u1(const svOpenArrayHandle i) { + printf("%s:\n", __func__); + svBitVecVal bit_vec_val[4]; + svLogicVecVal logic_vec_val[4]; + + svGetBitArrElem(i, 0); + svGetBitArrElem1(i, 0); + svGetBitArrElem1VecVal(bit_vec_val, i, 0); + svGetBitArrElemVecVal(bit_vec_val, i, 0); + svGetLogicArrElem(i, 0); + svGetLogicArrElem1(i, 0); + svGetLogicArrElem1VecVal(logic_vec_val, i, 0); + svGetLogicArrElemVecVal(logic_vec_val, i, 0); + svPutBitArrElem(i, 0, 0); + svPutBitArrElem1(i, 0, 0); + svPutBitArrElem1VecVal(i, bit_vec_val, 0); + svPutBitArrElemVecVal(i, bit_vec_val, 0); + svPutLogicArrElem(i, 0, 0); + svPutLogicArrElem1(i, 0, 0); + svPutLogicArrElem1VecVal(i, logic_vec_val, 0); + svPutLogicArrElemVecVal(i, logic_vec_val, 0); +} + +void dpii_bit_u6(const svOpenArrayHandle i) { + printf("%s:\n", __func__); + svBitVecVal bit_vec_val[4]; + svLogicVecVal logic_vec_val[4]; + + svGetBitArrElem(i, 0, 0, 0, 0, 0, 0); + svGetBitArrElemVecVal(bit_vec_val, i, 0, 0, 0, 0, 0, 0); + svGetLogicArrElem(i, 0, 0, 0, 0, 0, 0); + svGetLogicArrElemVecVal(logic_vec_val, i, 0, 0, 0, 0, 0, 0); + svPutBitArrElem(i, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0); + svPutBitArrElemVecVal(i, bit_vec_val, 0, 0, 0, 0, 0, 0); + svPutLogicArrElem(i, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0); + svPutLogicArrElemVecVal(i, logic_vec_val, 0, 0, 0, 0, 0, 0); +} + +void dpii_real_u6(const svOpenArrayHandle i) { + printf("%s:\n", __func__); + svGetArrElemPtr(i, 0, 0, 0, 0, 0, 0); +} diff --git a/test_regress/t/t_dpi_open_vecval.pl b/test_regress/t/t_dpi_open_vecval.pl new file mode 100755 index 000000000..542b88469 --- /dev/null +++ b/test_regress/t/t_dpi_open_vecval.pl @@ -0,0 +1,23 @@ +#!/usr/bin/env perl +if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); die; } +# DESCRIPTION: Verilator: Verilog Test driver/expect definition +# +# Copyright 2003 by Wilson Snyder. This program is free software; you +# can redistribute it and/or modify it under the terms of either the GNU +# Lesser General Public License Version 3 or the Perl Artistic License +# Version 2.0. +# SPDX-License-Identifier: LGPL-3.0-only OR Artistic-2.0 + +scenarios(simulator => 1); + +compile( + v_flags2 => ["t/t_dpi_open_vecval_c.cpp"], + verilator_flags2 => ["-Wall -Wno-DECLFILENAME -unroll-count 1"], + ); + +execute( + check_finished => 1, + ); + +ok(1); +1; diff --git a/test_regress/t/t_dpi_open_vecval.v b/test_regress/t/t_dpi_open_vecval.v new file mode 100644 index 000000000..8954f872a --- /dev/null +++ b/test_regress/t/t_dpi_open_vecval.v @@ -0,0 +1,156 @@ +// DESCRIPTION: Verilator: Verilog Test module +// +// Copyright 2017 by Wilson Snyder. This program is free software; you can +// redistribute it and/or modify it under the terms of either the GNU +// Lesser General Public License Version 3 or the Perl Artistic License +// Version 2.0. +// SPDX-License-Identifier: LGPL-3.0-only OR Artistic-2.0 + + `define checkh(gotv,expv) do if ((gotv) !== (expv)) begin $write("%%Error: %s:%0d: got='h%x exp='h%x\n", `__FILE__,`__LINE__, (gotv), (expv)); $stop; end while(0) + +module t (/*AUTOARG*/); + + // Note that a packed array is required, otherwise some simulators will return bad + // results using *ElemVecVal() routines instead of scalar *Elem() routines. + bit [0:0] i_bit_p1_u1 [2:-2]; + bit [0:0] o_bit_p1_u1 [2:-2]; + bit [0:0] q_bit_p1_u1 [2:-2]; + bit [60:0] i_bit61_p1_u1 [2:-2]; + bit [60:0] o_bit61_p1_u1 [2:-2]; + bit [60:0] q_bit61_p1_u1 [2:-2]; + bit [91:0] i_bit92_p1_u1 [2:-2]; + bit [91:0] o_bit92_p1_u1 [2:-2]; + bit [91:0] q_bit92_p1_u1 [2:-2]; + bit [11:0] i_bit12_p1_u2 [2:-2] [-3:3]; + bit [11:0] o_bit12_p1_u2 [2:-2] [-3:3]; + bit [11:0] q_bit12_p1_u2 [2:-2] [-3:3]; + bit [29:1] i_bit29_p1_u3 [2:-2] [-3:3] [4:-4]; + bit [29:1] o_bit29_p1_u3 [2:-2] [-3:3] [4:-4]; + bit [29:1] q_bit29_p1_u3 [2:-2] [-3:3] [4:-4]; + import "DPI-C" function void dpii_bit_vecval_p1_u1 + (int bits, int p, int u, input bit [0:0] i [], output bit [0:0] o [], output bit [0:0] q []); + import "DPI-C" function void dpii_bit61_vecval_p1_u1 + (int bits, int p, int u, input bit [60:0] i [], output bit [60:0] o [], output bit [60:0] q []); + import "DPI-C" function void dpii_bit92_vecval_p1_u1 + (int bits, int p, int u, input bit [91:0] i [], output bit [91:0] o [], output bit [91:0] q []); + import "DPI-C" function void dpii_bit12_vecval_p1_u2 + (int bits, int p, int u, input bit [11:0] i [] [], output bit [11:0] o [] [], output bit [11:0] q [] []); + import "DPI-C" function void dpii_bit29_vecval_p1_u3 + (int bits, int p, int u, input bit [29:1] i [] [] [], output bit [29:1] o [] [] [], output bit [29:1] q [] [] []); + + logic [0:0] i_logic_p1_u1 [2:-2]; + logic [0:0] o_logic_p1_u1 [2:-2]; + logic [0:0] q_logic_p1_u1 [2:-2]; + logic [60:0] i_logic61_p1_u1 [2:-2]; + logic [60:0] o_logic61_p1_u1 [2:-2]; + logic [60:0] q_logic61_p1_u1 [2:-2]; + logic [91:0] i_logic92_p1_u1 [2:-2]; + logic [91:0] o_logic92_p1_u1 [2:-2]; + logic [91:0] q_logic92_p1_u1 [2:-2]; + logic [11:0] i_logic12_p1_u2 [2:-2] [-3:3]; + logic [11:0] o_logic12_p1_u2 [2:-2] [-3:3]; + logic [11:0] q_logic12_p1_u2 [2:-2] [-3:3]; + logic [29:1] i_logic29_p1_u3 [2:-2] [-3:3] [4:-4]; + logic [29:1] o_logic29_p1_u3 [2:-2] [-3:3] [4:-4]; + logic [29:1] q_logic29_p1_u3 [2:-2] [-3:3] [4:-4]; + import "DPI-C" function void dpii_logic_vecval_p1_u1 + (int logics, int p, int u, input logic [0:0] i [], output logic [0:0] o [], output logic [0:0] q []); + import "DPI-C" function void dpii_logic61_vecval_p1_u1 + (int logics, int p, int u, input logic [60:0] i [], output logic [60:0] o [], output logic [60:0] q []); + import "DPI-C" function void dpii_logic92_vecval_p1_u1 + (int logics, int p, int u, input logic [91:0] i [], output logic [91:0] o [], output logic [91:0] q []); + import "DPI-C" function void dpii_logic12_vecval_p1_u2 + (int logics, int p, int u, input logic [11:0] i [] [], output logic [11:0] o [] [], output logic [11:0] q [] []); + import "DPI-C" function void dpii_logic29_vecval_p1_u3 + (int logics, int p, int u, input logic [29:1] i [] [] [], output logic [29:1] o [] [] [], output logic [29:1] q [] [] []); + + import "DPI-C" function int dpii_failure(); + + reg [95:0] crc; + + initial begin + crc = 96'h8a10a572_5aef0c8d_d70a4497; + + begin + for (int a=-2; a<=2; a=a+1) begin + i_bit_p1_u1[a] = crc[0]; + i_bit61_p1_u1[a] = crc[60:0]; + i_bit92_p1_u1[a] = crc[91:0]; + for (int b=-3; b<=3; b=b+1) begin + i_bit12_p1_u2[a][b] = crc[11:0]; + for (int c=-4; c<=4; c=c+1) begin + i_bit29_p1_u3[a][b][c] = crc[29:1]; + crc = {crc[94:0], crc[95]^crc[2]^crc[0]}; + end + end + end + dpii_bit_vecval_p1_u1(1, 1, 1, i_bit_p1_u1, o_bit_p1_u1, q_bit_p1_u1); + dpii_bit61_vecval_p1_u1(61, 1, 1, i_bit61_p1_u1, o_bit61_p1_u1, q_bit61_p1_u1); + dpii_bit92_vecval_p1_u1(92, 1, 1, i_bit92_p1_u1, o_bit92_p1_u1, q_bit92_p1_u1); + dpii_bit12_vecval_p1_u2(12, 1, 2, i_bit12_p1_u2, o_bit12_p1_u2, q_bit12_p1_u2); + dpii_bit29_vecval_p1_u3(29, 1, 3, i_bit29_p1_u3, o_bit29_p1_u3, q_bit29_p1_u3); + for (int a=-2; a<=2; a=a+1) begin + `checkh(o_bit_p1_u1[a], ~i_bit_p1_u1[a]); + `checkh(q_bit_p1_u1[a], ~i_bit_p1_u1[a]); + `checkh(o_bit61_p1_u1[a], ~i_bit61_p1_u1[a]); + `checkh(q_bit61_p1_u1[a], ~i_bit61_p1_u1[a]); + `checkh(o_bit92_p1_u1[a], ~i_bit92_p1_u1[a]); + `checkh(q_bit92_p1_u1[a], ~i_bit92_p1_u1[a]); + for (int b=-3; b<=3; b=b+1) begin + `checkh(o_bit12_p1_u2[a][b], ~i_bit12_p1_u2[a][b]); + `checkh(q_bit12_p1_u2[a][b], ~i_bit12_p1_u2[a][b]); + for (int c=-4; c<=4; c=c+1) begin + `checkh(o_bit29_p1_u3[a][b][c], ~i_bit29_p1_u3[a][b][c]); + `checkh(q_bit29_p1_u3[a][b][c], ~i_bit29_p1_u3[a][b][c]); + end + end + end + end + + begin + for (int a=-2; a<=2; a=a+1) begin + i_logic_p1_u1[a] = crc[0]; + i_logic61_p1_u1[a] = crc[60:0]; + i_logic92_p1_u1[a] = crc[91:0]; + for (int b=-3; b<=3; b=b+1) begin + i_logic12_p1_u2[a][b] = crc[11:0]; + for (int c=-4; c<=4; c=c+1) begin + i_logic29_p1_u3[a][b][c] = crc[29:1]; + crc = {crc[94:0], crc[95]^crc[2]^crc[0]}; + end + end + end + dpii_logic_vecval_p1_u1(1, 1, 1, i_logic_p1_u1, o_logic_p1_u1, q_logic_p1_u1); + dpii_logic61_vecval_p1_u1(61, 1, 1, i_logic61_p1_u1, o_logic61_p1_u1, q_logic61_p1_u1); + dpii_logic92_vecval_p1_u1(92, 1, 1, i_logic92_p1_u1, o_logic92_p1_u1, q_logic92_p1_u1); + dpii_logic12_vecval_p1_u2(12, 1, 2, i_logic12_p1_u2, o_logic12_p1_u2, q_logic12_p1_u2); + dpii_logic29_vecval_p1_u3(29, 1, 3, i_logic29_p1_u3, o_logic29_p1_u3, q_logic29_p1_u3); + for (int a=-2; a<=2; a=a+1) begin + `checkh(o_logic_p1_u1[a], ~i_logic_p1_u1[a]); + `checkh(q_logic_p1_u1[a], ~i_logic_p1_u1[a]); + `checkh(o_logic61_p1_u1[a], ~i_logic61_p1_u1[a]); + `checkh(q_logic61_p1_u1[a], ~i_logic61_p1_u1[a]); + `checkh(o_logic92_p1_u1[a], ~i_logic92_p1_u1[a]); + `checkh(q_logic92_p1_u1[a], ~i_logic92_p1_u1[a]); + for (int b=-3; b<=3; b=b+1) begin + `checkh(o_logic12_p1_u2[a][b], ~i_logic12_p1_u2[a][b]); + `checkh(q_logic12_p1_u2[a][b], ~i_logic12_p1_u2[a][b]); + for (int c=-4; c<=4; c=c+1) begin + `checkh(o_logic29_p1_u3[a][b][c], ~i_logic29_p1_u3[a][b][c]); + `checkh(q_logic29_p1_u3[a][b][c], ~i_logic29_p1_u3[a][b][c]); + end + end + end + end + + if (dpii_failure()!=0) begin + $write("%%Error: Failure in DPI tests\n"); + $stop; + end + else begin + $write("*-* All Finished *-*\n"); + $finish; + end + end + +endmodule diff --git a/test_regress/t/t_dpi_open_vecval_c.cpp b/test_regress/t/t_dpi_open_vecval_c.cpp new file mode 100644 index 000000000..e8b49163c --- /dev/null +++ b/test_regress/t/t_dpi_open_vecval_c.cpp @@ -0,0 +1,236 @@ +// -*- mode: C++; c-file-style: "cc-mode" -*- +//************************************************************************* +// +// Copyright 2009-2020 by Wilson Snyder. This program is free software; you can +// redistribute it and/or modify it under the terms of either the GNU +// Lesser General Public License Version 3 or the Perl Artistic License +// Version 2.0. +// SPDX-License-Identifier: LGPL-3.0-only OR Artistic-2.0 +// +//************************************************************************* + +#include +#include +#include +#include "svdpi.h" + +//====================================================================== + +// clang-format off +#if defined(VERILATOR) +# include "Vt_dpi_open_vecval__Dpi.h" +#elif defined(VCS) +# include "../vc_hdrs.h" +#elif defined(NC) +# define NEED_EXTERNS +// #elif defined(MS) +// # define NEED_EXTERNS +#else +# error "Unknown simulator for DPI test" +#endif +// clang-format on + +#ifdef NEED_EXTERNS +extern "C" { +// If get ncsim: *F,NOFDPI: Function {foo} not found in default libdpi. +// Then probably forgot to list a function here. + +extern int dpii_failure(); +} +#endif + +int failure = 0; +int dpii_failure() { return failure; } + +#define CHECK_RESULT_HEX(got, exp) \ + do { \ + if ((got) != (exp)) { \ + std::cout << std::dec << "%Error: " << __FILE__ << ":" << __LINE__ << std::hex \ + << ": GOT=" << (got) << " EXP=" << (exp) << std::endl; \ + failure = __LINE__; \ + } \ + } while (0) + +#define CHECK_RESULT_HEX_NE(got, exp) \ + do { \ + if ((got) == (exp)) { \ + std::cout << std::dec << "%Error: " << __FILE__ << ":" << __LINE__ << std::hex \ + << ": GOT=" << (got) << " EXP!=" << (exp) << std::endl; \ + failure = __LINE__; \ + } \ + } while (0) + +static void _invert(int bits, svBitVecVal o[], const svBitVecVal i[]) { + for (int w = 0; w < SV_PACKED_DATA_NELEMS(bits); ++w) o[w] = ~i[w]; + o[SV_PACKED_DATA_NELEMS(bits) - 1] &= SV_MASK(bits & 31); +} +static void _invert(int bits, svLogicVecVal o[], const svLogicVecVal i[]) { + for (int w = 0; w < SV_PACKED_DATA_NELEMS(bits); ++w) { + o[w].aval = ~i[w].aval; + o[w].bval = 0; + } + o[SV_PACKED_DATA_NELEMS(bits) - 1].aval &= SV_MASK(bits & 31); + o[SV_PACKED_DATA_NELEMS(bits) - 1].bval &= SV_MASK(bits & 31); +} + +static bool _same(int bits, const svBitVecVal o[], const svBitVecVal i[]) { + for (int w = 0; w < SV_PACKED_DATA_NELEMS(bits); ++w) { + svBitVecVal mask = 0xffffffff; + if (w == SV_PACKED_DATA_NELEMS(bits) - 1) mask = SV_MASK(bits & 31); + if ((o[w] & mask) != (i[w] & mask)) return false; + } + return true; +} +static bool _same(int bits, const svLogicVecVal o[], const svLogicVecVal i[]) { + for (int w = 0; w < SV_PACKED_DATA_NELEMS(bits); ++w) { + svBitVecVal mask = 0xffffffff; + if (w == SV_PACKED_DATA_NELEMS(bits) - 1) mask = SV_MASK(bits & 31); + if ((o[w].aval & mask) != (i[w].aval & mask)) return false; + if ((o[w].bval & mask) != (i[w].bval & mask)) return false; + } + return true; +} + +void dpii_unused(const svOpenArrayHandle u) {} + +//====================================================================== + +static void _dpii_bit_vecval_ux(int bits, int p, int u, const svOpenArrayHandle i, + const svOpenArrayHandle o, const svOpenArrayHandle q) { + printf("%s: bits=%d p=%d u=%d\n", __func__, bits, p, u); + + int dim = svDimensions(i); +#ifndef NC + // NC always returns zero and warns + CHECK_RESULT_HEX(dim, u); +#endif + + svBitVecVal vv[SV_PACKED_DATA_NELEMS(bits)]; + svBitVecVal vv2[SV_PACKED_DATA_NELEMS(bits)]; + svBitVecVal vo[SV_PACKED_DATA_NELEMS(bits)]; + for (int a = svLow(i, 1); a <= svHigh(i, 1); ++a) { + fflush(stdout); + if (dim == 1) { + svGetBitArrElemVecVal(vv, i, a); + svGetBitArrElem1VecVal(vv2, i, a); + CHECK_RESULT_HEX(_same(bits, vv, vv2), true); + _invert(bits, vo, vv); + svPutBitArrElemVecVal(o, vo, a); + svPutBitArrElem1VecVal(q, vo, a); + } else { + for (int b = svLow(i, 2); b <= svHigh(i, 2); ++b) { + if (dim == 2) { + svGetBitArrElemVecVal(vv, i, a, b); + svGetBitArrElem2VecVal(vv2, i, a, b); + CHECK_RESULT_HEX(_same(bits, vv, vv2), true); + _invert(bits, vo, vv); + svPutBitArrElemVecVal(o, vo, a, b); + svPutBitArrElem2VecVal(q, vo, a, b); + } else { + for (int c = svLow(i, 3); c <= svHigh(i, 3); ++c) { + if (dim == 3) { + svGetBitArrElemVecVal(vv, i, a, b, c); + svGetBitArrElem3VecVal(vv2, i, a, b, c); + CHECK_RESULT_HEX(_same(bits, vv, vv2), true); + _invert(bits, vo, vv); + svPutBitArrElemVecVal(o, vo, a, b, c); + svPutBitArrElem3VecVal(q, vo, a, b, c); + } + } + } + } + } + } + fflush(stdout); +} +void dpii_bit_vecval_p1_u1(int bits, int p, int u, const svOpenArrayHandle i, + const svOpenArrayHandle o, const svOpenArrayHandle q) { + _dpii_bit_vecval_ux(bits, p, u, i, o, q); +} +void dpii_bit61_vecval_p1_u1(int bits, int p, int u, const svOpenArrayHandle i, + const svOpenArrayHandle o, const svOpenArrayHandle q) { + _dpii_bit_vecval_ux(bits, p, u, i, o, q); +} +void dpii_bit92_vecval_p1_u1(int bits, int p, int u, const svOpenArrayHandle i, + const svOpenArrayHandle o, const svOpenArrayHandle q) { + _dpii_bit_vecval_ux(bits, p, u, i, o, q); +} +void dpii_bit12_vecval_p1_u2(int bits, int p, int u, const svOpenArrayHandle i, + const svOpenArrayHandle o, const svOpenArrayHandle q) { + _dpii_bit_vecval_ux(bits, p, u, i, o, q); +} +void dpii_bit29_vecval_p1_u3(int bits, int p, int u, const svOpenArrayHandle i, + const svOpenArrayHandle o, const svOpenArrayHandle q) { + _dpii_bit_vecval_ux(bits, p, u, i, o, q); +} + +//====================================================================== + +static void _dpii_logic_vecval_ux(int bits, int p, int u, const svOpenArrayHandle i, + const svOpenArrayHandle o, const svOpenArrayHandle q) { + printf("%s: bits=%d p=%d u=%d\n", __func__, bits, p, u); + + int dim = svDimensions(i); +#ifndef NC + // NC always returns zero and warns + CHECK_RESULT_HEX(dim, u); +#endif + + svLogicVecVal vv[SV_PACKED_DATA_NELEMS(bits)]; + svLogicVecVal vv2[SV_PACKED_DATA_NELEMS(bits)]; + svLogicVecVal vo[SV_PACKED_DATA_NELEMS(bits)]; + for (int a = svLow(i, 1); a <= svHigh(i, 1); ++a) { + fflush(stdout); + if (dim == 1) { + svGetLogicArrElemVecVal(vv, i, a); + svGetLogicArrElem1VecVal(vv2, i, a); + CHECK_RESULT_HEX(_same(bits, vv, vv2), true); + _invert(bits, vo, vv); + svPutLogicArrElemVecVal(o, vo, a); + svPutLogicArrElem1VecVal(q, vo, a); + } else { + for (int b = svLow(i, 2); b <= svHigh(i, 2); ++b) { + if (dim == 2) { + svGetLogicArrElemVecVal(vv, i, a, b); + svGetLogicArrElem2VecVal(vv2, i, a, b); + CHECK_RESULT_HEX(_same(bits, vv, vv2), true); + _invert(bits, vo, vv); + svPutLogicArrElemVecVal(o, vo, a, b); + svPutLogicArrElem2VecVal(q, vo, a, b); + } else { + for (int c = svLow(i, 3); c <= svHigh(i, 3); ++c) { + if (dim == 3) { + svGetLogicArrElemVecVal(vv, i, a, b, c); + svGetLogicArrElem3VecVal(vv2, i, a, b, c); + CHECK_RESULT_HEX(_same(bits, vv, vv2), true); + _invert(bits, vo, vv); + svPutLogicArrElemVecVal(o, vo, a, b, c); + svPutLogicArrElem3VecVal(q, vo, a, b, c); + } + } + } + } + } + } + fflush(stdout); +} +void dpii_logic_vecval_p1_u1(int bits, int p, int u, const svOpenArrayHandle i, + const svOpenArrayHandle o, const svOpenArrayHandle q) { + _dpii_logic_vecval_ux(bits, p, u, i, o, q); +} +void dpii_logic61_vecval_p1_u1(int bits, int p, int u, const svOpenArrayHandle i, + const svOpenArrayHandle o, const svOpenArrayHandle q) { + _dpii_logic_vecval_ux(bits, p, u, i, o, q); +} +void dpii_logic92_vecval_p1_u1(int bits, int p, int u, const svOpenArrayHandle i, + const svOpenArrayHandle o, const svOpenArrayHandle q) { + _dpii_logic_vecval_ux(bits, p, u, i, o, q); +} +void dpii_logic12_vecval_p1_u2(int bits, int p, int u, const svOpenArrayHandle i, + const svOpenArrayHandle o, const svOpenArrayHandle q) { + _dpii_logic_vecval_ux(bits, p, u, i, o, q); +} +void dpii_logic29_vecval_p1_u3(int bits, int p, int u, const svOpenArrayHandle i, + const svOpenArrayHandle o, const svOpenArrayHandle q) { + _dpii_logic_vecval_ux(bits, p, u, i, o, q); +}