Internals: Parse extend/implements/etc using generic identifiers.

This commit is contained in:
Wilson Snyder 2020-05-21 21:31:15 -04:00
parent 3cb3b6c400
commit 01f3e81a36
9 changed files with 108 additions and 51 deletions

View File

@ -345,19 +345,18 @@ public:
};
class AstClassExtends : public AstNode {
// Children: AstClassRefDType during early parse, then moves to dtype
// Children: List of AstParseRef for packages/classes
// during early parse, then moves to dtype
public:
AstClassExtends(FileLine* fl, AstNodeDType* dtp)
AstClassExtends(FileLine* fl, AstNode* classOrPkgsp)
: ASTGEN_SUPER(fl) {
childDTypep(dtp); // Only for parser
setNOp1p(classOrPkgsp); // Only for parser
}
ASTNODE_NODE_FUNCS(ClassExtends)
virtual string verilogKwd() const { return "extends"; }
virtual bool hasDType() const { return true; }
AstNodeDType* getChildDTypep() const { return childDTypep(); }
// op1 = Type assigning to
AstNodeDType* childDTypep() const { return VN_CAST(op1p(), NodeDType); }
void childDTypep(AstNodeDType* nodep) { setOp1p(nodep); }
AstNodeDType* classOrPkgsp() const { return VN_CAST(op1p(), NodeDType); }
void classOrPkgsp(AstNodeDType* nodep) { setOp1p(nodep); }
AstClass* classp() const; // Class being extended (after link)
};

View File

@ -1928,11 +1928,12 @@ private:
}
virtual void visit(AstClassExtends* nodep) VL_OVERRIDE {
if (nodep->didWidthAndSet()) return;
if (nodep->childDTypep()) {
nodep->dtypep(moveChildDTypeEdit(nodep)); // data_type '{ pattern }
}
nodep->v3error("Unsupported: class extends"); // Member/meth access breaks
userIterateChildren(nodep, NULL);
VL_DO_DANGLING(nodep->unlinkFrBack()->deleteTree(), nodep);
// if (nodep->childDTypep()) {
// nodep->dtypep(moveChildDTypeEdit(nodep)); // data_type '{ pattern }
// }
//userIterateChildren(nodep, NULL);
}
virtual void visit(AstMemberDType* nodep) VL_OVERRIDE {
if (nodep->didWidthAndSet()) return; // This node is a dtype & not both PRELIMed+FINALed

View File

@ -1598,7 +1598,10 @@ simple_type<dtypep>: // ==IEEE: simple_type
| non_integer_type { $$ = $1; }
// // IEEE: ps_type_identifier
// // IEEE: ps_parameter_identifier (presumably a PARAMETER TYPE)
| ps_type { $$ = $1; }
// 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.
| package_scopeIdFollowsE idRefDType { $$ = $2; $2->packagep($1); }
//
// // { generate_block_identifer ... } '.'
// // Need to determine if generate_block_identifier can be lex-detected
;
@ -2453,8 +2456,10 @@ list_of_defparam_assignments<nodep>: //== IEEE: list_of_defparam_assignments
;
defparam_assignment<nodep>: // ==IEEE: defparam_assignment
id '.' id '=' expr { $$ = new AstDefParam($4,*$1,*$3,$5); }
//UNSUP More general dotted identifiers
idAny '.' idAny '=' expr { $$ = new AstDefParam($4, *$1, *$3, $5); }
| idAny '.' idAny '.'
{ $$ = NULL;
BBUNSUP($4, "Unsupported: defparam with more than one dot"); }
;
//************************************************
@ -4456,11 +4461,6 @@ idAny<strp>: // Any kind of identifier
| yaID__ETC { $$ = $1; $<fl>$=$<fl>1; }
;
idNonPkg<strp>: // Non-package identifier used by extents/implements
yaID__aTYPE { $$ = $1; $<fl>$=$<fl>1; }
| yaID__ETC { $$ = $1; $<fl>$=$<fl>1; }
;
idRefDType<refdtypep>: // IEEE: class_identifier or other type identifier
// Used where reference is needed
yaID__aTYPE { $$ = new AstRefDType($<fl>1, *$1); }
@ -5577,10 +5577,10 @@ classExtendsList<nodep>: // IEEE: part of class_declaration
;
classExtendsOne<nodep>: // IEEE: part of class_declaration
class_typeExtImp
class_typeExtImpList
{ $$ = new AstClassExtends($1->fileline(), $1); }
// // IEEE: Might not be legal to have more than one set of parameters in an extends
| class_typeExtImp '(' list_of_argumentsE ')'
| class_typeExtImpList '(' list_of_argumentsE ')'
{ $$ = new AstClassExtends($1->fileline(), $1);
if ($3) BBUNSUP($3, "Unsupported: extends with parameters"); }
;
@ -5593,32 +5593,36 @@ classImplementsE<nodep>: // IEEE: part of class_declaration
classImplementsList<nodep>: // IEEE: part of class_declaration
// // All 1800-2012
class_typeExtImp { $$ = NULL; BBUNSUP($1, "Unsupported: implements class"); }
| classImplementsList ',' class_typeExtImp { $$ = AstNode::addNextNull($1, $3); }
class_typeExtImpList { $$ = NULL; BBUNSUP($1, "Unsupported: implements class"); }
| classImplementsList ',' class_typeExtImpList { $$ = AstNode::addNextNull($1, $3); }
;
class_typeExtImp<refdtypep>: // as with class_typeWithoutId but from extends/implements
// // and we thus don't need to resolve it in specified package
class_typeExtImpOneList { $$ = $1; }
| package_scopeIdFollows class_typeExtImpOneList { $$ = $2; $2->packagep($1); }
;
class_typeExtImpOneList<refdtypep>: // IEEE: class_type: "id [ parameter_value_assignment ]"
class_typeExtImpList<nodep>: // IEEE: class_type: "[package_scope] id [ parameter_value_assignment ]"
// // but allow yaID__aTYPE for extends/implements
// // If you follow the rules down, class_type is really a list via ps_class_identifier
// // Must propagate scp up for next id
class_typeExtImpOne { $$ = $1; }
| class_typeExtImpOneList yP_COLONCOLON class_typeExtImpOne
{ $$ = $3; BBUNSUP($2, "Unsupported: Hierarchical class references"); }
| class_typeExtImpList yP_COLONCOLON class_typeExtImpOne
{ $$ = $3;
// Cannot just add as next() as that breaks implements lists
//UNSUP $$ = new AstColonColon($<fl>1, $1, $3);
BBUNSUP($2, "Unsupported: Hierarchical class references"); }
;
class_typeExtImpOne<refdtypep>: // IEEE: class_type: "id [ parameter_value_assignment ]"
// // but allow yaID__aTYPE for extends/implements
class_typeExtImpOne<nodep>: // part of IEEE: class_type, where we either get a package_scope component or class
// // If you follow the rules down, class_type is really a list via ps_class_identifier
// // Not listed in IEEE, but see bug627 any parameter type maybe a class
idNonPkg parameter_value_assignmentE
{ $$ = new AstRefDType($<fl>1, *$1);
// // If idAny below is a class, parameter_value is legal
// // If idAny below is a package, parameter_value is not legal
// // If idAny below is otherwise, not legal
idAny parameter_value_assignmentE
{ $$ = new AstParseRef($<fl>1, VParseRefExp::PX_TEXT, *$1, NULL, NULL);
if ($2) BBUNSUP($2->fileline(), "Unsupported: Parameterized classes"); }
// // package_sopeIdFollows expanded
| yD_UNIT yP_COLONCOLON
{ $$ = new AstParseRef($<fl>1, VParseRefExp::PX_TEXT, "$unit", NULL, NULL); }
| yLOCAL__COLONCOLON yP_COLONCOLON
{ $$ = new AstParseRef($<fl>1, VParseRefExp::PX_TEXT, "local", NULL, NULL);
BBUNSUP($1, "Unsupported: Randomize 'local::'"); }
;
//=========
@ -5627,17 +5631,9 @@ class_typeExtImpOne<refdtypep>: // IEEE: class_type: "id [ parameter_value_assig
// Each of these must end with {symsPackageDone | symsClassDone}
ps_id_etc<varrefp>: // package_scope + general id
package_scopeIdFollowsE varRefBase { $$ = $2; $2->packagep($1); }
package_scopeIdFollowsE varRefBase { $$ = $2; $2->packagep($1); }
;
ps_type<refdtypep>: // IEEE: ps_parameter_identifier | ps_type_identifier
// 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.
package_scopeIdFollowsE idRefDType { $$ = $2; $2->packagep($1); }
// // Simplify typing - from ps_covergroup_identifier
;
//=== Below rules assume special scoping per above
class_scopeWithoutId<nodep>: // class_type standalone without following id
@ -5680,13 +5676,15 @@ package_scopeIdFollowsE<packagep>: // IEEE: [package_scope]
package_scopeIdFollows<packagep>: // IEEE: package_scope
// // IMPORTANT: The lexer will parse the following ID to be in the found package
// // Also see class_typeExtImpOne which has these rules too
// //vv mid rule action needed otherwise we might not have NextId in time to parse the id token
yD_UNIT { SYMP->nextId(PARSEP->rootp()); }
/*cont*/ yP_COLONCOLON { $$ = GRAMMARP->unitPackage($<fl>1); }
| yaID__aPACKAGE { SYMP->nextId($<scp>1); }
yaID__aPACKAGE { SYMP->nextId($<scp>1); }
/*cont*/ yP_COLONCOLON { $$ = VN_CAST($<scp>1, Package); }
//UNSUP yLOCAL__COLONCOLON { PARSEP->symTableNextId($<scp>1); }
//UNSUP /*cont*/ yP_COLONCOLON { UNSUP }
| yD_UNIT yP_COLONCOLON
{ SYMP->nextId(PARSEP->rootp()); $$ = GRAMMARP->unitPackage($<fl>1); }
| yLOCAL__COLONCOLON yP_COLONCOLON
{ BBUNSUP($1, "Unsupported: Randomize 'local::'");
SYMP->nextId(PARSEP->rootp()); $$ = GRAMMARP->unitPackage($<fl>1); }
;
//^^^=========

View File

@ -1,10 +1,19 @@
%Error: t/t_class_extends.v:13:21: Unsupported: class extends
13 | class Base1 extends Base0;
| ^~~~~
%Error: t/t_class_extends.v:13:21: Found definition of 'Base0' as a CLASS but expected a variable
13 | class Base1 extends Base0;
| ^~~~~
%Error: t/t_class_extends.v:17:21: Unsupported: class extends
17 | class Base2 extends Base1;
| ^~~~~
%Error: t/t_class_extends.v:17:21: Found definition of 'Base1' as a CLASS but expected a variable
17 | class Base2 extends Base1;
| ^~~~~
%Error: t/t_class_extends.v:21:19: Unsupported: class extends
21 | class Cls extends Base2;
| ^~~~~
%Error: t/t_class_extends.v:21:19: Found definition of 'Base2' as a CLASS but expected a variable
21 | class Cls extends Base2;
| ^~~~~
%Error: Exiting due to

View File

@ -1,4 +1,7 @@
%Error: t/t_class_member_bad.v:11:20: Unsupported: class extends
11 | class Cls2 extends Base1;
| ^~~~~
%Error: t/t_class_member_bad.v:11:20: Found definition of 'Base1' as a CLASS but expected a variable
11 | class Cls2 extends Base1;
| ^~~~~
%Error: Exiting due to

View File

@ -1,4 +1,7 @@
%Error: t/t_class_method_bad.v:11:20: Unsupported: class extends
11 | class Cls2 extends Base1;
| ^~~~~
%Error: t/t_class_method_bad.v:11:20: Found definition of 'Base1' as a CLASS but expected a variable
11 | class Cls2 extends Base1;
| ^~~~~
%Error: Exiting due to

View File

@ -0,0 +1,7 @@
%Error: t/t_gen_defparam_unsup_bad.v:9:16: Unsupported: defparam with more than one dot
9 | defparam a.b.W = 3;
| ^
%Error: t/t_gen_defparam_unsup_bad.v:9:17: syntax error, unexpected IDENTIFIER, expecting ',' or ';'
9 | defparam a.b.W = 3;
| ^
%Error: Exiting due to

View File

@ -0,0 +1,19 @@
#!/usr/bin/env perl
if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); die; }
# DESCRIPTION: Verilator: Verilog Test driver/expect definition
#
# Copyright 2003 by Wilson Snyder. This program is free software; you
# can redistribute it and/or modify it under the terms of either the GNU
# Lesser General Public License Version 3 or the Perl Artistic License
# Version 2.0.
# SPDX-License-Identifier: LGPL-3.0-only OR Artistic-2.0
scenarios(vlt => 1);
lint(
fails => 1,
expect_filename => $Self->{golden_filename},
);
ok(1);
1;

View File

@ -0,0 +1,18 @@
// DESCRIPTION: Verilator: Verilog Test module
//
// This file ONLY is placed under the Creative Commons Public Domain, for
// any use, without warranty, 2012 by Wilson Snyder.
// SPDX-License-Identifier: CC0-1.0
module t (/*AUTOARG*/);
a a ();
defparam a.b.W = 3;
endmodule
module a;
b b();
endmodule
module b;
parameter W = 0;
endmodule