Parser clean-up
Signed-off-by: Matthew Ballance <matt.ballance@gmail.com>
This commit is contained in:
parent
42debebb07
commit
8860ad4b3e
|
|
@ -129,10 +129,10 @@ verilator_coverage Arguments
|
|||
.. option:: --filter-type <regex>
|
||||
|
||||
Skips records of coverage types that matches with <regex>
|
||||
Possible values are `toggle`, `line`, `branch`, `expr`, `funccov`, `user` and
|
||||
Possible values are `toggle`, `line`, `branch`, `expr`, `covergroup`, `user` and
|
||||
a wildcard with `\*` or `?`. The default value is `\*`.
|
||||
|
||||
The `funccov` type represents SystemVerilog functional coverage including
|
||||
The `covergroup` type represents SystemVerilog functional coverage including
|
||||
covergroups, coverpoints, bins, and cross coverage as defined in IEEE
|
||||
1800-2023 Section 19.
|
||||
|
||||
|
|
|
|||
|
|
@ -1157,13 +1157,17 @@ class AstCovergroup final : public AstNode {
|
|||
// @astgen op1 := argsp : List[AstVar]
|
||||
// @astgen op2 := membersp : List[AstNode]
|
||||
// @astgen op3 := eventp : Optional[AstSenTree]
|
||||
// @astgen op4 := sampleArgsp : List[AstVar]
|
||||
string m_name;
|
||||
bool m_isClass = false;
|
||||
|
||||
public:
|
||||
AstCovergroup(FileLine* fl, const string& name, AstNode* membersp, AstSenTree* eventp)
|
||||
AstCovergroup(FileLine* fl, const string& name, AstVar* argsp, AstVar* sampleArgsp,
|
||||
AstNode* membersp, AstSenTree* eventp)
|
||||
: ASTGEN_SUPER_Covergroup(fl)
|
||||
, m_name{name} {
|
||||
if (argsp) addArgsp(argsp);
|
||||
if (sampleArgsp) addSampleArgsp(sampleArgsp);
|
||||
if (membersp) addMembersp(membersp);
|
||||
this->eventp(eventp);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1006,6 +1006,213 @@ class LinkParseVisitor final : public VNVisitor {
|
|||
iterateChildren(nodep);
|
||||
}
|
||||
|
||||
// Create boilerplate covergroup methods on the given AstClass.
|
||||
// argsp/sampleArgsp are the raw arg lists still owned by the caller; they are iterated
|
||||
// (cloned) but not deleted here.
|
||||
static void createCovergroupMethods(AstClass* nodep, AstNode* argsp, AstNode* sampleArgsp) {
|
||||
// Hidden static to take unspecified reference argument results
|
||||
AstVar* const defaultVarp
|
||||
= new AstVar{nodep->fileline(), VVarType::MEMBER, "__Vint", nodep->findIntDType()};
|
||||
defaultVarp->lifetime(VLifetime::STATIC_EXPLICIT);
|
||||
nodep->addStmtsp(defaultVarp);
|
||||
|
||||
// Handle constructor arguments - add function parameters and assignments
|
||||
if (argsp) {
|
||||
// Find the 'new' function to add parameters to
|
||||
AstFunc* newFuncp = nullptr;
|
||||
for (AstNode* memberp = nodep->membersp(); memberp; memberp = memberp->nextp()) {
|
||||
if (AstFunc* const funcp = VN_CAST(memberp, Func)) {
|
||||
if (funcp->name() == "new") {
|
||||
newFuncp = funcp;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (newFuncp) {
|
||||
// Save the existing body statements and unlink them
|
||||
AstNode* const existingBodyp = newFuncp->stmtsp();
|
||||
if (existingBodyp) existingBodyp->unlinkFrBackWithNext();
|
||||
// Add function parameters and assignments
|
||||
for (AstNode* argp = argsp; argp; argp = argp->nextp()) {
|
||||
if (AstVar* const origVarp = VN_CAST(argp, Var)) {
|
||||
AstVar* const paramp = origVarp->cloneTree(false);
|
||||
paramp->funcLocal(true);
|
||||
paramp->direction(VDirection::INPUT);
|
||||
newFuncp->addStmtsp(paramp);
|
||||
AstNodeExpr* const lhsp
|
||||
= new AstParseRef{origVarp->fileline(), origVarp->name()};
|
||||
AstNodeExpr* const rhsp
|
||||
= new AstParseRef{paramp->fileline(), paramp->name()};
|
||||
newFuncp->addStmtsp(new AstAssign{origVarp->fileline(), lhsp, rhsp});
|
||||
}
|
||||
}
|
||||
if (existingBodyp) newFuncp->addStmtsp(existingBodyp);
|
||||
}
|
||||
}
|
||||
|
||||
// IEEE: option
|
||||
{
|
||||
v3Global.setUsesStdPackage();
|
||||
AstVar* const varp
|
||||
= new AstVar{nodep->fileline(), VVarType::MEMBER, "option", VFlagChildDType{},
|
||||
new AstRefDType{nodep->fileline(), "vl_covergroup_options_t",
|
||||
new AstClassOrPackageRef{nodep->fileline(), "std",
|
||||
nullptr, nullptr},
|
||||
nullptr}};
|
||||
nodep->addMembersp(varp);
|
||||
}
|
||||
|
||||
// IEEE: type_option
|
||||
{
|
||||
v3Global.setUsesStdPackage();
|
||||
AstVar* const varp
|
||||
= new AstVar{nodep->fileline(), VVarType::MEMBER, "type_option", VFlagChildDType{},
|
||||
new AstRefDType{nodep->fileline(), "vl_covergroup_type_options_t",
|
||||
new AstClassOrPackageRef{nodep->fileline(), "std",
|
||||
nullptr, nullptr},
|
||||
nullptr}};
|
||||
nodep->addMembersp(varp);
|
||||
}
|
||||
|
||||
// IEEE: function void sample([arguments])
|
||||
{
|
||||
AstFunc* const funcp = new AstFunc{nodep->fileline(), "sample", nullptr, nullptr};
|
||||
if (sampleArgsp) {
|
||||
for (AstNode* argp = sampleArgsp; argp; argp = argp->nextp()) {
|
||||
if (AstVar* const origVarp = VN_CAST(argp, Var)) {
|
||||
AstVar* const paramp = origVarp->cloneTree(false);
|
||||
paramp->funcLocal(true);
|
||||
paramp->direction(VDirection::INPUT);
|
||||
funcp->addStmtsp(paramp);
|
||||
AstNodeExpr* const lhsp
|
||||
= new AstParseRef{origVarp->fileline(), origVarp->name()};
|
||||
AstNodeExpr* const rhsp
|
||||
= new AstParseRef{paramp->fileline(), paramp->name()};
|
||||
funcp->addStmtsp(new AstAssign{origVarp->fileline(), lhsp, rhsp});
|
||||
}
|
||||
}
|
||||
}
|
||||
funcp->classMethod(true);
|
||||
funcp->dtypep(funcp->findVoidDType());
|
||||
nodep->addMembersp(funcp);
|
||||
}
|
||||
|
||||
// IEEE: function void start(), void stop()
|
||||
for (const string& name : {"start"s, "stop"s}) {
|
||||
AstFunc* const funcp = new AstFunc{nodep->fileline(), name, nullptr, nullptr};
|
||||
funcp->classMethod(true);
|
||||
funcp->dtypep(funcp->findVoidDType());
|
||||
nodep->addMembersp(funcp);
|
||||
}
|
||||
|
||||
// IEEE: static function real get_coverage(optional ref int, optional ref int)
|
||||
// IEEE: function real get_inst_coverage(optional ref int, optional ref int)
|
||||
for (const string& name : {"get_coverage"s, "get_inst_coverage"s}) {
|
||||
AstFunc* const funcp = new AstFunc{nodep->fileline(), name, nullptr, nullptr};
|
||||
funcp->fileline()->warnOff(V3ErrorCode::NORETURN, true);
|
||||
funcp->isStatic(name == "get_coverage");
|
||||
funcp->classMethod(true);
|
||||
funcp->dtypep(funcp->findVoidDType());
|
||||
nodep->addMembersp(funcp);
|
||||
{
|
||||
AstVar* const varp = new AstVar{nodep->fileline(), VVarType::MEMBER, name,
|
||||
nodep->findDoubleDType()};
|
||||
varp->lifetime(VLifetime::AUTOMATIC_EXPLICIT);
|
||||
varp->funcLocal(true);
|
||||
varp->direction(VDirection::OUTPUT);
|
||||
varp->funcReturn(true);
|
||||
funcp->fvarp(varp);
|
||||
}
|
||||
for (const string& varname : {"covered_bins"s, "total_bins"s}) {
|
||||
AstVar* const varp = new AstVar{nodep->fileline(), VVarType::MEMBER, varname,
|
||||
nodep->findStringDType()};
|
||||
varp->lifetime(VLifetime::AUTOMATIC_EXPLICIT);
|
||||
varp->funcLocal(true);
|
||||
varp->direction(VDirection::INPUT);
|
||||
varp->valuep(new AstVarRef{nodep->fileline(), defaultVarp, VAccess::READ});
|
||||
funcp->addStmtsp(varp);
|
||||
}
|
||||
}
|
||||
|
||||
// IEEE: function void set_inst_name(string)
|
||||
{
|
||||
AstFunc* const funcp
|
||||
= new AstFunc{nodep->fileline(), "set_inst_name", nullptr, nullptr};
|
||||
funcp->classMethod(true);
|
||||
funcp->dtypep(funcp->findVoidDType());
|
||||
nodep->addMembersp(funcp);
|
||||
AstVar* const varp = new AstVar{nodep->fileline(), VVarType::MEMBER, "name",
|
||||
nodep->findStringDType()};
|
||||
varp->lifetime(VLifetime::AUTOMATIC_EXPLICIT);
|
||||
varp->funcLocal(true);
|
||||
varp->direction(VDirection::INPUT);
|
||||
funcp->addStmtsp(varp);
|
||||
}
|
||||
}
|
||||
|
||||
void visit(AstCovergroup* nodep) override {
|
||||
// Transform raw parse-time AstCovergroup into a fully-formed AstClass
|
||||
cleanFileline(nodep);
|
||||
|
||||
const string libname = m_modp ? m_modp->libname() : "";
|
||||
AstClass* const cgClassp = new AstClass{nodep->fileline(), nodep->name(), libname};
|
||||
cgClassp->isCovergroup(true);
|
||||
v3Global.useCovergroup(true);
|
||||
|
||||
// Clocking event: unlink before deleteTree, attach as AstCovergroup child on class
|
||||
if (AstSenTree* const eventp = nodep->eventp()) {
|
||||
eventp->unlinkFrBack();
|
||||
AstCovergroup* const cgNodep
|
||||
= new AstCovergroup{nodep->fileline(), nodep->name(),
|
||||
nullptr, nullptr, nullptr, eventp};
|
||||
cgClassp->addMembersp(cgNodep);
|
||||
}
|
||||
|
||||
// Convert constructor args to member variables
|
||||
for (AstNode* argp = nodep->argsp(); argp; argp = argp->nextp()) {
|
||||
if (AstVar* const origVarp = VN_CAST(argp, Var)) {
|
||||
AstVar* const memberp = origVarp->cloneTree(false);
|
||||
memberp->varType(VVarType::MEMBER);
|
||||
memberp->funcLocal(false);
|
||||
memberp->direction(VDirection::NONE);
|
||||
cgClassp->addMembersp(memberp);
|
||||
}
|
||||
}
|
||||
|
||||
// Convert sample args to member variables
|
||||
for (AstNode* argp = nodep->sampleArgsp(); argp; argp = argp->nextp()) {
|
||||
if (AstVar* const origVarp = VN_CAST(argp, Var)) {
|
||||
AstVar* const memberp = origVarp->cloneTree(false);
|
||||
memberp->varType(VVarType::MEMBER);
|
||||
memberp->funcLocal(false);
|
||||
memberp->direction(VDirection::NONE);
|
||||
cgClassp->addMembersp(memberp);
|
||||
}
|
||||
}
|
||||
|
||||
// Create the constructor; detach membersp (coverage body) and use as its body
|
||||
{
|
||||
AstFunc* const newp = new AstFunc{nodep->fileline(), "new", nullptr, nullptr};
|
||||
newp->fileline()->warnOff(V3ErrorCode::NORETURN, true);
|
||||
newp->classMethod(true);
|
||||
newp->isConstructor(true);
|
||||
newp->dtypep(cgClassp->dtypep());
|
||||
if (AstNode* const bodyp = nodep->membersp()) {
|
||||
bodyp->unlinkFrBackWithNext();
|
||||
newp->addStmtsp(bodyp);
|
||||
}
|
||||
cgClassp->addMembersp(newp);
|
||||
}
|
||||
|
||||
// Add all boilerplate covergroup methods (reads argsp/sampleArgsp from nodep)
|
||||
createCovergroupMethods(cgClassp, nodep->argsp(), nodep->sampleArgsp());
|
||||
|
||||
// Replace AstCovergroup with AstClass and process the new class normally
|
||||
nodep->replaceWith(cgClassp);
|
||||
VL_DO_DANGLING(nodep->deleteTree(), nodep);
|
||||
iterate(cgClassp);
|
||||
}
|
||||
|
||||
void visit(AstNode* nodep) override {
|
||||
// Default: Just iterate
|
||||
cleanFileline(nodep);
|
||||
|
|
|
|||
|
|
@ -94,169 +94,6 @@ public:
|
|||
nodep->trace(singletonp()->allTracingOn(fileline));
|
||||
return nodep;
|
||||
}
|
||||
void createCoverGroupMethods(AstClass* nodep, AstNode* constructorArgs, AstNode* sampleArgs) {
|
||||
// Hidden static to take unspecified reference argument results
|
||||
AstVar* const defaultVarp
|
||||
= new AstVar{nodep->fileline(), VVarType::MEMBER, "__Vint", nodep->findIntDType()};
|
||||
defaultVarp->lifetime(VLifetime::STATIC_EXPLICIT);
|
||||
nodep->addStmtsp(defaultVarp);
|
||||
|
||||
// Handle constructor arguments - add function parameters and assignments
|
||||
// Member variables have already been created in verilog.y
|
||||
if (constructorArgs) {
|
||||
// Find the 'new' function to add parameters to
|
||||
AstFunc* newFuncp = nullptr;
|
||||
for (AstNode* memberp = nodep->membersp(); memberp; memberp = memberp->nextp()) {
|
||||
if (AstFunc* funcp = VN_CAST(memberp, Func)) {
|
||||
if (funcp->name() == "new") {
|
||||
newFuncp = funcp;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (newFuncp) {
|
||||
// Save the existing body statements and unlink them
|
||||
AstNode* const existingBodyp = newFuncp->stmtsp();
|
||||
if (existingBodyp) existingBodyp->unlinkFrBackWithNext();
|
||||
|
||||
// Add function parameters and assignments
|
||||
AstNode* nextArgp = nullptr;
|
||||
for (AstNode* argp = constructorArgs; argp; argp = nextArgp) {
|
||||
nextArgp = argp->nextp(); // Save next before any modifications
|
||||
if (AstVar* const origVarp = VN_CAST(argp, Var)) {
|
||||
// Create a constructor parameter
|
||||
AstVar* const paramp = origVarp->cloneTree(false);
|
||||
paramp->funcLocal(true);
|
||||
paramp->direction(VDirection::INPUT);
|
||||
newFuncp->addStmtsp(paramp);
|
||||
|
||||
// Create assignment: member = parameter
|
||||
AstNodeExpr* const lhsp
|
||||
= new AstParseRef{origVarp->fileline(), origVarp->name()};
|
||||
AstNodeExpr* const rhsp
|
||||
= new AstParseRef{paramp->fileline(), paramp->name()};
|
||||
newFuncp->addStmtsp(new AstAssign{origVarp->fileline(), lhsp, rhsp});
|
||||
}
|
||||
}
|
||||
|
||||
// Finally, add back the existing body
|
||||
if (existingBodyp) newFuncp->addStmtsp(existingBodyp);
|
||||
}
|
||||
}
|
||||
|
||||
// IEEE: option
|
||||
{
|
||||
v3Global.setUsesStdPackage();
|
||||
AstVar* const varp
|
||||
= new AstVar{nodep->fileline(), VVarType::MEMBER, "option", VFlagChildDType{},
|
||||
new AstRefDType{nodep->fileline(), "vl_covergroup_options_t",
|
||||
new AstClassOrPackageRef{nodep->fileline(), "std",
|
||||
nullptr, nullptr},
|
||||
nullptr}};
|
||||
nodep->addMembersp(varp);
|
||||
}
|
||||
|
||||
// IEEE: type_option
|
||||
{
|
||||
v3Global.setUsesStdPackage();
|
||||
AstVar* const varp
|
||||
= new AstVar{nodep->fileline(), VVarType::MEMBER, "type_option", VFlagChildDType{},
|
||||
new AstRefDType{nodep->fileline(), "vl_covergroup_type_options_t",
|
||||
new AstClassOrPackageRef{nodep->fileline(), "std",
|
||||
nullptr, nullptr},
|
||||
nullptr}};
|
||||
nodep->addMembersp(varp);
|
||||
}
|
||||
|
||||
// IEEE: function void sample([arguments])
|
||||
{
|
||||
AstFunc* const funcp = new AstFunc{nodep->fileline(), "sample", nullptr, nullptr};
|
||||
|
||||
// Add sample arguments as function parameters and assignments
|
||||
// Member variables have already been created in verilog.y
|
||||
if (sampleArgs) {
|
||||
// Add function parameters and assignments
|
||||
AstNode* nextArgp = nullptr;
|
||||
for (AstNode* argp = sampleArgs; argp; argp = nextArgp) {
|
||||
nextArgp = argp->nextp(); // Save next before any modifications
|
||||
if (AstVar* const origVarp = VN_CAST(argp, Var)) {
|
||||
// Create a function parameter
|
||||
AstVar* const paramp = origVarp->cloneTree(false);
|
||||
paramp->funcLocal(true);
|
||||
paramp->direction(VDirection::INPUT);
|
||||
funcp->addStmtsp(paramp);
|
||||
|
||||
// Create assignment: member = parameter
|
||||
AstNodeExpr* const lhsp
|
||||
= new AstParseRef{origVarp->fileline(), origVarp->name()};
|
||||
AstNodeExpr* const rhsp
|
||||
= new AstParseRef{paramp->fileline(), paramp->name()};
|
||||
funcp->addStmtsp(new AstAssign{origVarp->fileline(), lhsp, rhsp});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
funcp->classMethod(true);
|
||||
funcp->dtypep(funcp->findVoidDType());
|
||||
nodep->addMembersp(funcp);
|
||||
}
|
||||
|
||||
// IEEE: function void start(), void stop()
|
||||
for (const string& name : {"start"s, "stop"s}) {
|
||||
AstFunc* const funcp = new AstFunc{nodep->fileline(), name, nullptr, nullptr};
|
||||
funcp->classMethod(true);
|
||||
funcp->dtypep(funcp->findVoidDType());
|
||||
nodep->addMembersp(funcp);
|
||||
}
|
||||
|
||||
// IEEE: static function real get_coverage(optional ref int, optional ref int)
|
||||
// IEEE: function real get_inst_coverage(optional ref int, optional ref int)
|
||||
for (const string& name : {"get_coverage"s, "get_inst_coverage"s}) {
|
||||
AstFunc* const funcp = new AstFunc{nodep->fileline(), name, nullptr, nullptr};
|
||||
funcp->fileline()->warnOff(V3ErrorCode::NORETURN, true);
|
||||
funcp->isStatic(name == "get_coverage");
|
||||
funcp->classMethod(true);
|
||||
funcp->dtypep(funcp->findVoidDType());
|
||||
nodep->addMembersp(funcp);
|
||||
{
|
||||
AstVar* const varp = new AstVar{nodep->fileline(), VVarType::MEMBER, name,
|
||||
nodep->findDoubleDType()};
|
||||
varp->lifetime(VLifetime::AUTOMATIC_EXPLICIT);
|
||||
varp->funcLocal(true);
|
||||
varp->direction(VDirection::OUTPUT);
|
||||
varp->funcReturn(true);
|
||||
funcp->fvarp(varp);
|
||||
}
|
||||
for (const string& varname : {"covered_bins"s, "total_bins"s}) {
|
||||
AstVar* const varp = new AstVar{nodep->fileline(), VVarType::MEMBER, varname,
|
||||
nodep->findStringDType()};
|
||||
varp->lifetime(VLifetime::AUTOMATIC_EXPLICIT);
|
||||
varp->funcLocal(true);
|
||||
varp->direction(VDirection::INPUT);
|
||||
varp->valuep(new AstVarRef{nodep->fileline(), defaultVarp, VAccess::READ});
|
||||
funcp->addStmtsp(varp);
|
||||
}
|
||||
}
|
||||
// IEEE: function void set_inst_name(string)
|
||||
{
|
||||
AstFunc* const funcp
|
||||
= new AstFunc{nodep->fileline(), "set_inst_name", nullptr, nullptr};
|
||||
funcp->classMethod(true);
|
||||
funcp->dtypep(funcp->findVoidDType());
|
||||
nodep->addMembersp(funcp);
|
||||
AstVar* const varp = new AstVar{nodep->fileline(), VVarType::MEMBER, "name",
|
||||
nodep->findStringDType()};
|
||||
varp->lifetime(VLifetime::AUTOMATIC_EXPLICIT);
|
||||
varp->funcLocal(true);
|
||||
varp->direction(VDirection::INPUT);
|
||||
funcp->addStmtsp(varp);
|
||||
}
|
||||
|
||||
// The original arg lists were cloned above; delete the orphaned originals
|
||||
if (constructorArgs) VL_DO_DANGLING(constructorArgs->deleteTree(), constructorArgs);
|
||||
if (sampleArgs) VL_DO_DANGLING(sampleArgs->deleteTree(), sampleArgs);
|
||||
}
|
||||
// Helper to move bins from parser list to coverpoint
|
||||
void addCoverpointBins(AstCoverpoint* cp, AstNode* binsList) {
|
||||
if (!binsList) return;
|
||||
|
|
|
|||
126
src/verilog.y
126
src/verilog.y
|
|
@ -6905,89 +6905,23 @@ covergroup_declaration<nodep>: // ==IEEE: covergroup_declaration
|
|||
yCOVERGROUP idAny cgPortListE coverage_eventE ';'
|
||||
/*cont*/ coverage_spec_or_optionListE
|
||||
/*cont*/ yENDGROUP endLabelE
|
||||
{ AstClass *cgClassp = new AstClass{$<fl>2, *$2, PARSEP->libname()};
|
||||
cgClassp->isCovergroup(true);
|
||||
v3Global.useCovergroup(true);
|
||||
|
||||
AstNode* sampleArgs = nullptr;
|
||||
|
||||
// coverage_eventE can be either a clocking event or sample arguments
|
||||
{ AstSenTree* clockp = nullptr;
|
||||
AstNode* sampleArgsp = nullptr;
|
||||
if ($4) {
|
||||
if (VN_IS($4, SenItem)) {
|
||||
// Clocking event: @(posedge clk)
|
||||
// Create an AstCovergroup node to hold the clocking event
|
||||
AstSenTree* senTreep = new AstSenTree{$<fl>1, VN_AS($4, SenItem)};
|
||||
AstCovergroup* const cgNodep = new AstCovergroup{$<fl>1, *$2, nullptr, senTreep};
|
||||
cgClassp->addMembersp(cgNodep);
|
||||
} else {
|
||||
// Sample arguments: with function sample(...)
|
||||
sampleArgs = $4;
|
||||
}
|
||||
if (VN_IS($4, SenItem))
|
||||
clockp = new AstSenTree{$<fl>1, VN_AS($4, SenItem)};
|
||||
else
|
||||
sampleArgsp = $4;
|
||||
}
|
||||
|
||||
// Convert constructor parameters to member variables
|
||||
// This must happen BEFORE the covergroup body is added,
|
||||
// so coverpoints can reference these members
|
||||
// We iterate carefully to avoid issues with modified AST
|
||||
if ($3) {
|
||||
AstNode* nextArgp = nullptr;
|
||||
for (AstNode* argp = $3; argp; argp = nextArgp) {
|
||||
nextArgp = argp->nextp(); // Save next before any modifications
|
||||
if (AstVar* origVarp = VN_CAST(argp, Var)) {
|
||||
AstVar* memberp = origVarp->cloneTree(false);
|
||||
memberp->varType(VVarType::MEMBER);
|
||||
memberp->funcLocal(false);
|
||||
memberp->direction(VDirection::NONE);
|
||||
cgClassp->addMembersp(memberp);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Convert sample parameters to member variables
|
||||
if (sampleArgs) {
|
||||
AstNode* nextArgp = nullptr;
|
||||
for (AstNode* argp = sampleArgs; argp; argp = nextArgp) {
|
||||
nextArgp = argp->nextp(); // Save next before any modifications
|
||||
if (AstVar* origVarp = VN_CAST(argp, Var)) {
|
||||
AstVar* memberp = origVarp->cloneTree(false);
|
||||
memberp->varType(VVarType::MEMBER);
|
||||
memberp->funcLocal(false);
|
||||
memberp->direction(VDirection::NONE);
|
||||
cgClassp->addMembersp(memberp);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
AstFunc* const newp = new AstFunc{$<fl>1, "new", nullptr, nullptr};
|
||||
newp->fileline()->warnOff(V3ErrorCode::NORETURN, true);
|
||||
newp->classMethod(true);
|
||||
newp->isConstructor(true);
|
||||
newp->dtypep(cgClassp->dtypep());
|
||||
newp->addStmtsp($6);
|
||||
cgClassp->addMembersp(newp);
|
||||
GRAMMARP->createCoverGroupMethods(cgClassp, $3, sampleArgs);
|
||||
|
||||
$$ = cgClassp;
|
||||
GRAMMARP->endLabel($<fl>8, $$, $8);
|
||||
}
|
||||
$$ = new AstCovergroup{$<fl>2, *$2, static_cast<AstVar*>($3),
|
||||
static_cast<AstVar*>(sampleArgsp), $6, clockp};
|
||||
GRAMMARP->endLabel($<fl>8, $$, $8); }
|
||||
| yCOVERGROUP yEXTENDS idAny ';'
|
||||
/*cont*/ coverage_spec_or_optionListE
|
||||
/*cont*/ yENDGROUP endLabelE
|
||||
{ BBCOVERIGN($1, "Ignoring unsupported: covergroup inheritance (extends)");
|
||||
AstClass *cgClassp = new AstClass{$<fl>3, *$3, PARSEP->libname()};
|
||||
cgClassp->isCovergroup(true);
|
||||
AstFunc* const newp = new AstFunc{$<fl>1, "new", nullptr, nullptr};
|
||||
newp->fileline()->warnOff(V3ErrorCode::NORETURN, true);
|
||||
newp->classMethod(true);
|
||||
newp->isConstructor(true);
|
||||
newp->dtypep(cgClassp->dtypep());
|
||||
newp->addStmtsp($5);
|
||||
cgClassp->addMembersp(newp);
|
||||
GRAMMARP->createCoverGroupMethods(cgClassp, nullptr, nullptr);
|
||||
|
||||
$$ = cgClassp;
|
||||
GRAMMARP->endLabel($<fl>7, $$, $7);
|
||||
}
|
||||
$$ = new AstCovergroup{$<fl>3, *$3, nullptr, nullptr, $5, nullptr};
|
||||
GRAMMARP->endLabel($<fl>7, $$, $7); }
|
||||
;
|
||||
|
||||
cgPortListE<nodep>:
|
||||
|
|
@ -7034,43 +6968,43 @@ 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
|
||||
{ auto* cp = new AstCoverpoint{$<fl>1, "", $2};
|
||||
{ AstCoverpoint* const cp = new AstCoverpoint{$<fl>1, "", $2};
|
||||
if ($3) cp->iffp(VN_AS($3, NodeExpr));
|
||||
GRAMMARP->addCoverpointBins(cp, $4);
|
||||
$$ = cp; }
|
||||
// // IEEE-2012: class_scope before an ID
|
||||
| id/*cover_point_id*/ ':' yCOVERPOINT expr iffE bins_or_empty
|
||||
{ auto* cp = new AstCoverpoint{$<fl>3, *$1, $4};
|
||||
{ AstCoverpoint* const cp = new AstCoverpoint{$<fl>3, *$1, $4};
|
||||
if ($5) cp->iffp(VN_AS($5, NodeExpr));
|
||||
GRAMMARP->addCoverpointBins(cp, $6);
|
||||
$$ = cp; }
|
||||
// // data_type_or_implicit expansion
|
||||
| data_type id/*cover_point_id*/ ':' yCOVERPOINT expr iffE bins_or_empty
|
||||
{ auto* cp = new AstCoverpoint{$<fl>4, *$2, $5};
|
||||
{ AstCoverpoint* const cp = new AstCoverpoint{$<fl>4, *$2, $5};
|
||||
if ($6) cp->iffp(VN_AS($6, NodeExpr));
|
||||
GRAMMARP->addCoverpointBins(cp, $7);
|
||||
$$ = cp;
|
||||
DEL($1); }
|
||||
| yVAR data_type id/*cover_point_id*/ ':' yCOVERPOINT expr iffE bins_or_empty
|
||||
{ auto* cp = new AstCoverpoint{$<fl>5, *$3, $6};
|
||||
{ AstCoverpoint* const cp = new AstCoverpoint{$<fl>5, *$3, $6};
|
||||
if ($7) cp->iffp(VN_AS($7, NodeExpr));
|
||||
GRAMMARP->addCoverpointBins(cp, $8);
|
||||
$$ = cp;
|
||||
DEL($2); }
|
||||
| yVAR implicit_typeE id/*cover_point_id*/ ':' yCOVERPOINT expr iffE bins_or_empty
|
||||
{ auto* cp = new AstCoverpoint{$<fl>5, *$3, $6};
|
||||
{ AstCoverpoint* const cp = new AstCoverpoint{$<fl>5, *$3, $6};
|
||||
if ($7) cp->iffp(VN_AS($7, NodeExpr));
|
||||
GRAMMARP->addCoverpointBins(cp, $8);
|
||||
$$ = cp;
|
||||
DEL($2); }
|
||||
| signingE rangeList id/*cover_point_id*/ ':' yCOVERPOINT expr iffE bins_or_empty
|
||||
{ auto* cp = new AstCoverpoint{$<fl>5, *$3, $6};
|
||||
{ AstCoverpoint* const cp = new AstCoverpoint{$<fl>5, *$3, $6};
|
||||
if ($7) cp->iffp(VN_AS($7, NodeExpr));
|
||||
GRAMMARP->addCoverpointBins(cp, $8);
|
||||
$$ = cp;
|
||||
DEL($2); }
|
||||
| signing id/*cover_point_id*/ ':' yCOVERPOINT expr iffE bins_or_empty
|
||||
{ auto* cp = new AstCoverpoint{$<fl>4, *$2, $5};
|
||||
{ AstCoverpoint* const cp = new AstCoverpoint{$<fl>4, *$2, $5};
|
||||
if ($6) cp->iffp(VN_AS($6, NodeExpr));
|
||||
GRAMMARP->addCoverpointBins(cp, $7);
|
||||
$$ = cp; }
|
||||
|
|
@ -7161,23 +7095,17 @@ bins_or_options<nodep>: // ==IEEE: bins_or_options
|
|||
//
|
||||
// // cgexpr part of trans_list
|
||||
| yBINS idAny/*bin_identifier*/ bins_orBraE '=' trans_list iffE
|
||||
{
|
||||
FileLine* isArray = $<fl>3;
|
||||
$$ = new AstCoverBin{$<fl>2, *$2, static_cast<AstCoverTransSet*>($5), false, false, isArray != nullptr};
|
||||
DEL($6);
|
||||
}
|
||||
{ FileLine* isArray = $<fl>3;
|
||||
$$ = new AstCoverBin{$<fl>2, *$2, static_cast<AstCoverTransSet*>($5), false, false, isArray != nullptr};
|
||||
DEL($6); }
|
||||
| yIGNORE_BINS idAny/*bin_identifier*/ bins_orBraE '=' trans_list iffE
|
||||
{
|
||||
FileLine* isArray = $<fl>3;
|
||||
$$ = new AstCoverBin{$<fl>2, *$2, static_cast<AstCoverTransSet*>($5), true, false, isArray != nullptr};
|
||||
DEL($6);
|
||||
}
|
||||
{ FileLine* isArray = $<fl>3;
|
||||
$$ = new AstCoverBin{$<fl>2, *$2, static_cast<AstCoverTransSet*>($5), true, false, isArray != nullptr};
|
||||
DEL($6); }
|
||||
| yILLEGAL_BINS idAny/*bin_identifier*/ bins_orBraE '=' trans_list iffE
|
||||
{
|
||||
FileLine* isArray = $<fl>3;
|
||||
$$ = new AstCoverBin{$<fl>2, *$2, static_cast<AstCoverTransSet*>($5), false, true, isArray != nullptr};
|
||||
DEL($6);
|
||||
}
|
||||
{ FileLine* isArray = $<fl>3;
|
||||
$$ = new AstCoverBin{$<fl>2, *$2, static_cast<AstCoverTransSet*>($5), false, true, isArray != nullptr};
|
||||
DEL($6); }
|
||||
| yWILDCARD yBINS idAny/*bin_identifier*/ bins_orBraE '=' trans_list iffE
|
||||
{ $$ = nullptr; BBCOVERIGN($<fl>1, "Ignoring unsupported: cover bin 'wildcard' trans list"); DEL($6, $7);}
|
||||
| yWILDCARD yIGNORE_BINS idAny/*bin_identifier*/ bins_orBraE '=' trans_list iffE
|
||||
|
|
|
|||
Loading…
Reference in New Issue