Cleanup mis-merge ; move initial Ast manipulation out of Grammar
Signed-off-by: Matthew Ballance <matt.ballance@gmail.com>
This commit is contained in:
parent
94a65f8e64
commit
8eb03568fd
|
|
@ -2737,7 +2737,7 @@ public:
|
|||
};
|
||||
class AstCoverpoint final : public AstNodeFuncCovItem {
|
||||
// @astgen op1 := exprp : AstNodeExpr
|
||||
// @astgen op2 := binsp : List[AstCoverBin]
|
||||
// @astgen op2 := binsp : List[AstNode] // Parse: mixed AstCoverBin/AstCgOptionAssign; post-LinkParse: AstCoverBin only
|
||||
// @astgen op3 := iffp : Optional[AstNodeExpr]
|
||||
// @astgen op4 := optionsp : List[AstCoverOption]
|
||||
public:
|
||||
|
|
|
|||
|
|
@ -227,12 +227,6 @@ class EmitVBaseVisitorConst VL_NOT_FINAL : public VNVisitorConst {
|
|||
iterateAndNextConstNull(nodep->rhsp());
|
||||
if (!m_suppressSemi) puts(";\n");
|
||||
}
|
||||
void visit(AstAssignDly* nodep) override {
|
||||
iterateAndNextConstNull(nodep->lhsp());
|
||||
putfs(nodep, " <= ");
|
||||
iterateAndNextConstNull(nodep->rhsp());
|
||||
puts(";\n");
|
||||
}
|
||||
void visit(AstAlias* nodep) override {
|
||||
putbs("alias ");
|
||||
iterateConst(nodep->itemsp());
|
||||
|
|
|
|||
|
|
@ -1327,6 +1327,40 @@ class LinkParseVisitor final : public VNVisitor {
|
|||
iterate(cgClassp);
|
||||
}
|
||||
|
||||
void visit(AstCoverpoint* nodep) override {
|
||||
cleanFileline(nodep);
|
||||
// Re-sort the parse-time mixed bins list (AstCoverBin + AstCgOptionAssign)
|
||||
// into the typed binsp and optionsp slots. The grammar attaches both node types
|
||||
// to binsp (op2) as a raw List[AstNode]; now that they are properly parented we
|
||||
// can iterate and split them without any temporary-parent tricks.
|
||||
for (AstNode *itemp = nodep->binsp(), *nextp; itemp; itemp = nextp) {
|
||||
nextp = itemp->nextp();
|
||||
if (AstCgOptionAssign* const optp = VN_CAST(itemp, CgOptionAssign)) {
|
||||
optp->unlinkFrBack();
|
||||
VCoverOptionType optType = VCoverOptionType::COMMENT;
|
||||
if (optp->name() == "at_least") {
|
||||
optType = VCoverOptionType::AT_LEAST;
|
||||
} else if (optp->name() == "weight") {
|
||||
optType = VCoverOptionType::WEIGHT;
|
||||
} else if (optp->name() == "goal") {
|
||||
optType = VCoverOptionType::GOAL;
|
||||
} else if (optp->name() == "auto_bin_max") {
|
||||
optType = VCoverOptionType::AUTO_BIN_MAX;
|
||||
} else if (optp->name() == "per_instance") {
|
||||
optType = VCoverOptionType::PER_INSTANCE;
|
||||
} else if (optp->name() == "comment") {
|
||||
optType = VCoverOptionType::COMMENT;
|
||||
} else {
|
||||
optp->v3warn(COVERIGN, "Ignoring unsupported coverage option: " + optp->name());
|
||||
}
|
||||
nodep->addOptionsp(
|
||||
new AstCoverOption{optp->fileline(), optType, optp->valuep()->cloneTree(false)});
|
||||
VL_DO_DANGLING(optp->deleteTree(), optp);
|
||||
}
|
||||
}
|
||||
iterateChildren(nodep);
|
||||
}
|
||||
|
||||
void visit(AstNode* nodep) override {
|
||||
// Default: Just iterate
|
||||
cleanFileline(nodep);
|
||||
|
|
|
|||
|
|
@ -295,6 +295,8 @@ class CodeMotionAnalysisVisitor final : public VNVisitorConst {
|
|||
iterateChildrenConst(nodep);
|
||||
}
|
||||
|
||||
// VISITORS
|
||||
|
||||
void visit(AstNode* nodep) override {
|
||||
// Push a new stack entry at the start of a list, but only if the list is not a
|
||||
// single element (this saves a lot of allocations in expressions)
|
||||
|
|
|
|||
|
|
@ -96,66 +96,6 @@ public:
|
|||
nodep->trace(singletonp()->allTracingOn(fileline));
|
||||
return nodep;
|
||||
}
|
||||
// Helper to move bins from parser list to coverpoint
|
||||
void addCoverpointBins(AstCoverpoint* cp, AstNode* binsList) {
|
||||
if (!binsList) return;
|
||||
|
||||
// CRITICAL FIX: The parser creates a linked list of bins. When we try to move them
|
||||
// to the coverpoint one by one while they're still linked, the addNext() logic
|
||||
// that updates headtailp pointers creates circular references. We must fully
|
||||
// unlink ALL bins before adding ANY to the coverpoint.
|
||||
std::vector<AstCoverBin*> bins;
|
||||
std::vector<AstCoverOption*> options;
|
||||
|
||||
// To unlink the head node (which has no backp), create a temporary parent
|
||||
AstBegin* tempParent = new AstBegin{binsList->fileline(), "[TEMP]", nullptr, true};
|
||||
tempParent->addStmtsp(binsList); // Now binsList has a backp
|
||||
|
||||
// Now unlink all bins - they all have backp now
|
||||
for (AstNode *binp = binsList, *nextp; binp; binp = nextp) {
|
||||
nextp = binp->nextp();
|
||||
|
||||
if (AstCoverBin* cbinp = VN_CAST(binp, CoverBin)) {
|
||||
cbinp->unlinkFrBack(); // Now this works for all bins including head
|
||||
bins.push_back(cbinp);
|
||||
} else if (AstCgOptionAssign* optp = VN_CAST(binp, CgOptionAssign)) {
|
||||
optp->unlinkFrBack();
|
||||
// Convert AstCgOptionAssign to AstCoverOption
|
||||
VCoverOptionType optType = VCoverOptionType::COMMENT; // default
|
||||
if (optp->name() == "at_least") {
|
||||
optType = VCoverOptionType::AT_LEAST;
|
||||
} else if (optp->name() == "weight") {
|
||||
optType = VCoverOptionType::WEIGHT;
|
||||
} else if (optp->name() == "goal") {
|
||||
optType = VCoverOptionType::GOAL;
|
||||
} else if (optp->name() == "auto_bin_max") {
|
||||
optType = VCoverOptionType::AUTO_BIN_MAX;
|
||||
} else if (optp->name() == "per_instance") {
|
||||
optType = VCoverOptionType::PER_INSTANCE;
|
||||
} else if (optp->name() == "comment") {
|
||||
optType = VCoverOptionType::COMMENT;
|
||||
} else {
|
||||
optp->v3warn(COVERIGN,
|
||||
"Ignoring unsupported coverage option: " + optp->name());
|
||||
}
|
||||
AstCoverOption* coverOptp = new AstCoverOption{optp->fileline(), optType,
|
||||
optp->valuep()->cloneTree(false)};
|
||||
options.push_back(coverOptp);
|
||||
VL_DO_DANGLING(optp->deleteTree(), optp);
|
||||
} else {
|
||||
binp->v3warn(COVERIGN,
|
||||
"Unexpected node in bins list, ignoring"); // LCOV_EXCL_LINE
|
||||
VL_DO_DANGLING(binp->deleteTree(), binp);
|
||||
}
|
||||
}
|
||||
|
||||
// Delete the temporary parent
|
||||
VL_DO_DANGLING(tempParent->deleteTree(), tempParent);
|
||||
|
||||
// Now add standalone bins and options to coverpoint
|
||||
for (AstCoverBin* cbinp : bins) { cp->addBinsp(cbinp); }
|
||||
for (AstCoverOption* optp : options) { cp->addOptionsp(optp); }
|
||||
}
|
||||
AstDisplay* createDisplayError(FileLine* fileline) {
|
||||
AstDisplay* nodep = new AstDisplay{fileline, VDisplayType::DT_ERROR, "", nullptr, nullptr};
|
||||
AstNode::addNext<AstNode, AstNode>(nodep, new AstStop{fileline, false});
|
||||
|
|
|
|||
|
|
@ -7001,43 +7001,43 @@ cover_point<nodep>: // ==IEEE: cover_point
|
|||
yCOVERPOINT expr iffE bins_or_empty
|
||||
{ AstCoverpoint* const cp = new AstCoverpoint{$<fl>1, "", $2};
|
||||
if ($3) cp->iffp(VN_AS($3, NodeExpr));
|
||||
GRAMMARP->addCoverpointBins(cp, $4);
|
||||
if ($4) cp->addBinsp($4);
|
||||
$$ = cp; }
|
||||
// // IEEE-2012: class_scope before an ID
|
||||
| id/*cover_point_id*/ ':' yCOVERPOINT expr iffE bins_or_empty
|
||||
{ AstCoverpoint* const cp = new AstCoverpoint{$<fl>3, *$1, $4};
|
||||
if ($5) cp->iffp(VN_AS($5, NodeExpr));
|
||||
GRAMMARP->addCoverpointBins(cp, $6);
|
||||
if ($6) cp->addBinsp($6);
|
||||
$$ = cp; }
|
||||
// // data_type_or_implicit expansion
|
||||
| data_type id/*cover_point_id*/ ':' yCOVERPOINT expr iffE bins_or_empty
|
||||
{ AstCoverpoint* const cp = new AstCoverpoint{$<fl>4, *$2, $5};
|
||||
if ($6) cp->iffp(VN_AS($6, NodeExpr));
|
||||
GRAMMARP->addCoverpointBins(cp, $7);
|
||||
if ($7) cp->addBinsp($7);
|
||||
$$ = cp;
|
||||
DEL($1); }
|
||||
| yVAR data_type id/*cover_point_id*/ ':' yCOVERPOINT expr iffE bins_or_empty
|
||||
{ AstCoverpoint* const cp = new AstCoverpoint{$<fl>5, *$3, $6};
|
||||
if ($7) cp->iffp(VN_AS($7, NodeExpr));
|
||||
GRAMMARP->addCoverpointBins(cp, $8);
|
||||
if ($8) cp->addBinsp($8);
|
||||
$$ = cp;
|
||||
DEL($2); }
|
||||
| yVAR implicit_typeE id/*cover_point_id*/ ':' yCOVERPOINT expr iffE bins_or_empty
|
||||
{ AstCoverpoint* const cp = new AstCoverpoint{$<fl>5, *$3, $6};
|
||||
if ($7) cp->iffp(VN_AS($7, NodeExpr));
|
||||
GRAMMARP->addCoverpointBins(cp, $8);
|
||||
if ($8) cp->addBinsp($8);
|
||||
$$ = cp;
|
||||
DEL($2); }
|
||||
| signingE rangeList id/*cover_point_id*/ ':' yCOVERPOINT expr iffE bins_or_empty
|
||||
{ AstCoverpoint* const cp = new AstCoverpoint{$<fl>5, *$3, $6};
|
||||
if ($7) cp->iffp(VN_AS($7, NodeExpr));
|
||||
GRAMMARP->addCoverpointBins(cp, $8);
|
||||
if ($8) cp->addBinsp($8);
|
||||
$$ = cp;
|
||||
DEL($2); }
|
||||
| signing id/*cover_point_id*/ ':' yCOVERPOINT expr iffE bins_or_empty
|
||||
{ AstCoverpoint* const cp = new AstCoverpoint{$<fl>4, *$2, $5};
|
||||
if ($6) cp->iffp(VN_AS($6, NodeExpr));
|
||||
GRAMMARP->addCoverpointBins(cp, $7);
|
||||
if ($7) cp->addBinsp($7);
|
||||
$$ = cp; }
|
||||
// // IEEE-2012:
|
||||
| bins_or_empty { $$ = $1; }
|
||||
|
|
|
|||
Loading…
Reference in New Issue