mirror of
https://github.com/verilator/verilator.git
synced 2026-08-22 14:06:52 +02:00
@@ -6961,6 +6961,40 @@ class WidthVisitor final : public VNVisitor {
|
|||||||
}
|
}
|
||||||
userIterateChildren(nodep, nullptr);
|
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) {
|
void visitClass(AstClass* nodep) {
|
||||||
if (nodep->didWidthAndSet()) return;
|
if (nodep->didWidthAndSet()) return;
|
||||||
|
|
||||||
|
|||||||
Executable
+18
@@ -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()
|
||||||
@@ -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
|
||||||
Reference in New Issue
Block a user