Clean VPI struct member coverage
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
parent
2004c87892
commit
91c2147fa9
|
|
@ -3929,8 +3929,6 @@ uint32_t VerilatedVarProps::entSize() const VL_MT_SAFE {
|
|||
case VLVT_UINT32: size = sizeof(IData); break;
|
||||
case VLVT_UINT64: size = sizeof(QData); break;
|
||||
case VLVT_WDATA: size = VL_WORDS_I(entBits()) * sizeof(IData); break;
|
||||
case VLVT_STRUCT: size = 0; break;
|
||||
case VLVT_UNION: size = 0; break;
|
||||
default: size = 0; break; // LCOV_EXCL_LINE
|
||||
}
|
||||
return size;
|
||||
|
|
@ -4041,9 +4039,9 @@ VerilatedVar* VerilatedScope::varInsert(const char* namep, void* datap, bool isP
|
|||
|
||||
VerilatedVar* VerilatedScope::varInsertSized(const char* namep, void* datap, bool isParam,
|
||||
VerilatedVarType vltype, int vlflags, int udims,
|
||||
int pdims, uint32_t entSize...) VL_MT_UNSAFE {
|
||||
uint32_t entSize...) VL_MT_UNSAFE {
|
||||
if (!m_varsp) m_varsp = new VerilatedVarNameMap;
|
||||
VerilatedVar var(namep, datap, vltype, static_cast<VerilatedVarFlags>(vlflags), udims, pdims,
|
||||
VerilatedVar var(namep, datap, vltype, static_cast<VerilatedVarFlags>(vlflags), udims, 0,
|
||||
isParam, entSize);
|
||||
|
||||
va_list ap;
|
||||
|
|
@ -4054,12 +4052,6 @@ VerilatedVar* VerilatedScope::varInsertSized(const char* namep, void* datap, boo
|
|||
var.m_unpacked[i].m_left = msb;
|
||||
var.m_unpacked[i].m_right = lsb;
|
||||
}
|
||||
for (int i = 0; i < pdims; ++i) {
|
||||
const int msb = va_arg(ap, int);
|
||||
const int lsb = va_arg(ap, int);
|
||||
var.m_packed[i].m_left = msb;
|
||||
var.m_packed[i].m_right = lsb;
|
||||
}
|
||||
va_end(ap);
|
||||
|
||||
m_varsp->emplace(namep, std::move(var));
|
||||
|
|
|
|||
|
|
@ -766,8 +766,8 @@ public: // But internals only - called from verilated modules, VerilatedSyms
|
|||
VerilatedVar* varInsert(const char* namep, void* datap, bool isParam, VerilatedVarType vltype,
|
||||
int vlflags, int udims, int pdims, ...) VL_MT_UNSAFE;
|
||||
VerilatedVar* varInsertSized(const char* namep, void* datap, bool isParam,
|
||||
VerilatedVarType vltype, int vlflags, int udims, int pdims,
|
||||
uint32_t entSize, ...) VL_MT_UNSAFE;
|
||||
VerilatedVarType vltype, int vlflags, int udims, uint32_t entSize,
|
||||
...) VL_MT_UNSAFE;
|
||||
VerilatedVar* forceableVarInsert(const char* namep, void* datap, bool isParam,
|
||||
VerilatedVarType vltype, int vlflags,
|
||||
void* forceReadSignalData, const char* forceReadSignalName,
|
||||
|
|
|
|||
|
|
@ -505,9 +505,6 @@ public:
|
|||
const char* const parentName = varp()->name();
|
||||
const std::string memberName = memberVarp->name();
|
||||
const size_t parentLen = std::strlen(parentName);
|
||||
if (memberName.size() <= parentLen || memberName.compare(0, parentLen, parentName) != 0
|
||||
|| memberName[parentLen] != '.')
|
||||
return nullptr; // LCOV_EXCL_LINE: Defensive; callers pass exact synthetic members
|
||||
|
||||
void* const parentDatap = varp()->datap();
|
||||
void* const memberDatap = memberVarp->datap();
|
||||
|
|
@ -2514,7 +2511,7 @@ static bool vl_vpi_parse_indices(std::string& name, std::vector<PLI_INT32>& indi
|
|||
return true;
|
||||
}
|
||||
|
||||
static const VerilatedScope* vl_vpi_top_port_scopep(const VerilatedScope* const scopep) {
|
||||
static const VerilatedScope* _vl_vpi_top_port_scopep(const VerilatedScope* const scopep) {
|
||||
if (VL_UNLIKELY(!scopep)) return nullptr;
|
||||
if (scopep->type() != VerilatedScope::SCOPE_MODULE) return nullptr;
|
||||
if (std::strcmp(scopep->name(), "TOP") == 0) return nullptr;
|
||||
|
|
@ -2522,9 +2519,9 @@ static const VerilatedScope* vl_vpi_top_port_scopep(const VerilatedScope* const
|
|||
return Verilated::threadContextp()->scopeFind("TOP");
|
||||
}
|
||||
|
||||
static bool vl_vpi_find_dotted_var(const std::string& scopename, const std::string& basename,
|
||||
const VerilatedScope*& scopep, const VerilatedVar*& varp,
|
||||
std::string& fullname) {
|
||||
static bool _vl_vpi_find_dotted_var(const std::string& scopename, const std::string& basename,
|
||||
const VerilatedScope*& scopep, const VerilatedVar*& varp,
|
||||
std::string& fullname) {
|
||||
if (scopename.empty()) return false;
|
||||
|
||||
// Unpacked struct/union members are exposed as synthetic vars whose names contain dots
|
||||
|
|
@ -2542,7 +2539,7 @@ static bool vl_vpi_find_dotted_var(const std::string& scopename, const std::stri
|
|||
scopep = Verilated::threadContextp()->scopeFind(dottedScope.empty() ? "TOP"
|
||||
: dottedScope.c_str());
|
||||
if (scopep) {
|
||||
if (const VerilatedScope* const topScopep = vl_vpi_top_port_scopep(scopep)) {
|
||||
if (const VerilatedScope* const topScopep = _vl_vpi_top_port_scopep(scopep)) {
|
||||
if (const VerilatedVar* const topVarp = topScopep->varFind(dottedName.c_str())) {
|
||||
scopep = topScopep;
|
||||
varp = topVarp;
|
||||
|
|
@ -2557,8 +2554,8 @@ static bool vl_vpi_find_dotted_var(const std::string& scopename, const std::stri
|
|||
}
|
||||
}
|
||||
|
||||
static VerilatedVpioVar* vl_vpi_handle_member_by_name(const std::string& name,
|
||||
const VerilatedVpioVar* vop) {
|
||||
static VerilatedVpioVar* _vl_vpi_handle_member_by_name(const std::string& name,
|
||||
const VerilatedVpioVar* vop) {
|
||||
const VerilatedScope* const scopep = vop->scopep();
|
||||
if (VL_UNLIKELY(!scopep)) return nullptr;
|
||||
const std::string memberName = std::string{vop->varp()->name()} + "." + name;
|
||||
|
|
@ -2567,8 +2564,8 @@ static VerilatedVpioVar* vl_vpi_handle_member_by_name(const std::string& name,
|
|||
return vop->withMember(memberVarp);
|
||||
}
|
||||
|
||||
static VerilatedVpioVar* vl_vpi_handle_apply_indices(VerilatedVpioVar* vop,
|
||||
const std::vector<PLI_INT32>& indices) {
|
||||
static VerilatedVpioVar* _vl_vpi_handle_apply_indices(VerilatedVpioVar* vop,
|
||||
const std::vector<PLI_INT32>& indices) {
|
||||
for (const PLI_INT32 index : indices) {
|
||||
VerilatedVpioVar* const nextVop = vop->withIndex(index);
|
||||
VL_DO_CLEAR(delete vop, vop = nullptr);
|
||||
|
|
@ -2578,7 +2575,7 @@ static VerilatedVpioVar* vl_vpi_handle_apply_indices(VerilatedVpioVar* vop,
|
|||
return vop;
|
||||
}
|
||||
|
||||
static bool vl_vpi_parse_optional_indices(std::string& name, std::vector<PLI_INT32>& indices) {
|
||||
static bool _vl_vpi_parse_optional_indices(std::string& name, std::vector<PLI_INT32>& indices) {
|
||||
indices.clear();
|
||||
if (name.empty()) return false;
|
||||
if (name.back() != ']') return true;
|
||||
|
|
@ -2587,8 +2584,8 @@ static bool vl_vpi_parse_optional_indices(std::string& name, std::vector<PLI_INT
|
|||
return vl_vpi_parse_indices(name, indices, &bitRange) && !bitRange.valid;
|
||||
}
|
||||
|
||||
static std::vector<std::string> vl_vpi_split_dotted_name(const std::string& name) {
|
||||
std::vector<std::string> parts;
|
||||
static void _vl_vpi_split_dotted_name(const std::string& name, std::vector<std::string>& parts) {
|
||||
parts.clear();
|
||||
const char* const namep = name.c_str();
|
||||
const char* beginp = namep;
|
||||
const char* posp = beginp;
|
||||
|
|
@ -2597,23 +2594,22 @@ static std::vector<std::string> vl_vpi_split_dotted_name(const std::string& name
|
|||
beginp = ++posp;
|
||||
}
|
||||
parts.emplace_back(beginp);
|
||||
return parts;
|
||||
}
|
||||
|
||||
static VerilatedVpioVar*
|
||||
vl_vpi_handle_indexed_member_from_scope(const VerilatedScope* const scopep,
|
||||
const std::vector<std::string>& parts,
|
||||
const size_t firstPart) {
|
||||
_vl_vpi_handle_indexed_member_from_scope(const VerilatedScope* const scopep,
|
||||
const std::vector<std::string>& parts,
|
||||
const size_t firstPart) {
|
||||
if (VL_UNLIKELY(!scopep) || VL_UNLIKELY(firstPart >= parts.size())) return nullptr;
|
||||
|
||||
std::string baseName = parts[firstPart];
|
||||
std::vector<PLI_INT32> indices;
|
||||
if (!vl_vpi_parse_optional_indices(baseName, indices)) return nullptr;
|
||||
if (!_vl_vpi_parse_optional_indices(baseName, indices)) return nullptr;
|
||||
|
||||
const VerilatedScope* varScopep = scopep;
|
||||
const VerilatedVar* baseVarp = nullptr;
|
||||
std::string fullnameOverride;
|
||||
if (const VerilatedScope* const topScopep = vl_vpi_top_port_scopep(scopep)) {
|
||||
if (const VerilatedScope* const topScopep = _vl_vpi_top_port_scopep(scopep)) {
|
||||
if (const VerilatedVar* const topVarp = topScopep->varFind(baseName.c_str())) {
|
||||
varScopep = topScopep;
|
||||
baseVarp = topVarp;
|
||||
|
|
@ -2629,29 +2625,30 @@ vl_vpi_handle_indexed_member_from_scope(const VerilatedScope* const scopep,
|
|||
: new VerilatedVpioVar{baseVarp, varScopep, baseVarp->datap(),
|
||||
_vl_vpi_member_local_name(baseVarp->name()),
|
||||
fullnameOverride};
|
||||
VerilatedVpioVar* vop = vl_vpi_handle_apply_indices(baseVop, indices);
|
||||
VerilatedVpioVar* vop = _vl_vpi_handle_apply_indices(baseVop, indices);
|
||||
if (!vop) return nullptr;
|
||||
|
||||
for (size_t i = firstPart + 1; i < parts.size(); ++i) {
|
||||
std::string memberName = parts[i];
|
||||
if (!vl_vpi_parse_optional_indices(memberName, indices)) {
|
||||
if (!_vl_vpi_parse_optional_indices(memberName, indices)) {
|
||||
VL_DO_CLEAR(delete vop, vop = nullptr);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
VerilatedVpioVar* const memberVop = vl_vpi_handle_member_by_name(memberName, vop);
|
||||
VerilatedVpioVar* const memberVop = _vl_vpi_handle_member_by_name(memberName, vop);
|
||||
VL_DO_CLEAR(delete vop, vop = nullptr);
|
||||
if (!memberVop) return nullptr;
|
||||
|
||||
vop = vl_vpi_handle_apply_indices(memberVop, indices);
|
||||
vop = _vl_vpi_handle_apply_indices(memberVop, indices);
|
||||
if (!vop) return nullptr;
|
||||
}
|
||||
return vop;
|
||||
}
|
||||
|
||||
static VerilatedVpioVar*
|
||||
vl_vpi_handle_dotted_indexed_member_by_name(const std::string& scopeAndName) {
|
||||
const std::vector<std::string> parts = vl_vpi_split_dotted_name(scopeAndName);
|
||||
_vl_vpi_handle_dotted_indexed_member_by_name(const std::string& scopeAndName) {
|
||||
std::vector<std::string> parts;
|
||||
_vl_vpi_split_dotted_name(scopeAndName, parts);
|
||||
if (parts.size() < 2) return nullptr;
|
||||
|
||||
for (size_t firstPart = parts.size() - 1; firstPart > 0; --firstPart) {
|
||||
|
|
@ -2661,13 +2658,13 @@ vl_vpi_handle_dotted_indexed_member_by_name(const std::string& scopeAndName) {
|
|||
= Verilated::threadContextp()->scopeFind(scopeName.c_str());
|
||||
if (!scopep) continue;
|
||||
if (VerilatedVpioVar* const vop
|
||||
= vl_vpi_handle_indexed_member_from_scope(scopep, parts, firstPart)) {
|
||||
= _vl_vpi_handle_indexed_member_from_scope(scopep, parts, firstPart)) {
|
||||
return vop;
|
||||
}
|
||||
}
|
||||
|
||||
const VerilatedScope* const topScopep = Verilated::threadContextp()->scopeFind("TOP");
|
||||
return vl_vpi_handle_indexed_member_from_scope(topScopep, parts, 0);
|
||||
return _vl_vpi_handle_indexed_member_from_scope(topScopep, parts, 0);
|
||||
}
|
||||
|
||||
// for obtaining handles
|
||||
|
|
@ -2702,7 +2699,8 @@ vpiHandle vpi_handle_by_name(PLI_BYTE8* namep, vpiHandle scope) {
|
|||
scopeAndName
|
||||
= std::string{voScopep->fullname()} + (scopeIsPackage ? "" : ".") + scopeAndName;
|
||||
} else if (voVarp && voVarp->isStructOrUnion()) {
|
||||
if (VerilatedVpioVar* const memberp = vl_vpi_handle_member_by_name(scopeAndName, voVarp)) {
|
||||
if (VerilatedVpioVar* const memberp
|
||||
= _vl_vpi_handle_member_by_name(scopeAndName, voVarp)) {
|
||||
return memberp->castVpiHandle();
|
||||
}
|
||||
scopeAndName = std::string{voVarp->fullname()} + "." + scopeAndName;
|
||||
|
|
@ -2769,9 +2767,9 @@ vpiHandle vpi_handle_by_name(PLI_BYTE8* namep, vpiHandle scope) {
|
|||
// Exact unindexed member names can be found directly; indexed member paths need the
|
||||
// component walker so array indices are applied before member offsets.
|
||||
if (!varp
|
||||
&& !vl_vpi_find_dotted_var(scopename, basename, scopep, varp, fullnameOverride)) {
|
||||
&& !_vl_vpi_find_dotted_var(scopename, basename, scopep, varp, fullnameOverride)) {
|
||||
if (VerilatedVpioVar* const memberp
|
||||
= vl_vpi_handle_dotted_indexed_member_by_name(scopeAndName)) {
|
||||
= _vl_vpi_handle_dotted_indexed_member_by_name(scopeAndName)) {
|
||||
return memberp->castVpiHandle();
|
||||
}
|
||||
return nullptr;
|
||||
|
|
@ -3030,13 +3028,13 @@ PLI_INT32 vpi_get(PLI_INT32 property, vpiHandle object) {
|
|||
case vpiPacked: {
|
||||
const VerilatedVpioVarBase* const vop = VerilatedVpioVarBase::castp(object);
|
||||
if (VL_LIKELY(vop && vop->isStructOrUnion())) return 0;
|
||||
break;
|
||||
// FALLTHRU
|
||||
}
|
||||
default: break;
|
||||
default:
|
||||
VL_VPI_ERROR_(__FILE__, __LINE__, "%s: Unsupported property %s, nothing will be returned",
|
||||
__func__, VerilatedVpiError::strFromVpiProp(property));
|
||||
return vpiUndefined;
|
||||
}
|
||||
VL_VPI_ERROR_(__FILE__, __LINE__, "%s: Unsupported property %s, nothing will be returned",
|
||||
__func__, VerilatedVpiError::strFromVpiProp(property));
|
||||
return vpiUndefined;
|
||||
}
|
||||
|
||||
PLI_INT64 vpi_get64(PLI_INT32 /*property*/, vpiHandle /*object*/) {
|
||||
|
|
|
|||
|
|
@ -253,11 +253,12 @@ class EmitCSyms final : EmitCBaseVisitorConst {
|
|||
stmt += vlEnumDir; // VLVD_IN etc
|
||||
stmt += ", ";
|
||||
stmt += std::to_string(udim);
|
||||
stmt += ", ";
|
||||
stmt += std::to_string(pdim);
|
||||
if (!entSize.empty()) {
|
||||
stmt += ", ";
|
||||
stmt += entSize;
|
||||
} else {
|
||||
stmt += ", ";
|
||||
stmt += std::to_string(pdim);
|
||||
}
|
||||
stmt += bounds;
|
||||
stmt += ")";
|
||||
|
|
|
|||
|
|
@ -2232,6 +2232,7 @@ int main(int argc, char** argv) {
|
|||
uint64_t sim_time = 1100;
|
||||
contextp->debug(0);
|
||||
contextp->commandArgs(argc, argv);
|
||||
VerilatedVpi::selfTest();
|
||||
|
||||
const std::unique_ptr<VM_PREFIX> topp{new VM_PREFIX{contextp.get(),
|
||||
// Note null name - we're flattening it out
|
||||
|
|
|
|||
Loading…
Reference in New Issue