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);
|
||||
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;
|
||||
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
|
||||
// done as unique visitor
|
||||
// If the rhs is not pure, we need a temporary variable anyway
|
||||
const VNUser4InUse m_inuser4;
|
||||
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) {
|
||||
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
|
||||
// and RHS. In that case, we must use temporaries, or {a,b}={b,a} will break.
|
||||
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