diff --git a/Changes b/Changes index 72b5fed6f..19bd0f854 100644 --- a/Changes +++ b/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 part-select in constant function, bug916. [Andrew Bardsley] + * Verilator 3.872 2015-04-05 diff --git a/src/V3Number.cpp b/src/V3Number.cpp index 33aeaa9a5..399b0d6af 100644 --- a/src/V3Number.cpp +++ b/src/V3Number.cpp @@ -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=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)) { diff --git a/src/V3Number.h b/src/V3Number.h index 31cb00de6..5541c33e6 100644 --- a/src/V3Number.h +++ b/src/V3Number.h @@ -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); diff --git a/src/V3Simulate.h b/src/V3Simulate.h index 8b700cbca..a61b25b00 100644 --- a/src/V3Simulate.h +++ b/src/V3Simulate.h @@ -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; diff --git a/test_regress/t/t_param_const_part.pl b/test_regress/t/t_param_const_part.pl new file mode 100755 index 000000000..f91289753 --- /dev/null +++ b/test_regress/t/t_param_const_part.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_param_const_part.v b/test_regress/t/t_param_const_part.v new file mode 100644 index 000000000..1de26f4bc --- /dev/null +++ b/test_regress/t/t_param_const_part.v @@ -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