mirror of
https://github.com/verilator/verilator.git
synced 2026-10-06 10:03:44 +02:00
The constant pool is now an ordinary package, created with the netlist and instantiated under $root like any other package, and most special handling has been removed, including AstConstPool. Lookups go through V3ConstPool, which has a singleton instance owned by V3Global. Static methods on V3Common form the public interfce to add/find constant pool entries. With that, the constant pool is usable at any stage during compilation, so enum and dimension tables created by V3Width, and enum value tables created by V3Randomize now also live in the constant pool instead of $unit, so identical tables are shared. Associative array constants are handled separately from unpacked tables, which used to be broken but unused. Emitted constant pool variables use direct initialization, and `constinit` with C++20 where the type allows it. This ensures we don't change a run-time in a way that would result in unintended code size increase. -fno-merge-const-pool, which was introduced years ago but never prompted a bug report is deprecated and has no effect. This is also prep for future work.
126 lines
4.9 KiB
C++
126 lines
4.9 KiB
C++
// -*- mode: C++; c-file-style: "cc-mode" -*-
|
|
//*************************************************************************
|
|
// DESCRIPTION: Verilator: Handle SV classes
|
|
//
|
|
// Code available from: https://verilator.org
|
|
//
|
|
//*************************************************************************
|
|
//
|
|
// 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-FileCopyrightText: 2003-2026 Wilson Snyder
|
|
// SPDX-License-Identifier: LGPL-3.0-only OR Artistic-2.0
|
|
//
|
|
//*************************************************************************
|
|
// V3CUse's Transformations:
|
|
//
|
|
// Each module:
|
|
// Each cell:
|
|
// Create CUse for cell forward declaration
|
|
// Search for dtypes referencing class, and create CUse for forward declaration
|
|
//
|
|
//*************************************************************************
|
|
|
|
#include "V3PchAstNoMT.h" // VL_MT_DISABLED_CODE_UNIT
|
|
|
|
#include "V3CUse.h"
|
|
|
|
VL_DEFINE_DEBUG_FUNCTIONS;
|
|
|
|
//######################################################################
|
|
|
|
// Visit within a module all nodes and data types they reference, finding
|
|
// any classes so we can make sure they are defined when Verilated code
|
|
// compiles
|
|
class CUseVisitor final : public VNVisitorConst {
|
|
// NODE STATE
|
|
// AstNode::user1() -> bool. True if already visited
|
|
const VNUser1InUse m_inuser1;
|
|
|
|
// MEMBERS
|
|
AstNodeModule* const m_modp; // Current module
|
|
std::map<std::string, std::pair<FileLine*, VUseType>> m_didUse; // What we already used
|
|
|
|
// METHODS
|
|
void addNewUse(const AstNode* nodep, VUseType useType, const string& name) {
|
|
auto e = m_didUse.emplace(name, std::make_pair(nodep->fileline(), useType));
|
|
if (e.second || ((e.first->second.second & useType) != useType)) {
|
|
e.first->second.second = e.first->second.second | useType;
|
|
}
|
|
}
|
|
|
|
// VISITORS
|
|
void visit(AstClassRefDType* nodep) override {
|
|
addNewUse(nodep, VUseType::INT_FWD_CLASS, nodep->classp()->name());
|
|
}
|
|
void visit(AstCFunc* nodep) override {
|
|
if (nodep->user1SetOnce()) return;
|
|
iterateAndNextConstNull(nodep->argsp());
|
|
iterateAndNextConstNull(nodep->stmtsp());
|
|
}
|
|
void visit(AstCCall* /*nodep*/) override {}
|
|
void visit(AstCReturn* nodep) override {
|
|
UASSERT_OBJ(!nodep->user1SetOnce(), nodep, "Visited same return twice");
|
|
iterateConst(nodep->lhsp()->dtypep());
|
|
}
|
|
void visit(AstNodeDType* nodep) override {
|
|
if (nodep->user1SetOnce()) return; // Process once
|
|
if (nodep->virtRefDTypep()) iterateConst(nodep->virtRefDTypep());
|
|
if (nodep->virtRefDType2p()) iterateConst(nodep->virtRefDType2p());
|
|
|
|
// Add a CUse for every struct that requires a declaration
|
|
AstNodeUOrStructDType* const stypep = VN_CAST(nodep->skipRefp(), NodeUOrStructDType);
|
|
if (stypep && stypep->classOrPackagep()) {
|
|
addNewUse(nodep, VUseType::INT_INCLUDE, stypep->classOrPackagep()->name());
|
|
iterateChildrenConst(stypep);
|
|
} else if (const AstClassRefDType* const classp
|
|
= VN_CAST(nodep->skipRefp(), ClassRefDType)) {
|
|
addNewUse(nodep, VUseType::INT_FWD_CLASS, classp->name());
|
|
}
|
|
}
|
|
void visit(AstNode* nodep) override {
|
|
if (nodep->user1SetOnce()) return; // Process once
|
|
if (nodep->dtypep()) iterateConst(nodep->dtypep());
|
|
iterateChildrenConst(nodep);
|
|
}
|
|
void visit(AstCell* nodep) override {
|
|
if (nodep->user1SetOnce()) return; // Process once
|
|
if (nodep->modp()->isConstPool()) return; // Special emit rules
|
|
// Currently no IMP_INCLUDE because we include __Syms which has them all
|
|
addNewUse(nodep, VUseType::INT_FWD_CLASS, nodep->modp()->name());
|
|
iterateChildrenConst(nodep);
|
|
}
|
|
|
|
public:
|
|
// CONSTRUCTORS
|
|
explicit CUseVisitor(AstNodeModule* modp)
|
|
: m_modp{modp} {
|
|
iterateConst(modp);
|
|
|
|
for (const auto& used : m_didUse) {
|
|
AstCUse* const newp = new AstCUse{used.second.first, used.second.second, used.first};
|
|
m_modp->addStmtsp(newp);
|
|
UINFO(8, "Insert " << newp);
|
|
}
|
|
}
|
|
~CUseVisitor() override = default;
|
|
VL_UNCOPYABLE(CUseVisitor);
|
|
};
|
|
|
|
//######################################################################
|
|
// Class class functions
|
|
|
|
void V3CUse::cUseAll() {
|
|
UINFO(2, __FUNCTION__ << ":");
|
|
// Call visitor separately for each module, so visitor state is cleared
|
|
for (AstNodeModule* modp = v3Global.rootp()->modulesp(); modp;
|
|
modp = VN_AS(modp->nextp(), NodeModule)) {
|
|
if (modp->isConstPool()) continue; // Special emit rules
|
|
// Insert under this module; someday we should e.g. make Ast
|
|
// for each output file and put under that
|
|
CUseVisitor{modp};
|
|
}
|
|
V3Global::dumpCheckGlobalTree("cuse", 0, dumpTreeEitherLevel() >= 3);
|
|
}
|