Fix error on resized lvalues with warning suppressed (#6497) (#6816)

This commit is contained in:
Alex Solomatnikov 2025-12-15 03:49:32 -08:00 committed by GitHub
parent a1cd7d1f3a
commit 8da8ca4203
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
3 changed files with 136 additions and 0 deletions

View File

@ -6961,6 +6961,40 @@ class WidthVisitor final : public VNVisitor {
}
userIterateChildren(nodep, nullptr);
}
void visit(AstResizeLValue* nodep) override {
// RESIZELVALUE adjusts width of lvalues for assignments/function calls
// The parent context determines the required width
UINFO(9, "visit AstResizeLValue " << nodep << endl);
if (nodep->didWidthAndSet()) return;
UASSERT_OBJ(nodep->lhsp(), nodep, "ResizeLValue missing lhs expression");
// First, process child to know its natural width
if (m_vup->prelim()) {
userIterateAndNext(nodep->lhsp(), WidthVP{CONTEXT_DET, PRELIM}.p());
}
// Get the required width from parent context
if (AstNodeDType* const vdtypep = m_vup->dtypeNullp()) {
// Parent specified required width - use it
nodep->dtypeFrom(vdtypep);
} else if (!nodep->dtypep()) {
// No parent context, use child's type
nodep->dtypeFrom(nodep->lhsp());
}
// Verify we ended up with a valid datatype
UASSERT_OBJ(nodep->dtypep(), nodep, "ResizeLValue still missing dtype after visiting");
UASSERT_OBJ(nodep->width() > 0, nodep, "ResizeLValue has invalid width");
// Log the transformation for debugging
UINFO(9, " ResizeLValue: " << nodep->lhsp()->width() << " bits -> " << nodep->width()
<< " bits" << endl);
// Final processing
userIterateAndNext(nodep->lhsp(), WidthVP{SELF, FINAL}.p());
nodep->didWidth(true);
}
void visitClass(AstClass* nodep) {
if (nodep->didWidthAndSet()) return;

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(verilator_flags2=["--binary -Wno-WIDTHEXPAND"])
test.execute()
test.passes()

View File

@ -0,0 +1,84 @@
// DESCRIPTION: Verilator: Verilog Test module
//
// This file ONLY is placed under the Creative Commons Public Domain, for
// any use, without warranty, 2025 by Alex Solomatnikov.
// SPDX-License-Identifier: CC0-1.0
package x_pkg;
typedef bit unsigned [64-1:0] x_reg_data_t ;
virtual class x_reg;
extern virtual task read(output int status, output x_reg_data_t value, input int path);
endclass: x_reg
task x_reg::read(output int status, output x_reg_data_t value, input int path);
endtask: read
endpackage // x_pkg
package s_c_env_pkg;
import x_pkg::*;
class r_reg_p_s_reg_n_doorbell extends x_reg;
x_reg_data_t val;
function new(int _val);
val = _val;
endfunction
extern virtual task read(output int status, output x_reg_data_t value, input int path);
endclass : r_reg_p_s_reg_n_doorbell
task r_reg_p_s_reg_n_doorbell::read(output int status, output x_reg_data_t value, input int path);
status = 1;
value = val;
endtask: read
class r_block_p_s_reg;
rand r_reg_p_s_reg_n_doorbell n_doorbell;
function new(int _val);
n_doorbell = new(_val);
endfunction
endclass : r_block_p_s_reg
class r_top_s_reg;
rand r_block_p_s_reg p_s[16];
endclass
class s_c_env;
r_top_s_reg r_reg_model;
endclass: s_c_env
endpackage // s_c_env_pkg
package s_c_sequences_pkg;
import x_pkg::*;
import s_c_env_pkg::*;
class s_c_v_regs_seq;
s_c_env m_env;
virtual task body();
int unsigned p, rdata;
int status;
if (m_env == null)
m_env = new;
if (m_env.r_reg_model == null)
m_env.r_reg_model = new;
foreach (m_env.r_reg_model.p_s[p]) begin
if (m_env.r_reg_model.p_s[p] == null) begin
m_env.r_reg_model.p_s[p] = new(p);
end
m_env.r_reg_model.p_s[p].n_doorbell.read(status, rdata, 0);
if (status != 1) $stop;
if (rdata != p) $stop;
end
endtask
endclass
endpackage // s_c_sequences_pkg
module t;
s_c_sequences_pkg::s_c_v_regs_seq seq;
initial begin
seq = new;
seq.body();
$write("*-* All Finished *-*\n");
$finish;
end
endmodule // t