2012-04-13 01:08:20 +00:00
|
|
|
|
// -*- mode: C++; c-file-style: "cc-mode" -*-
|
2006-08-26 11:35:28 +00:00
|
|
|
|
//*************************************************************************
|
|
|
|
|
// DESCRIPTION: Verilator: Ast node structure
|
|
|
|
|
//
|
2008-04-25 12:14:27 +00:00
|
|
|
|
// Code available from: http://www.veripool.org/verilator
|
2006-08-26 11:35:28 +00:00
|
|
|
|
//
|
|
|
|
|
//*************************************************************************
|
|
|
|
|
//
|
2016-01-07 01:36:41 +00:00
|
|
|
|
// Copyright 2003-2016 by Wilson Snyder. This program is free software; you can
|
2006-08-26 11:35:28 +00:00
|
|
|
|
// redistribute it and/or modify it under the terms of either the GNU
|
2009-05-04 21:07:57 +00:00
|
|
|
|
// Lesser General Public License Version 3 or the Perl Artistic License
|
|
|
|
|
// Version 2.0.
|
2006-08-26 11:35:28 +00:00
|
|
|
|
//
|
|
|
|
|
// Verilator is distributed in the hope that it will be useful,
|
|
|
|
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
|
|
// GNU General Public License for more details.
|
|
|
|
|
//
|
|
|
|
|
//*************************************************************************
|
|
|
|
|
|
|
|
|
|
#ifndef _V3AST_H_
|
|
|
|
|
#define _V3AST_H_ 1
|
2006-12-18 19:20:45 +00:00
|
|
|
|
#include "config_build.h"
|
|
|
|
|
#include "verilatedos.h"
|
2006-08-26 11:35:28 +00:00
|
|
|
|
#include "V3Error.h"
|
2014-11-22 16:48:39 +00:00
|
|
|
|
#include "V3FileLine.h"
|
2006-08-26 11:35:28 +00:00
|
|
|
|
#include "V3Number.h"
|
2011-11-30 03:09:50 +00:00
|
|
|
|
#include "V3Global.h"
|
2006-08-26 11:35:28 +00:00
|
|
|
|
#include <vector>
|
2011-09-29 01:35:16 +00:00
|
|
|
|
#include <cmath>
|
2012-02-20 14:55:20 +00:00
|
|
|
|
#include <map>
|
2006-08-26 11:35:28 +00:00
|
|
|
|
|
|
|
|
|
#include "V3Ast__gen_classes.h" // From ./astgen
|
|
|
|
|
// Things like:
|
|
|
|
|
// class V3AstNode;
|
|
|
|
|
|
2009-11-05 03:31:53 +00:00
|
|
|
|
// Hint class so we can choose constructors
|
2012-03-31 15:10:34 +00:00
|
|
|
|
class VFlagLogicPacked {};
|
|
|
|
|
class VFlagBitPacked {};
|
2012-03-31 15:22:19 +00:00
|
|
|
|
class VFlagChildDType {}; // Used by parser.y to select constructor that sets childDType
|
2009-11-05 03:31:53 +00:00
|
|
|
|
|
2013-05-25 21:05:22 +00:00
|
|
|
|
// For broken() function, return error string if have a match
|
|
|
|
|
#define BROKEN_RTN(test) do { if (VL_UNLIKELY(test)) return # test; } while(0)
|
|
|
|
|
|
2006-08-26 11:35:28 +00:00
|
|
|
|
//######################################################################
|
2016-11-05 13:47:56 +00:00
|
|
|
|
|
2006-08-26 11:35:28 +00:00
|
|
|
|
class AstType {
|
|
|
|
|
public:
|
|
|
|
|
#include "V3Ast__gen_types.h" // From ./astgen
|
|
|
|
|
// Above include has:
|
|
|
|
|
// enum en {...};
|
|
|
|
|
// const char* ascii() const {...};
|
|
|
|
|
enum en m_e;
|
2013-02-03 18:27:37 +00:00
|
|
|
|
// cppcheck-suppress uninitVar // responsiblity of each subclass
|
2009-07-22 18:38:20 +00:00
|
|
|
|
inline AstType () {}
|
2015-10-04 02:33:06 +00:00
|
|
|
|
// cppcheck-suppress noExplicitConstructor
|
2009-07-22 18:38:20 +00:00
|
|
|
|
inline AstType (en _e) : m_e(_e) {}
|
|
|
|
|
explicit inline AstType (int _e) : m_e(static_cast<en>(_e)) {}
|
|
|
|
|
operator en () const { return m_e; }
|
2006-08-26 11:35:28 +00:00
|
|
|
|
};
|
|
|
|
|
inline bool operator== (AstType lhs, AstType rhs) { return (lhs.m_e == rhs.m_e); }
|
|
|
|
|
inline bool operator== (AstType lhs, AstType::en rhs) { return (lhs.m_e == rhs); }
|
|
|
|
|
inline bool operator== (AstType::en lhs, AstType rhs) { return (lhs == rhs.m_e); }
|
|
|
|
|
inline ostream& operator<<(ostream& os, AstType rhs) { return os<<rhs.ascii(); }
|
|
|
|
|
|
|
|
|
|
//######################################################################
|
|
|
|
|
|
2012-04-29 12:30:02 +00:00
|
|
|
|
enum VSignedState {
|
|
|
|
|
// This can't be in the fancy class as the lexer union will get upset
|
2012-04-29 14:14:13 +00:00
|
|
|
|
signedst_UNSIGNED=0, signedst_SIGNED=1, signedst_NOSIGN=2
|
2012-04-29 12:30:02 +00:00
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
//######################################################################
|
|
|
|
|
|
2011-07-23 23:58:34 +00:00
|
|
|
|
class AstNumeric {
|
|
|
|
|
public:
|
|
|
|
|
enum en {
|
|
|
|
|
UNSIGNED,
|
|
|
|
|
SIGNED,
|
2012-04-29 14:14:13 +00:00
|
|
|
|
NOSIGN,
|
2012-04-29 12:30:02 +00:00
|
|
|
|
_ENUM_MAX // Leave last
|
2011-07-23 23:58:34 +00:00
|
|
|
|
};
|
|
|
|
|
enum en m_e;
|
|
|
|
|
const char* ascii() const {
|
|
|
|
|
static const char* names[] = {
|
2012-04-29 14:14:13 +00:00
|
|
|
|
"UNSIGNED","SIGNED","NOSIGN"
|
2011-07-23 23:58:34 +00:00
|
|
|
|
};
|
|
|
|
|
return names[m_e];
|
|
|
|
|
};
|
2011-08-05 01:58:45 +00:00
|
|
|
|
inline AstNumeric () : m_e(UNSIGNED) {}
|
2015-10-04 02:33:06 +00:00
|
|
|
|
// cppcheck-suppress noExplicitConstructor
|
2011-07-23 23:58:34 +00:00
|
|
|
|
inline AstNumeric (en _e) : m_e(_e) {}
|
2015-10-04 02:33:06 +00:00
|
|
|
|
// cppcheck-suppress noExplicitConstructor
|
2012-04-29 14:14:13 +00:00
|
|
|
|
inline AstNumeric (VSignedState signst) {
|
|
|
|
|
if (signst==signedst_UNSIGNED) m_e=UNSIGNED;
|
|
|
|
|
else if (signst==signedst_SIGNED) m_e=SIGNED;
|
|
|
|
|
else m_e=NOSIGN;
|
|
|
|
|
}
|
2014-04-05 19:52:05 +00:00
|
|
|
|
static inline AstNumeric fromBool (bool isSigned) { // Factory method
|
|
|
|
|
return isSigned ? AstNumeric(SIGNED) : AstNumeric(UNSIGNED); }
|
2011-07-23 23:58:34 +00:00
|
|
|
|
explicit inline AstNumeric (int _e) : m_e(static_cast<en>(_e)) {}
|
|
|
|
|
operator en () const { return m_e; }
|
|
|
|
|
inline bool isSigned() const { return m_e==SIGNED; }
|
2012-04-29 14:14:13 +00:00
|
|
|
|
inline bool isNosign() const { return m_e==NOSIGN; }
|
|
|
|
|
// No isUnsigned() as it's ambiguous if NOSIGN should be included or not.
|
2011-07-23 23:58:34 +00:00
|
|
|
|
};
|
|
|
|
|
inline bool operator== (AstNumeric lhs, AstNumeric rhs) { return (lhs.m_e == rhs.m_e); }
|
|
|
|
|
inline bool operator== (AstNumeric lhs, AstNumeric::en rhs) { return (lhs.m_e == rhs); }
|
|
|
|
|
inline bool operator== (AstNumeric::en lhs, AstNumeric rhs) { return (lhs == rhs.m_e); }
|
|
|
|
|
inline ostream& operator<<(ostream& os, AstNumeric rhs) { return os<<rhs.ascii(); }
|
|
|
|
|
|
|
|
|
|
//######################################################################
|
|
|
|
|
|
2006-08-26 11:35:28 +00:00
|
|
|
|
class AstPragmaType {
|
|
|
|
|
public:
|
|
|
|
|
enum en {
|
2011-08-05 01:58:45 +00:00
|
|
|
|
ILLEGAL,
|
2006-08-26 11:35:28 +00:00
|
|
|
|
COVERAGE_BLOCK_OFF,
|
|
|
|
|
INLINE_MODULE,
|
|
|
|
|
NO_INLINE_MODULE,
|
2006-10-11 15:41:42 +00:00
|
|
|
|
NO_INLINE_TASK,
|
2006-08-26 11:35:28 +00:00
|
|
|
|
PUBLIC_MODULE,
|
|
|
|
|
PUBLIC_TASK
|
|
|
|
|
};
|
|
|
|
|
enum en m_e;
|
2011-08-05 01:58:45 +00:00
|
|
|
|
inline AstPragmaType () : m_e(ILLEGAL) {}
|
2015-10-04 02:33:06 +00:00
|
|
|
|
// cppcheck-suppress noExplicitConstructor
|
2009-07-22 18:38:20 +00:00
|
|
|
|
inline AstPragmaType (en _e) : m_e(_e) {}
|
|
|
|
|
explicit inline AstPragmaType (int _e) : m_e(static_cast<en>(_e)) {}
|
|
|
|
|
operator en () const { return m_e; }
|
2006-08-26 11:35:28 +00:00
|
|
|
|
};
|
|
|
|
|
inline bool operator== (AstPragmaType lhs, AstPragmaType rhs) { return (lhs.m_e == rhs.m_e); }
|
|
|
|
|
inline bool operator== (AstPragmaType lhs, AstPragmaType::en rhs) { return (lhs.m_e == rhs); }
|
|
|
|
|
inline bool operator== (AstPragmaType::en lhs, AstPragmaType rhs) { return (lhs == rhs.m_e); }
|
|
|
|
|
|
|
|
|
|
//######################################################################
|
|
|
|
|
|
|
|
|
|
class AstCFuncType {
|
|
|
|
|
public:
|
|
|
|
|
enum en {
|
2010-02-02 01:15:48 +00:00
|
|
|
|
FT_NORMAL,
|
2006-08-26 11:35:28 +00:00
|
|
|
|
TRACE_INIT,
|
2008-11-17 22:13:57 +00:00
|
|
|
|
TRACE_INIT_SUB,
|
2006-08-26 11:35:28 +00:00
|
|
|
|
TRACE_FULL,
|
2008-11-17 22:13:57 +00:00
|
|
|
|
TRACE_FULL_SUB,
|
|
|
|
|
TRACE_CHANGE,
|
|
|
|
|
TRACE_CHANGE_SUB
|
2006-08-26 11:35:28 +00:00
|
|
|
|
};
|
|
|
|
|
enum en m_e;
|
2011-08-05 01:58:45 +00:00
|
|
|
|
inline AstCFuncType () : m_e(FT_NORMAL) {}
|
2015-10-04 02:33:06 +00:00
|
|
|
|
// cppcheck-suppress noExplicitConstructor
|
2009-07-22 18:38:20 +00:00
|
|
|
|
inline AstCFuncType (en _e) : m_e(_e) {}
|
|
|
|
|
explicit inline AstCFuncType (int _e) : m_e(static_cast<en>(_e)) {}
|
|
|
|
|
operator en () const { return m_e; }
|
2008-11-17 22:13:57 +00:00
|
|
|
|
// METHODS
|
|
|
|
|
bool isTrace() const { return (m_e==TRACE_INIT || m_e==TRACE_INIT_SUB
|
|
|
|
|
|| m_e==TRACE_FULL || m_e==TRACE_FULL_SUB
|
|
|
|
|
|| m_e==TRACE_CHANGE || m_e==TRACE_CHANGE_SUB); }
|
2006-08-26 11:35:28 +00:00
|
|
|
|
};
|
|
|
|
|
inline bool operator== (AstCFuncType lhs, AstCFuncType rhs) { return (lhs.m_e == rhs.m_e); }
|
|
|
|
|
inline bool operator== (AstCFuncType lhs, AstCFuncType::en rhs) { return (lhs.m_e == rhs); }
|
|
|
|
|
inline bool operator== (AstCFuncType::en lhs, AstCFuncType rhs) { return (lhs == rhs.m_e); }
|
|
|
|
|
|
|
|
|
|
//######################################################################
|
|
|
|
|
|
|
|
|
|
class AstEdgeType {
|
|
|
|
|
public:
|
|
|
|
|
// REMEMBER to edit the strings below too
|
|
|
|
|
enum en {
|
2009-01-07 14:37:59 +00:00
|
|
|
|
// These must be in general -> most specific order, as we sort by it in V3Const::visit AstSenTre
|
2010-02-02 01:15:48 +00:00
|
|
|
|
ET_ILLEGAL,
|
2006-08-26 11:35:28 +00:00
|
|
|
|
// Involving a variable
|
2010-02-02 01:15:48 +00:00
|
|
|
|
ET_ANYEDGE, // Default for sensitivities; rip them out
|
|
|
|
|
ET_BOTHEDGE, // POSEDGE | NEGEDGE
|
|
|
|
|
ET_POSEDGE,
|
|
|
|
|
ET_NEGEDGE,
|
|
|
|
|
ET_HIGHEDGE, // Is high now (latches)
|
|
|
|
|
ET_LOWEDGE, // Is low now (latches)
|
2006-08-26 11:35:28 +00:00
|
|
|
|
// Not involving anything
|
2010-02-02 01:15:48 +00: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 11:35:28 +00:00
|
|
|
|
};
|
|
|
|
|
enum en m_e;
|
|
|
|
|
bool clockedStmt() const {
|
|
|
|
|
static const bool clocked[] = {
|
|
|
|
|
false, false, true, true, true, true, true,
|
|
|
|
|
false, false, false
|
|
|
|
|
};
|
|
|
|
|
return clocked[m_e];
|
|
|
|
|
}
|
|
|
|
|
AstEdgeType invert() const {
|
|
|
|
|
switch (m_e) {
|
2010-02-02 01:15:48 +00: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;
|
2006-08-26 11:35:28 +00:00
|
|
|
|
default: UASSERT_STATIC(0,"Inverting bad edgeType()");
|
|
|
|
|
};
|
2010-02-02 01:15:48 +00:00
|
|
|
|
return AstEdgeType::ET_ILLEGAL;
|
2006-08-26 11:35:28 +00:00
|
|
|
|
}
|
|
|
|
|
const char* ascii() const {
|
|
|
|
|
static const char* names[] = {
|
|
|
|
|
"%E-edge", "ANY", "BOTH", "POS", "NEG", "HIGH", "LOW",
|
|
|
|
|
"COMBO","INITIAL","SETTLE","NEVER"
|
|
|
|
|
};
|
|
|
|
|
return names[m_e];
|
|
|
|
|
};
|
|
|
|
|
const char* verilogKwd() const {
|
|
|
|
|
static const char* names[] = {
|
2009-12-29 00:49:40 +00:00
|
|
|
|
"%E-edge", "[any]", "edge", "posedge", "negedge", "[high]","[low]",
|
2008-11-20 12:55:54 +00:00
|
|
|
|
"*","[initial]","[settle]","[never]"
|
2006-08-26 11:35:28 +00:00
|
|
|
|
};
|
|
|
|
|
return names[m_e];
|
|
|
|
|
};
|
2011-08-05 01:58:45 +00:00
|
|
|
|
inline AstEdgeType () : m_e(ET_ILLEGAL) {}
|
2015-10-04 02:33:06 +00:00
|
|
|
|
// cppcheck-suppress noExplicitConstructor
|
2009-07-22 18:38:20 +00:00
|
|
|
|
inline AstEdgeType (en _e) : m_e(_e) {}
|
|
|
|
|
explicit inline AstEdgeType (int _e) : m_e(static_cast<en>(_e)) {}
|
|
|
|
|
operator en () const { return m_e; }
|
2006-08-26 11:35:28 +00:00
|
|
|
|
};
|
|
|
|
|
inline bool operator== (AstEdgeType lhs, AstEdgeType rhs) { return (lhs.m_e == rhs.m_e); }
|
|
|
|
|
inline bool operator== (AstEdgeType lhs, AstEdgeType::en rhs) { return (lhs.m_e == rhs); }
|
|
|
|
|
inline bool operator== (AstEdgeType::en lhs, AstEdgeType rhs) { return (lhs == rhs.m_e); }
|
|
|
|
|
|
|
|
|
|
//######################################################################
|
|
|
|
|
|
|
|
|
|
class AstAttrType {
|
|
|
|
|
public:
|
|
|
|
|
enum en {
|
2011-08-05 01:58:45 +00:00
|
|
|
|
ILLEGAL,
|
2013-01-20 17:19:22 +00:00
|
|
|
|
//
|
|
|
|
|
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
|
2009-05-07 22:28:05 +00:00
|
|
|
|
//
|
2014-11-07 12:50:11 +00:00
|
|
|
|
DT_PUBLIC, // V3LinkParse moves to AstTypedef::attrPublic
|
|
|
|
|
//
|
2015-08-13 01:33:40 +00:00
|
|
|
|
ENUM_BASE, // V3LinkResolve creates for AstPreSel, V3LinkParam removes
|
2014-11-29 01:34:23 +00:00
|
|
|
|
ENUM_FIRST, // V3Width processes
|
|
|
|
|
ENUM_LAST, // V3Width processes
|
|
|
|
|
ENUM_NUM, // V3Width processes
|
|
|
|
|
ENUM_NEXT, // V3Width processes
|
|
|
|
|
ENUM_PREV, // V3Width processes
|
|
|
|
|
ENUM_NAME, // V3Width processes
|
|
|
|
|
//
|
2012-07-29 14:16:20 +00:00
|
|
|
|
MEMBER_BASE, // V3LinkResolve creates for AstPreSel, V3LinkParam removes
|
|
|
|
|
//
|
2009-10-25 20:53:55 +00:00
|
|
|
|
VAR_BASE, // V3LinkResolve creates for AstPreSel, V3LinkParam removes
|
2009-05-07 22:28:05 +00:00
|
|
|
|
VAR_CLOCK, // V3LinkParse moves to AstVar::attrScClocked
|
|
|
|
|
VAR_CLOCK_ENABLE, // V3LinkParse moves to AstVar::attrClockEn
|
|
|
|
|
VAR_PUBLIC, // V3LinkParse moves to AstVar::sigPublic
|
|
|
|
|
VAR_PUBLIC_FLAT, // V3LinkParse moves to AstVar::sigPublic
|
2010-04-06 00:01:17 +00:00
|
|
|
|
VAR_PUBLIC_FLAT_RD, // V3LinkParse moves to AstVar::sigPublic
|
|
|
|
|
VAR_PUBLIC_FLAT_RW, // V3LinkParse moves to AstVar::sigPublic
|
2010-01-18 00:13:44 +00:00
|
|
|
|
VAR_ISOLATE_ASSIGNMENTS, // V3LinkParse moves to AstVar::attrIsolateAssign
|
2011-10-26 12:57:27 +00:00
|
|
|
|
VAR_SC_BV, // V3LinkParse moves to AstVar::attrScBv
|
2015-03-12 23:20:46 +00:00
|
|
|
|
VAR_SFORMAT, // V3LinkParse moves to AstVar::attrSFormat
|
|
|
|
|
VAR_CLOCKER, // V3LinkParse moves to AstVar::attrClocker
|
|
|
|
|
VAR_NO_CLOCKER // V3LinkParse moves to AstVar::attrClocker
|
2006-08-26 11:35:28 +00:00
|
|
|
|
};
|
|
|
|
|
enum en m_e;
|
2009-05-07 22:28:05 +00:00
|
|
|
|
const char* ascii() const {
|
|
|
|
|
static const char* names[] = {
|
2013-01-20 17:19:22 +00:00
|
|
|
|
"%E-AT",
|
|
|
|
|
"DIM_BITS", "DIM_DIMENSIONS", "DIM_HIGH", "DIM_INCREMENT", "DIM_LEFT",
|
|
|
|
|
"DIM_LOW", "DIM_RIGHT", "DIM_SIZE", "DIM_UNPK_DIMENSIONS",
|
2014-11-07 12:50:11 +00:00
|
|
|
|
"DT_PUBLIC",
|
2015-08-13 01:33:40 +00:00
|
|
|
|
"ENUM_BASE", "ENUM_FIRST", "ENUM_LAST", "ENUM_NUM", "ENUM_NEXT", "ENUM_PREV", "ENUM_NAME",
|
2013-01-20 17:19:22 +00:00
|
|
|
|
"MEMBER_BASE",
|
2012-07-29 14:16:20 +00:00
|
|
|
|
"VAR_BASE", "VAR_CLOCK", "VAR_CLOCK_ENABLE", "VAR_PUBLIC",
|
2010-04-06 00:01:17 +00:00
|
|
|
|
"VAR_PUBLIC_FLAT", "VAR_PUBLIC_FLAT_RD","VAR_PUBLIC_FLAT_RW",
|
2015-03-12 23:20:46 +00:00
|
|
|
|
"VAR_ISOLATE_ASSIGNMENTS", "VAR_SC_BV", "VAR_SFORMAT", "VAR_CLOCKER",
|
|
|
|
|
"VAR_NO_CLOCKER"
|
2009-05-07 22:28:05 +00:00
|
|
|
|
};
|
|
|
|
|
return names[m_e];
|
|
|
|
|
};
|
2011-08-05 01:58:45 +00:00
|
|
|
|
inline AstAttrType () : m_e(ILLEGAL) {}
|
2015-10-04 02:33:06 +00:00
|
|
|
|
// cppcheck-suppress noExplicitConstructor
|
2009-07-22 18:38:20 +00:00
|
|
|
|
inline AstAttrType (en _e) : m_e(_e) {}
|
|
|
|
|
explicit inline AstAttrType (int _e) : m_e(static_cast<en>(_e)) {}
|
|
|
|
|
operator en () const { return m_e; }
|
2006-08-26 11:35:28 +00:00
|
|
|
|
};
|
|
|
|
|
inline bool operator== (AstAttrType lhs, AstAttrType rhs) { return (lhs.m_e == rhs.m_e); }
|
|
|
|
|
inline bool operator== (AstAttrType lhs, AstAttrType::en rhs) { return (lhs.m_e == rhs); }
|
|
|
|
|
inline bool operator== (AstAttrType::en lhs, AstAttrType rhs) { return (lhs == rhs.m_e); }
|
|
|
|
|
|
|
|
|
|
//######################################################################
|
|
|
|
|
|
2009-11-02 13:06:04 +00:00
|
|
|
|
class AstBasicDTypeKwd {
|
|
|
|
|
public:
|
|
|
|
|
enum en {
|
2011-08-05 01:58:45 +00:00
|
|
|
|
UNKNOWN,
|
2009-11-24 14:11:25 +00:00
|
|
|
|
BIT, BYTE, CHANDLE, INT, INTEGER, LOGIC, LONGINT,
|
2011-07-22 02:10:25 +00:00
|
|
|
|
DOUBLE, SHORTINT, FLOAT, TIME,
|
2009-12-04 12:05:44 +00:00
|
|
|
|
// Closer to a class type, but limited usage
|
|
|
|
|
STRING,
|
2009-12-05 15:38:49 +00:00
|
|
|
|
// Internal types for mid-steps
|
|
|
|
|
SCOPEPTR, CHARPTR,
|
2012-04-29 14:14:13 +00:00
|
|
|
|
// Unsigned and two state; fundamental types
|
|
|
|
|
UINT32, UINT64,
|
2009-12-05 15:38:49 +00:00
|
|
|
|
// Internal types, eliminated after parsing
|
2012-04-14 14:45:24 +00:00
|
|
|
|
LOGIC_IMPLICIT,
|
|
|
|
|
// Leave last
|
|
|
|
|
_ENUM_MAX
|
2009-11-02 13:06:04 +00:00
|
|
|
|
};
|
|
|
|
|
enum en m_e;
|
|
|
|
|
const char* ascii() const {
|
|
|
|
|
static const char* names[] = {
|
2011-08-05 01:58:45 +00:00
|
|
|
|
"%E-unk",
|
2009-11-24 14:11:25 +00:00
|
|
|
|
"bit", "byte", "chandle", "int", "integer", "logic", "longint",
|
2011-07-06 01:05:35 +00:00
|
|
|
|
"real", "shortint", "shortreal", "time",
|
2009-12-04 12:05:44 +00:00
|
|
|
|
"string",
|
2009-12-05 15:38:49 +00:00
|
|
|
|
"VerilatedScope*", "char*",
|
2012-04-29 14:14:13 +00:00
|
|
|
|
"IData", "QData",
|
2012-04-14 14:45:24 +00:00
|
|
|
|
"LOGIC_IMPLICIT",
|
|
|
|
|
" MAX"
|
2009-11-02 13:06:04 +00:00
|
|
|
|
};
|
|
|
|
|
return names[m_e];
|
|
|
|
|
};
|
2009-12-03 11:55:29 +00:00
|
|
|
|
const char* dpiType() const {
|
|
|
|
|
static const char* names[] = {
|
2011-08-05 01:58:45 +00:00
|
|
|
|
"%E-unk",
|
2009-12-03 11:55:29 +00:00
|
|
|
|
"unsigned char", "char", "void*", "int", "int", "svLogic", "long long",
|
2011-07-06 01:05:35 +00:00
|
|
|
|
"double", "short int", "float", "long long",
|
2010-01-15 13:20:25 +00:00
|
|
|
|
"const char*",
|
2009-12-17 02:28:35 +00:00
|
|
|
|
"dpiScope", "const char*",
|
2012-04-29 14:14:13 +00:00
|
|
|
|
"IData", "QData",
|
|
|
|
|
"svLogic", // Though shouldn't be needed
|
2012-04-14 14:45:24 +00:00
|
|
|
|
" MAX"
|
2009-12-03 11:55:29 +00:00
|
|
|
|
};
|
|
|
|
|
return names[m_e];
|
|
|
|
|
};
|
2012-04-14 14:45:24 +00:00
|
|
|
|
static void test() {
|
|
|
|
|
UASSERT(0==strcmp(AstBasicDTypeKwd(_ENUM_MAX).ascii()," MAX"),"Enum array mismatch");
|
|
|
|
|
UASSERT(0==strcmp(AstBasicDTypeKwd(_ENUM_MAX).dpiType()," MAX"),"Enum array mismatch");
|
|
|
|
|
}
|
2011-08-05 01:58:45 +00:00
|
|
|
|
inline AstBasicDTypeKwd () : m_e(UNKNOWN) {}
|
2015-10-04 02:33:06 +00:00
|
|
|
|
// cppcheck-suppress noExplicitConstructor
|
2009-11-02 13:06:04 +00:00
|
|
|
|
inline AstBasicDTypeKwd (en _e) : m_e(_e) {}
|
|
|
|
|
explicit inline AstBasicDTypeKwd (int _e) : m_e(static_cast<en>(_e)) {}
|
|
|
|
|
operator en () const { return m_e; }
|
2009-11-03 03:14:11 +00:00
|
|
|
|
int width() const {
|
|
|
|
|
switch (m_e) {
|
2012-03-21 02:45:35 +00:00
|
|
|
|
case BIT: return 1; // scalar, can't bit extract unless ranged
|
2009-11-03 03:14:11 +00:00
|
|
|
|
case BYTE: return 8;
|
2009-11-24 14:11:25 +00:00
|
|
|
|
case CHANDLE: return 64;
|
2009-11-03 03:14:11 +00:00
|
|
|
|
case INT: return 32;
|
|
|
|
|
case INTEGER: return 32;
|
2012-03-21 02:45:35 +00:00
|
|
|
|
case LOGIC: return 1; // scalar, can't bit extract unless ranged
|
2009-11-19 15:45:59 +00:00
|
|
|
|
case LONGINT: return 64;
|
2012-03-03 17:10:29 +00:00
|
|
|
|
case DOUBLE: return 64; // opaque
|
|
|
|
|
case FLOAT: return 32; // opaque
|
2009-11-19 15:45:59 +00:00
|
|
|
|
case SHORTINT: return 16;
|
|
|
|
|
case TIME: return 64;
|
2012-03-03 17:10:29 +00:00
|
|
|
|
case STRING: return 64; // opaque // Just the pointer, for today
|
|
|
|
|
case SCOPEPTR: return 0; // opaque
|
|
|
|
|
case CHARPTR: return 0; // opaque
|
2012-04-29 14:14:13 +00:00
|
|
|
|
case UINT32: return 32;
|
|
|
|
|
case UINT64: return 64;
|
2009-11-03 03:14:11 +00:00
|
|
|
|
default: return 0;
|
|
|
|
|
}
|
|
|
|
|
}
|
2010-01-15 13:20:25 +00:00
|
|
|
|
bool isSigned() const {
|
2012-04-29 14:14:13 +00:00
|
|
|
|
return m_e==BYTE || m_e==SHORTINT || m_e==INT || m_e==LONGINT || m_e==INTEGER
|
|
|
|
|
|| m_e==DOUBLE || m_e==FLOAT;
|
|
|
|
|
}
|
|
|
|
|
bool isUnsigned() const {
|
|
|
|
|
return m_e==CHANDLE || m_e==STRING || m_e==SCOPEPTR || m_e==CHARPTR
|
|
|
|
|
|| m_e==UINT32 || m_e==UINT64;
|
2009-11-03 03:14:11 +00:00
|
|
|
|
}
|
2010-01-15 13:20:25 +00:00
|
|
|
|
bool isFourstate() const {
|
2009-11-03 03:14:11 +00:00
|
|
|
|
return m_e==INTEGER || m_e==LOGIC || m_e==LOGIC_IMPLICIT;
|
|
|
|
|
}
|
2010-01-15 13:20:25 +00:00
|
|
|
|
bool isZeroInit() const { // Otherwise initializes to X
|
2009-12-04 12:05:44 +00:00
|
|
|
|
return (m_e==BIT || m_e==BYTE || m_e==CHANDLE || m_e==INT || m_e==LONGINT || m_e==SHORTINT
|
2011-07-22 02:10:25 +00:00
|
|
|
|
|| m_e==STRING || m_e==DOUBLE || m_e==FLOAT);
|
2009-11-24 00:08:25 +00:00
|
|
|
|
}
|
2012-04-29 14:14:13 +00:00
|
|
|
|
bool isIntNumeric() const { // Enum increment supported
|
|
|
|
|
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);
|
|
|
|
|
}
|
2010-01-15 13:20:25 +00:00
|
|
|
|
bool isSloppy() const { // Don't be as anal about width warnings
|
2009-11-03 03:14:11 +00:00
|
|
|
|
return !(m_e==LOGIC || m_e==BIT);
|
|
|
|
|
}
|
2012-03-08 02:48:02 +00:00
|
|
|
|
bool isBitLogic() const { // Bit/logic vector types; can form a packed array
|
2009-11-03 03:14:11 +00:00
|
|
|
|
return (m_e==LOGIC || m_e==BIT);
|
|
|
|
|
}
|
2010-01-15 13:20:25 +00:00
|
|
|
|
bool isDpiUnsupported() const {
|
2011-07-06 01:05:35 +00:00
|
|
|
|
return (m_e==LOGIC || m_e==TIME);
|
2009-12-03 11:55:29 +00:00
|
|
|
|
}
|
2012-12-04 01:43:13 +00:00
|
|
|
|
bool isDpiUnsignable() const { // Can add "unsigned" to DPI
|
|
|
|
|
return (m_e==BYTE || m_e==SHORTINT || m_e==INT || m_e==LONGINT || m_e==INTEGER);
|
|
|
|
|
}
|
2010-01-17 20:10:37 +00:00
|
|
|
|
bool isOpaque() const { // IE not a simple number we can bit optimize
|
2011-07-22 02:10:25 +00:00
|
|
|
|
return (m_e==STRING || m_e==SCOPEPTR || m_e==CHARPTR || m_e==DOUBLE || m_e==FLOAT);
|
2011-07-06 01:05:35 +00:00
|
|
|
|
}
|
2014-11-28 20:01:50 +00:00
|
|
|
|
bool isDouble() const { return m_e==DOUBLE; }
|
|
|
|
|
bool isString() const { return m_e==STRING; }
|
2009-11-02 13:06:04 +00:00
|
|
|
|
};
|
|
|
|
|
inline bool operator== (AstBasicDTypeKwd lhs, AstBasicDTypeKwd rhs) { return (lhs.m_e == rhs.m_e); }
|
|
|
|
|
inline bool operator== (AstBasicDTypeKwd lhs, AstBasicDTypeKwd::en rhs) { return (lhs.m_e == rhs); }
|
|
|
|
|
inline bool operator== (AstBasicDTypeKwd::en lhs, AstBasicDTypeKwd rhs) { return (lhs == rhs.m_e); }
|
|
|
|
|
|
|
|
|
|
//######################################################################
|
|
|
|
|
|
2006-08-26 11:35:28 +00:00
|
|
|
|
class AstVarType {
|
|
|
|
|
public:
|
|
|
|
|
enum en {
|
|
|
|
|
UNKNOWN,
|
|
|
|
|
GPARAM,
|
|
|
|
|
LPARAM,
|
|
|
|
|
GENVAR,
|
2009-11-02 13:06:04 +00:00
|
|
|
|
VAR, // Reg, integer, logic, etc
|
2006-08-26 11:35:28 +00:00
|
|
|
|
INPUT,
|
|
|
|
|
OUTPUT,
|
|
|
|
|
INOUT,
|
|
|
|
|
SUPPLY0,
|
|
|
|
|
SUPPLY1,
|
|
|
|
|
WIRE,
|
2009-11-03 03:14:11 +00:00
|
|
|
|
IMPLICITWIRE,
|
2006-08-26 11:35:28 +00:00
|
|
|
|
TRIWIRE,
|
2012-04-21 23:30:08 +00:00
|
|
|
|
TRI0,
|
|
|
|
|
TRI1,
|
2009-05-07 22:28:05 +00:00
|
|
|
|
PORT, // Temp type used in parser only
|
2006-08-26 11:35:28 +00:00
|
|
|
|
BLOCKTEMP,
|
|
|
|
|
MODULETEMP,
|
2008-07-14 14:42:58 +00:00
|
|
|
|
STMTTEMP,
|
2013-05-28 01:39:19 +00:00
|
|
|
|
XTEMP,
|
|
|
|
|
IFACEREF // Used to link Interfaces between modules
|
2006-08-26 11:35:28 +00:00
|
|
|
|
};
|
|
|
|
|
enum en m_e;
|
2011-08-05 01:58:45 +00:00
|
|
|
|
inline AstVarType () : m_e(UNKNOWN) {}
|
2015-10-04 02:33:06 +00:00
|
|
|
|
// cppcheck-suppress noExplicitConstructor
|
2009-07-22 18:38:20 +00:00
|
|
|
|
inline AstVarType (en _e) : m_e(_e) {}
|
|
|
|
|
explicit inline AstVarType (int _e) : m_e(static_cast<en>(_e)) {}
|
|
|
|
|
operator en () const { return m_e; }
|
2006-08-26 11:35:28 +00:00
|
|
|
|
const char* ascii() const {
|
|
|
|
|
static const char* names[] = {
|
|
|
|
|
"?","GPARAM","LPARAM","GENVAR",
|
2009-11-02 13:06:04 +00:00
|
|
|
|
"VAR","INPUT","OUTPUT","INOUT",
|
2012-04-21 23:30:08 +00:00
|
|
|
|
"SUPPLY0","SUPPLY1","WIRE","IMPLICITWIRE",
|
|
|
|
|
"TRIWIRE","TRI0","TRI1",
|
|
|
|
|
"PORT",
|
2013-05-28 01:39:19 +00:00
|
|
|
|
"BLOCKTEMP","MODULETEMP","STMTTEMP","XTEMP",
|
|
|
|
|
"IFACEREF"};
|
2009-07-22 18:38:20 +00:00
|
|
|
|
return names[m_e]; }
|
2012-04-24 11:12:51 +00:00
|
|
|
|
bool isSignal() const { return (m_e==WIRE || m_e==IMPLICITWIRE
|
|
|
|
|
|| m_e==TRIWIRE
|
|
|
|
|
|| m_e==TRI0 || m_e==TRI1
|
|
|
|
|
|| m_e==SUPPLY0 || m_e==SUPPLY1
|
|
|
|
|
|| m_e==VAR); }
|
2006-08-26 11:35:28 +00:00
|
|
|
|
};
|
|
|
|
|
inline bool operator== (AstVarType lhs, AstVarType rhs) { return (lhs.m_e == rhs.m_e); }
|
|
|
|
|
inline bool operator== (AstVarType lhs, AstVarType::en rhs) { return (lhs.m_e == rhs); }
|
|
|
|
|
inline bool operator== (AstVarType::en lhs, AstVarType rhs) { return (lhs == rhs.m_e); }
|
|
|
|
|
inline ostream& operator<<(ostream& os, AstVarType rhs) { return os<<rhs.ascii(); }
|
|
|
|
|
|
|
|
|
|
//######################################################################
|
|
|
|
|
|
|
|
|
|
class AstBranchPred {
|
|
|
|
|
public:
|
|
|
|
|
enum en {
|
2010-02-02 01:15:48 +00:00
|
|
|
|
BP_UNKNOWN=0,
|
|
|
|
|
BP_LIKELY,
|
|
|
|
|
BP_UNLIKELY,
|
2006-08-26 11:35:28 +00:00
|
|
|
|
_ENUM_END
|
|
|
|
|
};
|
|
|
|
|
enum en m_e;
|
|
|
|
|
// CONSTRUCTOR - note defaults to *UNKNOWN*
|
2010-02-02 01:15:48 +00:00
|
|
|
|
inline AstBranchPred () : m_e(BP_UNKNOWN) {}
|
2015-10-04 02:33:06 +00:00
|
|
|
|
// cppcheck-suppress noExplicitConstructor
|
2009-07-22 18:38:20 +00:00
|
|
|
|
inline AstBranchPred (en _e) : m_e(_e) {}
|
|
|
|
|
explicit inline AstBranchPred (int _e) : m_e(static_cast<en>(_e)) {}
|
|
|
|
|
operator en () const { return m_e; }
|
2006-08-26 11:35:28 +00:00
|
|
|
|
AstBranchPred invert() const {
|
2010-02-02 01:15:48 +00:00
|
|
|
|
if (m_e==BP_UNLIKELY) return BP_LIKELY;
|
|
|
|
|
else if (m_e==BP_LIKELY) return BP_UNLIKELY;
|
2006-08-26 11:35:28 +00:00
|
|
|
|
else return m_e;
|
|
|
|
|
}
|
|
|
|
|
const char* ascii() const {
|
|
|
|
|
static const char* names[] = {
|
|
|
|
|
"","VL_LIKELY","VL_UNLIKELY"};
|
2009-07-22 18:38:20 +00:00
|
|
|
|
return names[m_e]; }
|
2006-08-26 11:35:28 +00:00
|
|
|
|
};
|
|
|
|
|
inline bool operator== (AstBranchPred lhs, AstBranchPred rhs) { return (lhs.m_e == rhs.m_e); }
|
|
|
|
|
inline bool operator== (AstBranchPred lhs, AstBranchPred::en rhs) { return (lhs.m_e == rhs); }
|
|
|
|
|
inline bool operator== (AstBranchPred::en lhs, AstBranchPred rhs) { return (lhs == rhs.m_e); }
|
|
|
|
|
inline ostream& operator<<(ostream& os, AstBranchPred rhs) { return os<<rhs.ascii(); }
|
|
|
|
|
|
2006-12-21 21:53:51 +00:00
|
|
|
|
//######################################################################
|
|
|
|
|
|
2015-03-12 23:20:46 +00:00
|
|
|
|
class AstVarAttrClocker {
|
|
|
|
|
public:
|
|
|
|
|
enum en {
|
|
|
|
|
CLOCKER_UNKNOWN=0,
|
|
|
|
|
CLOCKER_YES,
|
|
|
|
|
CLOCKER_NO,
|
|
|
|
|
_ENUM_END
|
|
|
|
|
};
|
|
|
|
|
enum en m_e;
|
|
|
|
|
// CONSTRUCTOR - note defaults to *UNKNOWN*
|
|
|
|
|
inline AstVarAttrClocker () : m_e(CLOCKER_UNKNOWN) {}
|
2015-10-04 02:33:06 +00:00
|
|
|
|
// cppcheck-suppress noExplicitConstructor
|
2015-03-12 23:20:46 +00:00
|
|
|
|
inline AstVarAttrClocker (en _e) : m_e(_e) {}
|
|
|
|
|
explicit inline AstVarAttrClocker (int _e) : m_e(static_cast<en>(_e)) {}
|
|
|
|
|
operator en () const { return m_e; }
|
2016-05-06 02:40:19 +00:00
|
|
|
|
bool unknown() const { return m_e==CLOCKER_UNKNOWN; }
|
2015-03-12 23:20:46 +00:00
|
|
|
|
AstVarAttrClocker invert() const {
|
|
|
|
|
if (m_e==CLOCKER_YES) return CLOCKER_NO;
|
|
|
|
|
else if (m_e==CLOCKER_NO) return CLOCKER_YES;
|
|
|
|
|
else return m_e;
|
|
|
|
|
}
|
|
|
|
|
const char* ascii() const {
|
|
|
|
|
static const char* names[] = {
|
|
|
|
|
"","clker","non_clker"};
|
|
|
|
|
return names[m_e]; }
|
|
|
|
|
};
|
|
|
|
|
inline bool operator== (AstVarAttrClocker lhs, AstVarAttrClocker rhs) { return (lhs.m_e == rhs.m_e); }
|
|
|
|
|
inline bool operator== (AstVarAttrClocker lhs, AstVarAttrClocker::en rhs) { return (lhs.m_e == rhs); }
|
|
|
|
|
inline bool operator== (AstVarAttrClocker::en lhs, AstVarAttrClocker rhs) { return (lhs == rhs.m_e); }
|
|
|
|
|
inline ostream& operator<<(ostream& os, AstVarAttrClocker rhs) { return os<<rhs.ascii(); }
|
|
|
|
|
|
|
|
|
|
//######################################################################
|
|
|
|
|
|
2013-05-01 02:55:28 +00:00
|
|
|
|
class VAlwaysKwd {
|
|
|
|
|
public:
|
|
|
|
|
enum en {
|
|
|
|
|
ALWAYS,
|
|
|
|
|
ALWAYS_FF,
|
|
|
|
|
ALWAYS_LATCH,
|
|
|
|
|
ALWAYS_COMB
|
|
|
|
|
};
|
|
|
|
|
enum en m_e;
|
|
|
|
|
inline VAlwaysKwd () : m_e(ALWAYS) {}
|
2015-10-04 02:33:06 +00:00
|
|
|
|
// cppcheck-suppress noExplicitConstructor
|
2013-05-01 02:55:28 +00:00
|
|
|
|
inline VAlwaysKwd (en _e) : m_e(_e) {}
|
|
|
|
|
explicit inline VAlwaysKwd (int _e) : m_e(static_cast<en>(_e)) {}
|
|
|
|
|
operator en () const { return m_e; }
|
|
|
|
|
const char* ascii() const {
|
|
|
|
|
static const char* names[] = {
|
|
|
|
|
"always","always_ff","always_latch","always_comb"};
|
|
|
|
|
return names[m_e]; }
|
|
|
|
|
};
|
|
|
|
|
inline bool operator== (VAlwaysKwd lhs, VAlwaysKwd rhs) { return (lhs.m_e == rhs.m_e); }
|
|
|
|
|
inline bool operator== (VAlwaysKwd lhs, VAlwaysKwd::en rhs) { return (lhs.m_e == rhs); }
|
|
|
|
|
inline bool operator== (VAlwaysKwd::en lhs, VAlwaysKwd rhs) { return (lhs == rhs.m_e); }
|
|
|
|
|
|
|
|
|
|
//######################################################################
|
|
|
|
|
|
2014-01-21 02:59:53 +00:00
|
|
|
|
class VCaseType {
|
2008-07-22 17:07:19 +00:00
|
|
|
|
public:
|
|
|
|
|
enum en {
|
2010-02-02 01:15:48 +00:00
|
|
|
|
CT_CASE,
|
|
|
|
|
CT_CASEX,
|
2014-01-21 02:59:53 +00:00
|
|
|
|
CT_CASEZ,
|
|
|
|
|
CT_CASEINSIDE
|
2008-07-22 17:07:19 +00:00
|
|
|
|
};
|
|
|
|
|
enum en m_e;
|
2014-01-21 02:59:53 +00:00
|
|
|
|
inline VCaseType () : m_e(CT_CASE) {}
|
2015-10-04 02:33:06 +00:00
|
|
|
|
// cppcheck-suppress noExplicitConstructor
|
2014-01-21 02:59:53 +00:00
|
|
|
|
inline VCaseType (en _e) : m_e(_e) {}
|
|
|
|
|
explicit inline VCaseType (int _e) : m_e(static_cast<en>(_e)) {}
|
2009-07-22 18:38:20 +00:00
|
|
|
|
operator en () const { return m_e; }
|
2008-07-22 17:07:19 +00:00
|
|
|
|
};
|
2014-01-21 02:59:53 +00:00
|
|
|
|
inline bool operator== (VCaseType lhs, VCaseType rhs) { return (lhs.m_e == rhs.m_e); }
|
|
|
|
|
inline bool operator== (VCaseType lhs, VCaseType::en rhs) { return (lhs.m_e == rhs); }
|
|
|
|
|
inline bool operator== (VCaseType::en lhs, VCaseType rhs) { return (lhs == rhs.m_e); }
|
2008-07-22 17:07:19 +00:00
|
|
|
|
|
|
|
|
|
//######################################################################
|
|
|
|
|
|
2007-03-06 21:43:38 +00:00
|
|
|
|
class AstDisplayType {
|
|
|
|
|
public:
|
|
|
|
|
enum en {
|
2010-02-02 01:15:48 +00:00
|
|
|
|
DT_DISPLAY,
|
|
|
|
|
DT_WRITE,
|
|
|
|
|
DT_INFO,
|
|
|
|
|
DT_ERROR,
|
|
|
|
|
DT_WARNING,
|
|
|
|
|
DT_FATAL
|
2007-03-06 21:43:38 +00:00
|
|
|
|
};
|
|
|
|
|
enum en m_e;
|
2011-08-05 01:58:45 +00:00
|
|
|
|
inline AstDisplayType () : m_e(DT_DISPLAY) {}
|
2015-10-04 02:33:06 +00:00
|
|
|
|
// cppcheck-suppress noExplicitConstructor
|
2009-07-22 18:38:20 +00:00
|
|
|
|
inline AstDisplayType (en _e) : m_e(_e) {}
|
|
|
|
|
explicit inline AstDisplayType (int _e) : m_e(static_cast<en>(_e)) {}
|
|
|
|
|
operator en () const { return m_e; }
|
2010-02-02 01:15:48 +00:00
|
|
|
|
bool addNewline() const { return m_e!=DT_WRITE; }
|
|
|
|
|
bool needScopeTracking() const { return m_e!=DT_DISPLAY && m_e!=DT_WRITE; }
|
2007-03-06 21:43:38 +00:00
|
|
|
|
const char* ascii() const {
|
|
|
|
|
static const char* names[] = {
|
|
|
|
|
"display","write","info","error","warning","fatal"};
|
2009-07-22 18:38:20 +00:00
|
|
|
|
return names[m_e]; }
|
2007-03-06 21:43:38 +00:00
|
|
|
|
};
|
|
|
|
|
inline bool operator== (AstDisplayType lhs, AstDisplayType rhs) { return (lhs.m_e == rhs.m_e); }
|
|
|
|
|
inline bool operator== (AstDisplayType lhs, AstDisplayType::en rhs) { return (lhs.m_e == rhs); }
|
|
|
|
|
inline bool operator== (AstDisplayType::en lhs, AstDisplayType rhs) { return (lhs == rhs.m_e); }
|
|
|
|
|
|
|
|
|
|
//######################################################################
|
|
|
|
|
|
2006-12-21 21:53:51 +00:00
|
|
|
|
class AstParseRefExp {
|
|
|
|
|
public:
|
|
|
|
|
enum en {
|
2010-02-02 01:15:48 +00:00
|
|
|
|
PX_NONE, // Used in V3LinkParse only
|
2012-12-31 22:05:13 +00:00
|
|
|
|
PX_TEXT // Unknown ID component
|
2006-12-21 21:53:51 +00:00
|
|
|
|
};
|
|
|
|
|
enum en m_e;
|
2010-02-02 01:15:48 +00:00
|
|
|
|
inline AstParseRefExp() : m_e(PX_NONE) {}
|
2015-10-04 02:33:06 +00:00
|
|
|
|
// cppcheck-suppress noExplicitConstructor
|
2009-07-22 18:38:20 +00:00
|
|
|
|
inline AstParseRefExp (en _e) : m_e(_e) {}
|
|
|
|
|
explicit inline AstParseRefExp (int _e) : m_e(static_cast<en>(_e)) {}
|
|
|
|
|
operator en () const { return m_e; }
|
2006-12-21 21:53:51 +00:00
|
|
|
|
const char* ascii() const {
|
|
|
|
|
static const char* names[] = {
|
2012-12-31 22:05:13 +00:00
|
|
|
|
"","TEXT","PREDOT"};
|
2009-07-22 18:38:20 +00:00
|
|
|
|
return names[m_e]; }
|
2006-12-21 21:53:51 +00:00
|
|
|
|
};
|
|
|
|
|
inline bool operator== (AstParseRefExp lhs, AstParseRefExp rhs) { return (lhs.m_e == rhs.m_e); }
|
|
|
|
|
inline bool operator== (AstParseRefExp lhs, AstParseRefExp::en rhs) { return (lhs.m_e == rhs); }
|
|
|
|
|
inline bool operator== (AstParseRefExp::en lhs, AstParseRefExp rhs) { return (lhs == rhs.m_e); }
|
|
|
|
|
inline ostream& operator<<(ostream& os, AstParseRefExp rhs) { return os<<rhs.ascii(); }
|
|
|
|
|
|
2012-04-29 14:14:13 +00:00
|
|
|
|
//######################################################################
|
|
|
|
|
// VNumRange - Structure containing numberic range information
|
|
|
|
|
// See also AstRange, which is a symbolic version of this
|
|
|
|
|
|
|
|
|
|
struct VNumRange {
|
2013-01-18 01:29:20 +00:00
|
|
|
|
int m_hi; // HI part, HI always >= LO
|
|
|
|
|
int m_lo; // LO
|
2012-04-29 14:14:13 +00:00
|
|
|
|
union {
|
|
|
|
|
int mu_flags;
|
|
|
|
|
struct {
|
|
|
|
|
bool m_ranged:1; // Has a range
|
|
|
|
|
bool m_littleEndian:1; // Bit vector is little endian
|
|
|
|
|
};
|
|
|
|
|
};
|
|
|
|
|
inline bool operator== (const VNumRange& rhs) const {
|
2013-01-18 01:29:20 +00:00
|
|
|
|
return m_hi == rhs.m_hi
|
|
|
|
|
&& m_lo == rhs.m_lo
|
2012-04-29 14:14:13 +00:00
|
|
|
|
&& mu_flags == rhs.mu_flags; }
|
|
|
|
|
inline bool operator< (const VNumRange& rhs) const {
|
2013-01-18 01:29:20 +00:00
|
|
|
|
if ( (m_hi < rhs.m_hi)) return true;
|
|
|
|
|
if (!(m_hi == rhs.m_hi)) return false; // lhs > rhs
|
|
|
|
|
if ( (m_lo < rhs.m_lo)) return true;
|
|
|
|
|
if (!(m_lo == rhs.m_lo)) return false; // lhs > rhs
|
2012-04-29 14:14:13 +00:00
|
|
|
|
if ( (mu_flags < rhs.mu_flags)) return true;
|
|
|
|
|
if (!(mu_flags == rhs.mu_flags)) return false; // lhs > rhs
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
//
|
2013-01-18 01:29:20 +00:00
|
|
|
|
VNumRange() : m_hi(0), m_lo(0), mu_flags(0) {}
|
|
|
|
|
VNumRange(int hi, int lo, bool littleEndian)
|
|
|
|
|
: m_hi(0), m_lo(0), mu_flags(0)
|
|
|
|
|
{ init(hi,lo,littleEndian); }
|
2012-04-29 14:14:13 +00:00
|
|
|
|
~VNumRange() {}
|
|
|
|
|
// MEMBERS
|
2013-01-18 01:29:20 +00:00
|
|
|
|
void init(int hi, int lo, bool littleEndian) {
|
|
|
|
|
m_hi=hi; m_lo=lo; mu_flags=0; m_ranged=true; m_littleEndian=littleEndian;
|
2012-04-29 14:14:13 +00:00
|
|
|
|
}
|
2013-01-18 01:29:20 +00:00
|
|
|
|
int hi() const { return m_hi; }
|
|
|
|
|
int lo() const { return m_lo; }
|
|
|
|
|
int left() const { return littleEndian()?lo():hi(); } // How to show a declaration
|
|
|
|
|
int right() const { return littleEndian()?hi():lo(); }
|
2014-03-30 14:20:12 +00:00
|
|
|
|
int leftToRightInc() const { return littleEndian()?1:-1; }
|
2013-01-18 01:29:20 +00:00
|
|
|
|
int elements() const { return hi()-lo()+1; }
|
2012-04-29 14:14:13 +00:00
|
|
|
|
bool ranged() const { return m_ranged; }
|
|
|
|
|
bool littleEndian() const { return m_littleEndian; }
|
2013-01-18 01:29:20 +00:00
|
|
|
|
int hiMaxSelect() const { return (lo()<0 ? hi()-lo() : hi()); } // Maximum value a [] select may index
|
2012-04-29 14:14:13 +00:00
|
|
|
|
bool representableByWidth() const // Could be represented by just width=1, or [width-1:0]
|
2013-01-18 01:29:20 +00:00
|
|
|
|
{ return (!m_ranged || (m_lo==0 && m_hi>=1 && !m_littleEndian)); }
|
2014-04-16 00:20:45 +00:00
|
|
|
|
void dump(ostream& str) const { if (ranged()) str<<"["<<left()<<":"<<right()<<"]"; else str<<"[norg]"; }
|
2012-04-29 14:14:13 +00:00
|
|
|
|
};
|
2014-04-16 00:20:45 +00:00
|
|
|
|
inline ostream& operator<<(ostream& os, VNumRange rhs) { rhs.dump(os); return os; }
|
2012-04-29 14:14:13 +00:00
|
|
|
|
|
|
|
|
|
//######################################################################
|
|
|
|
|
|
|
|
|
|
struct VBasicTypeKey {
|
|
|
|
|
int m_width; // From AstNodeDType: Bit width of operation
|
|
|
|
|
int m_widthMin; // From AstNodeDType: If unsized, bitwidth of minimum implementation
|
|
|
|
|
AstNumeric m_numeric; // From AstNodeDType: Node is signed
|
|
|
|
|
AstBasicDTypeKwd m_keyword; // From AstBasicDType: What keyword created basic type
|
|
|
|
|
VNumRange m_nrange; // From AstBasicDType: Numeric msb/lsb (if non-opaque keyword)
|
|
|
|
|
inline bool operator== (const VBasicTypeKey& rhs) const {
|
|
|
|
|
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; }
|
|
|
|
|
inline bool operator< (const VBasicTypeKey& rhs) const {
|
|
|
|
|
if ( (m_width < rhs.m_width)) return true;
|
|
|
|
|
if (!(m_width == rhs.m_width)) return false; // lhs > rhs
|
|
|
|
|
if ( (m_widthMin < rhs.m_widthMin)) return true;
|
|
|
|
|
if (!(m_widthMin == rhs.m_widthMin)) return false; // lhs > rhs
|
|
|
|
|
if ( (m_numeric < rhs.m_numeric)) return true;
|
|
|
|
|
if (!(m_numeric == rhs.m_numeric)) return false; // lhs > rhs
|
|
|
|
|
if ( (m_keyword < rhs.m_keyword)) return true;
|
|
|
|
|
if (!(m_keyword == rhs.m_keyword)) return false; // lhs > rhs
|
|
|
|
|
if ( (m_nrange < rhs.m_nrange)) return true;
|
|
|
|
|
if (!(m_nrange == rhs.m_nrange)) return false; // lhs > rhs
|
|
|
|
|
return false; }
|
|
|
|
|
VBasicTypeKey(int width, int widthMin, AstNumeric numeric, AstBasicDTypeKwd kwd,
|
|
|
|
|
VNumRange nrange)
|
|
|
|
|
: m_width(width), m_widthMin(widthMin), m_numeric(numeric),
|
|
|
|
|
m_keyword(kwd), m_nrange(nrange) {}
|
|
|
|
|
~VBasicTypeKey() {}
|
|
|
|
|
};
|
|
|
|
|
|
2006-08-26 11:35:28 +00:00
|
|
|
|
//######################################################################
|
|
|
|
|
// AstNUser - Generic pointer base class for AST User nodes.
|
|
|
|
|
// - Also used to allow parameter passing up/down iterate calls
|
|
|
|
|
|
|
|
|
|
class WidthVP;
|
|
|
|
|
class LinkVP;
|
|
|
|
|
class OrderBlockNU;
|
|
|
|
|
class OrderVarNU;
|
|
|
|
|
class V3GraphVertex;
|
2012-06-20 10:13:28 +00:00
|
|
|
|
class VSymEnt;
|
2006-08-26 11:35:28 +00:00
|
|
|
|
struct AstNUser {
|
|
|
|
|
AstNUser* p() { return this; } // So can take address of temporary: iterate(...,AstNUser(args).p())
|
|
|
|
|
// Casters
|
|
|
|
|
WidthVP* c() { return ((WidthVP*)this); }
|
|
|
|
|
LinkVP* castLinkVP() { return ((LinkVP*)this); }
|
2012-06-20 10:13:28 +00:00
|
|
|
|
VSymEnt* castSymEnt() { return ((VSymEnt*)this); }
|
2006-08-26 11:35:28 +00:00
|
|
|
|
AstNode* castNode() { return ((AstNode*)this); }
|
|
|
|
|
OrderBlockNU* castOrderBlock() { return ((OrderBlockNU*)this); }
|
|
|
|
|
OrderVarNU* castOrderVar() { return ((OrderVarNU*)this); }
|
|
|
|
|
V3GraphVertex* castGraphVertex() { return ((V3GraphVertex*)this); }
|
|
|
|
|
inline int castInt() {
|
|
|
|
|
union { AstNUser* up; int ui; } u;
|
|
|
|
|
u.up = this;
|
|
|
|
|
return u.ui;
|
|
|
|
|
}
|
|
|
|
|
static inline AstNUser* fromInt (int i) {
|
|
|
|
|
union { AstNUser* up; int ui; } u;
|
|
|
|
|
u.up=0; u.ui=i;
|
|
|
|
|
return u.up;
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
|
2008-11-21 20:50:33 +00:00
|
|
|
|
//######################################################################
|
|
|
|
|
// AstUserResource - Generic pointer base class for tracking usage of user()
|
|
|
|
|
//
|
|
|
|
|
// Where AstNode->user2() is going to be used, for example, you write:
|
|
|
|
|
//
|
|
|
|
|
// AstUser2InUse m_userres;
|
|
|
|
|
//
|
|
|
|
|
// This will clear the tree, and prevent another visitor from clobering
|
|
|
|
|
// user2. When the member goes out of scope it will be automagically
|
|
|
|
|
// freed up.
|
|
|
|
|
|
|
|
|
|
class AstUserInUseBase {
|
|
|
|
|
protected:
|
2009-09-24 03:10:46 +00:00
|
|
|
|
static void allocate(int id, uint32_t& cntGblRef, bool& userBusyRef) {
|
2008-11-21 20:50:33 +00:00
|
|
|
|
// Perhaps there's still a AstUserInUse in scope for this?
|
2009-09-24 03:10:46 +00:00
|
|
|
|
UASSERT_STATIC(!userBusyRef, "Conflicting user use; AstUser"+cvtToStr(id)+"InUse request when under another AstUserInUse");
|
2008-11-21 20:50:33 +00:00
|
|
|
|
userBusyRef = true;
|
2009-09-24 03:10:46 +00:00
|
|
|
|
clearcnt(id, cntGblRef, userBusyRef);
|
2008-11-21 20:50:33 +00:00
|
|
|
|
}
|
2009-09-24 03:10:46 +00:00
|
|
|
|
static void free(int id, uint32_t& cntGblRef, bool& userBusyRef) {
|
|
|
|
|
UASSERT_STATIC(userBusyRef, "Free of User"+cvtToStr(id)+"() not under AstUserInUse");
|
|
|
|
|
clearcnt(id, cntGblRef, userBusyRef); // Includes a checkUse for us
|
2008-11-21 20:50:33 +00:00
|
|
|
|
userBusyRef = false;
|
|
|
|
|
}
|
2009-09-24 03:10:46 +00:00
|
|
|
|
static void clearcnt(int id, uint32_t& cntGblRef, bool& userBusyRef) {
|
|
|
|
|
UASSERT_STATIC(userBusyRef, "Clear of User"+cvtToStr(id)+"() not under AstUserInUse");
|
2008-11-21 20:50:33 +00: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!");
|
|
|
|
|
}
|
2009-11-07 23:03:23 +00:00
|
|
|
|
static void checkcnt(int id, uint32_t&, bool& userBusyRef) {
|
|
|
|
|
UASSERT_STATIC(userBusyRef, "Check of User"+cvtToStr(id)+"() failed, not under AstUserInUse");
|
|
|
|
|
}
|
2008-11-21 20:50:33 +00: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.
|
2008-11-25 14:03:49 +00:00
|
|
|
|
class AstUser1InUse : AstUserInUseBase {
|
2008-11-21 20:50:33 +00:00
|
|
|
|
protected:
|
|
|
|
|
friend class AstNode;
|
2008-11-25 13:10:41 +00: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 20:50:33 +00:00
|
|
|
|
public:
|
2009-09-24 03:10:46 +00: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-07 23:03:23 +00:00
|
|
|
|
static void check() { checkcnt(1, s_userCntGbl/*ref*/, s_userBusy/*ref*/); }
|
2008-11-21 20:50:33 +00:00
|
|
|
|
};
|
|
|
|
|
class AstUser2InUse : AstUserInUseBase {
|
|
|
|
|
protected:
|
|
|
|
|
friend class AstNode;
|
2008-11-25 13:10:41 +00: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 20:50:33 +00:00
|
|
|
|
public:
|
2009-09-24 03:10:46 +00: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*/); }
|
2009-11-07 23:03:23 +00:00
|
|
|
|
static void check() { checkcnt(2, s_userCntGbl/*ref*/, s_userBusy/*ref*/); }
|
2008-11-21 20:50:33 +00:00
|
|
|
|
};
|
|
|
|
|
class AstUser3InUse : AstUserInUseBase {
|
|
|
|
|
protected:
|
|
|
|
|
friend class AstNode;
|
2008-11-25 13:10:41 +00: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 20:50:33 +00:00
|
|
|
|
public:
|
2009-09-24 03:10:46 +00: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*/); }
|
2009-11-07 23:03:23 +00:00
|
|
|
|
static void check() { checkcnt(3, s_userCntGbl/*ref*/, s_userBusy/*ref*/); }
|
2008-11-21 20:50:33 +00:00
|
|
|
|
};
|
|
|
|
|
class AstUser4InUse : AstUserInUseBase {
|
|
|
|
|
protected:
|
|
|
|
|
friend class AstNode;
|
2008-11-25 13:10:41 +00: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 20:50:33 +00:00
|
|
|
|
public:
|
2009-09-24 03:10:46 +00: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*/); }
|
2009-11-07 23:03:23 +00:00
|
|
|
|
static void check() { checkcnt(4, s_userCntGbl/*ref*/, s_userBusy/*ref*/); }
|
2008-11-21 20:50:33 +00:00
|
|
|
|
};
|
2010-02-01 23:55:32 +00:00
|
|
|
|
class AstUser5InUse : AstUserInUseBase {
|
|
|
|
|
protected:
|
|
|
|
|
friend class AstNode;
|
|
|
|
|
static uint32_t s_userCntGbl; // Count of which usage of userp() this is
|
|
|
|
|
static bool s_userBusy; // Count is in use
|
|
|
|
|
public:
|
|
|
|
|
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*/); }
|
|
|
|
|
};
|
2008-11-21 20:50:33 +00:00
|
|
|
|
|
2006-08-26 11:35:28 +00:00
|
|
|
|
//######################################################################
|
|
|
|
|
// AstNVisitor -- Allows new functions to be called on each node
|
|
|
|
|
// type without changing the base classes. See "Modern C++ Design".
|
|
|
|
|
|
|
|
|
|
class AstNVisitor {
|
|
|
|
|
private:
|
|
|
|
|
vector<AstNode*> m_deleteps; // Nodes to delete when we are finished
|
|
|
|
|
protected:
|
|
|
|
|
friend class AstNode;
|
|
|
|
|
public:
|
|
|
|
|
// Cleaning
|
|
|
|
|
void pushDeletep(AstNode* nodep) {
|
|
|
|
|
m_deleteps.push_back(nodep);
|
|
|
|
|
}
|
|
|
|
|
void doDeletes();
|
|
|
|
|
public:
|
|
|
|
|
virtual ~AstNVisitor() {
|
|
|
|
|
doDeletes();
|
|
|
|
|
}
|
|
|
|
|
#include "V3Ast__gen_visitor.h" // From ./astgen
|
|
|
|
|
// Things like:
|
2016-11-27 13:11:38 +00:00
|
|
|
|
// virtual void visit(AstBreak* nodep) { visit((AstNodeStmt*)(nodep)); }
|
|
|
|
|
// virtual void visit(AstNodeStmt* nodep) { visit((AstNode*)(nodep)); }
|
2006-08-26 11:35:28 +00:00
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
//######################################################################
|
|
|
|
|
// AstNRelinker -- Holds the state of a unlink so a new node can be
|
|
|
|
|
// added at the same point.
|
|
|
|
|
|
|
|
|
|
class AstNRelinker {
|
|
|
|
|
protected:
|
|
|
|
|
friend class AstNode;
|
|
|
|
|
enum RelinkWhatEn {
|
|
|
|
|
RELINK_BAD, RELINK_NEXT, RELINK_OP1, RELINK_OP2, RELINK_OP3, RELINK_OP4
|
|
|
|
|
};
|
|
|
|
|
AstNode* m_oldp; // The old node that was linked to this point in the tree
|
|
|
|
|
AstNode* m_backp;
|
|
|
|
|
RelinkWhatEn m_chg;
|
|
|
|
|
AstNode** m_iterpp;
|
|
|
|
|
public:
|
2013-02-03 18:27:37 +00:00
|
|
|
|
AstNRelinker() { m_oldp=NULL; m_backp=NULL; m_chg=RELINK_BAD; m_iterpp=NULL;}
|
2006-08-26 11:35:28 +00:00
|
|
|
|
void relink(AstNode* newp);
|
|
|
|
|
AstNode* oldp() const { return m_oldp; }
|
2011-08-05 01:58:45 +00:00
|
|
|
|
void dump(ostream& str=cout) const;
|
2006-08-26 11:35:28 +00:00
|
|
|
|
};
|
|
|
|
|
inline ostream& operator<<(ostream& os, AstNRelinker& rhs) { rhs.dump(os); return os;}
|
|
|
|
|
|
|
|
|
|
//######################################################################
|
|
|
|
|
// V3Hash -- Node hashing for V3Combine
|
|
|
|
|
|
|
|
|
|
class V3Hash {
|
|
|
|
|
// A hash of a tree of nodes, consisting of 8 bits with the number of nodes in the hash
|
|
|
|
|
// and 24 bit value hash of relevant information about the node.
|
|
|
|
|
// A value of 0 is illegal
|
|
|
|
|
uint32_t m_both;
|
|
|
|
|
static const uint32_t M24 = ((1<<24)-1);
|
|
|
|
|
void setBoth(uint32_t depth, uint32_t hshval) {
|
|
|
|
|
if (depth==0) depth=1; if (depth>255) depth=255;
|
|
|
|
|
m_both = (depth<<24) | (hshval & M24);
|
|
|
|
|
}
|
|
|
|
|
public:
|
|
|
|
|
// METHODS
|
|
|
|
|
bool isIllegal() const { return m_both==0; }
|
|
|
|
|
uint32_t fullValue() const { return m_both; }
|
|
|
|
|
uint32_t depth() const { return (m_both >> 24) & 255; }
|
|
|
|
|
uint32_t hshval() const { return m_both & M24; }
|
|
|
|
|
// OPERATORS
|
2009-07-22 18:38:20 +00:00
|
|
|
|
inline bool operator== (const V3Hash& rh) const { return m_both==rh.m_both; }
|
|
|
|
|
inline bool operator!= (const V3Hash& rh) const { return m_both!=rh.m_both; }
|
|
|
|
|
inline bool operator< (const V3Hash& rh) const { return m_both<rh.m_both; }
|
2006-08-26 11:35:28 +00:00
|
|
|
|
// CREATORS
|
|
|
|
|
class Illegal {}; // for creator type-overload selection
|
|
|
|
|
class FullValue {}; // for creator type-overload selection
|
2015-10-04 02:33:06 +00:00
|
|
|
|
explicit V3Hash(Illegal) { m_both=0; }
|
2006-08-26 11:35:28 +00:00
|
|
|
|
// Saving and restoring inside a userp
|
2015-10-04 02:33:06 +00:00
|
|
|
|
explicit V3Hash(AstNUser* up) { m_both=up->castInt(); }
|
2006-08-26 11:35:28 +00:00
|
|
|
|
V3Hash operator+= (const V3Hash& rh) {
|
|
|
|
|
setBoth(depth()+rh.depth(), (hshval()*31+rh.hshval()));
|
|
|
|
|
return *this; };
|
|
|
|
|
// Creating from raw data (sameHash functions)
|
|
|
|
|
V3Hash() { setBoth(1,0); }
|
2015-10-04 02:33:06 +00:00
|
|
|
|
// cppcheck-suppress noExplicitConstructor
|
2006-08-26 11:35:28 +00:00
|
|
|
|
V3Hash(uint32_t val) { setBoth(1,val); }
|
2015-10-04 02:33:06 +00:00
|
|
|
|
// cppcheck-suppress noExplicitConstructor
|
2012-04-02 01:04:28 +00:00
|
|
|
|
V3Hash(const void* vp) { setBoth(1,cvtToHash(vp)); }
|
2015-10-04 02:33:06 +00:00
|
|
|
|
// cppcheck-suppress noExplicitConstructor
|
2006-08-26 11:35:28 +00:00
|
|
|
|
V3Hash(const string& name);
|
2012-04-02 01:04:28 +00:00
|
|
|
|
V3Hash(V3Hash h1, V3Hash h2) {
|
|
|
|
|
setBoth(1,h1.hshval()*31+h2.hshval()); }
|
|
|
|
|
V3Hash(V3Hash h1, V3Hash h2, V3Hash h3) {
|
|
|
|
|
setBoth(1,(h1.hshval()*31+h2.hshval())*31+h3.hshval()); }
|
|
|
|
|
V3Hash(V3Hash h1, V3Hash h2, V3Hash h3, V3Hash h4) {
|
|
|
|
|
setBoth(1,((h1.hshval()*31+h2.hshval())*31+h3.hshval())*31+h4.hshval()); }
|
2006-08-26 11:35:28 +00:00
|
|
|
|
};
|
|
|
|
|
ostream& operator<<(ostream& os, V3Hash rhs);
|
|
|
|
|
|
|
|
|
|
//######################################################################
|
|
|
|
|
// AstNode -- Base type of all Ast types
|
|
|
|
|
|
2008-11-22 19:59:22 +00:00
|
|
|
|
// Prefetch a node.
|
|
|
|
|
// The if() makes it faster, even though prefetch won't fault on null pointers
|
|
|
|
|
#define ASTNODE_PREFETCH(nodep) \
|
|
|
|
|
{ if (nodep) { VL_PREFETCH_RD(&(nodep->m_nextp)); VL_PREFETCH_RD(&(nodep->m_iterpp)); }}
|
|
|
|
|
|
2006-08-26 11:35:28 +00:00
|
|
|
|
class AstNode {
|
2008-11-22 19:59:22 +00:00
|
|
|
|
// v ASTNODE_PREFETCH depends on below ordering of members
|
2006-08-26 11:35:28 +00:00
|
|
|
|
AstNode* m_nextp; // Next peer in the parent's list
|
|
|
|
|
AstNode* m_backp; // Node that points to this one (via next/op1/op2/...)
|
|
|
|
|
AstNode* m_op1p; // Generic pointer 1
|
|
|
|
|
AstNode* m_op2p; // Generic pointer 2
|
|
|
|
|
AstNode* m_op3p; // Generic pointer 3
|
|
|
|
|
AstNode* m_op4p; // Generic pointer 4
|
|
|
|
|
AstNode** m_iterpp; // Pointer to node iterating on, change it if we replace this node.
|
2008-11-22 19:59:22 +00:00
|
|
|
|
// ^ ASTNODE_PREFETCH depends on above ordering of members
|
|
|
|
|
|
|
|
|
|
AstNode* m_headtailp; // When at begin/end of list, the opposite end of the list
|
2006-08-26 11:35:28 +00:00
|
|
|
|
|
|
|
|
|
FileLine* m_fileline; // Where it was declared
|
2006-09-19 15:27:15 +00:00
|
|
|
|
vluint64_t m_editCount; // When it was last edited
|
|
|
|
|
static vluint64_t s_editCntGbl; // Global edit counter
|
|
|
|
|
static vluint64_t s_editCntLast;// Global edit counter, last value for printing * near node #s
|
2006-08-26 11:35:28 +00:00
|
|
|
|
|
2012-04-29 14:14:13 +00:00
|
|
|
|
AstNodeDType* m_dtypep; // Data type of output or assignment (etc)
|
|
|
|
|
|
2008-11-25 13:10:41 +00:00
|
|
|
|
AstNode* m_clonep; // Pointer to clone of/ source of this module (for *LAST* cloneTree() ONLY)
|
|
|
|
|
int m_cloneCnt; // Mark of when userp was set
|
|
|
|
|
static int s_cloneCntGbl; // Count of which userp is set
|
|
|
|
|
|
2006-08-26 11:35:28 +00:00
|
|
|
|
// Attributes
|
2011-07-23 23:58:34 +00:00
|
|
|
|
bool m_didWidth:1; // Did V3Width computation
|
|
|
|
|
bool m_doingWidth:1; // Inside V3Width
|
2009-10-16 01:47:15 +00:00
|
|
|
|
// // Space for more bools here
|
|
|
|
|
|
2008-11-25 13:10:41 +00:00
|
|
|
|
// This member ordering both allows 64 bit alignment and puts associated data together
|
2008-11-25 14:03:49 +00:00
|
|
|
|
AstNUser* m_user1p; // Pointer to any information the user iteration routine wants
|
|
|
|
|
uint32_t m_user1Cnt; // Mark of when userp was set
|
2008-11-25 13:10:41 +00:00
|
|
|
|
uint32_t m_user2Cnt; // Mark of when userp was set
|
2006-08-26 11:35:28 +00:00
|
|
|
|
AstNUser* m_user2p; // Pointer to any information the user iteration routine wants
|
|
|
|
|
AstNUser* m_user3p; // Pointer to any information the user iteration routine wants
|
2008-11-25 13:10:41 +00:00
|
|
|
|
uint32_t m_user3Cnt; // Mark of when userp was set
|
|
|
|
|
uint32_t m_user4Cnt; // Mark of when userp was set
|
2006-08-26 11:35:28 +00:00
|
|
|
|
AstNUser* m_user4p; // Pointer to any information the user iteration routine wants
|
2010-02-01 23:55:32 +00:00
|
|
|
|
AstNUser* m_user5p; // Pointer to any information the user iteration routine wants
|
|
|
|
|
uint32_t m_user5Cnt; // Mark of when userp was set
|
2006-08-26 11:35:28 +00:00
|
|
|
|
|
|
|
|
|
// METHODS
|
|
|
|
|
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; }
|
|
|
|
|
|
|
|
|
|
void init(); // initialize value of AstNode
|
2016-11-27 13:11:38 +00:00
|
|
|
|
void iterateListBackwards(AstNVisitor& v);
|
2015-09-18 23:06:15 +00:00
|
|
|
|
private:
|
2006-08-26 11:35:28 +00:00
|
|
|
|
AstNode* cloneTreeIter();
|
|
|
|
|
AstNode* cloneTreeIterList();
|
|
|
|
|
void checkTreeIter(AstNode* backp);
|
|
|
|
|
void checkTreeIterList(AstNode* backp);
|
2015-09-18 23:06:15 +00:00
|
|
|
|
bool gateTreeIter();
|
2016-02-04 01:44:31 +00:00
|
|
|
|
bool sameTreeIter(AstNode* node1p, AstNode* node2p, bool ignNext, bool gateOnly);
|
2006-08-26 11:35:28 +00:00
|
|
|
|
void deleteTreeIter();
|
|
|
|
|
void deleteNode();
|
2016-02-04 01:44:31 +00:00
|
|
|
|
public:
|
2006-08-26 11:35:28 +00:00
|
|
|
|
static void relinkOneLink(AstNode*& pointpr, AstNode* newp);
|
2011-08-05 01:58:45 +00:00
|
|
|
|
// cppcheck-suppress functionConst
|
2006-08-26 11:35:28 +00:00
|
|
|
|
void debugTreeChange(const char* prefix, int lineno, bool next);
|
|
|
|
|
|
|
|
|
|
protected:
|
|
|
|
|
// CONSTUCTORS
|
|
|
|
|
AstNode() {init(); }
|
2015-10-04 02:33:06 +00:00
|
|
|
|
explicit AstNode(FileLine* fileline) {init(); m_fileline = fileline; }
|
2008-11-20 14:04:29 +00:00
|
|
|
|
virtual AstNode* clone() = 0; // Generally, cloneTree is what you want instead
|
2006-08-26 11:35:28 +00:00
|
|
|
|
virtual void cloneRelink() {}
|
|
|
|
|
void cloneRelinkTree();
|
|
|
|
|
|
|
|
|
|
// METHODS
|
|
|
|
|
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
|
|
|
|
|
|
|
|
|
|
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); }
|
|
|
|
|
|
|
|
|
|
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
|
|
|
|
|
|
|
|
|
|
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); }
|
|
|
|
|
|
|
|
|
|
void clonep(AstNode* nodep) { m_clonep=nodep; m_cloneCnt=s_cloneCntGbl; }
|
|
|
|
|
static void cloneClearTree() { s_cloneCntGbl++; UASSERT_STATIC(s_cloneCntGbl,"Rollover"); }
|
|
|
|
|
|
|
|
|
|
public:
|
|
|
|
|
// ACCESSORS
|
|
|
|
|
virtual AstType type() const = 0;
|
2009-07-09 21:39:24 +00:00
|
|
|
|
const char* typeName() const { return type().ascii(); } // See also prettyTypeName
|
2006-08-26 11:35:28 +00:00
|
|
|
|
AstNode* nextp() const { return m_nextp; }
|
|
|
|
|
AstNode* backp() const { return m_backp; }
|
|
|
|
|
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 14:14:13 +00:00
|
|
|
|
AstNodeDType* dtypep() const { return m_dtypep; }
|
2006-08-26 11:35:28 +00:00
|
|
|
|
AstNode* clonep() const { return ((m_cloneCnt==s_cloneCntGbl)?m_clonep:NULL); }
|
2007-01-31 15:44:36 +00:00
|
|
|
|
AstNode* firstAbovep() const { return ((backp() && backp()->nextp()!=this) ? backp() : NULL); } // Returns NULL when second or later in list
|
2006-08-26 11:35:28 +00:00
|
|
|
|
bool brokeExists() const;
|
2010-02-14 15:01:21 +00:00
|
|
|
|
bool brokeExistsAbove() const;
|
2006-08-26 11:35:28 +00:00
|
|
|
|
|
|
|
|
|
// CONSTRUCTORS
|
|
|
|
|
virtual ~AstNode();
|
2007-11-02 11:23:03 +00: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 11:35:28 +00:00
|
|
|
|
|
|
|
|
|
// CONSTANT ACCESSORS
|
|
|
|
|
static int instrCountBranch() { return 4; } ///< Instruction cycles to branch
|
|
|
|
|
static int instrCountDiv() { return 10; } ///< Instruction cycles to divide
|
2009-12-03 11:55:29 +00:00
|
|
|
|
static int instrCountDpi() { return 1000; } ///< Instruction cycles to call user function
|
2006-08-26 11:35:28 +00:00
|
|
|
|
static int instrCountLd() { return 2; } ///< Instruction cycles to load memory
|
|
|
|
|
static int instrCountMul() { return 3; } ///< Instruction cycles to multiply integers
|
|
|
|
|
static int instrCountPli() { return 20; } ///< Instruction cycles to call pli routines
|
2011-07-24 19:01:51 +00:00
|
|
|
|
static int instrCountDouble() { return 8; } ///< Instruction cycles to convert or do floats
|
|
|
|
|
static int instrCountDoubleDiv() { return 40; } ///< Instruction cycles to divide floats
|
2011-09-29 01:35:16 +00:00
|
|
|
|
static int instrCountDoubleTrig() { return 200; } ///< Instruction cycles to do triganomics
|
2014-11-28 20:01:50 +00:00
|
|
|
|
static int instrCountString() { return 100; } ///< Instruction cycles to do string ops
|
2006-08-26 11:35:28 +00:00
|
|
|
|
static int instrCountCall() { return instrCountBranch()+10; } ///< Instruction cycles to call subroutine
|
|
|
|
|
static int instrCountTime() { return instrCountCall()+5; } ///< Instruction cycles to determine simulation time
|
|
|
|
|
|
|
|
|
|
// ACCESSORS
|
|
|
|
|
virtual string name() const { return ""; }
|
2009-07-22 19:21:41 +00:00
|
|
|
|
virtual void name(const string& name) { this->v3fatalSrc("name() called on object without name() method"); }
|
2006-08-26 11:35:28 +00:00
|
|
|
|
virtual string verilogKwd() const { return ""; }
|
|
|
|
|
string shortName() const; // Name with __PVT__ removed for concatenating scopes
|
2006-12-22 15:06:13 +00:00
|
|
|
|
static string dedotName(const string& namein); // Name with dots removed
|
2006-08-26 11:35:28 +00:00
|
|
|
|
static string prettyName(const string& namein); // Name for printing out to the user
|
2008-03-20 01:16:33 +00:00
|
|
|
|
static string encodeName(const string& namein); // Encode user name into internal C representation
|
2008-10-06 13:59:22 +00:00
|
|
|
|
static string encodeNumber(vlsint64_t numin); // Encode number into internal C representation
|
2009-09-26 13:31:50 +00:00
|
|
|
|
static string vcdName(const string& namein); // Name for printing out to vcd files
|
2006-08-26 11:35:28 +00:00
|
|
|
|
string prettyName() const { return prettyName(name()); }
|
2014-04-30 01:11:57 +00:00
|
|
|
|
string prettyTypeName() const; // "VARREF" for error messages
|
|
|
|
|
virtual string prettyOperatorName() const { return "operator "+prettyTypeName(); }
|
2006-08-26 11:35:28 +00:00
|
|
|
|
FileLine* fileline() const { return m_fileline; }
|
2010-01-20 02:30:12 +00:00
|
|
|
|
void fileline(FileLine* fl) { m_fileline=fl; }
|
2012-04-29 14:14:13 +00:00
|
|
|
|
bool width1() const;
|
|
|
|
|
int widthInstrs() const;
|
2011-07-23 23:58:34 +00:00
|
|
|
|
void didWidth(bool flag) { m_didWidth=flag; }
|
|
|
|
|
bool didWidth() const { return m_didWidth; }
|
2012-03-08 02:48:02 +00:00
|
|
|
|
bool didWidthAndSet() { if (didWidth()) return true; didWidth(true); return false;}
|
2011-07-23 23:58:34 +00:00
|
|
|
|
void doingWidth(bool flag) { m_doingWidth=flag; }
|
|
|
|
|
bool doingWidth() const { return m_doingWidth; }
|
2012-04-29 14:14:13 +00:00
|
|
|
|
|
|
|
|
|
//TODO stomp these width functions out, and call via dtypep() instead
|
|
|
|
|
int width() const;
|
|
|
|
|
int widthMin() const;
|
2015-05-15 01:46:07 +00:00
|
|
|
|
int widthMinV() const { return v3Global.widthMinUsage()==VWidthMinUsage::VERILOG_WIDTH ? widthMin() : width(); }
|
2012-04-29 14:14:13 +00:00
|
|
|
|
int widthWords() const { return VL_WORDS_I(width()); }
|
2006-08-26 11:35:28 +00:00
|
|
|
|
bool isQuad() const { return (width()>VL_WORDSIZE && width()<=VL_QUADSIZE); }
|
|
|
|
|
bool isWide() const { return (width()>VL_QUADSIZE); }
|
2012-03-03 17:10:29 +00:00
|
|
|
|
bool isDouble() const;
|
|
|
|
|
bool isSigned() const;
|
2014-11-28 20:01:50 +00:00
|
|
|
|
bool isString() const;
|
2006-08-26 11:35:28 +00:00
|
|
|
|
|
2008-11-25 14:03:49 +00:00
|
|
|
|
AstNUser* user1p() const {
|
2008-11-21 20:50:33 +00:00
|
|
|
|
// Slows things down measurably, so disabled by default
|
2008-11-25 14:03:49 +00:00
|
|
|
|
//UASSERT_STATIC(AstUser1InUse::s_userBusy, "userp set w/o busy");
|
|
|
|
|
return ((m_user1Cnt==AstUser1InUse::s_userCntGbl)?m_user1p:NULL);
|
2008-11-21 20:50:33 +00:00
|
|
|
|
}
|
2008-11-25 14:03:49 +00:00
|
|
|
|
void user1p(void* userp) { m_user1p=(AstNUser*)(userp); m_user1Cnt=AstUser1InUse::s_userCntGbl; }
|
|
|
|
|
int user1() const { return user1p()->castInt(); }
|
|
|
|
|
void user1(int val) { user1p(AstNUser::fromInt(val)); }
|
2016-05-07 02:26:15 +00:00
|
|
|
|
int user1Inc(int val=1) { int v=user1(); user1(v+val); return v; }
|
2012-04-29 12:55:33 +00:00
|
|
|
|
int user1SetOnce() { int v=user1(); if (!v) user1(1); return v; } // Better for cache than user1Inc()
|
2008-11-25 14:03:49 +00:00
|
|
|
|
static void user1ClearTree() { AstUser1InUse::clear(); } // Clear userp()'s across the entire tree
|
2008-11-21 20:50:33 +00:00
|
|
|
|
|
|
|
|
|
AstNUser* user2p() const {
|
|
|
|
|
//UASSERT_STATIC(AstUser2InUse::s_userBusy, "user2p set w/o busy");
|
|
|
|
|
return ((m_user2Cnt==AstUser2InUse::s_userCntGbl)?m_user2p:NULL); }
|
|
|
|
|
void user2p(void* userp) { m_user2p=(AstNUser*)(userp); m_user2Cnt=AstUser2InUse::s_userCntGbl; }
|
2006-08-26 11:35:28 +00:00
|
|
|
|
int user2() const { return user2p()->castInt(); }
|
|
|
|
|
void user2(int val) { user2p(AstNUser::fromInt(val)); }
|
2016-05-07 02:26:15 +00:00
|
|
|
|
int user2Inc(int val=1) { int v=user2(); user2(v+val); return v; }
|
2012-04-29 12:55:33 +00:00
|
|
|
|
int user2SetOnce() { int v=user2(); if (!v) user2(1); return v; }
|
2008-11-21 20:50:33 +00:00
|
|
|
|
static void user2ClearTree() { AstUser2InUse::clear(); }
|
|
|
|
|
|
|
|
|
|
AstNUser* user3p() const {
|
|
|
|
|
//UASSERT_STATIC(AstUser3InUse::s_userBusy, "user3p set w/o busy");
|
|
|
|
|
return ((m_user3Cnt==AstUser3InUse::s_userCntGbl)?m_user3p:NULL); }
|
|
|
|
|
void user3p(void* userp) { m_user3p=(AstNUser*)(userp); m_user3Cnt=AstUser3InUse::s_userCntGbl; }
|
2006-08-26 11:35:28 +00:00
|
|
|
|
int user3() const { return user3p()->castInt(); }
|
|
|
|
|
void user3(int val) { user3p(AstNUser::fromInt(val)); }
|
2016-05-07 02:26:15 +00:00
|
|
|
|
int user3Inc(int val=1) { int v=user3(); user3(v+val); return v; }
|
2012-04-29 12:55:33 +00:00
|
|
|
|
int user3SetOnce() { int v=user3(); if (!v) user3(1); return v; }
|
2008-11-21 20:50:33 +00:00
|
|
|
|
static void user3ClearTree() { AstUser3InUse::clear(); }
|
|
|
|
|
|
|
|
|
|
AstNUser* user4p() const {
|
|
|
|
|
//UASSERT_STATIC(AstUser4InUse::s_userBusy, "user4p set w/o busy");
|
|
|
|
|
return ((m_user4Cnt==AstUser4InUse::s_userCntGbl)?m_user4p:NULL); }
|
|
|
|
|
void user4p(void* userp) { m_user4p=(AstNUser*)(userp); m_user4Cnt=AstUser4InUse::s_userCntGbl; }
|
2006-08-26 11:35:28 +00:00
|
|
|
|
int user4() const { return user4p()->castInt(); }
|
|
|
|
|
void user4(int val) { user4p(AstNUser::fromInt(val)); }
|
2016-05-07 02:26:15 +00:00
|
|
|
|
int user4Inc(int val=1) { int v=user4(); user4(v+val); return v; }
|
2012-04-29 12:55:33 +00:00
|
|
|
|
int user4SetOnce() { int v=user4(); if (!v) user4(1); return v; }
|
2008-11-21 20:50:33 +00:00
|
|
|
|
static void user4ClearTree() { AstUser4InUse::clear(); }
|
|
|
|
|
|
2010-02-01 23:55:32 +00:00
|
|
|
|
AstNUser* user5p() const {
|
|
|
|
|
//UASSERT_STATIC(AstUser5InUse::s_userBusy, "user5p set w/o busy");
|
|
|
|
|
return ((m_user5Cnt==AstUser5InUse::s_userCntGbl)?m_user5p:NULL); }
|
|
|
|
|
void user5p(void* userp) { m_user5p=(AstNUser*)(userp); m_user5Cnt=AstUser5InUse::s_userCntGbl; }
|
|
|
|
|
int user5() const { return user5p()->castInt(); }
|
|
|
|
|
void user5(int val) { user5p(AstNUser::fromInt(val)); }
|
2016-05-07 02:26:15 +00:00
|
|
|
|
int user5Inc(int val=1) { int v=user5(); user5(v+val); return v; }
|
2012-04-29 12:55:33 +00:00
|
|
|
|
int user5SetOnce() { int v=user5(); if (!v) user5(1); return v; }
|
2010-02-01 23:55:32 +00:00
|
|
|
|
static void user5ClearTree() { AstUser5InUse::clear(); }
|
|
|
|
|
|
2006-09-19 15:27:15 +00:00
|
|
|
|
vluint64_t editCount() const { return m_editCount; }
|
2009-09-26 10:43:06 +00:00
|
|
|
|
void editCountInc() { m_editCount = ++s_editCntGbl; } // Preincrement, so can "watch AstNode::s_editCntGbl=##"
|
2006-09-19 15:27:15 +00:00
|
|
|
|
static vluint64_t editCountLast() { return s_editCntLast; }
|
|
|
|
|
static vluint64_t editCountGbl() { return s_editCntGbl; }
|
2006-08-26 11:35:28 +00:00
|
|
|
|
static void editCountSetLast() { s_editCntLast = editCountGbl(); }
|
|
|
|
|
|
|
|
|
|
// ACCESSORS for specific types
|
|
|
|
|
// Alas these can't be virtual or they break when passed a NULL
|
|
|
|
|
bool isZero();
|
|
|
|
|
bool isOne();
|
|
|
|
|
bool isNeqZero();
|
|
|
|
|
bool isAllOnes();
|
|
|
|
|
bool isAllOnesV(); // Verilog width rules apply
|
|
|
|
|
|
2011-12-01 00:32:33 +00:00
|
|
|
|
// METHODS - data type changes especially for initial creation
|
2012-04-29 14:14:13 +00:00
|
|
|
|
void dtypep(AstNodeDType* nodep) { if (m_dtypep != nodep) { m_dtypep = nodep; editCountInc(); } }
|
|
|
|
|
void dtypeFrom(AstNode* fromp) { if (fromp) { dtypep(fromp->dtypep()); }}
|
|
|
|
|
void dtypeChgSigned(bool flag=true);
|
|
|
|
|
void dtypeChgWidth(int width, int widthMin);
|
2013-01-19 02:35:43 +00:00
|
|
|
|
void dtypeChgWidthSigned(int width, int widthMin, AstNumeric numeric);
|
2012-05-10 02:12:57 +00:00
|
|
|
|
void dtypeSetBitSized(int width, int widthMin, AstNumeric numeric) { dtypep(findBitDType(width,widthMin,numeric)); }
|
|
|
|
|
void dtypeSetLogicSized(int width, int widthMin, AstNumeric numeric) { dtypep(findLogicDType(width,widthMin,numeric)); }
|
|
|
|
|
void dtypeSetLogicBool() { dtypep(findLogicBoolDType()); }
|
|
|
|
|
void dtypeSetDouble() { dtypep(findDoubleDType()); }
|
2014-11-28 20:01:50 +00:00
|
|
|
|
void dtypeSetString() { dtypep(findStringDType()); }
|
2012-05-10 02:12:57 +00:00
|
|
|
|
void dtypeSetSigned32() { dtypep(findSigned32DType()); }
|
|
|
|
|
void dtypeSetUInt32() { dtypep(findUInt32DType()); } // Twostate
|
|
|
|
|
void dtypeSetUInt64() { dtypep(findUInt64DType()); } // Twostate
|
|
|
|
|
|
|
|
|
|
// Data type locators
|
|
|
|
|
AstNodeDType* findLogicBoolDType() { return findBasicDType(AstBasicDTypeKwd::LOGIC); }
|
|
|
|
|
AstNodeDType* findDoubleDType() { return findBasicDType(AstBasicDTypeKwd::DOUBLE); }
|
2014-11-28 20:01:50 +00:00
|
|
|
|
AstNodeDType* findStringDType() { return findBasicDType(AstBasicDTypeKwd::STRING); }
|
2012-05-10 02:12:57 +00:00
|
|
|
|
AstNodeDType* findSigned32DType() { return findBasicDType(AstBasicDTypeKwd::INTEGER); }
|
|
|
|
|
AstNodeDType* findUInt32DType() { return findBasicDType(AstBasicDTypeKwd::UINT32); } // Twostate
|
|
|
|
|
AstNodeDType* findUInt64DType() { return findBasicDType(AstBasicDTypeKwd::UINT64); } // Twostate
|
2012-07-24 01:29:53 +00:00
|
|
|
|
AstNodeDType* findBitDType(int width, int widthMin, AstNumeric numeric) const;
|
|
|
|
|
AstNodeDType* findLogicDType(int width, int widthMin, AstNumeric numeric) const;
|
2013-01-17 01:58:48 +00:00
|
|
|
|
AstNodeDType* findLogicRangeDType(VNumRange range, int widthMin, AstNumeric numeric) const;
|
2012-07-24 01:29:53 +00:00
|
|
|
|
AstNodeDType* findBasicDType(AstBasicDTypeKwd kwd) const;
|
2012-05-10 02:12:57 +00:00
|
|
|
|
AstBasicDType* findInsertSameDType(AstBasicDType* nodep);
|
2011-12-01 00:32:33 +00:00
|
|
|
|
|
2011-11-30 23:50:21 +00:00
|
|
|
|
// METHODS - dump and error
|
|
|
|
|
void v3errorEnd(ostringstream& str) const;
|
2012-05-22 01:24:17 +00:00
|
|
|
|
string warnMore() const;
|
2011-11-30 23:50:21 +00:00
|
|
|
|
virtual void dump(ostream& str=cout);
|
2012-03-03 16:29:09 +00:00
|
|
|
|
void dumpGdb(); // For GDB only
|
|
|
|
|
void dumpGdbHeader() const;
|
2011-11-30 23:50:21 +00:00
|
|
|
|
|
|
|
|
|
// METHODS - Tree modifications
|
2016-02-09 03:15:44 +00:00
|
|
|
|
static AstNode* addNext(AstNode* nodep, AstNode* newp); // Returns nodep, adds newp to end of nodep's list
|
|
|
|
|
static AstNode* addNextNull(AstNode* nodep, AstNode* newp); // Returns nodep, adds newp (maybe NULL) to end of nodep's list
|
|
|
|
|
inline AstNode* addNext(AstNode* newp) { return addNext(this, newp); }
|
|
|
|
|
inline AstNode* addNextNull(AstNode* newp) { return addNextNull(this, newp); }
|
2006-08-26 11:35:28 +00:00
|
|
|
|
void addNextHere(AstNode* newp); // Adds after speced node
|
2010-02-14 15:01:21 +00:00
|
|
|
|
void addPrev(AstNode* newp) { replaceWith(newp); newp->addNext(this); }
|
2009-10-09 00:42:45 +00:00
|
|
|
|
void addHereThisAsNext(AstNode* newp); // Adds at old place of this, this becomes next
|
2006-08-26 11:35:28 +00:00
|
|
|
|
void replaceWith(AstNode* newp); // Replace current node in tree with new node
|
|
|
|
|
AstNode* unlinkFrBack(AstNRelinker* linkerp=NULL); // Unlink this from whoever points to it.
|
|
|
|
|
AstNode* unlinkFrBackWithNext(AstNRelinker* linkerp=NULL); // Unlink this from whoever points to it, keep entire next list with unlinked node
|
2009-09-24 03:10:46 +00:00
|
|
|
|
void swapWith(AstNode* bp);
|
2006-08-26 11:35:28 +00:00
|
|
|
|
void relink(AstNRelinker* linkerp); // Generally use linker->relink() instead
|
|
|
|
|
void cloneRelinkNode() { cloneRelink(); }
|
2009-10-09 00:42:45 +00:00
|
|
|
|
// Iterate and insert - assumes tree format
|
|
|
|
|
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 11:35:28 +00:00
|
|
|
|
|
|
|
|
|
// METHODS - Iterate on a tree
|
|
|
|
|
AstNode* cloneTree(bool cloneNextLink);
|
2015-09-18 23:06:15 +00:00
|
|
|
|
bool gateTree() { return gateTreeIter(); } // Is tree gateOptimizable?
|
2006-08-26 11:35:28 +00:00
|
|
|
|
bool sameTree(AstNode* node2p); // Does tree of this == node2p?
|
2014-11-03 00:52:49 +00:00
|
|
|
|
bool sameGateTree(AstNode* node2p); // Does tree of this == node2p?, not allowing non-isGateOptimizable
|
2006-08-26 11:35:28 +00:00
|
|
|
|
void deleteTree(); // Always deletes the next link
|
|
|
|
|
void checkTree(); // User Interface version
|
2013-09-04 01:40:43 +00:00
|
|
|
|
void checkIter() const;
|
|
|
|
|
void clearIter() { m_iterpp=NULL; }
|
2011-08-05 01:58:45 +00:00
|
|
|
|
void dumpPtrs(ostream& str=cout) const;
|
2006-08-26 11:35:28 +00:00
|
|
|
|
void dumpTree(ostream& str=cout, const string& indent=" ", int maxDepth=0);
|
2012-04-27 23:01:08 +00:00
|
|
|
|
void dumpTree(const string& indent, int maxDepth=0) { dumpTree(cout,indent,maxDepth); }
|
2012-03-03 16:29:09 +00:00
|
|
|
|
void dumpTreeGdb(); // For GDB only
|
2006-08-26 11:35:28 +00:00
|
|
|
|
void dumpTreeAndNext(ostream& str=cout, const string& indent=" ", int maxDepth=0);
|
2013-10-31 03:25:54 +00:00
|
|
|
|
void dumpTreeFile(const string& filename, bool append=false, bool doDump=true);
|
2012-07-24 00:21:04 +00:00
|
|
|
|
static void dumpTreeFileGdb(const char* filenamep=NULL);
|
2006-08-26 11:35:28 +00:00
|
|
|
|
|
|
|
|
|
// METHODS - queries
|
2011-12-16 00:13:54 +00:00
|
|
|
|
virtual bool isPure() const { return true; } // Else a $display, etc, that must be ordered with other displays
|
2011-12-16 03:23:11 +00:00
|
|
|
|
virtual bool isBrancher() const { return false; } // Changes control flow, disable some optimizations
|
2006-08-26 11:35:28 +00:00
|
|
|
|
virtual bool isGateOptimizable() const { return true; } // Else a AstTime etc that can't be pushed out
|
2013-02-21 01:14:15 +00:00
|
|
|
|
virtual bool isGateDedupable() const { return isGateOptimizable(); } // GateDedupable is a slightly larger superset of GateOptimzable (eg, AstNodeIf)
|
2006-08-26 11:35:28 +00:00
|
|
|
|
virtual bool isSubstOptimizable() const { return true; } // Else a AstTime etc that can't be substituted out
|
|
|
|
|
virtual bool isPredictOptimizable() const { return true; } // Else a AstTime etc which output can't be predicted from input
|
|
|
|
|
virtual bool isOutputter() const { return false; } // Else creates output or exits, etc, not unconsumed
|
|
|
|
|
virtual bool isUnlikely() const { return false; } // Else $stop or similar statement which means an above IF statement is unlikely to be taken
|
|
|
|
|
virtual int instrCount() const { return 0; }
|
|
|
|
|
virtual V3Hash sameHash() const { return V3Hash(V3Hash::Illegal()); } // Not a node that supports it
|
|
|
|
|
virtual bool same(AstNode* otherp) const { return true; }
|
2012-04-14 15:03:38 +00:00
|
|
|
|
virtual bool hasDType() const { return false; } // Iff has a data type; dtype() must be non null
|
2012-04-29 14:14:13 +00:00
|
|
|
|
virtual AstNodeDType* getChildDTypep() const { return NULL; } // Iff has a non-null childDTypep(), as generic node function
|
2006-10-05 00:45:39 +00:00
|
|
|
|
virtual bool maybePointedTo() const { return false; } // Another AstNode* may have a pointer into this node, other then normal front/back/etc.
|
2013-05-25 21:05:22 +00:00
|
|
|
|
virtual const char* broken() const { return NULL; }
|
2006-08-26 11:35:28 +00:00
|
|
|
|
|
|
|
|
|
// INVOKERS
|
2016-11-27 13:11:38 +00:00
|
|
|
|
virtual void accept(AstNVisitor& v) = 0;
|
|
|
|
|
void iterate(AstNVisitor& v) { this->accept(v); } // Does this; excludes following this->next
|
|
|
|
|
void iterateAndNext(AstNVisitor& v);
|
|
|
|
|
void iterateAndNextConst(AstNVisitor& v);
|
|
|
|
|
void iterateChildren(AstNVisitor& v); // Excludes following this->next
|
|
|
|
|
void iterateChildrenBackwards(AstNVisitor& v); // Excludes following this->next
|
|
|
|
|
void iterateChildrenConst(AstNVisitor& v); // Excludes following this->next
|
|
|
|
|
AstNode* iterateSubtreeReturnEdits(AstNVisitor& v); // Return edited nodep; see comments in V3Ast.cpp
|
2006-08-26 11:35:28 +00:00
|
|
|
|
|
|
|
|
|
// CONVERSION
|
|
|
|
|
#include "V3Ast__gen_interface.h" // From ./astgen
|
|
|
|
|
// Things like:
|
|
|
|
|
// AstAlways* castAlways();
|
|
|
|
|
};
|
|
|
|
|
|
2012-07-28 01:12:06 +00:00
|
|
|
|
inline ostream& operator<<(ostream& os, AstNode* rhs) { if (!rhs) os<<"NULL"; else rhs->dump(os); return os; }
|
2006-08-26 11:35:28 +00:00
|
|
|
|
inline void AstNRelinker::relink(AstNode* newp) { newp->AstNode::relink(this); }
|
|
|
|
|
|
|
|
|
|
//######################################################################
|
|
|
|
|
//######################################################################
|
|
|
|
|
//=== AstNode* : Derived generic node types
|
|
|
|
|
|
2008-11-20 01:15:05 +00:00
|
|
|
|
#define ASTNODE_BASE_FUNCS(name) \
|
|
|
|
|
virtual ~Ast ##name() {} \
|
2016-11-09 02:16:22 +00: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 01:15:05 +00:00
|
|
|
|
|
2014-09-12 01:28:53 +00:00
|
|
|
|
class AstNodeMath : public AstNode {
|
2006-08-26 11:35:28 +00:00
|
|
|
|
// Math -- anything that's part of an expression tree
|
2014-09-12 01:28:53 +00:00
|
|
|
|
public:
|
2015-10-04 02:33:06 +00:00
|
|
|
|
explicit AstNodeMath(FileLine* fl)
|
2006-08-26 11:35:28 +00:00
|
|
|
|
: AstNode(fl) {}
|
2008-11-20 01:15:05 +00:00
|
|
|
|
ASTNODE_BASE_FUNCS(NodeMath)
|
2006-08-26 11:35:28 +00:00
|
|
|
|
// METHODS
|
2012-04-14 15:03:38 +00:00
|
|
|
|
virtual bool hasDType() const { return true; }
|
2006-08-26 11:35:28 +00:00
|
|
|
|
virtual string emitVerilog() = 0; /// Format string for verilog writing; see V3EmitV
|
2008-06-30 00:02:24 +00:00
|
|
|
|
virtual string emitC() = 0;
|
2006-08-26 11:35:28 +00:00
|
|
|
|
virtual string emitSimpleOperator() { return ""; }
|
|
|
|
|
virtual bool cleanOut() = 0; // True if output has extra upper bits zero
|
2010-01-17 20:10:37 +00:00
|
|
|
|
// Someday we will generically support data types on every math node
|
|
|
|
|
// Until then isOpaque indicates we shouldn't constant optimize this node type
|
2010-01-25 01:53:24 +00:00
|
|
|
|
bool isOpaque() { return castCvtPackString()!=NULL; }
|
2006-08-26 11:35:28 +00:00
|
|
|
|
};
|
|
|
|
|
|
2014-09-12 01:28:53 +00:00
|
|
|
|
class AstNodeTermop : public AstNodeMath {
|
2006-08-26 11:35:28 +00:00
|
|
|
|
// Terminal operator -- a operator with no "inputs"
|
2014-09-12 01:28:53 +00:00
|
|
|
|
public:
|
2015-10-04 02:33:06 +00:00
|
|
|
|
explicit AstNodeTermop(FileLine* fl)
|
2006-08-26 11:35:28 +00:00
|
|
|
|
: AstNodeMath(fl) {}
|
2008-11-20 01:15:05 +00:00
|
|
|
|
ASTNODE_BASE_FUNCS(NodeTermop)
|
2008-11-22 20:28:29 +00:00
|
|
|
|
// Know no children, and hot function, so skip iterator for speed
|
|
|
|
|
// See checkTreeIter also that asserts no children
|
2011-08-05 01:58:45 +00:00
|
|
|
|
// cppcheck-suppress functionConst
|
2016-11-27 13:11:38 +00:00
|
|
|
|
void iterateChildren(AstNVisitor& v) { }
|
2006-08-26 11:35:28 +00:00
|
|
|
|
};
|
|
|
|
|
|
2014-09-12 01:28:53 +00:00
|
|
|
|
class AstNodeUniop : public AstNodeMath {
|
2006-08-26 11:35:28 +00:00
|
|
|
|
// Unary math
|
2014-09-12 01:28:53 +00:00
|
|
|
|
public:
|
2006-08-26 11:35:28 +00:00
|
|
|
|
AstNodeUniop(FileLine* fl, AstNode* lhsp)
|
|
|
|
|
: AstNodeMath(fl) {
|
2012-04-29 13:42:17 +00:00
|
|
|
|
dtypeFrom(lhsp);
|
2006-08-26 11:35:28 +00:00
|
|
|
|
setOp1p(lhsp); }
|
2008-11-20 01:15:05 +00:00
|
|
|
|
ASTNODE_BASE_FUNCS(NodeUniop)
|
2016-11-05 14:06:43 +00:00
|
|
|
|
AstNode* lhsp() const { return op1p(); }
|
2011-02-24 02:36:38 +00:00
|
|
|
|
void lhsp(AstNode* nodep) { return setOp1p(nodep); }
|
2006-08-26 11:35:28 +00:00
|
|
|
|
// METHODS
|
|
|
|
|
virtual void numberOperate(V3Number& out, const V3Number& lhs) = 0; // Set out to evaluation of a AstConst'ed lhs
|
|
|
|
|
virtual bool cleanLhs() = 0;
|
|
|
|
|
virtual bool sizeMattersLhs() = 0; // True if output result depends on lhs size
|
2011-07-23 23:58:34 +00:00
|
|
|
|
virtual bool doubleFlavor() const { return false; } // D flavor of nodes with both flavors?
|
2014-11-28 20:01:50 +00:00
|
|
|
|
virtual bool signedFlavor() const { return false; } // Signed flavor of nodes with both flavors?
|
|
|
|
|
virtual bool stringFlavor() const { return false; } // N flavor of nodes with both flavors?
|
2006-08-26 11:35:28 +00:00
|
|
|
|
virtual int instrCount() const { return widthInstrs(); }
|
|
|
|
|
virtual V3Hash sameHash() const { return V3Hash(); }
|
|
|
|
|
virtual bool same(AstNode*) const { return true; }
|
|
|
|
|
};
|
|
|
|
|
|
2014-09-12 01:28:53 +00:00
|
|
|
|
class AstNodeBiop : public AstNodeMath {
|
2006-08-26 11:35:28 +00:00
|
|
|
|
// Binary math
|
2014-09-12 01:28:53 +00:00
|
|
|
|
public:
|
2006-08-26 11:35:28 +00:00
|
|
|
|
AstNodeBiop(FileLine* fl, AstNode* lhs, AstNode* rhs)
|
|
|
|
|
: AstNodeMath(fl) {
|
|
|
|
|
setOp1p(lhs); setOp2p(rhs); }
|
2008-11-20 01:15:05 +00:00
|
|
|
|
ASTNODE_BASE_FUNCS(NodeBiop)
|
2016-07-23 20:54:36 +00:00
|
|
|
|
virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp)=0; // Clone single node, just get same type back.
|
|
|
|
|
// ACCESSORS
|
2016-11-05 14:06:43 +00:00
|
|
|
|
AstNode* lhsp() const { return op1p(); }
|
|
|
|
|
AstNode* rhsp() const { return op2p(); }
|
2006-08-26 11:35:28 +00:00
|
|
|
|
void lhsp(AstNode* nodep) { return setOp1p(nodep); }
|
|
|
|
|
void rhsp(AstNode* nodep) { return setOp2p(nodep); }
|
|
|
|
|
// METHODS
|
|
|
|
|
virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs) = 0; // Set out to evaluation of a AstConst'ed
|
|
|
|
|
virtual bool cleanLhs() = 0; // True if LHS must have extra upper bits zero
|
|
|
|
|
virtual bool cleanRhs() = 0; // True if RHS must have extra upper bits zero
|
|
|
|
|
virtual bool sizeMattersLhs() = 0; // True if output result depends on lhs size
|
|
|
|
|
virtual bool sizeMattersRhs() = 0; // True if output result depends on rhs size
|
2011-07-23 23:58:34 +00:00
|
|
|
|
virtual bool doubleFlavor() const { return false; } // D flavor of nodes with both flavors?
|
2014-11-28 20:01:50 +00:00
|
|
|
|
virtual bool signedFlavor() const { return false; } // Signed flavor of nodes with both flavors?
|
|
|
|
|
virtual bool stringFlavor() const { return false; } // N flavor of nodes with both flavors?
|
2006-08-26 11:35:28 +00:00
|
|
|
|
virtual int instrCount() const { return widthInstrs(); }
|
|
|
|
|
virtual V3Hash sameHash() const { return V3Hash(); }
|
|
|
|
|
virtual bool same(AstNode*) const { return true; }
|
|
|
|
|
};
|
|
|
|
|
|
2014-09-12 01:28:53 +00:00
|
|
|
|
class AstNodeTriop : public AstNodeMath {
|
2006-08-26 11:35:28 +00:00
|
|
|
|
// Trinary math
|
2014-09-12 01:28:53 +00:00
|
|
|
|
public:
|
2006-08-26 11:35:28 +00:00
|
|
|
|
AstNodeTriop(FileLine* fl, AstNode* lhs, AstNode* rhs, AstNode* ths)
|
|
|
|
|
: AstNodeMath(fl) {
|
|
|
|
|
setOp1p(lhs); setOp2p(rhs); setOp3p(ths); }
|
2008-11-20 01:15:05 +00:00
|
|
|
|
ASTNODE_BASE_FUNCS(NodeTriop)
|
2016-11-05 14:06:43 +00:00
|
|
|
|
AstNode* lhsp() const { return op1p(); }
|
|
|
|
|
AstNode* rhsp() const { return op2p(); }
|
|
|
|
|
AstNode* thsp() const { return op3p(); }
|
2006-08-26 11:35:28 +00:00
|
|
|
|
void lhsp(AstNode* nodep) { return setOp1p(nodep); }
|
|
|
|
|
void rhsp(AstNode* nodep) { return setOp2p(nodep); }
|
|
|
|
|
void thsp(AstNode* nodep) { return setOp3p(nodep); }
|
|
|
|
|
// METHODS
|
|
|
|
|
virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs, const V3Number& ths) = 0; // Set out to evaluation of a AstConst'ed
|
|
|
|
|
virtual bool cleanLhs() = 0; // True if LHS must have extra upper bits zero
|
|
|
|
|
virtual bool cleanRhs() = 0; // True if RHS must have extra upper bits zero
|
|
|
|
|
virtual bool cleanThs() = 0; // True if THS must have extra upper bits zero
|
|
|
|
|
virtual bool sizeMattersLhs() = 0; // True if output result depends on lhs size
|
|
|
|
|
virtual bool sizeMattersRhs() = 0; // True if output result depends on rhs size
|
|
|
|
|
virtual bool sizeMattersThs() = 0; // True if output result depends on ths size
|
|
|
|
|
virtual int instrCount() const { return widthInstrs(); }
|
|
|
|
|
virtual V3Hash sameHash() const { return V3Hash(); }
|
|
|
|
|
virtual bool same(AstNode*) const { return true; }
|
|
|
|
|
};
|
|
|
|
|
|
2014-09-12 01:28:53 +00:00
|
|
|
|
class AstNodeBiCom : public AstNodeBiop {
|
2006-08-26 11:35:28 +00:00
|
|
|
|
// Binary math with commutative properties
|
2014-09-12 01:28:53 +00:00
|
|
|
|
public:
|
2006-08-26 11:35:28 +00:00
|
|
|
|
AstNodeBiCom(FileLine* fl, AstNode* lhs, AstNode* rhs)
|
|
|
|
|
: AstNodeBiop(fl, lhs, rhs) {}
|
2008-11-20 01:15:05 +00:00
|
|
|
|
ASTNODE_BASE_FUNCS(NodeBiCom)
|
2006-08-26 11:35:28 +00:00
|
|
|
|
};
|
|
|
|
|
|
2014-09-12 01:28:53 +00:00
|
|
|
|
class AstNodeBiComAsv : public AstNodeBiCom {
|
2006-08-26 11:35:28 +00:00
|
|
|
|
// Binary math with commutative & associative properties
|
2014-09-12 01:28:53 +00:00
|
|
|
|
public:
|
2006-08-26 11:35:28 +00:00
|
|
|
|
AstNodeBiComAsv(FileLine* fl, AstNode* lhs, AstNode* rhs)
|
|
|
|
|
: AstNodeBiCom(fl, lhs, rhs) {}
|
2008-11-20 01:15:05 +00:00
|
|
|
|
ASTNODE_BASE_FUNCS(NodeBiComAsv)
|
2006-08-26 11:35:28 +00:00
|
|
|
|
};
|
2014-09-12 01:28:53 +00:00
|
|
|
|
class AstNodeCond : public AstNodeTriop {
|
|
|
|
|
public:
|
2006-08-26 11:35:28 +00:00
|
|
|
|
AstNodeCond(FileLine* fl, AstNode* condp, AstNode* expr1p, AstNode* expr2p)
|
|
|
|
|
: AstNodeTriop(fl, condp, expr1p, expr2p) {
|
2012-04-29 13:42:17 +00:00
|
|
|
|
if (expr1p) dtypeFrom(expr1p);
|
|
|
|
|
else if (expr2p) dtypeFrom(expr2p);
|
2006-08-26 11:35:28 +00:00
|
|
|
|
}
|
2008-11-20 01:15:05 +00:00
|
|
|
|
ASTNODE_BASE_FUNCS(NodeCond)
|
2006-08-26 11:35:28 +00:00
|
|
|
|
virtual void numberOperate(V3Number& out, const V3Number& lhs, const V3Number& rhs, const V3Number& ths) {
|
|
|
|
|
if (lhs.isNeqZero()) out.opAssign(rhs); else out.opAssign(ths); }
|
2016-11-05 14:06:43 +00:00
|
|
|
|
AstNode* condp() const { return op1p(); } // op1 = Condition
|
|
|
|
|
AstNode* expr1p() const { return op2p(); } // op2 = If true...
|
|
|
|
|
AstNode* expr2p() const { return op3p(); } // op3 = If false...
|
2009-12-29 03:19:03 +00:00
|
|
|
|
virtual string emitVerilog() { return "%k(%l %f? %r %k: %t)"; }
|
2008-06-30 00:02:24 +00:00
|
|
|
|
virtual string emitC() { return "VL_COND_%nq%lq%rq%tq(%nw,%lw,%rw,%tw, %P, %li, %ri, %ti)"; }
|
2006-08-26 11:35:28 +00:00
|
|
|
|
virtual bool cleanOut() { return false; } // clean if e1 & e2 clean
|
|
|
|
|
virtual bool cleanLhs() { return true; }
|
|
|
|
|
virtual bool cleanRhs() { return false; } virtual bool cleanThs() { return false; } // Propagates up
|
|
|
|
|
virtual bool sizeMattersLhs() { return false; } virtual bool sizeMattersRhs() { return false; }
|
|
|
|
|
virtual bool sizeMattersThs() { return false; }
|
|
|
|
|
virtual int instrCount() const { return instrCountBranch(); }
|
|
|
|
|
};
|
|
|
|
|
|
2014-09-12 01:28:53 +00:00
|
|
|
|
class AstNodePreSel : public AstNode {
|
2011-12-01 00:32:33 +00:00
|
|
|
|
// Something that becomes an AstSel
|
2014-09-12 01:28:53 +00:00
|
|
|
|
public:
|
2006-08-26 11:35:28 +00:00
|
|
|
|
AstNodePreSel(FileLine* fl, AstNode* lhs, AstNode* rhs, AstNode* ths)
|
|
|
|
|
: AstNode(fl) {
|
|
|
|
|
setOp1p(lhs); setOp2p(rhs); setNOp3p(ths); }
|
2008-11-20 01:15:05 +00:00
|
|
|
|
ASTNODE_BASE_FUNCS(NodePreSel)
|
2016-11-05 14:06:43 +00:00
|
|
|
|
AstNode* lhsp() const { return op1p(); }
|
2009-10-25 20:53:55 +00:00
|
|
|
|
AstNode* fromp() const { return lhsp(); }
|
2016-11-05 14:06:43 +00:00
|
|
|
|
AstNode* rhsp() const { return op2p(); }
|
|
|
|
|
AstNode* thsp() const { return op3p(); }
|
2009-10-25 20:53:55 +00:00
|
|
|
|
AstAttrOf* attrp() const { return op4p()->castAttrOf(); }
|
2006-08-26 11:35:28 +00:00
|
|
|
|
void lhsp(AstNode* nodep) { return setOp1p(nodep); }
|
|
|
|
|
void rhsp(AstNode* nodep) { return setOp2p(nodep); }
|
|
|
|
|
void thsp(AstNode* nodep) { return setOp3p(nodep); }
|
2009-10-25 20:53:55 +00:00
|
|
|
|
void attrp(AstAttrOf* nodep) { return setOp4p((AstNode*)nodep); }
|
2006-08-26 11:35:28 +00:00
|
|
|
|
// METHODS
|
|
|
|
|
virtual V3Hash sameHash() const { return V3Hash(); }
|
|
|
|
|
virtual bool same(AstNode*) const { return true; }
|
|
|
|
|
};
|
|
|
|
|
|
2014-09-12 01:28:53 +00:00
|
|
|
|
class AstNodeStmt : public AstNode {
|
2006-08-26 11:35:28 +00:00
|
|
|
|
// Statement -- anything that's directly under a function
|
2014-09-12 01:28:53 +00:00
|
|
|
|
public:
|
2015-10-04 02:33:06 +00:00
|
|
|
|
explicit AstNodeStmt(FileLine* fl)
|
2006-08-26 11:35:28 +00:00
|
|
|
|
: AstNode(fl) {}
|
2008-11-20 01:15:05 +00:00
|
|
|
|
ASTNODE_BASE_FUNCS(NodeStmt)
|
2006-08-26 11:35:28 +00:00
|
|
|
|
// METHODS
|
2012-03-20 20:01:53 +00:00
|
|
|
|
virtual void addNextStmt(AstNode* newp, AstNode* belowp); // Stop statement searchback here
|
|
|
|
|
virtual void addBeforeStmt(AstNode* newp, AstNode* belowp); // Stop statement searchback here
|
2006-08-26 11:35:28 +00:00
|
|
|
|
};
|
|
|
|
|
|
2014-09-12 01:28:53 +00:00
|
|
|
|
class AstNodeAssign : public AstNodeStmt {
|
|
|
|
|
public:
|
2006-08-26 11:35:28 +00:00
|
|
|
|
AstNodeAssign(FileLine* fl, AstNode* lhsp, AstNode* rhsp)
|
|
|
|
|
: AstNodeStmt(fl) {
|
|
|
|
|
setOp1p(rhsp); setOp2p(lhsp);
|
2012-04-29 13:42:17 +00:00
|
|
|
|
dtypeFrom(lhsp);
|
2006-08-26 11:35:28 +00:00
|
|
|
|
}
|
2008-11-20 01:15:05 +00:00
|
|
|
|
ASTNODE_BASE_FUNCS(NodeAssign)
|
2006-08-26 11:35:28 +00:00
|
|
|
|
virtual AstNode* cloneType(AstNode* lhsp, AstNode* rhsp)=0; // Clone single node, just get same type back.
|
|
|
|
|
// So iteration hits the RHS which is "earlier" in execution order, it's op1, not op2
|
2016-11-05 14:06:43 +00:00
|
|
|
|
AstNode* rhsp() const { return op1p(); } // op1 = Assign from
|
|
|
|
|
AstNode* lhsp() const { return op2p(); } // op2 = Assign to
|
2006-08-26 11:35:28 +00:00
|
|
|
|
void rhsp(AstNode* np) { setOp1p(np); }
|
|
|
|
|
void lhsp(AstNode* np) { setOp2p(np); }
|
2012-04-14 15:03:38 +00:00
|
|
|
|
virtual bool hasDType() const { return true; }
|
2006-08-26 11:35:28 +00:00
|
|
|
|
virtual bool cleanRhs() { return true; }
|
|
|
|
|
virtual int instrCount() const { return widthInstrs(); }
|
|
|
|
|
virtual V3Hash sameHash() const { return V3Hash(); }
|
|
|
|
|
virtual bool same(AstNode*) const { return true; }
|
2009-12-29 03:19:03 +00:00
|
|
|
|
virtual string verilogKwd() const { return "="; }
|
2006-08-26 11:35:28 +00:00
|
|
|
|
};
|
|
|
|
|
|
2014-09-12 01:28:53 +00:00
|
|
|
|
class AstNodeFor : public AstNodeStmt {
|
|
|
|
|
public:
|
2006-08-26 11:35:28 +00:00
|
|
|
|
AstNodeFor(FileLine* fileline, AstNode* initsp, AstNode* condp,
|
2006-09-05 20:06:23 +00:00
|
|
|
|
AstNode* incsp, AstNode* bodysp)
|
2006-08-26 11:35:28 +00:00
|
|
|
|
: AstNodeStmt(fileline) {
|
2006-09-05 20:06:23 +00:00
|
|
|
|
addNOp1p(initsp); setOp2p(condp); addNOp3p(incsp); addNOp4p(bodysp);
|
2006-08-26 11:35:28 +00:00
|
|
|
|
}
|
2008-11-20 01:15:05 +00:00
|
|
|
|
ASTNODE_BASE_FUNCS(NodeFor)
|
2016-11-05 14:06:43 +00: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
|
2006-08-26 11:35:28 +00:00
|
|
|
|
virtual bool isGateOptimizable() const { return false; }
|
|
|
|
|
virtual int instrCount() const { return instrCountBranch(); }
|
|
|
|
|
virtual V3Hash sameHash() const { return V3Hash(); }
|
|
|
|
|
virtual bool same(AstNode* samep) const { return true; }
|
|
|
|
|
};
|
|
|
|
|
|
2014-09-12 01:28:53 +00:00
|
|
|
|
class AstNodeIf : public AstNodeStmt {
|
2006-08-26 11:35:28 +00:00
|
|
|
|
private:
|
|
|
|
|
AstBranchPred m_branchPred; // Branch prediction as taken/untaken?
|
|
|
|
|
public:
|
|
|
|
|
AstNodeIf(FileLine* fl, AstNode* condp, AstNode* ifsp, AstNode* elsesp)
|
|
|
|
|
: AstNodeStmt(fl) {
|
|
|
|
|
setOp1p(condp); addNOp2p(ifsp); addNOp3p(elsesp);
|
|
|
|
|
}
|
2008-11-20 01:15:05 +00:00
|
|
|
|
ASTNODE_BASE_FUNCS(NodeIf)
|
2006-08-26 11:35:28 +00: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); }
|
|
|
|
|
virtual bool isGateOptimizable() const { return false; }
|
2013-02-21 01:14:15 +00:00
|
|
|
|
virtual bool isGateDedupable() const { return true; }
|
2006-08-26 11:35:28 +00:00
|
|
|
|
virtual int instrCount() const { return instrCountBranch(); }
|
|
|
|
|
virtual V3Hash sameHash() const { return V3Hash(); }
|
|
|
|
|
virtual bool same(AstNode* samep) const { return true; }
|
|
|
|
|
void branchPred(AstBranchPred flag) { m_branchPred = flag; }
|
|
|
|
|
AstBranchPred branchPred() const { return m_branchPred; }
|
|
|
|
|
};
|
|
|
|
|
|
2014-09-12 01:28:53 +00:00
|
|
|
|
class AstNodeCase : public AstNodeStmt {
|
|
|
|
|
public:
|
2006-08-26 11:35:28 +00:00
|
|
|
|
AstNodeCase(FileLine* fl, AstNode* exprp, AstNode* casesp)
|
|
|
|
|
: AstNodeStmt(fl) {
|
|
|
|
|
setOp1p(exprp); addNOp2p(casesp);
|
|
|
|
|
}
|
2008-11-20 01:15:05 +00:00
|
|
|
|
ASTNODE_BASE_FUNCS(NodeCase)
|
2006-08-26 11:35:28 +00:00
|
|
|
|
virtual int instrCount() const { return instrCountBranch(); }
|
2016-11-05 14:06:43 +00:00
|
|
|
|
AstNode* exprp() const { return op1p(); } // op1 = case condition <expression>
|
2006-08-26 11:35:28 +00:00
|
|
|
|
AstCaseItem* itemsp() const { return op2p()->castCaseItem(); } // op2 = list of case expressions
|
2016-11-05 14:06:43 +00:00
|
|
|
|
AstNode* notParallelp() const { return op3p(); } // op3 = assertion code for non-full case's
|
2006-08-26 11:35:28 +00:00
|
|
|
|
void addItemsp(AstNode* nodep) { addOp2p(nodep); }
|
|
|
|
|
void addNotParallelp(AstNode* nodep) { setOp3p(nodep); }
|
|
|
|
|
};
|
|
|
|
|
|
2014-09-12 01:28:53 +00:00
|
|
|
|
class AstNodeSenItem : public AstNode {
|
2008-11-22 22:37:20 +00:00
|
|
|
|
// An AstSenItem or AstSenGate
|
2014-09-12 01:28:53 +00:00
|
|
|
|
public:
|
2015-10-04 02:33:06 +00:00
|
|
|
|
explicit AstNodeSenItem(FileLine* fl) : AstNode(fl) {}
|
2008-11-20 12:55:54 +00:00
|
|
|
|
ASTNODE_BASE_FUNCS(NodeSenItem)
|
|
|
|
|
virtual bool isClocked() const = 0;
|
|
|
|
|
virtual bool isCombo() const = 0;
|
|
|
|
|
virtual bool isInitial() const = 0;
|
|
|
|
|
virtual bool isSettle() const = 0;
|
|
|
|
|
virtual bool isNever() const = 0;
|
|
|
|
|
};
|
|
|
|
|
|
2006-08-26 11:35:28 +00:00
|
|
|
|
class AstNodeVarRef : public AstNodeMath {
|
2008-11-22 22:37:20 +00:00
|
|
|
|
// An AstVarRef or AstVarXRef
|
2006-08-26 11:35:28 +00:00
|
|
|
|
private:
|
|
|
|
|
bool m_lvalue; // Left hand side assignment
|
|
|
|
|
AstVar* m_varp; // [AfterLink] Pointer to variable itself
|
|
|
|
|
AstVarScope* m_varScopep; // Varscope for hierarchy
|
2009-11-08 02:05:02 +00:00
|
|
|
|
AstPackage* m_packagep; // Package hierarchy
|
2006-08-26 11:35:28 +00:00
|
|
|
|
string m_name; // Name of variable
|
|
|
|
|
string m_hiername; // Scope converted into name-> for emitting
|
|
|
|
|
bool m_hierThis; // Hiername points to "this" function
|
2012-02-21 01:48:13 +00:00
|
|
|
|
void init();
|
2006-08-26 11:35:28 +00:00
|
|
|
|
public:
|
|
|
|
|
AstNodeVarRef(FileLine* fl, const string& name, bool lvalue)
|
|
|
|
|
: AstNodeMath(fl), m_lvalue(lvalue), m_varp(NULL), m_varScopep(NULL),
|
2009-11-08 02:05:02 +00:00
|
|
|
|
m_packagep(NULL), m_name(name), m_hierThis(false) {
|
2012-02-21 01:48:13 +00:00
|
|
|
|
init();
|
2006-08-26 11:35:28 +00:00
|
|
|
|
}
|
|
|
|
|
AstNodeVarRef(FileLine* fl, const string& name, AstVar* varp, bool lvalue)
|
|
|
|
|
: AstNodeMath(fl), m_lvalue(lvalue), m_varp(varp), m_varScopep(NULL),
|
2009-11-08 02:05:02 +00:00
|
|
|
|
m_packagep(NULL), m_name(name), m_hierThis(false) {
|
2006-08-26 11:35:28 +00:00
|
|
|
|
// May have varp==NULL
|
2012-02-21 01:48:13 +00:00
|
|
|
|
init();
|
2006-08-26 11:35:28 +00:00
|
|
|
|
}
|
2008-11-20 01:15:05 +00:00
|
|
|
|
ASTNODE_BASE_FUNCS(NodeVarRef)
|
2012-04-14 15:03:38 +00:00
|
|
|
|
virtual bool hasDType() const { return true; }
|
2013-05-25 21:05:22 +00:00
|
|
|
|
virtual const char* broken() const;
|
2006-08-26 11:35:28 +00:00
|
|
|
|
virtual int instrCount() const { return widthInstrs(); }
|
|
|
|
|
virtual void cloneRelink();
|
|
|
|
|
virtual string name() const { return m_name; } // * = Var name
|
2009-07-22 19:21:41 +00:00
|
|
|
|
virtual void name(const string& name) { m_name = name; }
|
2006-08-26 11:35:28 +00:00
|
|
|
|
bool lvalue() const { return m_lvalue; }
|
|
|
|
|
void lvalue(bool lval) { m_lvalue=lval; } // Avoid using this; Set in constructor
|
|
|
|
|
AstVar* varp() const { return m_varp; } // [After Link] Pointer to variable
|
|
|
|
|
void varp(AstVar* varp) { m_varp=varp; }
|
|
|
|
|
AstVarScope* varScopep() const { return m_varScopep; }
|
|
|
|
|
void varScopep(AstVarScope* varscp) { m_varScopep=varscp; }
|
|
|
|
|
string hiername() const { return m_hiername; }
|
|
|
|
|
void hiername(const string& hn) { m_hiername = hn; }
|
|
|
|
|
bool hierThis() const { return m_hierThis; }
|
|
|
|
|
void hierThis(bool flag) { m_hierThis = flag; }
|
2009-11-08 02:05:02 +00:00
|
|
|
|
AstPackage* packagep() const { return m_packagep; }
|
|
|
|
|
void packagep(AstPackage* nodep) { m_packagep=nodep; }
|
2008-11-22 20:28:29 +00:00
|
|
|
|
// Know no children, and hot function, so skip iterator for speed
|
|
|
|
|
// See checkTreeIter also that asserts no children
|
2011-08-05 01:58:45 +00:00
|
|
|
|
// cppcheck-suppress functionConst
|
2016-11-27 13:11:38 +00:00
|
|
|
|
void iterateChildren(AstNVisitor& v) { }
|
2006-08-26 11:35:28 +00:00
|
|
|
|
};
|
|
|
|
|
|
2014-09-12 01:28:53 +00:00
|
|
|
|
class AstNodeText : public AstNode {
|
2006-08-26 11:35:28 +00:00
|
|
|
|
private:
|
|
|
|
|
string m_text;
|
|
|
|
|
public:
|
|
|
|
|
// Node that simply puts text into the output stream
|
|
|
|
|
AstNodeText(FileLine* fileline, const string& textp)
|
|
|
|
|
: AstNode(fileline) {
|
|
|
|
|
m_text = textp; // Copy it
|
|
|
|
|
}
|
2008-11-20 01:15:05 +00:00
|
|
|
|
ASTNODE_BASE_FUNCS(NodeText)
|
2009-12-05 15:38:49 +00:00
|
|
|
|
virtual void dump(ostream& str=cout);
|
2006-08-26 11:35:28 +00:00
|
|
|
|
virtual V3Hash sameHash() const { return V3Hash(text()); }
|
|
|
|
|
virtual bool same(AstNode* samep) const {
|
|
|
|
|
return text()==samep->castNodeText()->text(); }
|
2009-12-05 15:38:49 +00:00
|
|
|
|
const string& text() const { return m_text; }
|
2006-08-26 11:35:28 +00:00
|
|
|
|
};
|
|
|
|
|
|
2014-09-12 01:28:53 +00:00
|
|
|
|
class AstNodeDType : public AstNode {
|
2012-04-29 14:14:13 +00: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 01:28:53 +00:00
|
|
|
|
private:
|
2012-04-29 14:14:13 +00: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
|
|
|
|
|
AstNumeric m_numeric; // (also in AstTypeTable::Key) Node is signed
|
|
|
|
|
// Other members
|
|
|
|
|
bool m_generic; // Simple globally referenced type, don't garbage collect
|
|
|
|
|
static int s_uniqueNum; // Unique number assigned to each dtype during creation for IEEE matching
|
|
|
|
|
public:
|
|
|
|
|
// CONSTRUCTORS
|
2015-10-04 02:33:06 +00:00
|
|
|
|
explicit AstNodeDType(FileLine* fl) : AstNode(fl) {
|
2012-04-29 14:14:13 +00:00
|
|
|
|
m_width=0; m_widthMin=0; m_generic=false;
|
|
|
|
|
}
|
2009-11-02 13:06:04 +00:00
|
|
|
|
ASTNODE_BASE_FUNCS(NodeDType)
|
2012-04-29 14:14:13 +00:00
|
|
|
|
// ACCESSORS
|
2012-02-20 14:55:20 +00:00
|
|
|
|
virtual void dump(ostream& str);
|
2012-04-29 14:14:13 +00:00
|
|
|
|
virtual void dumpSmall(ostream& str);
|
2012-04-14 15:03:38 +00:00
|
|
|
|
virtual bool hasDType() const { return true; }
|
2009-11-15 13:52:19 +00:00
|
|
|
|
virtual AstBasicDType* basicp() const = 0; // (Slow) recurse down to find basic data type
|
2014-11-07 12:50:11 +00:00
|
|
|
|
virtual AstNodeDType* skipRefp() const = 0; // recurses over typedefs/const/enum to next non-typeref type
|
2013-11-01 02:39:26 +00:00
|
|
|
|
virtual AstNodeDType* skipRefToConstp() const = 0; // recurses over typedefs to next non-typeref-or-const type
|
2014-11-07 12:50:11 +00:00
|
|
|
|
virtual AstNodeDType* skipRefToEnump() const = 0; // recurses over typedefs/const to next non-typeref-or-enum/struct type
|
2009-11-05 03:31:53 +00:00
|
|
|
|
virtual int widthAlignBytes() const = 0; // (Slow) recurses - Structure alignment 1,2,4 or 8 bytes (arrays affect this)
|
|
|
|
|
virtual int widthTotalBytes() const = 0; // (Slow) recurses - Width in bytes rounding up 1,2,4,8,12,...
|
2012-02-21 01:48:13 +00:00
|
|
|
|
virtual bool maybePointedTo() const { return true; }
|
2012-04-29 14:14:13 +00:00
|
|
|
|
virtual AstNodeDType* virtRefDTypep() const { return NULL; } // Iff has a non-null refDTypep(), as generic node function
|
|
|
|
|
virtual void virtRefDTypep(AstNodeDType* nodep) { } // Iff has refDTypep(), set as generic node function
|
|
|
|
|
//
|
|
|
|
|
// Changing the width may confuse the data type resolution, so must clear TypeTable cache after use.
|
|
|
|
|
void widthForce(int width, int sized) { m_width=width; m_widthMin=sized; }
|
2013-01-12 21:19:25 +00:00
|
|
|
|
// For backward compatibility inherit width and signing from the subDType/base type
|
2012-04-29 14:14:13 +00:00
|
|
|
|
void widthFromSub(AstNodeDType* nodep) { m_width=nodep->m_width; m_widthMin=nodep->m_widthMin; m_numeric=nodep->m_numeric; }
|
|
|
|
|
//
|
|
|
|
|
int width() const { return m_width; }
|
|
|
|
|
void numeric(AstNumeric flag) { m_numeric = flag; }
|
|
|
|
|
bool isSigned() const { return m_numeric.isSigned(); }
|
|
|
|
|
bool isNosign() const { return m_numeric.isNosign(); }
|
|
|
|
|
AstNumeric numeric() const { return m_numeric; }
|
|
|
|
|
int widthWords() const { return VL_WORDS_I(width()); }
|
|
|
|
|
int widthMin() const { return m_widthMin?m_widthMin:m_width; } // If sized, the size, if unsized the min digits to represent it
|
|
|
|
|
int widthPow2() const;
|
|
|
|
|
void widthMinFromWidth() { m_widthMin = m_width; }
|
|
|
|
|
bool widthSized() const { return !m_widthMin || m_widthMin==m_width; }
|
|
|
|
|
bool generic() const { return m_generic; }
|
|
|
|
|
void generic(bool flag) { m_generic = flag; }
|
2012-02-29 02:33:17 +00:00
|
|
|
|
AstNodeDType* dtypeDimensionp(int depth);
|
2013-01-20 17:19:22 +00:00
|
|
|
|
pair<uint32_t,uint32_t> dimensions(bool includeBasic);
|
2013-01-15 02:49:22 +00:00
|
|
|
|
uint32_t arrayUnpackedElements(); // 1, or total multiplication of all dimensions
|
2012-04-29 14:14:13 +00:00
|
|
|
|
static int uniqueNumInc() { return ++s_uniqueNum; }
|
2009-11-02 13:06:04 +00:00
|
|
|
|
};
|
|
|
|
|
|
2014-09-12 01:28:53 +00:00
|
|
|
|
class AstNodeClassDType : public AstNodeDType {
|
2012-07-29 14:16:20 +00:00
|
|
|
|
private:
|
|
|
|
|
// TYPES
|
|
|
|
|
typedef map<string,AstMemberDType*> MemberNameMap;
|
|
|
|
|
// MEMBERS
|
|
|
|
|
bool m_packed;
|
|
|
|
|
MemberNameMap m_members;
|
|
|
|
|
public:
|
|
|
|
|
AstNodeClassDType(FileLine* fl, AstNumeric numericUnpack)
|
|
|
|
|
: AstNodeDType(fl) {
|
|
|
|
|
// AstNumeric::NOSIGN overloaded to indicate not packed
|
|
|
|
|
m_packed = (numericUnpack != AstNumeric::NOSIGN);
|
|
|
|
|
numeric(numericUnpack.isSigned() ? AstNumeric::SIGNED : AstNumeric::UNSIGNED);
|
|
|
|
|
}
|
|
|
|
|
ASTNODE_BASE_FUNCS(NodeClassDType)
|
2013-05-25 21:05:22 +00:00
|
|
|
|
virtual const char* broken() const;
|
2012-07-29 14:16:20 +00:00
|
|
|
|
virtual void dump(ostream& str);
|
|
|
|
|
// For basicp() we reuse the size to indicate a "fake" basic type of same size
|
|
|
|
|
virtual AstBasicDType* basicp() const { return findLogicDType(width(),width(),numeric())->castBasicDType(); }
|
|
|
|
|
virtual AstNodeDType* skipRefp() const { return (AstNodeDType*)this; }
|
2013-11-01 02:39:26 +00:00
|
|
|
|
virtual AstNodeDType* skipRefToConstp() const { return (AstNodeDType*)this; }
|
2014-11-07 12:50:11 +00:00
|
|
|
|
virtual AstNodeDType* skipRefToEnump() const { return (AstNodeDType*)this; }
|
2012-07-29 14:16:20 +00:00
|
|
|
|
virtual int widthAlignBytes() const; // (Slow) recurses - Structure alignment 1,2,4 or 8 bytes (arrays affect this)
|
|
|
|
|
virtual int widthTotalBytes() const; // (Slow) recurses - Width in bytes rounding up 1,2,4,8,12,...
|
|
|
|
|
// op1 = members
|
|
|
|
|
AstMemberDType* membersp() const { return op1p()->castMemberDType(); } // op1 = AstMember list
|
|
|
|
|
void addMembersp(AstNode* nodep) { addNOp1p(nodep); }
|
|
|
|
|
bool packed() const { return m_packed; }
|
2013-10-29 00:41:05 +00:00
|
|
|
|
bool packedUnsup() const { return true; } // packed() but as don't support unpacked, presently all structs
|
2012-07-29 14:16:20 +00:00
|
|
|
|
void clearCache() { m_members.clear(); }
|
|
|
|
|
void repairMemberCache();
|
|
|
|
|
AstMemberDType* findMember(const string& name) const {
|
|
|
|
|
MemberNameMap::const_iterator it = m_members.find(name);
|
|
|
|
|
return (it==m_members.end()) ? NULL : it->second;
|
|
|
|
|
}
|
2013-01-13 19:30:56 +00:00
|
|
|
|
int lsb() const { return 0; }
|
|
|
|
|
int msb() const { return dtypep()->width()-1; } // Packed classes look like arrays
|
2013-01-18 01:41:45 +00:00
|
|
|
|
VNumRange declRange() const { return VNumRange(msb(), lsb(), false); }
|
2012-07-29 14:16:20 +00:00
|
|
|
|
};
|
|
|
|
|
|
2014-09-12 01:28:53 +00:00
|
|
|
|
class AstNodeArrayDType : public AstNodeDType {
|
2013-01-12 21:19:25 +00:00
|
|
|
|
// Array data type, ie "some_dtype var_name [2:0]"
|
|
|
|
|
// Children: DTYPE (moved to refDTypep() in V3Width)
|
|
|
|
|
// Children: RANGE (array bounds)
|
|
|
|
|
private:
|
|
|
|
|
AstNodeDType* m_refDTypep; // Elements of this type (after widthing)
|
|
|
|
|
AstNode* rangenp() const { return op2p(); } // op2 = Array(s) of variable
|
|
|
|
|
public:
|
2015-10-04 02:33:06 +00:00
|
|
|
|
explicit AstNodeArrayDType(FileLine* fl) : AstNodeDType(fl) {
|
2013-02-03 18:27:37 +00:00
|
|
|
|
m_refDTypep = NULL;
|
|
|
|
|
}
|
2013-01-12 21:19:25 +00:00
|
|
|
|
ASTNODE_BASE_FUNCS(NodeArrayDType)
|
2013-01-13 19:30:56 +00:00
|
|
|
|
virtual void dump(ostream& str);
|
|
|
|
|
virtual void dumpSmall(ostream& str);
|
2013-05-25 21:05:22 +00:00
|
|
|
|
virtual const char* broken() const { BROKEN_RTN(!((m_refDTypep && !childDTypep() && m_refDTypep->brokeExists())
|
|
|
|
|
|| (!m_refDTypep && childDTypep()))); return NULL; }
|
2013-01-12 21:19:25 +00:00
|
|
|
|
virtual void cloneRelink() { if (m_refDTypep && m_refDTypep->clonep()) {
|
2016-11-09 02:16:22 +00:00
|
|
|
|
m_refDTypep = m_refDTypep->clonep();
|
2013-01-12 21:19:25 +00:00
|
|
|
|
}}
|
|
|
|
|
virtual bool same(AstNode* samep) const {
|
|
|
|
|
AstNodeArrayDType* sp = samep->castNodeArrayDType();
|
|
|
|
|
return (msb()==sp->msb()
|
|
|
|
|
&& subDTypep()==sp->subDTypep()
|
|
|
|
|
&& rangenp()->sameTree(sp->rangenp())); } // HashedDT doesn't recurse, so need to check children
|
|
|
|
|
virtual V3Hash sameHash() const { return V3Hash(V3Hash(m_refDTypep),V3Hash(msb()),V3Hash(lsb())); }
|
|
|
|
|
AstNodeDType* getChildDTypep() const { return childDTypep(); }
|
|
|
|
|
AstNodeDType* childDTypep() const { return op1p()->castNodeDType(); } // op1 = Range of variable
|
|
|
|
|
void childDTypep(AstNodeDType* nodep) { setOp1p(nodep); }
|
|
|
|
|
AstNodeDType* subDTypep() const { return m_refDTypep ? m_refDTypep : childDTypep(); }
|
|
|
|
|
void refDTypep(AstNodeDType* nodep) { m_refDTypep = nodep; }
|
|
|
|
|
virtual AstNodeDType* virtRefDTypep() const { return m_refDTypep; }
|
|
|
|
|
virtual void virtRefDTypep(AstNodeDType* nodep) { refDTypep(nodep); }
|
|
|
|
|
AstRange* rangep() const { return op2p()->castRange(); } // op2 = Array(s) of variable
|
|
|
|
|
void rangep(AstRange* nodep);
|
|
|
|
|
// METHODS
|
|
|
|
|
virtual AstBasicDType* basicp() const { return subDTypep()->basicp(); } // (Slow) recurse down to find basic data type
|
|
|
|
|
virtual AstNodeDType* skipRefp() const { return (AstNodeDType*)this; }
|
2013-11-01 02:39:26 +00:00
|
|
|
|
virtual AstNodeDType* skipRefToConstp() const { return (AstNodeDType*)this; }
|
2014-11-07 12:50:11 +00:00
|
|
|
|
virtual AstNodeDType* skipRefToEnump() const { return (AstNodeDType*)this; }
|
2013-01-12 21:19:25 +00:00
|
|
|
|
virtual int widthAlignBytes() const { return subDTypep()->widthAlignBytes(); }
|
|
|
|
|
virtual int widthTotalBytes() const { return elementsConst() * subDTypep()->widthTotalBytes(); }
|
|
|
|
|
int msb() const;
|
|
|
|
|
int lsb() const;
|
|
|
|
|
int elementsConst() const;
|
2013-01-18 01:41:45 +00:00
|
|
|
|
VNumRange declRange() const;
|
2013-01-12 21:19:25 +00:00
|
|
|
|
};
|
|
|
|
|
|
2014-09-12 01:28:53 +00:00
|
|
|
|
class AstNodeSel : public AstNodeBiop {
|
2006-08-26 11:35:28 +00:00
|
|
|
|
// Single bit range extraction, perhaps with non-constant selection or array selection
|
2014-09-12 01:28:53 +00:00
|
|
|
|
public:
|
2006-08-26 11:35:28 +00:00
|
|
|
|
AstNodeSel(FileLine* fl, AstNode* fromp, AstNode* bitp)
|
|
|
|
|
:AstNodeBiop(fl, fromp, bitp) {}
|
2009-11-02 13:06:04 +00:00
|
|
|
|
ASTNODE_BASE_FUNCS(NodeSel)
|
2016-11-05 14:06:43 +00:00
|
|
|
|
AstNode* fromp() const { return op1p(); } // op1 = Extracting what (NULL=TBD during parsing)
|
2010-01-19 15:52:11 +00:00
|
|
|
|
void fromp(AstNode* nodep) { setOp1p(nodep); }
|
2016-11-05 14:06:43 +00:00
|
|
|
|
AstNode* bitp() const { return op2p(); } // op2 = Msb selection expression
|
2010-01-19 15:52:11 +00:00
|
|
|
|
void bitp(AstNode* nodep) { setOp2p(nodep); }
|
2006-08-26 11:35:28 +00:00
|
|
|
|
int bitConst() const;
|
2012-04-14 15:03:38 +00:00
|
|
|
|
virtual bool hasDType() const { return true; }
|
2006-08-26 11:35:28 +00:00
|
|
|
|
};
|
|
|
|
|
|
2014-09-12 01:28:53 +00:00
|
|
|
|
class AstNodeStream : public AstNodeBiop {
|
2014-04-10 00:29:35 +00:00
|
|
|
|
// Verilog {rhs{lhs}} - Note rhsp() is the slice size, not the lhsp()
|
2014-09-12 01:28:53 +00:00
|
|
|
|
public:
|
2014-04-10 00:29:35 +00:00
|
|
|
|
AstNodeStream(FileLine* fl, AstNode* lhsp, AstNode* rhsp) : AstNodeBiop(fl, lhsp, rhsp) {
|
|
|
|
|
if (lhsp->dtypep()) {
|
|
|
|
|
dtypeSetLogicSized(lhsp->dtypep()->width(), lhsp->dtypep()->width(), AstNumeric::UNSIGNED);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
ASTNODE_BASE_FUNCS(NodeStream)
|
|
|
|
|
};
|
|
|
|
|
|
2006-08-26 11:35:28 +00:00
|
|
|
|
//######################################################################
|
|
|
|
|
// Tasks/functions common handling
|
|
|
|
|
|
2014-09-12 01:28:53 +00:00
|
|
|
|
class AstNodeFTask : public AstNode {
|
2006-08-26 11:35:28 +00:00
|
|
|
|
private:
|
|
|
|
|
string m_name; // Name of task
|
2009-12-03 11:55:29 +00:00
|
|
|
|
string m_cname; // Name of task if DPI import
|
2009-11-03 03:14:11 +00:00
|
|
|
|
bool m_taskPublic:1; // Public task
|
2009-11-03 03:50:31 +00:00
|
|
|
|
bool m_attrIsolateAssign:1;// User isolate_assignments attribute
|
2009-12-03 11:55:29 +00:00
|
|
|
|
bool m_prototype:1; // Just a prototype
|
2009-12-20 13:27:00 +00:00
|
|
|
|
bool m_dpiExport:1; // DPI exported
|
2009-12-03 11:55:29 +00:00
|
|
|
|
bool m_dpiImport:1; // DPI imported
|
|
|
|
|
bool m_dpiContext:1; // DPI import context
|
|
|
|
|
bool m_dpiTask:1; // DPI import task (vs. void function)
|
|
|
|
|
bool m_pure:1; // DPI import pure
|
2006-08-26 11:35:28 +00:00
|
|
|
|
public:
|
|
|
|
|
AstNodeFTask(FileLine* fileline, const string& name, AstNode* stmtsp)
|
|
|
|
|
: AstNode(fileline)
|
2011-07-24 19:01:51 +00:00
|
|
|
|
, m_name(name), m_taskPublic(false)
|
2009-12-03 11:55:29 +00:00
|
|
|
|
, m_attrIsolateAssign(false), m_prototype(false)
|
2009-12-20 13:27:00 +00:00
|
|
|
|
, m_dpiExport(false), m_dpiImport(false), m_dpiContext(false)
|
|
|
|
|
, m_dpiTask(false), m_pure(false) {
|
2006-08-26 11:35:28 +00:00
|
|
|
|
addNOp3p(stmtsp);
|
2009-12-03 11:55:29 +00:00
|
|
|
|
cname(name); // Might be overridden by dpi import/export
|
2006-08-26 11:35:28 +00:00
|
|
|
|
}
|
2008-11-20 01:15:05 +00:00
|
|
|
|
ASTNODE_BASE_FUNCS(NodeFTask)
|
2006-08-26 11:35:28 +00:00
|
|
|
|
virtual void dump(ostream& str=cout);
|
|
|
|
|
virtual string name() const { return m_name; } // * = Var name
|
2006-10-05 00:45:39 +00:00
|
|
|
|
virtual bool maybePointedTo() const { return true; }
|
2015-09-18 23:06:15 +00:00
|
|
|
|
virtual bool isGateOptimizable() const { return !((m_dpiExport || m_dpiImport) && !m_pure); }
|
2006-08-26 11:35:28 +00:00
|
|
|
|
// {AstFunc only} op1 = Range output variable
|
2009-07-22 19:21:41 +00:00
|
|
|
|
virtual void name(const string& name) { m_name = name; }
|
2009-12-03 11:55:29 +00:00
|
|
|
|
string cname() const { return m_cname; }
|
|
|
|
|
void cname(const string& cname) { m_cname = cname; }
|
|
|
|
|
// op1 = Output variable (functions only, NULL for tasks)
|
2016-11-05 14:06:43 +00:00
|
|
|
|
AstNode* fvarp() const { return op1p(); }
|
2009-12-03 11:55:29 +00:00
|
|
|
|
void addFvarp(AstNode* nodep) { addNOp1p(nodep); }
|
2010-01-25 01:53:24 +00:00
|
|
|
|
bool isFunction() const { return fvarp()!=NULL; }
|
2009-12-03 11:55:29 +00:00
|
|
|
|
// op3 = Statements/Ports/Vars
|
2016-11-05 14:06:43 +00:00
|
|
|
|
AstNode* stmtsp() const { return op3p(); } // op3 = List of statements
|
2009-10-31 14:08:38 +00:00
|
|
|
|
void addStmtsp(AstNode* nodep) { addNOp3p(nodep); }
|
2009-12-20 13:27:00 +00:00
|
|
|
|
// op4 = scope name
|
|
|
|
|
AstScopeName* scopeNamep() const { return op4p()->castScopeName(); }
|
|
|
|
|
void scopeNamep(AstNode* nodep) { setNOp4p(nodep); }
|
2006-08-26 11:35:28 +00:00
|
|
|
|
void taskPublic(bool flag) { m_taskPublic=flag; }
|
|
|
|
|
bool taskPublic() const { return m_taskPublic; }
|
2009-11-03 03:50:31 +00:00
|
|
|
|
void attrIsolateAssign(bool flag) { m_attrIsolateAssign = flag; }
|
|
|
|
|
bool attrIsolateAssign() const { return m_attrIsolateAssign; }
|
2009-12-03 11:55:29 +00:00
|
|
|
|
void prototype(bool flag) { m_prototype = flag; }
|
|
|
|
|
bool prototype() const { return m_prototype; }
|
2009-12-20 13:27:00 +00:00
|
|
|
|
void dpiExport(bool flag) { m_dpiExport = flag; }
|
|
|
|
|
bool dpiExport() const { return m_dpiExport; }
|
2009-12-03 11:55:29 +00:00
|
|
|
|
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 dpiTask(bool flag) { m_dpiTask = flag; }
|
|
|
|
|
bool dpiTask() const { return m_dpiTask; }
|
|
|
|
|
void pure(bool flag) { m_pure = flag; }
|
|
|
|
|
bool pure() const { return m_pure; }
|
2006-08-26 11:35:28 +00:00
|
|
|
|
};
|
|
|
|
|
|
2014-09-12 01:28:53 +00:00
|
|
|
|
class AstNodeFTaskRef : public AstNode {
|
2006-08-26 11:35:28 +00:00
|
|
|
|
// A reference to a task (or function)
|
|
|
|
|
private:
|
|
|
|
|
AstNodeFTask* m_taskp; // [AfterLink] Pointer to task referenced
|
|
|
|
|
string m_name; // Name of variable
|
|
|
|
|
string m_dotted; // Dotted part of scope to task or ""
|
2007-05-22 12:15:01 +00:00
|
|
|
|
string m_inlinedDots; // Dotted hierarchy flattened out
|
2009-11-08 02:05:02 +00:00
|
|
|
|
AstPackage* m_packagep; // Package hierarchy
|
2006-08-26 11:35:28 +00:00
|
|
|
|
public:
|
2006-12-21 21:53:51 +00:00
|
|
|
|
AstNodeFTaskRef(FileLine* fl, AstNode* namep, AstNode* pinsp)
|
2006-08-26 11:35:28 +00:00
|
|
|
|
:AstNode(fl)
|
2009-11-08 02:05:02 +00:00
|
|
|
|
, m_taskp(NULL), m_packagep(NULL) {
|
2008-06-10 01:25:10 +00:00
|
|
|
|
setOp1p(namep); addNOp2p(pinsp);
|
2006-08-26 11:35:28 +00:00
|
|
|
|
}
|
2009-12-04 12:05:44 +00:00
|
|
|
|
AstNodeFTaskRef(FileLine* fl, const string& name, AstNode* pinsp)
|
|
|
|
|
:AstNode(fl)
|
|
|
|
|
, m_taskp(NULL), m_name(name), m_packagep(NULL) {
|
|
|
|
|
addNOp2p(pinsp);
|
|
|
|
|
}
|
2008-11-20 01:15:05 +00:00
|
|
|
|
ASTNODE_BASE_FUNCS(NodeFTaskRef)
|
2013-05-25 21:05:22 +00:00
|
|
|
|
virtual const char* broken() const { BROKEN_RTN(m_taskp && !m_taskp->brokeExists()); return NULL; }
|
2006-08-26 11:35:28 +00:00
|
|
|
|
virtual void cloneRelink() { if (m_taskp && m_taskp->clonep()) {
|
2016-11-09 02:16:22 +00:00
|
|
|
|
m_taskp = m_taskp->clonep();
|
2006-08-26 11:35:28 +00:00
|
|
|
|
}}
|
|
|
|
|
virtual void dump(ostream& str=cout);
|
|
|
|
|
virtual string name() const { return m_name; } // * = Var name
|
2015-09-18 23:06:15 +00:00
|
|
|
|
virtual bool isGateOptimizable() const { return m_taskp && m_taskp->isGateOptimizable(); }
|
2006-08-26 11:35:28 +00:00
|
|
|
|
string dotted() const { return m_dotted; } // * = Scope name or ""
|
|
|
|
|
string prettyDotted() const { return prettyName(dotted()); }
|
|
|
|
|
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; }
|
2009-07-22 19:21:41 +00:00
|
|
|
|
virtual void name(const string& name) { m_name = name; }
|
2006-12-21 21:53:51 +00:00
|
|
|
|
void dotted(const string& name) { m_dotted = name; }
|
2009-11-08 02:05:02 +00:00
|
|
|
|
AstPackage* packagep() const { return m_packagep; }
|
|
|
|
|
void packagep(AstPackage* nodep) { m_packagep=nodep; }
|
2006-12-21 21:53:51 +00:00
|
|
|
|
// op1 = namep
|
|
|
|
|
AstNode* namep() const { return op1p(); }
|
|
|
|
|
// op2 = Pin interconnection list
|
2016-11-05 14:06:43 +00:00
|
|
|
|
AstNode* pinsp() const { return op2p(); }
|
2006-12-21 21:53:51 +00:00
|
|
|
|
void addPinsp(AstNode* nodep) { addOp2p(nodep); }
|
2009-12-05 15:38:49 +00:00
|
|
|
|
// op3 = scope tracking
|
|
|
|
|
AstScopeName* scopeNamep() const { return op3p()->castScopeName(); }
|
|
|
|
|
void scopeNamep(AstNode* nodep) { setNOp3p(nodep); }
|
2006-08-26 11:35:28 +00:00
|
|
|
|
};
|
|
|
|
|
|
2014-09-12 01:28:53 +00:00
|
|
|
|
class AstNodeModule : public AstNode {
|
2009-11-07 11:20:20 +00:00
|
|
|
|
// A module, package, program or interface declaration;
|
|
|
|
|
// something that can live directly under the TOP,
|
|
|
|
|
// excluding $unit package stuff
|
|
|
|
|
private:
|
|
|
|
|
string m_name; // Name of the module
|
|
|
|
|
string m_origName; // Name of the module, ignoring name() changes, for dot lookup
|
|
|
|
|
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
|
2012-07-21 21:12:42 +00:00
|
|
|
|
bool m_dead:1; // LinkDot believes is dead; will remove in Dead visitors
|
2013-01-17 23:36:20 +00:00
|
|
|
|
bool m_internal:1; // Internally created
|
2009-11-07 11:20:20 +00:00
|
|
|
|
int m_level; // 1=top module, 2=cell off top module, ...
|
|
|
|
|
int m_varNum; // Incrementing variable number
|
2014-06-15 15:18:47 +00:00
|
|
|
|
int m_typeNum; // Incrementing implicit type number
|
2009-11-07 11:20:20 +00:00
|
|
|
|
public:
|
|
|
|
|
AstNodeModule(FileLine* fl, const string& name)
|
|
|
|
|
: AstNode (fl)
|
|
|
|
|
,m_name(name), m_origName(name)
|
2013-01-17 23:36:20 +00:00
|
|
|
|
,m_modPublic(false), m_modTrace(false), m_inLibrary(false), m_dead(false), m_internal(false)
|
2014-06-15 15:18:47 +00:00
|
|
|
|
,m_level(0), m_varNum(0), m_typeNum(0) { }
|
2009-11-07 11:20:20 +00:00
|
|
|
|
ASTNODE_BASE_FUNCS(NodeModule)
|
|
|
|
|
virtual void dump(ostream& str);
|
|
|
|
|
virtual bool maybePointedTo() const { return true; }
|
|
|
|
|
virtual string name() const { return m_name; }
|
2016-11-05 14:06:43 +00:00
|
|
|
|
AstNode* stmtsp() const { return op2p(); } // op2 = List of statements
|
2009-11-07 11:20:20 +00:00
|
|
|
|
AstActive* activesp() const { return op3p()->castActive(); } // op3 = List of i/sblocks
|
|
|
|
|
// METHODS
|
|
|
|
|
void addInlinesp(AstNode* nodep) { addOp1p(nodep); }
|
|
|
|
|
void addStmtp(AstNode* nodep) { addOp2p(nodep); }
|
|
|
|
|
void addActivep(AstNode* nodep) { addOp3p(nodep); }
|
|
|
|
|
// ACCESSORS
|
|
|
|
|
virtual void name(const string& name) { m_name = name; }
|
|
|
|
|
string origName() const { return m_origName; }
|
|
|
|
|
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; }
|
|
|
|
|
bool isTop() const { return level()==1; }
|
|
|
|
|
int varNumGetInc() { return ++m_varNum; }
|
2014-06-15 15:18:47 +00:00
|
|
|
|
int typeNumGetInc() { return ++m_typeNum; }
|
2009-11-07 11:20:20 +00: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; }
|
2012-07-21 21:12:42 +00:00
|
|
|
|
void dead(bool flag) { m_dead = flag; }
|
|
|
|
|
bool dead() const { return m_dead; }
|
2013-01-17 23:36:20 +00:00
|
|
|
|
void internal(bool flag) { m_internal = flag; }
|
|
|
|
|
bool internal() const { return m_internal; }
|
2009-11-07 11:20:20 +00:00
|
|
|
|
};
|
|
|
|
|
|
2006-08-26 11:35:28 +00:00
|
|
|
|
//######################################################################
|
|
|
|
|
|
|
|
|
|
#include "V3AstNodes.h"
|
|
|
|
|
|
|
|
|
|
#include "V3Ast__gen_impl.h" // From ./astgen
|
|
|
|
|
// Things like:
|
|
|
|
|
// inline AstAlways* AstNode::castAlways() { return dynamic_cast<AstAlways*>(this);}
|
|
|
|
|
|
|
|
|
|
//######################################################################
|
|
|
|
|
// Inline ACCESSORS
|
|
|
|
|
|
2012-04-29 14:14:13 +00:00
|
|
|
|
inline int AstNode::width() const { return dtypep() ? dtypep()->width() : 0; }
|
|
|
|
|
inline int AstNode::widthMin() const { return dtypep() ? dtypep()->widthMin() : 0; }
|
|
|
|
|
inline bool AstNode::width1() const { return dtypep() && dtypep()->width()==1; } // V3Const uses to know it can optimize
|
|
|
|
|
inline int AstNode::widthInstrs() const { return (!dtypep() ? 1 : (dtypep()->isWide() ? dtypep()->widthWords() : 1)); }
|
|
|
|
|
inline bool AstNode::isDouble() const { return dtypep() && dtypep()->castBasicDType() && dtypep()->castBasicDType()->isDouble(); }
|
2014-11-28 20:01:50 +00:00
|
|
|
|
inline bool AstNode::isString() const { return dtypep() && dtypep()->basicp() && dtypep()->basicp()->isString(); }
|
2012-04-29 14:14:13 +00:00
|
|
|
|
inline bool AstNode::isSigned() const { return dtypep() && dtypep()->isSigned(); }
|
2012-03-03 17:10:29 +00:00
|
|
|
|
|
2006-08-26 11:35:28 +00:00
|
|
|
|
inline bool AstNode::isZero() { return (this->castConst() && this->castConst()->num().isEqZero()); }
|
|
|
|
|
inline bool AstNode::isNeqZero() { return (this->castConst() && this->castConst()->num().isNeqZero()); }
|
|
|
|
|
inline bool AstNode::isOne() { return (this->castConst() && this->castConst()->num().isEqOne()); }
|
2011-11-30 23:50:21 +00:00
|
|
|
|
inline bool AstNode::isAllOnes() { return (this->castConst() && this->castConst()->isEqAllOnes()); }
|
|
|
|
|
inline bool AstNode::isAllOnesV() { return (this->castConst() && this->castConst()->isEqAllOnesV()); }
|
2016-02-04 01:44:31 +00:00
|
|
|
|
inline bool AstNode::sameTree(AstNode* node2p) { return sameTreeIter(this, node2p, true, false); }
|
|
|
|
|
inline bool AstNode::sameGateTree(AstNode* node2p) { return sameTreeIter(this, node2p, true, true); }
|
2006-08-26 11:35:28 +00:00
|
|
|
|
|
2012-04-29 14:14:13 +00:00
|
|
|
|
inline void AstNodeVarRef::init() { if (m_varp) dtypep(m_varp->dtypep()); }
|
2012-02-21 01:48:13 +00:00
|
|
|
|
|
2013-01-12 21:19:25 +00:00
|
|
|
|
inline void AstNodeArrayDType::rangep(AstRange* nodep) { setOp2p(nodep); }
|
|
|
|
|
inline int AstNodeArrayDType::msb() const { return rangep()->msbConst(); }
|
|
|
|
|
inline int AstNodeArrayDType::lsb() const { return rangep()->lsbConst(); }
|
|
|
|
|
inline int AstNodeArrayDType::elementsConst() const { return rangep()->elementsConst(); }
|
2013-01-18 01:41:45 +00:00
|
|
|
|
inline VNumRange AstNodeArrayDType::declRange() const { return VNumRange(msb(), lsb(), rangep()->littleEndian()); }
|
2013-01-12 21:19:25 +00:00
|
|
|
|
|
2013-05-28 01:39:19 +00:00
|
|
|
|
inline void AstIfaceRefDType::cloneRelink() {
|
2016-11-09 02:16:22 +00:00
|
|
|
|
if (m_cellp && m_cellp->clonep()) m_cellp = m_cellp->clonep();
|
|
|
|
|
if (m_ifacep && m_ifacep->clonep()) m_ifacep = m_ifacep->clonep();
|
|
|
|
|
if (m_modportp && m_modportp->clonep()) m_modportp = m_modportp->clonep(); }
|
2013-05-28 01:39:19 +00:00
|
|
|
|
|
2006-08-26 11:35:28 +00:00
|
|
|
|
#endif // Guard
|