diff --git a/src/V3Assert.cpp b/src/V3Assert.cpp index 245fe83d1..75cd26822 100644 --- a/src/V3Assert.cpp +++ b/src/V3Assert.cpp @@ -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}; diff --git a/src/V3AssertPre.cpp b/src/V3AssertPre.cpp index 5f413ecaf..b5ac1dacb 100644 --- a/src/V3AssertPre.cpp +++ b/src/V3AssertPre.cpp @@ -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()}, diff --git a/src/V3AstNodes.cpp b/src/V3AstNodes.cpp index 457613dd7..f8d1e84b4 100644 --- a/src/V3AstNodes.cpp +++ b/src/V3AstNodes.cpp @@ -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); diff --git a/src/V3Begin.cpp b/src/V3Begin.cpp index d7f43b0b3..f0e6c42de 100644 --- a/src/V3Begin.cpp +++ b/src/V3Begin.cpp @@ -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) { diff --git a/src/V3Case.cpp b/src/V3Case.cpp index 7af727731..154f81da6 100644 --- a/src/V3Case.cpp +++ b/src/V3Case.cpp @@ -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()}; diff --git a/src/V3EmitCMake.cpp b/src/V3EmitCMake.cpp index 02926abfc..294151bd9 100644 --- a/src/V3EmitCMake.cpp +++ b/src/V3EmitCMake.cpp @@ -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 "; diff --git a/src/V3EmitMk.cpp b/src/V3EmitMk.cpp index 2b5834d0d..2f53903ab 100644 --- a/src/V3EmitMk.cpp +++ b/src/V3EmitMk.cpp @@ -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); } diff --git a/src/V3EmitMkJson.cpp b/src/V3EmitMkJson.cpp index f272a31f4..65507d1f6 100644 --- a/src/V3EmitMkJson.cpp +++ b/src/V3EmitMkJson.cpp @@ -154,7 +154,7 @@ class V3EmitMkJsonEmitter final { std::vector 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( diff --git a/src/V3Expand.cpp b/src/V3Expand.cpp index 12b55af44..fe522db32 100644 --- a/src/V3Expand.cpp +++ b/src/V3Expand.cpp @@ -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); diff --git a/src/V3Force.cpp b/src/V3Force.cpp index 6042033d9..b2365067e 100644 --- a/src/V3Force.cpp +++ b/src/V3Force.cpp @@ -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; }); diff --git a/src/V3Global.cpp b/src/V3Global.cpp index 7847fcbac..a3e208d4d 100644 --- a/src/V3Global.cpp +++ b/src/V3Global.cpp @@ -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")); diff --git a/src/V3HierBlock.cpp b/src/V3HierBlock.cpp index 7b9e621dd..ceb37ce1c 100644 --- a/src/V3HierBlock.cpp +++ b/src/V3HierBlock.cpp @@ -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 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(); } diff --git a/src/V3HierBlock.h b/src/V3HierBlock.h index b06b9639c..d479a5483 100644 --- a/src/V3HierBlock.h +++ b/src/V3HierBlock.h @@ -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; + // TODO: this map is non-deterministic + using HierMap = std::unordered_map; HierMap m_blocks; V3HierBlockPlan() = default; diff --git a/src/V3Inline.cpp b/src/V3Inline.cpp index 9bbe9e384..cdba57ca7 100644 --- a/src/V3Inline.cpp +++ b/src/V3Inline.cpp @@ -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 diff --git a/src/V3Param.cpp b/src/V3Param.cpp index 816121e0e..65842af76 100644 --- a/src/V3Param.cpp +++ b/src/V3Param.cpp @@ -1100,6 +1100,7 @@ class ParamVisitor final : public VNVisitor { std::multimap m_cellps; // Cells left to process (in current module) std::multimap m_workQueue; // Modules left to process std::vector m_paramClasses; // Parameterized classes + std::deque m_strings; // Allocator for temporary strings // Map from AstNodeModule to set of all AstNodeModules that instantiates it. std::unordered_map> m_parentps; @@ -1162,7 +1163,6 @@ class ParamVisitor final : public VNVisitor { if (const string* const genHierNamep = cellp->user2u().to()) { 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); diff --git a/src/V3ParseGrammar.cpp b/src/V3ParseGrammar.cpp index ae76df10b..dfdb9edd7 100644 --- a/src/V3ParseGrammar.cpp +++ b/src/V3ParseGrammar.cpp @@ -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 "<ascii()<<" decl="<m_varDecl.ascii()<<" // io="<m_varIO.ascii()<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); } diff --git a/src/V3Randomize.cpp b/src/V3Randomize.cpp index bb5e1aca2..c3b2d2d46 100644 --- a/src/V3Randomize.cpp +++ b/src/V3Randomize.cpp @@ -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) { diff --git a/src/V3SchedVirtIface.cpp b/src/V3SchedVirtIface.cpp index 67e7d8957..75abdf436 100644 --- a/src/V3SchedVirtIface.cpp +++ b/src/V3SchedVirtIface.cpp @@ -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 diff --git a/src/V3Task.cpp b/src/V3Task.cpp index b45ecf5ae..10f277e3f 100644 --- a/src/V3Task.cpp +++ b/src/V3Task.cpp @@ -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); diff --git a/src/V3Tristate.cpp b/src/V3Tristate.cpp index 2845049f0..889c1911d 100644 --- a/src/V3Tristate.cpp +++ b/src/V3Tristate.cpp @@ -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 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); diff --git a/src/V3Width.cpp b/src/V3Width.cpp index 6eb0552cc..8bdf785f7 100644 --- a/src/V3Width.cpp +++ b/src/V3Width.cpp @@ -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 diff --git a/src/verilog.y b/src/verilog.y index d5448cb1a..4fbbdd836 100644 --- a/src/verilog.y +++ b/src/verilog.y @@ -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: // ==IEEE: value_range/open_value_range covergroup_value_range: // ==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: // IEEE: part of case_item @@ -5125,6 +5132,7 @@ exprScope: // scope and variable for use to inside an e { AstParseRef* const anodep = VN_CAST($1, ParseRef); if (anodep && anodep->name() == "this") { $$ = new AstParseRef{$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: // ==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: // ==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($1, "Ignoring unsupported: coverage option"); } + $$ = nullptr; BBCOVERIGN($1, "Ignoring unsupported: coverage option"); DELETE_ALL($5); } ; cover_point: // ==IEEE: cover_point // // [ [ data_type_or_implicit ] cover_point_identifier ':' ] yCOVERPOINT yCOVERPOINT expr iffE bins_or_empty - { $$ = nullptr; BBCOVERIGN($1, "Ignoring unsupported: coverpoint"); } + { $$ = nullptr; BBCOVERIGN($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($3, "Ignoring unsupported: coverpoint"); } + { $$ = nullptr; BBCOVERIGN($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($4, "Ignoring unsupported: coverpoint"); } + { $$ = nullptr; BBCOVERIGN($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($5, "Ignoring unsupported: coverpoint"); } + { $$ = nullptr; BBCOVERIGN($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($5, "Ignoring unsupported: coverpoint"); } + { $$ = nullptr; BBCOVERIGN($5, "Ignoring unsupported: coverpoint"); DELETE_ALL($2, $6, $7, $8); } | signingE rangeList id/*cover_point_id*/ ':' yCOVERPOINT expr iffE bins_or_empty - { $$ = nullptr; BBCOVERIGN($5, "Ignoring unsupported: coverpoint"); } + { $$ = nullptr; BBCOVERIGN($5, "Ignoring unsupported: coverpoint"); DELETE_ALL($2, $6, $7, $8); } | signing id/*cover_point_id*/ ':' yCOVERPOINT expr iffE bins_or_empty - { $$ = nullptr; BBCOVERIGN($4, "Ignoring unsupported: coverpoint"); } + { $$ = nullptr; BBCOVERIGN($4, "Ignoring unsupported: coverpoint"); DELETE_ALL($5, $6, $7); } // // IEEE-2012: | bins_or_empty { $$ = $1; } ; @@ -6761,7 +6769,7 @@ cover_point: // ==IEEE: cover_point iffE: // IEEE: part of cover_point, others /* empty */ { $$ = nullptr; } | yIFF '(' expr ')' - { $$ = nullptr; BBCOVERIGN($1, "Ignoring unsupported: cover 'iff'"); } + { $$ = nullptr; BBCOVERIGN($1, "Ignoring unsupported: cover 'iff'"); DELETE_ALL($3); } ; bins_or_empty: // ==IEEE: bins_or_empty @@ -6786,24 +6794,24 @@ bins_or_options: // ==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($4, "Ignoring unsupported: cover bin specification"); } + { $$ = nullptr; BBCOVERIGN($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($8, "Ignoring unsupported: cover bin 'with' specification"); } + { $$ = nullptr; BBCOVERIGN($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($5, "Ignoring unsupported: cover bin 'wildcard' specification"); } + { $$ = nullptr; BBCOVERIGN($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($9, "Ignoring unsupported: cover bin 'wildcard' 'with' specification"); } + { $$ = nullptr; BBCOVERIGN($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($4, "Ignoring unsupported: cover bin trans list"); } + { $$ = nullptr; BBCOVERIGN($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($1, "Ignoring unsupported: cover bin 'wildcard' trans list"); } + { $$ = nullptr; BBCOVERIGN($1, "Ignoring unsupported: cover bin 'wildcard' trans list"); DELETE_ALL($4, $6, $7);} // | bins_keyword idAny/*bin_identifier*/ bins_orBraE '=' yDEFAULT iffE - { $$ = nullptr; BBCOVERIGN($5, "Ignoring unsupported: cover bin 'default'"); } + { $$ = nullptr; BBCOVERIGN($5, "Ignoring unsupported: cover bin 'default'"); DELETE_ALL($3, $6); } | bins_keyword idAny/*bin_identifier*/ bins_orBraE '=' yDEFAULT ySEQUENCE iffE - { $$ = nullptr; BBCOVERIGN($6, "Ignoring unsupported: cover bin 'default' 'sequence'"); } + { $$ = nullptr; BBCOVERIGN($6, "Ignoring unsupported: cover bin 'default' 'sequence'"); DELETE_ALL($3, $7); } ; bins_orBraE: // IEEE: part of bins_or_options: @@ -6827,23 +6835,23 @@ trans_set: // ==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($2, "Ignoring unsupported: cover trans set '=>'"); } + { $$ = $1; BBCOVERIGN($2, "Ignoring unsupported: cover trans set '=>'"); DELETE_ALL($3); } ; trans_range_list: // ==IEEE: trans_range_list trans_item { $$ = $1; } | trans_item yP_BRASTAR cgexpr ']' - { $$ = nullptr; BBCOVERIGN($2, "Ignoring unsupported: cover '[*'"); } + { $$ = nullptr; BBCOVERIGN($2, "Ignoring unsupported: cover '[*'"); DELETE_ALL($1, $3); } | trans_item yP_BRASTAR cgexpr ':' cgexpr ']' - { $$ = nullptr; BBCOVERIGN($2, "Ignoring unsupported: cover '[*'"); } + { $$ = nullptr; BBCOVERIGN($2, "Ignoring unsupported: cover '[*'"); DELETE_ALL($1, $3, $5); } | trans_item yP_BRAMINUSGT cgexpr ']' - { $$ = nullptr; BBCOVERIGN($2, "Ignoring unsupported: cover '[->'"); } + { $$ = nullptr; BBCOVERIGN($2, "Ignoring unsupported: cover '[->'"); DELETE_ALL($1, $3); } | trans_item yP_BRAMINUSGT cgexpr ':' cgexpr ']' - { $$ = nullptr; BBCOVERIGN($2, "Ignoring unsupported: cover '[->'"); } + { $$ = nullptr; BBCOVERIGN($2, "Ignoring unsupported: cover '[->'"); DELETE_ALL($1, $3, $5); } | trans_item yP_BRAEQ cgexpr ']' - { $$ = nullptr; BBCOVERIGN($2, "Ignoring unsupported: cover '[='"); } + { $$ = nullptr; BBCOVERIGN($2, "Ignoring unsupported: cover '[='"); DELETE_ALL($1, $3); } | trans_item yP_BRAEQ cgexpr ':' cgexpr ']' - { $$ = nullptr; BBCOVERIGN($2, "Ignoring unsupported: cover '[='"); } + { $$ = nullptr; BBCOVERIGN($2, "Ignoring unsupported: cover '[='"); DELETE_ALL($1, $3, $5); } ; trans_item: // ==IEEE: range_list @@ -6858,9 +6866,9 @@ covergroup_range_list: // ==IEEE: covergroup_range_list cover_cross: // ==IEEE: cover_cross id/*cover_point_identifier*/ ':' yCROSS list_of_cross_items iffE cross_body - { $$ = nullptr; BBCOVERIGN($3, "Ignoring unsupported: cover cross"); } + { $$ = nullptr; BBCOVERIGN($3, "Ignoring unsupported: cover cross"); DELETE_ALL($4, $5, $6); } | yCROSS list_of_cross_items iffE cross_body - { $$ = nullptr; BBCOVERIGN($1, "Ignoring unsupported: cover cross"); } + { $$ = nullptr; BBCOVERIGN($1, "Ignoring unsupported: cover cross"); DELETE_ALL($2, $3, $4); } ; list_of_cross_items: // ==IEEE: list_of_cross_items @@ -6900,24 +6908,24 @@ cross_body_item: // ==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: // ==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: // ==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: // ==IEEE: select_expression //UNSUP cgexpr yMATCHES cgexpr {..} //UNSUP // Below are all removed | idAny '(' list_of_argumentsE ')' - { $$ = nullptr; BBCOVERIGN($1, "Ignoring unsupported: coverage select function call"); } + { $$ = nullptr; BBCOVERIGN($1, "Ignoring unsupported: coverage select function call"); DELETE_ALL($3); } //UNSUP // Above are all removed, replace with: ; @@ -6954,7 +6962,7 @@ bins_expression: // ==IEEE: bins_expression coverage_eventE: // IEEE: [ coverage_event ] /* empty */ { $$ = nullptr; } | clocking_event - { $$ = nullptr; BBCOVERIGN($1, "Ignoring unsupported: coverage clocking event"); } + { $$ = nullptr; BBCOVERIGN($1, "Ignoring unsupported: coverage clocking event"); DELETE_ALL($1); } | yWITH__ETC yFUNCTION idAny/*"sample"*/ '(' tf_port_listE ')' { if (*$3 != "sample") { $3->v3error("Coverage sampling function must be named 'sample'"); @@ -6964,7 +6972,7 @@ coverage_eventE: // IEEE: [ coverage_event ] } } | yP_ATAT '(' block_event_expression ')' - { $$ = nullptr; BBCOVERIGN($1, "Ignoring unsupported: coverage '@@' events"); } + { $$ = nullptr; BBCOVERIGN($1, "Ignoring unsupported: coverage '@@' events"); DELETE_ALL($3); } ; block_event_expression: // ==IEEE: block_event_expression diff --git a/test_regress/t/t_a1_first_cc.py b/test_regress/t/t_a1_first_cc.py index b56027489..ef2fc199d 100755 --- a/test_regress/t/t_a1_first_cc.py +++ b/test_regress/t/t_a1_first_cc.py @@ -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( diff --git a/test_regress/t/t_a2_first_sc.py b/test_regress/t/t_a2_first_sc.py index b970d2fbc..21e7254e0 100755 --- a/test_regress/t/t_a2_first_sc.py +++ b/test_regress/t/t_a2_first_sc.py @@ -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"]) diff --git a/test_regress/t/t_debug_sigsegv_bad.py b/test_regress/t/t_debug_sigsegv_bad.py index f57f79ad5..f13ae0816 100755 --- a/test_regress/t/t_debug_sigsegv_bad.py +++ b/test_regress/t/t_debug_sigsegv_bad.py @@ -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)