Fix part-select in constant function, bug916.
This commit is contained in:
parent
d5eb92a071
commit
a59639413d
2
Changes
2
Changes
|
|
@ -15,6 +15,8 @@ indicates the contributor was also the author of the fix; Thanks!
|
||||||
|
|
||||||
**** Fix preprocessing stringified newline escapes, bug915. [Anton Rapp]
|
**** Fix preprocessing stringified newline escapes, bug915. [Anton Rapp]
|
||||||
|
|
||||||
|
**** Fix part-select in constant function, bug916. [Andrew Bardsley]
|
||||||
|
|
||||||
|
|
||||||
* Verilator 3.872 2015-04-05
|
* Verilator 3.872 2015-04-05
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1569,6 +1569,24 @@ V3Number& V3Number::opSel (const V3Number& lhs, uint32_t msbval, uint32_t lsbval
|
||||||
return *this;
|
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& V3Number::opCond (const V3Number& lhs, const V3Number& if1s, const V3Number& if0s) {
|
||||||
V3Number lhstrue (lhs.m_fileline); lhstrue.opRedOr(lhs);
|
V3Number lhstrue (lhs.m_fileline); lhstrue.opRedOr(lhs);
|
||||||
if (lhstrue.bitIs0(0)) {
|
if (lhstrue.bitIs0(0)) {
|
||||||
|
|
|
||||||
|
|
@ -235,6 +235,8 @@ public:
|
||||||
V3Number& opStreamL (const V3Number& lhs, const V3Number& rhs);
|
V3Number& opStreamL (const V3Number& lhs, const V3Number& rhs);
|
||||||
V3Number& opSel (const V3Number& lhs, const V3Number& rhs, const V3Number& ths);
|
V3Number& opSel (const V3Number& lhs, const V3Number& rhs, const V3Number& ths);
|
||||||
V3Number& opSel (const V3Number& lhs, uint32_t rhs, uint32_t 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& opCond (const V3Number& lhs, const V3Number& rhs, const V3Number& ths);
|
||||||
V3Number& opCaseEq (const V3Number& lhs, const V3Number& rhs);
|
V3Number& opCaseEq (const V3Number& lhs, const V3Number& rhs);
|
||||||
V3Number& opCaseNeq (const V3Number& lhs, const V3Number& rhs);
|
V3Number& opCaseNeq (const V3Number& lhs, const V3Number& rhs);
|
||||||
|
|
|
||||||
|
|
@ -224,16 +224,24 @@ private:
|
||||||
if (!vscp) nodep->v3fatalSrc("Not linked");
|
if (!vscp) nodep->v3fatalSrc("Not linked");
|
||||||
return vscp;
|
return vscp;
|
||||||
}
|
}
|
||||||
|
|
||||||
int unrollCount() {
|
int unrollCount() {
|
||||||
return m_params ? v3Global.opt.unrollCount()*16
|
return m_params ? v3Global.opt.unrollCount()*16
|
||||||
: v3Global.opt.unrollCount();
|
: v3Global.opt.unrollCount();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool jumpingOver(AstNode* nodep) {
|
bool jumpingOver(AstNode* nodep) {
|
||||||
// True to jump over this node - all visitors must call this up front
|
// True to jump over this node - all visitors must call this up front
|
||||||
return (m_jumpp && m_jumpp->labelp()!=nodep);
|
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
|
// VISITORS
|
||||||
virtual void visit(AstAlways* nodep, AstNUser*) {
|
virtual void visit(AstAlways* nodep, AstNUser*) {
|
||||||
|
|
@ -438,7 +446,43 @@ private:
|
||||||
if (m_anyAssignDly) clearOptimizable(nodep, "Mix of dly/non-dly assigns");
|
if (m_anyAssignDly) clearOptimizable(nodep, "Mix of dly/non-dly assigns");
|
||||||
m_anyAssignComb = true;
|
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");
|
clearOptimizable(nodep, "LHS isn't simple variable");
|
||||||
}
|
}
|
||||||
else if (m_checkOnly) {
|
else if (m_checkOnly) {
|
||||||
|
|
@ -448,14 +492,7 @@ private:
|
||||||
nodep->rhsp()->iterateAndNext(*this);
|
nodep->rhsp()->iterateAndNext(*this);
|
||||||
if (optimizable()) {
|
if (optimizable()) {
|
||||||
AstNode* vscp = varOrScope(nodep->lhsp()->castVarRef());
|
AstNode* vscp = varOrScope(nodep->lhsp()->castVarRef());
|
||||||
// Copy by value, not reference, as we don't want a=a+1 to get right results
|
assignOutNumber(nodep, vscp, fetchNumber(nodep->rhsp()));
|
||||||
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()));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
m_inDlyAssign = false;
|
m_inDlyAssign = false;
|
||||||
|
|
|
||||||
|
|
@ -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;
|
||||||
|
|
@ -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
|
||||||
Loading…
Reference in New Issue