Fix memory leaks - batch 1 (#6411)

This commit is contained in:
Geza Lore 2025-09-09 22:39:44 +01:00 committed by GitHub
parent 83ff8e13ba
commit dd11d5a598
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
26 changed files with 228 additions and 191 deletions

View File

@ -358,6 +358,9 @@ class AssertVisitor final : public VNVisitor {
nodep->v3fatalSrc("Unknown node type");
}
if (passsp && !passsp->backp()) VL_DO_DANGLING(pushDeletep(passsp), passsp);
if (failsp && !failsp->backp()) VL_DO_DANGLING(pushDeletep(failsp), failsp);
AstNode* newp;
if (sentreep) {
newp = new AstAlways{nodep->fileline(), VAlwaysKwd::ALWAYS, sentreep, bodysp};

View File

@ -89,17 +89,6 @@ private:
while (VN_IS(propExprp, Var)) propExprp = propExprp->nextp();
return VN_CAST(propExprp, PropSpec);
}
void replaceVarRefsWithExprRecurse(AstNode* const nodep, const AstVar* varp,
AstNode* const exprp) {
if (!nodep) return;
if (const AstVarRef* varrefp = VN_CAST(nodep, VarRef)) {
if (varp == varrefp->varp()) nodep->replaceWith(exprp->cloneTree(false));
}
if (AstNode* const refp = nodep->op1p()) replaceVarRefsWithExprRecurse(refp, varp, exprp);
if (AstNode* const refp = nodep->op2p()) replaceVarRefsWithExprRecurse(refp, varp, exprp);
if (AstNode* const refp = nodep->op3p()) replaceVarRefsWithExprRecurse(refp, varp, exprp);
if (AstNode* const refp = nodep->op4p()) replaceVarRefsWithExprRecurse(refp, varp, exprp);
}
AstPropSpec* substitutePropertyCall(AstPropSpec* nodep) {
if (AstFuncRef* const funcrefp = VN_CAST(nodep->propp(), FuncRef)) {
if (const AstProperty* const propp = VN_CAST(funcrefp->taskp(), Property)) {
@ -116,9 +105,13 @@ private:
const AstVar* const portp = tconnect.first;
// cppcheck-suppress constVariablePointer // 'exprp' unlinked below
AstArg* const argp = tconnect.second;
AstNode* const pinp = argp->exprp()->unlinkFrBack();
replaceVarRefsWithExprRecurse(propExprp, portp, pinp);
VL_DO_DANGLING(pushDeletep(pinp), pinp);
propExprp->foreach([&](AstVarRef* refp) {
if (refp->varp() == portp) {
refp->replaceWith(argp->exprp()->cloneTree(false));
VL_DO_DANGLING(pushDeletep(refp), refp);
}
});
pushDeletep(argp->exprp()->unlinkFrBack());
}
// Handle case with 2 disable iff statement (IEEE 1800-2023 16.12.1)
if (nodep->disablep() && propExprp->disablep()) {
@ -146,6 +139,7 @@ private:
// Now substitute property reference with property body
nodep->replaceWith(propExprp);
VL_DO_DANGLING(pushDeletep(nodep), nodep);
return propExprp;
}
}
@ -486,7 +480,7 @@ private:
if (nodep->user1SetOnce()) return;
iterateChildren(nodep);
AstSenTree* const sentreep = nodep->sentreep();
if (sentreep) sentreep->unlinkFrBack();
if (sentreep) VL_DO_DANGLING(pushDeletep(sentreep->unlinkFrBack()), sentreep);
nodep->sentreep(newSenTree(nodep));
}
void visit(AstPast* nodep) override {
@ -559,7 +553,9 @@ private:
AstNodeExpr* const rhsp = nodep->rhsp()->unlinkFrBack();
AstNodeExpr* lhsp = nodep->lhsp()->unlinkFrBack();
if (m_disablep) lhsp = new AstAnd{fl, new AstNot{fl, m_disablep}, lhsp};
if (m_disablep) {
lhsp = new AstAnd{fl, new AstNot{fl, m_disablep->cloneTreePure(false)}, lhsp};
}
AstNodeExpr* const pastp = new AstPast{fl, lhsp};
pastp->dtypeFrom(lhsp);
@ -597,7 +593,7 @@ private:
nodep->disablep(m_defaultDisablep->condp()->cloneTreePure(true));
}
if (AstNodeExpr* const disablep = nodep->disablep()) {
m_disablep = disablep->cloneTreePure(false);
m_disablep = disablep;
if (VN_IS(nodep->backp(), Cover)) {
blockp = new AstAnd{disablep->fileline(),
new AstNot{disablep->fileline(), disablep->unlinkFrBack()},

View File

@ -1647,7 +1647,7 @@ void AstAlways::dumpJson(std::ostream& str) const {
dumpJsonGen(str);
}
AstAssertCtl::AstAssertCtl(FileLine* fl, VAssertCtlType ctlType, uint32_t assertType,
uint32_t directiveType, AstNodeExpr*, AstNodeExpr*)
uint32_t directiveType, AstNodeExpr* levelp, AstNodeExpr* itemsp)
: ASTGEN_SUPER_AssertCtl(fl)
, m_ctlType{VAssertCtlType::_TO_BE_EVALUATED}
, m_assertTypes{VAssertType::INTERNAL}
@ -1655,9 +1655,12 @@ AstAssertCtl::AstAssertCtl(FileLine* fl, VAssertCtlType ctlType, uint32_t assert
this->controlTypep(new AstConst{fl, ctlType});
this->assertTypesp(new AstConst{fl, assertType});
this->directiveTypesp(new AstConst{fl, directiveType});
// Parser creates these but are unused, nuke them
if (levelp) VL_DO_DANGLING(levelp->deleteTree(), levelp);
if (itemsp) VL_DO_DANGLING(itemsp->deleteTree(), itemsp);
}
AstAssertCtl::AstAssertCtl(FileLine* fl, AstNodeExpr* controlTypep, AstNodeExpr* assertTypesp,
AstNodeExpr* directiveTypep, AstNodeExpr*, AstNodeExpr*)
AstNodeExpr* directiveTypep, AstNodeExpr* levelp, AstNodeExpr* itemsp)
: ASTGEN_SUPER_AssertCtl(fl)
, m_ctlType{VAssertCtlType::_TO_BE_EVALUATED}
, m_assertTypes{VAssertType::INTERNAL}
@ -1665,6 +1668,9 @@ AstAssertCtl::AstAssertCtl(FileLine* fl, AstNodeExpr* controlTypep, AstNodeExpr*
this->controlTypep(controlTypep);
this->assertTypesp(assertTypesp);
this->directiveTypesp(directiveTypep);
// Parser creates these but are unused, nuke them
if (levelp) VL_DO_DANGLING(levelp->deleteTree(), levelp);
if (itemsp) VL_DO_DANGLING(itemsp->deleteTree(), itemsp);
}
void AstAssertCtl::dump(std::ostream& str) const {
this->AstNode::dump(str);

View File

@ -526,6 +526,7 @@ AstNode* V3Begin::convertToWhile(AstForeach* nodep) {
nestedIndexp = varp;
fromDtp = fromDtp->subDTypep();
}
VL_DO_DANGLING(subfromp->deleteTree(), subfromp);
// The parser validates we don't have "foreach (array[,,,])"
AstNode* const bodyp = nodep->stmtsp();
if (!newp) {

View File

@ -436,6 +436,7 @@ class CaseVisitor final : public VNVisitor {
// Similar logic in V3Width::visit(AstInside)
condp = irangep->newAndFromInside(cexprp, irangep->lhsp()->unlinkFrBack(),
irangep->rhsp()->unlinkFrBack());
VL_DO_DANGLING(icondp->deleteTree(), icondp);
} else if (iconstp && iconstp->num().isFourState()
&& (nodep->casex() || nodep->casez() || nodep->caseInside())) {
V3Number nummask{itemp, iconstp->width()};

View File

@ -218,7 +218,7 @@ class CMakeEmitter final {
<< v3Global.rootp()->topModulep()->name() << " DIRECTORY "
<< v3Global.opt.makeDir() << " SOURCES ";
for (const auto& itr : *planp) {
*of << " " << v3Global.opt.makeDir() + "/" + itr.second->hierWrapperFilename(true);
*of << " " << v3Global.opt.makeDir() + "/" + itr.second.hierWrapperFilename(true);
}
*of << " " << cmake_list(v3Global.opt.vFiles());
*of << " VERILATOR_ARGS ";

View File

@ -871,7 +871,7 @@ class EmitMkHierVerilation final {
of.puts(v3Global.opt.prefix()
+ ".mk: $(VM_HIER_INPUT_FILES) $(VM_HIER_VERILOG_LIBS) ");
of.puts(V3Os::filenameNonDir(argsFile) + " ");
for (const auto& itr : *m_planp) of.puts(itr.second->hierWrapperFilename(true) + " ");
for (const auto& itr : *m_planp) of.puts(itr.second.hierWrapperFilename(true) + " ");
of.puts("\n");
emitLaunchVerilator(of, argsFile);
}

View File

@ -154,7 +154,7 @@ class V3EmitMkJsonEmitter final {
std::vector<std::string> sources;
for (const auto& itr : *planp)
sources.emplace_back(makeDir + "/" + itr.second->hierWrapperFilename(true));
sources.emplace_back(makeDir + "/" + itr.second.hierWrapperFilename(true));
for (const auto& itr : v3Global.opt.vFiles())
sources.emplace_back(

View File

@ -277,7 +277,10 @@ class ExpandVisitor final : public VNVisitor {
// Return word of fromp that contains bit lsbp + the given word offset.
static AstNodeExpr* newWordSelBit(FileLine* flp, AstNodeExpr* fromp, AstNodeExpr* lsbp,
uint32_t wordOffset = 0) {
return newWordSelWord(flp, fromp, newWordIndex(lsbp, wordOffset));
AstNodeExpr* const indexp = newWordIndex(lsbp, wordOffset);
AstNodeExpr* const wordSelp = newWordSelWord(flp, fromp, indexp);
if (!indexp->backp()) VL_DO_DANGLING(indexp->deleteTree(), indexp);
return wordSelp;
}
static AstNodeExpr* newSelBitBit(AstNodeExpr* lsbp) {
@ -560,7 +563,9 @@ class ExpandVisitor final : public VNVisitor {
++m_nTmps;
// Compute word index of LSB, store to temporary if not constant
AstNodeExpr* wordIdxp = newWordIndex(rhsp->lsbp()->cloneTreePure(false));
AstNodeExpr* const wordLsbp = rhsp->lsbp()->cloneTreePure(false);
AstNodeExpr* wordIdxp = newWordIndex(wordLsbp);
if (!wordLsbp->backp()) VL_DO_DANGLING(wordLsbp->deleteTree(), wordLsbp);
wordIdxp = V3Const::constifyEditCpp(wordIdxp);
if (!VN_IS(wordIdxp, Const)) {
AstVar* const tmpp = addLocalTmp(nodep, "ExpandSel_WordIdx", wordIdxp);

View File

@ -116,8 +116,7 @@ public:
new AstVarRef{flp, m_enVscp, VAccess::READ}});
AstVarRef* const origp = new AstVarRef{flp, vscp, VAccess::READ};
ForceState::markNonReplaceable(origp);
itemsp->addNext(
new AstSenItem{flp, VEdgeType::ET_CHANGED, origp->cloneTree(false)});
itemsp->addNext(new AstSenItem{flp, VEdgeType::ET_CHANGED, origp});
AstActive* const activep
= new AstActive{flp, "force-update", new AstSenTree{flp, itemsp}};
activep->senTreeStorep(activep->sentreep());
@ -252,7 +251,7 @@ class ForceConvertVisitor final : public VNVisitor {
= new AstAssign{flp, lhsp->cloneTreePure(false), rhsp->cloneTreePure(false)};
transformWritenVarScopes(setValp->lhsp(), [this, rhsp](AstVarScope* vscp) {
AstVarScope* const valVscp = m_state.getForceComponents(vscp).m_valVscp;
m_state.setValVscpRhsExpr(valVscp, rhsp->cloneTreePure(false));
m_state.setValVscpRhsExpr(valVscp, rhsp);
rhsp->foreach([valVscp, this](AstVarRef* refp) { m_state.addValVscp(refp, valVscp); });
return valVscp;
});

View File

@ -69,46 +69,50 @@ void V3Global::readFiles() {
VInFilter filter{v3Global.opt.pipeFilter()};
V3Parse parser{v3Global.rootp(), &filter};
{
V3Parse parser{v3Global.rootp(), &filter};
// Parse the std waivers
if (v3Global.opt.stdWaiver()) {
parser.parseFile(
new FileLine{V3Options::getStdWaiverPath()}, V3Options::getStdWaiverPath(), false,
"work", "Cannot find verilated_std_waiver.vlt containing built-in lint waivers: ");
}
// Read .vlt files
for (const VFileLibName& filelib : v3Global.opt.vltFiles()) {
parser.parseFile(new FileLine{FileLine::commandLineFilename()}, filelib.filename(), false,
filelib.libname(), "Cannot find file containing .vlt file: ");
}
// Parse the std waivers
if (v3Global.opt.stdWaiver()) {
parser.parseFile(
new FileLine{V3Options::getStdWaiverPath()}, V3Options::getStdWaiverPath(), false,
"work", "Cannot find verilated_std_waiver.vlt containing built-in lint waivers: ");
}
// Read .vlt files
for (const VFileLibName& filelib : v3Global.opt.vltFiles()) {
parser.parseFile(new FileLine{FileLine::commandLineFilename()}, filelib.filename(),
false, filelib.libname(), "Cannot find file containing .vlt file: ");
}
// Parse the std package
if (v3Global.opt.stdPackage()) {
parser.parseFile(new FileLine{V3Options::getStdPackagePath()},
V3Options::getStdPackagePath(), false, "work",
"Cannot find verilated_std.sv containing built-in std:: definitions: ");
}
// Parse the std package
if (v3Global.opt.stdPackage()) {
parser.parseFile(
new FileLine{V3Options::getStdPackagePath()}, V3Options::getStdPackagePath(),
false, "work",
"Cannot find verilated_std.sv containing built-in std:: definitions: ");
}
// Read top module
for (const auto& filelib : v3Global.opt.vFiles()) {
parser.parseFile(new FileLine{FileLine::commandLineFilename()}, filelib.filename(), false,
filelib.libname(), "Cannot find file containing module: ");
}
// Read top module
for (const auto& filelib : v3Global.opt.vFiles()) {
parser.parseFile(new FileLine{FileLine::commandLineFilename()}, filelib.filename(),
false, filelib.libname(), "Cannot find file containing module: ");
}
// Read libraries
// To be compatible with other simulators,
// this needs to be done after the top file is read
for (const auto& filelib : v3Global.opt.libraryFiles()) {
parser.parseFile(new FileLine{FileLine::commandLineFilename()}, filelib.filename(), true,
filelib.libname(), "Cannot find file containing library module: ");
}
// Read libraries
// To be compatible with other simulators,
// this needs to be done after the top file is read
for (const auto& filelib : v3Global.opt.libraryFiles()) {
parser.parseFile(new FileLine{FileLine::commandLineFilename()}, filelib.filename(),
true, filelib.libname(),
"Cannot find file containing library module: ");
}
// Read hierarchical type parameter file
for (const auto& filelib : v3Global.opt.hierParamFile()) {
parser.parseFile(new FileLine{FileLine::commandLineFilename()}, filelib.filename(), false,
filelib.libname(),
"Cannot open file containing hierarchical parameter declarations: ");
// Read hierarchical type parameter file
for (const auto& filelib : v3Global.opt.hierParamFile()) {
parser.parseFile(new FileLine{FileLine::commandLineFilename()}, filelib.filename(),
false, filelib.libname(),
"Cannot open file containing hierarchical parameter declarations: ");
}
}
// v3Global.rootp()->dumpTreeFile(v3Global.debugFilename("parse.tree"));

View File

@ -158,14 +158,6 @@ V3HierBlock::StrGParams V3HierBlock::stringifyParams(const V3HierBlockParams::GP
return strParams;
}
V3HierBlock::~V3HierBlock() {
UASSERT(m_children.empty(), "at least one module must be a leaf");
for (const auto& hierblockp : m_children) {
const bool deleted = hierblockp->m_children.erase(this);
UASSERT_OBJ(deleted, m_modp, " is not registered");
}
}
V3StringList V3HierBlock::commandArgs(bool forCMake) const {
V3StringList opts;
const string prefix = hierPrefix();
@ -378,13 +370,14 @@ public:
//######################################################################
void V3HierBlockPlan::add(const AstNodeModule* modp, const V3HierBlockParams& params) {
const auto pair = m_blocks.emplace(modp, nullptr);
if (pair.second) {
V3HierBlock* hblockp = new V3HierBlock{modp, params};
const bool newEntry = m_blocks
.emplace(std::piecewise_construct, std::forward_as_tuple(modp),
std::forward_as_tuple(modp, params))
.second;
if (newEntry) {
UINFO(3, "Add " << modp->prettyNameQ() << " with " << params.gparams().size()
<< " parameters and " << params.gTypeParams().size()
<< " type parameters");
pair.first->second = hblockp;
}
}
@ -395,8 +388,8 @@ void V3HierBlockPlan::registerUsage(const AstNodeModule* parentp, const AstNodeM
if (child != m_blocks.end()) {
UINFO(3, "Found usage relation " << parentp->prettyNameQ() << " uses "
<< childp->prettyNameQ());
parent->second->addChild(child->second);
child->second->addParent(parent->second);
parent->second.addChild(&child->second);
child->second.addParent(&parent->second);
}
}
@ -431,12 +424,12 @@ V3HierBlockPlan::HierVector V3HierBlockPlan::hierBlocksSorted() const {
HierVector sorted;
for (const_iterator it = begin(); it != end(); ++it) {
if (!it->second->hasChild()) { // No children, already leaf
sorted.push_back(it->second);
if (!it->second.hasChild()) { // No children, already leaf
sorted.push_back(&it->second);
} else {
ChildrenMap::value_type::second_type& childrenSet
= childrenOfHierBlock[it->second]; // insert
const V3HierBlock::HierBlockSet& c = it->second->children();
= childrenOfHierBlock[&it->second]; // insert
const V3HierBlock::HierBlockSet& c = it->second.children();
childrenSet.insert(c.begin(), c.end());
}
}
@ -465,7 +458,7 @@ V3HierBlockPlan::HierVector V3HierBlockPlan::hierBlocksSorted() const {
void V3HierBlockPlan::writeCommandArgsFiles(bool forCMake) const {
for (const_iterator it = begin(); it != end(); ++it) {
it->second->writeCommandArgsFile(forCMake);
it->second.writeCommandArgsFile(forCMake);
}
// For the top module
const std::unique_ptr<std::ofstream> of{
@ -473,7 +466,7 @@ void V3HierBlockPlan::writeCommandArgsFiles(bool forCMake) const {
if (!forCMake) {
// Load wrappers first not to be overwritten by the original HDL
for (const_iterator it = begin(); it != end(); ++it) {
*of << it->second->hierWrapperFilename(true) << "\n";
*of << it->second.hierWrapperFilename(true) << "\n";
}
}
V3HierWriteCommonInputs(nullptr, of.get(), forCMake);
@ -486,7 +479,7 @@ void V3HierBlockPlan::writeCommandArgsFiles(bool forCMake) const {
*of << "--mod-prefix " << v3Global.opt.modPrefix() << "\n";
}
for (const_iterator it = begin(); it != end(); ++it) {
*of << it->second->hierBlockArgs().front() << "\n";
*of << it->second.hierBlockArgs().front() << "\n";
}
if (!v3Global.opt.libCreate().empty()) {
@ -505,5 +498,5 @@ string V3HierBlockPlan::topCommandArgsFilename(bool forCMake) {
}
void V3HierBlockPlan::writeParametersFiles() const {
for (const auto& block : *this) block.second->writeParametersFile();
for (const auto& block : *this) block.second.writeParametersFile();
}

View File

@ -81,6 +81,7 @@ private:
// METHODS
VL_UNCOPYABLE(V3HierBlock);
VL_UNMOVABLE(V3HierBlock);
static StrGParams stringifyParams(const V3HierBlockParams::GParams& params,
bool forGOption) VL_MT_DISABLED;
@ -89,7 +90,7 @@ public:
: m_modp{modp}
, m_params{params} {}
~V3HierBlock() VL_MT_DISABLED;
~V3HierBlock() VL_MT_DISABLED = default;
void addParent(V3HierBlock* parentp) { m_parents.insert(parentp); }
bool hasParent() const { return !m_parents.empty(); }
@ -123,7 +124,8 @@ public:
// Holds relationship between AstNodeModule and V3HierBlock
class V3HierBlockPlan final {
using HierMap = std::unordered_map<const AstNodeModule*, V3HierBlock*>;
// TODO: this map is non-deterministic
using HierMap = std::unordered_map<const AstNodeModule*, V3HierBlock>;
HierMap m_blocks;
V3HierBlockPlan() = default;

View File

@ -588,7 +588,7 @@ void inlineCell(AstNodeModule* modp, AstCell* cellp, bool last) {
// Delete the empty shell of the inlined module
VL_DO_DANGLING(inlinedp->deleteTree(), inlinedp);
// Remove the cell we just inlined
VL_DO_DANGLING(cellp->unlinkFrBack(), cellp);
VL_DO_DANGLING(cellp->unlinkFrBack()->deleteTree(), cellp);
}
// Apply all inlining decisions

View File

@ -1100,6 +1100,7 @@ class ParamVisitor final : public VNVisitor {
std::multimap<bool, AstNode*> m_cellps; // Cells left to process (in current module)
std::multimap<int, AstNodeModule*> m_workQueue; // Modules left to process
std::vector<AstClass*> m_paramClasses; // Parameterized classes
std::deque<std::string> m_strings; // Allocator for temporary strings
// Map from AstNodeModule to set of all AstNodeModules that instantiates it.
std::unordered_map<AstNodeModule*, std::unordered_set<AstNodeModule*>> m_parentps;
@ -1162,7 +1163,6 @@ class ParamVisitor final : public VNVisitor {
if (const string* const genHierNamep = cellp->user2u().to<string*>()) {
someInstanceName += *genHierNamep;
cellp->user2p(nullptr);
VL_DO_DANGLING(delete genHierNamep, genHierNamep);
}
// Apply parameter specialization
@ -1195,8 +1195,8 @@ class ParamVisitor final : public VNVisitor {
// A generic visitor for cells and class refs
void visitCellOrClassRef(AstNode* nodep, bool isIface) {
// Must do ifaces first, so push to list and do in proper order
string* const genHierNamep = new std::string{m_generateHierName};
nodep->user2p(genHierNamep);
m_strings.emplace_back(m_generateHierName);
nodep->user2p(&m_strings.back());
// Visit parameters in the instantiation.
iterateChildren(nodep);
m_cellps.emplace(!isIface, nodep);

View File

@ -216,8 +216,9 @@ AstVar* V3ParseGrammar::createVariable(FileLine* fileline, const string& name,
} else {
dtypep = new AstBasicDType{fileline, LOGIC_IMPLICIT};
}
} else { // May make new variables with same type, so clone
dtypep = dtypep->cloneTree(false);
} else {
// If already consumed by an earlier decl, clone it
if (dtypep->backp()) dtypep = dtypep->cloneTree(false);
}
// UINFO(0,"CREVAR "<<fileline->ascii()<<" decl="<<GRAMMARP->m_varDecl.ascii()<<"
// io="<<GRAMMARP->m_varIO.ascii()<<endl);

View File

@ -212,7 +212,9 @@ public:
}
}
void setDType(AstNodeDType* dtypep) {
if (m_varDTypep) VL_DO_CLEAR(m_varDTypep->deleteTree(), m_varDTypep = nullptr);
if (m_varDTypep && !m_varDTypep->backp()) {
VL_DO_CLEAR(m_varDTypep->deleteTree(), m_varDTypep = nullptr);
}
m_varDTypep = dtypep;
}
void setNetDelay(AstDelay* netDelayp) { m_netDelayp.reset(netDelayp); }

View File

@ -1628,16 +1628,16 @@ class RandomizeVisitor final : public VNVisitor {
}
AstNodeStmt* createArrayForeachLoop(FileLine* const fl, AstNodeDType* const dtypep,
AstNodeExpr* exprp, AstVar* const outputVarp) {
V3UniqueNames* uniqueNamep = new V3UniqueNames{"__Vrandarr"};
V3UniqueNames uniqueNames{"__Vrandarr"};
AstNodeDType* tempDTypep = dtypep;
AstVar* randLoopIndxp = nullptr;
AstNodeStmt* stmtsp = nullptr;
auto createLoopIndex = [&](AstNodeDType* tempDTypep) {
if (VN_IS(tempDTypep, AssocArrayDType)) {
return new AstVar{fl, VVarType::VAR, uniqueNamep->get(""),
return new AstVar{fl, VVarType::VAR, uniqueNames.get(""),
VN_AS(tempDTypep, AssocArrayDType)->keyDTypep()};
}
return new AstVar{fl, VVarType::VAR, uniqueNamep->get(""),
return new AstVar{fl, VVarType::VAR, uniqueNames.get(""),
dtypep->findBasicDType(VBasicDTypeKwd::UINT32)};
};
auto createForeachLoop = [&](AstNodeExpr* tempElementp, AstVar* randLoopIndxp) {

View File

@ -170,6 +170,7 @@ private:
if (writesToVirtIface(nodep)) {
// Convert to always, as we have to assign the trigger var
nodep->convertToAlways();
VL_DO_DANGLING(pushDeletep(nodep), nodep);
}
}
void visit(AstNodeIf* nodep) override {
@ -284,12 +285,13 @@ public:
VirtIfaceTriggers makeVirtIfaceTriggers(AstNetlist* nodep) {
UINFO(2, __FUNCTION__ << ":");
VirtIfaceTriggers triggers{};
if (v3Global.hasVirtIfaces()) {
VirtIfaceVisitor visitor{nodep};
triggers = VirtIfaceVisitor{nodep}.take_triggers();
// Dump afer destructor so VNDeleter runs
V3Global::dumpCheckGlobalTree("sched_vif", 0, dumpTreeEitherLevel() >= 6);
return visitor.take_triggers();
}
return {};
return triggers;
}
} //namespace V3Sched

View File

@ -1774,7 +1774,7 @@ V3TaskConnects V3Task::taskConnects(AstNodeFTaskRef* nodep, AstNode* taskStmtsp,
}
}
}
newvaluep = newvaluep->cloneTree(true);
newvaluep = newvaluep->backp() ? newvaluep->cloneTree(true) : newvaluep;
// To avoid problems with callee needing to know to deleteTree
// or not, we make this into a pin
UINFO(9, "Default pin for " << portp);

View File

@ -1383,14 +1383,11 @@ class TristateVisitor final : public TristateBaseVisitor {
} else {
enRhsp = getEnExprBasedOnOriginalp(rhsp);
}
const V3Number oneIfEn
= VN_AS(constp->user1p(), Const)
->num(); // visit(AstConst) already split into en/ones
const V3Number& oneIfEnOne = constp->num();
AstNodeExpr* newp
= new AstLogAnd{fl, new AstEq{fl, new AstConst{fl, oneIfEn}, enRhsp},
= new AstLogAnd{fl, new AstEq{fl, VN_AS(constp->user1p(), Const), enRhsp},
// Keep the caseeq if there are X's present
new AstEqCase{fl, new AstConst{fl, oneIfEnOne}, rhsp}};
new AstEqCase{fl, new AstConst{fl, constp->num()}, rhsp}};
constp->user1p(nullptr);
if (neq) newp = new AstLogNot{fl, newp};
UINFO(9, " newceq " << newp);
UINFOTREE(9, nodep, "", "caseeq-old");
@ -1619,30 +1616,26 @@ class TristateVisitor final : public TristateBaseVisitor {
// Therefore, create the enable, output and separate input pin,
// then pinReconnectSimple all
// Create the output enable pin, connect to new signal
AstNodeExpr* enrefp;
{
AstVar* const enVarp = new AstVar{nodep->fileline(), VVarType::MODULETEMP,
nodep->name() + "__en" + cvtToStr(m_unique++),
VFlagBitPacked{}, enModVarp->width()};
if (inDeclProcessing) { // __en(from-resolver-const) or __en(from-resolver-wire)
enModVarp->varType2In();
} else {
enModVarp->varType2Out();
}
UINFO(9, " newenv " << enVarp);
AstPin* const enpinp
= new AstPin{nodep->fileline(), nodep->pinNum(),
enModVarp->name(), // should be {var}"__en"
new AstVarRef{nodep->fileline(), enVarp, VAccess::WRITE}};
enpinp->modVarp(enModVarp);
UINFO(9, " newpin " << enpinp);
enpinp->user2(U2_BOTH); // don't iterate the pin later
nodep->addNextHere(enpinp);
m_modp->addStmtsp(enVarp);
enrefp = new AstVarRef{nodep->fileline(), enVarp, VAccess::READ};
UINFO(9, " newvrf " << enrefp);
UINFOTREE(9, enpinp, "", "pin-ena");
AstVar* const enVarp = new AstVar{nodep->fileline(), VVarType::MODULETEMP,
nodep->name() + "__en" + cvtToStr(m_unique++),
VFlagBitPacked{}, enModVarp->width()};
if (inDeclProcessing) { // __en(from-resolver-const) or __en(from-resolver-wire)
enModVarp->varType2In();
} else {
enModVarp->varType2Out();
}
UINFO(9, " newenv " << enVarp);
AstPin* const enpinp
= new AstPin{nodep->fileline(), nodep->pinNum(),
enModVarp->name(), // should be {var}"__en"
new AstVarRef{nodep->fileline(), enVarp, VAccess::WRITE}};
enpinp->modVarp(enModVarp);
UINFO(9, " newpin " << enpinp);
enpinp->user2(U2_BOTH); // don't iterate the pin later
nodep->addNextHere(enpinp);
m_modp->addStmtsp(enVarp);
UINFOTREE(9, enpinp, "", "pin-ena");
// Create new output pin
const AstAssignW* outAssignp = nullptr; // If reconnected, the related assignment
AstPin* outpinp = nullptr;
@ -1712,7 +1705,7 @@ class TristateVisitor final : public TristateBaseVisitor {
if (exprrefp) {
UINFO(9, "outref " << exprrefp);
// Mark as now tristated; iteration will pick it up from there
exprrefp->user1p(enrefp);
exprrefp->user1p(new AstVarRef{nodep->fileline(), enVarp, VAccess::READ});
if (!outAssignp) {
mapInsertLhsVarRef(exprrefp); // insertTristates will convert
// // to a varref to the __out# variable
@ -1877,9 +1870,20 @@ class TristateVisitor final : public TristateBaseVisitor {
public:
// CONSTRUCTORS
explicit TristateVisitor(AstNode* nodep) {
explicit TristateVisitor(AstNetlist* netlistp) {
m_tgraph.clear();
iterate(nodep);
iterate(netlistp);
#ifdef VL_LEAK_CHECKS
// It's a bit chaotic up there
std::vector<AstNode*> unusedRootps;
netlistp->foreach([&](AstNode* nodep) {
AstNode* const enp = nodep->user1p();
if (!enp) return;
if (enp->backp()) return;
unusedRootps.emplace_back(enp);
});
for (AstNode* const nodep : unusedRootps) VL_DO_DANGLING(nodep->deleteTree(), nodep);
#endif
}
~TristateVisitor() override {
V3Stats::addStat("Tristate, Tristate resolved nets", m_statTriSigs);

View File

@ -1829,9 +1829,12 @@ class WidthVisitor final : public VNVisitor {
// Created by V3LinkDot only to check that the prototype was correct when we got here
UASSERT_OBJ(m_ftaskp, nodep, "FUNC attr not under function");
AstNodeDType* const protoDtp = nodep->fromp()->dtypep();
AstNodeDType* const declDtp = m_ftaskp->fvarp()
? m_ftaskp->fvarp()->dtypep()
: new AstVoidDType{m_ftaskp->fileline()};
AstNodeDType* const declDtp = [&]() {
if (m_ftaskp->fvarp()) return m_ftaskp->fvarp()->dtypep();
AstNodeDType* const voidp = new AstVoidDType{m_ftaskp->fileline()};
pushDeletep(voidp);
return voidp;
}();
if (!similarDTypeRecurse(protoDtp, declDtp)) {
protoDtp->v3warn(
PROTOTYPEMIS,
@ -2129,8 +2132,7 @@ class WidthVisitor final : public VNVisitor {
// ? ExprStmt(ExprAssign(out, Cast(v, type)), 1) : 0)"
AstEnumDType* const enumDtp = VN_AS(toDtp, EnumDType);
UASSERT_OBJ(enumDtp, nodep, "$cast determined as enum, but not enum type");
AstNodeExpr* const testp
= enumTestValid(nodep->fromp()->cloneTreePure(false), enumDtp);
AstNodeExpr* const testp = enumTestValid(nodep->fromp(), enumDtp);
FileLine* const fl_novalue = new FileLine{fl};
fl_novalue->warnOff(V3ErrorCode::ENUMVALUE, true);
newp = new AstCond{
@ -4691,7 +4693,10 @@ class WidthVisitor final : public VNVisitor {
for (AstPatMember* patp = VN_AS(nodep->itemsp(), PatMember); patp;) {
AstPatMember* const nextp = VN_AS(patp->nextp(), PatMember);
if (patp->isDefault()) {
if (defaultp) nodep->v3error("Multiple '{ default: } clauses");
if (defaultp) {
VL_DO_DANGLING(pushDeletep(defaultp), defaultp);
nodep->v3error("Multiple '{ default: } clauses");
}
defaultp = patp;
patp->unlinkFrBack();
}
@ -4837,7 +4842,7 @@ class WidthVisitor final : public VNVisitor {
} else {
nodep->v3error("Assignment pattern with no members");
}
VL_DO_DANGLING(pushDeletep(nodep), nodep); // Deletes defaultp also, if present
VL_DO_DANGLING(pushDeletep(nodep), nodep);
}
AstNodeExpr* nestedvalueConcat_patternUOrStruct(AstNodeUOrStructDType* memp_vdtypep,
@ -4964,7 +4969,7 @@ class WidthVisitor final : public VNVisitor {
nodep->v3error("Assignment pattern with no members");
}
// UINFOTREE(9, newp, "", "apat-out");
VL_DO_DANGLING(pushDeletep(nodep), nodep); // Deletes defaultp also, if present
VL_DO_DANGLING(pushDeletep(nodep), nodep);
}
void patternAssoc(AstPattern* nodep, AstAssocArrayDType* arrayDtp, AstPatMember* defaultp) {
AstNode* defaultValuep = nullptr;
@ -4993,7 +4998,7 @@ class WidthVisitor final : public VNVisitor {
}
nodep->replaceWith(newp);
// UINFOTREE(9, newp, "", "apat-out");
VL_DO_DANGLING(pushDeletep(nodep), nodep); // Deletes defaultp also, if present
VL_DO_DANGLING(pushDeletep(nodep), nodep);
}
void patternWildcard(AstPattern* nodep, AstWildcardArrayDType* arrayDtp,
AstPatMember* defaultp) {
@ -5013,7 +5018,7 @@ class WidthVisitor final : public VNVisitor {
}
nodep->replaceWith(newp);
// UINFOTREE(9, newp, "", "apat-out");
VL_DO_DANGLING(pushDeletep(nodep), nodep); // Deletes defaultp also, if present
VL_DO_DANGLING(pushDeletep(nodep), nodep);
}
void patternDynArray(AstPattern* nodep, AstDynArrayDType* arrayp, AstPatMember*) {
AstNode* newp = new AstConsDynArray{nodep->fileline()};
@ -5032,7 +5037,7 @@ class WidthVisitor final : public VNVisitor {
}
nodep->replaceWith(newp);
// UINFOTREE(9, newp, "", "apat-out");
VL_DO_DANGLING(pushDeletep(nodep), nodep); // Deletes defaultp also, if present
VL_DO_DANGLING(pushDeletep(nodep), nodep);
}
void patternQueue(AstPattern* nodep, AstQueueDType* arrayp, AstPatMember*) {
AstNode* newp = new AstConsQueue{nodep->fileline()};
@ -5053,7 +5058,7 @@ class WidthVisitor final : public VNVisitor {
}
nodep->replaceWith(newp);
// UINFOTREE(9, newp, "", "apat-out");
VL_DO_DANGLING(pushDeletep(nodep), nodep); // Deletes defaultp also, if present
VL_DO_DANGLING(pushDeletep(nodep), nodep);
}
void patternBasic(AstPattern* nodep, AstNodeDType* vdtypep, AstPatMember* defaultp) {
const AstBasicDType* bdtypep = VN_AS(vdtypep, BasicDType);
@ -5102,7 +5107,7 @@ class WidthVisitor final : public VNVisitor {
nodep->v3error("Assignment pattern with no members");
}
// UINFOTREE(9, newp, "", "apat-out");
VL_DO_DANGLING(pushDeletep(nodep), nodep); // Deletes defaultp also, if present
VL_DO_DANGLING(pushDeletep(nodep), nodep);
}
AstNodeExpr* patternMemberValueIterate(AstPatMember* patp) {
// Determine values - might be another InitArray
@ -8461,7 +8466,8 @@ class WidthVisitor final : public VNVisitor {
fl_novalue->warnOff(V3ErrorCode::CMPCONST, true);
if (assoc) {
AstVar* const varp = enumVarp(enumDtp, VAttrType::ENUM_VALID, true, 0);
testp = new AstAssocSel{fl_novalue, newVarRefDollarUnit(varp), valp};
testp = new AstAssocSel{fl_novalue, newVarRefDollarUnit(varp),
valp->cloneTreePure(false)};
} else {
const int selwidth = V3Number::log2b(maxval) + 1; // Width to address a bit
AstVar* const varp

View File

@ -30,8 +30,15 @@
// Pick up new lexer
#define yylex PARSEP->tokenToBison
#define BBCOVERIGN(fl, msg) (fl)->v3warn(COVERIGN, msg)
#define BBUNSUP(fl, msg) (fl)->v3warn(E_UNSUPPORTED, msg)
#define DELETE_ALL(...) \
{ \
AstNode* nodeps[] = {__VA_ARGS__}; \
for (AstNode* const nodep : nodeps) \
if (nodep) nodep->deleteTree(); \
}
#define GATEUNSUP(fl, tok) \
{ BBUNSUP((fl), "Unsupported: Verilog 1995 gate primitive: " << (tok)); }
#define RISEFALLDLYUNSUP(nodep) \
@ -3818,16 +3825,16 @@ value_range<nodeExprp>: // ==IEEE: value_range/open_value_range
covergroup_value_range<nodeExprp>: // ==IEEE-2012: covergroup_value_range
cgexpr { $$ = $1; }
| '[' cgexpr ':' cgexpr ']'
{ $$ = nullptr; BBCOVERIGN($1, "Ignoring unsupported: covergroup value range"); }
{ $$ = nullptr; BBCOVERIGN($1, "Ignoring unsupported: covergroup value range"); DELETE_ALL($2, $4); }
// // IEEE-2023: added all four:
// // Skipped as '$' is part of our expr
// // IEEE-2023: '[' '$' ':' cgexpr ']'
// // Skipped as '$' is part of our expr
// // IEEE-2023: '[' cgexpr ':' '$' ']'
| '[' cgexpr yP_PLUSSLASHMINUS cgexpr ']'
{ $$ = nullptr; BBCOVERIGN($1, "Ignoring unsupported: covergroup value range"); }
{ $$ = nullptr; BBCOVERIGN($1, "Ignoring unsupported: covergroup value range"); DELETE_ALL($2, $4); }
| '[' cgexpr yP_PLUSPCTMINUS cgexpr ']'
{ $$ = nullptr; BBCOVERIGN($1, "Ignoring unsupported: covergroup value range"); }
{ $$ = nullptr; BBCOVERIGN($1, "Ignoring unsupported: covergroup value range"); DELETE_ALL($2, $4); }
;
caseCondList<nodeExprp>: // IEEE: part of case_item
@ -5125,6 +5132,7 @@ exprScope<nodeExprp>: // scope and variable for use to inside an e
{ AstParseRef* const anodep = VN_CAST($1, ParseRef);
if (anodep && anodep->name() == "this") {
$$ = new AstParseRef{$<fl>1, VParseRefExp::PX_ROOT, "super"};
$1->deleteTree();
} else {
$$ = $1; $$->v3error("Syntax error: 'super' must be first name component, or after 'this.'");
}
@ -6209,13 +6217,13 @@ concurrent_assertion_statement<nodep>: // ==IEEE: concurrent_assertion_statemen
{ $$ = new AstCover{$1, $4, $6, VAssertType::CONCURRENT}; }
// // IEEE: cover_sequence_statement
| yCOVER ySEQUENCE '(' sexpr ')' stmt
{ $$ = nullptr; BBCOVERIGN($2, "Ignoring unsupported: cover sequence"); }
{ $$ = nullptr; BBCOVERIGN($2, "Ignoring unsupported: cover sequence"); DELETE_ALL($4, $6); }
// // IEEE: yCOVER ySEQUENCE '(' clocking_event sexpr ')' stmt
// // sexpr already includes "clocking_event sexpr"
| yCOVER ySEQUENCE '(' clocking_event yDISABLE yIFF '(' expr/*expression_or_dist*/ ')' sexpr ')' stmt
{ $$ = nullptr; BBCOVERIGN($2, "Ignoring unsupported: cover sequence"); }
{ $$ = nullptr; BBCOVERIGN($2, "Ignoring unsupported: cover sequence"); DELETE_ALL($4, $8, $10, $12);}
| yCOVER ySEQUENCE '(' yDISABLE yIFF '(' expr/*expression_or_dist*/ ')' sexpr ')' stmt
{ $$ = nullptr; BBCOVERIGN($2, "Ignoring unsupported: cover sequence"); }
{ $$ = nullptr; BBCOVERIGN($2, "Ignoring unsupported: cover sequence"); DELETE_ALL($7, $9, $11); }
// // IEEE: restrict_property_statement
| yRESTRICT yPROPERTY '(' property_spec ')' ';'
{ $$ = new AstRestrict{$1, $4}; }
@ -6733,27 +6741,27 @@ coverage_option<nodep>: // ==IEEE: coverage_option
// // option/type_option aren't really keywords
id/*yOPTION | yTYPE_OPTION*/ '.' idAny/*member_identifier*/ '=' expr
{ // TODO: check that 'id' is 'option' or 'type_option'
$$ = nullptr; BBCOVERIGN($<fl>1, "Ignoring unsupported: coverage option"); }
$$ = nullptr; BBCOVERIGN($<fl>1, "Ignoring unsupported: coverage option"); DELETE_ALL($5); }
;
cover_point<nodep>: // ==IEEE: cover_point
// // [ [ data_type_or_implicit ] cover_point_identifier ':' ] yCOVERPOINT
yCOVERPOINT expr iffE bins_or_empty
{ $$ = nullptr; BBCOVERIGN($<fl>1, "Ignoring unsupported: coverpoint"); }
{ $$ = nullptr; BBCOVERIGN($<fl>1, "Ignoring unsupported: coverpoint"); DELETE_ALL($2, $3, $4); }
// // IEEE-2012: class_scope before an ID
| id/*cover_point_id*/ ':' yCOVERPOINT expr iffE bins_or_empty
{ $$ = nullptr; BBCOVERIGN($<fl>3, "Ignoring unsupported: coverpoint"); }
{ $$ = nullptr; BBCOVERIGN($<fl>3, "Ignoring unsupported: coverpoint"); DELETE_ALL($4, $5, $6);}
// // data_type_or_implicit expansion
| data_type id/*cover_point_id*/ ':' yCOVERPOINT expr iffE bins_or_empty
{ $$ = nullptr; BBCOVERIGN($<fl>4, "Ignoring unsupported: coverpoint"); }
{ $$ = nullptr; BBCOVERIGN($<fl>4, "Ignoring unsupported: coverpoint"); DELETE_ALL($1, $5, $6, $7);}
| yVAR data_type id/*cover_point_id*/ ':' yCOVERPOINT expr iffE bins_or_empty
{ $$ = nullptr; BBCOVERIGN($<fl>5, "Ignoring unsupported: coverpoint"); }
{ $$ = nullptr; BBCOVERIGN($<fl>5, "Ignoring unsupported: coverpoint"); DELETE_ALL($2, $6, $7, $8); }
| yVAR implicit_typeE id/*cover_point_id*/ ':' yCOVERPOINT expr iffE bins_or_empty
{ $$ = nullptr; BBCOVERIGN($<fl>5, "Ignoring unsupported: coverpoint"); }
{ $$ = nullptr; BBCOVERIGN($<fl>5, "Ignoring unsupported: coverpoint"); DELETE_ALL($2, $6, $7, $8); }
| signingE rangeList id/*cover_point_id*/ ':' yCOVERPOINT expr iffE bins_or_empty
{ $$ = nullptr; BBCOVERIGN($<fl>5, "Ignoring unsupported: coverpoint"); }
{ $$ = nullptr; BBCOVERIGN($<fl>5, "Ignoring unsupported: coverpoint"); DELETE_ALL($2, $6, $7, $8); }
| signing id/*cover_point_id*/ ':' yCOVERPOINT expr iffE bins_or_empty
{ $$ = nullptr; BBCOVERIGN($<fl>4, "Ignoring unsupported: coverpoint"); }
{ $$ = nullptr; BBCOVERIGN($<fl>4, "Ignoring unsupported: coverpoint"); DELETE_ALL($5, $6, $7); }
// // IEEE-2012:
| bins_or_empty { $$ = $1; }
;
@ -6761,7 +6769,7 @@ cover_point<nodep>: // ==IEEE: cover_point
iffE<nodep>: // IEEE: part of cover_point, others
/* empty */ { $$ = nullptr; }
| yIFF '(' expr ')'
{ $$ = nullptr; BBCOVERIGN($<fl>1, "Ignoring unsupported: cover 'iff'"); }
{ $$ = nullptr; BBCOVERIGN($<fl>1, "Ignoring unsupported: cover 'iff'"); DELETE_ALL($3); }
;
bins_or_empty<nodep>: // ==IEEE: bins_or_empty
@ -6786,24 +6794,24 @@ bins_or_options<nodep>: // ==IEEE: bins_or_options
coverage_option { $$ = $1; }
// // Can't use wildcardE as results in conflicts
| bins_keyword idAny/*bin_identifier*/ bins_orBraE '=' '{' range_list '}' iffE
{ $$ = nullptr; BBCOVERIGN($<fl>4, "Ignoring unsupported: cover bin specification"); }
{ $$ = nullptr; BBCOVERIGN($<fl>4, "Ignoring unsupported: cover bin specification"); DELETE_ALL($3, $6, $8); }
| bins_keyword idAny/*bin_identifier*/ bins_orBraE '=' '{' range_list '}' yWITH__CUR '{' cgexpr '}' iffE
{ $$ = nullptr; BBCOVERIGN($<fl>8, "Ignoring unsupported: cover bin 'with' specification"); }
{ $$ = nullptr; BBCOVERIGN($<fl>8, "Ignoring unsupported: cover bin 'with' specification"); DELETE_ALL($3, $6, $10, $12); }
| yWILDCARD bins_keyword idAny/*bin_identifier*/ bins_orBraE '=' '{' range_list '}' iffE
{ $$ = nullptr; BBCOVERIGN($<fl>5, "Ignoring unsupported: cover bin 'wildcard' specification"); }
{ $$ = nullptr; BBCOVERIGN($<fl>5, "Ignoring unsupported: cover bin 'wildcard' specification"); DELETE_ALL($4, $7, $9); }
| yWILDCARD bins_keyword idAny/*bin_identifier*/ bins_orBraE '=' '{' range_list '}' yWITH__CUR '{' cgexpr '}' iffE
{ $$ = nullptr; BBCOVERIGN($<fl>9, "Ignoring unsupported: cover bin 'wildcard' 'with' specification"); }
{ $$ = nullptr; BBCOVERIGN($<fl>9, "Ignoring unsupported: cover bin 'wildcard' 'with' specification"); DELETE_ALL($4, $7, $11, $13); }
//
// // cgexpr part of trans_list
| bins_keyword idAny/*bin_identifier*/ bins_orBraE '=' trans_list iffE
{ $$ = nullptr; BBCOVERIGN($<fl>4, "Ignoring unsupported: cover bin trans list"); }
{ $$ = nullptr; BBCOVERIGN($<fl>4, "Ignoring unsupported: cover bin trans list"); DELETE_ALL($3, $5, $6); }
| yWILDCARD bins_keyword idAny/*bin_identifier*/ bins_orBraE '=' trans_list iffE
{ $$ = nullptr; BBCOVERIGN($<fl>1, "Ignoring unsupported: cover bin 'wildcard' trans list"); }
{ $$ = nullptr; BBCOVERIGN($<fl>1, "Ignoring unsupported: cover bin 'wildcard' trans list"); DELETE_ALL($4, $6, $7);}
//
| bins_keyword idAny/*bin_identifier*/ bins_orBraE '=' yDEFAULT iffE
{ $$ = nullptr; BBCOVERIGN($<fl>5, "Ignoring unsupported: cover bin 'default'"); }
{ $$ = nullptr; BBCOVERIGN($<fl>5, "Ignoring unsupported: cover bin 'default'"); DELETE_ALL($3, $6); }
| bins_keyword idAny/*bin_identifier*/ bins_orBraE '=' yDEFAULT ySEQUENCE iffE
{ $$ = nullptr; BBCOVERIGN($<fl>6, "Ignoring unsupported: cover bin 'default' 'sequence'"); }
{ $$ = nullptr; BBCOVERIGN($<fl>6, "Ignoring unsupported: cover bin 'default' 'sequence'"); DELETE_ALL($3, $7); }
;
bins_orBraE<nodep>: // IEEE: part of bins_or_options:
@ -6827,23 +6835,23 @@ trans_set<nodep>: // ==IEEE: trans_set
trans_range_list { $$ = $1; }
// // Note the { => } in the grammar, this is really a list
| trans_set yP_EQGT trans_range_list
{ $$ = $1; BBCOVERIGN($<fl>2, "Ignoring unsupported: cover trans set '=>'"); }
{ $$ = $1; BBCOVERIGN($<fl>2, "Ignoring unsupported: cover trans set '=>'"); DELETE_ALL($3); }
;
trans_range_list<nodep>: // ==IEEE: trans_range_list
trans_item { $$ = $1; }
| trans_item yP_BRASTAR cgexpr ']'
{ $$ = nullptr; BBCOVERIGN($<fl>2, "Ignoring unsupported: cover '[*'"); }
{ $$ = nullptr; BBCOVERIGN($<fl>2, "Ignoring unsupported: cover '[*'"); DELETE_ALL($1, $3); }
| trans_item yP_BRASTAR cgexpr ':' cgexpr ']'
{ $$ = nullptr; BBCOVERIGN($<fl>2, "Ignoring unsupported: cover '[*'"); }
{ $$ = nullptr; BBCOVERIGN($<fl>2, "Ignoring unsupported: cover '[*'"); DELETE_ALL($1, $3, $5); }
| trans_item yP_BRAMINUSGT cgexpr ']'
{ $$ = nullptr; BBCOVERIGN($<fl>2, "Ignoring unsupported: cover '[->'"); }
{ $$ = nullptr; BBCOVERIGN($<fl>2, "Ignoring unsupported: cover '[->'"); DELETE_ALL($1, $3); }
| trans_item yP_BRAMINUSGT cgexpr ':' cgexpr ']'
{ $$ = nullptr; BBCOVERIGN($<fl>2, "Ignoring unsupported: cover '[->'"); }
{ $$ = nullptr; BBCOVERIGN($<fl>2, "Ignoring unsupported: cover '[->'"); DELETE_ALL($1, $3, $5); }
| trans_item yP_BRAEQ cgexpr ']'
{ $$ = nullptr; BBCOVERIGN($<fl>2, "Ignoring unsupported: cover '[='"); }
{ $$ = nullptr; BBCOVERIGN($<fl>2, "Ignoring unsupported: cover '[='"); DELETE_ALL($1, $3); }
| trans_item yP_BRAEQ cgexpr ':' cgexpr ']'
{ $$ = nullptr; BBCOVERIGN($<fl>2, "Ignoring unsupported: cover '[='"); }
{ $$ = nullptr; BBCOVERIGN($<fl>2, "Ignoring unsupported: cover '[='"); DELETE_ALL($1, $3, $5); }
;
trans_item<nodep>: // ==IEEE: range_list
@ -6858,9 +6866,9 @@ covergroup_range_list<nodep>: // ==IEEE: covergroup_range_list
cover_cross<nodep>: // ==IEEE: cover_cross
id/*cover_point_identifier*/ ':' yCROSS list_of_cross_items iffE cross_body
{ $$ = nullptr; BBCOVERIGN($<fl>3, "Ignoring unsupported: cover cross"); }
{ $$ = nullptr; BBCOVERIGN($<fl>3, "Ignoring unsupported: cover cross"); DELETE_ALL($4, $5, $6); }
| yCROSS list_of_cross_items iffE cross_body
{ $$ = nullptr; BBCOVERIGN($<fl>1, "Ignoring unsupported: cover cross"); }
{ $$ = nullptr; BBCOVERIGN($<fl>1, "Ignoring unsupported: cover cross"); DELETE_ALL($2, $3, $4); }
;
list_of_cross_items<nodep>: // ==IEEE: list_of_cross_items
@ -6900,24 +6908,24 @@ cross_body_item<nodep>: // ==IEEE: cross_body_item
| coverage_option ';' { $$ = $1; }
// // IEEE: bins_selection
| bins_keyword idAny/*new-bin_identifier*/ '=' select_expression iffE ';'
{ $$ = nullptr; BBCOVERIGN($1, "Ignoring unsupported: coverage cross bin"); }
{ $$ = nullptr; BBCOVERIGN($1, "Ignoring unsupported: coverage cross bin"); DELETE_ALL($4, $5); }
| error ';' { $$ = nullptr; }
;
select_expression<nodep>: // ==IEEE: select_expression
// // IEEE: select_condition expanded here
yBINSOF '(' bins_expression ')'
{ $$ = nullptr; BBCOVERIGN($1, "Ignoring unsupported: coverage select expression 'binsof'"); }
{ $$ = nullptr; BBCOVERIGN($1, "Ignoring unsupported: coverage select expression 'binsof'"); DELETE_ALL($3); }
| '!' yBINSOF '(' bins_expression ')'
{ $$ = nullptr; BBCOVERIGN($1, "Ignoring unsupported: coverage select expression 'binsof'"); }
{ $$ = nullptr; BBCOVERIGN($1, "Ignoring unsupported: coverage select expression 'binsof'"); DELETE_ALL($4); }
| yBINSOF '(' bins_expression ')' yINTERSECT '{' covergroup_range_list '}'
{ $$ = nullptr; BBCOVERIGN($5, "Ignoring unsupported: coverage select expression 'intersect'"); }
{ $$ = nullptr; BBCOVERIGN($5, "Ignoring unsupported: coverage select expression 'intersect'"); DELETE_ALL($3, $7); }
| '!' yBINSOF '(' bins_expression ')' yINTERSECT '{' covergroup_range_list '}' { }
{ $$ = nullptr; BBCOVERIGN($5, "Ignoring unsupported: coverage select expression 'intersect'"); }
{ $$ = nullptr; BBCOVERIGN($5, "Ignoring unsupported: coverage select expression 'intersect'"); DELETE_ALL($4, $8); }
| yWITH__PAREN '(' cgexpr ')'
{ $$ = nullptr; BBCOVERIGN($1, "Ignoring unsupported: coverage select expression with"); }
{ $$ = nullptr; BBCOVERIGN($1, "Ignoring unsupported: coverage select expression with"); DELETE_ALL($3); }
| '!' yWITH__PAREN '(' cgexpr ')'
{ $$ = nullptr; BBCOVERIGN($1, "Ignoring unsupported: coverage select expression with"); }
{ $$ = nullptr; BBCOVERIGN($1, "Ignoring unsupported: coverage select expression with"); DELETE_ALL($4); }
// // IEEE-2012: Need clarification as to precedence
//UNSUP yWITH__PAREN '(' cgexpr ')' yMATCHES cgexpr { }
// // IEEE-2012: Need clarification as to precedence
@ -6925,9 +6933,9 @@ select_expression<nodep>: // ==IEEE: select_expression
//
| '(' select_expression ')' { $$ = $2; }
| select_expression yP_ANDAND select_expression
{ $$ = nullptr; BBCOVERIGN($2, "Ignoring unsupported: coverage select expression '&&'"); }
{ $$ = nullptr; BBCOVERIGN($2, "Ignoring unsupported: coverage select expression '&&'"); DELETE_ALL($1, $3); }
| select_expression yP_OROR select_expression
{ $$ = nullptr; BBCOVERIGN($2, "Ignoring unsupported: coverage select expression '||'"); }
{ $$ = nullptr; BBCOVERIGN($2, "Ignoring unsupported: coverage select expression '||'"); DELETE_ALL($1, $3); }
// // IEEE-2012: cross_identifier
// // Part of covergroup_expression - generic identifier
// // IEEE-2012: Need clarification as to precedence
@ -6939,7 +6947,7 @@ select_expression<nodep>: // ==IEEE: select_expression
//UNSUP cgexpr yMATCHES cgexpr {..}
//UNSUP // Below are all removed
| idAny '(' list_of_argumentsE ')'
{ $$ = nullptr; BBCOVERIGN($<fl>1, "Ignoring unsupported: coverage select function call"); }
{ $$ = nullptr; BBCOVERIGN($<fl>1, "Ignoring unsupported: coverage select function call"); DELETE_ALL($3); }
//UNSUP // Above are all removed, replace with:
;
@ -6954,7 +6962,7 @@ bins_expression<nodep>: // ==IEEE: bins_expression
coverage_eventE<nodep>: // IEEE: [ coverage_event ]
/* empty */ { $$ = nullptr; }
| clocking_event
{ $$ = nullptr; BBCOVERIGN($<fl>1, "Ignoring unsupported: coverage clocking event"); }
{ $$ = nullptr; BBCOVERIGN($<fl>1, "Ignoring unsupported: coverage clocking event"); DELETE_ALL($1); }
| yWITH__ETC yFUNCTION idAny/*"sample"*/ '(' tf_port_listE ')'
{ if (*$3 != "sample") {
$<fl>3->v3error("Coverage sampling function must be named 'sample'");
@ -6964,7 +6972,7 @@ coverage_eventE<nodep>: // IEEE: [ coverage_event ]
}
}
| yP_ATAT '(' block_event_expression ')'
{ $$ = nullptr; BBCOVERIGN($<fl>1, "Ignoring unsupported: coverage '@@' events"); }
{ $$ = nullptr; BBCOVERIGN($<fl>1, "Ignoring unsupported: coverage '@@' events"); DELETE_ALL($3); }
;
block_event_expression<nodep>: // ==IEEE: block_event_expression

View File

@ -15,6 +15,8 @@ import vltest_bootstrap
test.scenarios('vlt')
os.environ["ASAN_OPTIONS"] = "detect_leaks=0"
DEBUG_QUIET = "--debug --debugi 0 --gdbbt --no-dump-tree"
test.run(

View File

@ -16,6 +16,8 @@ import vltest_bootstrap
test.scenarios('vlt')
test.top_filename = "t/t_a1_first_cc.v"
os.environ["ASAN_OPTIONS"] = "detect_leaks=0"
DEBUG_QUIET = "--debug --debugi 0 --gdbbt --no-dump-tree"
test.compile(verilator_flags2=[DEBUG_QUIET, "-sc --trace-vcd"])

View File

@ -11,7 +11,7 @@ import vltest_bootstrap
test.scenarios('vlt')
os.environ["ASAN_OPTIONS"] = "handle_segv=0"
os.environ["ASAN_OPTIONS"] = "handle_segv=0:detect_leaks=0"
test.lint(v_flags=["--debug-sigsegv"], fails=True, sanitize=0)