From ffbd1fd47492806a96798fd4f0d8fe793b912b10 Mon Sep 17 00:00:00 2001 From: Wilson Snyder Date: Thu, 5 Nov 2009 09:57:23 -0500 Subject: [PATCH] Support "reg [1:0][1:0][1:0]", bug176. --- Changes | 2 + src/V3AstNodes.h | 8 ++- src/V3Link.cpp | 2 +- src/V3ParseImp.h | 2 +- src/verilog.y | 91 ++++++++++++++++++----------- test_regress/driver.pl | 2 +- test_regress/t/t_mem_packed.pl | 18 ++++++ test_regress/t/t_mem_packed.v | 45 +++++++++++++++ test_regress/t/t_trace_public.out | 96 +++++++++++++++++++++++++++++++ 9 files changed, 227 insertions(+), 39 deletions(-) create mode 100755 test_regress/t/t_mem_packed.pl create mode 100644 test_regress/t/t_mem_packed.v create mode 100644 test_regress/t/t_trace_public.out diff --git a/Changes b/Changes index 1bb8654ad..7da71d744 100644 --- a/Changes +++ b/Changes @@ -10,6 +10,8 @@ indicates the contributor was also the author of the fix; Thanks! *** Support void functions. +*** Support "reg [1:0][1:0][1:0]", bug176. [Byron Bradley] + * Verilator 3.720 2009/10/26 ** Support little endian bit vectors ("reg [0:2] x;"). diff --git a/src/V3AstNodes.h b/src/V3AstNodes.h index d9e840ba8..24d53c410 100644 --- a/src/V3AstNodes.h +++ b/src/V3AstNodes.h @@ -136,22 +136,23 @@ private: AstBasicDTypeKwd m_keyword; // What keyword created it bool m_implicit; // Implicitly declared public: - AstBasicDType(FileLine* fl, AstBasicDTypeKwd kwd, AstRange* rangep=NULL, AstSignedState signst=signedst_NOP) + AstBasicDType(FileLine* fl, AstBasicDTypeKwd kwd, AstSignedState signst=signedst_NOP) : AstNodeDType(fl) { - init(kwd, signst, rangep); + init(kwd, signst, NULL); } AstBasicDType(FileLine* fl, AstLogicPacked, int wantwidth) : AstNodeDType(fl) { init(AstBasicDTypeKwd::LOGIC, signedst_NOP, ((wantwidth > 1) ? new AstRange(fl, wantwidth-1, 0) : NULL)); } + // See also addRange in verilog.y private: void init(AstBasicDTypeKwd kwd, AstSignedState signst, AstRange* rangep) { m_keyword = kwd; // Implicitness: // "parameter X" is implicit and sized from initial value, "parameter reg x" not m_implicit = false; if (keyword()==AstBasicDTypeKwd::LOGIC_IMPLICIT) { - if (!rangep) m_implicit = true; + if (!rangep) m_implicit = true; // Also cleared if range added later m_keyword = AstBasicDTypeKwd::LOGIC; } if (signst == signedst_NOP && keyword().isSigned()) signst = signedst_SIGNED; @@ -191,6 +192,7 @@ public: int msbMaxSelect() const { return (lsb()<0 ? msb()-lsb() : msb()); } // Maximum value a [] select may index bool littleEndian() const { return (rangep() && rangep()->littleEndian()); } bool implicit() const { return m_implicit; } + void implicit(bool flag) { m_implicit = flag; } }; //###################################################################### diff --git a/src/V3Link.cpp b/src/V3Link.cpp index 0299058ff..58972c1aa 100644 --- a/src/V3Link.cpp +++ b/src/V3Link.cpp @@ -303,7 +303,7 @@ private: // If unspecified, function returns one bit; however when we support NEW() it could // also return the class reference. if (dtypep) dtypep->unlinkFrBack(); - else dtypep = new AstBasicDType(nodep->fileline(), AstBasicDTypeKwd::LOGIC, NULL); + else dtypep = new AstBasicDType(nodep->fileline(), AstBasicDTypeKwd::LOGIC); AstVar* newvarp = new AstVar(nodep->fileline(), AstVarType::OUTPUT, nodep->name(), dtypep); newvarp->isSigned(funcp->isSigned()); newvarp->funcReturn(true); diff --git a/src/V3ParseImp.h b/src/V3ParseImp.h index c5ae7e4fd..03f2784ec 100644 --- a/src/V3ParseImp.h +++ b/src/V3ParseImp.h @@ -62,7 +62,7 @@ struct V3ParseBisonYYSType { AstCaseItem* caseitemp; AstConst* constp; AstModule* modulep; - AstNodeDType* typep; + AstNodeDType* dtypep; AstNodeFTask* ftaskp; AstNodeSenItem* senitemp; AstNodeVarRef* varnodep; diff --git a/src/verilog.y b/src/verilog.y index 85db9e276..2f6ecb893 100644 --- a/src/verilog.y +++ b/src/verilog.y @@ -75,6 +75,7 @@ public: } // METHODS + AstNodeDType* createArray(AstNodeDType* basep, AstRange* rangep); AstVar* createVariable(FileLine* fileline, string name, AstRange* arrayp, AstNode* attrsp); AstNode* createSupplyExpr(FileLine* fileline, string name, int value); AstText* createTextQuoted(FileLine* fileline, string text) { @@ -95,6 +96,24 @@ public: if (m_varDTypep) { m_varDTypep->deleteTree(); m_varDTypep=NULL; } // It was cloned, so this is safe. m_varDTypep = dtypep; } + AstNodeDType* addRange(AstBasicDType* dtypep, AstRange* rangesp) { + if (!rangesp) { + return dtypep; + } else { + // Only the first range becomes the basicdtype range; everything else is arraying + AstRange* rangearraysp = NULL; + if (dtypep->rangep()) { + rangearraysp = rangesp; // Already a range; everything is an array + } else { + if (rangesp->nextp()) { + rangearraysp = rangesp->nextp()->unlinkFrBackWithNext()->castRange(); + } + dtypep->rangep(rangesp); + dtypep->implicit(false); + } + return createArray(dtypep, rangearraysp); + } + } string deQuote(FileLine* fileline, string text); }; @@ -632,7 +651,7 @@ port: // ==IEEE: port portDirNetE data_type portSig variable_dimensionListE sigAttrListE { $$=$3; VARDTYPE($2); $$->addNextNull(VARDONEP($$,$4,$5)); } //UNSUP portDirNetE yVAR data_type portSig variable_dimensionListE sigAttrListE { $$=$4; VARDTYPE($3); $$->addNextNull(VARDONEP($$,$5,$6)); } //UNSUP portDirNetE yVAR implicit_type portSig variable_dimensionListE sigAttrListE { $$=$4; VARDTYPE($3); $$->addNextNull(VARDONEP($$,$5,$6)); } - | portDirNetE signingE rangeList portSig variable_dimensionListE sigAttrListE { $$=$4; VARDTYPE(new AstBasicDType($3->fileline(), LOGIC_IMPLICIT, $3, $2)); $$->addNextNull(VARDONEP($$,$5,$6)); } + | portDirNetE signingE rangeList portSig variable_dimensionListE sigAttrListE { $$=$4; VARDTYPE(GRAMMARP->addRange(new AstBasicDType($3->fileline(), LOGIC_IMPLICIT, $2), $3)); $$->addNextNull(VARDONEP($$,$5,$6)); } | portDirNetE /*implicit*/ portSig variable_dimensionListE sigAttrListE { $$=$2; /*VARDTYPE-same*/ $$->addNextNull(VARDONEP($$,$3,$4)); } // | portDirNetE data_type portSig variable_dimensionListE sigAttrListE '=' constExpr { $$=$3; VARDTYPE($2); $$->addNextNull(VARDONEP($$,$4,$5)); $$->addNextNull(GRAMMARP->newVarInit($6,$$,$7)); } @@ -722,7 +741,7 @@ net_declaration: // IEEE: net_declaration - excluding implict ; net_declarationFront: // IEEE: beginning of net_declaration - net_declRESET net_type strengthSpecE signingE delayrange { VARDTYPE($5); $5->setSignedState($4); } + net_declRESET net_type strengthSpecE signingE delayrange { VARDTYPE($5); $5->basicp()->setSignedState($4); } ; net_declRESET: @@ -785,9 +804,9 @@ port_declaration: // ==IEEE: port_declaration list_of_variable_decl_assignments { $$ = $5; } //UNSUP port_directionReset port_declNetE yVAR data_type { VARDTYPE($4); } list_of_variable_decl_assignments { $$ = $6; } //UNSUP port_directionReset port_declNetE yVAR implicit_type { VARDTYPE($4); } list_of_variable_decl_assignments { $$ = $6; } - | port_directionReset port_declNetE signingE rangeList { VARDTYPE(new AstBasicDType($4->fileline(), LOGIC_IMPLICIT, $4, $3)); } + | port_directionReset port_declNetE signingE rangeList { VARDTYPE(GRAMMARP->addRange(new AstBasicDType($4->fileline(), LOGIC_IMPLICIT, $3),$4)); } list_of_variable_decl_assignments { $$ = $6; } - | port_directionReset port_declNetE signing { VARDTYPE(new AstBasicDType($3, LOGIC_IMPLICIT, NULL, $3)); } + | port_directionReset port_declNetE signing { VARDTYPE(new AstBasicDType($3, LOGIC_IMPLICIT, $3)); } list_of_variable_decl_assignments { $$ = $5; } | port_directionReset port_declNetE /*implicit*/ { VARDTYPE(NULL);/*default_nettype*/} list_of_variable_decl_assignments { $$ = $4; } @@ -831,7 +850,7 @@ signing: // ==IEEE: signing //************************************************ // Data Types -data_type: // ==IEEE: data_type +data_type: // ==IEEE: data_type // // This expansion also replicated elsewhere, IE data_type__AndID data_typeNoRef { $$ = $1; } // // IEEE: [ class_scope | package_scope ] type_identifier { packed_dimension } @@ -843,13 +862,13 @@ data_type: // ==IEEE: data_type //UNSUP ps_covergroup_identifier { $$ = $1; } ; -data_typeBasic: // IEEE: part of data_type - integer_vector_type signingE rangeListE { $$ = $1; $$->setSignedState($2); $$->rangep($3); } - | integer_atom_type signingE { $$ = $1; $$->setSignedState($2); } +data_typeBasic: // IEEE: part of data_type + integer_vector_type signingE rangeListE { $1->setSignedState($2); $$ = GRAMMARP->addRange($1,$3); } + | integer_atom_type signingE { $1->setSignedState($2); $$ = $1; } //UNSUP non_integer_type { UNSUP } ; -data_typeNoRef: // ==IEEE: data_type, excluding class_type etc references +data_typeNoRef: // ==IEEE: data_type, excluding class_type etc references data_typeBasic { $$ = $1; } //UNSUP ySTRUCT packedSigningE '{' struct_union_memberList '}' packed_dimensionE { UNSUP } //UNSUP yUNION taggedE packedSigningE '{' struct_union_memberList '}' packed_dimensionE { UNSUP } @@ -964,11 +983,11 @@ data_declarationVarFront: // IEEE: part of data_declaration // // = class_new is in variable_decl_assignment ; -implicit_type: // IEEE: part of *data_type_or_implicit +implicit_type: // IEEE: part of *data_type_or_implicit // // Also expanded in data_declaration /* empty */ { $$ = NULL; } - | signingE rangeList { $$ = new AstBasicDType($2->fileline(), LOGIC_IMPLICIT, $2, $1); } - | signing { $$ = new AstBasicDType($1, LOGIC_IMPLICIT, NULL, $1); } + | signingE rangeList { $$ = GRAMMARP->addRange(new AstBasicDType($2->fileline(), LOGIC_IMPLICIT, $1),$2); } + | signing { $$ = new AstBasicDType($1, LOGIC_IMPLICIT, $1); } ; //************************************************ @@ -1246,9 +1265,9 @@ rangeList: // IEEE: {packed_dimension} | rangeList anyrange { $$ = $1; $1->addNext($2); } ; -wirerangeE: - /* empty */ { $$ = new AstBasicDType(CRELINE(), LOGIC, NULL); } // not implicit - | anyrange { $$ = new AstBasicDType(CRELINE(), LOGIC, $1); } // not implicit +wirerangeE: + /* empty */ { $$ = new AstBasicDType(CRELINE(), LOGIC); } // not implicit + | anyrange { $$ = GRAMMARP->addRange(new AstBasicDType(CRELINE(), LOGIC),$1); } // not implicit ; // IEEE: select @@ -1258,7 +1277,7 @@ anyrange: '[' constExpr ':' constExpr ']' { $$ = new AstRange($1,$2,$4); } ; -delayrange: +delayrange: wirerangeE delayE { $$ = $1; } | ySCALARED wirerangeE delayE { $$ = $2; } | yVECTORED wirerangeE delayE { $$ = $2; } @@ -1782,15 +1801,15 @@ funcId: // IEEE: function_data_type_or_implicit + part of function_bod // // function_data_type expanded here to prevent conflicts with implicit_type:empty vs data_type:ID /**/ tfIdScoped { $$ = new AstFunc ($1,*$1,NULL, - new AstBasicDType($1, LOGIC_IMPLICIT, NULL)); + new AstBasicDType($1, LOGIC_IMPLICIT)); SYMP->pushNewUnder($$, NULL); } | signingE rangeList tfIdScoped { $$ = new AstFunc ($3,*$3,NULL, - new AstBasicDType($3, LOGIC_IMPLICIT, $2, $1)); + GRAMMARP->addRange(new AstBasicDType($3, LOGIC_IMPLICIT, $1), $2)); SYMP->pushNewUnder($$, NULL); } | signing tfIdScoped { $$ = new AstFunc ($2,*$2,NULL, - new AstBasicDType($2, LOGIC_IMPLICIT, NULL, $1)); + new AstBasicDType($2, LOGIC_IMPLICIT, $1)); SYMP->pushNewUnder($$, NULL); } | data_type tfIdScoped { $$ = new AstFunc ($2,*$2,NULL,$1); @@ -1855,15 +1874,15 @@ tf_port_item: // ==IEEE: tf_port_item tf_port_itemFront: // IEEE: part of tf_port_item, which has the data type data_type { VARDTYPE($1); } - | signingE rangeList { VARDTYPE(new AstBasicDType($2->fileline(), LOGIC_IMPLICIT, $2, $1)); } - | signing { VARDTYPE(new AstBasicDType($1, LOGIC_IMPLICIT, NULL, $1)); } + | signingE rangeList { VARDTYPE(GRAMMARP->addRange(new AstBasicDType($2->fileline(), LOGIC_IMPLICIT, $1), $2)); } + | signing { VARDTYPE(new AstBasicDType($1, LOGIC_IMPLICIT, $1)); } //UNSUP yVAR data_type { VARDTYPE($2); } //UNSUP yVAR implicit_type { VARDTYPE($2); } // | tf_port_itemDir /*implicit*/ { VARDTYPE(NULL); /*default_nettype-see spec*/ } | tf_port_itemDir data_type { VARDTYPE($2); } - | tf_port_itemDir signingE rangeList { VARDTYPE(new AstBasicDType($3->fileline(), LOGIC_IMPLICIT, $3, $2)); } - | tf_port_itemDir signing { VARDTYPE(new AstBasicDType($2, LOGIC_IMPLICIT, NULL, $2)); } + | tf_port_itemDir signingE rangeList { VARDTYPE(GRAMMARP->addRange(new AstBasicDType($3->fileline(), LOGIC_IMPLICIT, $2),$3)); } + | tf_port_itemDir signing { VARDTYPE(new AstBasicDType($2, LOGIC_IMPLICIT, $2)); } //UNSUP tf_port_itemDir yVAR data_type { VARDTYPE($3); } //UNSUP tf_port_itemDir yVAR implicit_type { VARDTYPE($3); } ; @@ -2590,6 +2609,21 @@ AstNode* V3ParseGrammar::createSupplyExpr(FileLine* fileline, string name, int v return nodep; } +AstNodeDType* V3ParseGrammar::createArray(AstNodeDType* basep, AstRange* rangep) { + // Split RANGE0-RANGE1-RANGE2 into ARRAYDTYPE0(ARRAYDTYPE1(ARRAYDTYPE2(BASICTYPE3),RANGE),RANGE) + AstNodeDType* arrayp = basep; + if (rangep) { // Maybe no range - return unmodified base type + while (rangep->nextp()) rangep = rangep->nextp()->castRange(); + while (rangep) { + AstRange* prevp = rangep->backp()->castRange(); + if (prevp) rangep->unlinkFrBack(); + arrayp = new AstArrayDType(rangep->fileline(), arrayp, rangep); + rangep = prevp; + } + } + return arrayp; +} + AstVar* V3ParseGrammar::createVariable(FileLine* fileline, string name, AstRange* arrayp, AstNode* attrsp) { AstNodeDType* dtypep = GRAMMARP->m_varDTypep; UINFO(5," creVar "<nextp()) arrayp = arrayp->nextp()->castRange(); - while (arrayp) { - AstRange* prevp = arrayp->backp()->castRange(); - if (prevp) arrayp->unlinkFrBack(); - arrayDTypep = new AstArrayDType(arrayp->fileline(), arrayDTypep, arrayp); - arrayp = prevp; - } - } + AstNodeDType* arrayDTypep = createArray(dtypep,arrayp); AstVar* nodep = new AstVar(fileline, type, name, arrayDTypep); diff --git a/test_regress/driver.pl b/test_regress/driver.pl index 5076bf823..0d6e26461 100755 --- a/test_regress/driver.pl +++ b/test_regress/driver.pl @@ -250,7 +250,7 @@ sub new { v_other_filenames => [], # After the filename so we can spec multiple files # IV iv => 0, - iv_flags => [split(/\s+/,"-o $self->{obj_dir}/simiv")], + iv_flags => [split(/\s+/,"+define+iverilog -o $self->{obj_dir}/simiv")], iv_flags2 => [], # Overridden in some sim files ivrun_flags => [], # VCS diff --git a/test_regress/t/t_mem_packed.pl b/test_regress/t/t_mem_packed.pl new file mode 100755 index 000000000..7058e622f --- /dev/null +++ b/test_regress/t/t_mem_packed.pl @@ -0,0 +1,18 @@ +#!/usr/bin/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. + +compile ( + ); + +execute ( + check_finished=>1, + ); + +ok(1); +1; diff --git a/test_regress/t/t_mem_packed.v b/test_regress/t/t_mem_packed.v new file mode 100644 index 000000000..2eb71815d --- /dev/null +++ b/test_regress/t/t_mem_packed.v @@ -0,0 +1,45 @@ +// DESCRIPTION: Verilator: Verilog Test module +// +// This file ONLY is placed into the Public Domain, for any use, +// without warranty, 2009 by Wilson Snyder. + +module t (/*AUTOARG*/ + // Inputs + clk + ); + + input clk; + + integer cyc; initial cyc = 0; +`ifdef iverilog + reg [7:0] arr [3:0]; +`else + reg [3:0] [7:0] arr; +`endif + reg [7:0] sum; + integer i0; + + initial begin + for (i0=0; i0<5; i0=i0+1) begin + arr[i0] = 1 << i0[1:0]; + end + end + + always @ (posedge clk) begin + cyc <= cyc + 1; + if (cyc==0) begin + // Setup + sum <= 0; + end + else if (cyc >= 10 && cyc < 14) begin + sum <= sum + {4'b0,arr[cyc-10]}; + end + else if (cyc==99) begin + $write("[%0t] cyc==%0d sum=%x\n",$time, cyc, sum); + if (sum != 8'h0f) $stop; + $write("*-* All Finished *-*\n"); + $finish; + end + end + +endmodule diff --git a/test_regress/t/t_trace_public.out b/test_regress/t/t_trace_public.out new file mode 100644 index 000000000..9a12118bb --- /dev/null +++ b/test_regress/t/t_trace_public.out @@ -0,0 +1,96 @@ +$version Generated by SpTraceVcd $end +$date Tue Nov 3 09:34:23 2009 + $end +$timescale 1ns $end + + $scope module TOP $end + $var wire 1 6 CLK $end + $var wire 1 7 RESET $end + $scope module v $end + $var wire 1 6 CLK $end + $var wire 1 # RESET $end + $var wire 32 $ val [31:0] $end + $var wire 2 3 vec(3) [2:1] $end + $var wire 2 4 vec(4) [2:1] $end + $scope module glbl $end + $var wire 1 5 GSR $end + $upscope $end + $scope module little $end + $var wire 1 6 clk $end + $var wire 128 / i128 [63:190] $end + $var wire 49 - i48 [1:49] $end + $var wire 8 , i8 [0:7] $end + $upscope $end + $scope module neg $end + $var wire 1 6 clk $end + $var wire 128 ( i128 [63:-64] $end + $var wire 48 & i48 [-1:-48] $end + $var wire 8 % i8 [0:-7] $end + $upscope $end + $upscope $end + $upscope $end +$enddefinitions $end + + +#0 +1# +b00000000000000000000000000000000 $ +b00000000 % +b000000000000000000000000000000000000000000000000 & +b00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 ( +b00000000 , +b0000000000000000000000000000000000000000000000000 - +b00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 / +b00 3 +b00 4 +15 +17 +06 +#1 +#2 +#3 +b11111111 % +b111111111111111111111111111111111111111111111111 & +b11111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111 ( +b11111111 , +b1111111111111111111111111111111111111111111111111 - +b11111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111 / +16 +#4 +#5 +#6 +06 +#7 +05 +#8 +#9 +0# +b00000000 % +b000000000000000000000000000000000000000000000000 & +b00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 ( +b00000000 , +b0000000000000000000000000000000000000000000000000 - +b00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 / +07 +16 +#10 +#11 +#12 +06 +#13 +#14 +#15 +b00000000000000000000000000000001 $ +b11111111 % +b111111111111111111111111111111111111111111111111 & +b11111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111 ( +b11111111 , +b1111111111111111111111111111111111111111111111111 - +b11111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111 / +16 +#16 +#17 +#18 +06 +#19 +#20