From e2343c03e07db2c40c6a7d71512220e36155f9d9 Mon Sep 17 00:00:00 2001 From: Wilson Snyder Date: Fri, 6 Oct 2023 23:18:26 -0400 Subject: [PATCH] Internals: Create V3WidthCommit from overly fat header. No functional change intended. --- src/CMakeLists.txt | 2 + src/Makefile_obj.in | 3 +- src/V3Width.cpp | 12 +-- src/V3Width.h | 2 - src/V3WidthCommit.cpp | 236 ++++++++++++++++++++++++++++++++++++++++++ src/V3WidthCommit.h | 235 +---------------------------------------- src/V3WidthRemove.h | 63 +++++++++++ src/Verilator.cpp | 3 +- 8 files changed, 312 insertions(+), 244 deletions(-) create mode 100644 src/V3WidthCommit.cpp create mode 100644 src/V3WidthRemove.h diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 393eba402..b2fbf9f4d 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -166,6 +166,7 @@ set(HEADERS V3Waiver.h V3Width.h V3WidthCommit.h + V3WidthRemove.h VlcBucket.h VlcOptions.h VlcPoint.h @@ -298,6 +299,7 @@ set(COMMON_SOURCES V3VariableOrder.cpp V3Waiver.cpp V3Width.cpp + V3WidthCommit.cpp V3WidthSel.cpp V3ParseImp.cpp V3ParseGrammar.cpp diff --git a/src/Makefile_obj.in b/src/Makefile_obj.in index b076f1a2a..36ae799bb 100644 --- a/src/Makefile_obj.in +++ b/src/Makefile_obj.in @@ -278,6 +278,7 @@ RAW_OBJS = \ V3VariableOrder.o \ V3Waiver.o \ V3Width.o \ + V3WidthCommit.o \ V3WidthSel.o \ # verilator_coverage @@ -291,7 +292,7 @@ NON_STANDALONE_HEADERS = \ V3AstNodeOther.h \ V3DfgVertices.h \ V3ThreadPool.h \ - V3WidthCommit.h \ + V3WidthRemove.h \ AST_DEFS := \ V3AstNodeDType.h \ diff --git a/src/V3Width.cpp b/src/V3Width.cpp index 7f7e8214f..b87fe81e4 100644 --- a/src/V3Width.cpp +++ b/src/V3Width.cpp @@ -77,12 +77,13 @@ #include "V3Randomize.h" #include "V3String.h" #include "V3Task.h" +#include "V3WidthCommit.h" #include // More code; this file was getting too large; see actions there #define VERILATOR_V3WIDTH_CPP_ -#include "V3WidthCommit.h" +#include "V3WidthRemove.h" VL_DEFINE_DEBUG_FUNCTIONS; @@ -4311,8 +4312,7 @@ private: if (VN_IS(valuep, Const)) { // Forming a AstConcat will cause problems with // unsized (uncommitted sized) constants - if (AstConst* const newp - = WidthCommitVisitor::newIfConstCommitSize(VN_AS(valuep, Const))) { + if (AstConst* const newp = V3WidthCommit::newIfConstCommitSize(VN_AS(valuep, Const))) { VL_DO_DANGLING(pushDeletep(valuep), valuep); valuep = newp; } @@ -7614,9 +7614,3 @@ AstNode* V3Width::widthGenerateParamsEdit( // No WidthRemoveVisitor, as don't want to drop $signed etc inside gen blocks return nodep; } - -void V3Width::widthCommit(AstNetlist* nodep) { - UINFO(2, __FUNCTION__ << ": " << endl); - { WidthCommitVisitor{nodep}; } // Destruct before checking - V3Global::dumpCheckGlobalTree("widthcommit", 0, dumpTreeLevel() >= 6); -} diff --git a/src/V3Width.h b/src/V3Width.h index 29021146f..fd9f17af5 100644 --- a/src/V3Width.h +++ b/src/V3Width.h @@ -33,8 +33,6 @@ public: static void width(AstNetlist* nodep) VL_MT_DISABLED; static AstNode* widthParamsEdit(AstNode* nodep) VL_MT_DISABLED; static AstNode* widthGenerateParamsEdit(AstNode* nodep) VL_MT_DISABLED; - // Final step... Mark all widths as equal - static void widthCommit(AstNetlist* nodep) VL_MT_DISABLED; static AstNodeDType* getCommonClassTypep(AstNode* nodep1, AstNode* nodep2) VL_MT_DISABLED; diff --git a/src/V3WidthCommit.cpp b/src/V3WidthCommit.cpp new file mode 100644 index 000000000..295d3be8d --- /dev/null +++ b/src/V3WidthCommit.cpp @@ -0,0 +1,236 @@ +// -*- mode: C++; c-file-style: "cc-mode" -*- +//************************************************************************* +// DESCRIPTION: Verilator: Commit expression widths +// +// Code available from: https://verilator.org +// +//************************************************************************* +// +// Copyright 2003-2023 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 +// +//************************************************************************* +// +// Remove all $signed, $unsigned, we're done with them. +// +// This step is only called on real V3Width, not intermediate e.g. widthParams +// +//************************************************************************* + +#define VL_MT_DISABLED_CODE_UNIT 1 + +#include "config_build.h" +#include "verilatedos.h" + +#include "V3WidthCommit.h" + +VL_DEFINE_DEBUG_FUNCTIONS; + +//###################################################################### +// Now that all widthing is complete, +// Copy all width() to widthMin(). V3Const expects this + +class WidthCommitVisitor final : public VNVisitor { + // NODE STATE + // AstVar::user1p -> bool, processed + const VNUser1InUse m_inuser1; + + // STATE + AstNodeModule* m_modp = nullptr; + +public: + // METHODS + VL_DEFINE_DEBUG_FUNCTIONS; + +private: + // METHODS + void editDType(AstNode* nodep) { + // Edit dtypes for this node + nodep->dtypep(editOneDType(nodep->dtypep())); + } + AstNodeDType* editOneDType(AstNodeDType* nodep) { + // See if the dtype/refDType can be converted to a standard one + // This reduces the number of dtypes in the system, and since + // dtypep() figures into sameTree() results in better optimizations + if (!nodep) return nullptr; + // Recurse to handle the data type, as may change the size etc of this type + if (!nodep->user1()) iterate(nodep); + // Look for duplicate + if (AstBasicDType* const bdtypep = VN_CAST(nodep, BasicDType)) { + AstBasicDType* const newp = nodep->findInsertSameDType(bdtypep); + if (newp != bdtypep && debug() >= 9) { + UINFO(9, "dtype replacement "); + nodep->dumpSmall(std::cout); + std::cout << " ----> "; + newp->dumpSmall(std::cout); + std::cout << std::endl; + } + return newp; + } + return nodep; + } + void classEncapCheck(AstNode* nodep, AstNode* defp, AstClass* defClassp) { + // Call on non-local class to check local/protected status and complain + bool local = false; + bool prot = false; + if (const auto varp = VN_CAST(defp, Var)) { + local = varp->isHideLocal(); + prot = varp->isHideProtected(); + } else if (const auto ftaskp = VN_CAST(defp, NodeFTask)) { + local = ftaskp->isHideLocal(); + prot = ftaskp->isHideProtected(); + } else { + nodep->v3fatalSrc("ref to unhandled definition type " << defp->prettyTypeName()); + } + if (local || prot) { + const auto refClassp = VN_CAST(m_modp, Class); + const char* how = nullptr; + if (local && defClassp && refClassp != defClassp) { + how = "'local'"; + } else if (prot && defClassp && !AstClass::isClassExtendedFrom(refClassp, defClassp)) { + how = "'protected'"; + } + if (how) { + UINFO(9, "refclass " << refClassp << endl); + UINFO(9, "defclass " << defClassp << endl); + nodep->v3warn(ENCAPSULATED, nodep->prettyNameQ() + << " is hidden as " << how + << " within this context (IEEE 1800-2017 8.18)\n" + << nodep->warnContextPrimary() << endl + << nodep->warnOther() + << "... Location of definition" << endl + << defp->warnContextSecondary()); + } + } + } + + // VISITORS + void visit(AstNodeModule* nodep) override { + VL_RESTORER(m_modp); + { + m_modp = nodep; + iterateChildren(nodep); + editDType(nodep); + } + } + void visit(AstConst* nodep) override { + if (nodep->user1SetOnce()) return; // Process once + UASSERT_OBJ(nodep->dtypep(), nodep, "No dtype"); + iterate(nodep->dtypep()); // Do datatype first + if (AstConst* const newp = V3WidthCommit::newIfConstCommitSize(nodep)) { + nodep->replaceWith(newp); + AstNode* const oldp = nodep; + nodep = newp; + // if (debug() > 4) oldp->dumpTree("- fixConstSize_old: "); + // if (debug() > 4) newp->dumpTree("- _new: "); + VL_DO_DANGLING(pushDeletep(oldp), oldp); + } + editDType(nodep); + } + void visit(AstCastWrap* nodep) override { + iterateChildren(nodep); + editDType(nodep); + UINFO(6, " Replace " << nodep << " w/ " << nodep->lhsp() << endl); + nodep->replaceWith(nodep->lhsp()->unlinkFrBack()); + VL_DO_DANGLING(pushDeletep(nodep), nodep); + } + void visit(AstNodeDType* nodep) override { + // Note some specific dtypes have unique visitors + visitIterateNodeDType(nodep); + } + void visit(AstNodeUOrStructDType* nodep) override { + if (nodep->user1SetOnce()) return; // Process once + visitIterateNodeDType(nodep); + } + void visit(AstEnumDType* nodep) override { + nodep->tableMap().clear(); // Only needed up through V3Width process + visitIterateNodeDType(nodep); + } + void visit(AstParamTypeDType* nodep) override { + if (nodep->user1SetOnce()) return; // Process once + visitIterateNodeDType(nodep); + // Move to type table as all dtype pointers must resolve there + nodep->unlinkFrBack(); // Make non-child + v3Global.rootp()->typeTablep()->addTypesp(nodep); + } + void visitIterateNodeDType(AstNodeDType* nodep) { + // Rather than use dtypeChg which may make new nodes, we edit in place, + // as we don't need to preserve any widthMin's, and every dtype with the same width + // gets an identical edit. + if (nodep->user1SetOnce()) return; // Process once + nodep->widthMinFromWidth(); + // Too late to any unspecified sign to be anything but unsigned + if (nodep->numeric().isNosign()) nodep->numeric(VSigning::UNSIGNED); + iterateChildren(nodep); + nodep->virtRefDTypep(editOneDType(nodep->virtRefDTypep())); + nodep->virtRefDType2p(editOneDType(nodep->virtRefDType2p())); + } + void visit(AstNodeFTask* nodep) override { + iterateChildren(nodep); + editDType(nodep); + AstClass* classp = VN_CAST(m_modp, Class); + if (nodep->classMethod() && nodep->pureVirtual() && classp && !classp->isInterfaceClass() + && !classp->isVirtual()) { + nodep->v3error( + "Illegal to have 'pure virtual' in non-virtual class (IEEE 1800-2017 8.21)"); + } + } + void visit(AstNodeVarRef* nodep) override { + iterateChildren(nodep); + editDType(nodep); + classEncapCheck(nodep, nodep->varp(), VN_CAST(nodep->classOrPackagep(), Class)); + } + void visit(AstNodeFTaskRef* nodep) override { + iterateChildren(nodep); + editDType(nodep); + classEncapCheck(nodep, nodep->taskp(), VN_CAST(nodep->classOrPackagep(), Class)); + } + void visit(AstMemberSel* nodep) override { + iterateChildren(nodep); + editDType(nodep); + if (auto* const classrefp = VN_CAST(nodep->fromp()->dtypep(), ClassRefDType)) { + classEncapCheck(nodep, nodep->varp(), classrefp->classp()); + } // else might be struct, etc + } + void visit(AstVar* nodep) override { + iterateChildren(nodep); + editDType(nodep); + if (nodep->isFuncLocal() && nodep->direction() == VDirection::INPUT && nodep->valuep()) { + // It's the default value of optional argument. + // Such values are added to function calls in V3Width so can be removed now + pushDeletep(nodep->valuep()->unlinkFrBack()); + } + } + void visit(AstNodePreSel* nodep) override { // LCOV_EXCL_LINE + // This check could go anywhere after V3Param + nodep->v3fatalSrc("Presels should have been removed before this point"); + } + void visit(AstNode* nodep) override { + iterateChildren(nodep); + editDType(nodep); + } + +public: + // CONSTRUCTORS + explicit WidthCommitVisitor(AstNetlist* nodep) { + // Were changing widthMin's, so the table is now somewhat trashed + nodep->typeTablep()->clearCache(); + iterate(nodep); + // Don't want to AstTypeTable::repairCache, as all needed nodes + // have been added back in; a repair would prevent dead nodes from + // being detected + } + ~WidthCommitVisitor() override = default; +}; + +//###################################################################### +// V3WidthCommit class functions + +void V3WidthCommit::widthCommit(AstNetlist* nodep) { + UINFO(2, __FUNCTION__ << ": " << endl); + { WidthCommitVisitor{nodep}; } // Destruct before checking + V3Global::dumpCheckGlobalTree("widthcommit", 0, dumpTreeLevel() >= 6); +} diff --git a/src/V3WidthCommit.h b/src/V3WidthCommit.h index ec538084c..4c61e0da8 100644 --- a/src/V3WidthCommit.h +++ b/src/V3WidthCommit.h @@ -23,60 +23,10 @@ #include "V3Ast.h" #include "V3Error.h" -// clang-format off -#ifndef VERILATOR_V3WIDTH_CPP_ -# error "V3WidthCommit for V3Width internal use only" -#endif -// clang-format on - -//###################################################################### - -/// Remove all $signed, $unsigned, we're done with them. -/// This step is only called on real V3Width, not intermediate e.g. widthParams - -class WidthRemoveVisitor final : public VNVisitor { - // METHODS - VL_DEFINE_DEBUG_FUNCTIONS; - - void replaceWithSignedVersion(AstNode* nodep, AstNode* newp) { - UINFO(6, " Replace " << nodep << " w/ " << newp << endl); - nodep->replaceWith(newp); - newp->dtypeFrom(nodep); - VL_DO_DANGLING(pushDeletep(nodep), nodep); - } - - // VISITORS - void visit(AstSigned* nodep) override { - VL_DO_DANGLING(replaceWithSignedVersion(nodep, nodep->lhsp()->unlinkFrBack()), nodep); - } - void visit(AstUnsigned* nodep) override { - VL_DO_DANGLING(replaceWithSignedVersion(nodep, nodep->lhsp()->unlinkFrBack()), nodep); - } - void visit(AstNode* nodep) override { iterateChildren(nodep); } +//============================================================================ +class V3WidthCommit final { public: - // CONSTRUCTORS - WidthRemoveVisitor() = default; - ~WidthRemoveVisitor() override = default; - AstNode* mainAcceptEdit(AstNode* nodep) { return iterateSubtreeReturnEdits(nodep); } -}; - -//###################################################################### -// Now that all widthing is complete, -// Copy all width() to widthMin(). V3Const expects this - -class WidthCommitVisitor final : public VNVisitor { - // NODE STATE - // AstVar::user1p -> bool, processed - const VNUser1InUse m_inuser1; - - // STATE - AstNodeModule* m_modp = nullptr; - -public: - // METHODS - VL_DEFINE_DEBUG_FUNCTIONS; - static AstConst* newIfConstCommitSize(AstConst* nodep) { if (((nodep->dtypep()->width() != nodep->num().width()) || !nodep->num().sized()) && !nodep->num().isString()) { // Need to force the number from unsized to sized @@ -92,185 +42,8 @@ public: } } -private: - // METHODS - void editDType(AstNode* nodep) { - // Edit dtypes for this node - nodep->dtypep(editOneDType(nodep->dtypep())); - } - AstNodeDType* editOneDType(AstNodeDType* nodep) { - // See if the dtype/refDType can be converted to a standard one - // This reduces the number of dtypes in the system, and since - // dtypep() figures into sameTree() results in better optimizations - if (!nodep) return nullptr; - // Recurse to handle the data type, as may change the size etc of this type - if (!nodep->user1()) iterate(nodep); - // Look for duplicate - if (AstBasicDType* const bdtypep = VN_CAST(nodep, BasicDType)) { - AstBasicDType* const newp = nodep->findInsertSameDType(bdtypep); - if (newp != bdtypep && debug() >= 9) { - UINFO(9, "dtype replacement "); - nodep->dumpSmall(std::cout); - std::cout << " ----> "; - newp->dumpSmall(std::cout); - std::cout << std::endl; - } - return newp; - } - return nodep; - } - void classEncapCheck(AstNode* nodep, AstNode* defp, AstClass* defClassp) { - // Call on non-local class to check local/protected status and complain - bool local = false; - bool prot = false; - if (const auto varp = VN_CAST(defp, Var)) { - local = varp->isHideLocal(); - prot = varp->isHideProtected(); - } else if (const auto ftaskp = VN_CAST(defp, NodeFTask)) { - local = ftaskp->isHideLocal(); - prot = ftaskp->isHideProtected(); - } else { - nodep->v3fatalSrc("ref to unhandled definition type " << defp->prettyTypeName()); - } - if (local || prot) { - const auto refClassp = VN_CAST(m_modp, Class); - const char* how = nullptr; - if (local && defClassp && refClassp != defClassp) { - how = "'local'"; - } else if (prot && defClassp && !AstClass::isClassExtendedFrom(refClassp, defClassp)) { - how = "'protected'"; - } - if (how) { - UINFO(9, "refclass " << refClassp << endl); - UINFO(9, "defclass " << defClassp << endl); - nodep->v3warn(ENCAPSULATED, nodep->prettyNameQ() - << " is hidden as " << how - << " within this context (IEEE 1800-2017 8.18)\n" - << nodep->warnContextPrimary() << endl - << nodep->warnOther() - << "... Location of definition" << endl - << defp->warnContextSecondary()); - } - } - } - - // VISITORS - void visit(AstNodeModule* nodep) override { - VL_RESTORER(m_modp); - { - m_modp = nodep; - iterateChildren(nodep); - editDType(nodep); - } - } - void visit(AstConst* nodep) override { - if (nodep->user1SetOnce()) return; // Process once - UASSERT_OBJ(nodep->dtypep(), nodep, "No dtype"); - iterate(nodep->dtypep()); // Do datatype first - if (AstConst* const newp = newIfConstCommitSize(nodep)) { - nodep->replaceWith(newp); - AstNode* const oldp = nodep; - nodep = newp; - // if (debug() > 4) oldp->dumpTree("- fixConstSize_old: "); - // if (debug() > 4) newp->dumpTree("- _new: "); - VL_DO_DANGLING(pushDeletep(oldp), oldp); - } - editDType(nodep); - } - void visit(AstCastWrap* nodep) override { - iterateChildren(nodep); - editDType(nodep); - UINFO(6, " Replace " << nodep << " w/ " << nodep->lhsp() << endl); - nodep->replaceWith(nodep->lhsp()->unlinkFrBack()); - VL_DO_DANGLING(pushDeletep(nodep), nodep); - } - void visit(AstNodeDType* nodep) override { - // Note some specific dtypes have unique visitors - visitIterateNodeDType(nodep); - } - void visit(AstNodeUOrStructDType* nodep) override { - if (nodep->user1SetOnce()) return; // Process once - visitIterateNodeDType(nodep); - } - void visit(AstEnumDType* nodep) override { - nodep->tableMap().clear(); // Only needed up through V3Width process - visitIterateNodeDType(nodep); - } - void visit(AstParamTypeDType* nodep) override { - if (nodep->user1SetOnce()) return; // Process once - visitIterateNodeDType(nodep); - // Move to type table as all dtype pointers must resolve there - nodep->unlinkFrBack(); // Make non-child - v3Global.rootp()->typeTablep()->addTypesp(nodep); - } - void visitIterateNodeDType(AstNodeDType* nodep) { - // Rather than use dtypeChg which may make new nodes, we edit in place, - // as we don't need to preserve any widthMin's, and every dtype with the same width - // gets an identical edit. - if (nodep->user1SetOnce()) return; // Process once - nodep->widthMinFromWidth(); - // Too late to any unspecified sign to be anything but unsigned - if (nodep->numeric().isNosign()) nodep->numeric(VSigning::UNSIGNED); - iterateChildren(nodep); - nodep->virtRefDTypep(editOneDType(nodep->virtRefDTypep())); - nodep->virtRefDType2p(editOneDType(nodep->virtRefDType2p())); - } - void visit(AstNodeFTask* nodep) override { - iterateChildren(nodep); - editDType(nodep); - AstClass* classp = VN_CAST(m_modp, Class); - if (nodep->classMethod() && nodep->pureVirtual() && classp && !classp->isInterfaceClass() - && !classp->isVirtual()) { - nodep->v3error( - "Illegal to have 'pure virtual' in non-virtual class (IEEE 1800-2017 8.21)"); - } - } - void visit(AstNodeVarRef* nodep) override { - iterateChildren(nodep); - editDType(nodep); - classEncapCheck(nodep, nodep->varp(), VN_CAST(nodep->classOrPackagep(), Class)); - } - void visit(AstNodeFTaskRef* nodep) override { - iterateChildren(nodep); - editDType(nodep); - classEncapCheck(nodep, nodep->taskp(), VN_CAST(nodep->classOrPackagep(), Class)); - } - void visit(AstMemberSel* nodep) override { - iterateChildren(nodep); - editDType(nodep); - if (auto* const classrefp = VN_CAST(nodep->fromp()->dtypep(), ClassRefDType)) { - classEncapCheck(nodep, nodep->varp(), classrefp->classp()); - } // else might be struct, etc - } - void visit(AstVar* nodep) override { - iterateChildren(nodep); - editDType(nodep); - if (nodep->isFuncLocal() && nodep->direction() == VDirection::INPUT && nodep->valuep()) { - // It's the default value of optional argument. - // Such values are added to function calls in V3Width so can be removed now - pushDeletep(nodep->valuep()->unlinkFrBack()); - } - } - void visit(AstNodePreSel* nodep) override { // LCOV_EXCL_LINE - // This check could go anywhere after V3Param - nodep->v3fatalSrc("Presels should have been removed before this point"); - } - void visit(AstNode* nodep) override { - iterateChildren(nodep); - editDType(nodep); - } - -public: - // CONSTRUCTORS - explicit WidthCommitVisitor(AstNetlist* nodep) { - // Were changing widthMin's, so the table is now somewhat trashed - nodep->typeTablep()->clearCache(); - iterate(nodep); - // Don't want to AstTypeTable::repairCache, as all needed nodes - // have been added back in; a repair would prevent dead nodes from - // being detected - } - ~WidthCommitVisitor() override = default; + // Final step... Mark all widths as equal + static void widthCommit(AstNetlist* nodep) VL_MT_DISABLED; }; //###################################################################### diff --git a/src/V3WidthRemove.h b/src/V3WidthRemove.h new file mode 100644 index 000000000..23469299e --- /dev/null +++ b/src/V3WidthRemove.h @@ -0,0 +1,63 @@ +// -*- mode: C++; c-file-style: "cc-mode" -*- +//************************************************************************* +// DESCRIPTION: Verilator: Cleanup stage in V3Width +// +// Code available from: https://verilator.org +// +//************************************************************************* +// +// Copyright 2003-2023 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 +// +//************************************************************************* + +#ifndef VERILATOR_V3WIDTHREMOVE_H_ +#define VERILATOR_V3WIDTHREMOVE_H_ + +#include "config_build.h" +#include "verilatedos.h" + +#include "V3Ast.h" +#include "V3Error.h" + +// clang-format off +#ifndef VERILATOR_V3WIDTH_CPP_ +# error "V3WidthRemove for V3Width internal use only" +#endif +// clang-format on + +//###################################################################### + +class WidthRemoveVisitor final : public VNVisitor { + // METHODS + VL_DEFINE_DEBUG_FUNCTIONS; + + void replaceWithSignedVersion(AstNode* nodep, AstNode* newp) { + UINFO(6, " Replace " << nodep << " w/ " << newp << endl); + nodep->replaceWith(newp); + newp->dtypeFrom(nodep); + VL_DO_DANGLING(pushDeletep(nodep), nodep); + } + + // VISITORS + void visit(AstSigned* nodep) override { + VL_DO_DANGLING(replaceWithSignedVersion(nodep, nodep->lhsp()->unlinkFrBack()), nodep); + } + void visit(AstUnsigned* nodep) override { + VL_DO_DANGLING(replaceWithSignedVersion(nodep, nodep->lhsp()->unlinkFrBack()), nodep); + } + void visit(AstNode* nodep) override { iterateChildren(nodep); } + +public: + // CONSTRUCTORS + WidthRemoveVisitor() = default; + ~WidthRemoveVisitor() override = default; + AstNode* mainAcceptEdit(AstNode* nodep) { return iterateSubtreeReturnEdits(nodep); } +}; + +//###################################################################### + +#endif // Guard diff --git a/src/Verilator.cpp b/src/Verilator.cpp index 99af25820..e5ba41c55 100644 --- a/src/Verilator.cpp +++ b/src/Verilator.cpp @@ -104,6 +104,7 @@ #include "V3VariableOrder.h" #include "V3Waiver.h" #include "V3Width.h" +#include "V3WidthCommit.h" #include @@ -189,7 +190,7 @@ static void process() { V3Error::abortIfErrors(); // Commit to the widths we've chosen; Make widthMin==width - V3Width::widthCommit(v3Global.rootp()); + V3WidthCommit::widthCommit(v3Global.rootp()); v3Global.assertDTypesResolved(true); v3Global.widthMinUsage(VWidthMinUsage::MATCHES_WIDTH);