diff --git a/Changes b/Changes index f739e6fdb..a62e994ce 100644 --- a/Changes +++ b/Changes @@ -6,6 +6,8 @@ indicates the contributor was also the author of the fix; Thanks! * Verilator 3.887 devel +**** Add error on DPI functions > 32 bits, msg1995. [Elliot Mednick] + **** Fix SystemC compiles with VPI, bug1081. [Arthur Kahlich] **** Fix error on wide numbers that represent small msb/lsb, msg1991. [Mandy Xu] diff --git a/src/V3Task.cpp b/src/V3Task.cpp index 12a0f5caa..138ff8911 100644 --- a/src/V3Task.cpp +++ b/src/V3Task.cpp @@ -584,9 +584,14 @@ private: return new AstCStmt(portp->fileline(), stmt); } - AstNode* createAssignInternalToDpi(AstVar* portp, bool isPtr, const string& frSuffix, const string& toSuffix) { + AstNode* createAssignInternalToDpi(AstVar* portp, bool isRtn, bool isPtr, + const string& frSuffix, const string& toSuffix) { // Create assignment from internal format into DPI temporary bool bitvec = (portp->basicp()->isBitLogic() && portp->width() > 32); + if (isRtn && bitvec) { + portp->v3error("DPI functions cannot return > 32 bits; use a two-state type or task instead: "<prettyName()); + // Code below works, but won't compile right, and IEEE illegal + } string stmt; string ket; // Someday we'll have better type support, and this can make variables and casts. @@ -727,14 +732,14 @@ private: for (AstNode* stmtp = nodep->stmtsp(); stmtp; stmtp=stmtp->nextp()) { if (AstVar* portp = stmtp->castVar()) { if (portp->isIO() && portp->isOutput() && !portp->isFuncReturn()) { - dpip->addStmtsp(createAssignInternalToDpi(portp,true,"__Vcvt","")); + dpip->addStmtsp(createAssignInternalToDpi(portp,false,true,"__Vcvt","")); } } } if (rtnvarp) { dpip->addStmtsp(createDpiTemp(rtnvarp,"")); - dpip->addStmtsp(createAssignInternalToDpi(rtnvarp,false,"__Vcvt","")); + dpip->addStmtsp(createAssignInternalToDpi(rtnvarp,true,false,"__Vcvt","")); string stmt = "return "+rtnvarp->name()+";\n"; dpip->addStmtsp(new AstCStmt(nodep->fileline(), stmt)); } @@ -784,7 +789,7 @@ private: cfuncp->addStmtsp(createDpiTemp(portp,"__Vcvt")); if (portp->isInput()) { - cfuncp->addStmtsp(createAssignInternalToDpi(portp,false,"","__Vcvt")); + cfuncp->addStmtsp(createAssignInternalToDpi(portp,false,false,"","__Vcvt")); } } } diff --git a/test_regress/t/t_dpi_exp_bad.pl b/test_regress/t/t_dpi_exp_bad.pl new file mode 100755 index 000000000..99494afb2 --- /dev/null +++ b/test_regress/t/t_dpi_exp_bad.pl @@ -0,0 +1,19 @@ +#!/usr/bin/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. + +compile ( + v_flags2 => ["--lint-only"], + fails=>$Self->{v3}, + expect=> +'%Error: t/t_dpi_exp_bad.v:\d+: DPI functions cannot return > 32 bits; use a two-state type or task instead: dpix_f_bit48__Vfuncrtn +%Error: Exiting due to .*' + ); + +ok(1); +1; diff --git a/test_regress/t/t_dpi_exp_bad.v b/test_regress/t/t_dpi_exp_bad.v new file mode 100644 index 000000000..f051e1ecb --- /dev/null +++ b/test_regress/t/t_dpi_exp_bad.v @@ -0,0 +1,13 @@ +// DESCRIPTION: Verilator: Verilog Test module +// +// Copyright 2009 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. + +module t; + + export "DPI-C" function dpix_f_bit48; + function bit [47:0] dpix_f_bit48 (bit [47:0] i); dpix_f_bit48 = ~i; endfunction + +endmodule diff --git a/test_regress/t/t_dpi_export.v b/test_regress/t/t_dpi_export.v index 9f02d8f92..bb441d3df 100644 --- a/test_regress/t/t_dpi_export.v +++ b/test_regress/t/t_dpi_export.v @@ -38,6 +38,8 @@ 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_bit48; + task dpix_t_bit48(input bit [47:0] i, output bit [47:0] o); o = ~i; endtask export "DPI-C" task dpix_t_bit95; task dpix_t_bit95(input bit [94:0] i, output bit [94:0] o); o = ~i; endtask export "DPI-C" task dpix_t_bit96; diff --git a/test_regress/t/t_dpi_export_c.cpp b/test_regress/t/t_dpi_export_c.cpp index 54c41b018..ebf1cca15 100644 --- a/test_regress/t/t_dpi_export_c.cpp +++ b/test_regress/t/t_dpi_export_c.cpp @@ -46,6 +46,8 @@ extern "C" { extern int dpix_int123(); extern unsigned char dpix_f_bit(unsigned char i); + extern svBitVecVal dpix_f_bit15(const svBitVecVal* i); + extern svBitVecVal dpix_f_bit48(const svBitVecVal* i); extern int dpix_f_int(int i); extern char dpix_f_byte(char i); extern short int dpix_f_shortint(short int i); @@ -136,6 +138,17 @@ 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_vec48[2] = {0xab782a12,0x8a413bd9}; + svBitVecVal o_vec48[2] = {0,0}; + dpix_t_bit48(i_vec48, o_vec48); + CHECK_RESULT(int, o_vec48[0], ~i_vec48[0]); +#ifdef VCS // VCS has bug where doesn't clean input + CHECK_RESULT(int, o_vec48[1], (~i_vec48[1])); +#else + CHECK_RESULT(int, o_vec48[1], (~i_vec48[1])&0x0000ffffUL); +#endif + } { svBitVecVal i_vec95[3] = {0x72912312,0xab782a12,0x8a413bd9}; svBitVecVal o_vec95[3] = {0,0,0};