mirror of
https://github.com/verilator/verilator.git
synced 2026-10-06 01:54:01 +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.
231 lines
9.1 KiB
C++
231 lines
9.1 KiB
C++
// -*- mode: C++; c-file-style: "cc-mode" -*-
|
|
//*************************************************************************
|
|
// DESCRIPTION: Verilator: Ast node inline functions
|
|
//
|
|
// 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
|
|
//
|
|
//*************************************************************************
|
|
|
|
#ifndef VERILATOR_V3ASTINLINES_H_
|
|
#define VERILATOR_V3ASTINLINES_H_
|
|
|
|
#ifndef VERILATOR_V3AST_H_
|
|
#error "Use V3Ast.h as the include"
|
|
#include "V3Ast.h" // This helps code analysis tools pick up symbols in V3Ast.h and related
|
|
#endif
|
|
|
|
//######################################################################
|
|
// Inline METHODS
|
|
|
|
int AstNode::width() const VL_MT_STABLE { return dtypep() ? dtypep()->width() : 0; }
|
|
int AstNode::widthMin() const VL_MT_STABLE { return dtypep() ? dtypep()->widthMin() : 0; }
|
|
bool AstNode::width1() const { // V3Const uses to know it can optimize
|
|
return dtypep() && dtypep()->width() == 1;
|
|
}
|
|
int AstNode::widthInstrs() const {
|
|
return (!dtypep() ? 1 : (dtypep()->isWide() ? dtypep()->widthWords() : 1));
|
|
}
|
|
bool AstNode::isCHandle() const VL_MT_STABLE {
|
|
return dtypep() && dtypep()->basicp() && dtypep()->basicp()->isCHandle();
|
|
}
|
|
bool AstNode::isDouble() const VL_MT_STABLE {
|
|
return dtypep() && dtypep()->basicp() && dtypep()->basicp()->isDouble();
|
|
}
|
|
bool AstNode::isString() const VL_MT_STABLE {
|
|
return dtypep() && dtypep()->basicp() && dtypep()->basicp()->isString();
|
|
}
|
|
bool AstNode::isEvent() const VL_MT_STABLE {
|
|
return dtypep() && dtypep()->basicp() && dtypep()->basicp()->isEvent();
|
|
}
|
|
|
|
bool AstNode::isSigned() const VL_MT_STABLE { return dtypep() && dtypep()->isSigned(); }
|
|
|
|
bool AstNode::isClassHandleValue() const {
|
|
return (VN_IS(this, Const) && VN_AS(this, Const)->num().isNull())
|
|
|| (dtypep() && VN_IS(dtypep()->skipRefp(), ClassRefDType));
|
|
}
|
|
bool AstNode::isNull() const { return VN_IS(this, Const) && VN_AS(this, Const)->num().isNull(); }
|
|
bool AstNode::isZero() const {
|
|
return (VN_IS(this, Const) && VN_AS(this, Const)->num().isEqZero());
|
|
}
|
|
bool AstNode::isNeqZero() const {
|
|
return (VN_IS(this, Const) && VN_AS(this, Const)->num().isNeqZero());
|
|
}
|
|
bool AstNode::isOne() const { return (VN_IS(this, Const) && VN_AS(this, Const)->num().isEqOne()); }
|
|
bool AstNode::isAllOnes() const {
|
|
return (VN_IS(this, Const) && VN_AS(this, Const)->isEqAllOnes());
|
|
}
|
|
bool AstNode::isAllOnesV() const {
|
|
return (VN_IS(this, Const) && VN_AS(this, Const)->isEqAllOnesV());
|
|
}
|
|
bool AstNode::sameTree(const AstNode* node2p) const {
|
|
return sameTreeIter(this, node2p, true, false);
|
|
}
|
|
bool AstNode::sameGateTree(const AstNode* node2p) const {
|
|
return sameTreeIter(this, node2p, true, true);
|
|
}
|
|
|
|
int AstNodeArrayDType::left() const VL_MT_STABLE { return rangep()->leftConst(); }
|
|
int AstNodeArrayDType::right() const VL_MT_STABLE { return rangep()->rightConst(); }
|
|
int AstNodeArrayDType::hi() const VL_MT_STABLE { return rangep()->hiConst(); }
|
|
int AstNodeArrayDType::lo() const VL_MT_STABLE { return rangep()->loConst(); }
|
|
int AstNodeArrayDType::elementsConst() const VL_MT_STABLE { return rangep()->elementsConst(); }
|
|
VNumRange AstNodeArrayDType::declRange() const VL_MT_STABLE { return VNumRange{left(), right()}; }
|
|
|
|
AstFuncRef::AstFuncRef(FileLine* fl, AstFunc* taskp, AstArg* argsp)
|
|
: ASTGEN_SUPER_FuncRef(fl, taskp->name(), argsp) {
|
|
this->taskp(taskp);
|
|
dtypeFrom(taskp);
|
|
}
|
|
|
|
AstRange::AstRange(FileLine* fl, int left, int right)
|
|
: ASTGEN_SUPER_Range(fl) {
|
|
leftp(new AstConst{fl, static_cast<uint32_t>(left)});
|
|
rightp(new AstConst{fl, static_cast<uint32_t>(right)});
|
|
}
|
|
AstRange::AstRange(FileLine* fl, const VNumRange& range)
|
|
: ASTGEN_SUPER_Range(fl) {
|
|
leftp(new AstConst{fl, static_cast<uint32_t>(range.left())});
|
|
rightp(new AstConst{fl, static_cast<uint32_t>(range.right())});
|
|
}
|
|
int AstRange::leftConst() const VL_MT_STABLE {
|
|
const AstConst* const constp = VN_CAST(leftp(), Const);
|
|
return (constp ? constp->toSInt() : 0);
|
|
}
|
|
int AstRange::rightConst() const VL_MT_STABLE {
|
|
const AstConst* const constp = VN_CAST(rightp(), Const);
|
|
return (constp ? constp->toSInt() : 0);
|
|
}
|
|
|
|
AstPackArrayDType::AstPackArrayDType(FileLine* fl, VFlagChildDType, AstNodeDType* dtp,
|
|
AstRange* rangep)
|
|
: ASTGEN_SUPER_PackArrayDType(fl) {
|
|
childDTypep(dtp); // Only for parser
|
|
refDTypep(nullptr);
|
|
this->rangep(rangep);
|
|
dtypep(nullptr); // V3Width will resolve
|
|
const int width = subDTypep()->width() * rangep->elementsConst();
|
|
widthForce(width, width);
|
|
}
|
|
AstPackArrayDType::AstPackArrayDType(FileLine* fl, AstNodeDType* dtp, AstRange* rangep)
|
|
: ASTGEN_SUPER_PackArrayDType(fl) {
|
|
refDTypep(dtp);
|
|
this->rangep(rangep);
|
|
dtypep(this);
|
|
const int width = subDTypep()->width() * rangep->elementsConst();
|
|
widthForce(width, width);
|
|
}
|
|
|
|
int AstQueueDType::boundConst() const VL_MT_STABLE {
|
|
const AstConst* const constp = VN_CAST(boundp(), Const);
|
|
return (constp ? constp->toSInt() : 0);
|
|
}
|
|
|
|
AstTaskRef::AstTaskRef(FileLine* fl, AstTask* taskp, AstArg* argsp)
|
|
: ASTGEN_SUPER_TaskRef(fl, taskp->name(), argsp) {
|
|
this->taskp(taskp);
|
|
dtypeSetVoid();
|
|
}
|
|
|
|
int AstBasicDType::hi() const { return (rangep() ? rangep()->hiConst() : m.m_nrange.hi()); }
|
|
int AstBasicDType::lo() const { return (rangep() ? rangep()->loConst() : m.m_nrange.lo()); }
|
|
int AstBasicDType::elements() const {
|
|
return (rangep() ? rangep()->elementsConst() : m.m_nrange.elements());
|
|
}
|
|
bool AstBasicDType::ascending() const {
|
|
return (rangep() ? rangep()->ascending() : m.m_nrange.ascending());
|
|
}
|
|
|
|
bool AstActive::hasClocked() const { return m_sentreep->hasClocked(); }
|
|
bool AstActive::hasCombo() const { return m_sentreep->hasCombo(); }
|
|
bool AstActive::hasInitial() const { return m_sentreep->hasInitial(); }
|
|
bool AstActive::hasStatic() const { return m_sentreep->hasStatic(); }
|
|
|
|
bool AstNodeModule::isDollarUnit() const { return this == v3Global.rootp()->dollarUnitPkgp(); }
|
|
bool AstNodeModule::isConstPool() const { return this == v3Global.rootp()->constPoolPkgp(); }
|
|
|
|
AstAlways::AstAlways(AstAssignW* assignp)
|
|
: ASTGEN_SUPER_Always(assignp->fileline(), assignp)
|
|
, m_keyword{VAlwaysKwd::CONT_ASSIGN} {}
|
|
|
|
AstElabDisplay::AstElabDisplay(FileLine* fl, VDisplayType dispType, AstNodeExpr* exprsp)
|
|
: ASTGEN_SUPER_ElabDisplay(fl) {
|
|
addFmtp(new AstSFormatF{fl, "", true, exprsp});
|
|
m_displayType = dispType;
|
|
}
|
|
|
|
bool AstVar::sameNode(const AstNode* samep) const {
|
|
const AstVar* const asamep = VN_DBG_AS(samep, Var);
|
|
return m_name == asamep->m_name && varType() == asamep->varType()
|
|
&& covergroupRefMember() == asamep->covergroupRefMember();
|
|
}
|
|
|
|
AstMatchMasked::AstMatchMasked(FileLine* fl, AstNodeExpr* lhsp, AstVarRef* matchp)
|
|
: ASTGEN_SUPER_MatchMasked(fl) {
|
|
this->lhsp(lhsp);
|
|
this->matchp(matchp);
|
|
dtypeSetUInt32();
|
|
}
|
|
|
|
AstVarRef::AstVarRef(FileLine* fl, AstVar* varp, const VAccess& access)
|
|
: ASTGEN_SUPER_VarRef(fl, varp, access) {
|
|
if (v3Global.assertDTypesResolved()) {
|
|
UASSERT_OBJ(varp, this, "Require non-null varp post resolution");
|
|
} else if (varp) {
|
|
m_name = varp->name();
|
|
}
|
|
}
|
|
AstVarRef::AstVarRef(FileLine* fl, AstNodeModule* pkgp, AstVar* varp, const VAccess& access)
|
|
: AstVarRef{fl, varp, access} {
|
|
classOrPackagep(pkgp);
|
|
}
|
|
// This form only allowed post-link (see above)
|
|
AstVarRef::AstVarRef(FileLine* fl, AstVarScope* varscp, const VAccess& access)
|
|
: ASTGEN_SUPER_VarRef(fl, varscp->varp(), access) {
|
|
varScopep(varscp);
|
|
}
|
|
|
|
string AstVarRef::name() const { return varp() ? varp()->name() : nameThis(); }
|
|
|
|
bool AstVarRef::sameNode(const AstVarRef* samep) const {
|
|
if (varScopep()) return (varScopep() == samep->varScopep() && access() == samep->access());
|
|
return (selfPointer() == samep->selfPointer() && classOrPackagep() == samep->classOrPackagep()
|
|
&& access() == samep->access()
|
|
&& (varp() && samep->varp() && varp()->sameNode(samep->varp())));
|
|
}
|
|
bool AstVarRef::sameNoLvalue(const AstVarRef* samep) const {
|
|
if (varScopep()) return (varScopep() == samep->varScopep());
|
|
|
|
return (selfPointer() == samep->selfPointer() && classOrPackagep() == samep->classOrPackagep()
|
|
&& (!selfPointer().isEmpty() || !samep->selfPointer().isEmpty())
|
|
&& varp()->sameNode(samep->varp()));
|
|
}
|
|
|
|
AstVarXRef::AstVarXRef(FileLine* fl, AstVar* varp, const string& dotted, const VAccess& access)
|
|
: ASTGEN_SUPER_VarXRef(fl, varp, access)
|
|
, m_name{varp->name()}
|
|
, m_dotted{dotted} {
|
|
dtypeFrom(varp);
|
|
}
|
|
|
|
AstStmtExpr* AstNodeExpr::makeStmt() { return new AstStmtExpr{fileline(), this}; }
|
|
|
|
// Walk up the AST via backp() to find the containing AstNodeModule.
|
|
// Returns nullptr if not found.
|
|
inline AstNodeModule* findParentModule(AstNode* nodep) {
|
|
for (AstNode* curp = nodep; curp; curp = curp->backp()) {
|
|
if (AstNodeModule* const modp = VN_CAST(curp, NodeModule)) return modp;
|
|
}
|
|
return nullptr;
|
|
}
|
|
|
|
#endif // Guard
|