Fix NBAs to unpacked arrays of unpacked structs (#5603)

This happened to work before #5516, by creating a whole shadow copy of
the entire array. Revert back to that behaviour for now, it will be
slow, but works still.

Fixes #5590
This commit is contained in:
Geza Lore 2024-11-10 17:38:28 +00:00 committed by GitHub
parent 03bd1bfc63
commit 863abdb1f7
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
3 changed files with 119 additions and 3 deletions

View File

@ -251,10 +251,11 @@ class DelayedVisitor final : public VNVisitor {
const AstNodeDType* const dtypep = vscp->dtypep()->skipRefp();
// Unpacked arrays
if (const AstUnpackArrayDType* const uaDTypep = VN_CAST(dtypep, UnpackArrayDType)) {
// Basic underlying type of elements, if any.
AstBasicDType* const basicp = uaDTypep->basicp();
// If used in a loop, we must have a dynamic commit queue. (Also works in suspendables)
if (vscpInfo.m_inLoop) {
// Arrays with compound element types are currently not supported in loops
AstBasicDType* const basicp = uaDTypep->basicp();
if (!basicp
|| !(basicp->isIntegralOrPacked() //
|| basicp->isDouble() //
@ -266,8 +267,12 @@ class DelayedVisitor final : public VNVisitor {
}
// In a suspendable of fork, we must use the unique flag scheme, TODO: why?
if (vscpInfo.m_inSuspOrFork) return Scheme::FlagUnique;
// Otherwise use the shared flag scheme
return Scheme::FlagShared;
// Otherwise if an array of packed/basic elements, use the shared flag scheme
if (basicp) return Scheme::FlagShared;
// Finally fall back on the shadow variable scheme, e.g. for
// arrays of unpacked structs. This will be slow.
// TODO: generic LHS scheme as discussed in #5092
return Scheme::ShadowVar;
}
// In a suspendable of fork, we must use the unique flag scheme, TODO: why?

View File

@ -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(check_finished=True)
test.passes()

View File

@ -0,0 +1,93 @@
// DESCRIPTION: Verilator: Verilog Test module
//
// This file ONLY is placed under the Creative Commons Public Domain, for
// any use, without warranty, 2024 by Wilson Snyder.
// SPDX-License-Identifier: CC0-1.0
`define stop $stop
`define checkh(gotv,expv) do if ((gotv) !== (expv)) begin $write("%%Error: %s:%0d: got='h%x exp='h%x\n", `__FILE__,`__LINE__, (gotv), (expv)); `stop; end while(0)
module t(clk);
input clk;
logic [31:0] cyc = 0;
always @(posedge clk) begin
cyc <= cyc + 1;
if (cyc == 99) begin
$write("*-* All Finished *-*\n");
$finish;
end
end
`define at_posedge_clk_on_cycle(n) always @(posedge clk) if (cyc == n)
struct {
int foo;
int bar;
} arr [2];
initial begin
arr[0].foo = 0;
arr[0].bar = 100;
arr[1].foo = 0;
arr[1].bar = 100;
end
`at_posedge_clk_on_cycle(0) begin
for (int i = 0; i < 2; ++i) begin
`checkh(arr[i].foo, 0);
`checkh(arr[i].bar, 100);
end
end
`at_posedge_clk_on_cycle(1) begin
for (int i = 0; i < 2; ++i) begin
`checkh(arr[i].foo, 0);
`checkh(arr[i].bar, 100);
end
arr[0].foo <= 0;
arr[0].bar <= -0;
arr[1].foo <= 1;
arr[1].bar <= -1;
for (int i = 0; i < 2; ++i) begin
`checkh(arr[i].foo, 0);
`checkh(arr[i].bar, 100);
end
end
`at_posedge_clk_on_cycle(2) begin
for (int i = 0; i < 2; ++i) begin
`checkh(arr[i].foo, i);
`checkh(arr[i].bar, -i);
end
arr[0].foo <= ~0;
arr[0].bar <= 0;
arr[1].foo <= ~1;
arr[1].bar <= 1;
for (int i = 0; i < 2; ++i) begin
`checkh(arr[i].foo, i);
`checkh(arr[i].bar, -i);
end
end
`at_posedge_clk_on_cycle(3) begin
for (int i = 0; i < 2; ++i) begin
`checkh(arr[i].foo, ~i);
`checkh(arr[i].bar, i);
end
arr[0].foo <= -1;
arr[0].bar <= -2;
arr[1].foo <= -1;
arr[1].bar <= -2;
for (int i = 0; i < 2; ++i) begin
`checkh(arr[i].foo, ~i);
`checkh(arr[i].bar, i);
end
end
`at_posedge_clk_on_cycle(4) begin
for (int i = 0; i < 2; ++i) begin
`checkh(arr[i].foo, -1);
`checkh(arr[i].bar, -2);
end
end
endmodule