Internals: Detab and fix spacing style issues. No functional change.

When diff, recommend using "git diff --ignore-all-space"
When merging, recommend using "git merge -Xignore-all-space"
This commit is contained in:
Wilson Snyder
2019-05-19 16:13:13 -04:00
parent 59d7d9e8c3
commit b83b606267
184 changed files with 33256 additions and 32136 deletions
+276 -265
View File
@@ -18,8 +18,8 @@
//
//*************************************************************************
// LinkParse TRANSFORMATIONS:
// Top-down traversal
// Move some attributes around
// Top-down traversal
// Move some attributes around
//*************************************************************************
#include "config_build.h"
@@ -42,43 +42,43 @@ class LinkParseVisitor : public AstNVisitor {
private:
// NODE STATE
// Cleared on netlist
// AstNode::user1() -> bool. True if processed
// AstNode::user2() -> bool. True if fileline recomputed
AstUser1InUse m_inuser1;
AstUser2InUse m_inuser2;
// AstNode::user1() -> bool. True if processed
// AstNode::user2() -> bool. True if fileline recomputed
AstUser1InUse m_inuser1;
AstUser2InUse m_inuser2;
// TYPES
typedef std::map<std::pair<void*,string>,AstTypedef*> ImplTypedefMap;
typedef std::set<FileLine*> FileLineSet;
// STATE
AstVar* m_varp; // Variable we're under
ImplTypedefMap m_implTypedef; // Created typedefs for each <container,name>
FileLineSet m_filelines; // Filelines that have been seen
bool m_inAlways; // Inside an always
bool m_inGenerate; // Inside a generate
bool m_needStart; // Need start marker on lower AstParse
AstNodeModule* m_valueModp; // If set, move AstVar->valuep() initial values to this module
AstNodeModule* m_modp; // Current module
AstNodeFTask* m_ftaskp; // Current task
AstNodeDType* m_dtypep; // Current data type
AstVar* m_varp; // Variable we're under
ImplTypedefMap m_implTypedef; // Created typedefs for each <container,name>
FileLineSet m_filelines; // Filelines that have been seen
bool m_inAlways; // Inside an always
bool m_inGenerate; // Inside a generate
bool m_needStart; // Need start marker on lower AstParse
AstNodeModule* m_valueModp; // If set, move AstVar->valuep() initial values to this module
AstNodeModule* m_modp; // Current module
AstNodeFTask* m_ftaskp; // Current task
AstNodeDType* m_dtypep; // Current data type
// METHODS
VL_DEBUG_FUNC; // Declare debug()
void cleanFileline(AstNode* nodep) {
if (!nodep->user2SetOnce()) { // Process once
// We make all filelines unique per AstNode. This allows us to
// later turn off messages on a fileline when an issue is found
// so that messages on replicated blocks occur only once,
// without suppressing other token's messages as a side effect.
// We could have verilog.l create a new one on every token,
// but that's a lot more structures than only doing AST nodes.
if (m_filelines.find(nodep->fileline()) != m_filelines.end()) {
nodep->fileline(new FileLine(nodep->fileline()));
}
m_filelines.insert(nodep->fileline());
}
if (!nodep->user2SetOnce()) { // Process once
// We make all filelines unique per AstNode. This allows us to
// later turn off messages on a fileline when an issue is found
// so that messages on replicated blocks occur only once,
// without suppressing other token's messages as a side effect.
// We could have verilog.l create a new one on every token,
// but that's a lot more structures than only doing AST nodes.
if (m_filelines.find(nodep->fileline()) != m_filelines.end()) {
nodep->fileline(new FileLine(nodep->fileline()));
}
m_filelines.insert(nodep->fileline());
}
}
string nameFromTypedef(AstNode* nodep) {
@@ -106,22 +106,22 @@ private:
// VISITs
virtual void visit(AstNodeFTask* nodep) {
if (!nodep->user1SetOnce()) { // Process only once.
cleanFileline(nodep);
m_ftaskp = nodep;
if (!nodep->user1SetOnce()) { // Process only once.
cleanFileline(nodep);
m_ftaskp = nodep;
iterateChildren(nodep);
m_ftaskp = NULL;
}
m_ftaskp = NULL;
}
}
virtual void visit(AstNodeFTaskRef* nodep) {
if (!nodep->user1SetOnce()) { // Process only once.
cleanFileline(nodep);
UINFO(5," "<<nodep<<endl);
AstNodeModule* upperValueModp = m_valueModp;
m_valueModp = NULL;
if (!nodep->user1SetOnce()) { // Process only once.
cleanFileline(nodep);
UINFO(5," "<<nodep<<endl);
AstNodeModule* upperValueModp = m_valueModp;
m_valueModp = NULL;
iterateChildren(nodep);
m_valueModp = upperValueModp;
}
m_valueModp = upperValueModp;
}
}
virtual void visit(AstNodeDType* nodep) {
visitIterateNodeDType(nodep);
@@ -135,78 +135,86 @@ private:
virtual void visit(AstNodeClassDType* nodep) {
if (nodep->name() == "") {
nodep->name(nameFromTypedef(nodep)); // Might still remain ""
}
}
visitIterateNodeDType(nodep);
}
virtual void visit(AstEnumItem* nodep) {
// Expand ranges
cleanFileline(nodep);
// Expand ranges
cleanFileline(nodep);
iterateChildren(nodep);
if (nodep->rangep()) {
if (nodep->rangep()) {
if (!VN_IS(nodep->rangep()->msbp(), Const)
|| !VN_IS(nodep->rangep()->lsbp(), Const)) nodep->v3error("Enum ranges must be integral, per spec");
int msb = nodep->rangep()->msbConst();
int lsb = nodep->rangep()->lsbConst();
int increment = (msb > lsb) ? -1 : 1;
int offset_from_init = 0;
AstNode* addp = NULL;
for (int i=msb; i!=(lsb+increment); i+=increment, offset_from_init++) {
string name = nodep->name() + cvtToStr(i);
AstNode* valuep = NULL;
if (nodep->valuep()) valuep = new AstAdd(nodep->fileline(), nodep->valuep()->cloneTree(true),
new AstConst(nodep->fileline(), AstConst::Unsized32(), offset_from_init));
AstNode* newp = new AstEnumItem(nodep->fileline(), name, NULL, valuep);
if (addp) addp = addp->addNextNull(newp);
else addp = newp;
}
nodep->replaceWith(addp);
nodep->deleteTree();
}
|| !VN_IS(nodep->rangep()->lsbp(), Const)) {
nodep->v3error("Enum ranges must be integral, per spec");
}
int msb = nodep->rangep()->msbConst();
int lsb = nodep->rangep()->lsbConst();
int increment = (msb > lsb) ? -1 : 1;
int offset_from_init = 0;
AstNode* addp = NULL;
for (int i=msb; i!=(lsb+increment); i+=increment, offset_from_init++) {
string name = nodep->name() + cvtToStr(i);
AstNode* valuep = NULL;
if (nodep->valuep()) valuep = new AstAdd
(nodep->fileline(),
nodep->valuep()->cloneTree(true),
new AstConst(nodep->fileline(),
AstConst::Unsized32(),
offset_from_init));
AstNode* newp = new AstEnumItem(nodep->fileline(), name, NULL, valuep);
if (addp) addp = addp->addNextNull(newp);
else addp = newp;
}
nodep->replaceWith(addp);
nodep->deleteTree();
}
}
virtual void visit(AstVar* nodep) {
cleanFileline(nodep);
cleanFileline(nodep);
if (VN_IS(nodep->subDTypep(), ParseTypeDType)) {
// It's a parameter type. Use a different node type for this.
// It's a parameter type. Use a different node type for this.
AstNodeDType* dtypep = VN_CAST(nodep->valuep(), NodeDType);
if (!dtypep) {
nodep->v3error("Parameter type's initial value isn't a type: "<<nodep->prettyName());
nodep->unlinkFrBack();
} else {
dtypep->unlinkFrBack();
AstNode* newp = new AstParamTypeDType(nodep->fileline(), nodep->varType(), nodep->name(),
VFlagChildDType(), dtypep);
nodep->replaceWith(newp); nodep->deleteTree(); VL_DANGLING(nodep);
}
return;
}
if (!dtypep) {
nodep->v3error("Parameter type's initial value isn't a type: "
<<nodep->prettyName());
nodep->unlinkFrBack();
} else {
dtypep->unlinkFrBack();
AstNode* newp = new AstParamTypeDType(nodep->fileline(),
nodep->varType(), nodep->name(),
VFlagChildDType(), dtypep);
nodep->replaceWith(newp); nodep->deleteTree(); VL_DANGLING(nodep);
}
return;
}
// We used modTrace before leveling, and we may now
// want to turn it off now that we know the levelizations
if (v3Global.opt.traceDepth()
&& m_modp
&& (m_modp->level()-1) > v3Global.opt.traceDepth()) {
m_modp->modTrace(false);
nodep->trace(false);
}
m_varp = nodep;
// We used modTrace before leveling, and we may now
// want to turn it off now that we know the levelizations
if (v3Global.opt.traceDepth()
&& m_modp
&& (m_modp->level()-1) > v3Global.opt.traceDepth()) {
m_modp->modTrace(false);
nodep->trace(false);
}
m_varp = nodep;
iterateChildren(nodep);
m_varp = NULL;
// temporaries under an always aren't expected to be blocking
if (m_inAlways) nodep->fileline()->modifyWarnOff(V3ErrorCode::BLKSEQ, true);
if (nodep->valuep()) {
// A variable with an = value can be three things:
FileLine* fl = nodep->valuep()->fileline();
// 1. Parameters and function inputs: It's a default to use if not overridden
m_varp = NULL;
// temporaries under an always aren't expected to be blocking
if (m_inAlways) nodep->fileline()->modifyWarnOff(V3ErrorCode::BLKSEQ, true);
if (nodep->valuep()) {
// A variable with an = value can be three things:
FileLine* fl = nodep->valuep()->fileline();
// 1. Parameters and function inputs: It's a default to use if not overridden
if (nodep->isParam() || (m_ftaskp && nodep->isNonOutput())) {
}
else if (!m_ftaskp && nodep->isNonOutput()) {
nodep->v3error("Unsupported: Default value on module input: "<<nodep->prettyName());
nodep->valuep()->unlinkFrBack()->deleteTree();
nodep->v3error("Unsupported: Default value on module input: "<<nodep->prettyName());
nodep->valuep()->unlinkFrBack()->deleteTree();
} // 2. Under modules, it's an initial value to be loaded at time 0 via an AstInitial
else if (m_valueModp) {
// Making an AstAssign (vs AstAssignW) to a wire is an error, suppress it
FileLine* newfl = new FileLine (fl);
FileLine* newfl = new FileLine(fl);
newfl->warnOff(V3ErrorCode::PROCASSWIRE, true);
nodep->addNextHere
(new AstInitial
@@ -217,164 +225,167 @@ private:
nodep->addNextHere
(new AstAssign(fl, new AstVarRef(fl, nodep->name(), true),
nodep->valuep()->unlinkFrBack()));
}
}
if (nodep->isIfaceRef() && !nodep->isIfaceParent()) {
// Only AstIfaceRefDType's at this point correspond to ports;
// haven't made additional ones for interconnect yet, so assert is simple
// What breaks later is we don't have a Scope/Cell representing the interface to attach to
if (m_modp->level()<=2) nodep->v3error("Unsupported: Interfaced port on top level module");
}
}
}
if (nodep->isIfaceRef() && !nodep->isIfaceParent()) {
// Only AstIfaceRefDType's at this point correspond to ports;
// haven't made additional ones for interconnect yet, so assert is simple
// What breaks later is we don't have a Scope/Cell representing
// the interface to attach to
if (m_modp->level()<=2) nodep->v3error("Unsupported: Interfaced port on top level module");
}
}
virtual void visit(AstAttrOf* nodep) {
cleanFileline(nodep);
cleanFileline(nodep);
iterateChildren(nodep);
if (nodep->attrType() == AstAttrType::DT_PUBLIC) {
if (nodep->attrType() == AstAttrType::DT_PUBLIC) {
AstTypedef* typep = VN_CAST(nodep->backp(), Typedef);
if (!typep) nodep->v3fatalSrc("Attribute not attached to typedef");
typep->attrPublic(true);
nodep->unlinkFrBack()->deleteTree(); VL_DANGLING(nodep);
}
else if (nodep->attrType() == AstAttrType::VAR_CLOCK) {
if (!m_varp) nodep->v3fatalSrc("Attribute not attached to variable");
m_varp->attrScClocked(true);
nodep->unlinkFrBack()->deleteTree(); VL_DANGLING(nodep);
}
else if (nodep->attrType() == AstAttrType::VAR_CLOCK_ENABLE) {
if (!m_varp) nodep->v3fatalSrc("Attribute not attached to variable");
m_varp->attrClockEn(true);
nodep->unlinkFrBack()->deleteTree(); VL_DANGLING(nodep);
}
else if (nodep->attrType() == AstAttrType::VAR_PUBLIC) {
if (!m_varp) nodep->v3fatalSrc("Attribute not attached to variable");
m_varp->sigUserRWPublic(true); m_varp->sigModPublic(true);
nodep->unlinkFrBack()->deleteTree(); VL_DANGLING(nodep);
}
else if (nodep->attrType() == AstAttrType::VAR_PUBLIC_FLAT) {
if (!m_varp) nodep->v3fatalSrc("Attribute not attached to variable");
m_varp->sigUserRWPublic(true);
nodep->unlinkFrBack()->deleteTree(); VL_DANGLING(nodep);
}
else if (nodep->attrType() == AstAttrType::VAR_PUBLIC_FLAT_RD) {
if (!m_varp) nodep->v3fatalSrc("Attribute not attached to variable");
m_varp->sigUserRdPublic(true);
nodep->unlinkFrBack()->deleteTree(); VL_DANGLING(nodep);
}
else if (nodep->attrType() == AstAttrType::VAR_PUBLIC_FLAT_RW) {
if (!m_varp) nodep->v3fatalSrc("Attribute not attached to variable");
m_varp->sigUserRWPublic(true);
nodep->unlinkFrBack()->deleteTree(); VL_DANGLING(nodep);
}
else if (nodep->attrType() == AstAttrType::VAR_ISOLATE_ASSIGNMENTS) {
if (!m_varp) nodep->v3fatalSrc("Attribute not attached to variable");
m_varp->attrIsolateAssign(true);
nodep->unlinkFrBack()->deleteTree(); VL_DANGLING(nodep);
}
else if (nodep->attrType() == AstAttrType::VAR_SFORMAT) {
if (!m_varp) nodep->v3fatalSrc("Attribute not attached to variable");
m_varp->attrSFormat(true);
nodep->unlinkFrBack()->deleteTree(); VL_DANGLING(nodep);
}
else if (nodep->attrType() == AstAttrType::VAR_SC_BV) {
if (!m_varp) nodep->v3fatalSrc("Attribute not attached to variable");
m_varp->attrScBv(true);
nodep->unlinkFrBack()->deleteTree(); VL_DANGLING(nodep);
}
else if (nodep->attrType() == AstAttrType::VAR_CLOCKER) {
if (!m_varp) nodep->v3fatalSrc("Attribute not attached to variable");
m_varp->attrClocker(AstVarAttrClocker::CLOCKER_YES);
nodep->unlinkFrBack()->deleteTree(); VL_DANGLING(nodep);
}
else if (nodep->attrType() == AstAttrType::VAR_NO_CLOCKER) {
if (!m_varp) nodep->v3fatalSrc("Attribute not attached to variable");
m_varp->attrClocker(AstVarAttrClocker::CLOCKER_NO);
nodep->unlinkFrBack()->deleteTree(); VL_DANGLING(nodep);
}
if (!typep) nodep->v3fatalSrc("Attribute not attached to typedef");
typep->attrPublic(true);
nodep->unlinkFrBack()->deleteTree(); VL_DANGLING(nodep);
}
else if (nodep->attrType() == AstAttrType::VAR_CLOCK) {
if (!m_varp) nodep->v3fatalSrc("Attribute not attached to variable");
m_varp->attrScClocked(true);
nodep->unlinkFrBack()->deleteTree(); VL_DANGLING(nodep);
}
else if (nodep->attrType() == AstAttrType::VAR_CLOCK_ENABLE) {
if (!m_varp) nodep->v3fatalSrc("Attribute not attached to variable");
m_varp->attrClockEn(true);
nodep->unlinkFrBack()->deleteTree(); VL_DANGLING(nodep);
}
else if (nodep->attrType() == AstAttrType::VAR_PUBLIC) {
if (!m_varp) nodep->v3fatalSrc("Attribute not attached to variable");
m_varp->sigUserRWPublic(true); m_varp->sigModPublic(true);
nodep->unlinkFrBack()->deleteTree(); VL_DANGLING(nodep);
}
else if (nodep->attrType() == AstAttrType::VAR_PUBLIC_FLAT) {
if (!m_varp) nodep->v3fatalSrc("Attribute not attached to variable");
m_varp->sigUserRWPublic(true);
nodep->unlinkFrBack()->deleteTree(); VL_DANGLING(nodep);
}
else if (nodep->attrType() == AstAttrType::VAR_PUBLIC_FLAT_RD) {
if (!m_varp) nodep->v3fatalSrc("Attribute not attached to variable");
m_varp->sigUserRdPublic(true);
nodep->unlinkFrBack()->deleteTree(); VL_DANGLING(nodep);
}
else if (nodep->attrType() == AstAttrType::VAR_PUBLIC_FLAT_RW) {
if (!m_varp) nodep->v3fatalSrc("Attribute not attached to variable");
m_varp->sigUserRWPublic(true);
nodep->unlinkFrBack()->deleteTree(); VL_DANGLING(nodep);
}
else if (nodep->attrType() == AstAttrType::VAR_ISOLATE_ASSIGNMENTS) {
if (!m_varp) nodep->v3fatalSrc("Attribute not attached to variable");
m_varp->attrIsolateAssign(true);
nodep->unlinkFrBack()->deleteTree(); VL_DANGLING(nodep);
}
else if (nodep->attrType() == AstAttrType::VAR_SFORMAT) {
if (!m_varp) nodep->v3fatalSrc("Attribute not attached to variable");
m_varp->attrSFormat(true);
nodep->unlinkFrBack()->deleteTree(); VL_DANGLING(nodep);
}
else if (nodep->attrType() == AstAttrType::VAR_SC_BV) {
if (!m_varp) nodep->v3fatalSrc("Attribute not attached to variable");
m_varp->attrScBv(true);
nodep->unlinkFrBack()->deleteTree(); VL_DANGLING(nodep);
}
else if (nodep->attrType() == AstAttrType::VAR_CLOCKER) {
if (!m_varp) nodep->v3fatalSrc("Attribute not attached to variable");
m_varp->attrClocker(AstVarAttrClocker::CLOCKER_YES);
nodep->unlinkFrBack()->deleteTree(); VL_DANGLING(nodep);
}
else if (nodep->attrType() == AstAttrType::VAR_NO_CLOCKER) {
if (!m_varp) nodep->v3fatalSrc("Attribute not attached to variable");
m_varp->attrClocker(AstVarAttrClocker::CLOCKER_NO);
nodep->unlinkFrBack()->deleteTree(); VL_DANGLING(nodep);
}
}
virtual void visit(AstAlwaysPublic* nodep) {
// AlwaysPublic was attached under a var, but it's a statement that should be
// at the same level as the var
cleanFileline(nodep);
// AlwaysPublic was attached under a var, but it's a statement that should be
// at the same level as the var
cleanFileline(nodep);
iterateChildren(nodep);
if (m_varp) {
nodep->unlinkFrBack();
m_varp->addNext(nodep);
// lvalue is true, because we know we have a verilator public_flat_rw
// but someday we may be more general
bool lvalue = m_varp->isSigUserRWPublic();
nodep->addStmtp(new AstVarRef(nodep->fileline(), m_varp, lvalue));
}
if (m_varp) {
nodep->unlinkFrBack();
m_varp->addNext(nodep);
// lvalue is true, because we know we have a verilator public_flat_rw
// but someday we may be more general
bool lvalue = m_varp->isSigUserRWPublic();
nodep->addStmtp(new AstVarRef(nodep->fileline(), m_varp, lvalue));
}
}
virtual void visit(AstDefImplicitDType* nodep) {
cleanFileline(nodep);
UINFO(8," DEFIMPLICIT "<<nodep<<endl);
// Must remember what names we've already created, and combine duplicates
// so that for "var enum {...} a,b" a & b will share a common typedef
// Unique name space under each containerp() so that an addition of a new type won't change every verilated module.
AstTypedef* defp = NULL;
ImplTypedefMap::iterator it = m_implTypedef.find(make_pair(nodep->containerp(), nodep->name()));
if (it != m_implTypedef.end()) {
defp = it->second;
} else {
// Definition must be inserted right after the variable (etc) that needed it
// AstVar, AstTypedef, AstNodeFTask are common containers
AstNode* backp = nodep->backp();
for (; backp; backp=backp->backp()) {
cleanFileline(nodep);
UINFO(8," DEFIMPLICIT "<<nodep<<endl);
// Must remember what names we've already created, and combine duplicates
// so that for "var enum {...} a,b" a & b will share a common typedef
// Unique name space under each containerp() so that an addition of
// a new type won't change every verilated module.
AstTypedef* defp = NULL;
ImplTypedefMap::iterator it = m_implTypedef.find(make_pair(nodep->containerp(), nodep->name()));
if (it != m_implTypedef.end()) {
defp = it->second;
} else {
// Definition must be inserted right after the variable (etc) that needed it
// AstVar, AstTypedef, AstNodeFTask are common containers
AstNode* backp = nodep->backp();
for (; backp; backp=backp->backp()) {
if (VN_IS(backp, Var)) break;
else if (VN_IS(backp, Typedef)) break;
else if (VN_IS(backp, NodeFTask)) break;
}
if (!backp) nodep->v3fatalSrc("Implicit enum/struct type created under unexpected node type");
AstNodeDType* dtypep = nodep->childDTypep(); dtypep->unlinkFrBack();
}
if (!backp) nodep->v3fatalSrc("Implicit enum/struct type created under unexpected node type");
AstNodeDType* dtypep = nodep->childDTypep(); dtypep->unlinkFrBack();
if (VN_IS(backp, Typedef)) { // A typedef doesn't need us to make yet another level of typedefing
// For typedefs just remove the AstRefDType level of abstraction
nodep->replaceWith(dtypep);
nodep->deleteTree(); VL_DANGLING(nodep);
return;
} else {
defp = new AstTypedef(nodep->fileline(), nodep->name(), NULL, VFlagChildDType(), dtypep);
m_implTypedef.insert(make_pair(make_pair(nodep->containerp(), defp->name()), defp));
backp->addNextHere(defp);
}
}
nodep->replaceWith(new AstRefDType(nodep->fileline(), defp->name()));
nodep->deleteTree(); VL_DANGLING(nodep);
// For typedefs just remove the AstRefDType level of abstraction
nodep->replaceWith(dtypep);
nodep->deleteTree(); VL_DANGLING(nodep);
return;
} else {
defp = new AstTypedef(nodep->fileline(), nodep->name(), NULL,
VFlagChildDType(), dtypep);
m_implTypedef.insert(make_pair(make_pair(nodep->containerp(), defp->name()), defp));
backp->addNextHere(defp);
}
}
nodep->replaceWith(new AstRefDType(nodep->fileline(), defp->name()));
nodep->deleteTree(); VL_DANGLING(nodep);
}
virtual void visit(AstTypedefFwd* nodep) {
// We only needed the forward declaration in order to parse correctly.
// We won't even check it was ever really defined, as it might have been in a header
// file referring to a module we never needed
nodep->unlinkFrBack()->deleteTree();
// We only needed the forward declaration in order to parse correctly.
// We won't even check it was ever really defined, as it might have been in a header
// file referring to a module we never needed
nodep->unlinkFrBack()->deleteTree();
}
virtual void visit(AstForeach* nodep) {
// FOREACH(array,loopvars,body)
// -> BEGIN(declare vars, loopa=lowest; WHILE(loopa<=highest, ... body))
//nodep->dumpTree(cout, "-foreach-old:");
AstNode* newp = nodep->bodysp()->unlinkFrBackWithNext();
AstNode* arrayp = nodep->arrayp();
int dimension = 1;
// Must do innermost (last) variable first
AstNode* firstVarsp = nodep->varsp()->unlinkFrBackWithNext();
AstNode* lastVarsp = firstVarsp;
while (lastVarsp->nextp()) { lastVarsp = lastVarsp->nextp(); dimension++; }
for (AstNode* varsp = lastVarsp; varsp; varsp=varsp->backp()) {
UINFO(9,"foreachVar "<<varsp<<endl);
FileLine* fl = varsp->fileline();
AstNode* varp = new AstVar(fl, AstVarType::BLOCKTEMP,
varsp->name(), nodep->findSigned32DType());
// FOREACH(array,loopvars,body)
// -> BEGIN(declare vars, loopa=lowest; WHILE(loopa<=highest, ... body))
//nodep->dumpTree(cout, "-foreach-old:");
AstNode* newp = nodep->bodysp()->unlinkFrBackWithNext();
AstNode* arrayp = nodep->arrayp();
int dimension = 1;
// Must do innermost (last) variable first
AstNode* firstVarsp = nodep->varsp()->unlinkFrBackWithNext();
AstNode* lastVarsp = firstVarsp;
while (lastVarsp->nextp()) { lastVarsp = lastVarsp->nextp(); dimension++; }
for (AstNode* varsp = lastVarsp; varsp; varsp=varsp->backp()) {
UINFO(9,"foreachVar "<<varsp<<endl);
FileLine* fl = varsp->fileline();
AstNode* varp = new AstVar(fl, AstVarType::BLOCKTEMP,
varsp->name(), nodep->findSigned32DType());
// These will be the left and right dimensions of the array:
AstNode* leftp = new AstAttrOf(fl, AstAttrType::DIM_LEFT,
new AstVarRef(fl, arrayp->name(), false),
new AstConst(fl, dimension));
AstNode* rightp = new AstAttrOf(fl, AstAttrType::DIM_RIGHT,
new AstVarRef(fl, arrayp->name(), false),
new AstConst(fl, dimension));
AstNode* stmtsp = varp;
AstNode* leftp = new AstAttrOf(fl, AstAttrType::DIM_LEFT,
new AstVarRef(fl, arrayp->name(), false),
new AstConst(fl, dimension));
AstNode* rightp = new AstAttrOf(fl, AstAttrType::DIM_RIGHT,
new AstVarRef(fl, arrayp->name(), false),
new AstConst(fl, dimension));
AstNode* stmtsp = varp;
// Assign left-dimension into the loop var:
stmtsp->addNext(new AstAssign
(fl, new AstVarRef(fl, varp->name(), true), leftp));
@@ -395,69 +406,69 @@ private:
new AstCond(fl, countupp,
new AstConst(fl, 1),
new AstConst(fl, -1))));
stmtsp->addNext(new AstWhile(fl, comparep, newp, incp));
newp = new AstBegin(nodep->fileline(),"",stmtsp);
dimension--;
}
//newp->dumpTree(cout, "-foreach-new:");
firstVarsp->deleteTree(); VL_DANGLING(firstVarsp);
nodep->replaceWith(newp); nodep->deleteTree(); VL_DANGLING(nodep);
stmtsp->addNext(new AstWhile(fl, comparep, newp, incp));
newp = new AstBegin(nodep->fileline(), "", stmtsp);
dimension--;
}
//newp->dumpTree(cout, "-foreach-new:");
firstVarsp->deleteTree(); VL_DANGLING(firstVarsp);
nodep->replaceWith(newp); nodep->deleteTree(); VL_DANGLING(nodep);
}
virtual void visit(AstNodeModule* nodep) {
// Module: Create sim table for entire module and iterate
cleanFileline(nodep);
//
m_modp = nodep;
m_valueModp = nodep;
// Module: Create sim table for entire module and iterate
cleanFileline(nodep);
//
m_modp = nodep;
m_valueModp = nodep;
iterateChildren(nodep);
m_modp = NULL;
m_valueModp = NULL;
m_modp = NULL;
m_valueModp = NULL;
}
void visitIterateNoValueMod(AstNode* nodep) {
// Iterate a node which shouldn't have any local variables moved to an Initial
cleanFileline(nodep);
//
AstNodeModule* upperValueModp = m_valueModp;
m_valueModp = NULL;
// Iterate a node which shouldn't have any local variables moved to an Initial
cleanFileline(nodep);
//
AstNodeModule* upperValueModp = m_valueModp;
m_valueModp = NULL;
iterateChildren(nodep);
m_valueModp = upperValueModp;
m_valueModp = upperValueModp;
}
virtual void visit(AstInitial* nodep) {
visitIterateNoValueMod(nodep);
visitIterateNoValueMod(nodep);
}
virtual void visit(AstFinal* nodep) {
visitIterateNoValueMod(nodep);
visitIterateNoValueMod(nodep);
}
virtual void visit(AstAlways* nodep) {
m_inAlways = true;
visitIterateNoValueMod(nodep);
m_inAlways = false;
m_inAlways = true;
visitIterateNoValueMod(nodep);
m_inAlways = false;
}
virtual void visit(AstPslCover* nodep) {
visitIterateNoValueMod(nodep);
visitIterateNoValueMod(nodep);
}
virtual void visit(AstPslRestrict* nodep) {
visitIterateNoValueMod(nodep);
}
virtual void visit(AstNode* nodep) {
// Default: Just iterate
cleanFileline(nodep);
// Default: Just iterate
cleanFileline(nodep);
iterateChildren(nodep);
}
public:
// CONSTUCTORS
explicit LinkParseVisitor(AstNetlist* rootp) {
m_varp = NULL;
m_modp = NULL;
m_ftaskp = NULL;
m_dtypep = NULL;
m_inAlways = false;
m_inGenerate = false;
m_needStart = false;
m_valueModp = NULL;
m_varp = NULL;
m_modp = NULL;
m_ftaskp = NULL;
m_dtypep = NULL;
m_inAlways = false;
m_inGenerate = false;
m_needStart = false;
m_valueModp = NULL;
iterate(rootp);
}
virtual ~LinkParseVisitor() {}