V3Order: Minor refactoring for clarity
Refactor ProcessMoveBuildGraph utilizing the fact that OrderGraph is a bipartite graph, also remove unnecessary unordered_map and distribute variable domain map. No functional change.
This commit is contained in:
parent
8de21e9bb7
commit
546aeab9f2
151
src/V3Order.cpp
151
src/V3Order.cpp
|
|
@ -542,10 +542,9 @@ inline std::ostream& operator<<(std::ostream& lhs, const OrderMoveDomScope& rhs)
|
||||||
|
|
||||||
template <class T_MoveVertex>
|
template <class T_MoveVertex>
|
||||||
class ProcessMoveBuildGraph final {
|
class ProcessMoveBuildGraph final {
|
||||||
// ProcessMoveBuildGraph takes as input the fine-grained graph of
|
// ProcessMoveBuildGraph takes as input the fine-grained bipartite OrderGraph of
|
||||||
// OrderLogicVertex, OrderVarVertex, etc; this is 'm_graph' in
|
// OrderLogicVertex and OrderVarVertex vertices. It produces a slightly coarsened graph to
|
||||||
// OrderVisitor. It produces a slightly coarsened graph to drive the
|
// drive the code scheduling.
|
||||||
// code scheduling.
|
|
||||||
//
|
//
|
||||||
// * For the serial code scheduler, the new graph contains
|
// * For the serial code scheduler, the new graph contains
|
||||||
// nodes of type OrderMoveVertex.
|
// nodes of type OrderMoveVertex.
|
||||||
|
|
@ -561,8 +560,7 @@ class ProcessMoveBuildGraph final {
|
||||||
// AstSenTree::user1p() -> AstSenTree: Original AstSenTree for trigger
|
// AstSenTree::user1p() -> AstSenTree: Original AstSenTree for trigger
|
||||||
|
|
||||||
// TYPES
|
// TYPES
|
||||||
using VxDomPair = std::pair<const V3GraphVertex*, const AstSenTree*>;
|
using DomainMap = std::map<const AstSenTree*, T_MoveVertex*>;
|
||||||
using Logic2Move = std::unordered_map<const OrderLogicVertex*, T_MoveVertex*>;
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
class MoveVertexMaker VL_NOT_FINAL {
|
class MoveVertexMaker VL_NOT_FINAL {
|
||||||
|
|
@ -574,31 +572,28 @@ public:
|
||||||
const OrderEitherVertex* varVertexp,
|
const OrderEitherVertex* varVertexp,
|
||||||
const AstSenTree* domainp)
|
const AstSenTree* domainp)
|
||||||
= 0;
|
= 0;
|
||||||
virtual void freeVertexp(T_MoveVertex* freeMep) = 0;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
private:
|
private:
|
||||||
// MEMBERS
|
// MEMBERS
|
||||||
const V3Graph* m_graphp; // Input graph of OrderLogicVertex's etc
|
const OrderGraph* const m_graphp; // Input OrderGraph
|
||||||
|
V3Graph* const m_outGraphp; // Output graph of T_MoveVertex vertices
|
||||||
// Map from Trigger reference AstSenItem to the original AstSenTree
|
// Map from Trigger reference AstSenItem to the original AstSenTree
|
||||||
const std::unordered_map<const AstSenItem*, const AstSenTree*>& m_trigToSen;
|
const std::unordered_map<const AstSenItem*, const AstSenTree*>& m_trigToSen;
|
||||||
V3Graph* m_outGraphp; // Output graph of T_MoveVertex's
|
|
||||||
MoveVertexMaker* const m_vxMakerp; // Factory class for T_MoveVertex's
|
MoveVertexMaker* const m_vxMakerp; // Factory class for T_MoveVertex's
|
||||||
Logic2Move m_logic2move; // Map Logic to Vertex
|
// Storage for domain -> T_MoveVertex, maps held in OrderVarVertex::userp()
|
||||||
// Maps an (original graph vertex, domain) pair to a T_MoveVertex
|
std::deque<DomainMap> m_domainMaps;
|
||||||
// Not std::unordered_map, because std::pair doesn't provide std::hash
|
|
||||||
std::map<VxDomPair, T_MoveVertex*> m_var2move;
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
// CONSTRUCTORS
|
// CONSTRUCTORS
|
||||||
ProcessMoveBuildGraph(
|
ProcessMoveBuildGraph(
|
||||||
const V3Graph* logicGraphp, // Input graph of OrderLogicVertex etc.
|
const OrderGraph* logicGraphp, // Input graph of OrderLogicVertex etc.
|
||||||
const std::unordered_map<const AstSenItem*, const AstSenTree*>& trigToSen,
|
|
||||||
V3Graph* outGraphp, // Output graph of T_MoveVertex's
|
V3Graph* outGraphp, // Output graph of T_MoveVertex's
|
||||||
|
const std::unordered_map<const AstSenItem*, const AstSenTree*>& trigToSen,
|
||||||
MoveVertexMaker* vxMakerp)
|
MoveVertexMaker* vxMakerp)
|
||||||
: m_graphp{logicGraphp}
|
: m_graphp{logicGraphp}
|
||||||
, m_trigToSen{trigToSen}
|
|
||||||
, m_outGraphp{outGraphp}
|
, m_outGraphp{outGraphp}
|
||||||
|
, m_trigToSen{trigToSen}
|
||||||
, m_vxMakerp{vxMakerp} {}
|
, m_vxMakerp{vxMakerp} {}
|
||||||
virtual ~ProcessMoveBuildGraph() = default;
|
virtual ~ProcessMoveBuildGraph() = default;
|
||||||
|
|
||||||
|
|
@ -616,22 +611,20 @@ public:
|
||||||
// already created that pair, in which case, we've already
|
// already created that pair, in which case, we've already
|
||||||
// done the forward search, so stop.
|
// done the forward search, so stop.
|
||||||
|
|
||||||
// For each logic node, make a T_MoveVertex
|
// For each logic vertex, make a T_MoveVertex, for each variable vertex, allocate storage
|
||||||
for (V3GraphVertex* itp = m_graphp->verticesBeginp(); itp; itp = itp->verticesNextp()) {
|
for (V3GraphVertex* itp = m_graphp->verticesBeginp(); itp; itp = itp->verticesNextp()) {
|
||||||
if (OrderLogicVertex* const lvertexp = dynamic_cast<OrderLogicVertex*>(itp)) {
|
if (OrderLogicVertex* const lvtxp = dynamic_cast<OrderLogicVertex*>(itp)) {
|
||||||
T_MoveVertex* const moveVxp
|
lvtxp->userp(m_vxMakerp->makeVertexp(lvtxp, nullptr, lvtxp->domainp()));
|
||||||
= m_vxMakerp->makeVertexp(lvertexp, nullptr, lvertexp->domainp());
|
} else {
|
||||||
if (moveVxp) {
|
// This is an OrderVarVertex
|
||||||
// Cross link so we can find it later
|
m_domainMaps.emplace_back();
|
||||||
m_logic2move[lvertexp] = moveVxp;
|
itp->userp(&m_domainMaps.back());
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Build edges between logic vertices
|
// Build edges between logic vertices
|
||||||
for (V3GraphVertex* itp = m_graphp->verticesBeginp(); itp; itp = itp->verticesNextp()) {
|
for (V3GraphVertex* itp = m_graphp->verticesBeginp(); itp; itp = itp->verticesNextp()) {
|
||||||
if (OrderLogicVertex* const lvertexp = dynamic_cast<OrderLogicVertex*>(itp)) {
|
if (OrderLogicVertex* const lvtxp = dynamic_cast<OrderLogicVertex*>(itp)) {
|
||||||
T_MoveVertex* const moveVxp = m_logic2move[lvertexp];
|
iterateLogicVertex(lvtxp);
|
||||||
if (moveVxp) iterate(moveVxp, lvertexp, lvertexp->domainp());
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -695,61 +688,62 @@ private:
|
||||||
return fromSenItemp->edgeType().exclusiveEdge(toSenItemp->edgeType());
|
return fromSenItemp->edgeType().exclusiveEdge(toSenItemp->edgeType());
|
||||||
}
|
}
|
||||||
|
|
||||||
// Return true if moveVxp has downstream dependencies
|
void iterateLogicVertex(const OrderLogicVertex* lvtxp) {
|
||||||
bool iterate(T_MoveVertex* moveVxp, const V3GraphVertex* origVxp, AstSenTree* domainp) {
|
AstSenTree* const domainp = lvtxp->domainp();
|
||||||
bool madeDeps = false;
|
T_MoveVertex* const lMoveVtxp = static_cast<T_MoveVertex*>(lvtxp->userp());
|
||||||
// Search forward from given original vertex, making new edges from
|
// Search forward from lvtxp, making new edges from lMoveVtxp forward
|
||||||
// moveVxp forward
|
for (V3GraphEdge* edgep = lvtxp->outBeginp(); edgep; edgep = edgep->outNextp()) {
|
||||||
for (V3GraphEdge* edgep = origVxp->outBeginp(); edgep; edgep = edgep->outNextp()) {
|
if (edgep->weight() == 0) continue; // Was cut
|
||||||
if (edgep->weight() == 0) { // Was cut
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
const int weight = edgep->weight();
|
|
||||||
if (const OrderLogicVertex* const toLVertexp
|
|
||||||
= dynamic_cast<const OrderLogicVertex*>(edgep->top())) {
|
|
||||||
|
|
||||||
// Do not construct dependencies across exclusive domains.
|
// OrderGraph is a bipartite graph, so we know it's an OrderVarVertex
|
||||||
if (domainsExclusive(domainp, toLVertexp->domainp())) continue;
|
const OrderVarVertex* const vvtxp = static_cast<const OrderVarVertex*>(edgep->top());
|
||||||
|
|
||||||
// Path from vertexp to a logic vertex; new edge.
|
// Look up T_MoveVertex for this domain on this variable
|
||||||
// Note we use the last edge's weight, not some function of
|
DomainMap& mapp = *static_cast<DomainMap*>(vvtxp->userp());
|
||||||
// multiple edges
|
const auto pair = mapp.emplace(domainp, nullptr);
|
||||||
new V3GraphEdge(m_outGraphp, moveVxp, m_logic2move[toLVertexp], weight);
|
// Reference to the mapped T_MoveVertex
|
||||||
madeDeps = true;
|
T_MoveVertex*& vMoveVtxp = pair.first->second;
|
||||||
} else {
|
|
||||||
// This is an OrderVarVertex.
|
|
||||||
const V3GraphVertex* nonLogicVxp = edgep->top();
|
|
||||||
const VxDomPair key(nonLogicVxp, domainp);
|
|
||||||
if (!m_var2move[key]) {
|
|
||||||
const OrderVarVertex* const eithp
|
|
||||||
= static_cast<const OrderVarVertex*>(nonLogicVxp);
|
|
||||||
T_MoveVertex* const newMoveVxp
|
|
||||||
= m_vxMakerp->makeVertexp(nullptr, eithp, domainp);
|
|
||||||
m_var2move[key] = newMoveVxp;
|
|
||||||
|
|
||||||
// Find downstream logics that depend on (var, domain)
|
// On first encounter, visit downstream logic dependent on this (var, domain)
|
||||||
if (!iterate(newMoveVxp, edgep->top(), domainp)) {
|
if (pair.second) vMoveVtxp = iterateVarVertex(vvtxp, domainp);
|
||||||
// No downstream dependencies, so remove this
|
|
||||||
// intermediate vertex.
|
|
||||||
m_var2move[key] = nullptr;
|
|
||||||
m_vxMakerp->freeVertexp(newMoveVxp);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Create incoming edge, from previous logic that writes
|
// If no downstream dependents from this variable, then there is no need to add this
|
||||||
// this var, to the Vertex representing the (var,domain)
|
// variable as a dependent.
|
||||||
new V3GraphEdge(m_outGraphp, moveVxp, m_var2move[key], weight);
|
if (!vMoveVtxp) continue;
|
||||||
madeDeps = true;
|
|
||||||
}
|
// Add this (variable, domain) as dependent of the logic that writes it.
|
||||||
|
new V3GraphEdge{m_outGraphp, lMoveVtxp, vMoveVtxp, 1};
|
||||||
}
|
}
|
||||||
return madeDeps;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Return the T_MoveVertex for this (var, domain) pair, iff it has downstream dependencies,
|
||||||
|
// otherwise return nullptr.
|
||||||
|
T_MoveVertex* iterateVarVertex(const OrderVarVertex* vvtxp, AstSenTree* domainp) {
|
||||||
|
T_MoveVertex* vMoveVtxp = nullptr;
|
||||||
|
// Search forward from vvtxp, making new edges from vMoveVtxp forward
|
||||||
|
for (V3GraphEdge* edgep = vvtxp->outBeginp(); edgep; edgep = edgep->outNextp()) {
|
||||||
|
if (edgep->weight() == 0) continue; // Was cut
|
||||||
|
|
||||||
|
// OrderGraph is a bipartite graph, so we know it's an OrderLogicVertex
|
||||||
|
const OrderLogicVertex* const lvtxp
|
||||||
|
= static_cast<const OrderLogicVertex*>(edgep->top());
|
||||||
|
|
||||||
|
// Do not construct dependencies across exclusive domains.
|
||||||
|
if (domainsExclusive(domainp, lvtxp->domainp())) continue;
|
||||||
|
|
||||||
|
// there is a path from this vvtx to a logic vertex. Add the new edge.
|
||||||
|
if (!vMoveVtxp) vMoveVtxp = m_vxMakerp->makeVertexp(nullptr, vvtxp, domainp);
|
||||||
|
T_MoveVertex* const lMoveVxp = static_cast<T_MoveVertex*>(lvtxp->userp());
|
||||||
|
new V3GraphEdge{m_outGraphp, vMoveVtxp, lMoveVxp, 1};
|
||||||
|
}
|
||||||
|
return vMoveVtxp;
|
||||||
|
}
|
||||||
|
|
||||||
VL_UNCOPYABLE(ProcessMoveBuildGraph);
|
VL_UNCOPYABLE(ProcessMoveBuildGraph);
|
||||||
};
|
};
|
||||||
|
|
||||||
//######################################################################
|
// ######################################################################
|
||||||
// OrderMoveVertexMaker and related
|
// OrderMoveVertexMaker and related
|
||||||
|
|
||||||
class OrderMoveVertexMaker final : public ProcessMoveBuildGraph<OrderMoveVertex>::MoveVertexMaker {
|
class OrderMoveVertexMaker final : public ProcessMoveBuildGraph<OrderMoveVertex>::MoveVertexMaker {
|
||||||
// MEMBERS
|
// MEMBERS
|
||||||
|
|
@ -770,10 +764,6 @@ public:
|
||||||
resultp->m_pomWaitingE.pushBack(*m_pomWaitingp, resultp);
|
resultp->m_pomWaitingE.pushBack(*m_pomWaitingp, resultp);
|
||||||
return resultp;
|
return resultp;
|
||||||
}
|
}
|
||||||
virtual void freeVertexp(OrderMoveVertex* freeMep) override {
|
|
||||||
freeMep->m_pomWaitingE.unlink(*m_pomWaitingp, freeMep);
|
|
||||||
freeMep->unlinkDelete(m_pomGraphp);
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
VL_UNCOPYABLE(OrderMoveVertexMaker);
|
VL_UNCOPYABLE(OrderMoveVertexMaker);
|
||||||
|
|
@ -791,9 +781,6 @@ public:
|
||||||
const AstSenTree* domainp) override {
|
const AstSenTree* domainp) override {
|
||||||
return new MTaskMoveVertex(m_pomGraphp, lvertexp, varVertexp, domainp);
|
return new MTaskMoveVertex(m_pomGraphp, lvertexp, varVertexp, domainp);
|
||||||
}
|
}
|
||||||
virtual void freeVertexp(MTaskMoveVertex* freeMep) override {
|
|
||||||
freeMep->unlinkDelete(m_pomGraphp);
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
VL_UNCOPYABLE(OrderMTaskMoveVertexMaker);
|
VL_UNCOPYABLE(OrderMTaskMoveVertexMaker);
|
||||||
|
|
@ -1109,7 +1096,7 @@ void OrderProcess::processMoveBuildGraph() {
|
||||||
m_pomGraph.userClearVertices();
|
m_pomGraph.userClearVertices();
|
||||||
|
|
||||||
OrderMoveVertexMaker createOrderMoveVertex(&m_pomGraph, &m_pomWaiting);
|
OrderMoveVertexMaker createOrderMoveVertex(&m_pomGraph, &m_pomWaiting);
|
||||||
ProcessMoveBuildGraph<OrderMoveVertex> serialPMBG(&m_graph, m_trigToSen, &m_pomGraph,
|
ProcessMoveBuildGraph<OrderMoveVertex> serialPMBG(&m_graph, &m_pomGraph, m_trigToSen,
|
||||||
&createOrderMoveVertex);
|
&createOrderMoveVertex);
|
||||||
serialPMBG.build();
|
serialPMBG.build();
|
||||||
}
|
}
|
||||||
|
|
@ -1326,7 +1313,7 @@ void OrderProcess::processMTasks() {
|
||||||
// This is quite similar to the 'm_pomGraph' of the serial code gen:
|
// This is quite similar to the 'm_pomGraph' of the serial code gen:
|
||||||
V3Graph logicGraph;
|
V3Graph logicGraph;
|
||||||
OrderMTaskMoveVertexMaker create_mtask_vertex(&logicGraph);
|
OrderMTaskMoveVertexMaker create_mtask_vertex(&logicGraph);
|
||||||
ProcessMoveBuildGraph<MTaskMoveVertex> mtask_pmbg(&m_graph, m_trigToSen, &logicGraph,
|
ProcessMoveBuildGraph<MTaskMoveVertex> mtask_pmbg(&m_graph, &logicGraph, m_trigToSen,
|
||||||
&create_mtask_vertex);
|
&create_mtask_vertex);
|
||||||
mtask_pmbg.build();
|
mtask_pmbg.build();
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue