Support --bbox-unsup parsing of class extend typedefs

This commit is contained in:
Wilson Snyder 2020-06-09 20:59:45 -04:00
parent 91f30af01f
commit cef56c6fca
5 changed files with 95 additions and 36 deletions

View File

@ -145,11 +145,19 @@ public:
return NULL; return NULL;
} }
} }
void importExtends(AstNode* classp) {
// Import from package::id_or_star to this
VSymEnt* symp = getTable(classp);
UASSERT_OBJ(symp, classp, // Internal problem, because we earlier found it
"Extends class package not found");
// Walk old sym table and reinsert into current table
// We let V3LinkDot report the error instead of us
symCurrentp()->importFromClass(&m_syms, symp);
}
void importItem(AstNode* packagep, const string& id_or_star) { void importItem(AstNode* packagep, const string& id_or_star) {
// Import from package::id_or_star to this // Import from package::id_or_star to this
VSymEnt* symp = getTable(packagep); VSymEnt* symp = getTable(packagep);
UASSERT_OBJ(symp, packagep, UASSERT_OBJ(symp, packagep, // Internal problem, because we earlier found it
// Internal problem, because we earlier found pkg in parsing
"Import package not found"); "Import package not found");
// Walk old sym table and reinsert into current table // Walk old sym table and reinsert into current table
// We let V3LinkDot report the error instead of us // We let V3LinkDot report the error instead of us
@ -158,8 +166,7 @@ public:
void exportItem(AstNode* packagep, const string& id_or_star) { void exportItem(AstNode* packagep, const string& id_or_star) {
// Export from this the remote package::id_or_star // Export from this the remote package::id_or_star
VSymEnt* symp = getTable(packagep); VSymEnt* symp = getTable(packagep);
UASSERT_OBJ(symp, packagep, UASSERT_OBJ(symp, packagep, // Internal problem, because we earlier found it
// Internal problem, because we earlier found pkg in parsing
"Export package not found"); "Export package not found");
symCurrentp()->exportFromPackage(&m_syms, symp, id_or_star); symCurrentp()->exportFromPackage(&m_syms, symp, id_or_star);
} }

View File

@ -181,8 +181,10 @@ public:
} }
private: private:
void importOneSymbol(VSymGraph* graphp, const string& name, const VSymEnt* srcp) { void importOneSymbol(VSymGraph* graphp, const string& name, const VSymEnt* srcp,
if (srcp->exported() && !findIdFlat(name)) { // Don't insert over existing entry bool honorExport) {
if ((!honorExport || srcp->exported())
&& !findIdFlat(name)) { // Don't insert over existing entry
VSymEnt* symp = new VSymEnt(graphp, srcp); VSymEnt* symp = new VSymEnt(graphp, srcp);
symp->exported(false); // Can't reimport an import without an export symp->exported(false); // Can't reimport an import without an export
symp->imported(true); symp->imported(true);
@ -198,15 +200,25 @@ private:
} }
public: public:
void importFromClass(VSymGraph* graphp, const VSymEnt* srcp) {
// Import tokens from source symbol table into this symbol table
// Used for classes in early parsing only to handle "extends"
for (IdNameMap::const_iterator it = srcp->m_idNameMap.begin();
it != srcp->m_idNameMap.end(); ++it) {
importOneSymbol(graphp, it->first, it->second, false);
}
}
void importFromPackage(VSymGraph* graphp, const VSymEnt* srcp, const string& id_or_star) { void importFromPackage(VSymGraph* graphp, const VSymEnt* srcp, const string& id_or_star) {
// Import tokens from source symbol table into this symbol table // Import tokens from source symbol table into this symbol table
if (id_or_star != "*") { if (id_or_star != "*") {
IdNameMap::const_iterator it = srcp->m_idNameMap.find(id_or_star); IdNameMap::const_iterator it = srcp->m_idNameMap.find(id_or_star);
if (it != srcp->m_idNameMap.end()) importOneSymbol(graphp, it->first, it->second); if (it != srcp->m_idNameMap.end()) {
importOneSymbol(graphp, it->first, it->second, true);
}
} else { } else {
for (IdNameMap::const_iterator it = srcp->m_idNameMap.begin(); for (IdNameMap::const_iterator it = srcp->m_idNameMap.begin();
it != srcp->m_idNameMap.end(); ++it) { it != srcp->m_idNameMap.end(); ++it) {
importOneSymbol(graphp, it->first, it->second); importOneSymbol(graphp, it->first, it->second, true);
} }
} }
} }

View File

@ -2519,7 +2519,7 @@ delay_control<nodep>: //== IEEE: delay_control
delay_value<nodep>: // ==IEEE:delay_value delay_value<nodep>: // ==IEEE:delay_value
// // IEEE: ps_identifier // // IEEE: ps_identifier
ps_id_etc { $$ = $1; } packageClassScopeE varRefBase { $$ = $2; $2->packagep($1); }
| yaINTNUM { $$ = new AstConst($<fl>1, *$1); } | yaINTNUM { $$ = new AstConst($<fl>1, *$1); }
| yaFLOATNUM { $$ = new AstConst($<fl>1, AstConst::RealDouble(), $1); } | yaFLOATNUM { $$ = new AstConst($<fl>1, AstConst::RealDouble(), $1); }
| timeNumAdjusted { $$ = $1; } | timeNumAdjusted { $$ = $1; }
@ -3824,10 +3824,16 @@ funcIdNew<ftaskp>: // IEEE: from class_constructor_declaration
tfIdScoped<strp>: // IEEE: part of function_body_declaration/task_body_declaration tfIdScoped<strp>: // IEEE: part of function_body_declaration/task_body_declaration
// // IEEE: [ interface_identifier '.' | class_scope ] function_identifier // // IEEE: [ interface_identifier '.' | class_scope ] function_identifier
id { $<fl>$=$<fl>1; $<strp>$ = $1; } id
| id/*interface_identifier*/ '.' id { $<fl>$=$<fl>3; $<strp>$ = $3; BBUNSUP($2, "Unsupported: Out of block function declaration"); } { $<fl>$ = $<fl>1; $<scp>$ = NULL; $<strp>$ = $1; }
| packageClassScope id { $<fl>$=$<fl>2; $<scp>$=$<scp>1; $<strp>$=$<strp>2; //
BBUNSUP($<fl>1, "Unsupported: Out of class block function declaration"); } | id/*interface_identifier*/ '.' id
{ $<fl>$ = $<fl>3; $<scp>$ = NULL; $<strp>$ = $3;
BBUNSUP($2, "Unsupported: Out of block function declaration"); }
//
| packageClassScope id
{ $<fl>$ = $<fl>2; $<scp>$ = $<scp>1; $<strp>$ = $<strp>2;
BBUNSUP($<fl>1, "Unsupported: Out of class block function declaration"); }
; ;
tfGuts<nodep>: tfGuts<nodep>:
@ -5762,13 +5768,16 @@ class_declaration<nodep>: // ==IEEE: part of class_declaration
// // The classExtendsE rule relys on classFront having the // // The classExtendsE rule relys on classFront having the
// // new class scope correct via classFront // // new class scope correct via classFront
classFront parameter_port_listE classExtendsE classImplementsE ';' classFront parameter_port_listE classExtendsE classImplementsE ';'
/*mid*/ { // Allow resolving types declared in base extends class
if ($<scp>3) SYMP->importExtends($<scp>3);
}
/*cont*/ class_itemListE yENDCLASS endLabelE /*cont*/ class_itemListE yENDCLASS endLabelE
{ $$ = $1; $1->addMembersp($2); { $$ = $1; $1->addMembersp($2);
$1->extendsp($3); $1->extendsp($3);
$1->addMembersp($4); $1->addMembersp($4);
$1->addMembersp($6); $1->addMembersp($7);
SYMP->popScope($$); SYMP->popScope($$);
GRAMMARP->endLabel($<fl>7, $1, $8); } GRAMMARP->endLabel($<fl>7, $1, $9); }
; ;
classFront<classp>: // IEEE: part of class_declaration classFront<classp>: // IEEE: part of class_declaration
@ -5792,23 +5801,26 @@ classVirtualE:
classExtendsE<nodep>: // IEEE: part of class_declaration classExtendsE<nodep>: // IEEE: part of class_declaration
// // The classExtendsE rule relys on classFront having the // // The classExtendsE rule relys on classFront having the
// // new class scope correct via classFront // // new class scope correct via classFront
/* empty */ { $$ = NULL; } /* empty */ { $$ = NULL; $<scp>$ = NULL; }
| yEXTENDS classExtendsList { $$ = $2; } | yEXTENDS classExtendsList { $$ = $2; $<scp>$ = $<scp>2; }
; ;
classExtendsList<nodep>: // IEEE: part of class_declaration classExtendsList<nodep>: // IEEE: part of class_declaration
classExtendsOne { $$ = $1; } classExtendsOne { $$ = $1; $<scp>$ = $<scp>1; }
| classExtendsList ',' classExtendsOne | classExtendsList ',' classExtendsOne
{ $$ = $3; BBUNSUP($3, "Multiple inheritance illegal on non-interface classes (IEEE 1800-2017 8.13)" { $$ = $3; $<scp>$ = $<scp>3;
", and unsupported for interface classes."); } BBUNSUP($3, "Multiple inheritance illegal on non-interface classes (IEEE 1800-2017 8.13), "
"and unsupported for interface classes."); }
; ;
classExtendsOne<nodep>: // IEEE: part of class_declaration classExtendsOne<nodep>: // IEEE: part of class_declaration
class_typeExtImpList class_typeExtImpList
{ $$ = new AstClassExtends($1->fileline(), $1); } { $$ = new AstClassExtends($1->fileline(), $1);
// // IEEE: Might not be legal to have more than one set of parameters in an extends $<scp>$ = $<scp>1; }
//
| class_typeExtImpList '(' list_of_argumentsE ')' | class_typeExtImpList '(' list_of_argumentsE ')'
{ $$ = new AstClassExtends($1->fileline(), $1); { $$ = new AstClassExtends($1->fileline(), $1);
$<scp>$ = $<scp>1;
if ($3) BBUNSUP($3, "Unsupported: extends with parameters"); } if ($3) BBUNSUP($3, "Unsupported: extends with parameters"); }
; ;
@ -5827,9 +5839,9 @@ classImplementsList<nodep>: // IEEE: part of class_declaration
class_typeExtImpList<nodep>: // IEEE: class_type: "[package_scope] id [ parameter_value_assignment ]" class_typeExtImpList<nodep>: // IEEE: class_type: "[package_scope] id [ parameter_value_assignment ]"
// // but allow yaID__aTYPE for extends/implements // // but allow yaID__aTYPE for extends/implements
// // If you follow the rules down, class_type is really a list via ps_class_identifier // // If you follow the rules down, class_type is really a list via ps_class_identifier
class_typeExtImpOne { $$ = $1; } class_typeExtImpOne { $$ = $1; $<scp>$ = $<scp>1; }
| class_typeExtImpList yP_COLONCOLON class_typeExtImpOne | class_typeExtImpList yP_COLONCOLON class_typeExtImpOne
{ $$ = $3; { $$ = $3; $<scp>$ = $<scp>1;
// Cannot just add as next() as that breaks implements lists // Cannot just add as next() as that breaks implements lists
//UNSUP $$ = new AstDot($<fl>1, true, $1, $3); //UNSUP $$ = new AstDot($<fl>1, true, $1, $3);
BBUNSUP($2, "Unsupported: Hierarchical class references"); } BBUNSUP($2, "Unsupported: Hierarchical class references"); }
@ -5845,13 +5857,18 @@ class_typeExtImpOne<nodep>: // part of IEEE: class_type, where we either get a p
/*mid*/ { /* no nextId as not refing it above this*/ } /*mid*/ { /* no nextId as not refing it above this*/ }
/*cont*/ parameter_value_assignmentE /*cont*/ parameter_value_assignmentE
{ $$ = new AstParseRef($<fl>1, VParseRefExp::PX_TEXT, *$1, NULL, NULL); { $$ = new AstParseRef($<fl>1, VParseRefExp::PX_TEXT, *$1, NULL, NULL);
$<scp>$ = $<scp>1;
if ($3) BBUNSUP($3->fileline(), "Unsupported: Parameterized classes"); } if ($3) BBUNSUP($3->fileline(), "Unsupported: Parameterized classes"); }
//
// // package_sopeIdFollows expanded // // package_sopeIdFollows expanded
| yD_UNIT yP_COLONCOLON | yD_UNIT yP_COLONCOLON
{ $$ = new AstParseRef($<fl>1, VParseRefExp::PX_TEXT, "$unit", NULL, NULL); { $$ = new AstParseRef($<fl>1, VParseRefExp::PX_TEXT, "$unit", NULL, NULL);
$<scp>$ = NULL; // No purpose otherwise, every symtab can see root
SYMP->nextId(PARSEP->rootp()); } SYMP->nextId(PARSEP->rootp()); }
//
| yLOCAL__COLONCOLON yP_COLONCOLON | yLOCAL__COLONCOLON yP_COLONCOLON
{ $$ = new AstParseRef($<fl>1, VParseRefExp::PX_TEXT, "local", NULL, NULL); { $$ = new AstParseRef($<fl>1, VParseRefExp::PX_TEXT, "local", NULL, NULL);
$<scp>$ = NULL; // UNSUP
SYMP->nextId(PARSEP->rootp()); SYMP->nextId(PARSEP->rootp());
BBUNSUP($1, "Unsupported: Randomize 'local::'"); } BBUNSUP($1, "Unsupported: Randomize 'local::'"); }
; ;
@ -5861,10 +5878,6 @@ class_typeExtImpOne<nodep>: // part of IEEE: class_type, where we either get a p
// must be included in the rules below. // must be included in the rules below.
// Each of these must end with {symsPackageDone | symsClassDone} // Each of these must end with {symsPackageDone | symsClassDone}
ps_id_etc<varrefp>: // package_scope + general id
packageClassScopeE varRefBase { $$ = $2; $2->packagep($1); }
;
//=== Below rules assume special scoping per above //=== Below rules assume special scoping per above
packageClassScopeNoId<packagep>: // IEEE: [package_scope] not followed by yaID packageClassScopeNoId<packagep>: // IEEE: [package_scope] not followed by yaID
@ -5885,6 +5898,7 @@ packageClassScope<packagep>: // IEEE: class_scope + type
// // IMPORTANT: The lexer will parse the following ID to be in the found package // // IMPORTANT: The lexer will parse the following ID to be in the found package
// // if not needed must use packageClassScopeNoId // // if not needed must use packageClassScopeNoId
// // In this parser <package_identifier>:: and <class_identifier>:: are indistinguishible // // In this parser <package_identifier>:: and <class_identifier>:: are indistinguishible
// // This copies <scp> to document it is important
packageClassScopeList { $$ = $1; $<scp>$ = $<scp>1; } packageClassScopeList { $$ = $1; $<scp>$ = $<scp>1; }
| localNextId yP_COLONCOLON { $$ = $1; $<scp>$ = $<scp>1; } | localNextId yP_COLONCOLON { $$ = $1; $<scp>$ = $<scp>1; }
| dollarUnitNextId yP_COLONCOLON { $$ = $1; $<scp>$ = $<scp>1; } | dollarUnitNextId yP_COLONCOLON { $$ = $1; $<scp>$ = $<scp>1; }

View File

@ -4,16 +4,25 @@
%Error: t/t_class_extends.v:13:21: Found definition of 'Base0' as a CLASS but expected a variable %Error: t/t_class_extends.v:13:21: Found definition of 'Base0' as a CLASS but expected a variable
13 | class Base1 extends Base0; 13 | class Base1 extends Base0;
| ^~~~~ | ^~~~~
%Error-UNSUPPORTED: t/t_class_extends.v:17:21: Unsupported: class extends %Error-UNSUPPORTED: t/t_class_extends.v:18:21: Unsupported: class extends
17 | class Base2 extends Base1; 18 | class Base2 extends Base1;
| ^~~~~ | ^~~~~
%Error: t/t_class_extends.v:17:21: Found definition of 'Base1' as a CLASS but expected a variable %Error: t/t_class_extends.v:18:21: Found definition of 'Base1' as a CLASS but expected a variable
17 | class Base2 extends Base1; 18 | class Base2 extends Base1;
| ^~~~~ | ^~~~~
%Error-UNSUPPORTED: t/t_class_extends.v:21:19: Unsupported: class extends %Error-UNSUPPORTED: t/t_class_extends.v:22:19: Unsupported: class extends
21 | class Cls extends Base2; 22 | class Cls extends Base2;
| ^~~~~ | ^~~~~
%Error: t/t_class_extends.v:21:19: Found definition of 'Base2' as a CLASS but expected a variable %Error: t/t_class_extends.v:22:19: Found definition of 'Base2' as a CLASS but expected a variable
21 | class Cls extends Base2; 22 | class Cls extends Base2;
| ^~~~~ | ^~~~~
%Error: t/t_class_extends.v:25:4: Can't find typedef: 'T'
25 | T imemberc;
| ^
%Error-UNSUPPORTED: t/t_class_extends.v:33:43: Unsupported: class extends
33 | class uvm__registry #(type T=int) extends uvm_object_wrapper;
| ^~~~~~~~~~~~~~~~~~
%Error: t/t_class_extends.v:33:43: Found definition of 'uvm_object_wrapper' as a CLASS but expected a variable
33 | class uvm__registry #(type T=int) extends uvm_object_wrapper;
| ^~~~~~~~~~~~~~~~~~
%Error: Exiting due to %Error: Exiting due to

View File

@ -12,6 +12,7 @@ endclass
class Base1 extends Base0; class Base1 extends Base0;
int b1member; int b1member;
typedef int T;
endclass endclass
class Base2 extends Base1; class Base2 extends Base1;
@ -21,8 +22,22 @@ endclass
class Cls extends Base2; class Cls extends Base2;
int imembera; int imembera;
int imemberb; int imemberb;
T imemberc;
endclass : Cls endclass : Cls
class uvm_object_wrapper;
function int create ();
endfunction
endclass
class uvm__registry #(type T=int) extends uvm_object_wrapper;
// This override must be in the new symbol table, not
// under the extend's symbol table
function int create ();
T obj;
endfunction
endclass
module t (/*AUTOARG*/); module t (/*AUTOARG*/);
initial begin initial begin
Cls c; Cls c;
@ -31,11 +46,13 @@ module t (/*AUTOARG*/);
c.b2member = 30; c.b2member = 30;
c.imembera = 100; c.imembera = 100;
c.imemberb = 110; c.imemberb = 110;
c.imemberc = 120;
$display("Display: set = \"%p\"", c); // '{all 4 members} $display("Display: set = \"%p\"", c); // '{all 4 members}
if (c.b1member != 10) $stop; if (c.b1member != 10) $stop;
if (c.b2member != 30) $stop; if (c.b2member != 30) $stop;
if (c.imembera != 100) $stop; if (c.imembera != 100) $stop;
if (c.imemberb != 110) $stop; if (c.imemberb != 110) $stop;
if (c.imemberc != 120) $stop;
$write("*-* All Finished *-*\n"); $write("*-* All Finished *-*\n");
$finish; $finish;
end end