Parser: Move class parameter unsupported messages down out of parser

This commit is contained in:
Wilson Snyder 2020-07-11 18:39:01 -04:00
parent bb8899f307
commit 9e5cd463e5
6 changed files with 103 additions and 66 deletions

View File

@ -1139,6 +1139,15 @@ public:
, m_refDTypep(NULL)
, m_name(name)
, m_packagep(NULL) {}
AstRefDType(FileLine* fl, const string& name, AstNode* classOrPackagep, AstNode* paramsp)
: ASTGEN_SUPER(fl)
, m_typedefp(NULL)
, m_refDTypep(NULL)
, m_name(name)
, m_packagep(NULL) {
setNOp3p(classOrPackagep);
addNOp4p(paramsp);
}
class FlagTypeOfExpr {}; // type(expr) for parser only
AstRefDType(FileLine* fl, FlagTypeOfExpr, AstNode* typeofp)
: ASTGEN_SUPER(fl)
@ -1216,6 +1225,8 @@ public:
AstNodeModule* packagep() const { return m_packagep; }
void packagep(AstNodeModule* nodep) { m_packagep = nodep; }
AstNode* typeofp() const { return op2p(); }
AstNode* classOrPackagep() const { return op3p(); }
AstPin* paramsp() const { return VN_CAST(op4p(), Pin); }
};
class AstStructDType : public AstNodeUOrStructDType {
@ -2893,15 +2904,20 @@ public:
class AstClassOrPackageRef : public AstNode {
private:
string m_name;
AstNode* m_classOrPackagep; // Package hierarchy
public:
AstClassOrPackageRef(FileLine* fl, AstNode* classOrPackagep)
AstClassOrPackageRef(FileLine* fl, const string& name, AstNode* classOrPackagep,
AstNode* paramsp)
: ASTGEN_SUPER(fl)
, m_classOrPackagep(classOrPackagep) {}
, m_name(name)
, m_classOrPackagep(classOrPackagep) {
addNOp4p(paramsp);
}
ASTNODE_NODE_FUNCS(ClassOrPackageRef)
// METHODS
virtual const char* broken() const {
BROKEN_RTN(!m_classOrPackagep || !m_classOrPackagep->brokeExists());
BROKEN_RTN(m_classOrPackagep && !m_classOrPackagep->brokeExists());
return NULL;
}
virtual void cloneRelink() {
@ -2915,9 +2931,11 @@ public:
}
virtual V3Hash sameHash() const { return V3Hash(m_classOrPackagep); }
virtual void dump(std::ostream& str = std::cout) const;
virtual string name() const { return m_name; } // * = Var name
AstNode* classOrPackagep() const { return m_classOrPackagep; }
AstPackage* packagep() const { return VN_CAST(classOrPackagep(), Package); }
void classOrPackagep(AstNode* nodep) { m_classOrPackagep = nodep; }
AstPin* paramsp() const { return VN_CAST(op4p(), Pin); }
};
class AstDot : public AstNode {
@ -2933,9 +2951,9 @@ public:
}
ASTNODE_NODE_FUNCS(Dot)
// For parser, make only if non-null package
static AstNode* newIfPkg(FileLine* fl, AstPackage* packagep, AstNode* rhsp) {
if (!packagep) return rhsp;
return new AstDot(fl, true, new AstClassOrPackageRef(fl, packagep), rhsp);
static AstNode* newIfPkg(FileLine* fl, AstNode* packageOrClassp, AstNode* rhsp) {
if (!packageOrClassp) return rhsp;
return new AstDot(fl, true, packageOrClassp, rhsp);
}
virtual void dump(std::ostream& str) const;
virtual string emitVerilog() { V3ERROR_NA_RETURN(""); }

View File

@ -2049,7 +2049,14 @@ private:
allowVar = true;
UASSERT_OBJ(VN_IS(m_ds.m_dotp->lhsp(), ClassOrPackageRef), m_ds.m_dotp->lhsp(),
"Bad package link");
packagep = VN_CAST(m_ds.m_dotp->lhsp(), ClassOrPackageRef)->packagep();
AstClassOrPackageRef* cpackagerefp
= VN_CAST(m_ds.m_dotp->lhsp(), ClassOrPackageRef);
packagep = cpackagerefp->packagep();
if (!packagep && cpackagerefp->classOrPackagep()) {
nodep->v3warn(E_UNSUPPORTED,
"Unsupported: Class '::' references: "
<< AstNode::prettyNameQ(cpackagerefp->name()));
}
UASSERT_OBJ(packagep, m_ds.m_dotp->lhsp(), "Bad package link");
m_ds.m_dotSymp = m_statep->getNodeSym(packagep);
m_ds.m_dotPos = DP_SCOPE;
@ -2401,6 +2408,14 @@ private:
if (m_ds.m_dotp && m_ds.m_dotPos == DP_PACKAGE) {
UASSERT_OBJ(VN_IS(m_ds.m_dotp->lhsp(), ClassOrPackageRef), m_ds.m_dotp->lhsp(),
"Bad package link");
AstClassOrPackageRef* cpackagerefp = VN_CAST(m_ds.m_dotp->lhsp(), ClassOrPackageRef);
if (cpackagerefp->name() == "process" || cpackagerefp->name() == "local") {
nodep->v3warn(E_UNSUPPORTED,
"Unsupported: " << AstNode::prettyNameQ(cpackagerefp->name()));
}
if (cpackagerefp->paramsp()) {
nodep->v3warn(E_UNSUPPORTED, "Unsupported: parameterized packages");
}
UASSERT_OBJ(VN_CAST(m_ds.m_dotp->lhsp(), ClassOrPackageRef)->packagep(),
m_ds.m_dotp->lhsp(), "Bad package link");
nodep->packagep(VN_CAST(m_ds.m_dotp->lhsp(), ClassOrPackageRef)->packagep());
@ -2667,6 +2682,22 @@ private:
virtual void visit(AstRefDType* nodep) VL_OVERRIDE {
// Resolve its reference
if (nodep->user3SetOnce()) return;
if (AstNode* cpackagep = nodep->classOrPackagep()) {
if (AstClassOrPackageRef* cpackagerefp = VN_CAST(cpackagep, ClassOrPackageRef)) {
if (cpackagerefp->packagep()) {
nodep->packagep(cpackagerefp->packagep());
} else {
cpackagep->v3warn(E_UNSUPPORTED, "Unsupported: Class '::' reference");
// if (cpackagerefp->paramsp()) {
// nodep->v3warn(E_UNSUPPORTED, "Unsupported: parameterized packages");
// }
}
} else {
cpackagep->v3warn(E_UNSUPPORTED,
"Unsupported: Multiple '::' package/class reference");
}
VL_DO_DANGLING(cpackagep->unlinkFrBack()->deleteTree(), cpackagep);
}
if (m_ds.m_dotp && m_ds.m_dotPos == DP_PACKAGE) {
UASSERT_OBJ(VN_IS(m_ds.m_dotp->lhsp(), ClassOrPackageRef), m_ds.m_dotp->lhsp(),
"Bad package link");

View File

@ -264,17 +264,6 @@ int V3ParseGrammar::s_modTypeImpNum = 0;
GRAMMARP->m_instParamp = paramsp; \
}
static AstPackage* CAST_PACKAGE_CLASS(AstNode* nodep) {
if (!nodep) {
return NULL;
} else if (AstPackage* pkgp = VN_CAST(nodep, Package)) {
return pkgp;
} else {
BBUNSUP(nodep->fileline(), "Unsupported class :: reference");
return NULL;
}
}
#define DEL(nodep) \
{ \
if (nodep) nodep->deleteTree(); \
@ -1783,8 +1772,8 @@ simple_type<dtypep>: // ==IEEE: simple_type
// // Even though we looked up the type and have a AstNode* to it,
// // we can't fully resolve it because it may have been just a forward definition.
| packageClassScopeE idType
{ AstRefDType* refp = new AstRefDType($<fl>2, *$2);
refp->packagep($1); $$ = refp; }
{ AstRefDType* refp = new AstRefDType($<fl>2, *$2, $1, NULL);
$$ = refp; }
//
// // { generate_block_identifer ... } '.'
// // Need to determine if generate_block_identifier can be lex-detected
@ -1801,12 +1790,10 @@ data_type<dtypep>: // ==IEEE: data_type
// // IEEE: ps_covergroup_identifier
// // Don't distinguish between types and classes so all these combined
| packageClassScopeE idType packed_dimensionListE
{ AstRefDType* refp = new AstRefDType($<fl>2, *$2);
refp->packagep($1);
{ AstRefDType* refp = new AstRefDType($<fl>2, *$2, $1, NULL);
$$ = GRAMMARP->createArray(refp, $3, true); }
| packageClassScopeE idType parameter_value_assignmentClass packed_dimensionListE
{ AstRefDType* refp = new AstRefDType($<fl>2, *$2);
refp->packagep($1);
{ AstRefDType* refp = new AstRefDType($<fl>2, *$2, $1, $3);
BBUNSUP($3->fileline(), "Unsupported: Parameter classes");
$$ = GRAMMARP->createArray(refp, $4, true); }
;
@ -1851,7 +1838,8 @@ var_data_type<dtypep>: // ==IEEE: var_data_type
;
type_reference<dtypep>: // ==IEEE: type_reference
yTYPE '(' exprOrDataType ')' { $$ = new AstRefDType($1, AstRefDType::FlagTypeOfExpr(), $3); }
yTYPE '(' exprOrDataType ')'
{ $$ = new AstRefDType($1, AstRefDType::FlagTypeOfExpr(), $3); }
;
struct_unionDecl<uorstructp>: // IEEE: part of data_type
@ -2021,8 +2009,7 @@ enum_base_typeE<dtypep>: // IEEE: enum_base_type
| idAny rangeListE
{ $$ = GRAMMARP->createArray(new AstRefDType($<fl>1, *$1), $2, true); }
| packageClassScope idAny rangeListE
{ AstRefDType* refp = new AstRefDType($<fl>2, *$2);
refp->packagep($1);
{ AstRefDType* refp = new AstRefDType($<fl>2, *$2, $1, NULL);
$$ = GRAMMARP->createArray(refp, $3, true); }
;
@ -2526,7 +2513,7 @@ delay_control<nodep>: //== IEEE: delay_control
delay_value<nodep>: // ==IEEE:delay_value
// // IEEE: ps_identifier
packageClassScopeE varRefBase { $$ = AstDot::newIfPkg($<fl>2, CAST_PACKAGE_CLASS($1), $2); }
packageClassScopeE varRefBase { $$ = AstDot::newIfPkg($<fl>2, $1, $2); }
| yaINTNUM { $$ = new AstConst($<fl>1, *$1); }
| yaFLOATNUM { $$ = new AstConst($<fl>1, AstConst::RealDouble(), $1); }
| timeNumAdjusted { $$ = $1; }
@ -3412,7 +3399,7 @@ taskRef<nodep>: // IEEE: part of tf_call
id { $$ = new AstTaskRef($<fl>1,*$1,NULL); }
| id '(' list_of_argumentsE ')' { $$ = new AstTaskRef($<fl>1,*$1,$3); }
| packageClassScope id '(' list_of_argumentsE ')'
{ $$ = AstDot::newIfPkg($<fl>2, CAST_PACKAGE_CLASS($1), new AstTaskRef($<fl>2, *$2, $4)); }
{ $$ = AstDot::newIfPkg($<fl>2, $1, new AstTaskRef($<fl>2, *$2, $4)); }
;
funcRef<nodep>: // IEEE: part of tf_call
@ -3428,7 +3415,7 @@ funcRef<nodep>: // IEEE: part of tf_call
id '(' list_of_argumentsE ')'
{ $$ = new AstFuncRef($<fl>1, *$1, $3); }
| packageClassScope id '(' list_of_argumentsE ')'
{ $$ = AstDot::newIfPkg($<fl>2, CAST_PACKAGE_CLASS($1), new AstFuncRef($<fl>2, *$2, $4)); }
{ $$ = AstDot::newIfPkg($<fl>2, $1, new AstFuncRef($<fl>2, *$2, $4)); }
//UNSUP list_of_argumentE should be pev_list_of_argumentE
//UNSUP: idDotted is really just id to allow dotted method calls
;
@ -4263,7 +4250,7 @@ exprScope<nodep>: // scope and variable for use to inside an expression
yTHIS { $$ = new AstParseRef($<fl>1, VParseRefExp::PX_ROOT, "this"); }
| yD_ROOT { $$ = new AstParseRef($<fl>1, VParseRefExp::PX_ROOT, "$root"); }
| idArrayed { $$ = $1; }
| packageClassScope idArrayed { $$ = AstDot::newIfPkg($2->fileline(), CAST_PACKAGE_CLASS($1), $2); }
| packageClassScope idArrayed { $$ = AstDot::newIfPkg($2->fileline(), $1, $2); }
| ~l~expr '.' idArrayed { $$ = new AstDot($<fl>2, false, $1, $3); }
// // expr below must be a "yTHIS"
| ~l~expr '.' ySUPER { $$ = $1; BBUNSUP($3, "Unsupported: super"); }
@ -5912,11 +5899,11 @@ class_typeExtImpOne<nodep>: // part of IEEE: class_type, where we either get a p
//=== Below rules assume special scoping per above
packageClassScopeNoId<packagep>: // IEEE: [package_scope] not followed by yaID
packageClassScopeNoId<nodep>: // IEEE: [package_scope] not followed by yaID
packageClassScope { $$ = $1; $<scp>$ = $<scp>1; SYMP->nextId(NULL); }
;
packageClassScopeE<packagep>: // IEEE: [package_scope]
packageClassScopeE<nodep>: // IEEE: [package_scope]
// // IMPORTANT: The lexer will parse the following ID to be in the found package
// // if not needed must use packageClassScopeNoId
// // TODO: To support classes should return generic type, not packagep
@ -5925,7 +5912,7 @@ packageClassScopeE<packagep>: // IEEE: [package_scope]
| packageClassScope { $$ = $1; $<scp>$ = $<scp>1; }
;
packageClassScope<packagep>: // IEEE: class_scope + type
packageClassScope<nodep>: // IEEE: class_scope
// // IEEE: "class_type yP_COLONCOLON"
// // IMPORTANT: The lexer will parse the following ID to be in the found package
// // if not needed must use packageClassScopeNoId
@ -5934,10 +5921,11 @@ packageClassScope<packagep>: // IEEE: class_scope + type
packageClassScopeList { $$ = $1; $<scp>$ = $<scp>1; }
| localNextId yP_COLONCOLON { $$ = $1; $<scp>$ = $<scp>1; }
| dollarUnitNextId yP_COLONCOLON { $$ = $1; $<scp>$ = $<scp>1; }
| dollarUnitNextId yP_COLONCOLON packageClassScopeList { $$ = $3; $<scp>$ = $<scp>3; }
| dollarUnitNextId yP_COLONCOLON packageClassScopeList
{ $$ = new AstDot($2, true, $1, $3); $<scp>$ = $<scp>3; }
;
packageClassScopeList<packagep>: // IEEE: class_type: "id [ parameter_value_assignment ]" but allow yaID__aTYPE
packageClassScopeList<nodep>: // IEEE: class_type: "id [ parameter_value_assignment ]" but allow yaID__aTYPE
// // Or IEEE: [package_scope]
// // IMPORTANT: The lexer will parse the following ID to be in the found package
// // if not needed must use packageClassScopeNoId
@ -5945,10 +5933,10 @@ packageClassScopeList<packagep>: // IEEE: class_type: "id [ parameter_value_assi
// // If you follow the rules down, class_type is really a list via ps_class_identifier
packageClassScopeItem { $$ = $1; $<scp>$ = $<scp>1; }
| packageClassScopeList packageClassScopeItem
{ $$ = $2; $<scp>$ = $<scp>2; BBUNSUP($<fl>2, "Unsupported: Nested :: references"); }
{ $$ = new AstDot($<fl>2, true, $1, $2); $<scp>$ = $<scp>2; }
;
packageClassScopeItem<packagep>: // IEEE: package_scope or [package_scope]::[class_scope]
packageClassScopeItem<nodep>: // IEEE: package_scope or [package_scope]::[class_scope]
// // IMPORTANT: The lexer will parse the following ID to be in the found package
// // if not needed must use packageClassScopeNoId
// // IEEE: class_type: "id [ parameter_value_assignment ]" but allow yaID__aTYPE
@ -5956,29 +5944,30 @@ packageClassScopeItem<packagep>: // IEEE: package_scope or [package_scope]::[cla
idCC
/*mid*/ { SYMP->nextId($<scp>1); }
/*cont*/ yP_COLONCOLON
{ $$ = VN_CAST($<scp>1, Package); $<scp>$ = $<scp>1; } // UNSUP classes
{ $$ = new AstClassOrPackageRef($<fl>1, *$1, $<scp>1, NULL); $<scp>$ = $<scp>1; }
//
| idCC parameter_value_assignment
/*mid*/ { SYMP->nextId($<scp>1); } // Change next *after* we handle parameters, not before
/*cont*/ yP_COLONCOLON
{ $$ = VN_CAST($<scp>1, Package); $<scp>$ = $<scp>1; // UNSUP classes
if ($2) BBUNSUP($2->fileline(), "Unsupported: Parameterized classes"); }
{ $$ = new AstClassOrPackageRef($<fl>1, *$1, $<scp>1, $2); $<scp>$ = $<scp>1; }
;
dollarUnitNextId<packagep>: // $unit
dollarUnitNextId<nodep>: // $unit
// // IMPORTANT: The lexer will parse the following ID to be in the found package
// // if not needed must use packageClassScopeNoId
// // Must call nextId without any additional tokens following
yD_UNIT
{ $$ = GRAMMARP->unitPackage($<fl>1); SYMP->nextId(PARSEP->rootp()); }
{ $$ = new AstClassOrPackageRef($1, "$unit", GRAMMARP->unitPackage($<fl>1), NULL);
SYMP->nextId(PARSEP->rootp()); }
;
localNextId<packagep>: // local
localNextId<nodep>: // local
// // IMPORTANT: The lexer will parse the following ID to be in the found package
// // if not needed must use packageClassScopeNoId
// // Must call nextId without any additional tokens following
yLOCAL__COLONCOLON
{ $$ = GRAMMARP->unitPackage($<fl>1); SYMP->nextId(PARSEP->rootp());
{ $$ = new AstClassOrPackageRef($1, "local::", GRAMMARP->unitPackage($<fl>1), NULL);
SYMP->nextId(PARSEP->rootp());
BBUNSUP($<fl>1, "Unsupported: Randomize 'local::'"); }
;

View File

@ -1,4 +1,7 @@
%Error: t/t_class2.v:35:16: Can't find definition of variable: 'ENUM_VAL'
%Error-UNSUPPORTED: t/t_class2.v:35:16: Unsupported: Class '::' references: 'Cls'
35 | if (Cls::ENUM_VAL != 22) $stop;
| ^~~~~~~~
%Error: Exiting due to
%Error: Internal Error: t/t_class2.v:35:11: ../V3LinkDot.cpp:#: Bad package link
35 | if (Cls::ENUM_VAL != 22) $stop;
| ^~~
... See the manual and https://verilator.org for more assistance.

View File

@ -1,4 +1,13 @@
%Error-UNSUPPORTED: t/t_class_typedef.v:14:24: Unsupported: Parameterized classes
%Error-UNSUPPORTED: t/t_class_typedef.v:12:4: Unsupported: Class '::' reference
12 | uvm_resource_types::rsrc_q_t rtab [string];
| ^~~~~~~~~~~~~~~~~~
%Error: t/t_class_typedef.v:12:24: Can't find typedef: 'rsrc_q_t'
12 | uvm_resource_types::rsrc_q_t rtab [string];
| ^~~~~~~~
%Error-UNSUPPORTED: t/t_class_typedef.v:14:4: Unsupported: Class '::' reference
14 | uvm_resource_types#(1,2,3)::rsrc_q_t rtab_paramed [string];
| ^
| ^~~~~~~~~~~~~~~~~~
%Error: t/t_class_typedef.v:14:32: Can't find typedef: 'rsrc_q_t'
14 | uvm_resource_types#(1,2,3)::rsrc_q_t rtab_paramed [string];
| ^~~~~~~~
%Error: Exiting due to

View File

@ -1,22 +1,9 @@
%Error: t/t_process.v:22:4: Can't find typedef: 'process'
22 | process p;
| ^~~~~~~
%Error: t/t_process.v:26:20: Can't find definition of task/function: 'self'
%Error-UNSUPPORTED: t/t_process.v:26:20: Unsupported: 'process'
26 | p = process::self();
| ^~~~
%Error: t/t_process.v:27:34: Can't find definition of variable: 'RUNNING'
27 | if (p.status() != process::RUNNING) $stop;
| ^~~~~~~
%Error: t/t_process.v:28:34: Can't find definition of variable: 'WAITING'
28 | if (p.status() == process::WAITING) $stop;
| ^~~~~~~
%Error: t/t_process.v:29:34: Can't find definition of variable: 'SUSPENDED'
29 | if (p.status() == process::SUSPENDED) $stop;
| ^~~~~~~~~
%Error: t/t_process.v:30:34: Can't find definition of variable: 'KILLED'
30 | if (p.status() == process::KILLED) $stop;
| ^~~~~~
%Error: t/t_process.v:31:34: Can't find definition of variable: 'FINISHED'
31 | if (p.status() == process::FINISHED) $stop;
| ^~~~~~~~
%Error: Exiting due to
%Error: Internal Error: t/t_process.v:26:11: ../V3LinkDot.cpp:#: Bad package link
26 | p = process::self();
| ^~~~~~~