Internals: Remove dead NEW_ORDERING code.
This commit is contained in:
parent
ed39c66715
commit
3b43556c41
|
|
@ -326,12 +326,10 @@ private:
|
|||
bool sequent = m_itemSequent;
|
||||
|
||||
if (!combo && !sequent) combo=true; // If no list, Verilog 2000: always @ (*)
|
||||
#ifndef NEW_ORDERING
|
||||
if (combo && sequent) {
|
||||
nodep->v3error("Unsupported: Mixed edge (pos/negedge) and activity (no edge) sensitive activity list");
|
||||
sequent = false;
|
||||
}
|
||||
#endif
|
||||
|
||||
AstActive* wantactivep = NULL;
|
||||
if (combo && !sequent) {
|
||||
|
|
|
|||
|
|
@ -81,9 +81,6 @@ private:
|
|||
}
|
||||
|
||||
void genChangeDet(AstVarScope* vscp) {
|
||||
#ifdef NEW_ORDERING
|
||||
vscp->v3fatalSrc("Not applicable\n");
|
||||
#endif
|
||||
AstVar* varp = vscp->varp();
|
||||
vscp->v3warn(IMPERFECTSCH,"Imperfect scheduling of variable: "<<vscp);
|
||||
AstUnpackArrayDType* arrayp = varp->dtypeSkipRefp()->castUnpackArrayDType();
|
||||
|
|
|
|||
109
src/V3Clock.cpp
109
src/V3Clock.cpp
|
|
@ -406,115 +406,6 @@ private:
|
|||
}
|
||||
}
|
||||
|
||||
#ifdef NEW_ORDERING
|
||||
virtual void visit(AstUntilStable* nodep, AstNUser*) {
|
||||
// Process any sub ACTIVE statements first
|
||||
UINFO(4," UNTILSTABLE "<<nodep<<endl);
|
||||
{
|
||||
// Keep vars if in middle of other stable
|
||||
AstUntilStable* lastUntilp = m_untilp;
|
||||
AstSenTree* lastSenp = m_lastSenp;
|
||||
AstIf* lastIfp = m_lastIfp;
|
||||
m_untilp = nodep;
|
||||
m_lastSenp = NULL;
|
||||
m_lastIfp = NULL;
|
||||
nodep->iterateChildren(*this);
|
||||
m_untilp = lastUntilp;
|
||||
m_lastSenp = lastSenp;
|
||||
m_lastIfp = lastIfp;
|
||||
}
|
||||
// Set "unstable" to 100. (non-stabilization count)
|
||||
// int __VclockLoop = 0
|
||||
// IData __Vchange = 1
|
||||
// while (__Vchange) {
|
||||
// Save old values of each until stable variable
|
||||
// Evaluate the body
|
||||
// __Vchange = {change_detect} contribution
|
||||
// if (++__VclockLoop > 100) converge_error
|
||||
if (debug()>4) nodep->dumpTree(cout, " UntilSt-old: ");
|
||||
FileLine* fl = nodep->fileline();
|
||||
if (nodep->bodysp()) fl = nodep->bodysp()->fileline(); // Point to applicable code...
|
||||
m_stableNum++;
|
||||
AstNode* origBodysp = nodep->bodysp(); if (origBodysp) origBodysp->unlinkFrBackWithNext();
|
||||
AstVarScope* changeVarp = getCreateLocalVar(fl, "__Vchange"+cvtToStr(m_stableNum), NULL, 32);
|
||||
AstVarScope* countVarp = getCreateLocalVar(fl, "__VloopCount"+cvtToStr(m_stableNum), NULL, 32);
|
||||
AstWhile* untilp = new AstWhile(fl, new AstVarRef(fl, changeVarp, false), NULL);
|
||||
AstNode* preUntilp = new AstComment(fl, "Change loop "+cvtToStr(m_stableNum));
|
||||
preUntilp->addNext(new AstAssign(fl, new AstVarRef(fl, changeVarp, true),
|
||||
new AstConst(fl, 1)));
|
||||
preUntilp->addNext(new AstAssign(fl, new AstVarRef(fl, countVarp, true),
|
||||
new AstConst(fl, 0)));
|
||||
|
||||
// Add stable variables & preinits
|
||||
AstNode* setChglastp = NULL;
|
||||
for (AstVarRef* varrefp = nodep->stablesp(); varrefp; varrefp=varrefp->nextp()->castVarRef()) {
|
||||
AstVarScope* cmpvscp = getCreateLocalVar(varrefp->varp()->fileline(),
|
||||
"__Vchglast"+cvtToStr(m_stableNum)+"__"+varrefp->name(),
|
||||
varrefp->varp(), 0);
|
||||
varrefp->varScopep()->user2p(cmpvscp);
|
||||
setChglastp = setChglastp->addNext(
|
||||
new AstAssign(fl, new AstVarRef(fl, cmpvscp, true),
|
||||
new AstVarRef(fl, varrefp->varScopep(), false)));
|
||||
}
|
||||
if (!setChglastp) nodep->v3fatalSrc("UntilStable without any variables");
|
||||
untilp->addBodysp(setChglastp);
|
||||
untilp->addBodysp(new AstComment(fl, "Change Loop body begin"));
|
||||
if (origBodysp) untilp->addBodysp(origBodysp);
|
||||
untilp->addBodysp(new AstComment(fl, "Change Loop body end"));
|
||||
// Add stable checks
|
||||
// The order of the variables doesn't matter, but it's more expensive to test
|
||||
// wide variables, and more so 64 bit wide ones. Someday it might be faster to
|
||||
// set the changed variable in a "distributed" fashion over the code, IE,
|
||||
// logic... logic.... a=....; Changed |= (a ^ old_a); more logic... Changed |=...
|
||||
// But then, one hopes users don't have much unoptimized logic
|
||||
AstNode* changeExprp = NULL;
|
||||
int doublecount = 0;
|
||||
for (int wide=0; wide<3; wide++) { // Adding backwards; wide, quad, then normal
|
||||
for (AstVarRef* varrefp = nodep->stablesp(); varrefp; varrefp=varrefp->nextp()->castVarRef()) {
|
||||
if (wide== ( varrefp->isQuad()?0:(varrefp->isWide() ? 1:2))) {
|
||||
AstVarScope* cmpvscp = (AstVarScope*)(varrefp->varScopep()->user2p());
|
||||
if (!cmpvscp) varrefp->v3fatalSrc("should have created above");
|
||||
AstChangeXor* changep
|
||||
= new AstChangeXor (fl,
|
||||
new AstVarRef(fl, varrefp->varScopep(), false),
|
||||
new AstVarRef(fl, cmpvscp, false));
|
||||
if (!changeExprp) changeExprp = changep;
|
||||
else if (doublecount++ > DOUBLE_OR_RATE) {
|
||||
doublecount = 0;
|
||||
changeExprp = new AstLogOr (fl, changep, changeExprp);
|
||||
} else {
|
||||
changeExprp = new AstOr (fl, changep, changeExprp);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!changeExprp) nodep->v3fatalSrc("UntilStable without any variables");
|
||||
changeExprp = new AstAssign(fl, new AstVarRef(fl, changeVarp, true),
|
||||
changeExprp);
|
||||
untilp->addBodysp(changeExprp);
|
||||
//
|
||||
// Final body
|
||||
AstNode* ifstmtp = new AstAssign(fl, new AstVarRef(fl, countVarp, true),
|
||||
new AstAdd(fl, new AstConst(fl, 1),
|
||||
new AstVarRef(fl, countVarp, false)));
|
||||
ifstmtp->addNext(new AstIf(fl,
|
||||
new AstLt (fl, new AstConst(fl, 100),
|
||||
new AstVarRef(fl, countVarp, false)),
|
||||
(new AstDisplay (fl, AstDisplayType::DT_DISPLAY,
|
||||
"%%Error: Verilated model didn't converge", NULL, NULL))
|
||||
->addNext(new AstStop (fl)),
|
||||
NULL));
|
||||
untilp->addBodysp(new AstIf(fl, new AstNeq(fl, new AstConst(fl, 0),
|
||||
new AstVarRef(fl, changeVarp, false)),
|
||||
ifstmtp, NULL));
|
||||
//
|
||||
// Replace it
|
||||
preUntilp->addNext(untilp);
|
||||
if (debug()>4) preUntilp->dumpTreeAndNext(cout, " UntilSt-new: ");
|
||||
nodep->replaceWith(preUntilp); nodep->deleteTree(); nodep=NULL;
|
||||
}
|
||||
#endif
|
||||
|
||||
//--------------------
|
||||
// Default: Just iterate
|
||||
virtual void visit(AstNode* nodep, AstNUser*) {
|
||||
|
|
|
|||
|
|
@ -786,9 +786,7 @@ class EmitCImp : EmitCStmts {
|
|||
|
||||
if (nodep->stmtsp()) puts("// Body\n");
|
||||
nodep->stmtsp()->iterateAndNext(*this);
|
||||
#ifndef NEW_ORDERING
|
||||
if (!m_blkChangeDetVec.empty()) emitChangeDet();
|
||||
#endif
|
||||
|
||||
if (nodep->finalsp()) puts("// Final\n");
|
||||
nodep->finalsp()->iterateAndNext(*this);
|
||||
|
|
@ -1621,20 +1619,16 @@ void EmitCImp::emitWrapEval(AstNodeModule* modp) {
|
|||
}
|
||||
puts("// Evaluate till stable\n");
|
||||
puts("VL_DEBUG_IF(VL_PRINTF(\"\\n----TOP Evaluate "+modClassName(modp)+"::eval\\n\"); );\n");
|
||||
#ifndef NEW_ORDERING
|
||||
puts("int __VclockLoop = 0;\n");
|
||||
puts("IData __Vchange=1;\n");
|
||||
puts("while (VL_LIKELY(__Vchange)) {\n");
|
||||
puts( "VL_DEBUG_IF(VL_PRINTF(\" Clock loop\\n\"););\n");
|
||||
#endif
|
||||
puts( "vlSymsp->__Vm_activity = true;\n");
|
||||
puts( "_eval(vlSymsp);\n");
|
||||
#ifndef NEW_ORDERING
|
||||
puts( "__Vchange = _change_request(vlSymsp);\n");
|
||||
puts( "if (++__VclockLoop > "+cvtToStr(v3Global.opt.convergeLimit())
|
||||
+") vl_fatal(__FILE__,__LINE__,__FILE__,\"Verilated model didn't converge\");\n");
|
||||
puts("}\n");
|
||||
#endif
|
||||
puts("}\n");
|
||||
splitSizeInc(10);
|
||||
|
||||
|
|
@ -1642,20 +1636,16 @@ void EmitCImp::emitWrapEval(AstNodeModule* modp) {
|
|||
puts("\nvoid "+modClassName(modp)+"::_eval_initial_loop("+EmitCBaseVisitor::symClassVar()+") {\n");
|
||||
puts("vlSymsp->__Vm_didInit = true;\n");
|
||||
puts("_eval_initial(vlSymsp);\n");
|
||||
#ifndef NEW_ORDERING
|
||||
puts( "vlSymsp->__Vm_activity = true;\n");
|
||||
puts( "int __VclockLoop = 0;\n");
|
||||
puts( "IData __Vchange=1;\n");
|
||||
puts( "while (VL_LIKELY(__Vchange)) {\n");
|
||||
#endif
|
||||
puts( "_eval_settle(vlSymsp);\n");
|
||||
puts( "_eval(vlSymsp);\n");
|
||||
#ifndef NEW_ORDERING
|
||||
puts( "__Vchange = _change_request(vlSymsp);\n");
|
||||
puts( "if (++__VclockLoop > "+cvtToStr(v3Global.opt.convergeLimit())
|
||||
+") vl_fatal(__FILE__,__LINE__,__FILE__,\"Verilated model didn't DC converge\");\n");
|
||||
puts( "}\n");
|
||||
#endif
|
||||
puts("}\n");
|
||||
splitSizeInc(10);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -222,7 +222,7 @@ private:
|
|||
// V3Const cleans up any NOTs by flipping the edges for us
|
||||
if (m_buffersOnly
|
||||
&& !(nodep->rhsp()->castVarRef()
|
||||
// Until NEW_ORDERING, avoid making non-clocked logic into clocked,
|
||||
// Avoid making non-clocked logic into clocked,
|
||||
// as it slows down the verilator_sim_benchmark
|
||||
|| (nodep->rhsp()->castNot()
|
||||
&& nodep->rhsp()->castNot()->lhsp()->castVarRef()
|
||||
|
|
|
|||
|
|
@ -591,9 +591,6 @@ string V3Options::getenvVERILATOR_ROOT() {
|
|||
string V3Options::version() {
|
||||
string ver = DTVERSION;
|
||||
ver += " rev "+cvtToStr(DTVERSION_rev);
|
||||
#ifdef NEW_ORDERING
|
||||
ver += " (ord)";
|
||||
#endif
|
||||
return ver;
|
||||
}
|
||||
|
||||
|
|
|
|||
392
src/V3Order.cpp
392
src/V3Order.cpp
|
|
@ -63,16 +63,6 @@
|
|||
// the generated signal to become a primary input again.
|
||||
//
|
||||
//
|
||||
#ifdef NEW_ORDERING
|
||||
// Determine nodes that form loops within combo logic
|
||||
// (Strongly connected ignoring assign post/pre's)
|
||||
// Make a subgraph for each loop of combo logic
|
||||
// Break circular logic in each subgraph
|
||||
//
|
||||
// Determine nodes that form loops within a single eval call
|
||||
// Make a subgraph for each loop of sequential logic
|
||||
// Break circular logic in each subgraph
|
||||
#endif
|
||||
//
|
||||
// Rank the graph starting at INPUTS (see V3Graph)
|
||||
//
|
||||
|
|
@ -366,14 +356,6 @@ private:
|
|||
}
|
||||
|
||||
void process();
|
||||
#ifdef NEW_ORDERING
|
||||
void processLoops(string stepName, V3EdgeFuncP edgeFuncp);
|
||||
void processInsLoop();
|
||||
void processInsLoopEdge(V3GraphEdge* edgep);
|
||||
void processInsLoopNewEdge(V3GraphEdge* oldEdgep, V3GraphVertex* newFromp, V3GraphVertex* newTop);
|
||||
OrderVarVertex* processInsLoopNewVar(OrderVarVertex* oldVertexp, bool& createdr);
|
||||
void processBrokeLoop();
|
||||
#endif
|
||||
void processCircular();
|
||||
typedef deque<OrderEitherVertex*> VertexVec;
|
||||
void processInputs();
|
||||
|
|
@ -573,12 +555,7 @@ private:
|
|||
UINFO(5," DeleteDomain = "<<m_deleteDomainp<<endl);
|
||||
// Base vertices
|
||||
m_activeSenVxp = NULL;
|
||||
#ifdef NEW_ORDERING
|
||||
m_inputsVxp = new OrderInputsVertex(&m_graph, m_comboDomainp);
|
||||
m_settleVxp = new OrderSettleVertex(&m_graph, m_settleDomainp);
|
||||
#else
|
||||
m_inputsVxp = new OrderInputsVertex(&m_graph, NULL);
|
||||
#endif
|
||||
//
|
||||
nodep->iterateChildren(*this);
|
||||
// Done topscope, erase extra user information
|
||||
|
|
@ -666,32 +643,7 @@ private:
|
|||
|| m_inPost
|
||||
) {
|
||||
// Combo logic
|
||||
if (
|
||||
#ifdef NEW_ORDERING
|
||||
m_activep && m_activep->hasSettle()
|
||||
#else
|
||||
0
|
||||
#endif
|
||||
) {
|
||||
// Inside settlement; we use special variable names to prevent
|
||||
// having extra logic to break arcs within
|
||||
#ifdef NEW_ORDERING
|
||||
if (gen) {
|
||||
// Add edge logic_vertex->logic_generated_var
|
||||
bool created = false;
|
||||
OrderVarVertex* varVxp = newVarUserVertex(varscp, WV_SETL, &created);
|
||||
new OrderComboCutEdge(&m_graph, m_logicVxp, varVxp);
|
||||
if (created) new OrderEdge(&m_graph, m_settleVxp, varVxp, WEIGHT_INPUT);
|
||||
}
|
||||
if (con) {
|
||||
// Add edge logic_consumed_var->logic_vertex
|
||||
bool created = false;
|
||||
OrderVarVertex* varVxp = newVarUserVertex(varscp, WV_SETL, &created);
|
||||
new OrderEdge(&m_graph, varVxp, m_logicVxp, WEIGHT_MEDIUM);
|
||||
if (created) new OrderEdge(&m_graph, m_settleVxp, varVxp, WEIGHT_INPUT);
|
||||
}
|
||||
#endif // NEW_ORDERING
|
||||
} else { // not settle and (combo or inPost)
|
||||
{ // not settle and (combo or inPost)
|
||||
if (gen) {
|
||||
// Add edge logic_vertex->logic_generated_var
|
||||
OrderVarVertex* varVxp = newVarUserVertex(varscp, WV_STD);
|
||||
|
|
@ -858,212 +810,6 @@ public:
|
|||
}
|
||||
};
|
||||
|
||||
//######################################################################
|
||||
// Pre-Loop elimination
|
||||
|
||||
#ifdef NEW_ORDERING
|
||||
void OrderVisitor::processInsLoop() {
|
||||
// Input is graph with color() reflecting the sub-graphs we need
|
||||
// to loop remove. Take all the I/O from each subgraph and route
|
||||
// through a new begin/end vertex
|
||||
// Note we DON'T only do certain edges; we want all edges to be preserved,
|
||||
// we'll select which are important later on.
|
||||
|
||||
uint32_t maxcolor = 0;
|
||||
for (V3GraphVertex* vertexp = m_graph.verticesBeginp(); vertexp; vertexp=vertexp->verticesNextp()) {
|
||||
if (maxcolor <= vertexp->color()) maxcolor = vertexp->color() + 1;
|
||||
if (OrderVarVertex* vvertexp = dynamic_cast<OrderVarVertex*>(vertexp)) {
|
||||
vvertexp->pilNewVertexp(NULL); // Clear user-ish information before loop
|
||||
}
|
||||
}
|
||||
|
||||
m_pmlLoopEndps.clear();
|
||||
m_pmlLoopEndps.reserve(maxcolor);
|
||||
m_pmlLoopEndps.assign(maxcolor,NULL);
|
||||
|
||||
m_graph.userClearVertices(); // Vertex::user() // true if added as begin/end
|
||||
for (V3GraphVertex* vertexp = m_graph.verticesBeginp(); vertexp; vertexp=vertexp->verticesNextp()) {
|
||||
if (uint32_t loopColor = vertexp->color()) {
|
||||
OrderEitherVertex* evertexp = dynamic_cast<OrderEitherVertex*>(vertexp);
|
||||
if (!evertexp) v3fatalSrc("Non either vertex found");
|
||||
if (!vertexp->user()) {
|
||||
UINFO(8," pil:nowInLoop lp="<<m_loopIdMax<<" waslp="
|
||||
<<evertexp->inLoop()<<" "<<evertexp<<endl);
|
||||
if (!m_pmlLoopEndps[loopColor]) {
|
||||
AstUntilStable* untilp = new AstUntilStable(m_topScopep->fileline(), NULL, NULL);
|
||||
m_topScopep->addStmtsp(untilp);
|
||||
OrderLoopBeginVertex* beginp
|
||||
= new OrderLoopBeginVertex(&m_graph, m_scopetopp,
|
||||
evertexp->domainp(),
|
||||
untilp,
|
||||
m_loopIdMax, loopColor);
|
||||
m_loopIdMax = (OrderLoopId)(m_loopIdMax+1);
|
||||
UASSERT(LOOPID_MAX>m_loopIdMax, "loopid overflow "<<m_loopIdMax<<" "<<LOOPID_MAX);
|
||||
OrderLoopEndVertex* endp = new OrderLoopEndVertex(&m_graph, beginp);
|
||||
new OrderEdge(&m_graph, beginp, endp, WEIGHT_LOOPBE);
|
||||
m_pmlLoopEndps[loopColor] = endp;
|
||||
// Color edges to belong to subgraph
|
||||
beginp->color(loopColor);
|
||||
endp->color(loopColor);
|
||||
beginp->user(1); // Added; don't iterate on it
|
||||
endp->user(1); // Added; don't iterate on it
|
||||
}
|
||||
if (evertexp->inLoop()) {
|
||||
// Adding node to loop, but already in loop...
|
||||
// Ok if the nodes were a combo loop and now become a sequent loop,
|
||||
// The combo loop will be "under" the sequent loop, so keep the combo #.
|
||||
//UINFO(9, "Adding node to loop, but already in loop: "<<evertexp->name()<<endl);
|
||||
} else {
|
||||
// Make all nodes point from/to the begin/end nodes
|
||||
OrderLoopEndVertex* endp = m_pmlLoopEndps[loopColor];
|
||||
OrderLoopBeginVertex* beginp = endp->beginVertexp();
|
||||
new OrderEdge(&m_graph, beginp, vertexp, WEIGHT_LOOPBE);
|
||||
new OrderEdge(&m_graph, vertexp, endp, WEIGHT_LOOPBE);
|
||||
evertexp->inLoop(beginp->loopId());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
m_graph.userClearEdges(); // Edge::user() // true if we added it
|
||||
for (V3GraphVertex* vertexp = m_graph.verticesBeginp(); vertexp; vertexp=vertexp->verticesNextp()) {
|
||||
if (vertexp->color()) {
|
||||
for (V3GraphEdge* nextp,* edgep = vertexp->outBeginp(); edgep; edgep = nextp) {
|
||||
nextp = edgep->outNextp(); // Func may edit the list
|
||||
if (edgep->weight()) {
|
||||
processInsLoopEdge(edgep);
|
||||
} else { // No purpose to this edge any longer
|
||||
edgep->unlinkDelete(); edgep=NULL; // remove old edge
|
||||
}
|
||||
}
|
||||
for (V3GraphEdge* nextp,* edgep = vertexp->inBeginp(); edgep; edgep = nextp) {
|
||||
nextp = edgep->inNextp(); // Func may edit the list
|
||||
if (edgep->weight()) {
|
||||
processInsLoopEdge(edgep);
|
||||
} else { // No purpose to this edge any longer
|
||||
edgep->unlinkDelete(); edgep=NULL; // remove old edge
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Done with space
|
||||
m_pmlLoopEndps.clear();
|
||||
}
|
||||
|
||||
void OrderVisitor::processInsLoopNewEdge(V3GraphEdge* oldEdgep, V3GraphVertex* newFromp, V3GraphVertex* newTop) {
|
||||
// Create new edge based on the old edge's parameters
|
||||
const OrderEdge* oedgep = dynamic_cast<const OrderEdge*>(oldEdgep);
|
||||
V3GraphEdge* newEdgep = oedgep->clone(&m_graph, newFromp, newTop);
|
||||
newEdgep->user(1); // New edge doesn't need to be changed
|
||||
}
|
||||
|
||||
OrderVarVertex* OrderVisitor::processInsLoopNewVar(OrderVarVertex* oldVertexp, bool& createdr) {
|
||||
// Create new VarVertex from given template
|
||||
if (oldVertexp->pilNewVertexp()) {
|
||||
createdr = false;
|
||||
} else {
|
||||
OrderVarVertex* newVertexp = oldVertexp->clone(&m_graph);
|
||||
oldVertexp->pilNewVertexp(newVertexp);
|
||||
createdr = true;
|
||||
}
|
||||
return oldVertexp->pilNewVertexp();
|
||||
}
|
||||
|
||||
void OrderVisitor::processInsLoopEdge(V3GraphEdge* oldEdgep) {
|
||||
if (!oldEdgep->user()) { // if not processed
|
||||
oldEdgep->user(1); // mark as processed
|
||||
if (oldEdgep->fromp()->color() == oldEdgep->top()->color()) {
|
||||
return; // Doesn't cross subgraphs
|
||||
} else {
|
||||
V3GraphVertex* newFromp = oldEdgep->fromp();
|
||||
V3GraphVertex* newTop = oldEdgep->top();
|
||||
//UINFO(6, " pile: "<<newFromp<<" -> "<<newTop<<endl);
|
||||
if (uint32_t fromId = oldEdgep->fromp()->color()) {
|
||||
// Change to come from end block
|
||||
OrderLoopEndVertex* endp = m_pmlLoopEndps[fromId];
|
||||
newFromp = endp;
|
||||
// If it goes from(to) a cutable VarVertex inside the Begin/End block,
|
||||
// we can't lose the variable, as we might need to cut that variable out
|
||||
// in the next pass of processLoops, and processBrokeLoops needs the var pointer.
|
||||
// We'll make another VarVertex (dup of the one "inside" the loop)
|
||||
// and point to it.
|
||||
if (oldEdgep->cutable()) {
|
||||
if (OrderVarVertex* vvFromp = dynamic_cast<OrderVarVertex*>(oldEdgep->fromp())) {
|
||||
// end => newvarvtx -> {whatever}
|
||||
bool created;
|
||||
newFromp = processInsLoopNewVar(vvFromp, created/*ref*/);
|
||||
if (created) processInsLoopNewEdge(oldEdgep, endp, newFromp);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (uint32_t toId = oldEdgep->top()->color()) {
|
||||
// Change to go to begin block
|
||||
OrderLoopEndVertex* endp = m_pmlLoopEndps[toId];
|
||||
OrderLoopBeginVertex* beginp = endp->beginVertexp();
|
||||
newTop = beginp;
|
||||
// Ditto above
|
||||
if (oldEdgep->cutable()) {
|
||||
if (OrderVarVertex* vvTop = dynamic_cast<OrderVarVertex*>(oldEdgep->top())) {
|
||||
// oldfrom -> newvarvtx => begin
|
||||
bool created;
|
||||
newTop = processInsLoopNewVar(vvTop, created/*ref*/);
|
||||
if (created) processInsLoopNewEdge(oldEdgep, newTop, beginp);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// New edge with appropriate to/from
|
||||
processInsLoopNewEdge(oldEdgep, newFromp, newTop);
|
||||
oldEdgep->unlinkDelete(); oldEdgep=NULL; // remove old edge
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif // NEW_ORDERING
|
||||
|
||||
//######################################################################
|
||||
// Pre-Loop elimination
|
||||
|
||||
#ifdef NEW_ORDERING
|
||||
void OrderVisitor::processBrokeLoop() {
|
||||
// Find those loops that were broken
|
||||
for (V3GraphVertex* vertexp = m_graph.verticesBeginp(); vertexp; vertexp=vertexp->verticesNextp()) {
|
||||
// Above processInsLoopEdge makes sure there's always a OrderVarVertex on
|
||||
// boundaries to/from LoopBegin/EndVertex'es
|
||||
if (OrderVarVertex* vvertexp = dynamic_cast<OrderVarVertex*>(vertexp)) {
|
||||
// Any cut edges?
|
||||
bool anyCut = false;
|
||||
for (V3GraphEdge* nextp,* edgep = vertexp->inBeginp(); edgep; edgep = nextp) {
|
||||
nextp = edgep->inNextp(); // We may edit the list
|
||||
if (edgep->weight()==0) { // was cut
|
||||
anyCut = true;
|
||||
edgep->unlinkDelete(); edgep=NULL; // remove old edge
|
||||
}
|
||||
}
|
||||
for (V3GraphEdge* nextp,* edgep = vertexp->outBeginp(); edgep; edgep = nextp) {
|
||||
nextp = edgep->outNextp(); // We may edit the list
|
||||
if (edgep->weight()==0) { // was cut
|
||||
anyCut = true;
|
||||
edgep->unlinkDelete(); edgep=NULL; // remove old edge
|
||||
}
|
||||
}
|
||||
if (anyCut) {
|
||||
UINFO(6," pbl: Cut "<<vertexp->name()<<endl);
|
||||
nodeMarkCircular(vvertexp, NULL);
|
||||
OrderLoopEndVertex* endp = NULL; // Set below in findEndEdge
|
||||
V3GraphEdge* endedgep = findEndEdge(vertexp, vvertexp->varScp(), endp/*ref*/);
|
||||
// Add edge to graphically indicate change detect required
|
||||
endedgep->unlinkDelete(); endedgep=NULL; // remove old edge
|
||||
new OrderChangeDetEdge(&m_graph, vvertexp, endp);
|
||||
// Add variable dependency to until loop
|
||||
AstUntilStable* untilp = endp->beginVertexp()->untilp();
|
||||
untilp->addStablesp(new AstVarRef(vvertexp->varScp()->fileline(), vvertexp->varScp(), false));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif // NEW_ORDERING
|
||||
|
||||
//######################################################################
|
||||
// Clock propagation
|
||||
|
||||
|
|
@ -1146,7 +892,6 @@ void OrderVisitor::processInputsOutIterate(OrderEitherVertex* vertexp, VertexVec
|
|||
//######################################################################
|
||||
// Circular detection
|
||||
|
||||
#ifndef NEW_ORDERING // *NOT* new ordering
|
||||
void OrderVisitor::processCircular() {
|
||||
// Take broken edges and add circular flags
|
||||
// The change detect code will use this to force changedets
|
||||
|
|
@ -1193,7 +938,6 @@ void OrderVisitor::processCircular() {
|
|||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
void OrderVisitor::processSensitive() {
|
||||
// Sc sensitives are required on all inputs that go to a combo
|
||||
|
|
@ -1238,11 +982,9 @@ void OrderVisitor::processDomainsIterate(OrderEitherVertex* vertexp) {
|
|||
OrderVarVertex* vvertexp = dynamic_cast<OrderVarVertex*>(vertexp);
|
||||
AstSenTree* domainp = NULL;
|
||||
UASSERT(m_comboDomainp, "not preset");
|
||||
#ifndef NEW_ORDERING // New ordering set the input node as combo, so this happens automatically
|
||||
if (vvertexp && vvertexp->varScp()->varp()->isInput()) {
|
||||
domainp = m_comboDomainp;
|
||||
}
|
||||
#endif
|
||||
if (vvertexp && vvertexp->varScp()->isCircular()) {
|
||||
domainp = m_comboDomainp;
|
||||
}
|
||||
|
|
@ -1250,9 +992,7 @@ void OrderVisitor::processDomainsIterate(OrderEitherVertex* vertexp) {
|
|||
for (V3GraphEdge* edgep = vertexp->inBeginp(); edgep; edgep = edgep->inNextp()) {
|
||||
OrderEitherVertex* fromVertexp = (OrderEitherVertex*)edgep->fromp();
|
||||
if (edgep->weight()
|
||||
#ifndef NEW_ORDERING
|
||||
&& fromVertexp->domainMatters()
|
||||
#endif
|
||||
) {
|
||||
UINFO(9," from d="<<(void*)fromVertexp->domainp()<<" "<<fromVertexp<<endl);
|
||||
if (!domainp // First input to this vertex
|
||||
|
|
@ -1426,58 +1166,6 @@ void OrderVisitor::processMove() {
|
|||
|
||||
// New domain... another loop
|
||||
UINFO(5," MoveIterate\n");
|
||||
#ifdef NEW_ORDERING
|
||||
OrderMoveDomScope* domScopep = NULL; // Currently active domain/scope
|
||||
while (!m_pomReadyDomScope.empty()) {
|
||||
// Always need to reamin in same loop construct
|
||||
OrderLoopId curLoop = processMoveLoopCurrent();
|
||||
// Scan list to find search candidates
|
||||
OrderMoveDomScope* loopHuntp = NULL; // Found domscope under same loop
|
||||
OrderMoveDomScope* domHuntp = NULL; // Found domscope under same domain
|
||||
OrderMoveDomScope* scopeHuntp = NULL; // Found domscope under same scope
|
||||
if (domScopep) { UINFO(6," MoveSearch: loop="<<curLoop<<" "<<*domScopep<<endl); }
|
||||
else { UINFO(6," MoveSearch: loop="<<curLoop<<" NULL"<<endl); }
|
||||
for (OrderMoveDomScope* huntp = m_pomReadyDomScope.begin(); huntp; huntp = huntp->readyDomScopeNextp()) {
|
||||
if (huntp->inLoop() == curLoop) {
|
||||
if (!loopHuntp) loopHuntp = huntp;
|
||||
if (domScopep && huntp->domainp() == domScopep->domainp()) {
|
||||
if (!domHuntp) domHuntp = huntp;
|
||||
if (domScopep && huntp->scopep() == domScopep->scopep()) {
|
||||
if (!scopeHuntp) scopeHuntp = huntp;
|
||||
break; // Exact match; all we can hope for
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// Recompute the next domScopep to process
|
||||
if (scopeHuntp) {
|
||||
domScopep = scopeHuntp;
|
||||
UINFO(6," MoveIt: SameScope "<<*domScopep<<endl);
|
||||
} else if (domHuntp) { // No exact scope matches, try only matching the domain
|
||||
domScopep = domHuntp;
|
||||
UINFO(6," MoveIt: SameDomain "<<*domScopep<<endl);
|
||||
} else if (loopHuntp) { // No exact scope or domain matches, only match the loop
|
||||
domScopep = loopHuntp;
|
||||
UINFO(6," MoveIt: SameLoop "<<*domScopep<<endl);
|
||||
} else { // else we're hopefully all done
|
||||
if (curLoop != LOOPID_NOTLOOPED)
|
||||
domScopep->domainp()->v3fatalSrc("Can't find more nodes like "<<*domScopep); // Should be at least a "end loop"
|
||||
break;
|
||||
}
|
||||
// Work on all vertices in this loop/domain/scope
|
||||
OrderMoveVertex* topVertexp = domScopep->readyVertices().begin();
|
||||
UASSERT(topVertexp, "domScope on ready list without any nodes ready under it");
|
||||
m_pomNewFuncp = NULL;
|
||||
while (OrderMoveVertex* vertexp = domScopep->readyVertices().begin()) {
|
||||
processMoveOne(vertexp, domScopep, 1);
|
||||
if (curLoop != processMoveLoopCurrent()) break; // Hit a LoopBegin/end, change loop
|
||||
}
|
||||
}
|
||||
if (!m_pomWaiting.empty()) {
|
||||
OrderMoveVertex* vertexp = m_pomWaiting.begin();
|
||||
vertexp->logicp()->nodep()->v3fatalSrc("Didn't converge; nodes waiting, none ready, perhaps some input activations lost: "<<vertexp<<endl);
|
||||
}
|
||||
#else
|
||||
while (!m_pomReadyDomScope.empty()) {
|
||||
// Start with top node on ready list's domain & scope
|
||||
OrderMoveDomScope* domScopep = m_pomReadyDomScope.begin();
|
||||
|
|
@ -1504,7 +1192,6 @@ void OrderVisitor::processMove() {
|
|||
}
|
||||
}
|
||||
UASSERT (m_pomWaiting.empty(), "Didn't converge; nodes waiting, none ready, perhaps some input activations lost.");
|
||||
#endif
|
||||
// Cleanup memory
|
||||
processMoveClear();
|
||||
}
|
||||
|
|
@ -1578,36 +1265,7 @@ void OrderVisitor::processMoveOne(OrderMoveVertex* vertexp, OrderMoveDomScope* d
|
|||
AstNode* nodep = lvertexp->nodep();
|
||||
AstNodeModule* modp = scopep->user1p()->castNode()->castNodeModule(); UASSERT(modp,"NULL"); // Stashed by visitor func
|
||||
if (nodep->castUntilStable()) {
|
||||
#ifdef NEW_ORDERING
|
||||
// Beginning of loop.
|
||||
if (OrderLoopBeginVertex* beginp = dynamic_cast<OrderLoopBeginVertex*>(lvertexp)) {
|
||||
m_pomNewFuncp = NULL; // Close out any old function
|
||||
// Create new active record
|
||||
string name = cfuncName(modp, domainp, scopep, nodep);
|
||||
AstActive* callunderp = new AstActive(nodep->fileline(), name, domainp);
|
||||
if (domainp == m_deleteDomainp) {
|
||||
UINFO(6," Delete loop "<<beginp<<endl);
|
||||
pushDeletep(callunderp);
|
||||
} else {
|
||||
processMoveLoopStmt(callunderp);
|
||||
}
|
||||
// Put loop under the activate
|
||||
nodep->unlinkFrBack();
|
||||
callunderp->addStmtsp(nodep);
|
||||
// Remember we're in a loop
|
||||
processMoveLoopPush(beginp);
|
||||
}
|
||||
else if (OrderLoopEndVertex* endp = dynamic_cast<OrderLoopEndVertex*>(lvertexp)) {
|
||||
// Nodep is identical to OrderLoopBeginVertex's, so we don't move it
|
||||
m_pomNewFuncp = NULL; // Close out any old function
|
||||
processMoveLoopPop(endp->beginVertexp());
|
||||
}
|
||||
else {
|
||||
nodep->v3fatalSrc("AstUntilStable node isn't under an OrderLoop{End}Vertex.\n");
|
||||
}
|
||||
#else
|
||||
nodep->v3fatalSrc("Not implemented");
|
||||
#endif
|
||||
}
|
||||
else if (nodep->castSenTree()) {
|
||||
// Just ignore sensitivities, we'll deal with them when we move statements that need them
|
||||
|
|
@ -1708,55 +1366,10 @@ inline void OrderMoveDomScope::movedVertex(OrderVisitor* ovp, OrderMoveVertex* v
|
|||
//######################################################################
|
||||
// Top processing
|
||||
|
||||
#ifdef NEW_ORDERING
|
||||
void OrderVisitor::processLoops(string stepName, V3EdgeFuncP edgeFuncp) {
|
||||
UINFO(2," "<<stepName<<" Loop Detect...\n");
|
||||
m_graph.stronglyConnected(edgeFuncp);
|
||||
m_graph.dumpDotFilePrefixed((string)"orderg_"+stepName+"_strong", true);
|
||||
|
||||
UINFO(2," "<<stepName<<" Insert Loop Begin/Ends...\n");
|
||||
processInsLoop();
|
||||
if (debug()>=4) m_graph.dumpDotFilePrefixed((string)"orderg_"+stepName+"_loops", true);
|
||||
|
||||
// Remove loops from the graph
|
||||
UINFO(2," "<<stepName<<" Acyclic...\n");
|
||||
m_graph.acyclic(edgeFuncp);
|
||||
if (debug()) m_graph.dumpDotFilePrefixed((string)"orderg_"+stepName+"_acyc", true);
|
||||
|
||||
// For any broken edges, add to change detect and remove edge
|
||||
UINFO(2," "<<stepName<<" ProcessBrokeLoop...\n");
|
||||
processBrokeLoop();
|
||||
if (debug()>=4) m_graph.dumpDotFilePrefixed((string)"orderg_"+stepName+"_broke", true);
|
||||
|
||||
m_graph.makeEdgesNonCutable(edgeFuncp);
|
||||
m_graph.dumpDotFilePrefixed((string)"orderg_"+stepName+"_done", true);
|
||||
}
|
||||
#endif
|
||||
|
||||
void OrderVisitor::process() {
|
||||
// Dump data
|
||||
m_graph.dumpDotFilePrefixed("orderg_pre");
|
||||
|
||||
#ifdef NEW_ORDERING
|
||||
// Ignoring POST assignments and clocked statements, detect strongly connected components
|
||||
// Split components into subgraphs
|
||||
|
||||
// Detect, loop begin/end, and acyc combo loops
|
||||
UINFO(2," Combo loop elimination...\n");
|
||||
processLoops("combo", &OrderEdge::followComboConnected);
|
||||
|
||||
// Detect, loop begin/end, and acyc post assigns
|
||||
UINFO(2," Sequential loop elimination...\n");
|
||||
processLoops("sequent", &OrderEdge::followSequentConnected);
|
||||
|
||||
// Detect and acyc any PRE assigns
|
||||
// As breaking these does not cause any problems, we don't need to loop begin/end, etc.
|
||||
UINFO(2," Pre Loop Detect & Acyc...\n");
|
||||
m_graph.stronglyConnected(&V3GraphEdge::followAlwaysTrue);
|
||||
if (debug()>=4) m_graph.dumpDotFilePrefixed("orderg_preasn_strong", true);
|
||||
m_graph.acyclic(&V3GraphEdge::followAlwaysTrue);
|
||||
m_graph.dumpDotFilePrefixed("orderg_preasn_done", true);
|
||||
#else
|
||||
// Break cycles. Each strongly connected subgraph (including cutable
|
||||
// edges) will have its own color, and corresponds to a loop in the
|
||||
// original graph. However the new graph will be acyclic (the removed
|
||||
|
|
@ -1764,7 +1377,6 @@ void OrderVisitor::process() {
|
|||
UINFO(2," Acyclic & Order...\n");
|
||||
m_graph.acyclic(&V3GraphEdge::followAlwaysTrue);
|
||||
m_graph.dumpDotFilePrefixed("orderg_acyc");
|
||||
#endif
|
||||
|
||||
// Assign ranks so we know what to follow
|
||||
// Then, sort vertices and edges by that ordering
|
||||
|
|
@ -1777,10 +1389,8 @@ void OrderVisitor::process() {
|
|||
UINFO(2," Process Clocks...\n");
|
||||
processInputs(); // must be before processCircular
|
||||
|
||||
#ifndef NEW_ORDERING
|
||||
UINFO(2," Process Circulars...\n");
|
||||
processCircular(); // must be before processDomains
|
||||
#endif
|
||||
|
||||
// Assign logic verticesto new domains
|
||||
UINFO(2," Domains...\n");
|
||||
|
|
|
|||
|
|
@ -435,11 +435,9 @@ void process () {
|
|||
V3Order::orderAll(v3Global.rootp());
|
||||
V3Global::dumpCheckGlobalTree("order.tree");
|
||||
|
||||
#ifndef NEW_ORDERING
|
||||
// Change generated clocks to look at delayed signals
|
||||
V3GenClk::genClkAll(v3Global.rootp());
|
||||
V3Global::dumpCheckGlobalTree("genclk.tree");
|
||||
#endif
|
||||
|
||||
// Convert sense lists into IF statements.
|
||||
V3Clock::clockAll(v3Global.rootp());
|
||||
|
|
@ -464,11 +462,9 @@ void process () {
|
|||
V3Dead::deadifyAll(v3Global.rootp());
|
||||
V3Global::dumpCheckGlobalTree("const.tree");
|
||||
|
||||
#ifndef NEW_ORDERING
|
||||
// Detect change loop
|
||||
V3Changed::changedAll(v3Global.rootp());
|
||||
V3Global::dumpCheckGlobalTree("changed.tree");
|
||||
#endif
|
||||
|
||||
// Create tracing logic, since we ripped out some signals the user might want to trace
|
||||
// Note past this point, we presume traced variables won't move between CFuncs
|
||||
|
|
|
|||
Loading…
Reference in New Issue