2012-04-13 03:08:20 +02:00
|
|
|
// -*- mode: C++; c-file-style: "cc-mode" -*-
|
2006-08-26 13:35:28 +02:00
|
|
|
//*************************************************************************
|
|
|
|
|
// DESCRIPTION: Verilator: Ast node structure
|
|
|
|
|
//
|
2019-11-08 04:33:59 +01:00
|
|
|
// Code available from: https://verilator.org
|
2006-08-26 13:35:28 +02:00
|
|
|
//
|
|
|
|
|
//*************************************************************************
|
|
|
|
|
//
|
2022-01-01 14:26:40 +01:00
|
|
|
// Copyright 2003-2022 by Wilson Snyder. This program is free software; you
|
2020-03-21 16:24:24 +01:00
|
|
|
// can redistribute it and/or modify it under the terms of either the GNU
|
2009-05-04 23:07:57 +02:00
|
|
|
// Lesser General Public License Version 3 or the Perl Artistic License
|
|
|
|
|
// Version 2.0.
|
2020-03-21 16:24:24 +01:00
|
|
|
// SPDX-License-Identifier: LGPL-3.0-only OR Artistic-2.0
|
2006-08-26 13:35:28 +02:00
|
|
|
//
|
|
|
|
|
//*************************************************************************
|
2019-10-05 02:17:11 +02:00
|
|
|
|
2021-03-04 03:57:07 +01:00
|
|
|
#ifndef VERILATOR_V3AST_H_
|
|
|
|
|
#define VERILATOR_V3AST_H_
|
2018-10-14 19:43:24 +02:00
|
|
|
|
2006-12-18 20:20:45 +01:00
|
|
|
#include "config_build.h"
|
|
|
|
|
#include "verilatedos.h"
|
2018-10-14 19:43:24 +02:00
|
|
|
|
2006-08-26 13:35:28 +02:00
|
|
|
#include "V3Error.h"
|
2014-11-22 17:48:39 +01:00
|
|
|
#include "V3FileLine.h"
|
2006-08-26 13:35:28 +02:00
|
|
|
#include "V3Number.h"
|
2011-11-30 04:09:50 +01:00
|
|
|
#include "V3Global.h"
|
2021-07-10 17:13:05 +02:00
|
|
|
#include "V3Broken.h"
|
2018-10-14 19:43:24 +02:00
|
|
|
|
2011-09-29 03:35:16 +02:00
|
|
|
#include <cmath>
|
2021-06-17 18:27:45 +02:00
|
|
|
#include <type_traits>
|
2020-08-15 16:03:34 +02:00
|
|
|
#include <unordered_set>
|
2006-08-26 13:35:28 +02:00
|
|
|
|
2019-05-19 22:13:13 +02:00
|
|
|
#include "V3Ast__gen_classes.h" // From ./astgen
|
2006-08-26 13:35:28 +02:00
|
|
|
// Things like:
|
|
|
|
|
// class V3AstNode;
|
|
|
|
|
|
2018-07-23 02:54:28 +02:00
|
|
|
// Forward declarations
|
|
|
|
|
class V3Graph;
|
|
|
|
|
class ExecMTask;
|
|
|
|
|
|
2009-11-05 04:31:53 +01:00
|
|
|
// Hint class so we can choose constructors
|
2012-03-31 17:10:34 +02:00
|
|
|
class VFlagLogicPacked {};
|
|
|
|
|
class VFlagBitPacked {};
|
2012-03-31 17:22:19 +02:00
|
|
|
class VFlagChildDType {}; // Used by parser.y to select constructor that sets childDType
|
2009-11-05 04:31:53 +01:00
|
|
|
|
2018-07-23 02:54:28 +02:00
|
|
|
// Used as key for another map, needs operator<, hence not an unordered_set
|
2021-03-13 00:10:45 +01:00
|
|
|
using MTaskIdSet = std::set<int>; // Set of mtaskIds for Var sorting
|
2018-07-23 02:54:28 +02:00
|
|
|
|
2018-07-14 23:27:05 +02:00
|
|
|
//######################################################################
|
|
|
|
|
|
2013-05-25 23:05:22 +02:00
|
|
|
// For broken() function, return error string if have a match
|
2020-01-20 22:53:27 +01:00
|
|
|
#define BROKEN_RTN(test) \
|
|
|
|
|
do { \
|
2021-07-11 15:40:41 +02:00
|
|
|
if (VL_UNCOVERABLE(test)) return "'" #test "' @ " __FILE__ ":" VL_STRINGIFY(__LINE__); \
|
2020-04-04 04:31:54 +02:00
|
|
|
} while (false)
|
2020-03-07 18:52:11 +01:00
|
|
|
// For broken() function, return error string if a base of this class has a match
|
|
|
|
|
#define BROKEN_BASE_RTN(test) \
|
|
|
|
|
do { \
|
2021-11-13 19:50:44 +01:00
|
|
|
const char* const reasonp = (test); \
|
2020-03-07 18:52:11 +01:00
|
|
|
if (VL_UNCOVERABLE(reasonp)) return reasonp; \
|
2020-04-04 04:31:54 +02:00
|
|
|
} while (false)
|
2013-05-25 23:05:22 +02:00
|
|
|
|
2021-10-22 16:15:42 +02:00
|
|
|
// (V)erilator (N)ode is: Returns true if and only if AstNode is of the given AstNode subtype,
|
|
|
|
|
// and not nullptr.
|
2021-10-22 18:36:58 +02:00
|
|
|
#define VN_IS(nodep, nodetypename) (AstNode::privateIs<Ast##nodetypename, decltype(nodep)>(nodep))
|
2018-02-02 03:32:58 +01:00
|
|
|
|
2021-10-22 16:15:42 +02:00
|
|
|
// (V)erilator (N)ode cast: Similar to dynamic_cast, but more efficient, use this instead.
|
|
|
|
|
// Cast to given type if node is of such type, otherwise returns nullptr. If 'nodep' is nullptr,
|
|
|
|
|
// return nullptr. Pointer constness is preserved, i.e.: given a 'const AstNode*',
|
|
|
|
|
// a 'const Ast<nodetypename>*' is returned.
|
2021-10-22 18:36:58 +02:00
|
|
|
#define VN_CAST(nodep, nodetypename) \
|
|
|
|
|
(AstNode::privateCast<Ast##nodetypename, decltype(nodep)>(nodep))
|
2018-02-02 03:32:58 +01:00
|
|
|
|
2021-10-22 16:15:42 +02:00
|
|
|
// (V)erilator (N)ode as: Assert node is of given type then cast to that type. Use this to
|
|
|
|
|
// downcast instead of VN_CAST when you know the true type of the node. If 'nodep' is nullptr,
|
|
|
|
|
// return nullptr. Pointer constness is preserved, i.e.: given a 'const AstNode*', a 'const
|
|
|
|
|
// Ast<nodetypename>*' is returned.
|
2021-10-22 18:36:58 +02:00
|
|
|
#define VN_AS(nodep, nodetypename) (AstNode::privateAs<Ast##nodetypename, decltype(nodep)>(nodep))
|
2021-10-16 20:29:38 +02:00
|
|
|
|
|
|
|
|
// (V)erilator (N)ode deleted: Pointer to deleted AstNode (for assertions only)
|
2019-08-04 03:49:39 +02:00
|
|
|
#define VN_DELETED(nodep) VL_UNLIKELY((vluint64_t)(nodep) == 0x1)
|
|
|
|
|
|
2018-02-02 03:32:58 +01:00
|
|
|
//######################################################################
|
|
|
|
|
|
2020-11-19 03:32:16 +01:00
|
|
|
class AstType final {
|
2006-08-26 13:35:28 +02:00
|
|
|
public:
|
2019-05-19 22:13:13 +02:00
|
|
|
#include "V3Ast__gen_types.h" // From ./astgen
|
2006-08-26 13:35:28 +02:00
|
|
|
// Above include has:
|
|
|
|
|
// enum en {...};
|
|
|
|
|
// const char* ascii() const {...};
|
|
|
|
|
enum en m_e;
|
2019-09-09 13:50:21 +02:00
|
|
|
// cppcheck-suppress uninitVar // responsibility of each subclass
|
2018-08-25 15:52:45 +02:00
|
|
|
inline AstType() {}
|
2015-10-04 04:33:06 +02:00
|
|
|
// cppcheck-suppress noExplicitConstructor
|
2020-04-15 13:58:34 +02:00
|
|
|
inline AstType(en _e)
|
2020-08-16 17:40:42 +02:00
|
|
|
: m_e{_e} {}
|
2020-04-15 13:58:34 +02:00
|
|
|
explicit inline AstType(int _e)
|
2020-08-18 14:10:44 +02:00
|
|
|
: m_e(static_cast<en>(_e)) {} // Need () or GCC 4.8 false warning
|
2018-08-25 15:52:45 +02:00
|
|
|
operator en() const { return m_e; }
|
2020-02-02 16:34:29 +01:00
|
|
|
};
|
|
|
|
|
inline bool operator==(const AstType& lhs, const AstType& rhs) { return lhs.m_e == rhs.m_e; }
|
|
|
|
|
inline bool operator==(const AstType& lhs, AstType::en rhs) { return lhs.m_e == rhs; }
|
|
|
|
|
inline bool operator==(AstType::en lhs, const AstType& rhs) { return lhs == rhs.m_e; }
|
|
|
|
|
inline std::ostream& operator<<(std::ostream& os, const AstType& rhs) { return os << rhs.ascii(); }
|
2006-08-26 13:35:28 +02:00
|
|
|
|
|
|
|
|
//######################################################################
|
|
|
|
|
|
2020-11-19 03:32:16 +01:00
|
|
|
class VLifetime final {
|
2020-04-26 18:45:06 +02:00
|
|
|
public:
|
2020-08-16 18:05:35 +02:00
|
|
|
enum en : uint8_t { NONE, AUTOMATIC, STATIC };
|
2020-04-26 18:45:06 +02:00
|
|
|
enum en m_e;
|
|
|
|
|
const char* ascii() const {
|
|
|
|
|
static const char* const names[] = {"NONE", "VAUTOM", "VSTATIC"};
|
|
|
|
|
return names[m_e];
|
|
|
|
|
}
|
|
|
|
|
inline VLifetime()
|
2020-08-16 17:40:42 +02:00
|
|
|
: m_e{NONE} {}
|
2020-04-26 18:45:06 +02:00
|
|
|
// cppcheck-suppress noExplicitConstructor
|
|
|
|
|
inline VLifetime(en _e)
|
2020-08-16 17:40:42 +02:00
|
|
|
: m_e{_e} {}
|
2020-04-26 18:45:06 +02:00
|
|
|
explicit inline VLifetime(int _e)
|
2020-08-18 14:10:44 +02:00
|
|
|
: m_e(static_cast<en>(_e)) {} // Need () or GCC 4.8 false warning
|
2020-04-26 18:45:06 +02:00
|
|
|
operator en() const { return m_e; }
|
|
|
|
|
bool isNone() const { return m_e == NONE; }
|
|
|
|
|
bool isAutomatic() const { return m_e == AUTOMATIC; }
|
|
|
|
|
bool isStatic() const { return m_e == STATIC; }
|
|
|
|
|
};
|
|
|
|
|
inline bool operator==(const VLifetime& lhs, const VLifetime& rhs) { return lhs.m_e == rhs.m_e; }
|
|
|
|
|
inline bool operator==(const VLifetime& lhs, VLifetime::en rhs) { return lhs.m_e == rhs; }
|
|
|
|
|
inline bool operator==(VLifetime::en lhs, const VLifetime& rhs) { return lhs == rhs.m_e; }
|
2020-07-03 03:02:49 +02:00
|
|
|
inline std::ostream& operator<<(std::ostream& os, const VLifetime& rhs) {
|
|
|
|
|
return os << rhs.ascii();
|
|
|
|
|
}
|
2020-04-26 18:45:06 +02:00
|
|
|
|
|
|
|
|
//######################################################################
|
|
|
|
|
|
2020-11-19 03:32:16 +01:00
|
|
|
class VAccess final {
|
2020-09-07 23:09:25 +02:00
|
|
|
public:
|
2020-11-07 16:37:55 +01:00
|
|
|
enum en : uint8_t {
|
|
|
|
|
READ, // Read/Consumed, variable not changed
|
|
|
|
|
WRITE, // Written/Updated, variable might be updated, but not consumed
|
|
|
|
|
// // so variable might be removable if not consumed elsewhere
|
|
|
|
|
READWRITE, // Read/Consumed and written/updated, variable both set and
|
|
|
|
|
// // also consumed, cannot remove usage of variable.
|
|
|
|
|
// // For non-simple data types only e.g. no tristates/delayed vars.
|
|
|
|
|
NOCHANGE // No change to previous state, used only in V3LinkLValue
|
|
|
|
|
};
|
2020-09-07 23:09:25 +02:00
|
|
|
enum en m_e;
|
|
|
|
|
const char* ascii() const {
|
2020-11-07 16:37:55 +01:00
|
|
|
static const char* const names[] = {"RD", "WR", "RW", "--"};
|
2020-09-07 23:09:25 +02:00
|
|
|
return names[m_e];
|
|
|
|
|
}
|
2020-11-01 22:59:23 +01:00
|
|
|
const char* arrow() const {
|
2020-11-07 16:37:55 +01:00
|
|
|
static const char* const names[] = {"[RV] <-", "[LV] =>", "[LV] <=>", "--"};
|
2020-11-01 22:59:23 +01:00
|
|
|
return names[m_e];
|
|
|
|
|
}
|
2020-09-07 23:09:25 +02:00
|
|
|
inline VAccess()
|
|
|
|
|
: m_e{READ} {}
|
|
|
|
|
// cppcheck-suppress noExplicitConstructor
|
|
|
|
|
inline VAccess(en _e)
|
|
|
|
|
: m_e{_e} {}
|
|
|
|
|
explicit inline VAccess(int _e)
|
|
|
|
|
: m_e(static_cast<en>(_e)) {} // Need () or GCC 4.8 false warning
|
|
|
|
|
operator en() const { return m_e; }
|
2020-11-07 16:37:55 +01:00
|
|
|
VAccess invert() const {
|
|
|
|
|
return (m_e == READWRITE) ? VAccess(m_e) : (m_e == WRITE ? VAccess(READ) : VAccess(WRITE));
|
|
|
|
|
}
|
|
|
|
|
bool isReadOnly() const { return m_e == READ; } // False with READWRITE
|
2021-06-17 19:49:45 +02:00
|
|
|
bool isWriteOnly() const { return m_e == WRITE; } // False with READWRITE
|
2020-11-07 16:37:55 +01:00
|
|
|
bool isReadOrRW() const { return m_e == READ || m_e == READWRITE; }
|
|
|
|
|
bool isWriteOrRW() const { return m_e == WRITE || m_e == READWRITE; }
|
2021-01-05 20:26:01 +01:00
|
|
|
bool isRW() const { return m_e == READWRITE; }
|
2020-09-07 23:09:25 +02:00
|
|
|
};
|
|
|
|
|
inline bool operator==(const VAccess& lhs, const VAccess& rhs) { return lhs.m_e == rhs.m_e; }
|
|
|
|
|
inline bool operator==(const VAccess& lhs, VAccess::en rhs) { return lhs.m_e == rhs; }
|
|
|
|
|
inline bool operator==(VAccess::en lhs, const VAccess& rhs) { return lhs == rhs.m_e; }
|
|
|
|
|
inline std::ostream& operator<<(std::ostream& os, const VAccess& rhs) { return os << rhs.ascii(); }
|
|
|
|
|
|
|
|
|
|
//######################################################################
|
|
|
|
|
|
2020-11-19 03:32:16 +01:00
|
|
|
class VSigning final {
|
2011-07-24 01:58:34 +02:00
|
|
|
public:
|
2020-08-16 18:05:35 +02:00
|
|
|
enum en : uint8_t {
|
2019-05-19 22:13:13 +02:00
|
|
|
UNSIGNED,
|
|
|
|
|
SIGNED,
|
|
|
|
|
NOSIGN,
|
|
|
|
|
_ENUM_MAX // Leave last
|
2011-07-24 01:58:34 +02:00
|
|
|
};
|
|
|
|
|
enum en m_e;
|
|
|
|
|
const char* ascii() const {
|
2020-04-15 13:58:34 +02:00
|
|
|
static const char* const names[] = {"UNSIGNED", "SIGNED", "NOSIGN"};
|
2019-05-19 22:13:13 +02:00
|
|
|
return names[m_e];
|
2020-02-04 04:10:29 +01:00
|
|
|
}
|
2020-04-20 03:19:09 +02:00
|
|
|
inline VSigning()
|
2020-08-16 17:40:42 +02:00
|
|
|
: m_e{UNSIGNED} {}
|
2015-10-04 04:33:06 +02:00
|
|
|
// cppcheck-suppress noExplicitConstructor
|
2020-04-20 03:19:09 +02:00
|
|
|
inline VSigning(en _e)
|
2020-08-16 17:40:42 +02:00
|
|
|
: m_e{_e} {}
|
2020-04-20 03:19:09 +02:00
|
|
|
static inline VSigning fromBool(bool isSigned) { // Factory method
|
|
|
|
|
return isSigned ? VSigning(SIGNED) : VSigning(UNSIGNED);
|
2020-04-15 13:58:34 +02:00
|
|
|
}
|
2020-04-20 03:19:09 +02:00
|
|
|
explicit inline VSigning(int _e)
|
2020-08-18 14:10:44 +02:00
|
|
|
: m_e(static_cast<en>(_e)) {} // Need () or GCC 4.8 false warning
|
2018-08-25 15:52:45 +02:00
|
|
|
operator en() const { return m_e; }
|
2020-04-15 13:58:34 +02:00
|
|
|
inline bool isSigned() const { return m_e == SIGNED; }
|
|
|
|
|
inline bool isNosign() const { return m_e == NOSIGN; }
|
2012-04-29 16:14:13 +02:00
|
|
|
// No isUnsigned() as it's ambiguous if NOSIGN should be included or not.
|
2020-02-02 16:34:29 +01:00
|
|
|
};
|
2020-04-20 03:19:09 +02:00
|
|
|
inline bool operator==(const VSigning& lhs, const VSigning& rhs) { return lhs.m_e == rhs.m_e; }
|
|
|
|
|
inline bool operator==(const VSigning& lhs, VSigning::en rhs) { return lhs.m_e == rhs; }
|
|
|
|
|
inline bool operator==(VSigning::en lhs, const VSigning& rhs) { return lhs == rhs.m_e; }
|
|
|
|
|
inline std::ostream& operator<<(std::ostream& os, const VSigning& rhs) {
|
2020-02-02 16:34:29 +01:00
|
|
|
return os << rhs.ascii();
|
|
|
|
|
}
|
2011-07-24 01:58:34 +02:00
|
|
|
|
|
|
|
|
//######################################################################
|
|
|
|
|
|
2020-11-19 03:32:16 +01:00
|
|
|
class AstPragmaType final {
|
2006-08-26 13:35:28 +02:00
|
|
|
public:
|
2020-08-16 18:05:35 +02:00
|
|
|
enum en : uint8_t {
|
2019-05-19 22:13:13 +02:00
|
|
|
ILLEGAL,
|
|
|
|
|
COVERAGE_BLOCK_OFF,
|
2020-08-15 15:43:53 +02:00
|
|
|
HIER_BLOCK,
|
2019-05-19 22:13:13 +02:00
|
|
|
INLINE_MODULE,
|
|
|
|
|
NO_INLINE_MODULE,
|
|
|
|
|
NO_INLINE_TASK,
|
|
|
|
|
PUBLIC_MODULE,
|
2020-01-12 10:03:17 +01:00
|
|
|
PUBLIC_TASK,
|
|
|
|
|
FULL_CASE,
|
|
|
|
|
PARALLEL_CASE,
|
|
|
|
|
ENUM_SIZE
|
2006-08-26 13:35:28 +02:00
|
|
|
};
|
|
|
|
|
enum en m_e;
|
2020-04-15 13:58:34 +02:00
|
|
|
inline AstPragmaType()
|
2020-08-16 17:40:42 +02:00
|
|
|
: m_e{ILLEGAL} {}
|
2015-10-04 04:33:06 +02:00
|
|
|
// cppcheck-suppress noExplicitConstructor
|
2020-04-15 13:58:34 +02:00
|
|
|
inline AstPragmaType(en _e)
|
2020-08-16 17:40:42 +02:00
|
|
|
: m_e{_e} {}
|
2020-04-15 13:58:34 +02:00
|
|
|
explicit inline AstPragmaType(int _e)
|
2020-08-18 14:10:44 +02:00
|
|
|
: m_e(static_cast<en>(_e)) {} // Need () or GCC 4.8 false warning
|
2018-08-25 15:52:45 +02:00
|
|
|
operator en() const { return m_e; }
|
2020-02-02 16:34:29 +01:00
|
|
|
};
|
|
|
|
|
inline bool operator==(const AstPragmaType& lhs, const AstPragmaType& rhs) {
|
|
|
|
|
return lhs.m_e == rhs.m_e;
|
|
|
|
|
}
|
|
|
|
|
inline bool operator==(const AstPragmaType& lhs, AstPragmaType::en rhs) { return lhs.m_e == rhs; }
|
|
|
|
|
inline bool operator==(AstPragmaType::en lhs, const AstPragmaType& rhs) { return lhs == rhs.m_e; }
|
2006-08-26 13:35:28 +02:00
|
|
|
|
|
|
|
|
//######################################################################
|
|
|
|
|
|
2020-11-19 03:32:16 +01:00
|
|
|
class VEdgeType final {
|
2006-08-26 13:35:28 +02:00
|
|
|
public:
|
2020-04-15 13:58:34 +02:00
|
|
|
// REMEMBER to edit the strings below too
|
2020-08-16 18:05:35 +02:00
|
|
|
enum en : uint8_t {
|
2019-05-19 22:13:13 +02:00
|
|
|
// These must be in general -> most specific order, as we sort by it
|
|
|
|
|
// in V3Const::visit AstSenTree
|
|
|
|
|
ET_ILLEGAL,
|
|
|
|
|
// Involving a variable
|
2020-04-15 13:58:34 +02:00
|
|
|
ET_ANYEDGE, // Default for sensitivities; rip them out
|
|
|
|
|
ET_BOTHEDGE, // POSEDGE | NEGEDGE
|
2019-05-19 22:13:13 +02:00
|
|
|
ET_POSEDGE,
|
|
|
|
|
ET_NEGEDGE,
|
2020-04-15 13:58:34 +02:00
|
|
|
ET_HIGHEDGE, // Is high now (latches)
|
|
|
|
|
ET_LOWEDGE, // Is low now (latches)
|
2019-05-19 22:13:13 +02:00
|
|
|
// Not involving anything
|
2020-04-15 13:58:34 +02:00
|
|
|
ET_COMBO, // Sensitive to all combo inputs to this block
|
|
|
|
|
ET_INITIAL, // User initial statements
|
|
|
|
|
ET_SETTLE, // Like combo but for initial wire resolutions after initial statement
|
|
|
|
|
ET_NEVER // Never occurs (optimized away)
|
2006-08-26 13:35:28 +02:00
|
|
|
};
|
|
|
|
|
enum en m_e;
|
|
|
|
|
bool clockedStmt() const {
|
2020-04-15 13:58:34 +02:00
|
|
|
static const bool clocked[]
|
|
|
|
|
= {false, false, true, true, true, true, true, false, false, false};
|
2019-05-19 22:13:13 +02:00
|
|
|
return clocked[m_e];
|
2006-08-26 13:35:28 +02:00
|
|
|
}
|
2019-10-05 13:54:14 +02:00
|
|
|
VEdgeType invert() const {
|
2019-05-19 22:13:13 +02:00
|
|
|
switch (m_e) {
|
2020-04-15 13:58:34 +02:00
|
|
|
case ET_ANYEDGE: return ET_ANYEDGE;
|
|
|
|
|
case ET_BOTHEDGE: return ET_BOTHEDGE;
|
|
|
|
|
case ET_POSEDGE: return ET_NEGEDGE;
|
|
|
|
|
case ET_NEGEDGE: return ET_POSEDGE;
|
|
|
|
|
case ET_HIGHEDGE: return ET_LOWEDGE;
|
|
|
|
|
case ET_LOWEDGE: return ET_HIGHEDGE;
|
2019-05-19 22:13:13 +02:00
|
|
|
default: UASSERT_STATIC(0, "Inverting bad edgeType()");
|
2020-05-30 19:46:12 +02:00
|
|
|
}
|
2019-10-05 13:54:14 +02:00
|
|
|
return VEdgeType::ET_ILLEGAL;
|
2006-08-26 13:35:28 +02:00
|
|
|
}
|
|
|
|
|
const char* ascii() const {
|
2020-04-15 13:58:34 +02:00
|
|
|
static const char* const names[]
|
|
|
|
|
= {"%E-edge", "ANY", "BOTH", "POS", "NEG", "HIGH",
|
|
|
|
|
"LOW", "COMBO", "INITIAL", "SETTLE", "NEVER"};
|
2019-05-19 22:13:13 +02:00
|
|
|
return names[m_e];
|
2017-10-28 19:31:04 +02:00
|
|
|
}
|
2006-08-26 13:35:28 +02:00
|
|
|
const char* verilogKwd() const {
|
2020-04-15 13:58:34 +02:00
|
|
|
static const char* const names[]
|
|
|
|
|
= {"%E-edge", "[any]", "edge", "posedge", "negedge", "[high]",
|
|
|
|
|
"[low]", "*", "[initial]", "[settle]", "[never]"};
|
2019-05-19 22:13:13 +02:00
|
|
|
return names[m_e];
|
2017-10-28 19:31:04 +02:00
|
|
|
}
|
|
|
|
|
// Return true iff this and the other have mutually exclusive transitions
|
2019-10-05 13:54:14 +02:00
|
|
|
bool exclusiveEdge(const VEdgeType& other) const {
|
2017-10-28 19:31:04 +02:00
|
|
|
switch (m_e) {
|
2019-10-05 13:54:14 +02:00
|
|
|
case VEdgeType::ET_POSEDGE:
|
2017-10-28 19:31:04 +02:00
|
|
|
switch (other.m_e) {
|
2019-10-05 13:54:14 +02:00
|
|
|
case VEdgeType::ET_NEGEDGE: // FALLTHRU
|
2020-04-15 13:58:34 +02:00
|
|
|
case VEdgeType::ET_LOWEDGE: return true;
|
2020-04-15 23:36:48 +02:00
|
|
|
default:;
|
2017-10-28 19:31:04 +02:00
|
|
|
}
|
|
|
|
|
break;
|
2019-10-05 13:54:14 +02:00
|
|
|
case VEdgeType::ET_NEGEDGE:
|
2017-10-28 19:31:04 +02:00
|
|
|
switch (other.m_e) {
|
2019-10-05 13:54:14 +02:00
|
|
|
case VEdgeType::ET_POSEDGE: // FALLTHRU
|
2020-04-15 13:58:34 +02:00
|
|
|
case VEdgeType::ET_HIGHEDGE: return true;
|
2020-04-15 23:36:48 +02:00
|
|
|
default:;
|
2017-10-28 19:31:04 +02:00
|
|
|
}
|
|
|
|
|
break;
|
2020-04-15 23:36:48 +02:00
|
|
|
default:;
|
2017-10-28 19:31:04 +02:00
|
|
|
}
|
|
|
|
|
return false;
|
|
|
|
|
}
|
2020-04-15 13:58:34 +02:00
|
|
|
inline VEdgeType()
|
2020-08-16 17:40:42 +02:00
|
|
|
: m_e{ET_ILLEGAL} {}
|
2015-10-04 04:33:06 +02:00
|
|
|
// cppcheck-suppress noExplicitConstructor
|
2020-04-15 13:58:34 +02:00
|
|
|
inline VEdgeType(en _e)
|
2020-08-16 17:40:42 +02:00
|
|
|
: m_e{_e} {}
|
2020-04-15 13:58:34 +02:00
|
|
|
explicit inline VEdgeType(int _e)
|
2020-08-18 14:10:44 +02:00
|
|
|
: m_e(static_cast<en>(_e)) {} // Need () or GCC 4.8 false warning
|
2018-08-25 15:52:45 +02:00
|
|
|
operator en() const { return m_e; }
|
2020-02-02 16:34:29 +01:00
|
|
|
};
|
|
|
|
|
inline bool operator==(const VEdgeType& lhs, const VEdgeType& rhs) { return lhs.m_e == rhs.m_e; }
|
|
|
|
|
inline bool operator==(const VEdgeType& lhs, VEdgeType::en rhs) { return lhs.m_e == rhs; }
|
|
|
|
|
inline bool operator==(VEdgeType::en lhs, const VEdgeType& rhs) { return lhs == rhs.m_e; }
|
2006-08-26 13:35:28 +02:00
|
|
|
|
|
|
|
|
//######################################################################
|
|
|
|
|
|
2020-11-19 03:32:16 +01:00
|
|
|
class AstAttrType final {
|
2006-08-26 13:35:28 +02:00
|
|
|
public:
|
2020-04-15 13:58:34 +02:00
|
|
|
// clang-format off
|
2020-08-16 18:05:35 +02:00
|
|
|
enum en: uint8_t {
|
2019-05-19 22:13:13 +02:00
|
|
|
ILLEGAL,
|
|
|
|
|
//
|
|
|
|
|
DIM_BITS, // V3Const converts to constant
|
|
|
|
|
DIM_DIMENSIONS, // V3Width converts to constant
|
|
|
|
|
DIM_HIGH, // V3Width processes
|
|
|
|
|
DIM_INCREMENT, // V3Width processes
|
|
|
|
|
DIM_LEFT, // V3Width processes
|
|
|
|
|
DIM_LOW, // V3Width processes
|
|
|
|
|
DIM_RIGHT, // V3Width processes
|
|
|
|
|
DIM_SIZE, // V3Width processes
|
|
|
|
|
DIM_UNPK_DIMENSIONS, // V3Width converts to constant
|
|
|
|
|
//
|
|
|
|
|
DT_PUBLIC, // V3LinkParse moves to AstTypedef::attrPublic
|
|
|
|
|
//
|
|
|
|
|
ENUM_BASE, // V3LinkResolve creates for AstPreSel, V3LinkParam removes
|
|
|
|
|
ENUM_FIRST, // V3Width processes
|
|
|
|
|
ENUM_LAST, // V3Width processes
|
|
|
|
|
ENUM_NUM, // V3Width processes
|
|
|
|
|
ENUM_NEXT, // V3Width processes
|
|
|
|
|
ENUM_PREV, // V3Width processes
|
|
|
|
|
ENUM_NAME, // V3Width processes
|
2020-12-06 04:58:36 +01:00
|
|
|
ENUM_VALID, // V3Width processes
|
2019-05-19 22:13:13 +02:00
|
|
|
//
|
|
|
|
|
MEMBER_BASE, // V3LinkResolve creates for AstPreSel, V3LinkParam removes
|
|
|
|
|
//
|
2020-01-26 19:21:25 +01:00
|
|
|
TYPENAME, // V3Width processes
|
|
|
|
|
//
|
2019-05-19 22:13:13 +02:00
|
|
|
VAR_BASE, // V3LinkResolve creates for AstPreSel, V3LinkParam removes
|
|
|
|
|
VAR_CLOCK_ENABLE, // V3LinkParse moves to AstVar::attrClockEn
|
|
|
|
|
VAR_PUBLIC, // V3LinkParse moves to AstVar::sigPublic
|
|
|
|
|
VAR_PUBLIC_FLAT, // V3LinkParse moves to AstVar::sigPublic
|
|
|
|
|
VAR_PUBLIC_FLAT_RD, // V3LinkParse moves to AstVar::sigPublic
|
|
|
|
|
VAR_PUBLIC_FLAT_RW, // V3LinkParse moves to AstVar::sigPublic
|
|
|
|
|
VAR_ISOLATE_ASSIGNMENTS, // V3LinkParse moves to AstVar::attrIsolateAssign
|
|
|
|
|
VAR_SC_BV, // V3LinkParse moves to AstVar::attrScBv
|
|
|
|
|
VAR_SFORMAT, // V3LinkParse moves to AstVar::attrSFormat
|
|
|
|
|
VAR_CLOCKER, // V3LinkParse moves to AstVar::attrClocker
|
2020-02-29 01:15:08 +01:00
|
|
|
VAR_NO_CLOCKER, // V3LinkParse moves to AstVar::attrClocker
|
|
|
|
|
VAR_SPLIT_VAR // V3LinkParse moves to AstVar::attrSplitVar
|
2006-08-26 13:35:28 +02:00
|
|
|
};
|
2020-04-15 13:58:34 +02:00
|
|
|
// clang-format on
|
2006-08-26 13:35:28 +02:00
|
|
|
enum en m_e;
|
2009-05-08 00:28:05 +02:00
|
|
|
const char* ascii() const {
|
2020-04-15 13:58:34 +02:00
|
|
|
// clang-format off
|
2019-05-19 22:13:13 +02:00
|
|
|
static const char* const names[] = {
|
|
|
|
|
"%E-AT",
|
|
|
|
|
"DIM_BITS", "DIM_DIMENSIONS", "DIM_HIGH", "DIM_INCREMENT", "DIM_LEFT",
|
|
|
|
|
"DIM_LOW", "DIM_RIGHT", "DIM_SIZE", "DIM_UNPK_DIMENSIONS",
|
|
|
|
|
"DT_PUBLIC",
|
|
|
|
|
"ENUM_BASE", "ENUM_FIRST", "ENUM_LAST", "ENUM_NUM",
|
2020-12-06 04:58:36 +01:00
|
|
|
"ENUM_NEXT", "ENUM_PREV", "ENUM_NAME", "ENUM_VALID",
|
2019-05-19 22:13:13 +02:00
|
|
|
"MEMBER_BASE",
|
2020-01-26 19:21:25 +01:00
|
|
|
"TYPENAME",
|
2020-08-29 16:45:47 +02:00
|
|
|
"VAR_BASE", "VAR_CLOCK_ENABLE", "VAR_PUBLIC",
|
2019-05-19 22:13:13 +02:00
|
|
|
"VAR_PUBLIC_FLAT", "VAR_PUBLIC_FLAT_RD", "VAR_PUBLIC_FLAT_RW",
|
|
|
|
|
"VAR_ISOLATE_ASSIGNMENTS", "VAR_SC_BV", "VAR_SFORMAT", "VAR_CLOCKER",
|
2020-02-29 01:15:08 +01:00
|
|
|
"VAR_NO_CLOCKER", "VAR_SPLIT_VAR"
|
2019-05-19 22:13:13 +02:00
|
|
|
};
|
2020-04-15 13:58:34 +02:00
|
|
|
// clang-format on
|
2019-05-19 22:13:13 +02:00
|
|
|
return names[m_e];
|
2020-02-04 04:10:29 +01:00
|
|
|
}
|
2020-04-15 13:58:34 +02:00
|
|
|
inline AstAttrType()
|
2020-08-16 17:40:42 +02:00
|
|
|
: m_e{ILLEGAL} {}
|
2015-10-04 04:33:06 +02:00
|
|
|
// cppcheck-suppress noExplicitConstructor
|
2020-04-15 13:58:34 +02:00
|
|
|
inline AstAttrType(en _e)
|
2020-08-16 17:40:42 +02:00
|
|
|
: m_e{_e} {}
|
2020-04-15 13:58:34 +02:00
|
|
|
explicit inline AstAttrType(int _e)
|
2020-08-18 14:10:44 +02:00
|
|
|
: m_e(static_cast<en>(_e)) {} // Need () or GCC 4.8 false warning
|
2018-08-25 15:52:45 +02:00
|
|
|
operator en() const { return m_e; }
|
2020-02-02 16:34:29 +01:00
|
|
|
};
|
|
|
|
|
inline bool operator==(const AstAttrType& lhs, const AstAttrType& rhs) {
|
|
|
|
|
return lhs.m_e == rhs.m_e;
|
|
|
|
|
}
|
|
|
|
|
inline bool operator==(const AstAttrType& lhs, AstAttrType::en rhs) { return lhs.m_e == rhs; }
|
|
|
|
|
inline bool operator==(AstAttrType::en lhs, const AstAttrType& rhs) { return lhs == rhs.m_e; }
|
2006-08-26 13:35:28 +02:00
|
|
|
|
|
|
|
|
//######################################################################
|
|
|
|
|
|
2020-11-19 03:32:16 +01:00
|
|
|
class AstBasicDTypeKwd final {
|
2009-11-02 14:06:04 +01:00
|
|
|
public:
|
2020-08-16 18:05:35 +02:00
|
|
|
enum en : uint8_t {
|
2019-05-19 22:13:13 +02:00
|
|
|
UNKNOWN,
|
2020-04-15 13:58:34 +02:00
|
|
|
BIT,
|
|
|
|
|
BYTE,
|
|
|
|
|
CHANDLE,
|
2020-04-25 21:37:46 +02:00
|
|
|
EVENTVALUE, // See comments in t_event_copy as to why this is EVENTVALUE
|
2020-04-15 13:58:34 +02:00
|
|
|
INT,
|
|
|
|
|
INTEGER,
|
|
|
|
|
LOGIC,
|
|
|
|
|
LONGINT,
|
|
|
|
|
DOUBLE,
|
|
|
|
|
SHORTINT,
|
|
|
|
|
TIME,
|
2019-05-19 22:13:13 +02:00
|
|
|
// Closer to a class type, but limited usage
|
|
|
|
|
STRING,
|
|
|
|
|
// Internal types for mid-steps
|
2020-04-15 13:58:34 +02:00
|
|
|
SCOPEPTR,
|
|
|
|
|
CHARPTR,
|
2021-06-16 13:18:56 +02:00
|
|
|
MTASKSTATE,
|
2019-05-19 22:13:13 +02:00
|
|
|
// Unsigned and two state; fundamental types
|
2020-04-15 13:58:34 +02:00
|
|
|
UINT32,
|
|
|
|
|
UINT64,
|
2019-05-19 22:13:13 +02:00
|
|
|
// Internal types, eliminated after parsing
|
|
|
|
|
LOGIC_IMPLICIT,
|
|
|
|
|
// Leave last
|
|
|
|
|
_ENUM_MAX
|
2009-11-02 14:06:04 +01:00
|
|
|
};
|
|
|
|
|
enum en m_e;
|
|
|
|
|
const char* ascii() const {
|
2021-06-16 13:18:56 +02:00
|
|
|
static const char* const names[]
|
|
|
|
|
= {"%E-unk", "bit", "byte", "chandle", "event",
|
|
|
|
|
"int", "integer", "logic", "longint", "real",
|
|
|
|
|
"shortint", "time", "string", "VerilatedScope*", "char*",
|
|
|
|
|
"VlMTaskState", "IData", "QData", "LOGIC_IMPLICIT", " MAX"};
|
2019-05-19 22:13:13 +02:00
|
|
|
return names[m_e];
|
2020-02-04 04:10:29 +01:00
|
|
|
}
|
2009-12-03 12:55:29 +01:00
|
|
|
const char* dpiType() const {
|
2020-04-15 13:58:34 +02:00
|
|
|
static const char* const names[]
|
2021-06-16 13:18:56 +02:00
|
|
|
= {"%E-unk", "svBit", "char", "void*", "char",
|
|
|
|
|
"int", "%E-integer", "svLogic", "long long", "double",
|
|
|
|
|
"short", "%E-time", "const char*", "dpiScope", "const char*",
|
|
|
|
|
"%E-mtaskstate", "IData", "QData", "%E-logic-implct", " MAX"};
|
2019-05-19 22:13:13 +02:00
|
|
|
return names[m_e];
|
2020-02-04 04:10:29 +01:00
|
|
|
}
|
2017-10-31 00:01:58 +01:00
|
|
|
static void selfTest() {
|
2020-04-15 13:58:34 +02:00
|
|
|
UASSERT(0 == strcmp(AstBasicDTypeKwd(_ENUM_MAX).ascii(), " MAX"),
|
|
|
|
|
"SelfTest: Enum mismatch");
|
|
|
|
|
UASSERT(0 == strcmp(AstBasicDTypeKwd(_ENUM_MAX).dpiType(), " MAX"),
|
|
|
|
|
"SelfTest: Enum mismatch");
|
2012-04-14 16:45:24 +02:00
|
|
|
}
|
2020-04-15 13:58:34 +02:00
|
|
|
inline AstBasicDTypeKwd()
|
2020-08-16 17:40:42 +02:00
|
|
|
: m_e{UNKNOWN} {}
|
2015-10-04 04:33:06 +02:00
|
|
|
// cppcheck-suppress noExplicitConstructor
|
2020-04-15 13:58:34 +02:00
|
|
|
inline AstBasicDTypeKwd(en _e)
|
2020-08-16 17:40:42 +02:00
|
|
|
: m_e{_e} {}
|
2020-04-15 13:58:34 +02:00
|
|
|
explicit inline AstBasicDTypeKwd(int _e)
|
2020-08-18 14:10:44 +02:00
|
|
|
: m_e(static_cast<en>(_e)) {} // Need () or GCC 4.8 false warning
|
2018-08-25 15:52:45 +02:00
|
|
|
operator en() const { return m_e; }
|
2009-11-03 04:14:11 +01:00
|
|
|
int width() const {
|
2019-05-19 22:13:13 +02:00
|
|
|
switch (m_e) {
|
2020-04-15 13:58:34 +02:00
|
|
|
case BIT: return 1; // scalar, can't bit extract unless ranged
|
|
|
|
|
case BYTE: return 8;
|
|
|
|
|
case CHANDLE: return 64;
|
2020-04-25 21:37:46 +02:00
|
|
|
case EVENTVALUE: return 1;
|
2020-04-15 13:58:34 +02:00
|
|
|
case INT: return 32;
|
|
|
|
|
case INTEGER: return 32;
|
|
|
|
|
case LOGIC: return 1; // scalar, can't bit extract unless ranged
|
|
|
|
|
case LONGINT: return 64;
|
|
|
|
|
case DOUBLE: return 64; // opaque
|
|
|
|
|
case SHORTINT: return 16;
|
|
|
|
|
case TIME: return 64;
|
|
|
|
|
case STRING: return 64; // opaque // Just the pointer, for today
|
|
|
|
|
case SCOPEPTR: return 0; // opaque
|
|
|
|
|
case CHARPTR: return 0; // opaque
|
2021-06-16 13:18:56 +02:00
|
|
|
case MTASKSTATE: return 0; // opaque
|
2020-04-15 13:58:34 +02:00
|
|
|
case UINT32: return 32;
|
|
|
|
|
case UINT64: return 64;
|
2019-05-19 22:13:13 +02:00
|
|
|
default: return 0;
|
|
|
|
|
}
|
2009-11-03 04:14:11 +01:00
|
|
|
}
|
2010-01-15 14:20:25 +01:00
|
|
|
bool isSigned() const {
|
2020-04-15 13:58:34 +02:00
|
|
|
return m_e == BYTE || m_e == SHORTINT || m_e == INT || m_e == LONGINT || m_e == INTEGER
|
2020-11-29 03:43:37 +01:00
|
|
|
|| m_e == DOUBLE;
|
2012-04-29 16:14:13 +02:00
|
|
|
}
|
|
|
|
|
bool isUnsigned() const {
|
2020-04-25 21:37:46 +02:00
|
|
|
return m_e == CHANDLE || m_e == EVENTVALUE || m_e == STRING || m_e == SCOPEPTR
|
2021-11-09 22:29:28 +01:00
|
|
|
|| m_e == CHARPTR || m_e == UINT32 || m_e == UINT64 || m_e == BIT || m_e == LOGIC
|
|
|
|
|
|| m_e == TIME;
|
2009-11-03 04:14:11 +01:00
|
|
|
}
|
2010-01-15 14:20:25 +01:00
|
|
|
bool isFourstate() const {
|
2020-04-08 01:07:47 +02:00
|
|
|
return m_e == INTEGER || m_e == LOGIC || m_e == LOGIC_IMPLICIT || m_e == TIME;
|
2009-11-03 04:14:11 +01:00
|
|
|
}
|
2019-05-19 22:13:13 +02:00
|
|
|
bool isZeroInit() const { // Otherwise initializes to X
|
2020-04-25 21:37:46 +02:00
|
|
|
return (m_e == BIT || m_e == BYTE || m_e == CHANDLE || m_e == EVENTVALUE || m_e == INT
|
2020-11-29 03:43:37 +01:00
|
|
|
|| m_e == LONGINT || m_e == SHORTINT || m_e == STRING || m_e == DOUBLE);
|
2009-11-24 01:08:25 +01:00
|
|
|
}
|
2019-05-19 22:13:13 +02:00
|
|
|
bool isIntNumeric() const { // Enum increment supported
|
2020-04-15 13:58:34 +02:00
|
|
|
return (m_e == BIT || m_e == BYTE || m_e == INT || m_e == INTEGER || m_e == LOGIC
|
|
|
|
|
|| m_e == LONGINT || m_e == SHORTINT || m_e == UINT32 || m_e == UINT64);
|
2012-04-29 16:14:13 +02:00
|
|
|
}
|
2019-05-19 22:13:13 +02:00
|
|
|
bool isBitLogic() const { // Bit/logic vector types; can form a packed array
|
2020-04-15 13:58:34 +02:00
|
|
|
return (m_e == LOGIC || m_e == BIT);
|
2009-11-03 04:14:11 +01:00
|
|
|
}
|
2012-12-04 02:43:13 +01:00
|
|
|
bool isDpiUnsignable() const { // Can add "unsigned" to DPI
|
2020-04-15 13:58:34 +02:00
|
|
|
return (m_e == BYTE || m_e == SHORTINT || m_e == INT || m_e == LONGINT || m_e == INTEGER);
|
2012-12-04 02:43:13 +01:00
|
|
|
}
|
2017-12-17 22:28:58 +01:00
|
|
|
bool isDpiCLayout() const { // Uses standard C layout, for DPI runtime access
|
2020-04-15 13:58:34 +02:00
|
|
|
return (m_e == BIT || m_e == BYTE || m_e == CHANDLE || m_e == INT || m_e == LONGINT
|
|
|
|
|
|| m_e == DOUBLE || m_e == SHORTINT || m_e == UINT32 || m_e == UINT64);
|
2017-12-17 22:28:58 +01:00
|
|
|
}
|
2010-01-17 21:10:37 +01:00
|
|
|
bool isOpaque() const { // IE not a simple number we can bit optimize
|
2021-06-16 13:18:56 +02:00
|
|
|
return (m_e == STRING || m_e == SCOPEPTR || m_e == CHARPTR || m_e == MTASKSTATE
|
|
|
|
|
|| m_e == DOUBLE);
|
2011-07-06 03:05:35 +02:00
|
|
|
}
|
2020-04-15 13:58:34 +02:00
|
|
|
bool isDouble() const { return m_e == DOUBLE; }
|
2020-04-25 21:37:46 +02:00
|
|
|
bool isEventValue() const { return m_e == EVENTVALUE; }
|
2020-04-15 13:58:34 +02:00
|
|
|
bool isString() const { return m_e == STRING; }
|
2021-06-16 13:18:56 +02:00
|
|
|
bool isMTaskState() const { return m_e == MTASKSTATE; }
|
2021-07-22 19:59:03 +02:00
|
|
|
// Does this represent a C++ LiteralType? (can be constexpr)
|
|
|
|
|
bool isLiteralType() const {
|
|
|
|
|
switch (m_e) {
|
|
|
|
|
case BIT:
|
|
|
|
|
case BYTE:
|
|
|
|
|
case CHANDLE:
|
|
|
|
|
case INT:
|
|
|
|
|
case INTEGER:
|
|
|
|
|
case LOGIC:
|
|
|
|
|
case LONGINT:
|
|
|
|
|
case DOUBLE:
|
|
|
|
|
case SHORTINT:
|
|
|
|
|
case SCOPEPTR:
|
|
|
|
|
case CHARPTR:
|
|
|
|
|
case UINT32:
|
|
|
|
|
case UINT64: return true;
|
|
|
|
|
default: return false;
|
|
|
|
|
}
|
|
|
|
|
}
|
2020-02-02 16:34:29 +01:00
|
|
|
};
|
|
|
|
|
inline bool operator==(const AstBasicDTypeKwd& lhs, const AstBasicDTypeKwd& rhs) {
|
|
|
|
|
return lhs.m_e == rhs.m_e;
|
|
|
|
|
}
|
|
|
|
|
inline bool operator==(const AstBasicDTypeKwd& lhs, AstBasicDTypeKwd::en rhs) {
|
|
|
|
|
return lhs.m_e == rhs;
|
|
|
|
|
}
|
|
|
|
|
inline bool operator==(AstBasicDTypeKwd::en lhs, const AstBasicDTypeKwd& rhs) {
|
|
|
|
|
return lhs == rhs.m_e;
|
|
|
|
|
}
|
2009-11-02 14:06:04 +01:00
|
|
|
|
|
|
|
|
//######################################################################
|
|
|
|
|
|
2020-11-19 03:32:16 +01:00
|
|
|
class VDirection final {
|
2018-10-27 23:29:00 +02:00
|
|
|
public:
|
2020-08-16 18:05:35 +02:00
|
|
|
enum en : uint8_t { NONE, INPUT, OUTPUT, INOUT, REF, CONSTREF };
|
2018-10-27 23:29:00 +02:00
|
|
|
enum en m_e;
|
2020-04-15 13:58:34 +02:00
|
|
|
inline VDirection()
|
2020-08-16 17:40:42 +02:00
|
|
|
: m_e{NONE} {}
|
2018-10-27 23:29:00 +02:00
|
|
|
// cppcheck-suppress noExplicitConstructor
|
2020-04-15 13:58:34 +02:00
|
|
|
inline VDirection(en _e)
|
2020-08-16 17:40:42 +02:00
|
|
|
: m_e{_e} {}
|
2020-04-15 13:58:34 +02:00
|
|
|
explicit inline VDirection(int _e)
|
2020-08-18 14:10:44 +02:00
|
|
|
: m_e(static_cast<en>(_e)) {} // Need () or GCC 4.8 false warning
|
2018-10-27 23:29:00 +02:00
|
|
|
operator en() const { return m_e; }
|
|
|
|
|
const char* ascii() const {
|
2020-04-15 13:58:34 +02:00
|
|
|
static const char* const names[] = {"NONE", "INPUT", "OUTPUT", "INOUT", "REF", "CONSTREF"};
|
|
|
|
|
return names[m_e];
|
|
|
|
|
}
|
2018-10-27 23:29:00 +02:00
|
|
|
string verilogKwd() const {
|
2020-04-15 13:58:34 +02:00
|
|
|
static const char* const names[] = {"", "input", "output", "inout", "ref", "const ref"};
|
|
|
|
|
return names[m_e];
|
|
|
|
|
}
|
2018-10-27 23:29:00 +02:00
|
|
|
string xmlKwd() const { // For historical reasons no "put" suffix
|
2020-04-15 13:58:34 +02:00
|
|
|
static const char* const names[] = {"", "in", "out", "inout", "ref", "const ref"};
|
|
|
|
|
return names[m_e];
|
|
|
|
|
}
|
2018-10-27 23:29:00 +02:00
|
|
|
string prettyName() const { return verilogKwd(); }
|
|
|
|
|
bool isAny() const { return m_e != NONE; }
|
|
|
|
|
// Looks like inout - "ish" because not identical to being an INOUT
|
|
|
|
|
bool isInoutish() const { return m_e == INOUT; }
|
2020-04-15 13:58:34 +02:00
|
|
|
bool isNonOutput() const {
|
|
|
|
|
return m_e == INPUT || m_e == INOUT || m_e == REF || m_e == CONSTREF;
|
|
|
|
|
}
|
2018-10-31 01:50:09 +01:00
|
|
|
bool isReadOnly() const { return m_e == INPUT || m_e == CONSTREF; }
|
2020-04-15 13:58:34 +02:00
|
|
|
bool isWritable() const { return m_e == OUTPUT || m_e == INOUT || m_e == REF; }
|
2018-10-31 01:50:09 +01:00
|
|
|
bool isRefOrConstRef() const { return m_e == REF || m_e == CONSTREF; }
|
2020-02-02 16:34:29 +01:00
|
|
|
};
|
|
|
|
|
inline bool operator==(const VDirection& lhs, const VDirection& rhs) { return lhs.m_e == rhs.m_e; }
|
|
|
|
|
inline bool operator==(const VDirection& lhs, VDirection::en rhs) { return lhs.m_e == rhs; }
|
|
|
|
|
inline bool operator==(VDirection::en lhs, const VDirection& rhs) { return lhs == rhs.m_e; }
|
|
|
|
|
inline std::ostream& operator<<(std::ostream& os, const VDirection& rhs) {
|
|
|
|
|
return os << rhs.ascii();
|
|
|
|
|
}
|
2018-10-27 23:29:00 +02:00
|
|
|
|
|
|
|
|
//######################################################################
|
|
|
|
|
|
2019-01-16 06:38:42 +01:00
|
|
|
/// Boolean or unknown
|
2020-11-19 03:32:16 +01:00
|
|
|
class VBoolOrUnknown final {
|
2019-01-16 06:38:42 +01:00
|
|
|
public:
|
2020-08-16 18:05:35 +02:00
|
|
|
enum en : uint8_t { BU_FALSE = 0, BU_TRUE = 1, BU_UNKNOWN = 2, _ENUM_END };
|
2019-01-16 06:38:42 +01:00
|
|
|
enum en m_e;
|
|
|
|
|
// CONSTRUCTOR - note defaults to *UNKNOWN*
|
2020-04-15 13:58:34 +02:00
|
|
|
inline VBoolOrUnknown()
|
2020-08-16 17:40:42 +02:00
|
|
|
: m_e{BU_UNKNOWN} {}
|
2019-01-16 06:38:42 +01:00
|
|
|
// cppcheck-suppress noExplicitConstructor
|
2020-04-15 13:58:34 +02:00
|
|
|
inline VBoolOrUnknown(en _e)
|
2020-08-16 17:40:42 +02:00
|
|
|
: m_e{_e} {}
|
2020-04-15 13:58:34 +02:00
|
|
|
explicit inline VBoolOrUnknown(int _e)
|
2020-08-18 14:10:44 +02:00
|
|
|
: m_e(static_cast<en>(_e)) {} // Need () or GCC 4.8 false warning
|
2019-01-16 06:38:42 +01:00
|
|
|
const char* ascii() const {
|
2020-04-15 13:58:34 +02:00
|
|
|
static const char* const names[] = {"FALSE", "TRUE", "UNK"};
|
|
|
|
|
return names[m_e];
|
|
|
|
|
}
|
2020-02-01 16:57:55 +01:00
|
|
|
bool trueKnown() const { return m_e == BU_TRUE; }
|
|
|
|
|
bool trueUnknown() const { return m_e == BU_TRUE || m_e == BU_UNKNOWN; }
|
|
|
|
|
bool falseKnown() const { return m_e == BU_FALSE; }
|
|
|
|
|
bool falseUnknown() const { return m_e == BU_FALSE || m_e == BU_UNKNOWN; }
|
2019-01-16 06:38:42 +01:00
|
|
|
bool unknown() const { return m_e == BU_UNKNOWN; }
|
2020-02-01 16:57:55 +01:00
|
|
|
void setTrueOrFalse(bool flag) { m_e = flag ? BU_TRUE : BU_FALSE; }
|
2020-02-02 16:34:29 +01:00
|
|
|
};
|
|
|
|
|
inline bool operator==(const VBoolOrUnknown& lhs, const VBoolOrUnknown& rhs) {
|
|
|
|
|
return lhs.m_e == rhs.m_e;
|
|
|
|
|
}
|
|
|
|
|
inline bool operator==(const VBoolOrUnknown& lhs, VBoolOrUnknown::en rhs) {
|
|
|
|
|
return lhs.m_e == rhs;
|
|
|
|
|
}
|
|
|
|
|
inline bool operator==(VBoolOrUnknown::en lhs, const VBoolOrUnknown& rhs) {
|
|
|
|
|
return lhs == rhs.m_e;
|
|
|
|
|
}
|
|
|
|
|
inline std::ostream& operator<<(std::ostream& os, const VBoolOrUnknown& rhs) {
|
|
|
|
|
return os << rhs.ascii();
|
|
|
|
|
}
|
2019-01-16 06:38:42 +01:00
|
|
|
|
|
|
|
|
//######################################################################
|
|
|
|
|
|
2020-04-23 03:31:40 +02:00
|
|
|
/// Join type
|
2020-11-19 03:32:16 +01:00
|
|
|
class VJoinType final {
|
2020-04-23 03:31:40 +02:00
|
|
|
public:
|
2020-08-16 18:05:35 +02:00
|
|
|
enum en : uint8_t { JOIN = 0, JOIN_ANY = 1, JOIN_NONE = 2 };
|
2020-04-23 03:31:40 +02:00
|
|
|
enum en m_e;
|
|
|
|
|
// CONSTRUCTOR - note defaults to *UNKNOWN*
|
|
|
|
|
inline VJoinType()
|
2020-08-16 17:40:42 +02:00
|
|
|
: m_e{JOIN} {}
|
2020-04-23 03:31:40 +02:00
|
|
|
// cppcheck-suppress noExplicitConstructor
|
|
|
|
|
inline VJoinType(en _e)
|
2020-08-16 17:40:42 +02:00
|
|
|
: m_e{_e} {}
|
2020-04-23 03:31:40 +02:00
|
|
|
explicit inline VJoinType(int _e)
|
2020-08-18 14:10:44 +02:00
|
|
|
: m_e(static_cast<en>(_e)) {} // Need () or GCC 4.8 false warning
|
2020-04-23 03:31:40 +02:00
|
|
|
const char* ascii() const {
|
|
|
|
|
static const char* const names[] = {"JOIN", "JOIN_ANY", "JOIN_NONE"};
|
|
|
|
|
return names[m_e];
|
|
|
|
|
}
|
|
|
|
|
const char* verilogKwd() const {
|
|
|
|
|
static const char* const names[] = {"join", "join_any", "join_none"};
|
|
|
|
|
return names[m_e];
|
|
|
|
|
}
|
|
|
|
|
bool join() const { return m_e == JOIN; }
|
|
|
|
|
bool joinAny() const { return m_e == JOIN_ANY; }
|
|
|
|
|
bool joinNone() const { return m_e == JOIN_NONE; }
|
|
|
|
|
};
|
|
|
|
|
inline bool operator==(const VJoinType& lhs, const VJoinType& rhs) { return lhs.m_e == rhs.m_e; }
|
|
|
|
|
inline bool operator==(const VJoinType& lhs, VJoinType::en rhs) { return lhs.m_e == rhs; }
|
|
|
|
|
inline bool operator==(VJoinType::en lhs, const VJoinType& rhs) { return lhs == rhs.m_e; }
|
|
|
|
|
inline std::ostream& operator<<(std::ostream& os, const VJoinType& rhs) {
|
|
|
|
|
return os << rhs.ascii();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//######################################################################
|
|
|
|
|
|
2020-11-19 03:32:16 +01:00
|
|
|
class AstVarType final {
|
2006-08-26 13:35:28 +02:00
|
|
|
public:
|
2020-08-16 18:05:35 +02:00
|
|
|
enum en : uint8_t {
|
2018-10-27 23:29:00 +02:00
|
|
|
UNKNOWN,
|
|
|
|
|
GPARAM,
|
|
|
|
|
LPARAM,
|
|
|
|
|
GENVAR,
|
|
|
|
|
VAR, // Reg, integer, logic, etc
|
|
|
|
|
SUPPLY0,
|
2019-05-19 22:13:13 +02:00
|
|
|
SUPPLY1,
|
|
|
|
|
WIRE,
|
|
|
|
|
WREAL,
|
|
|
|
|
IMPLICITWIRE,
|
|
|
|
|
TRIWIRE,
|
|
|
|
|
TRI0,
|
|
|
|
|
TRI1,
|
2020-04-15 13:58:34 +02:00
|
|
|
PORT, // Temp type used in parser only
|
2019-05-19 22:13:13 +02:00
|
|
|
BLOCKTEMP,
|
|
|
|
|
MODULETEMP,
|
|
|
|
|
STMTTEMP,
|
|
|
|
|
XTEMP,
|
2020-04-11 03:10:21 +02:00
|
|
|
IFACEREF, // Used to link Interfaces between modules
|
2020-11-01 16:56:07 +01:00
|
|
|
MEMBER
|
2006-08-26 13:35:28 +02:00
|
|
|
};
|
|
|
|
|
enum en m_e;
|
2020-04-15 13:58:34 +02:00
|
|
|
inline AstVarType()
|
2020-08-16 17:40:42 +02:00
|
|
|
: m_e{UNKNOWN} {}
|
2015-10-04 04:33:06 +02:00
|
|
|
// cppcheck-suppress noExplicitConstructor
|
2020-04-15 13:58:34 +02:00
|
|
|
inline AstVarType(en _e)
|
2020-08-16 17:40:42 +02:00
|
|
|
: m_e{_e} {}
|
2020-04-15 13:58:34 +02:00
|
|
|
explicit inline AstVarType(int _e)
|
2020-08-18 14:10:44 +02:00
|
|
|
: m_e(static_cast<en>(_e)) {} // Need () or GCC 4.8 false warning
|
2018-08-25 15:52:45 +02:00
|
|
|
operator en() const { return m_e; }
|
2006-08-26 13:35:28 +02:00
|
|
|
const char* ascii() const {
|
2018-10-27 23:29:00 +02:00
|
|
|
static const char* const names[] = {
|
2020-04-15 13:58:34 +02:00
|
|
|
"?", "GPARAM", "LPARAM", "GENVAR", "VAR", "SUPPLY0", "SUPPLY1",
|
|
|
|
|
"WIRE", "WREAL", "IMPLICITWIRE", "TRIWIRE", "TRI0", "TRI1", "PORT",
|
2020-11-01 16:56:07 +01:00
|
|
|
"BLOCKTEMP", "MODULETEMP", "STMTTEMP", "XTEMP", "IFACEREF", "MEMBER"};
|
2020-04-15 13:58:34 +02:00
|
|
|
return names[m_e];
|
|
|
|
|
}
|
2018-11-26 23:58:18 +01:00
|
|
|
bool isSignal() const {
|
2020-04-15 13:58:34 +02:00
|
|
|
return (m_e == WIRE || m_e == WREAL || m_e == IMPLICITWIRE || m_e == TRIWIRE || m_e == TRI0
|
|
|
|
|
|| m_e == TRI1 || m_e == PORT || m_e == SUPPLY0 || m_e == SUPPLY1 || m_e == VAR);
|
2018-11-26 23:58:18 +01:00
|
|
|
}
|
2018-12-01 16:12:10 +01:00
|
|
|
bool isContAssignable() const { // In Verilog, always ok in SystemVerilog
|
2020-04-15 13:58:34 +02:00
|
|
|
return (m_e == SUPPLY0 || m_e == SUPPLY1 || m_e == WIRE || m_e == WREAL
|
|
|
|
|
|| m_e == IMPLICITWIRE || m_e == TRIWIRE || m_e == TRI0 || m_e == TRI1
|
|
|
|
|
|| m_e == PORT || m_e == BLOCKTEMP || m_e == MODULETEMP || m_e == STMTTEMP
|
|
|
|
|
|| m_e == XTEMP || m_e == IFACEREF);
|
2018-12-01 16:12:10 +01:00
|
|
|
}
|
2018-11-26 23:58:18 +01:00
|
|
|
bool isProcAssignable() const {
|
2020-04-15 13:58:34 +02:00
|
|
|
return (m_e == GPARAM || m_e == LPARAM || m_e == GENVAR || m_e == VAR || m_e == BLOCKTEMP
|
|
|
|
|
|| m_e == MODULETEMP || m_e == STMTTEMP || m_e == XTEMP || m_e == IFACEREF
|
2020-11-01 16:56:07 +01:00
|
|
|
|| m_e == MEMBER);
|
2018-11-26 23:58:18 +01:00
|
|
|
}
|
2019-10-27 14:27:18 +01:00
|
|
|
bool isTemp() const {
|
2020-04-15 13:58:34 +02:00
|
|
|
return (m_e == BLOCKTEMP || m_e == MODULETEMP || m_e == STMTTEMP || m_e == XTEMP);
|
2019-10-27 14:27:18 +01:00
|
|
|
}
|
2020-02-02 16:34:29 +01:00
|
|
|
};
|
|
|
|
|
inline bool operator==(const AstVarType& lhs, const AstVarType& rhs) { return lhs.m_e == rhs.m_e; }
|
|
|
|
|
inline bool operator==(const AstVarType& lhs, AstVarType::en rhs) { return lhs.m_e == rhs; }
|
|
|
|
|
inline bool operator==(AstVarType::en lhs, const AstVarType& rhs) { return lhs == rhs.m_e; }
|
|
|
|
|
inline std::ostream& operator<<(std::ostream& os, const AstVarType& rhs) {
|
|
|
|
|
return os << rhs.ascii();
|
|
|
|
|
}
|
2006-08-26 13:35:28 +02:00
|
|
|
|
|
|
|
|
//######################################################################
|
|
|
|
|
|
2020-11-19 03:32:16 +01:00
|
|
|
class VBranchPred final {
|
2006-08-26 13:35:28 +02:00
|
|
|
public:
|
2020-08-16 18:05:35 +02:00
|
|
|
enum en : uint8_t { BP_UNKNOWN = 0, BP_LIKELY, BP_UNLIKELY, _ENUM_END };
|
2006-08-26 13:35:28 +02:00
|
|
|
enum en m_e;
|
|
|
|
|
// CONSTRUCTOR - note defaults to *UNKNOWN*
|
2020-04-15 13:58:34 +02:00
|
|
|
inline VBranchPred()
|
2020-08-16 17:40:42 +02:00
|
|
|
: m_e{BP_UNKNOWN} {}
|
2015-10-04 04:33:06 +02:00
|
|
|
// cppcheck-suppress noExplicitConstructor
|
2020-04-15 13:58:34 +02:00
|
|
|
inline VBranchPred(en _e)
|
2020-08-16 17:40:42 +02:00
|
|
|
: m_e{_e} {}
|
2020-04-15 13:58:34 +02:00
|
|
|
explicit inline VBranchPred(int _e)
|
2020-08-18 14:10:44 +02:00
|
|
|
: m_e(static_cast<en>(_e)) {} // Need () or GCC 4.8 false warning
|
2018-08-25 15:52:45 +02:00
|
|
|
operator en() const { return m_e; }
|
2019-10-05 13:54:14 +02:00
|
|
|
bool unknown() const { return m_e == BP_UNKNOWN; }
|
|
|
|
|
bool likely() const { return m_e == BP_LIKELY; }
|
|
|
|
|
bool unlikely() const { return m_e == BP_UNLIKELY; }
|
|
|
|
|
VBranchPred invert() const {
|
2020-04-15 13:58:34 +02:00
|
|
|
if (m_e == BP_UNLIKELY) {
|
|
|
|
|
return BP_LIKELY;
|
|
|
|
|
} else if (m_e == BP_LIKELY) {
|
|
|
|
|
return BP_UNLIKELY;
|
|
|
|
|
} else {
|
|
|
|
|
return m_e;
|
|
|
|
|
}
|
2006-08-26 13:35:28 +02:00
|
|
|
}
|
|
|
|
|
const char* ascii() const {
|
2020-04-15 13:58:34 +02:00
|
|
|
static const char* const names[] = {"", "VL_LIKELY", "VL_UNLIKELY"};
|
|
|
|
|
return names[m_e];
|
|
|
|
|
}
|
2020-02-02 16:34:29 +01:00
|
|
|
};
|
|
|
|
|
inline bool operator==(const VBranchPred& lhs, const VBranchPred& rhs) {
|
|
|
|
|
return lhs.m_e == rhs.m_e;
|
|
|
|
|
}
|
|
|
|
|
inline bool operator==(const VBranchPred& lhs, VBranchPred::en rhs) { return lhs.m_e == rhs; }
|
|
|
|
|
inline bool operator==(VBranchPred::en lhs, const VBranchPred& rhs) { return lhs == rhs.m_e; }
|
|
|
|
|
inline std::ostream& operator<<(std::ostream& os, const VBranchPred& rhs) {
|
|
|
|
|
return os << rhs.ascii();
|
|
|
|
|
}
|
2006-08-26 13:35:28 +02:00
|
|
|
|
2006-12-21 22:53:51 +01:00
|
|
|
//######################################################################
|
|
|
|
|
|
2020-11-19 03:32:16 +01:00
|
|
|
class VVarAttrClocker final {
|
2015-03-13 00:20:46 +01:00
|
|
|
public:
|
2020-08-16 18:05:35 +02:00
|
|
|
enum en : uint8_t { CLOCKER_UNKNOWN = 0, CLOCKER_YES, CLOCKER_NO, _ENUM_END };
|
2015-03-13 00:20:46 +01:00
|
|
|
enum en m_e;
|
|
|
|
|
// CONSTRUCTOR - note defaults to *UNKNOWN*
|
2020-04-15 13:58:34 +02:00
|
|
|
inline VVarAttrClocker()
|
2020-08-16 17:40:42 +02:00
|
|
|
: m_e{CLOCKER_UNKNOWN} {}
|
2015-10-04 04:33:06 +02:00
|
|
|
// cppcheck-suppress noExplicitConstructor
|
2020-04-15 13:58:34 +02:00
|
|
|
inline VVarAttrClocker(en _e)
|
2020-08-16 17:40:42 +02:00
|
|
|
: m_e{_e} {}
|
2020-04-15 13:58:34 +02:00
|
|
|
explicit inline VVarAttrClocker(int _e)
|
2020-08-18 14:10:44 +02:00
|
|
|
: m_e(static_cast<en>(_e)) {} // Need () or GCC 4.8 false warning
|
2018-08-25 15:52:45 +02:00
|
|
|
operator en() const { return m_e; }
|
2020-04-15 13:58:34 +02:00
|
|
|
bool unknown() const { return m_e == CLOCKER_UNKNOWN; }
|
2019-10-05 13:54:14 +02:00
|
|
|
VVarAttrClocker invert() const {
|
2020-04-15 13:58:34 +02:00
|
|
|
if (m_e == CLOCKER_YES) {
|
|
|
|
|
return CLOCKER_NO;
|
|
|
|
|
} else if (m_e == CLOCKER_NO) {
|
|
|
|
|
return CLOCKER_YES;
|
|
|
|
|
} else {
|
|
|
|
|
return m_e;
|
|
|
|
|
}
|
2015-03-13 00:20:46 +01:00
|
|
|
}
|
|
|
|
|
const char* ascii() const {
|
2020-04-15 13:58:34 +02:00
|
|
|
static const char* const names[] = {"", "clker", "non_clker"};
|
|
|
|
|
return names[m_e];
|
|
|
|
|
}
|
2020-02-02 16:34:29 +01:00
|
|
|
};
|
|
|
|
|
inline bool operator==(const VVarAttrClocker& lhs, const VVarAttrClocker& rhs) {
|
|
|
|
|
return lhs.m_e == rhs.m_e;
|
|
|
|
|
}
|
|
|
|
|
inline bool operator==(const VVarAttrClocker& lhs, VVarAttrClocker::en rhs) {
|
|
|
|
|
return lhs.m_e == rhs;
|
|
|
|
|
}
|
|
|
|
|
inline bool operator==(VVarAttrClocker::en lhs, const VVarAttrClocker& rhs) {
|
|
|
|
|
return lhs == rhs.m_e;
|
|
|
|
|
}
|
|
|
|
|
inline std::ostream& operator<<(std::ostream& os, const VVarAttrClocker& rhs) {
|
|
|
|
|
return os << rhs.ascii();
|
|
|
|
|
}
|
2015-03-13 00:20:46 +01:00
|
|
|
|
|
|
|
|
//######################################################################
|
|
|
|
|
|
2020-11-19 03:32:16 +01:00
|
|
|
class VAlwaysKwd final {
|
2013-05-01 04:55:28 +02:00
|
|
|
public:
|
2020-08-16 18:05:35 +02:00
|
|
|
enum en : uint8_t { ALWAYS, ALWAYS_FF, ALWAYS_LATCH, ALWAYS_COMB };
|
2013-05-01 04:55:28 +02:00
|
|
|
enum en m_e;
|
2020-04-15 13:58:34 +02:00
|
|
|
inline VAlwaysKwd()
|
2020-08-16 17:40:42 +02:00
|
|
|
: m_e{ALWAYS} {}
|
2015-10-04 04:33:06 +02:00
|
|
|
// cppcheck-suppress noExplicitConstructor
|
2020-04-15 13:58:34 +02:00
|
|
|
inline VAlwaysKwd(en _e)
|
2020-08-16 17:40:42 +02:00
|
|
|
: m_e{_e} {}
|
2020-04-15 13:58:34 +02:00
|
|
|
explicit inline VAlwaysKwd(int _e)
|
2020-08-18 14:10:44 +02:00
|
|
|
: m_e(static_cast<en>(_e)) {} // Need () or GCC 4.8 false warning
|
2018-08-25 15:52:45 +02:00
|
|
|
operator en() const { return m_e; }
|
2013-05-01 04:55:28 +02:00
|
|
|
const char* ascii() const {
|
2020-04-15 13:58:34 +02:00
|
|
|
static const char* const names[] = {"always", "always_ff", "always_latch", "always_comb"};
|
|
|
|
|
return names[m_e];
|
|
|
|
|
}
|
2020-02-02 16:34:29 +01:00
|
|
|
};
|
|
|
|
|
inline bool operator==(const VAlwaysKwd& lhs, const VAlwaysKwd& rhs) { return lhs.m_e == rhs.m_e; }
|
|
|
|
|
inline bool operator==(const VAlwaysKwd& lhs, VAlwaysKwd::en rhs) { return lhs.m_e == rhs; }
|
|
|
|
|
inline bool operator==(VAlwaysKwd::en lhs, const VAlwaysKwd& rhs) { return lhs == rhs.m_e; }
|
2013-05-01 04:55:28 +02:00
|
|
|
|
|
|
|
|
//######################################################################
|
|
|
|
|
|
2020-11-19 03:32:16 +01:00
|
|
|
class VCaseType final {
|
2008-07-22 19:07:19 +02:00
|
|
|
public:
|
2020-08-16 18:05:35 +02:00
|
|
|
enum en : uint8_t { CT_CASE, CT_CASEX, CT_CASEZ, CT_CASEINSIDE };
|
2008-07-22 19:07:19 +02:00
|
|
|
enum en m_e;
|
2020-04-15 13:58:34 +02:00
|
|
|
inline VCaseType()
|
2020-08-16 17:40:42 +02:00
|
|
|
: m_e{CT_CASE} {}
|
2015-10-04 04:33:06 +02:00
|
|
|
// cppcheck-suppress noExplicitConstructor
|
2020-04-15 13:58:34 +02:00
|
|
|
inline VCaseType(en _e)
|
2020-08-16 17:40:42 +02:00
|
|
|
: m_e{_e} {}
|
2020-04-15 13:58:34 +02:00
|
|
|
explicit inline VCaseType(int _e)
|
2020-08-18 14:10:44 +02:00
|
|
|
: m_e(static_cast<en>(_e)) {} // Need () or GCC 4.8 false warning
|
2018-08-25 15:52:45 +02:00
|
|
|
operator en() const { return m_e; }
|
2020-02-02 16:34:29 +01:00
|
|
|
};
|
|
|
|
|
inline bool operator==(const VCaseType& lhs, const VCaseType& rhs) { return lhs.m_e == rhs.m_e; }
|
|
|
|
|
inline bool operator==(const VCaseType& lhs, VCaseType::en rhs) { return lhs.m_e == rhs; }
|
|
|
|
|
inline bool operator==(VCaseType::en lhs, const VCaseType& rhs) { return lhs == rhs.m_e; }
|
2008-07-22 19:07:19 +02:00
|
|
|
|
|
|
|
|
//######################################################################
|
|
|
|
|
|
2020-11-19 03:32:16 +01:00
|
|
|
class AstDisplayType final {
|
2007-03-06 22:43:38 +01:00
|
|
|
public:
|
2020-11-29 17:31:38 +01:00
|
|
|
enum en : uint8_t {
|
|
|
|
|
DT_DISPLAY,
|
|
|
|
|
DT_WRITE,
|
|
|
|
|
DT_MONITOR,
|
|
|
|
|
DT_STROBE,
|
|
|
|
|
DT_INFO,
|
|
|
|
|
DT_ERROR,
|
|
|
|
|
DT_WARNING,
|
|
|
|
|
DT_FATAL
|
|
|
|
|
};
|
2007-03-06 22:43:38 +01:00
|
|
|
enum en m_e;
|
2020-11-29 17:31:38 +01:00
|
|
|
AstDisplayType()
|
2020-08-16 17:40:42 +02:00
|
|
|
: m_e{DT_DISPLAY} {}
|
2015-10-04 04:33:06 +02:00
|
|
|
// cppcheck-suppress noExplicitConstructor
|
2020-11-29 17:31:38 +01:00
|
|
|
AstDisplayType(en _e)
|
2020-08-16 17:40:42 +02:00
|
|
|
: m_e{_e} {}
|
2020-04-15 13:58:34 +02:00
|
|
|
explicit inline AstDisplayType(int _e)
|
2020-08-18 14:10:44 +02:00
|
|
|
: m_e(static_cast<en>(_e)) {} // Need () or GCC 4.8 false warning
|
2018-08-25 15:52:45 +02:00
|
|
|
operator en() const { return m_e; }
|
2020-04-15 13:58:34 +02:00
|
|
|
bool addNewline() const { return m_e != DT_WRITE; }
|
|
|
|
|
bool needScopeTracking() const { return m_e != DT_DISPLAY && m_e != DT_WRITE; }
|
2007-03-06 22:43:38 +01:00
|
|
|
const char* ascii() const {
|
2020-04-15 13:58:34 +02:00
|
|
|
static const char* const names[]
|
2020-11-29 17:31:38 +01:00
|
|
|
= {"display", "write", "monitor", "strobe", "info", "error", "warning", "fatal"};
|
2020-04-15 13:58:34 +02:00
|
|
|
return names[m_e];
|
|
|
|
|
}
|
2020-02-02 16:34:29 +01:00
|
|
|
};
|
|
|
|
|
inline bool operator==(const AstDisplayType& lhs, const AstDisplayType& rhs) {
|
|
|
|
|
return lhs.m_e == rhs.m_e;
|
|
|
|
|
}
|
|
|
|
|
inline bool operator==(const AstDisplayType& lhs, AstDisplayType::en rhs) {
|
|
|
|
|
return lhs.m_e == rhs;
|
|
|
|
|
}
|
|
|
|
|
inline bool operator==(AstDisplayType::en lhs, const AstDisplayType& rhs) {
|
|
|
|
|
return lhs == rhs.m_e;
|
|
|
|
|
}
|
2007-03-06 22:43:38 +01:00
|
|
|
|
|
|
|
|
//######################################################################
|
|
|
|
|
|
2020-11-19 03:32:16 +01:00
|
|
|
class VDumpCtlType final {
|
2020-03-02 03:39:23 +01:00
|
|
|
public:
|
2020-08-16 18:05:35 +02:00
|
|
|
enum en : uint8_t { FILE, VARS, ALL, FLUSH, LIMIT, OFF, ON };
|
2020-03-02 03:39:23 +01:00
|
|
|
enum en m_e;
|
|
|
|
|
inline VDumpCtlType()
|
2020-08-16 17:40:42 +02:00
|
|
|
: m_e{ON} {}
|
2020-03-02 03:39:23 +01:00
|
|
|
// cppcheck-suppress noExplicitConstructor
|
|
|
|
|
inline VDumpCtlType(en _e)
|
2020-08-16 17:40:42 +02:00
|
|
|
: m_e{_e} {}
|
2020-03-02 03:39:23 +01:00
|
|
|
explicit inline VDumpCtlType(int _e)
|
2020-08-18 14:10:44 +02:00
|
|
|
: m_e(static_cast<en>(_e)) {} // Need () or GCC 4.8 false warning
|
2020-03-02 03:39:23 +01:00
|
|
|
operator en() const { return m_e; }
|
|
|
|
|
const char* ascii() const {
|
2020-04-15 13:58:34 +02:00
|
|
|
static const char* const names[] = {"$dumpfile", "$dumpvars", "$dumpall", "$dumpflush",
|
|
|
|
|
"$dumplimit", "$dumpoff", "$dumpon"};
|
2020-03-02 03:39:23 +01:00
|
|
|
return names[m_e];
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
inline bool operator==(const VDumpCtlType& lhs, const VDumpCtlType& rhs) {
|
|
|
|
|
return lhs.m_e == rhs.m_e;
|
|
|
|
|
}
|
|
|
|
|
inline bool operator==(const VDumpCtlType& lhs, VDumpCtlType::en rhs) { return lhs.m_e == rhs; }
|
|
|
|
|
inline bool operator==(VDumpCtlType::en lhs, const VDumpCtlType& rhs) { return lhs == rhs.m_e; }
|
|
|
|
|
|
|
|
|
|
//######################################################################
|
|
|
|
|
|
2020-11-19 03:32:16 +01:00
|
|
|
class VParseRefExp final {
|
2006-12-21 22:53:51 +01:00
|
|
|
public:
|
2020-08-16 18:05:35 +02:00
|
|
|
enum en : uint8_t {
|
2020-04-15 13:58:34 +02:00
|
|
|
PX_NONE, // Used in V3LinkParse only
|
2020-05-02 14:29:20 +02:00
|
|
|
PX_ROOT,
|
2020-04-15 13:58:34 +02:00
|
|
|
PX_TEXT // Unknown ID component
|
2006-12-21 22:53:51 +01:00
|
|
|
};
|
|
|
|
|
enum en m_e;
|
2020-04-15 13:58:34 +02:00
|
|
|
inline VParseRefExp()
|
2020-08-16 17:40:42 +02:00
|
|
|
: m_e{PX_NONE} {}
|
2015-10-04 04:33:06 +02:00
|
|
|
// cppcheck-suppress noExplicitConstructor
|
2020-04-15 13:58:34 +02:00
|
|
|
inline VParseRefExp(en _e)
|
2020-08-16 17:40:42 +02:00
|
|
|
: m_e{_e} {}
|
2020-04-15 13:58:34 +02:00
|
|
|
explicit inline VParseRefExp(int _e)
|
2020-08-18 14:10:44 +02:00
|
|
|
: m_e(static_cast<en>(_e)) {} // Need () or GCC 4.8 false warning
|
2018-08-25 15:52:45 +02:00
|
|
|
operator en() const { return m_e; }
|
2006-12-21 22:53:51 +01:00
|
|
|
const char* ascii() const {
|
2020-05-02 14:29:20 +02:00
|
|
|
static const char* const names[] = {"", "$root", "TEXT", "PREDOT"};
|
2020-04-15 13:58:34 +02:00
|
|
|
return names[m_e];
|
|
|
|
|
}
|
2020-02-02 16:34:29 +01:00
|
|
|
};
|
|
|
|
|
inline bool operator==(const VParseRefExp& lhs, const VParseRefExp& rhs) {
|
|
|
|
|
return lhs.m_e == rhs.m_e;
|
|
|
|
|
}
|
|
|
|
|
inline bool operator==(const VParseRefExp& lhs, VParseRefExp::en rhs) { return lhs.m_e == rhs; }
|
|
|
|
|
inline bool operator==(VParseRefExp::en lhs, const VParseRefExp& rhs) { return lhs == rhs.m_e; }
|
|
|
|
|
inline std::ostream& operator<<(std::ostream& os, const VParseRefExp& rhs) {
|
|
|
|
|
return os << rhs.ascii();
|
|
|
|
|
}
|
2006-12-21 22:53:51 +01:00
|
|
|
|
2012-04-29 16:14:13 +02:00
|
|
|
//######################################################################
|
2019-09-09 13:50:21 +02:00
|
|
|
// VNumRange - Structure containing numeric range information
|
2012-04-29 16:14:13 +02:00
|
|
|
// See also AstRange, which is a symbolic version of this
|
|
|
|
|
|
2020-11-19 03:32:16 +01:00
|
|
|
class VNumRange final {
|
2019-10-05 13:54:14 +02:00
|
|
|
public:
|
2020-12-07 03:13:56 +01:00
|
|
|
int m_left = 0;
|
|
|
|
|
int m_right = 0;
|
|
|
|
|
bool m_ranged = false; // Has a range
|
2020-12-02 00:49:03 +01:00
|
|
|
bool operator==(const VNumRange& rhs) const {
|
2020-12-07 03:13:56 +01:00
|
|
|
return m_left == rhs.m_left && m_right == rhs.m_right && m_ranged == rhs.m_ranged;
|
2020-04-15 13:58:34 +02:00
|
|
|
}
|
2020-12-02 00:49:03 +01:00
|
|
|
bool operator<(const VNumRange& rhs) const {
|
2020-12-07 03:13:56 +01:00
|
|
|
if ((m_left < rhs.m_left)) return true;
|
|
|
|
|
if (!(m_left == rhs.m_left)) return false; // lhs > rhs
|
|
|
|
|
if ((m_right < rhs.m_right)) return true;
|
|
|
|
|
if (!(m_right == rhs.m_right)) return false; // lhs > rhs
|
|
|
|
|
if ((m_ranged < rhs.m_ranged)) return true;
|
|
|
|
|
if (!(m_ranged == rhs.m_ranged)) return false; // lhs > rhs
|
2019-05-19 22:13:13 +02:00
|
|
|
return false;
|
2012-04-29 16:14:13 +02:00
|
|
|
}
|
|
|
|
|
//
|
2020-12-07 03:13:56 +01:00
|
|
|
VNumRange() {}
|
|
|
|
|
VNumRange(int hi, int lo, bool littleEndian) { init(hi, lo, littleEndian); }
|
|
|
|
|
VNumRange(int left, int right)
|
|
|
|
|
: m_left{left}
|
|
|
|
|
, m_right{right}
|
|
|
|
|
, m_ranged{true} {}
|
2020-11-17 01:56:16 +01:00
|
|
|
~VNumRange() = default;
|
2012-04-29 16:14:13 +02:00
|
|
|
// MEMBERS
|
2013-01-18 02:29:20 +01:00
|
|
|
void init(int hi, int lo, bool littleEndian) {
|
2020-12-07 03:13:56 +01:00
|
|
|
if (lo > hi) {
|
2021-11-26 23:55:36 +01:00
|
|
|
const int t = hi;
|
2020-12-07 03:13:56 +01:00
|
|
|
hi = lo;
|
|
|
|
|
lo = t;
|
|
|
|
|
}
|
|
|
|
|
m_left = littleEndian ? lo : hi;
|
|
|
|
|
m_right = littleEndian ? hi : lo;
|
2020-04-15 13:58:34 +02:00
|
|
|
m_ranged = true;
|
2012-04-29 16:14:13 +02:00
|
|
|
}
|
2020-12-07 03:13:56 +01:00
|
|
|
int left() const { return m_left; }
|
|
|
|
|
int right() const { return m_right; }
|
|
|
|
|
int hi() const { return m_left > m_right ? m_left : m_right; } // How to show a declaration
|
|
|
|
|
int lo() const { return m_left > m_right ? m_right : m_left; } // How to show a declaration
|
2020-04-15 13:58:34 +02:00
|
|
|
int leftToRightInc() const { return littleEndian() ? 1 : -1; }
|
|
|
|
|
int elements() const { return hi() - lo() + 1; }
|
2012-04-29 16:14:13 +02:00
|
|
|
bool ranged() const { return m_ranged; }
|
2020-12-07 03:13:56 +01:00
|
|
|
bool littleEndian() const { return m_left < m_right; }
|
2020-04-15 13:58:34 +02:00
|
|
|
int hiMaxSelect() const {
|
|
|
|
|
return (lo() < 0 ? hi() - lo() : hi());
|
|
|
|
|
} // Maximum value a [] select may index
|
2019-05-19 22:13:13 +02:00
|
|
|
void dump(std::ostream& str) const {
|
2020-04-15 13:58:34 +02:00
|
|
|
if (ranged()) {
|
|
|
|
|
str << "[" << left() << ":" << right() << "]";
|
|
|
|
|
} else {
|
|
|
|
|
str << "[norg]";
|
|
|
|
|
}
|
|
|
|
|
}
|
2012-04-29 16:14:13 +02:00
|
|
|
};
|
2020-04-15 13:58:34 +02:00
|
|
|
inline std::ostream& operator<<(std::ostream& os, const VNumRange& rhs) {
|
|
|
|
|
rhs.dump(os);
|
|
|
|
|
return os;
|
|
|
|
|
}
|
2012-04-29 16:14:13 +02:00
|
|
|
|
|
|
|
|
//######################################################################
|
|
|
|
|
|
2020-11-19 03:32:16 +01:00
|
|
|
class VUseType final {
|
2020-02-01 22:45:11 +01:00
|
|
|
public:
|
2020-08-16 18:05:35 +02:00
|
|
|
enum en : uint8_t {
|
2020-02-01 22:45:11 +01:00
|
|
|
IMP_INCLUDE, // Implementation (.cpp) needs an include
|
|
|
|
|
INT_INCLUDE, // Interface (.h) needs an include
|
|
|
|
|
IMP_FWD_CLASS, // Implementation (.cpp) needs a forward class declaration
|
|
|
|
|
INT_FWD_CLASS, // Interface (.h) needs a forward class declaration
|
|
|
|
|
};
|
|
|
|
|
enum en m_e;
|
2020-04-15 13:58:34 +02:00
|
|
|
inline VUseType()
|
2020-08-16 17:40:42 +02:00
|
|
|
: m_e{IMP_FWD_CLASS} {}
|
2020-02-01 22:45:11 +01:00
|
|
|
// cppcheck-suppress noExplicitConstructor
|
2020-04-15 13:58:34 +02:00
|
|
|
inline VUseType(en _e)
|
2020-08-16 17:40:42 +02:00
|
|
|
: m_e{_e} {}
|
2020-04-15 13:58:34 +02:00
|
|
|
explicit inline VUseType(int _e)
|
2020-08-18 14:10:44 +02:00
|
|
|
: m_e(static_cast<en>(_e)) {} // Need () or GCC 4.8 false warning
|
2020-02-01 22:45:11 +01:00
|
|
|
bool isInclude() const { return m_e == IMP_INCLUDE || m_e == INT_INCLUDE; }
|
|
|
|
|
bool isFwdClass() const { return m_e == IMP_FWD_CLASS || m_e == INT_FWD_CLASS; }
|
|
|
|
|
operator en() const { return m_e; }
|
|
|
|
|
const char* ascii() const {
|
|
|
|
|
static const char* const names[] = {"IMP_INC", "INT_INC", "IMP_FWD", "INT_FWD"};
|
|
|
|
|
return names[m_e];
|
|
|
|
|
}
|
|
|
|
|
};
|
2020-02-02 16:34:29 +01:00
|
|
|
inline bool operator==(const VUseType& lhs, const VUseType& rhs) { return lhs.m_e == rhs.m_e; }
|
|
|
|
|
inline bool operator==(const VUseType& lhs, VUseType::en rhs) { return lhs.m_e == rhs; }
|
|
|
|
|
inline bool operator==(VUseType::en lhs, const VUseType& rhs) { return lhs == rhs.m_e; }
|
2020-02-01 22:45:11 +01:00
|
|
|
inline std::ostream& operator<<(std::ostream& os, const VUseType& rhs) {
|
|
|
|
|
return os << rhs.ascii();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//######################################################################
|
|
|
|
|
|
2020-11-19 03:32:16 +01:00
|
|
|
class VBasicTypeKey final {
|
2019-10-05 13:54:14 +02:00
|
|
|
public:
|
2021-11-26 23:55:36 +01:00
|
|
|
const int m_width; // From AstNodeDType: Bit width of operation
|
|
|
|
|
const int m_widthMin; // From AstNodeDType: If unsized, bitwidth of minimum implementation
|
|
|
|
|
const VSigning m_numeric; // From AstNodeDType: Node is signed
|
|
|
|
|
const AstBasicDTypeKwd m_keyword; // From AstBasicDType: What keyword created basic type
|
|
|
|
|
const VNumRange m_nrange; // From AstBasicDType: Numeric msb/lsb (if non-opaque keyword)
|
2020-12-02 00:49:03 +01:00
|
|
|
bool operator==(const VBasicTypeKey& rhs) const {
|
2020-04-15 13:58:34 +02:00
|
|
|
return m_width == rhs.m_width && m_widthMin == rhs.m_widthMin && m_numeric == rhs.m_numeric
|
|
|
|
|
&& m_keyword == rhs.m_keyword && m_nrange == rhs.m_nrange;
|
|
|
|
|
}
|
2020-12-02 00:49:03 +01:00
|
|
|
bool operator<(const VBasicTypeKey& rhs) const {
|
2020-04-15 13:58:34 +02:00
|
|
|
if ((m_width < rhs.m_width)) return true;
|
2019-05-19 22:13:13 +02:00
|
|
|
if (!(m_width == rhs.m_width)) return false; // lhs > rhs
|
2020-04-15 13:58:34 +02:00
|
|
|
if ((m_widthMin < rhs.m_widthMin)) return true;
|
2019-05-19 22:13:13 +02:00
|
|
|
if (!(m_widthMin == rhs.m_widthMin)) return false; // lhs > rhs
|
2020-04-15 13:58:34 +02:00
|
|
|
if ((m_numeric < rhs.m_numeric)) return true;
|
2019-05-19 22:13:13 +02:00
|
|
|
if (!(m_numeric == rhs.m_numeric)) return false; // lhs > rhs
|
2020-04-15 13:58:34 +02:00
|
|
|
if ((m_keyword < rhs.m_keyword)) return true;
|
2019-05-19 22:13:13 +02:00
|
|
|
if (!(m_keyword == rhs.m_keyword)) return false; // lhs > rhs
|
2020-04-15 13:58:34 +02:00
|
|
|
if ((m_nrange < rhs.m_nrange)) return true;
|
2019-05-19 22:13:13 +02:00
|
|
|
if (!(m_nrange == rhs.m_nrange)) return false; // lhs > rhs
|
2020-04-15 13:58:34 +02:00
|
|
|
return false;
|
|
|
|
|
}
|
2020-04-20 03:19:09 +02:00
|
|
|
VBasicTypeKey(int width, int widthMin, VSigning numeric, AstBasicDTypeKwd kwd,
|
2019-05-19 22:13:13 +02:00
|
|
|
const VNumRange& nrange)
|
2020-08-16 17:40:42 +02:00
|
|
|
: m_width{width}
|
|
|
|
|
, m_widthMin{widthMin}
|
|
|
|
|
, m_numeric{numeric}
|
|
|
|
|
, m_keyword{kwd}
|
|
|
|
|
, m_nrange{nrange} {}
|
2020-11-17 01:56:16 +01:00
|
|
|
~VBasicTypeKey() = default;
|
2012-04-29 16:14:13 +02:00
|
|
|
};
|
|
|
|
|
|
2006-08-26 13:35:28 +02:00
|
|
|
//######################################################################
|
2016-11-27 15:40:12 +01:00
|
|
|
// AstNUser - Generic base class for AST User nodes.
|
2019-05-19 22:13:13 +02:00
|
|
|
// - Also used to allow parameter passing up/down iterate calls
|
2006-08-26 13:35:28 +02:00
|
|
|
|
|
|
|
|
class WidthVP;
|
|
|
|
|
class V3GraphVertex;
|
2012-06-20 12:13:28 +02:00
|
|
|
class VSymEnt;
|
2016-11-27 15:40:12 +01:00
|
|
|
|
2020-11-19 03:32:16 +01:00
|
|
|
class VNUser final {
|
2016-11-27 15:40:12 +01:00
|
|
|
union {
|
2019-05-19 22:13:13 +02:00
|
|
|
void* up;
|
|
|
|
|
int ui;
|
2016-11-27 15:40:12 +01:00
|
|
|
} m_u;
|
2020-04-15 13:58:34 +02:00
|
|
|
|
2016-11-27 15:40:12 +01:00
|
|
|
public:
|
|
|
|
|
VNUser() {}
|
2017-07-07 02:25:59 +02:00
|
|
|
// non-explicit:
|
2017-10-14 20:51:57 +02:00
|
|
|
// cppcheck-suppress noExplicitConstructor
|
2020-04-15 13:58:34 +02:00
|
|
|
VNUser(int i) {
|
|
|
|
|
m_u.up = 0;
|
|
|
|
|
m_u.ui = i;
|
|
|
|
|
}
|
2017-07-07 02:25:59 +02:00
|
|
|
explicit VNUser(void* p) { m_u.up = p; }
|
2020-11-17 01:56:16 +01:00
|
|
|
~VNUser() = default;
|
2006-08-26 13:35:28 +02:00
|
|
|
// Casters
|
2021-06-17 18:27:45 +02:00
|
|
|
template <class T> //
|
|
|
|
|
typename std::enable_if<std::is_pointer<T>::value, T>::type to() const {
|
|
|
|
|
return reinterpret_cast<T>(m_u.up);
|
|
|
|
|
}
|
|
|
|
|
WidthVP* c() const { return to<WidthVP*>(); }
|
|
|
|
|
VSymEnt* toSymEnt() const { return to<VSymEnt*>(); }
|
|
|
|
|
AstNode* toNodep() const { return to<AstNode*>(); }
|
|
|
|
|
V3GraphVertex* toGraphVertex() const { return to<V3GraphVertex*>(); }
|
2020-06-02 05:16:02 +02:00
|
|
|
int toInt() const { return m_u.ui; }
|
2020-12-02 00:49:03 +01:00
|
|
|
static VNUser fromInt(int i) { return VNUser(i); }
|
2006-08-26 13:35:28 +02:00
|
|
|
};
|
|
|
|
|
|
2008-11-21 21:50:33 +01:00
|
|
|
//######################################################################
|
|
|
|
|
// AstUserResource - Generic pointer base class for tracking usage of user()
|
|
|
|
|
//
|
|
|
|
|
// Where AstNode->user2() is going to be used, for example, you write:
|
|
|
|
|
//
|
2019-05-19 22:13:13 +02:00
|
|
|
// AstUser2InUse m_userres;
|
2008-11-21 21:50:33 +01:00
|
|
|
//
|
2019-09-09 13:50:21 +02:00
|
|
|
// This will clear the tree, and prevent another visitor from clobbering
|
2008-11-21 21:50:33 +01:00
|
|
|
// user2. When the member goes out of scope it will be automagically
|
|
|
|
|
// freed up.
|
|
|
|
|
|
2020-11-19 03:32:16 +01:00
|
|
|
class AstUserInUseBase VL_NOT_FINAL {
|
2008-11-21 21:50:33 +01:00
|
|
|
protected:
|
2019-05-19 22:13:13 +02:00
|
|
|
static void allocate(int id, uint32_t& cntGblRef, bool& userBusyRef) {
|
|
|
|
|
// Perhaps there's still a AstUserInUse in scope for this?
|
2020-04-15 13:58:34 +02:00
|
|
|
UASSERT_STATIC(!userBusyRef, "Conflicting user use; AstUser" + cvtToStr(id)
|
|
|
|
|
+ "InUse request when under another AstUserInUse");
|
2019-05-19 22:13:13 +02:00
|
|
|
userBusyRef = true;
|
|
|
|
|
clearcnt(id, cntGblRef, userBusyRef);
|
2008-11-21 21:50:33 +01:00
|
|
|
}
|
2019-05-19 22:13:13 +02:00
|
|
|
static void free(int id, uint32_t& cntGblRef, bool& userBusyRef) {
|
2020-04-15 13:58:34 +02:00
|
|
|
UASSERT_STATIC(userBusyRef, "Free of User" + cvtToStr(id) + "() not under AstUserInUse");
|
2019-05-19 22:13:13 +02:00
|
|
|
clearcnt(id, cntGblRef, userBusyRef); // Includes a checkUse for us
|
|
|
|
|
userBusyRef = false;
|
2008-11-21 21:50:33 +01:00
|
|
|
}
|
2020-02-04 05:21:56 +01:00
|
|
|
static void clearcnt(int id, uint32_t& cntGblRef, const bool& userBusyRef) {
|
2020-04-15 13:58:34 +02:00
|
|
|
UASSERT_STATIC(userBusyRef, "Clear of User" + cvtToStr(id) + "() not under AstUserInUse");
|
2019-05-19 22:13:13 +02:00
|
|
|
// If this really fires and is real (after 2^32 edits???)
|
|
|
|
|
// we could just walk the tree and clear manually
|
|
|
|
|
++cntGblRef;
|
|
|
|
|
UASSERT_STATIC(cntGblRef, "User*() overflowed!");
|
2008-11-21 21:50:33 +01:00
|
|
|
}
|
2020-02-04 05:21:56 +01:00
|
|
|
static void checkcnt(int id, uint32_t&, const bool& userBusyRef) {
|
2020-04-15 13:58:34 +02:00
|
|
|
UASSERT_STATIC(userBusyRef,
|
|
|
|
|
"Check of User" + cvtToStr(id) + "() failed, not under AstUserInUse");
|
2009-11-08 00:03:23 +01:00
|
|
|
}
|
2008-11-21 21:50:33 +01:00
|
|
|
};
|
|
|
|
|
|
|
|
|
|
// For each user() declare the in use structure
|
|
|
|
|
// We let AstNode peek into here, because when under low optimization even
|
|
|
|
|
// an accessor would be way too slow.
|
2020-04-15 13:58:34 +02:00
|
|
|
// clang-format off
|
2020-11-19 03:32:16 +01:00
|
|
|
class AstUser1InUse final : AstUserInUseBase {
|
2008-11-21 21:50:33 +01:00
|
|
|
protected:
|
|
|
|
|
friend class AstNode;
|
2019-05-19 22:13:13 +02:00
|
|
|
static uint32_t s_userCntGbl; // Count of which usage of userp() this is
|
|
|
|
|
static bool s_userBusy; // Count is in use
|
2008-11-21 21:50:33 +01:00
|
|
|
public:
|
2009-09-24 05:10:46 +02:00
|
|
|
AstUser1InUse() { allocate(1, s_userCntGbl/*ref*/, s_userBusy/*ref*/); }
|
|
|
|
|
~AstUser1InUse() { free (1, s_userCntGbl/*ref*/, s_userBusy/*ref*/); }
|
|
|
|
|
static void clear() { clearcnt(1, s_userCntGbl/*ref*/, s_userBusy/*ref*/); }
|
2009-11-08 00:03:23 +01:00
|
|
|
static void check() { checkcnt(1, s_userCntGbl/*ref*/, s_userBusy/*ref*/); }
|
2008-11-21 21:50:33 +01:00
|
|
|
};
|
2020-11-19 03:32:16 +01:00
|
|
|
class AstUser2InUse final : AstUserInUseBase {
|
2008-11-21 21:50:33 +01:00
|
|
|
protected:
|
|
|
|
|
friend class AstNode;
|
2019-05-19 22:13:13 +02:00
|
|
|
static uint32_t s_userCntGbl; // Count of which usage of userp() this is
|
|
|
|
|
static bool s_userBusy; // Count is in use
|
2008-11-21 21:50:33 +01:00
|
|
|
public:
|
2019-05-19 22:13:13 +02:00
|
|
|
AstUser2InUse() { allocate(2, s_userCntGbl/*ref*/, s_userBusy/*ref*/); }
|
|
|
|
|
~AstUser2InUse() { free (2, s_userCntGbl/*ref*/, s_userBusy/*ref*/); }
|
|
|
|
|
static void clear() { clearcnt(2, s_userCntGbl/*ref*/, s_userBusy/*ref*/); }
|
|
|
|
|
static void check() { checkcnt(2, s_userCntGbl/*ref*/, s_userBusy/*ref*/); }
|
2008-11-21 21:50:33 +01:00
|
|
|
};
|
2020-11-19 03:32:16 +01:00
|
|
|
class AstUser3InUse final : AstUserInUseBase {
|
2008-11-21 21:50:33 +01:00
|
|
|
protected:
|
|
|
|
|
friend class AstNode;
|
2019-05-19 22:13:13 +02:00
|
|
|
static uint32_t s_userCntGbl; // Count of which usage of userp() this is
|
|
|
|
|
static bool s_userBusy; // Count is in use
|
2008-11-21 21:50:33 +01:00
|
|
|
public:
|
2019-05-19 22:13:13 +02:00
|
|
|
AstUser3InUse() { allocate(3, s_userCntGbl/*ref*/, s_userBusy/*ref*/); }
|
|
|
|
|
~AstUser3InUse() { free (3, s_userCntGbl/*ref*/, s_userBusy/*ref*/); }
|
|
|
|
|
static void clear() { clearcnt(3, s_userCntGbl/*ref*/, s_userBusy/*ref*/); }
|
|
|
|
|
static void check() { checkcnt(3, s_userCntGbl/*ref*/, s_userBusy/*ref*/); }
|
2008-11-21 21:50:33 +01:00
|
|
|
};
|
2020-11-19 03:32:16 +01:00
|
|
|
class AstUser4InUse final : AstUserInUseBase {
|
2008-11-21 21:50:33 +01:00
|
|
|
protected:
|
|
|
|
|
friend class AstNode;
|
2019-05-19 22:13:13 +02:00
|
|
|
static uint32_t s_userCntGbl; // Count of which usage of userp() this is
|
|
|
|
|
static bool s_userBusy; // Count is in use
|
2008-11-21 21:50:33 +01:00
|
|
|
public:
|
2019-05-19 22:13:13 +02:00
|
|
|
AstUser4InUse() { allocate(4, s_userCntGbl/*ref*/, s_userBusy/*ref*/); }
|
|
|
|
|
~AstUser4InUse() { free (4, s_userCntGbl/*ref*/, s_userBusy/*ref*/); }
|
|
|
|
|
static void clear() { clearcnt(4, s_userCntGbl/*ref*/, s_userBusy/*ref*/); }
|
|
|
|
|
static void check() { checkcnt(4, s_userCntGbl/*ref*/, s_userBusy/*ref*/); }
|
2008-11-21 21:50:33 +01:00
|
|
|
};
|
2020-11-19 03:32:16 +01:00
|
|
|
class AstUser5InUse final : AstUserInUseBase {
|
2010-02-02 00:55:32 +01:00
|
|
|
protected:
|
|
|
|
|
friend class AstNode;
|
2019-05-19 22:13:13 +02:00
|
|
|
static uint32_t s_userCntGbl; // Count of which usage of userp() this is
|
|
|
|
|
static bool s_userBusy; // Count is in use
|
2010-02-02 00:55:32 +01:00
|
|
|
public:
|
2019-05-19 22:13:13 +02:00
|
|
|
AstUser5InUse() { allocate(5, s_userCntGbl/*ref*/, s_userBusy/*ref*/); }
|
|
|
|
|
~AstUser5InUse() { free (5, s_userCntGbl/*ref*/, s_userBusy/*ref*/); }
|
|
|
|
|
static void clear() { clearcnt(5, s_userCntGbl/*ref*/, s_userBusy/*ref*/); }
|
|
|
|
|
static void check() { checkcnt(5, s_userCntGbl/*ref*/, s_userBusy/*ref*/); }
|
2010-02-02 00:55:32 +01:00
|
|
|
};
|
2020-04-15 13:58:34 +02:00
|
|
|
// clang-format on
|
2008-11-21 21:50:33 +01:00
|
|
|
|
2006-08-26 13:35:28 +02:00
|
|
|
//######################################################################
|
2021-10-17 12:40:44 +02:00
|
|
|
// Node deleter, deletes all enqueued AstNode* on destruction, or when
|
|
|
|
|
// explicitly told to do so. This is useful when the deletion of removed
|
|
|
|
|
// nodes needs to be deferred to a later time, because pointers to the
|
|
|
|
|
// removed nodes might still exist.
|
2006-08-26 13:35:28 +02:00
|
|
|
|
2021-10-17 12:40:44 +02:00
|
|
|
class AstNDeleter VL_NOT_FINAL {
|
2018-05-14 12:50:47 +02:00
|
|
|
// MEMBERS
|
2021-10-17 12:40:44 +02:00
|
|
|
std::vector<AstNode*> m_deleteps; // Nodes to delete
|
2020-04-15 13:58:34 +02:00
|
|
|
|
2006-08-26 13:35:28 +02:00
|
|
|
public:
|
2018-05-14 12:50:47 +02:00
|
|
|
// METHODS
|
2021-10-17 12:40:44 +02:00
|
|
|
|
|
|
|
|
// Enqueue node for deletion on next 'doDelete' (or destruction)
|
2020-10-18 19:23:02 +02:00
|
|
|
void pushDeletep(AstNode* nodep) {
|
|
|
|
|
UASSERT_STATIC(nodep, "Cannot delete nullptr node");
|
|
|
|
|
m_deleteps.push_back(nodep);
|
|
|
|
|
}
|
2021-10-17 12:40:44 +02:00
|
|
|
|
|
|
|
|
// Delete all previously pushed nodes (by callint deleteTree)
|
2006-08-26 13:35:28 +02:00
|
|
|
void doDeletes();
|
2020-04-15 13:58:34 +02:00
|
|
|
|
2021-10-17 12:40:44 +02:00
|
|
|
// Do the deletions on destruction
|
|
|
|
|
virtual ~AstNDeleter() { doDeletes(); }
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
//######################################################################
|
|
|
|
|
// AstNVisitor -- Allows new functions to be called on each node
|
|
|
|
|
// type without changing the base classes. See "Modern C++ Design".
|
|
|
|
|
|
|
|
|
|
class AstNVisitor VL_NOT_FINAL : public AstNDeleter {
|
|
|
|
|
friend class AstNode;
|
|
|
|
|
|
2006-08-26 13:35:28 +02:00
|
|
|
public:
|
2018-05-11 02:55:37 +02:00
|
|
|
/// Call visit()s on nodep
|
|
|
|
|
void iterate(AstNode* nodep);
|
2021-05-21 15:34:27 +02:00
|
|
|
/// Call visit()s on nodep
|
|
|
|
|
void iterateNull(AstNode* nodep);
|
2018-05-11 02:55:37 +02:00
|
|
|
/// Call visit()s on nodep's children
|
|
|
|
|
void iterateChildren(AstNode* nodep);
|
|
|
|
|
/// Call visit()s on nodep's children in backp() order
|
|
|
|
|
void iterateChildrenBackwards(AstNode* nodep);
|
|
|
|
|
/// Call visit()s on const nodep's children
|
|
|
|
|
void iterateChildrenConst(AstNode* nodep);
|
2020-08-15 16:12:55 +02:00
|
|
|
/// Call visit()s on nodep (maybe nullptr) and nodep's nextp() list
|
2018-05-11 02:55:37 +02:00
|
|
|
void iterateAndNextNull(AstNode* nodep);
|
2020-08-15 16:12:55 +02:00
|
|
|
/// Call visit()s on const nodep (maybe nullptr) and nodep's nextp() list
|
2018-05-11 02:55:37 +02:00
|
|
|
void iterateAndNextConstNull(AstNode* nodep);
|
|
|
|
|
/// Return edited nodep; see comments in V3Ast.cpp
|
|
|
|
|
AstNode* iterateSubtreeReturnEdits(AstNode* nodep);
|
|
|
|
|
|
2019-05-19 22:13:13 +02:00
|
|
|
#include "V3Ast__gen_visitor.h" // From ./astgen
|
2006-08-26 13:35:28 +02:00
|
|
|
// Things like:
|
2016-11-27 14:11:38 +01:00
|
|
|
// virtual void visit(AstBreak* nodep) { visit((AstNodeStmt*)(nodep)); }
|
|
|
|
|
// virtual void visit(AstNodeStmt* nodep) { visit((AstNode*)(nodep)); }
|
2006-08-26 13:35:28 +02:00
|
|
|
};
|
|
|
|
|
|
|
|
|
|
//######################################################################
|
|
|
|
|
// AstNRelinker -- Holds the state of a unlink so a new node can be
|
|
|
|
|
// added at the same point.
|
|
|
|
|
|
2020-11-19 03:32:16 +01:00
|
|
|
class AstNRelinker final {
|
2006-08-26 13:35:28 +02:00
|
|
|
protected:
|
|
|
|
|
friend class AstNode;
|
2020-08-16 18:05:35 +02:00
|
|
|
enum RelinkWhatEn : uint8_t {
|
|
|
|
|
RELINK_BAD,
|
|
|
|
|
RELINK_NEXT,
|
|
|
|
|
RELINK_OP1,
|
|
|
|
|
RELINK_OP2,
|
|
|
|
|
RELINK_OP3,
|
|
|
|
|
RELINK_OP4
|
|
|
|
|
};
|
2020-08-15 19:11:27 +02:00
|
|
|
AstNode* m_oldp = nullptr; // The old node that was linked to this point in the tree
|
|
|
|
|
AstNode* m_backp = nullptr;
|
|
|
|
|
RelinkWhatEn m_chg = RELINK_BAD;
|
|
|
|
|
AstNode** m_iterpp = nullptr;
|
2020-04-15 13:58:34 +02:00
|
|
|
|
2006-08-26 13:35:28 +02:00
|
|
|
public:
|
2020-11-17 01:56:16 +01:00
|
|
|
AstNRelinker() = default;
|
2006-08-26 13:35:28 +02:00
|
|
|
void relink(AstNode* newp);
|
|
|
|
|
AstNode* oldp() const { return m_oldp; }
|
2020-04-15 13:58:34 +02:00
|
|
|
void dump(std::ostream& str = std::cout) const;
|
2006-08-26 13:35:28 +02:00
|
|
|
};
|
2019-05-19 22:13:13 +02:00
|
|
|
inline std::ostream& operator<<(std::ostream& os, const AstNRelinker& rhs) {
|
2020-04-15 13:58:34 +02:00
|
|
|
rhs.dump(os);
|
|
|
|
|
return os;
|
|
|
|
|
}
|
2006-08-26 13:35:28 +02:00
|
|
|
|
2019-07-14 02:30:32 +02:00
|
|
|
//######################################################################
|
|
|
|
|
// Callback base class to determine if node matches some formula
|
|
|
|
|
|
2020-11-19 03:32:16 +01:00
|
|
|
class VNodeMatcher VL_NOT_FINAL {
|
2019-07-14 02:30:32 +02:00
|
|
|
public:
|
|
|
|
|
virtual bool nodeMatch(const AstNode* nodep) const { return true; }
|
|
|
|
|
};
|
|
|
|
|
|
2006-08-26 13:35:28 +02:00
|
|
|
//######################################################################
|
|
|
|
|
// AstNode -- Base type of all Ast types
|
|
|
|
|
|
2008-11-22 20:59:22 +01:00
|
|
|
// Prefetch a node.
|
|
|
|
|
// The if() makes it faster, even though prefetch won't fault on null pointers
|
|
|
|
|
#define ASTNODE_PREFETCH(nodep) \
|
2020-05-30 19:46:12 +02:00
|
|
|
do { \
|
2020-04-15 13:58:34 +02:00
|
|
|
if (nodep) { \
|
|
|
|
|
VL_PREFETCH_RD(&((nodep)->m_nextp)); \
|
2020-11-16 04:03:06 +01:00
|
|
|
VL_PREFETCH_RD(&((nodep)->m_type)); \
|
2020-04-15 13:58:34 +02:00
|
|
|
} \
|
2020-05-30 19:46:12 +02:00
|
|
|
} while (false)
|
2008-11-22 20:59:22 +01:00
|
|
|
|
2020-11-19 03:32:16 +01:00
|
|
|
class AstNode VL_NOT_FINAL {
|
2008-11-22 20:59:22 +01:00
|
|
|
// v ASTNODE_PREFETCH depends on below ordering of members
|
2022-01-01 17:46:49 +01:00
|
|
|
AstNode* m_nextp = nullptr; // Next peer in the parent's list
|
|
|
|
|
AstNode* m_backp = nullptr; // Node that points to this one (via next/op1/op2/...)
|
|
|
|
|
AstNode* m_op1p = nullptr; // Generic pointer 1
|
|
|
|
|
AstNode* m_op2p = nullptr; // Generic pointer 2
|
|
|
|
|
AstNode* m_op3p = nullptr; // Generic pointer 3
|
|
|
|
|
AstNode* m_op4p = nullptr; // Generic pointer 4
|
|
|
|
|
AstNode** m_iterpp
|
|
|
|
|
= nullptr; // Pointer to node iterating on, change it if we replace this node.
|
2020-11-16 04:03:06 +01:00
|
|
|
const AstType m_type; // Node sub-type identifier
|
2008-11-22 20:59:22 +01:00
|
|
|
// ^ ASTNODE_PREFETCH depends on above ordering of members
|
|
|
|
|
|
2021-07-10 09:01:58 +02:00
|
|
|
// AstType is 2 bytes, so we can stick another 6 bytes after it to utilize what would
|
2021-07-10 17:13:05 +02:00
|
|
|
// otherwise be padding (on a 64-bit system). We stick the attribute flags, broken state,
|
|
|
|
|
// and the clone count here.
|
2021-07-10 09:01:58 +02:00
|
|
|
|
|
|
|
|
struct {
|
|
|
|
|
bool didWidth : 1; // Did V3Width computation
|
|
|
|
|
bool doingWidth : 1; // Inside V3Width
|
|
|
|
|
bool protect : 1; // Protect name if protection is on
|
2021-07-10 17:13:05 +02:00
|
|
|
// Space for more flags here (there must be 8 bits in total)
|
|
|
|
|
uint8_t unused : 5;
|
2021-07-10 09:01:58 +02:00
|
|
|
} m_flags; // Attribute flags
|
|
|
|
|
|
2021-07-10 17:13:05 +02:00
|
|
|
// State variable used by V3Broken for consistency checking. The top bit of this is byte is a
|
|
|
|
|
// flag, representing V3Broken is currently proceeding under this node. The bottom 7 bits are
|
|
|
|
|
// a generation number. This is hot when --debug-checks so we access as a whole to avoid bit
|
|
|
|
|
// field masking resulting in unnecessary read-modify-write ops.
|
|
|
|
|
uint8_t m_brokenState = 0;
|
|
|
|
|
|
2022-01-01 17:46:49 +01:00
|
|
|
int m_cloneCnt = 0; // Sequence number for when last clone was made
|
2021-07-10 09:01:58 +02:00
|
|
|
|
|
|
|
|
#if defined(__x86_64__) && defined(__gnu_linux__)
|
|
|
|
|
// Only assert this on known platforms, as it only affects performance, not correctness
|
2021-07-10 17:13:05 +02:00
|
|
|
static_assert(sizeof(m_type) + sizeof(m_flags) + sizeof(m_brokenState) + sizeof(m_cloneCnt)
|
|
|
|
|
<= sizeof(void*),
|
2021-07-10 09:01:58 +02:00
|
|
|
"packing requires padding");
|
|
|
|
|
#endif
|
2020-01-25 21:29:44 +01:00
|
|
|
|
2022-01-01 17:46:49 +01:00
|
|
|
AstNodeDType* m_dtypep = nullptr; // Data type of output or assignment (etc)
|
2020-11-16 04:03:06 +01:00
|
|
|
AstNode* m_headtailp; // When at begin/end of list, the opposite end of the list
|
2020-04-15 13:58:34 +02:00
|
|
|
FileLine* m_fileline; // Where it was declared
|
|
|
|
|
vluint64_t m_editCount; // When it was last edited
|
2019-05-19 22:13:13 +02:00
|
|
|
static vluint64_t s_editCntGbl; // Global edit counter
|
2020-04-15 13:58:34 +02:00
|
|
|
// Global edit counter, last value for printing * near node #s
|
|
|
|
|
static vluint64_t s_editCntLast;
|
2006-08-26 13:35:28 +02:00
|
|
|
|
2022-01-01 17:46:49 +01:00
|
|
|
AstNode* m_clonep
|
|
|
|
|
= nullptr; // Pointer to clone of/ source of this module (for *LAST* cloneTree() ONLY)
|
2020-04-15 13:58:34 +02:00
|
|
|
static int s_cloneCntGbl; // Count of which userp is set
|
2008-11-25 14:10:41 +01:00
|
|
|
|
|
|
|
|
// This member ordering both allows 64 bit alignment and puts associated data together
|
2022-01-01 17:46:49 +01:00
|
|
|
VNUser m_user1u = VNUser{0}; // Contains any information the user iteration routine wants
|
|
|
|
|
uint32_t m_user1Cnt = 0; // Mark of when userp was set
|
|
|
|
|
uint32_t m_user2Cnt = 0; // Mark of when userp was set
|
|
|
|
|
VNUser m_user2u = VNUser{0}; // Contains any information the user iteration routine wants
|
|
|
|
|
VNUser m_user3u = VNUser{0}; // Contains any information the user iteration routine wants
|
|
|
|
|
uint32_t m_user3Cnt = 0; // Mark of when userp was set
|
|
|
|
|
uint32_t m_user4Cnt = 0; // Mark of when userp was set
|
|
|
|
|
VNUser m_user4u = VNUser{0}; // Contains any information the user iteration routine wants
|
|
|
|
|
VNUser m_user5u = VNUser{0}; // Contains any information the user iteration routine wants
|
|
|
|
|
uint32_t m_user5Cnt = 0; // Mark of when userp was set
|
2006-08-26 13:35:28 +02:00
|
|
|
|
|
|
|
|
// METHODS
|
2020-04-15 13:58:34 +02:00
|
|
|
void op1p(AstNode* nodep) {
|
|
|
|
|
m_op1p = nodep;
|
|
|
|
|
if (nodep) nodep->m_backp = this;
|
|
|
|
|
}
|
|
|
|
|
void op2p(AstNode* nodep) {
|
|
|
|
|
m_op2p = nodep;
|
|
|
|
|
if (nodep) nodep->m_backp = this;
|
|
|
|
|
}
|
|
|
|
|
void op3p(AstNode* nodep) {
|
|
|
|
|
m_op3p = nodep;
|
|
|
|
|
if (nodep) nodep->m_backp = this;
|
|
|
|
|
}
|
|
|
|
|
void op4p(AstNode* nodep) {
|
|
|
|
|
m_op4p = nodep;
|
|
|
|
|
if (nodep) nodep->m_backp = this;
|
|
|
|
|
}
|
2006-08-26 13:35:28 +02:00
|
|
|
|
2015-09-19 01:06:15 +02:00
|
|
|
private:
|
2020-04-15 13:58:34 +02:00
|
|
|
AstNode* cloneTreeIter();
|
|
|
|
|
AstNode* cloneTreeIterList();
|
|
|
|
|
void checkTreeIter(AstNode* backp);
|
|
|
|
|
void checkTreeIterList(AstNode* backp);
|
|
|
|
|
bool gateTreeIter() const;
|
|
|
|
|
static bool sameTreeIter(const AstNode* node1p, const AstNode* node2p, bool ignNext,
|
|
|
|
|
bool gateOnly);
|
|
|
|
|
void deleteTreeIter();
|
|
|
|
|
void deleteNode();
|
|
|
|
|
string locationStr() const;
|
|
|
|
|
|
2016-02-04 02:44:31 +01:00
|
|
|
public:
|
2019-05-19 22:13:13 +02:00
|
|
|
static void relinkOneLink(AstNode*& pointpr, AstNode* newp);
|
2011-08-05 03:58:45 +02:00
|
|
|
// cppcheck-suppress functionConst
|
2021-09-25 23:10:57 +02:00
|
|
|
static void debugTreeChange(const AstNode* nodep, const char* prefix, int lineno, bool next);
|
2006-08-26 13:35:28 +02:00
|
|
|
|
|
|
|
|
protected:
|
2019-09-12 13:22:22 +02:00
|
|
|
// CONSTRUCTORS
|
2020-09-15 13:35:53 +02:00
|
|
|
AstNode(AstType t, FileLine* fl);
|
2019-05-19 22:13:13 +02:00
|
|
|
virtual AstNode* clone() = 0; // Generally, cloneTree is what you want instead
|
2006-08-26 13:35:28 +02:00
|
|
|
virtual void cloneRelink() {}
|
2019-11-09 19:33:54 +01:00
|
|
|
void cloneRelinkTree();
|
2006-08-26 13:35:28 +02:00
|
|
|
|
|
|
|
|
// METHODS
|
2019-05-19 22:13:13 +02:00
|
|
|
void setOp1p(AstNode* newp); // Set non-list-type op1 to non-list element
|
|
|
|
|
void setOp2p(AstNode* newp); // Set non-list-type op2 to non-list element
|
|
|
|
|
void setOp3p(AstNode* newp); // Set non-list-type op3 to non-list element
|
|
|
|
|
void setOp4p(AstNode* newp); // Set non-list-type op4 to non-list element
|
2006-08-26 13:35:28 +02:00
|
|
|
|
2019-05-19 22:13:13 +02:00
|
|
|
void addOp1p(AstNode* newp); // Append newp to end of op1
|
|
|
|
|
void addOp2p(AstNode* newp); // Append newp to end of op2
|
|
|
|
|
void addOp3p(AstNode* newp); // Append newp to end of op3
|
|
|
|
|
void addOp4p(AstNode* newp); // Append newp to end of op4
|
2006-08-26 13:35:28 +02:00
|
|
|
|
2020-04-15 13:58:34 +02:00
|
|
|
// clang-format off
|
|
|
|
|
void setNOp1p(AstNode* newp) { if (newp) setOp1p(newp); }
|
|
|
|
|
void setNOp2p(AstNode* newp) { if (newp) setOp2p(newp); }
|
|
|
|
|
void setNOp3p(AstNode* newp) { if (newp) setOp3p(newp); }
|
|
|
|
|
void setNOp4p(AstNode* newp) { if (newp) setOp4p(newp); }
|
|
|
|
|
|
2019-05-19 22:13:13 +02:00
|
|
|
void addNOp1p(AstNode* newp) { if (newp) addOp1p(newp); }
|
|
|
|
|
void addNOp2p(AstNode* newp) { if (newp) addOp2p(newp); }
|
|
|
|
|
void addNOp3p(AstNode* newp) { if (newp) addOp3p(newp); }
|
|
|
|
|
void addNOp4p(AstNode* newp) { if (newp) addOp4p(newp); }
|
2020-04-15 13:58:34 +02:00
|
|
|
// clang-format on
|
2006-08-26 13:35:28 +02:00
|
|
|
|
2020-04-15 13:58:34 +02:00
|
|
|
void clonep(AstNode* nodep) {
|
|
|
|
|
m_clonep = nodep;
|
|
|
|
|
m_cloneCnt = s_cloneCntGbl;
|
|
|
|
|
}
|
|
|
|
|
static void cloneClearTree() {
|
|
|
|
|
s_cloneCntGbl++;
|
|
|
|
|
UASSERT_STATIC(s_cloneCntGbl, "Rollover");
|
|
|
|
|
}
|
2006-08-26 13:35:28 +02:00
|
|
|
|
|
|
|
|
public:
|
|
|
|
|
// ACCESSORS
|
2020-01-25 21:29:44 +01:00
|
|
|
inline AstType type() const { return m_type; }
|
2019-05-19 22:13:13 +02:00
|
|
|
const char* typeName() const { return type().ascii(); } // See also prettyTypeName
|
|
|
|
|
AstNode* nextp() const { return m_nextp; }
|
|
|
|
|
AstNode* backp() const { return m_backp; }
|
2019-12-01 23:19:18 +01:00
|
|
|
AstNode* abovep() const; // Parent node above, only when no nextp() as otherwise slow
|
2019-05-19 22:13:13 +02:00
|
|
|
AstNode* op1p() const { return m_op1p; }
|
|
|
|
|
AstNode* op2p() const { return m_op2p; }
|
|
|
|
|
AstNode* op3p() const { return m_op3p; }
|
|
|
|
|
AstNode* op4p() const { return m_op4p; }
|
2012-04-29 16:14:13 +02:00
|
|
|
AstNodeDType* dtypep() const { return m_dtypep; }
|
2020-08-15 16:12:55 +02:00
|
|
|
AstNode* clonep() const { return ((m_cloneCnt == s_cloneCntGbl) ? m_clonep : nullptr); }
|
|
|
|
|
AstNode* firstAbovep() const { // Returns nullptr when second or later in list
|
|
|
|
|
return ((backp() && backp()->nextp() != this) ? backp() : nullptr);
|
2020-04-15 13:58:34 +02:00
|
|
|
}
|
2021-07-10 17:13:05 +02:00
|
|
|
uint8_t brokenState() const { return m_brokenState; }
|
|
|
|
|
void brokenState(uint8_t value) { m_brokenState = value; }
|
|
|
|
|
|
2022-01-01 18:24:19 +01:00
|
|
|
void prefetch() const {
|
|
|
|
|
ASTNODE_PREFETCH(m_op1p);
|
|
|
|
|
ASTNODE_PREFETCH(m_op2p);
|
|
|
|
|
ASTNODE_PREFETCH(m_op3p);
|
|
|
|
|
ASTNODE_PREFETCH(m_op4p);
|
|
|
|
|
ASTNODE_PREFETCH(m_nextp);
|
|
|
|
|
}
|
|
|
|
|
|
2021-07-10 17:13:05 +02:00
|
|
|
// Used by AstNode::broken()
|
|
|
|
|
bool brokeExists() const { return V3Broken::isLinkable(this); }
|
|
|
|
|
bool brokeExistsAbove() const { return brokeExists() && (m_brokenState >> 7); }
|
|
|
|
|
bool brokeExistsBelow() const { return brokeExists() && !(m_brokenState >> 7); }
|
|
|
|
|
// Note: brokeExistsBelow is not quite precise, as it is true for sibling nodes as well
|
2006-08-26 13:35:28 +02:00
|
|
|
|
|
|
|
|
// CONSTRUCTORS
|
2020-11-17 01:56:16 +01:00
|
|
|
virtual ~AstNode() = default;
|
2007-11-02 12:23:03 +01:00
|
|
|
#ifdef VL_LEAK_CHECKS
|
|
|
|
|
static void* operator new(size_t size);
|
|
|
|
|
static void operator delete(void* obj, size_t size);
|
|
|
|
|
#endif
|
2006-08-26 13:35:28 +02:00
|
|
|
|
2021-07-25 14:32:36 +02:00
|
|
|
// CONSTANTS
|
|
|
|
|
// The following are relative dynamic costs (~ execution cycle count) of various operations.
|
|
|
|
|
// They are used by V3InstCount to estimate the relative execution time of code fragments.
|
|
|
|
|
static constexpr int INSTR_COUNT_BRANCH = 4; // Branch
|
|
|
|
|
static constexpr int INSTR_COUNT_CALL = INSTR_COUNT_BRANCH + 10; // Subroutine call
|
|
|
|
|
static constexpr int INSTR_COUNT_LD = 2; // Load memory
|
|
|
|
|
static constexpr int INSTR_COUNT_INT_MUL = 3; // Integer multiply
|
|
|
|
|
static constexpr int INSTR_COUNT_INT_DIV = 10; // Integer divide
|
|
|
|
|
static constexpr int INSTR_COUNT_DBL = 8; // Convert or do float ops
|
|
|
|
|
static constexpr int INSTR_COUNT_DBL_DIV = 40; // Double divide
|
|
|
|
|
static constexpr int INSTR_COUNT_DBL_TRIG = 200; // Double trigonometric ops
|
|
|
|
|
static constexpr int INSTR_COUNT_STR = 100; // String ops
|
|
|
|
|
static constexpr int INSTR_COUNT_TIME = INSTR_COUNT_CALL + 5; // Determine simulation time
|
|
|
|
|
static constexpr int INSTR_COUNT_PLI = 20; // PLI routines
|
2006-08-26 13:35:28 +02:00
|
|
|
|
|
|
|
|
// ACCESSORS
|
|
|
|
|
virtual string name() const { return ""; }
|
2019-12-24 14:47:30 +01:00
|
|
|
virtual string origName() const { return ""; }
|
2020-04-15 13:58:34 +02:00
|
|
|
virtual void name(const string& name) {
|
|
|
|
|
this->v3fatalSrc("name() called on object without name() method");
|
|
|
|
|
}
|
2017-10-06 13:33:52 +02:00
|
|
|
virtual void tag(const string& text) {}
|
|
|
|
|
virtual string tag() const { return ""; }
|
2006-08-26 13:35:28 +02:00
|
|
|
virtual string verilogKwd() const { return ""; }
|
2019-10-06 19:24:21 +02:00
|
|
|
string nameProtect() const; // Name with --protect-id applied
|
2019-12-24 14:47:30 +01:00
|
|
|
string origNameProtect() const; // origName with --protect-id applied
|
2019-05-19 22:13:13 +02:00
|
|
|
string shortName() const; // Name with __PVT__ removed for concatenating scopes
|
|
|
|
|
static string dedotName(const string& namein); // Name with dots removed
|
|
|
|
|
static string prettyName(const string& namein); // Name for printing out to the user
|
2019-07-12 04:09:30 +02:00
|
|
|
static string prettyNameQ(const string& namein) { // Quoted pretty name (for errors)
|
2020-04-15 13:58:34 +02:00
|
|
|
return string("'") + prettyName(namein) + "'";
|
|
|
|
|
}
|
|
|
|
|
static string
|
|
|
|
|
encodeName(const string& namein); // Encode user name into internal C representation
|
2018-10-15 00:39:33 +02:00
|
|
|
static string encodeNumber(vlsint64_t num); // Encode number into internal C representation
|
|
|
|
|
static string vcdName(const string& namein); // Name for printing out to vcd files
|
2019-05-19 22:13:13 +02:00
|
|
|
string prettyName() const { return prettyName(name()); }
|
2019-07-12 04:09:30 +02:00
|
|
|
string prettyNameQ() const { return prettyNameQ(name()); }
|
2020-01-26 19:21:25 +01:00
|
|
|
string prettyTypeName() const; // "VARREF" for error messages (NOT dtype's pretty name)
|
2020-04-15 13:58:34 +02:00
|
|
|
virtual string prettyOperatorName() const { return "operator " + prettyTypeName(); }
|
2019-05-19 22:13:13 +02:00
|
|
|
FileLine* fileline() const { return m_fileline; }
|
|
|
|
|
void fileline(FileLine* fl) { m_fileline = fl; }
|
|
|
|
|
bool width1() const;
|
|
|
|
|
int widthInstrs() const;
|
2021-07-10 09:01:58 +02:00
|
|
|
void didWidth(bool flag) { m_flags.didWidth = flag; }
|
|
|
|
|
bool didWidth() const { return m_flags.didWidth; }
|
2020-04-15 13:58:34 +02:00
|
|
|
bool didWidthAndSet() {
|
|
|
|
|
if (didWidth()) return true;
|
|
|
|
|
didWidth(true);
|
|
|
|
|
return false;
|
|
|
|
|
}
|
2021-07-10 09:01:58 +02:00
|
|
|
bool doingWidth() const { return m_flags.doingWidth; }
|
|
|
|
|
void doingWidth(bool flag) { m_flags.doingWidth = flag; }
|
|
|
|
|
bool protect() const { return m_flags.protect; }
|
|
|
|
|
void protect(bool flag) { m_flags.protect = flag; }
|
2012-04-29 16:14:13 +02:00
|
|
|
|
2020-04-15 13:58:34 +02:00
|
|
|
// TODO stomp these width functions out, and call via dtypep() instead
|
2019-05-19 22:13:13 +02:00
|
|
|
int width() const;
|
|
|
|
|
int widthMin() const;
|
2020-04-15 13:58:34 +02:00
|
|
|
int widthMinV() const {
|
|
|
|
|
return v3Global.widthMinUsage() == VWidthMinUsage::VERILOG_WIDTH ? widthMin() : width();
|
|
|
|
|
}
|
2019-05-19 22:13:13 +02:00
|
|
|
int widthWords() const { return VL_WORDS_I(width()); }
|
2019-12-09 03:36:38 +01:00
|
|
|
bool isQuad() const { return (width() > VL_IDATASIZE && width() <= VL_QUADSIZE); }
|
|
|
|
|
bool isWide() const { return (width() > VL_QUADSIZE); }
|
2019-05-19 22:13:13 +02:00
|
|
|
bool isDouble() const;
|
|
|
|
|
bool isSigned() const;
|
|
|
|
|
bool isString() const;
|
|
|
|
|
|
2020-04-15 13:58:34 +02:00
|
|
|
// clang-format off
|
2019-05-19 22:13:13 +02:00
|
|
|
VNUser user1u() const {
|
|
|
|
|
// Slows things down measurably, so disabled by default
|
|
|
|
|
//UASSERT_STATIC(AstUser1InUse::s_userBusy, "userp set w/o busy");
|
|
|
|
|
return ((m_user1Cnt==AstUser1InUse::s_userCntGbl) ? m_user1u : VNUser(0));
|
2008-11-21 21:50:33 +01:00
|
|
|
}
|
2019-05-19 22:13:13 +02:00
|
|
|
AstNode* user1p() const { return user1u().toNodep(); }
|
|
|
|
|
void user1u(const VNUser& user) { m_user1u=user; m_user1Cnt=AstUser1InUse::s_userCntGbl; }
|
|
|
|
|
void user1p(void* userp) { user1u(VNUser(userp)); }
|
|
|
|
|
int user1() const { return user1u().toInt(); }
|
|
|
|
|
void user1(int val) { user1u(VNUser(val)); }
|
|
|
|
|
int user1Inc(int val=1) { int v=user1(); user1(v+val); return v; }
|
|
|
|
|
int user1SetOnce() { int v=user1(); if (!v) user1(1); return v; } // Better for cache than user1Inc()
|
|
|
|
|
static void user1ClearTree() { AstUser1InUse::clear(); } // Clear userp()'s across the entire tree
|
|
|
|
|
|
|
|
|
|
VNUser user2u() const {
|
|
|
|
|
// Slows things down measurably, so disabled by default
|
|
|
|
|
//UASSERT_STATIC(AstUser2InUse::s_userBusy, "userp set w/o busy");
|
|
|
|
|
return ((m_user2Cnt==AstUser2InUse::s_userCntGbl) ? m_user2u : VNUser(0));
|
2016-11-27 15:40:12 +01:00
|
|
|
}
|
2019-05-19 22:13:13 +02:00
|
|
|
AstNode* user2p() const { return user2u().toNodep(); }
|
|
|
|
|
void user2u(const VNUser& user) { m_user2u=user; m_user2Cnt=AstUser2InUse::s_userCntGbl; }
|
|
|
|
|
void user2p(void* userp) { user2u(VNUser(userp)); }
|
|
|
|
|
int user2() const { return user2u().toInt(); }
|
|
|
|
|
void user2(int val) { user2u(VNUser(val)); }
|
|
|
|
|
int user2Inc(int val=1) { int v=user2(); user2(v+val); return v; }
|
|
|
|
|
int user2SetOnce() { int v=user2(); if (!v) user2(1); return v; } // Better for cache than user2Inc()
|
|
|
|
|
static void user2ClearTree() { AstUser2InUse::clear(); } // Clear userp()'s across the entire tree
|
|
|
|
|
|
|
|
|
|
VNUser user3u() const {
|
|
|
|
|
// Slows things down measurably, so disabled by default
|
|
|
|
|
//UASSERT_STATIC(AstUser3InUse::s_userBusy, "userp set w/o busy");
|
|
|
|
|
return ((m_user3Cnt==AstUser3InUse::s_userCntGbl) ? m_user3u : VNUser(0));
|
2016-11-27 15:40:12 +01:00
|
|
|
}
|
2019-05-19 22:13:13 +02:00
|
|
|
AstNode* user3p() const { return user3u().toNodep(); }
|
|
|
|
|
void user3u(const VNUser& user) { m_user3u=user; m_user3Cnt=AstUser3InUse::s_userCntGbl; }
|
|
|
|
|
void user3p(void* userp) { user3u(VNUser(userp)); }
|
|
|
|
|
int user3() const { return user3u().toInt(); }
|
|
|
|
|
void user3(int val) { user3u(VNUser(val)); }
|
|
|
|
|
int user3Inc(int val=1) { int v=user3(); user3(v+val); return v; }
|
|
|
|
|
int user3SetOnce() { int v=user3(); if (!v) user3(1); return v; } // Better for cache than user3Inc()
|
|
|
|
|
static void user3ClearTree() { AstUser3InUse::clear(); } // Clear userp()'s across the entire tree
|
|
|
|
|
|
|
|
|
|
VNUser user4u() const {
|
|
|
|
|
// Slows things down measurably, so disabled by default
|
|
|
|
|
//UASSERT_STATIC(AstUser4InUse::s_userBusy, "userp set w/o busy");
|
|
|
|
|
return ((m_user4Cnt==AstUser4InUse::s_userCntGbl) ? m_user4u : VNUser(0));
|
2016-11-27 15:40:12 +01:00
|
|
|
}
|
2019-05-19 22:13:13 +02:00
|
|
|
AstNode* user4p() const { return user4u().toNodep(); }
|
|
|
|
|
void user4u(const VNUser& user) { m_user4u=user; m_user4Cnt=AstUser4InUse::s_userCntGbl; }
|
|
|
|
|
void user4p(void* userp) { user4u(VNUser(userp)); }
|
|
|
|
|
int user4() const { return user4u().toInt(); }
|
|
|
|
|
void user4(int val) { user4u(VNUser(val)); }
|
|
|
|
|
int user4Inc(int val=1) { int v=user4(); user4(v+val); return v; }
|
|
|
|
|
int user4SetOnce() { int v=user4(); if (!v) user4(1); return v; } // Better for cache than user4Inc()
|
|
|
|
|
static void user4ClearTree() { AstUser4InUse::clear(); } // Clear userp()'s across the entire tree
|
|
|
|
|
|
|
|
|
|
VNUser user5u() const {
|
|
|
|
|
// Slows things down measurably, so disabled by default
|
|
|
|
|
//UASSERT_STATIC(AstUser5InUse::s_userBusy, "userp set w/o busy");
|
|
|
|
|
return ((m_user5Cnt==AstUser5InUse::s_userCntGbl) ? m_user5u : VNUser(0));
|
2016-11-27 15:40:12 +01:00
|
|
|
}
|
2019-05-19 22:13:13 +02:00
|
|
|
AstNode* user5p() const { return user5u().toNodep(); }
|
|
|
|
|
void user5u(const VNUser& user) { m_user5u=user; m_user5Cnt=AstUser5InUse::s_userCntGbl; }
|
|
|
|
|
void user5p(void* userp) { user5u(VNUser(userp)); }
|
|
|
|
|
int user5() const { return user5u().toInt(); }
|
|
|
|
|
void user5(int val) { user5u(VNUser(val)); }
|
|
|
|
|
int user5Inc(int val=1) { int v=user5(); user5(v+val); return v; }
|
|
|
|
|
int user5SetOnce() { int v=user5(); if (!v) user5(1); return v; } // Better for cache than user5Inc()
|
|
|
|
|
static void user5ClearTree() { AstUser5InUse::clear(); } // Clear userp()'s across the entire tree
|
2020-04-15 13:58:34 +02:00
|
|
|
// clang-format on
|
2019-05-19 22:13:13 +02:00
|
|
|
|
2022-01-01 18:24:19 +01:00
|
|
|
AstNode* usernp(int n) const; // Return user1..userN based on provided n
|
|
|
|
|
void usernp(int n, void* userp); // Set user1..userN based on provided n
|
|
|
|
|
|
2019-05-19 22:13:13 +02:00
|
|
|
vluint64_t editCount() const { return m_editCount; }
|
2020-04-15 13:58:34 +02:00
|
|
|
void editCountInc() {
|
|
|
|
|
m_editCount = ++s_editCntGbl; // Preincrement, so can "watch AstNode::s_editCntGbl=##"
|
|
|
|
|
}
|
2019-05-19 22:13:13 +02:00
|
|
|
static vluint64_t editCountLast() { return s_editCntLast; }
|
|
|
|
|
static vluint64_t editCountGbl() { return s_editCntGbl; }
|
|
|
|
|
static void editCountSetLast() { s_editCntLast = editCountGbl(); }
|
2006-08-26 13:35:28 +02:00
|
|
|
|
|
|
|
|
// ACCESSORS for specific types
|
2020-08-15 16:12:55 +02:00
|
|
|
// Alas these can't be virtual or they break when passed a nullptr
|
2018-02-02 03:32:58 +01:00
|
|
|
bool isZero() const;
|
|
|
|
|
bool isOne() const;
|
|
|
|
|
bool isNeqZero() const;
|
|
|
|
|
bool isAllOnes() const;
|
|
|
|
|
bool isAllOnesV() const; // Verilog width rules apply
|
2006-08-26 13:35:28 +02:00
|
|
|
|
2011-12-01 01:32:33 +01:00
|
|
|
// METHODS - data type changes especially for initial creation
|
2020-04-15 13:58:34 +02:00
|
|
|
void dtypep(AstNodeDType* nodep) {
|
|
|
|
|
if (m_dtypep != nodep) {
|
|
|
|
|
m_dtypep = nodep;
|
|
|
|
|
editCountInc();
|
|
|
|
|
}
|
|
|
|
|
}
|
2022-01-02 04:14:46 +01:00
|
|
|
void dtypeFrom(const AstNode* fromp) {
|
2021-02-22 03:25:21 +01:00
|
|
|
if (fromp) dtypep(fromp->dtypep());
|
2020-04-15 13:58:34 +02:00
|
|
|
}
|
|
|
|
|
void dtypeChgSigned(bool flag = true);
|
2019-05-19 22:13:13 +02:00
|
|
|
void dtypeChgWidth(int width, int widthMin);
|
2020-04-20 03:19:09 +02:00
|
|
|
void dtypeChgWidthSigned(int width, int widthMin, VSigning numeric);
|
|
|
|
|
void dtypeSetBitUnsized(int width, int widthMin, VSigning numeric) {
|
2020-04-15 13:58:34 +02:00
|
|
|
dtypep(findBitDType(width, widthMin, numeric));
|
|
|
|
|
}
|
2020-04-20 03:19:09 +02:00
|
|
|
void dtypeSetBitSized(int width, VSigning numeric) {
|
2020-04-15 13:58:34 +02:00
|
|
|
dtypep(findBitDType(width, width, numeric)); // Since sized, widthMin is width
|
|
|
|
|
}
|
2020-04-20 03:19:09 +02:00
|
|
|
void dtypeSetLogicUnsized(int width, int widthMin, VSigning numeric) {
|
2020-04-15 13:58:34 +02:00
|
|
|
dtypep(findLogicDType(width, widthMin, numeric));
|
|
|
|
|
}
|
2020-04-20 03:19:09 +02:00
|
|
|
void dtypeSetLogicSized(int width, VSigning numeric) {
|
2020-04-15 13:58:34 +02:00
|
|
|
dtypep(findLogicDType(width, width, numeric)); // Since sized, widthMin is width
|
|
|
|
|
}
|
2020-11-29 14:23:36 +01:00
|
|
|
void dtypeSetBit() { dtypep(findBitDType()); }
|
2020-04-15 13:58:34 +02:00
|
|
|
void dtypeSetDouble() { dtypep(findDoubleDType()); }
|
|
|
|
|
void dtypeSetString() { dtypep(findStringDType()); }
|
|
|
|
|
void dtypeSetSigned32() { dtypep(findSigned32DType()); }
|
|
|
|
|
void dtypeSetUInt32() { dtypep(findUInt32DType()); } // Twostate
|
|
|
|
|
void dtypeSetUInt64() { dtypep(findUInt64DType()); } // Twostate
|
2021-08-28 23:23:35 +02:00
|
|
|
void dtypeSetEmptyQueue() { dtypep(findEmptyQueueDType()); }
|
2019-12-01 17:52:48 +01:00
|
|
|
void dtypeSetVoid() { dtypep(findVoidDType()); }
|
2012-05-10 04:12:57 +02:00
|
|
|
|
|
|
|
|
// Data type locators
|
2020-11-29 14:23:36 +01:00
|
|
|
AstNodeDType* findBitDType() { return findBasicDType(AstBasicDTypeKwd::LOGIC); }
|
2020-04-15 13:58:34 +02:00
|
|
|
AstNodeDType* findDoubleDType() { return findBasicDType(AstBasicDTypeKwd::DOUBLE); }
|
|
|
|
|
AstNodeDType* findStringDType() { return findBasicDType(AstBasicDTypeKwd::STRING); }
|
|
|
|
|
AstNodeDType* findSigned32DType() { return findBasicDType(AstBasicDTypeKwd::INTEGER); }
|
|
|
|
|
AstNodeDType* findUInt32DType() { return findBasicDType(AstBasicDTypeKwd::UINT32); }
|
|
|
|
|
AstNodeDType* findUInt64DType() { return findBasicDType(AstBasicDTypeKwd::UINT64); }
|
2021-06-13 15:33:11 +02:00
|
|
|
AstNodeDType* findCHandleDType() { return findBasicDType(AstBasicDTypeKwd::CHANDLE); }
|
2021-08-28 23:23:35 +02:00
|
|
|
AstNodeDType* findEmptyQueueDType() const;
|
2019-12-01 17:52:48 +01:00
|
|
|
AstNodeDType* findVoidDType() const;
|
2020-11-01 16:56:07 +01:00
|
|
|
AstNodeDType* findQueueIndexDType() const;
|
2020-04-20 03:19:09 +02:00
|
|
|
AstNodeDType* findBitDType(int width, int widthMin, VSigning numeric) const;
|
|
|
|
|
AstNodeDType* findLogicDType(int width, int widthMin, VSigning numeric) const;
|
2020-04-04 04:31:54 +02:00
|
|
|
AstNodeDType* findLogicRangeDType(const VNumRange& range, int widthMin,
|
2020-04-20 03:19:09 +02:00
|
|
|
VSigning numeric) const;
|
|
|
|
|
AstNodeDType* findBitRangeDType(const VNumRange& range, int widthMin, VSigning numeric) const;
|
2012-07-24 03:29:53 +02:00
|
|
|
AstNodeDType* findBasicDType(AstBasicDTypeKwd kwd) const;
|
2021-07-25 19:38:27 +02:00
|
|
|
static AstBasicDType* findInsertSameDType(AstBasicDType* nodep);
|
2011-12-01 01:32:33 +01:00
|
|
|
|
2011-12-01 00:50:21 +01:00
|
|
|
// METHODS - dump and error
|
2019-05-19 22:13:13 +02:00
|
|
|
void v3errorEnd(std::ostringstream& str) const;
|
|
|
|
|
void v3errorEndFatal(std::ostringstream& str) const VL_ATTR_NORETURN;
|
2019-06-22 23:01:39 +02:00
|
|
|
string warnContextPrimary() const { return fileline()->warnContextPrimary(); }
|
|
|
|
|
string warnContextSecondary() const { return fileline()->warnContextSecondary(); }
|
|
|
|
|
string warnMore() const { return fileline()->warnMore(); }
|
2019-07-12 01:15:40 +02:00
|
|
|
string warnOther() const { return fileline()->warnOther(); }
|
2019-06-22 23:01:39 +02:00
|
|
|
|
2020-04-15 13:58:34 +02:00
|
|
|
virtual void dump(std::ostream& str = std::cout) const;
|
2020-11-25 00:35:12 +01:00
|
|
|
static void dumpGdb(const AstNode* nodep); // For GDB only
|
2019-05-19 22:13:13 +02:00
|
|
|
void dumpGdbHeader() const;
|
2011-12-01 00:50:21 +01:00
|
|
|
|
|
|
|
|
// METHODS - Tree modifications
|
2020-04-15 13:58:34 +02:00
|
|
|
// Returns nodep, adds newp to end of nodep's list
|
|
|
|
|
static AstNode* addNext(AstNode* nodep, AstNode* newp);
|
2020-08-15 16:12:55 +02:00
|
|
|
// Returns nodep, adds newp (maybe nullptr) to end of nodep's list
|
2020-04-15 13:58:34 +02:00
|
|
|
static AstNode* addNextNull(AstNode* nodep, AstNode* newp);
|
2016-02-09 04:15:44 +01:00
|
|
|
inline AstNode* addNext(AstNode* newp) { return addNext(this, newp); }
|
|
|
|
|
inline AstNode* addNextNull(AstNode* newp) { return addNextNull(this, newp); }
|
2018-02-27 13:16:16 +01:00
|
|
|
void addNextHere(AstNode* newp); // Insert newp at this->nextp
|
2020-04-15 13:58:34 +02:00
|
|
|
void addPrev(AstNode* newp) {
|
|
|
|
|
replaceWith(newp);
|
|
|
|
|
newp->addNext(this);
|
|
|
|
|
}
|
2019-05-19 22:13:13 +02:00
|
|
|
void addHereThisAsNext(AstNode* newp); // Adds at old place of this, this becomes next
|
|
|
|
|
void replaceWith(AstNode* newp); // Replace current node in tree with new node
|
2020-08-15 16:12:55 +02:00
|
|
|
AstNode* unlinkFrBack(AstNRelinker* linkerp
|
|
|
|
|
= nullptr); // Unlink this from whoever points to it.
|
2018-03-10 22:32:04 +01:00
|
|
|
// Unlink this from whoever points to it, keep entire next list with unlinked node
|
2020-08-15 16:12:55 +02:00
|
|
|
AstNode* unlinkFrBackWithNext(AstNRelinker* linkerp = nullptr);
|
2019-05-19 22:13:13 +02:00
|
|
|
void swapWith(AstNode* bp);
|
|
|
|
|
void relink(AstNRelinker* linkerp); // Generally use linker->relink() instead
|
|
|
|
|
void cloneRelinkNode() { cloneRelink(); }
|
2009-10-09 02:42:45 +02:00
|
|
|
// Iterate and insert - assumes tree format
|
2020-04-15 13:58:34 +02:00
|
|
|
virtual void addNextStmt(AstNode* newp,
|
|
|
|
|
AstNode* belowp); // When calling, "this" is second argument
|
|
|
|
|
virtual void addBeforeStmt(AstNode* newp,
|
|
|
|
|
AstNode* belowp); // When calling, "this" is second argument
|
2006-08-26 13:35:28 +02:00
|
|
|
|
|
|
|
|
// METHODS - Iterate on a tree
|
2020-08-15 16:12:55 +02:00
|
|
|
// Clone or return nullptr if nullptr
|
2019-11-09 19:33:54 +01:00
|
|
|
static AstNode* cloneTreeNull(AstNode* nodep, bool cloneNextLink) {
|
2020-08-15 16:12:55 +02:00
|
|
|
return nodep ? nodep->cloneTree(cloneNextLink) : nullptr;
|
2020-04-15 13:58:34 +02:00
|
|
|
}
|
2019-11-09 19:33:54 +01:00
|
|
|
AstNode* cloneTree(bool cloneNextLink); // Not const, as sets clonep() on original nodep
|
2019-05-19 22:13:13 +02:00
|
|
|
bool gateTree() { return gateTreeIter(); } // Is tree isGateOptimizable?
|
|
|
|
|
bool sameTree(const AstNode* node2p) const; // Does tree of this == node2p?
|
2020-04-15 13:58:34 +02:00
|
|
|
// Does tree of this == node2p?, not allowing non-isGateOptimizable
|
|
|
|
|
bool sameGateTree(const AstNode* node2p) const;
|
2019-05-19 22:13:13 +02:00
|
|
|
void deleteTree(); // Always deletes the next link
|
|
|
|
|
void checkTree(); // User Interface version
|
|
|
|
|
void checkIter() const;
|
2020-08-15 16:12:55 +02:00
|
|
|
void clearIter() { m_iterpp = nullptr; }
|
2020-04-15 13:58:34 +02:00
|
|
|
void dumpPtrs(std::ostream& os = std::cout) const;
|
|
|
|
|
void dumpTree(std::ostream& os = std::cout, const string& indent = " ",
|
|
|
|
|
int maxDepth = 0) const;
|
|
|
|
|
void dumpTree(const string& indent, int maxDepth = 0) const {
|
|
|
|
|
dumpTree(cout, indent, maxDepth);
|
|
|
|
|
}
|
2020-11-25 00:35:12 +01:00
|
|
|
static void dumpTreeGdb(const AstNode* nodep); // For GDB only
|
2020-04-15 13:58:34 +02:00
|
|
|
void dumpTreeAndNext(std::ostream& os = std::cout, const string& indent = " ",
|
|
|
|
|
int maxDepth = 0) const;
|
2020-11-12 01:00:10 +01:00
|
|
|
void dumpTreeFile(const string& filename, bool append = false, bool doDump = true,
|
|
|
|
|
bool doCheck = true);
|
2020-11-25 00:35:12 +01:00
|
|
|
static void dumpTreeFileGdb(const AstNode* nodep, const char* filenamep = nullptr);
|
2006-08-26 13:35:28 +02:00
|
|
|
|
|
|
|
|
// METHODS - queries
|
2020-04-15 13:58:34 +02:00
|
|
|
// Changes control flow, disable some optimizations
|
|
|
|
|
virtual bool isBrancher() const { return false; }
|
|
|
|
|
// Else a AstTime etc that can't be pushed out
|
|
|
|
|
virtual bool isGateOptimizable() const { return true; }
|
2018-03-10 22:32:04 +01:00
|
|
|
// GateDedupable is a slightly larger superset of GateOptimzable (eg, AstNodeIf)
|
|
|
|
|
virtual bool isGateDedupable() const { return isGateOptimizable(); }
|
2020-04-15 13:58:34 +02:00
|
|
|
// Else creates output or exits, etc, not unconsumed
|
|
|
|
|
virtual bool isOutputter() const { return false; }
|
2020-05-25 21:34:24 +02:00
|
|
|
// Else a AstTime etc which output can't be predicted from input
|
|
|
|
|
virtual bool isPredictOptimizable() const { return true; }
|
|
|
|
|
// Else a $display, etc, that must be ordered with other displays
|
|
|
|
|
virtual bool isPure() const { return true; }
|
|
|
|
|
// Else a AstTime etc that can't be substituted out
|
|
|
|
|
virtual bool isSubstOptimizable() const { return true; }
|
2019-05-19 22:13:13 +02:00
|
|
|
// isUnlikely handles $stop or similar statement which means an above IF
|
|
|
|
|
// statement is unlikely to be taken
|
2018-03-10 22:32:04 +01:00
|
|
|
virtual bool isUnlikely() const { return false; }
|
2019-05-19 22:13:13 +02:00
|
|
|
virtual int instrCount() const { return 0; }
|
2017-10-28 16:26:19 +02:00
|
|
|
virtual bool same(const AstNode*) const { return true; }
|
2020-04-15 13:58:34 +02:00
|
|
|
// Iff has a data type; dtype() must be non null
|
|
|
|
|
virtual bool hasDType() const { return false; }
|
|
|
|
|
// Iff has a non-null childDTypep(), as generic node function
|
2020-08-15 16:12:55 +02:00
|
|
|
virtual AstNodeDType* getChildDTypep() const { return nullptr; }
|
2020-06-08 12:47:18 +02:00
|
|
|
// Iff has a non-null child2DTypep(), as generic node function
|
2020-08-15 16:12:55 +02:00
|
|
|
virtual AstNodeDType* getChild2DTypep() const { return nullptr; }
|
2018-03-10 22:32:04 +01:00
|
|
|
// Another AstNode* may have a pointer into this node, other then normal front/back/etc.
|
|
|
|
|
virtual bool maybePointedTo() const { return false; }
|
2021-12-13 00:10:52 +01:00
|
|
|
// Don't reclaim this node in V3Dead
|
|
|
|
|
virtual bool undead() const { return false; }
|
|
|
|
|
// Check if node is consistent, return nullptr if ok, else reason string
|
2020-08-15 16:12:55 +02:00
|
|
|
virtual const char* broken() const { return nullptr; }
|
2006-08-26 13:35:28 +02:00
|
|
|
|
|
|
|
|
// INVOKERS
|
2016-11-27 14:11:38 +01:00
|
|
|
virtual void accept(AstNVisitor& v) = 0;
|
2018-05-11 02:55:37 +02:00
|
|
|
|
|
|
|
|
protected:
|
|
|
|
|
// All AstNVisitor related functions are called as methods off the visitor
|
|
|
|
|
friend class AstNVisitor;
|
2020-04-15 13:58:34 +02:00
|
|
|
// Use instead AstNVisitor::iterateChildren
|
|
|
|
|
void iterateChildren(AstNVisitor& v);
|
|
|
|
|
// Use instead AstNVisitor::iterateChildrenBackwards
|
|
|
|
|
void iterateChildrenBackwards(AstNVisitor& v);
|
|
|
|
|
// Use instead AstNVisitor::iterateChildrenConst
|
|
|
|
|
void iterateChildrenConst(AstNVisitor& v);
|
|
|
|
|
// Use instead AstNVisitor::iterateAndNextNull
|
|
|
|
|
void iterateAndNext(AstNVisitor& v);
|
|
|
|
|
// Use instead AstNVisitor::iterateAndNextConstNull
|
|
|
|
|
void iterateAndNextConst(AstNVisitor& v);
|
|
|
|
|
// Use instead AstNVisitor::iterateSubtreeReturnEdits
|
|
|
|
|
AstNode* iterateSubtreeReturnEdits(AstNVisitor& v);
|
|
|
|
|
|
2018-05-11 02:55:37 +02:00
|
|
|
private:
|
|
|
|
|
void iterateListBackwards(AstNVisitor& v);
|
2006-08-26 13:35:28 +02:00
|
|
|
|
2021-10-16 20:18:06 +02:00
|
|
|
// For internal use only.
|
|
|
|
|
template <typename T> inline static bool privateTypeTest(const AstNode* nodep);
|
2020-01-23 01:07:48 +01:00
|
|
|
|
2021-10-22 18:36:58 +02:00
|
|
|
template <typename TargetType, typename DeclType> constexpr static bool uselessCast() {
|
|
|
|
|
using NonRef = typename std::remove_reference<DeclType>::type;
|
|
|
|
|
using NonPtr = typename std::remove_pointer<NonRef>::type;
|
|
|
|
|
using NonCV = typename std::remove_cv<NonPtr>::type;
|
|
|
|
|
return std::is_base_of<TargetType, NonCV>::value;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
template <typename TargetType, typename DeclType> constexpr static bool impossibleCast() {
|
|
|
|
|
using NonRef = typename std::remove_reference<DeclType>::type;
|
|
|
|
|
using NonPtr = typename std::remove_pointer<NonRef>::type;
|
|
|
|
|
using NonCV = typename std::remove_cv<NonPtr>::type;
|
|
|
|
|
return !std::is_base_of<NonCV, TargetType>::value;
|
|
|
|
|
}
|
|
|
|
|
|
2021-10-16 20:18:06 +02:00
|
|
|
public:
|
|
|
|
|
// For use via the VN_IS macro only
|
2021-10-22 18:36:58 +02:00
|
|
|
template <typename T, typename E> inline static bool privateIs(const AstNode* nodep) {
|
|
|
|
|
static_assert(!uselessCast<T, E>(), "Unnecessary VN_IS, node known to have target type.");
|
|
|
|
|
static_assert(!impossibleCast<T, E>(), "Unnecessary VN_IS, node cannot be this type.");
|
2021-10-16 20:18:06 +02:00
|
|
|
return nodep && privateTypeTest<T>(nodep);
|
|
|
|
|
}
|
2021-10-22 16:15:42 +02:00
|
|
|
|
2021-10-16 20:18:06 +02:00
|
|
|
// For use via the VN_CAST macro only
|
2021-10-22 18:36:58 +02:00
|
|
|
template <typename T, typename E> inline static T* privateCast(AstNode* nodep) {
|
|
|
|
|
static_assert(!uselessCast<T, E>(),
|
|
|
|
|
"Unnecessary VN_CAST, node known to have target type.");
|
|
|
|
|
static_assert(!impossibleCast<T, E>(), "Unnecessary VN_CAST, node cannot be this type.");
|
|
|
|
|
return nodep && privateTypeTest<T>(nodep) ? reinterpret_cast<T*>(nodep) : nullptr;
|
2021-10-16 20:18:06 +02:00
|
|
|
}
|
2021-10-22 16:15:42 +02:00
|
|
|
template <typename T, typename E> inline static const T* privateCast(const AstNode* nodep) {
|
2021-10-22 18:36:58 +02:00
|
|
|
static_assert(!uselessCast<T, E>(),
|
2021-10-22 16:15:42 +02:00
|
|
|
"Unnecessary VN_CAST, node known to have target type.");
|
|
|
|
|
static_assert(!impossibleCast<T, E>(), "Unnecessary VN_CAST, node cannot be this type.");
|
2021-10-22 18:36:58 +02:00
|
|
|
return nodep && privateTypeTest<T>(nodep) ? reinterpret_cast<const T*>(nodep) : nullptr;
|
2021-10-16 20:18:06 +02:00
|
|
|
}
|
2021-10-22 16:15:42 +02:00
|
|
|
|
2021-10-16 20:29:38 +02:00
|
|
|
// For use via the VN_AS macro only
|
2021-10-22 18:36:58 +02:00
|
|
|
template <typename T, typename E> inline static T* privateAs(AstNode* nodep) {
|
|
|
|
|
static_assert(!uselessCast<T, E>(), "Unnecessary VN_AS, node known to have target type.");
|
|
|
|
|
static_assert(!impossibleCast<T, E>(), "Unnecessary VN_AS, node cannot be this type.");
|
2021-10-16 20:29:38 +02:00
|
|
|
UASSERT_OBJ(!nodep || privateTypeTest<T>(nodep), nodep,
|
|
|
|
|
"AstNode is not of expected type, but instead has type '" << nodep->typeName()
|
|
|
|
|
<< "'");
|
|
|
|
|
return reinterpret_cast<T*>(nodep);
|
|
|
|
|
}
|
2021-10-22 16:15:42 +02:00
|
|
|
template <typename T, typename E> inline static const T* privateAs(const AstNode* nodep) {
|
|
|
|
|
static_assert(!uselessCast<T, E>(), "Unnecessary VN_AS, node known to have target type.");
|
|
|
|
|
static_assert(!impossibleCast<T, E>(), "Unnecessary VN_AS, node cannot be this type.");
|
2021-10-16 20:29:38 +02:00
|
|
|
UASSERT_OBJ(!nodep || privateTypeTest<T>(nodep), nodep,
|
|
|
|
|
"AstNode is not of expected type, but instead has type '" << nodep->typeName()
|
|
|
|
|
<< "'");
|
|
|
|
|
return reinterpret_cast<const T*>(nodep);
|
|
|
|
|
}
|
2006-08-26 13:35:28 +02:00
|
|
|
};
|
|
|
|
|
|
2020-01-23 01:07:48 +01:00
|
|
|
// Specialisations of privateIs/privateCast
|
|
|
|
|
#include "V3Ast__gen_impl.h" // From ./astgen
|
|
|
|
|
|
2019-10-20 17:49:41 +02:00
|
|
|
inline std::ostream& operator<<(std::ostream& os, const AstNode* rhs) {
|
2020-04-15 13:58:34 +02:00
|
|
|
if (!rhs) {
|
2020-08-15 16:12:55 +02:00
|
|
|
os << "nullptr";
|
2020-04-15 13:58:34 +02:00
|
|
|
} else {
|
|
|
|
|
rhs->dump(os);
|
|
|
|
|
}
|
|
|
|
|
return os;
|
2019-05-19 22:13:13 +02:00
|
|
|
}
|
2006-08-26 13:35:28 +02:00
|
|
|
inline void AstNRelinker::relink(AstNode* newp) { newp->AstNode::relink(this); }
|
|
|
|
|
|
|
|
|
|
//######################################################################
|
|
|
|
|
//######################################################################
|
|
|
|
|
//=== AstNode* : Derived generic node types
|
|
|
|
|
|
2020-04-15 13:58:34 +02:00
|
|
|
#define ASTNODE_BASE_FUNCS(name) \
|
2020-11-17 01:56:16 +01:00
|
|
|
virtual ~Ast##name() override = default; \
|
2020-04-15 13:58:34 +02:00
|
|
|
static Ast##name* cloneTreeNull(Ast##name* nodep, bool cloneNextLink) { \
|
2020-08-15 16:12:55 +02:00
|
|
|
return nodep ? nodep->cloneTree(cloneNextLink) : nullptr; \
|
2020-04-15 13:58:34 +02:00
|
|
|
} \
|
|
|
|
|
Ast##name* cloneTree(bool cloneNext) { \
|
|
|
|
|
return static_cast<Ast##name*>(AstNode::cloneTree(cloneNext)); \
|
|
|
|
|
} \
|
|
|
|
|
Ast##name* clonep() const { return static_cast<Ast##name*>(AstNode::clonep()); }
|
2008-11-20 02:15:05 +01:00
|
|
|
|
2020-11-19 03:32:16 +01:00
|
|
|
class AstNodeMath VL_NOT_FINAL : public AstNode {
|
2006-08-26 13:35:28 +02:00
|
|
|
// Math -- anything that's part of an expression tree
|
2021-05-15 22:10:16 +02:00
|
|
|
protected:
|
2020-01-25 21:29:44 +01:00
|
|
|
AstNodeMath(AstType t, FileLine* fl)
|
2020-08-16 17:40:42 +02:00
|
|
|
: AstNode{t, fl} {}
|
2021-05-15 22:10:16 +02:00
|
|
|
|
|
|
|
|
public:
|
2008-11-20 02:15:05 +01:00
|
|
|
ASTNODE_BASE_FUNCS(NodeMath)
|
2006-08-26 13:35:28 +02:00
|
|
|
// METHODS
|
2020-09-17 03:52:24 +02:00
|
|
|
virtual void dump(std::ostream& str) const override;
|
2020-08-15 17:44:10 +02:00
|
|
|
virtual bool hasDType() const override { return true; }
|
2006-08-26 13:35:28 +02:00
|
|
|
virtual string emitVerilog() = 0; /// Format string for verilog writing; see V3EmitV
|
Introduce model interface class, make $root part or Syms (#3036)
This patch implements #3032. Verilator creates a module representing the
SystemVerilog $root scope (V3LinkLevel::wrapTop). Until now, this was
called the "TOP" module, which also acted as the user instantiated model
class. Syms used to hold a pointer to this root module, but hold
instances of any submodule. This patch renames this root scope module
from "TOP" to "$root", and introduces a separate model class which is
now an interface class. As the root module is no longer the user
interface class, it can now be made an instance of Syms, just like any
other submodule. This allows absolute references into the root module to
avoid an additional pointer indirection resulting in a potential speedup
(about 1.5% on OpenTitan). The model class now also contains all non
design specific generated code (e.g.: eval loops, trace config, etc),
which additionally simplifies Verilator internals.
Please see the updated documentation for the model interface changes.
2021-06-21 16:30:20 +02:00
|
|
|
// For documentation on emitC format see EmitCFunc::emitOpName
|
2008-06-30 02:02:24 +02:00
|
|
|
virtual string emitC() = 0;
|
2021-02-14 17:15:12 +01:00
|
|
|
virtual string emitSimpleOperator() { return ""; } // "" means not ok to use
|
2020-08-04 04:12:13 +02:00
|
|
|
virtual bool emitCheckMaxWords() { return false; } // Check VL_MULS_MAX_WORDS
|
2019-10-20 17:58:41 +02:00
|
|
|
virtual bool cleanOut() const = 0; // True if output has extra upper bits zero
|
2010-01-17 21:10:37 +01:00
|
|
|
// Someday we will generically support data types on every math node
|
|
|
|
|
// Until then isOpaque indicates we shouldn't constant optimize this node type
|
2021-11-13 17:38:12 +01:00
|
|
|
bool isOpaque() const { return VN_IS(this, CvtPackString); }
|
2006-08-26 13:35:28 +02:00
|
|
|
};
|
|
|
|
|
|
2020-11-19 03:32:16 +01:00
|
|
|
class AstNodeTermop VL_NOT_FINAL : public AstNodeMath {
|
2006-08-26 13:35:28 +02:00
|
|
|
// Terminal operator -- a operator with no "inputs"
|
2021-05-15 22:10:16 +02:00
|
|
|
protected:
|
2020-01-25 21:29:44 +01:00
|
|
|
AstNodeTermop(AstType t, FileLine* fl)
|
2020-08-16 17:40:42 +02:00
|
|
|
: AstNodeMath{t, fl} {}
|
2021-05-15 22:10:16 +02:00
|
|
|
|
|
|
|
|
public:
|
2008-11-20 02:15:05 +01:00
|
|
|
ASTNODE_BASE_FUNCS(NodeTermop)
|
2008-11-22 21:28:29 +01:00
|
|
|
// Know no children, and hot function, so skip iterator for speed
|
|
|
|
|
// See checkTreeIter also that asserts no children
|
2011-08-05 03:58:45 +02:00
|
|
|
// cppcheck-suppress functionConst
|
2020-04-15 13:58:34 +02:00
|
|
|
void iterateChildren(AstNVisitor& v) {}
|
2020-09-17 03:52:24 +02:00
|
|
|
virtual void dump(std::ostream& str) const override;
|
2006-08-26 13:35:28 +02:00
|
|
|
};
|
|
|
|
|
|
2020-11-19 03:32:16 +01:00
|
|
|
class AstNodeUniop VL_NOT_FINAL : public AstNodeMath {
|
2006-08-26 13:35:28 +02:00
|
|
|
// Unary math
|
2021-05-15 22:10:16 +02:00
|
|
|
protected:
|
2020-01-25 21:29:44 +01:00
|
|
|
AstNodeUniop(AstType t, FileLine* fl, AstNode* lhsp)
|
2020-08-16 17:40:42 +02:00
|
|
|
: AstNodeMath{t, fl} {
|
2019-05-19 22:13:13 +02:00
|
|
|
dtypeFrom(lhsp);
|
2020-04-15 13:58:34 +02:00
|
|
|
setOp1p(lhsp);
|
|
|
|
|
}
|
2021-05-15 22:10:16 +02:00
|
|
|
|
|
|
|
|
public:
|
2008-11-20 02:15:05 +01:00
|
|
|
ASTNODE_BASE_FUNCS(NodeUniop)
|
2019-05-19 22:13:13 +02:00
|
|
|
AstNode* lhsp() const { return op1p(); }
|
|
|
|
|
void lhsp(AstNode* nodep) { return setOp1p(nodep); }
|
2006-08-26 13:35:28 +02:00
|
|
|
// METHODS
|
2020-09-17 03:52:24 +02:00
|
|
|
virtual void dump(std::ostream& str) const override;
|
2020-04-15 13:58:34 +02:00
|
|
|
// Set out to evaluation of a AstConst'ed lhs
|
|
|
|
|
virtual void numberOperate(V3Number& out, const V3Number& lhs) = 0;
|
2019-10-20 17:58:41 +02:00
|
|
|
virtual bool cleanLhs() const = 0;
|
|
|
|
|
virtual bool sizeMattersLhs() const = 0; // True if output result depends on lhs size
|
2019-05-19 22:13:13 +02:00
|
|
|
virtual bool doubleFlavor() const { return false; } // D flavor of nodes with both flavors?
|
2020-04-15 13:58:34 +02:00
|
|
|
// Signed flavor of nodes with both flavors?
|
|
|
|
|
virtual bool signedFlavor() const { return false; }
|
2019-05-19 22:13:13 +02:00
|
|
|
virtual bool stringFlavor() const { return false; } // N flavor of nodes with both flavors?
|
2020-08-15 17:44:10 +02:00
|
|
|
virtual int instrCount() const override { return widthInstrs(); }
|
|
|
|
|
virtual bool same(const AstNode*) const override { return true; }
|
2006-08-26 13:35:28 +02:00
|
|
|
};
|
|
|
|
|
|
2020-11-19 03:32:16 +01:00
|
|
|
class AstNodeBiop VL_NOT_FINAL : public AstNodeMath {
|
2006-08-26 13:35:28 +02:00
|
|
|
// Binary math
|
2021-05-15 22:10:16 +02:00
|
|
|
protected:
|
2020-01-25 21:29:44 +01:00
|
|
|
AstNodeBiop(AstType t, FileLine* fl, AstNode* lhs, AstNode* rhs)
|
2020-08-16 17:40:42 +02:00
|
|
|
: AstNodeMath{t, fl} {
|
2020-04-15 13:58:34 +02:00
|
|
|
setOp1p(lhs);
|
|
|
|
|
setOp2p(rhs);
|
|
|
|
|
}
|
2021-05-15 22:10:16 +02:00
|
|
|
|
|
|
|
|
public:
|
2008-11-20 02:15:05 +01:00
|
|
|
ASTNODE_BASE_FUNCS(NodeBiop)
|
2020-04-15 13:58:34 +02:00
|
|
|
// Clone single node, just get same type back.
|
|
|
|
|
virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) = 0;
|
2016-07-23 22:54:36 +02:00
|
|
|
// ACCESSORS
|
2019-05-19 22:13:13 +02:00
|
|
|
AstNode* lhsp() const { return op1p(); }
|
|
|
|
|
AstNode* rhsp() const { return op2p(); }
|
|
|
|
|
void lhsp(AstNode* nodep) { return setOp1p(nodep); }
|
|
|
|
|
void rhsp(AstNode* nodep) { return setOp2p(nodep); }
|
2006-08-26 13:35:28 +02:00
|
|
|
// METHODS
|
2020-04-15 13:58:34 +02:00
|
|
|
// Set out to evaluation of a AstConst'ed
|
|
|
|
|
virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) = 0;
|
2019-10-20 17:58:41 +02:00
|
|
|
virtual bool cleanLhs() const = 0; // True if LHS must have extra upper bits zero
|
|
|
|
|
virtual bool cleanRhs() const = 0; // True if RHS must have extra upper bits zero
|
|
|
|
|
virtual bool sizeMattersLhs() const = 0; // True if output result depends on lhs size
|
|
|
|
|
virtual bool sizeMattersRhs() const = 0; // True if output result depends on rhs size
|
2019-05-19 22:13:13 +02:00
|
|
|
virtual bool doubleFlavor() const { return false; } // D flavor of nodes with both flavors?
|
2020-04-15 13:58:34 +02:00
|
|
|
// Signed flavor of nodes with both flavors?
|
|
|
|
|
virtual bool signedFlavor() const { return false; }
|
2019-05-19 22:13:13 +02:00
|
|
|
virtual bool stringFlavor() const { return false; } // N flavor of nodes with both flavors?
|
2020-08-15 17:44:10 +02:00
|
|
|
virtual int instrCount() const override { return widthInstrs(); }
|
|
|
|
|
virtual bool same(const AstNode*) const override { return true; }
|
2006-08-26 13:35:28 +02:00
|
|
|
};
|
|
|
|
|
|
2020-11-19 03:32:16 +01:00
|
|
|
class AstNodeTriop VL_NOT_FINAL : public AstNodeMath {
|
2006-08-26 13:35:28 +02:00
|
|
|
// Trinary math
|
2021-05-15 22:10:16 +02:00
|
|
|
protected:
|
2020-01-25 21:29:44 +01:00
|
|
|
AstNodeTriop(AstType t, FileLine* fl, AstNode* lhs, AstNode* rhs, AstNode* ths)
|
2020-08-16 17:40:42 +02:00
|
|
|
: AstNodeMath{t, fl} {
|
2020-04-15 13:58:34 +02:00
|
|
|
setOp1p(lhs);
|
|
|
|
|
setOp2p(rhs);
|
|
|
|
|
setOp3p(ths);
|
|
|
|
|
}
|
2021-05-15 22:10:16 +02:00
|
|
|
|
|
|
|
|
public:
|
2008-11-20 02:15:05 +01:00
|
|
|
ASTNODE_BASE_FUNCS(NodeTriop)
|
2019-05-19 22:13:13 +02:00
|
|
|
AstNode* lhsp() const { return op1p(); }
|
|
|
|
|
AstNode* rhsp() const { return op2p(); }
|
|
|
|
|
AstNode* thsp() const { return op3p(); }
|
|
|
|
|
void lhsp(AstNode* nodep) { return setOp1p(nodep); }
|
|
|
|
|
void rhsp(AstNode* nodep) { return setOp2p(nodep); }
|
|
|
|
|
void thsp(AstNode* nodep) { return setOp3p(nodep); }
|
2006-08-26 13:35:28 +02:00
|
|
|
// METHODS
|
2020-09-17 03:52:24 +02:00
|
|
|
virtual void dump(std::ostream& str) const override;
|
2018-03-10 22:32:04 +01:00
|
|
|
// Set out to evaluation of a AstConst'ed
|
2020-04-15 13:58:34 +02:00
|
|
|
virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs,
|
|
|
|
|
const V3Number& ths)
|
|
|
|
|
= 0;
|
2019-10-20 17:58:41 +02:00
|
|
|
virtual bool cleanLhs() const = 0; // True if LHS must have extra upper bits zero
|
|
|
|
|
virtual bool cleanRhs() const = 0; // True if RHS must have extra upper bits zero
|
|
|
|
|
virtual bool cleanThs() const = 0; // True if THS must have extra upper bits zero
|
|
|
|
|
virtual bool sizeMattersLhs() const = 0; // True if output result depends on lhs size
|
|
|
|
|
virtual bool sizeMattersRhs() const = 0; // True if output result depends on rhs size
|
|
|
|
|
virtual bool sizeMattersThs() const = 0; // True if output result depends on ths size
|
2020-08-15 17:44:10 +02:00
|
|
|
virtual int instrCount() const override { return widthInstrs(); }
|
|
|
|
|
virtual bool same(const AstNode*) const override { return true; }
|
2006-08-26 13:35:28 +02:00
|
|
|
};
|
|
|
|
|
|
2020-11-19 03:32:16 +01:00
|
|
|
class AstNodeQuadop VL_NOT_FINAL : public AstNodeMath {
|
2020-05-10 20:27:22 +02:00
|
|
|
// Quaternary math
|
2021-05-15 22:10:16 +02:00
|
|
|
protected:
|
2020-05-10 20:27:22 +02:00
|
|
|
AstNodeQuadop(AstType t, FileLine* fl, AstNode* lhs, AstNode* rhs, AstNode* ths, AstNode* fhs)
|
2020-08-16 17:40:42 +02:00
|
|
|
: AstNodeMath{t, fl} {
|
2020-05-10 20:27:22 +02:00
|
|
|
setOp1p(lhs);
|
|
|
|
|
setOp2p(rhs);
|
|
|
|
|
setOp3p(ths);
|
|
|
|
|
setOp4p(fhs);
|
|
|
|
|
}
|
2021-05-15 22:10:16 +02:00
|
|
|
|
|
|
|
|
public:
|
2020-05-10 20:27:22 +02:00
|
|
|
ASTNODE_BASE_FUNCS(NodeQuadop)
|
|
|
|
|
AstNode* lhsp() const { return op1p(); }
|
|
|
|
|
AstNode* rhsp() const { return op2p(); }
|
|
|
|
|
AstNode* thsp() const { return op3p(); }
|
|
|
|
|
AstNode* fhsp() const { return op4p(); }
|
|
|
|
|
void lhsp(AstNode* nodep) { return setOp1p(nodep); }
|
|
|
|
|
void rhsp(AstNode* nodep) { return setOp2p(nodep); }
|
|
|
|
|
void thsp(AstNode* nodep) { return setOp3p(nodep); }
|
|
|
|
|
void fhsp(AstNode* nodep) { return setOp4p(nodep); }
|
|
|
|
|
// METHODS
|
|
|
|
|
// Set out to evaluation of a AstConst'ed
|
|
|
|
|
virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs,
|
|
|
|
|
const V3Number& ths, const V3Number& fhs)
|
|
|
|
|
= 0;
|
|
|
|
|
virtual bool cleanLhs() const = 0; // True if LHS must have extra upper bits zero
|
|
|
|
|
virtual bool cleanRhs() const = 0; // True if RHS must have extra upper bits zero
|
|
|
|
|
virtual bool cleanThs() const = 0; // True if THS must have extra upper bits zero
|
|
|
|
|
virtual bool cleanFhs() const = 0; // True if THS must have extra upper bits zero
|
|
|
|
|
virtual bool sizeMattersLhs() const = 0; // True if output result depends on lhs size
|
|
|
|
|
virtual bool sizeMattersRhs() const = 0; // True if output result depends on rhs size
|
|
|
|
|
virtual bool sizeMattersThs() const = 0; // True if output result depends on ths size
|
|
|
|
|
virtual bool sizeMattersFhs() const = 0; // True if output result depends on ths size
|
2020-08-15 17:44:10 +02:00
|
|
|
virtual int instrCount() const override { return widthInstrs(); }
|
|
|
|
|
virtual bool same(const AstNode*) const override { return true; }
|
2020-05-10 20:27:22 +02:00
|
|
|
};
|
|
|
|
|
|
2020-11-19 03:32:16 +01:00
|
|
|
class AstNodeBiCom VL_NOT_FINAL : public AstNodeBiop {
|
2006-08-26 13:35:28 +02:00
|
|
|
// Binary math with commutative properties
|
2021-05-15 22:10:16 +02:00
|
|
|
protected:
|
2020-01-25 21:29:44 +01:00
|
|
|
AstNodeBiCom(AstType t, FileLine* fl, AstNode* lhs, AstNode* rhs)
|
2020-08-16 17:40:42 +02:00
|
|
|
: AstNodeBiop{t, fl, lhs, rhs} {}
|
2021-05-15 22:10:16 +02:00
|
|
|
|
|
|
|
|
public:
|
2008-11-20 02:15:05 +01:00
|
|
|
ASTNODE_BASE_FUNCS(NodeBiCom)
|
2006-08-26 13:35:28 +02:00
|
|
|
};
|
|
|
|
|
|
2020-11-19 03:32:16 +01:00
|
|
|
class AstNodeBiComAsv VL_NOT_FINAL : public AstNodeBiCom {
|
2006-08-26 13:35:28 +02:00
|
|
|
// Binary math with commutative & associative properties
|
2021-05-15 22:10:16 +02:00
|
|
|
protected:
|
2020-01-25 21:29:44 +01:00
|
|
|
AstNodeBiComAsv(AstType t, FileLine* fl, AstNode* lhs, AstNode* rhs)
|
2020-08-16 17:40:42 +02:00
|
|
|
: AstNodeBiCom{t, fl, lhs, rhs} {}
|
2021-05-15 22:10:16 +02:00
|
|
|
|
|
|
|
|
public:
|
2008-11-20 02:15:05 +01:00
|
|
|
ASTNODE_BASE_FUNCS(NodeBiComAsv)
|
2006-08-26 13:35:28 +02:00
|
|
|
};
|
2021-05-15 22:10:16 +02:00
|
|
|
|
2020-11-19 03:32:16 +01:00
|
|
|
class AstNodeCond VL_NOT_FINAL : public AstNodeTriop {
|
2021-05-15 22:10:16 +02:00
|
|
|
protected:
|
2020-01-25 21:29:44 +01:00
|
|
|
AstNodeCond(AstType t, FileLine* fl, AstNode* condp, AstNode* expr1p, AstNode* expr2p)
|
2020-08-16 17:40:42 +02:00
|
|
|
: AstNodeTriop{t, fl, condp, expr1p, expr2p} {
|
2020-04-15 13:58:34 +02:00
|
|
|
if (expr1p) {
|
|
|
|
|
dtypeFrom(expr1p);
|
|
|
|
|
} else if (expr2p) {
|
|
|
|
|
dtypeFrom(expr2p);
|
|
|
|
|
}
|
2006-08-26 13:35:28 +02:00
|
|
|
}
|
2021-05-15 22:10:16 +02:00
|
|
|
|
|
|
|
|
public:
|
2008-11-20 02:15:05 +01:00
|
|
|
ASTNODE_BASE_FUNCS(NodeCond)
|
2020-04-15 13:58:34 +02:00
|
|
|
virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs,
|
2020-08-15 17:44:10 +02:00
|
|
|
const V3Number& ths) override;
|
2019-05-10 02:03:19 +02:00
|
|
|
AstNode* condp() const { return op1p(); } // op1 = Condition
|
|
|
|
|
AstNode* expr1p() const { return op2p(); } // op2 = If true...
|
|
|
|
|
AstNode* expr2p() const { return op3p(); } // op3 = If false...
|
2020-08-15 17:44:10 +02:00
|
|
|
virtual string emitVerilog() override { return "%k(%l %f? %r %k: %t)"; }
|
2021-11-28 19:44:16 +01:00
|
|
|
virtual string emitC() override { return "VL_COND_%nq%lq%rq%tq(%nw, %P, %li, %ri, %ti)"; }
|
2020-08-15 17:44:10 +02:00
|
|
|
virtual bool cleanOut() const override { return false; } // clean if e1 & e2 clean
|
|
|
|
|
virtual bool cleanLhs() const override { return true; }
|
|
|
|
|
virtual bool cleanRhs() const override { return false; }
|
|
|
|
|
virtual bool cleanThs() const override { return false; } // Propagates up
|
|
|
|
|
virtual bool sizeMattersLhs() const override { return false; }
|
|
|
|
|
virtual bool sizeMattersRhs() const override { return false; }
|
|
|
|
|
virtual bool sizeMattersThs() const override { return false; }
|
2021-07-25 14:32:36 +02:00
|
|
|
virtual int instrCount() const override { return INSTR_COUNT_BRANCH; }
|
2017-10-05 03:15:19 +02:00
|
|
|
virtual AstNode* cloneType(AstNode* condp, AstNode* expr1p, AstNode* expr2p) = 0;
|
2006-08-26 13:35:28 +02:00
|
|
|
};
|
|
|
|
|
|
2020-11-19 03:32:16 +01:00
|
|
|
class AstNodeBlock VL_NOT_FINAL : public AstNode {
|
2020-04-23 03:31:40 +02:00
|
|
|
// A Begin/fork block
|
|
|
|
|
// Parents: statement
|
|
|
|
|
// Children: statements
|
|
|
|
|
private:
|
|
|
|
|
string m_name; // Name of block
|
|
|
|
|
bool m_unnamed; // Originally unnamed (name change does not affect this)
|
2021-05-15 22:10:16 +02:00
|
|
|
protected:
|
2020-04-23 03:31:40 +02:00
|
|
|
AstNodeBlock(AstType t, FileLine* fl, const string& name, AstNode* stmtsp)
|
2020-08-16 17:40:42 +02:00
|
|
|
: AstNode{t, fl}
|
|
|
|
|
, m_name{name} {
|
2020-04-23 03:31:40 +02:00
|
|
|
addNOp1p(stmtsp);
|
|
|
|
|
m_unnamed = (name == "");
|
|
|
|
|
}
|
2021-05-15 22:10:16 +02:00
|
|
|
|
|
|
|
|
public:
|
2020-04-23 03:31:40 +02:00
|
|
|
ASTNODE_BASE_FUNCS(NodeBlock)
|
2020-08-15 17:44:10 +02:00
|
|
|
virtual void dump(std::ostream& str) const override;
|
|
|
|
|
virtual string name() const override { return m_name; } // * = Block name
|
|
|
|
|
virtual void name(const string& name) override { m_name = name; }
|
2020-04-23 03:31:40 +02:00
|
|
|
// op1 = Statements
|
|
|
|
|
AstNode* stmtsp() const { return op1p(); } // op1 = List of statements
|
|
|
|
|
void addStmtsp(AstNode* nodep) { addNOp1p(nodep); }
|
|
|
|
|
bool unnamed() const { return m_unnamed; }
|
|
|
|
|
};
|
|
|
|
|
|
2020-11-19 03:32:16 +01:00
|
|
|
class AstNodePreSel VL_NOT_FINAL : public AstNode {
|
2011-12-01 01:32:33 +01:00
|
|
|
// Something that becomes an AstSel
|
2021-05-15 22:10:16 +02:00
|
|
|
protected:
|
2020-12-08 00:45:54 +01:00
|
|
|
AstNodePreSel(AstType t, FileLine* fl, AstNode* fromp, AstNode* rhs, AstNode* ths)
|
2020-08-16 17:40:42 +02:00
|
|
|
: AstNode{t, fl} {
|
2020-12-08 00:45:54 +01:00
|
|
|
setOp1p(fromp);
|
2020-04-15 13:58:34 +02:00
|
|
|
setOp2p(rhs);
|
|
|
|
|
setNOp3p(ths);
|
|
|
|
|
}
|
2021-05-15 22:10:16 +02:00
|
|
|
|
|
|
|
|
public:
|
2008-11-20 02:15:05 +01:00
|
|
|
ASTNODE_BASE_FUNCS(NodePreSel)
|
2020-12-08 00:45:54 +01:00
|
|
|
AstNode* fromp() const { return op1p(); }
|
2019-05-19 22:13:13 +02:00
|
|
|
AstNode* rhsp() const { return op2p(); }
|
|
|
|
|
AstNode* thsp() const { return op3p(); }
|
2021-10-22 14:56:48 +02:00
|
|
|
AstAttrOf* attrp() const { return VN_AS(op4p(), AttrOf); }
|
2020-12-08 00:45:54 +01:00
|
|
|
void fromp(AstNode* nodep) { return setOp1p(nodep); }
|
2019-05-19 22:13:13 +02:00
|
|
|
void rhsp(AstNode* nodep) { return setOp2p(nodep); }
|
|
|
|
|
void thsp(AstNode* nodep) { return setOp3p(nodep); }
|
|
|
|
|
void attrp(AstAttrOf* nodep) { return setOp4p((AstNode*)nodep); }
|
2006-08-26 13:35:28 +02:00
|
|
|
// METHODS
|
2020-08-15 17:44:10 +02:00
|
|
|
virtual bool same(const AstNode*) const override { return true; }
|
2006-08-26 13:35:28 +02:00
|
|
|
};
|
|
|
|
|
|
2020-11-19 03:32:16 +01:00
|
|
|
class AstNodeProcedure VL_NOT_FINAL : public AstNode {
|
2020-05-06 01:12:36 +02:00
|
|
|
// IEEE procedure: initial, final, always
|
2021-05-15 22:10:16 +02:00
|
|
|
protected:
|
2020-05-06 01:12:36 +02:00
|
|
|
AstNodeProcedure(AstType t, FileLine* fl, AstNode* bodysp)
|
2020-08-16 17:40:42 +02:00
|
|
|
: AstNode{t, fl} {
|
2020-05-06 01:12:36 +02:00
|
|
|
addNOp2p(bodysp);
|
|
|
|
|
}
|
2021-05-15 22:10:16 +02:00
|
|
|
|
|
|
|
|
public:
|
2020-05-06 01:12:36 +02:00
|
|
|
ASTNODE_BASE_FUNCS(NodeProcedure)
|
|
|
|
|
// METHODS
|
2020-09-17 03:52:24 +02:00
|
|
|
virtual void dump(std::ostream& str) const override;
|
2020-05-06 01:12:36 +02:00
|
|
|
AstNode* bodysp() const { return op2p(); } // op2 = Statements to evaluate
|
|
|
|
|
void addStmtp(AstNode* nodep) { addOp2p(nodep); }
|
|
|
|
|
bool isJustOneBodyStmt() const { return bodysp() && !bodysp()->nextp(); }
|
|
|
|
|
};
|
|
|
|
|
|
2020-11-19 03:32:16 +01:00
|
|
|
class AstNodeStmt VL_NOT_FINAL : public AstNode {
|
2006-08-26 13:35:28 +02:00
|
|
|
// Statement -- anything that's directly under a function
|
2020-01-18 19:02:42 +01:00
|
|
|
bool m_statement; // Really a statement (e.g. not a function with return)
|
2021-05-15 22:10:16 +02:00
|
|
|
protected:
|
2020-01-25 21:29:44 +01:00
|
|
|
AstNodeStmt(AstType t, FileLine* fl, bool statement = true)
|
2020-08-16 17:40:42 +02:00
|
|
|
: AstNode{t, fl}
|
|
|
|
|
, m_statement{statement} {}
|
2021-05-15 22:10:16 +02:00
|
|
|
|
|
|
|
|
public:
|
2008-11-20 02:15:05 +01:00
|
|
|
ASTNODE_BASE_FUNCS(NodeStmt)
|
2006-08-26 13:35:28 +02:00
|
|
|
// METHODS
|
2020-01-18 19:02:42 +01:00
|
|
|
bool isStatement() const { return m_statement; } // Really a statement
|
|
|
|
|
void statement(bool flag) { m_statement = flag; }
|
2020-09-17 03:52:24 +02:00
|
|
|
virtual void addNextStmt(AstNode* newp,
|
|
|
|
|
AstNode* belowp) override; // Stop statement searchback here
|
|
|
|
|
virtual void addBeforeStmt(AstNode* newp,
|
|
|
|
|
AstNode* belowp) override; // Stop statement searchback here
|
|
|
|
|
virtual void dump(std::ostream& str = std::cout) const override;
|
2006-08-26 13:35:28 +02:00
|
|
|
};
|
|
|
|
|
|
2020-11-19 03:32:16 +01:00
|
|
|
class AstNodeAssign VL_NOT_FINAL : public AstNodeStmt {
|
2021-05-15 22:10:16 +02:00
|
|
|
protected:
|
2020-01-25 21:29:44 +01:00
|
|
|
AstNodeAssign(AstType t, FileLine* fl, AstNode* lhsp, AstNode* rhsp)
|
2020-08-16 17:40:42 +02:00
|
|
|
: AstNodeStmt{t, fl} {
|
2020-04-15 13:58:34 +02:00
|
|
|
setOp1p(rhsp);
|
|
|
|
|
setOp2p(lhsp);
|
2019-05-19 22:13:13 +02:00
|
|
|
dtypeFrom(lhsp);
|
2006-08-26 13:35:28 +02:00
|
|
|
}
|
2021-05-15 22:10:16 +02:00
|
|
|
|
|
|
|
|
public:
|
2008-11-20 02:15:05 +01:00
|
|
|
ASTNODE_BASE_FUNCS(NodeAssign)
|
2020-04-15 13:58:34 +02:00
|
|
|
// Clone single node, just get same type back.
|
|
|
|
|
virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp) = 0;
|
2006-08-26 13:35:28 +02:00
|
|
|
// So iteration hits the RHS which is "earlier" in execution order, it's op1, not op2
|
2019-05-19 22:13:13 +02:00
|
|
|
AstNode* rhsp() const { return op1p(); } // op1 = Assign from
|
|
|
|
|
AstNode* lhsp() const { return op2p(); } // op2 = Assign to
|
2006-08-26 13:35:28 +02:00
|
|
|
void rhsp(AstNode* np) { setOp1p(np); }
|
|
|
|
|
void lhsp(AstNode* np) { setOp2p(np); }
|
2020-08-15 17:44:10 +02:00
|
|
|
virtual bool hasDType() const override { return true; }
|
2019-10-20 17:58:41 +02:00
|
|
|
virtual bool cleanRhs() const { return true; }
|
2020-08-15 17:44:10 +02:00
|
|
|
virtual int instrCount() const override { return widthInstrs(); }
|
|
|
|
|
virtual bool same(const AstNode*) const override { return true; }
|
|
|
|
|
virtual string verilogKwd() const override { return "="; }
|
2017-08-14 00:08:44 +02:00
|
|
|
virtual bool brokeLhsMustBeLvalue() const = 0;
|
2006-08-26 13:35:28 +02:00
|
|
|
};
|
|
|
|
|
|
2020-11-19 03:32:16 +01:00
|
|
|
class AstNodeFor VL_NOT_FINAL : public AstNodeStmt {
|
2021-05-15 22:10:16 +02:00
|
|
|
protected:
|
2020-04-15 13:58:34 +02:00
|
|
|
AstNodeFor(AstType t, FileLine* fl, AstNode* initsp, AstNode* condp, AstNode* incsp,
|
|
|
|
|
AstNode* bodysp)
|
2020-08-16 17:40:42 +02:00
|
|
|
: AstNodeStmt{t, fl} {
|
2020-04-15 13:58:34 +02:00
|
|
|
addNOp1p(initsp);
|
|
|
|
|
setOp2p(condp);
|
|
|
|
|
addNOp3p(incsp);
|
|
|
|
|
addNOp4p(bodysp);
|
2006-08-26 13:35:28 +02:00
|
|
|
}
|
2021-05-15 22:10:16 +02:00
|
|
|
|
|
|
|
|
public:
|
2008-11-20 02:15:05 +01:00
|
|
|
ASTNODE_BASE_FUNCS(NodeFor)
|
2019-05-19 22:13:13 +02:00
|
|
|
AstNode* initsp() const { return op1p(); } // op1 = initial statements
|
|
|
|
|
AstNode* condp() const { return op2p(); } // op2 = condition to continue
|
|
|
|
|
AstNode* incsp() const { return op3p(); } // op3 = increment statements
|
|
|
|
|
AstNode* bodysp() const { return op4p(); } // op4 = body of loop
|
2020-08-15 17:44:10 +02:00
|
|
|
virtual bool isGateOptimizable() const override { return false; }
|
2021-07-25 14:32:36 +02:00
|
|
|
virtual int instrCount() const override { return INSTR_COUNT_BRANCH; }
|
2020-08-15 17:44:10 +02:00
|
|
|
virtual bool same(const AstNode* samep) const override { return true; }
|
2006-08-26 13:35:28 +02:00
|
|
|
};
|
|
|
|
|
|
2020-11-19 03:32:16 +01:00
|
|
|
class AstNodeIf VL_NOT_FINAL : public AstNodeStmt {
|
2006-08-26 13:35:28 +02:00
|
|
|
private:
|
2019-10-05 13:54:14 +02:00
|
|
|
VBranchPred m_branchPred; // Branch prediction as taken/untaken?
|
2021-06-01 15:01:18 +02:00
|
|
|
bool m_isBoundsCheck; // True if this if node was inserted for array bounds checking
|
2021-05-15 22:10:16 +02:00
|
|
|
protected:
|
2020-01-25 21:29:44 +01:00
|
|
|
AstNodeIf(AstType t, FileLine* fl, AstNode* condp, AstNode* ifsp, AstNode* elsesp)
|
2020-08-16 17:40:42 +02:00
|
|
|
: AstNodeStmt{t, fl} {
|
2020-04-15 13:58:34 +02:00
|
|
|
setOp1p(condp);
|
|
|
|
|
addNOp2p(ifsp);
|
|
|
|
|
addNOp3p(elsesp);
|
2021-06-01 15:01:18 +02:00
|
|
|
isBoundsCheck(false);
|
2006-08-26 13:35:28 +02:00
|
|
|
}
|
2021-05-15 22:10:16 +02:00
|
|
|
|
|
|
|
|
public:
|
2008-11-20 02:15:05 +01:00
|
|
|
ASTNODE_BASE_FUNCS(NodeIf)
|
2019-05-19 22:13:13 +02:00
|
|
|
AstNode* condp() const { return op1p(); } // op1 = condition
|
|
|
|
|
AstNode* ifsp() const { return op2p(); } // op2 = list of true statements
|
|
|
|
|
AstNode* elsesp() const { return op3p(); } // op3 = list of false statements
|
|
|
|
|
void condp(AstNode* newp) { setOp1p(newp); }
|
|
|
|
|
void addIfsp(AstNode* newp) { addOp2p(newp); }
|
|
|
|
|
void addElsesp(AstNode* newp) { addOp3p(newp); }
|
2020-08-15 17:44:10 +02:00
|
|
|
virtual bool isGateOptimizable() const override { return false; }
|
|
|
|
|
virtual bool isGateDedupable() const override { return true; }
|
2021-07-25 14:32:36 +02:00
|
|
|
virtual int instrCount() const override { return INSTR_COUNT_BRANCH; }
|
2020-08-15 17:44:10 +02:00
|
|
|
virtual bool same(const AstNode* samep) const override { return true; }
|
2019-10-05 13:54:14 +02:00
|
|
|
void branchPred(VBranchPred flag) { m_branchPred = flag; }
|
|
|
|
|
VBranchPred branchPred() const { return m_branchPred; }
|
2021-06-01 15:01:18 +02:00
|
|
|
void isBoundsCheck(bool flag) { m_isBoundsCheck = flag; }
|
|
|
|
|
bool isBoundsCheck() const { return m_isBoundsCheck; }
|
2006-08-26 13:35:28 +02:00
|
|
|
};
|
|
|
|
|
|
2020-11-19 03:32:16 +01:00
|
|
|
class AstNodeCase VL_NOT_FINAL : public AstNodeStmt {
|
2021-05-15 22:10:16 +02:00
|
|
|
protected:
|
2020-01-25 21:29:44 +01:00
|
|
|
AstNodeCase(AstType t, FileLine* fl, AstNode* exprp, AstNode* casesp)
|
2020-08-16 17:40:42 +02:00
|
|
|
: AstNodeStmt{t, fl} {
|
2020-04-15 13:58:34 +02:00
|
|
|
setOp1p(exprp);
|
|
|
|
|
addNOp2p(casesp);
|
2006-08-26 13:35:28 +02:00
|
|
|
}
|
2021-05-15 22:10:16 +02:00
|
|
|
|
|
|
|
|
public:
|
2008-11-20 02:15:05 +01:00
|
|
|
ASTNODE_BASE_FUNCS(NodeCase)
|
2021-07-25 14:32:36 +02:00
|
|
|
virtual int instrCount() const override { return INSTR_COUNT_BRANCH; }
|
2019-05-19 22:13:13 +02:00
|
|
|
AstNode* exprp() const { return op1p(); } // op1 = case condition <expression>
|
2020-04-15 13:58:34 +02:00
|
|
|
AstCaseItem* itemsp() const {
|
2021-10-22 14:56:48 +02:00
|
|
|
return VN_AS(op2p(), CaseItem);
|
2020-04-15 13:58:34 +02:00
|
|
|
} // op2 = list of case expressions
|
2019-05-19 22:13:13 +02:00
|
|
|
AstNode* notParallelp() const { return op3p(); } // op3 = assertion code for non-full case's
|
2006-08-26 13:35:28 +02:00
|
|
|
void addItemsp(AstNode* nodep) { addOp2p(nodep); }
|
|
|
|
|
void addNotParallelp(AstNode* nodep) { setOp3p(nodep); }
|
|
|
|
|
};
|
|
|
|
|
|
2020-11-19 03:32:16 +01:00
|
|
|
class AstNodeVarRef VL_NOT_FINAL : public AstNodeMath {
|
2008-11-22 23:37:20 +01:00
|
|
|
// An AstVarRef or AstVarXRef
|
2006-08-26 13:35:28 +02:00
|
|
|
private:
|
2020-09-07 23:09:25 +02:00
|
|
|
VAccess m_access; // Left hand side assignment
|
2020-04-15 13:58:34 +02:00
|
|
|
AstVar* m_varp; // [AfterLink] Pointer to variable itself
|
2020-08-15 19:11:27 +02:00
|
|
|
AstVarScope* m_varScopep = nullptr; // Varscope for hierarchy
|
2020-11-25 03:56:03 +01:00
|
|
|
AstNodeModule* m_classOrPackagep = nullptr; // Package hierarchy
|
2020-04-15 13:58:34 +02:00
|
|
|
string m_name; // Name of variable
|
2021-06-13 15:33:11 +02:00
|
|
|
string m_selfPointer; // Output code object pointer (e.g.: 'this')
|
2020-04-15 13:58:34 +02:00
|
|
|
|
2021-05-15 22:10:16 +02:00
|
|
|
protected:
|
2020-09-07 23:09:25 +02:00
|
|
|
AstNodeVarRef(AstType t, FileLine* fl, const string& name, const VAccess& access)
|
2020-08-16 17:40:42 +02:00
|
|
|
: AstNodeMath{t, fl}
|
2020-09-07 23:09:25 +02:00
|
|
|
, m_access{access}
|
2020-08-16 17:40:42 +02:00
|
|
|
, m_name{name} {
|
2020-08-15 16:12:55 +02:00
|
|
|
this->varp(nullptr);
|
2006-08-26 13:35:28 +02:00
|
|
|
}
|
2020-09-07 23:09:25 +02:00
|
|
|
AstNodeVarRef(AstType t, FileLine* fl, const string& name, AstVar* varp, const VAccess& access)
|
2020-08-16 17:40:42 +02:00
|
|
|
: AstNodeMath{t, fl}
|
2020-09-07 23:09:25 +02:00
|
|
|
, m_access{access}
|
2020-08-16 17:40:42 +02:00
|
|
|
, m_name{name} {
|
2020-08-15 16:12:55 +02:00
|
|
|
// May have varp==nullptr
|
2020-07-04 18:58:22 +02:00
|
|
|
this->varp(varp);
|
2006-08-26 13:35:28 +02:00
|
|
|
}
|
2021-05-15 22:10:16 +02:00
|
|
|
|
|
|
|
|
public:
|
2008-11-20 02:15:05 +01:00
|
|
|
ASTNODE_BASE_FUNCS(NodeVarRef)
|
2020-09-17 03:52:24 +02:00
|
|
|
virtual void dump(std::ostream& str) const override;
|
2020-08-15 17:44:10 +02:00
|
|
|
virtual bool hasDType() const override { return true; }
|
|
|
|
|
virtual const char* broken() const override;
|
|
|
|
|
virtual int instrCount() const override { return widthInstrs(); }
|
|
|
|
|
virtual void cloneRelink() override;
|
|
|
|
|
virtual string name() const override { return m_name; } // * = Var name
|
|
|
|
|
virtual void name(const string& name) override { m_name = name; }
|
2020-09-07 23:09:25 +02:00
|
|
|
VAccess access() const { return m_access; }
|
|
|
|
|
void access(const VAccess& flag) { m_access = flag; } // Avoid using this; Set in constructor
|
2019-05-19 22:13:13 +02:00
|
|
|
AstVar* varp() const { return m_varp; } // [After Link] Pointer to variable
|
2020-07-04 18:58:22 +02:00
|
|
|
void varp(AstVar* varp);
|
2019-05-19 22:13:13 +02:00
|
|
|
AstVarScope* varScopep() const { return m_varScopep; }
|
|
|
|
|
void varScopep(AstVarScope* varscp) { m_varScopep = varscp; }
|
2021-06-13 15:33:11 +02:00
|
|
|
string selfPointer() const { return m_selfPointer; }
|
|
|
|
|
void selfPointer(const string& value) { m_selfPointer = value; }
|
|
|
|
|
string selfPointerProtect(bool useSelfForThis) const;
|
2020-11-25 03:56:03 +01:00
|
|
|
AstNodeModule* classOrPackagep() const { return m_classOrPackagep; }
|
|
|
|
|
void classOrPackagep(AstNodeModule* nodep) { m_classOrPackagep = nodep; }
|
2008-11-22 21:28:29 +01:00
|
|
|
// Know no children, and hot function, so skip iterator for speed
|
|
|
|
|
// See checkTreeIter also that asserts no children
|
2011-08-05 03:58:45 +02:00
|
|
|
// cppcheck-suppress functionConst
|
2020-04-15 13:58:34 +02:00
|
|
|
void iterateChildren(AstNVisitor& v) {}
|
2006-08-26 13:35:28 +02:00
|
|
|
};
|
|
|
|
|
|
2020-11-19 03:32:16 +01:00
|
|
|
class AstNodeText VL_NOT_FINAL : public AstNode {
|
2006-08-26 13:35:28 +02:00
|
|
|
private:
|
2020-04-15 13:58:34 +02:00
|
|
|
string m_text;
|
|
|
|
|
|
2021-05-15 22:10:16 +02:00
|
|
|
protected:
|
2006-08-26 13:35:28 +02:00
|
|
|
// Node that simply puts text into the output stream
|
2020-01-25 21:29:44 +01:00
|
|
|
AstNodeText(AstType t, FileLine* fl, const string& textp)
|
2020-08-16 17:40:42 +02:00
|
|
|
: AstNode{t, fl} {
|
2019-05-19 22:13:13 +02:00
|
|
|
m_text = textp; // Copy it
|
2006-08-26 13:35:28 +02:00
|
|
|
}
|
2021-05-15 22:10:16 +02:00
|
|
|
|
|
|
|
|
public:
|
2008-11-20 02:15:05 +01:00
|
|
|
ASTNODE_BASE_FUNCS(NodeText)
|
2020-08-15 17:44:10 +02:00
|
|
|
virtual void dump(std::ostream& str = std::cout) const override;
|
|
|
|
|
virtual bool same(const AstNode* samep) const override {
|
2019-05-19 22:13:13 +02:00
|
|
|
const AstNodeText* asamep = static_cast<const AstNodeText*>(samep);
|
2020-04-15 13:58:34 +02:00
|
|
|
return text() == asamep->text();
|
|
|
|
|
}
|
2009-12-05 16:38:49 +01:00
|
|
|
const string& text() const { return m_text; }
|
2006-08-26 13:35:28 +02:00
|
|
|
};
|
|
|
|
|
|
2020-11-19 03:32:16 +01:00
|
|
|
class AstNodeDType VL_NOT_FINAL : public AstNode {
|
2012-04-29 16:14:13 +02:00
|
|
|
// Ideally width() would migrate to BasicDType as that's where it makes sense,
|
|
|
|
|
// but it's currently so prevalent in the code we leave it here.
|
|
|
|
|
// Note the below members are included in AstTypeTable::Key lookups
|
2014-09-12 03:28:53 +02:00
|
|
|
private:
|
2020-04-15 13:58:34 +02:00
|
|
|
int m_width; // (also in AstTypeTable::Key) Bit width of operation
|
|
|
|
|
int m_widthMin; // (also in AstTypeTable::Key) If unsized, bitwidth of minimum implementation
|
2020-04-20 03:19:09 +02:00
|
|
|
VSigning m_numeric; // (also in AstTypeTable::Key) Node is signed
|
2012-04-29 16:14:13 +02:00
|
|
|
// Other members
|
2020-04-15 13:58:34 +02:00
|
|
|
bool m_generic; // Simple globally referenced type, don't garbage collect
|
|
|
|
|
// Unique number assigned to each dtype during creation for IEEE matching
|
|
|
|
|
static int s_uniqueNum;
|
|
|
|
|
|
2021-05-15 22:10:16 +02:00
|
|
|
protected:
|
2012-04-29 16:14:13 +02:00
|
|
|
// CONSTRUCTORS
|
2020-01-25 21:29:44 +01:00
|
|
|
AstNodeDType(AstType t, FileLine* fl)
|
2020-08-16 17:40:42 +02:00
|
|
|
: AstNode{t, fl} {
|
2020-04-15 13:58:34 +02:00
|
|
|
m_width = 0;
|
|
|
|
|
m_widthMin = 0;
|
|
|
|
|
m_generic = false;
|
2012-04-29 16:14:13 +02:00
|
|
|
}
|
2021-05-15 22:10:16 +02:00
|
|
|
|
|
|
|
|
public:
|
2009-11-02 14:06:04 +01:00
|
|
|
ASTNODE_BASE_FUNCS(NodeDType)
|
2012-04-29 16:14:13 +02:00
|
|
|
// ACCESSORS
|
2020-08-15 17:44:10 +02:00
|
|
|
virtual void dump(std::ostream& str) const override;
|
2019-10-20 17:49:41 +02:00
|
|
|
virtual void dumpSmall(std::ostream& str) const;
|
2020-08-15 17:44:10 +02:00
|
|
|
virtual bool hasDType() const override { return true; }
|
2020-12-13 01:19:16 +01:00
|
|
|
/// Require VlUnpacked, instead of [] for POD elements.
|
|
|
|
|
/// A non-POD object is always compound, but some POD elements
|
|
|
|
|
/// are compound when methods calls operate on object, or when
|
|
|
|
|
/// under another compound-requiring object e.g. class
|
|
|
|
|
virtual bool isCompound() const = 0;
|
|
|
|
|
// (Slow) recurse down to find basic data type
|
|
|
|
|
virtual AstBasicDType* basicp() const = 0;
|
2020-04-15 13:58:34 +02:00
|
|
|
// recurses over typedefs/const/enum to next non-typeref type
|
|
|
|
|
virtual AstNodeDType* skipRefp() const = 0;
|
|
|
|
|
// recurses over typedefs to next non-typeref-or-const type
|
|
|
|
|
virtual AstNodeDType* skipRefToConstp() const = 0;
|
|
|
|
|
// recurses over typedefs/const to next non-typeref-or-enum/struct type
|
|
|
|
|
virtual AstNodeDType* skipRefToEnump() const = 0;
|
|
|
|
|
// (Slow) recurses - Structure alignment 1,2,4 or 8 bytes (arrays affect this)
|
|
|
|
|
virtual int widthAlignBytes() const = 0;
|
|
|
|
|
// (Slow) recurses - Width in bytes rounding up 1,2,4,8,12,...
|
2020-05-24 03:57:08 +02:00
|
|
|
virtual int widthTotalBytes() const = 0;
|
2020-08-15 17:44:10 +02:00
|
|
|
virtual bool maybePointedTo() const override { return true; }
|
2020-04-15 13:58:34 +02:00
|
|
|
// Iff has a non-null refDTypep(), as generic node function
|
2020-08-15 16:12:55 +02:00
|
|
|
virtual AstNodeDType* virtRefDTypep() const { return nullptr; }
|
2020-04-15 13:58:34 +02:00
|
|
|
// Iff has refDTypep(), set as generic node function
|
|
|
|
|
virtual void virtRefDTypep(AstNodeDType* nodep) {}
|
|
|
|
|
// Iff has a non-null second dtypep, as generic node function
|
2020-08-15 16:12:55 +02:00
|
|
|
virtual AstNodeDType* virtRefDType2p() const { return nullptr; }
|
2020-04-15 13:58:34 +02:00
|
|
|
// Iff has second dtype, set as generic node function
|
|
|
|
|
virtual void virtRefDType2p(AstNodeDType* nodep) {}
|
|
|
|
|
// Assignable equivalence. Call skipRefp() on this and samep before calling
|
|
|
|
|
virtual bool similarDType(AstNodeDType* samep) const = 0;
|
|
|
|
|
// Iff has a non-null subDTypep(), as generic node function
|
2020-08-15 16:12:55 +02:00
|
|
|
virtual AstNodeDType* subDTypep() const { return nullptr; }
|
2017-12-10 02:17:37 +01:00
|
|
|
virtual bool isFourstate() const;
|
2020-04-15 13:58:34 +02:00
|
|
|
// Ideally an IEEE $typename
|
|
|
|
|
virtual string prettyDTypeName() const { return prettyTypeName(); }
|
2020-01-26 19:21:25 +01:00
|
|
|
string prettyDTypeNameQ() const { return "'" + prettyDTypeName() + "'"; }
|
2012-04-29 16:14:13 +02:00
|
|
|
//
|
2019-05-19 22:13:13 +02:00
|
|
|
// Changing the width may confuse the data type resolution, so must clear
|
|
|
|
|
// TypeTable cache after use.
|
2020-04-15 13:58:34 +02:00
|
|
|
void widthForce(int width, int widthMin) {
|
|
|
|
|
m_width = width;
|
|
|
|
|
m_widthMin = widthMin;
|
|
|
|
|
}
|
2013-01-12 22:19:25 +01:00
|
|
|
// For backward compatibility inherit width and signing from the subDType/base type
|
2020-04-15 13:58:34 +02:00
|
|
|
void widthFromSub(AstNodeDType* nodep) {
|
|
|
|
|
m_width = nodep->m_width;
|
|
|
|
|
m_widthMin = nodep->m_widthMin;
|
|
|
|
|
m_numeric = nodep->m_numeric;
|
|
|
|
|
}
|
2012-04-29 16:14:13 +02:00
|
|
|
//
|
2019-05-19 22:13:13 +02:00
|
|
|
int width() const { return m_width; }
|
2020-04-20 03:19:09 +02:00
|
|
|
void numeric(VSigning flag) { m_numeric = flag; }
|
2012-04-29 16:14:13 +02:00
|
|
|
bool isSigned() const { return m_numeric.isSigned(); }
|
|
|
|
|
bool isNosign() const { return m_numeric.isNosign(); }
|
2020-04-20 03:19:09 +02:00
|
|
|
VSigning numeric() const { return m_numeric; }
|
2019-05-19 22:13:13 +02:00
|
|
|
int widthWords() const { return VL_WORDS_I(width()); }
|
2018-03-10 22:32:04 +01:00
|
|
|
int widthMin() const { // If sized, the size, if unsized the min digits to represent it
|
2020-04-15 13:58:34 +02:00
|
|
|
return m_widthMin ? m_widthMin : m_width;
|
|
|
|
|
}
|
2012-04-29 16:14:13 +02:00
|
|
|
int widthPow2() const;
|
|
|
|
|
void widthMinFromWidth() { m_widthMin = m_width; }
|
2020-04-15 13:58:34 +02:00
|
|
|
bool widthSized() const { return !m_widthMin || m_widthMin == m_width; }
|
2012-04-29 16:14:13 +02:00
|
|
|
bool generic() const { return m_generic; }
|
|
|
|
|
void generic(bool flag) { m_generic = flag; }
|
2020-04-15 13:58:34 +02:00
|
|
|
std::pair<uint32_t, uint32_t> dimensions(bool includeBasic);
|
2019-05-19 22:13:13 +02:00
|
|
|
uint32_t arrayUnpackedElements(); // 1, or total multiplication of all dimensions
|
2012-04-29 16:14:13 +02:00
|
|
|
static int uniqueNumInc() { return ++s_uniqueNum; }
|
2020-04-15 13:58:34 +02:00
|
|
|
const char* charIQWN() const {
|
|
|
|
|
return (isString() ? "N" : isWide() ? "W" : isQuad() ? "Q" : "I");
|
|
|
|
|
}
|
2020-10-17 22:48:11 +02:00
|
|
|
string cType(const string& name, bool forFunc, bool isRef) const;
|
2021-07-22 19:59:03 +02:00
|
|
|
bool isLiteralType() const; // Does this represent a C++ LiteralType? (can be constexpr)
|
2020-10-17 22:48:11 +02:00
|
|
|
|
|
|
|
|
private:
|
|
|
|
|
class CTypeRecursed;
|
2020-11-11 03:40:14 +01:00
|
|
|
CTypeRecursed cTypeRecurse(bool compound) const;
|
2009-11-02 14:06:04 +01:00
|
|
|
};
|
|
|
|
|
|
2020-11-19 03:32:16 +01:00
|
|
|
class AstNodeUOrStructDType VL_NOT_FINAL : public AstNodeDType {
|
2019-12-17 04:46:09 +01:00
|
|
|
// A struct or union; common handling
|
2012-07-29 16:16:20 +02:00
|
|
|
private:
|
|
|
|
|
// TYPES
|
2021-03-13 00:10:45 +01:00
|
|
|
using MemberNameMap = std::map<const std::string, AstMemberDType*>;
|
2012-07-29 16:16:20 +02:00
|
|
|
// MEMBERS
|
2018-10-08 00:07:42 +02:00
|
|
|
string m_name; // Name from upper typedef, if any
|
2020-04-15 13:58:34 +02:00
|
|
|
bool m_packed;
|
|
|
|
|
bool m_isFourstate;
|
|
|
|
|
MemberNameMap m_members;
|
2021-05-21 15:34:27 +02:00
|
|
|
const int m_uniqueNum;
|
2020-04-15 13:58:34 +02:00
|
|
|
|
2021-05-15 22:10:16 +02:00
|
|
|
protected:
|
2020-04-20 03:19:09 +02:00
|
|
|
AstNodeUOrStructDType(AstType t, FileLine* fl, VSigning numericUnpack)
|
2021-05-21 15:34:27 +02:00
|
|
|
: AstNodeDType{t, fl}
|
|
|
|
|
, m_uniqueNum{uniqueNumInc()} {
|
2020-04-20 03:19:09 +02:00
|
|
|
// VSigning::NOSIGN overloaded to indicate not packed
|
|
|
|
|
m_packed = (numericUnpack != VSigning::NOSIGN);
|
2017-12-10 02:17:37 +01:00
|
|
|
m_isFourstate = false; // V3Width computes
|
2020-04-20 03:19:09 +02:00
|
|
|
numeric(VSigning::fromBool(numericUnpack.isSigned()));
|
2012-07-29 16:16:20 +02:00
|
|
|
}
|
2021-05-15 22:10:16 +02:00
|
|
|
|
|
|
|
|
public:
|
2019-12-17 04:46:09 +01:00
|
|
|
ASTNODE_BASE_FUNCS(NodeUOrStructDType)
|
2021-05-21 15:34:27 +02:00
|
|
|
int uniqueNum() const { return m_uniqueNum; }
|
2020-08-15 17:44:10 +02:00
|
|
|
virtual const char* broken() const override;
|
|
|
|
|
virtual void dump(std::ostream& str) const override;
|
2020-12-13 04:16:10 +01:00
|
|
|
virtual bool isCompound() const override { return false; } // Because don't support unpacked
|
2012-07-29 16:16:20 +02:00
|
|
|
// For basicp() we reuse the size to indicate a "fake" basic type of same size
|
2020-08-15 17:44:10 +02:00
|
|
|
virtual AstBasicDType* basicp() const override {
|
2020-12-07 03:13:56 +01:00
|
|
|
return (isFourstate()
|
2021-10-22 14:56:48 +02:00
|
|
|
? VN_AS(findLogicRangeDType(VNumRange{width() - 1, 0}, width(), numeric()),
|
|
|
|
|
BasicDType)
|
|
|
|
|
: VN_AS(findBitRangeDType(VNumRange{width() - 1, 0}, width(), numeric()),
|
|
|
|
|
BasicDType));
|
2020-04-08 01:07:47 +02:00
|
|
|
}
|
2020-08-15 17:44:10 +02:00
|
|
|
virtual AstNodeDType* skipRefp() const override { return (AstNodeDType*)this; }
|
|
|
|
|
virtual AstNodeDType* skipRefToConstp() const override { return (AstNodeDType*)this; }
|
|
|
|
|
virtual AstNodeDType* skipRefToEnump() const override { return (AstNodeDType*)this; }
|
|
|
|
|
// (Slow) recurses - Structure alignment 1,2,4 or 8 bytes (arrays affect this)
|
|
|
|
|
virtual int widthAlignBytes() const override;
|
|
|
|
|
// (Slow) recurses - Width in bytes rounding up 1,2,4,8,12,...
|
|
|
|
|
virtual int widthTotalBytes() const override;
|
2012-07-29 16:16:20 +02:00
|
|
|
// op1 = members
|
2020-08-15 17:44:10 +02:00
|
|
|
virtual bool similarDType(AstNodeDType* samep) const override {
|
2020-04-15 13:58:34 +02:00
|
|
|
return this == samep; // We don't compare members, require exact equivalence
|
2017-04-28 12:10:14 +02:00
|
|
|
}
|
2020-08-15 17:44:10 +02:00
|
|
|
virtual string name() const override { return m_name; }
|
|
|
|
|
virtual void name(const string& flag) override { m_name = flag; }
|
2020-04-15 13:58:34 +02:00
|
|
|
AstMemberDType* membersp() const {
|
2021-10-22 14:56:48 +02:00
|
|
|
return VN_AS(op1p(), MemberDType);
|
2020-04-15 13:58:34 +02:00
|
|
|
} // op1 = AstMember list
|
2012-07-29 16:16:20 +02:00
|
|
|
void addMembersp(AstNode* nodep) { addNOp1p(nodep); }
|
|
|
|
|
bool packed() const { return m_packed; }
|
2020-06-02 05:16:02 +02:00
|
|
|
// packed() but as don't support unpacked, presently all structs
|
|
|
|
|
static bool packedUnsup() { return true; }
|
2017-12-10 02:17:37 +01:00
|
|
|
void isFourstate(bool flag) { m_isFourstate = flag; }
|
2020-08-15 17:44:10 +02:00
|
|
|
virtual bool isFourstate() const override { return m_isFourstate; }
|
2012-07-29 16:16:20 +02:00
|
|
|
void clearCache() { m_members.clear(); }
|
|
|
|
|
void repairMemberCache();
|
|
|
|
|
AstMemberDType* findMember(const string& name) const {
|
2020-08-16 17:43:49 +02:00
|
|
|
const auto it = m_members.find(name);
|
2020-08-15 16:12:55 +02:00
|
|
|
return (it == m_members.end()) ? nullptr : it->second;
|
2012-07-29 16:16:20 +02:00
|
|
|
}
|
2020-12-07 03:13:56 +01:00
|
|
|
static int lo() { return 0; }
|
|
|
|
|
int hi() const { return dtypep()->width() - 1; } // Packed classes look like arrays
|
|
|
|
|
VNumRange declRange() const { return VNumRange{hi(), lo()}; }
|
2012-07-29 16:16:20 +02:00
|
|
|
};
|
|
|
|
|
|
2020-11-19 03:32:16 +01:00
|
|
|
class AstNodeArrayDType VL_NOT_FINAL : public AstNodeDType {
|
2013-01-12 22:19:25 +01:00
|
|
|
// Array data type, ie "some_dtype var_name [2:0]"
|
|
|
|
|
// Children: DTYPE (moved to refDTypep() in V3Width)
|
|
|
|
|
// Children: RANGE (array bounds)
|
|
|
|
|
private:
|
2020-08-16 17:40:42 +02:00
|
|
|
AstNodeDType* m_refDTypep = nullptr; // Elements of this type (after widthing)
|
2019-05-19 22:13:13 +02:00
|
|
|
AstNode* rangenp() const { return op2p(); } // op2 = Array(s) of variable
|
2021-05-15 22:10:16 +02:00
|
|
|
protected:
|
2020-01-25 21:29:44 +01:00
|
|
|
AstNodeArrayDType(AstType t, FileLine* fl)
|
2020-08-16 17:40:42 +02:00
|
|
|
: AstNodeDType{t, fl} {}
|
2021-05-15 22:10:16 +02:00
|
|
|
|
|
|
|
|
public:
|
2013-01-12 22:19:25 +01:00
|
|
|
ASTNODE_BASE_FUNCS(NodeArrayDType)
|
2020-08-15 17:44:10 +02:00
|
|
|
virtual void dump(std::ostream& str) const override;
|
|
|
|
|
virtual void dumpSmall(std::ostream& str) const override;
|
|
|
|
|
virtual const char* broken() const override {
|
2019-05-19 22:13:13 +02:00
|
|
|
BROKEN_RTN(!((m_refDTypep && !childDTypep() && m_refDTypep->brokeExists())
|
2020-04-15 13:58:34 +02:00
|
|
|
|| (!m_refDTypep && childDTypep())));
|
2020-08-15 16:12:55 +02:00
|
|
|
return nullptr;
|
2020-04-15 13:58:34 +02:00
|
|
|
}
|
2020-08-15 17:44:10 +02:00
|
|
|
virtual void cloneRelink() override {
|
2021-02-22 03:25:21 +01:00
|
|
|
if (m_refDTypep && m_refDTypep->clonep()) m_refDTypep = m_refDTypep->clonep();
|
2020-04-15 13:58:34 +02:00
|
|
|
}
|
2020-08-15 17:44:10 +02:00
|
|
|
virtual bool same(const AstNode* samep) const override {
|
2021-11-26 23:55:36 +01:00
|
|
|
const AstNodeArrayDType* const asamep = static_cast<const AstNodeArrayDType*>(samep);
|
2020-12-07 03:13:56 +01:00
|
|
|
return (hi() == asamep->hi() && subDTypep() == asamep->subDTypep()
|
2020-04-15 13:58:34 +02:00
|
|
|
&& rangenp()->sameTree(asamep->rangenp()));
|
|
|
|
|
} // HashedDT doesn't recurse, so need to check children
|
2020-08-15 17:44:10 +02:00
|
|
|
virtual bool similarDType(AstNodeDType* samep) const override {
|
2021-11-26 23:55:36 +01:00
|
|
|
const AstNodeArrayDType* const asamep = static_cast<const AstNodeArrayDType*>(samep);
|
2020-12-07 03:13:56 +01:00
|
|
|
return (asamep && type() == samep->type() && hi() == asamep->hi()
|
2019-05-19 22:13:13 +02:00
|
|
|
&& rangenp()->sameTree(asamep->rangenp())
|
|
|
|
|
&& subDTypep()->skipRefp()->similarDType(asamep->subDTypep()->skipRefp()));
|
2017-04-28 12:10:14 +02:00
|
|
|
}
|
2020-08-15 17:44:10 +02:00
|
|
|
virtual AstNodeDType* getChildDTypep() const override { return childDTypep(); }
|
2021-10-22 14:56:48 +02:00
|
|
|
AstNodeDType* childDTypep() const { return VN_AS(op1p(), NodeDType); }
|
2019-05-19 22:13:13 +02:00
|
|
|
void childDTypep(AstNodeDType* nodep) { setOp1p(nodep); }
|
2020-08-15 17:44:10 +02:00
|
|
|
virtual AstNodeDType* subDTypep() const override {
|
|
|
|
|
return m_refDTypep ? m_refDTypep : childDTypep();
|
|
|
|
|
}
|
2013-01-12 22:19:25 +01:00
|
|
|
void refDTypep(AstNodeDType* nodep) { m_refDTypep = nodep; }
|
2020-08-15 17:44:10 +02:00
|
|
|
virtual AstNodeDType* virtRefDTypep() const override { return m_refDTypep; }
|
|
|
|
|
virtual void virtRefDTypep(AstNodeDType* nodep) override { refDTypep(nodep); }
|
2021-10-22 14:56:48 +02:00
|
|
|
AstRange* rangep() const { return VN_AS(op2p(), Range); } // op2 = Array(s) of variable
|
2019-05-19 22:13:13 +02:00
|
|
|
void rangep(AstRange* nodep);
|
2013-01-12 22:19:25 +01:00
|
|
|
// METHODS
|
2020-08-15 17:44:10 +02:00
|
|
|
virtual AstBasicDType* basicp() const override {
|
2020-04-15 13:58:34 +02:00
|
|
|
return subDTypep()->basicp();
|
|
|
|
|
} // (Slow) recurse down to find basic data type
|
2020-08-15 17:44:10 +02:00
|
|
|
virtual AstNodeDType* skipRefp() const override { return (AstNodeDType*)this; }
|
|
|
|
|
virtual AstNodeDType* skipRefToConstp() const override { return (AstNodeDType*)this; }
|
|
|
|
|
virtual AstNodeDType* skipRefToEnump() const override { return (AstNodeDType*)this; }
|
|
|
|
|
virtual int widthAlignBytes() const override { return subDTypep()->widthAlignBytes(); }
|
|
|
|
|
virtual int widthTotalBytes() const override {
|
2020-04-15 13:58:34 +02:00
|
|
|
return elementsConst() * subDTypep()->widthTotalBytes();
|
|
|
|
|
}
|
2020-12-07 03:13:56 +01:00
|
|
|
int left() const;
|
|
|
|
|
int right() const;
|
|
|
|
|
int hi() const;
|
|
|
|
|
int lo() const;
|
2019-05-19 22:13:13 +02:00
|
|
|
int elementsConst() const;
|
2013-01-18 02:41:45 +01:00
|
|
|
VNumRange declRange() const;
|
2013-01-12 22:19:25 +01:00
|
|
|
};
|
|
|
|
|
|
2020-11-19 03:32:16 +01:00
|
|
|
class AstNodeSel VL_NOT_FINAL : public AstNodeBiop {
|
2006-08-26 13:35:28 +02:00
|
|
|
// Single bit range extraction, perhaps with non-constant selection or array selection
|
2021-05-15 22:10:16 +02:00
|
|
|
protected:
|
2020-01-25 21:29:44 +01:00
|
|
|
AstNodeSel(AstType t, FileLine* fl, AstNode* fromp, AstNode* bitp)
|
2020-08-16 17:40:42 +02:00
|
|
|
: AstNodeBiop{t, fl, fromp, bitp} {}
|
2021-05-15 22:10:16 +02:00
|
|
|
|
|
|
|
|
public:
|
2009-11-02 14:06:04 +01:00
|
|
|
ASTNODE_BASE_FUNCS(NodeSel)
|
2020-08-15 16:12:55 +02:00
|
|
|
AstNode* fromp() const {
|
|
|
|
|
return op1p();
|
|
|
|
|
} // op1 = Extracting what (nullptr=TBD during parsing)
|
2010-01-19 16:52:11 +01:00
|
|
|
void fromp(AstNode* nodep) { setOp1p(nodep); }
|
2019-01-05 11:46:37 +01:00
|
|
|
AstNode* bitp() const { return op2p(); } // op2 = Msb selection expression
|
2010-01-19 16:52:11 +01:00
|
|
|
void bitp(AstNode* nodep) { setOp2p(nodep); }
|
2019-01-05 11:46:37 +01:00
|
|
|
int bitConst() const;
|
2020-08-15 17:44:10 +02:00
|
|
|
virtual bool hasDType() const override { return true; }
|
2006-08-26 13:35:28 +02:00
|
|
|
};
|
|
|
|
|
|
2020-11-19 03:32:16 +01:00
|
|
|
class AstNodeStream VL_NOT_FINAL : public AstNodeBiop {
|
2014-04-10 02:29:35 +02:00
|
|
|
// Verilog {rhs{lhs}} - Note rhsp() is the slice size, not the lhsp()
|
2021-05-15 22:10:16 +02:00
|
|
|
protected:
|
2020-01-25 21:29:44 +01:00
|
|
|
AstNodeStream(AstType t, FileLine* fl, AstNode* lhsp, AstNode* rhsp)
|
2020-08-16 17:40:42 +02:00
|
|
|
: AstNodeBiop{t, fl, lhsp, rhsp} {
|
2021-02-22 03:25:21 +01:00
|
|
|
if (lhsp->dtypep()) dtypeSetLogicSized(lhsp->dtypep()->width(), VSigning::UNSIGNED);
|
2014-04-10 02:29:35 +02:00
|
|
|
}
|
2021-05-15 22:10:16 +02:00
|
|
|
|
|
|
|
|
public:
|
2014-04-10 02:29:35 +02:00
|
|
|
ASTNODE_BASE_FUNCS(NodeStream)
|
|
|
|
|
};
|
|
|
|
|
|
2006-08-26 13:35:28 +02:00
|
|
|
//######################################################################
|
|
|
|
|
// Tasks/functions common handling
|
|
|
|
|
|
2020-11-19 03:32:16 +01:00
|
|
|
class AstNodeCCall VL_NOT_FINAL : public AstNodeStmt {
|
2020-03-07 18:52:11 +01:00
|
|
|
// A call of a C++ function, perhaps a AstCFunc or perhaps globally named
|
|
|
|
|
// Functions are not statements, while tasks are. AstNodeStmt needs isStatement() to deal.
|
|
|
|
|
AstCFunc* m_funcp;
|
|
|
|
|
string m_argTypes;
|
2020-04-15 13:58:34 +02:00
|
|
|
|
2021-05-15 22:10:16 +02:00
|
|
|
protected:
|
2020-08-15 16:12:55 +02:00
|
|
|
AstNodeCCall(AstType t, FileLine* fl, AstCFunc* funcp, AstNode* argsp = nullptr)
|
2020-08-16 17:40:42 +02:00
|
|
|
: AstNodeStmt{t, fl, true}
|
|
|
|
|
, m_funcp{funcp} {
|
2020-03-07 18:52:11 +01:00
|
|
|
addNOp2p(argsp);
|
|
|
|
|
}
|
2021-05-15 22:10:16 +02:00
|
|
|
|
|
|
|
|
public:
|
2020-03-07 18:52:11 +01:00
|
|
|
ASTNODE_BASE_FUNCS(NodeCCall)
|
2020-08-15 17:44:10 +02:00
|
|
|
virtual void dump(std::ostream& str = std::cout) const override;
|
|
|
|
|
virtual void cloneRelink() override;
|
|
|
|
|
virtual const char* broken() const override;
|
2021-07-25 14:32:36 +02:00
|
|
|
virtual int instrCount() const override { return INSTR_COUNT_CALL; }
|
2020-08-15 17:44:10 +02:00
|
|
|
virtual bool same(const AstNode* samep) const override {
|
2021-11-26 23:55:36 +01:00
|
|
|
const AstNodeCCall* const asamep = static_cast<const AstNodeCCall*>(samep);
|
2020-03-07 18:52:11 +01:00
|
|
|
return (funcp() == asamep->funcp() && argTypes() == asamep->argTypes());
|
|
|
|
|
}
|
|
|
|
|
AstNode* exprsp() const { return op2p(); } // op2 = expressions to print
|
2020-08-15 17:44:10 +02:00
|
|
|
virtual bool isGateOptimizable() const override { return false; }
|
|
|
|
|
virtual bool isPredictOptimizable() const override { return false; }
|
|
|
|
|
virtual bool isPure() const override;
|
|
|
|
|
virtual bool isOutputter() const override { return !isPure(); }
|
2020-03-07 18:52:11 +01:00
|
|
|
AstCFunc* funcp() const { return m_funcp; }
|
|
|
|
|
void argTypes(const string& str) { m_argTypes = str; }
|
|
|
|
|
string argTypes() const { return m_argTypes; }
|
|
|
|
|
// op1p reserved for AstCMethodCall
|
|
|
|
|
AstNode* argsp() const { return op2p(); }
|
|
|
|
|
void addArgsp(AstNode* nodep) { addOp2p(nodep); }
|
|
|
|
|
};
|
|
|
|
|
|
2020-11-19 03:32:16 +01:00
|
|
|
class AstNodeFTask VL_NOT_FINAL : public AstNode {
|
2006-08-26 13:35:28 +02:00
|
|
|
private:
|
2020-04-15 13:58:34 +02:00
|
|
|
string m_name; // Name of task
|
|
|
|
|
string m_cname; // Name of task if DPI import
|
2020-08-15 19:11:27 +02:00
|
|
|
uint64_t m_dpiOpenParent = 0; // DPI import open array, if !=0, how many callees
|
2020-04-15 13:58:34 +02:00
|
|
|
bool m_taskPublic : 1; // Public task
|
|
|
|
|
bool m_attrIsolateAssign : 1; // User isolate_assignments attribute
|
|
|
|
|
bool m_classMethod : 1; // Class method
|
2020-08-23 01:46:21 +02:00
|
|
|
bool m_externProto : 1; // Extern prototype
|
|
|
|
|
bool m_externDef : 1; // Extern definition
|
2020-04-15 13:58:34 +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)
|
2021-11-27 23:07:27 +01:00
|
|
|
bool m_dpiTraceInit : 1; // DPI trace_init
|
2020-04-15 13:58:34 +02:00
|
|
|
bool m_isConstructor : 1; // Class constructor
|
2020-11-25 13:03:01 +01:00
|
|
|
bool m_isHideLocal : 1; // Verilog local
|
|
|
|
|
bool m_isHideProtected : 1; // Verilog protected
|
2020-04-15 13:58:34 +02:00
|
|
|
bool m_pure : 1; // DPI import pure (vs. virtual pure)
|
2020-07-02 14:24:35 +02:00
|
|
|
bool m_pureVirtual : 1; // Pure virtual
|
2021-08-21 16:33:20 +02:00
|
|
|
bool m_underGenerate : 1; // Under generate (for warning)
|
2020-07-01 13:31:53 +02:00
|
|
|
bool m_virtual : 1; // Virtual method in class
|
2020-04-26 18:45:06 +02:00
|
|
|
VLifetime m_lifetime; // Lifetime
|
2021-05-15 22:10:16 +02:00
|
|
|
protected:
|
2020-01-25 21:29:44 +01:00
|
|
|
AstNodeFTask(AstType t, FileLine* fl, const string& name, AstNode* stmtsp)
|
2020-08-16 17:40:42 +02:00
|
|
|
: AstNode{t, fl}
|
|
|
|
|
, m_name{name}
|
|
|
|
|
, m_taskPublic{false}
|
|
|
|
|
, m_attrIsolateAssign{false}
|
|
|
|
|
, m_classMethod{false}
|
2020-08-23 01:46:21 +02:00
|
|
|
, m_externProto{false}
|
|
|
|
|
, m_externDef{false}
|
2020-08-16 17:40:42 +02:00
|
|
|
, m_prototype{false}
|
|
|
|
|
, m_dpiExport{false}
|
|
|
|
|
, m_dpiImport{false}
|
|
|
|
|
, m_dpiContext{false}
|
|
|
|
|
, m_dpiOpenChild{false}
|
|
|
|
|
, m_dpiTask{false}
|
2021-11-27 23:07:27 +01:00
|
|
|
, m_dpiTraceInit{false}
|
2020-08-16 17:40:42 +02:00
|
|
|
, m_isConstructor{false}
|
2020-11-25 13:03:01 +01:00
|
|
|
, m_isHideLocal{false}
|
|
|
|
|
, m_isHideProtected{false}
|
2020-08-16 17:40:42 +02:00
|
|
|
, m_pure{false}
|
|
|
|
|
, m_pureVirtual{false}
|
2021-08-21 16:33:20 +02:00
|
|
|
, m_underGenerate{false}
|
2020-08-16 17:40:42 +02:00
|
|
|
, m_virtual{false} {
|
2019-05-19 22:13:13 +02:00
|
|
|
addNOp3p(stmtsp);
|
|
|
|
|
cname(name); // Might be overridden by dpi import/export
|
2006-08-26 13:35:28 +02:00
|
|
|
}
|
2021-05-15 22:10:16 +02:00
|
|
|
|
|
|
|
|
public:
|
2008-11-20 02:15:05 +01:00
|
|
|
ASTNODE_BASE_FUNCS(NodeFTask)
|
2020-08-15 17:44:10 +02:00
|
|
|
virtual void dump(std::ostream& str = std::cout) const override;
|
|
|
|
|
virtual string name() const override { return m_name; } // * = Var name
|
|
|
|
|
virtual bool maybePointedTo() const override { return true; }
|
|
|
|
|
virtual bool isGateOptimizable() const override {
|
|
|
|
|
return !((m_dpiExport || m_dpiImport) && !m_pure);
|
|
|
|
|
}
|
2006-08-26 13:35:28 +02:00
|
|
|
// {AstFunc only} op1 = Range output variable
|
2020-08-15 17:44:10 +02:00
|
|
|
virtual void name(const string& name) override { m_name = name; }
|
2009-12-03 12:55:29 +01:00
|
|
|
string cname() const { return m_cname; }
|
|
|
|
|
void cname(const string& cname) { m_cname = cname; }
|
2020-08-15 16:12:55 +02:00
|
|
|
// op1 = Output variable (functions only, nullptr for tasks)
|
2019-05-19 22:13:13 +02:00
|
|
|
AstNode* fvarp() const { return op1p(); }
|
|
|
|
|
void addFvarp(AstNode* nodep) { addNOp1p(nodep); }
|
2020-08-15 16:12:55 +02:00
|
|
|
bool isFunction() const { return fvarp() != nullptr; }
|
2020-08-22 22:24:29 +02:00
|
|
|
// op2 = Class/package scope
|
2020-11-25 03:56:03 +01:00
|
|
|
AstNode* classOrPackagep() const { return op2p(); }
|
|
|
|
|
void classOrPackagep(AstNode* nodep) { setNOp2p(nodep); }
|
2009-12-03 12:55:29 +01:00
|
|
|
// op3 = Statements/Ports/Vars
|
2019-05-19 22:13:13 +02:00
|
|
|
AstNode* stmtsp() const { return op3p(); } // op3 = List of statements
|
|
|
|
|
void addStmtsp(AstNode* nodep) { addNOp3p(nodep); }
|
2009-12-20 14:27:00 +01:00
|
|
|
// op4 = scope name
|
2021-10-22 14:56:48 +02:00
|
|
|
AstScopeName* scopeNamep() const { return VN_AS(op4p(), ScopeName); }
|
2017-12-17 22:28:58 +01:00
|
|
|
// MORE ACCESSORS
|
|
|
|
|
void dpiOpenParentInc() { ++m_dpiOpenParent; }
|
2019-05-19 22:13:13 +02:00
|
|
|
void dpiOpenParentClear() { m_dpiOpenParent = 0; }
|
2017-12-17 22:28:58 +01:00
|
|
|
uint64_t dpiOpenParent() const { return m_dpiOpenParent; }
|
|
|
|
|
void scopeNamep(AstNode* nodep) { setNOp4p(nodep); }
|
2019-05-19 22:13:13 +02:00
|
|
|
void taskPublic(bool flag) { m_taskPublic = flag; }
|
2017-12-17 22:28:58 +01:00
|
|
|
bool taskPublic() const { return m_taskPublic; }
|
|
|
|
|
void attrIsolateAssign(bool flag) { m_attrIsolateAssign = flag; }
|
|
|
|
|
bool attrIsolateAssign() const { return m_attrIsolateAssign; }
|
2020-04-05 15:30:23 +02:00
|
|
|
void classMethod(bool flag) { m_classMethod = flag; }
|
|
|
|
|
bool classMethod() const { return m_classMethod; }
|
2020-08-23 01:46:21 +02:00
|
|
|
void isExternProto(bool flag) { m_externProto = flag; }
|
|
|
|
|
bool isExternProto() const { return m_externProto; }
|
|
|
|
|
void isExternDef(bool flag) { m_externDef = flag; }
|
|
|
|
|
bool isExternDef() const { return m_externDef; }
|
2017-12-17 22:28:58 +01:00
|
|
|
void prototype(bool flag) { m_prototype = flag; }
|
|
|
|
|
bool prototype() const { return m_prototype; }
|
|
|
|
|
void dpiExport(bool flag) { m_dpiExport = flag; }
|
|
|
|
|
bool dpiExport() const { return m_dpiExport; }
|
|
|
|
|
void dpiImport(bool flag) { m_dpiImport = flag; }
|
|
|
|
|
bool dpiImport() const { return m_dpiImport; }
|
|
|
|
|
void dpiContext(bool flag) { m_dpiContext = flag; }
|
|
|
|
|
bool dpiContext() const { return m_dpiContext; }
|
|
|
|
|
void dpiOpenChild(bool flag) { m_dpiOpenChild = flag; }
|
|
|
|
|
bool dpiOpenChild() const { return m_dpiOpenChild; }
|
|
|
|
|
void dpiTask(bool flag) { m_dpiTask = flag; }
|
|
|
|
|
bool dpiTask() const { return m_dpiTask; }
|
2021-11-27 23:07:27 +01:00
|
|
|
void dpiTraceInit(bool flag) { m_dpiTraceInit = flag; }
|
|
|
|
|
bool dpiTraceInit() const { return m_dpiTraceInit; }
|
2020-04-05 15:30:23 +02:00
|
|
|
void isConstructor(bool flag) { m_isConstructor = flag; }
|
|
|
|
|
bool isConstructor() const { return m_isConstructor; }
|
2020-11-25 13:03:01 +01: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; }
|
2017-12-17 22:28:58 +01:00
|
|
|
void pure(bool flag) { m_pure = flag; }
|
|
|
|
|
bool pure() const { return m_pure; }
|
2020-07-02 14:24:35 +02:00
|
|
|
void pureVirtual(bool flag) { m_pureVirtual = flag; }
|
|
|
|
|
bool pureVirtual() const { return m_pureVirtual; }
|
2021-08-21 16:33:20 +02:00
|
|
|
void underGenerate(bool flag) { m_underGenerate = flag; }
|
|
|
|
|
bool underGenerate() const { return m_underGenerate; }
|
2020-07-01 13:31:53 +02:00
|
|
|
void isVirtual(bool flag) { m_virtual = flag; }
|
|
|
|
|
bool isVirtual() const { return m_virtual; }
|
2020-04-26 18:45:06 +02:00
|
|
|
void lifetime(const VLifetime& flag) { m_lifetime = flag; }
|
|
|
|
|
VLifetime lifetime() const { return m_lifetime; }
|
2006-08-26 13:35:28 +02:00
|
|
|
};
|
|
|
|
|
|
2020-11-19 03:32:16 +01:00
|
|
|
class AstNodeFTaskRef VL_NOT_FINAL : public AstNodeStmt {
|
2006-08-26 13:35:28 +02:00
|
|
|
// A reference to a task (or function)
|
2019-01-06 23:38:27 +01:00
|
|
|
// Functions are not statements, while tasks are. AstNodeStmt needs isStatement() to deal.
|
2006-08-26 13:35:28 +02:00
|
|
|
private:
|
2020-08-15 19:11:27 +02:00
|
|
|
AstNodeFTask* m_taskp = nullptr; // [AfterLink] Pointer to task referenced
|
2020-11-25 03:56:03 +01:00
|
|
|
AstNodeModule* m_classOrPackagep = nullptr; // Package hierarchy
|
2020-04-15 13:58:34 +02:00
|
|
|
string m_name; // Name of variable
|
|
|
|
|
string m_dotted; // Dotted part of scope the name()ed task/func is under or ""
|
|
|
|
|
string m_inlinedDots; // Dotted hierarchy flattened out
|
2020-08-15 19:11:27 +02:00
|
|
|
bool m_pli = false; // Pli system call ($name)
|
2021-05-15 22:10:16 +02:00
|
|
|
protected:
|
2020-01-25 21:29:44 +01:00
|
|
|
AstNodeFTaskRef(AstType t, FileLine* fl, bool statement, AstNode* namep, AstNode* pinsp)
|
2020-08-16 17:40:42 +02:00
|
|
|
: AstNodeStmt{t, fl, statement} {
|
2020-04-15 13:58:34 +02:00
|
|
|
setOp1p(namep);
|
|
|
|
|
addNOp3p(pinsp);
|
2006-08-26 13:35:28 +02:00
|
|
|
}
|
2020-01-25 21:29:44 +01:00
|
|
|
AstNodeFTaskRef(AstType t, FileLine* fl, bool statement, const string& name, AstNode* pinsp)
|
2020-08-16 17:40:42 +02:00
|
|
|
: AstNodeStmt{t, fl, statement}
|
|
|
|
|
, m_name{name} {
|
2020-03-07 18:52:11 +01:00
|
|
|
addNOp3p(pinsp);
|
2009-12-04 13:05:44 +01:00
|
|
|
}
|
2021-05-15 22:10:16 +02:00
|
|
|
|
|
|
|
|
public:
|
2008-11-20 02:15:05 +01:00
|
|
|
ASTNODE_BASE_FUNCS(NodeFTaskRef)
|
2020-08-22 16:22:56 +02:00
|
|
|
virtual const char* broken() const override;
|
2021-12-13 00:10:52 +01:00
|
|
|
virtual void cloneRelink() override;
|
2020-08-15 17:44:10 +02:00
|
|
|
virtual void dump(std::ostream& str = std::cout) const override;
|
|
|
|
|
virtual string name() const override { return m_name; } // * = Var name
|
|
|
|
|
virtual bool isGateOptimizable() const override {
|
|
|
|
|
return m_taskp && m_taskp->isGateOptimizable();
|
|
|
|
|
}
|
2019-05-19 22:13:13 +02:00
|
|
|
string dotted() const { return m_dotted; } // * = Scope name or ""
|
|
|
|
|
string inlinedDots() const { return m_inlinedDots; }
|
|
|
|
|
void inlinedDots(const string& flag) { m_inlinedDots = flag; }
|
|
|
|
|
AstNodeFTask* taskp() const { return m_taskp; } // [After Link] Pointer to variable
|
|
|
|
|
void taskp(AstNodeFTask* taskp) { m_taskp = taskp; }
|
2020-08-15 17:44:10 +02:00
|
|
|
virtual void name(const string& name) override { m_name = name; }
|
2019-05-19 22:13:13 +02:00
|
|
|
void dotted(const string& name) { m_dotted = name; }
|
2020-11-25 03:56:03 +01:00
|
|
|
AstNodeModule* classOrPackagep() const { return m_classOrPackagep; }
|
|
|
|
|
void classOrPackagep(AstNodeModule* nodep) { m_classOrPackagep = nodep; }
|
2020-05-23 17:55:34 +02:00
|
|
|
bool pli() const { return m_pli; }
|
|
|
|
|
void pli(bool flag) { m_pli = flag; }
|
2006-12-21 22:53:51 +01:00
|
|
|
// op1 = namep
|
2019-05-19 22:13:13 +02:00
|
|
|
AstNode* namep() const { return op1p(); }
|
2020-03-07 18:52:11 +01:00
|
|
|
// op2 = reserved for AstMethodCall
|
|
|
|
|
// op3 = Pin interconnection list
|
|
|
|
|
AstNode* pinsp() const { return op3p(); }
|
|
|
|
|
void addPinsp(AstNode* nodep) { addOp3p(nodep); }
|
|
|
|
|
// op4 = scope tracking
|
2021-10-22 14:56:48 +02:00
|
|
|
AstScopeName* scopeNamep() const { return VN_AS(op4p(), ScopeName); }
|
2020-03-07 18:52:11 +01:00
|
|
|
void scopeNamep(AstNode* nodep) { setNOp4p(nodep); }
|
2006-08-26 13:35:28 +02:00
|
|
|
};
|
|
|
|
|
|
2020-11-19 03:32:16 +01:00
|
|
|
class AstNodeModule VL_NOT_FINAL : public AstNode {
|
2009-11-07 12:20:20 +01:00
|
|
|
// A module, package, program or interface declaration;
|
|
|
|
|
// something that can live directly under the TOP,
|
|
|
|
|
// excluding $unit package stuff
|
|
|
|
|
private:
|
2020-04-15 13:58:34 +02:00
|
|
|
string m_name; // Name of the module
|
2021-11-26 23:55:36 +01:00
|
|
|
const string m_origName; // Name of the module, ignoring name() changes, for dot lookup
|
2020-04-15 13:58:34 +02:00
|
|
|
string m_hierName; // Hierarchical name for errors, etc.
|
|
|
|
|
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
|
2020-08-15 15:43:53 +02:00
|
|
|
bool m_hierBlock : 1; // Hiearchical Block marked by HIER_BLOCK pragma
|
2020-04-15 13:58:34 +02:00
|
|
|
bool m_internal : 1; // Internally created
|
|
|
|
|
bool m_recursive : 1; // Recursive module
|
2020-08-15 16:12:55 +02:00
|
|
|
bool m_recursiveClone : 1; // If recursive, what module it clones, otherwise nullptr
|
2020-08-15 19:11:27 +02:00
|
|
|
int m_level = 0; // 1=top module, 2=cell off top module, ...
|
2020-04-26 18:45:06 +02:00
|
|
|
VLifetime m_lifetime; // Lifetime
|
2020-04-16 01:39:03 +02:00
|
|
|
VTimescale m_timeunit; // Global time unit
|
2020-04-10 05:26:03 +02:00
|
|
|
VOptionBool m_unconnectedDrive; // State of `unconnected_drive
|
2021-05-15 22:10:16 +02:00
|
|
|
protected:
|
2020-01-25 21:29:44 +01:00
|
|
|
AstNodeModule(AstType t, FileLine* fl, const string& name)
|
2020-08-16 17:40:42 +02:00
|
|
|
: AstNode{t, fl}
|
|
|
|
|
, m_name{name}
|
|
|
|
|
, m_origName{name}
|
|
|
|
|
, m_modPublic{false}
|
|
|
|
|
, m_modTrace{false}
|
|
|
|
|
, m_inLibrary{false}
|
|
|
|
|
, m_dead{false}
|
|
|
|
|
, m_hierBlock{false}
|
|
|
|
|
, m_internal{false}
|
|
|
|
|
, m_recursive{false}
|
|
|
|
|
, m_recursiveClone{false} {}
|
2021-05-15 22:10:16 +02:00
|
|
|
|
|
|
|
|
public:
|
2009-11-07 12:20:20 +01:00
|
|
|
ASTNODE_BASE_FUNCS(NodeModule)
|
2020-08-15 17:44:10 +02:00
|
|
|
virtual void dump(std::ostream& str) const override;
|
|
|
|
|
virtual bool maybePointedTo() const override { return true; }
|
|
|
|
|
virtual string name() const override { return m_name; }
|
2021-03-17 03:52:29 +01:00
|
|
|
virtual bool timescaleMatters() const = 0;
|
2019-05-19 22:13:13 +02:00
|
|
|
AstNode* stmtsp() const { return op2p(); } // op2 = List of statements
|
2021-10-22 14:56:48 +02:00
|
|
|
AstActive* activesp() const { return VN_AS(op3p(), Active); } // op3 = List of i/sblocks
|
2009-11-07 12:20:20 +01:00
|
|
|
// METHODS
|
|
|
|
|
void addInlinesp(AstNode* nodep) { addOp1p(nodep); }
|
2020-01-20 19:27:27 +01:00
|
|
|
void addStmtp(AstNode* nodep) { addNOp2p(nodep); }
|
2009-11-07 12:20:20 +01:00
|
|
|
void addActivep(AstNode* nodep) { addOp3p(nodep); }
|
|
|
|
|
// ACCESSORS
|
2020-08-15 17:44:10 +02:00
|
|
|
virtual void name(const string& name) override { m_name = name; }
|
|
|
|
|
virtual string origName() const override { return m_origName; }
|
2020-04-15 13:58:34 +02:00
|
|
|
string hierName() const { return m_hierName; }
|
2019-07-26 18:52:38 +02:00
|
|
|
void hierName(const string& hierName) { m_hierName = hierName; }
|
2019-05-19 22:13:13 +02:00
|
|
|
bool inLibrary() const { return m_inLibrary; }
|
|
|
|
|
void inLibrary(bool flag) { m_inLibrary = flag; }
|
|
|
|
|
void level(int level) { m_level = level; }
|
|
|
|
|
int level() const { return m_level; }
|
2020-04-15 13:58:34 +02:00
|
|
|
bool isTop() const { return level() == 1; }
|
2019-05-19 22:13:13 +02:00
|
|
|
void modPublic(bool flag) { m_modPublic = flag; }
|
|
|
|
|
bool modPublic() const { return m_modPublic; }
|
|
|
|
|
void modTrace(bool flag) { m_modTrace = flag; }
|
|
|
|
|
bool modTrace() const { return m_modTrace; }
|
|
|
|
|
void dead(bool flag) { m_dead = flag; }
|
|
|
|
|
bool dead() const { return m_dead; }
|
2020-08-15 15:43:53 +02:00
|
|
|
void hierBlock(bool flag) { m_hierBlock = flag; }
|
|
|
|
|
bool hierBlock() const { return m_hierBlock; }
|
2019-05-19 22:13:13 +02:00
|
|
|
void internal(bool flag) { m_internal = flag; }
|
|
|
|
|
bool internal() const { return m_internal; }
|
2017-11-18 23:42:35 +01:00
|
|
|
void recursive(bool flag) { m_recursive = flag; }
|
|
|
|
|
bool recursive() const { return m_recursive; }
|
|
|
|
|
void recursiveClone(bool flag) { m_recursiveClone = flag; }
|
|
|
|
|
bool recursiveClone() const { return m_recursiveClone; }
|
2020-04-26 18:45:06 +02:00
|
|
|
void lifetime(const VLifetime& flag) { m_lifetime = flag; }
|
|
|
|
|
VLifetime lifetime() const { return m_lifetime; }
|
2020-04-16 01:39:03 +02:00
|
|
|
void timeunit(const VTimescale& flag) { m_timeunit = flag; }
|
|
|
|
|
VTimescale timeunit() const { return m_timeunit; }
|
2020-04-10 05:26:03 +02:00
|
|
|
void unconnectedDrive(const VOptionBool flag) { m_unconnectedDrive = flag; }
|
|
|
|
|
VOptionBool unconnectedDrive() const { return m_unconnectedDrive; }
|
2009-11-07 12:20:20 +01:00
|
|
|
};
|
|
|
|
|
|
2020-11-19 03:32:16 +01:00
|
|
|
class AstNodeRange VL_NOT_FINAL : public AstNode {
|
2017-12-17 22:28:58 +01:00
|
|
|
// A range, sized or unsized
|
2021-05-15 22:10:16 +02:00
|
|
|
protected:
|
2020-01-25 21:29:44 +01:00
|
|
|
AstNodeRange(AstType t, FileLine* fl)
|
2020-08-16 17:40:42 +02:00
|
|
|
: AstNode{t, fl} {}
|
2021-05-15 22:10:16 +02:00
|
|
|
|
|
|
|
|
public:
|
2017-12-17 22:28:58 +01:00
|
|
|
ASTNODE_BASE_FUNCS(NodeRange)
|
2020-09-17 03:52:24 +02:00
|
|
|
virtual void dump(std::ostream& str) const override;
|
2017-12-17 22:28:58 +01:00
|
|
|
};
|
|
|
|
|
|
2018-05-11 02:55:37 +02:00
|
|
|
//######################################################################
|
|
|
|
|
// Inline AstNVisitor METHODS
|
|
|
|
|
|
2020-04-15 13:58:34 +02:00
|
|
|
inline void AstNVisitor::iterate(AstNode* nodep) { nodep->accept(*this); }
|
2021-05-21 15:34:27 +02:00
|
|
|
inline void AstNVisitor::iterateNull(AstNode* nodep) {
|
|
|
|
|
if (VL_LIKELY(nodep)) nodep->accept(*this);
|
|
|
|
|
}
|
2020-04-15 13:58:34 +02:00
|
|
|
inline void AstNVisitor::iterateChildren(AstNode* nodep) { nodep->iterateChildren(*this); }
|
2018-05-11 02:55:37 +02:00
|
|
|
inline void AstNVisitor::iterateChildrenBackwards(AstNode* nodep) {
|
|
|
|
|
nodep->iterateChildrenBackwards(*this);
|
|
|
|
|
}
|
|
|
|
|
inline void AstNVisitor::iterateChildrenConst(AstNode* nodep) {
|
|
|
|
|
nodep->iterateChildrenConst(*this);
|
|
|
|
|
}
|
|
|
|
|
inline void AstNVisitor::iterateAndNextNull(AstNode* nodep) {
|
|
|
|
|
if (VL_LIKELY(nodep)) nodep->iterateAndNext(*this);
|
|
|
|
|
}
|
|
|
|
|
inline void AstNVisitor::iterateAndNextConstNull(AstNode* nodep) {
|
|
|
|
|
if (VL_LIKELY(nodep)) nodep->iterateAndNextConst(*this);
|
|
|
|
|
}
|
|
|
|
|
inline AstNode* AstNVisitor::iterateSubtreeReturnEdits(AstNode* nodep) {
|
|
|
|
|
return nodep->iterateSubtreeReturnEdits(*this);
|
|
|
|
|
}
|
|
|
|
|
|
2006-08-26 13:35:28 +02:00
|
|
|
//######################################################################
|
|
|
|
|
|
2021-06-05 18:40:56 +02:00
|
|
|
#include "V3AstNodes.h"
|
2013-05-28 03:39:19 +02:00
|
|
|
|
2019-05-19 22:13:13 +02:00
|
|
|
#endif // Guard
|