Move AST building from parser proper to LinkParse ; simplify Coverpoint construction
Signed-off-by: Matthew Ballance <matt.ballance@gmail.com>
This commit is contained in:
parent
fd6311a74b
commit
45de7acffd
|
|
@ -2721,9 +2721,11 @@ public:
|
|||
void dumpJson(std::ostream& str = std::cout) const override;
|
||||
};
|
||||
class AstCoverCross final : public AstNodeFuncCovItem {
|
||||
// @astgen op1 := itemsp : List[AstCoverpointRef]
|
||||
// @astgen op2 := binsp : List[AstCoverCrossBins]
|
||||
// @astgen op3 := optionsp : List[AstCoverOption]
|
||||
// @astgen op1 := itemsp : List[AstCoverpointRef]
|
||||
// @astgen op2 := binsp : List[AstCoverCrossBins] // post-LinkParse only
|
||||
// @astgen op3 := optionsp : List[AstCoverOption] // post-LinkParse only
|
||||
// @astgen op4 := rawBodyp : List[AstNode] // Parse: raw cross_body items;
|
||||
// // post-LinkParse: empty
|
||||
public:
|
||||
AstCoverCross(FileLine* fl, const string& name, AstCoverpointRef* itemsp)
|
||||
: ASTGEN_SUPER_CoverCross(fl, name) {
|
||||
|
|
@ -2740,9 +2742,12 @@ class AstCoverpoint final : public AstNodeFuncCovItem {
|
|||
// @astgen op3 := iffp : Optional[AstNodeExpr]
|
||||
// @astgen op4 := optionsp : List[AstCoverOption]
|
||||
public:
|
||||
AstCoverpoint(FileLine* fl, const string& name, AstNodeExpr* exprp)
|
||||
AstCoverpoint(FileLine* fl, const string& name, AstNodeExpr* exprp,
|
||||
AstNodeExpr* iffp = nullptr, AstNode* binsp = nullptr)
|
||||
: ASTGEN_SUPER_Coverpoint(fl, name) {
|
||||
this->exprp(exprp);
|
||||
this->iffp(iffp);
|
||||
if (binsp) addBinsp(binsp);
|
||||
}
|
||||
ASTGEN_MEMBERS_AstCoverpoint;
|
||||
void dump(std::ostream& str) const override;
|
||||
|
|
|
|||
|
|
@ -1361,6 +1361,26 @@ class LinkParseVisitor final : public VNVisitor {
|
|||
iterateChildren(nodep);
|
||||
}
|
||||
|
||||
void visit(AstCoverCross* nodep) override {
|
||||
cleanFileline(nodep);
|
||||
// Distribute the parse-time raw cross_body list (rawBodyp, op4) into the
|
||||
// typed binsp and optionsp slots. Nodes are properly in-tree here so
|
||||
// unlinkFrBack() works cleanly with no bison-list hackery.
|
||||
for (AstNode *itemp = nodep->rawBodyp(), *nextp; itemp; itemp = nextp) {
|
||||
nextp = itemp->nextp();
|
||||
itemp->unlinkFrBack();
|
||||
if (AstCoverOption* const optp = VN_CAST(itemp, CoverOption)) {
|
||||
nodep->addOptionsp(optp);
|
||||
} else if (AstCoverCrossBins* const binp = VN_CAST(itemp, CoverCrossBins)) {
|
||||
nodep->addBinsp(binp);
|
||||
} else {
|
||||
// AstCgOptionAssign, AstFunc, and other unsupported items
|
||||
VL_DO_DANGLING(itemp->deleteTree(), itemp);
|
||||
}
|
||||
}
|
||||
iterateChildren(nodep);
|
||||
}
|
||||
|
||||
void visit(AstNode* nodep) override {
|
||||
// Default: Just iterate
|
||||
cleanFileline(nodep);
|
||||
|
|
|
|||
105
src/verilog.y
105
src/verilog.y
|
|
@ -7000,46 +7000,25 @@ coverage_option<nodep>: // ==IEEE: coverage_option
|
|||
cover_point<nodep>: // ==IEEE: cover_point
|
||||
// // [ [ data_type_or_implicit ] cover_point_identifier ':' ] yCOVERPOINT
|
||||
yCOVERPOINT expr iffE bins_or_empty
|
||||
{ AstCoverpoint* const cp = new AstCoverpoint{$<fl>1, "", $2};
|
||||
if ($3) cp->iffp($3);
|
||||
if ($4) cp->addBinsp($4);
|
||||
$$ = cp; }
|
||||
{ $$ = new AstCoverpoint{$<fl>1, "", $2, $3, $4}; }
|
||||
// // 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($5);
|
||||
if ($6) cp->addBinsp($6);
|
||||
$$ = cp; }
|
||||
{ $$ = new AstCoverpoint{$<fl>3, *$1, $4, $5, $6}; }
|
||||
// // 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($6);
|
||||
if ($7) cp->addBinsp($7);
|
||||
$$ = cp;
|
||||
{ $$ = new AstCoverpoint{$<fl>4, *$2, $5, $6, $7};
|
||||
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($7);
|
||||
if ($8) cp->addBinsp($8);
|
||||
$$ = cp;
|
||||
{ $$ = new AstCoverpoint{$<fl>5, *$3, $6, $7, $8};
|
||||
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($7);
|
||||
if ($8) cp->addBinsp($8);
|
||||
$$ = cp;
|
||||
{ $$ = new AstCoverpoint{$<fl>5, *$3, $6, $7, $8};
|
||||
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($7);
|
||||
if ($8) cp->addBinsp($8);
|
||||
$$ = cp;
|
||||
{ $$ = new AstCoverpoint{$<fl>5, *$3, $6, $7, $8};
|
||||
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($6);
|
||||
if ($7) cp->addBinsp($7);
|
||||
$$ = cp; }
|
||||
{ $$ = new AstCoverpoint{$<fl>4, *$2, $5, $6, $7}; }
|
||||
// // IEEE-2012:
|
||||
| bins_or_empty { $$ = $1; }
|
||||
;
|
||||
|
|
@ -7224,40 +7203,7 @@ cover_cross<nodep>: // ==IEEE: cover_cross
|
|||
{
|
||||
AstCoverCross* const nodep = new AstCoverCross{$<fl>3, *$1,
|
||||
VN_AS($4, CoverpointRef)};
|
||||
if ($6) { // cross_body items (options, bins)
|
||||
for (AstNode* itemp = $6; itemp; ) {
|
||||
AstNode* const nextp = itemp->nextp();
|
||||
// Helper: unlink itemp from the standalone bison list.
|
||||
// Head nodes have m_backp==nullptr; use nextp->unlinkFrBackWithNext()
|
||||
// to detach the rest of the list so itemp->m_nextp becomes null.
|
||||
const auto unlinkItem = [&]() {
|
||||
if (itemp->backp()) {
|
||||
itemp->unlinkFrBack();
|
||||
} else if (nextp) {
|
||||
nextp->unlinkFrBackWithNext();
|
||||
}
|
||||
};
|
||||
if (AstCoverOption* optp = VN_CAST(itemp, CoverOption)) {
|
||||
unlinkItem();
|
||||
nodep->addOptionsp(optp);
|
||||
} else if (AstCoverCrossBins* binp = VN_CAST(itemp, CoverCrossBins)) {
|
||||
unlinkItem();
|
||||
nodep->addBinsp(binp);
|
||||
} else if (VN_IS(itemp, CgOptionAssign)) {
|
||||
unlinkItem();
|
||||
VL_DO_DANGLING(itemp->deleteTree(), itemp);
|
||||
} else if (VN_IS(itemp, Func)) {
|
||||
// Function declarations in cross bodies are unsupported
|
||||
// Skip them - they will be deleted when bins expressions referencing
|
||||
// them are deleted via DEL() in the cross_body_item rules
|
||||
} else {
|
||||
// Delete other unsupported items
|
||||
unlinkItem();
|
||||
VL_DO_DANGLING(itemp->deleteTree(), itemp);
|
||||
}
|
||||
itemp = nextp;
|
||||
}
|
||||
}
|
||||
if ($6) nodep->addRawBodyp($6);
|
||||
if ($5) {
|
||||
$5->v3warn(COVERIGN, "Unsupported: 'iff' in coverage cross");
|
||||
VL_DO_DANGLING($5->deleteTree(), $5);
|
||||
|
|
@ -7269,40 +7215,7 @@ cover_cross<nodep>: // ==IEEE: cover_cross
|
|||
AstCoverCross* const nodep = new AstCoverCross{$<fl>1,
|
||||
"__cross" + cvtToStr(GRAMMARP->s_typeImpNum++),
|
||||
VN_AS($2, CoverpointRef)};
|
||||
if ($4) { // cross_body items (options, bins)
|
||||
for (AstNode* itemp = $4; itemp; ) {
|
||||
AstNode* const nextp = itemp->nextp();
|
||||
// Helper: unlink itemp from the standalone bison list.
|
||||
// Head nodes have m_backp==nullptr; use nextp->unlinkFrBackWithNext()
|
||||
// to detach the rest of the list so itemp->m_nextp becomes null.
|
||||
const auto unlinkItem = [&]() {
|
||||
if (itemp->backp()) {
|
||||
itemp->unlinkFrBack();
|
||||
} else if (nextp) {
|
||||
nextp->unlinkFrBackWithNext();
|
||||
}
|
||||
};
|
||||
if (AstCoverOption* optp = VN_CAST(itemp, CoverOption)) {
|
||||
unlinkItem();
|
||||
nodep->addOptionsp(optp);
|
||||
} else if (AstCoverCrossBins* binp = VN_CAST(itemp, CoverCrossBins)) {
|
||||
unlinkItem();
|
||||
nodep->addBinsp(binp);
|
||||
} else if (VN_IS(itemp, CgOptionAssign)) {
|
||||
unlinkItem();
|
||||
VL_DO_DANGLING(itemp->deleteTree(), itemp);
|
||||
} else if (VN_IS(itemp, Func)) {
|
||||
// Function declarations in cross bodies are unsupported
|
||||
// Skip them - they will be deleted when bins expressions referencing
|
||||
// them are deleted via DEL() in the cross_body_item rules
|
||||
} else {
|
||||
// Delete other unsupported items
|
||||
unlinkItem();
|
||||
VL_DO_DANGLING(itemp->deleteTree(), itemp);
|
||||
}
|
||||
itemp = nextp;
|
||||
}
|
||||
}
|
||||
if ($4) nodep->addRawBodyp($4);
|
||||
if ($3) {
|
||||
$3->v3warn(COVERIGN, "Unsupported: 'iff' in coverage cross");
|
||||
VL_DO_DANGLING($3->deleteTree(), $3);
|
||||
|
|
|
|||
Loading…
Reference in New Issue