diff --git a/include/verilated_vpi.cpp b/include/verilated_vpi.cpp index 18b768b7c..cca51db67 100644 --- a/include/verilated_vpi.cpp +++ b/include/verilated_vpi.cpp @@ -382,10 +382,12 @@ class VerilatedVpioVarIter final : public VerilatedVpio { VerilatedVarNameMap::const_iterator m_it; bool m_started = false; const VerilatedScope* m_topscopep = nullptr; + bool m_onlyParams; public: - explicit VerilatedVpioVarIter(const VerilatedVpioScope* vop) - : m_scopep{vop->scopep()} { + explicit VerilatedVpioVarIter(const VerilatedVpioScope* vop, bool onlyParams = false) + : m_scopep{vop->scopep()} + , m_onlyParams{onlyParams} { if (VL_UNLIKELY(vop->toplevel())) // This is a toplevel, so get TOP scope to search for ports during vpi_scan. m_topscopep = Verilated::threadContextp()->scopeFind("TOP"); @@ -396,7 +398,11 @@ public: } uint32_t type() const override { return vpiIterator; } vpiHandle dovpi_scan() override { - if (VL_LIKELY(m_scopep->varsp())) { + if (VL_UNLIKELY(!m_scopep->varsp())) { + delete this; // IEEE 37.2.2 vpi_scan at end does a vpi_release_handle + return nullptr; // End of list - only one deep + } + while (true) { const VerilatedVarNameMap* const varsp = m_scopep->varsp(); if (VL_UNLIKELY(!m_started)) { m_it = varsp->begin(); @@ -411,14 +417,13 @@ public: delete this; // IEEE 37.2.2 vpi_scan at end does a vpi_release_handle return nullptr; } + if (m_onlyParams && !m_it->second.isParam()) continue; if (VL_UNLIKELY(m_topscopep)) { if (const VerilatedVar* topvarp = m_topscopep->varFind(m_it->second.name())) return ((new VerilatedVpioVar{topvarp, m_topscopep})->castVpiHandle()); } return ((new VerilatedVpioVar{&(m_it->second), m_scopep})->castVpiHandle()); } - delete this; // IEEE 37.2.2 vpi_scan at end does a vpi_release_handle - return nullptr; // End of list - only one deep } }; @@ -1922,6 +1927,11 @@ vpiHandle vpi_iterate(PLI_INT32 type, vpiHandle object) { if (VL_UNLIKELY(!vop)) return nullptr; return ((new VerilatedVpioVarIter{vop})->castVpiHandle()); } + case vpiParameter: { + const VerilatedVpioScope* const vop = VerilatedVpioScope::castp(object); + if (VL_UNLIKELY(!vop)) return nullptr; + return ((new VerilatedVpioVarIter{vop, true})->castVpiHandle()); + } case vpiModule: { const VerilatedVpioModule* const vop = VerilatedVpioModule::castp(object); const VerilatedHierarchyMap* const map = VerilatedImp::hierarchyMap(); diff --git a/test_regress/t/t_vpi_package.cpp b/test_regress/t/t_vpi_package.cpp index 5d019bad5..41568fca7 100644 --- a/test_regress/t/t_vpi_package.cpp +++ b/test_regress/t/t_vpi_package.cpp @@ -68,12 +68,29 @@ } extern "C" { +int count_params(TestVpiHandle& handle, int expectedParams) { + TestVpiHandle it = vpi_iterate(vpiParameter, handle); + CHECK_RESULT_NZ(it) + + int params = 0; + while (true) { + TestVpiHandle handle = vpi_scan(it); + if (handle == NULL) break; + params++; + } + it.freed(); + CHECK_RESULT(params, expectedParams); + + return 0; +} + int mon_check() { #ifdef TEST_VERBOSE printf("-mon_check()\n"); #endif TestVpiHandle it = vpi_iterate(vpiModule, NULL); + CHECK_RESULT_NZ(it) bool found_t = false; while (true) { @@ -87,10 +104,11 @@ int mon_check() { CHECK_RESULT_NZ(found_t); it = vpi_iterate(vpiInstance, NULL); + CHECK_RESULT_NZ(it) - found_t = false; - bool found_somepackage = false; - bool found_dollar_unit = false; + TestVpiHandle pkgHandle = NULL; + TestVpiHandle tHandle = NULL; + TestVpiHandle unitHandle = NULL; while (true) { TestVpiHandle handle = vpi_scan(it); if (handle == NULL) break; @@ -98,24 +116,31 @@ int mon_check() { const char* fullname = vpi_get_str(vpiFullName, handle); if (!strcmp("t", name)) { CHECK_RESULT_CSTR("t", fullname) - CHECK_RESULT_Z(found_t) - found_t = true; + CHECK_RESULT_Z(tHandle) + tHandle = handle; + handle.freed(); } else if (!strcmp("somepackage", name)) { CHECK_RESULT_CSTR("somepackage::", fullname) - CHECK_RESULT_Z(found_somepackage) - found_somepackage = true; + CHECK_RESULT_Z(pkgHandle) + pkgHandle = handle; + handle.freed(); } else if (!strcmp("$unit", name)) { CHECK_RESULT_CSTR("$unit::", fullname) - CHECK_RESULT_Z(found_dollar_unit) - found_dollar_unit = true; + CHECK_RESULT_Z(unitHandle) + unitHandle = handle; + handle.freed(); } else { CHECK_RESULT_NZ(0) } } it.freed(); - CHECK_RESULT_NZ(found_t) - CHECK_RESULT_NZ(found_somepackage) - CHECK_RESULT_NZ(found_dollar_unit) + CHECK_RESULT_NZ(pkgHandle) + CHECK_RESULT_NZ(tHandle) + CHECK_RESULT_NZ(unitHandle) + + CHECK_RESULT_Z(count_params(unitHandle, 1)); + CHECK_RESULT_Z(count_params(pkgHandle, 2)); + CHECK_RESULT_Z(count_params(tHandle, 3)); return 0; // Ok } diff --git a/test_regress/t/t_vpi_package.v b/test_regress/t/t_vpi_package.v index 3e7f1782d..9f9ca4161 100644 --- a/test_regress/t/t_vpi_package.v +++ b/test_regress/t/t_vpi_package.v @@ -12,12 +12,15 @@ parameter int dollarUnitInt /*verilator public_flat_rd*/ = 3; package somepackage; parameter int someInt /*verilator public_flat_rd*/ = 5; + parameter int anotherInt /*verilator public_flat_rd*/ = 6; endpackage module t (/*AUTOARG*/ ); /*verilator public_module*/ parameter int someOtherInt /* verilator public_flat_rd*/ = 7; + parameter int yetAnotherInt /* verilator public_flat_rd*/ = 9; + parameter int stillAnotherInt /* verilator public_flat_rd*/ = 17; integer status;