From cef56c6fca5a7b28ddbf729ad94fe14ded074cbc Mon Sep 17 00:00:00 2001 From: Wilson Snyder Date: Tue, 9 Jun 2020 20:59:45 -0400 Subject: [PATCH] Support --bbox-unsup parsing of class extend typedefs --- src/V3ParseSym.h | 15 ++++++--- src/V3SymTable.h | 20 ++++++++--- src/verilog.y | 54 +++++++++++++++++++----------- test_regress/t/t_class_extends.out | 25 +++++++++----- test_regress/t/t_class_extends.v | 17 ++++++++++ 5 files changed, 95 insertions(+), 36 deletions(-) diff --git a/src/V3ParseSym.h b/src/V3ParseSym.h index 474b4630b..2befc7669 100644 --- a/src/V3ParseSym.h +++ b/src/V3ParseSym.h @@ -145,11 +145,19 @@ public: 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) { // Import from package::id_or_star to this VSymEnt* symp = getTable(packagep); - UASSERT_OBJ(symp, packagep, - // Internal problem, because we earlier found pkg in parsing + UASSERT_OBJ(symp, packagep, // Internal problem, because we earlier found it "Import package not found"); // Walk old sym table and reinsert into current table // We let V3LinkDot report the error instead of us @@ -158,8 +166,7 @@ public: void exportItem(AstNode* packagep, const string& id_or_star) { // Export from this the remote package::id_or_star VSymEnt* symp = getTable(packagep); - UASSERT_OBJ(symp, packagep, - // Internal problem, because we earlier found pkg in parsing + UASSERT_OBJ(symp, packagep, // Internal problem, because we earlier found it "Export package not found"); symCurrentp()->exportFromPackage(&m_syms, symp, id_or_star); } diff --git a/src/V3SymTable.h b/src/V3SymTable.h index 10dd2f439..a6d66421e 100644 --- a/src/V3SymTable.h +++ b/src/V3SymTable.h @@ -181,8 +181,10 @@ public: } private: - void importOneSymbol(VSymGraph* graphp, const string& name, const VSymEnt* srcp) { - if (srcp->exported() && !findIdFlat(name)) { // Don't insert over existing entry + void importOneSymbol(VSymGraph* graphp, const string& name, const VSymEnt* srcp, + bool honorExport) { + if ((!honorExport || srcp->exported()) + && !findIdFlat(name)) { // Don't insert over existing entry VSymEnt* symp = new VSymEnt(graphp, srcp); symp->exported(false); // Can't reimport an import without an export symp->imported(true); @@ -198,15 +200,25 @@ private: } 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) { // Import tokens from source symbol table into this symbol table if (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 { for (IdNameMap::const_iterator it = srcp->m_idNameMap.begin(); it != srcp->m_idNameMap.end(); ++it) { - importOneSymbol(graphp, it->first, it->second); + importOneSymbol(graphp, it->first, it->second, true); } } } diff --git a/src/verilog.y b/src/verilog.y index 889e1b7a5..2013bf334 100644 --- a/src/verilog.y +++ b/src/verilog.y @@ -2519,7 +2519,7 @@ delay_control: //== IEEE: delay_control delay_value: // ==IEEE:delay_value // // IEEE: ps_identifier - ps_id_etc { $$ = $1; } + packageClassScopeE varRefBase { $$ = $2; $2->packagep($1); } | yaINTNUM { $$ = new AstConst($1, *$1); } | yaFLOATNUM { $$ = new AstConst($1, AstConst::RealDouble(), $1); } | timeNumAdjusted { $$ = $1; } @@ -3824,10 +3824,16 @@ funcIdNew: // IEEE: from class_constructor_declaration tfIdScoped: // IEEE: part of function_body_declaration/task_body_declaration // // IEEE: [ interface_identifier '.' | class_scope ] function_identifier - id { $$=$1; $$ = $1; } - | id/*interface_identifier*/ '.' id { $$=$3; $$ = $3; BBUNSUP($2, "Unsupported: Out of block function declaration"); } - | packageClassScope id { $$=$2; $$=$1; $$=$2; - BBUNSUP($1, "Unsupported: Out of class block function declaration"); } + id + { $$ = $1; $$ = NULL; $$ = $1; } + // + | id/*interface_identifier*/ '.' id + { $$ = $3; $$ = NULL; $$ = $3; + BBUNSUP($2, "Unsupported: Out of block function declaration"); } + // + | packageClassScope id + { $$ = $2; $$ = $1; $$ = $2; + BBUNSUP($1, "Unsupported: Out of class block function declaration"); } ; tfGuts: @@ -5762,13 +5768,16 @@ class_declaration: // ==IEEE: part of class_declaration // // The classExtendsE rule relys on classFront having the // // new class scope correct via classFront classFront parameter_port_listE classExtendsE classImplementsE ';' + /*mid*/ { // Allow resolving types declared in base extends class + if ($3) SYMP->importExtends($3); + } /*cont*/ class_itemListE yENDCLASS endLabelE { $$ = $1; $1->addMembersp($2); $1->extendsp($3); $1->addMembersp($4); - $1->addMembersp($6); + $1->addMembersp($7); SYMP->popScope($$); - GRAMMARP->endLabel($7, $1, $8); } + GRAMMARP->endLabel($7, $1, $9); } ; classFront: // IEEE: part of class_declaration @@ -5792,23 +5801,26 @@ classVirtualE: classExtendsE: // IEEE: part of class_declaration // // The classExtendsE rule relys on classFront having the // // new class scope correct via classFront - /* empty */ { $$ = NULL; } - | yEXTENDS classExtendsList { $$ = $2; } + /* empty */ { $$ = NULL; $$ = NULL; } + | yEXTENDS classExtendsList { $$ = $2; $$ = $2; } ; classExtendsList: // IEEE: part of class_declaration - classExtendsOne { $$ = $1; } + classExtendsOne { $$ = $1; $$ = $1; } | classExtendsList ',' classExtendsOne - { $$ = $3; BBUNSUP($3, "Multiple inheritance illegal on non-interface classes (IEEE 1800-2017 8.13)" - ", and unsupported for interface classes."); } + { $$ = $3; $$ = $3; + BBUNSUP($3, "Multiple inheritance illegal on non-interface classes (IEEE 1800-2017 8.13), " + "and unsupported for interface classes."); } ; classExtendsOne: // IEEE: part of class_declaration class_typeExtImpList - { $$ = new AstClassExtends($1->fileline(), $1); } - // // IEEE: Might not be legal to have more than one set of parameters in an extends + { $$ = new AstClassExtends($1->fileline(), $1); + $$ = $1; } + // | class_typeExtImpList '(' list_of_argumentsE ')' { $$ = new AstClassExtends($1->fileline(), $1); + $$ = $1; if ($3) BBUNSUP($3, "Unsupported: extends with parameters"); } ; @@ -5827,9 +5839,9 @@ classImplementsList: // IEEE: part of class_declaration class_typeExtImpList: // 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 - class_typeExtImpOne { $$ = $1; } + class_typeExtImpOne { $$ = $1; $$ = $1; } | class_typeExtImpList yP_COLONCOLON class_typeExtImpOne - { $$ = $3; + { $$ = $3; $$ = $1; // Cannot just add as next() as that breaks implements lists //UNSUP $$ = new AstDot($1, true, $1, $3); BBUNSUP($2, "Unsupported: Hierarchical class references"); } @@ -5845,13 +5857,18 @@ class_typeExtImpOne: // part of IEEE: class_type, where we either get a p /*mid*/ { /* no nextId as not refing it above this*/ } /*cont*/ parameter_value_assignmentE { $$ = new AstParseRef($1, VParseRefExp::PX_TEXT, *$1, NULL, NULL); + $$ = $1; if ($3) BBUNSUP($3->fileline(), "Unsupported: Parameterized classes"); } + // // // package_sopeIdFollows expanded | yD_UNIT yP_COLONCOLON { $$ = new AstParseRef($1, VParseRefExp::PX_TEXT, "$unit", NULL, NULL); + $$ = NULL; // No purpose otherwise, every symtab can see root SYMP->nextId(PARSEP->rootp()); } + // | yLOCAL__COLONCOLON yP_COLONCOLON { $$ = new AstParseRef($1, VParseRefExp::PX_TEXT, "local", NULL, NULL); + $$ = NULL; // UNSUP SYMP->nextId(PARSEP->rootp()); BBUNSUP($1, "Unsupported: Randomize 'local::'"); } ; @@ -5861,10 +5878,6 @@ class_typeExtImpOne: // part of IEEE: class_type, where we either get a p // must be included in the rules below. // Each of these must end with {symsPackageDone | symsClassDone} -ps_id_etc: // package_scope + general id - packageClassScopeE varRefBase { $$ = $2; $2->packagep($1); } - ; - //=== Below rules assume special scoping per above packageClassScopeNoId: // IEEE: [package_scope] not followed by yaID @@ -5885,6 +5898,7 @@ packageClassScope: // IEEE: class_scope + type // // IMPORTANT: The lexer will parse the following ID to be in the found package // // if not needed must use packageClassScopeNoId // // In this parser :: and :: are indistinguishible + // // This copies to document it is important packageClassScopeList { $$ = $1; $$ = $1; } | localNextId yP_COLONCOLON { $$ = $1; $$ = $1; } | dollarUnitNextId yP_COLONCOLON { $$ = $1; $$ = $1; } diff --git a/test_regress/t/t_class_extends.out b/test_regress/t/t_class_extends.out index 81442acc4..c839d805a 100644 --- a/test_regress/t/t_class_extends.out +++ b/test_regress/t/t_class_extends.out @@ -4,16 +4,25 @@ %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-UNSUPPORTED: t/t_class_extends.v:17:21: Unsupported: class extends - 17 | class Base2 extends Base1; +%Error-UNSUPPORTED: t/t_class_extends.v:18:21: Unsupported: class extends + 18 | 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:18:21: Found definition of 'Base1' as a CLASS but expected a variable + 18 | class Base2 extends Base1; | ^~~~~ -%Error-UNSUPPORTED: t/t_class_extends.v:21:19: Unsupported: class extends - 21 | class Cls extends Base2; +%Error-UNSUPPORTED: t/t_class_extends.v:22:19: Unsupported: class extends + 22 | 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: t/t_class_extends.v:22:19: Found definition of 'Base2' as a CLASS but expected a variable + 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 diff --git a/test_regress/t/t_class_extends.v b/test_regress/t/t_class_extends.v index 66120b89c..f439ede91 100644 --- a/test_regress/t/t_class_extends.v +++ b/test_regress/t/t_class_extends.v @@ -12,6 +12,7 @@ endclass class Base1 extends Base0; int b1member; + typedef int T; endclass class Base2 extends Base1; @@ -21,8 +22,22 @@ endclass class Cls extends Base2; int imembera; int imemberb; + T imemberc; 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*/); initial begin Cls c; @@ -31,11 +46,13 @@ module t (/*AUTOARG*/); c.b2member = 30; c.imembera = 100; c.imemberb = 110; + c.imemberc = 120; $display("Display: set = \"%p\"", c); // '{all 4 members} if (c.b1member != 10) $stop; if (c.b2member != 30) $stop; if (c.imembera != 100) $stop; if (c.imemberb != 110) $stop; + if (c.imemberc != 120) $stop; $write("*-* All Finished *-*\n"); $finish; end