Fix unpacked split_var (#5782) (#5785)

This commit is contained in:
Yutetsu TAKATSUKASA 2025-02-18 03:34:57 +09:00 committed by GitHub
parent c840ffb0ae
commit 1a07af57a3
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
3 changed files with 63 additions and 6 deletions

View File

@ -900,8 +900,9 @@ public:
const AstBasicDType* basicp() const { return m_basicp; }
// Make a plan for variables after split
// when skipUnused==true, split variable for unread bits will not be created.
std::vector<SplitNewVar> splitPlan(bool skipUnused) const {
std::vector<SplitNewVar> splitPlan(const AstVar* varp, bool skipUnused) const {
UASSERT(m_dedupDone, "dedup() must be called before");
AstNodeDType* const dtypep = varp->dtypeSkipRefp();
std::vector<SplitNewVar> plan;
std::vector<std::pair<int, bool>> points; // <bit location, is end>
points.reserve(m_lhs.size() * 2 + 2); // 2 points will be added per one PackedVarRefEntry
@ -909,9 +910,17 @@ public:
points.emplace_back(ref.lsb(), false); // Start of a region
points.emplace_back(ref.msb() + 1, true); // End of a region
}
int bit_hi, bit_lo;
if (basicp() == dtypep) {
bit_hi = basicp()->hi();
bit_lo = basicp()->lo();
} else { // packed struct, packed array. lo is 0
bit_hi = dtypep->width() - 1;
bit_lo = 0;
}
if (skipUnused && !m_rhs.empty()) { // Range to be read must be kept, so add points here
int lsb = m_basicp->hi() + 1;
int msb = m_basicp->lo() - 1;
int lsb = bit_hi + 1;
int msb = bit_lo - 1;
for (const PackedVarRefEntry& ref : m_rhs) {
lsb = std::min(lsb, ref.lsb());
msb = std::max(msb, ref.msb());
@ -921,8 +930,8 @@ public:
points.emplace_back(msb + 1, true);
}
if (!skipUnused) { // All bits are necessary
points.emplace_back(m_basicp->lo(), false);
points.emplace_back(m_basicp->hi() + 1, true);
points.emplace_back(bit_lo, false);
points.emplace_back(bit_hi + 1, true);
}
std::sort(points.begin(), points.end(), SortByFirst());
@ -1154,7 +1163,7 @@ class SplitPackedVarVisitor final : public VNVisitor, public SplitVarImpl {
<< " which has " << ref.lhs().size() << " lhs refs and "
<< ref.rhs().size() << " rhs refs will be split.\n");
std::vector<SplitNewVar> vars
= ref.splitPlan(!varp->isTrace()); // If traced, all bit must be kept
= ref.splitPlan(varp, !varp->isTrace()); // If traced, all bit must be kept
if (vars.empty()) continue;
if (vars.size() == 1 && vars.front().bitwidth() == varp->width())
continue; // No split

View File

@ -0,0 +1,17 @@
#!/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(verilator_flags2=['--trace'])
test.execute()
test.passes()

View File

@ -0,0 +1,31 @@
// DESCRIPTION: Verilator: Verilog Test module
//
// This file ONLY is placed under the Creative Commons Public Domain, for
// any use, without warranty, 2025
// SPDX-License-Identifier: CC0-1.0
module t(/*AUTOARG*/
// Inputs
clk
);
input clk;
// Test loop
always @ (posedge clk) begin
$write("*-* All Finished *-*\n");
$finish;
end
bug5782 u_bug5782(.data_out());
endmodule
// #5782 internal error with --trace. Bit range is not properly handled.
module bug5782 (
output logic [31:0][15:0] data_out
);
logic [31:0][15:0] data [8] /*verilator split_var*/;
always begin
data_out = data[7];
end
endmodule