Support "reg [1:0][1:0][1:0]", bug176.

This commit is contained in:
Wilson Snyder 2009-11-05 09:57:23 -05:00
parent 700c1f836d
commit ffbd1fd474
9 changed files with 227 additions and 39 deletions

View File

@ -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;").

View File

@ -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; }
};
//######################################################################

View File

@ -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);

View File

@ -62,7 +62,7 @@ struct V3ParseBisonYYSType {
AstCaseItem* caseitemp;
AstConst* constp;
AstModule* modulep;
AstNodeDType* typep;
AstNodeDType* dtypep;
AstNodeFTask* ftaskp;
AstNodeSenItem* senitemp;
AstNodeVarRef* varnodep;

View File

@ -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<nodep>: // ==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<nodep>: // 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<nodep>: // ==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($<fl>3, LOGIC_IMPLICIT, NULL, $3)); }
| port_directionReset port_declNetE signing { VARDTYPE(new AstBasicDType($<fl>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<signstate>: // ==IEEE: signing
//************************************************
// Data Types
data_type<typep>: // ==IEEE: data_type
data_type<dtypep>: // ==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<typep>: // ==IEEE: data_type
//UNSUP ps_covergroup_identifier { $$ = $1; }
;
data_typeBasic<bdtypep>: // IEEE: part of data_type
integer_vector_type signingE rangeListE { $$ = $1; $$->setSignedState($2); $$->rangep($3); }
| integer_atom_type signingE { $$ = $1; $$->setSignedState($2); }
data_typeBasic<dtypep>: // 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<typep>: // ==IEEE: data_type, excluding class_type etc references
data_typeNoRef<dtypep>: // ==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<typep>: // IEEE: part of *data_type_or_implicit
implicit_type<dtypep>: // 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($<fl>1, LOGIC_IMPLICIT, NULL, $1); }
| signingE rangeList { $$ = GRAMMARP->addRange(new AstBasicDType($2->fileline(), LOGIC_IMPLICIT, $1),$2); }
| signing { $$ = new AstBasicDType($<fl>1, LOGIC_IMPLICIT, $1); }
;
//************************************************
@ -1246,9 +1265,9 @@ rangeList<rangep>: // IEEE: {packed_dimension}
| rangeList anyrange { $$ = $1; $1->addNext($2); }
;
wirerangeE<bdtypep>:
/* empty */ { $$ = new AstBasicDType(CRELINE(), LOGIC, NULL); } // not implicit
| anyrange { $$ = new AstBasicDType(CRELINE(), LOGIC, $1); } // not implicit
wirerangeE<dtypep>:
/* empty */ { $$ = new AstBasicDType(CRELINE(), LOGIC); } // not implicit
| anyrange { $$ = GRAMMARP->addRange(new AstBasicDType(CRELINE(), LOGIC),$1); } // not implicit
;
// IEEE: select
@ -1258,7 +1277,7 @@ anyrange<rangep>:
'[' constExpr ':' constExpr ']' { $$ = new AstRange($1,$2,$4); }
;
delayrange<bdtypep>:
delayrange<dtypep>:
wirerangeE delayE { $$ = $1; }
| ySCALARED wirerangeE delayE { $$ = $2; }
| yVECTORED wirerangeE delayE { $$ = $2; }
@ -1782,15 +1801,15 @@ funcId<ftaskp>: // 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 ($<fl>1,*$<strp>1,NULL,
new AstBasicDType($<fl>1, LOGIC_IMPLICIT, NULL));
new AstBasicDType($<fl>1, LOGIC_IMPLICIT));
SYMP->pushNewUnder($$, NULL); }
| signingE rangeList tfIdScoped
{ $$ = new AstFunc ($<fl>3,*$<strp>3,NULL,
new AstBasicDType($<fl>3, LOGIC_IMPLICIT, $2, $1));
GRAMMARP->addRange(new AstBasicDType($<fl>3, LOGIC_IMPLICIT, $1), $2));
SYMP->pushNewUnder($$, NULL); }
| signing tfIdScoped
{ $$ = new AstFunc ($<fl>2,*$<strp>2,NULL,
new AstBasicDType($<fl>2, LOGIC_IMPLICIT, NULL, $1));
new AstBasicDType($<fl>2, LOGIC_IMPLICIT, $1));
SYMP->pushNewUnder($$, NULL); }
| data_type tfIdScoped
{ $$ = new AstFunc ($<fl>2,*$<strp>2,NULL,$1);
@ -1855,15 +1874,15 @@ tf_port_item<nodep>: // ==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($<fl>1, LOGIC_IMPLICIT, NULL, $1)); }
| signingE rangeList { VARDTYPE(GRAMMARP->addRange(new AstBasicDType($2->fileline(), LOGIC_IMPLICIT, $1), $2)); }
| signing { VARDTYPE(new AstBasicDType($<fl>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($<fl>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($<fl>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 "<<name<<" decl="<<GRAMMARP->m_varDecl<<" io="<<GRAMMARP->m_varIO<<" dt="<<(dtypep?"set":"")<<endl);
@ -2615,16 +2649,7 @@ AstVar* V3ParseGrammar::createVariable(FileLine* fileline, string name, AstRange
}
// Split RANGE0-RANGE1-RANGE2 into ARRAYDTYPE0(ARRAYDTYPE1(ARRAYDTYPE2(BASICTYPE3),RANGE),RANGE)
AstNodeDType* arrayDTypep = dtypep;
if (arrayp) {
while (arrayp->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);

View File

@ -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

18
test_regress/t/t_mem_packed.pl Executable file
View File

@ -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;

View File

@ -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

View File

@ -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