From 9a16001e51a7d2bd66b2e6cf3adad5ecb9d98de8 Mon Sep 17 00:00:00 2001 From: Wilson Snyder Date: Fri, 25 Sep 2015 22:57:28 -0400 Subject: [PATCH] Add --vpi flag, and fix VPI linkage, bug969. --- Changes | 2 + bin/verilator | 38 +- include/verilated_vpi.cpp | 1036 +++++++++++++++++++++++++++++++ include/verilated_vpi.h | 1001 +---------------------------- src/V3EmitMk.cpp | 3 + src/V3Options.cpp | 4 +- src/V3Options.h | 4 +- test_regress/t/t_vpi_get.cpp | 1 - test_regress/t/t_vpi_get.pl | 2 +- test_regress/t/t_vpi_memory.cpp | 1 - test_regress/t/t_vpi_memory.pl | 2 +- test_regress/t/t_vpi_unimpl.cpp | 5 +- test_regress/t/t_vpi_unimpl.pl | 2 +- test_regress/t/t_vpi_var.cpp | 44 +- test_regress/t/t_vpi_var.pl | 2 +- 15 files changed, 1095 insertions(+), 1052 deletions(-) diff --git a/Changes b/Changes index 214fb5321..6463c4a07 100644 --- a/Changes +++ b/Changes @@ -5,6 +5,8 @@ indicates the contributor was also the author of the fix; Thanks! * Verilator 3.877 devel +** Add --vpi flag, and fix VPI linkage, bug969. [Arthur Kahlich] + **** Add VerilatedScopeNameMap for introspection, bug966. [Todd Strader] **** Fix very long module names, bug937. [Todd Strader] diff --git a/bin/verilator b/bin/verilator index 8477f6084..db6ddcff4 100755 --- a/bin/verilator +++ b/bin/verilator @@ -331,6 +331,7 @@ descriptions in the next sections for more information. -v Verilog library +verilog1995ext+ Synonym for +1364-1995ext+ +verilog2001ext+ Synonym for +1364-2001ext+ + --vpi Enable VPI compiles -Werror- Convert warning to error -Wfuture- Disable unknown message warnings -Wno- Disable warning @@ -1103,6 +1104,10 @@ Note -v is fairly standard across Verilog tools. Synonyms for C<+1364-1995ext+>I and C<+1364-2001ext+>I respectively +=item --vpi + +Enable use of VPI and linking against the verilated_vpi.cpp files. + =item -Wall Enable all warnings, including code style warnings that are normally @@ -1802,6 +1807,8 @@ Verilator supports a very limited subset of the VPI. This subset allows inspection, examination, value change callbacks, and depositing of values to public signals only. +VPI is enabled with the verilator --vpi switch. + To access signals via the VPI, Verilator must be told exactly which signals are to be accessed. This is done using the Verilator public pragmas documented below. @@ -1835,17 +1842,28 @@ changed on the specified clock edge. There are many online tutorials and books on the VPI, but an example that accesses the above would be: -void read_and_check() { - vpiHandle vh1 = vpi_handle_by_name((PLI_BYTE8*)"t.readme", NULL); - if (!vh1) { error... } - const char* name = vpi_get_str(vpiName, vh1); - printf("Module name: %s\n"); // Prints "readme" + void read_and_check() { + vpiHandle vh1 = vpi_handle_by_name((PLI_BYTE8*)"t.readme", NULL); + if (!vh1) { error... } + const char* name = vpi_get_str(vpiName, vh1); + printf("Module name: %s\n"); // Prints "readme" + + s_vpi_value v; + v.format = vpiIntVal; + vpi_get_value(vh1, &v); + printf("Value of v: %d\n", v.value.integer); // Prints "readme" + } - s_vpi_value v; - v.format = vpiIntVal; - vpi_get_value(vh1, &v); - printf("Value of v: %d\n", v.value.integer); // Prints "readme" -} +For signal callbacks to work the main loop of the program must call +VerilatedVpi::callValueCbs(). + + #include "verilated_vpi.h" // Required to get definitions + ... + while (time passes) { + ... + topp->eval(); + VerilatedVpi::callValueCbs(); + } =head1 CROSS COMPILATION diff --git a/include/verilated_vpi.cpp b/include/verilated_vpi.cpp index 2b7b2d0b0..2110fcbdc 100644 --- a/include/verilated_vpi.cpp +++ b/include/verilated_vpi.cpp @@ -19,10 +19,14 @@ /// This file must be compiled and linked against all objects /// created from Verilator or called by Verilator that use the VPI. /// +/// Use "verilator --vpi" to add this to the Makefile for the linker. +/// /// Code available from: http://www.veripool.org/verilator /// //========================================================================= + +#include "verilated.h" #include "verilated_vpi.h" //====================================================================== @@ -31,6 +35,18 @@ VerilatedVpi VerilatedVpi::s_s; // Singleton vluint8_t* VerilatedVpio::s_freeHead = NULL; //====================================================================== +// VerilatedVpi Methods + + +VerilatedVpiError* VerilatedVpi::error_info() { + if (s_s.m_errorInfop == NULL) { + s_s.m_errorInfop = new VerilatedVpiError(); + } + return s_s.m_errorInfop; +} + +//====================================================================== +// VerilatedVpiError Methods const char* VerilatedVpiError::strFromVpiVal(PLI_INT32 vpiVal) { static const char *names[] = { @@ -241,6 +257,7 @@ const char* VerilatedVpiError::strFromVpiMethod(PLI_INT32 vpiVal) { } return names[vpiVal-vpiCondition]; } + const char* VerilatedVpiError::strFromVpiCallbackReason(PLI_INT32 vpiVal) { static const char *names[] = { "*undefined*", @@ -279,6 +296,7 @@ const char* VerilatedVpiError::strFromVpiCallbackReason(PLI_INT32 vpiVal) { if (vpiVal < 0) return names[0]; return names[(vpiVal<=cbAtEndOfSimTime)?vpiVal:0]; } + const char* VerilatedVpiError::strFromVpiProp(PLI_INT32 vpiVal) { static const char *names[] = { "*undefined or other*", @@ -362,3 +380,1021 @@ const char* VerilatedVpiError::strFromVpiProp(PLI_INT32 vpiVal) { } return names[(vpiVal<=vpiIsProtected)?vpiVal:0]; } + +#define CHECK_RESULT_CSTR(got, exp) \ + if (strcmp((got),(exp))) { \ + string msg = string("%Error: ") \ + + "GOT = '"+((got)?(got):"")+"'" \ + + " EXP = '"+((exp)?(exp):"")+"'"; \ + vl_fatal(__FILE__,__LINE__,"",msg.c_str()); \ + } + +#define CHECK_ENUM_STR(fn, enum) \ + do { \ + const char* strVal = VerilatedVpiError::fn(enum); \ + CHECK_RESULT_CSTR(strVal, #enum); \ + } while (0) + +void VerilatedVpiError::selfTest() { + CHECK_ENUM_STR(strFromVpiVal, vpiBinStrVal); + CHECK_ENUM_STR(strFromVpiVal, vpiRawFourStateVal); + + CHECK_ENUM_STR(strFromVpiObjType, vpiAlways); + CHECK_ENUM_STR(strFromVpiObjType, vpiWhile); + CHECK_ENUM_STR(strFromVpiObjType, vpiAttribute); + CHECK_ENUM_STR(strFromVpiObjType, vpiUdpArray); + CHECK_ENUM_STR(strFromVpiObjType, vpiContAssignBit); + CHECK_ENUM_STR(strFromVpiObjType, vpiGenVar); + + CHECK_ENUM_STR(strFromVpiMethod, vpiCondition); + CHECK_ENUM_STR(strFromVpiMethod, vpiStmt); + + CHECK_ENUM_STR(strFromVpiCallbackReason, cbValueChange); + CHECK_ENUM_STR(strFromVpiCallbackReason, cbAtEndOfSimTime); + + CHECK_ENUM_STR(strFromVpiProp, vpiType); + CHECK_ENUM_STR(strFromVpiProp, vpiProtected); + CHECK_ENUM_STR(strFromVpiProp, vpiDirection); + CHECK_ENUM_STR(strFromVpiProp, vpiTermIndex); + CHECK_ENUM_STR(strFromVpiProp, vpiConstType); + CHECK_ENUM_STR(strFromVpiProp, vpiAutomatic); + CHECK_ENUM_STR(strFromVpiProp, vpiOffset); + CHECK_ENUM_STR(strFromVpiProp, vpiStop); + CHECK_ENUM_STR(strFromVpiProp, vpiIsProtected); +} + +#undef CHECK_ENUM_STR +#undef CHECK_RESULT_CSTR + +//====================================================================== +// callback related + +vpiHandle vpi_register_cb(p_cb_data cb_data_p) { + _VL_VPI_ERROR_RESET(); // reset vpi error status + if (VL_UNLIKELY(!cb_data_p)) { + _VL_VPI_WARNING(__FILE__, __LINE__, "%s : callback data pointer is null", VL_FUNC); + return NULL; + } + switch (cb_data_p->reason) { + case cbAfterDelay: { + QData time = 0; + if (cb_data_p->time) time = _VL_SET_QII(cb_data_p->time->high, cb_data_p->time->low); + VerilatedVpioCb* vop = new VerilatedVpioCb(cb_data_p, VL_TIME_Q()+time); + VL_DEBUG_IF_PLI(VL_PRINTF("-vltVpi: vpi_register_cb %d %p delay=%" VL_PRI64 "d\n",cb_data_p->reason,vop,time);); + VerilatedVpi::cbTimedAdd(vop); + return vop->castVpiHandle(); + } + case cbReadWriteSynch: // FALLTHRU // Supported via vlt_main.cpp + case cbReadOnlySynch: // FALLTHRU // Supported via vlt_main.cpp + case cbNextSimTime: // FALLTHRU // Supported via vlt_main.cpp + case cbStartOfSimulation: // FALLTHRU // Supported via vlt_main.cpp + case cbEndOfSimulation: // FALLTHRU // Supported via vlt_main.cpp + case cbValueChange: // FALLTHRU // Supported via vlt_main.cpp + case cbPLIError: // FALLTHRU // NOP, but need to return handle, so make object + case cbEnterInteractive: // FALLTHRU // NOP, but need to return handle, so make object + case cbExitInteractive: // FALLTHRU // NOP, but need to return handle, so make object + case cbInteractiveScopeChange: { // FALLTHRU // NOP, but need to return handle, so make object + VerilatedVpioCb* vop = new VerilatedVpioCb(cb_data_p, 0); + VL_DEBUG_IF_PLI(VL_PRINTF("-vltVpi: vpi_register_cb %d %p\n",cb_data_p->reason,vop);); + VerilatedVpi::cbReasonAdd(vop); + return vop->castVpiHandle(); + } + default: + _VL_VPI_WARNING(__FILE__, __LINE__, "%s: Unsupported callback type %s", + VL_FUNC, VerilatedVpiError::strFromVpiCallbackReason(cb_data_p->reason)); + return NULL; + }; +} + +PLI_INT32 vpi_remove_cb(vpiHandle object) { + VL_DEBUG_IF_PLI(VL_PRINTF("-vltVpi: vpi_remove_cb %p\n",object);); + VerilatedVpioCb* vop = VerilatedVpioCb::castp(object); + _VL_VPI_ERROR_RESET(); // reset vpi error status + if (VL_UNLIKELY(!vop)) return 0; + if (vop->cb_datap()->reason == cbAfterDelay) { + VerilatedVpi::cbTimedRemove(vop); + } else { + VerilatedVpi::cbReasonRemove(vop); + } + return 1; +} + +void vpi_get_cb_info(vpiHandle object, p_cb_data cb_data_p) { + _VL_VPI_UNIMP(); return; +} +vpiHandle vpi_register_systf(p_vpi_systf_data systf_data_p) { + _VL_VPI_UNIMP(); return 0; +} +void vpi_get_systf_info(vpiHandle object, p_vpi_systf_data systf_data_p) { + _VL_VPI_UNIMP(); return; +} + +// for obtaining handles + +vpiHandle vpi_handle_by_name(PLI_BYTE8* namep, vpiHandle scope) { + _VL_VPI_ERROR_RESET(); // reset vpi error status + if (VL_UNLIKELY(!namep)) return NULL; + VL_DEBUG_IF_PLI(VL_PRINTF("-vltVpi: vpi_handle_by_name %s %p\n",namep,scope);); + VerilatedVpioScope* voScopep = VerilatedVpioScope::castp(scope); + const VerilatedVar* varp; + const VerilatedScope* scopep; + string scopeAndName = namep; + if (voScopep) { + scopeAndName = string(voScopep->fullname()) + "." + namep; + namep = (PLI_BYTE8*)scopeAndName.c_str(); + } + { + // This doesn't yet follow the hierarchy in the proper way + scopep = Verilated::scopeFind(namep); + if (scopep) { // Whole thing found as a scope + return (new VerilatedVpioScope(scopep))->castVpiHandle(); + } + const char* baseNamep = scopeAndName.c_str(); + string scopename; + const char* dotp = strrchr(namep, '.'); + if (VL_LIKELY(dotp)) { + baseNamep = dotp+1; + scopename = string(namep,dotp-namep); + } + scopep = Verilated::scopeFind(scopename.c_str()); + if (!scopep) return NULL; + varp = scopep->varFind(baseNamep); + } + if (!varp) return NULL; + return (new VerilatedVpioVar(varp, scopep))->castVpiHandle(); +} + +vpiHandle vpi_handle_by_index(vpiHandle object, PLI_INT32 indx) { + // Used to get array entries + VL_DEBUG_IF_PLI(VL_PRINTF("-vltVpi: vpi_handle_by_index %p %d\n",object, indx);); + VerilatedVpioVar* varop = VerilatedVpioVar::castp(object); + _VL_VPI_ERROR_RESET(); // reset vpi error status + if (VL_LIKELY(varop)) { + if (varop->varp()->dims()<2) return 0; + if (VL_LIKELY(varop->varp()->array().left() >= varop->varp()->array().right())) { + if (VL_UNLIKELY(indx > varop->varp()->array().left() || indx < varop->varp()->array().right())) return 0; + return (new VerilatedVpioMemoryWord(varop->varp(), varop->scopep(), indx, + indx - varop->varp()->array().right())) + ->castVpiHandle(); + } else { + if (VL_UNLIKELY(indx < varop->varp()->array().left() || indx > varop->varp()->array().right())) return 0; + return (new VerilatedVpioMemoryWord(varop->varp(), varop->scopep(), indx, + indx - varop->varp()->array().left())) + ->castVpiHandle(); + } + } else { + _VL_VPI_INTERNAL(__FILE__, __LINE__, "%s : can't resolve handle", VL_FUNC); + return 0; + } +} + +// for traversing relationships + +vpiHandle vpi_handle(PLI_INT32 type, vpiHandle object) { + VL_DEBUG_IF_PLI(VL_PRINTF("-vltVpi: vpi_handle %d %p\n",type,object);); + _VL_VPI_ERROR_RESET(); // reset vpi error status + switch (type) { + case vpiLeftRange: { + VerilatedVpioVar* vop = VerilatedVpioVar::castp(object); + if (VL_UNLIKELY(!vop)) return 0; + if (VL_UNLIKELY(!vop->rangep())) return 0; + return (new VerilatedVpioConst(vop->rangep()->left()))->castVpiHandle(); + } + case vpiRightRange: { + VerilatedVpioVar* vop = VerilatedVpioVar::castp(object); + if (VL_UNLIKELY(!vop)) return 0; + if (VL_UNLIKELY(!vop->rangep())) return 0; + return (new VerilatedVpioConst(vop->rangep()->right()))->castVpiHandle(); + } + case vpiIndex: { + VerilatedVpioVar* vop = VerilatedVpioVar::castp(object); + if (VL_UNLIKELY(!vop)) return 0; + return (new VerilatedVpioConst(vop->index()))->castVpiHandle(); + } + case vpiScope: { + VerilatedVpioVar* vop = VerilatedVpioVar::castp(object); + if (VL_UNLIKELY(!vop)) return 0; + return (new VerilatedVpioScope(vop->scopep()))->castVpiHandle(); + } + case vpiParent: { + VerilatedVpioMemoryWord* vop = VerilatedVpioMemoryWord::castp(object); + if (VL_UNLIKELY(!vop)) return 0; + return (new VerilatedVpioVar(vop->varp(), vop->scopep()))->castVpiHandle(); + } + default: + _VL_VPI_WARNING(__FILE__, __LINE__, "%s: Unsupported type %s, nothing will be returned", + VL_FUNC, VerilatedVpiError::strFromVpiMethod(type)); + return 0; + } +} + +vpiHandle vpi_handle_multi(PLI_INT32 type, vpiHandle refHandle1, vpiHandle refHandle2, ... ) { + _VL_VPI_UNIMP(); return 0; +} + +vpiHandle vpi_iterate(PLI_INT32 type, vpiHandle object) { + VL_DEBUG_IF_PLI(VL_PRINTF("-vltVpi: vpi_iterate %d %p\n",type,object);); + _VL_VPI_ERROR_RESET(); // reset vpi error status + switch (type) { + case vpiMemoryWord: { + VerilatedVpioVar* vop = VerilatedVpioVar::castp(object); + if (VL_UNLIKELY(!vop)) return 0; + if (vop->varp()->dims() < 2) return 0; + if (vop->varp()->dims() > 2) { + _VL_VPI_WARNING(__FILE__, __LINE__, "%s: %s, object %s has unsupported number of indices (%d)", + VL_FUNC, VerilatedVpiError::strFromVpiMethod(type), vop->fullname() , vop->varp()->dims()); + } + return (new VerilatedVpioMemoryWordIter(object, vop->varp()))->castVpiHandle(); + } + case vpiRange: { + VerilatedVpioVar* vop = VerilatedVpioVar::castp(object); + if (VL_UNLIKELY(!vop)) return 0; + if (vop->varp()->dims() < 2) return 0; + // Unsupported is multidim list + if (vop->varp()->dims() > 2) { + _VL_VPI_WARNING(__FILE__, __LINE__, "%s: %s, object %s has unsupported number of indices (%d)", + VL_FUNC, VerilatedVpiError::strFromVpiMethod(type), vop->fullname() , vop->varp()->dims()); + } + return ((new VerilatedVpioRange(vop->rangep()))->castVpiHandle()); + } + case vpiReg: { + VerilatedVpioScope* vop = VerilatedVpioScope::castp(object); + if (VL_UNLIKELY(!vop)) return 0; + return ((new VerilatedVpioVarIter(vop->scopep())) + ->castVpiHandle()); + } + default: + _VL_VPI_WARNING(__FILE__, __LINE__, "%s: Unsupported type %s, nothing will be returned", + VL_FUNC, VerilatedVpiError::strFromVpiObjType(type)); + return 0; + } +} +vpiHandle vpi_scan(vpiHandle object) { + VL_DEBUG_IF_PLI(VL_PRINTF("-vltVpi: vpi_scan %p\n",object);); + _VL_VPI_ERROR_RESET(); // reset vpi error status + VerilatedVpio* vop = VerilatedVpio::castp(object); + if (VL_UNLIKELY(!vop)) return NULL; + return vop->dovpi_scan(); +} + +// for processing properties + +PLI_INT32 vpi_get(PLI_INT32 property, vpiHandle object) { + // Leave this in the header file - in many cases the compiler can constant propagate "object" + VL_DEBUG_IF_PLI(VL_PRINTF("-vltVpi: vpi_get %d %p\n",property,object);); + _VL_VPI_ERROR_RESET(); // reset vpi error status + switch (property) { + case vpiTimePrecision: { + return VL_TIME_PRECISION; + } + case vpiType: { + VerilatedVpio* vop = VerilatedVpioVar::castp(object); + if (VL_UNLIKELY(!vop)) return 0; + return vop->type(); + } + case vpiDirection: { + // By forthought, the directions already are vpi enumerated + VerilatedVpioVar* vop = VerilatedVpioVar::castp(object); + if (VL_UNLIKELY(!vop)) return 0; + return vop->varp()->vldir(); + } + case vpiScalar: // FALLTHRU + case vpiVector: { + VerilatedVpioVar* vop = VerilatedVpioVar::castp(object); + if (VL_UNLIKELY(!vop)) return 0; + return (property==vpiVector)^(vop->varp()->dims()==0); + } + case vpiSize: { + VerilatedVpioVar* vop = VerilatedVpioVar::castp(object); + if (VL_UNLIKELY(!vop)) return 0; + return vop->size(); + } + default: + _VL_VPI_WARNING(__FILE__, __LINE__, "%s: Unsupported type %s, nothing will be returned", + VL_FUNC, VerilatedVpiError::strFromVpiProp(property)); + return 0; + } +} + +PLI_INT64 vpi_get64(PLI_INT32 property, vpiHandle object) { + _VL_VPI_UNIMP(); + return 0; +} + +PLI_BYTE8 *vpi_get_str(PLI_INT32 property, vpiHandle object) { + VL_DEBUG_IF_PLI(VL_PRINTF("-vltVpi: vpi_get_str %d %p\n",property,object);); + VerilatedVpio* vop = VerilatedVpio::castp(object); + _VL_VPI_ERROR_RESET(); // reset vpi error status + if (VL_UNLIKELY(!vop)) return NULL; + switch (property) { + case vpiName: { + return (PLI_BYTE8*)vop->name(); + } + case vpiFullName: { + return (PLI_BYTE8*)vop->fullname(); + } + case vpiDefName: { + return (PLI_BYTE8*)vop->defname(); + } + default: + _VL_VPI_WARNING(__FILE__, __LINE__, "%s: Unsupported type %s, nothing will be returned", + VL_FUNC, VerilatedVpiError::strFromVpiProp(property)); + return 0; + } +} + +// delay processing + +void vpi_get_delays(vpiHandle object, p_vpi_delay delay_p) { + _VL_VPI_UNIMP(); + return; +} +void vpi_put_delays(vpiHandle object, p_vpi_delay delay_p) { + _VL_VPI_UNIMP(); + return; +} + +// value processing + +void vpi_get_value(vpiHandle object, p_vpi_value value_p) { + static VL_THREAD char outStr[1+VL_MULS_MAX_WORDS*32]; // Maximum required size is for binary string, one byte per bit plus null termination + // cppcheck-suppress variableScope + static VL_THREAD int outStrSz = sizeof(outStr)-1; + VL_DEBUG_IF_PLI(VL_PRINTF("-vltVpi: vpi_get_value %p\n",object);); + _VL_VPI_ERROR_RESET(); // reset vpi error status + if (VL_UNLIKELY(!value_p)) return; + if (VerilatedVpioVar* vop = VerilatedVpioVar::castp(object)) { + // We used to presume vpiValue.format = vpiIntVal or if single bit vpiScalarVal + // This may cause backward compatability issues with older code. + if (value_p->format == vpiVectorVal) { + // Vector pointer must come from our memory pool + // It only needs to persist until the next vpi_get_value + static VL_THREAD t_vpi_vecval out[VL_MULS_MAX_WORDS*2]; + value_p->value.vector = out; + switch (vop->varp()->vltype()) { + case VLVT_UINT8: + out[0].aval = *((CData*)(vop->varDatap())); + out[0].bval = 0; + return; + case VLVT_UINT16: + out[0].aval = *((SData*)(vop->varDatap())); + out[0].bval = 0; + return; + case VLVT_UINT32: + out[0].aval = *((IData*)(vop->varDatap())); + out[0].bval = 0; + return; + case VLVT_WDATA: { + int words = VL_WORDS_I(vop->varp()->range().elements()); + if (VL_UNLIKELY(words >= VL_MULS_MAX_WORDS)) { + vl_fatal(__FILE__,__LINE__,"", "vpi_get_value with more than VL_MULS_MAX_WORDS; increase and recompile"); + } + WDataInP datap = ((IData*)(vop->varDatap())); + for (int i=0; ivarDatap())); + out[1].aval = (IData)(data>>VL_ULL(32)); + out[1].bval = 0; + out[0].aval = (IData)(data); + out[0].bval = 0; + return; + } + default: { + _VL_VPI_ERROR(__FILE__, __LINE__, "%s: Unsupported format (%s) for %s", + VL_FUNC, VerilatedVpiError::strFromVpiVal(value_p->format), vop->fullname()); + return; + } + } + } else if (value_p->format == vpiBinStrVal) { + value_p->value.str = outStr; + switch (vop->varp()->vltype()) { + case VLVT_UINT8 : + case VLVT_UINT16: + case VLVT_UINT32: + case VLVT_UINT64: + case VLVT_WDATA: { + int bits = vop->varp()->range().elements(); + CData* datap = ((CData*)(vop->varDatap())); + int i; + if (bits > outStrSz) { + // limit maximum size of output to size of buffer to prevent overrun. + bits = outStrSz; + _VL_VPI_WARNING(__FILE__, __LINE__, "%s: Truncating string value of %s for %s as buffer size (%d, VL_MULS_MAX_WORDS=%d) is less than required (%d)", + VL_FUNC, VerilatedVpiError::strFromVpiVal(value_p->format), vop->fullname(), outStrSz, VL_MULS_MAX_WORDS, bits); + } + for (i=0; i>3]>>(i&7))&1; + outStr[bits-i-1] = val?'1':'0'; + } + outStr[i]=0; // NULL terminate + return; + } + default: + _VL_VPI_ERROR(__FILE__, __LINE__, "%s: Unsupported format (%s) for %s", + VL_FUNC, VerilatedVpiError::strFromVpiVal(value_p->format), vop->fullname()); + return; + } + } else if (value_p->format == vpiOctStrVal) { + value_p->value.str = outStr; + switch (vop->varp()->vltype()) { + case VLVT_UINT8 : + case VLVT_UINT16: + case VLVT_UINT32: + case VLVT_UINT64: + case VLVT_WDATA: { + int chars = (vop->varp()->range().elements()+2)/3; + int bytes = VL_BYTES_I(vop->varp()->range().elements()); + CData* datap = ((CData*)(vop->varDatap())); + int i; + if (chars > outStrSz) { + // limit maximum size of output to size of buffer to prevent overrun. + _VL_VPI_WARNING(__FILE__, __LINE__, "%s: Truncating string value of %s for %s as buffer size (%d, VL_MULS_MAX_WORDS=%d) is less than required (%d)", + VL_FUNC, VerilatedVpiError::strFromVpiVal(value_p->format), vop->fullname(), outStrSz, VL_MULS_MAX_WORDS, chars); + chars = outStrSz; + } + for (i=0; i>= idx.rem; + if (i==(chars-1)) { + // most signifcant char, mask off non existant bits when vector + // size is not a multiple of 3 + unsigned int rem = vop->varp()->range().elements() % 3; + if (rem) { + // generate bit mask & zero non existant bits + val &= (1<format), vop->fullname()); + return; + } + } else if (value_p->format == vpiDecStrVal) { + value_p->value.str = outStr; + switch (vop->varp()->vltype()) { + // outStrSz does not include NULL termination so add one + case VLVT_UINT8 : VL_SNPRINTF(outStr, outStrSz+1, "%hhu", (unsigned char )*((CData*)(vop->varDatap()))); return; + case VLVT_UINT16: VL_SNPRINTF(outStr, outStrSz+1, "%hu", (unsigned short)*((SData*)(vop->varDatap()))); return; + case VLVT_UINT32: VL_SNPRINTF(outStr, outStrSz+1, "%u", (unsigned int )*((IData*)(vop->varDatap()))); return; + case VLVT_UINT64: VL_SNPRINTF(outStr, outStrSz+1, "%llu", (unsigned long long)*((QData*)(vop->varDatap()))); return; + default: + strcpy(outStr, "-1"); + _VL_VPI_ERROR(__FILE__, __LINE__, "%s: Unsupported format (%s) for %s, maximum limit is 64 bits", + VL_FUNC, VerilatedVpiError::strFromVpiVal(value_p->format), vop->fullname()); + return; + } + } else if (value_p->format == vpiHexStrVal) { + value_p->value.str = outStr; + switch (vop->varp()->vltype()) { + case VLVT_UINT8 : + case VLVT_UINT16: + case VLVT_UINT32: + case VLVT_UINT64: + case VLVT_WDATA: { + int chars = (vop->varp()->range().elements()+3)>>2; + CData* datap = ((CData*)(vop->varDatap())); + int i; + if (chars > outStrSz) { + // limit maximum size of output to size of buffer to prevent overrun. + _VL_VPI_WARNING(__FILE__, __LINE__, "%s: Truncating string value of %s for %s as buffer size (%d, VL_MULS_MAX_WORDS=%d) is less than required (%d)", + VL_FUNC, VerilatedVpiError::strFromVpiVal(value_p->format), vop->fullname(), outStrSz, VL_MULS_MAX_WORDS, chars); + chars = outStrSz; + } + for (i=0; i>1]>>((i&1)<<2))&15; + static char hex[] = "0123456789abcdef"; + if (i==(chars-1)) { + // most signifcant char, mask off non existant bits when vector + // size is not a multiple of 4 + unsigned int rem = vop->varp()->range().elements() & 3; + if (rem) { + // generate bit mask & zero non existant bits + val &= (1<(val)]; + } + outStr[i]=0; // NULL terminate + return; + } + default: + _VL_VPI_ERROR(__FILE__, __LINE__, "%s: Unsupported format (%s) for %s", + VL_FUNC, VerilatedVpiError::strFromVpiVal(value_p->format), vop->fullname()); + return; + } + } else if (value_p->format == vpiStringVal) { + value_p->value.str = outStr; + switch (vop->varp()->vltype()) { + case VLVT_UINT8 : + case VLVT_UINT16: + case VLVT_UINT32: + case VLVT_UINT64: + case VLVT_WDATA: { + int bytes = VL_BYTES_I(vop->varp()->range().elements()); + CData* datap = ((CData*)(vop->varDatap())); + int i; + if (bytes > outStrSz) { + // limit maximum size of output to size of buffer to prevent overrun. + _VL_VPI_WARNING(__FILE__, __LINE__, "%s: Truncating string value of %s for %s as buffer size (%d, VL_MULS_MAX_WORDS=%d) is less than required (%d)", + VL_FUNC, VerilatedVpiError::strFromVpiVal(value_p->format), + vop->fullname(), outStrSz, VL_MULS_MAX_WORDS, bytes); + bytes = outStrSz; + } + for (i=0; iformat), vop->fullname()); + return; + } + } else if (value_p->format == vpiIntVal) { + switch (vop->varp()->vltype()) { + case VLVT_UINT8: + value_p->value.integer = *((CData*)(vop->varDatap())); + return; + case VLVT_UINT16: + value_p->value.integer = *((SData*)(vop->varDatap())); + return; + case VLVT_UINT32: + value_p->value.integer = *((IData*)(vop->varDatap())); + return; + case VLVT_WDATA: + case VLVT_UINT64: + // Not legal + value_p->value.integer = 0; + default: + _VL_VPI_ERROR(__FILE__, __LINE__, "%s: Unsupported format (%s) for %s", + VL_FUNC, VerilatedVpiError::strFromVpiVal(value_p->format), vop->fullname()); + return; + } + } else if (value_p->format == vpiSuppressVal) { + return; + } + _VL_VPI_ERROR(__FILE__, __LINE__, "%s: Unsupported format (%s) as requested for %s", + VL_FUNC, VerilatedVpiError::strFromVpiVal(value_p->format), vop->fullname()); + return; + } + else if (VerilatedVpioConst* vop = VerilatedVpioConst::castp(object)) { + if (value_p->format == vpiIntVal) { + value_p->value.integer = vop->num(); + return; + } + _VL_VPI_ERROR(__FILE__, __LINE__, "%s: Unsupported format (%s) for %s", + VL_FUNC, VerilatedVpiError::strFromVpiVal(value_p->format), vop->fullname()); + return; + } + _VL_VPI_ERROR(__FILE__, __LINE__, "%s: Unsupported format %s", + VL_FUNC, VerilatedVpiError::strFromVpiVal(value_p->format)); +} + +vpiHandle vpi_put_value(vpiHandle object, p_vpi_value value_p, + p_vpi_time time_p, PLI_INT32 flags) { + VL_DEBUG_IF_PLI(VL_PRINTF("-vltVpi: vpi_put_value %p %p\n",object, value_p);); + _VL_VPI_ERROR_RESET(); // reset vpi error status + if (VL_UNLIKELY(!value_p)) { + _VL_VPI_WARNING(__FILE__, __LINE__, "Ignoring vpi_put_value with NULL value pointer"); + return 0; + } + if (VerilatedVpioVar* vop = VerilatedVpioVar::castp(object)) { + VL_DEBUG_IF_PLI(VL_PRINTF("-vltVpi: vpi_put_value name=%s fmt=%d vali=%d\n", + vop->fullname(), value_p->format, value_p->value.integer); + VL_PRINTF("-vltVpi: varp=%p putatp=%p\n", + vop->varp()->datap(), vop->varDatap());); + if (VL_UNLIKELY(!vop->varp()->isPublicRW())) { + _VL_VPI_WARNING(__FILE__, __LINE__, "Ignoring vpi_put_value to signal marked read-only, use public_flat_rw instead: ", vop->fullname()); + return 0; + } + if (value_p->format == vpiVectorVal) { + if (VL_UNLIKELY(!value_p->value.vector)) return NULL; + switch (vop->varp()->vltype()) { + case VLVT_UINT8: + *((CData*)(vop->varDatap())) = value_p->value.vector[0].aval & vop->mask(); + return object; + case VLVT_UINT16: + *((SData*)(vop->varDatap())) = value_p->value.vector[0].aval & vop->mask(); + return object; + case VLVT_UINT32: + *((IData*)(vop->varDatap())) = value_p->value.vector[0].aval & vop->mask(); + return object; + case VLVT_WDATA: { + int words = VL_WORDS_I(vop->varp()->range().elements()); + WDataOutP datap = ((IData*)(vop->varDatap())); + for (int i=0; ivalue.vector[i].aval; + if (i==(words-1)) { + datap[i] &= vop->mask(); + } + } + return object; + } + case VLVT_UINT64: { + *((QData*)(vop->varDatap())) = _VL_SET_QII( + value_p->value.vector[1].aval & vop->mask(), + value_p->value.vector[0].aval); + return object; + } + default: { + _VL_VPI_ERROR(__FILE__, __LINE__, "%s: Unsupported format (%s) for %s", + VL_FUNC, VerilatedVpiError::strFromVpiVal(value_p->format), vop->fullname()); + return NULL; + } + } + } else if (value_p->format == vpiBinStrVal) { + switch (vop->varp()->vltype()) { + case VLVT_UINT8 : + case VLVT_UINT16: + case VLVT_UINT32: + case VLVT_UINT64: + case VLVT_WDATA: { + int bits = vop->varp()->range().elements(); + int len = strlen(value_p->value.str); + CData* datap = ((CData*)(vop->varDatap())); + for (int i=0; ivalue.str[len-i-1]=='1'):0; + // zero bits 7:1 of byte when assigning to bit 0, else + // or in 1 if bit set + if (i&7) { + datap[i>>3] |= set<<(i&7); + } else { + datap[i>>3] = set; + } + } + return object; + } + default: + _VL_VPI_ERROR(__FILE__, __LINE__, "%s: Unsupported format (%s) for %s", + VL_FUNC, VerilatedVpiError::strFromVpiVal(value_p->format), vop->fullname()); + return 0; + } + } else if (value_p->format == vpiOctStrVal) { + switch (vop->varp()->vltype()) { + case VLVT_UINT8 : + case VLVT_UINT16: + case VLVT_UINT32: + case VLVT_UINT64: + case VLVT_WDATA: { + int chars = (vop->varp()->range().elements()+2)/3; + int bytes = VL_BYTES_I(vop->varp()->range().elements()); + int len = strlen(value_p->value.str); + CData* datap = ((CData*)(vop->varDatap())); + div_t idx; + datap[0] = 0; // reset zero'th byte + for (int i=0; ivalue.str[len-i-1]; + if (digit >= '0' && digit <= '7') { + val.half = digit-'0'; + } else { + _VL_VPI_WARNING(__FILE__, __LINE__, "%s: Non octal character '%c' in '%s' as value %s for %s", + VL_FUNC, digit, value_p->value.str, + VerilatedVpiError::strFromVpiVal(value_p->format), vop->fullname()); + val.half = 0; + } + } else { + val.half = 0; + } + // align octal character to position within vector, note that + // the three bits may straddle a byte bounday so two byte wide + // assignments are made to adjacent bytes - but not if the least + // signifcant byte of the aligned value is the most significant + // byte of the destination. + val.half <<= idx.rem; + datap[idx.quot] |= val.byte[0]; // or in value + if ((idx.quot+1) < bytes) { + datap[idx.quot+1] = val.byte[1]; // this also resets all bits to 0 prior to or'ing above + } + } + // mask off non existant bits in the most significant byte + if (idx.quot == (bytes-1)) { + datap[idx.quot] &= vop->mask_byte(idx.quot); + } else if (idx.quot+1 == (bytes-1)) { + datap[idx.quot+1] &= vop->mask_byte(idx.quot+1); + } + // zero off remaining top bytes + for (int i=idx.quot+2; iformat), vop->fullname()); + return 0; + } + } else if (value_p->format == vpiDecStrVal) { + char remainder[16]; + unsigned long long val; + int success = sscanf(value_p->value.str, "%30llu%15s", &val, remainder); + if (success < 1) { + _VL_VPI_ERROR(__FILE__, __LINE__, "%s: Parsing failed for '%s' as value %s for %s", + VL_FUNC, value_p->value.str, VerilatedVpiError::strFromVpiVal(value_p->format), vop->fullname()); + return 0; + } + if (success > 1) { + _VL_VPI_WARNING(__FILE__, __LINE__, "%s: Trailing garbage '%s' in '%s' as value %s for %s", + VL_FUNC, remainder, value_p->value.str, VerilatedVpiError::strFromVpiVal(value_p->format), vop->fullname()); + } + switch (vop->varp()->vltype()) { + case VLVT_UINT8 : *((CData*)(vop->varDatap())) = val & vop->mask(); break; + case VLVT_UINT16: *((SData*)(vop->varDatap())) = val & vop->mask(); break; + case VLVT_UINT32: *((IData*)(vop->varDatap())) = val & vop->mask(); break; + case VLVT_UINT64: *((QData*)(vop->varDatap())) = val; ((IData*)(vop->varDatap()))[1] &= vop->mask(); break; + case VLVT_WDATA: + default: + _VL_VPI_ERROR(__FILE__, __LINE__, "%s: Unsupported format (%s) for %s, maximum limit is 64 bits", + VL_FUNC, VerilatedVpiError::strFromVpiVal(value_p->format), vop->fullname()); + return 0; + } + return object; + } else if (value_p->format == vpiHexStrVal) { + switch (vop->varp()->vltype()) { + case VLVT_UINT8 : + case VLVT_UINT16: + case VLVT_UINT32: + case VLVT_UINT64: + case VLVT_WDATA: { + int chars = (vop->varp()->range().elements()+3)>>2; + CData* datap = ((CData*)(vop->varDatap())); + char* val = value_p->value.str; + // skip hex ident if one is detected at the start of the string + if (val[0] == '0' && (val[1] == 'x' || val[1] == 'X')) { + val += 2; + } + int len = strlen(val); + for (int i=0; i= '0' && digit <= '9') hex = digit - '0'; + else if (digit >= 'a' && digit <= 'f') hex = digit - 'a' + 10; + else if (digit >= 'A' && digit <= 'F') hex = digit - 'A' + 10; + else { + _VL_VPI_WARNING(__FILE__, __LINE__, "%s: Non hex character '%c' in '%s' as value %s for %s", + VL_FUNC, digit, value_p->value.str, VerilatedVpiError::strFromVpiVal(value_p->format), vop->fullname()); + hex = 0; + } + } else { + hex = 0; + } + // assign hex digit value to destination + if (i&1) { + datap[i>>1] |= hex<<4; + } else { + datap[i>>1] = hex; // this also resets all bits to 0 prior to or'ing above of the msb + } + } + // apply bit mask to most significant byte + datap[(chars-1)>>1] &= vop->mask_byte((chars-1)>>1); + return object; + } + default: + _VL_VPI_ERROR(__FILE__, __LINE__, "%s: Unsupported format (%s) for %s", + VL_FUNC, VerilatedVpiError::strFromVpiVal(value_p->format), vop->fullname()); + return 0; + } + } else if (value_p->format == vpiStringVal) { + switch (vop->varp()->vltype()) { + case VLVT_UINT8 : + case VLVT_UINT16: + case VLVT_UINT32: + case VLVT_UINT64: + case VLVT_WDATA: { + int bytes = VL_BYTES_I(vop->varp()->range().elements()); + int len = strlen(value_p->value.str); + CData* datap = ((CData*)(vop->varDatap())); + for (int i=0; ivalue.str[len-i-1]:0; // prepend with 0 values before placing string the least signifcant bytes + } + return object; + } + default: + _VL_VPI_ERROR(__FILE__, __LINE__, "%s: Unsupported format (%s) for %s", + VL_FUNC, VerilatedVpiError::strFromVpiVal(value_p->format), vop->fullname()); + return 0; + } + } else if (value_p->format == vpiIntVal) { + switch (vop->varp()->vltype()) { + case VLVT_UINT8: + *((CData*)(vop->varDatap())) = vop->mask() & value_p->value.integer; + return object; + case VLVT_UINT16: + *((SData*)(vop->varDatap())) = vop->mask() & value_p->value.integer; + return object; + case VLVT_UINT32: + *((IData*)(vop->varDatap())) = vop->mask() & value_p->value.integer; + return object; + case VLVT_WDATA: // FALLTHRU + case VLVT_UINT64: // FALLTHRU + default: + _VL_VPI_ERROR(__FILE__, __LINE__, "%s: Unsupported format (%s) for %s", + VL_FUNC, VerilatedVpiError::strFromVpiVal(value_p->format), vop->fullname()); + return 0; + } + } + _VL_VPI_ERROR(__FILE__, __LINE__, "%s: Unsupported format (%s) as requested for %s", + VL_FUNC, VerilatedVpiError::strFromVpiVal(value_p->format), vop->fullname()); + return NULL; + } + _VL_VPI_ERROR(__FILE__, __LINE__, "%s: Unsupported format (%s) for ??", + VL_FUNC, VerilatedVpiError::strFromVpiVal(value_p->format)); + return NULL; +} + +void vpi_get_value_array(vpiHandle object, p_vpi_arrayvalue arrayvalue_p, + PLI_INT32 *index_p, PLI_UINT32 num) { + _VL_VPI_UNIMP(); return; +} +void vpi_put_value_array(vpiHandle object, p_vpi_arrayvalue arrayvalue_p, + PLI_INT32 *index_p, PLI_UINT32 num) { + _VL_VPI_UNIMP(); return; +} + + +// time processing + +void vpi_get_time(vpiHandle object, p_vpi_time time_p) { + if (VL_UNLIKELY(!time_p)) { + _VL_VPI_WARNING(__FILE__, __LINE__, "Ignoring vpi_get_time with NULL value pointer"); + return; + } + if (time_p->type == vpiSimTime) { + QData qtime = VL_TIME_Q(); + IData itime[2]; + VL_SET_WQ(itime, qtime); + time_p->low = itime[0]; + time_p->high = itime[1]; + return; + } + _VL_VPI_ERROR(__FILE__, __LINE__, "%s: Unsupported type (%d)", + VL_FUNC, time_p->type); + return; +} + +// I/O routines + +PLI_UINT32 vpi_mcd_open(PLI_BYTE8 *filenamep) { + _VL_VPI_ERROR_RESET(); // reset vpi error status + return VL_FOPEN_S(filenamep,"wb"); +} + +PLI_UINT32 vpi_mcd_close(PLI_UINT32 mcd) { + _VL_VPI_ERROR_RESET(); // reset vpi error status + VL_FCLOSE_I(mcd); return 0; +} + +PLI_BYTE8 *vpi_mcd_name(PLI_UINT32 mcd) { + _VL_VPI_UNIMP(); return 0; +} + +PLI_INT32 vpi_mcd_printf(PLI_UINT32 mcd, PLI_BYTE8 *formatp, ...) { + _VL_VPI_ERROR_RESET(); // reset vpi error status + va_list ap; + va_start(ap,formatp); + int chars = vpi_mcd_vprintf(mcd, formatp, ap); + va_end(ap); + return chars; +} + +PLI_INT32 vpi_printf(PLI_BYTE8 *formatp, ...) { + _VL_VPI_ERROR_RESET(); // reset vpi error status + va_list ap; + va_start(ap,formatp); + int chars = vpi_vprintf(formatp, ap); + va_end(ap); + return chars; +} + +PLI_INT32 vpi_vprintf(PLI_BYTE8* formatp, va_list ap) { + _VL_VPI_ERROR_RESET(); // reset vpi error status + return VL_VPRINTF(formatp, ap); +} + +PLI_INT32 vpi_mcd_vprintf(PLI_UINT32 mcd, PLI_BYTE8 *format, va_list ap) { + FILE* fp = VL_CVT_I_FP(mcd); + _VL_VPI_ERROR_RESET(); // reset vpi error status + if (VL_UNLIKELY(!fp)) return 0; + int chars = vfprintf(fp, format, ap); + return chars; +} + +PLI_INT32 vpi_flush(void) { + _VL_VPI_ERROR_RESET(); // reset vpi error status + Verilated::flushCall(); + return 0; +} + +PLI_INT32 vpi_mcd_flush(PLI_UINT32 mcd) { + FILE* fp = VL_CVT_I_FP(mcd); + _VL_VPI_ERROR_RESET(); // reset vpi error status + if (VL_UNLIKELY(!fp)) return 1; + fflush(fp); + return 0; +} + +// utility routines + +PLI_INT32 vpi_compare_objects(vpiHandle object1, vpiHandle object2) { + _VL_VPI_UNIMP(); return 0; +} +PLI_INT32 vpi_chk_error(p_vpi_error_info error_info_p) { + // executing vpi_chk_error does not reset error + // error_info_p can be NULL, so only return level in that case + p_vpi_error_info _error_info_p = VerilatedVpi::error_info()->getError(); + if (error_info_p && _error_info_p) { + *error_info_p = *_error_info_p; + } + if (!_error_info_p) return 0; // no error occured + return _error_info_p->level; // return error severity level +}; + +PLI_INT32 vpi_free_object(vpiHandle object) { + _VL_VPI_ERROR_RESET(); // reset vpi error status + return vpi_release_handle(object); // Deprecated +} + +PLI_INT32 vpi_release_handle (vpiHandle object) { + VL_DEBUG_IF_PLI(VL_PRINTF("-vltVpi: vpi_release_handle %p\n",object);); + VerilatedVpio* vop = VerilatedVpio::castp(object); + _VL_VPI_ERROR_RESET(); // reset vpi error status + if (VL_UNLIKELY(!vop)) return 0; + vpi_remove_cb(object); // May not be a callback, but that's ok + delete vop; + return 1; +} + +PLI_INT32 vpi_get_vlog_info(p_vpi_vlog_info vlog_info_p) { + _VL_VPI_ERROR_RESET(); // reset vpi error status + vlog_info_p->argc = Verilated::getCommandArgs()->argc; + vlog_info_p->argv = (PLI_BYTE8**)Verilated::getCommandArgs()->argv; + vlog_info_p->product = (PLI_BYTE8*)Verilated::productName(); + vlog_info_p->version = (PLI_BYTE8*)Verilated::productVersion(); + return 1; +} + +// routines added with 1364-2001 + +PLI_INT32 vpi_get_data(PLI_INT32 id, PLI_BYTE8 *dataLoc, PLI_INT32 numOfBytes) { + _VL_VPI_UNIMP(); return 0; +} +PLI_INT32 vpi_put_data(PLI_INT32 id, PLI_BYTE8 *dataLoc, PLI_INT32 numOfBytes) { + _VL_VPI_UNIMP(); return 0; +} +void *vpi_get_userdata(vpiHandle obj) { + _VL_VPI_UNIMP(); return 0; +} +PLI_INT32 vpi_put_userdata(vpiHandle obj, void *userdata) { + _VL_VPI_UNIMP(); return 0; +} + +PLI_INT32 vpi_control(PLI_INT32 operation, ...) { + VL_DEBUG_IF_PLI(VL_PRINTF("-vltVpi: vpi_control %d\n",operation);); + _VL_VPI_ERROR_RESET(); // reset vpi error status + switch (operation) { + case vpiFinish: { + vl_finish(__FILE__,__LINE__,"*VPI*"); + return 1; + } + case vpiStop: { + vl_stop(__FILE__,__LINE__,"*VPI*"); + return 1; + } + } + _VL_VPI_WARNING(__FILE__, __LINE__, "%s: Unsupported type %s, ignoring", + VL_FUNC, VerilatedVpiError::strFromVpiProp(operation)); + return 0; +} + +vpiHandle vpi_handle_by_multi_index(vpiHandle obj, PLI_INT32 num_index, PLI_INT32 *index_array) { + _VL_VPI_UNIMP(); return 0; +} diff --git a/include/verilated_vpi.h b/include/verilated_vpi.h index e5fc4fc45..4acc99a9f 100644 --- a/include/verilated_vpi.h +++ b/include/verilated_vpi.h @@ -23,17 +23,27 @@ /// //========================================================================= -#ifndef CHPI_VERILATED_VPI_H -#define CHPI_VERILATED_VPI_H 1 +#ifndef _VERILATED_VPI_H_ +#define _VERILATED_VPI_H_ 1 ///< Header Guard #include "verilated.h" #include "verilated_syms.h" +#include +#include +#include + //====================================================================== // From IEEE 1800-2009 annex K #include "vltstd/vpi_user.h" +//====================================================================== +// Internal constants + +#define VL_DEBUG_IF_PLI VL_DEBUG_IF +#define VL_VPI_LINE_SIZE 8192 + //====================================================================== // Internal macros @@ -51,13 +61,6 @@ //====================================================================== // Implementation -#include -#include -#include - -#define VL_DEBUG_IF_PLI VL_DEBUG_IF -#define VL_VPI_LINE_SIZE 8192 - // Base VPI handled object class VerilatedVpio { // MEM MANGLEMENT @@ -454,6 +457,7 @@ public: m_errorInfo.product = (PLI_BYTE8*)Verilated::productName(); } ~VerilatedVpiError() {} + static void selfTest(); VerilatedVpiError* setMessage(PLI_INT32 level) { m_flag=true; m_errorInfo.level = level; @@ -489,985 +493,6 @@ public: static const char* strFromVpiProp(PLI_INT32 vpiVal); }; -VerilatedVpiError* VerilatedVpi::error_info() { - if (s_s.m_errorInfop == NULL) { - s_s.m_errorInfop = new VerilatedVpiError(); - } - return s_s.m_errorInfop; -} - -// callback related - -vpiHandle vpi_register_cb(p_cb_data cb_data_p) { - _VL_VPI_ERROR_RESET(); // reset vpi error status - if (VL_UNLIKELY(!cb_data_p)) { - _VL_VPI_WARNING(__FILE__, __LINE__, "%s : callback data pointer is null", VL_FUNC); - return NULL; - } - switch (cb_data_p->reason) { - case cbAfterDelay: { - QData time = 0; - if (cb_data_p->time) time = _VL_SET_QII(cb_data_p->time->high, cb_data_p->time->low); - VerilatedVpioCb* vop = new VerilatedVpioCb(cb_data_p, VL_TIME_Q()+time); - VL_DEBUG_IF_PLI(VL_PRINTF("-vltVpi: vpi_register_cb %d %p delay=%" VL_PRI64 "d\n",cb_data_p->reason,vop,time);); - VerilatedVpi::cbTimedAdd(vop); - return vop->castVpiHandle(); - } - case cbReadWriteSynch: // FALLTHRU // Supported via vlt_main.cpp - case cbReadOnlySynch: // FALLTHRU // Supported via vlt_main.cpp - case cbNextSimTime: // FALLTHRU // Supported via vlt_main.cpp - case cbStartOfSimulation: // FALLTHRU // Supported via vlt_main.cpp - case cbEndOfSimulation: // FALLTHRU // Supported via vlt_main.cpp - case cbValueChange: // FALLTHRU // Supported via vlt_main.cpp - case cbPLIError: // FALLTHRU // NOP, but need to return handle, so make object - case cbEnterInteractive: // FALLTHRU // NOP, but need to return handle, so make object - case cbExitInteractive: // FALLTHRU // NOP, but need to return handle, so make object - case cbInteractiveScopeChange: { // FALLTHRU // NOP, but need to return handle, so make object - VerilatedVpioCb* vop = new VerilatedVpioCb(cb_data_p, 0); - VL_DEBUG_IF_PLI(VL_PRINTF("-vltVpi: vpi_register_cb %d %p\n",cb_data_p->reason,vop);); - VerilatedVpi::cbReasonAdd(vop); - return vop->castVpiHandle(); - } - default: - _VL_VPI_WARNING(__FILE__, __LINE__, "%s: Unsupported callback type %s", - VL_FUNC, VerilatedVpiError::strFromVpiCallbackReason(cb_data_p->reason)); - return NULL; - }; -} - -PLI_INT32 vpi_remove_cb(vpiHandle object) { - VL_DEBUG_IF_PLI(VL_PRINTF("-vltVpi: vpi_remove_cb %p\n",object);); - VerilatedVpioCb* vop = VerilatedVpioCb::castp(object); - _VL_VPI_ERROR_RESET(); // reset vpi error status - if (VL_UNLIKELY(!vop)) return 0; - if (vop->cb_datap()->reason == cbAfterDelay) { - VerilatedVpi::cbTimedRemove(vop); - } else { - VerilatedVpi::cbReasonRemove(vop); - } - return 1; -} - -void vpi_get_cb_info(vpiHandle object, p_cb_data cb_data_p) { - _VL_VPI_UNIMP(); return; -} -vpiHandle vpi_register_systf(p_vpi_systf_data systf_data_p) { - _VL_VPI_UNIMP(); return 0; -} -void vpi_get_systf_info(vpiHandle object, p_vpi_systf_data systf_data_p) { - _VL_VPI_UNIMP(); return; -} - -// for obtaining handles - -vpiHandle vpi_handle_by_name(PLI_BYTE8* namep, vpiHandle scope) { - _VL_VPI_ERROR_RESET(); // reset vpi error status - if (VL_UNLIKELY(!namep)) return NULL; - VL_DEBUG_IF_PLI(VL_PRINTF("-vltVpi: vpi_handle_by_name %s %p\n",namep,scope);); - VerilatedVpioScope* voScopep = VerilatedVpioScope::castp(scope); - const VerilatedVar* varp; - const VerilatedScope* scopep; - string scopeAndName = namep; - if (voScopep) { - scopeAndName = string(voScopep->fullname()) + "." + namep; - namep = (PLI_BYTE8*)scopeAndName.c_str(); - } - { - // This doesn't yet follow the hierarchy in the proper way - scopep = Verilated::scopeFind(namep); - if (scopep) { // Whole thing found as a scope - return (new VerilatedVpioScope(scopep))->castVpiHandle(); - } - const char* baseNamep = scopeAndName.c_str(); - string scopename; - const char* dotp = strrchr(namep, '.'); - if (VL_LIKELY(dotp)) { - baseNamep = dotp+1; - scopename = string(namep,dotp-namep); - } - scopep = Verilated::scopeFind(scopename.c_str()); - if (!scopep) return NULL; - varp = scopep->varFind(baseNamep); - } - if (!varp) return NULL; - return (new VerilatedVpioVar(varp, scopep))->castVpiHandle(); -} - -vpiHandle vpi_handle_by_index(vpiHandle object, PLI_INT32 indx) { - // Used to get array entries - VL_DEBUG_IF_PLI(VL_PRINTF("-vltVpi: vpi_handle_by_index %p %d\n",object, indx);); - VerilatedVpioVar* varop = VerilatedVpioVar::castp(object); - _VL_VPI_ERROR_RESET(); // reset vpi error status - if (VL_LIKELY(varop)) { - if (varop->varp()->dims()<2) return 0; - if (VL_LIKELY(varop->varp()->array().left() >= varop->varp()->array().right())) { - if (VL_UNLIKELY(indx > varop->varp()->array().left() || indx < varop->varp()->array().right())) return 0; - return (new VerilatedVpioMemoryWord(varop->varp(), varop->scopep(), indx, - indx - varop->varp()->array().right())) - ->castVpiHandle(); - } else { - if (VL_UNLIKELY(indx < varop->varp()->array().left() || indx > varop->varp()->array().right())) return 0; - return (new VerilatedVpioMemoryWord(varop->varp(), varop->scopep(), indx, - indx - varop->varp()->array().left())) - ->castVpiHandle(); - } - } else { - _VL_VPI_INTERNAL(__FILE__, __LINE__, "%s : can't resolve handle", VL_FUNC); - return 0; - } -} - -// for traversing relationships - -vpiHandle vpi_handle(PLI_INT32 type, vpiHandle object) { - VL_DEBUG_IF_PLI(VL_PRINTF("-vltVpi: vpi_handle %d %p\n",type,object);); - _VL_VPI_ERROR_RESET(); // reset vpi error status - switch (type) { - case vpiLeftRange: { - VerilatedVpioVar* vop = VerilatedVpioVar::castp(object); - if (VL_UNLIKELY(!vop)) return 0; - if (VL_UNLIKELY(!vop->rangep())) return 0; - return (new VerilatedVpioConst(vop->rangep()->left()))->castVpiHandle(); - } - case vpiRightRange: { - VerilatedVpioVar* vop = VerilatedVpioVar::castp(object); - if (VL_UNLIKELY(!vop)) return 0; - if (VL_UNLIKELY(!vop->rangep())) return 0; - return (new VerilatedVpioConst(vop->rangep()->right()))->castVpiHandle(); - } - case vpiIndex: { - VerilatedVpioVar* vop = VerilatedVpioVar::castp(object); - if (VL_UNLIKELY(!vop)) return 0; - return (new VerilatedVpioConst(vop->index()))->castVpiHandle(); - } - case vpiScope: { - VerilatedVpioVar* vop = VerilatedVpioVar::castp(object); - if (VL_UNLIKELY(!vop)) return 0; - return (new VerilatedVpioScope(vop->scopep()))->castVpiHandle(); - } - case vpiParent: { - VerilatedVpioMemoryWord* vop = VerilatedVpioMemoryWord::castp(object); - if (VL_UNLIKELY(!vop)) return 0; - return (new VerilatedVpioVar(vop->varp(), vop->scopep()))->castVpiHandle(); - } - default: - _VL_VPI_WARNING(__FILE__, __LINE__, "%s: Unsupported type %s, nothing will be returned", - VL_FUNC, VerilatedVpiError::strFromVpiMethod(type)); - return 0; - } -} - -vpiHandle vpi_handle_multi(PLI_INT32 type, vpiHandle refHandle1, vpiHandle refHandle2, ... ) { - _VL_VPI_UNIMP(); return 0; -} - -vpiHandle vpi_iterate(PLI_INT32 type, vpiHandle object) { - VL_DEBUG_IF_PLI(VL_PRINTF("-vltVpi: vpi_iterate %d %p\n",type,object);); - _VL_VPI_ERROR_RESET(); // reset vpi error status - switch (type) { - case vpiMemoryWord: { - VerilatedVpioVar* vop = VerilatedVpioVar::castp(object); - if (VL_UNLIKELY(!vop)) return 0; - if (vop->varp()->dims() < 2) return 0; - if (vop->varp()->dims() > 2) { - _VL_VPI_WARNING(__FILE__, __LINE__, "%s: %s, object %s has unsupported number of indices (%d)", - VL_FUNC, VerilatedVpiError::strFromVpiMethod(type), vop->fullname() , vop->varp()->dims()); - } - return (new VerilatedVpioMemoryWordIter(object, vop->varp()))->castVpiHandle(); - } - case vpiRange: { - VerilatedVpioVar* vop = VerilatedVpioVar::castp(object); - if (VL_UNLIKELY(!vop)) return 0; - if (vop->varp()->dims() < 2) return 0; - // Unsupported is multidim list - if (vop->varp()->dims() > 2) { - _VL_VPI_WARNING(__FILE__, __LINE__, "%s: %s, object %s has unsupported number of indices (%d)", - VL_FUNC, VerilatedVpiError::strFromVpiMethod(type), vop->fullname() , vop->varp()->dims()); - } - return ((new VerilatedVpioRange(vop->rangep()))->castVpiHandle()); - } - case vpiReg: { - VerilatedVpioScope* vop = VerilatedVpioScope::castp(object); - if (VL_UNLIKELY(!vop)) return 0; - return ((new VerilatedVpioVarIter(vop->scopep())) - ->castVpiHandle()); - } - default: - _VL_VPI_WARNING(__FILE__, __LINE__, "%s: Unsupported type %s, nothing will be returned", - VL_FUNC, VerilatedVpiError::strFromVpiObjType(type)); - return 0; - } -} -vpiHandle vpi_scan(vpiHandle object) { - VL_DEBUG_IF_PLI(VL_PRINTF("-vltVpi: vpi_scan %p\n",object);); - _VL_VPI_ERROR_RESET(); // reset vpi error status - VerilatedVpio* vop = VerilatedVpio::castp(object); - if (VL_UNLIKELY(!vop)) return NULL; - return vop->dovpi_scan(); -} - -// for processing properties - -PLI_INT32 vpi_get(PLI_INT32 property, vpiHandle object) { - // Leave this in the header file - in many cases the compiler can constant propagate "object" - VL_DEBUG_IF_PLI(VL_PRINTF("-vltVpi: vpi_get %d %p\n",property,object);); - _VL_VPI_ERROR_RESET(); // reset vpi error status - switch (property) { - case vpiTimePrecision: { - return VL_TIME_PRECISION; - } - case vpiType: { - VerilatedVpio* vop = VerilatedVpioVar::castp(object); - if (VL_UNLIKELY(!vop)) return 0; - return vop->type(); - } - case vpiDirection: { - // By forthought, the directions already are vpi enumerated - VerilatedVpioVar* vop = VerilatedVpioVar::castp(object); - if (VL_UNLIKELY(!vop)) return 0; - return vop->varp()->vldir(); - } - case vpiScalar: // FALLTHRU - case vpiVector: { - VerilatedVpioVar* vop = VerilatedVpioVar::castp(object); - if (VL_UNLIKELY(!vop)) return 0; - return (property==vpiVector)^(vop->varp()->dims()==0); - } - case vpiSize: { - VerilatedVpioVar* vop = VerilatedVpioVar::castp(object); - if (VL_UNLIKELY(!vop)) return 0; - return vop->size(); - } - default: - _VL_VPI_WARNING(__FILE__, __LINE__, "%s: Unsupported type %s, nothing will be returned", - VL_FUNC, VerilatedVpiError::strFromVpiProp(property)); - return 0; - } -} - -PLI_INT64 vpi_get64(PLI_INT32 property, vpiHandle object) { - _VL_VPI_UNIMP(); - return 0; -} - -PLI_BYTE8 *vpi_get_str(PLI_INT32 property, vpiHandle object) { - VL_DEBUG_IF_PLI(VL_PRINTF("-vltVpi: vpi_get_str %d %p\n",property,object);); - VerilatedVpio* vop = VerilatedVpio::castp(object); - _VL_VPI_ERROR_RESET(); // reset vpi error status - if (VL_UNLIKELY(!vop)) return NULL; - switch (property) { - case vpiName: { - return (PLI_BYTE8*)vop->name(); - } - case vpiFullName: { - return (PLI_BYTE8*)vop->fullname(); - } - case vpiDefName: { - return (PLI_BYTE8*)vop->defname(); - } - default: - _VL_VPI_WARNING(__FILE__, __LINE__, "%s: Unsupported type %s, nothing will be returned", - VL_FUNC, VerilatedVpiError::strFromVpiProp(property)); - return 0; - } -} - -// delay processing - -void vpi_get_delays(vpiHandle object, p_vpi_delay delay_p) { - _VL_VPI_UNIMP(); - return; -} -void vpi_put_delays(vpiHandle object, p_vpi_delay delay_p) { - _VL_VPI_UNIMP(); - return; -} - -// value processing - -void vpi_get_value(vpiHandle object, p_vpi_value value_p) { - static VL_THREAD char outStr[1+VL_MULS_MAX_WORDS*32]; // Maximum required size is for binary string, one byte per bit plus null termination - // cppcheck-suppress variableScope - static VL_THREAD int outStrSz = sizeof(outStr)-1; - VL_DEBUG_IF_PLI(VL_PRINTF("-vltVpi: vpi_get_value %p\n",object);); - _VL_VPI_ERROR_RESET(); // reset vpi error status - if (VL_UNLIKELY(!value_p)) return; - if (VerilatedVpioVar* vop = VerilatedVpioVar::castp(object)) { - // We used to presume vpiValue.format = vpiIntVal or if single bit vpiScalarVal - // This may cause backward compatability issues with older code. - if (value_p->format == vpiVectorVal) { - // Vector pointer must come from our memory pool - // It only needs to persist until the next vpi_get_value - static VL_THREAD t_vpi_vecval out[VL_MULS_MAX_WORDS*2]; - value_p->value.vector = out; - switch (vop->varp()->vltype()) { - case VLVT_UINT8: - out[0].aval = *((CData*)(vop->varDatap())); - out[0].bval = 0; - return; - case VLVT_UINT16: - out[0].aval = *((SData*)(vop->varDatap())); - out[0].bval = 0; - return; - case VLVT_UINT32: - out[0].aval = *((IData*)(vop->varDatap())); - out[0].bval = 0; - return; - case VLVT_WDATA: { - int words = VL_WORDS_I(vop->varp()->range().elements()); - if (VL_UNLIKELY(words >= VL_MULS_MAX_WORDS)) { - vl_fatal(__FILE__,__LINE__,"", "vpi_get_value with more than VL_MULS_MAX_WORDS; increase and recompile"); - } - WDataInP datap = ((IData*)(vop->varDatap())); - for (int i=0; ivarDatap())); - out[1].aval = (IData)(data>>VL_ULL(32)); - out[1].bval = 0; - out[0].aval = (IData)(data); - out[0].bval = 0; - return; - } - default: { - _VL_VPI_ERROR(__FILE__, __LINE__, "%s: Unsupported format (%s) for %s", - VL_FUNC, VerilatedVpiError::strFromVpiVal(value_p->format), vop->fullname()); - return; - } - } - } else if (value_p->format == vpiBinStrVal) { - value_p->value.str = outStr; - switch (vop->varp()->vltype()) { - case VLVT_UINT8 : - case VLVT_UINT16: - case VLVT_UINT32: - case VLVT_UINT64: - case VLVT_WDATA: { - int bits = vop->varp()->range().elements(); - CData* datap = ((CData*)(vop->varDatap())); - int i; - if (bits > outStrSz) { - // limit maximum size of output to size of buffer to prevent overrun. - bits = outStrSz; - _VL_VPI_WARNING(__FILE__, __LINE__, "%s: Truncating string value of %s for %s as buffer size (%d, VL_MULS_MAX_WORDS=%d) is less than required (%d)", - VL_FUNC, VerilatedVpiError::strFromVpiVal(value_p->format), vop->fullname(), outStrSz, VL_MULS_MAX_WORDS, bits); - } - for (i=0; i>3]>>(i&7))&1; - outStr[bits-i-1] = val?'1':'0'; - } - outStr[i]=0; // NULL terminate - return; - } - default: - _VL_VPI_ERROR(__FILE__, __LINE__, "%s: Unsupported format (%s) for %s", - VL_FUNC, VerilatedVpiError::strFromVpiVal(value_p->format), vop->fullname()); - return; - } - } else if (value_p->format == vpiOctStrVal) { - value_p->value.str = outStr; - switch (vop->varp()->vltype()) { - case VLVT_UINT8 : - case VLVT_UINT16: - case VLVT_UINT32: - case VLVT_UINT64: - case VLVT_WDATA: { - int chars = (vop->varp()->range().elements()+2)/3; - int bytes = VL_BYTES_I(vop->varp()->range().elements()); - CData* datap = ((CData*)(vop->varDatap())); - int i; - if (chars > outStrSz) { - // limit maximum size of output to size of buffer to prevent overrun. - _VL_VPI_WARNING(__FILE__, __LINE__, "%s: Truncating string value of %s for %s as buffer size (%d, VL_MULS_MAX_WORDS=%d) is less than required (%d)", - VL_FUNC, VerilatedVpiError::strFromVpiVal(value_p->format), vop->fullname(), outStrSz, VL_MULS_MAX_WORDS, chars); - chars = outStrSz; - } - for (i=0; i>= idx.rem; - if (i==(chars-1)) { - // most signifcant char, mask off non existant bits when vector - // size is not a multiple of 3 - unsigned int rem = vop->varp()->range().elements() % 3; - if (rem) { - // generate bit mask & zero non existant bits - val &= (1<format), vop->fullname()); - return; - } - } else if (value_p->format == vpiDecStrVal) { - value_p->value.str = outStr; - switch (vop->varp()->vltype()) { - // outStrSz does not include NULL termination so add one - case VLVT_UINT8 : VL_SNPRINTF(outStr, outStrSz+1, "%hhu", (unsigned char )*((CData*)(vop->varDatap()))); return; - case VLVT_UINT16: VL_SNPRINTF(outStr, outStrSz+1, "%hu", (unsigned short)*((SData*)(vop->varDatap()))); return; - case VLVT_UINT32: VL_SNPRINTF(outStr, outStrSz+1, "%u", (unsigned int )*((IData*)(vop->varDatap()))); return; - case VLVT_UINT64: VL_SNPRINTF(outStr, outStrSz+1, "%llu", (unsigned long long)*((QData*)(vop->varDatap()))); return; - default: - strcpy(outStr, "-1"); - _VL_VPI_ERROR(__FILE__, __LINE__, "%s: Unsupported format (%s) for %s, maximum limit is 64 bits", - VL_FUNC, VerilatedVpiError::strFromVpiVal(value_p->format), vop->fullname()); - return; - } - } else if (value_p->format == vpiHexStrVal) { - value_p->value.str = outStr; - switch (vop->varp()->vltype()) { - case VLVT_UINT8 : - case VLVT_UINT16: - case VLVT_UINT32: - case VLVT_UINT64: - case VLVT_WDATA: { - int chars = (vop->varp()->range().elements()+3)>>2; - CData* datap = ((CData*)(vop->varDatap())); - int i; - if (chars > outStrSz) { - // limit maximum size of output to size of buffer to prevent overrun. - _VL_VPI_WARNING(__FILE__, __LINE__, "%s: Truncating string value of %s for %s as buffer size (%d, VL_MULS_MAX_WORDS=%d) is less than required (%d)", - VL_FUNC, VerilatedVpiError::strFromVpiVal(value_p->format), vop->fullname(), outStrSz, VL_MULS_MAX_WORDS, chars); - chars = outStrSz; - } - for (i=0; i>1]>>((i&1)<<2))&15; - static char hex[] = "0123456789abcdef"; - if (i==(chars-1)) { - // most signifcant char, mask off non existant bits when vector - // size is not a multiple of 4 - unsigned int rem = vop->varp()->range().elements() & 3; - if (rem) { - // generate bit mask & zero non existant bits - val &= (1<(val)]; - } - outStr[i]=0; // NULL terminate - return; - } - default: - _VL_VPI_ERROR(__FILE__, __LINE__, "%s: Unsupported format (%s) for %s", - VL_FUNC, VerilatedVpiError::strFromVpiVal(value_p->format), vop->fullname()); - return; - } - } else if (value_p->format == vpiStringVal) { - value_p->value.str = outStr; - switch (vop->varp()->vltype()) { - case VLVT_UINT8 : - case VLVT_UINT16: - case VLVT_UINT32: - case VLVT_UINT64: - case VLVT_WDATA: { - int bytes = VL_BYTES_I(vop->varp()->range().elements()); - CData* datap = ((CData*)(vop->varDatap())); - int i; - if (bytes > outStrSz) { - // limit maximum size of output to size of buffer to prevent overrun. - _VL_VPI_WARNING(__FILE__, __LINE__, "%s: Truncating string value of %s for %s as buffer size (%d, VL_MULS_MAX_WORDS=%d) is less than required (%d)", - VL_FUNC, VerilatedVpiError::strFromVpiVal(value_p->format), - vop->fullname(), outStrSz, VL_MULS_MAX_WORDS, bytes); - bytes = outStrSz; - } - for (i=0; iformat), vop->fullname()); - return; - } - } else if (value_p->format == vpiIntVal) { - switch (vop->varp()->vltype()) { - case VLVT_UINT8: - value_p->value.integer = *((CData*)(vop->varDatap())); - return; - case VLVT_UINT16: - value_p->value.integer = *((SData*)(vop->varDatap())); - return; - case VLVT_UINT32: - value_p->value.integer = *((IData*)(vop->varDatap())); - return; - case VLVT_WDATA: - case VLVT_UINT64: - // Not legal - value_p->value.integer = 0; - default: - _VL_VPI_ERROR(__FILE__, __LINE__, "%s: Unsupported format (%s) for %s", - VL_FUNC, VerilatedVpiError::strFromVpiVal(value_p->format), vop->fullname()); - return; - } - } else if (value_p->format == vpiSuppressVal) { - return; - } - _VL_VPI_ERROR(__FILE__, __LINE__, "%s: Unsupported format (%s) as requested for %s", - VL_FUNC, VerilatedVpiError::strFromVpiVal(value_p->format), vop->fullname()); - return; - } - else if (VerilatedVpioConst* vop = VerilatedVpioConst::castp(object)) { - if (value_p->format == vpiIntVal) { - value_p->value.integer = vop->num(); - return; - } - _VL_VPI_ERROR(__FILE__, __LINE__, "%s: Unsupported format (%s) for %s", - VL_FUNC, VerilatedVpiError::strFromVpiVal(value_p->format), vop->fullname()); - return; - } - _VL_VPI_ERROR(__FILE__, __LINE__, "%s: Unsupported format %s", - VL_FUNC, VerilatedVpiError::strFromVpiVal(value_p->format)); -} - -vpiHandle vpi_put_value(vpiHandle object, p_vpi_value value_p, - p_vpi_time time_p, PLI_INT32 flags) { - VL_DEBUG_IF_PLI(VL_PRINTF("-vltVpi: vpi_put_value %p %p\n",object, value_p);); - _VL_VPI_ERROR_RESET(); // reset vpi error status - if (VL_UNLIKELY(!value_p)) { - _VL_VPI_WARNING(__FILE__, __LINE__, "Ignoring vpi_put_value with NULL value pointer"); - return 0; - } - if (VerilatedVpioVar* vop = VerilatedVpioVar::castp(object)) { - VL_DEBUG_IF_PLI(VL_PRINTF("-vltVpi: vpi_put_value name=%s fmt=%d vali=%d\n", - vop->fullname(), value_p->format, value_p->value.integer); - VL_PRINTF("-vltVpi: varp=%p putatp=%p\n", - vop->varp()->datap(), vop->varDatap());); - if (VL_UNLIKELY(!vop->varp()->isPublicRW())) { - _VL_VPI_WARNING(__FILE__, __LINE__, "Ignoring vpi_put_value to signal marked read-only, use public_flat_rw instead: ", vop->fullname()); - return 0; - } - if (value_p->format == vpiVectorVal) { - if (VL_UNLIKELY(!value_p->value.vector)) return NULL; - switch (vop->varp()->vltype()) { - case VLVT_UINT8: - *((CData*)(vop->varDatap())) = value_p->value.vector[0].aval & vop->mask(); - return object; - case VLVT_UINT16: - *((SData*)(vop->varDatap())) = value_p->value.vector[0].aval & vop->mask(); - return object; - case VLVT_UINT32: - *((IData*)(vop->varDatap())) = value_p->value.vector[0].aval & vop->mask(); - return object; - case VLVT_WDATA: { - int words = VL_WORDS_I(vop->varp()->range().elements()); - WDataOutP datap = ((IData*)(vop->varDatap())); - for (int i=0; ivalue.vector[i].aval; - if (i==(words-1)) { - datap[i] &= vop->mask(); - } - } - return object; - } - case VLVT_UINT64: { - *((QData*)(vop->varDatap())) = _VL_SET_QII( - value_p->value.vector[1].aval & vop->mask(), - value_p->value.vector[0].aval); - return object; - } - default: { - _VL_VPI_ERROR(__FILE__, __LINE__, "%s: Unsupported format (%s) for %s", - VL_FUNC, VerilatedVpiError::strFromVpiVal(value_p->format), vop->fullname()); - return NULL; - } - } - } else if (value_p->format == vpiBinStrVal) { - switch (vop->varp()->vltype()) { - case VLVT_UINT8 : - case VLVT_UINT16: - case VLVT_UINT32: - case VLVT_UINT64: - case VLVT_WDATA: { - int bits = vop->varp()->range().elements(); - int len = strlen(value_p->value.str); - CData* datap = ((CData*)(vop->varDatap())); - for (int i=0; ivalue.str[len-i-1]=='1'):0; - // zero bits 7:1 of byte when assigning to bit 0, else - // or in 1 if bit set - if (i&7) { - datap[i>>3] |= set<<(i&7); - } else { - datap[i>>3] = set; - } - } - return object; - } - default: - _VL_VPI_ERROR(__FILE__, __LINE__, "%s: Unsupported format (%s) for %s", - VL_FUNC, VerilatedVpiError::strFromVpiVal(value_p->format), vop->fullname()); - return 0; - } - } else if (value_p->format == vpiOctStrVal) { - switch (vop->varp()->vltype()) { - case VLVT_UINT8 : - case VLVT_UINT16: - case VLVT_UINT32: - case VLVT_UINT64: - case VLVT_WDATA: { - int chars = (vop->varp()->range().elements()+2)/3; - int bytes = VL_BYTES_I(vop->varp()->range().elements()); - int len = strlen(value_p->value.str); - CData* datap = ((CData*)(vop->varDatap())); - div_t idx; - datap[0] = 0; // reset zero'th byte - for (int i=0; ivalue.str[len-i-1]; - if (digit >= '0' && digit <= '7') { - val.half = digit-'0'; - } else { - _VL_VPI_WARNING(__FILE__, __LINE__, "%s: Non octal character '%c' in '%s' as value %s for %s", - VL_FUNC, digit, value_p->value.str, - VerilatedVpiError::strFromVpiVal(value_p->format), vop->fullname()); - val.half = 0; - } - } else { - val.half = 0; - } - // align octal character to position within vector, note that - // the three bits may straddle a byte bounday so two byte wide - // assignments are made to adjacent bytes - but not if the least - // signifcant byte of the aligned value is the most significant - // byte of the destination. - val.half <<= idx.rem; - datap[idx.quot] |= val.byte[0]; // or in value - if ((idx.quot+1) < bytes) { - datap[idx.quot+1] = val.byte[1]; // this also resets all bits to 0 prior to or'ing above - } - } - // mask off non existant bits in the most significant byte - if (idx.quot == (bytes-1)) { - datap[idx.quot] &= vop->mask_byte(idx.quot); - } else if (idx.quot+1 == (bytes-1)) { - datap[idx.quot+1] &= vop->mask_byte(idx.quot+1); - } - // zero off remaining top bytes - for (int i=idx.quot+2; iformat), vop->fullname()); - return 0; - } - } else if (value_p->format == vpiDecStrVal) { - char remainder[16]; - unsigned long long val; - int success = sscanf(value_p->value.str, "%30llu%15s", &val, remainder); - if (success < 1) { - _VL_VPI_ERROR(__FILE__, __LINE__, "%s: Parsing failed for '%s' as value %s for %s", - VL_FUNC, value_p->value.str, VerilatedVpiError::strFromVpiVal(value_p->format), vop->fullname()); - return 0; - } - if (success > 1) { - _VL_VPI_WARNING(__FILE__, __LINE__, "%s: Trailing garbage '%s' in '%s' as value %s for %s", - VL_FUNC, remainder, value_p->value.str, VerilatedVpiError::strFromVpiVal(value_p->format), vop->fullname()); - } - switch (vop->varp()->vltype()) { - case VLVT_UINT8 : *((CData*)(vop->varDatap())) = val & vop->mask(); break; - case VLVT_UINT16: *((SData*)(vop->varDatap())) = val & vop->mask(); break; - case VLVT_UINT32: *((IData*)(vop->varDatap())) = val & vop->mask(); break; - case VLVT_UINT64: *((QData*)(vop->varDatap())) = val; ((IData*)(vop->varDatap()))[1] &= vop->mask(); break; - case VLVT_WDATA: - default: - _VL_VPI_ERROR(__FILE__, __LINE__, "%s: Unsupported format (%s) for %s, maximum limit is 64 bits", - VL_FUNC, VerilatedVpiError::strFromVpiVal(value_p->format), vop->fullname()); - return 0; - } - return object; - } else if (value_p->format == vpiHexStrVal) { - switch (vop->varp()->vltype()) { - case VLVT_UINT8 : - case VLVT_UINT16: - case VLVT_UINT32: - case VLVT_UINT64: - case VLVT_WDATA: { - int chars = (vop->varp()->range().elements()+3)>>2; - CData* datap = ((CData*)(vop->varDatap())); - char* val = value_p->value.str; - // skip hex ident if one is detected at the start of the string - if (val[0] == '0' && (val[1] == 'x' || val[1] == 'X')) { - val += 2; - } - int len = strlen(val); - for (int i=0; i= '0' && digit <= '9') hex = digit - '0'; - else if (digit >= 'a' && digit <= 'f') hex = digit - 'a' + 10; - else if (digit >= 'A' && digit <= 'F') hex = digit - 'A' + 10; - else { - _VL_VPI_WARNING(__FILE__, __LINE__, "%s: Non hex character '%c' in '%s' as value %s for %s", - VL_FUNC, digit, value_p->value.str, VerilatedVpiError::strFromVpiVal(value_p->format), vop->fullname()); - hex = 0; - } - } else { - hex = 0; - } - // assign hex digit value to destination - if (i&1) { - datap[i>>1] |= hex<<4; - } else { - datap[i>>1] = hex; // this also resets all bits to 0 prior to or'ing above of the msb - } - } - // apply bit mask to most significant byte - datap[(chars-1)>>1] &= vop->mask_byte((chars-1)>>1); - return object; - } - default: - _VL_VPI_ERROR(__FILE__, __LINE__, "%s: Unsupported format (%s) for %s", - VL_FUNC, VerilatedVpiError::strFromVpiVal(value_p->format), vop->fullname()); - return 0; - } - } else if (value_p->format == vpiStringVal) { - switch (vop->varp()->vltype()) { - case VLVT_UINT8 : - case VLVT_UINT16: - case VLVT_UINT32: - case VLVT_UINT64: - case VLVT_WDATA: { - int bytes = VL_BYTES_I(vop->varp()->range().elements()); - int len = strlen(value_p->value.str); - CData* datap = ((CData*)(vop->varDatap())); - for (int i=0; ivalue.str[len-i-1]:0; // prepend with 0 values before placing string the least signifcant bytes - } - return object; - } - default: - _VL_VPI_ERROR(__FILE__, __LINE__, "%s: Unsupported format (%s) for %s", - VL_FUNC, VerilatedVpiError::strFromVpiVal(value_p->format), vop->fullname()); - return 0; - } - } else if (value_p->format == vpiIntVal) { - switch (vop->varp()->vltype()) { - case VLVT_UINT8: - *((CData*)(vop->varDatap())) = vop->mask() & value_p->value.integer; - return object; - case VLVT_UINT16: - *((SData*)(vop->varDatap())) = vop->mask() & value_p->value.integer; - return object; - case VLVT_UINT32: - *((IData*)(vop->varDatap())) = vop->mask() & value_p->value.integer; - return object; - case VLVT_WDATA: // FALLTHRU - case VLVT_UINT64: // FALLTHRU - default: - _VL_VPI_ERROR(__FILE__, __LINE__, "%s: Unsupported format (%s) for %s", - VL_FUNC, VerilatedVpiError::strFromVpiVal(value_p->format), vop->fullname()); - return 0; - } - } - _VL_VPI_ERROR(__FILE__, __LINE__, "%s: Unsupported format (%s) as requested for %s", - VL_FUNC, VerilatedVpiError::strFromVpiVal(value_p->format), vop->fullname()); - return NULL; - } - _VL_VPI_ERROR(__FILE__, __LINE__, "%s: Unsupported format (%s) for ??", - VL_FUNC, VerilatedVpiError::strFromVpiVal(value_p->format)); - return NULL; -} - -void vpi_get_value_array(vpiHandle object, p_vpi_arrayvalue arrayvalue_p, - PLI_INT32 *index_p, PLI_UINT32 num) { - _VL_VPI_UNIMP(); return; -} -void vpi_put_value_array(vpiHandle object, p_vpi_arrayvalue arrayvalue_p, - PLI_INT32 *index_p, PLI_UINT32 num) { - _VL_VPI_UNIMP(); return; -} - - -// time processing - -void vpi_get_time(vpiHandle object, p_vpi_time time_p) { - if (VL_UNLIKELY(!time_p)) { - _VL_VPI_WARNING(__FILE__, __LINE__, "Ignoring vpi_get_time with NULL value pointer"); - return; - } - if (time_p->type == vpiSimTime) { - QData qtime = VL_TIME_Q(); - IData itime[2]; - VL_SET_WQ(itime, qtime); - time_p->low = itime[0]; - time_p->high = itime[1]; - return; - } - _VL_VPI_ERROR(__FILE__, __LINE__, "%s: Unsupported type (%d)", - VL_FUNC, time_p->type); - return; -} - -// I/O routines - -PLI_UINT32 vpi_mcd_open(PLI_BYTE8 *filenamep) { - _VL_VPI_ERROR_RESET(); // reset vpi error status - return VL_FOPEN_S(filenamep,"wb"); -} - -PLI_UINT32 vpi_mcd_close(PLI_UINT32 mcd) { - _VL_VPI_ERROR_RESET(); // reset vpi error status - VL_FCLOSE_I(mcd); return 0; -} - -PLI_BYTE8 *vpi_mcd_name(PLI_UINT32 mcd) { - _VL_VPI_UNIMP(); return 0; -} - -PLI_INT32 vpi_mcd_printf(PLI_UINT32 mcd, PLI_BYTE8 *formatp, ...) { - _VL_VPI_ERROR_RESET(); // reset vpi error status - va_list ap; - va_start(ap,formatp); - int chars = vpi_mcd_vprintf(mcd, formatp, ap); - va_end(ap); - return chars; -} - -PLI_INT32 vpi_printf(PLI_BYTE8 *formatp, ...) { - _VL_VPI_ERROR_RESET(); // reset vpi error status - va_list ap; - va_start(ap,formatp); - int chars = vpi_vprintf(formatp, ap); - va_end(ap); - return chars; -} - -PLI_INT32 vpi_vprintf(PLI_BYTE8* formatp, va_list ap) { - _VL_VPI_ERROR_RESET(); // reset vpi error status - return VL_VPRINTF(formatp, ap); -} - -PLI_INT32 vpi_mcd_vprintf(PLI_UINT32 mcd, PLI_BYTE8 *format, va_list ap) { - FILE* fp = VL_CVT_I_FP(mcd); - _VL_VPI_ERROR_RESET(); // reset vpi error status - if (VL_UNLIKELY(!fp)) return 0; - int chars = vfprintf(fp, format, ap); - return chars; -} - -PLI_INT32 vpi_flush(void) { - _VL_VPI_ERROR_RESET(); // reset vpi error status - Verilated::flushCall(); - return 0; -} - -PLI_INT32 vpi_mcd_flush(PLI_UINT32 mcd) { - FILE* fp = VL_CVT_I_FP(mcd); - _VL_VPI_ERROR_RESET(); // reset vpi error status - if (VL_UNLIKELY(!fp)) return 1; - fflush(fp); - return 0; -} - -// utility routines - -PLI_INT32 vpi_compare_objects(vpiHandle object1, vpiHandle object2) { - _VL_VPI_UNIMP(); return 0; -} -PLI_INT32 vpi_chk_error(p_vpi_error_info error_info_p) { - // executing vpi_chk_error does not reset error - // error_info_p can be NULL, so only return level in that case - p_vpi_error_info _error_info_p = VerilatedVpi::error_info()->getError(); - if (error_info_p && _error_info_p) { - *error_info_p = *_error_info_p; - } - if (!_error_info_p) return 0; // no error occured - return _error_info_p->level; // return error severity level -}; - -PLI_INT32 vpi_free_object(vpiHandle object) { - _VL_VPI_ERROR_RESET(); // reset vpi error status - return vpi_release_handle(object); // Deprecated -} - -PLI_INT32 vpi_release_handle (vpiHandle object) { - VL_DEBUG_IF_PLI(VL_PRINTF("-vltVpi: vpi_release_handle %p\n",object);); - VerilatedVpio* vop = VerilatedVpio::castp(object); - _VL_VPI_ERROR_RESET(); // reset vpi error status - if (VL_UNLIKELY(!vop)) return 0; - vpi_remove_cb(object); // May not be a callback, but that's ok - delete vop; - return 1; -} - -PLI_INT32 vpi_get_vlog_info(p_vpi_vlog_info vlog_info_p) { - _VL_VPI_ERROR_RESET(); // reset vpi error status - vlog_info_p->argc = Verilated::getCommandArgs()->argc; - vlog_info_p->argv = (PLI_BYTE8**)Verilated::getCommandArgs()->argv; - vlog_info_p->product = (PLI_BYTE8*)Verilated::productName(); - vlog_info_p->version = (PLI_BYTE8*)Verilated::productVersion(); - return 1; -} - -// routines added with 1364-2001 - -PLI_INT32 vpi_get_data(PLI_INT32 id, PLI_BYTE8 *dataLoc, PLI_INT32 numOfBytes) { - _VL_VPI_UNIMP(); return 0; -} -PLI_INT32 vpi_put_data(PLI_INT32 id, PLI_BYTE8 *dataLoc, PLI_INT32 numOfBytes) { - _VL_VPI_UNIMP(); return 0; -} -void *vpi_get_userdata(vpiHandle obj) { - _VL_VPI_UNIMP(); return 0; -} -PLI_INT32 vpi_put_userdata(vpiHandle obj, void *userdata) { - _VL_VPI_UNIMP(); return 0; -} - -PLI_INT32 vpi_control(PLI_INT32 operation, ...) { - VL_DEBUG_IF_PLI(VL_PRINTF("-vltVpi: vpi_control %d\n",operation);); - _VL_VPI_ERROR_RESET(); // reset vpi error status - switch (operation) { - case vpiFinish: { - vl_finish(__FILE__,__LINE__,"*VPI*"); - return 1; - } - case vpiStop: { - vl_stop(__FILE__,__LINE__,"*VPI*"); - return 1; - } - } - _VL_VPI_WARNING(__FILE__, __LINE__, "%s: Unsupported type %s, ignoring", - VL_FUNC, VerilatedVpiError::strFromVpiProp(operation)); - return 0; -} - -vpiHandle vpi_handle_by_multi_index(vpiHandle obj, PLI_INT32 num_index, PLI_INT32 *index_array) { - _VL_VPI_UNIMP(); return 0; -} - //====================================================================== #endif // Guard diff --git a/src/V3EmitMk.cpp b/src/V3EmitMk.cpp index c84c8559e..4d1f5add9 100644 --- a/src/V3EmitMk.cpp +++ b/src/V3EmitMk.cpp @@ -81,6 +81,9 @@ public: if (v3Global.dpi()) { putMakeClassEntry(of, "verilated_dpi.cpp"); } + if (v3Global.opt.vpi()) { + putMakeClassEntry(of, "verilated_vpi.cpp"); + } if (v3Global.opt.savable()) { putMakeClassEntry(of, "verilated_save.cpp"); } diff --git a/src/V3Options.cpp b/src/V3Options.cpp index edcd57786..a30e75ec1 100644 --- a/src/V3Options.cpp +++ b/src/V3Options.cpp @@ -672,6 +672,7 @@ void V3Options::parseOptsList(FileLine* fl, const string& optdir, int argc, char else if ( onoff (sw, "-trace-structs", flag/*ref*/) ) { m_traceStructs = flag; } else if ( onoff (sw, "-trace-underscore", flag/*ref*/) ) { m_traceUnderscore = flag; } else if ( onoff (sw, "-underline-zero", flag/*ref*/) ) { m_underlineZero = flag; } // Undocumented, old Verilator-2 + else if ( onoff (sw, "-vpi", flag/*ref*/) ) { m_vpi = flag; } else if ( onoff (sw, "-x-initial-edge", flag/*ref*/) ) { m_xInitialEdge = flag; } else if ( onoff (sw, "-xml-only", flag/*ref*/) ) { m_xmlOnly = flag; } // Undocumented, still experimental // Optimization @@ -1154,6 +1155,7 @@ V3Options::V3Options() { m_preprocOnly = false; m_preprocNoLine = false; m_public = false; + m_reportUnoptflat = false; m_savable = false; m_skipIdentical = true; m_stats = false; @@ -1166,7 +1168,7 @@ V3Options::V3Options() { m_traceStructs = false; m_traceUnderscore = false; m_underlineZero = false; - m_reportUnoptflat = false; + m_vpi = false; m_xInitialEdge = false; m_xmlOnly = false; diff --git a/src/V3Options.h b/src/V3Options.h index 69194a3cf..2534c2a3a 100644 --- a/src/V3Options.h +++ b/src/V3Options.h @@ -85,6 +85,7 @@ class V3Options { bool m_pinsUint8; // main switch: --pins-uint8 bool m_profileCFuncs;// main switch: --profile-cfuncs bool m_public; // main switch: --public + bool m_reportUnoptflat; // main switch: --report-unoptflat bool m_savable; // main switch: --savable bool m_systemC; // main switch: --sc: System C instead of simple C++ bool m_skipIdentical;// main switch: --skip-identical @@ -97,7 +98,7 @@ class V3Options { bool m_traceStructs; // main switch: --trace-structs bool m_traceUnderscore;// main switch: --trace-underscore bool m_underlineZero;// main switch: --underline-zero; undocumented old Verilator 2 - bool m_reportUnoptflat; // main switch: --report-unoptflat + bool m_vpi; // main switch: --vpi bool m_xInitialEdge; // main switch: --x-initial-edge bool m_xmlOnly; // main switch: --xml-netlist @@ -239,6 +240,7 @@ class V3Options { bool ignc() const { return m_ignc; } bool inhibitSim() const { return m_inhibitSim; } bool reportUnoptflat() const { return m_reportUnoptflat; } + bool vpi() const { return m_vpi; } bool xInitialEdge() const { return m_xInitialEdge; } bool xmlOnly() const { return m_xmlOnly; } diff --git a/test_regress/t/t_vpi_get.cpp b/test_regress/t/t_vpi_get.cpp index a6f6cee74..0d1a4407a 100644 --- a/test_regress/t/t_vpi_get.cpp +++ b/test_regress/t/t_vpi_get.cpp @@ -27,7 +27,6 @@ #include "Vt_vpi_get__Dpi.h" #include "verilated_vpi.h" -#include "verilated_vpi.cpp" #include "verilated_vcd_c.h" #endif diff --git a/test_regress/t/t_vpi_get.pl b/test_regress/t/t_vpi_get.pl index bb8c84c39..3de835d11 100755 --- a/test_regress/t/t_vpi_get.pl +++ b/test_regress/t/t_vpi_get.pl @@ -10,7 +10,7 @@ if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); di compile ( make_top_shell => 0, make_main => 0, - verilator_flags2 => ["-CFLAGS '-DVL_DEBUG -ggdb' --exe --no-l2name $Self->{t_dir}/t_vpi_get.cpp"], + verilator_flags2 => ["-CFLAGS '-DVL_DEBUG -ggdb' --exe --vpi --no-l2name $Self->{t_dir}/t_vpi_get.cpp"], make_pli => 1, iv_flags2 => ["-g2005-sv -D USE_VPI_NOT_DPI"], v_flags2 => ["+define+USE_VPI_NOT_DPI"], diff --git a/test_regress/t/t_vpi_memory.cpp b/test_regress/t/t_vpi_memory.cpp index e5234d69f..ab58de157 100644 --- a/test_regress/t/t_vpi_memory.cpp +++ b/test_regress/t/t_vpi_memory.cpp @@ -27,7 +27,6 @@ #include "Vt_vpi_memory__Dpi.h" #include "verilated_vpi.h" -#include "verilated_vpi.cpp" #include "verilated_vcd_c.h" #endif diff --git a/test_regress/t/t_vpi_memory.pl b/test_regress/t/t_vpi_memory.pl index ee515df9d..d071f4c98 100755 --- a/test_regress/t/t_vpi_memory.pl +++ b/test_regress/t/t_vpi_memory.pl @@ -13,7 +13,7 @@ compile ( make_pli => 1, iv_flags2 => ["-g2005-sv -D USE_VPI_NOT_DPI"], v_flags2 => ["+define+USE_VPI_NOT_DPI"], - verilator_flags2 => ["-CFLAGS '-DVL_DEBUG -ggdb' --exe --no-l2name $Self->{t_dir}/t_vpi_memory.cpp"], + verilator_flags2 => ["-CFLAGS '-DVL_DEBUG -ggdb' --exe --vpi --no-l2name $Self->{t_dir}/t_vpi_memory.cpp"], ); execute ( diff --git a/test_regress/t/t_vpi_unimpl.cpp b/test_regress/t/t_vpi_unimpl.cpp index 4fa1a6546..35148bc4c 100644 --- a/test_regress/t/t_vpi_unimpl.cpp +++ b/test_regress/t/t_vpi_unimpl.cpp @@ -19,9 +19,8 @@ #include "Vt_vpi_unimpl__Dpi.h" -#include "verilated_vpi.h" -#include "verilated_vpi.cpp" #include "verilated_vcd_c.h" +// No verilated_vpi.h, make sure can link without it #include @@ -174,7 +173,7 @@ int main(int argc, char **argv, char **env) { while (sc_time_stamp() < sim_time && !Verilated::gotFinish()) { main_time += 1; topp->eval(); - VerilatedVpi::callValueCbs(); + //VerilatedVpi::callValueCbs(); // Make sure can link without verilated_vpi.h included topp->clk = !topp->clk; //mon_do(); #if VM_TRACE diff --git a/test_regress/t/t_vpi_unimpl.pl b/test_regress/t/t_vpi_unimpl.pl index 105ab3452..78c55b76d 100755 --- a/test_regress/t/t_vpi_unimpl.pl +++ b/test_regress/t/t_vpi_unimpl.pl @@ -10,7 +10,7 @@ if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); di compile ( make_top_shell => 0, make_main => 0, - verilator_flags2 => ["-CFLAGS '-DVL_DEBUG -ggdb' --exe --no-l2name $Self->{t_dir}/t_vpi_unimpl.cpp"], + verilator_flags2 => ["-CFLAGS '-DVL_DEBUG -ggdb' --exe --vpi --no-l2name $Self->{t_dir}/t_vpi_unimpl.cpp"], ); execute ( diff --git a/test_regress/t/t_vpi_var.cpp b/test_regress/t/t_vpi_var.cpp index 5c21fa592..f55055f38 100644 --- a/test_regress/t/t_vpi_var.cpp +++ b/test_regress/t/t_vpi_var.cpp @@ -26,7 +26,6 @@ #include "Vt_vpi_var__Dpi.h" #include "verilated_vpi.h" -#include "verilated_vpi.cpp" #include "verilated_vcd_c.h" #endif @@ -550,47 +549,6 @@ int _mon_check_vlog_info() { return 0; } -#ifndef IS_VPI - -#define CHECK_ENUM_STR(fn, enum) \ - do { \ - const char* strVal = VerilatedVpiError::fn(enum); \ - CHECK_RESULT_CSTR(strVal, #enum); \ - } while (0) - -int _mon_check_vl_str() { - - CHECK_ENUM_STR(strFromVpiVal, vpiBinStrVal); - CHECK_ENUM_STR(strFromVpiVal, vpiRawFourStateVal); - - CHECK_ENUM_STR(strFromVpiObjType, vpiAlways); - CHECK_ENUM_STR(strFromVpiObjType, vpiWhile); - CHECK_ENUM_STR(strFromVpiObjType, vpiAttribute); - CHECK_ENUM_STR(strFromVpiObjType, vpiUdpArray); - CHECK_ENUM_STR(strFromVpiObjType, vpiContAssignBit); - CHECK_ENUM_STR(strFromVpiObjType, vpiGenVar); - - CHECK_ENUM_STR(strFromVpiMethod, vpiCondition); - CHECK_ENUM_STR(strFromVpiMethod, vpiStmt); - - CHECK_ENUM_STR(strFromVpiCallbackReason, cbValueChange); - CHECK_ENUM_STR(strFromVpiCallbackReason, cbAtEndOfSimTime); - - CHECK_ENUM_STR(strFromVpiProp, vpiType); - CHECK_ENUM_STR(strFromVpiProp, vpiProtected); - CHECK_ENUM_STR(strFromVpiProp, vpiDirection); - CHECK_ENUM_STR(strFromVpiProp, vpiTermIndex); - CHECK_ENUM_STR(strFromVpiProp, vpiConstType); - CHECK_ENUM_STR(strFromVpiProp, vpiAutomatic); - CHECK_ENUM_STR(strFromVpiProp, vpiOffset); - CHECK_ENUM_STR(strFromVpiProp, vpiStop); - CHECK_ENUM_STR(strFromVpiProp, vpiIsProtected); - - return 0; -} - -#endif - int mon_check() { // Callback from initial block in monitor if (int status = _mon_check_mcd()) return status; @@ -604,7 +562,7 @@ int mon_check() { if (int status = _mon_check_putget_str(NULL)) return status; if (int status = _mon_check_vlog_info()) return status; #ifndef IS_VPI - if (int status = _mon_check_vl_str()) return status; + VerilatedVpiError::selfTest(); #endif return 0; // Ok } diff --git a/test_regress/t/t_vpi_var.pl b/test_regress/t/t_vpi_var.pl index 5061134a6..750bced9a 100755 --- a/test_regress/t/t_vpi_var.pl +++ b/test_regress/t/t_vpi_var.pl @@ -14,7 +14,7 @@ compile ( sim_time => 2100, iv_flags2 => ["-g2005-sv -D USE_VPI_NOT_DPI -DWAVES"], v_flags2 => ["+define+USE_VPI_NOT_DPI"], - verilator_flags2 => ["-CFLAGS '-DVL_DEBUG -ggdb' --exe --no-l2name $Self->{t_dir}/t_vpi_var.cpp"], + verilator_flags2 => ["-CFLAGS '-DVL_DEBUG -ggdb' --exe --vpi --no-l2name $Self->{t_dir}/t_vpi_var.cpp"], ); execute (