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 active domains
|
|
|
|
//
|
2019-11-08 03:33:59 +00:00
|
|
|
// Code available from: https://verilator.org
|
2006-08-26 11:35:28 +00:00
|
|
|
//
|
|
|
|
//*************************************************************************
|
|
|
|
//
|
2020-01-06 23:05:53 +00:00
|
|
|
// Copyright 2003-2020 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.
|
|
|
|
//
|
|
|
|
//*************************************************************************
|
|
|
|
// V3Active's Transformations:
|
2008-06-10 01:25:10 +00:00
|
|
|
//
|
2006-08-26 11:35:28 +00:00
|
|
|
// Note this can be called multiple times.
|
|
|
|
// Across all ACTIVES
|
2019-05-19 20:13:13 +00:00
|
|
|
// SenTrees are now under each ACTIVE statement, we want them global:
|
|
|
|
// Find SenTree in under global TopScope, or create it there
|
|
|
|
// Move SenTree the global SenTree
|
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"
|
2006-08-26 11:35:28 +00:00
|
|
|
|
|
|
|
#include "V3Global.h"
|
|
|
|
#include "V3ActiveTop.h"
|
|
|
|
#include "V3Ast.h"
|
|
|
|
#include "V3SenTree.h"
|
2009-01-07 14:37:59 +00:00
|
|
|
#include "V3Const.h"
|
2006-08-26 11:35:28 +00:00
|
|
|
|
|
|
|
//######################################################################
|
|
|
|
// Active class functions
|
|
|
|
|
|
|
|
class ActiveTopVisitor : public AstNVisitor {
|
|
|
|
private:
|
|
|
|
// NODE STATE
|
|
|
|
// Entire netlist
|
2019-05-19 20:13:13 +00:00
|
|
|
// AstNode::user() bool. True if processed
|
2009-01-07 14:37:59 +00:00
|
|
|
// Each call to V3Const::constify
|
2019-05-19 20:13:13 +00:00
|
|
|
// AstNode::user4() Used by V3Const::constify, called below
|
|
|
|
AstUser1InUse m_inuser1;
|
2008-11-21 20:50:33 +00:00
|
|
|
|
2006-08-26 11:35:28 +00:00
|
|
|
// STATE
|
2019-05-19 20:13:13 +00:00
|
|
|
AstTopScope* m_topscopep; // Top scope for adding sentrees under
|
|
|
|
SenTreeFinder m_finder; // Find global sentree's and add them
|
2009-01-21 21:56:50 +00:00
|
|
|
|
|
|
|
// METHODS
|
2018-05-14 10:50:47 +00:00
|
|
|
VL_DEBUG_FUNC; // Declare debug()
|
2006-08-26 11:35:28 +00:00
|
|
|
|
|
|
|
// VISITORS
|
2020-01-21 22:35:56 +00:00
|
|
|
virtual void visit(AstTopScope* nodep) VL_OVERRIDE {
|
2019-05-19 20:13:13 +00:00
|
|
|
m_topscopep = nodep;
|
|
|
|
m_finder.main(m_topscopep);
|
2018-05-11 00:55:37 +00:00
|
|
|
iterateChildren(nodep);
|
2019-05-19 20:13:13 +00:00
|
|
|
m_topscopep = NULL;
|
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 actives and add to module
|
|
|
|
// We can start ordering at a module, or a scope
|
|
|
|
UINFO(4," MOD "<<nodep<<endl);
|
2018-05-11 00:55:37 +00:00
|
|
|
iterateChildren(nodep);
|
2006-08-26 11:35:28 +00:00
|
|
|
}
|
2020-01-21 22:35:56 +00:00
|
|
|
virtual void visit(AstActive* nodep) VL_OVERRIDE {
|
2019-05-19 20:13:13 +00:00
|
|
|
UINFO(4," ACTIVE "<<nodep<<endl);
|
|
|
|
V3Const::constifyExpensiveEdit(nodep); // Remove duplicate clocks and such; sensesp() may change!
|
|
|
|
AstSenTree* sensesp = nodep->sensesp();
|
2019-07-06 16:57:50 +00:00
|
|
|
UASSERT_OBJ(sensesp, nodep, "NULL");
|
2019-05-19 20:13:13 +00:00
|
|
|
if (sensesp->sensesp()
|
2018-02-02 02:32:58 +00:00
|
|
|
&& VN_IS(sensesp->sensesp(), SenItem)
|
|
|
|
&& VN_CAST(sensesp->sensesp(), SenItem)->isNever()) {
|
2019-05-19 20:13:13 +00:00
|
|
|
// Never executing. Kill it.
|
2019-07-06 16:57:50 +00:00
|
|
|
UASSERT_OBJ(!sensesp->sensesp()->nextp(), nodep,
|
|
|
|
"Never senitem should be alone, else the never should be eliminated.");
|
2020-01-17 01:17:11 +00:00
|
|
|
VL_DO_DANGLING(nodep->unlinkFrBack()->deleteTree(), nodep);
|
2019-05-19 20:13:13 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
// Copy combo tree to settlement tree with duplicated statements
|
|
|
|
if (sensesp->hasCombo()) {
|
|
|
|
AstSenTree* newsentreep
|
2018-08-25 13:52:45 +00:00
|
|
|
= new AstSenTree(nodep->fileline(),
|
2019-05-19 20:13:13 +00:00
|
|
|
new AstSenItem(nodep->fileline(), AstSenItem::Settle()));
|
|
|
|
AstActive* newp = new AstActive(nodep->fileline(),"settle", newsentreep);
|
|
|
|
newp->sensesStorep(newsentreep);
|
|
|
|
if (nodep->stmtsp()) newp->addStmtsp(nodep->stmtsp()->cloneTree(true));
|
|
|
|
nodep->addNextHere(newp);
|
|
|
|
}
|
|
|
|
// Move the SENTREE for each active up to the global level.
|
|
|
|
// This way we'll easily see what clock domains are identical
|
|
|
|
AstSenTree* wantp = m_finder.getSenTree(nodep->fileline(), sensesp);
|
|
|
|
UINFO(4," lookdone\n");
|
|
|
|
if (wantp != sensesp) {
|
|
|
|
// Move the active's contents to the other active
|
|
|
|
UINFO(4," merge active "<<sensesp<<" into "<<wantp<<endl);
|
|
|
|
if (nodep->sensesStorep()) {
|
2019-07-06 16:57:50 +00:00
|
|
|
UASSERT_OBJ(sensesp == nodep->sensesStorep(), nodep,
|
|
|
|
"sensesStore should have been deleted earlier if different");
|
2019-05-19 20:13:13 +00:00
|
|
|
sensesp->unlinkFrBack();
|
|
|
|
// There may be other references to same sense tree,
|
|
|
|
// we'll be removing all references when we get to them,
|
|
|
|
// but don't dangle our pointer yet!
|
|
|
|
pushDeletep(sensesp);
|
|
|
|
}
|
|
|
|
nodep->sensesp(wantp);
|
|
|
|
}
|
|
|
|
// No need to do statements under it, they're already moved.
|
2018-05-11 00:55:37 +00:00
|
|
|
//iterateChildren(nodep);
|
2006-08-26 11:35:28 +00:00
|
|
|
}
|
2020-01-21 22:35:56 +00:00
|
|
|
virtual void visit(AstInitial* nodep) VL_OVERRIDE { // LCOV_EXCL_LINE
|
2019-05-19 20:13:13 +00:00
|
|
|
nodep->v3fatalSrc("Node should have been under ACTIVE");
|
2006-08-26 11:35:28 +00:00
|
|
|
}
|
2020-01-21 22:35:56 +00:00
|
|
|
virtual void visit(AstAssignAlias* nodep) VL_OVERRIDE { // LCOV_EXCL_LINE
|
2019-05-19 20:13:13 +00:00
|
|
|
nodep->v3fatalSrc("Node should have been under ACTIVE");
|
2006-08-26 11:35:28 +00:00
|
|
|
}
|
2020-01-21 22:35:56 +00:00
|
|
|
virtual void visit(AstAssignW* nodep) VL_OVERRIDE { // LCOV_EXCL_LINE
|
2019-05-19 20:13:13 +00:00
|
|
|
nodep->v3fatalSrc("Node should have been under ACTIVE");
|
2006-08-26 11:35:28 +00:00
|
|
|
}
|
2020-01-21 22:35:56 +00:00
|
|
|
virtual void visit(AstAlways* nodep) VL_OVERRIDE { // LCOV_EXCL_LINE
|
2019-05-19 20:13:13 +00:00
|
|
|
nodep->v3fatalSrc("Node should have been under ACTIVE");
|
2006-08-26 11:35:28 +00:00
|
|
|
}
|
2020-01-21 22:35:56 +00:00
|
|
|
virtual void visit(AstAlwaysPublic* nodep) VL_OVERRIDE { // LCOV_EXCL_LINE
|
2019-05-19 20:13:13 +00:00
|
|
|
nodep->v3fatalSrc("Node should have been under ACTIVE");
|
2010-04-06 00:01:17 +00:00
|
|
|
}
|
2020-01-21 22:35:56 +00:00
|
|
|
virtual void visit(AstFinal* nodep) VL_OVERRIDE { // LCOV_EXCL_LINE
|
2019-05-19 20:13:13 +00:00
|
|
|
nodep->v3fatalSrc("Node should have been deleted");
|
2006-08-26 11:35:28 +00:00
|
|
|
}
|
|
|
|
// Empty visitors, speed things up
|
2020-01-21 22:35:56 +00:00
|
|
|
virtual void visit(AstNodeMath* nodep) VL_OVERRIDE {}
|
|
|
|
virtual void visit(AstVarScope* nodep) VL_OVERRIDE {}
|
2006-08-26 11:35:28 +00:00
|
|
|
//--------------------
|
2020-01-21 22:35:56 +00:00
|
|
|
virtual void visit(AstNode* nodep) VL_OVERRIDE {
|
2018-05-11 00:55:37 +00:00
|
|
|
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 ActiveTopVisitor(AstNetlist* nodep) {
|
2019-05-19 20:13:13 +00:00
|
|
|
m_topscopep = NULL;
|
2018-05-11 00:55:37 +00:00
|
|
|
iterate(nodep);
|
2006-08-26 11:35:28 +00:00
|
|
|
}
|
|
|
|
virtual ~ActiveTopVisitor() {}
|
|
|
|
};
|
|
|
|
|
|
|
|
//######################################################################
|
|
|
|
// Active class functions
|
|
|
|
|
|
|
|
void V3ActiveTop::activeTopAll(AstNetlist* nodep) {
|
|
|
|
UINFO(2,__FUNCTION__<<": "<<endl);
|
2018-03-10 17:57:50 +00:00
|
|
|
{
|
|
|
|
ActiveTopVisitor visitor (nodep);
|
|
|
|
} // Destruct before checking
|
2017-09-18 02:52:57 +00:00
|
|
|
V3Global::dumpCheckGlobalTree("activetop", 0, v3Global.opt.dumpTreeLevel(__FILE__) >= 3);
|
2006-08-26 11:35:28 +00:00
|
|
|
}
|