Fix constant function assigned to packed structs, bug997.
Signed-off-by: Wilson Snyder <wsnyder@wsnyder.org>
This commit is contained in:
parent
c7e0f2e196
commit
4e4bc7b90f
4
Changes
4
Changes
|
|
@ -5,13 +5,15 @@ indicates the contributor was also the author of the fix; Thanks!
|
||||||
|
|
||||||
* Verilator 3.879 devel
|
* Verilator 3.879 devel
|
||||||
|
|
||||||
|
**** Fix display %u, %v, %p, %z, bug989. [Johan Bjork]
|
||||||
|
|
||||||
**** Fix real parameters causing bad module names, bug992. [Johan Bjork]
|
**** Fix real parameters causing bad module names, bug992. [Johan Bjork]
|
||||||
|
|
||||||
**** Fix size-changing cast on packed struct, bug993. [Johan Bjork]
|
**** Fix size-changing cast on packed struct, bug993. [Johan Bjork]
|
||||||
|
|
||||||
**** Fix function calls on arrayed interface, bug994. [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
|
* Verilator 3.878 2015-11-01
|
||||||
|
|
|
||||||
|
|
@ -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*) {
|
virtual void visit(AstNodeAssign* nodep, AstNUser*) {
|
||||||
if (jumpingOver(nodep)) return;
|
if (jumpingOver(nodep)) return;
|
||||||
if (!optimizable()) return; // Accelerate
|
if (!optimizable()) return; // Accelerate
|
||||||
|
|
@ -462,41 +512,10 @@ 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 (AstSel* selp = nodep->lhsp()->castSel()) {
|
if (AstSel* selp = nodep->lhsp()->castSel()) {
|
||||||
if (!m_params) { clearOptimizable(nodep, "LHS has select"); return; }
|
if (!m_params) { clearOptimizable(nodep, "LHS has select"); return; }
|
||||||
checkNodeInfo(selp);
|
handleAssignSel(nodep, selp, NULL, 0);
|
||||||
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()) {
|
else if (!nodep->lhsp()->castVarRef()) {
|
||||||
clearOptimizable(nodep, "LHS isn't simple variable");
|
clearOptimizable(nodep, "LHS isn't simple variable");
|
||||||
|
|
|
||||||
|
|
@ -13,6 +13,19 @@ module t;
|
||||||
localparam P6 = f_return(P4);
|
localparam P6 = f_return(P4);
|
||||||
localparam P3 = 3;
|
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
|
initial begin
|
||||||
`ifdef TEST_VERBOSE
|
`ifdef TEST_VERBOSE
|
||||||
$display("P5=%0d P8=%0d P16=%0d P18=%0d",P5,P8,P16,P18);
|
$display("P5=%0d P8=%0d P16=%0d P18=%0d",P5,P8,P16,P18);
|
||||||
|
|
@ -24,6 +37,11 @@ module t;
|
||||||
if (P8 !== 8) $stop;
|
if (P8 !== 8) $stop;
|
||||||
if (P16 !== 16) $stop;
|
if (P16 !== 16) $stop;
|
||||||
if (P18 !== 18) $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");
|
$write("*-* All Finished *-*\n");
|
||||||
$finish;
|
$finish;
|
||||||
end
|
end
|
||||||
|
|
@ -36,7 +54,7 @@ module t;
|
||||||
function integer f_add2(input [31:0] a, input [31:0] b, input [31:0] c);
|
function integer f_add2(input [31:0] a, input [31:0] b, input [31:0] c);
|
||||||
f_add2 = f_add(a,b)+c;
|
f_add2 = f_add(a,b)+c;
|
||||||
endfunction
|
endfunction
|
||||||
|
|
||||||
// Speced ok: local variables
|
// Speced ok: local variables
|
||||||
function integer f_for(input [31:0] a);
|
function integer f_for(input [31:0] a);
|
||||||
integer i;
|
integer i;
|
||||||
|
|
@ -84,4 +102,17 @@ module t;
|
||||||
end
|
end
|
||||||
f_return = 0;
|
f_return = 0;
|
||||||
endfunction
|
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
|
endmodule
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue