diff --git a/Changes b/Changes index 4f4758f1d..8a205db0a 100644 --- a/Changes +++ b/Changes @@ -5,13 +5,15 @@ indicates the contributor was also the author of the fix; Thanks! * Verilator 3.879 devel +**** Fix display %u, %v, %p, %z, bug989. [Johan Bjork] + **** Fix real parameters causing bad module names, bug992. [Johan Bjork] **** Fix size-changing cast on packed struct, bug993. [Johan Bjork] **** Fix function calls on arrayed interface, bug994. [Johan Bjork] -**** Fix display %u, %v, %p, %z, bug989. [Johan Bjork] +**** Fix constant function assigned to packed structs, bug997. [Johan Bjork] * Verilator 3.878 2015-11-01 diff --git a/src/V3Simulate.h b/src/V3Simulate.h index 0c80a4966..60a0301b0 100644 --- a/src/V3Simulate.h +++ b/src/V3Simulate.h @@ -451,6 +451,56 @@ private: } } } + + bool handleAssignSel(AstNodeAssign* nodep, AstSel* selp, AstVarRef** outVarrefp, int depth) { + checkNodeInfo(selp); + AstVarRef* varrefp = selp->fromp()->castVarRef(); + if (!varrefp) { + selp = selp->lhsp()->castSel(); + if (selp) { + if (!handleAssignSel(nodep, selp, &varrefp, depth+1)) { + clearOptimizable(nodep, "Select LHS isn't simple variable"); + return false; + } + } + } + + if (m_checkOnly) { + nodep->iterateChildren(*this); + } else { + selp->lsbp()->iterateAndNext(*this); + nodep->rhsp()->iterateAndNext(*this); + + if (optimizable()) { + AstNode* vscp; + if (varrefp) { + vscp = varOrScope(varrefp); + V3Number outnum = V3Number(nodep->fileline()); + if (V3Number* vscpnump = fetchOutNumberNull(vscp)) { + outnum = *vscpnump; + } else if (V3Number* vscpnump = fetchNumberNull(vscp)) { + outnum = *vscpnump; + } else { // Assignment to unassigned variable, all bits are X or 0 + outnum = V3Number(nodep->fileline(), varrefp->varp()->widthMin()); + if (varrefp->varp()->basicp() && varrefp->varp()->basicp()->isZeroInit()) { + outnum.setAllBits0(); + } else { + outnum.setAllBitsX(); + } + } + if (depth == 0) { + outnum.opSelInto(*fetchNumber(nodep->rhsp()), + *fetchNumber(selp->lsbp()), + selp->widthConst()); + assignOutNumber(nodep, vscp, &outnum); + } + } + } + } + if (outVarrefp) *outVarrefp = varrefp; + return true; + } + virtual void visit(AstNodeAssign* nodep, AstNUser*) { if (jumpingOver(nodep)) return; if (!optimizable()) return; // Accelerate @@ -462,41 +512,10 @@ private: if (m_anyAssignDly) clearOptimizable(nodep, "Mix of dly/non-dly assigns"); m_anyAssignComb = true; } + 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); - } - } - } + handleAssignSel(nodep, selp, NULL, 0); } else if (!nodep->lhsp()->castVarRef()) { clearOptimizable(nodep, "LHS isn't simple variable"); diff --git a/test_regress/t/t_func_const.v b/test_regress/t/t_func_const.v index 771218d65..a783b8f8b 100644 --- a/test_regress/t/t_func_const.v +++ b/test_regress/t/t_func_const.v @@ -13,6 +13,19 @@ module t; localparam P6 = f_return(P4); localparam P3 = 3; + typedef struct packed { + logic [7:0] data; + } type_t; + typedef type_t [1:0] flist; + localparam flist PLIST = {8'd4,8'd8}; + localparam flist PARR = f_list_swap_2(PLIST); + typedef struct packed { + logic first; + logic second; + logic [31:0] data; + } bigstruct_t; + localparam bigstruct_t bigparam = f_return_struct(1'b1, 1'b0, 32'hfff12fff); + initial begin `ifdef TEST_VERBOSE $display("P5=%0d P8=%0d P16=%0d P18=%0d",P5,P8,P16,P18); @@ -24,6 +37,11 @@ module t; if (P8 !== 8) $stop; if (P16 !== 16) $stop; if (P18 !== 18) $stop; + if (PARR[0] != PLIST[1]) $stop; + if (PARR[1] != PLIST[0]) $stop; + if (bigparam.first != 1'b1) $stop; + if (bigparam.second != 1'b0) $stop; + if (bigparam.data != 32'hfff12fff) $stop; $write("*-* All Finished *-*\n"); $finish; end @@ -36,7 +54,7 @@ module t; function integer f_add2(input [31:0] a, input [31:0] b, input [31:0] c); f_add2 = f_add(a,b)+c; endfunction - + // Speced ok: local variables function integer f_for(input [31:0] a); integer i; @@ -84,4 +102,17 @@ module t; end f_return = 0; endfunction + + function flist f_list_swap_2(input flist in_list); + f_list_swap_2[0].data = in_list[1].data; + f_list_swap_2[1].data = in_list[0].data; + endfunction + + function bigstruct_t f_return_struct(input first, input second, input [31:0] data); + bigstruct_t result; + result.data = data; + result.first = first; + result.second = second; + return result; + endfunction endmodule