mirror of
https://github.com/verilator/verilator.git
synced 2025-01-01 04:07:34 +00:00
Internals: Create V3WidthCommit from overly fat header. No functional change intended.
This commit is contained in:
parent
0e0df1fb3b
commit
e2343c03e0
@ -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
|
||||
|
@ -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 \
|
||||
|
@ -77,12 +77,13 @@
|
||||
#include "V3Randomize.h"
|
||||
#include "V3String.h"
|
||||
#include "V3Task.h"
|
||||
#include "V3WidthCommit.h"
|
||||
|
||||
#include <algorithm>
|
||||
|
||||
// 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);
|
||||
}
|
||||
|
@ -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;
|
||||
|
||||
|
236
src/V3WidthCommit.cpp
Normal file
236
src/V3WidthCommit.cpp
Normal file
@ -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);
|
||||
}
|
@ -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;
|
||||
};
|
||||
|
||||
//######################################################################
|
||||
|
63
src/V3WidthRemove.h
Normal file
63
src/V3WidthRemove.h
Normal file
@ -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
|
@ -104,6 +104,7 @@
|
||||
#include "V3VariableOrder.h"
|
||||
#include "V3Waiver.h"
|
||||
#include "V3Width.h"
|
||||
#include "V3WidthCommit.h"
|
||||
|
||||
#include <ctime>
|
||||
|
||||
@ -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);
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user