diff --git a/Changes b/Changes index 9dced9b36..d78084856 100644 --- a/Changes +++ b/Changes @@ -5,6 +5,8 @@ indicates the contributor was also the author of the fix; Thanks! * Verilator 3.813**** +**** Support bit vectors > 64 bits wide in DPI import and exports. + **** Fix error on enum references to other packages, bug339. [Alex Solomatnikov] **** Fix DPI undeclared svBitVecVal compile error, bug346. [Chandan Egbert] diff --git a/include/verilated.h b/include/verilated.h index f1d1c3a40..b5ff1b3a0 100644 --- a/include/verilated.h +++ b/include/verilated.h @@ -1633,6 +1633,6 @@ static inline WDataOutP VL_CONST_W_9X(int obits, WDataOutP o, #undef _END -// Debugging +//====================================================================== #endif /*_VERILATED_H_*/ diff --git a/include/verilated_dpi.cpp b/include/verilated_dpi.cpp index 2b50191cd..d0d7731f5 100644 --- a/include/verilated_dpi.cpp +++ b/include/verilated_dpi.cpp @@ -25,6 +25,7 @@ #define _VERILATED_DPI_CPP_ #include "verilatedos.h" +#include "verilated_dpi.h" #include "verilated_imp.h" // On MSVC++ we need svdpi.h to declare exports, not imports diff --git a/include/verilated_dpi.h b/include/verilated_dpi.h new file mode 100644 index 000000000..2aac27973 --- /dev/null +++ b/include/verilated_dpi.h @@ -0,0 +1,64 @@ +// -*- C++ -*- +//************************************************************************* +// +// Copyright 2003-2011 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. +// +// Verilator is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +//************************************************************************* +/// +/// \file +/// \brief Verilator: Common include for all Verilated C files that use DPI +/// +/// This file is included automatically by Verilator at the top of +/// all C++ files it generates where DPI is used. It contains +/// DPI interface functions required by the Verilated code. +/// +/// Code available from: http://www.veripool.org/verilator +/// +//************************************************************************* + + +#ifndef _VERILATED_DPI_H_ +#define _VERILATED_DPI_H_ 1 ///< Header Guard + +#include "verilated.h" // Presumed done by caller +#include "svdpi.h" + +//=================================================================== +// SETTING OPERATORS + +/// Return svBitVecVal from WData +static inline void VL_SET_W_SVBV(int obits, WDataOutP owp, svBitVecVal* lwp) { + int words = VL_WORDS_I(obits); + for (int i=0; i 32-bits"); if (basicp()->isBitLogic()) { if (widthMin() == 1) { arg = "unsigned char"; diff --git a/src/V3EmitC.cpp b/src/V3EmitC.cpp index 19cee0ea9..572312c1a 100644 --- a/src/V3EmitC.cpp +++ b/src/V3EmitC.cpp @@ -1803,6 +1803,11 @@ void EmitCImp::emitImp(AstNodeModule* modp) { // Us puts("#include \""+ symClassName() +".h\"\n"); + if (v3Global.dpi()) { + puts("\n"); + puts("#include \"verilated_dpi.h\"\n"); + } + if (optSystemPerl() && (splitFilenum() || !m_fast)) { puts("\n"); puts("SP_MODULE_CONTINUED("+modClassName(modp)+");\n"); diff --git a/src/V3Slice.cpp b/src/V3Slice.cpp index d4b5d37d8..888da6e99 100644 --- a/src/V3Slice.cpp +++ b/src/V3Slice.cpp @@ -328,7 +328,6 @@ class SliceVisitor : public AstNVisitor { m_assignp->v3error("Unsupported: Assignment between a constant and an array slice"); m_assignError = true; } - nodep->iterateChildren(*this); } virtual void visit(AstArraySel* nodep, AstNUser*) { diff --git a/src/V3Task.cpp b/src/V3Task.cpp index 8b55882d4..f4829f104 100644 --- a/src/V3Task.cpp +++ b/src/V3Task.cpp @@ -587,8 +587,12 @@ private: // Someday we'll have better type support, and this can make variables and casts. // But for now, we'll just text-bash it. if (bitvec) { - // We only support quads, so don't need to sweat longer stuff - stmt += "VL_SET_WQ("+portp->name()+toSuffix+", "+portp->name()+frSuffix+")"; + if (portp->isWide()) { + stmt += ("VL_SET_SVBV_W("+cvtToStr(portp->width()) + +", "+portp->name()+toSuffix+", "+portp->name()+frSuffix+")"); + } else { + stmt += "VL_SET_WQ("+portp->name()+toSuffix+", "+portp->name()+frSuffix+")"; + } } else { if (isPtr) stmt += "*"; // DPI outputs are pointers stmt += portp->name()+toSuffix+" = "; @@ -615,7 +619,8 @@ private: ket += ")"; } if (!cvt - && portp->basicp() && portp->basicp()->isBitLogic() && portp->widthMin() != 1) stmt += "*"; // it's a svBitVecVal + && portp->basicp() && portp->basicp()->isBitLogic() && portp->widthMin() != 1 && !portp->isWide()) + stmt += "*"; // it's a svBitVecVal, which other code won't think is arrayed (as WData aren't), but really is stmt += frName; stmt += ket; // Use a AstCMath, as we want V3Clean to mask off bits that don't make sense. diff --git a/test_regress/t/t_dpi_export.v b/test_regress/t/t_dpi_export.v index 1601771de..516a7bfb5 100644 --- a/test_regress/t/t_dpi_export.v +++ b/test_regress/t/t_dpi_export.v @@ -38,6 +38,9 @@ module t; function longint dpix_f_longint (longint i); dpix_f_longint = ~i; endfunction function chandle dpix_f_chandle (chandle i); dpix_f_chandle = i; endfunction + export "DPI-C" task dpix_t_bit95; + task dpix_t_bit95(input bit [94:0] i, output bit [94:0] o); o = ~i; endtask + int lineno; initial begin diff --git a/test_regress/t/t_dpi_export_c.cpp b/test_regress/t/t_dpi_export_c.cpp index c6f8b6eab..9bc0d519a 100644 --- a/test_regress/t/t_dpi_export_c.cpp +++ b/test_regress/t/t_dpi_export_c.cpp @@ -136,6 +136,15 @@ int dpix_run_tests() { CHECK_RESULT (unsigned long long, dpix_f_longint(1), 0xfffffffffffffffeULL); CHECK_RESULT (void*, dpix_f_chandle((void*)(12345)), (void*)(12345)); + { + svBitVecVal i_vec95[3] = {0x72912312,0xab782a12,0x8a413bd9}; + svBitVecVal o_vec95[3] = {0,0,0}; + dpix_t_bit95(i_vec95, o_vec95); + CHECK_RESULT(int, o_vec95[0], ~i_vec95[0]); + CHECK_RESULT(int, o_vec95[1], ~i_vec95[1]); + CHECK_RESULT(int, o_vec95[2], (~i_vec95[2])&0x7fffffffUL); + } + if (int bad=check_sub("top.t.a",1)) return bad; if (int bad=check_sub("top.t.b",2)) return bad; diff --git a/test_regress/t/t_dpi_import.v b/test_regress/t/t_dpi_import.v index 582479c67..33edd4da9 100644 --- a/test_regress/t/t_dpi_import.v +++ b/test_regress/t/t_dpi_import.v @@ -59,6 +59,7 @@ module t (); `ifndef NO_SHORTREAL import "DPI-C" pure function void dpii_v_shortreal(input shortreal i, output shortreal o); `endif + import "DPI-C" pure function void dpii_v_bit95 (input bit [95-1:0] i, output bit [95-1:0] o); import "DPI-C" pure function int dpii_f_strlen (input string i); @@ -82,6 +83,7 @@ module t (); bit [31:0] i_b32, o_b32; bit [32:0] i_b33, o_b33; bit [63:0] i_b64, o_b64; + bit [94:0] i_b95, o_b95; int i_i, o_i; byte i_y, o_y; @@ -111,6 +113,7 @@ module t (); i_b32 = {1'b1,wide[32-2:0]}; i_b33 = {1'b1,wide[33-2:0]}; i_b64 = {1'b1,wide[64-2:0]}; + i_b95 = {1'b1,wide[95-2:0]}; i_i = {1'b1,wide[32-2:0]}; i_y = {1'b1,wide[8-2:0]}; @@ -159,6 +162,7 @@ module t (); `ifndef NO_SHORTREAL dpii_v_shortreal(i_f,o_f); if (o_f != i_f+1.5) $stop; `endif + dpii_v_bit95 (i_b95,o_b95); if (o_b95 !== ~i_b95) $stop; if (dpii_f_strlen ("")!=0) $stop; if (dpii_f_strlen ("s")!=1) $stop; diff --git a/test_regress/t/t_dpi_import_c.cpp b/test_regress/t/t_dpi_import_c.cpp index 70d95cfa8..3fe8150bf 100644 --- a/test_regress/t/t_dpi_import_c.cpp +++ b/test_regress/t/t_dpi_import_c.cpp @@ -33,13 +33,14 @@ extern "C" { extern unsigned char dpii_f_bit (unsigned char i); - extern svBitVecVal dpii_f_bit8 (const svBitVecVal *i); - extern svBitVecVal dpii_f_bit9 (const svBitVecVal *i); - extern svBitVecVal dpii_f_bit16 (const svBitVecVal *i); - extern svBitVecVal dpii_f_bit17 (const svBitVecVal *i); - extern svBitVecVal dpii_f_bit32 (const svBitVecVal *i); - extern long long dpii_f_bit33 (const svBitVecVal *i); - extern long long dpii_f_bit64 (const svBitVecVal *i); + extern svBitVecVal dpii_f_bit8 (const svBitVecVal* i); + extern svBitVecVal dpii_f_bit9 (const svBitVecVal* i); + extern svBitVecVal dpii_f_bit16 (const svBitVecVal* i); + extern svBitVecVal dpii_f_bit17 (const svBitVecVal* i); + extern svBitVecVal dpii_f_bit32 (const svBitVecVal* i); + extern long long dpii_f_bit33 (const svBitVecVal* i); + extern long long dpii_f_bit64 (const svBitVecVal* i); + extern long long dpii_f_bit95 (const svBitVecVal* i, svBitVecVal* o); extern int dpii_f_int (int i); extern char dpii_f_byte (char i); extern short int dpii_f_shortint(short int i); @@ -49,7 +50,7 @@ extern "C" { extern double dpii_f_real (double i); extern float dpii_f_shortreal(float i); - extern void dpii_v_bit (unsigned char i, unsigned char *o); + extern void dpii_v_bit (unsigned char i, unsigned char* o); extern void dpii_v_int (int i, int *o); extern void dpii_v_byte (char i, char *o); extern void dpii_v_shortint (short int i, short int *o); @@ -100,6 +101,12 @@ void dpii_v_string (const char* i, const char** o) { *o = i; } void dpii_v_real (double i, double* o) { *o = i + 1.5; } void dpii_v_shortreal(float i, float* o) { *o = i + 1.5; } +void dpii_v_bit95(const svBitVecVal* i, svBitVecVal* o) { + o[0] = ~i[0]; + o[1] = ~i[1]; + o[2] = SV_MASK(95-64) & ~i[2]; +} + int dpii_f_strlen (const char* i) { return strlen(i); } //======================================================================