Fix implicit one bit parameter selection, bug603.

This commit is contained in:
Wilson Snyder 2013-01-16 20:58:48 -05:00
parent f0a4bd28b6
commit 6d1b42bedb
9 changed files with 94 additions and 7 deletions

View File

@ -12,9 +12,12 @@ indicates the contributor was also the author of the fix; Thanks!
*** Support bind, to module names only, bug602. [Ed Lander]
*** Fix pin width mismatch error, bug595. [Alex Solomatnikov]
*** Define SYSTEMVERILOG, SV_COV_START and other IEEE mandated predefines.
**** Fix pin width mismatch error, bug595. [Alex Solomatnikov]
**** Fix implicit one bit parameter selection, bug603. [Jeremy Bennett]
**** Define SYSTEMVERILOG, SV_COV_START and other IEEE mandated predefines.
* Verilator 3.844 2013/01/09

View File

@ -1099,6 +1099,10 @@ AstNodeDType* AstNode::findLogicDType(int width, int widthMin, AstNumeric numeri
return v3Global.rootp()->typeTablep()
->findLogicBitDType(fileline(), AstBasicDTypeKwd::LOGIC, width, widthMin, numeric);
}
AstNodeDType* AstNode::findLogicRangeDType(VNumRange range, int widthMin, AstNumeric numeric) const {
return v3Global.rootp()->typeTablep()
->findLogicBitDType(fileline(), AstBasicDTypeKwd::LOGIC, range, widthMin, numeric);
}
AstBasicDType* AstNode::findInsertSameDType(AstBasicDType* nodep) {
return v3Global.rootp()->typeTablep()
->findInsertSameDType(nodep);

View File

@ -551,6 +551,9 @@ struct VNumRange {
}
//
VNumRange() : m_msb(0), m_lsb(0), mu_flags(0) {}
VNumRange(int msb, int lsb, bool littleEndian)
: m_msb(0), m_lsb(0), mu_flags(0)
{ init(msb,lsb,littleEndian); }
~VNumRange() {}
// MEMBERS
void init(int msb, int lsb, bool littleEndian) {
@ -1076,6 +1079,7 @@ public:
AstNodeDType* findUInt64DType() { return findBasicDType(AstBasicDTypeKwd::UINT64); } // Twostate
AstNodeDType* findBitDType(int width, int widthMin, AstNumeric numeric) const;
AstNodeDType* findLogicDType(int width, int widthMin, AstNumeric numeric) const;
AstNodeDType* findLogicRangeDType(VNumRange range, int widthMin, AstNumeric numeric) const;
AstNodeDType* findBasicDType(AstBasicDTypeKwd kwd) const;
AstBasicDType* findInsertSameDType(AstBasicDType* nodep);

View File

@ -557,6 +557,15 @@ AstBasicDType* AstTypeTable::findLogicBitDType(FileLine* fl, AstBasicDTypeKwd kw
return newp;
}
AstBasicDType* AstTypeTable::findLogicBitDType(FileLine* fl, AstBasicDTypeKwd kwd,
VNumRange range, int widthMin, AstNumeric numeric) {
AstBasicDType* new1p = new AstBasicDType(fl, kwd, numeric, range, widthMin);
AstBasicDType* newp = findInsertSameDType(new1p);
if (newp != new1p) new1p->deleteTree();
else addTypesp(newp);
return newp;
}
AstBasicDType* AstTypeTable::findInsertSameDType(AstBasicDType* nodep) {
VBasicTypeKey key (nodep->width(), nodep->widthMin(), nodep->numeric(),
nodep->keyword(), nodep->nrange());

View File

@ -302,6 +302,11 @@ public:
: AstNodeDType(fl) {
init(kwd, numer, wantwidth, widthmin, NULL);
}
AstBasicDType(FileLine* fl, AstBasicDTypeKwd kwd, AstNumeric numer, VNumRange range, int widthmin)
: AstNodeDType(fl) {
init(kwd, numer, range.elements(), widthmin, NULL);
m.m_nrange = range; // as init() presumes lsb==0, but range.lsb() might not be
}
// See also addRange in verilog.y
private:
void init(AstBasicDTypeKwd kwd, AstNumeric numer,
@ -4482,6 +4487,8 @@ public:
AstBasicDType* findBasicDType(FileLine* fl, AstBasicDTypeKwd kwd);
AstBasicDType* findLogicBitDType(FileLine* fl, AstBasicDTypeKwd kwd,
int width, int widthMin, AstNumeric numeric);
AstBasicDType* findLogicBitDType(FileLine* fl, AstBasicDTypeKwd kwd,
VNumRange range, int widthMin, AstNumeric numeric);
AstBasicDType* findInsertSameDType(AstBasicDType* nodep);
void clearCache();
void repairCache();

View File

@ -840,7 +840,17 @@ private:
width = 32;
}
// Can't just inherit valuep()->dtypep() as mwidth might not equal width
nodep->dtypeChgWidthSigned(width, nodep->valuep()->widthMin(),issigned);
if (width==1) {
// one bit parameter is same as "parameter [0] foo", not "parameter logic foo"
// as you can extract "foo[0]" from a parameter but not a wire
nodep->dtypeChgWidthSigned(width, nodep->valuep()->widthMin(),issigned);
nodep->dtypep(nodep->findLogicRangeDType
(VNumRange(0,0,false),
nodep->valuep()->widthMin(),
issigned?AstNumeric::SIGNED : AstNumeric::UNSIGNED));
} else {
nodep->dtypeChgWidthSigned(width, nodep->valuep()->widthMin(),issigned);
}
didchk = true;
nodep->valuep()->iterateAndNext(*this,WidthVP(width,nodep->widthMin(),FINAL).p());
}

View File

@ -104,10 +104,7 @@ private:
false); // big endian
}
else if (AstBasicDType* adtypep = ddtypep->castBasicDType()) {
if (!adtypep->isRanged()) {
nodep->v3error("Illegal bit or array select; type does not have a bit range, or bad dimension: type is "
<<errp->prettyName());
} else {
if (adtypep->isRanged()) {
if (adtypep->rangep()
&& (!adtypep->rangep()->msbp()->castConst()
|| !adtypep->rangep()->lsbp()->castConst()))
@ -115,6 +112,9 @@ private:
fromRange.init(adtypep->msb(),
adtypep->lsb(),
adtypep->littleEndian());
} else {
nodep->v3error("Illegal bit or array select; type does not have a bit range, or bad dimension: type is "
<<errp->prettyName());
}
}
else {

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,32 @@
// DESCRIPTION: Verilator: Verilog Test module
//
// We see Verilator assumes a 1-bit parameter is a scalar rather than a 1-bit
// long vector. This causes the following code to fail.
//
// Other event drive simulators accept this.
//
// This file ONLY is placed into the Public Domain, for any use,
// without warranty, 2013 by Jeremy Bennett.
module t (/*AUTOARG*/
// Inputs
clk
);
input clk;
// At this point it is ambiguous whether a is scalar or vector
parameter a = 1'b0;
wire b = a[0];
// Note however b[0] is illegal.
always @(posedge clk) begin
if (b == 1'b0) begin
$write("*-* All Finished *-*\n");
$finish;
end
else begin
$stop;
end
end
endmodule