Fixes #7427.
This commit is contained in:
parent
7f571971ca
commit
c143c2fdd2
|
|
@ -230,6 +230,7 @@ Risto Pejašinović
|
|||
Robert Balas
|
||||
Robin Heinemann
|
||||
Rodrigo Batista de Moraes
|
||||
Rowan Goemans
|
||||
Rupert Swarbrick
|
||||
Ryan Ziegler
|
||||
Ryszard Rozak
|
||||
|
|
|
|||
|
|
@ -105,8 +105,8 @@ class SliceVisitor final : public VNVisitor {
|
|||
newp = nullptr;
|
||||
int itemIdx = 0;
|
||||
int i = 0;
|
||||
const AstInitArray::KeyItemMap& itemMap = initp->map();
|
||||
if (const int prevItemIdx = initp->user2()) {
|
||||
const AstInitArray::KeyItemMap& itemMap = initp->map();
|
||||
const auto it = itemMap.find(considerOrder(arrayp, prevItemIdx));
|
||||
if (it != itemMap.end()) {
|
||||
const AstInitItem* itemp = it->second;
|
||||
|
|
@ -119,8 +119,10 @@ class SliceVisitor final : public VNVisitor {
|
|||
}
|
||||
const AstNodeDType* const expectedItemDTypep = arrayp->subDTypep()->skipRefp();
|
||||
while (i <= elemIdx) {
|
||||
const auto itemIt = itemMap.find(considerOrder(arrayp, itemIdx));
|
||||
AstNodeExpr* const itemp
|
||||
= initp->getIndexDefaultedValuep(considerOrder(arrayp, itemIdx));
|
||||
= itemIt != itemMap.end() ? itemIt->second->valuep() : initp->defaultp();
|
||||
const bool directItem = itemIt != itemMap.end();
|
||||
if (!itemp && !m_assignError) {
|
||||
nodep->v3error("Array initialization has too few elements, need element "
|
||||
<< elemIdx);
|
||||
|
|
@ -132,7 +134,7 @@ class SliceVisitor final : public VNVisitor {
|
|||
= AstNode::computeCastable(expectedItemDTypep, itemRawDTypep, itemp);
|
||||
if (castable == VCastable::SAMEISH || castable == VCastable::COMPATIBLE) {
|
||||
if (i == elemIdx) {
|
||||
newp = itemp->cloneTreePure(false);
|
||||
newp = itemp->cloneTree(false, !directItem && needPure);
|
||||
break;
|
||||
} else { // Check the next item
|
||||
++i;
|
||||
|
|
@ -184,7 +186,6 @@ class SliceVisitor final : public VNVisitor {
|
|||
m_assignError = true;
|
||||
}
|
||||
if (newp) {
|
||||
const AstInitArray::KeyItemMap& itemMap = initp->map();
|
||||
const auto it = itemMap.find(considerOrder(arrayp, itemIdx));
|
||||
if (it != itemMap.end()) { // Remember current position for the next invocation.
|
||||
initp->user2(itemIdx);
|
||||
|
|
@ -283,16 +284,6 @@ class SliceVisitor final : public VNVisitor {
|
|||
AstNodeAssign* const newp
|
||||
= nodep->cloneType(cloneAndSel(nodep->lhsp(), elements, elemIdx, elemIdx != 0),
|
||||
cloneAndSel(nodep->rhsp(), elements, elemIdx, elemIdx != 0));
|
||||
if (elemIdx == 0) {
|
||||
nodep->foreach([this](AstExprStmt* const exprp) {
|
||||
// Result expression is always evaluated to the same value, so the statements
|
||||
// can be removed once they were included in the expression created for the 1st
|
||||
// element.
|
||||
AstNodeExpr* const resultp = exprp->resultp()->unlinkFrBack();
|
||||
exprp->replaceWith(resultp);
|
||||
VL_DO_DANGLING(pushDeletep(exprp), exprp);
|
||||
});
|
||||
}
|
||||
UINFOTREE(9, newp, "", "new");
|
||||
newlistp = AstNode::addNext(newlistp, newp);
|
||||
}
|
||||
|
|
@ -356,17 +347,6 @@ class SliceVisitor final : public VNVisitor {
|
|||
T_NodeBiop* const clonep = new T_NodeBiop{
|
||||
nodep->fileline(), cloneAndSel(nodep->lhsp(), elements, elemIdx, elemIdx != 0),
|
||||
cloneAndSel(nodep->rhsp(), elements, elemIdx, elemIdx != 0)};
|
||||
if (elemIdx == 0) {
|
||||
nodep->foreach([this](AstExprStmt* const exprp) {
|
||||
// Result expression is always evaluated to the same value, so the
|
||||
// statements can be removed once they were included in the expression
|
||||
// created for the 1st element.
|
||||
AstNodeExpr* const resultp = exprp->resultp()->unlinkFrBack();
|
||||
exprp->replaceWith(resultp);
|
||||
VL_DO_DANGLING(pushDeletep(exprp), exprp);
|
||||
});
|
||||
}
|
||||
|
||||
if (!logp) {
|
||||
logp = clonep;
|
||||
} else {
|
||||
|
|
|
|||
|
|
@ -0,0 +1,18 @@
|
|||
#!/usr/bin/env python3
|
||||
# DESCRIPTION: Verilator: Verilog Test driver/expect definition
|
||||
#
|
||||
# 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-FileCopyrightText: 2026 Wilson Snyder
|
||||
# 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,49 @@
|
|||
// DESCRIPTION: Verilator: Assignment pattern preserves array expression side effects
|
||||
//
|
||||
// This file ONLY is placed under the Creative Commons Public Domain.
|
||||
// SPDX-FileCopyrightText: 2026 Wilson Snyder
|
||||
// SPDX-FileCopyrightText: 2026 Rowan Goemans
|
||||
// SPDX-License-Identifier: CC0-1.0
|
||||
|
||||
// verilog_format: off
|
||||
`define stop $stop
|
||||
`define checkd(gotv,expv) do if ((gotv) !== (expv)) begin $write("%%Error: %s:%0d: got=%0d exp=%0d (%s !== %s)\n", `__FILE__,`__LINE__, (gotv), (expv), `"gotv`", `"expv`"); `stop; end while(0);
|
||||
// verilog_format: on
|
||||
|
||||
module t;
|
||||
|
||||
// verilator lint_off ASCRANGE
|
||||
typedef logic [0:2][7:0] triple_lv_t;
|
||||
// verilator lint_on ASCRANGE
|
||||
typedef triple_lv_t pair_t [0:1];
|
||||
|
||||
function automatic triple_lv_t mk3(
|
||||
input logic [7:0] a,
|
||||
input logic [7:0] b,
|
||||
input logic [7:0] c
|
||||
);
|
||||
mk3 = '{0: a, 1: b, 2: c};
|
||||
endfunction
|
||||
|
||||
pair_t pair;
|
||||
|
||||
initial begin
|
||||
// verilator lint_off SIDEEFFECT
|
||||
pair = '{
|
||||
0: mk3(8'd1, 8'd2, 8'd3),
|
||||
1: mk3(8'd4, 8'd5, 8'd6)
|
||||
};
|
||||
// verilator lint_on SIDEEFFECT
|
||||
|
||||
`checkd(pair[0][0], 8'd1);
|
||||
`checkd(pair[0][1], 8'd2);
|
||||
`checkd(pair[0][2], 8'd3);
|
||||
`checkd(pair[1][0], 8'd4);
|
||||
`checkd(pair[1][1], 8'd5);
|
||||
`checkd(pair[1][2], 8'd6);
|
||||
|
||||
$write("*-* All Finished *-*\n");
|
||||
$finish;
|
||||
end
|
||||
|
||||
endmodule
|
||||
Loading…
Reference in New Issue