parent
0e62cd11da
commit
282887d9c6
|
|
@ -514,10 +514,9 @@ private:
|
|||
visitAlways(nodep, nodep->sensesp(), nodep->keyword());
|
||||
}
|
||||
virtual void visit(AstAlwaysPostponed* nodep) override {
|
||||
if (!nodep->bodysp()) { // Empty always. Remove it now.
|
||||
VL_DO_DANGLING(nodep->unlinkFrBack()->deleteTree(), nodep);
|
||||
return;
|
||||
}
|
||||
// Might be empty with later optimizations, so this assertion can be removed,
|
||||
// but for now it is guaranteed to be not empty.
|
||||
UASSERT_OBJ(nodep->bodysp(), nodep, "Should not be empty");
|
||||
visitAlways(nodep, nullptr, VAlwaysKwd::ALWAYS);
|
||||
}
|
||||
virtual void visit(AstAlwaysPublic* nodep) override {
|
||||
|
|
|
|||
|
|
@ -119,30 +119,26 @@ private:
|
|||
pushDeletep(nodep); // Delete it later, AstActives still pointing to it
|
||||
}
|
||||
virtual void visit(AstActive* nodep) override {
|
||||
// Careful if adding variables here, ACTIVES can be under other ACTIVES
|
||||
// Need to save and restore any member state in AstUntilStable block
|
||||
UASSERT_OBJ(nodep->hasClocked(), nodep, "Should have been converted by V3Sched");
|
||||
UASSERT_OBJ(nodep->stmtsp(), nodep, "Should not have been created if empty");
|
||||
|
||||
VNRelinker relinker;
|
||||
nodep->unlinkFrBack(&relinker);
|
||||
UASSERT_OBJ(nodep->stmtsp(), nodep, "Should not have been created if empty");
|
||||
AstNode* const stmtsp = nodep->stmtsp()->unlinkFrBackWithNext();
|
||||
if (nodep->hasClocked()) {
|
||||
// Create 'if' statement, if needed
|
||||
if (!m_lastSenp || !nodep->sensesp()->sameTree(m_lastSenp)) {
|
||||
clearLastSen();
|
||||
m_lastSenp = nodep->sensesp();
|
||||
// Make a new if statement
|
||||
m_lastIfp = makeActiveIf(m_lastSenp);
|
||||
relinker.relink(m_lastIfp);
|
||||
}
|
||||
// Move statements to if
|
||||
m_lastIfp->addIfsp(stmtsp);
|
||||
} else if (nodep->hasCombo()) {
|
||||
|
||||
// Create 'if' statement, if needed
|
||||
if (!m_lastSenp || !nodep->sensesp()->sameTree(m_lastSenp)) {
|
||||
clearLastSen();
|
||||
// Move statements to body
|
||||
relinker.relink(stmtsp);
|
||||
} else {
|
||||
nodep->v3fatalSrc("Should have been removed by V3Sched::schedule");
|
||||
m_lastSenp = nodep->sensesp();
|
||||
// Make a new if statement
|
||||
m_lastIfp = makeActiveIf(m_lastSenp);
|
||||
relinker.relink(m_lastIfp);
|
||||
}
|
||||
|
||||
// Move statements to if
|
||||
m_lastIfp->addIfsp(stmtsp);
|
||||
|
||||
// Dispose of the AstActive
|
||||
VL_DO_DANGLING(nodep->deleteTree(), nodep);
|
||||
}
|
||||
virtual void visit(AstExecGraph* nodep) override {
|
||||
|
|
|
|||
170
src/V3Order.cpp
170
src/V3Order.cpp
|
|
@ -112,8 +112,8 @@ void OrderGraph::loopsVertexCb(V3GraphVertex* vertexp) {
|
|||
<< " Example path: " << vvertexp->nodep()->typeName() << endl;
|
||||
}
|
||||
if (OrderVarVertex* const vvertexp = dynamic_cast<OrderVarVertex*>(vertexp)) {
|
||||
std::cerr << vvertexp->varScp()->fileline()->warnOther()
|
||||
<< " Example path: " << vvertexp->varScp()->prettyName() << endl;
|
||||
std::cerr << vvertexp->vscp()->fileline()->warnOther()
|
||||
<< " Example path: " << vvertexp->vscp()->prettyName() << endl;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -924,9 +924,6 @@ class OrderProcess final : VNDeleter {
|
|||
V3List<OrderMoveDomScope*> m_pomReadyDomScope; // List of ready domain/scope pairs, by loopId
|
||||
std::map<std::pair<AstNodeModule*, std::string>, unsigned> m_funcNums; // Function ordinals
|
||||
|
||||
// STATS
|
||||
std::array<VDouble0, OrderVEdgeType::_ENUM_END> m_statCut; // Count of each edge type cut
|
||||
|
||||
// METHODS
|
||||
VL_DEBUG_FUNC; // Declare debug()
|
||||
|
||||
|
|
@ -999,15 +996,7 @@ class OrderProcess final : VNDeleter {
|
|||
pushDeletep(m_deleteDomainp);
|
||||
}
|
||||
|
||||
~OrderProcess() {
|
||||
// Stats
|
||||
for (int type = 0; type < OrderVEdgeType::_ENUM_END; type++) {
|
||||
const double count = double(m_statCut[type]);
|
||||
if (count != 0.0) {
|
||||
V3Stats::addStat(string("Order, cut, ") + OrderVEdgeType(type).ascii(), count);
|
||||
}
|
||||
}
|
||||
}
|
||||
~OrderProcess() = default;
|
||||
|
||||
public:
|
||||
// Order the logic
|
||||
|
|
@ -1071,16 +1060,18 @@ void OrderProcess::processDomainsIterate(OrderEitherVertex* vertexp) {
|
|||
OrderEitherVertex* const fromVertexp = static_cast<OrderEitherVertex*>(edgep->fromp());
|
||||
if (edgep->weight() && fromVertexp->domainMatters()) {
|
||||
AstSenTree* fromDomainp = fromVertexp->domainp();
|
||||
UASSERT(!fromDomainp->hasCombo(), "There should be no need for combinational domains");
|
||||
|
||||
if (OrderVarVertex* const varVtxp = dynamic_cast<OrderVarVertex*>(fromVertexp)) {
|
||||
AstVarScope* const vscp = varVtxp->varScp();
|
||||
AstVarScope* const vscp = varVtxp->vscp();
|
||||
if (AstSenTree* const externalDomainp = m_externalDomain(vscp)) {
|
||||
UASSERT(!externalDomainp->hasCombo(),
|
||||
"There should be no need for combinational domains");
|
||||
fromDomainp = fromDomainp == m_deleteDomainp
|
||||
? externalDomainp
|
||||
: combineDomains(fromDomainp, externalDomainp);
|
||||
}
|
||||
}
|
||||
UINFO(9, " from d=" << cvtToHex(fromDomainp) << " " << fromVertexp << endl);
|
||||
UASSERT(!fromDomainp->hasCombo(), "There should be no need for combinational domains");
|
||||
|
||||
// Irrelevant input vertex (never triggered)
|
||||
if (fromDomainp == m_deleteDomainp) continue;
|
||||
|
|
@ -1088,29 +1079,22 @@ void OrderProcess::processDomainsIterate(OrderEitherVertex* vertexp) {
|
|||
// First input to this vertex
|
||||
if (!domainp) domainp = fromDomainp;
|
||||
|
||||
// Once in combo, keep in combo; already as severe as we can get
|
||||
if (domainp->hasCombo()) break;
|
||||
|
||||
// Make a domain that merges the two domains
|
||||
if (domainp != fromDomainp) domainp = combineDomains(domainp, fromDomainp);
|
||||
}
|
||||
}
|
||||
|
||||
// Default the domain
|
||||
// This is a node which has only constant inputs, or is otherwise indeterminate.
|
||||
// Presumably it has inputs which we never trigger, or nothing it's sensitive to,
|
||||
// so we can rip it out.
|
||||
if (!domainp && vertexp->scopep()) domainp = m_deleteDomainp;
|
||||
// If nothing triggers this vertex, we can delete the corresponding logic
|
||||
if (!domainp) domainp = m_deleteDomainp;
|
||||
|
||||
if (domainp) {
|
||||
vertexp->domainp(domainp);
|
||||
UINFO(5, " done d=" << cvtToHex(vertexp->domainp())
|
||||
<< (domainp == m_deleteDomainp ? " [DEL]"
|
||||
: vertexp->domainp()->hasCombo() ? " [COMB]"
|
||||
: vertexp->domainp()->isMulti() ? " [MULT]"
|
||||
: "")
|
||||
<< " " << vertexp << endl);
|
||||
}
|
||||
// Set the domain of the vertex
|
||||
vertexp->domainp(domainp);
|
||||
UINFO(5, " done d=" << cvtToHex(vertexp->domainp())
|
||||
<< (domainp == m_deleteDomainp ? " [DEL]"
|
||||
: vertexp->domainp()->hasCombo() ? " [COMB]"
|
||||
: vertexp->domainp()->isMulti() ? " [MULT]"
|
||||
: "")
|
||||
<< " " << vertexp << endl);
|
||||
}
|
||||
|
||||
//######################################################################
|
||||
|
|
@ -1131,7 +1115,7 @@ void OrderProcess::processEdgeReport() {
|
|||
|
||||
for (V3GraphVertex* itp = m_graph.verticesBeginp(); itp; itp = itp->verticesNextp()) {
|
||||
if (OrderVarVertex* const vvertexp = dynamic_cast<OrderVarVertex*>(itp)) {
|
||||
string name(vvertexp->varScp()->prettyName());
|
||||
string name(vvertexp->vscp()->prettyName());
|
||||
if (dynamic_cast<OrderVarPreVertex*>(itp)) {
|
||||
name += " {PRE}";
|
||||
} else if (dynamic_cast<OrderVarPostVertex*>(itp)) {
|
||||
|
|
@ -1141,7 +1125,7 @@ void OrderProcess::processEdgeReport() {
|
|||
}
|
||||
std::ostringstream os;
|
||||
os.setf(std::ios::left);
|
||||
os << " " << cvtToHex(vvertexp->varScp()) << " " << std::setw(50) << name << " ";
|
||||
os << " " << cvtToHex(vvertexp->vscp()) << " " << std::setw(50) << name << " ";
|
||||
AstSenTree* const senTreep = vvertexp->domainp();
|
||||
if (senTreep == m_deleteDomainp) {
|
||||
os << "DELETED";
|
||||
|
|
@ -1314,67 +1298,65 @@ AstActive* OrderProcess::processMoveOneLogic(const OrderLogicVertex* lvertexp,
|
|||
AstNode* nodep = lvertexp->nodep();
|
||||
AstNodeModule* const modp = scopep->modp();
|
||||
UASSERT(modp, "nullptr");
|
||||
if (VN_IS(nodep, Active)) {
|
||||
// Just ignore sensitivities, we'll deal with them when we move statements that need them
|
||||
} else { // Normal logic
|
||||
// Move the logic into a CFunc
|
||||
|
||||
// We are move the logic into a CFunc, so unlink it from the AstActive
|
||||
nodep->unlinkFrBack();
|
||||
|
||||
// Process procedures per statement (unless profCFuncs), so we can split CFuncs within
|
||||
// procedures. Everything else is handled in one go
|
||||
if (AstNodeProcedure* const procp = VN_CAST(nodep, NodeProcedure)) {
|
||||
nodep = procp->bodysp();
|
||||
pushDeletep(procp);
|
||||
}
|
||||
|
||||
// When profCFuncs, create a new function for all logic block
|
||||
if (v3Global.opt.profCFuncs()) newFuncpr = nullptr;
|
||||
|
||||
while (nodep) {
|
||||
// Split the CFunc if too large (but not when profCFuncs)
|
||||
if (!v3Global.opt.profCFuncs()
|
||||
&& (v3Global.opt.outputSplitCFuncs()
|
||||
&& v3Global.opt.outputSplitCFuncs() < newStmtsr)) {
|
||||
// Put every statement into a unique function to ease profiling or reduce function
|
||||
// size
|
||||
newFuncpr = nullptr;
|
||||
}
|
||||
if (!newFuncpr && domainp != m_deleteDomainp) {
|
||||
const string name = cfuncName(modp, domainp, scopep, nodep);
|
||||
newFuncpr = new AstCFunc(nodep->fileline(), name, scopep);
|
||||
newFuncpr->isStatic(false);
|
||||
newFuncpr->isLoose(true);
|
||||
newFuncpr->slow(m_slow);
|
||||
newStmtsr = 0;
|
||||
scopep->addActivep(newFuncpr);
|
||||
// Create top call to it
|
||||
AstCCall* const callp = new AstCCall(nodep->fileline(), newFuncpr);
|
||||
// Where will we be adding the call?
|
||||
AstActive* const newActivep = new AstActive(nodep->fileline(), name, domainp);
|
||||
newActivep->addStmtsp(callp);
|
||||
if (!activep) {
|
||||
activep = newActivep;
|
||||
} else {
|
||||
activep->addNext(newActivep);
|
||||
}
|
||||
UINFO(6, " New " << newFuncpr << endl);
|
||||
}
|
||||
|
||||
AstNode* const nextp = nodep->nextp();
|
||||
// When processing statements in a procedure, unlink the current statement
|
||||
if (nodep->backp()) nodep->unlinkFrBack();
|
||||
|
||||
// Process procedures per statement (unless profCFuncs), so we can split CFuncs within
|
||||
// procedures. Everything else is handled in one go
|
||||
if (AstNodeProcedure* const procp = VN_CAST(nodep, NodeProcedure)) {
|
||||
nodep = procp->bodysp();
|
||||
pushDeletep(procp);
|
||||
if (domainp == m_deleteDomainp) {
|
||||
VL_DO_DANGLING(pushDeletep(nodep), nodep);
|
||||
} else {
|
||||
newFuncpr->addStmtsp(nodep);
|
||||
// Add in the number of nodes we're adding
|
||||
if (v3Global.opt.outputSplitCFuncs()) newStmtsr += nodep->nodeCount();
|
||||
}
|
||||
|
||||
// When profCFuncs, create a new function for all logic block
|
||||
if (v3Global.opt.profCFuncs()) newFuncpr = nullptr;
|
||||
|
||||
while (nodep) {
|
||||
// Split the CFunc if too large (but not when profCFuncs)
|
||||
if (!v3Global.opt.profCFuncs()
|
||||
&& (v3Global.opt.outputSplitCFuncs()
|
||||
&& v3Global.opt.outputSplitCFuncs() < newStmtsr)) {
|
||||
// Put every statement into a unique function to ease profiling or reduce function
|
||||
// size
|
||||
newFuncpr = nullptr;
|
||||
}
|
||||
if (!newFuncpr && domainp != m_deleteDomainp) {
|
||||
const string name = cfuncName(modp, domainp, scopep, nodep);
|
||||
newFuncpr = new AstCFunc(nodep->fileline(), name, scopep);
|
||||
newFuncpr->isStatic(false);
|
||||
newFuncpr->isLoose(true);
|
||||
newFuncpr->slow(m_slow);
|
||||
newStmtsr = 0;
|
||||
scopep->addActivep(newFuncpr);
|
||||
// Create top call to it
|
||||
AstCCall* const callp = new AstCCall(nodep->fileline(), newFuncpr);
|
||||
// Where will we be adding the call?
|
||||
AstActive* const newActivep = new AstActive(nodep->fileline(), name, domainp);
|
||||
newActivep->addStmtsp(callp);
|
||||
if (!activep) {
|
||||
activep = newActivep;
|
||||
} else {
|
||||
activep->addNext(newActivep);
|
||||
}
|
||||
UINFO(6, " New " << newFuncpr << endl);
|
||||
}
|
||||
|
||||
AstNode* const nextp = nodep->nextp();
|
||||
// When processing statements in a procedure, unlink the current statement
|
||||
if (nodep->backp()) nodep->unlinkFrBack();
|
||||
|
||||
if (domainp == m_deleteDomainp) {
|
||||
VL_DO_DANGLING(pushDeletep(nodep), nodep);
|
||||
} else {
|
||||
newFuncpr->addStmtsp(nodep);
|
||||
// Add in the number of nodes we're adding
|
||||
if (v3Global.opt.outputSplitCFuncs()) newStmtsr += nodep->nodeCount();
|
||||
}
|
||||
|
||||
nodep = nextp;
|
||||
}
|
||||
nodep = nextp;
|
||||
}
|
||||
|
||||
return activep;
|
||||
}
|
||||
|
||||
|
|
@ -1430,7 +1412,7 @@ void OrderProcess::processMTasks() {
|
|||
const OrderVarVertex* const pre_varp
|
||||
= dynamic_cast<const OrderVarVertex*>(edgep->fromp());
|
||||
if (!pre_varp) continue;
|
||||
AstVar* const varp = pre_varp->varScp()->varp();
|
||||
AstVar* const varp = pre_varp->vscp()->varp();
|
||||
// varp depends on logicp, so logicp produces varp,
|
||||
// and vice-versa below
|
||||
varp->addProducingMTaskId(mtaskId);
|
||||
|
|
@ -1440,7 +1422,7 @@ void OrderProcess::processMTasks() {
|
|||
const OrderVarVertex* const post_varp
|
||||
= dynamic_cast<const OrderVarVertex*>(edgep->top());
|
||||
if (!post_varp) continue;
|
||||
AstVar* const varp = post_varp->varScp()->varp();
|
||||
AstVar* const varp = post_varp->vscp()->varp();
|
||||
varp->addConsumingMTaskId(mtaskId);
|
||||
}
|
||||
// TODO? We ignore IO vars here, so those will have empty mtask
|
||||
|
|
|
|||
|
|
@ -43,7 +43,6 @@
|
|||
|
||||
#include <unordered_map>
|
||||
|
||||
class OrderVisitor;
|
||||
class OrderMoveVertex;
|
||||
class OrderMoveVertexMaker;
|
||||
class OrderMoveDomScope;
|
||||
|
|
@ -55,50 +54,8 @@ enum OrderWeights : uint8_t {
|
|||
WEIGHT_POST = 2, // Post-delayed used var
|
||||
WEIGHT_PRE = 3, // Breakable pre-delayed used var
|
||||
WEIGHT_MEDIUM = 8, // Medium weight just so dot graph looks nice
|
||||
WEIGHT_NORMAL = 32
|
||||
}; // High weight just so dot graph looks nice
|
||||
|
||||
struct OrderVEdgeType {
|
||||
enum en : uint8_t {
|
||||
VERTEX_UNKNOWN = 0,
|
||||
VERTEX_LOGIC,
|
||||
VERTEX_VARSTD,
|
||||
VERTEX_VARPRE,
|
||||
VERTEX_VARPOST,
|
||||
VERTEX_VARPORD,
|
||||
VERTEX_MOVE,
|
||||
EDGE_STD,
|
||||
EDGE_COMBOCUT,
|
||||
EDGE_PRECUT,
|
||||
EDGE_POSTCUT,
|
||||
_ENUM_END
|
||||
};
|
||||
const char* ascii() const {
|
||||
static const char* const names[]
|
||||
= {"%E-vedge", "VERTEX_LOGIC", "VERTEX_VARSTD", "VERTEX_VARPRE",
|
||||
"VERTEX_VARPOST", "VERTEX_VARPORD", "VERTEX_MOVE", "EDGE_STD",
|
||||
"EDGE_COMBOCUT", "EDGE_PRECUT", "EDGE_POSTCUT", "_ENUM_END"};
|
||||
return names[m_e];
|
||||
}
|
||||
enum en m_e;
|
||||
inline OrderVEdgeType()
|
||||
: m_e{VERTEX_UNKNOWN} {}
|
||||
// cppcheck-suppress noExplicitConstructor
|
||||
inline OrderVEdgeType(en _e)
|
||||
: m_e{_e} {}
|
||||
explicit inline OrderVEdgeType(int _e)
|
||||
: m_e(static_cast<en>(_e)) {} // Need () or GCC 4.8 false warning
|
||||
operator en() const { return m_e; }
|
||||
WEIGHT_NORMAL = 32 // High weight just so dot graph looks nice
|
||||
};
|
||||
inline bool operator==(const OrderVEdgeType& lhs, const OrderVEdgeType& rhs) {
|
||||
return lhs.m_e == rhs.m_e;
|
||||
}
|
||||
inline bool operator==(const OrderVEdgeType& lhs, OrderVEdgeType::en rhs) {
|
||||
return lhs.m_e == rhs;
|
||||
}
|
||||
inline bool operator==(OrderVEdgeType::en lhs, const OrderVEdgeType& rhs) {
|
||||
return lhs == rhs.m_e;
|
||||
}
|
||||
|
||||
//######################################################################
|
||||
// Graph types
|
||||
|
|
@ -107,7 +64,7 @@ class OrderGraph final : public V3Graph {
|
|||
public:
|
||||
OrderGraph() = default;
|
||||
virtual ~OrderGraph() override = default;
|
||||
// Methods
|
||||
// METHODS
|
||||
virtual void loopsVertexCb(V3GraphVertex* vertexp) override;
|
||||
};
|
||||
|
||||
|
|
@ -117,156 +74,187 @@ public:
|
|||
class OrderEitherVertex VL_NOT_FINAL : public V3GraphVertex {
|
||||
AstScope* const m_scopep; // Scope the vertex is in
|
||||
AstSenTree* m_domainp; // Clock domain (nullptr = to be computed as we iterate)
|
||||
protected:
|
||||
OrderEitherVertex(V3Graph* graphp, const OrderEitherVertex& old)
|
||||
: V3GraphVertex{graphp, old}
|
||||
, m_scopep{old.m_scopep}
|
||||
, m_domainp{old.m_domainp} {}
|
||||
|
||||
public:
|
||||
protected:
|
||||
// CONSTRUCTOR
|
||||
OrderEitherVertex(V3Graph* graphp, AstScope* scopep, AstSenTree* domainp)
|
||||
: V3GraphVertex{graphp}
|
||||
, m_scopep{scopep}
|
||||
, m_domainp{domainp} {}
|
||||
, m_domainp{domainp} {
|
||||
UASSERT(scopep, "Must not be null");
|
||||
}
|
||||
virtual ~OrderEitherVertex() override = default;
|
||||
virtual OrderEitherVertex* clone(V3Graph* graphp) const override = 0;
|
||||
// Methods
|
||||
virtual OrderVEdgeType type() const = 0;
|
||||
virtual bool domainMatters() = 0; // Must be in same domain when cross edge to this vertex
|
||||
virtual string dotName() const override { return cvtToHex(m_scopep) + "_"; }
|
||||
|
||||
public:
|
||||
// METHODS
|
||||
virtual bool domainMatters() = 0;
|
||||
|
||||
// ACCESSORS
|
||||
AstSenTree* domainp() const { return m_domainp; }
|
||||
void domainp(AstSenTree* domainp) { m_domainp = domainp; }
|
||||
AstScope* scopep() const { return m_scopep; }
|
||||
AstSenTree* domainp() const { return m_domainp; }
|
||||
|
||||
// LCOV_EXCL_START // Debug code
|
||||
virtual string dotName() const override { return cvtToHex(m_scopep) + "_"; }
|
||||
// LCOV_EXCL_STOP
|
||||
};
|
||||
|
||||
class OrderLogicVertex final : public OrderEitherVertex {
|
||||
AstNode* const m_nodep;
|
||||
AstSenTree* const m_hybridp;
|
||||
|
||||
protected:
|
||||
OrderLogicVertex(V3Graph* graphp, const OrderLogicVertex& old)
|
||||
: OrderEitherVertex{graphp, old}
|
||||
, m_nodep{old.m_nodep}
|
||||
, m_hybridp{old.m_hybridp} {}
|
||||
|
||||
public:
|
||||
// CONSTRUCTOR
|
||||
OrderLogicVertex(V3Graph* graphp, AstScope* scopep, AstSenTree* domainp, AstSenTree* hybridp,
|
||||
AstNode* nodep)
|
||||
: OrderEitherVertex{graphp, scopep, domainp}
|
||||
, m_nodep{nodep}
|
||||
, m_hybridp{hybridp} {
|
||||
UASSERT_OBJ(!(domainp && hybridp), nodep, "Can't have bot domainp and hybridp set");
|
||||
UASSERT_OBJ(!(domainp && hybridp), nodep, "Cannot have bot domainp and hybridp set");
|
||||
}
|
||||
virtual ~OrderLogicVertex() override = default;
|
||||
virtual OrderLogicVertex* clone(V3Graph* graphp) const override {
|
||||
return new OrderLogicVertex(graphp, *this);
|
||||
}
|
||||
virtual OrderVEdgeType type() const override { return OrderVEdgeType::VERTEX_LOGIC; }
|
||||
|
||||
// METHODS
|
||||
virtual bool domainMatters() override { return true; }
|
||||
|
||||
// ACCESSORS
|
||||
AstNode* nodep() const { return m_nodep; }
|
||||
AstSenTree* hybridp() const { return m_hybridp; }
|
||||
|
||||
// LCOV_EXCL_START // Debug code
|
||||
virtual string name() const override {
|
||||
return (cvtToHex(m_nodep) + "\\n " + cvtToStr(nodep()->typeName()));
|
||||
}
|
||||
AstNode* nodep() const { return m_nodep; }
|
||||
AstSenTree* hybridp() const { return m_hybridp; }
|
||||
virtual string dotShape() const override {
|
||||
return VN_IS(m_nodep, Active) ? "doubleoctagon" : "rect";
|
||||
}
|
||||
// LCOV_EXCL_STOP
|
||||
};
|
||||
|
||||
class OrderVarVertex VL_NOT_FINAL : public OrderEitherVertex {
|
||||
AstVarScope* const m_varScp;
|
||||
|
||||
protected:
|
||||
OrderVarVertex(V3Graph* graphp, const OrderVarVertex& old)
|
||||
: OrderEitherVertex{graphp, old}
|
||||
, m_varScp{old.m_varScp} {}
|
||||
AstVarScope* const m_vscp;
|
||||
|
||||
public:
|
||||
OrderVarVertex(V3Graph* graphp, AstScope* scopep, AstVarScope* varScp)
|
||||
// CONSTRUCTOR
|
||||
OrderVarVertex(V3Graph* graphp, AstScope* scopep, AstVarScope* vscp)
|
||||
: OrderEitherVertex{graphp, scopep, nullptr}
|
||||
, m_varScp{varScp} {}
|
||||
, m_vscp{vscp} {}
|
||||
virtual ~OrderVarVertex() override = default;
|
||||
virtual OrderVarVertex* clone(V3Graph* graphp) const override = 0;
|
||||
virtual OrderVEdgeType type() const override = 0;
|
||||
virtual FileLine* fileline() const override { return varScp()->fileline(); }
|
||||
|
||||
// ACCESSORS
|
||||
AstVarScope* varScp() const { return m_varScp; }
|
||||
virtual string dotShape() const override { return "ellipse"; }
|
||||
AstVarScope* vscp() const { return m_vscp; }
|
||||
|
||||
// LCOV_EXCL_START // Debug code
|
||||
virtual string dotShape() const override final { return "ellipse"; }
|
||||
virtual string nameSuffix() const = 0;
|
||||
virtual string name() const override final {
|
||||
return cvtToHex(m_vscp) + " " + nameSuffix() + "\\n " + m_vscp->name();
|
||||
}
|
||||
// LCOV_EXCL_STOP
|
||||
};
|
||||
|
||||
class OrderVarStdVertex final : public OrderVarVertex {
|
||||
OrderVarStdVertex(V3Graph* graphp, const OrderVarStdVertex& old)
|
||||
: OrderVarVertex{graphp, old} {}
|
||||
|
||||
public:
|
||||
// CONSTRUCTOR
|
||||
OrderVarStdVertex(V3Graph* graphp, AstScope* scopep, AstVarScope* varScp)
|
||||
: OrderVarVertex{graphp, scopep, varScp} {}
|
||||
virtual ~OrderVarStdVertex() override = default;
|
||||
virtual OrderVarStdVertex* clone(V3Graph* graphp) const override {
|
||||
return new OrderVarStdVertex(graphp, *this);
|
||||
}
|
||||
virtual OrderVEdgeType type() const override { return OrderVEdgeType::VERTEX_VARSTD; }
|
||||
virtual string name() const override {
|
||||
return (cvtToHex(varScp()) + "\\n " + varScp()->name());
|
||||
}
|
||||
virtual string dotColor() const override { return "grey"; }
|
||||
virtual bool domainMatters() override { return true; }
|
||||
};
|
||||
class OrderVarPreVertex final : public OrderVarVertex {
|
||||
OrderVarPreVertex(V3Graph* graphp, const OrderVarPreVertex& old)
|
||||
: OrderVarVertex{graphp, old} {}
|
||||
|
||||
// METHODS
|
||||
virtual bool domainMatters() override { return true; }
|
||||
|
||||
// LCOV_EXCL_START // Debug code
|
||||
virtual string nameSuffix() const override { return ""; }
|
||||
virtual string dotColor() const override { return "grey"; }
|
||||
// LCOV_EXCL_STOP
|
||||
};
|
||||
|
||||
class OrderVarPreVertex final : public OrderVarVertex {
|
||||
public:
|
||||
// CONSTRUCTOR
|
||||
OrderVarPreVertex(V3Graph* graphp, AstScope* scopep, AstVarScope* varScp)
|
||||
: OrderVarVertex{graphp, scopep, varScp} {}
|
||||
virtual ~OrderVarPreVertex() override = default;
|
||||
virtual OrderVarPreVertex* clone(V3Graph* graphp) const override {
|
||||
return new OrderVarPreVertex(graphp, *this);
|
||||
}
|
||||
virtual OrderVEdgeType type() const override { return OrderVEdgeType::VERTEX_VARPRE; }
|
||||
virtual string name() const override {
|
||||
return (cvtToHex(varScp()) + " PRE\\n " + varScp()->name());
|
||||
}
|
||||
virtual string dotColor() const override { return "green"; }
|
||||
virtual bool domainMatters() override { return false; }
|
||||
};
|
||||
class OrderVarPostVertex final : public OrderVarVertex {
|
||||
OrderVarPostVertex(V3Graph* graphp, const OrderVarPostVertex& old)
|
||||
: OrderVarVertex{graphp, old} {}
|
||||
|
||||
// METHODS
|
||||
virtual bool domainMatters() override { return false; }
|
||||
|
||||
// LCOV_EXCL_START // Debug code
|
||||
virtual string nameSuffix() const override { return "PRE"; }
|
||||
virtual string dotColor() const override { return "green"; }
|
||||
// LCOV_EXCL_STOP
|
||||
};
|
||||
|
||||
class OrderVarPostVertex final : public OrderVarVertex {
|
||||
public:
|
||||
// CONSTRUCTOR
|
||||
OrderVarPostVertex(V3Graph* graphp, AstScope* scopep, AstVarScope* varScp)
|
||||
: OrderVarVertex{graphp, scopep, varScp} {}
|
||||
virtual OrderVarPostVertex* clone(V3Graph* graphp) const override {
|
||||
return new OrderVarPostVertex(graphp, *this);
|
||||
}
|
||||
virtual OrderVEdgeType type() const override { return OrderVEdgeType::VERTEX_VARPOST; }
|
||||
virtual ~OrderVarPostVertex() override = default;
|
||||
virtual string name() const override {
|
||||
return (cvtToHex(varScp()) + " POST\\n " + varScp()->name());
|
||||
}
|
||||
virtual string dotColor() const override { return "red"; }
|
||||
virtual bool domainMatters() override { return false; }
|
||||
};
|
||||
class OrderVarPordVertex final : public OrderVarVertex {
|
||||
OrderVarPordVertex(V3Graph* graphp, const OrderVarPordVertex& old)
|
||||
: OrderVarVertex{graphp, old} {}
|
||||
|
||||
// METHODS
|
||||
virtual bool domainMatters() override { return false; }
|
||||
|
||||
// LCOV_EXCL_START // Debug code
|
||||
virtual string nameSuffix() const override { return "POST"; }
|
||||
virtual string dotColor() const override { return "red"; }
|
||||
// LCOV_EXCL_STOP
|
||||
};
|
||||
|
||||
class OrderVarPordVertex final : public OrderVarVertex {
|
||||
public:
|
||||
// CONSTRUCTOR
|
||||
OrderVarPordVertex(V3Graph* graphp, AstScope* scopep, AstVarScope* varScp)
|
||||
: OrderVarVertex{graphp, scopep, varScp} {}
|
||||
virtual ~OrderVarPordVertex() override = default;
|
||||
virtual OrderVarPordVertex* clone(V3Graph* graphp) const override {
|
||||
return new OrderVarPordVertex(graphp, *this);
|
||||
}
|
||||
virtual OrderVEdgeType type() const override { return OrderVEdgeType::VERTEX_VARPORD; }
|
||||
virtual string name() const override {
|
||||
return (cvtToHex(varScp()) + " PORD\\n " + varScp()->name());
|
||||
}
|
||||
virtual string dotColor() const override { return "blue"; }
|
||||
|
||||
// METHODS
|
||||
virtual bool domainMatters() override { return false; }
|
||||
|
||||
// LCOV_EXCL_START // Debug code
|
||||
virtual string nameSuffix() const override { return "PORD"; }
|
||||
virtual string dotColor() const override { return "blue"; }
|
||||
// LCOV_EXCL_STOP
|
||||
};
|
||||
|
||||
//######################################################################
|
||||
// Edge types
|
||||
|
||||
class OrderEdge VL_NOT_FINAL : public V3GraphEdge {
|
||||
public:
|
||||
// CONSTRUCTOR
|
||||
OrderEdge(V3Graph* graphp, V3GraphVertex* fromp, V3GraphVertex* top, int weight,
|
||||
bool cutable = false)
|
||||
: V3GraphEdge{graphp, fromp, top, weight, cutable} {}
|
||||
virtual ~OrderEdge() override = default;
|
||||
};
|
||||
|
||||
class OrderPostCutEdge final : public OrderEdge {
|
||||
// Edge created from output of post assignment
|
||||
public:
|
||||
// CONSTRUCTOR
|
||||
OrderPostCutEdge(V3Graph* graphp, V3GraphVertex* fromp, V3GraphVertex* top)
|
||||
: OrderEdge{graphp, fromp, top, WEIGHT_COMBO, CUTABLE} {}
|
||||
virtual ~OrderPostCutEdge() override = default;
|
||||
|
||||
// LCOV_EXCL_START // Debug code
|
||||
virtual string dotColor() const override { return "palegreen"; }
|
||||
// LCOV_EXCL_STOP
|
||||
};
|
||||
|
||||
class OrderPreCutEdge final : public OrderEdge {
|
||||
// Edge created from var_PREVAR->consuming logic vertex
|
||||
// Always breakable, just results in performance loss
|
||||
// in which case we can't optimize away the pre/post delayed assignments
|
||||
public:
|
||||
// CONSTRUCTOR
|
||||
OrderPreCutEdge(V3Graph* graphp, V3GraphVertex* fromp, V3GraphVertex* top)
|
||||
: OrderEdge{graphp, fromp, top, WEIGHT_PRE, CUTABLE} {}
|
||||
virtual ~OrderPreCutEdge() override = default;
|
||||
|
||||
// LCOV_EXCL_START // Debug code
|
||||
virtual string dotColor() const override { return "khaki"; }
|
||||
// LCOV_EXCL_STOP
|
||||
};
|
||||
|
||||
//######################################################################
|
||||
|
|
@ -283,7 +271,7 @@ protected:
|
|||
friend class OrderProcess;
|
||||
friend class OrderMoveVertexMaker;
|
||||
// These only contain the "next" item,
|
||||
// for the head of the list, see the same var name under OrderVisitor
|
||||
// for the head of the list, see the same var name under OrderProcess
|
||||
V3ListEnt<OrderMoveVertex*> m_pomWaitingE; // List of nodes needing inputs to become ready
|
||||
V3ListEnt<OrderMoveVertex*> m_readyVerticesE; // List of ready under domain/scope
|
||||
public:
|
||||
|
|
@ -294,12 +282,8 @@ public:
|
|||
, m_state{POM_WAIT}
|
||||
, m_domScopep{nullptr} {}
|
||||
virtual ~OrderMoveVertex() override = default;
|
||||
virtual OrderMoveVertex* clone(V3Graph* graphp) const override {
|
||||
v3fatalSrc("Unsupported");
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
// METHODS
|
||||
virtual OrderVEdgeType type() const { return OrderVEdgeType::VERTEX_MOVE; }
|
||||
virtual string dotColor() const override {
|
||||
if (logicp()) {
|
||||
return logicp()->dotColor();
|
||||
|
|
@ -307,13 +291,7 @@ public:
|
|||
return "";
|
||||
}
|
||||
}
|
||||
virtual FileLine* fileline() const override {
|
||||
if (logicp()) {
|
||||
return logicp()->fileline();
|
||||
} else {
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
virtual string name() const override {
|
||||
string nm;
|
||||
if (VL_UNCOVERABLE(!logicp())) { // Avoid crash when debugging
|
||||
|
|
@ -350,9 +328,6 @@ class MTaskMoveVertex final : public V3GraphVertex {
|
|||
const AstScope* const m_scopep;
|
||||
const AstSenTree* const m_domainp;
|
||||
|
||||
protected:
|
||||
friend class OrderVisitor;
|
||||
|
||||
public:
|
||||
MTaskMoveVertex(V3Graph* graphp, OrderLogicVertex* logicp, const OrderEitherVertex* varp,
|
||||
const AstScope* scopep, const AstSenTree* domainp)
|
||||
|
|
@ -364,11 +339,13 @@ public:
|
|||
UASSERT(!(logicp && varp), "MTaskMoveVertex: logicp and varp may not both be set!\n");
|
||||
}
|
||||
virtual ~MTaskMoveVertex() override = default;
|
||||
virtual MTaskMoveVertex* clone(V3Graph* graphp) const override {
|
||||
v3fatalSrc("Unsupported");
|
||||
return nullptr;
|
||||
}
|
||||
virtual OrderVEdgeType type() const { return OrderVEdgeType::VERTEX_MOVE; }
|
||||
|
||||
// ACCESSORS
|
||||
OrderLogicVertex* logicp() const { return m_logicp; }
|
||||
const OrderEitherVertex* varp() const { return m_varp; }
|
||||
const AstScope* scopep() const { return m_scopep; }
|
||||
const AstSenTree* domainp() const { return m_domainp; }
|
||||
|
||||
virtual string dotColor() const override {
|
||||
if (logicp()) {
|
||||
return logicp()->dotColor();
|
||||
|
|
@ -389,71 +366,6 @@ public:
|
|||
}
|
||||
return nm;
|
||||
}
|
||||
// ACCESSORS
|
||||
OrderLogicVertex* logicp() const { return m_logicp; }
|
||||
const OrderEitherVertex* varp() const { return m_varp; }
|
||||
const AstScope* scopep() const { return m_scopep; }
|
||||
const AstSenTree* domainp() const { return m_domainp; }
|
||||
};
|
||||
|
||||
//######################################################################
|
||||
// Edge types
|
||||
|
||||
class OrderEdge VL_NOT_FINAL : public V3GraphEdge {
|
||||
protected:
|
||||
OrderEdge(V3Graph* graphp, V3GraphVertex* fromp, V3GraphVertex* top, const OrderEdge& old)
|
||||
: V3GraphEdge{graphp, fromp, top, old} {}
|
||||
|
||||
public:
|
||||
OrderEdge(V3Graph* graphp, V3GraphVertex* fromp, V3GraphVertex* top, int weight,
|
||||
bool cutable = false)
|
||||
: V3GraphEdge{graphp, fromp, top, weight, cutable} {}
|
||||
virtual ~OrderEdge() override = default;
|
||||
virtual OrderVEdgeType type() const { return OrderVEdgeType::EDGE_STD; }
|
||||
virtual OrderEdge* clone(V3Graph* graphp, V3GraphVertex* fromp,
|
||||
V3GraphVertex* top) const override {
|
||||
return new OrderEdge(graphp, fromp, top, *this);
|
||||
}
|
||||
};
|
||||
|
||||
class OrderPostCutEdge final : public OrderEdge {
|
||||
// Edge created from output of post assignment
|
||||
// Breakable if the output var feeds back to input combo logic or another clock pin
|
||||
// in which case we'll need a change detect loop around this var.
|
||||
OrderPostCutEdge(V3Graph* graphp, V3GraphVertex* fromp, V3GraphVertex* top,
|
||||
const OrderPostCutEdge& old)
|
||||
: OrderEdge{graphp, fromp, top, old} {}
|
||||
|
||||
public:
|
||||
OrderPostCutEdge(V3Graph* graphp, V3GraphVertex* fromp, V3GraphVertex* top)
|
||||
: OrderEdge{graphp, fromp, top, WEIGHT_COMBO, CUTABLE} {}
|
||||
virtual OrderVEdgeType type() const override { return OrderVEdgeType::EDGE_POSTCUT; }
|
||||
virtual ~OrderPostCutEdge() override = default;
|
||||
virtual OrderPostCutEdge* clone(V3Graph* graphp, V3GraphVertex* fromp,
|
||||
V3GraphVertex* top) const override {
|
||||
return new OrderPostCutEdge(graphp, fromp, top, *this);
|
||||
}
|
||||
virtual string dotColor() const override { return "PaleGreen"; }
|
||||
};
|
||||
|
||||
class OrderPreCutEdge final : public OrderEdge {
|
||||
// Edge created from var_PREVAR->consuming logic vertex
|
||||
// Always breakable, just results in performance loss
|
||||
// in which case we can't optimize away the pre/post delayed assignments
|
||||
OrderPreCutEdge(V3Graph* graphp, V3GraphVertex* fromp, V3GraphVertex* top,
|
||||
const OrderPreCutEdge& old)
|
||||
: OrderEdge{graphp, fromp, top, old} {}
|
||||
|
||||
public:
|
||||
OrderPreCutEdge(V3Graph* graphp, V3GraphVertex* fromp, V3GraphVertex* top)
|
||||
: OrderEdge{graphp, fromp, top, WEIGHT_PRE, CUTABLE} {}
|
||||
virtual OrderVEdgeType type() const override { return OrderVEdgeType::EDGE_PRECUT; }
|
||||
virtual OrderPreCutEdge* clone(V3Graph* graphp, V3GraphVertex* fromp,
|
||||
V3GraphVertex* top) const override {
|
||||
return new OrderPreCutEdge(graphp, fromp, top, *this);
|
||||
}
|
||||
virtual ~OrderPreCutEdge() override = default;
|
||||
virtual string dotColor() const override { return "khaki"; }
|
||||
};
|
||||
|
||||
#endif // Guard
|
||||
|
|
|
|||
|
|
@ -1951,7 +1951,7 @@ public:
|
|||
const OrderVarStdVertex* const ovvp
|
||||
= dynamic_cast<OrderVarStdVertex*>(edgep->top());
|
||||
if (!ovvp) continue;
|
||||
if (ovvp->varScp()->varp()->isSc()) {
|
||||
if (ovvp->vscp()->varp()->isSc()) {
|
||||
ovvSetSystemC.insert(ovvp);
|
||||
} else {
|
||||
ovvSet.insert(ovvp);
|
||||
|
|
|
|||
|
|
@ -128,7 +128,8 @@ void splitCheck(AstCFunc* ofuncp) {
|
|||
// Unlink all statements, then add item by item to new sub-functions
|
||||
AstBegin* const tempp = new AstBegin{ofuncp->fileline(), "[EditWrapper]",
|
||||
ofuncp->stmtsp()->unlinkFrBackWithNext()};
|
||||
if (ofuncp->finalsp()) tempp->addStmtsp(ofuncp->finalsp()->unlinkFrBackWithNext());
|
||||
// Currently we do not use finalsp in V3Sched, if we do, it needs to be handled here
|
||||
UASSERT_OBJ(!ofuncp->finalsp(), ofuncp, "Should not have any finalps");
|
||||
while (tempp->stmtsp()) {
|
||||
AstNode* const itemp = tempp->stmtsp()->unlinkFrBack();
|
||||
const int stmts = itemp->nodeCount();
|
||||
|
|
|
|||
|
|
@ -69,9 +69,10 @@ public:
|
|||
AstNode* logicp() const { return m_logicp; }
|
||||
AstScope* scopep() const { return m_scopep; }
|
||||
|
||||
// For graph dumping
|
||||
// LCOV_EXCL_START // Debug code
|
||||
string name() const override { return m_logicp->fileline()->ascii(); };
|
||||
string dotShape() const override { return "rectangle"; }
|
||||
// LCOV_EXCL_STOP
|
||||
};
|
||||
|
||||
class VarVertex final : public V3GraphVertex {
|
||||
|
|
@ -84,10 +85,11 @@ public:
|
|||
AstVarScope* vscp() const { return m_vscp; }
|
||||
AstVar* varp() const { return m_vscp->varp(); }
|
||||
|
||||
// For graph dumping
|
||||
// LCOV_EXCL_START // Debug code
|
||||
string name() const override { return m_vscp->name(); }
|
||||
string dotShape() const override { return "ellipse"; }
|
||||
string dotColor() const override { return "blue"; }
|
||||
// LCOV_EXCL_STOP
|
||||
};
|
||||
|
||||
class Graph final : public V3Graph {
|
||||
|
|
@ -97,8 +99,9 @@ class Graph final : public V3Graph {
|
|||
AstNode* const logicp = lvtxp->logicp();
|
||||
std::cerr << logicp->fileline()->warnOther()
|
||||
<< " Example path: " << logicp->typeName() << endl;
|
||||
}
|
||||
if (VarVertex* const vvtxp = dynamic_cast<VarVertex*>(vtxp)) {
|
||||
} else {
|
||||
VarVertex* const vvtxp = dynamic_cast<VarVertex*>(vtxp);
|
||||
UASSERT(vvtxp, "Cannot be anything else");
|
||||
AstVarScope* const vscp = vvtxp->vscp();
|
||||
std::cerr << vscp->fileline()->warnOther()
|
||||
<< " Example path: " << vscp->prettyName() << endl;
|
||||
|
|
@ -369,11 +372,7 @@ LogicByScope fixCuts(AstNetlist* netlistp, const std::vector<VarVertex*>& cutVer
|
|||
for (AstVarScope* const vscp : lvtx2Cuts[lvtxp]) {
|
||||
AstVarRef* const refp = new AstVarRef{flp, vscp, VAccess::READ};
|
||||
AstSenItem* const nextp = new AstSenItem{flp, VEdgeType::ET_HYBRID, refp};
|
||||
if (!senItemsp) {
|
||||
senItemsp = nextp;
|
||||
} else {
|
||||
senItemsp->addNext(nextp);
|
||||
}
|
||||
senItemsp = VN_AS(AstNode::addNext(senItemsp, nextp), SenItem);
|
||||
}
|
||||
AstSenTree* const senTree = new AstSenTree{flp, senItemsp};
|
||||
// Add logic to result with new sensitivity
|
||||
|
|
|
|||
|
|
@ -59,6 +59,8 @@ public:
|
|||
SchedSenVertex(V3Graph* graphp, const AstSenItem* senItemp)
|
||||
: V3GraphVertex{graphp}
|
||||
, m_senItemp{senItemp} {}
|
||||
|
||||
// LCOV_EXCL_START // Debug code
|
||||
string name() const override {
|
||||
std::ostringstream os;
|
||||
V3EmitV::verilogForTree(const_cast<AstSenItem*>(m_senItemp), os);
|
||||
|
|
@ -66,6 +68,7 @@ public:
|
|||
}
|
||||
string dotShape() const override { return "doubleoctagon"; }
|
||||
string dotColor() const override { return "red"; }
|
||||
// LCOV_EXCL_STOP
|
||||
};
|
||||
|
||||
class SchedLogicVertex final : public V3GraphVertex {
|
||||
|
|
@ -83,10 +86,12 @@ public:
|
|||
AstSenTree* senTreep() const { return m_senTreep; }
|
||||
AstNode* logicp() const { return m_logicp; }
|
||||
|
||||
// LCOV_EXCL_START // Debug code
|
||||
string name() const override {
|
||||
return m_logicp->typeName() + ("\n" + m_logicp->fileline()->ascii());
|
||||
};
|
||||
string dotShape() const override { return "rectangle"; }
|
||||
// LCOV_EXCL_STOP
|
||||
};
|
||||
|
||||
class SchedVarVertex final : public V3GraphVertex {
|
||||
|
|
@ -96,6 +101,8 @@ public:
|
|||
SchedVarVertex(V3Graph* graphp, AstVarScope* vscp)
|
||||
: V3GraphVertex{graphp}
|
||||
, m_vscp{vscp} {}
|
||||
|
||||
// LCOV_EXCL_START // Debug code
|
||||
string name() const override { return m_vscp->name(); }
|
||||
string dotShape() const override {
|
||||
return m_vscp->scopep()->isTop() && m_vscp->varp()->isNonOutput() ? "invhouse" : "ellipse";
|
||||
|
|
@ -103,6 +110,7 @@ public:
|
|||
string dotColor() const override {
|
||||
return m_vscp->scopep()->isTop() && m_vscp->varp()->isNonOutput() ? "green" : "black";
|
||||
}
|
||||
// LCOV_EXCL_STOP
|
||||
};
|
||||
|
||||
class SchedGraphBuilder final : public VNVisitor {
|
||||
|
|
@ -229,18 +237,23 @@ class SchedGraphBuilder final : public VNVisitor {
|
|||
virtual void visit(AstAssignPost* nodep) override {}
|
||||
virtual void visit(AstAlwaysPost* nodep) override {}
|
||||
|
||||
// LCOV_EXCL_START
|
||||
// Ignore
|
||||
virtual void visit(AstInitialStatic* nodep) override { // LCOV_EXCL_START
|
||||
virtual void visit(AstInitialStatic* nodep) override {
|
||||
nodep->v3fatalSrc("Should not need ordering");
|
||||
}
|
||||
virtual void visit(AstInitial* nodep) override {
|
||||
virtual void visit(AstInitial* nodep) override { //
|
||||
nodep->v3fatalSrc("Should not need ordering");
|
||||
}
|
||||
virtual void visit(AstFinal* nodep) override {
|
||||
virtual void visit(AstFinal* nodep) override { //
|
||||
nodep->v3fatalSrc("Should not need ordering");
|
||||
} // LCOV_EXCL_STOP
|
||||
}
|
||||
|
||||
virtual void visit(AstNode* nodep) override { iterateChildrenConst(nodep); }
|
||||
// Default - Any other AstActive content not handled above will hit this
|
||||
virtual void visit(AstNode* nodep) override { //
|
||||
nodep->v3fatalSrc("Should behandled above");
|
||||
}
|
||||
// LCOV_EXCL_STOP
|
||||
|
||||
SchedGraphBuilder(const LogicByScope& clockedLogic, const LogicByScope& combinationalLogic,
|
||||
const LogicByScope& hybridLogic) {
|
||||
|
|
|
|||
|
|
@ -70,7 +70,7 @@ public:
|
|||
m_drivingRegions = static_cast<RegionFlags>(m_drivingRegions | regions);
|
||||
}
|
||||
|
||||
// For graph dumping
|
||||
// LCOV_EXCL_START // Debug code
|
||||
string dotColor() const override {
|
||||
switch (static_cast<unsigned>(m_drivingRegions)) {
|
||||
case NONE: return "black";
|
||||
|
|
@ -81,9 +81,10 @@ public:
|
|||
case INPUT | NBA: return "magenta";
|
||||
case ACTIVE | NBA: return "cyan";
|
||||
case INPUT | ACTIVE | NBA: return "gray80"; // don't want white on white background
|
||||
default: v3fatal("There are only 3 region bits"); return ""; // LCOV_EXCL_LINE
|
||||
default: v3fatal("There are only 3 region bits"); return "";
|
||||
}
|
||||
}
|
||||
// LCOV_EXCL_STOP
|
||||
};
|
||||
|
||||
class LogicVertex final : public Vertex {
|
||||
|
|
|
|||
|
|
@ -0,0 +1,21 @@
|
|||
#!/usr/bin/env perl
|
||||
if (!$::Driver) { use FindBin; exec("$FindBin::Bin/bootstrap.pl", @ARGV, $0); die; }
|
||||
# DESCRIPTION: Verilator: Verilog Test driver/expect definition
|
||||
#
|
||||
# Copyright 2003 by Wilson Snyder. This program is free software; you
|
||||
# can redistribute it and/or modify it under the terms of either the GNU
|
||||
# Lesser General Public License Version 3 or the Perl Artistic License
|
||||
# Version 2.0.
|
||||
# SPDX-License-Identifier: LGPL-3.0-only OR Artistic-2.0
|
||||
|
||||
scenarios(vlt_all => 1);
|
||||
|
||||
compile(
|
||||
verilator_flags2 => ["--stats"],
|
||||
);
|
||||
|
||||
# We must not convert these blocks into combinational blocks
|
||||
file_grep($Self->{stats}, qr/Scheduling, size of class: combinational\s+(\d+)/i, 0);
|
||||
|
||||
ok(1);
|
||||
1;
|
||||
|
|
@ -0,0 +1,57 @@
|
|||
// DESCRIPTION: Verilator: Verilog Test module
|
||||
//
|
||||
// This file ONLY is placed under the Creative Commons Public Domain, for
|
||||
// any use, without warranty, 2022 by Geza Lore.
|
||||
// SPDX-License-Identifier: CC0-1.0
|
||||
|
||||
module t (
|
||||
clk,
|
||||
input wire i,
|
||||
output reg o_0,
|
||||
output reg o_1,
|
||||
output reg o_2,
|
||||
output reg o_3,
|
||||
output reg o_4,
|
||||
output reg o_5
|
||||
);
|
||||
|
||||
input clk;
|
||||
|
||||
reg a = 0;
|
||||
reg b = 0;
|
||||
|
||||
event e;
|
||||
|
||||
// We must not convert these blocks into combinational blocks
|
||||
|
||||
always @(i) begin
|
||||
a <= ~a;
|
||||
o_0 = i;
|
||||
end
|
||||
|
||||
always @(i) begin
|
||||
force b = 1;
|
||||
o_1 = i;
|
||||
end
|
||||
|
||||
always @(i) begin
|
||||
release b;
|
||||
o_2 = i;
|
||||
end
|
||||
|
||||
always @(i) begin
|
||||
-> e;
|
||||
o_3 = i;
|
||||
end
|
||||
|
||||
always @(i) begin
|
||||
->> e;
|
||||
o_4 = i;
|
||||
end
|
||||
|
||||
always @(i) begin
|
||||
$display("Hello");
|
||||
o_5 = i;
|
||||
end
|
||||
|
||||
endmodule
|
||||
Loading…
Reference in New Issue