Support VPI parameter iteration (#4765)

This commit is contained in:
Todd Strader 2023-12-15 13:53:13 -05:00 committed by GitHub
parent 668dbb25ab
commit 1066f06ec1
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 55 additions and 17 deletions

View File

@ -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();

View File

@ -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
}

View File

@ -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;