Fix memory leaks - batch 1 (#6411)
This commit is contained in:
parent
83ff8e13ba
commit
dd11d5a598
|
|
@ -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};
|
||||
|
|
|
|||
|
|
@ -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()},
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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) {
|
||||
|
|
|
|||
|
|
@ -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()};
|
||||
|
|
|
|||
|
|
@ -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 ";
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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(
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
});
|
||||
|
|
|
|||
|
|
@ -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"));
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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); }
|
||||
|
|
|
|||
|
|
@ -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) {
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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(
|
||||
|
|
|
|||
|
|
@ -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"])
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue