Fix constant function assigned to packed structs, bug997.

Signed-off-by: Wilson Snyder <wsnyder@wsnyder.org>
This commit is contained in:
Johan Bjork 2015-11-11 20:49:45 -05:00 committed by Wilson Snyder
parent c7e0f2e196
commit 4e4bc7b90f
3 changed files with 87 additions and 35 deletions

View File

@ -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

View File

@ -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");

View File

@ -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