2022-09-15 14:10:39 +02:00
|
|
|
// -*- mode: C++; c-file-style: "cc-mode" -*-
|
|
|
|
|
//*************************************************************************
|
|
|
|
|
// DESCRIPTION: Verilator: AstNode sub-types representing other constructs
|
|
|
|
|
//
|
|
|
|
|
// 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
|
2022-09-15 14:10:39 +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
|
|
|
|
|
//
|
|
|
|
|
//*************************************************************************
|
|
|
|
|
//
|
|
|
|
|
// This files contains all 'AstNode' sub-types that relate to other constructs
|
2022-12-03 00:46:38 +01:00
|
|
|
// not covered by the more specific V3AstNode*.h files.
|
2022-09-15 14:10:39 +02:00
|
|
|
//
|
|
|
|
|
//*************************************************************************
|
|
|
|
|
|
|
|
|
|
#ifndef VERILATOR_V3ASTNODES_H_
|
|
|
|
|
#define VERILATOR_V3ASTNODES_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
|
|
|
|
|
#define VL_NOT_FINAL // This #define fixes broken code folding in the CLion IDE
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
// === Abstract base node types (AstNode*) =====================================
|
|
|
|
|
|
|
|
|
|
class AstNodeBlock VL_NOT_FINAL : public AstNode {
|
|
|
|
|
// A Begin/fork block
|
2023-09-08 16:40:14 +02:00
|
|
|
// @astgen op2 := stmtsp : List[AstNode]
|
2022-09-15 14:10:39 +02:00
|
|
|
// Parents: statement
|
|
|
|
|
string m_name; // Name of block
|
|
|
|
|
bool m_unnamed; // Originally unnamed (name change does not affect this)
|
|
|
|
|
protected:
|
|
|
|
|
AstNodeBlock(VNType t, FileLine* fl, const string& name, AstNode* stmtsp)
|
|
|
|
|
: AstNode{t, fl}
|
|
|
|
|
, m_name{name} {
|
2022-09-15 20:43:56 +02:00
|
|
|
addStmtsp(stmtsp);
|
2022-09-15 14:10:39 +02:00
|
|
|
m_unnamed = (name == "");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public:
|
2022-10-04 12:03:41 +02:00
|
|
|
ASTGEN_MEMBERS_AstNodeBlock;
|
2025-07-09 22:59:26 +02:00
|
|
|
bool maybePointedTo() const override VL_MT_SAFE { return true; }
|
2022-09-16 12:22:11 +02:00
|
|
|
void dump(std::ostream& str) const override;
|
2024-02-09 23:50:09 +01:00
|
|
|
void dumpJson(std::ostream& str) const override;
|
2023-03-18 01:24:15 +01:00
|
|
|
string name() const override VL_MT_STABLE { return m_name; } // * = Block name
|
2022-09-16 12:22:11 +02:00
|
|
|
void name(const string& name) override { m_name = name; }
|
2022-09-15 14:10:39 +02:00
|
|
|
bool unnamed() const { return m_unnamed; }
|
|
|
|
|
bool isFirstInMyListOfStatements(AstNode* nodep) const override { return nodep == stmtsp(); }
|
|
|
|
|
};
|
2025-08-19 12:14:17 +02:00
|
|
|
class AstNodeCoverDecl VL_NOT_FINAL : public AstNode {
|
|
|
|
|
// Coverage analysis point declaration
|
|
|
|
|
//
|
|
|
|
|
// [After V3CoverageJoin] Duplicate declaration to get data from instead
|
|
|
|
|
// @astgen ptr := m_dataDeclp : Optional[AstNodeCoverDecl]
|
|
|
|
|
string m_page; // Coverage point's page tag
|
|
|
|
|
string m_text; // Coverage point's text
|
|
|
|
|
string m_hier; // Coverage point's hierarchy
|
|
|
|
|
int m_binNum = 0; // Set by V3EmitCSyms to tell final V3Emit what to increment
|
|
|
|
|
public:
|
|
|
|
|
AstNodeCoverDecl(VNType t, FileLine* fl, const string& page, const string& comment)
|
|
|
|
|
: AstNode(t, fl)
|
|
|
|
|
, m_page{page}
|
|
|
|
|
, m_text{comment} {}
|
|
|
|
|
ASTGEN_MEMBERS_AstNodeCoverDecl;
|
|
|
|
|
const char* broken() const override {
|
|
|
|
|
if (m_dataDeclp
|
|
|
|
|
&& (m_dataDeclp == this || m_dataDeclp->m_dataDeclp)) { // Avoid O(n^2) accessing
|
|
|
|
|
v3fatalSrc("dataDeclp should point to real data, not be a list: " << cvtToHex(this));
|
|
|
|
|
}
|
|
|
|
|
return nullptr;
|
|
|
|
|
}
|
|
|
|
|
void dump(std::ostream& str) const override;
|
|
|
|
|
void dumpJson(std::ostream& str) const override;
|
|
|
|
|
int instrCount() const override { return 1 + 2 * INSTR_COUNT_LD; }
|
|
|
|
|
bool maybePointedTo() const override VL_MT_SAFE { return true; }
|
|
|
|
|
int binNum() const { return m_binNum; }
|
|
|
|
|
void binNum(int flag) { m_binNum = flag; }
|
|
|
|
|
virtual int size() const = 0;
|
|
|
|
|
const string& comment() const { return m_text; } // text to insert in code
|
|
|
|
|
const string& page() const { return m_page; }
|
|
|
|
|
const string& hier() const { return m_hier; }
|
|
|
|
|
void hier(const string& flag) { m_hier = flag; }
|
|
|
|
|
void comment(const string& flag) { m_text = flag; }
|
|
|
|
|
bool sameNode(const AstNode* samep) const override {
|
|
|
|
|
const AstNodeCoverDecl* const asamep = VN_DBG_AS(samep, NodeCoverDecl);
|
|
|
|
|
return (fileline() == asamep->fileline() && hier() == asamep->hier()
|
|
|
|
|
&& comment() == asamep->comment() && page() == asamep->page());
|
|
|
|
|
}
|
|
|
|
|
bool isPredictOptimizable() const override { return false; }
|
|
|
|
|
void dataDeclp(AstNodeCoverDecl* nodep) { m_dataDeclp = nodep; }
|
|
|
|
|
// dataDecl nullptr means "use this one", but often you want "this" to
|
|
|
|
|
// indicate to get data from here
|
|
|
|
|
AstNodeCoverDecl* dataDeclNullp() const { return m_dataDeclp; }
|
|
|
|
|
AstNodeCoverDecl* dataDeclThisp() { return dataDeclNullp() ? dataDeclNullp() : this; }
|
|
|
|
|
};
|
2022-09-15 14:10:39 +02:00
|
|
|
class AstNodeFTask VL_NOT_FINAL : public AstNode {
|
2022-09-15 20:43:56 +02:00
|
|
|
// Output variable in functions, nullptr in tasks
|
|
|
|
|
// @astgen op1 := fvarp : Optional[AstNode]
|
|
|
|
|
// Class/package scope
|
|
|
|
|
// @astgen op2 := classOrPackagep : Optional[AstNode]
|
|
|
|
|
// Statements/Ports/Vars
|
|
|
|
|
// @astgen op3 := stmtsp : List[AstNode]
|
|
|
|
|
// Scope name
|
|
|
|
|
// @astgen op4 := scopeNamep : Optional[AstScopeName]
|
2022-09-15 14:10:39 +02:00
|
|
|
string m_name; // Name of task
|
|
|
|
|
string m_cname; // Name of task if DPI import
|
|
|
|
|
uint64_t m_dpiOpenParent = 0; // DPI import open array, if !=0, how many callees
|
|
|
|
|
bool m_taskPublic : 1; // Public task
|
|
|
|
|
bool m_attrIsolateAssign : 1; // User isolate_assignments attribute
|
|
|
|
|
bool m_classMethod : 1; // Class method
|
2025-08-12 01:50:47 +02:00
|
|
|
bool m_didProto : 1; // Did prototype processing
|
2022-09-15 14:10:39 +02:00
|
|
|
bool m_prototype : 1; // Just a prototype
|
|
|
|
|
bool m_dpiExport : 1; // DPI exported
|
|
|
|
|
bool m_dpiImport : 1; // DPI imported
|
|
|
|
|
bool m_dpiContext : 1; // DPI import context
|
|
|
|
|
bool m_dpiOpenChild : 1; // DPI import open array child wrapper
|
|
|
|
|
bool m_dpiTask : 1; // DPI import task (vs. void function)
|
|
|
|
|
bool m_isConstructor : 1; // Class constructor
|
2024-12-12 14:16:19 +01:00
|
|
|
bool m_isExternProto : 1; // Extern prototype
|
|
|
|
|
bool m_isExternDef : 1; // Extern definition
|
2022-09-15 14:10:39 +02:00
|
|
|
bool m_isHideLocal : 1; // Verilog local
|
|
|
|
|
bool m_isHideProtected : 1; // Verilog protected
|
2023-09-08 08:51:19 +02:00
|
|
|
bool m_dpiPure : 1; // DPI import pure (vs. virtual pure)
|
2022-09-15 14:10:39 +02:00
|
|
|
bool m_pureVirtual : 1; // Pure virtual
|
2022-12-03 00:46:38 +01:00
|
|
|
bool m_recursive : 1; // Recursive or part of recursion
|
2023-10-31 13:15:54 +01:00
|
|
|
bool m_static : 1; // Static method in class
|
2022-09-15 14:10:39 +02:00
|
|
|
bool m_underGenerate : 1; // Under generate (for warning)
|
|
|
|
|
bool m_virtual : 1; // Virtual method in class
|
2023-10-16 14:02:29 +02:00
|
|
|
bool m_needProcess : 1; // Needs access to VlProcess of the caller
|
2024-03-28 04:57:58 +01:00
|
|
|
VBaseOverride m_baseOverride; // BaseOverride (inital/final/extends)
|
2023-10-31 13:15:54 +01:00
|
|
|
VLifetime m_lifetime; // Default lifetime of local vars
|
2023-09-29 12:23:51 +02:00
|
|
|
VIsCached m_purity; // Pure state
|
2023-09-18 15:21:30 +02:00
|
|
|
|
2022-09-15 14:10:39 +02:00
|
|
|
protected:
|
|
|
|
|
AstNodeFTask(VNType t, FileLine* fl, const string& name, AstNode* stmtsp)
|
|
|
|
|
: AstNode{t, fl}
|
|
|
|
|
, m_name{name}
|
|
|
|
|
, m_taskPublic{false}
|
|
|
|
|
, m_attrIsolateAssign{false}
|
|
|
|
|
, m_classMethod{false}
|
2025-08-12 01:50:47 +02:00
|
|
|
, m_didProto{false}
|
2022-09-15 14:10:39 +02:00
|
|
|
, m_prototype{false}
|
|
|
|
|
, m_dpiExport{false}
|
|
|
|
|
, m_dpiImport{false}
|
|
|
|
|
, m_dpiContext{false}
|
|
|
|
|
, m_dpiOpenChild{false}
|
|
|
|
|
, m_dpiTask{false}
|
|
|
|
|
, m_isConstructor{false}
|
2024-12-12 14:16:19 +01:00
|
|
|
, m_isExternProto{false}
|
|
|
|
|
, m_isExternDef{false}
|
2022-09-15 14:10:39 +02:00
|
|
|
, m_isHideLocal{false}
|
|
|
|
|
, m_isHideProtected{false}
|
2023-09-08 08:51:19 +02:00
|
|
|
, m_dpiPure{false}
|
2022-09-15 14:10:39 +02:00
|
|
|
, m_pureVirtual{false}
|
|
|
|
|
, m_recursive{false}
|
2023-10-31 13:15:54 +01:00
|
|
|
, m_static{false}
|
2022-09-15 14:10:39 +02:00
|
|
|
, m_underGenerate{false}
|
2023-06-01 16:02:08 +02:00
|
|
|
, m_virtual{false}
|
2023-08-05 09:07:23 +02:00
|
|
|
, m_needProcess{false} {
|
2022-09-15 20:43:56 +02:00
|
|
|
addStmtsp(stmtsp);
|
2022-09-15 14:10:39 +02:00
|
|
|
cname(name); // Might be overridden by dpi import/export
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public:
|
2022-10-04 12:03:41 +02:00
|
|
|
ASTGEN_MEMBERS_AstNodeFTask;
|
2023-09-16 23:37:25 +02:00
|
|
|
virtual AstNodeFTask* cloneType(const string& name) = 0;
|
2022-09-16 12:22:11 +02:00
|
|
|
void dump(std::ostream& str = std::cout) const override;
|
2024-02-09 23:50:09 +01:00
|
|
|
void dumpJson(std::ostream& str = std::cout) const override;
|
2023-03-18 01:24:15 +01:00
|
|
|
string name() const override VL_MT_STABLE { return m_name; } // * = Var name
|
2024-10-01 03:34:34 +02:00
|
|
|
bool maybePointedTo() const override VL_MT_SAFE { return true; }
|
2023-09-08 08:51:19 +02:00
|
|
|
bool isGateOptimizable() const override {
|
|
|
|
|
return !((m_dpiExport || m_dpiImport) && !m_dpiPure);
|
|
|
|
|
}
|
2022-09-15 14:10:39 +02:00
|
|
|
// {AstFunc only} op1 = Range output variable
|
2022-09-16 12:22:11 +02:00
|
|
|
void name(const string& name) override { m_name = name; }
|
2022-09-15 14:10:39 +02:00
|
|
|
string cname() const { return m_cname; }
|
|
|
|
|
void cname(const string& cname) { m_cname = cname; }
|
|
|
|
|
bool isFunction() const { return fvarp() != nullptr; }
|
|
|
|
|
// MORE ACCESSORS
|
|
|
|
|
void dpiOpenParentInc() { ++m_dpiOpenParent; }
|
|
|
|
|
void dpiOpenParentClear() { m_dpiOpenParent = 0; }
|
|
|
|
|
uint64_t dpiOpenParent() const { return m_dpiOpenParent; }
|
|
|
|
|
bool taskPublic() const { return m_taskPublic; }
|
2024-06-23 01:50:46 +02:00
|
|
|
void taskPublic(bool flag) { m_taskPublic = flag; }
|
2022-09-15 14:10:39 +02:00
|
|
|
bool attrIsolateAssign() const { return m_attrIsolateAssign; }
|
2024-06-23 01:50:46 +02:00
|
|
|
void attrIsolateAssign(bool flag) { m_attrIsolateAssign = flag; }
|
2022-09-15 14:10:39 +02:00
|
|
|
bool classMethod() const { return m_classMethod; }
|
2024-06-23 01:50:46 +02:00
|
|
|
void classMethod(bool flag) { m_classMethod = flag; }
|
2025-08-12 01:50:47 +02:00
|
|
|
bool didProto() const { return m_didProto; }
|
|
|
|
|
void didProto(bool flag) { m_didProto = flag; }
|
2024-12-12 14:16:19 +01:00
|
|
|
bool isExternProto() const { return m_isExternProto; }
|
|
|
|
|
void isExternProto(bool flag) { m_isExternProto = flag; }
|
|
|
|
|
bool isExternDef() const { return m_isExternDef; }
|
|
|
|
|
void isExternDef(bool flag) { m_isExternDef = flag; }
|
2022-09-15 14:10:39 +02:00
|
|
|
bool prototype() const { return m_prototype; }
|
2024-06-23 01:50:46 +02:00
|
|
|
void prototype(bool flag) { m_prototype = flag; }
|
2022-09-15 14:10:39 +02:00
|
|
|
bool dpiExport() const { return m_dpiExport; }
|
2024-06-23 01:50:46 +02:00
|
|
|
void dpiExport(bool flag) { m_dpiExport = flag; }
|
2022-09-15 14:10:39 +02:00
|
|
|
bool dpiImport() const { return m_dpiImport; }
|
2024-06-23 01:50:46 +02:00
|
|
|
void dpiImport(bool flag) { m_dpiImport = flag; }
|
2022-09-15 14:10:39 +02:00
|
|
|
bool dpiContext() const { return m_dpiContext; }
|
2024-06-23 01:50:46 +02:00
|
|
|
void dpiContext(bool flag) { m_dpiContext = flag; }
|
2022-09-15 14:10:39 +02:00
|
|
|
bool dpiOpenChild() const { return m_dpiOpenChild; }
|
2024-06-23 01:50:46 +02:00
|
|
|
void dpiOpenChild(bool flag) { m_dpiOpenChild = flag; }
|
2022-09-15 14:10:39 +02:00
|
|
|
bool dpiTask() const { return m_dpiTask; }
|
2024-06-23 01:50:46 +02:00
|
|
|
void dpiTask(bool flag) { m_dpiTask = flag; }
|
2022-09-15 14:10:39 +02:00
|
|
|
bool isConstructor() const { return m_isConstructor; }
|
2024-06-23 01:50:46 +02:00
|
|
|
void isConstructor(bool flag) { m_isConstructor = flag; }
|
2022-09-15 14:10:39 +02:00
|
|
|
bool isHideLocal() const { return m_isHideLocal; }
|
|
|
|
|
void isHideLocal(bool flag) { m_isHideLocal = flag; }
|
|
|
|
|
bool isHideProtected() const { return m_isHideProtected; }
|
|
|
|
|
void isHideProtected(bool flag) { m_isHideProtected = flag; }
|
2023-09-08 08:51:19 +02:00
|
|
|
bool dpiPure() const { return m_dpiPure; }
|
2024-06-23 01:50:46 +02:00
|
|
|
void dpiPure(bool flag) { m_dpiPure = flag; }
|
2022-09-15 14:10:39 +02:00
|
|
|
bool pureVirtual() const { return m_pureVirtual; }
|
2024-06-23 01:50:46 +02:00
|
|
|
void pureVirtual(bool flag) { m_pureVirtual = flag; }
|
2022-09-15 14:10:39 +02:00
|
|
|
bool recursive() const { return m_recursive; }
|
2024-06-23 01:50:46 +02:00
|
|
|
void recursive(bool flag) { m_recursive = flag; }
|
2023-10-31 13:15:54 +01:00
|
|
|
bool isStatic() const { return m_static; }
|
2024-06-23 01:50:46 +02:00
|
|
|
void isStatic(bool flag) { m_static = flag; }
|
2022-09-15 14:10:39 +02:00
|
|
|
bool underGenerate() const { return m_underGenerate; }
|
2024-06-23 01:50:46 +02:00
|
|
|
void underGenerate(bool flag) { m_underGenerate = flag; }
|
2022-09-15 14:10:39 +02:00
|
|
|
bool isVirtual() const { return m_virtual; }
|
2024-06-23 01:50:46 +02:00
|
|
|
void isVirtual(bool flag) { m_virtual = flag; }
|
2023-08-05 09:07:23 +02:00
|
|
|
bool needProcess() const { return m_needProcess; }
|
2024-06-23 01:50:46 +02:00
|
|
|
void setNeedProcess() { m_needProcess = true; }
|
2024-03-28 04:57:58 +01:00
|
|
|
void baseOverride(const VBaseOverride& flag) { m_baseOverride = flag; }
|
|
|
|
|
VBaseOverride baseOverride() const { return m_baseOverride; }
|
2022-09-15 14:10:39 +02:00
|
|
|
void lifetime(const VLifetime& flag) { m_lifetime = flag; }
|
|
|
|
|
VLifetime lifetime() const { return m_lifetime; }
|
|
|
|
|
bool isFirstInMyListOfStatements(AstNode* n) const override { return n == stmtsp(); }
|
2023-09-18 15:21:30 +02:00
|
|
|
bool isPure() override;
|
|
|
|
|
const char* broken() const override;
|
2023-09-16 23:37:25 +02:00
|
|
|
void propagateAttrFrom(const AstNodeFTask* fromp) {
|
|
|
|
|
// Creating a wrapper with e.g. cloneType(); preserve some attributes
|
|
|
|
|
classMethod(fromp->classMethod());
|
|
|
|
|
isHideLocal(fromp->isHideLocal());
|
|
|
|
|
isHideProtected(fromp->isHideProtected());
|
|
|
|
|
isVirtual(fromp->isVirtual());
|
2024-10-14 13:41:17 +02:00
|
|
|
isStatic(fromp->isStatic());
|
2023-09-16 23:37:25 +02:00
|
|
|
lifetime(fromp->lifetime());
|
|
|
|
|
underGenerate(fromp->underGenerate());
|
|
|
|
|
}
|
2023-09-18 15:21:30 +02:00
|
|
|
|
|
|
|
|
private:
|
2023-09-29 12:23:51 +02:00
|
|
|
bool getPurityRecurse() const;
|
2022-09-15 14:10:39 +02:00
|
|
|
};
|
|
|
|
|
class AstNodeFile VL_NOT_FINAL : public AstNode {
|
2022-12-03 00:46:38 +01:00
|
|
|
// Emitted Output file
|
2022-09-15 14:10:39 +02:00
|
|
|
// Parents: NETLIST
|
2022-09-15 20:43:56 +02:00
|
|
|
// @astgen op1 := tblockp : Optional[AstTextBlock]
|
2022-09-15 14:10:39 +02:00
|
|
|
string m_name; ///< Filename
|
|
|
|
|
public:
|
|
|
|
|
AstNodeFile(VNType t, FileLine* fl, const string& name)
|
2022-09-16 01:58:01 +02:00
|
|
|
: AstNode{t, fl}
|
2022-09-15 14:54:04 +02:00
|
|
|
, m_name{name} {}
|
2022-10-04 12:03:41 +02:00
|
|
|
ASTGEN_MEMBERS_AstNodeFile;
|
2022-09-16 12:22:11 +02:00
|
|
|
void dump(std::ostream& str) const override;
|
2024-02-09 23:50:09 +01:00
|
|
|
void dumpJson(std::ostream& str) const override;
|
2023-03-18 01:24:15 +01:00
|
|
|
string name() const override VL_MT_STABLE { return m_name; }
|
2024-11-28 20:37:11 +01:00
|
|
|
bool sameNode(const AstNode* /*samep*/) const override { return true; }
|
2022-09-15 14:10:39 +02:00
|
|
|
};
|
|
|
|
|
class AstNodeModule VL_NOT_FINAL : public AstNode {
|
|
|
|
|
// A module, package, program or interface declaration;
|
|
|
|
|
// something that can live directly under the TOP,
|
|
|
|
|
// excluding $unit package stuff
|
2022-09-15 20:43:56 +02:00
|
|
|
// @astgen op1 := inlinesp : List[AstNode]
|
|
|
|
|
// @astgen op2 := stmtsp : List[AstNode]
|
2022-09-15 14:10:39 +02:00
|
|
|
string m_name; // Name of the module
|
|
|
|
|
const string m_origName; // Name of the module, ignoring name() changes, for dot lookup
|
|
|
|
|
string m_someInstanceName; // Hierarchical name of some arbitrary instance of this module.
|
|
|
|
|
// Used for user messages only.
|
2025-06-30 02:17:27 +02:00
|
|
|
string m_libname; // Work library
|
2022-11-13 15:26:46 +01:00
|
|
|
int m_level = 0; // 1=top module, 2=cell off top module, ...
|
|
|
|
|
VLifetime m_lifetime; // Lifetime
|
|
|
|
|
VTimescale m_timeunit; // Global time unit
|
|
|
|
|
VOptionBool m_unconnectedDrive; // State of `unconnected_drive
|
|
|
|
|
|
2022-09-15 14:10:39 +02:00
|
|
|
bool m_modPublic : 1; // Module has public references
|
|
|
|
|
bool m_modTrace : 1; // Tracing this module
|
|
|
|
|
bool m_inLibrary : 1; // From a library, no error if not used, never top level
|
|
|
|
|
bool m_dead : 1; // LinkDot believes is dead; will remove in Dead visitors
|
2023-03-04 03:06:52 +01:00
|
|
|
bool m_hasGParam : 1; // Has global parameter (for link)
|
2023-09-25 17:39:04 +02:00
|
|
|
bool m_hasParameterList : 1; // Has #() for parameter declaration
|
2022-12-03 00:46:38 +01:00
|
|
|
bool m_hierBlock : 1; // Hierarchical Block marked by HIER_BLOCK pragma
|
2025-08-26 00:47:08 +02:00
|
|
|
bool m_hierParams : 1; // Block containing params for parameterized hier blocks
|
2022-09-15 14:10:39 +02:00
|
|
|
bool m_internal : 1; // Internally created
|
|
|
|
|
bool m_recursive : 1; // Recursive module
|
|
|
|
|
bool m_recursiveClone : 1; // If recursive, what module it clones, otherwise nullptr
|
|
|
|
|
protected:
|
2025-06-30 02:17:27 +02:00
|
|
|
AstNodeModule(VNType t, FileLine* fl, const string& name, const string& libname)
|
2022-09-15 14:10:39 +02:00
|
|
|
: AstNode{t, fl}
|
|
|
|
|
, m_name{name}
|
|
|
|
|
, m_origName{name}
|
2025-06-30 02:17:27 +02:00
|
|
|
, m_libname{libname}
|
2022-09-15 14:10:39 +02:00
|
|
|
, m_modPublic{false}
|
|
|
|
|
, m_modTrace{false}
|
|
|
|
|
, m_inLibrary{false}
|
|
|
|
|
, m_dead{false}
|
2023-03-04 03:06:52 +01:00
|
|
|
, m_hasGParam{false}
|
2023-09-25 17:39:04 +02:00
|
|
|
, m_hasParameterList{false}
|
2022-09-15 14:10:39 +02:00
|
|
|
, m_hierBlock{false}
|
2024-08-21 11:30:59 +02:00
|
|
|
, m_hierParams{false}
|
2022-09-15 14:10:39 +02:00
|
|
|
, m_internal{false}
|
|
|
|
|
, m_recursive{false}
|
|
|
|
|
, m_recursiveClone{false} {}
|
|
|
|
|
|
|
|
|
|
public:
|
2022-10-04 12:03:41 +02:00
|
|
|
ASTGEN_MEMBERS_AstNodeModule;
|
2022-09-16 12:22:11 +02:00
|
|
|
void dump(std::ostream& str) const override;
|
2024-02-09 23:50:09 +01:00
|
|
|
void dumpJson(std::ostream& str) const override;
|
2024-10-01 03:34:34 +02:00
|
|
|
bool maybePointedTo() const override VL_MT_SAFE { return true; }
|
2023-03-18 01:24:15 +01:00
|
|
|
string name() const override VL_MT_STABLE { return m_name; }
|
2022-09-15 14:10:39 +02:00
|
|
|
virtual bool timescaleMatters() const = 0;
|
|
|
|
|
// ACCESSORS
|
2022-09-16 12:22:11 +02:00
|
|
|
void name(const string& name) override { m_name = name; }
|
|
|
|
|
string origName() const override { return m_origName; }
|
2022-10-18 23:07:09 +02:00
|
|
|
string someInstanceName() const VL_MT_SAFE { return m_someInstanceName; }
|
2022-09-15 14:10:39 +02:00
|
|
|
void someInstanceName(const string& name) { m_someInstanceName = name; }
|
|
|
|
|
bool inLibrary() const { return m_inLibrary; }
|
|
|
|
|
void inLibrary(bool flag) { m_inLibrary = flag; }
|
|
|
|
|
void level(int level) { m_level = level; }
|
2022-10-18 23:07:09 +02:00
|
|
|
int level() const VL_MT_SAFE { return m_level; }
|
2025-06-30 02:17:27 +02:00
|
|
|
string libname() const { return m_libname; }
|
|
|
|
|
string prettyLibnameQ() const { return "'" + prettyName(libname()) + "'"; }
|
2022-10-18 23:07:09 +02:00
|
|
|
bool isTop() const VL_MT_SAFE { return level() == 1; }
|
2022-09-15 14:10:39 +02:00
|
|
|
bool modPublic() const { return m_modPublic; }
|
2024-06-23 01:50:46 +02:00
|
|
|
void modPublic(bool flag) { m_modPublic = flag; }
|
2022-09-15 14:10:39 +02:00
|
|
|
bool modTrace() const { return m_modTrace; }
|
2024-06-23 01:50:46 +02:00
|
|
|
void modTrace(bool flag) { m_modTrace = flag; }
|
2022-09-15 14:10:39 +02:00
|
|
|
bool dead() const { return m_dead; }
|
2024-06-23 01:50:46 +02:00
|
|
|
void dead(bool flag) { m_dead = flag; }
|
2023-03-04 03:06:52 +01:00
|
|
|
bool hasGParam() const { return m_hasGParam; }
|
2024-06-23 01:50:46 +02:00
|
|
|
void hasGParam(bool flag) { m_hasGParam = flag; }
|
2023-09-25 17:39:04 +02:00
|
|
|
bool hasParameterList() const { return m_hasParameterList; }
|
2024-06-23 01:50:46 +02:00
|
|
|
void hasParameterList(bool flag) { m_hasParameterList = flag; }
|
2022-09-15 14:10:39 +02:00
|
|
|
bool hierBlock() const { return m_hierBlock; }
|
2024-06-23 01:50:46 +02:00
|
|
|
void hierBlock(bool flag) { m_hierBlock = flag; }
|
2024-08-21 11:30:59 +02:00
|
|
|
bool hierParams() const { return m_hierParams; }
|
|
|
|
|
void hierParams(bool flag) { m_hierParams = flag; }
|
2022-09-15 14:10:39 +02:00
|
|
|
bool internal() const { return m_internal; }
|
2024-06-23 01:50:46 +02:00
|
|
|
void internal(bool flag) { m_internal = flag; }
|
2022-09-15 14:10:39 +02:00
|
|
|
bool recursive() const { return m_recursive; }
|
2024-06-23 01:50:46 +02:00
|
|
|
void recursive(bool flag) { m_recursive = flag; }
|
2022-09-15 14:10:39 +02:00
|
|
|
void recursiveClone(bool flag) { m_recursiveClone = flag; }
|
|
|
|
|
bool recursiveClone() const { return m_recursiveClone; }
|
|
|
|
|
VLifetime lifetime() const { return m_lifetime; }
|
2024-06-23 01:50:46 +02:00
|
|
|
void lifetime(const VLifetime& flag) { m_lifetime = flag; }
|
2022-09-15 14:10:39 +02:00
|
|
|
VTimescale timeunit() const { return m_timeunit; }
|
2024-06-23 01:50:46 +02:00
|
|
|
void timeunit(const VTimescale& flag) { m_timeunit = flag; }
|
2022-09-15 14:10:39 +02:00
|
|
|
VOptionBool unconnectedDrive() const { return m_unconnectedDrive; }
|
2024-06-23 01:50:46 +02:00
|
|
|
void unconnectedDrive(const VOptionBool flag) { m_unconnectedDrive = flag; }
|
2022-09-15 14:10:39 +02:00
|
|
|
};
|
|
|
|
|
class AstNodeProcedure VL_NOT_FINAL : public AstNode {
|
|
|
|
|
// IEEE procedure: initial, final, always
|
2022-09-15 20:43:56 +02:00
|
|
|
// @astgen op2 := stmtsp : List[AstNode] // Note: op1 is used in some sub-types only
|
2023-06-01 16:02:08 +02:00
|
|
|
bool m_suspendable : 1; // Is suspendable by a Delay, EventControl, etc.
|
2023-10-16 14:02:29 +02:00
|
|
|
bool m_needProcess : 1; // Uses VlProcess
|
2022-09-15 14:10:39 +02:00
|
|
|
protected:
|
2022-09-15 20:43:56 +02:00
|
|
|
AstNodeProcedure(VNType t, FileLine* fl, AstNode* stmtsp)
|
2022-09-15 14:10:39 +02:00
|
|
|
: AstNode{t, fl} {
|
2023-06-01 16:02:08 +02:00
|
|
|
m_needProcess = false;
|
|
|
|
|
m_suspendable = false;
|
2022-09-15 20:43:56 +02:00
|
|
|
addStmtsp(stmtsp);
|
2022-09-15 14:10:39 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public:
|
2022-10-04 12:03:41 +02:00
|
|
|
ASTGEN_MEMBERS_AstNodeProcedure;
|
2022-09-15 14:10:39 +02:00
|
|
|
// METHODS
|
2022-09-16 12:22:11 +02:00
|
|
|
void dump(std::ostream& str) const override;
|
2024-02-09 23:50:09 +01:00
|
|
|
void dumpJson(std::ostream& str) const override;
|
2022-09-15 20:43:56 +02:00
|
|
|
bool isJustOneBodyStmt() const { return stmtsp() && !stmtsp()->nextp(); }
|
2022-09-15 14:17:00 +02:00
|
|
|
bool isSuspendable() const { return m_suspendable; }
|
|
|
|
|
void setSuspendable() { m_suspendable = true; }
|
2023-06-01 16:02:08 +02:00
|
|
|
bool needProcess() const { return m_needProcess; }
|
|
|
|
|
void setNeedProcess() { m_needProcess = true; }
|
2022-09-15 14:10:39 +02:00
|
|
|
};
|
|
|
|
|
class AstNodeRange VL_NOT_FINAL : public AstNode {
|
|
|
|
|
// A range, sized or unsized
|
|
|
|
|
protected:
|
|
|
|
|
AstNodeRange(VNType t, FileLine* fl)
|
|
|
|
|
: AstNode{t, fl} {}
|
|
|
|
|
|
|
|
|
|
public:
|
2022-10-04 12:03:41 +02:00
|
|
|
ASTGEN_MEMBERS_AstNodeRange;
|
2022-09-16 12:22:11 +02:00
|
|
|
void dump(std::ostream& str) const override;
|
2024-02-09 23:50:09 +01:00
|
|
|
void dumpJson(std::ostream& str) const override;
|
2022-09-15 14:10:39 +02:00
|
|
|
};
|
|
|
|
|
class AstNodeText VL_NOT_FINAL : public AstNode {
|
|
|
|
|
string m_text;
|
2024-02-09 23:50:09 +01:00
|
|
|
// METHODS
|
|
|
|
|
string shortText() const;
|
2022-09-15 14:10:39 +02:00
|
|
|
|
|
|
|
|
protected:
|
|
|
|
|
// Node that puts text into the output stream
|
2022-09-15 14:54:04 +02:00
|
|
|
AstNodeText(VNType t, FileLine* fl, const string& text)
|
|
|
|
|
: AstNode{t, fl}
|
|
|
|
|
, m_text{text} {}
|
2022-09-15 14:10:39 +02:00
|
|
|
|
|
|
|
|
public:
|
2022-10-04 12:03:41 +02:00
|
|
|
ASTGEN_MEMBERS_AstNodeText;
|
2022-09-16 12:22:11 +02:00
|
|
|
void dump(std::ostream& str = std::cout) const override;
|
2024-02-09 23:50:09 +01:00
|
|
|
void dumpJson(std::ostream& str = std::cout) const override;
|
2024-11-28 20:37:11 +01:00
|
|
|
bool sameNode(const AstNode* samep) const override {
|
2023-10-16 11:17:52 +02:00
|
|
|
const AstNodeText* asamep = VN_DBG_AS(samep, NodeText);
|
2022-09-15 14:10:39 +02:00
|
|
|
return text() == asamep->text();
|
|
|
|
|
}
|
2022-10-18 23:07:09 +02:00
|
|
|
const string& text() const VL_MT_SAFE { return m_text; }
|
2022-09-15 14:17:00 +02:00
|
|
|
void text(const string& value) { m_text = value; }
|
2022-09-15 14:10:39 +02:00
|
|
|
};
|
|
|
|
|
class AstNodeSimpleText VL_NOT_FINAL : public AstNodeText {
|
|
|
|
|
bool m_tracking; // When emit, it's ok to parse the string to do indentation
|
|
|
|
|
public:
|
|
|
|
|
AstNodeSimpleText(VNType t, FileLine* fl, const string& textp, bool tracking = false)
|
2022-11-20 21:06:49 +01:00
|
|
|
: AstNodeText{t, fl, textp}
|
|
|
|
|
, m_tracking{tracking} {}
|
2022-10-04 12:03:41 +02:00
|
|
|
ASTGEN_MEMBERS_AstNodeSimpleText;
|
2022-09-15 14:10:39 +02:00
|
|
|
void tracking(bool flag) { m_tracking = flag; }
|
|
|
|
|
bool tracking() const { return m_tracking; }
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
// === Concrete node types =====================================================
|
|
|
|
|
|
|
|
|
|
// === AstNode ===
|
|
|
|
|
class AstActive final : public AstNode {
|
|
|
|
|
// Block of code with sensitivity activation
|
|
|
|
|
// Parents: MODULE | CFUNC
|
2025-08-18 01:14:34 +02:00
|
|
|
// @astgen op1 := senTreeStorep : Optional[AstSenTree] // Moved into m_sensesp in V3Active
|
2022-09-15 20:43:56 +02:00
|
|
|
// @astgen op2 := stmtsp : List[AstNode] // Logic
|
2023-12-01 01:58:16 +01:00
|
|
|
//
|
2025-08-18 01:14:34 +02:00
|
|
|
// @astgen ptr := m_sentreep : Optional[AstSenTree] // Sensitivity list for this process
|
2022-09-15 14:10:39 +02:00
|
|
|
string m_name;
|
|
|
|
|
|
|
|
|
|
public:
|
2025-08-18 01:14:34 +02:00
|
|
|
AstActive(FileLine* fl, const string& name, AstSenTree* sentreep)
|
2022-09-15 14:54:04 +02:00
|
|
|
: ASTGEN_SUPER_Active(fl)
|
|
|
|
|
, m_name{name}
|
2025-08-18 01:14:34 +02:00
|
|
|
, m_sentreep{sentreep} {
|
|
|
|
|
UASSERT(sentreep, "Sentreep required arg");
|
2022-09-15 14:10:39 +02:00
|
|
|
}
|
2022-10-04 12:03:41 +02:00
|
|
|
ASTGEN_MEMBERS_AstActive;
|
2022-09-16 12:22:11 +02:00
|
|
|
void dump(std::ostream& str = std::cout) const override;
|
2024-02-09 23:50:09 +01:00
|
|
|
void dumpJson(std::ostream& str = std::cout) const override;
|
2023-03-18 01:24:15 +01:00
|
|
|
string name() const override VL_MT_STABLE { return m_name; }
|
2022-09-15 14:10:39 +02:00
|
|
|
// Statements are broken into pieces, as some must come before others.
|
2025-08-18 01:14:34 +02:00
|
|
|
void sentreep(AstSenTree* nodep) { m_sentreep = nodep; }
|
|
|
|
|
AstSenTree* sentreep() const { return m_sentreep; }
|
2022-09-15 14:10:39 +02:00
|
|
|
// METHODS
|
|
|
|
|
inline bool hasClocked() const;
|
2022-09-15 14:17:00 +02:00
|
|
|
inline bool hasCombo() const;
|
2022-09-15 14:10:39 +02:00
|
|
|
};
|
|
|
|
|
class AstBind final : public AstNode {
|
|
|
|
|
// Parents: MODULE
|
|
|
|
|
// Children: CELL
|
2022-09-15 20:43:56 +02:00
|
|
|
// @astgen op1 := cellsp : List[AstNode]
|
2022-09-15 14:10:39 +02:00
|
|
|
string m_name; // Binding to name
|
|
|
|
|
public:
|
|
|
|
|
AstBind(FileLine* fl, const string& name, AstNode* cellsp)
|
|
|
|
|
: ASTGEN_SUPER_Bind(fl)
|
|
|
|
|
, m_name{name} {
|
|
|
|
|
UASSERT_OBJ(VN_IS(cellsp, Cell), cellsp, "Only instances allowed to be bound");
|
2025-03-08 23:48:20 +01:00
|
|
|
addCellsp(cellsp);
|
2022-09-15 14:10:39 +02:00
|
|
|
}
|
2022-10-04 12:03:41 +02:00
|
|
|
ASTGEN_MEMBERS_AstBind;
|
2022-09-15 14:10:39 +02:00
|
|
|
// ACCESSORS
|
2023-03-18 01:24:15 +01:00
|
|
|
string name() const override VL_MT_STABLE { return m_name; } // * = Bind Target name
|
2022-09-16 12:22:11 +02:00
|
|
|
void name(const string& name) override { m_name = name; }
|
2022-09-15 14:10:39 +02:00
|
|
|
};
|
|
|
|
|
class AstCFunc final : public AstNode {
|
|
|
|
|
// C++ function
|
|
|
|
|
// Parents: MODULE/SCOPE
|
2022-09-15 20:43:56 +02:00
|
|
|
// If adding node accessors, see below emptyBody
|
|
|
|
|
// @astgen op1 := argsp : List[AstNode]
|
|
|
|
|
// @astgen op2 := initsp : List[AstNode]
|
|
|
|
|
// @astgen op3 := stmtsp : List[AstNode]
|
|
|
|
|
// @astgen op4 := finalsp : List[AstNode]
|
2023-12-01 01:58:16 +01:00
|
|
|
//
|
|
|
|
|
// @astgen ptr := m_scopep : Optional[AstScope] // Scope that function is under
|
2022-09-15 14:10:39 +02:00
|
|
|
string m_name;
|
|
|
|
|
string m_cname; // C name, for dpiExports
|
|
|
|
|
string m_rtnType; // void, bool, or other return type
|
|
|
|
|
string m_argTypes; // Argument types
|
|
|
|
|
string m_ifdef; // #ifdef symbol around this function
|
|
|
|
|
VBoolOrUnknown m_isConst; // Function is declared const (*this not changed)
|
|
|
|
|
bool m_isStatic : 1; // Function is static (no need for a 'this' pointer)
|
|
|
|
|
bool m_isTrace : 1; // Function is related to tracing
|
|
|
|
|
bool m_dontCombine : 1; // V3Combine shouldn't compare this func tree, it's special
|
|
|
|
|
bool m_declPrivate : 1; // Declare it private
|
2025-01-25 18:13:25 +01:00
|
|
|
bool m_keepIfEmpty : 1; // Keep declaration and definition separate, even if empty
|
2022-09-15 14:10:39 +02:00
|
|
|
bool m_slow : 1; // Slow routine, called once or just at init time
|
|
|
|
|
bool m_funcPublic : 1; // From user public task/function
|
|
|
|
|
bool m_isConstructor : 1; // Is C class constructor
|
|
|
|
|
bool m_isDestructor : 1; // Is C class destructor
|
|
|
|
|
bool m_isMethod : 1; // Is inside a class definition
|
2025-04-26 15:51:02 +02:00
|
|
|
bool m_isLoose : 1; // Semantically this is a method, but is implemented as a function with
|
|
|
|
|
// an explicitly passed 'self' pointer as the first argument. This can
|
|
|
|
|
// be slightly faster due to __restrict, and we do not declare in header
|
|
|
|
|
// so adding/removing loose functions doesn't recompile everything.
|
2022-09-15 14:10:39 +02:00
|
|
|
bool m_isInline : 1; // Inline function
|
|
|
|
|
bool m_isVirtual : 1; // Virtual function
|
|
|
|
|
bool m_entryPoint : 1; // User may call into this top level function
|
2023-09-08 08:51:19 +02:00
|
|
|
bool m_dpiPure : 1; // Pure DPI function
|
2022-09-15 14:10:39 +02:00
|
|
|
bool m_dpiContext : 1; // Declared as 'context' DPI import/export function
|
|
|
|
|
bool m_dpiExportDispatcher : 1; // This is the DPI export entry point (i.e.: called by user)
|
|
|
|
|
bool m_dpiExportImpl : 1; // DPI export implementation (called from DPI dispatcher via lookup)
|
|
|
|
|
bool m_dpiImportPrototype : 1; // This is the DPI import prototype (i.e.: provided by user)
|
|
|
|
|
bool m_dpiImportWrapper : 1; // Wrapper for invoking DPI import prototype from generated code
|
2023-10-16 14:02:29 +02:00
|
|
|
bool m_needProcess : 1; // Needs access to VlProcess of the caller
|
2023-10-17 13:38:45 +02:00
|
|
|
bool m_recursive : 1; // Recursive or part of recursion
|
2025-01-20 20:24:09 +01:00
|
|
|
int m_cost; // Function call cost
|
2022-09-15 14:10:39 +02:00
|
|
|
public:
|
|
|
|
|
AstCFunc(FileLine* fl, const string& name, AstScope* scopep, const string& rtnType = "")
|
|
|
|
|
: ASTGEN_SUPER_CFunc(fl) {
|
|
|
|
|
m_isConst = VBoolOrUnknown::BU_UNKNOWN; // Unknown until analyzed
|
|
|
|
|
m_scopep = scopep;
|
|
|
|
|
m_name = name;
|
|
|
|
|
m_rtnType = rtnType;
|
|
|
|
|
m_isStatic = false;
|
|
|
|
|
m_isTrace = false;
|
|
|
|
|
m_dontCombine = false;
|
|
|
|
|
m_declPrivate = false;
|
2025-01-25 18:13:25 +01:00
|
|
|
m_keepIfEmpty = false;
|
2022-09-15 14:10:39 +02:00
|
|
|
m_slow = false;
|
|
|
|
|
m_funcPublic = false;
|
|
|
|
|
m_isConstructor = false;
|
|
|
|
|
m_isDestructor = false;
|
|
|
|
|
m_isMethod = true;
|
|
|
|
|
m_isLoose = false;
|
|
|
|
|
m_isInline = false;
|
|
|
|
|
m_isVirtual = false;
|
2023-06-01 16:02:08 +02:00
|
|
|
m_needProcess = false;
|
2022-09-15 14:10:39 +02:00
|
|
|
m_entryPoint = false;
|
2023-09-08 08:51:19 +02:00
|
|
|
m_dpiPure = false;
|
2022-09-15 14:10:39 +02:00
|
|
|
m_dpiContext = false;
|
|
|
|
|
m_dpiExportDispatcher = false;
|
|
|
|
|
m_dpiExportImpl = false;
|
|
|
|
|
m_dpiImportPrototype = false;
|
|
|
|
|
m_dpiImportWrapper = false;
|
2023-10-17 13:38:45 +02:00
|
|
|
m_recursive = false;
|
2025-01-20 20:24:09 +01:00
|
|
|
m_cost = v3Global.opt.instrCountDpi(); // As proxy for unknown general DPI cost
|
2022-09-15 14:10:39 +02:00
|
|
|
}
|
2022-10-04 12:03:41 +02:00
|
|
|
ASTGEN_MEMBERS_AstCFunc;
|
2023-03-18 01:24:15 +01:00
|
|
|
string name() const override VL_MT_STABLE { return m_name; }
|
2024-10-01 03:34:34 +02:00
|
|
|
bool maybePointedTo() const override VL_MT_SAFE { return true; }
|
2022-09-16 12:22:11 +02:00
|
|
|
void dump(std::ostream& str = std::cout) const override;
|
2024-02-09 23:50:09 +01:00
|
|
|
void dumpJson(std::ostream& str = std::cout) const override;
|
2024-11-28 20:37:11 +01:00
|
|
|
bool sameNode(const AstNode* samep) const override {
|
2023-10-16 11:17:52 +02:00
|
|
|
const AstCFunc* const asamep = VN_DBG_AS(samep, CFunc);
|
2022-09-15 14:10:39 +02:00
|
|
|
return ((isTrace() == asamep->isTrace()) && (rtnTypeVoid() == asamep->rtnTypeVoid())
|
2024-01-24 01:36:11 +01:00
|
|
|
&& (argTypes() == asamep->argTypes()) && isLoose() == asamep->isLoose()
|
2022-09-15 14:10:39 +02:00
|
|
|
&& (!(dpiImportPrototype() || dpiExportImpl()) || name() == asamep->name()));
|
|
|
|
|
}
|
|
|
|
|
//
|
2022-09-16 12:22:11 +02:00
|
|
|
void name(const string& name) override { m_name = name; }
|
2025-01-20 20:24:09 +01:00
|
|
|
int instrCount() const override { return m_cost; }
|
2022-09-15 14:10:39 +02:00
|
|
|
VBoolOrUnknown isConst() const { return m_isConst; }
|
|
|
|
|
void isConst(bool flag) { m_isConst.setTrueOrFalse(flag); }
|
|
|
|
|
void isConst(VBoolOrUnknown flag) { m_isConst = flag; }
|
|
|
|
|
bool isStatic() const { return m_isStatic; }
|
|
|
|
|
void isStatic(bool flag) { m_isStatic = flag; }
|
2022-10-18 23:07:09 +02:00
|
|
|
bool isTrace() const VL_MT_SAFE { return m_isTrace; }
|
2022-09-15 14:10:39 +02:00
|
|
|
void isTrace(bool flag) { m_isTrace = flag; }
|
|
|
|
|
void cname(const string& name) { m_cname = name; }
|
|
|
|
|
string cname() const { return m_cname; }
|
|
|
|
|
AstScope* scopep() const { return m_scopep; }
|
|
|
|
|
void scopep(AstScope* nodep) { m_scopep = nodep; }
|
|
|
|
|
string rtnTypeVoid() const { return ((m_rtnType == "") ? "void" : m_rtnType); }
|
2022-09-15 14:17:00 +02:00
|
|
|
void rtnType(const string& rtnType) { m_rtnType = rtnType; }
|
2022-09-15 14:10:39 +02:00
|
|
|
bool dontCombine() const { return m_dontCombine || isTrace() || entryPoint(); }
|
|
|
|
|
void dontCombine(bool flag) { m_dontCombine = flag; }
|
|
|
|
|
bool dontInline() const { return dontCombine() || slow() || funcPublic(); }
|
|
|
|
|
bool declPrivate() const { return m_declPrivate; }
|
|
|
|
|
void declPrivate(bool flag) { m_declPrivate = flag; }
|
2025-01-25 18:13:25 +01:00
|
|
|
bool keepIfEmpty() const VL_MT_SAFE { return m_keepIfEmpty; }
|
|
|
|
|
void keepIfEmpty(bool flag) { m_keepIfEmpty = flag; }
|
2022-10-18 23:07:09 +02:00
|
|
|
bool slow() const VL_MT_SAFE { return m_slow; }
|
2022-09-15 14:10:39 +02:00
|
|
|
void slow(bool flag) { m_slow = flag; }
|
|
|
|
|
bool funcPublic() const { return m_funcPublic; }
|
|
|
|
|
void funcPublic(bool flag) { m_funcPublic = flag; }
|
|
|
|
|
void argTypes(const string& str) { m_argTypes = str; }
|
|
|
|
|
string argTypes() const { return m_argTypes; }
|
|
|
|
|
void ifdef(const string& str) { m_ifdef = str; }
|
|
|
|
|
string ifdef() const { return m_ifdef; }
|
|
|
|
|
bool isConstructor() const { return m_isConstructor; }
|
|
|
|
|
void isConstructor(bool flag) { m_isConstructor = flag; }
|
|
|
|
|
bool isDestructor() const { return m_isDestructor; }
|
|
|
|
|
void isDestructor(bool flag) { m_isDestructor = flag; }
|
|
|
|
|
bool isMethod() const { return m_isMethod; }
|
|
|
|
|
void isMethod(bool flag) { m_isMethod = flag; }
|
|
|
|
|
bool isLoose() const { return m_isLoose; }
|
|
|
|
|
void isLoose(bool flag) { m_isLoose = flag; }
|
|
|
|
|
bool isProperMethod() const { return isMethod() && !isLoose(); }
|
|
|
|
|
bool isInline() const { return m_isInline; }
|
|
|
|
|
void isInline(bool flag) { m_isInline = flag; }
|
|
|
|
|
bool isVirtual() const { return m_isVirtual; }
|
|
|
|
|
void isVirtual(bool flag) { m_isVirtual = flag; }
|
2023-06-01 16:02:08 +02:00
|
|
|
bool needProcess() const { return m_needProcess; }
|
|
|
|
|
void setNeedProcess() { m_needProcess = true; }
|
2022-09-15 14:10:39 +02:00
|
|
|
bool entryPoint() const { return m_entryPoint; }
|
|
|
|
|
void entryPoint(bool flag) { m_entryPoint = flag; }
|
2023-09-08 08:51:19 +02:00
|
|
|
bool dpiPure() const { return m_dpiPure; }
|
|
|
|
|
void dpiPure(bool flag) { m_dpiPure = flag; }
|
2022-09-15 14:10:39 +02:00
|
|
|
bool dpiContext() const { return m_dpiContext; }
|
|
|
|
|
void dpiContext(bool flag) { m_dpiContext = flag; }
|
2022-10-18 23:07:09 +02:00
|
|
|
bool dpiExportDispatcher() const VL_MT_SAFE { return m_dpiExportDispatcher; }
|
2022-09-15 14:10:39 +02:00
|
|
|
void dpiExportDispatcher(bool flag) { m_dpiExportDispatcher = flag; }
|
|
|
|
|
bool dpiExportImpl() const { return m_dpiExportImpl; }
|
|
|
|
|
void dpiExportImpl(bool flag) { m_dpiExportImpl = flag; }
|
2022-10-18 23:07:09 +02:00
|
|
|
bool dpiImportPrototype() const VL_MT_SAFE { return m_dpiImportPrototype; }
|
2022-09-15 14:10:39 +02:00
|
|
|
void dpiImportPrototype(bool flag) { m_dpiImportPrototype = flag; }
|
|
|
|
|
bool dpiImportWrapper() const { return m_dpiImportWrapper; }
|
|
|
|
|
void dpiImportWrapper(bool flag) { m_dpiImportWrapper = flag; }
|
2022-09-15 14:17:00 +02:00
|
|
|
bool isCoroutine() const { return m_rtnType == "VlCoroutine"; }
|
2023-10-17 13:38:45 +02:00
|
|
|
void recursive(bool flag) { m_recursive = flag; }
|
|
|
|
|
bool recursive() const { return m_recursive; }
|
2025-01-20 20:24:09 +01:00
|
|
|
void cost(int cost) { m_cost = cost; }
|
2022-09-15 14:10:39 +02:00
|
|
|
// Special methods
|
|
|
|
|
bool emptyBody() const {
|
2025-01-25 18:13:25 +01:00
|
|
|
return !keepIfEmpty() && !argsp() && !initsp() && !stmtsp() && !finalsp();
|
2022-09-15 14:10:39 +02:00
|
|
|
}
|
|
|
|
|
};
|
2023-08-11 18:28:37 +02:00
|
|
|
class AstCLocalScope final : public AstNode {
|
|
|
|
|
// Pack statements into an unnamed scope when generating C++
|
|
|
|
|
// @astgen op1 := stmtsp : List[AstNode]
|
|
|
|
|
public:
|
|
|
|
|
AstCLocalScope(FileLine* fl, AstNode* stmtsp)
|
|
|
|
|
: ASTGEN_SUPER_CLocalScope(fl) {
|
2025-03-08 23:48:20 +01:00
|
|
|
addStmtsp(stmtsp);
|
2023-08-11 18:28:37 +02:00
|
|
|
}
|
|
|
|
|
ASTGEN_MEMBERS_AstCLocalScope;
|
|
|
|
|
};
|
2022-09-15 14:10:39 +02:00
|
|
|
class AstCUse final : public AstNode {
|
|
|
|
|
// C++ use of a class or #include; indicates need of forward declaration
|
|
|
|
|
// Parents: NODEMODULE
|
|
|
|
|
const string m_name;
|
2022-11-13 15:26:46 +01:00
|
|
|
const VUseType m_useType; // What sort of use this is
|
2022-09-15 14:10:39 +02:00
|
|
|
|
|
|
|
|
public:
|
|
|
|
|
AstCUse(FileLine* fl, VUseType useType, const string& name)
|
|
|
|
|
: ASTGEN_SUPER_CUse(fl)
|
2022-11-13 15:26:46 +01:00
|
|
|
, m_name{name}
|
|
|
|
|
, m_useType{useType} {}
|
2022-10-04 12:03:41 +02:00
|
|
|
ASTGEN_MEMBERS_AstCUse;
|
2022-09-16 12:22:11 +02:00
|
|
|
void dump(std::ostream& str = std::cout) const override;
|
2024-02-09 23:50:09 +01:00
|
|
|
void dumpJson(std::ostream& str = std::cout) const override;
|
2023-03-18 01:24:15 +01:00
|
|
|
string name() const override VL_MT_STABLE { return m_name; }
|
2022-09-15 14:10:39 +02:00
|
|
|
VUseType useType() const { return m_useType; }
|
|
|
|
|
};
|
|
|
|
|
class AstCaseItem final : public AstNode {
|
|
|
|
|
// Single item of a case statement
|
2022-11-13 21:33:11 +01:00
|
|
|
// @astgen op1 := condsp : List[AstNodeExpr]
|
2022-09-15 20:43:56 +02:00
|
|
|
// @astgen op2 := stmtsp : List[AstNode]
|
2022-09-15 14:10:39 +02:00
|
|
|
public:
|
2022-11-13 21:33:11 +01:00
|
|
|
AstCaseItem(FileLine* fl, AstNodeExpr* condsp, AstNode* stmtsp)
|
2022-09-15 14:10:39 +02:00
|
|
|
: ASTGEN_SUPER_CaseItem(fl) {
|
2025-03-08 23:48:20 +01:00
|
|
|
addCondsp(condsp);
|
|
|
|
|
addStmtsp(stmtsp);
|
2022-09-15 14:10:39 +02:00
|
|
|
}
|
2022-10-04 12:03:41 +02:00
|
|
|
ASTGEN_MEMBERS_AstCaseItem;
|
2022-09-16 12:22:11 +02:00
|
|
|
int instrCount() const override { return widthInstrs() + INSTR_COUNT_BRANCH; }
|
2022-09-15 14:10:39 +02:00
|
|
|
bool isDefault() const { return condsp() == nullptr; }
|
2022-09-15 20:43:56 +02:00
|
|
|
bool isFirstInMyListOfStatements(AstNode* n) const override { return n == stmtsp(); }
|
2022-09-15 14:10:39 +02:00
|
|
|
};
|
|
|
|
|
class AstCell final : public AstNode {
|
|
|
|
|
// A instantiation cell or interface call (don't know which until link)
|
2022-09-15 20:43:56 +02:00
|
|
|
// @astgen op1 := pinsp : List[AstPin] // List of port assignments
|
|
|
|
|
// @astgen op2 := paramsp : List[AstPin] // List of parameter assignments
|
|
|
|
|
// @astgen op3 := rangep : Optional[AstRange] // Range for arrayed instances
|
2023-10-24 17:33:29 +02:00
|
|
|
// @astgen op4 := intfRefsp : List[AstIntfRef] // List of interface references, for tracing
|
2023-12-01 01:58:16 +01:00
|
|
|
//
|
|
|
|
|
// @astgen ptr := m_modp : Optional[AstNodeModule] // [AfterLink] Pointer to module instanced
|
2022-09-15 14:10:39 +02:00
|
|
|
FileLine* m_modNameFileline; // Where module the cell instances token was
|
|
|
|
|
string m_name; // Cell name
|
|
|
|
|
string m_origName; // Original name before dot addition
|
|
|
|
|
string m_modName; // Module the cell instances
|
|
|
|
|
bool m_hasIfaceVar : 1; // True if a Var has been created for this cell
|
|
|
|
|
bool m_recursive : 1; // Self-recursive module
|
|
|
|
|
bool m_trace : 1; // Trace this cell
|
|
|
|
|
public:
|
|
|
|
|
AstCell(FileLine* fl, FileLine* mfl, const string& instName, const string& modName,
|
|
|
|
|
AstPin* pinsp, AstPin* paramsp, AstRange* rangep)
|
|
|
|
|
: ASTGEN_SUPER_Cell(fl)
|
|
|
|
|
, m_modNameFileline{mfl}
|
|
|
|
|
, m_name{instName}
|
|
|
|
|
, m_origName{instName}
|
|
|
|
|
, m_modName{modName}
|
|
|
|
|
, m_hasIfaceVar{false}
|
|
|
|
|
, m_recursive{false}
|
|
|
|
|
, m_trace{true} {
|
2025-03-08 23:48:20 +01:00
|
|
|
addPinsp(pinsp);
|
|
|
|
|
addParamsp(paramsp);
|
2022-09-15 20:43:56 +02:00
|
|
|
this->rangep(rangep);
|
2022-09-15 14:10:39 +02:00
|
|
|
}
|
2022-10-04 12:03:41 +02:00
|
|
|
ASTGEN_MEMBERS_AstCell;
|
2022-09-15 14:10:39 +02:00
|
|
|
// No cloneRelink, we presume cloneee's want the same module linkages
|
2023-12-01 01:58:16 +01:00
|
|
|
void cloneRelink() override {} // TODO V3Param shouldn't require avoiding cloneRelinkGen
|
2022-09-16 12:22:11 +02:00
|
|
|
void dump(std::ostream& str) const override;
|
2024-02-09 23:50:09 +01:00
|
|
|
void dumpJson(std::ostream& str) const override;
|
2024-10-01 03:34:34 +02:00
|
|
|
bool maybePointedTo() const override VL_MT_SAFE { return true; }
|
2022-09-15 14:10:39 +02:00
|
|
|
// ACCESSORS
|
2023-03-18 01:24:15 +01:00
|
|
|
string name() const override VL_MT_STABLE { return m_name; } // * = Cell name
|
2022-09-16 12:22:11 +02:00
|
|
|
void name(const string& name) override { m_name = name; }
|
|
|
|
|
string origName() const override { return m_origName; } // * = Original name
|
2022-09-15 14:10:39 +02:00
|
|
|
void origName(const string& name) { m_origName = name; }
|
|
|
|
|
string modName() const { return m_modName; } // * = Instance name
|
|
|
|
|
void modName(const string& name) { m_modName = name; }
|
|
|
|
|
FileLine* modNameFileline() const { return m_modNameFileline; }
|
|
|
|
|
AstNodeModule* modp() const { return m_modp; } // [AfterLink] = Pointer to module instantiated
|
|
|
|
|
void modp(AstNodeModule* nodep) { m_modp = nodep; }
|
|
|
|
|
bool hasIfaceVar() const { return m_hasIfaceVar; }
|
|
|
|
|
void hasIfaceVar(bool flag) { m_hasIfaceVar = flag; }
|
|
|
|
|
void trace(bool flag) { m_trace = flag; }
|
|
|
|
|
bool isTrace() const { return m_trace; }
|
|
|
|
|
void recursive(bool flag) { m_recursive = flag; }
|
|
|
|
|
bool recursive() const { return m_recursive; }
|
|
|
|
|
};
|
|
|
|
|
class AstCellInline final : public AstNode {
|
|
|
|
|
// A instantiation cell that was removed by inlining
|
|
|
|
|
// For communication between V3Inline and V3LinkDot,
|
|
|
|
|
// except for VPI runs where it exists until the end.
|
|
|
|
|
// It is augmented with the scope in V3Scope for VPI.
|
|
|
|
|
// Children: When 2 levels inlined, other CellInline under this
|
2023-12-01 01:58:16 +01:00
|
|
|
// @astgen ptr := m_scopep : Optional[AstScope] // The scope that the cell is inlined into
|
2022-09-15 14:10:39 +02:00
|
|
|
string m_name; // Cell name, possibly {a}__DOT__{b}...
|
2023-12-01 01:58:16 +01:00
|
|
|
const string m_origModName; // Original name of module, ignoring name() changes, for LinkDot
|
2022-09-15 14:10:39 +02:00
|
|
|
VTimescale m_timeunit; // Parent module time unit
|
|
|
|
|
public:
|
|
|
|
|
AstCellInline(FileLine* fl, const string& name, const string& origModName,
|
|
|
|
|
const VTimescale& timeunit)
|
|
|
|
|
: ASTGEN_SUPER_CellInline(fl)
|
|
|
|
|
, m_name{name}
|
|
|
|
|
, m_origModName{origModName}
|
|
|
|
|
, m_timeunit{timeunit} {}
|
2022-10-04 12:03:41 +02:00
|
|
|
ASTGEN_MEMBERS_AstCellInline;
|
2022-09-16 12:22:11 +02:00
|
|
|
void dump(std::ostream& str) const override;
|
2024-02-09 23:50:09 +01:00
|
|
|
void dumpJson(std::ostream& str) const override;
|
2022-09-15 14:10:39 +02:00
|
|
|
// ACCESSORS
|
2023-03-18 01:24:15 +01:00
|
|
|
string name() const override VL_MT_STABLE { return m_name; } // * = Cell name
|
2024-10-01 03:34:34 +02:00
|
|
|
bool maybePointedTo() const override VL_MT_SAFE { return true; }
|
2022-09-15 14:10:39 +02:00
|
|
|
string origModName() const { return m_origModName; } // * = modp()->origName() before inlining
|
2022-09-16 12:22:11 +02:00
|
|
|
void name(const string& name) override { m_name = name; }
|
2022-09-15 14:10:39 +02:00
|
|
|
void timeunit(const VTimescale& flag) { m_timeunit = flag; }
|
|
|
|
|
VTimescale timeunit() const { return m_timeunit; }
|
|
|
|
|
};
|
2024-04-02 05:11:15 +02:00
|
|
|
class AstCellInlineScope final : public AstNode {
|
|
|
|
|
// A particular scoped usage of a Cell Inline
|
|
|
|
|
// Parents: Scope
|
|
|
|
|
// Children: none
|
|
|
|
|
//
|
|
|
|
|
// @astgen ptr := m_scopep : Optional[AstScope] // Scope variable is underneath
|
|
|
|
|
// @astgen ptr := m_cellp : Optional[AstCellInline] // Cell ref
|
|
|
|
|
const string m_origModName; // Original name of module, ignoring name() changes, for LinkDot
|
|
|
|
|
public:
|
|
|
|
|
AstCellInlineScope(FileLine* fl, AstScope* scopep, AstCellInline* cellp)
|
|
|
|
|
: ASTGEN_SUPER_CellInlineScope(fl)
|
|
|
|
|
, m_scopep{scopep}
|
|
|
|
|
, m_cellp{cellp} {
|
|
|
|
|
UASSERT_OBJ(scopep, fl, "Scope must be non-null");
|
|
|
|
|
UASSERT_OBJ(cellp, fl, "CellInline must be non-null");
|
|
|
|
|
}
|
|
|
|
|
ASTGEN_MEMBERS_AstCellInlineScope;
|
|
|
|
|
void dump(std::ostream& str) const override;
|
|
|
|
|
void dumpJson(std::ostream& str) const override;
|
|
|
|
|
// ACCESSORS
|
|
|
|
|
string name() const override VL_MT_STABLE { return m_cellp->name(); }
|
2024-10-01 03:34:34 +02:00
|
|
|
bool maybePointedTo() const override VL_MT_SAFE { return true; }
|
2024-04-02 05:11:15 +02:00
|
|
|
AstScope* scopep() const VL_MT_STABLE { return m_scopep; } // Pointer to scope it's under
|
|
|
|
|
string origModName() const {
|
|
|
|
|
return m_cellp->origModName();
|
|
|
|
|
} // * = modp()->origName() before inlining
|
|
|
|
|
void scopep(AstScope* nodep) { m_scopep = nodep; }
|
|
|
|
|
};
|
2022-09-15 14:10:39 +02:00
|
|
|
class AstClassExtends final : public AstNode {
|
2023-01-28 22:30:47 +01:00
|
|
|
// class extends class name, or class implements class name
|
2022-09-15 14:10:39 +02:00
|
|
|
// Children: List of AstParseRef for packages/classes
|
|
|
|
|
// during early parse, then moves to dtype
|
2022-09-15 20:43:56 +02:00
|
|
|
// @astgen op1 := childDTypep : Optional[AstNodeDType]
|
|
|
|
|
// @astgen op2 := classOrPkgsp : Optional[AstNode]
|
2025-04-09 04:09:40 +02:00
|
|
|
// @astgen op3 := argsp : List[AstNodeExpr]
|
2025-08-19 23:02:10 +02:00
|
|
|
const bool m_isImplements; // class implements
|
2023-05-16 01:50:04 +02:00
|
|
|
bool m_parameterized = false; // has parameters in its statement
|
|
|
|
|
|
2022-09-15 14:10:39 +02:00
|
|
|
public:
|
2023-01-28 22:30:47 +01:00
|
|
|
AstClassExtends(FileLine* fl, AstNode* classOrPkgsp, bool isImplements)
|
|
|
|
|
: ASTGEN_SUPER_ClassExtends(fl)
|
|
|
|
|
, m_isImplements{isImplements} {
|
2022-09-15 20:43:56 +02:00
|
|
|
this->classOrPkgsp(classOrPkgsp); // Only for parser
|
2022-09-15 14:10:39 +02:00
|
|
|
}
|
2022-10-04 12:03:41 +02:00
|
|
|
ASTGEN_MEMBERS_AstClassExtends;
|
2023-01-28 22:30:47 +01:00
|
|
|
void dump(std::ostream& str) const override;
|
2024-02-09 23:50:09 +01:00
|
|
|
void dumpJson(std::ostream& str) const override;
|
2024-10-01 03:34:34 +02:00
|
|
|
bool hasDType() const override VL_MT_SAFE { return true; }
|
2023-01-28 22:30:47 +01:00
|
|
|
string verilogKwd() const override { return isImplements() ? "implements" : "extends"; }
|
2023-05-16 01:50:04 +02:00
|
|
|
// Class being extended (after link and instantiation if needed)
|
|
|
|
|
AstClass* classOrNullp() const;
|
|
|
|
|
AstClass* classp() const; // Like above, but throws error if nulll
|
2023-01-28 22:30:47 +01:00
|
|
|
bool isImplements() const { return m_isImplements; }
|
2023-05-16 01:50:04 +02:00
|
|
|
void parameterized(bool flag) { m_parameterized = flag; }
|
|
|
|
|
bool parameterized() const { return m_parameterized; }
|
2022-09-15 14:10:39 +02:00
|
|
|
};
|
|
|
|
|
class AstClocking final : public AstNode {
|
|
|
|
|
// Parents: MODULE
|
2022-12-23 13:34:49 +01:00
|
|
|
// Children: SENITEM, CLOCKING ITEMs, VARs
|
|
|
|
|
// @astgen op1 := sensesp : AstSenItem
|
|
|
|
|
// @astgen op2 := itemsp : List[AstClockingItem]
|
2024-06-30 21:19:02 +02:00
|
|
|
// @astgen op3 := eventp : Optional[AstVar]
|
2022-12-23 13:34:49 +01:00
|
|
|
std::string m_name; // Clocking block name
|
2025-08-19 23:02:10 +02:00
|
|
|
const bool m_isDefault; // True if default clocking
|
|
|
|
|
const bool m_isGlobal; // True if global clocking
|
2022-12-23 13:34:49 +01:00
|
|
|
|
2022-09-15 14:10:39 +02:00
|
|
|
public:
|
2022-12-23 13:34:49 +01:00
|
|
|
AstClocking(FileLine* fl, const std::string& name, AstSenItem* sensesp,
|
2023-01-28 18:22:23 +01:00
|
|
|
AstClockingItem* itemsp, bool isDefault, bool isGlobal)
|
2022-12-23 13:34:49 +01:00
|
|
|
: ASTGEN_SUPER_Clocking(fl)
|
2025-06-29 02:32:19 +02:00
|
|
|
, m_name{name}
|
2023-01-28 18:22:23 +01:00
|
|
|
, m_isDefault{isDefault}
|
|
|
|
|
, m_isGlobal{isGlobal} {
|
2022-12-23 13:34:49 +01:00
|
|
|
this->sensesp(sensesp);
|
|
|
|
|
addItemsp(itemsp);
|
2022-09-15 14:10:39 +02:00
|
|
|
}
|
2022-10-04 12:03:41 +02:00
|
|
|
ASTGEN_MEMBERS_AstClocking;
|
2023-01-28 18:22:23 +01:00
|
|
|
void dump(std::ostream& str) const override;
|
2024-02-09 23:50:09 +01:00
|
|
|
void dumpJson(std::ostream& str) const override;
|
2023-03-18 01:24:15 +01:00
|
|
|
std::string name() const override VL_MT_STABLE { return m_name; }
|
2022-12-23 13:34:49 +01:00
|
|
|
bool isDefault() const { return m_isDefault; }
|
2023-01-28 18:22:23 +01:00
|
|
|
bool isGlobal() const { return m_isGlobal; }
|
2024-09-04 10:05:15 +02:00
|
|
|
AstVar* ensureEventp(bool childDType = false);
|
2022-12-23 13:34:49 +01:00
|
|
|
};
|
|
|
|
|
class AstClockingItem final : public AstNode {
|
|
|
|
|
// Parents: CLOCKING
|
|
|
|
|
// Children: EXPRs, ASSIGNs, VARs
|
|
|
|
|
// @astgen op1 := skewp : Optional[AstNodeExpr]
|
|
|
|
|
// @astgen op2 := exprp : Optional[AstNodeExpr]
|
|
|
|
|
// @astgen op3 := assignp : Optional[AstAssign]
|
|
|
|
|
// @astgen op4 := varp : Optional[AstVar]
|
2024-06-07 14:30:58 +02:00
|
|
|
// @astgen ptr := m_outputp : Optional[AstClockingItem]
|
2022-12-23 13:34:49 +01:00
|
|
|
VDirection m_direction;
|
|
|
|
|
|
|
|
|
|
public:
|
|
|
|
|
AstClockingItem(FileLine* fl, VDirection direction, AstNodeExpr* skewp, AstNode* clockingDeclp)
|
|
|
|
|
: ASTGEN_SUPER_ClockingItem(fl) {
|
|
|
|
|
m_direction = direction;
|
|
|
|
|
this->skewp(skewp);
|
2023-03-19 00:28:48 +01:00
|
|
|
if (AstAssign* const clkAssignp = VN_CAST(clockingDeclp, Assign)) {
|
|
|
|
|
this->assignp(clkAssignp);
|
2022-12-23 13:34:49 +01:00
|
|
|
} else {
|
|
|
|
|
exprp(VN_AS(clockingDeclp, NodeExpr));
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
ASTGEN_MEMBERS_AstClockingItem;
|
|
|
|
|
VDirection direction() const { return m_direction; }
|
2024-06-07 14:30:58 +02:00
|
|
|
AstClockingItem* outputp() const { return m_outputp; }
|
|
|
|
|
void outputp(AstClockingItem* outputp) { m_outputp = outputp; }
|
2024-10-01 03:34:34 +02:00
|
|
|
bool maybePointedTo() const override VL_MT_SAFE { return true; }
|
2022-09-15 14:10:39 +02:00
|
|
|
};
|
2025-06-29 02:32:19 +02:00
|
|
|
class AstConfig final : public AstNode {
|
|
|
|
|
// Parents: NETLIST
|
|
|
|
|
// @astgen op1 := designp : List[AstConfigCell]
|
|
|
|
|
// @astgen op2 := itemsp : List[AstNode]
|
|
|
|
|
std::string m_name; // Config block name
|
|
|
|
|
|
|
|
|
|
public:
|
|
|
|
|
AstConfig(FileLine* fl, const std::string& name, AstNode* itemsp)
|
|
|
|
|
: ASTGEN_SUPER_Config(fl)
|
|
|
|
|
, m_name{name} {
|
|
|
|
|
addItemsp(itemsp);
|
|
|
|
|
}
|
|
|
|
|
ASTGEN_MEMBERS_AstConfig;
|
|
|
|
|
std::string name() const override VL_MT_STABLE { return m_name; }
|
|
|
|
|
};
|
|
|
|
|
class AstConfigCell final : public AstNode {
|
|
|
|
|
// Parents: CONFIGRULE
|
|
|
|
|
std::string m_libname; // Cell library, or ""
|
|
|
|
|
std::string m_cellname; // Cell name within library
|
|
|
|
|
|
|
|
|
|
public:
|
|
|
|
|
AstConfigCell(FileLine* fl, const std::string& libname, const std::string& cellname)
|
|
|
|
|
: ASTGEN_SUPER_ConfigCell(fl)
|
|
|
|
|
, m_libname{libname}
|
|
|
|
|
, m_cellname{cellname} {}
|
|
|
|
|
ASTGEN_MEMBERS_AstConfigCell;
|
|
|
|
|
std::string name() const override VL_MT_STABLE { return m_libname + "." + m_cellname; }
|
|
|
|
|
std::string libname() const VL_MT_STABLE { return m_libname; }
|
|
|
|
|
std::string cellname() const VL_MT_STABLE { return m_cellname; }
|
|
|
|
|
};
|
|
|
|
|
class AstConfigRule final : public AstNode {
|
|
|
|
|
// Parents: CONFIG
|
|
|
|
|
// @astgen op1 := cellp : Optional[AstNode] // Cells to apply to, or nullptr=default
|
|
|
|
|
// @astgen op2 := usep : List[AstNode] // Use or design to apply
|
|
|
|
|
const bool m_isCell; // Declared as "cell" versus "instance"
|
|
|
|
|
|
|
|
|
|
public:
|
|
|
|
|
AstConfigRule(FileLine* fl, AstNode* cellp, AstNode* usep, bool isCell)
|
|
|
|
|
: ASTGEN_SUPER_ConfigRule(fl)
|
|
|
|
|
, m_isCell{isCell} {
|
|
|
|
|
this->cellp(cellp);
|
|
|
|
|
addUsep(usep);
|
|
|
|
|
}
|
|
|
|
|
ASTGEN_MEMBERS_AstConfigRule;
|
|
|
|
|
bool isCell() const VL_MT_STABLE { return m_isCell; }
|
|
|
|
|
void dump(std::ostream& str) const override;
|
|
|
|
|
void dumpJson(std::ostream& str) const override;
|
|
|
|
|
};
|
|
|
|
|
class AstConfigUse final : public AstNode {
|
|
|
|
|
// Parents: CONFIGRULE
|
|
|
|
|
// @astgen op1 := paramsp : List[AstPin]
|
|
|
|
|
std::string m_libname; // Use library, or ""
|
|
|
|
|
std::string m_cellname; // Use name within library
|
|
|
|
|
const bool m_isConfig; // ":config"; Config, not module/primitive name
|
|
|
|
|
|
|
|
|
|
public:
|
|
|
|
|
AstConfigUse(FileLine* fl, const std::string& libname, const std::string& cellname,
|
|
|
|
|
AstPin* paramsp, bool isConfig)
|
|
|
|
|
: ASTGEN_SUPER_ConfigUse(fl)
|
|
|
|
|
, m_libname{libname}
|
|
|
|
|
, m_cellname{cellname}
|
|
|
|
|
, m_isConfig{isConfig} {
|
|
|
|
|
addParamsp(paramsp);
|
|
|
|
|
}
|
|
|
|
|
ASTGEN_MEMBERS_AstConfigUse;
|
|
|
|
|
std::string name() const override VL_MT_STABLE { return m_libname + "." + m_cellname; }
|
|
|
|
|
std::string libname() const VL_MT_STABLE { return m_libname; }
|
|
|
|
|
std::string cellname() const VL_MT_STABLE { return m_cellname; }
|
|
|
|
|
bool isConfig() const VL_MT_STABLE { return m_isConfig; }
|
|
|
|
|
void dump(std::ostream& str) const override;
|
|
|
|
|
void dumpJson(std::ostream& str) const override;
|
|
|
|
|
};
|
2022-09-15 14:10:39 +02:00
|
|
|
class AstConstPool final : public AstNode {
|
|
|
|
|
// Container for const static data
|
2022-09-15 20:43:56 +02:00
|
|
|
// @astgen op1 := modulep : AstModule // m_modp below TODO: fix this mess
|
2023-12-01 01:58:16 +01:00
|
|
|
//
|
|
|
|
|
// @astgen ptr := m_modp : AstModule // The Module holding the Scope below ...
|
|
|
|
|
// @astgen ptr := m_scopep : AstScope // Scope holding the constant variables
|
2022-09-15 14:10:39 +02:00
|
|
|
std::unordered_multimap<uint32_t, AstVarScope*> m_tables; // Constant tables (unpacked arrays)
|
|
|
|
|
std::unordered_multimap<uint32_t, AstVarScope*> m_consts; // Constant tables (scalars)
|
|
|
|
|
|
2022-11-13 21:33:11 +01:00
|
|
|
AstVarScope* createNewEntry(const string& name, AstNodeExpr* initp);
|
2022-09-15 14:10:39 +02:00
|
|
|
|
|
|
|
|
public:
|
|
|
|
|
explicit AstConstPool(FileLine* fl);
|
2022-10-04 12:03:41 +02:00
|
|
|
ASTGEN_MEMBERS_AstConstPool;
|
2024-10-01 03:34:34 +02:00
|
|
|
bool maybePointedTo() const override VL_MT_SAFE { return true; }
|
2022-09-16 12:22:11 +02:00
|
|
|
void cloneRelink() override { V3ERROR_NA; }
|
2022-09-15 14:10:39 +02:00
|
|
|
AstModule* modp() const { return m_modp; }
|
|
|
|
|
|
|
|
|
|
// Find a table (unpacked array) within the constant pool which is initialized with the
|
|
|
|
|
// given value, or create one if one does not already exists. The returned VarScope *might*
|
|
|
|
|
// have a different dtype than the given initp->dtypep(), including a different element type,
|
|
|
|
|
// but it will always have the same size and element width. In contexts where this matters,
|
|
|
|
|
// the caller must handle the dtype difference as appropriate.
|
|
|
|
|
AstVarScope* findTable(AstInitArray* initp);
|
|
|
|
|
// Find a constant within the constant pool which is initialized with the given value, or
|
|
|
|
|
// create one if one does not already exists. If 'mergeDType' is true, then the returned
|
|
|
|
|
// VarScope *might* have a different type than the given initp->dtypep(). In contexts where
|
|
|
|
|
// this matters, the caller must handle the dtype difference as appropriate. If 'mergeDType' is
|
|
|
|
|
// false, the returned VarScope will have _->dtypep()->sameTree(initp->dtypep()) return true.
|
|
|
|
|
AstVarScope* findConst(AstConst* initp, bool mergeDType);
|
|
|
|
|
};
|
2023-11-12 02:20:37 +01:00
|
|
|
class AstConstraint final : public AstNode {
|
|
|
|
|
// Constraint
|
|
|
|
|
// @astgen op1 := itemsp : List[AstNode]
|
2024-12-12 14:16:19 +01:00
|
|
|
// @astgen op2 := classOrPackagep : Optional[AstNode]
|
2023-11-12 02:20:37 +01:00
|
|
|
string m_name; // Name of constraint
|
2024-12-12 14:16:19 +01:00
|
|
|
VBaseOverride m_baseOverride; // BaseOverride (inital/final/extends)
|
|
|
|
|
bool m_isExternDef = false; // Extern prototype definition
|
|
|
|
|
bool m_isExternExplicit = false; // Explicit prototype declaration (has extern)
|
|
|
|
|
bool m_isExternProto = false; // Prototype declaration (implicit or explicit)
|
2024-11-09 18:05:26 +01:00
|
|
|
bool m_isKwdPure = false; // Pure constraint
|
|
|
|
|
bool m_isStatic = false; // Static constraint
|
2023-11-12 02:20:37 +01:00
|
|
|
public:
|
|
|
|
|
AstConstraint(FileLine* fl, const string& name, AstNode* itemsp)
|
|
|
|
|
: ASTGEN_SUPER_Constraint(fl)
|
2025-07-04 00:59:32 +02:00
|
|
|
, m_name{name} {
|
2025-03-08 23:48:20 +01:00
|
|
|
addItemsp(itemsp);
|
2023-11-12 02:20:37 +01:00
|
|
|
}
|
|
|
|
|
ASTGEN_MEMBERS_AstConstraint;
|
2024-11-09 18:05:26 +01:00
|
|
|
void dump(std::ostream& str) const override;
|
|
|
|
|
void dumpJson(std::ostream& str) const override;
|
2023-11-12 02:20:37 +01:00
|
|
|
string name() const override VL_MT_STABLE { return m_name; } // * = Scope name
|
|
|
|
|
bool isGateOptimizable() const override { return false; }
|
|
|
|
|
bool isPredictOptimizable() const override { return false; }
|
2024-10-01 03:34:34 +02:00
|
|
|
bool maybePointedTo() const override VL_MT_SAFE { return true; }
|
2024-11-28 20:37:11 +01:00
|
|
|
bool sameNode(const AstNode* /*samep*/) const override { return true; }
|
2024-12-12 14:16:19 +01:00
|
|
|
void baseOverride(const VBaseOverride& flag) { m_baseOverride = flag; }
|
|
|
|
|
VBaseOverride baseOverride() const { return m_baseOverride; }
|
|
|
|
|
bool isExternDef() const { return m_isExternDef; }
|
|
|
|
|
void isExternDef(bool flag) { m_isExternDef = flag; }
|
|
|
|
|
void isExternExplicit(bool flag) { m_isExternExplicit = flag; }
|
|
|
|
|
bool isExternExplicit() const { return m_isExternExplicit; }
|
|
|
|
|
void isExternProto(bool flag) { m_isExternProto = flag; }
|
|
|
|
|
bool isExternProto() const { return m_isExternProto; }
|
2024-11-09 18:05:26 +01:00
|
|
|
void isKwdPure(bool flag) { m_isKwdPure = flag; }
|
|
|
|
|
bool isKwdPure() const { return m_isKwdPure; }
|
2023-11-12 02:20:37 +01:00
|
|
|
void isStatic(bool flag) { m_isStatic = flag; }
|
|
|
|
|
bool isStatic() const { return m_isStatic; }
|
|
|
|
|
};
|
|
|
|
|
class AstConstraintBefore final : public AstNode {
|
|
|
|
|
// Constraint solve before item
|
|
|
|
|
// @astgen op1 := lhssp : List[AstNodeExpr]
|
|
|
|
|
// @astgen op2 := rhssp : List[AstNodeExpr]
|
|
|
|
|
public:
|
|
|
|
|
AstConstraintBefore(FileLine* fl, AstNodeExpr* lhssp, AstNodeExpr* rhssp)
|
|
|
|
|
: ASTGEN_SUPER_ConstraintBefore(fl) {
|
2025-03-08 23:48:20 +01:00
|
|
|
addLhssp(lhssp);
|
|
|
|
|
addRhssp(rhssp);
|
2023-11-12 02:20:37 +01:00
|
|
|
}
|
|
|
|
|
ASTGEN_MEMBERS_AstConstraintBefore;
|
|
|
|
|
bool isGateOptimizable() const override { return false; }
|
|
|
|
|
bool isPredictOptimizable() const override { return false; }
|
2024-11-28 20:37:11 +01:00
|
|
|
bool sameNode(const AstNode* /*samep*/) const override { return true; }
|
2023-11-12 02:20:37 +01:00
|
|
|
};
|
2022-09-15 14:10:39 +02:00
|
|
|
class AstDefParam final : public AstNode {
|
|
|
|
|
// A defparam assignment
|
|
|
|
|
// Parents: MODULE
|
2022-11-13 21:33:11 +01:00
|
|
|
// @astgen op1 := rhsp : AstNodeExpr
|
2022-09-15 14:10:39 +02:00
|
|
|
string m_name; // Name of variable getting set
|
|
|
|
|
string m_path; // Dotted cellname to set parameter of
|
|
|
|
|
public:
|
2022-11-13 21:33:11 +01:00
|
|
|
AstDefParam(FileLine* fl, const string& path, const string& name, AstNodeExpr* rhsp)
|
2022-09-15 14:54:04 +02:00
|
|
|
: ASTGEN_SUPER_DefParam(fl)
|
|
|
|
|
, m_name{name}
|
|
|
|
|
, m_path{path} {
|
2022-09-15 20:43:56 +02:00
|
|
|
this->rhsp(rhsp);
|
2022-09-15 14:10:39 +02:00
|
|
|
}
|
2023-03-18 01:24:15 +01:00
|
|
|
string name() const override VL_MT_STABLE { return m_name; } // * = Scope name
|
2022-10-04 12:03:41 +02:00
|
|
|
ASTGEN_MEMBERS_AstDefParam;
|
2024-11-28 20:37:11 +01:00
|
|
|
bool sameNode(const AstNode*) const override { return true; }
|
2022-09-15 14:10:39 +02:00
|
|
|
string path() const { return m_path; }
|
|
|
|
|
};
|
2024-11-27 04:27:32 +01:00
|
|
|
class AstDefaultDisable final : public AstNode {
|
|
|
|
|
// @astgen op1 := condp : AstNodeExpr
|
|
|
|
|
|
|
|
|
|
public:
|
|
|
|
|
AstDefaultDisable(FileLine* fl, AstNodeExpr* condp)
|
|
|
|
|
: ASTGEN_SUPER_DefaultDisable(fl) {
|
|
|
|
|
this->condp(condp);
|
|
|
|
|
}
|
|
|
|
|
ASTGEN_MEMBERS_AstDefaultDisable;
|
|
|
|
|
};
|
2022-09-15 14:10:39 +02:00
|
|
|
class AstDpiExport final : public AstNode {
|
|
|
|
|
// We could put an AstNodeFTaskRef instead of the verilog function name,
|
|
|
|
|
// however we're not *calling* it, so that seems somehow wrong.
|
|
|
|
|
// (Probably AstNodeFTaskRef should be renamed AstNodeFTaskCall and have-a AstNodeFTaskRef)
|
|
|
|
|
string m_name; // Name of function
|
|
|
|
|
string m_cname; // Name of function on c side
|
|
|
|
|
public:
|
|
|
|
|
AstDpiExport(FileLine* fl, const string& vname, const string& cname)
|
|
|
|
|
: ASTGEN_SUPER_DpiExport(fl)
|
|
|
|
|
, m_name{vname}
|
|
|
|
|
, m_cname{cname} {}
|
2022-10-04 12:03:41 +02:00
|
|
|
ASTGEN_MEMBERS_AstDpiExport;
|
2023-03-18 01:24:15 +01:00
|
|
|
string name() const override VL_MT_STABLE { return m_name; }
|
2022-09-16 12:22:11 +02:00
|
|
|
void name(const string& name) override { m_name = name; }
|
2022-09-15 14:10:39 +02:00
|
|
|
string cname() const { return m_cname; }
|
|
|
|
|
void cname(const string& cname) { m_cname = cname; }
|
|
|
|
|
};
|
|
|
|
|
class AstElabDisplay final : public AstNode {
|
|
|
|
|
// Parents: stmtlist
|
2022-09-15 20:43:56 +02:00
|
|
|
// @astgen op1 := fmtp : List[AstSFormatF]
|
2022-09-15 14:10:39 +02:00
|
|
|
VDisplayType m_displayType;
|
|
|
|
|
|
|
|
|
|
public:
|
2022-11-13 21:33:11 +01:00
|
|
|
inline AstElabDisplay(FileLine* fl, VDisplayType dispType, AstNodeExpr* exprsp);
|
2022-10-04 12:03:41 +02:00
|
|
|
ASTGEN_MEMBERS_AstElabDisplay;
|
2022-09-16 12:22:11 +02:00
|
|
|
const char* broken() const override {
|
2022-09-15 14:10:39 +02:00
|
|
|
BROKEN_RTN(!fmtp());
|
|
|
|
|
return nullptr;
|
|
|
|
|
}
|
2024-07-14 17:39:45 +02:00
|
|
|
string verilogKwd() const override { return "$"s + string{displayType().ascii()}; }
|
2022-09-16 12:22:11 +02:00
|
|
|
bool isGateOptimizable() const override { return false; }
|
|
|
|
|
bool isPredictOptimizable() const override { return false; }
|
2023-09-18 15:21:30 +02:00
|
|
|
bool isPure() override { return false; } // SPECIAL: $display has 'visual' ordering
|
|
|
|
|
bool isOutputter() override { return true; } // SPECIAL: $display makes output
|
2022-09-16 12:22:11 +02:00
|
|
|
bool isUnlikely() const override { return true; }
|
2024-11-28 20:37:11 +01:00
|
|
|
bool sameNode(const AstNode* samep) const override {
|
2023-10-16 11:17:52 +02:00
|
|
|
return displayType() == VN_DBG_AS(samep, ElabDisplay)->displayType();
|
2022-09-15 14:10:39 +02:00
|
|
|
}
|
2022-09-16 12:22:11 +02:00
|
|
|
int instrCount() const override { return INSTR_COUNT_PLI; }
|
2022-09-15 14:10:39 +02:00
|
|
|
VDisplayType displayType() const { return m_displayType; }
|
|
|
|
|
void displayType(VDisplayType type) { m_displayType = type; }
|
|
|
|
|
};
|
|
|
|
|
class AstEmpty final : public AstNode {
|
|
|
|
|
// Represents something missing, e.g. a missing argument in FOREACH
|
|
|
|
|
public:
|
|
|
|
|
explicit AstEmpty(FileLine* fl)
|
|
|
|
|
: ASTGEN_SUPER_Empty(fl) {}
|
2022-10-04 12:03:41 +02:00
|
|
|
ASTGEN_MEMBERS_AstEmpty;
|
2024-11-28 20:37:11 +01:00
|
|
|
bool sameNode(const AstNode* /*samep*/) const override { return true; }
|
2022-09-15 14:10:39 +02:00
|
|
|
};
|
|
|
|
|
class AstExecGraph final : public AstNode {
|
|
|
|
|
// For parallel execution, this node contains a dependency graph. Each
|
|
|
|
|
// vertex in the graph is an ExecMTask, which contains a body for the
|
|
|
|
|
// mtask (an AstMTaskBody), which contains sequentially executed statements.
|
|
|
|
|
//
|
|
|
|
|
// The AstMTaskBody nodes are also children of this node, so we can visit
|
|
|
|
|
// them without traversing the graph.
|
2022-09-15 20:43:56 +02:00
|
|
|
//
|
|
|
|
|
// @astgen op1 := mTaskBodiesp : List[AstMTaskBody]
|
|
|
|
|
// In later phases, the statements that start the parallel execution
|
|
|
|
|
// @astgen op2 := stmtsp : List[AstNode]
|
2022-09-15 14:10:39 +02:00
|
|
|
V3Graph* const m_depGraphp; // contains ExecMTask vertices
|
|
|
|
|
const string m_name; // Name of this AstExecGraph (for uniqueness at code generation)
|
|
|
|
|
|
|
|
|
|
public:
|
2023-09-25 04:12:23 +02:00
|
|
|
explicit AstExecGraph(FileLine* fl, const string& name) VL_MT_DISABLED;
|
2022-09-15 20:43:56 +02:00
|
|
|
~AstExecGraph() override;
|
2024-03-16 15:02:17 +01:00
|
|
|
ASTGEN_MEMBERS_AstExecGraph;
|
|
|
|
|
void cloneRelink() override { V3ERROR_NA; }
|
2022-09-16 12:22:11 +02:00
|
|
|
const char* broken() const override {
|
2022-09-15 14:10:39 +02:00
|
|
|
BROKEN_RTN(!m_depGraphp);
|
|
|
|
|
return nullptr;
|
|
|
|
|
}
|
2023-03-18 01:24:15 +01:00
|
|
|
string name() const override VL_MT_STABLE { return m_name; }
|
2022-09-15 14:10:39 +02:00
|
|
|
V3Graph* depGraphp() { return m_depGraphp; }
|
|
|
|
|
const V3Graph* depGraphp() const { return m_depGraphp; }
|
|
|
|
|
};
|
|
|
|
|
class AstImplicit final : public AstNode {
|
|
|
|
|
// Create implicit wires and do nothing else, for gates that are ignored
|
|
|
|
|
// Parents: MODULE
|
2022-09-15 20:43:56 +02:00
|
|
|
// @astgen op1 := exprsp : List[AstNode]
|
2022-09-15 14:10:39 +02:00
|
|
|
public:
|
|
|
|
|
AstImplicit(FileLine* fl, AstNode* exprsp)
|
|
|
|
|
: ASTGEN_SUPER_Implicit(fl) {
|
2025-03-08 23:48:20 +01:00
|
|
|
addExprsp(exprsp);
|
2022-09-15 14:10:39 +02:00
|
|
|
}
|
2022-10-04 12:03:41 +02:00
|
|
|
ASTGEN_MEMBERS_AstImplicit;
|
2022-09-15 14:10:39 +02:00
|
|
|
};
|
|
|
|
|
class AstInitItem final : public AstNode {
|
|
|
|
|
// Container for a item in an init array
|
|
|
|
|
// This container is present so that the value underneath may get replaced with a new nodep
|
|
|
|
|
// and the upper AstInitArray's map will remain correct (pointing to this InitItem)
|
2022-11-13 21:33:11 +01:00
|
|
|
// @astgen op1 := valuep : AstNodeExpr
|
2022-09-15 14:10:39 +02:00
|
|
|
public:
|
|
|
|
|
// Parents: INITARRAY
|
2022-11-13 21:33:11 +01:00
|
|
|
AstInitItem(FileLine* fl, AstNodeExpr* valuep)
|
2022-09-15 14:10:39 +02:00
|
|
|
: ASTGEN_SUPER_InitItem(fl) {
|
2022-09-15 20:43:56 +02:00
|
|
|
this->valuep(valuep);
|
2022-09-15 14:10:39 +02:00
|
|
|
}
|
2022-10-04 12:03:41 +02:00
|
|
|
ASTGEN_MEMBERS_AstInitItem;
|
2024-10-01 03:34:34 +02:00
|
|
|
bool maybePointedTo() const override VL_MT_SAFE { return true; }
|
|
|
|
|
bool hasDType() const override VL_MT_SAFE { return false; } // See valuep()'s dtype instead
|
2022-09-15 14:10:39 +02:00
|
|
|
};
|
|
|
|
|
class AstIntfRef final : public AstNode {
|
|
|
|
|
// An interface reference
|
|
|
|
|
string m_name; // Name of the reference
|
|
|
|
|
public:
|
|
|
|
|
AstIntfRef(FileLine* fl, const string& name)
|
|
|
|
|
: ASTGEN_SUPER_IntfRef(fl)
|
|
|
|
|
, m_name{name} {}
|
2023-03-18 01:24:15 +01:00
|
|
|
string name() const override VL_MT_STABLE { return m_name; }
|
2022-10-04 12:03:41 +02:00
|
|
|
ASTGEN_MEMBERS_AstIntfRef;
|
2022-09-15 14:10:39 +02:00
|
|
|
};
|
|
|
|
|
class AstMTaskBody final : public AstNode {
|
|
|
|
|
// Hold statements for each MTask
|
2022-09-15 20:43:56 +02:00
|
|
|
// @astgen op1 := stmtsp : List[AstNode]
|
2022-09-15 14:10:39 +02:00
|
|
|
ExecMTask* m_execMTaskp = nullptr;
|
|
|
|
|
|
|
|
|
|
public:
|
|
|
|
|
explicit AstMTaskBody(FileLine* fl)
|
|
|
|
|
: ASTGEN_SUPER_MTaskBody(fl) {}
|
2022-10-04 12:03:41 +02:00
|
|
|
ASTGEN_MEMBERS_AstMTaskBody;
|
2024-03-16 15:02:17 +01:00
|
|
|
void cloneRelink() override { V3ERROR_NA; }
|
2022-09-16 12:22:11 +02:00
|
|
|
const char* broken() const override {
|
2022-09-15 14:10:39 +02:00
|
|
|
BROKEN_RTN(!m_execMTaskp);
|
|
|
|
|
return nullptr;
|
|
|
|
|
}
|
|
|
|
|
void addStmtsFirstp(AstNode* nodep) {
|
|
|
|
|
if (stmtsp()) {
|
|
|
|
|
stmtsp()->addHereThisAsNext(nodep);
|
|
|
|
|
} else {
|
|
|
|
|
addStmtsp(nodep);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
ExecMTask* execMTaskp() const { return m_execMTaskp; }
|
|
|
|
|
void execMTaskp(ExecMTask* execMTaskp) { m_execMTaskp = execMTaskp; }
|
2022-09-16 12:22:11 +02:00
|
|
|
void dump(std::ostream& str = std::cout) const override;
|
2024-02-09 23:50:09 +01:00
|
|
|
void dumpJson(std::ostream& str = std::cout) const override;
|
2022-09-15 14:10:39 +02:00
|
|
|
};
|
|
|
|
|
class AstModport final : public AstNode {
|
|
|
|
|
// A modport in an interface
|
2022-09-15 20:43:56 +02:00
|
|
|
// @astgen op1 := varsp : List[AstNode]
|
2022-09-15 14:10:39 +02:00
|
|
|
string m_name; // Name of the modport
|
|
|
|
|
public:
|
|
|
|
|
AstModport(FileLine* fl, const string& name, AstNode* varsp)
|
|
|
|
|
: ASTGEN_SUPER_Modport(fl)
|
|
|
|
|
, m_name{name} {
|
2025-03-08 23:48:20 +01:00
|
|
|
addVarsp(varsp);
|
2022-09-15 14:10:39 +02:00
|
|
|
}
|
2025-02-21 22:49:14 +01:00
|
|
|
string verilogKwd() const override { return "modport"; }
|
2023-03-18 01:24:15 +01:00
|
|
|
string name() const override VL_MT_STABLE { return m_name; }
|
2024-10-01 03:34:34 +02:00
|
|
|
bool maybePointedTo() const override VL_MT_SAFE { return true; }
|
2022-10-04 12:03:41 +02:00
|
|
|
ASTGEN_MEMBERS_AstModport;
|
2022-09-15 14:10:39 +02:00
|
|
|
};
|
|
|
|
|
class AstModportFTaskRef final : public AstNode {
|
|
|
|
|
// An import/export referenced under a modport
|
|
|
|
|
// The storage for the function itself is inside the
|
|
|
|
|
// interface/instantiator, thus this is a reference
|
|
|
|
|
// PARENT: AstModport
|
2023-12-01 01:58:16 +01:00
|
|
|
//
|
|
|
|
|
// @astgen ptr := m_ftaskp : Optional[AstNodeFTask] // Link to the function
|
2022-09-15 14:10:39 +02:00
|
|
|
string m_name; // Name of the variable referenced
|
2022-11-13 15:26:46 +01:00
|
|
|
bool m_export; // Type of the function (import/export)
|
2022-09-15 14:10:39 +02:00
|
|
|
public:
|
|
|
|
|
AstModportFTaskRef(FileLine* fl, const string& name, bool isExport)
|
|
|
|
|
: ASTGEN_SUPER_ModportFTaskRef(fl)
|
|
|
|
|
, m_name{name}
|
|
|
|
|
, m_export{isExport} {}
|
2022-10-04 12:03:41 +02:00
|
|
|
ASTGEN_MEMBERS_AstModportFTaskRef;
|
2022-09-16 12:22:11 +02:00
|
|
|
void dump(std::ostream& str) const override;
|
2024-02-09 23:50:09 +01:00
|
|
|
void dumpJson(std::ostream& str) const override;
|
2023-03-18 01:24:15 +01:00
|
|
|
string name() const override VL_MT_STABLE { return m_name; }
|
2022-09-15 14:10:39 +02:00
|
|
|
bool isImport() const { return !m_export; }
|
|
|
|
|
bool isExport() const { return m_export; }
|
|
|
|
|
AstNodeFTask* ftaskp() const { return m_ftaskp; } // [After Link] Pointer to variable
|
|
|
|
|
void ftaskp(AstNodeFTask* ftaskp) { m_ftaskp = ftaskp; }
|
|
|
|
|
};
|
|
|
|
|
class AstModportVarRef final : public AstNode {
|
|
|
|
|
// A input/output/etc variable referenced under a modport
|
|
|
|
|
// The storage for the variable itself is inside the interface, thus this is a reference
|
|
|
|
|
// PARENT: AstModport
|
2023-12-01 01:58:16 +01:00
|
|
|
//
|
|
|
|
|
// @astgen ptr := m_varp : Optional[AstVar] // Link to the actual Var
|
2022-09-15 14:10:39 +02:00
|
|
|
string m_name; // Name of the variable referenced
|
2022-11-13 15:26:46 +01:00
|
|
|
VDirection m_direction; // Direction of the variable (in/out)
|
2022-09-15 14:10:39 +02:00
|
|
|
public:
|
|
|
|
|
AstModportVarRef(FileLine* fl, const string& name, VDirection::en direction)
|
|
|
|
|
: ASTGEN_SUPER_ModportVarRef(fl)
|
|
|
|
|
, m_name{name}
|
|
|
|
|
, m_direction{direction} {}
|
2022-10-04 12:03:41 +02:00
|
|
|
ASTGEN_MEMBERS_AstModportVarRef;
|
2022-09-16 12:22:11 +02:00
|
|
|
void dump(std::ostream& str) const override;
|
2024-02-09 23:50:09 +01:00
|
|
|
void dumpJson(std::ostream& str) const override;
|
2023-03-18 01:24:15 +01:00
|
|
|
string name() const override VL_MT_STABLE { return m_name; }
|
2022-09-15 14:10:39 +02:00
|
|
|
void direction(const VDirection& flag) { m_direction = flag; }
|
|
|
|
|
VDirection direction() const { return m_direction; }
|
2024-10-01 03:34:34 +02:00
|
|
|
AstVar* varp() const VL_MT_STABLE { return m_varp; } // [After Link] Pointer to variable
|
2022-09-15 14:10:39 +02:00
|
|
|
void varp(AstVar* varp) { m_varp = varp; }
|
|
|
|
|
};
|
|
|
|
|
class AstNetlist final : public AstNode {
|
|
|
|
|
// All modules are under this single top node.
|
|
|
|
|
// Parents: none
|
|
|
|
|
// Children: MODULEs & CFILEs
|
2022-09-15 20:43:56 +02:00
|
|
|
// @astgen op1 := modulesp : List[AstNodeModule]
|
|
|
|
|
// @astgen op2 := filesp : List[AstNodeFile]
|
|
|
|
|
// @astgen op3 := miscsp : List[AstNode]
|
2023-12-01 01:58:16 +01:00
|
|
|
//
|
|
|
|
|
// @astgen ptr := m_typeTablep : AstTypeTable // Reference to type table, for faster lookup
|
|
|
|
|
// @astgen ptr := m_constPoolp : AstConstPool // Reference to constant pool, for faster lookup
|
|
|
|
|
// @astgen ptr := m_dollarUnitPkgp : Optional[AstPackage] // $unit
|
|
|
|
|
// @astgen ptr := m_stdPackagep : Optional[AstPackage] // SystemVerilog std package
|
|
|
|
|
// @astgen ptr := m_evalp : Optional[AstCFunc] // The '_eval' function
|
|
|
|
|
// @astgen ptr := m_evalNbap : Optional[AstCFunc] // The '_eval__nba' function
|
|
|
|
|
// @astgen ptr := m_dpiExportTriggerp : Optional[AstVarScope] // DPI export trigger variable
|
|
|
|
|
// @astgen ptr := m_delaySchedulerp : Optional[AstVar] // Delay scheduler variable
|
|
|
|
|
// @astgen ptr := m_nbaEventp : Optional[AstVarScope] // NBA event variable
|
|
|
|
|
// @astgen ptr := m_nbaEventTriggerp : Optional[AstVarScope] // NBA event trigger
|
|
|
|
|
// @astgen ptr := m_topScopep : Optional[AstTopScope] // Singleton AstTopScope
|
2022-09-15 14:10:39 +02:00
|
|
|
VTimescale m_timeunit; // Global time unit
|
|
|
|
|
VTimescale m_timeprecision; // Global time precision
|
|
|
|
|
bool m_timescaleSpecified = false; // Input HDL specified timescale
|
|
|
|
|
public:
|
|
|
|
|
AstNetlist();
|
2022-10-04 12:03:41 +02:00
|
|
|
ASTGEN_MEMBERS_AstNetlist;
|
2025-07-24 07:47:16 +02:00
|
|
|
void deleteContents();
|
2022-09-16 12:22:11 +02:00
|
|
|
void cloneRelink() override { V3ERROR_NA; }
|
2023-03-18 01:24:15 +01:00
|
|
|
string name() const override VL_MT_STABLE { return "$root"; }
|
2022-09-16 12:22:11 +02:00
|
|
|
void dump(std::ostream& str) const override;
|
2024-02-09 23:50:09 +01:00
|
|
|
void dumpJson(std::ostream& str) const override;
|
2023-04-20 13:02:31 +02:00
|
|
|
AstNodeModule* topModulep() const VL_MT_STABLE { // Top module in hierarchy
|
2022-09-15 14:10:39 +02:00
|
|
|
return modulesp(); // First one in the list, for now
|
|
|
|
|
}
|
|
|
|
|
AstTypeTable* typeTablep() { return m_typeTablep; }
|
|
|
|
|
AstConstPool* constPoolp() { return m_constPoolp; }
|
|
|
|
|
AstPackage* dollarUnitPkgp() const { return m_dollarUnitPkgp; }
|
|
|
|
|
AstPackage* dollarUnitPkgAddp();
|
|
|
|
|
AstCFunc* evalp() const { return m_evalp; }
|
2022-09-15 14:17:00 +02:00
|
|
|
void evalp(AstCFunc* funcp) { m_evalp = funcp; }
|
|
|
|
|
AstCFunc* evalNbap() const { return m_evalNbap; }
|
|
|
|
|
void evalNbap(AstCFunc* funcp) { m_evalNbap = funcp; }
|
2022-09-15 14:10:39 +02:00
|
|
|
AstVarScope* dpiExportTriggerp() const { return m_dpiExportTriggerp; }
|
|
|
|
|
void dpiExportTriggerp(AstVarScope* varScopep) { m_dpiExportTriggerp = varScopep; }
|
2022-09-15 14:17:00 +02:00
|
|
|
AstVar* delaySchedulerp() const { return m_delaySchedulerp; }
|
|
|
|
|
void delaySchedulerp(AstVar* const varScopep) { m_delaySchedulerp = varScopep; }
|
2023-10-21 02:01:45 +02:00
|
|
|
AstVarScope* nbaEventp() const { return m_nbaEventp; }
|
|
|
|
|
void nbaEventp(AstVarScope* const varScopep) { m_nbaEventp = varScopep; }
|
|
|
|
|
AstVarScope* nbaEventTriggerp() const { return m_nbaEventTriggerp; }
|
|
|
|
|
void nbaEventTriggerp(AstVarScope* const varScopep) { m_nbaEventTriggerp = varScopep; }
|
2022-11-28 16:53:55 +01:00
|
|
|
void stdPackagep(AstPackage* const packagep) { m_stdPackagep = packagep; }
|
|
|
|
|
AstPackage* stdPackagep() const { return m_stdPackagep; }
|
2022-09-15 14:10:39 +02:00
|
|
|
AstTopScope* topScopep() const { return m_topScopep; }
|
|
|
|
|
void createTopScope(AstScope* scopep);
|
|
|
|
|
VTimescale timeunit() const { return m_timeunit; }
|
|
|
|
|
void timeunit(const VTimescale& value) { m_timeunit = value; }
|
|
|
|
|
VTimescale timeprecision() const { return m_timeprecision; }
|
|
|
|
|
void timeInit() {
|
|
|
|
|
m_timeunit = v3Global.opt.timeDefaultUnit();
|
|
|
|
|
m_timeprecision = v3Global.opt.timeDefaultPrec();
|
|
|
|
|
}
|
|
|
|
|
void timeprecisionMerge(FileLine*, const VTimescale& value);
|
|
|
|
|
void timescaleSpecified(bool specified) { m_timescaleSpecified = specified; }
|
|
|
|
|
bool timescaleSpecified() const { return m_timescaleSpecified; }
|
|
|
|
|
};
|
|
|
|
|
class AstPackageExport final : public AstNode {
|
|
|
|
|
// A package export declaration
|
2023-12-01 01:58:16 +01:00
|
|
|
//
|
|
|
|
|
// @astgen ptr := m_packagep : Optional[AstPackage] // Package hierarchy
|
2024-09-29 02:55:22 +02:00
|
|
|
string m_name; // What imported e.g. "*"
|
|
|
|
|
string m_pkgName; // Module the cell instances
|
2023-12-01 01:58:16 +01:00
|
|
|
|
2022-09-15 14:10:39 +02:00
|
|
|
public:
|
|
|
|
|
AstPackageExport(FileLine* fl, AstPackage* packagep, const string& name)
|
|
|
|
|
: ASTGEN_SUPER_PackageExport(fl)
|
|
|
|
|
, m_name{name}
|
2024-09-29 02:55:22 +02:00
|
|
|
, m_packagep{packagep} {
|
|
|
|
|
pkgNameFrom();
|
|
|
|
|
}
|
|
|
|
|
AstPackageExport(FileLine* fl, const string& pkgName, const string& name)
|
|
|
|
|
: ASTGEN_SUPER_PackageExport(fl)
|
|
|
|
|
, m_name{name}
|
|
|
|
|
, m_pkgName{pkgName}
|
|
|
|
|
, m_packagep{nullptr} {}
|
2022-10-04 12:03:41 +02:00
|
|
|
ASTGEN_MEMBERS_AstPackageExport;
|
2022-09-16 12:22:11 +02:00
|
|
|
void dump(std::ostream& str) const override;
|
2024-02-09 23:50:09 +01:00
|
|
|
void dumpJson(std::ostream& str) const override;
|
2023-03-18 01:24:15 +01:00
|
|
|
string name() const override VL_MT_STABLE { return m_name; }
|
2024-09-29 02:55:22 +02:00
|
|
|
string pkgName() const VL_MT_STABLE { return m_pkgName; }
|
|
|
|
|
string prettyPkgNameQ() const { return "'" + prettyName(pkgName()) + "'"; }
|
2022-09-15 14:10:39 +02:00
|
|
|
AstPackage* packagep() const { return m_packagep; }
|
|
|
|
|
void packagep(AstPackage* nodep) { m_packagep = nodep; }
|
2024-09-29 02:55:22 +02:00
|
|
|
|
|
|
|
|
private:
|
|
|
|
|
void pkgNameFrom();
|
2022-09-15 14:10:39 +02:00
|
|
|
};
|
|
|
|
|
class AstPackageExportStarStar final : public AstNode {
|
|
|
|
|
// A package export *::* declaration
|
|
|
|
|
public:
|
|
|
|
|
// cppcheck-suppress noExplicitConstructor
|
|
|
|
|
AstPackageExportStarStar(FileLine* fl)
|
|
|
|
|
: ASTGEN_SUPER_PackageExportStarStar(fl) {}
|
2022-10-04 12:03:41 +02:00
|
|
|
ASTGEN_MEMBERS_AstPackageExportStarStar;
|
2022-09-15 14:10:39 +02:00
|
|
|
};
|
|
|
|
|
class AstPackageImport final : public AstNode {
|
|
|
|
|
// A package import declaration
|
2023-12-01 01:58:16 +01:00
|
|
|
//
|
|
|
|
|
// @astgen ptr := m_packagep : Optional[AstPackage] // Package hierarchy
|
2024-09-29 02:55:22 +02:00
|
|
|
string m_name; // What imported e.g. "*"
|
|
|
|
|
string m_pkgName; // Module the cell instances
|
2023-12-01 01:58:16 +01:00
|
|
|
|
2022-09-15 14:10:39 +02:00
|
|
|
public:
|
|
|
|
|
AstPackageImport(FileLine* fl, AstPackage* packagep, const string& name)
|
|
|
|
|
: ASTGEN_SUPER_PackageImport(fl)
|
|
|
|
|
, m_name{name}
|
2024-09-29 02:55:22 +02:00
|
|
|
, m_packagep{packagep} {
|
|
|
|
|
pkgNameFrom();
|
|
|
|
|
}
|
|
|
|
|
AstPackageImport(FileLine* fl, const string& pkgName, const string& name)
|
|
|
|
|
: ASTGEN_SUPER_PackageImport(fl)
|
|
|
|
|
, m_name{name}
|
|
|
|
|
, m_pkgName{pkgName}
|
|
|
|
|
, m_packagep{nullptr} {}
|
2022-10-04 12:03:41 +02:00
|
|
|
ASTGEN_MEMBERS_AstPackageImport;
|
2022-09-16 12:22:11 +02:00
|
|
|
void dump(std::ostream& str) const override;
|
2024-02-09 23:50:09 +01:00
|
|
|
void dumpJson(std::ostream& str) const override;
|
2023-03-18 01:24:15 +01:00
|
|
|
string name() const override VL_MT_STABLE { return m_name; }
|
2024-09-29 02:55:22 +02:00
|
|
|
string pkgName() const VL_MT_STABLE { return m_pkgName; }
|
|
|
|
|
string prettyPkgNameQ() const { return "'" + prettyName(pkgName()) + "'"; }
|
2022-09-15 14:10:39 +02:00
|
|
|
AstPackage* packagep() const { return m_packagep; }
|
|
|
|
|
void packagep(AstPackage* nodep) { m_packagep = nodep; }
|
2024-09-29 02:55:22 +02:00
|
|
|
|
|
|
|
|
private:
|
|
|
|
|
void pkgNameFrom();
|
2022-09-15 14:10:39 +02:00
|
|
|
};
|
|
|
|
|
class AstPin final : public AstNode {
|
2022-12-03 00:46:38 +01:00
|
|
|
// A port or parameter assignment on an instantiation
|
2024-10-01 04:25:28 +02:00
|
|
|
// @astgen op1 := exprp : Optional[AstNode<AstNodeExpr|AstNodeDType>] // nullptr=unconnected
|
2023-12-01 01:58:16 +01:00
|
|
|
//
|
|
|
|
|
// @astgen ptr := m_modVarp : Optional[AstVar] // Input/output connects to on submodule
|
|
|
|
|
// @astgen ptr := m_modPTypep : Optional[AstParamTypeDType] // Param type connects to on sub
|
2022-09-15 14:10:39 +02:00
|
|
|
int m_pinNum; // Pin number
|
|
|
|
|
string m_name; // Pin name, or "" for number based interconnect
|
|
|
|
|
bool m_param = false; // Pin connects to parameter
|
2023-03-02 03:19:21 +01:00
|
|
|
bool m_svDotName = false; // Pin is SystemVerilog .name'ed
|
|
|
|
|
bool m_svImplicit = false; // Pin is SystemVerilog .name'ed, allow implicit
|
2022-09-15 14:10:39 +02:00
|
|
|
public:
|
|
|
|
|
AstPin(FileLine* fl, int pinNum, const string& name, AstNode* exprp)
|
|
|
|
|
: ASTGEN_SUPER_Pin(fl)
|
|
|
|
|
, m_pinNum{pinNum}
|
|
|
|
|
, m_name{name} {
|
2022-09-15 20:43:56 +02:00
|
|
|
this->exprp(exprp);
|
2022-09-15 14:10:39 +02:00
|
|
|
}
|
|
|
|
|
inline AstPin(FileLine* fl, int pinNum, AstVarRef* varname, AstNode* exprp);
|
2022-10-04 12:03:41 +02:00
|
|
|
ASTGEN_MEMBERS_AstPin;
|
2023-12-01 01:58:16 +01:00
|
|
|
void cloneRelink() override {} // TODO V3Param shouldn't require avoiding cloneRelinkGen
|
2022-09-16 12:22:11 +02:00
|
|
|
void dump(std::ostream& str) const override;
|
2024-02-09 23:50:09 +01:00
|
|
|
void dumpJson(std::ostream& str) const override;
|
2023-03-18 01:24:15 +01:00
|
|
|
string name() const override VL_MT_STABLE { return m_name; } // * = Pin name, ""=go by number
|
2022-09-16 12:22:11 +02:00
|
|
|
void name(const string& name) override { m_name = name; }
|
2022-09-15 14:10:39 +02:00
|
|
|
string prettyOperatorName() const override;
|
|
|
|
|
bool dotStar() const { return name() == ".*"; } // Fake name for .* connections until linked
|
|
|
|
|
int pinNum() const { return m_pinNum; }
|
|
|
|
|
AstVar* modVarp() const { return m_modVarp; } // [After Link] Pointer to variable
|
|
|
|
|
void modVarp(AstVar* nodep) { m_modVarp = nodep; }
|
|
|
|
|
// [After Link] Pointer to variable
|
|
|
|
|
AstParamTypeDType* modPTypep() const { return m_modPTypep; }
|
|
|
|
|
void modPTypep(AstParamTypeDType* nodep) { m_modPTypep = nodep; }
|
|
|
|
|
bool param() const { return m_param; }
|
|
|
|
|
void param(bool flag) { m_param = flag; }
|
2023-03-02 03:19:21 +01:00
|
|
|
bool svDotName() const { return m_svDotName; }
|
|
|
|
|
void svDotName(bool flag) { m_svDotName = flag; }
|
2022-09-15 14:10:39 +02:00
|
|
|
bool svImplicit() const { return m_svImplicit; }
|
|
|
|
|
void svImplicit(bool flag) { m_svImplicit = flag; }
|
|
|
|
|
};
|
|
|
|
|
class AstPort final : public AstNode {
|
|
|
|
|
// A port (in/out/inout) on a module
|
2022-11-13 21:33:11 +01:00
|
|
|
// @astgen op1 := exprp : Optional[AstNodeExpr] // Expression connected to port
|
2022-09-15 20:43:56 +02:00
|
|
|
const int m_pinNum; // Pin number
|
|
|
|
|
const string m_name; // Name of pin
|
2022-09-15 14:10:39 +02:00
|
|
|
public:
|
|
|
|
|
AstPort(FileLine* fl, int pinnum, const string& name)
|
|
|
|
|
: ASTGEN_SUPER_Port(fl)
|
|
|
|
|
, m_pinNum{pinnum}
|
|
|
|
|
, m_name{name} {}
|
2022-10-04 12:03:41 +02:00
|
|
|
ASTGEN_MEMBERS_AstPort;
|
2023-03-18 01:24:15 +01:00
|
|
|
string name() const override VL_MT_STABLE { return m_name; } // * = Port name
|
2022-09-15 14:10:39 +02:00
|
|
|
int pinNum() const { return m_pinNum; } // * = Pin number, for order based instantiation
|
|
|
|
|
};
|
|
|
|
|
class AstPragma final : public AstNode {
|
|
|
|
|
const VPragmaType m_pragType; // Type of pragma
|
2025-05-06 12:34:49 +02:00
|
|
|
const VTimescale m_timescale; // For TIMEUNIT_SET
|
2022-09-15 14:10:39 +02:00
|
|
|
public:
|
|
|
|
|
// Pragmas don't result in any output code, they're just flags that affect
|
|
|
|
|
// other processing in verilator.
|
|
|
|
|
AstPragma(FileLine* fl, VPragmaType pragType)
|
|
|
|
|
: ASTGEN_SUPER_Pragma(fl)
|
|
|
|
|
, m_pragType{pragType} {}
|
2025-05-06 12:34:49 +02:00
|
|
|
AstPragma(FileLine* fl, VPragmaType pragType, const VTimescale& timescale)
|
|
|
|
|
: ASTGEN_SUPER_Pragma(fl)
|
|
|
|
|
, m_pragType{pragType}
|
2025-07-04 00:59:32 +02:00
|
|
|
, m_timescale{timescale} {}
|
2022-10-04 12:03:41 +02:00
|
|
|
ASTGEN_MEMBERS_AstPragma;
|
2022-09-15 14:10:39 +02:00
|
|
|
VPragmaType pragType() const { return m_pragType; } // *=type of the pragma
|
2022-09-16 12:22:11 +02:00
|
|
|
bool isPredictOptimizable() const override { return false; }
|
2024-11-28 20:37:11 +01:00
|
|
|
bool sameNode(const AstNode* samep) const override {
|
2023-10-16 11:17:52 +02:00
|
|
|
return pragType() == VN_DBG_AS(samep, Pragma)->pragType();
|
2022-09-15 14:10:39 +02:00
|
|
|
}
|
2025-05-06 12:34:49 +02:00
|
|
|
VTimescale timescale() const { return m_timescale; }
|
2022-09-15 14:10:39 +02:00
|
|
|
};
|
2022-11-01 23:53:47 +01:00
|
|
|
class AstPropSpec final : public AstNode {
|
2022-09-15 14:10:39 +02:00
|
|
|
// A clocked property
|
|
|
|
|
// Parents: ASSERT|COVER (property)
|
|
|
|
|
// Children: SENITEM, Properties
|
2022-09-15 20:43:56 +02:00
|
|
|
// @astgen op1 := sensesp : Optional[AstSenItem]
|
2022-11-13 21:33:11 +01:00
|
|
|
// @astgen op2 := disablep : Optional[AstNodeExpr]
|
2022-09-15 20:43:56 +02:00
|
|
|
// @astgen op3 := propp : AstNode
|
2022-09-15 14:10:39 +02:00
|
|
|
public:
|
2022-11-13 21:33:11 +01:00
|
|
|
AstPropSpec(FileLine* fl, AstSenItem* sensesp, AstNodeExpr* disablep, AstNode* propp)
|
2022-11-01 23:53:47 +01:00
|
|
|
: ASTGEN_SUPER_PropSpec(fl) {
|
2022-09-15 20:43:56 +02:00
|
|
|
this->sensesp(sensesp);
|
|
|
|
|
this->disablep(disablep);
|
|
|
|
|
this->propp(propp);
|
2022-09-15 14:10:39 +02:00
|
|
|
}
|
2022-11-01 23:53:47 +01:00
|
|
|
ASTGEN_MEMBERS_AstPropSpec;
|
2024-10-01 03:34:34 +02:00
|
|
|
bool hasDType() const override VL_MT_SAFE {
|
2022-09-15 14:10:39 +02:00
|
|
|
return true;
|
|
|
|
|
} // Used under Cover, which expects a bool child
|
|
|
|
|
};
|
|
|
|
|
class AstPull final : public AstNode {
|
2022-11-13 21:33:11 +01:00
|
|
|
// @astgen op1 := lhsp : AstNodeExpr
|
2022-09-15 20:43:56 +02:00
|
|
|
|
|
|
|
|
const bool m_direction;
|
2022-09-15 14:10:39 +02:00
|
|
|
|
|
|
|
|
public:
|
2022-11-13 21:33:11 +01:00
|
|
|
AstPull(FileLine* fl, AstNodeExpr* lhsp, bool direction)
|
2022-09-15 14:54:04 +02:00
|
|
|
: ASTGEN_SUPER_Pull(fl)
|
|
|
|
|
, m_direction{direction} {
|
2022-09-15 20:43:56 +02:00
|
|
|
this->lhsp(lhsp);
|
2022-09-15 14:10:39 +02:00
|
|
|
}
|
2022-10-04 12:03:41 +02:00
|
|
|
ASTGEN_MEMBERS_AstPull;
|
2024-11-28 20:37:11 +01:00
|
|
|
bool sameNode(const AstNode* samep) const override {
|
2023-10-16 11:17:52 +02:00
|
|
|
return direction() == VN_DBG_AS(samep, Pull)->direction();
|
2022-09-15 14:10:39 +02:00
|
|
|
}
|
|
|
|
|
uint32_t direction() const { return (uint32_t)m_direction; }
|
|
|
|
|
};
|
|
|
|
|
class AstScope final : public AstNode {
|
|
|
|
|
// A particular usage of a cell
|
|
|
|
|
// Parents: MODULE
|
|
|
|
|
// Children: NODEBLOCK
|
2022-09-15 20:43:56 +02:00
|
|
|
// @astgen op1 := varsp : List[AstVarScope]
|
|
|
|
|
// @astgen op2 := blocksp : List[AstNode] // Logic blocks/AstActive/AstCFunc
|
2024-04-02 05:11:15 +02:00
|
|
|
// @astgen op3 := inlinesp : List[AstCellInlineScope] // Cell Inlines
|
2023-12-01 01:58:16 +01:00
|
|
|
//
|
|
|
|
|
// Below scope and cell are nullptr if top scope
|
|
|
|
|
// @astgen ptr := m_aboveScopep : Optional[AstScope] // Scope above this one in the hierarchy
|
|
|
|
|
// @astgen ptr := m_aboveCellp : Optional[AstCell] // Cell above this in the hierarchy
|
|
|
|
|
// @astgen ptr := m_modp : AstNodeModule // Module scope corresponds to
|
2022-09-15 20:43:56 +02:00
|
|
|
|
2022-09-15 14:10:39 +02:00
|
|
|
// An AstScope->name() is special: . indicates an uninlined scope, __DOT__ an inlined scope
|
|
|
|
|
string m_name; // Name
|
|
|
|
|
public:
|
|
|
|
|
AstScope(FileLine* fl, AstNodeModule* modp, const string& name, AstScope* aboveScopep,
|
|
|
|
|
AstCell* aboveCellp)
|
|
|
|
|
: ASTGEN_SUPER_Scope(fl)
|
|
|
|
|
, m_name{name}
|
|
|
|
|
, m_aboveScopep{aboveScopep}
|
|
|
|
|
, m_aboveCellp{aboveCellp}
|
|
|
|
|
, m_modp{modp} {}
|
2022-10-04 12:03:41 +02:00
|
|
|
ASTGEN_MEMBERS_AstScope;
|
2023-12-01 01:58:16 +01:00
|
|
|
const char* broken() const override {
|
|
|
|
|
BROKEN_RTN(!m_modp);
|
|
|
|
|
return nullptr;
|
|
|
|
|
}
|
2024-10-01 03:34:34 +02:00
|
|
|
bool maybePointedTo() const override VL_MT_SAFE { return true; }
|
2023-03-18 01:24:15 +01:00
|
|
|
string name() const override VL_MT_STABLE { return m_name; } // * = Scope name
|
2022-09-16 12:22:11 +02:00
|
|
|
void name(const string& name) override { m_name = name; }
|
|
|
|
|
void dump(std::ostream& str) const override;
|
2024-02-09 23:50:09 +01:00
|
|
|
void dumpJson(std::ostream& str) const override;
|
2024-11-28 20:37:11 +01:00
|
|
|
bool sameNode(const AstNode* samep) const override;
|
2022-09-15 14:10:39 +02:00
|
|
|
string nameDotless() const;
|
|
|
|
|
AstNodeModule* modp() const { return m_modp; }
|
2022-09-15 14:17:00 +02:00
|
|
|
//
|
2022-10-18 23:07:09 +02:00
|
|
|
AstScope* aboveScopep() const VL_MT_SAFE { return m_aboveScopep; }
|
2022-09-15 14:10:39 +02:00
|
|
|
AstCell* aboveCellp() const { return m_aboveCellp; }
|
2022-10-18 23:07:09 +02:00
|
|
|
bool isTop() const VL_MT_SAFE { return aboveScopep() == nullptr; } // At top of hierarchy
|
2022-09-15 14:17:00 +02:00
|
|
|
// Create new MODULETEMP variable under this scope
|
|
|
|
|
AstVarScope* createTemp(const string& name, unsigned width);
|
|
|
|
|
AstVarScope* createTemp(const string& name, AstNodeDType* dtypep);
|
2025-08-19 23:02:10 +02:00
|
|
|
AstVarScope* createTempLike(const string& name, const AstVarScope* vscp);
|
2022-09-15 14:10:39 +02:00
|
|
|
};
|
|
|
|
|
class AstSenItem final : public AstNode {
|
|
|
|
|
// Parents: SENTREE
|
2022-11-13 21:33:11 +01:00
|
|
|
// @astgen op1 := sensp : Optional[AstNodeExpr] // Sensitivity expression
|
2023-11-29 19:10:32 +01:00
|
|
|
// @astgen op2 := condp : Optional[AstNodeExpr] // Sensitivity condition
|
2022-09-15 14:10:39 +02:00
|
|
|
VEdgeType m_edgeType; // Edge type
|
|
|
|
|
public:
|
2022-09-15 14:17:00 +02:00
|
|
|
class Combo {}; // for constructor type-overload selection
|
|
|
|
|
class Static {}; // for constructor type-overload selection
|
|
|
|
|
class Initial {}; // for constructor type-overload selection
|
|
|
|
|
class Final {}; // for constructor type-overload selection
|
|
|
|
|
class Never {}; // for constructor type-overload selection
|
2023-11-29 19:10:32 +01:00
|
|
|
AstSenItem(FileLine* fl, VEdgeType edgeType, AstNodeExpr* senp, AstNodeExpr* condp = nullptr)
|
2022-09-15 14:10:39 +02:00
|
|
|
: ASTGEN_SUPER_SenItem(fl)
|
|
|
|
|
, m_edgeType{edgeType} {
|
2022-09-15 20:43:56 +02:00
|
|
|
this->sensp(senp);
|
2023-11-29 19:10:32 +01:00
|
|
|
this->condp(condp);
|
2022-09-15 14:10:39 +02:00
|
|
|
}
|
|
|
|
|
AstSenItem(FileLine* fl, Combo)
|
|
|
|
|
: ASTGEN_SUPER_SenItem(fl)
|
|
|
|
|
, m_edgeType{VEdgeType::ET_COMBO} {}
|
2022-09-15 14:17:00 +02:00
|
|
|
AstSenItem(FileLine* fl, Static)
|
|
|
|
|
: ASTGEN_SUPER_SenItem(fl)
|
|
|
|
|
, m_edgeType{VEdgeType::ET_STATIC} {}
|
2022-09-15 14:10:39 +02:00
|
|
|
AstSenItem(FileLine* fl, Initial)
|
|
|
|
|
: ASTGEN_SUPER_SenItem(fl)
|
|
|
|
|
, m_edgeType{VEdgeType::ET_INITIAL} {}
|
2022-09-15 14:17:00 +02:00
|
|
|
AstSenItem(FileLine* fl, Final)
|
2022-09-15 14:10:39 +02:00
|
|
|
: ASTGEN_SUPER_SenItem(fl)
|
2022-09-15 14:17:00 +02:00
|
|
|
, m_edgeType{VEdgeType::ET_FINAL} {}
|
2022-09-15 14:10:39 +02:00
|
|
|
AstSenItem(FileLine* fl, Never)
|
|
|
|
|
: ASTGEN_SUPER_SenItem(fl)
|
|
|
|
|
, m_edgeType{VEdgeType::ET_NEVER} {}
|
2022-10-04 12:03:41 +02:00
|
|
|
ASTGEN_MEMBERS_AstSenItem;
|
2022-09-16 12:22:11 +02:00
|
|
|
void dump(std::ostream& str) const override;
|
2024-02-09 23:50:09 +01:00
|
|
|
void dumpJson(std::ostream& str) const override;
|
2024-11-28 20:37:11 +01:00
|
|
|
bool sameNode(const AstNode* samep) const override {
|
2023-10-16 11:17:52 +02:00
|
|
|
return edgeType() == VN_DBG_AS(samep, SenItem)->edgeType();
|
2022-09-15 14:10:39 +02:00
|
|
|
}
|
2022-09-15 14:17:00 +02:00
|
|
|
VEdgeType edgeType() const { return m_edgeType; }
|
2022-09-15 14:10:39 +02:00
|
|
|
void edgeType(VEdgeType type) {
|
|
|
|
|
m_edgeType = type;
|
|
|
|
|
editCountInc();
|
2022-09-15 14:17:00 +02:00
|
|
|
}
|
2022-09-15 20:43:56 +02:00
|
|
|
AstNodeVarRef* varrefp() const { return VN_CAST(sensp(), NodeVarRef); }
|
2022-09-15 14:10:39 +02:00
|
|
|
//
|
|
|
|
|
bool isClocked() const { return edgeType().clockedStmt(); }
|
2025-08-18 18:00:53 +02:00
|
|
|
bool isComboOrStar() const {
|
|
|
|
|
return edgeType() == VEdgeType::ET_COMBO || edgeType() == VEdgeType::ET_COMBO_STAR;
|
|
|
|
|
}
|
|
|
|
|
bool isComboStar() const { return edgeType() == VEdgeType::ET_COMBO_STAR; }
|
2022-09-15 14:17:00 +02:00
|
|
|
bool isHybrid() const { return edgeType() == VEdgeType::ET_HYBRID; }
|
|
|
|
|
bool isStatic() const { return edgeType() == VEdgeType::ET_STATIC; }
|
2022-09-15 14:10:39 +02:00
|
|
|
bool isInitial() const { return edgeType() == VEdgeType::ET_INITIAL; }
|
2022-09-15 14:17:00 +02:00
|
|
|
bool isFinal() const { return edgeType() == VEdgeType::ET_FINAL; }
|
2022-09-15 14:10:39 +02:00
|
|
|
bool isNever() const { return edgeType() == VEdgeType::ET_NEVER; }
|
|
|
|
|
};
|
|
|
|
|
class AstSenTree final : public AstNode {
|
2022-09-15 20:43:56 +02:00
|
|
|
// A sensitivity list
|
|
|
|
|
// @astgen op1 := sensesp : List[AstSenItem]
|
2022-09-15 14:10:39 +02:00
|
|
|
bool m_multi = false; // Created from combo logic by ORing multiple clock domains
|
|
|
|
|
public:
|
|
|
|
|
AstSenTree(FileLine* fl, AstSenItem* sensesp)
|
|
|
|
|
: ASTGEN_SUPER_SenTree(fl) {
|
2025-03-08 23:48:20 +01:00
|
|
|
addSensesp(sensesp);
|
2022-09-15 14:10:39 +02:00
|
|
|
}
|
2022-10-04 12:03:41 +02:00
|
|
|
ASTGEN_MEMBERS_AstSenTree;
|
2025-08-18 18:00:53 +02:00
|
|
|
bool sameNode(const AstNode* samep) const override {
|
|
|
|
|
const AstSenTree* const asamep = VN_DBG_AS(samep, SenTree);
|
|
|
|
|
return m_multi == asamep->m_multi;
|
|
|
|
|
}
|
2022-09-16 12:22:11 +02:00
|
|
|
void dump(std::ostream& str) const override;
|
2024-02-09 23:50:09 +01:00
|
|
|
void dumpJson(std::ostream& str) const override;
|
2024-10-01 03:34:34 +02:00
|
|
|
bool maybePointedTo() const override VL_MT_SAFE { return true; }
|
2022-09-15 14:10:39 +02:00
|
|
|
bool isMulti() const { return m_multi; }
|
|
|
|
|
void multi(bool flag) { m_multi = true; }
|
|
|
|
|
// METHODS
|
|
|
|
|
bool hasClocked() const; // Includes a clocked statement
|
2022-09-15 14:17:00 +02:00
|
|
|
bool hasStatic() const; // Includes a STATIC SenItem
|
2022-09-15 14:10:39 +02:00
|
|
|
bool hasInitial() const; // Includes a INITIAL SenItem
|
2022-09-15 14:17:00 +02:00
|
|
|
bool hasFinal() const; // Includes a FINAL SenItem
|
2022-09-15 14:10:39 +02:00
|
|
|
bool hasCombo() const; // Includes a COMBO SenItem
|
2022-09-15 14:17:00 +02:00
|
|
|
bool hasHybrid() const; // Includes a HYBRID SenItem
|
2022-09-15 14:10:39 +02:00
|
|
|
};
|
|
|
|
|
class AstStrengthSpec final : public AstNode {
|
|
|
|
|
VStrength m_s0; // Drive 0 strength
|
|
|
|
|
VStrength m_s1; // Drive 1 strength
|
|
|
|
|
|
|
|
|
|
public:
|
|
|
|
|
AstStrengthSpec(FileLine* fl, VStrength s0, VStrength s1)
|
|
|
|
|
: ASTGEN_SUPER_StrengthSpec(fl)
|
|
|
|
|
, m_s0{s0}
|
|
|
|
|
, m_s1{s1} {}
|
|
|
|
|
|
2022-10-04 12:03:41 +02:00
|
|
|
ASTGEN_MEMBERS_AstStrengthSpec;
|
2022-09-15 14:10:39 +02:00
|
|
|
VStrength strength0() { return m_s0; }
|
|
|
|
|
VStrength strength1() { return m_s1; }
|
2022-09-16 12:22:11 +02:00
|
|
|
void dump(std::ostream& str) const override;
|
2024-02-09 23:50:09 +01:00
|
|
|
void dumpJson(std::ostream& str) const override;
|
2022-09-15 14:10:39 +02:00
|
|
|
};
|
|
|
|
|
class AstTopScope final : public AstNode {
|
2022-09-15 20:43:56 +02:00
|
|
|
// A singleton, held under the top level AstModule. Holds the top level
|
|
|
|
|
// AstScope, and after V3ActiveTop, the global list of AstSenTrees (list of
|
|
|
|
|
// unique sensitivity lists).
|
|
|
|
|
//
|
|
|
|
|
// @astgen op1 := senTreesp : List[AstSenTree] // Globally unique sensitivity lists
|
|
|
|
|
// @astgen op2 := scopep : AstScope // The AstScope of the top-leveL
|
|
|
|
|
|
2022-09-15 14:10:39 +02:00
|
|
|
friend class AstNetlist; // Only the AstNetlist can create one
|
|
|
|
|
AstTopScope(FileLine* fl, AstScope* ascopep)
|
|
|
|
|
: ASTGEN_SUPER_TopScope(fl) {
|
2022-09-15 20:43:56 +02:00
|
|
|
this->scopep(ascopep);
|
2022-09-15 14:10:39 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public:
|
2022-10-04 12:03:41 +02:00
|
|
|
ASTGEN_MEMBERS_AstTopScope;
|
2024-10-01 03:34:34 +02:00
|
|
|
bool maybePointedTo() const override VL_MT_SAFE { return true; }
|
2022-09-15 14:10:39 +02:00
|
|
|
};
|
|
|
|
|
class AstTypeTable final : public AstNode {
|
|
|
|
|
// Container for hash of standard data types
|
2022-09-15 20:43:56 +02:00
|
|
|
// @astgen op1 := typesp : List[AstNodeDType]
|
2023-12-01 01:58:16 +01:00
|
|
|
//
|
|
|
|
|
// @astgen ptr := m_constraintRefp : Optional[AstConstraintRefDType]
|
|
|
|
|
// @astgen ptr := m_emptyQueuep : Optional[AstEmptyQueueDType]
|
|
|
|
|
// @astgen ptr := m_queueIndexp : Optional[AstQueueDType]
|
|
|
|
|
// @astgen ptr := m_streamp : Optional[AstStreamDType]
|
|
|
|
|
// @astgen ptr := m_voidp : Optional[AstVoidDType]
|
2022-09-15 14:10:39 +02:00
|
|
|
AstBasicDType* m_basicps[VBasicDTypeKwd::_ENUM_MAX]{};
|
|
|
|
|
//
|
|
|
|
|
using DetailedMap = std::map<VBasicTypeKey, AstBasicDType*>;
|
|
|
|
|
DetailedMap m_detailedMap;
|
|
|
|
|
|
|
|
|
|
public:
|
|
|
|
|
explicit AstTypeTable(FileLine* fl);
|
2022-10-04 12:03:41 +02:00
|
|
|
ASTGEN_MEMBERS_AstTypeTable;
|
2024-10-01 03:34:34 +02:00
|
|
|
bool maybePointedTo() const override VL_MT_SAFE { return true; }
|
2022-09-16 12:22:11 +02:00
|
|
|
void cloneRelink() override { V3ERROR_NA; }
|
2022-09-15 14:10:39 +02:00
|
|
|
AstBasicDType* findBasicDType(FileLine* fl, VBasicDTypeKwd kwd);
|
|
|
|
|
AstBasicDType* findLogicBitDType(FileLine* fl, VBasicDTypeKwd kwd, int width, int widthMin,
|
|
|
|
|
VSigning numeric);
|
|
|
|
|
AstBasicDType* findLogicBitDType(FileLine* fl, VBasicDTypeKwd kwd, const VNumRange& range,
|
|
|
|
|
int widthMin, VSigning numeric);
|
|
|
|
|
AstBasicDType* findInsertSameDType(AstBasicDType* nodep);
|
2023-11-12 02:20:37 +01:00
|
|
|
AstConstraintRefDType* findConstraintRefDType(FileLine* fl);
|
2022-09-15 14:10:39 +02:00
|
|
|
AstEmptyQueueDType* findEmptyQueueDType(FileLine* fl);
|
|
|
|
|
AstQueueDType* findQueueIndexDType(FileLine* fl);
|
2023-06-14 04:46:42 +02:00
|
|
|
AstStreamDType* findStreamDType(FileLine* fl);
|
2023-11-12 02:20:37 +01:00
|
|
|
AstVoidDType* findVoidDType(FileLine* fl);
|
2022-09-15 14:10:39 +02:00
|
|
|
void clearCache();
|
|
|
|
|
void repairCache();
|
2022-09-16 12:22:11 +02:00
|
|
|
void dump(std::ostream& str = std::cout) const override;
|
2024-02-09 23:50:09 +01:00
|
|
|
void dumpJson(std::ostream& str = std::cout) const override;
|
2022-09-15 14:10:39 +02:00
|
|
|
};
|
|
|
|
|
class AstTypedef final : public AstNode {
|
2022-09-15 20:43:56 +02:00
|
|
|
// @astgen op1 := childDTypep : Optional[AstNodeDType]
|
|
|
|
|
// @astgen op4 := attrsp : List[AstNode] // Attributes during early parse
|
|
|
|
|
|
2022-09-15 14:10:39 +02:00
|
|
|
string m_name;
|
|
|
|
|
string m_tag; // Holds the string of the verilator tag -- used in XML output.
|
2025-07-26 23:11:35 +02:00
|
|
|
uint32_t m_declTokenNum; // Declaration token number
|
2022-11-13 15:26:46 +01:00
|
|
|
bool m_attrPublic = false;
|
2024-10-07 00:08:40 +02:00
|
|
|
bool m_isHideLocal : 1; // Verilog local
|
|
|
|
|
bool m_isHideProtected : 1; // Verilog protected
|
2025-07-30 15:14:13 +02:00
|
|
|
bool m_isUnderClass : 1; // Underneath class
|
2022-11-13 15:27:37 +01:00
|
|
|
|
2022-09-15 14:10:39 +02:00
|
|
|
public:
|
|
|
|
|
AstTypedef(FileLine* fl, const string& name, AstNode* attrsp, VFlagChildDType,
|
|
|
|
|
AstNodeDType* dtp)
|
|
|
|
|
: ASTGEN_SUPER_Typedef(fl)
|
2024-10-07 00:08:40 +02:00
|
|
|
, m_name{name}
|
2025-07-26 23:11:35 +02:00
|
|
|
, m_declTokenNum{fl->tokenNum()}
|
2024-10-07 00:08:40 +02:00
|
|
|
, m_isHideLocal{false}
|
2025-07-30 15:14:13 +02:00
|
|
|
, m_isHideProtected{false}
|
|
|
|
|
, m_isUnderClass{false} {
|
2022-09-15 14:10:39 +02:00
|
|
|
childDTypep(dtp); // Only for parser
|
|
|
|
|
addAttrsp(attrsp);
|
|
|
|
|
dtypep(nullptr); // V3Width will resolve
|
|
|
|
|
}
|
2022-10-04 12:03:41 +02:00
|
|
|
ASTGEN_MEMBERS_AstTypedef;
|
2022-09-16 12:22:11 +02:00
|
|
|
void dump(std::ostream& str) const override;
|
2024-02-09 23:50:09 +01:00
|
|
|
void dumpJson(std::ostream& str) const override;
|
2022-09-16 12:22:11 +02:00
|
|
|
AstNodeDType* getChildDTypep() const override { return childDTypep(); }
|
2023-03-17 00:48:56 +01:00
|
|
|
virtual AstNodeDType* subDTypep() const VL_MT_STABLE {
|
|
|
|
|
return dtypep() ? dtypep() : childDTypep();
|
|
|
|
|
}
|
2022-09-15 14:10:39 +02:00
|
|
|
// METHODS
|
2025-07-26 23:11:35 +02:00
|
|
|
uint32_t declTokenNum() const override { return m_declTokenNum; }
|
|
|
|
|
void declTokenNumSetMin(uint32_t tokenNum) override {
|
|
|
|
|
m_declTokenNum = std::min(m_declTokenNum, tokenNum);
|
|
|
|
|
}
|
2023-03-18 01:24:15 +01:00
|
|
|
string name() const override VL_MT_STABLE { return m_name; }
|
2024-10-01 03:34:34 +02:00
|
|
|
bool maybePointedTo() const override VL_MT_SAFE { return true; }
|
|
|
|
|
bool hasDType() const override VL_MT_SAFE { return true; }
|
2022-09-16 12:22:11 +02:00
|
|
|
void name(const string& flag) override { m_name = flag; }
|
2022-09-15 14:10:39 +02:00
|
|
|
bool attrPublic() const { return m_attrPublic; }
|
|
|
|
|
void attrPublic(bool flag) { m_attrPublic = flag; }
|
2024-10-07 00:08:40 +02:00
|
|
|
bool isHideLocal() const { return m_isHideLocal; }
|
|
|
|
|
void isHideLocal(bool flag) { m_isHideLocal = flag; }
|
|
|
|
|
bool isHideProtected() const { return m_isHideProtected; }
|
|
|
|
|
void isHideProtected(bool flag) { m_isHideProtected = flag; }
|
2025-07-30 15:14:13 +02:00
|
|
|
bool isUnderClass() const { return m_isUnderClass; }
|
|
|
|
|
void isUnderClass(bool flag) { m_isUnderClass = flag; }
|
2022-09-16 12:22:11 +02:00
|
|
|
void tag(const string& text) override { m_tag = text; }
|
|
|
|
|
string tag() const override { return m_tag; }
|
2022-09-15 14:10:39 +02:00
|
|
|
};
|
|
|
|
|
class AstTypedefFwd final : public AstNode {
|
|
|
|
|
// Forward declaration of a type; stripped after netlist parsing is complete
|
|
|
|
|
string m_name;
|
2025-07-26 23:11:35 +02:00
|
|
|
const VFwdType m_fwdType; // Forward type for lint check
|
2022-09-15 14:10:39 +02:00
|
|
|
|
|
|
|
|
public:
|
2025-07-26 23:11:35 +02:00
|
|
|
AstTypedefFwd(FileLine* fl, const string& name, const VFwdType& fwdType)
|
2022-09-15 14:10:39 +02:00
|
|
|
: ASTGEN_SUPER_TypedefFwd(fl)
|
2025-07-26 23:11:35 +02:00
|
|
|
, m_name{name}
|
|
|
|
|
, m_fwdType{fwdType} {}
|
2022-10-04 12:03:41 +02:00
|
|
|
ASTGEN_MEMBERS_AstTypedefFwd;
|
2022-09-15 14:10:39 +02:00
|
|
|
// METHODS
|
2023-03-18 01:24:15 +01:00
|
|
|
string name() const override VL_MT_STABLE { return m_name; }
|
2025-07-26 23:11:35 +02:00
|
|
|
void dump(std::ostream& str = std::cout) const override;
|
|
|
|
|
void dumpJson(std::ostream& str = std::cout) const override;
|
2024-10-01 03:34:34 +02:00
|
|
|
bool maybePointedTo() const override VL_MT_SAFE { return true; }
|
2025-07-26 23:11:35 +02:00
|
|
|
VFwdType fwdType() const { return m_fwdType; }
|
2022-09-15 14:10:39 +02:00
|
|
|
};
|
|
|
|
|
class AstUdpTable final : public AstNode {
|
2022-09-15 20:43:56 +02:00
|
|
|
// @astgen op1 := linesp : List[AstUdpTableLine]
|
2022-09-15 14:10:39 +02:00
|
|
|
public:
|
2022-09-15 20:43:56 +02:00
|
|
|
AstUdpTable(FileLine* fl, AstUdpTableLine* linesp)
|
2022-09-15 14:10:39 +02:00
|
|
|
: ASTGEN_SUPER_UdpTable(fl) {
|
2025-04-16 12:32:18 +02:00
|
|
|
this->addLinesp(linesp);
|
|
|
|
|
if (!v3Global.hasTable()) v3Global.setHasTable();
|
2022-09-15 14:10:39 +02:00
|
|
|
}
|
2022-10-04 12:03:41 +02:00
|
|
|
ASTGEN_MEMBERS_AstUdpTable;
|
2022-09-15 14:10:39 +02:00
|
|
|
};
|
|
|
|
|
class AstUdpTableLine final : public AstNode {
|
2025-04-16 12:32:18 +02:00
|
|
|
// @astgen op1 := iFieldsp : List[AstUdpTableLineVal] // Input fields
|
|
|
|
|
// @astgen op2 := oFieldsp : List[AstUdpTableLineVal] // Output fields
|
|
|
|
|
private:
|
|
|
|
|
const bool m_udpIsCombo; // Combinational or sequential UDP
|
2022-09-15 14:10:39 +02:00
|
|
|
|
|
|
|
|
public:
|
2025-04-16 12:32:18 +02:00
|
|
|
class UdpCombo {};
|
|
|
|
|
AstUdpTableLine(UdpCombo, FileLine* fl, AstUdpTableLineVal* iFieldsp,
|
|
|
|
|
AstUdpTableLineVal* oFieldsp)
|
2022-09-15 14:10:39 +02:00
|
|
|
: ASTGEN_SUPER_UdpTableLine(fl)
|
2025-04-16 12:32:18 +02:00
|
|
|
, m_udpIsCombo{true} {
|
|
|
|
|
addIFieldsp(iFieldsp);
|
|
|
|
|
addOFieldsp(oFieldsp);
|
|
|
|
|
}
|
|
|
|
|
class UdpSequential {};
|
|
|
|
|
AstUdpTableLine(UdpSequential, FileLine* fl, AstUdpTableLineVal* iFieldsp,
|
|
|
|
|
AstUdpTableLineVal* oFieldsp1, AstUdpTableLineVal* oFieldsp2)
|
|
|
|
|
: ASTGEN_SUPER_UdpTableLine(fl)
|
|
|
|
|
, m_udpIsCombo{false} {
|
|
|
|
|
addIFieldsp(iFieldsp);
|
|
|
|
|
addOFieldsp(oFieldsp1);
|
|
|
|
|
addOFieldsp(oFieldsp2);
|
|
|
|
|
}
|
2022-10-04 12:03:41 +02:00
|
|
|
ASTGEN_MEMBERS_AstUdpTableLine;
|
2025-04-16 12:32:18 +02:00
|
|
|
int udpIsCombo() const { return m_udpIsCombo; }
|
|
|
|
|
};
|
|
|
|
|
class AstUdpTableLineVal final : public AstNode {
|
|
|
|
|
string m_text; // Value character
|
|
|
|
|
|
|
|
|
|
public:
|
|
|
|
|
AstUdpTableLineVal(FileLine* fl, const string& text)
|
|
|
|
|
: ASTGEN_SUPER_UdpTableLineVal(fl)
|
|
|
|
|
, m_text{text} {}
|
|
|
|
|
ASTGEN_MEMBERS_AstUdpTableLineVal;
|
2023-03-18 01:24:15 +01:00
|
|
|
string name() const override VL_MT_STABLE { return m_text; }
|
2025-04-16 12:32:18 +02:00
|
|
|
void name(std::string const& text) override VL_MT_STABLE { m_text = text; }
|
2024-10-01 03:34:34 +02:00
|
|
|
string text() const VL_MT_SAFE { return m_text; }
|
2022-09-15 14:10:39 +02:00
|
|
|
};
|
|
|
|
|
class AstVar final : public AstNode {
|
|
|
|
|
// A variable (in/out/wire/reg/param) inside a module
|
2022-09-15 20:43:56 +02:00
|
|
|
//
|
|
|
|
|
// @astgen op1 := childDTypep : Optional[AstNodeDType]
|
2022-10-14 09:35:26 +02:00
|
|
|
// @astgen op2 := delayp : Optional[AstDelay] // Net delay
|
2022-09-15 20:43:56 +02:00
|
|
|
// Initial value that never changes (static const), or constructor argument for
|
|
|
|
|
// MTASKSTATE variables
|
2024-10-01 04:25:28 +02:00
|
|
|
// @astgen op3 := valuep : Optional[AstNode<AstNodeExpr|AstNodeDType>]
|
|
|
|
|
// Value is a DType for type parameter defaults
|
2022-09-15 20:43:56 +02:00
|
|
|
// @astgen op4 := attrsp : List[AstNode] // Attributes during early parse
|
2023-12-05 04:11:07 +01:00
|
|
|
// @astgen ptr := m_sensIfacep : Optional[AstIface] // Interface type to which reads from this
|
|
|
|
|
// var are sensitive
|
2022-09-15 20:43:56 +02:00
|
|
|
|
2022-09-15 14:10:39 +02:00
|
|
|
string m_name; // Name of variable
|
|
|
|
|
string m_origName; // Original name before dot addition
|
|
|
|
|
string m_tag; // Holds the string of the verilator tag -- used in XML output.
|
|
|
|
|
VVarType m_varType; // Type of variable
|
|
|
|
|
VDirection m_direction; // Direction input/output etc
|
|
|
|
|
VDirection m_declDirection; // Declared direction input/output etc
|
|
|
|
|
VLifetime m_lifetime; // Lifetime
|
|
|
|
|
VVarAttrClocker m_attrClocker;
|
2024-08-13 20:20:31 +02:00
|
|
|
VRandAttr m_rand; // Randomizability of this variable (rand, randc, etc)
|
2022-09-15 14:10:39 +02:00
|
|
|
int m_pinNum = 0; // For XML, if non-zero the connection pin number
|
2023-09-25 17:39:04 +02:00
|
|
|
bool m_ansi : 1; // Params or pins declared in the module header, rather than the body
|
2022-09-15 14:10:39 +02:00
|
|
|
bool m_declTyped : 1; // Declared as type (for dedup check)
|
|
|
|
|
bool m_tristate : 1; // Inout or triwire or trireg
|
|
|
|
|
bool m_primaryIO : 1; // In/out to top level (or directly assigned from same)
|
|
|
|
|
bool m_sc : 1; // SystemC variable
|
|
|
|
|
bool m_scClocked : 1; // SystemC sc_clk<> needed
|
|
|
|
|
bool m_scSensitive : 1; // SystemC sensitive() needed
|
|
|
|
|
bool m_sigPublic : 1; // User C code accesses this signal or is top signal
|
|
|
|
|
bool m_sigModPublic : 1; // User C code accesses this signal and module
|
|
|
|
|
bool m_sigUserRdPublic : 1; // User C code accesses this signal, read only
|
|
|
|
|
bool m_sigUserRWPublic : 1; // User C code accesses this signal, read-write
|
|
|
|
|
bool m_usedClock : 1; // Signal used as a clock
|
|
|
|
|
bool m_usedParam : 1; // Parameter is referenced (on link; later signals not setup)
|
|
|
|
|
bool m_usedLoopIdx : 1; // Variable subject of for unrolling
|
|
|
|
|
bool m_funcLocal : 1; // Local variable for a function
|
2023-06-12 15:24:46 +02:00
|
|
|
bool m_funcLocalSticky : 1; // As m_funcLocal but remains set if var is moved to a static
|
2022-09-15 14:10:39 +02:00
|
|
|
bool m_funcReturn : 1; // Return variable for a function
|
|
|
|
|
bool m_attrScBv : 1; // User force bit vector attribute
|
|
|
|
|
bool m_attrIsolateAssign : 1; // User isolate_assignments attribute
|
|
|
|
|
bool m_attrSFormat : 1; // User sformat attribute
|
|
|
|
|
bool m_attrSplitVar : 1; // declared with split_var metacomment
|
|
|
|
|
bool m_fileDescr : 1; // File descriptor
|
2025-08-01 00:38:50 +02:00
|
|
|
bool m_gotNansiType : 1; // Linker saw Non-ANSI type declaration
|
2022-09-15 14:10:39 +02:00
|
|
|
bool m_isConst : 1; // Table contains constant data
|
|
|
|
|
bool m_isContinuously : 1; // Ever assigned continuously (for force/release)
|
|
|
|
|
bool m_hasStrengthAssignment : 1; // Is on LHS of assignment with strength specifier
|
2025-07-14 12:51:58 +02:00
|
|
|
bool m_isStatic : 1; // Static C variable (for Verilog see instead lifetime())
|
2022-09-15 14:10:39 +02:00
|
|
|
bool m_isPulldown : 1; // Tri0
|
|
|
|
|
bool m_isPullup : 1; // Tri1
|
|
|
|
|
bool m_isIfaceParent : 1; // dtype is reference to interface present in this module
|
2023-09-19 03:17:21 +02:00
|
|
|
bool m_isInternal : 1; // Internal state, don't add to method pinter
|
2022-09-15 14:10:39 +02:00
|
|
|
bool m_isDpiOpenArray : 1; // DPI import open array
|
|
|
|
|
bool m_isHideLocal : 1; // Verilog local
|
|
|
|
|
bool m_isHideProtected : 1; // Verilog protected
|
|
|
|
|
bool m_noReset : 1; // Do not do automated reset/randomization
|
|
|
|
|
bool m_noSubst : 1; // Do not substitute out references
|
|
|
|
|
bool m_overridenParam : 1; // Overridden parameter by #(...) or defparam
|
|
|
|
|
bool m_trace : 1; // Trace this variable
|
|
|
|
|
bool m_isLatched : 1; // Not assigned in all control paths of combo always
|
|
|
|
|
bool m_isForceable : 1; // May be forced/released externally from user C code
|
2024-05-10 19:19:51 +02:00
|
|
|
bool m_isForcedByCode : 1; // May be forced/released from AstAssignForce/AstRelease
|
2022-09-15 14:17:00 +02:00
|
|
|
bool m_isWrittenByDpi : 1; // This variable can be written by a DPI Export
|
|
|
|
|
bool m_isWrittenBySuspendable : 1; // This variable can be written by a suspendable process
|
2025-06-28 21:45:45 +02:00
|
|
|
bool m_ignorePostRead : 1; // Ignore reads in 'Post' blocks during ordering
|
2024-10-09 12:43:53 +02:00
|
|
|
bool m_ignorePostWrite : 1; // Ignore writes in 'Post' blocks during ordering
|
2025-06-17 00:14:24 +02:00
|
|
|
bool m_ignoreSchedWrite : 1; // Ignore writes in scheduling (for special optimizations)
|
Optimize complex combinational logic in DFG (#6298)
This patch adds DfgLogic, which is a vertex that represents a whole,
arbitrarily complex combinational AstAlways or AstAssignW in the
DfgGraph.
Implementing this requires computing the variables live at entry to the
AstAlways (variables read by the block), so there is a new
ControlFlowGraph data structure and a classical data-flow analysis based
live variable analysis to do that at the variable level (as opposed to
bit/element level).
The actual CFG construction and live variable analysis is best effort,
and might fail for currently unhandled constructs or data types. This
can be extended later.
V3DfgAstToDfg is changed to convert the Ast into an initial DfgGraph
containing only DfgLogic, DfgVertexSplice and DfgVertexVar vertices.
The DfgLogic are then subsequently synthesized into primitive operations
by the new V3DfgSynthesize pass, which is a combination of the old
V3DfgAstToDfg conversion and new code to handle AstAlways blocks with
complex flow control.
V3DfgSynthesize by default will synthesize roughly the same constructs
as V3DfgAstToDfg used to handle before, plus any logic that is part of a
combinational cycle within the DfgGraph. This enables breaking up these
cycles, for which there are extensions to V3DfgBreakCycles in this patch
as well. V3DfgSynthesize will then delete all non synthesized or non
synthesizable DfgLogic vertices and the rest of the Dfg pipeline is
identical, with minor changes to adjust for the changed representation.
Because with this change we can now eliminate many more UNOPTFLAT, DFG
has been disabled in all the tests that specifically target testing the
scheduling and reporting of circular combinational logic.
2025-08-19 16:06:38 +02:00
|
|
|
bool m_dfgMultidriven : 1; // Singal is multidriven, used by DFG to avoid repeat processing
|
2022-09-15 14:10:39 +02:00
|
|
|
|
|
|
|
|
void init() {
|
|
|
|
|
m_ansi = false;
|
|
|
|
|
m_declTyped = false;
|
|
|
|
|
m_tristate = false;
|
|
|
|
|
m_primaryIO = false;
|
|
|
|
|
m_sc = false;
|
|
|
|
|
m_scClocked = false;
|
|
|
|
|
m_scSensitive = false;
|
|
|
|
|
m_usedClock = false;
|
|
|
|
|
m_usedParam = false;
|
|
|
|
|
m_usedLoopIdx = false;
|
|
|
|
|
m_sigPublic = false;
|
|
|
|
|
m_sigModPublic = false;
|
|
|
|
|
m_sigUserRdPublic = false;
|
|
|
|
|
m_sigUserRWPublic = false;
|
|
|
|
|
m_funcLocal = false;
|
2023-06-12 15:24:46 +02:00
|
|
|
m_funcLocalSticky = false;
|
2022-09-15 14:10:39 +02:00
|
|
|
m_funcReturn = false;
|
|
|
|
|
m_attrScBv = false;
|
|
|
|
|
m_attrIsolateAssign = false;
|
|
|
|
|
m_attrSFormat = false;
|
|
|
|
|
m_attrSplitVar = false;
|
|
|
|
|
m_fileDescr = false;
|
2025-08-01 00:38:50 +02:00
|
|
|
m_gotNansiType = false;
|
2022-09-15 14:10:39 +02:00
|
|
|
m_isConst = false;
|
|
|
|
|
m_isContinuously = false;
|
|
|
|
|
m_hasStrengthAssignment = false;
|
|
|
|
|
m_isStatic = false;
|
|
|
|
|
m_isPulldown = false;
|
|
|
|
|
m_isPullup = false;
|
|
|
|
|
m_isIfaceParent = false;
|
2023-09-19 03:17:21 +02:00
|
|
|
m_isInternal = false;
|
2022-09-15 14:10:39 +02:00
|
|
|
m_isDpiOpenArray = false;
|
|
|
|
|
m_isHideLocal = false;
|
|
|
|
|
m_isHideProtected = false;
|
|
|
|
|
m_noReset = false;
|
|
|
|
|
m_noSubst = false;
|
|
|
|
|
m_overridenParam = false;
|
|
|
|
|
m_trace = false;
|
|
|
|
|
m_isLatched = false;
|
|
|
|
|
m_isForceable = false;
|
2024-05-10 19:19:51 +02:00
|
|
|
m_isForcedByCode = false;
|
2022-09-15 14:17:00 +02:00
|
|
|
m_isWrittenByDpi = false;
|
|
|
|
|
m_isWrittenBySuspendable = false;
|
2025-06-28 21:45:45 +02:00
|
|
|
m_ignorePostRead = false;
|
2024-10-09 12:43:53 +02:00
|
|
|
m_ignorePostWrite = false;
|
2025-03-03 02:02:55 +01:00
|
|
|
m_ignoreSchedWrite = false;
|
Optimize complex combinational logic in DFG (#6298)
This patch adds DfgLogic, which is a vertex that represents a whole,
arbitrarily complex combinational AstAlways or AstAssignW in the
DfgGraph.
Implementing this requires computing the variables live at entry to the
AstAlways (variables read by the block), so there is a new
ControlFlowGraph data structure and a classical data-flow analysis based
live variable analysis to do that at the variable level (as opposed to
bit/element level).
The actual CFG construction and live variable analysis is best effort,
and might fail for currently unhandled constructs or data types. This
can be extended later.
V3DfgAstToDfg is changed to convert the Ast into an initial DfgGraph
containing only DfgLogic, DfgVertexSplice and DfgVertexVar vertices.
The DfgLogic are then subsequently synthesized into primitive operations
by the new V3DfgSynthesize pass, which is a combination of the old
V3DfgAstToDfg conversion and new code to handle AstAlways blocks with
complex flow control.
V3DfgSynthesize by default will synthesize roughly the same constructs
as V3DfgAstToDfg used to handle before, plus any logic that is part of a
combinational cycle within the DfgGraph. This enables breaking up these
cycles, for which there are extensions to V3DfgBreakCycles in this patch
as well. V3DfgSynthesize will then delete all non synthesized or non
synthesizable DfgLogic vertices and the rest of the Dfg pipeline is
identical, with minor changes to adjust for the changed representation.
Because with this change we can now eliminate many more UNOPTFLAT, DFG
has been disabled in all the tests that specifically target testing the
scheduling and reporting of circular combinational logic.
2025-08-19 16:06:38 +02:00
|
|
|
m_dfgMultidriven = false;
|
2022-09-15 14:10:39 +02:00
|
|
|
m_attrClocker = VVarAttrClocker::CLOCKER_UNKNOWN;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public:
|
|
|
|
|
AstVar(FileLine* fl, VVarType type, const string& name, VFlagChildDType, AstNodeDType* dtp)
|
|
|
|
|
: ASTGEN_SUPER_Var(fl)
|
|
|
|
|
, m_name{name}
|
|
|
|
|
, m_origName{name} {
|
|
|
|
|
init();
|
|
|
|
|
combineType(type);
|
|
|
|
|
childDTypep(dtp); // Only for parser
|
|
|
|
|
dtypep(nullptr); // V3Width will resolve
|
|
|
|
|
}
|
|
|
|
|
AstVar(FileLine* fl, VVarType type, const string& name, AstNodeDType* dtp)
|
|
|
|
|
: ASTGEN_SUPER_Var(fl)
|
|
|
|
|
, m_name{name}
|
|
|
|
|
, m_origName{name} {
|
|
|
|
|
init();
|
|
|
|
|
combineType(type);
|
|
|
|
|
UASSERT(dtp, "AstVar created with no dtype");
|
|
|
|
|
dtypep(dtp);
|
|
|
|
|
}
|
|
|
|
|
AstVar(FileLine* fl, VVarType type, const string& name, VFlagLogicPacked, int wantwidth)
|
|
|
|
|
: ASTGEN_SUPER_Var(fl)
|
|
|
|
|
, m_name{name}
|
|
|
|
|
, m_origName{name} {
|
|
|
|
|
init();
|
|
|
|
|
combineType(type);
|
|
|
|
|
dtypeSetLogicSized(wantwidth, VSigning::UNSIGNED);
|
|
|
|
|
}
|
|
|
|
|
AstVar(FileLine* fl, VVarType type, const string& name, VFlagBitPacked, int wantwidth)
|
|
|
|
|
: ASTGEN_SUPER_Var(fl)
|
|
|
|
|
, m_name{name}
|
|
|
|
|
, m_origName{name} {
|
|
|
|
|
init();
|
|
|
|
|
combineType(type);
|
|
|
|
|
dtypeSetBitSized(wantwidth, VSigning::UNSIGNED);
|
|
|
|
|
}
|
2025-08-19 23:02:10 +02:00
|
|
|
AstVar(FileLine* fl, VVarType type, const string& name, const AstVar* examplep)
|
2022-09-15 14:10:39 +02:00
|
|
|
: ASTGEN_SUPER_Var(fl)
|
|
|
|
|
, m_name{name}
|
|
|
|
|
, m_origName{name} {
|
|
|
|
|
init();
|
|
|
|
|
combineType(type);
|
|
|
|
|
if (examplep->childDTypep()) childDTypep(examplep->childDTypep()->cloneTree(true));
|
|
|
|
|
dtypeFrom(examplep);
|
|
|
|
|
}
|
2022-10-04 12:03:41 +02:00
|
|
|
ASTGEN_MEMBERS_AstVar;
|
2022-09-16 12:22:11 +02:00
|
|
|
void dump(std::ostream& str) const override;
|
2024-02-09 23:50:09 +01:00
|
|
|
void dumpJson(std::ostream& str) const override;
|
2024-11-28 20:37:11 +01:00
|
|
|
bool sameNode(const AstNode* samep) const override;
|
2024-10-01 03:34:34 +02:00
|
|
|
string name() const override VL_MT_STABLE { return m_name; } // * = Var name
|
|
|
|
|
bool hasDType() const override VL_MT_SAFE { return true; }
|
|
|
|
|
bool maybePointedTo() const override VL_MT_SAFE { return true; }
|
2022-09-16 12:22:11 +02:00
|
|
|
string origName() const override { return m_origName; } // * = Original name
|
2022-09-15 14:10:39 +02:00
|
|
|
void origName(const string& name) { m_origName = name; }
|
2022-10-18 23:07:09 +02:00
|
|
|
VVarType varType() const VL_MT_SAFE { return m_varType; } // * = Type of variable
|
2022-09-15 14:10:39 +02:00
|
|
|
void direction(const VDirection& flag) {
|
|
|
|
|
m_direction = flag;
|
|
|
|
|
if (m_direction == VDirection::INOUT) m_tristate = true;
|
|
|
|
|
}
|
2022-10-18 23:07:09 +02:00
|
|
|
VDirection direction() const VL_MT_SAFE { return m_direction; }
|
|
|
|
|
bool isIO() const VL_MT_SAFE { return m_direction != VDirection::NONE; }
|
2022-09-15 14:10:39 +02:00
|
|
|
void declDirection(const VDirection& flag) { m_declDirection = flag; }
|
|
|
|
|
VDirection declDirection() const { return m_declDirection; }
|
|
|
|
|
void varType(VVarType type) { m_varType = type; }
|
|
|
|
|
void varType2Out() {
|
|
|
|
|
m_tristate = false;
|
|
|
|
|
m_direction = VDirection::OUTPUT;
|
|
|
|
|
}
|
|
|
|
|
void varType2In() {
|
|
|
|
|
m_tristate = false;
|
|
|
|
|
m_direction = VDirection::INPUT;
|
|
|
|
|
}
|
|
|
|
|
string scType() const; // Return SysC type: bool, uint32_t, uint64_t, sc_bv
|
|
|
|
|
// Return C /*public*/ type for argument: bool, uint32_t, uint64_t, etc.
|
|
|
|
|
string cPubArgType(bool named, bool forReturn) const;
|
|
|
|
|
string dpiArgType(bool named, bool forReturn) const; // Return DPI-C type for argument
|
|
|
|
|
string dpiTmpVarType(const string& varName) const;
|
|
|
|
|
// Return Verilator internal type for argument: CData, SData, IData, WData
|
|
|
|
|
string vlArgType(bool named, bool forReturn, bool forFunc, const string& namespc = "",
|
2023-08-03 08:52:52 +02:00
|
|
|
bool asRef = false) const;
|
2022-09-15 14:10:39 +02:00
|
|
|
string vlEnumType() const; // Return VerilatorVarType: VLVT_UINT32, etc
|
|
|
|
|
string vlEnumDir() const; // Return VerilatorVarDir: VLVD_INOUT, etc
|
|
|
|
|
string vlPropDecl(const string& propName) const; // Return VerilatorVarProps declaration
|
|
|
|
|
void combineType(VVarType type);
|
2022-09-16 12:22:11 +02:00
|
|
|
AstNodeDType* getChildDTypep() const override { return childDTypep(); }
|
2023-03-17 00:48:56 +01:00
|
|
|
AstNodeDType* dtypeSkipRefp() const VL_MT_STABLE { return subDTypep()->skipRefp(); }
|
2022-09-15 14:10:39 +02:00
|
|
|
// (Slow) recurse down to find basic data type (Note don't need virtual -
|
|
|
|
|
// AstVar isn't a NodeDType)
|
2023-03-17 00:48:56 +01:00
|
|
|
AstBasicDType* basicp() const VL_MT_STABLE { return subDTypep()->basicp(); }
|
|
|
|
|
virtual AstNodeDType* subDTypep() const VL_MT_STABLE {
|
2022-10-18 23:07:09 +02:00
|
|
|
return dtypep() ? dtypep() : childDTypep();
|
|
|
|
|
}
|
2022-09-15 14:10:39 +02:00
|
|
|
void ansi(bool flag) { m_ansi = flag; }
|
|
|
|
|
void declTyped(bool flag) { m_declTyped = flag; }
|
2023-12-05 04:11:07 +01:00
|
|
|
void sensIfacep(AstIface* nodep) { m_sensIfacep = nodep; }
|
2022-09-15 14:10:39 +02:00
|
|
|
void attrClocker(VVarAttrClocker flag) { m_attrClocker = flag; }
|
|
|
|
|
void attrFileDescr(bool flag) { m_fileDescr = flag; }
|
|
|
|
|
void attrScClocked(bool flag) { m_scClocked = flag; }
|
|
|
|
|
void attrScBv(bool flag) { m_attrScBv = flag; }
|
|
|
|
|
void attrIsolateAssign(bool flag) { m_attrIsolateAssign = flag; }
|
|
|
|
|
void attrSFormat(bool flag) { m_attrSFormat = flag; }
|
|
|
|
|
void attrSplitVar(bool flag) { m_attrSplitVar = flag; }
|
2024-08-13 20:20:31 +02:00
|
|
|
void rand(const VRandAttr flag) { m_rand = flag; }
|
2022-09-15 14:10:39 +02:00
|
|
|
void usedClock(bool flag) { m_usedClock = flag; }
|
|
|
|
|
void usedParam(bool flag) { m_usedParam = flag; }
|
|
|
|
|
void usedLoopIdx(bool flag) { m_usedLoopIdx = flag; }
|
|
|
|
|
void sigPublic(bool flag) { m_sigPublic = flag; }
|
|
|
|
|
void sigModPublic(bool flag) { m_sigModPublic = flag; }
|
|
|
|
|
void sigUserRdPublic(bool flag) {
|
|
|
|
|
m_sigUserRdPublic = flag;
|
|
|
|
|
if (flag) sigPublic(true);
|
|
|
|
|
}
|
|
|
|
|
void sigUserRWPublic(bool flag) {
|
|
|
|
|
m_sigUserRWPublic = flag;
|
|
|
|
|
if (flag) sigUserRdPublic(true);
|
|
|
|
|
}
|
|
|
|
|
void sc(bool flag) { m_sc = flag; }
|
|
|
|
|
void scSensitive(bool flag) { m_scSensitive = flag; }
|
|
|
|
|
void primaryIO(bool flag) { m_primaryIO = flag; }
|
|
|
|
|
void isConst(bool flag) { m_isConst = flag; }
|
|
|
|
|
void isContinuously(bool flag) { m_isContinuously = flag; }
|
|
|
|
|
void isStatic(bool flag) { m_isStatic = flag; }
|
|
|
|
|
void isIfaceParent(bool flag) { m_isIfaceParent = flag; }
|
2023-09-19 03:17:21 +02:00
|
|
|
void isInternal(bool flag) { m_isInternal = flag; }
|
2023-06-12 15:24:46 +02:00
|
|
|
void funcLocal(bool flag) {
|
|
|
|
|
m_funcLocal = flag;
|
|
|
|
|
if (flag) m_funcLocalSticky = true;
|
|
|
|
|
}
|
2022-09-15 14:10:39 +02:00
|
|
|
void funcReturn(bool flag) { m_funcReturn = flag; }
|
2025-08-01 00:38:50 +02:00
|
|
|
void gotNansiType(bool flag) { m_gotNansiType = flag; }
|
|
|
|
|
bool gotNansiType() { return m_gotNansiType; }
|
2022-09-15 14:10:39 +02:00
|
|
|
void hasStrengthAssignment(bool flag) { m_hasStrengthAssignment = flag; }
|
|
|
|
|
bool hasStrengthAssignment() { return m_hasStrengthAssignment; }
|
|
|
|
|
void isDpiOpenArray(bool flag) { m_isDpiOpenArray = flag; }
|
2022-10-18 23:07:09 +02:00
|
|
|
bool isDpiOpenArray() const VL_MT_SAFE { return m_isDpiOpenArray; }
|
2022-09-15 14:10:39 +02:00
|
|
|
bool isHideLocal() const { return m_isHideLocal; }
|
|
|
|
|
void isHideLocal(bool flag) { m_isHideLocal = flag; }
|
|
|
|
|
bool isHideProtected() const { return m_isHideProtected; }
|
|
|
|
|
void isHideProtected(bool flag) { m_isHideProtected = flag; }
|
|
|
|
|
void noReset(bool flag) { m_noReset = flag; }
|
|
|
|
|
bool noReset() const { return m_noReset; }
|
|
|
|
|
void noSubst(bool flag) { m_noSubst = flag; }
|
|
|
|
|
bool noSubst() const { return m_noSubst; }
|
|
|
|
|
void overriddenParam(bool flag) { m_overridenParam = flag; }
|
|
|
|
|
bool overriddenParam() const { return m_overridenParam; }
|
|
|
|
|
void trace(bool flag) { m_trace = flag; }
|
|
|
|
|
void isLatched(bool flag) { m_isLatched = flag; }
|
|
|
|
|
bool isForceable() const { return m_isForceable; }
|
|
|
|
|
void setForceable() { m_isForceable = true; }
|
2024-05-10 19:19:51 +02:00
|
|
|
void setForcedByCode() { m_isForcedByCode = true; }
|
|
|
|
|
bool isForced() const { return m_isForceable || m_isForcedByCode; }
|
2022-09-15 14:17:00 +02:00
|
|
|
bool isWrittenByDpi() const { return m_isWrittenByDpi; }
|
|
|
|
|
void setWrittenByDpi() { m_isWrittenByDpi = true; }
|
|
|
|
|
bool isWrittenBySuspendable() const { return m_isWrittenBySuspendable; }
|
|
|
|
|
void setWrittenBySuspendable() { m_isWrittenBySuspendable = true; }
|
2025-06-28 21:45:45 +02:00
|
|
|
bool ignorePostRead() const { return m_ignorePostRead; }
|
|
|
|
|
void setIgnorePostRead() { m_ignorePostRead = true; }
|
2024-10-09 12:43:53 +02:00
|
|
|
bool ignorePostWrite() const { return m_ignorePostWrite; }
|
|
|
|
|
void setIgnorePostWrite() { m_ignorePostWrite = true; }
|
2025-03-03 02:02:55 +01:00
|
|
|
bool ignoreSchedWrite() const { return m_ignoreSchedWrite; }
|
|
|
|
|
void setIgnoreSchedWrite() { m_ignoreSchedWrite = true; }
|
Optimize complex combinational logic in DFG (#6298)
This patch adds DfgLogic, which is a vertex that represents a whole,
arbitrarily complex combinational AstAlways or AstAssignW in the
DfgGraph.
Implementing this requires computing the variables live at entry to the
AstAlways (variables read by the block), so there is a new
ControlFlowGraph data structure and a classical data-flow analysis based
live variable analysis to do that at the variable level (as opposed to
bit/element level).
The actual CFG construction and live variable analysis is best effort,
and might fail for currently unhandled constructs or data types. This
can be extended later.
V3DfgAstToDfg is changed to convert the Ast into an initial DfgGraph
containing only DfgLogic, DfgVertexSplice and DfgVertexVar vertices.
The DfgLogic are then subsequently synthesized into primitive operations
by the new V3DfgSynthesize pass, which is a combination of the old
V3DfgAstToDfg conversion and new code to handle AstAlways blocks with
complex flow control.
V3DfgSynthesize by default will synthesize roughly the same constructs
as V3DfgAstToDfg used to handle before, plus any logic that is part of a
combinational cycle within the DfgGraph. This enables breaking up these
cycles, for which there are extensions to V3DfgBreakCycles in this patch
as well. V3DfgSynthesize will then delete all non synthesized or non
synthesizable DfgLogic vertices and the rest of the Dfg pipeline is
identical, with minor changes to adjust for the changed representation.
Because with this change we can now eliminate many more UNOPTFLAT, DFG
has been disabled in all the tests that specifically target testing the
scheduling and reporting of circular combinational logic.
2025-08-19 16:06:38 +02:00
|
|
|
bool dfgMultidriven() const { return m_dfgMultidriven; }
|
|
|
|
|
void setDfgMultidriven() { m_dfgMultidriven = true; }
|
2022-09-15 14:17:00 +02:00
|
|
|
|
2022-09-15 14:10:39 +02:00
|
|
|
// METHODS
|
2022-09-16 12:22:11 +02:00
|
|
|
void name(const string& name) override { m_name = name; }
|
|
|
|
|
void tag(const string& text) override { m_tag = text; }
|
|
|
|
|
string tag() const override { return m_tag; }
|
2022-09-15 14:10:39 +02:00
|
|
|
bool isAnsi() const { return m_ansi; }
|
|
|
|
|
bool isContinuously() const { return m_isContinuously; }
|
|
|
|
|
bool isDeclTyped() const { return m_declTyped; }
|
2024-11-26 00:25:36 +01:00
|
|
|
bool isInout() const { return m_direction.isInout(); }
|
|
|
|
|
bool isInoutOrRef() const { return m_direction.isInoutOrRef(); }
|
2024-08-15 16:04:07 +02:00
|
|
|
bool isInput() const { return m_direction.isInput(); }
|
2022-09-15 14:10:39 +02:00
|
|
|
bool isNonOutput() const { return m_direction.isNonOutput(); }
|
2022-10-18 23:07:09 +02:00
|
|
|
bool isReadOnly() const VL_MT_SAFE { return m_direction.isReadOnly(); }
|
2023-09-20 13:33:11 +02:00
|
|
|
bool isConstRef() const VL_MT_SAFE { return m_direction.isConstRef(); }
|
2023-09-18 15:21:30 +02:00
|
|
|
bool isRef() const VL_MT_SAFE { return m_direction.isRef(); }
|
2022-10-18 23:07:09 +02:00
|
|
|
bool isWritable() const VL_MT_SAFE { return m_direction.isWritable(); }
|
2022-09-15 14:10:39 +02:00
|
|
|
bool isTristate() const { return m_tristate; }
|
2024-09-06 14:04:26 +02:00
|
|
|
bool isPrimaryIO() const VL_MT_SAFE { return m_primaryIO; }
|
2022-09-15 14:10:39 +02:00
|
|
|
bool isPrimaryInish() const { return isPrimaryIO() && isNonOutput(); }
|
2024-11-05 06:17:40 +01:00
|
|
|
bool isIfaceRef() const { return varType() == VVarType::IFACEREF; }
|
2024-12-02 13:21:24 +01:00
|
|
|
void setIfaceRef() {
|
|
|
|
|
m_direction = VDirection::NONE;
|
|
|
|
|
m_varType = VVarType::IFACEREF;
|
|
|
|
|
}
|
2022-09-15 14:10:39 +02:00
|
|
|
bool isIfaceParent() const { return m_isIfaceParent; }
|
2023-09-19 03:17:21 +02:00
|
|
|
bool isInternal() const { return m_isInternal; }
|
2022-09-15 14:10:39 +02:00
|
|
|
bool isSignal() const { return varType().isSignal(); }
|
|
|
|
|
bool isNet() const { return varType().isNet(); }
|
2024-10-09 23:53:46 +02:00
|
|
|
bool isWor() const { return varType().isWor(); }
|
|
|
|
|
bool isWand() const { return varType().isWand(); }
|
|
|
|
|
bool isWiredNet() const { return varType().isWiredNet(); }
|
2022-09-15 14:10:39 +02:00
|
|
|
bool isTemp() const { return varType().isTemp(); }
|
|
|
|
|
bool isToggleCoverable() const {
|
|
|
|
|
return ((isIO() || isSignal())
|
|
|
|
|
&& (isIO() || isBitLogic())
|
|
|
|
|
// Wrapper would otherwise duplicate wrapped module's coverage
|
|
|
|
|
&& !isSc() && !isPrimaryIO() && !isConst() && !isDouble() && !isString());
|
|
|
|
|
}
|
|
|
|
|
bool isClassMember() const { return varType() == VVarType::MEMBER; }
|
2024-11-05 06:17:40 +01:00
|
|
|
bool isStatementTemp() const { return varType() == VVarType::STMTTEMP; }
|
|
|
|
|
bool isXTemp() const { return varType() == VVarType::XTEMP; }
|
2023-08-20 14:55:16 +02:00
|
|
|
bool isParam() const { return varType().isParam(); }
|
2024-11-05 06:17:40 +01:00
|
|
|
bool isGParam() const { return varType() == VVarType::GPARAM; }
|
|
|
|
|
bool isGenVar() const { return varType() == VVarType::GENVAR; }
|
2022-09-15 14:10:39 +02:00
|
|
|
bool isBitLogic() const {
|
2025-08-19 23:02:10 +02:00
|
|
|
const AstBasicDType* const bdtypep = basicp();
|
2022-09-15 14:10:39 +02:00
|
|
|
return bdtypep && bdtypep->isBitLogic();
|
|
|
|
|
}
|
2024-09-06 14:04:26 +02:00
|
|
|
bool isUsedClock() const VL_MT_SAFE { return m_usedClock; }
|
2022-09-15 14:10:39 +02:00
|
|
|
bool isUsedParam() const { return m_usedParam; }
|
|
|
|
|
bool isUsedLoopIdx() const { return m_usedLoopIdx; }
|
2022-10-18 23:07:09 +02:00
|
|
|
bool isSc() const VL_MT_SAFE { return m_sc; }
|
2022-09-15 14:10:39 +02:00
|
|
|
bool isScQuad() const;
|
2024-09-06 14:04:26 +02:00
|
|
|
bool isScBv() const VL_MT_STABLE;
|
2022-09-15 14:10:39 +02:00
|
|
|
bool isScUint() const;
|
2024-06-25 11:27:09 +02:00
|
|
|
bool isScUintBool() const;
|
2024-09-06 14:04:26 +02:00
|
|
|
bool isScBigUint() const VL_MT_STABLE;
|
2022-09-15 14:10:39 +02:00
|
|
|
bool isScSensitive() const { return m_scSensitive; }
|
|
|
|
|
bool isSigPublic() const;
|
2024-12-03 03:12:04 +01:00
|
|
|
bool isSigModPublic() const { return m_sigModPublic && !isIfaceRef(); }
|
|
|
|
|
bool isSigUserRdPublic() const { return m_sigUserRdPublic && !isIfaceRef(); }
|
|
|
|
|
bool isSigUserRWPublic() const { return m_sigUserRWPublic && !isIfaceRef(); }
|
2022-09-15 14:10:39 +02:00
|
|
|
bool isTrace() const { return m_trace; }
|
2024-08-13 20:20:31 +02:00
|
|
|
bool isRand() const { return m_rand.isRand(); }
|
|
|
|
|
bool isRandC() const { return m_rand.isRandC(); }
|
2022-10-18 23:07:09 +02:00
|
|
|
bool isConst() const VL_MT_SAFE { return m_isConst; }
|
|
|
|
|
bool isStatic() const VL_MT_SAFE { return m_isStatic; }
|
2022-09-15 14:10:39 +02:00
|
|
|
bool isLatched() const { return m_isLatched; }
|
|
|
|
|
bool isFuncLocal() const { return m_funcLocal; }
|
2023-06-12 15:24:46 +02:00
|
|
|
bool isFuncLocalSticky() const { return m_funcLocalSticky; }
|
2022-09-15 14:10:39 +02:00
|
|
|
bool isFuncReturn() const { return m_funcReturn; }
|
|
|
|
|
bool isPullup() const { return m_isPullup; }
|
|
|
|
|
bool isPulldown() const { return m_isPulldown; }
|
|
|
|
|
bool attrScBv() const { return m_attrScBv; }
|
|
|
|
|
bool attrFileDescr() const { return m_fileDescr; }
|
|
|
|
|
bool attrScClocked() const { return m_scClocked; }
|
|
|
|
|
bool attrSFormat() const { return m_attrSFormat; }
|
|
|
|
|
bool attrSplitVar() const { return m_attrSplitVar; }
|
|
|
|
|
bool attrIsolateAssign() const { return m_attrIsolateAssign; }
|
2023-12-05 04:11:07 +01:00
|
|
|
AstIface* sensIfacep() const { return m_sensIfacep; }
|
2022-09-15 14:10:39 +02:00
|
|
|
VVarAttrClocker attrClocker() const { return m_attrClocker; }
|
2024-08-13 20:20:31 +02:00
|
|
|
VRandAttr rand() const { return m_rand; }
|
2022-09-16 12:22:11 +02:00
|
|
|
string verilogKwd() const override;
|
2022-09-15 14:10:39 +02:00
|
|
|
void lifetime(const VLifetime& flag) { m_lifetime = flag; }
|
|
|
|
|
VLifetime lifetime() const { return m_lifetime; }
|
2025-02-26 04:48:53 +01:00
|
|
|
void pinNum(int id) { m_pinNum = id; }
|
|
|
|
|
int pinNum() const { return m_pinNum; }
|
2023-09-16 23:37:25 +02:00
|
|
|
void propagateAttrFrom(const AstVar* fromp) {
|
2022-09-15 14:10:39 +02:00
|
|
|
// This is getting connected to fromp; keep attributes
|
|
|
|
|
// Note the method below too
|
|
|
|
|
if (fromp->attrFileDescr()) attrFileDescr(true);
|
|
|
|
|
if (fromp->attrIsolateAssign()) attrIsolateAssign(true);
|
|
|
|
|
if (fromp->isContinuously()) isContinuously(true);
|
|
|
|
|
}
|
2023-09-16 23:37:25 +02:00
|
|
|
void propagateWrapAttrFrom(const AstVar* fromp) {
|
|
|
|
|
// Creating a function wrapper; keep attributes
|
|
|
|
|
propagateAttrFrom(fromp);
|
|
|
|
|
direction(fromp->direction());
|
|
|
|
|
declDirection(fromp->declDirection());
|
|
|
|
|
lifetime(fromp->lifetime());
|
|
|
|
|
}
|
2025-07-27 23:13:56 +02:00
|
|
|
void combineType(const AstVar* otherp);
|
2022-09-15 14:10:39 +02:00
|
|
|
void inlineAttrReset(const string& name) {
|
|
|
|
|
if (direction() == VDirection::INOUT && varType() == VVarType::WIRE) {
|
|
|
|
|
m_varType = VVarType::TRIWIRE;
|
|
|
|
|
}
|
|
|
|
|
m_direction = VDirection::NONE;
|
|
|
|
|
m_name = name;
|
|
|
|
|
}
|
2025-02-26 04:48:53 +01:00
|
|
|
bool needsCReset() const {
|
|
|
|
|
return !isIfaceParent() && !isIfaceRef() && !noReset() && !isParam() && !isStatementTemp()
|
|
|
|
|
&& !(basicp() && (basicp()->isEvent() || basicp()->isTriggerVec()));
|
|
|
|
|
}
|
2022-09-15 14:10:39 +02:00
|
|
|
static AstVar* scVarRecurse(AstNode* nodep);
|
|
|
|
|
};
|
|
|
|
|
class AstVarScope final : public AstNode {
|
|
|
|
|
// A particular scoped usage of a variable
|
|
|
|
|
// That is, as a module is used under multiple cells, we get a different
|
|
|
|
|
// varscope for each var in the module
|
|
|
|
|
// Parents: MODULE
|
|
|
|
|
// Children: none
|
2023-12-01 01:58:16 +01:00
|
|
|
//
|
|
|
|
|
// @astgen ptr := m_scopep : Optional[AstScope] // Scope variable is underneath
|
|
|
|
|
// @astgen ptr := m_varp : Optional[AstVar] // [AfterLink] Pointer to variable itself
|
2022-09-15 14:10:39 +02:00
|
|
|
bool m_trace : 1; // Tracing is turned on for this scope
|
2025-08-19 01:11:14 +02:00
|
|
|
bool m_optimizeLifePost : 1; // One half of an NBA pair using ShadowVariable scheme. Optimize.
|
2022-09-15 14:10:39 +02:00
|
|
|
public:
|
|
|
|
|
AstVarScope(FileLine* fl, AstScope* scopep, AstVar* varp)
|
|
|
|
|
: ASTGEN_SUPER_VarScope(fl)
|
|
|
|
|
, m_scopep{scopep}
|
|
|
|
|
, m_varp{varp} {
|
|
|
|
|
UASSERT_OBJ(scopep, fl, "Scope must be non-null");
|
|
|
|
|
UASSERT_OBJ(varp, fl, "Var must be non-null");
|
|
|
|
|
m_trace = true;
|
2025-08-19 01:11:14 +02:00
|
|
|
m_optimizeLifePost = false;
|
2022-09-15 14:10:39 +02:00
|
|
|
dtypeFrom(varp);
|
|
|
|
|
}
|
2022-10-04 12:03:41 +02:00
|
|
|
ASTGEN_MEMBERS_AstVarScope;
|
2022-09-16 12:22:11 +02:00
|
|
|
void cloneRelink() override {
|
2022-09-15 14:10:39 +02:00
|
|
|
if (m_varp && m_varp->clonep()) {
|
|
|
|
|
UASSERT(m_scopep->clonep(), "No clone cross link: " << this);
|
|
|
|
|
}
|
2023-12-01 01:58:16 +01:00
|
|
|
cloneRelinkGen();
|
2022-09-15 14:10:39 +02:00
|
|
|
}
|
2024-10-01 03:34:34 +02:00
|
|
|
bool maybePointedTo() const override VL_MT_SAFE { return true; }
|
2023-03-18 01:24:15 +01:00
|
|
|
string name() const override VL_MT_STABLE { return scopep()->name() + "->" + varp()->name(); }
|
2022-09-16 12:22:11 +02:00
|
|
|
void dump(std::ostream& str) const override;
|
2024-02-09 23:50:09 +01:00
|
|
|
void dumpJson(std::ostream& str) const override;
|
2024-11-28 20:37:11 +01:00
|
|
|
bool sameNode(const AstNode* samep) const override;
|
2024-10-01 03:34:34 +02:00
|
|
|
bool hasDType() const override VL_MT_SAFE { return true; }
|
2023-04-20 13:02:31 +02:00
|
|
|
AstVar* varp() const VL_MT_STABLE { return m_varp; } // [After Link] Pointer to variable
|
|
|
|
|
AstScope* scopep() const VL_MT_STABLE { return m_scopep; } // Pointer to scope it's under
|
2022-09-15 14:10:39 +02:00
|
|
|
void scopep(AstScope* nodep) { m_scopep = nodep; }
|
|
|
|
|
bool isTrace() const { return m_trace; }
|
|
|
|
|
void trace(bool flag) { m_trace = flag; }
|
2025-08-19 01:11:14 +02:00
|
|
|
bool optimizeLifePost() const { return m_optimizeLifePost; }
|
|
|
|
|
void optimizeLifePost(bool flag) { m_optimizeLifePost = flag; }
|
2022-09-15 14:10:39 +02:00
|
|
|
};
|
|
|
|
|
|
|
|
|
|
// === AstNodeBlock ===
|
|
|
|
|
class AstBegin final : public AstNodeBlock {
|
|
|
|
|
// A Begin/end named block, only exists shortly after parsing until linking
|
|
|
|
|
// Parents: statement
|
2023-09-08 16:40:14 +02:00
|
|
|
// @astgen op1 := genforp : Optional[AstNode]
|
2022-09-15 20:43:56 +02:00
|
|
|
|
2023-10-16 14:02:29 +02:00
|
|
|
bool m_generate : 1; // Underneath a generate
|
|
|
|
|
bool m_needProcess : 1; // Uses VlProcess
|
|
|
|
|
const bool m_implied : 1; // Not inserted by user
|
2022-09-15 14:10:39 +02:00
|
|
|
public:
|
|
|
|
|
// Node that puts name into the output stream
|
|
|
|
|
AstBegin(FileLine* fl, const string& name, AstNode* stmtsp, bool generate = false,
|
|
|
|
|
bool implied = false)
|
|
|
|
|
: ASTGEN_SUPER_Begin(fl, name, stmtsp)
|
|
|
|
|
, m_generate{generate}
|
2023-10-16 14:02:29 +02:00
|
|
|
, m_needProcess{false}
|
2022-09-15 14:10:39 +02:00
|
|
|
, m_implied{implied} {}
|
2022-10-04 12:03:41 +02:00
|
|
|
ASTGEN_MEMBERS_AstBegin;
|
2022-09-16 12:22:11 +02:00
|
|
|
void dump(std::ostream& str) const override;
|
2024-02-09 23:50:09 +01:00
|
|
|
void dumpJson(std::ostream& str) const override;
|
2022-09-15 14:10:39 +02:00
|
|
|
bool generate() const { return m_generate; }
|
2024-06-23 01:50:46 +02:00
|
|
|
void generate(bool flag) { m_generate = flag; }
|
2023-10-16 14:02:29 +02:00
|
|
|
void setNeedProcess() { m_needProcess = true; }
|
|
|
|
|
bool needProcess() const { return m_needProcess; }
|
2022-09-15 14:10:39 +02:00
|
|
|
bool implied() const { return m_implied; }
|
|
|
|
|
};
|
|
|
|
|
class AstFork final : public AstNodeBlock {
|
|
|
|
|
// A fork named block
|
2023-09-08 16:40:14 +02:00
|
|
|
// @astgen op1 := initsp : List[AstNode]
|
2022-09-15 14:10:39 +02:00
|
|
|
// Parents: statement
|
|
|
|
|
// Children: statements
|
|
|
|
|
VJoinType m_joinType; // Join keyword type
|
|
|
|
|
public:
|
|
|
|
|
// Node that puts name into the output stream
|
|
|
|
|
AstFork(FileLine* fl, const string& name, AstNode* stmtsp)
|
|
|
|
|
: ASTGEN_SUPER_Fork(fl, name, stmtsp) {}
|
2022-10-04 12:03:41 +02:00
|
|
|
ASTGEN_MEMBERS_AstFork;
|
2022-09-16 17:15:10 +02:00
|
|
|
bool isTimingControl() const override { return !joinType().joinNone(); }
|
2022-09-16 12:22:11 +02:00
|
|
|
void dump(std::ostream& str) const override;
|
2024-02-09 23:50:09 +01:00
|
|
|
void dumpJson(std::ostream& str) const override;
|
2022-09-15 14:10:39 +02:00
|
|
|
VJoinType joinType() const { return m_joinType; }
|
|
|
|
|
void joinType(const VJoinType& flag) { m_joinType = flag; }
|
|
|
|
|
};
|
|
|
|
|
|
2025-08-19 12:14:17 +02:00
|
|
|
// === AstNodeCoverDecl ===
|
|
|
|
|
class AstCoverOtherDecl final : public AstNodeCoverDecl {
|
|
|
|
|
// Coverage analysis point declaration
|
|
|
|
|
// Used for other than toggle types of coverage
|
|
|
|
|
string m_linescov;
|
|
|
|
|
int m_offset; // Offset column numbers to uniq-ify IFs
|
|
|
|
|
public:
|
|
|
|
|
AstCoverOtherDecl(FileLine* fl, const string& page, const string& comment,
|
|
|
|
|
const string& linescov, int offset)
|
|
|
|
|
: ASTGEN_SUPER_CoverOtherDecl(fl, page, comment)
|
|
|
|
|
, m_linescov{linescov}
|
|
|
|
|
, m_offset{offset} {}
|
|
|
|
|
ASTGEN_MEMBERS_AstCoverOtherDecl;
|
|
|
|
|
void dump(std::ostream& str) const override;
|
|
|
|
|
void dumpJson(std::ostream& str) const override;
|
|
|
|
|
int offset() const { return m_offset; }
|
|
|
|
|
int size() const override { return 1; }
|
|
|
|
|
const string& linescov() const { return m_linescov; }
|
|
|
|
|
bool sameNode(const AstNode* samep) const override {
|
|
|
|
|
const AstCoverOtherDecl* const asamep = VN_DBG_AS(samep, CoverOtherDecl);
|
|
|
|
|
return AstNodeCoverDecl::sameNode(samep) && linescov() == asamep->linescov();
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
class AstCoverToggleDecl final : public AstNodeCoverDecl {
|
|
|
|
|
// Coverage analysis point declaration
|
|
|
|
|
// Used for toggle coverage
|
|
|
|
|
const VNumRange m_range; // Packed array range covering each toggle bit
|
|
|
|
|
public:
|
|
|
|
|
AstCoverToggleDecl(FileLine* fl, const string& page, const string& comment,
|
|
|
|
|
const VNumRange& range)
|
|
|
|
|
: ASTGEN_SUPER_CoverToggleDecl(fl, page, comment)
|
|
|
|
|
, m_range{range} {}
|
|
|
|
|
ASTGEN_MEMBERS_AstCoverToggleDecl;
|
|
|
|
|
void dump(std::ostream& str) const override;
|
|
|
|
|
void dumpJson(std::ostream& str) const override;
|
2025-08-20 13:31:04 +02:00
|
|
|
int size() const override {
|
|
|
|
|
// Changes 0 -> 1 and 1 -> 0 are counted separately
|
|
|
|
|
return 2 * m_range.elements();
|
|
|
|
|
}
|
2025-08-19 12:14:17 +02:00
|
|
|
const VNumRange& range() const { return m_range; }
|
|
|
|
|
bool sameNode(const AstNode* samep) const override {
|
|
|
|
|
const AstCoverToggleDecl* const asamep = VN_DBG_AS(samep, CoverToggleDecl);
|
|
|
|
|
return AstNodeCoverDecl::sameNode(samep) && range() == asamep->range();
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
|
2022-09-15 14:10:39 +02:00
|
|
|
// === AstNodeFTask ===
|
|
|
|
|
class AstFunc final : public AstNodeFTask {
|
|
|
|
|
// A function inside a module
|
|
|
|
|
public:
|
2022-09-15 20:43:56 +02:00
|
|
|
AstFunc(FileLine* fl, const string& name, AstNode* stmtp, AstNode* fvarp)
|
2022-09-15 14:10:39 +02:00
|
|
|
: ASTGEN_SUPER_Func(fl, name, stmtp) {
|
2022-09-15 20:43:56 +02:00
|
|
|
this->fvarp(fvarp);
|
2022-09-15 14:10:39 +02:00
|
|
|
}
|
2022-10-04 12:03:41 +02:00
|
|
|
ASTGEN_MEMBERS_AstFunc;
|
2024-10-01 03:34:34 +02:00
|
|
|
bool hasDType() const override VL_MT_SAFE { return true; }
|
2023-09-16 23:52:02 +02:00
|
|
|
AstNodeFTask* cloneType(const string& name) override {
|
2023-09-16 23:37:25 +02:00
|
|
|
return new AstFunc{fileline(), name, nullptr, nullptr};
|
|
|
|
|
}
|
2025-08-05 23:12:00 +02:00
|
|
|
string verilogKwd() const override { return "function"; }
|
2022-09-15 14:10:39 +02:00
|
|
|
};
|
2023-09-08 03:45:51 +02:00
|
|
|
class AstLet final : public AstNodeFTask {
|
|
|
|
|
// Verilog "let" statement
|
|
|
|
|
// Parents: MODULE
|
2025-02-26 15:08:41 +01:00
|
|
|
// stmtp list first item is returned StmtExpr, as Let always returns AstNodeExpr
|
2023-09-08 03:45:51 +02:00
|
|
|
public:
|
|
|
|
|
AstLet(FileLine* fl, const string& name)
|
|
|
|
|
: ASTGEN_SUPER_Let(fl, name, nullptr) {}
|
|
|
|
|
ASTGEN_MEMBERS_AstLet;
|
2024-10-01 03:34:34 +02:00
|
|
|
bool hasDType() const override VL_MT_SAFE { return true; }
|
2023-09-08 03:45:51 +02:00
|
|
|
const char* broken() const override {
|
|
|
|
|
BROKEN_RTN(!VN_IS(stmtsp(), StmtExpr));
|
|
|
|
|
return nullptr;
|
|
|
|
|
}
|
2023-09-16 23:52:02 +02:00
|
|
|
AstNodeFTask* cloneType(const string& name) override { return new AstLet{fileline(), name}; }
|
2025-08-05 23:12:00 +02:00
|
|
|
string verilogKwd() const override { return "let"; }
|
2023-09-08 03:45:51 +02:00
|
|
|
};
|
2022-11-01 23:53:47 +01:00
|
|
|
class AstProperty final : public AstNodeFTask {
|
|
|
|
|
// A property inside a module
|
|
|
|
|
public:
|
|
|
|
|
AstProperty(FileLine* fl, const string& name, AstNode* stmtp)
|
|
|
|
|
: ASTGEN_SUPER_Property(fl, name, stmtp) {}
|
|
|
|
|
ASTGEN_MEMBERS_AstProperty;
|
2024-10-01 03:34:34 +02:00
|
|
|
bool hasDType() const override VL_MT_SAFE { return true; }
|
2023-09-16 23:52:02 +02:00
|
|
|
AstNodeFTask* cloneType(const string& name) override {
|
2023-09-16 23:37:25 +02:00
|
|
|
return new AstProperty{fileline(), name, nullptr};
|
|
|
|
|
}
|
2025-08-05 23:12:00 +02:00
|
|
|
string verilogKwd() const override { return "property"; }
|
2022-11-01 23:53:47 +01:00
|
|
|
};
|
2022-09-15 14:10:39 +02:00
|
|
|
class AstTask final : public AstNodeFTask {
|
|
|
|
|
// A task inside a module
|
|
|
|
|
public:
|
|
|
|
|
AstTask(FileLine* fl, const string& name, AstNode* stmtp)
|
|
|
|
|
: ASTGEN_SUPER_Task(fl, name, stmtp) {}
|
2022-10-04 12:03:41 +02:00
|
|
|
ASTGEN_MEMBERS_AstTask;
|
2023-09-16 23:52:02 +02:00
|
|
|
AstNodeFTask* cloneType(const string& name) override {
|
|
|
|
|
return new AstTask{fileline(), name, nullptr};
|
|
|
|
|
}
|
2025-08-05 23:12:00 +02:00
|
|
|
string verilogKwd() const override { return "task"; }
|
2022-09-15 14:10:39 +02:00
|
|
|
};
|
|
|
|
|
|
|
|
|
|
// === AstNodeFile ===
|
|
|
|
|
class AstCFile final : public AstNodeFile {
|
|
|
|
|
// C++ output file
|
|
|
|
|
// Parents: NETLIST
|
2024-10-01 03:42:36 +02:00
|
|
|
uint64_t m_complexityScore = 0;
|
2022-09-15 14:10:39 +02:00
|
|
|
bool m_slow : 1; ///< Compile w/o optimization
|
|
|
|
|
bool m_source : 1; ///< Source file (vs header file)
|
|
|
|
|
bool m_support : 1; ///< Support file (non systemc)
|
|
|
|
|
public:
|
|
|
|
|
AstCFile(FileLine* fl, const string& name)
|
|
|
|
|
: ASTGEN_SUPER_CFile(fl, name)
|
|
|
|
|
, m_slow{false}
|
|
|
|
|
, m_source{false}
|
|
|
|
|
, m_support{false} {}
|
2022-10-04 12:03:41 +02:00
|
|
|
ASTGEN_MEMBERS_AstCFile;
|
2022-09-16 12:22:11 +02:00
|
|
|
void dump(std::ostream& str = std::cout) const override;
|
2024-02-09 23:50:09 +01:00
|
|
|
void dumpJson(std::ostream& str = std::cout) const override;
|
2024-10-01 03:42:36 +02:00
|
|
|
uint64_t complexityScore() const { return m_complexityScore; }
|
|
|
|
|
void complexityScore(uint64_t newScore) { m_complexityScore = newScore; }
|
2022-09-15 14:10:39 +02:00
|
|
|
bool slow() const { return m_slow; }
|
|
|
|
|
void slow(bool flag) { m_slow = flag; }
|
|
|
|
|
bool source() const { return m_source; }
|
|
|
|
|
void source(bool flag) { m_source = flag; }
|
|
|
|
|
bool support() const { return m_support; }
|
2022-10-18 23:07:09 +02:00
|
|
|
void support(bool flag) VL_MT_SAFE { m_support = flag; }
|
2022-09-15 14:10:39 +02:00
|
|
|
};
|
|
|
|
|
class AstVFile final : public AstNodeFile {
|
|
|
|
|
// Verilog output file
|
|
|
|
|
// Parents: NETLIST
|
|
|
|
|
public:
|
|
|
|
|
AstVFile(FileLine* fl, const string& name)
|
|
|
|
|
: ASTGEN_SUPER_VFile(fl, name) {}
|
2022-10-04 12:03:41 +02:00
|
|
|
ASTGEN_MEMBERS_AstVFile;
|
2022-09-16 12:22:11 +02:00
|
|
|
void dump(std::ostream& str = std::cout) const override;
|
2024-02-09 23:50:09 +01:00
|
|
|
void dumpJson(std::ostream& str = std::cout) const override;
|
2022-09-15 14:10:39 +02:00
|
|
|
};
|
|
|
|
|
|
|
|
|
|
// === AstNodeModule ===
|
|
|
|
|
class AstClass final : public AstNodeModule {
|
2023-01-28 22:30:47 +01:00
|
|
|
// @astgen op4 := extendsp : List[AstClassExtends]
|
2022-09-15 14:10:39 +02:00
|
|
|
// MEMBERS
|
2023-12-01 01:58:16 +01:00
|
|
|
// @astgen ptr := m_classOrPackagep : Optional[AstClassPackage] // Package to be emitted with
|
2025-07-26 23:11:35 +02:00
|
|
|
uint32_t m_declTokenNum; // Declaration token number
|
2024-03-28 04:57:58 +01:00
|
|
|
VBaseOverride m_baseOverride; // BaseOverride (inital/final/extends)
|
2022-09-15 14:10:39 +02:00
|
|
|
bool m_extended = false; // Is extension or extended by other classes
|
2023-01-28 22:30:47 +01:00
|
|
|
bool m_interfaceClass = false; // Interface class
|
2023-04-01 16:50:27 +02:00
|
|
|
bool m_needRNG = false; // Need RNG, uses srandom/randomize
|
2024-01-24 01:36:11 +01:00
|
|
|
bool m_useVirtualPublic = false; // Subclasses need virtual public as uses interface class
|
|
|
|
|
bool m_virtual = false; // Virtual class
|
2022-09-15 14:10:39 +02:00
|
|
|
|
|
|
|
|
public:
|
2025-06-30 02:17:27 +02:00
|
|
|
AstClass(FileLine* fl, const string& name, const string& libname)
|
2025-07-26 23:11:35 +02:00
|
|
|
: ASTGEN_SUPER_Class(fl, name, libname)
|
|
|
|
|
, m_declTokenNum{fl->tokenNum()} {}
|
2022-10-04 12:03:41 +02:00
|
|
|
ASTGEN_MEMBERS_AstClass;
|
2022-09-16 12:22:11 +02:00
|
|
|
string verilogKwd() const override { return "class"; }
|
2024-10-01 03:34:34 +02:00
|
|
|
bool maybePointedTo() const override VL_MT_SAFE { return true; }
|
2022-09-16 12:22:11 +02:00
|
|
|
void dump(std::ostream& str) const override;
|
2024-02-09 23:50:09 +01:00
|
|
|
void dumpJson(std::ostream& str) const override;
|
2022-09-16 12:22:11 +02:00
|
|
|
bool timescaleMatters() const override { return false; }
|
2024-10-01 03:34:34 +02:00
|
|
|
AstClassPackage* classOrPackagep() const VL_MT_STABLE { return m_classOrPackagep; }
|
2022-09-15 14:10:39 +02:00
|
|
|
void classOrPackagep(AstClassPackage* classpackagep) { m_classOrPackagep = classpackagep; }
|
2024-10-01 03:34:34 +02:00
|
|
|
AstNode* membersp() const VL_MT_STABLE { return stmtsp(); }
|
2023-07-08 18:40:27 +02:00
|
|
|
void addMembersp(AstNode* nodep) { addStmtsp(nodep); }
|
2022-09-15 14:10:39 +02:00
|
|
|
bool isExtended() const { return m_extended; }
|
|
|
|
|
void isExtended(bool flag) { m_extended = flag; }
|
2023-01-28 22:30:47 +01:00
|
|
|
bool isInterfaceClass() const { return m_interfaceClass; }
|
|
|
|
|
void isInterfaceClass(bool flag) { m_interfaceClass = flag; }
|
2022-09-15 14:10:39 +02:00
|
|
|
bool isVirtual() const { return m_virtual; }
|
|
|
|
|
void isVirtual(bool flag) { m_virtual = flag; }
|
2023-04-01 16:50:27 +02:00
|
|
|
bool needRNG() const { return m_needRNG; }
|
|
|
|
|
void needRNG(bool flag) { m_needRNG = flag; }
|
2024-01-24 01:36:11 +01:00
|
|
|
bool useVirtualPublic() const { return m_useVirtualPublic; }
|
|
|
|
|
void useVirtualPublic(bool flag) { m_useVirtualPublic = flag; }
|
2022-09-15 14:10:39 +02:00
|
|
|
// Return true if this class is an extension of base class (SLOW)
|
|
|
|
|
// Accepts nullptrs
|
|
|
|
|
static bool isClassExtendedFrom(const AstClass* refClassp, const AstClass* baseClassp);
|
2025-07-26 23:11:35 +02:00
|
|
|
uint32_t declTokenNum() const override { return m_declTokenNum; }
|
|
|
|
|
void declTokenNumSetMin(uint32_t tokenNum) override {
|
|
|
|
|
m_declTokenNum = std::min(m_declTokenNum, tokenNum);
|
|
|
|
|
}
|
2024-03-28 04:57:58 +01:00
|
|
|
void baseOverride(const VBaseOverride& flag) { m_baseOverride = flag; }
|
|
|
|
|
VBaseOverride baseOverride() const { return m_baseOverride; }
|
2023-04-01 16:50:27 +02:00
|
|
|
// Return the lowest class extended from, or this class
|
|
|
|
|
AstClass* baseMostClassp();
|
2023-07-08 18:27:50 +02:00
|
|
|
static bool isCacheableChild(const AstNode* nodep);
|
2024-07-17 08:21:45 +02:00
|
|
|
// Iterates top level members of the class, taking into account inheritance (starting from the
|
|
|
|
|
// root superclass). Note: after V3Scope, several children are moved under an AstScope and will
|
|
|
|
|
// not be found by this.
|
2024-11-30 02:20:38 +01:00
|
|
|
template <typename T_Callable>
|
|
|
|
|
void foreachMember(const T_Callable& f) {
|
|
|
|
|
using T_Node = typename FunctionArgNoPointerNoCV<T_Callable, 1>::type;
|
2024-07-19 19:03:48 +02:00
|
|
|
static_assert(
|
2024-11-30 02:20:38 +01:00
|
|
|
vlstd::is_invocable<T_Callable, AstClass*, T_Node*>::value
|
2024-07-19 19:03:48 +02:00
|
|
|
&& std::is_base_of<AstNode, T_Node>::value,
|
2024-11-30 02:20:38 +01:00
|
|
|
"T_Callable 'f' must have a signature compatible with 'void(AstClass*, T_Node*)', "
|
2024-07-19 19:03:48 +02:00
|
|
|
"with 'T_Node' being a subtype of 'AstNode'");
|
2025-08-19 23:02:10 +02:00
|
|
|
if (const AstClassExtends* const cextendsp = this->extendsp()) {
|
2024-08-24 00:24:34 +02:00
|
|
|
cextendsp->classp()->foreachMember(f);
|
2024-07-17 08:21:45 +02:00
|
|
|
}
|
|
|
|
|
for (AstNode* stmtp = stmtsp(); stmtp; stmtp = stmtp->nextp()) {
|
2024-08-09 11:05:52 +02:00
|
|
|
if (AstNode::privateTypeTest<T_Node>(stmtp)) f(this, static_cast<T_Node*>(stmtp));
|
2024-07-17 08:21:45 +02:00
|
|
|
}
|
|
|
|
|
}
|
2024-07-19 19:03:48 +02:00
|
|
|
// Same as above, but stops after first match
|
2024-11-30 02:20:38 +01:00
|
|
|
template <typename T_Callable>
|
|
|
|
|
bool existsMember(const T_Callable& p) const {
|
|
|
|
|
using T_Node = typename FunctionArgNoPointerNoCV<T_Callable, 1>::type;
|
|
|
|
|
static_assert(
|
|
|
|
|
vlstd::is_invocable_r<bool, T_Callable, const AstClass*, const T_Node*>::value
|
|
|
|
|
&& std::is_base_of<AstNode, T_Node>::value,
|
|
|
|
|
"Predicate 'p' must have a signature compatible with 'bool(const AstClass*, "
|
|
|
|
|
"const T_Node*)', with 'T_Node' being a subtype of 'AstNode'");
|
2025-08-19 23:02:10 +02:00
|
|
|
if (const AstClassExtends* const cextendsp = this->extendsp()) {
|
2024-08-24 00:24:34 +02:00
|
|
|
if (cextendsp->classp()->existsMember(p)) return true;
|
2024-07-19 19:03:48 +02:00
|
|
|
}
|
|
|
|
|
for (AstNode* stmtp = stmtsp(); stmtp; stmtp = stmtp->nextp()) {
|
2024-08-09 11:05:52 +02:00
|
|
|
if (AstNode::privateTypeTest<T_Node>(stmtp)) {
|
|
|
|
|
if (p(this, static_cast<T_Node*>(stmtp))) return true;
|
2024-07-19 19:03:48 +02:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return false;
|
|
|
|
|
}
|
2022-09-15 14:10:39 +02:00
|
|
|
};
|
|
|
|
|
class AstClassPackage final : public AstNodeModule {
|
|
|
|
|
// The static information portion of a class (treated similarly to a package)
|
2023-12-01 01:58:16 +01:00
|
|
|
//
|
|
|
|
|
// @astgen ptr := m_classp : Optional[AstClass] // Class package this is under
|
|
|
|
|
// // (weak pointer, hard link is other way)
|
2022-09-15 14:10:39 +02:00
|
|
|
public:
|
2025-06-30 02:17:27 +02:00
|
|
|
AstClassPackage(FileLine* fl, const string& name, const string& libname)
|
|
|
|
|
: ASTGEN_SUPER_ClassPackage(fl, name, libname) {}
|
2022-10-04 12:03:41 +02:00
|
|
|
ASTGEN_MEMBERS_AstClassPackage;
|
2022-09-16 12:22:11 +02:00
|
|
|
string verilogKwd() const override { return "classpackage"; }
|
|
|
|
|
bool timescaleMatters() const override { return false; }
|
2022-10-18 23:07:09 +02:00
|
|
|
AstClass* classp() const VL_MT_SAFE { return m_classp; }
|
2022-09-15 14:10:39 +02:00
|
|
|
void classp(AstClass* classp) { m_classp = classp; }
|
|
|
|
|
};
|
|
|
|
|
class AstIface final : public AstNodeModule {
|
|
|
|
|
// A module declaration
|
|
|
|
|
public:
|
2025-06-30 02:17:27 +02:00
|
|
|
AstIface(FileLine* fl, const string& name, const string& libname)
|
|
|
|
|
: ASTGEN_SUPER_Iface(fl, name, libname) {}
|
2022-10-04 12:03:41 +02:00
|
|
|
ASTGEN_MEMBERS_AstIface;
|
2022-09-15 14:10:39 +02:00
|
|
|
// Interfaces have `timescale applicability but lots of code seems to
|
|
|
|
|
// get false warnings if we enable this
|
2022-09-16 12:22:11 +02:00
|
|
|
string verilogKwd() const override { return "interface"; }
|
|
|
|
|
bool timescaleMatters() const override { return false; }
|
2022-09-15 14:10:39 +02:00
|
|
|
};
|
|
|
|
|
class AstModule final : public AstNodeModule {
|
|
|
|
|
// A module declaration
|
2025-08-19 23:02:10 +02:00
|
|
|
const bool m_isChecker; // Module represents a checker
|
|
|
|
|
const bool m_isProgram; // Module represents a program
|
2025-08-22 12:44:35 +02:00
|
|
|
bool m_hasGenericIface = false; // Module contains a generic interface
|
|
|
|
|
|
2025-04-07 05:42:49 +02:00
|
|
|
public:
|
|
|
|
|
class Checker {}; // for constructor type-overload selection
|
|
|
|
|
class Program {}; // for constructor type-overload selection
|
2025-06-30 02:17:27 +02:00
|
|
|
AstModule(FileLine* fl, const string& name, const string& libname)
|
2025-08-19 23:02:10 +02:00
|
|
|
: ASTGEN_SUPER_Module(fl, name, libname)
|
|
|
|
|
, m_isChecker{false}
|
|
|
|
|
, m_isProgram{false} {}
|
2025-06-30 02:17:27 +02:00
|
|
|
AstModule(FileLine* fl, const string& name, const string& libname, Checker)
|
|
|
|
|
: ASTGEN_SUPER_Module(fl, name, libname)
|
2025-08-19 23:02:10 +02:00
|
|
|
, m_isChecker{true}
|
|
|
|
|
, m_isProgram{false} {}
|
2025-06-30 02:17:27 +02:00
|
|
|
AstModule(FileLine* fl, const string& name, const string& libname, Program)
|
|
|
|
|
: ASTGEN_SUPER_Module(fl, name, libname)
|
2025-08-19 23:02:10 +02:00
|
|
|
, m_isChecker{false}
|
2025-04-07 05:42:49 +02:00
|
|
|
, m_isProgram{true} {}
|
2022-10-04 12:03:41 +02:00
|
|
|
ASTGEN_MEMBERS_AstModule;
|
2025-04-07 05:42:49 +02:00
|
|
|
string verilogKwd() const override {
|
|
|
|
|
return m_isChecker ? "checker" : m_isProgram ? "program" : "module";
|
|
|
|
|
}
|
2022-09-16 12:22:11 +02:00
|
|
|
bool timescaleMatters() const override { return true; }
|
2025-04-07 05:42:49 +02:00
|
|
|
bool isChecker() const { return m_isChecker; }
|
|
|
|
|
bool isProgram() const { return m_isProgram; }
|
2025-08-22 12:44:35 +02:00
|
|
|
bool hasGenericIface() const { return m_hasGenericIface; }
|
|
|
|
|
void hasGenericIface(bool hasGenericIface) { m_hasGenericIface = hasGenericIface; }
|
2025-04-07 05:42:49 +02:00
|
|
|
void dump(std::ostream& str) const override;
|
|
|
|
|
void dumpJson(std::ostream& str) const override;
|
2022-09-15 14:10:39 +02:00
|
|
|
};
|
|
|
|
|
class AstNotFoundModule final : public AstNodeModule {
|
|
|
|
|
// A missing module declaration
|
|
|
|
|
public:
|
2025-06-30 02:17:27 +02:00
|
|
|
AstNotFoundModule(FileLine* fl, const string& name, const string& libname)
|
|
|
|
|
: ASTGEN_SUPER_NotFoundModule(fl, name, libname) {}
|
2022-10-04 12:03:41 +02:00
|
|
|
ASTGEN_MEMBERS_AstNotFoundModule;
|
2022-09-16 12:22:11 +02:00
|
|
|
string verilogKwd() const override { return "/*not-found-*/ module"; }
|
|
|
|
|
bool timescaleMatters() const override { return false; }
|
2022-09-15 14:10:39 +02:00
|
|
|
};
|
|
|
|
|
class AstPackage final : public AstNodeModule {
|
|
|
|
|
// A package declaration
|
|
|
|
|
public:
|
2025-06-30 02:17:27 +02:00
|
|
|
AstPackage(FileLine* fl, const string& name, const string& libname)
|
|
|
|
|
: ASTGEN_SUPER_Package(fl, name, libname) {}
|
2022-10-04 12:03:41 +02:00
|
|
|
ASTGEN_MEMBERS_AstPackage;
|
2022-09-16 12:22:11 +02:00
|
|
|
string verilogKwd() const override { return "package"; }
|
|
|
|
|
bool timescaleMatters() const override { return !isDollarUnit(); }
|
2022-09-15 14:10:39 +02:00
|
|
|
static string dollarUnitName() { return AstNode::encodeName("$unit"); }
|
|
|
|
|
bool isDollarUnit() const { return name() == dollarUnitName(); }
|
|
|
|
|
};
|
|
|
|
|
class AstPrimitive final : public AstNodeModule {
|
|
|
|
|
// A primitive declaration
|
|
|
|
|
public:
|
2025-06-30 02:17:27 +02:00
|
|
|
AstPrimitive(FileLine* fl, const string& name, const string& libname)
|
|
|
|
|
: ASTGEN_SUPER_Primitive(fl, name, libname) {}
|
2022-10-04 12:03:41 +02:00
|
|
|
ASTGEN_MEMBERS_AstPrimitive;
|
2022-09-16 12:22:11 +02:00
|
|
|
string verilogKwd() const override { return "primitive"; }
|
|
|
|
|
bool timescaleMatters() const override { return false; }
|
2022-09-15 14:10:39 +02:00
|
|
|
};
|
|
|
|
|
|
|
|
|
|
// === AstNodeProcedure ===
|
|
|
|
|
class AstAlways final : public AstNodeProcedure {
|
2025-08-18 01:14:34 +02:00
|
|
|
// @astgen op1 := sentreep : Optional[AstSenTree] // Sensitivity list iff clocked
|
2022-09-15 14:10:39 +02:00
|
|
|
const VAlwaysKwd m_keyword;
|
|
|
|
|
|
|
|
|
|
public:
|
2025-08-18 01:14:34 +02:00
|
|
|
AstAlways(FileLine* fl, VAlwaysKwd keyword, AstSenTree* sentreep, AstNode* stmtsp)
|
2022-09-15 20:43:56 +02:00
|
|
|
: ASTGEN_SUPER_Always(fl, stmtsp)
|
2022-09-15 14:10:39 +02:00
|
|
|
, m_keyword{keyword} {
|
2025-08-18 01:14:34 +02:00
|
|
|
this->sentreep(sentreep);
|
2022-09-15 14:10:39 +02:00
|
|
|
}
|
2022-10-04 12:03:41 +02:00
|
|
|
ASTGEN_MEMBERS_AstAlways;
|
2022-09-15 14:10:39 +02:00
|
|
|
//
|
2022-09-16 12:22:11 +02:00
|
|
|
void dump(std::ostream& str) const override;
|
2024-02-09 23:50:09 +01:00
|
|
|
void dumpJson(std::ostream& str) const override;
|
2022-09-15 14:10:39 +02:00
|
|
|
VAlwaysKwd keyword() const { return m_keyword; }
|
|
|
|
|
};
|
2022-12-23 13:34:49 +01:00
|
|
|
class AstAlwaysObserved final : public AstNodeProcedure {
|
|
|
|
|
// Like always but Observed scheduling region
|
2025-08-18 01:14:34 +02:00
|
|
|
// @astgen op1 := sentreep : Optional[AstSenTree] // Sensitivity list, removed in V3Active
|
2022-12-23 13:34:49 +01:00
|
|
|
|
|
|
|
|
public:
|
2025-08-18 01:14:34 +02:00
|
|
|
AstAlwaysObserved(FileLine* fl, AstSenTree* sentreep, AstNode* bodysp)
|
2022-12-23 13:34:49 +01:00
|
|
|
: ASTGEN_SUPER_AlwaysObserved(fl, bodysp) {
|
2025-08-18 01:14:34 +02:00
|
|
|
this->sentreep(sentreep);
|
2022-12-23 13:34:49 +01:00
|
|
|
}
|
|
|
|
|
ASTGEN_MEMBERS_AstAlwaysObserved;
|
|
|
|
|
};
|
2022-09-15 14:10:39 +02:00
|
|
|
class AstAlwaysPost final : public AstNodeProcedure {
|
2024-05-02 00:06:25 +02:00
|
|
|
// Like always but 'post' scheduled, e.g. for array NBA commits
|
|
|
|
|
|
2022-09-15 14:10:39 +02:00
|
|
|
public:
|
2024-06-14 03:29:03 +02:00
|
|
|
explicit AstAlwaysPost(FileLine* fl)
|
2024-05-02 00:06:25 +02:00
|
|
|
: ASTGEN_SUPER_AlwaysPost(fl, nullptr) {}
|
2022-10-04 12:03:41 +02:00
|
|
|
ASTGEN_MEMBERS_AstAlwaysPost;
|
2022-09-15 14:10:39 +02:00
|
|
|
};
|
|
|
|
|
class AstAlwaysPostponed final : public AstNodeProcedure {
|
2022-10-13 21:04:43 +02:00
|
|
|
// Like always but Postponed scheduling region
|
2022-09-15 14:10:39 +02:00
|
|
|
|
|
|
|
|
public:
|
2022-09-15 20:43:56 +02:00
|
|
|
AstAlwaysPostponed(FileLine* fl, AstNode* stmtsp)
|
|
|
|
|
: ASTGEN_SUPER_AlwaysPostponed(fl, stmtsp) {}
|
2022-10-04 12:03:41 +02:00
|
|
|
ASTGEN_MEMBERS_AstAlwaysPostponed;
|
2022-09-15 14:10:39 +02:00
|
|
|
};
|
2025-08-19 10:27:59 +02:00
|
|
|
class AstAlwaysPre final : public AstNodeProcedure {
|
|
|
|
|
// Like always but 'pre' scheduled, e.g. for implementing NBAs
|
|
|
|
|
|
|
|
|
|
public:
|
|
|
|
|
explicit AstAlwaysPre(FileLine* fl)
|
|
|
|
|
: ASTGEN_SUPER_AlwaysPre(fl, nullptr) {}
|
|
|
|
|
ASTGEN_MEMBERS_AstAlwaysPre;
|
|
|
|
|
};
|
2022-12-23 13:34:49 +01:00
|
|
|
class AstAlwaysReactive final : public AstNodeProcedure {
|
|
|
|
|
// Like always but Reactive scheduling region
|
2025-08-18 01:14:34 +02:00
|
|
|
// @astgen op1 := sentreep : Optional[AstSenTree] // Sensitivity list, removed in V3Active
|
2022-12-23 13:34:49 +01:00
|
|
|
|
|
|
|
|
public:
|
2025-08-18 01:14:34 +02:00
|
|
|
AstAlwaysReactive(FileLine* fl, AstSenTree* sentreep, AstNode* bodysp)
|
2022-12-23 13:34:49 +01:00
|
|
|
: ASTGEN_SUPER_AlwaysReactive(fl, bodysp) {
|
2025-08-18 01:14:34 +02:00
|
|
|
this->sentreep(sentreep);
|
2022-12-23 13:34:49 +01:00
|
|
|
}
|
|
|
|
|
ASTGEN_MEMBERS_AstAlwaysReactive;
|
|
|
|
|
};
|
2022-09-15 14:10:39 +02:00
|
|
|
class AstFinal final : public AstNodeProcedure {
|
|
|
|
|
public:
|
2022-09-15 20:43:56 +02:00
|
|
|
AstFinal(FileLine* fl, AstNode* stmtsp)
|
|
|
|
|
: ASTGEN_SUPER_Final(fl, stmtsp) {}
|
2022-10-04 12:03:41 +02:00
|
|
|
ASTGEN_MEMBERS_AstFinal;
|
2022-09-15 14:10:39 +02:00
|
|
|
};
|
|
|
|
|
class AstInitial final : public AstNodeProcedure {
|
|
|
|
|
public:
|
2022-09-15 20:43:56 +02:00
|
|
|
AstInitial(FileLine* fl, AstNode* stmtsp)
|
|
|
|
|
: ASTGEN_SUPER_Initial(fl, stmtsp) {}
|
2022-10-04 12:03:41 +02:00
|
|
|
ASTGEN_MEMBERS_AstInitial;
|
2022-09-15 14:10:39 +02:00
|
|
|
};
|
|
|
|
|
class AstInitialAutomatic final : public AstNodeProcedure {
|
|
|
|
|
// Automatic variable initialization
|
|
|
|
|
// That is, it runs every function start, or class construction
|
|
|
|
|
public:
|
2022-09-15 20:43:56 +02:00
|
|
|
AstInitialAutomatic(FileLine* fl, AstNode* stmtsp)
|
|
|
|
|
: ASTGEN_SUPER_InitialAutomatic(fl, stmtsp) {}
|
2022-10-04 12:03:41 +02:00
|
|
|
ASTGEN_MEMBERS_AstInitialAutomatic;
|
2022-09-15 14:10:39 +02:00
|
|
|
};
|
|
|
|
|
class AstInitialStatic final : public AstNodeProcedure {
|
|
|
|
|
// Static variable initialization
|
|
|
|
|
// That is, it runs at the beginning of simulation, before 'initial' blocks
|
|
|
|
|
public:
|
2022-09-15 20:43:56 +02:00
|
|
|
AstInitialStatic(FileLine* fl, AstNode* stmtsp)
|
|
|
|
|
: ASTGEN_SUPER_InitialStatic(fl, stmtsp) {}
|
2022-10-04 12:03:41 +02:00
|
|
|
ASTGEN_MEMBERS_AstInitialStatic;
|
2022-09-15 14:10:39 +02:00
|
|
|
};
|
|
|
|
|
|
|
|
|
|
// === AstNodeRange ===
|
|
|
|
|
class AstBracketRange final : public AstNodeRange {
|
2022-12-10 03:06:27 +01:00
|
|
|
// Parser only concept "[lhsp]", an AstUnknownRange, QueueRange or Range,
|
2022-09-15 14:10:39 +02:00
|
|
|
// unknown until lhsp type is determined
|
2024-10-01 04:25:28 +02:00
|
|
|
// @astgen op1 := elementsp : AstNode<AstNodeExpr|AstNodeDType>
|
2022-09-15 14:10:39 +02:00
|
|
|
public:
|
|
|
|
|
AstBracketRange(FileLine* fl, AstNode* elementsp)
|
|
|
|
|
: ASTGEN_SUPER_BracketRange(fl) {
|
2022-09-15 20:43:56 +02:00
|
|
|
this->elementsp(elementsp);
|
2022-09-15 14:10:39 +02:00
|
|
|
}
|
2022-10-04 12:03:41 +02:00
|
|
|
ASTGEN_MEMBERS_AstBracketRange;
|
2022-09-15 14:10:39 +02:00
|
|
|
virtual string emitC() { V3ERROR_NA_RETURN(""); }
|
|
|
|
|
virtual string emitVerilog() { V3ERROR_NA_RETURN(""); }
|
2024-11-28 20:37:11 +01:00
|
|
|
bool sameNode(const AstNode* /*samep*/) const override { return true; }
|
2022-09-15 14:10:39 +02:00
|
|
|
// Will be removed in V3Width, which relies on this
|
|
|
|
|
// being a child not a dtype pointed node
|
2024-10-01 03:34:34 +02:00
|
|
|
bool maybePointedTo() const override VL_MT_SAFE { return false; }
|
2022-09-15 14:10:39 +02:00
|
|
|
};
|
|
|
|
|
class AstRange final : public AstNodeRange {
|
|
|
|
|
// Range specification, for use under variables and cells
|
2022-11-13 21:33:11 +01:00
|
|
|
// @astgen op1 := leftp : AstNodeExpr
|
|
|
|
|
// @astgen op2 := rightp : AstNodeExpr
|
2022-09-15 14:10:39 +02:00
|
|
|
public:
|
2022-11-13 21:33:11 +01:00
|
|
|
AstRange(FileLine* fl, AstNodeExpr* leftp, AstNodeExpr* rightp)
|
2022-09-15 14:10:39 +02:00
|
|
|
: ASTGEN_SUPER_Range(fl) {
|
2022-09-15 20:43:56 +02:00
|
|
|
this->leftp(leftp);
|
|
|
|
|
this->rightp(rightp);
|
2022-09-15 14:10:39 +02:00
|
|
|
}
|
|
|
|
|
inline AstRange(FileLine* fl, int left, int right);
|
|
|
|
|
inline AstRange(FileLine* fl, const VNumRange& range);
|
2022-10-04 12:03:41 +02:00
|
|
|
ASTGEN_MEMBERS_AstRange;
|
2023-03-17 00:48:56 +01:00
|
|
|
inline int leftConst() const VL_MT_STABLE;
|
|
|
|
|
inline int rightConst() const VL_MT_STABLE;
|
|
|
|
|
int hiConst() const VL_MT_STABLE {
|
2022-09-15 14:10:39 +02:00
|
|
|
const int l = leftConst();
|
|
|
|
|
const int r = rightConst();
|
|
|
|
|
return l > r ? l : r;
|
|
|
|
|
}
|
2023-03-17 00:48:56 +01:00
|
|
|
int loConst() const VL_MT_STABLE {
|
2022-09-15 14:10:39 +02:00
|
|
|
const int l = leftConst();
|
|
|
|
|
const int r = rightConst();
|
|
|
|
|
return l > r ? r : l;
|
|
|
|
|
}
|
2023-03-17 00:48:56 +01:00
|
|
|
int elementsConst() const VL_MT_STABLE { return hiConst() - loConst() + 1; }
|
2023-03-21 01:44:11 +01:00
|
|
|
bool ascending() const { return leftConst() < rightConst(); }
|
2022-09-16 12:22:11 +02:00
|
|
|
void dump(std::ostream& str) const override;
|
2024-02-09 23:50:09 +01:00
|
|
|
void dumpJson(std::ostream& str) const override;
|
2022-09-15 14:10:39 +02:00
|
|
|
virtual string emitC() { V3ERROR_NA_RETURN(""); }
|
2024-11-28 20:37:11 +01:00
|
|
|
bool sameNode(const AstNode* /*samep*/) const override { return true; }
|
2022-09-15 14:10:39 +02:00
|
|
|
};
|
|
|
|
|
class AstUnsizedRange final : public AstNodeRange {
|
|
|
|
|
// Unsized range specification, for open arrays
|
|
|
|
|
public:
|
|
|
|
|
explicit AstUnsizedRange(FileLine* fl)
|
|
|
|
|
: ASTGEN_SUPER_UnsizedRange(fl) {}
|
2022-10-04 12:03:41 +02:00
|
|
|
ASTGEN_MEMBERS_AstUnsizedRange;
|
2022-09-15 14:10:39 +02:00
|
|
|
virtual string emitC() { V3ERROR_NA_RETURN(""); }
|
|
|
|
|
virtual string emitVerilog() { return "[]"; }
|
2024-11-28 20:37:11 +01:00
|
|
|
bool sameNode(const AstNode* /*samep*/) const override { return true; }
|
2022-09-15 14:10:39 +02:00
|
|
|
};
|
|
|
|
|
class AstWildcardRange final : public AstNodeRange {
|
|
|
|
|
// Wildcard range specification, for wildcard index type associative arrays
|
|
|
|
|
public:
|
|
|
|
|
explicit AstWildcardRange(FileLine* fl)
|
|
|
|
|
: ASTGEN_SUPER_WildcardRange(fl) {}
|
2022-10-04 12:03:41 +02:00
|
|
|
ASTGEN_MEMBERS_AstWildcardRange;
|
2022-09-15 14:10:39 +02:00
|
|
|
virtual string emitC() { V3ERROR_NA_RETURN(""); }
|
|
|
|
|
virtual string emitVerilog() { return "[*]"; }
|
2024-11-28 20:37:11 +01:00
|
|
|
bool sameNode(const AstNode* /*samep*/) const override { return true; }
|
2022-09-15 14:10:39 +02:00
|
|
|
};
|
|
|
|
|
|
|
|
|
|
// === AstNodeText ===
|
|
|
|
|
class AstScCtor final : public AstNodeText {
|
|
|
|
|
public:
|
|
|
|
|
AstScCtor(FileLine* fl, const string& textp)
|
|
|
|
|
: ASTGEN_SUPER_ScCtor(fl, textp) {}
|
2022-10-04 12:03:41 +02:00
|
|
|
ASTGEN_MEMBERS_AstScCtor;
|
2023-09-18 15:21:30 +02:00
|
|
|
bool isPure() override { return false; } // SPECIAL: User may order w/other sigs
|
|
|
|
|
bool isOutputter() override { return true; }
|
2022-09-15 14:10:39 +02:00
|
|
|
};
|
|
|
|
|
class AstScDtor final : public AstNodeText {
|
|
|
|
|
public:
|
|
|
|
|
AstScDtor(FileLine* fl, const string& textp)
|
|
|
|
|
: ASTGEN_SUPER_ScDtor(fl, textp) {}
|
2022-10-04 12:03:41 +02:00
|
|
|
ASTGEN_MEMBERS_AstScDtor;
|
2023-09-18 15:21:30 +02:00
|
|
|
bool isPure() override { return false; } // SPECIAL: User may order w/other sigs
|
|
|
|
|
bool isOutputter() override { return true; }
|
2022-09-15 14:10:39 +02:00
|
|
|
};
|
|
|
|
|
class AstScHdr final : public AstNodeText {
|
|
|
|
|
public:
|
|
|
|
|
AstScHdr(FileLine* fl, const string& textp)
|
|
|
|
|
: ASTGEN_SUPER_ScHdr(fl, textp) {}
|
2022-10-04 12:03:41 +02:00
|
|
|
ASTGEN_MEMBERS_AstScHdr;
|
2023-09-18 15:21:30 +02:00
|
|
|
bool isPure() override { return false; } // SPECIAL: User may order w/other sigs
|
|
|
|
|
bool isOutputter() override { return true; }
|
2022-09-15 14:10:39 +02:00
|
|
|
};
|
2025-03-29 03:24:39 +01:00
|
|
|
class AstScHdrPost final : public AstNodeText {
|
|
|
|
|
public:
|
|
|
|
|
AstScHdrPost(FileLine* fl, const string& textp)
|
|
|
|
|
: ASTGEN_SUPER_ScHdrPost(fl, textp) {}
|
|
|
|
|
ASTGEN_MEMBERS_AstScHdrPost;
|
|
|
|
|
bool isPure() override { return false; } // SPECIAL: User may order w/other sigs
|
|
|
|
|
bool isOutputter() override { return true; }
|
|
|
|
|
};
|
2022-09-15 14:10:39 +02:00
|
|
|
class AstScImp final : public AstNodeText {
|
|
|
|
|
public:
|
|
|
|
|
AstScImp(FileLine* fl, const string& textp)
|
|
|
|
|
: ASTGEN_SUPER_ScImp(fl, textp) {}
|
2022-10-04 12:03:41 +02:00
|
|
|
ASTGEN_MEMBERS_AstScImp;
|
2023-09-18 15:21:30 +02:00
|
|
|
bool isPure() override { return false; } // SPECIAL: User may order w/other sigs
|
|
|
|
|
bool isOutputter() override { return true; }
|
2022-09-15 14:10:39 +02:00
|
|
|
};
|
|
|
|
|
class AstScImpHdr final : public AstNodeText {
|
|
|
|
|
public:
|
|
|
|
|
AstScImpHdr(FileLine* fl, const string& textp)
|
|
|
|
|
: ASTGEN_SUPER_ScImpHdr(fl, textp) {}
|
2022-10-04 12:03:41 +02:00
|
|
|
ASTGEN_MEMBERS_AstScImpHdr;
|
2023-09-18 15:21:30 +02:00
|
|
|
bool isPure() override { return false; } // SPECIAL: User may order w/other sigs
|
|
|
|
|
bool isOutputter() override { return true; }
|
2022-09-15 14:10:39 +02:00
|
|
|
};
|
|
|
|
|
class AstScInt final : public AstNodeText {
|
|
|
|
|
public:
|
|
|
|
|
AstScInt(FileLine* fl, const string& textp)
|
|
|
|
|
: ASTGEN_SUPER_ScInt(fl, textp) {}
|
2022-10-04 12:03:41 +02:00
|
|
|
ASTGEN_MEMBERS_AstScInt;
|
2023-09-18 15:21:30 +02:00
|
|
|
bool isPure() override { return false; } // SPECIAL: User may order w/other sigs
|
|
|
|
|
bool isOutputter() override { return true; }
|
2022-09-15 14:10:39 +02:00
|
|
|
};
|
|
|
|
|
|
|
|
|
|
// === AstNodeSimpleText ===
|
|
|
|
|
class AstText final : public AstNodeSimpleText {
|
|
|
|
|
public:
|
|
|
|
|
AstText(FileLine* fl, const string& textp, bool tracking = false)
|
|
|
|
|
: ASTGEN_SUPER_Text(fl, textp, tracking) {}
|
2022-10-04 12:03:41 +02:00
|
|
|
ASTGEN_MEMBERS_AstText;
|
2022-09-15 14:10:39 +02:00
|
|
|
};
|
|
|
|
|
class AstTextBlock final : public AstNodeSimpleText {
|
2022-09-15 20:43:56 +02:00
|
|
|
// @astgen op1 := nodesp : List[AstNode]
|
2022-09-15 14:10:39 +02:00
|
|
|
bool m_commas; // Comma separate emitted children
|
|
|
|
|
public:
|
|
|
|
|
explicit AstTextBlock(FileLine* fl, const string& textp = "", bool tracking = false,
|
|
|
|
|
bool commas = false)
|
|
|
|
|
: ASTGEN_SUPER_TextBlock(fl, textp, tracking)
|
2025-07-04 00:59:32 +02:00
|
|
|
, m_commas{commas} {}
|
2022-10-04 12:03:41 +02:00
|
|
|
ASTGEN_MEMBERS_AstTextBlock;
|
2022-09-15 14:10:39 +02:00
|
|
|
bool commas() const { return m_commas; }
|
2024-06-23 01:50:46 +02:00
|
|
|
void commas(bool flag) { m_commas = flag; }
|
2022-09-15 14:10:39 +02:00
|
|
|
void addText(FileLine* fl, const string& textp, bool tracking = false) {
|
2022-11-20 21:06:49 +01:00
|
|
|
addNodesp(new AstText{fl, textp, tracking});
|
2022-09-15 14:10:39 +02:00
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
#endif // Guard
|