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: Break always into sensitivity block domains
|
|
|
|
//
|
2019-11-08 03:33:59 +00:00
|
|
|
// Code available from: https://verilator.org
|
2006-08-26 11:35:28 +00:00
|
|
|
//
|
|
|
|
//*************************************************************************
|
|
|
|
//
|
2020-03-21 15:24:24 +00:00
|
|
|
// Copyright 2003-2020 by Wilson Snyder. This program is free software; you
|
|
|
|
// can 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.
|
2020-03-21 15:24:24 +00:00
|
|
|
// SPDX-License-Identifier: LGPL-3.0-only OR Artistic-2.0
|
2006-08-26 11:35:28 +00:00
|
|
|
//
|
|
|
|
//*************************************************************************
|
|
|
|
// V3Scope's Transformations:
|
2008-06-10 01:25:10 +00:00
|
|
|
//
|
2019-05-19 20:13:13 +00:00
|
|
|
// For every CELL that references this module, create a
|
|
|
|
// SCOPE
|
|
|
|
// {all blocked statements}
|
2008-06-10 01:25:10 +00:00
|
|
|
//
|
2006-08-26 11:35:28 +00:00
|
|
|
//*************************************************************************
|
2019-10-05 00:17:11 +00:00
|
|
|
|
2006-12-18 19:20:45 +00:00
|
|
|
#include "config_build.h"
|
|
|
|
#include "verilatedos.h"
|
2018-10-14 17:43:24 +00:00
|
|
|
|
|
|
|
#include "V3Global.h"
|
|
|
|
#include "V3Scope.h"
|
|
|
|
#include "V3Ast.h"
|
|
|
|
|
2006-08-26 11:35:28 +00:00
|
|
|
#include <algorithm>
|
2018-10-14 11:04:18 +00:00
|
|
|
#include <cstdarg>
|
2006-08-26 11:35:28 +00:00
|
|
|
#include <iomanip>
|
|
|
|
#include <map>
|
2018-03-16 03:19:43 +00:00
|
|
|
#include VL_INCLUDE_UNORDERED_MAP
|
|
|
|
#include VL_INCLUDE_UNORDERED_SET
|
2006-08-26 11:35:28 +00:00
|
|
|
|
|
|
|
//######################################################################
|
|
|
|
// Scope class functions
|
|
|
|
|
|
|
|
class ScopeVisitor : public AstNVisitor {
|
|
|
|
private:
|
|
|
|
// NODE STATE
|
2019-05-19 20:13:13 +00:00
|
|
|
// AstVar::user1p -> AstVarScope replacement for this variable
|
|
|
|
// AstTask::user2p -> AstTask*. Replacement task
|
|
|
|
AstUser1InUse m_inuser1;
|
|
|
|
AstUser2InUse m_inuser2;
|
2014-03-15 00:24:00 +00:00
|
|
|
|
|
|
|
// TYPES
|
2018-03-16 03:19:43 +00:00
|
|
|
typedef vl_unordered_map<AstPackage*, AstScope*> PackageScopeMap;
|
2018-03-17 15:33:47 +00:00
|
|
|
// These cannot be unordered unless make a specialized hashing pair (gcc-8)
|
|
|
|
typedef std::map<std::pair<AstVar*, AstScope*>, AstVarScope*> VarScopeMap;
|
|
|
|
typedef std::set<std::pair<AstVarRef*, AstScope*> > VarRefScopeSet;
|
2006-08-26 11:35:28 +00:00
|
|
|
|
|
|
|
// STATE, inside processing a single module
|
2019-05-19 20:13:13 +00:00
|
|
|
AstNodeModule* m_modp; // Current module
|
|
|
|
AstScope* m_scopep; // Current scope we are building
|
2006-08-26 11:35:28 +00:00
|
|
|
// STATE, for passing down one level of hierarchy (may need save/restore)
|
2019-05-19 20:13:13 +00:00
|
|
|
AstCell* m_aboveCellp; // Cell that instantiates this module
|
|
|
|
AstScope* m_aboveScopep; // Scope that instantiates this scope
|
2017-09-11 23:18:58 +00:00
|
|
|
|
2019-05-19 20:13:13 +00:00
|
|
|
PackageScopeMap m_packageScopes; // Scopes for each package
|
|
|
|
VarScopeMap m_varScopes; // Varscopes created for each scope and var
|
2019-09-09 11:50:21 +00:00
|
|
|
VarRefScopeSet m_varRefScopes; // Varrefs-in-scopes needing fixup when done
|
2006-08-26 11:35:28 +00:00
|
|
|
|
2009-01-21 21:56:50 +00:00
|
|
|
// METHODS
|
2018-05-14 10:50:47 +00:00
|
|
|
VL_DEBUG_FUNC; // Declare debug()
|
2008-06-10 01:25:10 +00:00
|
|
|
|
2014-03-15 00:24:00 +00:00
|
|
|
void cleanupVarRefs() {
|
2019-05-19 20:13:13 +00:00
|
|
|
for (VarRefScopeSet::iterator it = m_varRefScopes.begin();
|
|
|
|
it!=m_varRefScopes.end(); ++it) {
|
|
|
|
AstVarRef* nodep = it->first;
|
|
|
|
AstScope* scopep = it->second;
|
|
|
|
if (nodep->packagep()) {
|
|
|
|
PackageScopeMap::iterator it2 = m_packageScopes.find(nodep->packagep());
|
2019-07-06 16:57:50 +00:00
|
|
|
UASSERT_OBJ(it2 != m_packageScopes.end(), nodep, "Can't locate package scope");
|
2019-05-19 20:13:13 +00:00
|
|
|
scopep = it2->second;
|
|
|
|
}
|
|
|
|
VarScopeMap::iterator it3 = m_varScopes.find(make_pair(nodep->varp(), scopep));
|
2019-07-06 16:57:50 +00:00
|
|
|
UASSERT_OBJ(it3 != m_varScopes.end(), nodep, "Can't locate varref scope");
|
2019-05-19 20:13:13 +00:00
|
|
|
AstVarScope* varscp = it3->second;
|
|
|
|
nodep->varScopep(varscp);
|
|
|
|
}
|
2014-03-15 00:24:00 +00:00
|
|
|
}
|
|
|
|
|
2006-08-26 11:35:28 +00:00
|
|
|
// VISITORS
|
2020-01-21 22:35:56 +00:00
|
|
|
virtual void visit(AstNetlist* nodep) VL_OVERRIDE {
|
2019-05-19 20:13:13 +00:00
|
|
|
AstNodeModule* modp = nodep->topModulep();
|
2019-06-30 20:46:48 +00:00
|
|
|
if (!modp) { nodep->v3error("No top level module found"); return; }
|
2019-05-19 20:13:13 +00:00
|
|
|
// Operate starting at the top of the hierarchy
|
|
|
|
m_aboveCellp = NULL;
|
|
|
|
m_aboveScopep = NULL;
|
2018-05-11 00:55:37 +00:00
|
|
|
iterate(modp);
|
2019-05-19 20:13:13 +00:00
|
|
|
cleanupVarRefs();
|
2006-08-26 11:35:28 +00:00
|
|
|
}
|
2020-01-21 22:35:56 +00:00
|
|
|
virtual void visit(AstNodeModule* nodep) VL_OVERRIDE {
|
2019-05-19 20:13:13 +00:00
|
|
|
// Create required blocks and add to module
|
|
|
|
string scopename;
|
|
|
|
if (!m_aboveScopep) scopename = "TOP";
|
|
|
|
else scopename = m_aboveScopep->name()+"."+m_aboveCellp->name();
|
2006-08-26 11:35:28 +00:00
|
|
|
|
2019-05-19 20:13:13 +00:00
|
|
|
UINFO(4," MOD AT "<<scopename<<" "<<nodep<<endl);
|
2008-11-25 14:03:49 +00:00
|
|
|
AstNode::user1ClearTree();
|
2008-06-10 01:25:10 +00:00
|
|
|
|
2018-10-14 22:39:33 +00:00
|
|
|
m_scopep = new AstScope((m_aboveCellp ? static_cast<AstNode*>(m_aboveCellp)
|
|
|
|
: static_cast<AstNode*>(nodep))
|
|
|
|
->fileline(),
|
2019-05-19 20:13:13 +00:00
|
|
|
nodep, scopename, m_aboveScopep, m_aboveCellp);
|
|
|
|
if (VN_IS(nodep, Package)) {
|
|
|
|
m_packageScopes.insert(make_pair(VN_CAST(nodep, Package), m_scopep));
|
|
|
|
}
|
2006-08-26 11:35:28 +00:00
|
|
|
|
2019-05-19 20:13:13 +00:00
|
|
|
// Now for each child cell, iterate the module this cell points to
|
|
|
|
for (AstNode* cellnextp = nodep->stmtsp(); cellnextp; cellnextp=cellnextp->nextp()) {
|
2018-02-02 02:32:58 +00:00
|
|
|
if (AstCell* cellp = VN_CAST(cellnextp, Cell)) {
|
2019-05-19 20:13:13 +00:00
|
|
|
AstScope* oldScopep = m_scopep;
|
|
|
|
AstCell* oldAbCellp = m_aboveCellp;
|
|
|
|
AstScope* oldAbScopep = m_aboveScopep;
|
|
|
|
{
|
|
|
|
m_aboveCellp = cellp;
|
|
|
|
m_aboveScopep = m_scopep;
|
|
|
|
AstNodeModule* modp = cellp->modp();
|
2019-07-06 16:57:50 +00:00
|
|
|
UASSERT_OBJ(modp, cellp, "Unlinked mod");
|
2018-05-11 00:55:37 +00:00
|
|
|
iterate(modp); // Recursive call to visit(AstNodeModule)
|
2019-05-19 20:13:13 +00:00
|
|
|
}
|
|
|
|
// Done, restore vars
|
|
|
|
m_scopep = oldScopep;
|
|
|
|
m_aboveCellp = oldAbCellp;
|
|
|
|
m_aboveScopep = oldAbScopep;
|
|
|
|
}
|
|
|
|
}
|
2006-08-26 11:35:28 +00:00
|
|
|
|
2019-05-19 20:13:13 +00:00
|
|
|
// Create scope for the current usage of this module
|
|
|
|
UINFO(4," back AT "<<scopename<<" "<<nodep<<endl);
|
2008-11-25 14:03:49 +00:00
|
|
|
AstNode::user1ClearTree();
|
2019-05-19 20:13:13 +00:00
|
|
|
m_modp = nodep;
|
|
|
|
if (m_modp->isTop()) {
|
|
|
|
AstTopScope* topscp = new AstTopScope(nodep->fileline(), m_scopep);
|
|
|
|
m_modp->addStmtp(topscp);
|
|
|
|
} else {
|
|
|
|
m_modp->addStmtp(m_scopep);
|
|
|
|
}
|
2006-08-26 11:35:28 +00:00
|
|
|
|
2019-05-19 20:13:13 +00:00
|
|
|
// Copy blocks into this scope
|
|
|
|
// If this is the first usage of the block ever, we can simply move the reference
|
2018-05-11 00:55:37 +00:00
|
|
|
iterateChildren(nodep);
|
2006-08-26 11:35:28 +00:00
|
|
|
|
2019-05-19 20:13:13 +00:00
|
|
|
// ***Note m_scopep is passed back to the caller of the routine (above)
|
2006-08-26 11:35:28 +00:00
|
|
|
}
|
2020-01-21 22:35:56 +00:00
|
|
|
virtual void visit(AstCellInline* nodep) VL_OVERRIDE {
|
2019-10-02 01:57:45 +00:00
|
|
|
nodep->scopep(m_scopep);
|
|
|
|
}
|
2020-01-21 22:35:56 +00:00
|
|
|
virtual void visit(AstActive* nodep) VL_OVERRIDE {
|
2019-05-19 20:13:13 +00:00
|
|
|
nodep->v3fatalSrc("Actives now made after scoping");
|
2006-08-26 11:35:28 +00:00
|
|
|
}
|
2020-01-21 22:35:56 +00:00
|
|
|
virtual void visit(AstInitial* nodep) VL_OVERRIDE {
|
2019-05-19 20:13:13 +00:00
|
|
|
// Add to list of blocks under this scope
|
|
|
|
UINFO(4," Move "<<nodep<<endl);
|
|
|
|
AstInitial* clonep = nodep->cloneTree(false);
|
|
|
|
nodep->user2p(clonep);
|
|
|
|
m_scopep->addActivep(clonep);
|
2018-05-11 00:55:37 +00:00
|
|
|
iterateChildren(clonep); // We iterate under the *clone*
|
2006-08-26 11:35:28 +00:00
|
|
|
}
|
2020-01-21 22:35:56 +00:00
|
|
|
virtual void visit(AstFinal* nodep) VL_OVERRIDE {
|
2019-05-19 20:13:13 +00:00
|
|
|
// Add to list of blocks under this scope
|
|
|
|
UINFO(4," Move "<<nodep<<endl);
|
|
|
|
AstFinal* clonep = nodep->cloneTree(false);
|
|
|
|
nodep->user2p(clonep);
|
|
|
|
m_scopep->addActivep(clonep);
|
2018-05-11 00:55:37 +00:00
|
|
|
iterateChildren(clonep); // We iterate under the *clone*
|
2006-08-26 11:35:28 +00:00
|
|
|
}
|
2020-01-21 22:35:56 +00:00
|
|
|
virtual void visit(AstAssignAlias* nodep) VL_OVERRIDE {
|
2019-05-19 20:13:13 +00:00
|
|
|
// Add to list of blocks under this scope
|
|
|
|
UINFO(4," Move "<<nodep<<endl);
|
|
|
|
AstNode* clonep = nodep->cloneTree(false);
|
|
|
|
nodep->user2p(clonep);
|
|
|
|
m_scopep->addActivep(clonep);
|
2018-05-11 00:55:37 +00:00
|
|
|
iterateChildren(clonep); // We iterate under the *clone*
|
2006-08-26 11:35:28 +00:00
|
|
|
}
|
2020-01-21 22:35:56 +00:00
|
|
|
virtual void visit(AstAssignVarScope* nodep) VL_OVERRIDE {
|
2019-05-19 20:13:13 +00:00
|
|
|
// Copy under the scope but don't recurse
|
|
|
|
UINFO(4," Move "<<nodep<<endl);
|
|
|
|
AstNode* clonep = nodep->cloneTree(false);
|
|
|
|
nodep->user2p(clonep);
|
|
|
|
m_scopep->addActivep(clonep);
|
2018-05-11 00:55:37 +00:00
|
|
|
iterateChildren(clonep); // We iterate under the *clone*
|
2013-05-28 01:39:19 +00:00
|
|
|
}
|
2020-01-21 22:35:56 +00:00
|
|
|
virtual void visit(AstAssignW* nodep) VL_OVERRIDE {
|
2019-05-19 20:13:13 +00:00
|
|
|
// Add to list of blocks under this scope
|
|
|
|
UINFO(4," Move "<<nodep<<endl);
|
|
|
|
AstNode* clonep = nodep->cloneTree(false);
|
|
|
|
nodep->user2p(clonep);
|
|
|
|
m_scopep->addActivep(clonep);
|
2018-05-11 00:55:37 +00:00
|
|
|
iterateChildren(clonep); // We iterate under the *clone*
|
2006-08-26 11:35:28 +00:00
|
|
|
}
|
2020-01-21 22:35:56 +00:00
|
|
|
virtual void visit(AstAlways* nodep) VL_OVERRIDE {
|
2019-05-19 20:13:13 +00:00
|
|
|
// Add to list of blocks under this scope
|
|
|
|
UINFO(4," Move "<<nodep<<endl);
|
|
|
|
AstNode* clonep = nodep->cloneTree(false);
|
|
|
|
nodep->user2p(clonep);
|
|
|
|
m_scopep->addActivep(clonep);
|
2018-05-11 00:55:37 +00:00
|
|
|
iterateChildren(clonep); // We iterate under the *clone*
|
2008-12-12 20:34:02 +00:00
|
|
|
}
|
2020-01-21 22:35:56 +00:00
|
|
|
virtual void visit(AstAlwaysPublic* nodep) VL_OVERRIDE {
|
2019-05-19 20:13:13 +00:00
|
|
|
// Add to list of blocks under this scope
|
|
|
|
UINFO(4," Move "<<nodep<<endl);
|
|
|
|
AstNode* clonep = nodep->cloneTree(false);
|
|
|
|
nodep->user2p(clonep);
|
|
|
|
m_scopep->addActivep(clonep);
|
2018-05-11 00:55:37 +00:00
|
|
|
iterateChildren(clonep); // We iterate under the *clone*
|
2010-04-06 00:01:17 +00:00
|
|
|
}
|
2020-01-21 22:35:56 +00:00
|
|
|
virtual void visit(AstCoverToggle* nodep) VL_OVERRIDE {
|
2019-05-19 20:13:13 +00:00
|
|
|
// Add to list of blocks under this scope
|
|
|
|
UINFO(4," Move "<<nodep<<endl);
|
|
|
|
AstNode* clonep = nodep->cloneTree(false);
|
|
|
|
nodep->user2p(clonep);
|
|
|
|
m_scopep->addActivep(clonep);
|
2018-05-11 00:55:37 +00:00
|
|
|
iterateChildren(clonep); // We iterate under the *clone*
|
2006-08-26 11:35:28 +00:00
|
|
|
}
|
2020-01-21 22:35:56 +00:00
|
|
|
virtual void visit(AstCFunc* nodep) VL_OVERRIDE {
|
2019-05-19 20:13:13 +00:00
|
|
|
// Add to list of blocks under this scope
|
|
|
|
UINFO(4," CFUNC "<<nodep<<endl);
|
|
|
|
AstCFunc* clonep = nodep->cloneTree(false);
|
|
|
|
nodep->user2p(clonep);
|
|
|
|
m_scopep->addActivep(clonep);
|
|
|
|
clonep->scopep(m_scopep);
|
|
|
|
// We iterate under the *clone*
|
2018-05-11 00:55:37 +00:00
|
|
|
iterateChildren(clonep);
|
2006-08-26 11:35:28 +00:00
|
|
|
}
|
2020-01-21 22:35:56 +00:00
|
|
|
virtual void visit(AstNodeFTask* nodep) VL_OVERRIDE {
|
2019-05-19 20:13:13 +00:00
|
|
|
// Add to list of blocks under this scope
|
|
|
|
UINFO(4," FTASK "<<nodep<<endl);
|
|
|
|
AstNodeFTask* clonep = nodep->cloneTree(false);
|
|
|
|
nodep->user2p(clonep);
|
|
|
|
m_scopep->addActivep(clonep);
|
|
|
|
// We iterate under the *clone*
|
2018-05-11 00:55:37 +00:00
|
|
|
iterateChildren(clonep);
|
2006-08-26 11:35:28 +00:00
|
|
|
}
|
2020-01-21 22:35:56 +00:00
|
|
|
virtual void visit(AstVar* nodep) VL_OVERRIDE {
|
2019-05-19 20:13:13 +00:00
|
|
|
// Make new scope variable
|
|
|
|
// This is called cross-module by AstVar, so we cannot trust any m_ variables
|
|
|
|
if (!nodep->user1p()) {
|
|
|
|
AstVarScope* varscp = new AstVarScope(nodep->fileline(), m_scopep, nodep);
|
|
|
|
UINFO(6," New scope "<<varscp<<endl);
|
|
|
|
if (m_aboveCellp && !m_aboveCellp->isTrace()) varscp->trace(false);
|
|
|
|
nodep->user1p(varscp);
|
|
|
|
if (v3Global.opt.isClocker(varscp->prettyName())) {
|
2019-10-05 11:54:14 +00:00
|
|
|
nodep->attrClocker(VVarAttrClocker::CLOCKER_YES);
|
2019-05-19 20:13:13 +00:00
|
|
|
}
|
|
|
|
if (v3Global.opt.isNoClocker(varscp->prettyName())) {
|
2019-10-05 11:54:14 +00:00
|
|
|
nodep->attrClocker(VVarAttrClocker::CLOCKER_NO);
|
2019-05-19 20:13:13 +00:00
|
|
|
}
|
2019-07-06 16:57:50 +00:00
|
|
|
UASSERT_OBJ(m_scopep, nodep, "No scope for var");
|
2019-05-19 20:13:13 +00:00
|
|
|
m_varScopes.insert(make_pair(make_pair(nodep, m_scopep), varscp));
|
|
|
|
m_scopep->addVarp(varscp);
|
|
|
|
}
|
2006-08-26 11:35:28 +00:00
|
|
|
}
|
2020-01-21 22:35:56 +00:00
|
|
|
virtual void visit(AstVarRef* nodep) VL_OVERRIDE {
|
2019-05-19 20:13:13 +00:00
|
|
|
// VarRef needs to point to VarScope
|
|
|
|
// Make sure variable has made user1p.
|
2019-07-06 16:57:50 +00:00
|
|
|
UASSERT_OBJ(nodep->varp(), nodep, "Unlinked");
|
2019-05-19 20:13:13 +00:00
|
|
|
if (nodep->varp()->isIfaceRef()) {
|
|
|
|
nodep->varScopep(NULL);
|
|
|
|
} else {
|
|
|
|
// We may have not made the variable yet, and we can't make it now as
|
|
|
|
// the var's referenced package etc might not be created yet.
|
|
|
|
// So push to a list and post-correct
|
|
|
|
m_varRefScopes.insert(make_pair(nodep, m_scopep));
|
|
|
|
}
|
2014-11-08 19:15:10 +00:00
|
|
|
}
|
2020-01-21 22:35:56 +00:00
|
|
|
virtual void visit(AstScopeName* nodep) VL_OVERRIDE {
|
2019-05-19 20:13:13 +00:00
|
|
|
// If there's a %m in the display text, we add a special node that will contain the name()
|
2018-10-14 02:02:39 +00:00
|
|
|
string prefix = string("__DOT__")+m_scopep->name();
|
2019-05-19 20:13:13 +00:00
|
|
|
// TOP and above will be the user's name().
|
|
|
|
// Note 'TOP.' is stripped by scopePrettyName
|
|
|
|
// To keep correct visual order, must add before other Text's
|
|
|
|
AstNode* afterp = nodep->scopeAttrp();
|
|
|
|
if (afterp) afterp->unlinkFrBackWithNext();
|
|
|
|
nodep->scopeAttrp(new AstText(nodep->fileline(), prefix));
|
|
|
|
if (afterp) nodep->scopeAttrp(afterp);
|
|
|
|
afterp = nodep->scopeEntrp();
|
|
|
|
if (afterp) afterp->unlinkFrBackWithNext();
|
|
|
|
nodep->scopeEntrp(new AstText(nodep->fileline(), prefix));
|
|
|
|
if (afterp) nodep->scopeEntrp(afterp);
|
2018-05-11 00:55:37 +00:00
|
|
|
iterateChildren(nodep);
|
2006-08-30 01:14:29 +00:00
|
|
|
}
|
2020-01-21 22:35:56 +00:00
|
|
|
virtual void visit(AstScope* nodep) VL_OVERRIDE {
|
2019-05-19 20:13:13 +00:00
|
|
|
// Scope that was made by this module for different cell;
|
|
|
|
// Want to ignore blocks under it, so just do nothing
|
2006-08-26 11:35:28 +00:00
|
|
|
}
|
|
|
|
//--------------------
|
2020-04-04 12:31:14 +00:00
|
|
|
virtual void visit(AstNode* nodep) VL_OVERRIDE { iterateChildren(nodep); }
|
|
|
|
|
2006-08-26 11:35:28 +00:00
|
|
|
public:
|
2019-09-12 11:22:22 +00:00
|
|
|
// CONSTRUCTORS
|
2015-10-04 02:33:06 +00:00
|
|
|
explicit ScopeVisitor(AstNetlist* nodep) {
|
2019-05-19 20:13:13 +00:00
|
|
|
m_aboveCellp = NULL;
|
|
|
|
m_aboveScopep = NULL;
|
|
|
|
m_modp = NULL;
|
|
|
|
m_scopep = NULL;
|
|
|
|
//
|
2018-05-11 00:55:37 +00:00
|
|
|
iterate(nodep);
|
2006-08-26 11:35:28 +00:00
|
|
|
}
|
|
|
|
virtual ~ScopeVisitor() {}
|
|
|
|
};
|
|
|
|
|
|
|
|
//######################################################################
|
|
|
|
// Scope cleanup -- remove unused activates
|
|
|
|
|
|
|
|
class ScopeCleanupVisitor : public AstNVisitor {
|
|
|
|
private:
|
|
|
|
// STATE
|
2019-05-19 20:13:13 +00:00
|
|
|
AstScope* m_scopep; // Current scope we are building
|
2006-08-26 11:35:28 +00:00
|
|
|
|
|
|
|
// METHODS
|
2018-05-14 10:50:47 +00:00
|
|
|
VL_DEBUG_FUNC; // Declare debug()
|
2009-01-21 21:56:50 +00:00
|
|
|
|
2006-08-26 11:35:28 +00:00
|
|
|
// VISITORS
|
2020-01-21 22:35:56 +00:00
|
|
|
virtual void visit(AstScope* nodep) VL_OVERRIDE {
|
2019-05-19 20:13:13 +00:00
|
|
|
// Want to ignore blocks under it
|
|
|
|
m_scopep = nodep;
|
2018-05-11 00:55:37 +00:00
|
|
|
iterateChildren(nodep);
|
2019-05-19 20:13:13 +00:00
|
|
|
m_scopep = NULL;
|
2006-08-26 11:35:28 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
virtual void movedDeleteOrIterate(AstNode* nodep) {
|
2019-05-19 20:13:13 +00:00
|
|
|
if (m_scopep) {
|
|
|
|
// The new block; repair varrefs
|
2018-05-11 00:55:37 +00:00
|
|
|
iterateChildren(nodep);
|
2019-05-19 20:13:13 +00:00
|
|
|
} else {
|
|
|
|
// A block that was just moved under a scope, Kill it.
|
|
|
|
// Certain nodes can be referenced later in this pass, notably
|
|
|
|
// an FTaskRef needs to access the FTask to find the cloned task
|
2020-01-17 01:17:11 +00:00
|
|
|
VL_DO_DANGLING(pushDeletep(nodep->unlinkFrBack()), nodep);
|
2019-05-19 20:13:13 +00:00
|
|
|
}
|
2006-08-26 11:35:28 +00:00
|
|
|
}
|
|
|
|
|
2020-01-21 22:35:56 +00:00
|
|
|
virtual void visit(AstInitial* nodep) VL_OVERRIDE {
|
2019-05-19 20:13:13 +00:00
|
|
|
movedDeleteOrIterate(nodep);
|
2006-08-26 11:35:28 +00:00
|
|
|
}
|
2020-01-21 22:35:56 +00:00
|
|
|
virtual void visit(AstFinal* nodep) VL_OVERRIDE {
|
2019-05-19 20:13:13 +00:00
|
|
|
movedDeleteOrIterate(nodep);
|
2006-08-26 11:35:28 +00:00
|
|
|
}
|
2020-01-21 22:35:56 +00:00
|
|
|
virtual void visit(AstAssignAlias* nodep) VL_OVERRIDE {
|
2019-05-19 20:13:13 +00:00
|
|
|
movedDeleteOrIterate(nodep);
|
2006-08-26 11:35:28 +00:00
|
|
|
}
|
2020-01-21 22:35:56 +00:00
|
|
|
virtual void visit(AstAssignVarScope* nodep) VL_OVERRIDE {
|
2019-05-19 20:13:13 +00:00
|
|
|
movedDeleteOrIterate(nodep);
|
2013-05-28 01:39:19 +00:00
|
|
|
}
|
2020-01-21 22:35:56 +00:00
|
|
|
virtual void visit(AstAssignW* nodep) VL_OVERRIDE {
|
2019-05-19 20:13:13 +00:00
|
|
|
movedDeleteOrIterate(nodep);
|
2006-08-26 11:35:28 +00:00
|
|
|
}
|
2020-01-21 22:35:56 +00:00
|
|
|
virtual void visit(AstAlways* nodep) VL_OVERRIDE {
|
2019-05-19 20:13:13 +00:00
|
|
|
movedDeleteOrIterate(nodep);
|
2006-08-26 11:35:28 +00:00
|
|
|
}
|
2020-01-21 22:35:56 +00:00
|
|
|
virtual void visit(AstAlwaysPublic* nodep) VL_OVERRIDE {
|
2019-05-19 20:13:13 +00:00
|
|
|
movedDeleteOrIterate(nodep);
|
2010-04-06 00:01:17 +00:00
|
|
|
}
|
2020-01-21 22:35:56 +00:00
|
|
|
virtual void visit(AstCoverToggle* nodep) VL_OVERRIDE {
|
2019-05-19 20:13:13 +00:00
|
|
|
movedDeleteOrIterate(nodep);
|
2008-12-12 20:34:02 +00:00
|
|
|
}
|
2020-01-21 22:35:56 +00:00
|
|
|
virtual void visit(AstNodeFTask* nodep) VL_OVERRIDE {
|
2019-05-19 20:13:13 +00:00
|
|
|
movedDeleteOrIterate(nodep);
|
2006-08-26 11:35:28 +00:00
|
|
|
}
|
2020-01-21 22:35:56 +00:00
|
|
|
virtual void visit(AstCFunc* nodep) VL_OVERRIDE {
|
2019-05-19 20:13:13 +00:00
|
|
|
movedDeleteOrIterate(nodep);
|
2006-08-26 11:35:28 +00:00
|
|
|
}
|
|
|
|
|
2020-01-21 22:35:56 +00:00
|
|
|
virtual void visit(AstVarXRef* nodep) VL_OVERRIDE {
|
2019-05-19 20:13:13 +00:00
|
|
|
// The crossrefs are dealt with in V3LinkDot
|
|
|
|
nodep->varp(NULL);
|
2009-11-08 02:05:02 +00:00
|
|
|
}
|
2020-01-21 22:35:56 +00:00
|
|
|
virtual void visit(AstNodeFTaskRef* nodep) VL_OVERRIDE {
|
2019-05-19 20:13:13 +00:00
|
|
|
// The crossrefs are dealt with in V3LinkDot
|
|
|
|
UINFO(9," Old pkg-taskref "<<nodep<<endl);
|
|
|
|
if (nodep->packagep()) {
|
|
|
|
// Point to the clone
|
2019-07-06 16:57:50 +00:00
|
|
|
UASSERT_OBJ(nodep->taskp(), nodep, "Unlinked");
|
2018-02-02 02:32:58 +00:00
|
|
|
AstNodeFTask* newp = VN_CAST(nodep->taskp()->user2p(), NodeFTask);
|
2019-07-06 16:57:50 +00:00
|
|
|
UASSERT_OBJ(newp, nodep, "No clone for package function");
|
2019-05-19 20:13:13 +00:00
|
|
|
nodep->taskp(newp);
|
|
|
|
UINFO(9," New pkg-taskref "<<nodep<<endl);
|
2020-03-07 17:52:11 +00:00
|
|
|
} else if (!VN_IS(nodep, MethodCall)) {
|
2019-05-19 20:13:13 +00:00
|
|
|
nodep->taskp(NULL);
|
|
|
|
UINFO(9," New pkg-taskref "<<nodep<<endl);
|
|
|
|
}
|
2018-05-11 00:55:37 +00:00
|
|
|
iterateChildren(nodep);
|
2009-11-08 02:05:02 +00:00
|
|
|
}
|
2020-01-21 22:35:56 +00:00
|
|
|
virtual void visit(AstModportFTaskRef* nodep) VL_OVERRIDE {
|
2019-05-19 20:13:13 +00:00
|
|
|
// The crossrefs are dealt with in V3LinkDot
|
|
|
|
nodep->ftaskp(NULL);
|
2018-05-11 00:55:37 +00:00
|
|
|
iterateChildren(nodep);
|
2013-12-21 11:51:15 +00:00
|
|
|
}
|
2009-11-08 02:05:02 +00:00
|
|
|
|
2006-08-26 11:35:28 +00:00
|
|
|
//--------------------
|
2020-04-04 12:31:14 +00:00
|
|
|
virtual void visit(AstNode* nodep) VL_OVERRIDE { iterateChildren(nodep); }
|
|
|
|
|
2006-08-26 11:35:28 +00:00
|
|
|
public:
|
2019-09-12 11:22:22 +00:00
|
|
|
// CONSTRUCTORS
|
2015-10-04 02:33:06 +00:00
|
|
|
explicit ScopeCleanupVisitor(AstNetlist* nodep) {
|
2019-05-19 20:13:13 +00:00
|
|
|
m_scopep = NULL;
|
2018-05-11 00:55:37 +00:00
|
|
|
iterate(nodep);
|
2006-08-26 11:35:28 +00:00
|
|
|
}
|
|
|
|
virtual ~ScopeCleanupVisitor() {}
|
|
|
|
};
|
|
|
|
|
|
|
|
//######################################################################
|
|
|
|
// Scope class functions
|
|
|
|
|
|
|
|
void V3Scope::scopeAll(AstNetlist* nodep) {
|
|
|
|
UINFO(2,__FUNCTION__<<": "<<endl);
|
2018-03-10 17:57:50 +00:00
|
|
|
{
|
|
|
|
ScopeVisitor visitor (nodep);
|
|
|
|
ScopeCleanupVisitor cleanVisitor (nodep);
|
|
|
|
} // Destruct before checking
|
2017-09-18 02:52:57 +00:00
|
|
|
V3Global::dumpCheckGlobalTree("scope", 0, v3Global.opt.dumpTreeLevel(__FILE__) >= 3);
|
2006-08-26 11:35:28 +00:00
|
|
|
}
|