Support for assignments to concatenations with impure RHS (#6002)
This commit is contained in:
parent
ac2313ecb7
commit
91c52a4972
|
|
@ -2077,20 +2077,41 @@ class ConstVisitor final : public VNVisitor {
|
||||||
VL_DO_DANGLING(pushDeletep(nodep->unlinkFrBack()), nodep);
|
VL_DO_DANGLING(pushDeletep(nodep->unlinkFrBack()), nodep);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
} else if (m_doV && VN_IS(nodep->lhsp(), Concat) && nodep->isPure()) {
|
} else if (m_doV && VN_IS(nodep->lhsp(), Concat)) {
|
||||||
bool need_temp = false;
|
bool need_temp = false;
|
||||||
if (m_warn && !VN_IS(nodep, AssignDly)) { // Is same var on LHS and RHS?
|
bool need_temp_pure = !nodep->rhsp()->isPure();
|
||||||
|
if (m_warn && !VN_IS(nodep, AssignDly)
|
||||||
|
&& !need_temp_pure) { // Is same var on LHS and RHS?
|
||||||
// Note only do this (need user4) when m_warn, which is
|
// Note only do this (need user4) when m_warn, which is
|
||||||
// done as unique visitor
|
// done as unique visitor
|
||||||
|
// If the rhs is not pure, we need a temporary variable anyway
|
||||||
const VNUser4InUse m_inuser4;
|
const VNUser4InUse m_inuser4;
|
||||||
nodep->lhsp()->foreach([](const AstVarRef* nodep) {
|
nodep->lhsp()->foreach([](const AstVarRef* nodep) {
|
||||||
if (nodep->varp()) nodep->varp()->user4(1);
|
UASSERT_OBJ(nodep->varp(), nodep, "Unlinked VarRef");
|
||||||
|
nodep->varp()->user4(1);
|
||||||
});
|
});
|
||||||
nodep->rhsp()->foreach([&need_temp](const AstVarRef* nodep) {
|
nodep->rhsp()->foreach([&need_temp](const AstVarRef* nodep) {
|
||||||
if (nodep->varp() && nodep->varp()->user4()) need_temp = true;
|
UASSERT_OBJ(nodep->varp(), nodep, "Unlinked VarRef");
|
||||||
|
if (nodep->varp()->user4()) need_temp = true;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
if (need_temp) {
|
if (need_temp_pure) {
|
||||||
|
// if the RHS is impure we need to create a temporary variable for it, because
|
||||||
|
// further handling involves copying of the RHS.
|
||||||
|
UINFO(4, " ASSITEMPPURE " << nodep << endl);
|
||||||
|
// ASSIGN(CONCAT(lc1,lc2),rhs) -> ASSIGN(temp,rhs),
|
||||||
|
// ASSIGN(lc1,SEL(temp,{size1})),
|
||||||
|
// ASSIGN(lc2,SEL(temp,{size2}))
|
||||||
|
|
||||||
|
AstNodeExpr* const rhsp = nodep->rhsp()->unlinkFrBack();
|
||||||
|
AstVar* const tempPurep = new AstVar{rhsp->fileline(), VVarType::BLOCKTEMP,
|
||||||
|
m_concswapNames.get(rhsp), rhsp->dtypep()};
|
||||||
|
m_modp->addStmtsp(tempPurep);
|
||||||
|
AstNodeAssign* const asnp = nodep->cloneType(
|
||||||
|
new AstVarRef{rhsp->fileline(), tempPurep, VAccess::WRITE}, rhsp);
|
||||||
|
nodep->addHereThisAsNext(asnp);
|
||||||
|
nodep->rhsp(new AstVarRef{rhsp->fileline(), tempPurep, VAccess::READ});
|
||||||
|
} else if (need_temp) {
|
||||||
// The first time we constify, there may be the same variable on the LHS
|
// The first time we constify, there may be the same variable on the LHS
|
||||||
// and RHS. In that case, we must use temporaries, or {a,b}={b,a} will break.
|
// and RHS. In that case, we must use temporaries, or {a,b}={b,a} will break.
|
||||||
UINFO(4, " ASSITEMP " << nodep << endl);
|
UINFO(4, " ASSITEMP " << nodep << endl);
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,18 @@
|
||||||
|
#!/usr/bin/env python3
|
||||||
|
# DESCRIPTION: Verilator: Verilog Test driver/expect definition
|
||||||
|
#
|
||||||
|
# Copyright 2024 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.
|
||||||
|
# SPDX-License-Identifier: LGPL-3.0-only OR Artistic-2.0
|
||||||
|
|
||||||
|
import vltest_bootstrap
|
||||||
|
|
||||||
|
test.scenarios('simulator')
|
||||||
|
|
||||||
|
test.compile()
|
||||||
|
|
||||||
|
test.execute()
|
||||||
|
|
||||||
|
test.passes()
|
||||||
|
|
@ -0,0 +1,27 @@
|
||||||
|
// DESCRIPTION: Verilator: Verilog Test module
|
||||||
|
//
|
||||||
|
// This file ONLY is placed under the Creative Commons Public Domain, for
|
||||||
|
// any use, without warranty, 2025 by Antmicro.
|
||||||
|
// SPDX-License-Identifier: CC0-1.0
|
||||||
|
|
||||||
|
int global_variable = 0;
|
||||||
|
|
||||||
|
function int side_effect;
|
||||||
|
global_variable++;
|
||||||
|
return 1;
|
||||||
|
endfunction
|
||||||
|
|
||||||
|
module t (/*AUTOARG*/);
|
||||||
|
reg [15:0] x;
|
||||||
|
reg [15:0] y;
|
||||||
|
initial begin
|
||||||
|
{x, y} = side_effect() + 2;
|
||||||
|
|
||||||
|
if (y != 3) $stop;
|
||||||
|
if (x != 0) $stop;
|
||||||
|
if (global_variable != 1) $stop;
|
||||||
|
|
||||||
|
$write("*-* All Finished *-*\n");
|
||||||
|
$finish;
|
||||||
|
end
|
||||||
|
endmodule
|
||||||
Loading…
Reference in New Issue