diff --git a/include/verilated.h b/include/verilated.h index 5db146d20..de9c06a2f 100644 --- a/include/verilated.h +++ b/include/verilated.h @@ -323,8 +323,12 @@ extern const char* vl_mc_scan_plusargs(const char* prefixp); // PLIish // Use a union to avoid cast-to-different-size warnings /// Return FILE* from QData static inline FILE* VL_CVT_Q_FP(QData lhs) { union { FILE* fp; QData q; } u; u.q=lhs; return u.fp; } +/// Return void* from QData +static inline void* VL_CVT_Q_VP(QData lhs) { union { void* fp; QData q; } u; u.q=lhs; return u.fp; } /// Return QData from FILE* static inline QData VL_CVT_FP_Q(FILE* fp) { union { FILE* fp; QData q; } u; u.q=0; u.fp=fp; return u.q; } +/// Return QData from void* +static inline QData VL_CVT_VP_Q(void* fp) { union { void* fp; QData q; } u; u.q=0; u.fp=fp; return u.q; } // Sign extend such that if MSB set, we get ffff_ffff, else 0s // (Requires clean input) diff --git a/src/Makefile.in b/src/Makefile.in index 22bb4501b..e81432926 100644 --- a/src/Makefile.in +++ b/src/Makefile.in @@ -60,8 +60,9 @@ obj_dbg: opt: ../verilator_bin ifeq ($(VERILATOR_NO_OPT_BUILD),1) # Faster laptop development... One build ../verilator_bin: ../verilator_bin_dbg - cp -p $< $@ - @-cp -p $<.exe $@.exe + -rm -rf $@ $@.exe + -cp -p $< $@ + -cp -p $<.exe $@.exe else ../verilator_bin: obj_opt prefiles cd obj_opt && $(MAKE) -j 1 TGT=../$@ -f ../Makefile_obj serial diff --git a/src/V3Task.cpp b/src/V3Task.cpp index 7922c34f0..ec80728ff 100644 --- a/src/V3Task.cpp +++ b/src/V3Task.cpp @@ -580,6 +580,7 @@ private: // Create assignment from internal format into DPI temporary bool bitvec = (portp->basicp()->isBitLogic() && portp->width() > 32); string stmt; + string ket; // 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) { @@ -589,14 +590,15 @@ private: if (isPtr) stmt += "*"; // DPI outputs are pointers stmt += portp->name()+toSuffix+" = "; if (portp->basicp() && portp->basicp()->keyword()==AstBasicDTypeKwd::CHANDLE) { - stmt += "(void*)"; + stmt += "VL_CVT_Q_VP("; + ket += ")"; } stmt += portp->name()+frSuffix; if (portp->basicp() && portp->basicp()->keyword()==AstBasicDTypeKwd::STRING) { stmt += ".c_str()"; } } - stmt += ";\n"; + stmt += ket + ";\n"; return new AstCStmt(portp->fileline(), stmt); } @@ -604,10 +606,13 @@ private: // Create assignment from DPI temporary into internal format AstVar* portp = portvscp->varp(); string stmt; + string ket; if (portp->basicp() && portp->basicp()->keyword()==AstBasicDTypeKwd::CHANDLE) { - stmt += "(QData)"; + stmt += "VL_CVT_VP_Q("; + ket += ")"; } stmt += frName; + stmt += ket; // Use a AstCMath, as we want V3Clean to mask off bits that don't make sense. int cwidth = VL_WORDSIZE; if (portp->basicp()) cwidth = portp->basicp()->keyword().width(); if (portp->basicp() && portp->basicp()->isBitLogic()) cwidth = VL_WORDSIZE*portp->widthWords(); diff --git a/test_regress/t/t_dpi_export.pl b/test_regress/t/t_dpi_export.pl index b42417818..bbe758e10 100755 --- a/test_regress/t/t_dpi_export.pl +++ b/test_regress/t/t_dpi_export.pl @@ -11,7 +11,8 @@ if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); di compile ( # Amazingly VCS, NC and Verilator all just accept the C file here! - v_flags2 => ["t/t_dpi_export_c.cpp", "-no-l2name"], + v_flags2 => ["t/t_dpi_export_c.cpp"], + verilator_flags2 => ["-no-l2name"], ); execute ( diff --git a/test_regress/t/t_dpi_export_c.cpp b/test_regress/t/t_dpi_export_c.cpp index 8a9419315..b9cb572b7 100644 --- a/test_regress/t/t_dpi_export_c.cpp +++ b/test_regress/t/t_dpi_export_c.cpp @@ -17,6 +17,12 @@ #include #include +#ifdef _WIN32 +# define T_PRI64 "I64" +#else // Linux or compliant Unix flavors +# define T_PRI64 "ll" +#endif + //====================================================================== #if defined(VERILATOR) @@ -53,10 +59,14 @@ extern "C" { //====================================================================== -#define CHECK_RESULT(got, exp) \ - if ((got) != (exp)) { \ - printf("%%Error: %s:%d: GOT = %" VL_PRI64 "x EXP = %" VL_PRI64 "x\n", \ - __FILE__,__LINE__, (long long)(got), (long long)(exp)); \ +#define CHECK_RESULT(type, got, exp) \ + if ((got) != (exp)) { \ + printf("%%Error: %s:%d:", __FILE__,__LINE__); \ + union { type a; long long l; } u; \ + u.l = 0; u.a = got; \ + printf(" GOT = %" T_PRI64 "x", u.l); \ + u.l = 0; u.a = exp; \ + printf(" EXP = %" T_PRI64 "x\n", u.l); \ return __LINE__; \ } #define CHECK_RESULT_NNULL(got) \ @@ -73,10 +83,10 @@ static int check_sub(const char* name, int i) { CHECK_RESULT_NNULL (scope); svScope prev = svGetScope(); svScope sout = svSetScope(scope); - CHECK_RESULT(sout, prev); - CHECK_RESULT(svGetScope(), scope); + CHECK_RESULT(svScope, sout, prev); + CHECK_RESULT(svScope, svGetScope(), scope); int out = dpix_sub_inst(100*i); - CHECK_RESULT(out, 100*i + i); + CHECK_RESULT(int, out, 100*i + i); return 0; // OK } @@ -96,31 +106,32 @@ int dpix_run_tests() { #ifndef CADENCE // Unimplemented; how hard is it? printf ("svDpiVersion: %s\n",svDpiVersion()); - CHECK_RESULT (strcmp(svDpiVersion(), "1800-2005")==0 + CHECK_RESULT (bool, + strcmp(svDpiVersion(), "1800-2005")==0 || strcmp(svDpiVersion(), "P1800-2005")==0 , 1); #endif - CHECK_RESULT (dpix_int123(), 0x123 ); + CHECK_RESULT (int, dpix_int123(), 0x123 ); #ifndef CADENCE // No export calls from an import int o; dpix_t_int(0x456, &o); - CHECK_RESULT (o, ~0x456UL); + CHECK_RESULT (unsigned long, o, ~0x456UL); dpix_t_renamed(0x456, &o); - CHECK_RESULT (o, 0x458UL); + CHECK_RESULT (int, o, 0x458UL); #endif - CHECK_RESULT (dpix_f_bit(1), 0x0); - CHECK_RESULT (dpix_f_bit(0), 0x1); + CHECK_RESULT (int, dpix_f_bit(1), 0x0); + CHECK_RESULT (int, dpix_f_bit(0), 0x1); // Simulators disagree over the next three's sign extension unless we mask the upper bits - CHECK_RESULT (dpix_f_int(1) & 0xffffffffUL, 0xfffffffeUL); - CHECK_RESULT (dpix_f_byte(1) & 0xffUL, 0xfe); - CHECK_RESULT (dpix_f_shortint(1) & 0xffffUL, 0xfffeUL); + CHECK_RESULT (int, dpix_f_int(1) & 0xffffffffUL, 0xfffffffeUL); + CHECK_RESULT (int, dpix_f_byte(1) & 0xffUL, 0xfe); + CHECK_RESULT (int, dpix_f_shortint(1) & 0xffffUL, 0xfffeUL); - CHECK_RESULT (dpix_f_longint(1), 0xfffffffffffffffeULL); - CHECK_RESULT (dpix_f_chandle((void*)(12345)), (void*)(12345)); + CHECK_RESULT (unsigned long long, dpix_f_longint(1), 0xfffffffffffffffeULL); + CHECK_RESULT (void*, dpix_f_chandle((void*)(12345)), (void*)(12345)); if (int bad=check_sub("top.t.a",1)) return bad; if (int bad=check_sub("top.t.b",2)) return bad;