mirror of
https://github.com/verilator/verilator.git
synced 2025-01-06 06:37:45 +00:00
Internals: Parse extend/implements/etc using generic identifiers.
This commit is contained in:
parent
3cb3b6c400
commit
01f3e81a36
@ -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)
|
||||
};
|
||||
|
||||
|
@ -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
|
||||
|
@ -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); }
|
||||
;
|
||||
|
||||
//^^^=========
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
7
test_regress/t/t_gen_defparam_unsup_bad.out
Normal file
7
test_regress/t/t_gen_defparam_unsup_bad.out
Normal 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
|
19
test_regress/t/t_gen_defparam_unsup_bad.pl
Executable file
19
test_regress/t/t_gen_defparam_unsup_bad.pl
Executable 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;
|
18
test_regress/t/t_gen_defparam_unsup_bad.v
Normal file
18
test_regress/t/t_gen_defparam_unsup_bad.v
Normal 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
|
Loading…
Reference in New Issue
Block a user