Fix part-select in constant function, bug916.

This commit is contained in:
Wilson Snyder 2015-05-09 14:01:54 -04:00
parent d5eb92a071
commit a59639413d
6 changed files with 115 additions and 11 deletions

View File

@ -15,6 +15,8 @@ indicates the contributor was also the author of the fix; Thanks!
**** Fix preprocessing stringified newline escapes, bug915. [Anton Rapp]
**** Fix part-select in constant function, bug916. [Andrew Bardsley]
* Verilator 3.872 2015-04-05

View File

@ -1569,6 +1569,24 @@ V3Number& V3Number::opSel (const V3Number& lhs, uint32_t msbval, uint32_t lsbval
return *this;
}
V3Number& V3Number::opSelInto (const V3Number& lhs, const V3Number& lsb, int width) {
return opSelInto(lhs, lsb.toSInt(), width);
}
V3Number& V3Number::opSelInto (const V3Number& lhs, int lsbval, int width) {
// this[lsbval+width-1 : lsbval] = lhs; Other bits of this are not affected
int ibit=0;
for(int bit=lsbval; bit<lsbval+width; bit++) {
if (ibit>=0 && ibit<(uint32_t)lhs.width()) {
setBit(bit,lhs.bitIs(ibit));
} else {
setBit(bit,'x');
}
ibit++;
}
return *this;
}
V3Number& V3Number::opCond (const V3Number& lhs, const V3Number& if1s, const V3Number& if0s) {
V3Number lhstrue (lhs.m_fileline); lhstrue.opRedOr(lhs);
if (lhstrue.bitIs0(0)) {

View File

@ -235,6 +235,8 @@ public:
V3Number& opStreamL (const V3Number& lhs, const V3Number& rhs);
V3Number& opSel (const V3Number& lhs, const V3Number& rhs, const V3Number& ths);
V3Number& opSel (const V3Number& lhs, uint32_t rhs, uint32_t ths);
V3Number& opSelInto (const V3Number& lhs, const V3Number& lsb, int width);
V3Number& opSelInto (const V3Number& lhs, int lsb, int width);
V3Number& opCond (const V3Number& lhs, const V3Number& rhs, const V3Number& ths);
V3Number& opCaseEq (const V3Number& lhs, const V3Number& rhs);
V3Number& opCaseNeq (const V3Number& lhs, const V3Number& rhs);

View File

@ -224,16 +224,24 @@ private:
if (!vscp) nodep->v3fatalSrc("Not linked");
return vscp;
}
int unrollCount() {
return m_params ? v3Global.opt.unrollCount()*16
: v3Global.opt.unrollCount();
}
bool jumpingOver(AstNode* nodep) {
// True to jump over this node - all visitors must call this up front
return (m_jumpp && m_jumpp->labelp()!=nodep);
}
void assignOutNumber(AstNodeAssign* nodep, AstNode* vscp, const V3Number* nump) {
// Don't do setNumber, as value isn't yet visible to following statements
if (nodep->castAssignDly()) {
// Don't do setNumber, as value isn't yet visible to following statements
newOutNumber(vscp)->opAssign(*nump);
} else {
newNumber(vscp)->opAssign(*nump);
newOutNumber(vscp)->opAssign(*nump);
}
}
// VISITORS
virtual void visit(AstAlways* nodep, AstNUser*) {
@ -438,7 +446,43 @@ private:
if (m_anyAssignDly) clearOptimizable(nodep, "Mix of dly/non-dly assigns");
m_anyAssignComb = true;
}
if (!nodep->lhsp()->castVarRef()) {
if (AstSel* selp = nodep->lhsp()->castSel()) {
if (!m_params) { clearOptimizable(nodep, "LHS has select"); return; }
checkNodeInfo(selp);
AstVarRef* varrefp = selp->fromp()->castVarRef();
if (!varrefp) {
clearOptimizable(nodep, "Select LHS isn't simple variable");
return;
}
if (m_checkOnly) {
nodep->iterateChildren(*this);
} else {
selp->lsbp()->iterateAndNext(*this);
nodep->rhsp()->iterateAndNext(*this);
if (optimizable()) {
AstNode* vscp = varOrScope(varrefp);
if (optimizable()) {
V3Number outnum (nodep->fileline(), varrefp->varp()->widthMin());
if (V3Number* outnump = fetchOutNumberNull(vscp)) {
outnum = *outnump;
} else if (V3Number* outnump = fetchNumberNull(vscp)) {
outnum = *outnump;
} else { // Assignment to unassigned variable, all bits are X or 0
if (varrefp->varp()->basicp() && varrefp->varp()->basicp()->isZeroInit()) {
outnum.setAllBits0();
} else {
outnum.setAllBitsX();
}
}
outnum.opSelInto(*fetchNumber(nodep->rhsp()),
*fetchNumber(selp->lsbp()),
selp->widthConst());
assignOutNumber(nodep, vscp, &outnum);
}
}
}
}
else if (!nodep->lhsp()->castVarRef()) {
clearOptimizable(nodep, "LHS isn't simple variable");
}
else if (m_checkOnly) {
@ -448,14 +492,7 @@ private:
nodep->rhsp()->iterateAndNext(*this);
if (optimizable()) {
AstNode* vscp = varOrScope(nodep->lhsp()->castVarRef());
// Copy by value, not reference, as we don't want a=a+1 to get right results
if (nodep->castAssignDly()) {
// Don't do setNumber, as value isn't yet visible to following statements
newOutNumber(vscp)->opAssign(*fetchNumber(nodep->rhsp()));
} else {
newNumber(vscp)->opAssign(*fetchNumber(nodep->rhsp()));
newOutNumber(vscp)->opAssign(*fetchNumber(nodep->rhsp()));
}
assignOutNumber(nodep, vscp, fetchNumber(nodep->rhsp()));
}
}
m_inDlyAssign = false;

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,27 @@
// DESCRIPTION: Verilator: Verilog Test module
//
// This file ONLY is placed into the Public Domain, for any use,
// without warranty, 2015 by Wilson Snyder.
module t;
function integer bottom_4bits;
input [7:0] i;
bottom_4bits = 0;
bottom_4bits[3:0] = i[3:0];
endfunction
function integer bottom_2_unknown;
input [7:0] i;
// bottom_4bits = 0; 'x
bottom_2_unknown[1:0] = i[1:0];
endfunction
localparam p = bottom_4bits(8'h13);
localparam bu = bottom_2_unknown(8'h13);
initial begin
if (p != 3) $stop;
$write("*-* All Finished *-*\n");
$finish;
end
endmodule