2006-08-26 11:35:28 +00:00
|
|
|
|
//*************************************************************************
|
|
|
|
|
// DESCRIPTION: Verilator: Ast node structures
|
|
|
|
|
//
|
2008-04-25 12:14:27 +00:00
|
|
|
|
// Code available from: http://www.veripool.org/verilator
|
2006-08-26 11:35:28 +00:00
|
|
|
|
//
|
|
|
|
|
// AUTHORS: Wilson Snyder with Paul Wasson, Duane Gabli
|
|
|
|
|
//
|
|
|
|
|
//*************************************************************************
|
|
|
|
|
//
|
2009-01-02 16:47:39 +00:00
|
|
|
|
// Copyright 2003-2009 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.
|
|
|
|
|
//
|
|
|
|
|
//*************************************************************************
|
|
|
|
|
|
2006-12-18 19:20:45 +00:00
|
|
|
|
#include "config_build.h"
|
|
|
|
|
#include "verilatedos.h"
|
2008-06-30 17:11:25 +00:00
|
|
|
|
#include <cstdio>
|
|
|
|
|
#include <cstdarg>
|
2006-08-26 11:35:28 +00:00
|
|
|
|
#include <fstream>
|
|
|
|
|
#include <iomanip>
|
|
|
|
|
#include <vector>
|
|
|
|
|
#include <algorithm>
|
|
|
|
|
|
|
|
|
|
#include "V3Ast.h"
|
|
|
|
|
#include "V3File.h"
|
|
|
|
|
#include "V3Global.h"
|
|
|
|
|
|
|
|
|
|
//======================================================================
|
|
|
|
|
// Special methods
|
|
|
|
|
|
|
|
|
|
// We need these here, because the classes they point to aren't defined when we declare the class
|
|
|
|
|
bool AstNodeVarRef::broken() const { return ((m_varScopep && !m_varScopep->brokeExists())
|
|
|
|
|
|| (m_varp && !m_varp->brokeExists())); }
|
|
|
|
|
|
|
|
|
|
void AstNodeVarRef::cloneRelink() {
|
|
|
|
|
if (m_varp && m_varp->clonep()) { m_varp = m_varp->clonep()->castVar(); }
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
int AstNodeSel::bitConst() const {
|
2008-10-06 13:59:22 +00:00
|
|
|
|
AstConst* constp=bitp()->castConst(); return (constp?constp->toSInt():0);
|
2006-08-26 11:35:28 +00:00
|
|
|
|
}
|
|
|
|
|
|
2009-11-05 03:31:53 +00:00
|
|
|
|
int AstBasicDType::widthAlignBytes() const {
|
|
|
|
|
if (width()<=8) return 1;
|
|
|
|
|
else if (width()<=16) return 2;
|
|
|
|
|
else if (isQuad()) return 8;
|
|
|
|
|
else return 4;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
int AstBasicDType::widthTotalBytes() const {
|
|
|
|
|
if (width()<=8) return 1;
|
|
|
|
|
else if (width()<=16) return 2;
|
|
|
|
|
else if (isQuad()) return 8;
|
|
|
|
|
else return widthWords()*(VL_WORDSIZE/8);
|
|
|
|
|
}
|
|
|
|
|
|
2006-08-26 11:35:28 +00:00
|
|
|
|
bool AstVar::isSigPublic() const {
|
2008-09-30 12:58:07 +00:00
|
|
|
|
return (m_sigPublic || (v3Global.opt.allPublic() && !isTemp() && !isGenVar()));
|
2006-08-26 11:35:28 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool AstVar::isScQuad() const {
|
2009-03-13 18:17:30 +00:00
|
|
|
|
return (isSc() && isQuad() && !isScBv());
|
2006-08-26 11:35:28 +00:00
|
|
|
|
}
|
|
|
|
|
|
2009-03-13 18:17:30 +00:00
|
|
|
|
bool AstVar::isScBv() const {
|
|
|
|
|
return (isSc() && width() >= v3Global.opt.pinsBv());
|
2006-08-26 11:35:28 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void AstVar::combineType(AstVarType type) {
|
|
|
|
|
if (type == AstVarType::SUPPLY0) type = AstVarType::WIRE;
|
|
|
|
|
if (type == AstVarType::SUPPLY1) type = AstVarType::WIRE;
|
|
|
|
|
m_varType=type; // For debugging prints only
|
|
|
|
|
// These flags get combined with the existing settings of the flags.
|
|
|
|
|
if (type==AstVarType::INPUT || type==AstVarType::INOUT)
|
|
|
|
|
m_input = true;
|
|
|
|
|
if (type==AstVarType::OUTPUT || type==AstVarType::INOUT)
|
|
|
|
|
m_output = true;
|
|
|
|
|
if (type==AstVarType::INOUT || type==AstVarType::TRIWIRE)
|
|
|
|
|
m_tristate = true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
string AstVar::verilogKwd() const {
|
2006-09-25 20:40:52 +00:00
|
|
|
|
if (isInout()) {
|
2006-08-26 11:35:28 +00:00
|
|
|
|
return "inout";
|
|
|
|
|
} else if (isInput()) {
|
|
|
|
|
return "input";
|
|
|
|
|
} else if (isOutput()) {
|
|
|
|
|
return "output";
|
2006-09-25 20:40:52 +00:00
|
|
|
|
} else if (isTristate()) {
|
|
|
|
|
return "tri";
|
2006-08-26 11:35:28 +00:00
|
|
|
|
} else if (varType()==AstVarType::WIRE) {
|
|
|
|
|
return "wire";
|
|
|
|
|
} else {
|
2009-11-03 03:14:11 +00:00
|
|
|
|
return dtypep()->name();
|
2006-08-26 11:35:28 +00:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2009-12-03 11:55:29 +00:00
|
|
|
|
string AstVar::vlArgType(bool named, bool forReturn) const {
|
|
|
|
|
if (forReturn) named=false;
|
|
|
|
|
if (forReturn) v3fatalSrc("verilator internal data is never passed as return, but as first argument");
|
|
|
|
|
string arg;
|
|
|
|
|
if (isWide() && isInOnly()) arg += "const ";
|
|
|
|
|
if (widthMin() <= 8) {
|
|
|
|
|
arg += "CData";
|
|
|
|
|
} else if (widthMin() <= 16) {
|
|
|
|
|
arg += "SData";
|
|
|
|
|
} else if (widthMin() <= VL_WORDSIZE) {
|
|
|
|
|
arg += "IData";
|
|
|
|
|
} else if (isQuad()) {
|
|
|
|
|
arg += "QData";
|
|
|
|
|
} else if (isWide()) {
|
|
|
|
|
arg += "WData"; // []'s added later
|
|
|
|
|
}
|
|
|
|
|
if (isWide()) {
|
|
|
|
|
arg += " (& "+name();
|
|
|
|
|
arg += ")["+cvtToStr(widthWords())+"]";
|
|
|
|
|
} else {
|
|
|
|
|
if (isOutput()) arg += "&";
|
|
|
|
|
if (named) arg += " "+name();
|
|
|
|
|
}
|
|
|
|
|
return arg;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
string AstVar::cpubArgType(bool named, bool forReturn) const {
|
|
|
|
|
if (forReturn) named=false;
|
|
|
|
|
string arg;
|
|
|
|
|
if (isWide() && isInOnly()) arg += "const ";
|
2006-10-05 14:53:17 +00:00
|
|
|
|
if (widthMin() == 1) {
|
2009-12-03 11:55:29 +00:00
|
|
|
|
arg += "bool";
|
2006-10-05 14:53:17 +00:00
|
|
|
|
} else if (widthMin() <= VL_WORDSIZE) {
|
2009-12-03 11:55:29 +00:00
|
|
|
|
arg += "uint32_t";
|
2009-03-13 18:17:30 +00:00
|
|
|
|
} else if (isWide()) {
|
2009-12-03 11:55:29 +00:00
|
|
|
|
arg += "uint32_t"; // []'s added later
|
2006-10-05 14:53:17 +00:00
|
|
|
|
} else {
|
2009-12-03 11:55:29 +00:00
|
|
|
|
arg += "uint64_t";
|
|
|
|
|
}
|
|
|
|
|
if (isWide()) {
|
|
|
|
|
if (forReturn) v3error("Unsupported: Public functions with >64 bit outputs; make an output of a public task instead");
|
|
|
|
|
arg += " (& "+name();
|
|
|
|
|
arg += ")["+cvtToStr(widthWords())+"]";
|
|
|
|
|
} else {
|
|
|
|
|
if (isOutput() && !forReturn) arg += "&";
|
|
|
|
|
if (named) arg += " "+name();
|
|
|
|
|
}
|
|
|
|
|
return arg;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
string AstVar::dpiArgType(bool named, bool forReturn) const {
|
|
|
|
|
if (forReturn) named=false;
|
|
|
|
|
string arg;
|
|
|
|
|
if (!basicp()) arg = "UNKNOWN";
|
|
|
|
|
if (isWide()) v3error("Unsupported: DPI functions with vectored outputs > 32-bits");
|
|
|
|
|
if (basicp()->isBitLogic()) {
|
|
|
|
|
if (widthMin() == 1) {
|
|
|
|
|
arg = "unsigned char";
|
|
|
|
|
if (!forReturn && isOutput()) arg += "*";
|
|
|
|
|
} else {
|
|
|
|
|
if (forReturn) {
|
|
|
|
|
arg = "svBitVecVal";
|
|
|
|
|
} else if (isInOnly()) {
|
|
|
|
|
arg = "const svBitVecVal*";
|
|
|
|
|
} else {
|
|
|
|
|
arg = "svBitVecVal*";
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
arg = basicp()->keyword().dpiType();
|
|
|
|
|
if (!forReturn && isOutput()) arg += "*";
|
2006-10-05 14:53:17 +00:00
|
|
|
|
}
|
2009-12-03 11:55:29 +00:00
|
|
|
|
if (named) arg += " "+name();
|
|
|
|
|
return arg;
|
2006-10-05 14:53:17 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
string AstVar::scType() const {
|
2009-03-13 18:17:30 +00:00
|
|
|
|
if (isScBv()) {
|
|
|
|
|
return (string("sc_bv<")+cvtToStr(widthMin())+"> "); // Keep the space so don't get >>
|
|
|
|
|
} else if (widthMin() == 1) {
|
2006-08-26 11:35:28 +00:00
|
|
|
|
return "bool";
|
|
|
|
|
} else if (widthMin() <= VL_WORDSIZE) {
|
2009-06-29 13:21:21 +00:00
|
|
|
|
if (widthMin() <= 8 && v3Global.opt.pinsUint8()) {
|
|
|
|
|
return "uint8_t";
|
|
|
|
|
} else if (widthMin() <= 16 && v3Global.opt.pinsUint8()) {
|
|
|
|
|
return "uint16_t";
|
|
|
|
|
} else {
|
|
|
|
|
return "uint32_t";
|
|
|
|
|
}
|
2006-08-26 11:35:28 +00:00
|
|
|
|
} else {
|
|
|
|
|
return "uint64_t";
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2009-11-05 03:31:53 +00:00
|
|
|
|
AstNodeDType* AstVar::dtypeDimensionp(int dimension) const {
|
|
|
|
|
// dimension passed from AstArraySel::dimension
|
|
|
|
|
// Dimension 0 means the VAR itself, 1 is the closest SEL to the AstVar,
|
|
|
|
|
// which is the lowest in the dtype list.
|
|
|
|
|
// ref order: a[1][2][3][4]
|
|
|
|
|
// Created as: reg [4] a [1][2][3];
|
|
|
|
|
// *or* reg a [1][2][3][4];
|
|
|
|
|
// // The bit select is optional; used only if "leftover" []'s
|
|
|
|
|
// SEL: SEL4(SEL3(SEL2(SEL1(VARREF0 a))))
|
|
|
|
|
// DECL: VAR a (ARRAYSEL0 (ARRAYSEL1 (ARRAYSEL2 (DT RANGE3))))
|
|
|
|
|
// *or* VAR a (ARRAYSEL0 (ARRAYSEL1 (ARRAYSEL2 (ARRAYSEL3 (DT))))
|
|
|
|
|
// SEL1 needs to select from entire variable which is a pointer to ARRAYSEL0
|
|
|
|
|
int dim = 0;
|
|
|
|
|
for (AstNodeDType* dtypep=this->dtypep(); dtypep; ) {
|
2009-11-07 04:16:06 +00:00
|
|
|
|
dtypep = dtypep->skipRefp(); // Skip AstRefDType/AstTypedef, or return same node
|
2009-11-05 03:31:53 +00:00
|
|
|
|
if (AstArrayDType* adtypep = dtypep->castArrayDType()) {
|
|
|
|
|
if ((dim++)==dimension) {
|
|
|
|
|
return dtypep;
|
|
|
|
|
}
|
|
|
|
|
dtypep = adtypep->dtypep();
|
|
|
|
|
continue;
|
2009-11-07 04:16:06 +00:00
|
|
|
|
}
|
|
|
|
|
else if (AstBasicDType* adtypep = dtypep->castBasicDType()) {
|
2009-11-05 03:31:53 +00:00
|
|
|
|
// AstBasicDType - nothing below, return null
|
|
|
|
|
if (adtypep->rangep()) {
|
|
|
|
|
if ((dim++) == dimension) {
|
|
|
|
|
return adtypep;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return NULL;
|
|
|
|
|
}
|
|
|
|
|
// Node no ->next in loop; use continue where necessary
|
|
|
|
|
break;
|
2006-08-26 11:35:28 +00:00
|
|
|
|
}
|
|
|
|
|
return NULL;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
uint32_t AstVar::arrayElements() const {
|
|
|
|
|
uint32_t entries=1;
|
2009-11-05 03:31:53 +00:00
|
|
|
|
for (AstNodeDType* dtypep=this->dtypep(); dtypep; ) {
|
2009-11-07 04:16:06 +00:00
|
|
|
|
dtypep = dtypep->skipRefp(); // Skip AstRefDType/AstTypedef, or return same node
|
2009-11-05 03:31:53 +00:00
|
|
|
|
if (AstArrayDType* adtypep = dtypep->castArrayDType()) {
|
|
|
|
|
entries *= adtypep->elementsConst();
|
|
|
|
|
dtypep = adtypep->dtypep();
|
2009-11-07 04:16:06 +00:00
|
|
|
|
}
|
|
|
|
|
else {
|
2009-11-05 03:31:53 +00:00
|
|
|
|
// AstBasicDType - nothing below, 1
|
|
|
|
|
break;
|
|
|
|
|
}
|
2006-08-26 11:35:28 +00:00
|
|
|
|
}
|
|
|
|
|
return entries;
|
|
|
|
|
}
|
|
|
|
|
|
2009-10-25 20:53:55 +00:00
|
|
|
|
// Special operators
|
2009-11-05 03:31:53 +00:00
|
|
|
|
int AstArraySel::dimension(AstNode* nodep) {
|
|
|
|
|
// How many dimensions is this reference from the base variable?
|
|
|
|
|
// nodep is typically the fromp() of a select; thus the first select
|
|
|
|
|
// is selecting from the entire variable type - effectively dimension 0.
|
|
|
|
|
// Dimension passed to AstVar::dtypeDimensionp; see comments there
|
2009-10-25 20:53:55 +00:00
|
|
|
|
int dim = 0;
|
|
|
|
|
while (nodep) {
|
|
|
|
|
if (nodep->castNodeSel()) { dim++; nodep=nodep->castNodeSel()->fromp(); continue; }
|
|
|
|
|
if (nodep->castNodePreSel()) { dim++; nodep=nodep->castNodePreSel()->fromp(); continue; }
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
return dim;
|
|
|
|
|
}
|
|
|
|
|
AstNode* AstArraySel::baseFromp(AstNode* nodep) { ///< What is the base variable (or const) this dereferences?
|
|
|
|
|
// Else AstArraySel etc; search for the base
|
|
|
|
|
while (nodep) {
|
|
|
|
|
if (nodep->castArraySel()) { nodep=nodep->castArraySel()->fromp(); continue; }
|
|
|
|
|
else if (nodep->castSel()) { nodep=nodep->castSel()->fromp(); continue; }
|
|
|
|
|
// AstNodeSelPre stashes the associated variable under a ATTROF so it isn't constified
|
|
|
|
|
else if (nodep->castAttrOf()) { nodep=nodep->castAttrOf()->fromp(); continue; }
|
|
|
|
|
else if (nodep->castNodePreSel()) {
|
|
|
|
|
if (nodep->castNodePreSel()->attrp()) {
|
|
|
|
|
nodep=nodep->castNodePreSel()->attrp();
|
|
|
|
|
} else {
|
|
|
|
|
nodep=nodep->castNodePreSel()->lhsp();
|
|
|
|
|
}
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
else break;
|
|
|
|
|
}
|
|
|
|
|
return nodep;
|
|
|
|
|
}
|
|
|
|
|
|
2006-08-26 11:35:28 +00:00
|
|
|
|
bool AstScope::broken() const {
|
|
|
|
|
return ((m_aboveScopep && !m_aboveScopep->brokeExists())
|
|
|
|
|
|| (m_aboveCellp && !m_aboveCellp->brokeExists())
|
2006-10-05 00:45:39 +00:00
|
|
|
|
|| !m_modp || !m_modp->brokeExists());
|
2006-08-26 11:35:28 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void AstScope::cloneRelink() {
|
|
|
|
|
if (m_aboveScopep && m_aboveScopep->clonep()) m_aboveScopep->clonep()->castScope();
|
|
|
|
|
if (m_aboveCellp && m_aboveCellp->clonep()) m_aboveCellp->clonep()->castCell();
|
2009-11-07 11:20:20 +00:00
|
|
|
|
if (m_modp && ((AstNode*)m_modp)->clonep()) ((AstNode*)m_modp)->clonep()->castNodeModule();
|
2006-08-26 11:35:28 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
string AstScope::nameDotless() const {
|
|
|
|
|
string dotless = shortName();
|
|
|
|
|
string::size_type pos;
|
|
|
|
|
while ((pos=dotless.find(".")) != string::npos) {
|
|
|
|
|
dotless.replace(pos, 1, "__");
|
|
|
|
|
}
|
|
|
|
|
return dotless;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool AstSenTree::hasClocked() {
|
|
|
|
|
if (!sensesp()) this->v3fatalSrc("SENTREE without any SENITEMs under it");
|
2008-11-20 12:55:54 +00:00
|
|
|
|
for (AstNodeSenItem* senp = sensesp(); senp; senp=senp->nextp()->castNodeSenItem()) {
|
2006-08-26 11:35:28 +00:00
|
|
|
|
if (senp->isClocked()) return true;
|
|
|
|
|
}
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
bool AstSenTree::hasSettle() {
|
|
|
|
|
if (!sensesp()) this->v3fatalSrc("SENTREE without any SENITEMs under it");
|
2008-11-20 12:55:54 +00:00
|
|
|
|
for (AstNodeSenItem* senp = sensesp(); senp; senp=senp->nextp()->castNodeSenItem()) {
|
2006-08-26 11:35:28 +00:00
|
|
|
|
if (senp->isSettle()) return true;
|
|
|
|
|
}
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
bool AstSenTree::hasInitial() {
|
|
|
|
|
if (!sensesp()) this->v3fatalSrc("SENTREE without any SENITEMs under it");
|
2008-11-20 12:55:54 +00:00
|
|
|
|
for (AstNodeSenItem* senp = sensesp(); senp; senp=senp->nextp()->castNodeSenItem()) {
|
2006-08-26 11:35:28 +00:00
|
|
|
|
if (senp->isInitial()) return true;
|
|
|
|
|
}
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
bool AstSenTree::hasCombo() {
|
|
|
|
|
if (!sensesp()) this->v3fatalSrc("SENTREE without any SENITEMs under it");
|
2008-11-20 12:55:54 +00:00
|
|
|
|
for (AstNodeSenItem* senp = sensesp(); senp; senp=senp->nextp()->castNodeSenItem()) {
|
2006-08-26 11:35:28 +00:00
|
|
|
|
if (senp->isCombo()) return true;
|
|
|
|
|
}
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
2009-10-09 00:42:45 +00:00
|
|
|
|
//======================================================================
|
|
|
|
|
// Special walking tree inserters
|
|
|
|
|
|
|
|
|
|
void AstNode::addBeforeStmt(AstNode* newp, AstNode*) {
|
|
|
|
|
if (!backp()) newp->v3fatalSrc("Can't find current statement to addBeforeStmt");
|
|
|
|
|
// Look up; virtual call will find where to put it
|
|
|
|
|
this->backp()->addBeforeStmt(newp, this);
|
|
|
|
|
}
|
|
|
|
|
void AstNode::addNextStmt(AstNode* newp, AstNode*) {
|
|
|
|
|
if (!backp()) newp->v3fatalSrc("Can't find current statement to addBeforeStmt");
|
|
|
|
|
// Look up; virtual call will find where to put it
|
|
|
|
|
this->backp()->addNextStmt(newp, this);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void AstNodeStmt::addBeforeStmt(AstNode* newp, AstNode*) {
|
|
|
|
|
// Insert newp before current node
|
|
|
|
|
this->addHereThisAsNext(newp);
|
|
|
|
|
}
|
|
|
|
|
void AstNodeStmt::addNextStmt(AstNode* newp, AstNode*) {
|
|
|
|
|
// Insert newp after current node
|
|
|
|
|
this->addNextHere(newp);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void AstWhile::addBeforeStmt(AstNode* newp, AstNode* belowp) {
|
|
|
|
|
// Special, as statements need to be put in different places
|
|
|
|
|
// Belowp is how we came to recurse up to this point
|
|
|
|
|
// Preconditions insert first just before themselves (the normal rule for other statement types)
|
|
|
|
|
if (belowp == precondsp()) {
|
|
|
|
|
// Must have been first statement in precondsp list, so newp is new first statement
|
|
|
|
|
belowp->addHereThisAsNext(newp);
|
|
|
|
|
} else if (belowp == condp()) {
|
|
|
|
|
// Goes before condition, IE in preconditions
|
|
|
|
|
addPrecondsp(newp);
|
|
|
|
|
} else if (belowp == bodysp()) {
|
|
|
|
|
// Was first statement in body, so new front
|
|
|
|
|
belowp->addHereThisAsNext(newp);
|
|
|
|
|
} else {
|
|
|
|
|
belowp->v3fatalSrc("Doesn't look like this was really under the while");
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
void AstWhile::addNextStmt(AstNode* newp, AstNode* belowp) {
|
|
|
|
|
// Special, as statements need to be put in different places
|
|
|
|
|
// Belowp is how we came to recurse up to this point
|
|
|
|
|
// Preconditions insert first just before themselves (the normal rule for other statement types)
|
|
|
|
|
if (belowp == precondsp()) {
|
|
|
|
|
// Next in precond list
|
|
|
|
|
belowp->addNextHere(newp);
|
|
|
|
|
} else if (belowp == condp()) {
|
|
|
|
|
// Becomes first statement in body, body may have been empty
|
|
|
|
|
if (bodysp()) {
|
|
|
|
|
bodysp()->addHereThisAsNext(newp);
|
|
|
|
|
} else {
|
|
|
|
|
addBodysp(newp);
|
|
|
|
|
}
|
|
|
|
|
} else if (belowp == bodysp()) {
|
|
|
|
|
// Next statement in body
|
|
|
|
|
belowp->addNextHere(newp);
|
|
|
|
|
} else {
|
|
|
|
|
belowp->v3fatalSrc("Doesn't look like this was really under the while");
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2006-08-26 11:35:28 +00:00
|
|
|
|
//======================================================================
|
|
|
|
|
// Per-type Debugging
|
|
|
|
|
|
|
|
|
|
void AstNode::dump(ostream& os) {
|
|
|
|
|
os<<typeName()<<" "<<(void*)this
|
|
|
|
|
//<<" "<<(void*)this->m_backp
|
|
|
|
|
<<" <e"<<dec<<editCount()
|
|
|
|
|
<<((editCount()>=editCountLast())?"#>":">")
|
|
|
|
|
<<" {"<<dec<<fileline()->lineno()<<"}"
|
|
|
|
|
<<" "<<(isSigned()?"s":"")
|
|
|
|
|
<<"w"<<(widthSized()?"":"u")<<width();
|
|
|
|
|
if (!widthSized()) os<<"/"<<widthMin();
|
2009-10-23 01:16:52 +00:00
|
|
|
|
if (name()!="") os<<" "<<AstNode::quoteName(name());
|
2006-08-26 11:35:28 +00:00
|
|
|
|
}
|
2009-05-07 22:28:05 +00:00
|
|
|
|
|
|
|
|
|
void AstAttrOf::dump(ostream& str) {
|
|
|
|
|
this->AstNode::dump(str);
|
|
|
|
|
str<<" ["<<attrType().ascii()<<"]";
|
|
|
|
|
}
|
2009-11-02 13:06:04 +00:00
|
|
|
|
void AstBasicDType::dump(ostream& str) {
|
|
|
|
|
this->AstNode::dump(str);
|
|
|
|
|
str<<" ["<<keyword().ascii()<<"]";
|
2009-11-03 03:14:11 +00:00
|
|
|
|
if (implicit()) str<<" [IMPLICIT]";
|
2009-11-02 13:06:04 +00:00
|
|
|
|
}
|
2006-08-26 11:35:28 +00:00
|
|
|
|
void AstCast::dump(ostream& str) {
|
|
|
|
|
this->AstNode::dump(str);
|
|
|
|
|
str<<" sz"<<size();
|
|
|
|
|
}
|
|
|
|
|
void AstCell::dump(ostream& str) {
|
|
|
|
|
this->AstNode::dump(str);
|
|
|
|
|
if (modp()) { str<<" -> "; modp()->dump(str); }
|
|
|
|
|
else { str<<" ->UNLINKED:"<<modName(); }
|
|
|
|
|
}
|
|
|
|
|
void AstCellInline::dump(ostream& str) {
|
|
|
|
|
this->AstNode::dump(str);
|
|
|
|
|
str<<" -> "<<origModName();
|
|
|
|
|
}
|
2008-03-26 14:58:30 +00:00
|
|
|
|
void AstDisplay::dump(ostream& str) {
|
|
|
|
|
this->AstNode::dump(str);
|
|
|
|
|
//str<<" "<<displayType().ascii();
|
|
|
|
|
}
|
2006-08-26 11:35:28 +00:00
|
|
|
|
void AstPin::dump(ostream& str) {
|
|
|
|
|
this->AstNode::dump(str);
|
|
|
|
|
if (modVarp()) { str<<" -> "; modVarp()->dump(str); }
|
|
|
|
|
else { str<<" ->UNLINKED"; }
|
2007-03-14 13:06:08 +00:00
|
|
|
|
if (svImplicit()) str<<" [.SV]";
|
2006-08-26 11:35:28 +00:00
|
|
|
|
}
|
2009-10-25 20:53:55 +00:00
|
|
|
|
void AstRange::dump(ostream& str) {
|
|
|
|
|
this->AstNode::dump(str);
|
|
|
|
|
if (littleEndian()) str<<" [LITTLE]";
|
|
|
|
|
}
|
2009-11-07 04:16:06 +00:00
|
|
|
|
void AstRefDType::dump(ostream& str) {
|
|
|
|
|
this->AstNode::dump(str);
|
|
|
|
|
if (defp()) { str<<" -> "; defp()->dump(str); }
|
|
|
|
|
else { str<<" -> UNLINKED"; }
|
|
|
|
|
}
|
2006-08-26 11:35:28 +00:00
|
|
|
|
void AstVarXRef::dump(ostream& str) {
|
|
|
|
|
this->AstNode::dump(str);
|
|
|
|
|
if (lvalue()) str<<" [LV] => ";
|
|
|
|
|
else str<<" [RV] <- ";
|
|
|
|
|
str<<dotted()<<". - ";
|
|
|
|
|
if (inlinedDots()!="") str<<" flat.="<<inlinedDots()<<" - ";
|
|
|
|
|
if (varScopep()) { varScopep()->dump(str); }
|
|
|
|
|
else if (varp()) { varp()->dump(str); }
|
|
|
|
|
else { str<<"UNLINKED"; }
|
|
|
|
|
}
|
2009-11-07 11:20:20 +00:00
|
|
|
|
void AstNodeModule::dump(ostream& str) {
|
2006-08-26 11:35:28 +00:00
|
|
|
|
this->AstNode::dump(str);
|
|
|
|
|
str<<" L"<<level();
|
|
|
|
|
if (modPublic()) str<<" [P]";
|
|
|
|
|
if (inLibrary()) str<<" [LIB]";
|
|
|
|
|
}
|
2009-11-10 00:07:59 +00:00
|
|
|
|
void AstPackageImport::dump(ostream& str) {
|
|
|
|
|
this->AstNode::dump(str);
|
|
|
|
|
str<<" -> "<<packagep();
|
|
|
|
|
}
|
2006-08-26 11:35:28 +00:00
|
|
|
|
void AstVarScope::dump(ostream& str) {
|
|
|
|
|
this->AstNode::dump(str);
|
|
|
|
|
if (isCircular()) str<<" [CIRC]";
|
|
|
|
|
if (varp()) { str<<" -> "; varp()->dump(str); }
|
|
|
|
|
else { str<<" ->UNLINKED"; }
|
|
|
|
|
}
|
|
|
|
|
void AstVarRef::dump(ostream& str) {
|
|
|
|
|
this->AstNode::dump(str);
|
|
|
|
|
if (lvalue()) str<<" [LV] => ";
|
|
|
|
|
else str<<" [RV] <- ";
|
|
|
|
|
if (varScopep()) { varScopep()->dump(str); }
|
|
|
|
|
else if (varp()) { varp()->dump(str); }
|
|
|
|
|
else { str<<"UNLINKED"; }
|
|
|
|
|
}
|
|
|
|
|
void AstVar::dump(ostream& str) {
|
|
|
|
|
this->AstNode::dump(str);
|
|
|
|
|
if (isSc()) str<<" [SC]";
|
2006-09-25 20:40:52 +00:00
|
|
|
|
if (isPrimaryIO()) str<<(isInout()?" [PIO]":(isInput()?" [PI]":" [PO]"));
|
|
|
|
|
else {
|
|
|
|
|
if (isInout()) str<<" [IO]";
|
|
|
|
|
else if (isInput()) str<<" [I]";
|
|
|
|
|
else if (isOutput()) str<<" [O]";
|
|
|
|
|
}
|
2006-08-26 11:35:28 +00:00
|
|
|
|
if (isUsedClock()) str<<" [C]";
|
|
|
|
|
if (isSigPublic()) str<<" [P]";
|
|
|
|
|
if (attrClockEn()) str<<" [aCLKEN]";
|
2007-01-18 00:51:26 +00:00
|
|
|
|
if (attrIsolateAssign()) str<<" [aISO]";
|
2006-08-26 11:35:28 +00:00
|
|
|
|
if (attrFileDescr()) str<<" [aFD]";
|
2006-10-11 15:41:42 +00:00
|
|
|
|
if (isFuncReturn()) str<<" [FUNCRTN]";
|
|
|
|
|
else if (isFuncLocal()) str<<" [FUNC]";
|
2006-08-26 11:35:28 +00:00
|
|
|
|
str<<" "<<varType();
|
|
|
|
|
}
|
|
|
|
|
void AstSenTree::dump(ostream& str) {
|
|
|
|
|
this->AstNode::dump(str);
|
|
|
|
|
if (isMulti()) str<<" [MULTI]";
|
|
|
|
|
}
|
|
|
|
|
void AstSenItem::dump(ostream& str) {
|
|
|
|
|
this->AstNode::dump(str);
|
2006-12-21 21:53:51 +00:00
|
|
|
|
str<<" ["<<edgeType().ascii()<<"]";
|
|
|
|
|
}
|
|
|
|
|
void AstParseRef::dump(ostream& str) {
|
|
|
|
|
this->AstNode::dump(str);
|
|
|
|
|
str<<" ["<<expect().ascii()<<"]";
|
2006-08-26 11:35:28 +00:00
|
|
|
|
}
|
|
|
|
|
void AstActive::dump(ostream& str) {
|
|
|
|
|
this->AstNode::dump(str);
|
|
|
|
|
str<<" => ";
|
|
|
|
|
if (sensesp()) { sensesp()->dump(str); }
|
|
|
|
|
else { str<<"UNLINKED"; }
|
|
|
|
|
}
|
|
|
|
|
void AstNodeFTaskRef::dump(ostream& str) {
|
|
|
|
|
this->AstNode::dump(str);
|
|
|
|
|
str<<" -> ";
|
|
|
|
|
if (dotted()!="") { str<<dotted()<<". - "; }
|
|
|
|
|
if (taskp()) { taskp()->dump(str); }
|
|
|
|
|
else { str<<"UNLINKED"; }
|
|
|
|
|
}
|
|
|
|
|
void AstNodeFTask::dump(ostream& str) {
|
|
|
|
|
this->AstNode::dump(str);
|
2006-10-11 15:41:42 +00:00
|
|
|
|
if (taskPublic()) str<<" [PUBLIC]";
|
2009-12-03 11:55:29 +00:00
|
|
|
|
if (prototype()) str<<" [PROTOTYPE]";
|
|
|
|
|
if (dpiImport()) str<<" [DPII]";
|
|
|
|
|
if (dpiImport() && cname()!=name()) str<<" [c="<<cname()<<"]";
|
2006-08-26 11:35:28 +00:00
|
|
|
|
}
|
2009-10-12 00:50:31 +00:00
|
|
|
|
void AstBegin::dump(ostream& str) {
|
|
|
|
|
this->AstNode::dump(str);
|
|
|
|
|
if (unnamed()) str<<" [UNNAMED]";
|
|
|
|
|
}
|
2006-08-26 11:35:28 +00:00
|
|
|
|
void AstCoverDecl::dump(ostream& str) {
|
|
|
|
|
this->AstNode::dump(str);
|
2008-12-12 20:34:02 +00:00
|
|
|
|
if (this->dataDeclNullp()) {
|
|
|
|
|
str<<" -> ";
|
|
|
|
|
this->dataDeclNullp()->dump(str);
|
|
|
|
|
} else {
|
|
|
|
|
if (binNum()) { str<<" bin"<<dec<<binNum(); }
|
|
|
|
|
}
|
2006-08-26 11:35:28 +00:00
|
|
|
|
}
|
|
|
|
|
void AstCoverInc::dump(ostream& str) {
|
|
|
|
|
this->AstNode::dump(str);
|
|
|
|
|
str<<" -> ";
|
|
|
|
|
if (declp()) { declp()->dump(str); }
|
|
|
|
|
else { str<<"%Error:UNLINKED"; }
|
|
|
|
|
}
|
|
|
|
|
void AstTraceInc::dump(ostream& str) {
|
|
|
|
|
this->AstNode::dump(str);
|
|
|
|
|
str<<" -> ";
|
|
|
|
|
if (declp()) { declp()->dump(str); }
|
|
|
|
|
else { str<<"%Error:UNLINKED"; }
|
|
|
|
|
}
|
|
|
|
|
void AstCFile::dump(ostream& str) {
|
|
|
|
|
this->AstNode::dump(str);
|
|
|
|
|
if (source()) str<<" [SRC]";
|
|
|
|
|
if (slow()) str<<" [SLOW]";
|
|
|
|
|
}
|
|
|
|
|
void AstCCall::dump(ostream& str) {
|
|
|
|
|
this->AstNode::dump(str);
|
|
|
|
|
if (funcp()) {
|
|
|
|
|
str<<" "<<funcp()->name()<<" => ";
|
|
|
|
|
funcp()->dump(str);
|
|
|
|
|
}
|
|
|
|
|
}
|
2008-08-06 21:09:33 +00:00
|
|
|
|
void AstCFunc::dump(ostream& str) {
|
|
|
|
|
this->AstNode::dump(str);
|
|
|
|
|
if (slow()) str<<" [SLOW]";
|
2009-12-03 11:55:29 +00:00
|
|
|
|
if (pure()) str<<" [PURE]";
|
|
|
|
|
if (dpiImport()) str<<" [DPII]";
|
2008-08-06 21:09:33 +00:00
|
|
|
|
}
|