From a3bbf135061126ba2ecfded8bc32e8ba3dade504 Mon Sep 17 00:00:00 2001 From: Wilson Snyder Date: Wed, 25 Sep 2024 20:41:49 -0400 Subject: [PATCH] Internals: Minor parser reorgs in prep for future pull. No functional change intended. --- src/V3ParseImp.cpp | 22 +++++++++++----- src/V3ParseImp.h | 1 + src/verilog.y | 40 ++++++++++++++++++++++------- test_regress/t/t_typedef_id_bad.out | 4 +++ test_regress/t/t_typedef_id_bad.py | 16 ++++++++++++ test_regress/t/t_typedef_id_bad.v | 10 ++++++++ 6 files changed, 77 insertions(+), 16 deletions(-) create mode 100644 test_regress/t/t_typedef_id_bad.out create mode 100755 test_regress/t/t_typedef_id_bad.py create mode 100644 test_regress/t/t_typedef_id_bad.v diff --git a/src/V3ParseImp.cpp b/src/V3ParseImp.cpp index fc6d979df..1a8076be4 100644 --- a/src/V3ParseImp.cpp +++ b/src/V3ParseImp.cpp @@ -447,6 +447,20 @@ size_t V3ParseImp::tokenPipeScanTypeEq(size_t depth) { return depth; } +int V3ParseImp::tokenPipelineId(int token) { + const V3ParseBisonYYSType* nexttokp = tokenPeekp(0); // First char after yaID + const int nexttok = nexttokp->token; + UASSERT(yylval.token == yaID__LEX, "Start with ID"); + if (nexttok == yP_COLONCOLON) { return yaID__CC; } + VL_RESTORER(yylval); // Remember value, as about to read ahead + if (nexttok == '#') { + VL_RESTORER(yylval); // Remember value, as about to read ahead + const size_t depth = tokenPipeScanParam(0); + if (tokenPeekp(depth)->token == yP_COLONCOLON) return yaID__CC; + } + return token; +} + void V3ParseImp::tokenPipeline() { // called from bison's "yylex", has a "this" if (m_tokensAhead.empty()) tokenPull(); // corrupts yylval @@ -552,13 +566,7 @@ void V3ParseImp::tokenPipeline() { token = yWITH__ETC; } } else if (token == yaID__LEX) { - if (nexttok == yP_COLONCOLON) { - token = yaID__CC; - } else if (nexttok == '#') { - VL_RESTORER(yylval); // Remember value, as about to read ahead - const size_t depth = tokenPipeScanParam(0); - if (tokenPeekp(depth)->token == yP_COLONCOLON) token = yaID__CC; - } + token = tokenPipelineId(token); } // If add to above "else if", also add to "if (token" further above } diff --git a/src/V3ParseImp.h b/src/V3ParseImp.h index 6570b5146..738323ffd 100644 --- a/src/V3ParseImp.h +++ b/src/V3ParseImp.h @@ -302,6 +302,7 @@ private: void yylexReadTok() VL_MT_DISABLED; void tokenPull() VL_MT_DISABLED; void tokenPipeline() VL_MT_DISABLED; // Internal; called from tokenToBison + int tokenPipelineId(int token) VL_MT_DISABLED; void tokenPipelineSym() VL_MT_DISABLED; size_t tokenPipeScanParam(size_t depth) VL_MT_DISABLED; size_t tokenPipeScanTypeEq(size_t depth) VL_MT_DISABLED; diff --git a/src/verilog.y b/src/verilog.y index 18be2aba6..ec95425b2 100644 --- a/src/verilog.y +++ b/src/verilog.y @@ -1412,12 +1412,17 @@ udpFront: SYMP->pushNew($$); } ; -parameter_value_assignmentE: // IEEE: [ parameter_value_assignment ] +parameter_value_assignmentInstE: // IEEE: [ parameter_value_assignment ] for instance /* empty */ { $$ = nullptr; } - | parameter_value_assignment { $$ = $1; } + | parameter_value_assignmentInst { $$ = $1; } ; -parameter_value_assignment: // IEEE: parameter_value_assignment +parameter_value_assignmentClassE: // IEEE: [ parameter_value_assignment ] for classes + /* empty */ { $$ = nullptr; } + | parameter_value_assignmentClass { $$ = $1; } + ; + +parameter_value_assignmentInst: // IEEE: parameter_value_assignment for instance '#' '(' cellparamListE ')' { $$ = $3; } // // Parentheses are optional around a single parameter | '#' yaINTNUM { $$ = new AstPin{$2, 1, "", new AstConst{$2, *$2}}; } @@ -3242,7 +3247,7 @@ instDecl: // // Currently disambiguated from data_declaration based on // // VARs being type, and cells non-type. // // IEEE requires a '(' to disambiguate, we need TODO force this - id parameter_value_assignmentE + id parameter_value_assignmentInstE /*mid*/ { INSTPREP($1, *$1, $2); } /*cont*/ instnameList ';' { $$ = $4; @@ -4506,7 +4511,14 @@ property_actual_arg: // ==IEEE: property_actual_arg exprOrDataType: // expr | data_type: combined to prevent conflicts expr { $$ = $1; } // // data_type includes id that overlaps expr, so special flavor - | data_type { $$ = $1; } + // // data_type expanded: + | data_typeNoRef { $$ = $1; } + | packageClassScopeE idType packed_dimensionListE + { AstRefDType* const refp = new AstRefDType{$2, *$2, $1, nullptr}; + $$ = GRAMMARP->createArray(refp, $3, true); } + | packageClassScopeE idType parameter_value_assignmentClass packed_dimensionListE + { AstRefDType* const refp = new AstRefDType{$2, *$2, $1, $3}; + $$ = GRAMMARP->createArray(refp, $4, true); } // // not in spec, but needed for $past(sig,1,,@(posedge clk)) //UNSUP event_control { } ; @@ -4634,10 +4646,20 @@ funcId: // IEEE: function_data_type_or_implicit + part o { $$ = $2; $$->fvarp(new AstBasicDType{$2, LOGIC_IMPLICIT, $1}); SYMP->pushNewUnderNodeOrCurrent($$, $2); } - | data_type fIdScoped + | data_typeNoRef fIdScoped { $$ = $2; $$->fvarp($1); SYMP->pushNewUnderNodeOrCurrent($$, $2); } + | packageClassScopeE idType packed_dimensionListE fIdScoped + { AstRefDType* const refp = new AstRefDType{$2, *$2, $1, nullptr}; + $$ = $4; + $$->fvarp(GRAMMARP->createArray(refp, $3, true)); + SYMP->pushNewUnderNodeOrCurrent($$, $4); } + | packageClassScopeE idType parameter_value_assignmentClass packed_dimensionListE fIdScoped + { AstRefDType* const refp = new AstRefDType{$2, *$2, $1, $3}; + $$ = $5; + $$->fvarp(GRAMMARP->createArray(refp, $4, true)); + SYMP->pushNewUnderNodeOrCurrent($$, $5); } // // To verilator tasks are the same as void functions (we separately detect time passing) | yVOID taskId { $$ = $2; } @@ -7151,12 +7173,12 @@ class_typeExtImpOne: // part of IEEE: class_type, where we either ge // // If idAny below is otherwise, not legal idAny /*mid*/ { /* no nextId as not refing it above this*/ } - /*cont*/ parameter_value_assignmentE + /*cont*/ parameter_value_assignmentClassE { $$ = new AstClassOrPackageRef{$1, *$1, $1, $3}; $$ = $1; } | idCC /*mid*/ { /* no nextId as not refing it above this*/ } - /*cont*/ parameter_value_assignmentE + /*cont*/ parameter_value_assignmentClassE { $$ = new AstClassOrPackageRef{$1, *$1, $1, $3}; $$ = $1; } // @@ -7227,7 +7249,7 @@ packageClassScopeItem: // IEEE: package_scope or [package_scope]::[ /*cont*/ yP_COLONCOLON { $$ = new AstClassOrPackageRef{$1, *$1, $1, nullptr}; $$ = $1; } // - | idCC parameter_value_assignment + | idCC parameter_value_assignmentClass /*mid*/ { SYMP->nextId($1); } // Change next *after* we handle parameters, not before /*cont*/ yP_COLONCOLON { $$ = new AstClassOrPackageRef{$1, *$1, $1, $2}; $$ = $1; } diff --git a/test_regress/t/t_typedef_id_bad.out b/test_regress/t/t_typedef_id_bad.out new file mode 100644 index 000000000..f970a5c97 --- /dev/null +++ b/test_regress/t/t_typedef_id_bad.out @@ -0,0 +1,4 @@ +%Error: t/t_typedef_id_bad.v:9:34: Expecting a data type: 'i' + 9 | class Cls #(parameter type P_T = i); + | ^ +%Error: Exiting due to diff --git a/test_regress/t/t_typedef_id_bad.py b/test_regress/t/t_typedef_id_bad.py new file mode 100755 index 000000000..30c3d4f77 --- /dev/null +++ b/test_regress/t/t_typedef_id_bad.py @@ -0,0 +1,16 @@ +#!/usr/bin/env python3 +# DESCRIPTION: Verilator: Verilog Test driver/expect definition +# +# Copyright 2024 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 + +import vltest_bootstrap + +test.scenarios('linter') + +test.lint(fails=test.vlt_all, expect_filename=test.golden_filename) + +test.passes() diff --git a/test_regress/t/t_typedef_id_bad.v b/test_regress/t/t_typedef_id_bad.v new file mode 100644 index 000000000..fd4482a5f --- /dev/null +++ b/test_regress/t/t_typedef_id_bad.v @@ -0,0 +1,10 @@ +// DESCRIPTION: Verilator: Verilog Test module +// +// This file ONLY is placed under the Creative Commons Public Domain, for +// any use, without warranty, 2019 by Wilson Snyder. +// SPDX-License-Identifier: CC0-1.0 + +int i; + +class Cls #(parameter type P_T = i); +endclass