From 76fe224e7cf78b56472d13159d418b59ed20da47 Mon Sep 17 00:00:00 2001 From: Todd Strader Date: Fri, 18 Oct 2024 19:52:25 -0400 Subject: [PATCH] Fix complex user type problem with --x-assign (#5543) --- src/V3LinkDot.cpp | 7 +++-- src/V3Unknown.cpp | 13 +++++--- test_regress/t/t_user_type_xassign.py | 18 +++++++++++ test_regress/t/t_user_type_xassign.v | 43 +++++++++++++++++++++++++++ 4 files changed, 74 insertions(+), 7 deletions(-) create mode 100755 test_regress/t/t_user_type_xassign.py create mode 100644 test_regress/t/t_user_type_xassign.v diff --git a/src/V3LinkDot.cpp b/src/V3LinkDot.cpp index 4a1150aac..41a449d33 100644 --- a/src/V3LinkDot.cpp +++ b/src/V3LinkDot.cpp @@ -1333,9 +1333,10 @@ class LinkDotFindVisitor final : public VNVisitor { } else { findvarp->combineType(nodep); findvarp->fileline()->modifyStateInherit(nodep->fileline()); - if (nodep->getChildDTypep()->numeric().isSigned() - && !findvarp->getChildDTypep()->numeric().isSigned()) { - findvarp->getChildDTypep()->numeric(VSigning{true}); + UASSERT_OBJ(nodep->subDTypep(), nodep, "Var has no type"); + if (nodep->subDTypep()->numeric().isSigned() + && !findvarp->subDTypep()->numeric().isSigned()) { + findvarp->subDTypep()->numeric(VSigning{true}); } AstBasicDType* const bdtypep = VN_CAST(findvarp->childDTypep(), BasicDType); diff --git a/src/V3Unknown.cpp b/src/V3Unknown.cpp index 0b89d02e4..44fdce79f 100644 --- a/src/V3Unknown.cpp +++ b/src/V3Unknown.cpp @@ -48,6 +48,7 @@ class UnknownVisitor final : public VNVisitor { // AstNode::user2p() -> AstIf* Inserted if assignment for conditional const VNUser1InUse m_inuser1; const VNUser2InUse m_inuser2; + static const std::string m_xrandPrefix; // STATE AstNodeModule* m_modp = nullptr; // Current module @@ -58,7 +59,7 @@ class UnknownVisitor final : public VNVisitor { bool m_allowXUnique = true; // Allow unique assignments VDouble0 m_statUnkVars; // Statistic tracking V3UniqueNames m_lvboundNames; // For generating unique temporary variable names - V3UniqueNames m_xrandNames; // For generating unique temporary variable names + std::unique_ptr m_xrandNames; // For generating unique temporary variable names // METHODS @@ -141,14 +142,16 @@ class UnknownVisitor final : public VNVisitor { VL_RESTORER(m_modp); VL_RESTORER(m_constXCvt); VL_RESTORER(m_allowXUnique); + auto xrandNames = std::make_unique(m_xrandPrefix); { m_modp = nodep; m_constXCvt = true; // Class X randomization causes Vxrand in strange places, so disable if (VN_IS(nodep, Class)) m_allowXUnique = false; m_lvboundNames.reset(); - m_xrandNames.reset(); + xrandNames.swap(m_xrandNames); iterateChildren(nodep); + xrandNames.swap(m_xrandNames); } } void visit(AstAssignDly* nodep) override { @@ -345,7 +348,7 @@ class UnknownVisitor final : public VNVisitor { // We use the special XTEMP type so it doesn't break pure functions UASSERT_OBJ(m_modp, nodep, "X number not under module"); AstVar* const newvarp - = new AstVar{nodep->fileline(), VVarType::XTEMP, m_xrandNames.get(nodep), + = new AstVar{nodep->fileline(), VVarType::XTEMP, m_xrandNames->get(nodep), VFlagLogicPacked{}, nodep->width()}; newvarp->lifetime(VLifetime::STATIC); ++m_statUnkVars; @@ -517,7 +520,7 @@ public: // CONSTRUCTORS explicit UnknownVisitor(AstNetlist* nodep) : m_lvboundNames{"__Vlvbound"} - , m_xrandNames{"__Vxrand"} { + , m_xrandNames{std::make_unique(m_xrandPrefix)} { iterate(nodep); } ~UnknownVisitor() override { // @@ -525,6 +528,8 @@ public: } }; +const std::string UnknownVisitor::m_xrandPrefix = "__Vxrand"; + //###################################################################### // Unknown class functions diff --git a/test_regress/t/t_user_type_xassign.py b/test_regress/t/t_user_type_xassign.py new file mode 100755 index 000000000..d4f986441 --- /dev/null +++ b/test_regress/t/t_user_type_xassign.py @@ -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() + +test.passes() diff --git a/test_regress/t/t_user_type_xassign.v b/test_regress/t/t_user_type_xassign.v new file mode 100644 index 000000000..9cfc02cd9 --- /dev/null +++ b/test_regress/t/t_user_type_xassign.v @@ -0,0 +1,43 @@ +// DESCRIPTION: Verilator: Demonstrate complex user typea problem with --x-assign +// +// This file ONLY is placed into the Public Domain, for any use, +// without warranty, 2024 by Wilson Snyder. +// SPDX-License-Identifier: CC0-1.0 + +module t (/*AUTOARG*/ + // Inputs + clk + ); + + input clk; + + typedef logic [31:0] int_t; + typedef int_t [6:0] bar_t; + bar_t the_bar; + + logic [31:0] thing_one; + always_comb begin + for (int sel = 0; sel < 1; sel++) + thing_one = the_bar[sel]; + end + + virtual class SomeClass; + static function logic compare(int a, int b); + return a > b; + endfunction + endclass + + logic [31:0] thing_two; + always_comb begin + for (int sel_a = 0; sel_a < 1; sel_a++) + thing_two = the_bar[sel_a]; + end + + // finish report + always @ (posedge clk) begin + $write("*-* All Finished *-*\n"); + $finish; + end + + +endmodule