diff --git a/Changes b/Changes index 46623b6f5..74fbd83ed 100644 --- a/Changes +++ b/Changes @@ -120,6 +120,7 @@ Verilator 5.043 devel * Fix randcase under fork (#6843). [Amal Araweelo Almis] * Fix JSON missing `signed` indication (#6845). * Fix class reference throwing cannot detect changes error (#6851). +* Fix `randc` on extended class (#6852). Verilator 5.042 2025-11-02 diff --git a/src/V3LinkDotIfaceCapture.cpp b/src/V3LinkDotIfaceCapture.cpp index 7bb3b5c63..03e5fe018 100644 --- a/src/V3LinkDotIfaceCapture.cpp +++ b/src/V3LinkDotIfaceCapture.cpp @@ -126,7 +126,7 @@ bool V3LinkDotIfaceCapture::replaceTypedef(const AstRefDType* refp, AstTypedef* void V3LinkDotIfaceCapture::propagateClone(const AstRefDType* origRefp, AstRefDType* newRefp) { if (!origRefp || !newRefp) return; - auto it = s_map.find(origRefp); + const auto it = s_map.find(origRefp); UASSERT_OBJ(it != s_map.end(), origRefp, "iface capture propagateClone missing entry for orig=" << cvtToStr(origRefp)); CapturedIfaceTypedef& entry = it->second; diff --git a/src/V3Randomize.cpp b/src/V3Randomize.cpp index 556f5abd0..b9f175fe1 100644 --- a/src/V3Randomize.cpp +++ b/src/V3Randomize.cpp @@ -1979,11 +1979,14 @@ class RandomizeVisitor final : public VNVisitor { return pair.first->second; } - AstVar* newRandcVarsp(AstVar* const varp) { + AstVar* newRandcVarsp(AstVar* const varp, AstClass* const classp) { + // Might be called multiple times on same var, if var is referenced in class extends, + // If so, each is randomized separately, so the select lands in the extending class + // If a randc, make a VlRandC object to hold the state if (!varp->isRandC()) return nullptr; - uint64_t items = 0; + uint64_t items = 0; if (AstEnumDType* const enumDtp = VN_CAST(varp->dtypep()->skipRefToEnump(), EnumDType)) { items = static_cast(enumDtp->itemCount()); } else if (AstBasicDType* const basicp = varp->dtypep()->skipRefp()->basicp()) { @@ -2002,11 +2005,11 @@ class RandomizeVisitor final : public VNVisitor { } else { varp->v3fatalSrc("Unexpected randc variable dtype"); } - AstCDType* newdtp = findVlRandCDType(varp->fileline(), items); - AstVar* newp + AstCDType* const newdtp = findVlRandCDType(varp->fileline(), items); + AstVar* const newp = new AstVar{varp->fileline(), VVarType::MEMBER, varp->name() + "__Vrandc", newdtp}; newp->isInternal(true); - varp->addNextHere(newp); + classp->addStmtsp(newp); UINFO(9, "created " << varp); return newp; } @@ -2285,6 +2288,7 @@ class RandomizeVisitor final : public VNVisitor { void addBasicRandomizeBody(AstFunc* const basicRandomizep, AstClass* const nodep, AstVar* randModeVarp) { + UINFO(9, "addBasicRTB " << nodep); FileLine* const fl = nodep->fileline(); AstVar* const basicFvarp = VN_AS(basicRandomizep->fvarp(), Var); AstVarRef* const basicFvarRefp = new AstVarRef{fl, basicFvarp, VAccess::WRITE}; @@ -2340,8 +2344,9 @@ class RandomizeVisitor final : public VNVisitor { new AstAnd{fl, basicFvarRefReadp, callp}}}; basicRandomizep->addStmtsp(wrapIfRandMode(nodep, memberVarp, assignIfNotNullp)); } else { - AstVar* const randcVarp = newRandcVarsp(memberVarp); - AstVarRef* const refp = new AstVarRef{fl, classp, memberVarp, VAccess::WRITE}; + AstVar* const randcVarp = newRandcVarsp(memberVarp, nodep); + AstVarRef* const refp + = new AstVarRef{memberVarp->fileline(), classp, memberVarp, VAccess::WRITE}; AstNodeStmt* const stmtp = newRandStmtsp(fl, refp, randcVarp, basicFvarp); if (!refp->backp()) VL_DO_DANGLING(refp->deleteTree(), refp); basicRandomizep->addStmtsp(new AstBegin{fl, "", stmtp, false}); diff --git a/test_regress/t/t_randc_extends.py b/test_regress/t/t_randc_extends.py new file mode 100755 index 000000000..f989a35fb --- /dev/null +++ b/test_regress/t/t_randc_extends.py @@ -0,0 +1,18 @@ +#!/usr/bin/env python3 +# DESCRIPTION: Verilator: Verilog Test driver/expect definition +# +# Copyright 2025 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() + +test.passes() diff --git a/test_regress/t/t_randc_extends.v b/test_regress/t/t_randc_extends.v new file mode 100644 index 000000000..d86b46a7d --- /dev/null +++ b/test_regress/t/t_randc_extends.v @@ -0,0 +1,38 @@ +// DESCRIPTION: Verilator: Verilog Test module +// +// This file ONLY is placed under the Creative Commons Public Domain, for +// any use, without warranty, 2025 by Wilson Snyder. +// SPDX-License-Identifier: CC0-1.0 + +package uvm_pkg; + + virtual class uvm_sequence #( + type REQ = int + ); + endclass + + class uvm_sequence_library #( + type REQ = int + ) extends uvm_sequence #(REQ); + randc bit [15:0] select_randc; // Passes without randc here + task body(); + if (0 == randomize(select_randc)) begin + end + endtask + endclass +endpackage + +module t; + import uvm_pkg::*; + + class t1 extends uvm_sequence_library; + endclass + + initial begin + t1 c; + c = new; + c.body; + $finish; + end + +endmodule diff --git a/test_regress/t/t_randomize_method_param.v b/test_regress/t/t_randomize_method_param.v index fd8b3d918..3aa32393d 100644 --- a/test_regress/t/t_randomize_method_param.v +++ b/test_regress/t/t_randomize_method_param.v @@ -15,12 +15,12 @@ package uvm_pkg; type REQ = int ) extends uvm_sequence #(REQ); rand bit [15:0] m_rand; - // TODO: randc bit [15:0] m_randc; + randc bit [15:0] m_randc; task body(); if (0 == randomize(m_rand)) begin end - // TODO: if (0 == randomize(m_randc)) begin - // TODO: end + if (0 == randomize(m_randc)) begin + end endtask endclass endpackage