From 97db128d6600f382ca1557b894129d27ee98075c Mon Sep 17 00:00:00 2001 From: Andrew Nolte Date: Tue, 5 Mar 2024 12:08:22 -0500 Subject: [PATCH] Tests: Add VPI dump testcases (#4838) --- .gitignore | 2 + test_regress/t/TestVpi.h | 469 +++++++++++++++++++++++++++++++ test_regress/t/TestVpiMain.cpp | 185 ++++++++++++ test_regress/t/t_vpi_dump.cpp | 179 ++++++++++++ test_regress/t/t_vpi_dump.iv.out | 352 +++++++++++++++++++++++ test_regress/t/t_vpi_dump.out | 169 +++++++++++ test_regress/t/t_vpi_dump.pl | 34 +++ test_regress/t/t_vpi_dump.v | 130 +++++++++ 8 files changed, 1520 insertions(+) create mode 100644 test_regress/t/TestVpiMain.cpp create mode 100644 test_regress/t/t_vpi_dump.cpp create mode 100644 test_regress/t/t_vpi_dump.iv.out create mode 100644 test_regress/t/t_vpi_dump.out create mode 100755 test_regress/t/t_vpi_dump.pl create mode 100644 test_regress/t/t_vpi_dump.v diff --git a/.gitignore b/.gitignore index c04dcedeb..96c6afa08 100644 --- a/.gitignore +++ b/.gitignore @@ -44,3 +44,5 @@ verilator-config-version.cmake /.idea/ /cmake-build-*/ /test_regress/snapshot/ +xmverilog.* +xrun.history diff --git a/test_regress/t/TestVpi.h b/test_regress/t/TestVpi.h index d5b746b1b..aa44dda90 100644 --- a/test_regress/t/TestVpi.h +++ b/test_regress/t/TestVpi.h @@ -9,6 +9,7 @@ // //************************************************************************* +#include "sv_vpi_user.h" #include "vpi_user.h" // Avoid C++11 in this file as not all simulators allow it @@ -52,3 +53,471 @@ public: m_freeit = false; } }; + +//====================================================================== +// VerilatedVpiError Methods + +const char* strFromVpiVal(PLI_INT32 vpiVal) { + // clang-format off + static const char* const names[] = { + "*undefined*", + "vpiBinStrVal", + "vpiOctStrVal", + "vpiDecStrVal", + "vpiHexStrVal", + "vpiScalarVal", + "vpiIntVal", + "vpiRealVal", + "vpiStringVal", + "vpiVectorVal", + "vpiStrengthVal", + "vpiTimeVal", + "vpiObjTypeVal", + "vpiSuppressVal", + "vpiShortIntVal", + "vpiLongIntVal", + "vpiShortRealVal", + "vpiRawTwoStateVal", + "vpiRawFourStateVal", + }; + // clang-format on + if ((vpiVal < 0)) return names[0]; + return names[(vpiVal <= vpiRawFourStateVal) ? vpiVal : 0]; +} +const char* strFromVpiObjType(PLI_INT32 vpiVal) { + // clang-format off + static const char* const names[] = { + "*undefined*", + "vpiAlways", + "vpiAssignStmt", + "vpiAssignment", + "vpiBegin", + "vpiCase", + "vpiCaseItem", + "vpiConstant", + "vpiContAssign", + "vpiDeassign", + "vpiDefParam", + "vpiDelayControl", + "vpiDisable", + "vpiEventControl", + "vpiEventStmt", + "vpiFor", + "vpiForce", + "vpiForever", + "vpiFork", + "vpiFuncCall", + "vpiFunction", + "vpiGate", + "vpiIf", + "vpiIfElse", + "vpiInitial", + "vpiIntegerVar", + "vpiInterModPath", + "vpiIterator", + "vpiIODecl", + "vpiMemory", + "vpiMemoryWord", + "vpiModPath", + "vpiModule", + "vpiNamedBegin", + "vpiNamedEvent", + "vpiNamedFork", + "vpiNet", + "vpiNetBit", + "vpiNullStmt", + "vpiOperation", + "vpiParamAssign", + "vpiParameter", + "vpiPartSelect", + "vpiPathTerm", + "vpiPort", + "vpiPortBit", + "vpiPrimTerm", + "vpiRealVar", + "vpiReg", + "vpiRegBit", + "vpiRelease", + "vpiRepeat", + "vpiRepeatControl", + "vpiSchedEvent", + "vpiSpecParam", + "vpiSwitch", + "vpiSysFuncCall", + "vpiSysTaskCall", + "vpiTableEntry", + "vpiTask", + "vpiTaskCall", + "vpiTchk", + "vpiTchkTerm", + "vpiTimeVar", + "vpiTimeQueue", + "vpiUdp", + "vpiUdpDefn", + "vpiUserSystf", + "vpiVarSelect", + "vpiWait", + "vpiWhile", + "vpiCondition", + "vpiDelay", + "vpiElseStmt", + "vpiForIncStmt", + "vpiForInitStmt", + "vpiHighConn", + "vpiLhs", + "vpiIndex", + "vpiLeftRange", + "vpiLowConn", + "vpiParent", + "vpiRhs", + "vpiRightRange", + "vpiScope", + "vpiSysTfCall", + "vpiTchkDataTerm", + "vpiTchkNotifier", + "vpiTchkRefTerm", + "vpiArgument", + "vpiBit", + "vpiDriver", + "vpiInternalScope", + "vpiLoad", + "vpiModDataPathIn", + "vpiModPathIn", + "vpiModPathOut", + "vpiOperand", + "vpiPortInst", + "vpiProcess", + "vpiVariables", + "vpiUse", + "vpiExpr", + "vpiPrimitive", + "vpiStmt", + "vpiAttribute", + "vpiBitSelect", + "vpiCallback", + "vpiDelayTerm", + "vpiDelayDevice", + "vpiFrame", + "vpiGateArray", + "vpiModuleArray", + "vpiPrimitiveArray", + "vpiNetArray", + "vpiRange", + "vpiRegArray", + "vpiSwitchArray", + "vpiUdpArray", + "vpiActiveTimeFormat", + "vpiInTerm", + "vpiInstanceArray", + "vpiLocalDriver", + "vpiLocalLoad", + "vpiOutTerm", + "vpiPorts", + "vpiSimNet", + "vpiTaskFunc", + "vpiContAssignBit", + "vpiNamedEventArray", + "vpiIndexedPartSelect", + "vpiBaseExpr", + "vpiWidthExpr", + "vpiGenScopeArray", + "vpiGenScope", + "vpiGenVar", + "vpiAutomatics" + }; + static const char* const sv_names1[] = { + "vpiPackage", + "vpiInterface", + "vpiProgram", + "vpiInterfaceArray", + "vpiProgramArray", + "vpiTypespec", + "vpiModport", + "vpiInterfaceTfDecl", + "vpiRefObj", + "vpiTypeParameter", + "vpiLongIntVar", + "vpiShortIntVar", + "vpiIntVar", + "vpiShortRealVar", + "vpiByteVar", + "vpiClassVar", + "vpiStringVar", + "vpiEnumVar", + "vpiStructVar", + "vpiUnionVar", + "vpiBitVar", + "vpiClassObj", + "vpiChandleVar", + "vpiPackedArrayVar", + "*undefined*", // 624 is not defined for object types + "vpiLongIntTypespec", + "vpiShortRealTypespec", + "vpiByteTypespec", + "vpiShortIntTypespec", + "vpiIntTypespec", + "vpiClassTypespec", + "vpiStringTypespec", + "vpiChandleTypespec", + "vpiEnumTypespec", + "vpiEnumConst", + "vpiIntegerTypespec", + "vpiTimeTypespec", + "vpiRealTypespec", + "vpiStructTypespec", + "vpiUnionTypespec", + "vpiBitTypespec", + "vpiLogicTypespec", + "vpiArrayTypespec", + "vpiVoidTypespec", + "vpiTypespecMember", + "vpiDistItem", + "vpiAliasStmt", + "vpiThread", + "vpiMethodFuncCall", + "vpiMethodTaskCall", + "vpiClockingBlock", + "vpiClockingIODecl", + "vpiClassDefn", + "vpiConstraint", + "vpiConstraintOrdering", + "vpiPropertyDecl", + "vpiPropertySpec", + "vpiPropertyExpr", + "vpiMulticlockSequenceExpr", + "vpiClockedSeq", + "vpiPropertyInst", + "vpiSequenceDecl", + "vpiCaseProperty", + "*undefined*", // 663 is not defined for object types + "vpiSequenceInst", + "vpiImmediateAssert", + "vpiReturn", + "vpiAnyPattern", + "vpiTaggedPattern", + "vpiStructPattern", + "vpiDoWhile", + "vpiOrderedWait", + "vpiWaitFork", + "vpiDisableFork", + "vpiExpectStmt", + "vpiForeachStmt", + "vpiFinal", + "vpiExtends", + "vpiDistribution", + "vpiSeqFormalDecl", + "vpiEnumNet", + "vpiIntegerNet", + "vpiTimeNet", + "vpiStructNet", + "vpiBreak", + "vpiContinue", + "vpiAssert", + "vpiAssume", + "vpiCover", + "vpiDisableCondition", + "vpiClockingEvent", + "vpiReturnStmt", + "vpiPackedArrayTypespec", + "vpiPackedArrayNet", + "vpiImmediateAssume", + "vpiImmediateCover", + "vpiSequenceTypespec", + "vpiPropertyTypespec", + "vpiEventTypespec", + "vpiPropFormalDecl", + }; + // clang-format on + if (vpiVal < 0) + return names[0]; + else if (vpiVal <= vpiAutomatics) + return names[vpiVal]; + else if (vpiVal >= vpiPackage && vpiVal <= vpiPropFormalDecl) + return sv_names1[(vpiVal - vpiPackage)]; + else + return names[0]; +} +const char* strFromVpiMethod(PLI_INT32 vpiVal) { + // clang-format off + static const char* const names[] = { + "vpiCondition", + "vpiDelay", + "vpiElseStmt", + "vpiForIncStmt", + "vpiForInitStmt", + "vpiHighConn", + "vpiLhs", + "vpiIndex", + "vpiLeftRange", + "vpiLowConn", + "vpiParent", + "vpiRhs", + "vpiRightRange", + "vpiScope", + "vpiSysTfCall", + "vpiTchkDataTerm", + "vpiTchkNotifier", + "vpiTchkRefTerm", + "vpiArgument", + "vpiBit", + "vpiDriver", + "vpiInternalScope", + "vpiLoad", + "vpiModDataPathIn", + "vpiModPathIn", + "vpiModPathOut", + "vpiOperand", + "vpiPortInst", + "vpiProcess", + "vpiVariables", + "vpiUse", + "vpiExpr", + "vpiPrimitive", + "vpiStmt" + }; + // clang-format on + if (vpiVal > vpiStmt || vpiVal < vpiCondition) return "*undefined*"; + return names[vpiVal - vpiCondition]; +} + +const char* strFromVpiCallbackReason(PLI_INT32 vpiVal) { + // clang-format off + static const char* const names[] = { + "*undefined*", + "cbValueChange", + "cbStmt", + "cbForce", + "cbRelease", + "cbAtStartOfSimTime", + "cbReadWriteSynch", + "cbReadOnlySynch", + "cbNextSimTime", + "cbAfterDelay", + "cbEndOfCompile", + "cbStartOfSimulation", + "cbEndOfSimulation", + "cbError", + "cbTchkViolation", + "cbStartOfSave", + "cbEndOfSave", + "cbStartOfRestart", + "cbEndOfRestart", + "cbStartOfReset", + "cbEndOfReset", + "cbEnterInteractive", + "cbExitInteractive", + "cbInteractiveScopeChange", + "cbUnresolvedSystf", + "cbAssign", + "cbDeassign", + "cbDisable", + "cbPLIError", + "cbSignal", + "cbNBASynch", + "cbAtEndOfSimTime" + }; + // clang-format on + if (vpiVal < 0) return names[0]; + return names[(vpiVal <= cbAtEndOfSimTime) ? vpiVal : 0]; +} + +const char* strFromVpiProp(PLI_INT32 vpiVal) { + // clang-format off + static const char* const names[] = { + "*undefined or other*", + "vpiType", + "vpiName", + "vpiFullName", + "vpiSize", + "vpiFile", + "vpiLineNo", + "vpiTopModule", + "vpiCellInstance", + "vpiDefName", + "vpiProtected", + "vpiTimeUnit", + "vpiTimePrecision", + "vpiDefNetType", + "vpiUnconnDrive", + "vpiDefFile", + "vpiDefLineNo", + "vpiScalar", + "vpiVector", + "vpiExplicitName", + "vpiDirection", + "vpiConnByName", + "vpiNetType", + "vpiExplicitScalared", + "vpiExplicitVectored", + "vpiExpanded", + "vpiImplicitDecl", + "vpiChargeStrength", + "vpiArray", + "vpiPortIndex", + "vpiTermIndex", + "vpiStrength0", + "vpiStrength1", + "vpiPrimType", + "vpiPolarity", + "vpiDataPolarity", + "vpiEdge", + "vpiPathType", + "vpiTchkType", + "vpiOpType", + "vpiConstType", + "vpiBlocking", + "vpiCaseType", + "vpiFuncType", + "vpiNetDeclAssign", + "vpiUserDefn", + "vpiScheduled", + "*undefined*", + "*undefined*", + "vpiActive", + "vpiAutomatic", + "vpiCell", + "vpiConfig", + "vpiConstantSelect", + "vpiDecompile", + "vpiDefAttribute", + "vpiDelayType", + "vpiIteratorType", + "vpiLibrary", + "*undefined*", + "vpiOffset", + "vpiResolvedNetType", + "vpiSaveRestartID", + "vpiSaveRestartLocation", + "vpiValid", + "vpiSigned", + "vpiStop", + "vpiFinish", + "vpiReset", + "vpiSetInteractiveScope", + "vpiLocalParam", + "vpiModPathHasIfNone", + "vpiIndexedPartSelectType", + "vpiIsMemory", + "vpiIsProtected" + }; + // clang-format on + if (vpiVal == vpiUndefined) return "vpiUndefined"; + return names[(vpiVal <= vpiIsProtected) ? vpiVal : 0]; +} +const char* strFromVpiConstType(PLI_INT32 constType) { + // clang-format off + static const char* const names[] = { + "*undefined*", + "vpiDecConst", + "vpiRealConst", + "vpiBinaryConst", + "vpiOctConst", + "vpiHexConst", + "vpiStringConst", + "vpiIntConst", + "vpiTimeConst", + }; + // clang-format on + if (constType < 0) return names[0]; + return names[(constType <= vpiTimeConst) ? constType : 0]; +} diff --git a/test_regress/t/TestVpiMain.cpp b/test_regress/t/TestVpiMain.cpp new file mode 100644 index 000000000..cbd09fa85 --- /dev/null +++ b/test_regress/t/TestVpiMain.cpp @@ -0,0 +1,185 @@ +// -*- mode: C++; c-file-style: "cc-mode" -*- +//************************************************************************* +// +// Copyright 2024 by Andrew Nolte. This program is free software; you can +// redistribute it and/or modify it under the terms of either the GNU +// Lesser General Public License Version 3 or the Perl Artistic License +// Version 2.0. +// SPDX-License-Identifier: LGPL-3.0-only OR Artistic-2.0 +// +//************************************************************************* + +// Copyright cocotb contributors +// Licensed under the Revised BSD License, see LICENSE for details. +// SPDX-License-Identifier: BSD-3-Clause + +#include "verilated.h" +#include "verilated_vpi.h" + +#include VM_PREFIX_INCLUDE + +#include +#include + +#ifndef VM_TRACE_FST +// emulate new verilator behavior for legacy versions +#define VM_TRACE_FST 0 +#endif + +#if VM_TRACE +#if VM_TRACE_FST +#include +#else +#include +#endif +#endif + +extern void (*vlog_startup_routines[])(); + +static bool settle_value_callbacks() { + bool cbs_called; + bool again; + + // Call Value Change callbacks + // These can modify signal values so we loop + // until there are no more changes + cbs_called = again = VerilatedVpi::callValueCbs(); + while (again) { again = VerilatedVpi::callValueCbs(); } + + return cbs_called; +} + +int main(int argc, char** argv) { + const std::unique_ptr contextp{new VerilatedContext}; + bool traceOn = false; + + for (int i = 1; i < argc; ++i) { + const std::string arg = std::string(argv[i]); + if (arg == "--trace") { + traceOn = true; + } else if (arg == "--help") { + fprintf(stderr, + "usage: %s [--trace]\n" + "\n" + "Cocotb + Verilator sim\n" + "\n" + "options:\n" + " --trace Enables tracing (VCD or FST)\n", + basename(argv[0])); + return 0; + } + } + + (void)traceOn; // Prevent unused if VM_TRACE not defined + contextp->commandArgs(argc, argv); +#ifdef VERILATOR_SIM_DEBUG + contextp->debug(99); +#endif + const std::unique_ptr top{new VM_PREFIX{contextp.get(), + // Note null name - we're flattening it out + ""}}; + contextp->fatalOnVpiError(false); // otherwise it will fail on systemtf + +#ifdef VERILATOR_SIM_DEBUG + contextp->internalsDump(); +#endif + for (auto it = &vlog_startup_routines[0]; *it != nullptr; it++) { + auto routine = *it; + routine(); + } + + VerilatedVpi::callCbs(cbStartOfSimulation); + +#if VM_TRACE +#if VM_TRACE_FST + std::unique_ptr tfp(new VerilatedFstC); + const char* traceFile = "dump.fst"; +#else + std::unique_ptr tfp(new VerilatedVcdC); + const char* traceFile = "dump.vcd"; +#endif + + if (traceOn) { + contextp->traceEverOn(true); + top->trace(tfp.get(), 99); + tfp->open(traceFile); + } +#endif + + while (!contextp->gotFinish()) { + // Call registered timed callbacks (e.g. clock timer) + // These are called at the beginning of the time step + // before the iterative regions (IEEE 1800-2012 4.4.1) + VerilatedVpi::callTimedCbs(); + + // Call Value Change callbacks triggered by Timer callbacks + // These can modify signal values + settle_value_callbacks(); + + // We must evaluate whole design until we process all 'events' + bool again = true; + while (again) { + // Evaluate design + top->eval_step(); + + // Call Value Change callbacks triggered by eval() + // These can modify signal values + again = settle_value_callbacks(); + + // Call registered ReadWrite callbacks + again |= VerilatedVpi::callCbs(cbReadWriteSynch); + + // Call Value Change callbacks triggered by ReadWrite callbacks + // These can modify signal values + again |= settle_value_callbacks(); + } + top->eval_end_step(); + + // Call ReadOnly callbacks + VerilatedVpi::callCbs(cbReadOnlySynch); + +#if VM_TRACE + if (traceOn) { tfp->dump(contextp->time()); } +#endif + // cocotb controls the clock inputs using cbAfterDelay so + // skip ahead to the next registered callback + const uint64_t NO_TOP_EVENTS_PENDING = static_cast(~0ULL); + const uint64_t next_time_cocotb = VerilatedVpi::cbNextDeadline(); + const uint64_t next_time_timing + = top->eventsPending() ? top->nextTimeSlot() : NO_TOP_EVENTS_PENDING; + const uint64_t next_time = std::min(next_time_cocotb, next_time_timing); + + // If there are no more cbAfterDelay callbacks, + // the next deadline is max value, so end the simulation now + if (next_time == NO_TOP_EVENTS_PENDING) { + break; + } else { + contextp->time(next_time); + } + + // Call registered NextSimTime + // It should be called in simulation cycle before everything else + // but not on first cycle + VerilatedVpi::callCbs(cbNextSimTime); + + // Call Value Change callbacks triggered by NextTimeStep callbacks + // These can modify signal values + settle_value_callbacks(); + } + + VerilatedVpi::callCbs(cbEndOfSimulation); + + top->final(); + +#if VM_TRACE + if (traceOn) { tfp->close(); } +#endif + +// VM_COVERAGE is a define which is set if Verilator is +// instructed to collect coverage (when compiling the simulation) +#if VM_COVERAGE + VerilatedCov::write("coverage.dat"); +#endif + + return 0; +}; diff --git a/test_regress/t/t_vpi_dump.cpp b/test_regress/t/t_vpi_dump.cpp new file mode 100644 index 000000000..874903973 --- /dev/null +++ b/test_regress/t/t_vpi_dump.cpp @@ -0,0 +1,179 @@ +// -*- mode: C++; c-file-style: "cc-mode" -*- +//************************************************************************* +// +// Copyright 2010-2011 by Wilson Snyder. This program is free software; you can +// redistribute it and/or modify it under the terms of either the GNU +// Lesser General Public License Version 3 or the Perl Artistic License +// Version 2.0. +// SPDX-License-Identifier: LGPL-3.0-only OR Artistic-2.0 +// +//************************************************************************* + +#include "svdpi.h" +#include "vpi_user.h" + +#include + +// These require the above. Comment prevents clang-format moving them +#include "TestCheck.h" +#include "TestSimulator.h" +#include "TestVpi.h" + +#include +#include + +int errors = 0; + +// vpiType -> list of vpiTypes to iterate over +std::map> iterate_over = [] { + // static decltype(iterate_over) iterate_over = [] { + /* for reused lists */ + + // vpiInstance is the base class for module, program, interface, etc. + std::vector instance_options = { + vpiNet, + vpiNetArray, + vpiReg, + vpiRegArray, + }; + + std::vector module_options = { + vpiModule, // Aldec SEGV on mixed language + // vpiModuleArray, // Aldec SEGV on mixed language + // vpiIODecl, // Don't care about these + vpiMemory, vpiIntegerVar, vpiRealVar, + // vpiRealNet, Vpi extension + vpiStructVar, vpiStructNet, vpiNamedEvent, vpiNamedEventArray, vpiParameter, + // vpiVariables, // parent of vpiReg, vpiRegArray, vpiIntegerVar, etc vars + // vpiSpecParam, // Don't care + // vpiParamAssign, // Aldec SEGV on mixed language + // vpiDefParam, // Don't care + vpiPrimitive, vpiPrimitiveArray, + // vpiContAssign, // Don't care + // vpiProcess, // Don't care + vpiModPath, vpiTchk, vpiAttribute, vpiPort, vpiInternalScope, + // vpiInterface, // Aldec SEGV on mixed language + // vpiInterfaceArray, // Aldec SEGV on mixed language + }; + + // append base class vpiInstance members + module_options.insert(module_options.begin(), instance_options.begin(), + instance_options.end()); + + std::vector struct_options = { + vpiNet, vpiReg, vpiRegArray, vpiMemory, + vpiParameter, vpiPrimitive, vpiPrimitiveArray, vpiAttribute, + vpiMember, + }; + + return decltype(iterate_over){ + {vpiModule, module_options}, + {vpiInterface, instance_options}, + {vpiGenScope, module_options}, + + {vpiStructVar, struct_options}, + {vpiStructNet, struct_options}, + + {vpiNet, + { + // vpiContAssign, // Driver and load handled separately + // vpiPrimTerm, + // vpiPathTerm, + // vpiTchkTerm, + // vpiDriver, + // vpiLocalDriver, + // vpiLoad, + // vpiLocalLoad, + vpiNetBit, + }}, + {vpiNetArray, + { + vpiNet, + }}, + {vpiRegArray, + { + vpiReg, + }}, + {vpiMemory, + { + vpiMemoryWord, + }}, + {vpiPort, + { + vpiPortBit, + }}, + {vpiGate, + { + vpiPrimTerm, + vpiTableEntry, + vpiUdpDefn, + }}, + {vpiPackage, + { + vpiParameter, + }}, + }; +}(); + +void modDump(TestVpiHandle& it, int n) { + + if (n > 8) { + printf("going too deep\n"); + return; + } + + while (const TestVpiHandle& hndl = vpi_scan(it)) { + for (int i = 0; i < n; i++) printf(" "); + const int type = vpi_get(vpiType, hndl); + const char* name = vpi_get_str(vpiName, hndl); + const char* fullname = vpi_get_str(vpiFullName, hndl); + printf("%s (%s) %s\n", name, strFromVpiObjType(type), fullname); + if (type == vpiParameter || type == vpiConstType) { + for (int i = 0; i < n + 1; i++) printf(" "); + printf("vpiConstType=%s\n", strFromVpiConstType(vpi_get(vpiConstType, hndl))); + } + + if (iterate_over.find(type) == iterate_over.end()) { continue; } + for (int type : iterate_over.at(type)) { + TestVpiHandle subIt = vpi_iterate(type, hndl); + if (subIt) { + for (int i = 0; i < n + 1; i++) printf(" "); + printf("%s:\n", strFromVpiObjType(type)); + modDump(subIt, n + 1); + } + } + } + it.freed(); +} + +PLI_INT32 start_of_sim(t_cb_data* data) { + TestVpiHandle it = vpi_iterate(vpiModule, NULL); + TEST_CHECK_NZ(it); + modDump(it, 0); + return 0; +} + +//cver, xcelium entry +void vpi_compat_bootstrap(void) { + + // We're able to call vpi_main() here on Verilator/Xcelium, + // but Icarus complains (rightfully so) + s_cb_data cb_data; + s_vpi_time vpi_time; + + vpi_time.high = 0; + vpi_time.low = 0; + vpi_time.type = vpiSimTime; + + cb_data.reason = cbStartOfSimulation; + cb_data.cb_rtn = &start_of_sim; + cb_data.obj = NULL; + cb_data.time = &vpi_time; + cb_data.value = NULL; + cb_data.index = 0; + cb_data.user_data = NULL; + TestVpiHandle callback_h = vpi_register_cb(&cb_data); +} + +// Verilator (via t_vpi_main.cpp), and standard LRM entry +void (*vlog_startup_routines[])() = {vpi_compat_bootstrap, 0}; diff --git a/test_regress/t/t_vpi_dump.iv.out b/test_regress/t/t_vpi_dump.iv.out new file mode 100644 index 000000000..ad543d558 --- /dev/null +++ b/test_regress/t/t_vpi_dump.iv.out @@ -0,0 +1,352 @@ +t (vpiModule) t + vpiNet: + t.a (vpiNet) t.a + t.clk (vpiNet) t.clk + vpiReg: + t.x (vpiReg) t.x + vpiModule: + t.sub (vpiModule) t.sub + vpiNet: + t.sub.redundant (vpiNet) t.sub.redundant + vpiReg: + t.sub.subsig1 (vpiReg) t.sub.subsig1 + t.sub.subsig2 (vpiReg) t.sub.subsig2 + vpiParameter: + t.do_generate (vpiParameter) t.do_generate + vpiConstType=vpiBinaryConst + t.long_int (vpiParameter) t.long_int + vpiConstType=vpiBinaryConst + vpiPort: + x (vpiPort) (null) + clk (vpiPort) (null) + a (vpiPort) (null) + vpiInternalScope: + t.arr[1] (vpiGenScope) t.arr[1] + vpiModule: + t.arr[1].arr (vpiModule) t.arr[1].arr + vpiReg: + t.arr[1].arr.check (vpiReg) t.arr[1].arr.check + t.arr[1].arr.rfr (vpiReg) t.arr[1].arr.rfr + t.arr[1].arr.sig (vpiReg) t.arr[1].arr.sig + t.arr[1].arr.verbose (vpiReg) t.arr[1].arr.verbose + vpiParameter: + t.arr[1].arr.LENGTH (vpiParameter) t.arr[1].arr.LENGTH + vpiConstType=vpiBinaryConst + vpiParameter: + t.arr[1].i (vpiParameter) t.arr[1].i + vpiConstType=vpiBinaryConst + vpiInternalScope: + t.arr[1].arr (vpiModule) t.arr[1].arr + vpiReg: + t.arr[1].arr.check (vpiReg) t.arr[1].arr.check + t.arr[1].arr.rfr (vpiReg) t.arr[1].arr.rfr + t.arr[1].arr.sig (vpiReg) t.arr[1].arr.sig + t.arr[1].arr.verbose (vpiReg) t.arr[1].arr.verbose + vpiParameter: + t.arr[1].arr.LENGTH (vpiParameter) t.arr[1].arr.LENGTH + vpiConstType=vpiBinaryConst + t.arr[2] (vpiGenScope) t.arr[2] + vpiModule: + t.arr[2].arr (vpiModule) t.arr[2].arr + vpiReg: + t.arr[2].arr.check (vpiReg) t.arr[2].arr.check + t.arr[2].arr.rfr (vpiReg) t.arr[2].arr.rfr + t.arr[2].arr.sig (vpiReg) t.arr[2].arr.sig + t.arr[2].arr.verbose (vpiReg) t.arr[2].arr.verbose + vpiParameter: + t.arr[2].arr.LENGTH (vpiParameter) t.arr[2].arr.LENGTH + vpiConstType=vpiBinaryConst + vpiParameter: + t.arr[2].i (vpiParameter) t.arr[2].i + vpiConstType=vpiBinaryConst + vpiInternalScope: + t.arr[2].arr (vpiModule) t.arr[2].arr + vpiReg: + t.arr[2].arr.check (vpiReg) t.arr[2].arr.check + t.arr[2].arr.rfr (vpiReg) t.arr[2].arr.rfr + t.arr[2].arr.sig (vpiReg) t.arr[2].arr.sig + t.arr[2].arr.verbose (vpiReg) t.arr[2].arr.verbose + vpiParameter: + t.arr[2].arr.LENGTH (vpiParameter) t.arr[2].arr.LENGTH + vpiConstType=vpiBinaryConst + t.cond_scope (vpiGenScope) t.cond_scope + vpiModule: + t.cond_scope.scoped_sub (vpiModule) t.cond_scope.scoped_sub + vpiNet: + t.cond_scope.scoped_sub.redundant (vpiNet) t.cond_scope.scoped_sub.redundant + vpiReg: + t.cond_scope.scoped_sub.subsig1 (vpiReg) t.cond_scope.scoped_sub.subsig1 + t.cond_scope.scoped_sub.subsig2 (vpiReg) t.cond_scope.scoped_sub.subsig2 + vpiParameter: + t.cond_scope.scoped_wire (vpiParameter) t.cond_scope.scoped_wire + vpiConstType=vpiBinaryConst + vpiInternalScope: + t.cond_scope.scoped_sub (vpiModule) t.cond_scope.scoped_sub + vpiNet: + t.cond_scope.scoped_sub.redundant (vpiNet) t.cond_scope.scoped_sub.redundant + vpiReg: + t.cond_scope.scoped_sub.subsig1 (vpiReg) t.cond_scope.scoped_sub.subsig1 + t.cond_scope.scoped_sub.subsig2 (vpiReg) t.cond_scope.scoped_sub.subsig2 + t.outer_scope[1] (vpiGenScope) t.outer_scope[1] + vpiParameter: + t.outer_scope[1].i (vpiParameter) t.outer_scope[1].i + vpiConstType=vpiBinaryConst + t.outer_scope[1].scoped_param (vpiParameter) t.outer_scope[1].scoped_param + vpiConstType=vpiBinaryConst + vpiInternalScope: + t.outer_scope[1].inner_scope[1] (vpiGenScope) t.outer_scope[1].inner_scope[1] + vpiModule: + t.outer_scope[1].inner_scope[1].arr (vpiModule) t.outer_scope[1].inner_scope[1].arr + vpiReg: + t.outer_scope[1].inner_scope[1].arr.check (vpiReg) t.outer_scope[1].inner_scope[1].arr.check + t.outer_scope[1].inner_scope[1].arr.rfr (vpiReg) t.outer_scope[1].inner_scope[1].arr.rfr + t.outer_scope[1].inner_scope[1].arr.sig (vpiReg) t.outer_scope[1].inner_scope[1].arr.sig + t.outer_scope[1].inner_scope[1].arr.verbose (vpiReg) t.outer_scope[1].inner_scope[1].arr.verbose + vpiParameter: + t.outer_scope[1].inner_scope[1].arr.LENGTH (vpiParameter) t.outer_scope[1].inner_scope[1].arr.LENGTH + vpiConstType=vpiBinaryConst + vpiParameter: + t.outer_scope[1].inner_scope[1].j (vpiParameter) t.outer_scope[1].inner_scope[1].j + vpiConstType=vpiBinaryConst + t.outer_scope[1].inner_scope[1].scoped_param_inner (vpiParameter) t.outer_scope[1].inner_scope[1].scoped_param_inner + vpiConstType=vpiBinaryConst + vpiInternalScope: + t.outer_scope[1].inner_scope[1].arr (vpiModule) t.outer_scope[1].inner_scope[1].arr + vpiReg: + t.outer_scope[1].inner_scope[1].arr.check (vpiReg) t.outer_scope[1].inner_scope[1].arr.check + t.outer_scope[1].inner_scope[1].arr.rfr (vpiReg) t.outer_scope[1].inner_scope[1].arr.rfr + t.outer_scope[1].inner_scope[1].arr.sig (vpiReg) t.outer_scope[1].inner_scope[1].arr.sig + t.outer_scope[1].inner_scope[1].arr.verbose (vpiReg) t.outer_scope[1].inner_scope[1].arr.verbose + vpiParameter: + t.outer_scope[1].inner_scope[1].arr.LENGTH (vpiParameter) t.outer_scope[1].inner_scope[1].arr.LENGTH + vpiConstType=vpiBinaryConst + t.outer_scope[1].inner_scope[2] (vpiGenScope) t.outer_scope[1].inner_scope[2] + vpiModule: + t.outer_scope[1].inner_scope[2].arr (vpiModule) t.outer_scope[1].inner_scope[2].arr + vpiReg: + t.outer_scope[1].inner_scope[2].arr.check (vpiReg) t.outer_scope[1].inner_scope[2].arr.check + t.outer_scope[1].inner_scope[2].arr.rfr (vpiReg) t.outer_scope[1].inner_scope[2].arr.rfr + t.outer_scope[1].inner_scope[2].arr.sig (vpiReg) t.outer_scope[1].inner_scope[2].arr.sig + t.outer_scope[1].inner_scope[2].arr.verbose (vpiReg) t.outer_scope[1].inner_scope[2].arr.verbose + vpiParameter: + t.outer_scope[1].inner_scope[2].arr.LENGTH (vpiParameter) t.outer_scope[1].inner_scope[2].arr.LENGTH + vpiConstType=vpiBinaryConst + vpiParameter: + t.outer_scope[1].inner_scope[2].j (vpiParameter) t.outer_scope[1].inner_scope[2].j + vpiConstType=vpiBinaryConst + t.outer_scope[1].inner_scope[2].scoped_param_inner (vpiParameter) t.outer_scope[1].inner_scope[2].scoped_param_inner + vpiConstType=vpiBinaryConst + vpiInternalScope: + t.outer_scope[1].inner_scope[2].arr (vpiModule) t.outer_scope[1].inner_scope[2].arr + vpiReg: + t.outer_scope[1].inner_scope[2].arr.check (vpiReg) t.outer_scope[1].inner_scope[2].arr.check + t.outer_scope[1].inner_scope[2].arr.rfr (vpiReg) t.outer_scope[1].inner_scope[2].arr.rfr + t.outer_scope[1].inner_scope[2].arr.sig (vpiReg) t.outer_scope[1].inner_scope[2].arr.sig + t.outer_scope[1].inner_scope[2].arr.verbose (vpiReg) t.outer_scope[1].inner_scope[2].arr.verbose + vpiParameter: + t.outer_scope[1].inner_scope[2].arr.LENGTH (vpiParameter) t.outer_scope[1].inner_scope[2].arr.LENGTH + vpiConstType=vpiBinaryConst + t.outer_scope[1].inner_scope[3] (vpiGenScope) t.outer_scope[1].inner_scope[3] + vpiModule: + t.outer_scope[1].inner_scope[3].arr (vpiModule) t.outer_scope[1].inner_scope[3].arr + vpiReg: + t.outer_scope[1].inner_scope[3].arr.check (vpiReg) t.outer_scope[1].inner_scope[3].arr.check + t.outer_scope[1].inner_scope[3].arr.rfr (vpiReg) t.outer_scope[1].inner_scope[3].arr.rfr + t.outer_scope[1].inner_scope[3].arr.sig (vpiReg) t.outer_scope[1].inner_scope[3].arr.sig + t.outer_scope[1].inner_scope[3].arr.verbose (vpiReg) t.outer_scope[1].inner_scope[3].arr.verbose + vpiParameter: + t.outer_scope[1].inner_scope[3].arr.LENGTH (vpiParameter) t.outer_scope[1].inner_scope[3].arr.LENGTH + vpiConstType=vpiBinaryConst + vpiParameter: + t.outer_scope[1].inner_scope[3].j (vpiParameter) t.outer_scope[1].inner_scope[3].j + vpiConstType=vpiBinaryConst + t.outer_scope[1].inner_scope[3].scoped_param_inner (vpiParameter) t.outer_scope[1].inner_scope[3].scoped_param_inner + vpiConstType=vpiBinaryConst + vpiInternalScope: + t.outer_scope[1].inner_scope[3].arr (vpiModule) t.outer_scope[1].inner_scope[3].arr + vpiReg: + t.outer_scope[1].inner_scope[3].arr.check (vpiReg) t.outer_scope[1].inner_scope[3].arr.check + t.outer_scope[1].inner_scope[3].arr.rfr (vpiReg) t.outer_scope[1].inner_scope[3].arr.rfr + t.outer_scope[1].inner_scope[3].arr.sig (vpiReg) t.outer_scope[1].inner_scope[3].arr.sig + t.outer_scope[1].inner_scope[3].arr.verbose (vpiReg) t.outer_scope[1].inner_scope[3].arr.verbose + vpiParameter: + t.outer_scope[1].inner_scope[3].arr.LENGTH (vpiParameter) t.outer_scope[1].inner_scope[3].arr.LENGTH + vpiConstType=vpiBinaryConst + t.outer_scope[2] (vpiGenScope) t.outer_scope[2] + vpiParameter: + t.outer_scope[2].i (vpiParameter) t.outer_scope[2].i + vpiConstType=vpiBinaryConst + t.outer_scope[2].scoped_param (vpiParameter) t.outer_scope[2].scoped_param + vpiConstType=vpiBinaryConst + vpiInternalScope: + t.outer_scope[2].inner_scope[1] (vpiGenScope) t.outer_scope[2].inner_scope[1] + vpiModule: + t.outer_scope[2].inner_scope[1].arr (vpiModule) t.outer_scope[2].inner_scope[1].arr + vpiReg: + t.outer_scope[2].inner_scope[1].arr.check (vpiReg) t.outer_scope[2].inner_scope[1].arr.check + t.outer_scope[2].inner_scope[1].arr.rfr (vpiReg) t.outer_scope[2].inner_scope[1].arr.rfr + t.outer_scope[2].inner_scope[1].arr.sig (vpiReg) t.outer_scope[2].inner_scope[1].arr.sig + t.outer_scope[2].inner_scope[1].arr.verbose (vpiReg) t.outer_scope[2].inner_scope[1].arr.verbose + vpiParameter: + t.outer_scope[2].inner_scope[1].arr.LENGTH (vpiParameter) t.outer_scope[2].inner_scope[1].arr.LENGTH + vpiConstType=vpiBinaryConst + vpiParameter: + t.outer_scope[2].inner_scope[1].j (vpiParameter) t.outer_scope[2].inner_scope[1].j + vpiConstType=vpiBinaryConst + t.outer_scope[2].inner_scope[1].scoped_param_inner (vpiParameter) t.outer_scope[2].inner_scope[1].scoped_param_inner + vpiConstType=vpiBinaryConst + vpiInternalScope: + t.outer_scope[2].inner_scope[1].arr (vpiModule) t.outer_scope[2].inner_scope[1].arr + vpiReg: + t.outer_scope[2].inner_scope[1].arr.check (vpiReg) t.outer_scope[2].inner_scope[1].arr.check + t.outer_scope[2].inner_scope[1].arr.rfr (vpiReg) t.outer_scope[2].inner_scope[1].arr.rfr + t.outer_scope[2].inner_scope[1].arr.sig (vpiReg) t.outer_scope[2].inner_scope[1].arr.sig + t.outer_scope[2].inner_scope[1].arr.verbose (vpiReg) t.outer_scope[2].inner_scope[1].arr.verbose + vpiParameter: + t.outer_scope[2].inner_scope[1].arr.LENGTH (vpiParameter) t.outer_scope[2].inner_scope[1].arr.LENGTH + vpiConstType=vpiBinaryConst + t.outer_scope[2].inner_scope[2] (vpiGenScope) t.outer_scope[2].inner_scope[2] + vpiModule: + t.outer_scope[2].inner_scope[2].arr (vpiModule) t.outer_scope[2].inner_scope[2].arr + vpiReg: + t.outer_scope[2].inner_scope[2].arr.check (vpiReg) t.outer_scope[2].inner_scope[2].arr.check + t.outer_scope[2].inner_scope[2].arr.rfr (vpiReg) t.outer_scope[2].inner_scope[2].arr.rfr + t.outer_scope[2].inner_scope[2].arr.sig (vpiReg) t.outer_scope[2].inner_scope[2].arr.sig + t.outer_scope[2].inner_scope[2].arr.verbose (vpiReg) t.outer_scope[2].inner_scope[2].arr.verbose + vpiParameter: + t.outer_scope[2].inner_scope[2].arr.LENGTH (vpiParameter) t.outer_scope[2].inner_scope[2].arr.LENGTH + vpiConstType=vpiBinaryConst + vpiParameter: + t.outer_scope[2].inner_scope[2].j (vpiParameter) t.outer_scope[2].inner_scope[2].j + vpiConstType=vpiBinaryConst + t.outer_scope[2].inner_scope[2].scoped_param_inner (vpiParameter) t.outer_scope[2].inner_scope[2].scoped_param_inner + vpiConstType=vpiBinaryConst + vpiInternalScope: + t.outer_scope[2].inner_scope[2].arr (vpiModule) t.outer_scope[2].inner_scope[2].arr + vpiReg: + t.outer_scope[2].inner_scope[2].arr.check (vpiReg) t.outer_scope[2].inner_scope[2].arr.check + t.outer_scope[2].inner_scope[2].arr.rfr (vpiReg) t.outer_scope[2].inner_scope[2].arr.rfr + t.outer_scope[2].inner_scope[2].arr.sig (vpiReg) t.outer_scope[2].inner_scope[2].arr.sig + t.outer_scope[2].inner_scope[2].arr.verbose (vpiReg) t.outer_scope[2].inner_scope[2].arr.verbose + vpiParameter: + t.outer_scope[2].inner_scope[2].arr.LENGTH (vpiParameter) t.outer_scope[2].inner_scope[2].arr.LENGTH + vpiConstType=vpiBinaryConst + t.outer_scope[2].inner_scope[3] (vpiGenScope) t.outer_scope[2].inner_scope[3] + vpiModule: + t.outer_scope[2].inner_scope[3].arr (vpiModule) t.outer_scope[2].inner_scope[3].arr + vpiReg: + t.outer_scope[2].inner_scope[3].arr.check (vpiReg) t.outer_scope[2].inner_scope[3].arr.check + t.outer_scope[2].inner_scope[3].arr.rfr (vpiReg) t.outer_scope[2].inner_scope[3].arr.rfr + t.outer_scope[2].inner_scope[3].arr.sig (vpiReg) t.outer_scope[2].inner_scope[3].arr.sig + t.outer_scope[2].inner_scope[3].arr.verbose (vpiReg) t.outer_scope[2].inner_scope[3].arr.verbose + vpiParameter: + t.outer_scope[2].inner_scope[3].arr.LENGTH (vpiParameter) t.outer_scope[2].inner_scope[3].arr.LENGTH + vpiConstType=vpiBinaryConst + vpiParameter: + t.outer_scope[2].inner_scope[3].j (vpiParameter) t.outer_scope[2].inner_scope[3].j + vpiConstType=vpiBinaryConst + t.outer_scope[2].inner_scope[3].scoped_param_inner (vpiParameter) t.outer_scope[2].inner_scope[3].scoped_param_inner + vpiConstType=vpiBinaryConst + vpiInternalScope: + t.outer_scope[2].inner_scope[3].arr (vpiModule) t.outer_scope[2].inner_scope[3].arr + vpiReg: + t.outer_scope[2].inner_scope[3].arr.check (vpiReg) t.outer_scope[2].inner_scope[3].arr.check + t.outer_scope[2].inner_scope[3].arr.rfr (vpiReg) t.outer_scope[2].inner_scope[3].arr.rfr + t.outer_scope[2].inner_scope[3].arr.sig (vpiReg) t.outer_scope[2].inner_scope[3].arr.sig + t.outer_scope[2].inner_scope[3].arr.verbose (vpiReg) t.outer_scope[2].inner_scope[3].arr.verbose + vpiParameter: + t.outer_scope[2].inner_scope[3].arr.LENGTH (vpiParameter) t.outer_scope[2].inner_scope[3].arr.LENGTH + vpiConstType=vpiBinaryConst + t.outer_scope[3] (vpiGenScope) t.outer_scope[3] + vpiParameter: + t.outer_scope[3].i (vpiParameter) t.outer_scope[3].i + vpiConstType=vpiBinaryConst + t.outer_scope[3].scoped_param (vpiParameter) t.outer_scope[3].scoped_param + vpiConstType=vpiBinaryConst + vpiInternalScope: + t.outer_scope[3].inner_scope[1] (vpiGenScope) t.outer_scope[3].inner_scope[1] + vpiModule: + t.outer_scope[3].inner_scope[1].arr (vpiModule) t.outer_scope[3].inner_scope[1].arr + vpiReg: + t.outer_scope[3].inner_scope[1].arr.check (vpiReg) t.outer_scope[3].inner_scope[1].arr.check + t.outer_scope[3].inner_scope[1].arr.rfr (vpiReg) t.outer_scope[3].inner_scope[1].arr.rfr + t.outer_scope[3].inner_scope[1].arr.sig (vpiReg) t.outer_scope[3].inner_scope[1].arr.sig + t.outer_scope[3].inner_scope[1].arr.verbose (vpiReg) t.outer_scope[3].inner_scope[1].arr.verbose + vpiParameter: + t.outer_scope[3].inner_scope[1].arr.LENGTH (vpiParameter) t.outer_scope[3].inner_scope[1].arr.LENGTH + vpiConstType=vpiBinaryConst + vpiParameter: + t.outer_scope[3].inner_scope[1].j (vpiParameter) t.outer_scope[3].inner_scope[1].j + vpiConstType=vpiBinaryConst + t.outer_scope[3].inner_scope[1].scoped_param_inner (vpiParameter) t.outer_scope[3].inner_scope[1].scoped_param_inner + vpiConstType=vpiBinaryConst + vpiInternalScope: + t.outer_scope[3].inner_scope[1].arr (vpiModule) t.outer_scope[3].inner_scope[1].arr + vpiReg: + t.outer_scope[3].inner_scope[1].arr.check (vpiReg) t.outer_scope[3].inner_scope[1].arr.check + t.outer_scope[3].inner_scope[1].arr.rfr (vpiReg) t.outer_scope[3].inner_scope[1].arr.rfr + t.outer_scope[3].inner_scope[1].arr.sig (vpiReg) t.outer_scope[3].inner_scope[1].arr.sig + t.outer_scope[3].inner_scope[1].arr.verbose (vpiReg) t.outer_scope[3].inner_scope[1].arr.verbose + vpiParameter: + t.outer_scope[3].inner_scope[1].arr.LENGTH (vpiParameter) t.outer_scope[3].inner_scope[1].arr.LENGTH + vpiConstType=vpiBinaryConst + t.outer_scope[3].inner_scope[2] (vpiGenScope) t.outer_scope[3].inner_scope[2] + vpiModule: + t.outer_scope[3].inner_scope[2].arr (vpiModule) t.outer_scope[3].inner_scope[2].arr + vpiReg: + t.outer_scope[3].inner_scope[2].arr.check (vpiReg) t.outer_scope[3].inner_scope[2].arr.check + t.outer_scope[3].inner_scope[2].arr.rfr (vpiReg) t.outer_scope[3].inner_scope[2].arr.rfr + t.outer_scope[3].inner_scope[2].arr.sig (vpiReg) t.outer_scope[3].inner_scope[2].arr.sig + t.outer_scope[3].inner_scope[2].arr.verbose (vpiReg) t.outer_scope[3].inner_scope[2].arr.verbose + vpiParameter: + t.outer_scope[3].inner_scope[2].arr.LENGTH (vpiParameter) t.outer_scope[3].inner_scope[2].arr.LENGTH + vpiConstType=vpiBinaryConst + vpiParameter: + t.outer_scope[3].inner_scope[2].j (vpiParameter) t.outer_scope[3].inner_scope[2].j + vpiConstType=vpiBinaryConst + t.outer_scope[3].inner_scope[2].scoped_param_inner (vpiParameter) t.outer_scope[3].inner_scope[2].scoped_param_inner + vpiConstType=vpiBinaryConst + vpiInternalScope: + t.outer_scope[3].inner_scope[2].arr (vpiModule) t.outer_scope[3].inner_scope[2].arr + vpiReg: + t.outer_scope[3].inner_scope[2].arr.check (vpiReg) t.outer_scope[3].inner_scope[2].arr.check + t.outer_scope[3].inner_scope[2].arr.rfr (vpiReg) t.outer_scope[3].inner_scope[2].arr.rfr + t.outer_scope[3].inner_scope[2].arr.sig (vpiReg) t.outer_scope[3].inner_scope[2].arr.sig + t.outer_scope[3].inner_scope[2].arr.verbose (vpiReg) t.outer_scope[3].inner_scope[2].arr.verbose + vpiParameter: + t.outer_scope[3].inner_scope[2].arr.LENGTH (vpiParameter) t.outer_scope[3].inner_scope[2].arr.LENGTH + vpiConstType=vpiBinaryConst + t.outer_scope[3].inner_scope[3] (vpiGenScope) t.outer_scope[3].inner_scope[3] + vpiModule: + t.outer_scope[3].inner_scope[3].arr (vpiModule) t.outer_scope[3].inner_scope[3].arr + vpiReg: + t.outer_scope[3].inner_scope[3].arr.check (vpiReg) t.outer_scope[3].inner_scope[3].arr.check + t.outer_scope[3].inner_scope[3].arr.rfr (vpiReg) t.outer_scope[3].inner_scope[3].arr.rfr + t.outer_scope[3].inner_scope[3].arr.sig (vpiReg) t.outer_scope[3].inner_scope[3].arr.sig + t.outer_scope[3].inner_scope[3].arr.verbose (vpiReg) t.outer_scope[3].inner_scope[3].arr.verbose + vpiParameter: + t.outer_scope[3].inner_scope[3].arr.LENGTH (vpiParameter) t.outer_scope[3].inner_scope[3].arr.LENGTH + vpiConstType=vpiBinaryConst + vpiParameter: + t.outer_scope[3].inner_scope[3].j (vpiParameter) t.outer_scope[3].inner_scope[3].j + vpiConstType=vpiBinaryConst + t.outer_scope[3].inner_scope[3].scoped_param_inner (vpiParameter) t.outer_scope[3].inner_scope[3].scoped_param_inner + vpiConstType=vpiBinaryConst + vpiInternalScope: + t.outer_scope[3].inner_scope[3].arr (vpiModule) t.outer_scope[3].inner_scope[3].arr + vpiReg: + t.outer_scope[3].inner_scope[3].arr.check (vpiReg) t.outer_scope[3].inner_scope[3].arr.check + t.outer_scope[3].inner_scope[3].arr.rfr (vpiReg) t.outer_scope[3].inner_scope[3].arr.rfr + t.outer_scope[3].inner_scope[3].arr.sig (vpiReg) t.outer_scope[3].inner_scope[3].arr.sig + t.outer_scope[3].inner_scope[3].arr.verbose (vpiReg) t.outer_scope[3].inner_scope[3].arr.verbose + vpiParameter: + t.outer_scope[3].inner_scope[3].arr.LENGTH (vpiParameter) t.outer_scope[3].inner_scope[3].arr.LENGTH + vpiConstType=vpiBinaryConst + t.sub (vpiModule) t.sub + vpiNet: + t.sub.redundant (vpiNet) t.sub.redundant + vpiReg: + t.sub.subsig1 (vpiReg) t.sub.subsig1 + t.sub.subsig2 (vpiReg) t.sub.subsig2 +*-* All Finished *-* +t/t_vpi_dump.v:65: $finish called at 0 (1s) diff --git a/test_regress/t/t_vpi_dump.out b/test_regress/t/t_vpi_dump.out new file mode 100644 index 000000000..b0ef51bca --- /dev/null +++ b/test_regress/t/t_vpi_dump.out @@ -0,0 +1,169 @@ +t (vpiModule) t + vpiReg: + LONGSTART_a_very_long_name_which_will_get_hashed_a_very_long_name_which_will_get_hashed_a_very_long_name_which_will_get_hashed_a_very_long_name_which_will_get_hashed_LONGEND (vpiReg) t.LONGSTART_a_very_long_name_which_will_get_hashed_a_very_long_name_which_will_get_hashed_a_very_long_name_which_will_get_hashed_a_very_long_name_which_will_get_hashed_LONGEND + a (vpiReg) TOP.a + bus1 (vpiReg) t.bus1 + clk (vpiReg) TOP.clk + count (vpiReg) t.count + do_generate (vpiParameter) t.do_generate + vpiConstType=vpiDecConst + fourthreetwoone (vpiMemory) t.fourthreetwoone + vpiMemoryWord: + fourthreetwoone (vpiMemoryWord) t.fourthreetwoone[3] + fourthreetwoone (vpiMemoryWord) t.fourthreetwoone[4] + half_count (vpiReg) t.half_count + long_int (vpiParameter) t.long_int + vpiConstType=vpiDecConst + onebit (vpiReg) t.onebit + quads (vpiMemory) t.quads + vpiMemoryWord: + quads (vpiMemoryWord) t.quads[3] + quads (vpiMemoryWord) t.quads[2] + real1 (vpiRealVar) t.real1 + status (vpiReg) t.status + str1 (vpiStringVar) t.str1 + text (vpiReg) t.text + text_byte (vpiReg) t.text_byte + text_half (vpiReg) t.text_half + text_long (vpiReg) t.text_long + text_word (vpiReg) t.text_word + twoone (vpiReg) t.twoone + x (vpiReg) TOP.x + vpiModule: + arr (vpiModule) t.arr[1].arr + vpiReg: + LENGTH (vpiParameter) t.arr[1].arr.LENGTH + vpiConstType=vpiDecConst + check (vpiReg) t.arr[1].arr.check + rfr (vpiReg) t.arr[1].arr.rfr + sig (vpiReg) t.arr[1].arr.sig + verbose (vpiReg) t.arr[1].arr.verbose + vpiParameter: + LENGTH (vpiParameter) t.arr[1].arr.LENGTH + vpiConstType=vpiDecConst + arr (vpiModule) t.arr[2].arr + vpiReg: + LENGTH (vpiParameter) t.arr[2].arr.LENGTH + vpiConstType=vpiDecConst + check (vpiReg) t.arr[2].arr.check + rfr (vpiReg) t.arr[2].arr.rfr + sig (vpiReg) t.arr[2].arr.sig + verbose (vpiReg) t.arr[2].arr.verbose + vpiParameter: + LENGTH (vpiParameter) t.arr[2].arr.LENGTH + vpiConstType=vpiDecConst + scoped_sub (vpiModule) t.cond_scope.scoped_sub + vpiReg: + subsig1 (vpiReg) t.cond_scope.scoped_sub.subsig1 + subsig2 (vpiReg) t.cond_scope.scoped_sub.subsig2 + vpiParameter: + arr (vpiModule) t.outer_scope[1].inner_scope[1].arr + vpiReg: + LENGTH (vpiParameter) t.outer_scope[1].inner_scope[1].arr.LENGTH + vpiConstType=vpiDecConst + check (vpiReg) t.outer_scope[1].inner_scope[1].arr.check + rfr (vpiReg) t.outer_scope[1].inner_scope[1].arr.rfr + sig (vpiReg) t.outer_scope[1].inner_scope[1].arr.sig + verbose (vpiReg) t.outer_scope[1].inner_scope[1].arr.verbose + vpiParameter: + LENGTH (vpiParameter) t.outer_scope[1].inner_scope[1].arr.LENGTH + vpiConstType=vpiDecConst + arr (vpiModule) t.outer_scope[1].inner_scope[2].arr + vpiReg: + LENGTH (vpiParameter) t.outer_scope[1].inner_scope[2].arr.LENGTH + vpiConstType=vpiDecConst + check (vpiReg) t.outer_scope[1].inner_scope[2].arr.check + rfr (vpiReg) t.outer_scope[1].inner_scope[2].arr.rfr + sig (vpiReg) t.outer_scope[1].inner_scope[2].arr.sig + verbose (vpiReg) t.outer_scope[1].inner_scope[2].arr.verbose + vpiParameter: + LENGTH (vpiParameter) t.outer_scope[1].inner_scope[2].arr.LENGTH + vpiConstType=vpiDecConst + arr (vpiModule) t.outer_scope[1].inner_scope[3].arr + vpiReg: + LENGTH (vpiParameter) t.outer_scope[1].inner_scope[3].arr.LENGTH + vpiConstType=vpiDecConst + check (vpiReg) t.outer_scope[1].inner_scope[3].arr.check + rfr (vpiReg) t.outer_scope[1].inner_scope[3].arr.rfr + sig (vpiReg) t.outer_scope[1].inner_scope[3].arr.sig + verbose (vpiReg) t.outer_scope[1].inner_scope[3].arr.verbose + vpiParameter: + LENGTH (vpiParameter) t.outer_scope[1].inner_scope[3].arr.LENGTH + vpiConstType=vpiDecConst + arr (vpiModule) t.outer_scope[2].inner_scope[1].arr + vpiReg: + LENGTH (vpiParameter) t.outer_scope[2].inner_scope[1].arr.LENGTH + vpiConstType=vpiDecConst + check (vpiReg) t.outer_scope[2].inner_scope[1].arr.check + rfr (vpiReg) t.outer_scope[2].inner_scope[1].arr.rfr + sig (vpiReg) t.outer_scope[2].inner_scope[1].arr.sig + verbose (vpiReg) t.outer_scope[2].inner_scope[1].arr.verbose + vpiParameter: + LENGTH (vpiParameter) t.outer_scope[2].inner_scope[1].arr.LENGTH + vpiConstType=vpiDecConst + arr (vpiModule) t.outer_scope[2].inner_scope[2].arr + vpiReg: + LENGTH (vpiParameter) t.outer_scope[2].inner_scope[2].arr.LENGTH + vpiConstType=vpiDecConst + check (vpiReg) t.outer_scope[2].inner_scope[2].arr.check + rfr (vpiReg) t.outer_scope[2].inner_scope[2].arr.rfr + sig (vpiReg) t.outer_scope[2].inner_scope[2].arr.sig + verbose (vpiReg) t.outer_scope[2].inner_scope[2].arr.verbose + vpiParameter: + LENGTH (vpiParameter) t.outer_scope[2].inner_scope[2].arr.LENGTH + vpiConstType=vpiDecConst + arr (vpiModule) t.outer_scope[2].inner_scope[3].arr + vpiReg: + LENGTH (vpiParameter) t.outer_scope[2].inner_scope[3].arr.LENGTH + vpiConstType=vpiDecConst + check (vpiReg) t.outer_scope[2].inner_scope[3].arr.check + rfr (vpiReg) t.outer_scope[2].inner_scope[3].arr.rfr + sig (vpiReg) t.outer_scope[2].inner_scope[3].arr.sig + verbose (vpiReg) t.outer_scope[2].inner_scope[3].arr.verbose + vpiParameter: + LENGTH (vpiParameter) t.outer_scope[2].inner_scope[3].arr.LENGTH + vpiConstType=vpiDecConst + arr (vpiModule) t.outer_scope[3].inner_scope[1].arr + vpiReg: + LENGTH (vpiParameter) t.outer_scope[3].inner_scope[1].arr.LENGTH + vpiConstType=vpiDecConst + check (vpiReg) t.outer_scope[3].inner_scope[1].arr.check + rfr (vpiReg) t.outer_scope[3].inner_scope[1].arr.rfr + sig (vpiReg) t.outer_scope[3].inner_scope[1].arr.sig + verbose (vpiReg) t.outer_scope[3].inner_scope[1].arr.verbose + vpiParameter: + LENGTH (vpiParameter) t.outer_scope[3].inner_scope[1].arr.LENGTH + vpiConstType=vpiDecConst + arr (vpiModule) t.outer_scope[3].inner_scope[2].arr + vpiReg: + LENGTH (vpiParameter) t.outer_scope[3].inner_scope[2].arr.LENGTH + vpiConstType=vpiDecConst + check (vpiReg) t.outer_scope[3].inner_scope[2].arr.check + rfr (vpiReg) t.outer_scope[3].inner_scope[2].arr.rfr + sig (vpiReg) t.outer_scope[3].inner_scope[2].arr.sig + verbose (vpiReg) t.outer_scope[3].inner_scope[2].arr.verbose + vpiParameter: + LENGTH (vpiParameter) t.outer_scope[3].inner_scope[2].arr.LENGTH + vpiConstType=vpiDecConst + arr (vpiModule) t.outer_scope[3].inner_scope[3].arr + vpiReg: + LENGTH (vpiParameter) t.outer_scope[3].inner_scope[3].arr.LENGTH + vpiConstType=vpiDecConst + check (vpiReg) t.outer_scope[3].inner_scope[3].arr.check + rfr (vpiReg) t.outer_scope[3].inner_scope[3].arr.rfr + sig (vpiReg) t.outer_scope[3].inner_scope[3].arr.sig + verbose (vpiReg) t.outer_scope[3].inner_scope[3].arr.verbose + vpiParameter: + LENGTH (vpiParameter) t.outer_scope[3].inner_scope[3].arr.LENGTH + vpiConstType=vpiDecConst + sub (vpiModule) t.sub + vpiReg: + subsig1 (vpiReg) t.sub.subsig1 + subsig2 (vpiReg) t.sub.subsig2 + vpiParameter: + vpiParameter: + do_generate (vpiParameter) t.do_generate + vpiConstType=vpiDecConst + long_int (vpiParameter) t.long_int + vpiConstType=vpiDecConst +*-* All Finished *-* diff --git a/test_regress/t/t_vpi_dump.pl b/test_regress/t/t_vpi_dump.pl new file mode 100755 index 000000000..0ea513860 --- /dev/null +++ b/test_regress/t/t_vpi_dump.pl @@ -0,0 +1,34 @@ +#!/usr/bin/env perl +if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); die; } +# DESCRIPTION: Verilator: Verilog Test driver/expect definition +# +# Copyright 2024 by Wilson Snyder. This program is free software; you +# can redistribute it and/or modify it under the terms of either the GNU +# Lesser General Public License Version 3 or the Perl Artistic License +# Version 2.0. +# SPDX-License-Identifier: LGPL-3.0-only OR Artistic-2.0 + +scenarios(simulator => 1); + +skip("Known compiler limitation") + if $Self->cxx_version =~ /\(GCC\) 4.4/; + +compile( + make_top_shell => 0, + make_main => 0, + make_pli => 1, + iv_flags2 => ["-g2005-sv"], + verilator_flags2 => ["--exe --vpi --public-flat-rw --no-l2name $Self->{t_dir}/t_vpi_dump.cpp $Self->{t_dir}/TestVpiMain.cpp"], + make_flags => 'CPPFLAGS_ADD=-DVL_NO_LEGACY', + ); + +execute( + use_libvpi => 1, + check_finished => 1, + expect_filename => $Self->{golden_filename}, + xrun_run_expect_filename => ($Self->{golden_filename} =~ s/\.out$/.xrun.out/r), + iv_run_expect_filename => ($Self->{golden_filename} =~ s/\.out$/.iv.out/r), + ); + +ok(1); +1; diff --git a/test_regress/t/t_vpi_dump.v b/test_regress/t/t_vpi_dump.v new file mode 100644 index 000000000..ea7a17d17 --- /dev/null +++ b/test_regress/t/t_vpi_dump.v @@ -0,0 +1,130 @@ +// DESCRIPTION: Verilator: Verilog Test module +// +// Copyright 2010 by Wilson Snyder. This program is free software; you can +// redistribute it and/or modify it under the terms of either the GNU +// Lesser General Public License Version 3 or the Perl Artistic License +// Version 2.0. +// SPDX-License-Identifier: LGPL-3.0-only OR Artistic-2.0 + + +typedef struct packed { + logic [3:0][7:0] adr; // address + logic [3:0][7:0] dat; // data + int sel; // select +} t_bus; + +module t ( /*AUTOARG*/ + // Outputs + x, + // Inputs + clk, + a +); + + + parameter int do_generate = 1; + parameter longint long_int = 64'h123456789abcdef; + + + input clk; + + input [7:0] a; + output reg [7:0] x; + + reg onebit; + reg [2:1] twoone; + reg [2:1] fourthreetwoone[4:3]; + reg LONGSTART_a_very_long_name_which_will_get_hashed_a_very_long_name_which_will_get_hashed_a_very_long_name_which_will_get_hashed_a_very_long_name_which_will_get_hashed_LONGEND ; + + // verilator lint_off ASCRANGE + reg [0:61] quads[2:3]; + // verilator lint_on ASCRANGE + + reg [31:0] count; + reg [31:0] half_count; + + reg [7:0] text_byte; + reg [15:0] text_half; + reg [31:0] text_word; + reg [63:0] text_long; + reg [511:0] text; + + integer status; + + real real1; + string str1; + + t_bus bus1; + + sub sub (); + + + initial begin + + $write("*-* All Finished *-*\n"); + $finish(); + end + + + genvar i; + generate + for (i = 1; i <= 2; i = i + 1) begin : arr + arr #(.LENGTH(i)) arr (); + end + + for (i = 1; i <= 3; i = i + 1) begin : outer_scope + + parameter int scoped_param = i * 2; + + genvar j; + for (j = 1; j <= 3; j = j + 1) begin : inner_scope + parameter int scoped_param_inner = scoped_param + 1; + arr #(.LENGTH(scoped_param_inner)) arr (); + + end + end + endgenerate + + + + if (do_generate == 1) begin : cond_scope + sub scoped_sub (); + parameter int scoped_wire = 1; + end else begin : cond_scope_else + sub scoped_sub (); + parameter int scoped_wire = 2; + end + +endmodule : t + +module sub; + reg subsig1; + reg subsig2; +`ifdef IVERILOG + // stop icarus optimizing signals away + wire redundant = subsig1 | subsig2; +`endif +endmodule : sub + +module arr; + + parameter LENGTH = 1; + + reg [LENGTH-1:0] sig; + reg [LENGTH-1:0] rfr; + + reg check; + reg verbose; + + initial begin + sig = {LENGTH{1'b0}}; + rfr = {LENGTH{1'b0}}; + end + + always @(posedge check) begin + if (verbose) $display("%m : %x %x", sig, rfr); + if (check && sig != rfr) $stop; + check <= 0; + end + +endmodule : arr