2021-06-05 18:40:56 +02:00
|
|
|
// -*- mode: C++; c-file-style: "cc-mode" -*-
|
|
|
|
|
//*************************************************************************
|
|
|
|
|
// DESCRIPTION: Verilator: Ast node inline functions
|
|
|
|
|
//
|
|
|
|
|
// Code available from: https://verilator.org
|
|
|
|
|
//
|
|
|
|
|
//*************************************************************************
|
|
|
|
|
//
|
2025-01-01 14:30:25 +01:00
|
|
|
// Copyright 2003-2025 by Wilson Snyder. This program is free software; you
|
2021-06-05 18:40:56 +02:00
|
|
|
// 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_V3ASTINLINES_H_
|
|
|
|
|
#define VERILATOR_V3ASTINLINES_H_
|
|
|
|
|
|
2022-09-15 14:10:39 +02:00
|
|
|
#ifndef VERILATOR_V3AST_H_
|
2021-06-05 18:40:56 +02:00
|
|
|
#error "Use V3Ast.h as the include"
|
2022-12-26 10:30:41 +01:00
|
|
|
#include "V3Ast.h" // This helps code analysis tools pick up symbols in V3Ast.h and related
|
2021-06-05 18:40:56 +02:00
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
//######################################################################
|
2022-08-29 15:26:00 +02:00
|
|
|
// Inline METHODS
|
|
|
|
|
|
2023-03-17 00:48:56 +01:00
|
|
|
int AstNode::width() const VL_MT_STABLE { return dtypep() ? dtypep()->width() : 0; }
|
2024-03-02 14:57:26 +01:00
|
|
|
int AstNode::widthMin() const VL_MT_STABLE { return dtypep() ? dtypep()->widthMin() : 0; }
|
2022-09-16 14:17:38 +02:00
|
|
|
bool AstNode::width1() const { // V3Const uses to know it can optimize
|
2021-06-05 18:40:56 +02:00
|
|
|
return dtypep() && dtypep()->width() == 1;
|
|
|
|
|
}
|
2022-09-16 14:17:38 +02:00
|
|
|
int AstNode::widthInstrs() const {
|
2021-06-05 18:40:56 +02:00
|
|
|
return (!dtypep() ? 1 : (dtypep()->isWide() ? dtypep()->widthWords() : 1));
|
|
|
|
|
}
|
2023-03-17 00:48:56 +01:00
|
|
|
bool AstNode::isDouble() const VL_MT_STABLE {
|
2025-05-04 22:34:37 +02:00
|
|
|
return dtypep() && dtypep()->basicp() && dtypep()->basicp()->isDouble();
|
2021-06-05 18:40:56 +02:00
|
|
|
}
|
2023-03-17 00:48:56 +01:00
|
|
|
bool AstNode::isString() const VL_MT_STABLE {
|
2021-06-05 18:40:56 +02:00
|
|
|
return dtypep() && dtypep()->basicp() && dtypep()->basicp()->isString();
|
|
|
|
|
}
|
2023-10-26 16:38:47 +02:00
|
|
|
bool AstNode::isEvent() const VL_MT_STABLE {
|
|
|
|
|
return dtypep() && dtypep()->basicp() && dtypep()->basicp()->isEvent();
|
|
|
|
|
}
|
|
|
|
|
|
2023-03-17 00:48:56 +01:00
|
|
|
bool AstNode::isSigned() const VL_MT_STABLE { return dtypep() && dtypep()->isSigned(); }
|
2021-06-05 18:40:56 +02:00
|
|
|
|
2023-05-30 14:59:00 +02:00
|
|
|
bool AstNode::isClassHandleValue() const {
|
|
|
|
|
return (VN_IS(this, Const) && VN_AS(this, Const)->num().isNull())
|
2024-03-16 14:12:10 +01:00
|
|
|
|| (dtypep() && VN_IS(dtypep()->skipRefp(), ClassRefDType));
|
2023-05-30 14:59:00 +02:00
|
|
|
}
|
2024-03-16 13:49:36 +01:00
|
|
|
bool AstNode::isNull() const { return VN_IS(this, Const) && VN_AS(this, Const)->num().isNull(); }
|
2022-09-16 14:17:38 +02:00
|
|
|
bool AstNode::isZero() const {
|
2021-10-22 16:15:42 +02:00
|
|
|
return (VN_IS(this, Const) && VN_AS(this, Const)->num().isEqZero());
|
2021-06-05 18:40:56 +02:00
|
|
|
}
|
2022-09-16 14:17:38 +02:00
|
|
|
bool AstNode::isNeqZero() const {
|
2021-10-22 16:15:42 +02:00
|
|
|
return (VN_IS(this, Const) && VN_AS(this, Const)->num().isNeqZero());
|
2021-06-05 18:40:56 +02:00
|
|
|
}
|
2022-09-16 14:17:38 +02:00
|
|
|
bool AstNode::isOne() const { return (VN_IS(this, Const) && VN_AS(this, Const)->num().isEqOne()); }
|
|
|
|
|
bool AstNode::isAllOnes() const {
|
2021-10-22 16:15:42 +02:00
|
|
|
return (VN_IS(this, Const) && VN_AS(this, Const)->isEqAllOnes());
|
2021-06-05 18:40:56 +02:00
|
|
|
}
|
2022-09-16 14:17:38 +02:00
|
|
|
bool AstNode::isAllOnesV() const {
|
2021-10-22 16:15:42 +02:00
|
|
|
return (VN_IS(this, Const) && VN_AS(this, Const)->isEqAllOnesV());
|
2021-06-05 18:40:56 +02:00
|
|
|
}
|
2022-09-16 14:17:38 +02:00
|
|
|
bool AstNode::sameTree(const AstNode* node2p) const {
|
2021-06-05 18:40:56 +02:00
|
|
|
return sameTreeIter(this, node2p, true, false);
|
|
|
|
|
}
|
2022-09-16 14:17:38 +02:00
|
|
|
bool AstNode::sameGateTree(const AstNode* node2p) const {
|
2021-06-05 18:40:56 +02:00
|
|
|
return sameTreeIter(this, node2p, true, true);
|
|
|
|
|
}
|
|
|
|
|
|
2023-03-17 00:48:56 +01:00
|
|
|
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()}; }
|
2021-06-05 18:40:56 +02:00
|
|
|
|
2024-12-15 15:15:49 +01:00
|
|
|
AstFuncRef::AstFuncRef(FileLine* fl, AstFunc* taskp, AstNodeExpr* pinsp)
|
|
|
|
|
: ASTGEN_SUPER_FuncRef(fl, taskp->name(), pinsp) {
|
|
|
|
|
this->taskp(taskp);
|
|
|
|
|
dtypeFrom(taskp);
|
|
|
|
|
}
|
|
|
|
|
|
2022-09-15 14:10:39 +02:00
|
|
|
AstRange::AstRange(FileLine* fl, int left, int right)
|
|
|
|
|
: ASTGEN_SUPER_Range(fl) {
|
2022-09-15 20:43:56 +02:00
|
|
|
leftp(new AstConst{fl, static_cast<uint32_t>(left)});
|
|
|
|
|
rightp(new AstConst{fl, static_cast<uint32_t>(right)});
|
2022-09-15 14:10:39 +02:00
|
|
|
}
|
|
|
|
|
AstRange::AstRange(FileLine* fl, const VNumRange& range)
|
|
|
|
|
: ASTGEN_SUPER_Range(fl) {
|
2022-09-15 20:43:56 +02:00
|
|
|
leftp(new AstConst{fl, static_cast<uint32_t>(range.left())});
|
|
|
|
|
rightp(new AstConst{fl, static_cast<uint32_t>(range.right())});
|
2022-09-15 14:10:39 +02:00
|
|
|
}
|
2023-03-17 00:48:56 +01:00
|
|
|
int AstRange::leftConst() const VL_MT_STABLE {
|
2025-08-19 23:02:10 +02:00
|
|
|
const AstConst* const constp = VN_CAST(leftp(), Const);
|
2022-09-15 14:10:39 +02:00
|
|
|
return (constp ? constp->toSInt() : 0);
|
|
|
|
|
}
|
2023-03-17 00:48:56 +01:00
|
|
|
int AstRange::rightConst() const VL_MT_STABLE {
|
2025-08-19 23:02:10 +02:00
|
|
|
const AstConst* const constp = VN_CAST(rightp(), Const);
|
2022-09-15 14:10:39 +02:00
|
|
|
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);
|
2022-09-15 20:43:56 +02:00
|
|
|
this->rangep(rangep);
|
2022-09-15 14:10:39 +02:00
|
|
|
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);
|
2022-09-15 20:43:56 +02:00
|
|
|
this->rangep(rangep);
|
2022-09-15 14:10:39 +02:00
|
|
|
dtypep(this);
|
|
|
|
|
const int width = subDTypep()->width() * rangep->elementsConst();
|
|
|
|
|
widthForce(width, width);
|
|
|
|
|
}
|
|
|
|
|
|
2024-12-15 15:15:49 +01:00
|
|
|
int AstQueueDType::boundConst() const VL_MT_STABLE {
|
2025-08-19 23:02:10 +02:00
|
|
|
const AstConst* const constp = VN_CAST(boundp(), Const);
|
2024-12-15 15:15:49 +01:00
|
|
|
return (constp ? constp->toSInt() : 0);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
AstTaskRef::AstTaskRef(FileLine* fl, AstTask* taskp, AstNodeExpr* pinsp)
|
|
|
|
|
: ASTGEN_SUPER_TaskRef(fl, taskp->name(), pinsp) {
|
|
|
|
|
this->taskp(taskp);
|
|
|
|
|
dtypeSetVoid();
|
|
|
|
|
}
|
|
|
|
|
|
2022-09-15 14:10:39 +02:00
|
|
|
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());
|
|
|
|
|
}
|
2023-03-21 01:44:11 +01:00
|
|
|
bool AstBasicDType::ascending() const {
|
|
|
|
|
return (rangep() ? rangep()->ascending() : m.m_nrange.ascending());
|
2022-09-15 14:10:39 +02:00
|
|
|
}
|
|
|
|
|
|
2025-08-18 01:14:34 +02:00
|
|
|
bool AstActive::hasClocked() const { return m_sentreep->hasClocked(); }
|
|
|
|
|
bool AstActive::hasCombo() const { return m_sentreep->hasCombo(); }
|
2022-09-15 14:10:39 +02:00
|
|
|
|
Internals: Make AstAssignW a procedural statement (#6280) (#6556)
Initial idea was to remodel AssignW as Assign under Alway. Trying that
uncovered some issues, the most difficult of them was that a delay
attached to a continuous assignment behaves differently from a delay
attached to a blocking assignment statement, so we need to keep the
knowledge of which flavour an assignment was until V3Timing.
So instead of removing AstAssignW, we always wrap it in an AstAlways,
with a special `keyword()` type. This makes it into a proper procedural
statement, which is almost equivalent to AstAssign, except for the case
when they contain a delay. We still gain the benefits of #6280 and can
simplify some code. Every AstNodeStmt should now be under an
AstNodeProcedure - which we should rename to AstProcess, or an
AstNodeFTask). As a result, V3Table can now handle AssignW for free.
Also uncovered and fixed a bug in handling intra-assignment delays if
a function is present on the RHS of an AssignW.
There is more work to be done towards #6280, and potentially simplifying
AssignW handing, but this is the minimal change required to tick it off
the TODO list for #6280.
2025-10-14 10:05:19 +02:00
|
|
|
AstAlways::AstAlways(AstAssignW* assignp)
|
|
|
|
|
: ASTGEN_SUPER_Always(assignp->fileline(), assignp)
|
|
|
|
|
, m_keyword{VAlwaysKwd::CONT_ASSIGN} {}
|
|
|
|
|
|
2022-11-13 21:33:11 +01:00
|
|
|
AstElabDisplay::AstElabDisplay(FileLine* fl, VDisplayType dispType, AstNodeExpr* exprsp)
|
2022-09-15 14:10:39 +02:00
|
|
|
: ASTGEN_SUPER_ElabDisplay(fl) {
|
2022-11-20 21:06:49 +01:00
|
|
|
addFmtp(new AstSFormatF{fl, AstSFormatF::NoFormat{}, exprsp});
|
2022-09-15 14:10:39 +02:00
|
|
|
m_displayType = dispType;
|
|
|
|
|
}
|
|
|
|
|
|
2025-10-01 16:01:30 +02:00
|
|
|
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();
|
|
|
|
|
}
|
|
|
|
|
|
2022-09-15 14:10:39 +02:00
|
|
|
AstVarRef::AstVarRef(FileLine* fl, AstVar* varp, const VAccess& access)
|
2025-12-09 02:11:28 +01:00
|
|
|
: 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();
|
|
|
|
|
}
|
|
|
|
|
}
|
2024-07-17 08:21:45 +02:00
|
|
|
AstVarRef::AstVarRef(FileLine* fl, AstNodeModule* pkgp, AstVar* varp, const VAccess& access)
|
|
|
|
|
: AstVarRef{fl, varp, access} {
|
|
|
|
|
classOrPackagep(pkgp);
|
|
|
|
|
}
|
2022-09-15 14:10:39 +02:00
|
|
|
// This form only allowed post-link (see above)
|
|
|
|
|
AstVarRef::AstVarRef(FileLine* fl, AstVarScope* varscp, const VAccess& access)
|
2023-08-03 08:52:52 +02:00
|
|
|
: ASTGEN_SUPER_VarRef(fl, varscp->varp(), access) {
|
2022-09-15 14:10:39 +02:00
|
|
|
varScopep(varscp);
|
|
|
|
|
}
|
2023-08-03 08:52:52 +02:00
|
|
|
|
2025-12-09 02:11:28 +01:00
|
|
|
string AstVarRef::name() const { return varp() ? varp()->name() : nameThis(); }
|
2023-08-03 08:52:52 +02:00
|
|
|
|
2024-11-28 20:37:11 +01:00
|
|
|
bool AstVarRef::sameNode(const AstVarRef* samep) const {
|
2022-09-15 14:10:39 +02:00
|
|
|
if (varScopep()) {
|
|
|
|
|
return (varScopep() == samep->varScopep() && access() == samep->access());
|
|
|
|
|
} else {
|
2025-01-18 21:25:49 +01:00
|
|
|
return (selfPointer() == samep->selfPointer()
|
2025-03-12 13:06:34 +01:00
|
|
|
&& classOrPackagep() == samep->classOrPackagep() && access() == samep->access()
|
2025-10-01 16:01:30 +02:00
|
|
|
&& (varp() && samep->varp() && varp()->sameNode(samep->varp())));
|
2022-09-15 14:10:39 +02:00
|
|
|
}
|
|
|
|
|
}
|
2025-08-19 23:02:10 +02:00
|
|
|
bool AstVarRef::sameNoLvalue(const AstVarRef* samep) const {
|
2022-09-15 14:10:39 +02:00
|
|
|
if (varScopep()) {
|
|
|
|
|
return (varScopep() == samep->varScopep());
|
|
|
|
|
} else {
|
|
|
|
|
return (selfPointer() == samep->selfPointer()
|
2025-01-18 21:25:49 +01:00
|
|
|
&& classOrPackagep() == samep->classOrPackagep()
|
2023-09-08 13:34:35 +02:00
|
|
|
&& (!selfPointer().isEmpty() || !samep->selfPointer().isEmpty())
|
2025-10-01 16:01:30 +02:00
|
|
|
&& varp()->sameNode(samep->varp()));
|
2022-09-15 14:10:39 +02:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
AstVarXRef::AstVarXRef(FileLine* fl, AstVar* varp, const string& dotted, const VAccess& access)
|
2023-08-03 08:52:52 +02:00
|
|
|
: ASTGEN_SUPER_VarXRef(fl, varp, access)
|
|
|
|
|
, m_name{varp->name()}
|
2022-09-15 14:10:39 +02:00
|
|
|
, m_dotted{dotted} {
|
|
|
|
|
dtypeFrom(varp);
|
|
|
|
|
}
|
|
|
|
|
|
2022-10-12 11:19:21 +02:00
|
|
|
AstStmtExpr* AstNodeExpr::makeStmt() { return new AstStmtExpr{fileline(), this}; }
|
|
|
|
|
|
2021-06-05 18:40:56 +02:00
|
|
|
#endif // Guard
|