mirror of
https://github.com/verilator/verilator.git
synced 2026-10-06 10:03:44 +02:00
Merge branch 'master' into develop-v5
This commit is contained in:
+212
-241
@@ -143,212 +143,6 @@ static void partCheckCachedScoreVsActual(uint32_t cached, uint32_t actual) {
|
||||
#endif
|
||||
}
|
||||
|
||||
//######################################################################
|
||||
// PartPropagateCp
|
||||
|
||||
// Propagate increasing critical path (CP) costs through a graph.
|
||||
//
|
||||
// Usage:
|
||||
// * Client increases the cost and/or CP at a node or small set of nodes
|
||||
// (often a pair in practice, eg. edge contraction.)
|
||||
// * Client instances a PartPropagateCp object
|
||||
// * Client calls PartPropagateCp::cpHasIncreased() one or more times.
|
||||
// Each call indicates that the inclusive CP of some "seed" vertex
|
||||
// has increased to a given value.
|
||||
// * NOTE: PartPropagateCp will neither read nor modify the cost
|
||||
// or CPs at the seed vertices, it only accesses and modifies
|
||||
// vertices wayward from the seeds.
|
||||
// * Client calls PartPropagateCp::go(). Internally, this iteratively
|
||||
// propagates the new CPs wayward through the graph.
|
||||
//
|
||||
template <class T_CostAccessor>
|
||||
class PartPropagateCp final : GraphAlg<> {
|
||||
private:
|
||||
// MEMBERS
|
||||
const GraphWay m_way; // CPs oriented in this direction: either FORWARD
|
||||
// // from graph-start to current node, or REVERSE
|
||||
// // from graph-end to current node.
|
||||
T_CostAccessor* const m_accessp; // Access cost and CPs on V3GraphVertex's.
|
||||
// // confirm we only process each vertex once.
|
||||
const bool m_slowAsserts; // Enable nontrivial asserts
|
||||
SortByValueMap<V3GraphVertex*, uint32_t> m_pending; // Pending rescores
|
||||
|
||||
public:
|
||||
// CONSTRUCTORS
|
||||
PartPropagateCp(V3Graph* graphp, GraphWay way, T_CostAccessor* accessp, bool slowAsserts,
|
||||
V3EdgeFuncP edgeFuncp = &V3GraphEdge::followAlwaysTrue)
|
||||
: GraphAlg<>{graphp, edgeFuncp}
|
||||
, m_way{way}
|
||||
, m_accessp{accessp}
|
||||
, m_slowAsserts{slowAsserts} {}
|
||||
|
||||
// METHODS
|
||||
void cpHasIncreased(V3GraphVertex* vxp, uint32_t newInclusiveCp) {
|
||||
// For *vxp, whose CP-inclusive has just increased to
|
||||
// newInclusiveCp, iterate to all wayward nodes, update the edges
|
||||
// of each, and add each to m_pending if its overall CP has grown.
|
||||
for (V3GraphEdge* edgep = vxp->beginp(m_way); edgep; edgep = edgep->nextp(m_way)) {
|
||||
if (!m_edgeFuncp(edgep)) continue;
|
||||
V3GraphVertex* const relativep = edgep->furtherp(m_way);
|
||||
m_accessp->notifyEdgeCp(relativep, m_way, vxp, newInclusiveCp);
|
||||
|
||||
if (m_accessp->critPathCost(relativep, m_way) < newInclusiveCp) {
|
||||
// relativep's critPathCost() is out of step with its
|
||||
// longest !wayward edge. Schedule that to be resolved.
|
||||
const uint32_t newPendingVal
|
||||
= newInclusiveCp - m_accessp->critPathCost(relativep, m_way);
|
||||
const auto pair = m_pending.emplace(relativep, newPendingVal);
|
||||
if (!pair.second && (newPendingVal > pair.first->second)) {
|
||||
m_pending.update(pair.first, newPendingVal);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void go() {
|
||||
// m_pending maps each pending vertex to the amount that it wayward
|
||||
// CP will grow.
|
||||
//
|
||||
// We can iterate over the pending set in reverse order, always
|
||||
// choosing the nodes with the largest pending CP-growth.
|
||||
//
|
||||
// The intuition is: if the original seed node had its CP grow by
|
||||
// 50, the most any wayward node can possibly grow is also 50. So
|
||||
// for anything pending to grow by 50, we know we can process it
|
||||
// once and we won't have to grow its CP again on the current pass.
|
||||
// After we're done with all the grow-by-50s, nothing else will
|
||||
// grow by 50 again on the current pass, and we can process the
|
||||
// grow-by-49s and we know we'll only have to process each one
|
||||
// once. And so on.
|
||||
//
|
||||
// This generalizes to multiple seed nodes also.
|
||||
while (!m_pending.empty()) {
|
||||
const auto it = m_pending.rbegin();
|
||||
V3GraphVertex* const updateMep = it->first;
|
||||
const uint32_t cpGrowBy = it->second;
|
||||
m_pending.erase(it);
|
||||
|
||||
// For *updateMep, whose critPathCost was out-of-date with respect
|
||||
// to its edges, update the critPathCost.
|
||||
const uint32_t startCp = m_accessp->critPathCost(updateMep, m_way);
|
||||
const uint32_t newCp = startCp + cpGrowBy;
|
||||
if (m_slowAsserts) m_accessp->checkNewCpVersusEdges(updateMep, m_way, newCp);
|
||||
|
||||
m_accessp->setCritPathCost(updateMep, m_way, newCp);
|
||||
cpHasIncreased(updateMep, newCp + m_accessp->cost(updateMep));
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
VL_DEBUG_FUNC;
|
||||
VL_UNCOPYABLE(PartPropagateCp);
|
||||
};
|
||||
|
||||
class PartPropagateCpSelfTest final {
|
||||
private:
|
||||
// MEMBERS
|
||||
V3Graph m_graph; // A graph
|
||||
V3GraphVertex* m_vx[50]; // All vertices within the graph
|
||||
using CpMap = std::unordered_map<V3GraphVertex*, uint32_t>;
|
||||
CpMap m_cp; // Vertex-to-CP map
|
||||
CpMap m_seen; // Set of vertices we've seen
|
||||
|
||||
// CONSTRUCTORS
|
||||
PartPropagateCpSelfTest() = default;
|
||||
~PartPropagateCpSelfTest() = default;
|
||||
|
||||
// METHODS
|
||||
protected:
|
||||
friend class PartPropagateCp<PartPropagateCpSelfTest>;
|
||||
void notifyEdgeCp(V3GraphVertex* /*vxp*/, GraphWay way, V3GraphVertex* throughp,
|
||||
uint32_t cp) const {
|
||||
const uint32_t throughCost = critPathCost(throughp, way);
|
||||
UASSERT_SELFTEST(uint32_t, cp, (1 + throughCost));
|
||||
}
|
||||
|
||||
private:
|
||||
void checkNewCpVersusEdges(V3GraphVertex* vxp, GraphWay way, uint32_t cp) const {
|
||||
// Don't need to check this in the self test; it supports an assert
|
||||
// that runs in production code.
|
||||
}
|
||||
void setCritPathCost(V3GraphVertex* vxp, GraphWay /*way*/, uint32_t cost) {
|
||||
m_cp[vxp] = cost;
|
||||
// Confirm that we only set each node's CP once. That's an
|
||||
// important property of PartPropagateCp which allows it to be far
|
||||
// faster than a recursive algorithm on some graphs.
|
||||
const auto it = m_seen.find(vxp);
|
||||
UASSERT_OBJ(it == m_seen.end(), vxp, "Set CP on node twice");
|
||||
m_seen[vxp] = cost;
|
||||
}
|
||||
uint32_t critPathCost(V3GraphVertex* vxp, GraphWay /*way*/) const {
|
||||
const auto it = m_cp.find(vxp);
|
||||
if (it != m_cp.end()) return it->second;
|
||||
return 0;
|
||||
}
|
||||
static uint32_t cost(const V3GraphVertex*) { return 1; }
|
||||
void partInitCriticalPaths(bool checkOnly) {
|
||||
// Set up the FORWARD cp's only. This test only looks in one
|
||||
// direction, it assumes REVERSE is symmetrical and would be
|
||||
// redundant to test.
|
||||
GraphStreamUnordered order(&m_graph);
|
||||
while (const V3GraphVertex* const cvxp = order.nextp()) {
|
||||
V3GraphVertex* const vxp = const_cast<V3GraphVertex*>(cvxp);
|
||||
uint32_t cpCost = 0;
|
||||
for (V3GraphEdge* edgep = vxp->inBeginp(); edgep; edgep = edgep->inNextp()) {
|
||||
V3GraphVertex* const parentp = edgep->fromp();
|
||||
cpCost = std::max(cpCost, critPathCost(parentp, GraphWay::FORWARD) + 1);
|
||||
}
|
||||
if (checkOnly) {
|
||||
UASSERT_SELFTEST(uint32_t, cpCost, critPathCost(vxp, GraphWay::FORWARD));
|
||||
} else {
|
||||
setCritPathCost(vxp, GraphWay::FORWARD, cpCost);
|
||||
}
|
||||
}
|
||||
}
|
||||
void go() {
|
||||
// Generate a pseudo-random graph
|
||||
std::array<uint64_t, 2> rngState
|
||||
= {{0x12345678ULL, 0x9abcdef0ULL}}; // GCC 3.8.0 wants {{}}
|
||||
// Create 50 vertices
|
||||
for (auto& i : m_vx) i = new V3GraphVertex(&m_graph);
|
||||
// Create 250 edges at random. Edges must go from
|
||||
// lower-to-higher index vertices, so we get a DAG.
|
||||
for (unsigned i = 0; i < 250; ++i) {
|
||||
const unsigned idx1 = V3Os::rand64(rngState) % 50;
|
||||
const unsigned idx2 = V3Os::rand64(rngState) % 50;
|
||||
if (idx1 > idx2) {
|
||||
new V3GraphEdge(&m_graph, m_vx[idx2], m_vx[idx1], 1);
|
||||
} else if (idx2 > idx1) {
|
||||
new V3GraphEdge(&m_graph, m_vx[idx1], m_vx[idx2], 1);
|
||||
}
|
||||
}
|
||||
|
||||
partInitCriticalPaths(false);
|
||||
|
||||
// This SelfTest class is also the T_CostAccessor
|
||||
PartPropagateCp<PartPropagateCpSelfTest> prop(&m_graph, GraphWay::FORWARD, this, true);
|
||||
|
||||
// Seed the propagator with every input node;
|
||||
// This should result in the complete graph getting all CP's assigned.
|
||||
for (const auto& i : m_vx) {
|
||||
if (!i->inBeginp()) prop.cpHasIncreased(i, 1 /* inclusive CP starts at 1 */);
|
||||
}
|
||||
|
||||
// Run the propagator.
|
||||
// * The setCritPathCost() routine checks that each node's CP changes
|
||||
// at most once.
|
||||
// * The notifyEdgeCp routine is also self checking.
|
||||
m_seen.clear();
|
||||
prop.go();
|
||||
|
||||
// Finally, confirm that the entire graph appears to have correct CPs.
|
||||
partInitCriticalPaths(true);
|
||||
}
|
||||
|
||||
public:
|
||||
static void selfTest() { PartPropagateCpSelfTest().go(); }
|
||||
};
|
||||
|
||||
//######################################################################
|
||||
// LogicMTask
|
||||
|
||||
@@ -738,6 +532,7 @@ public:
|
||||
|
||||
bool removedFromSb() const { return (m_id & REMOVED_MASK) != 0; }
|
||||
void removedFromSb(bool /*removed*/) { m_id |= REMOVED_MASK; }
|
||||
void clearRemovedFromSb() { m_id &= ~REMOVED_MASK; }
|
||||
bool operator<(const MergeCandidate& other) const { return m_id < other.m_id; }
|
||||
};
|
||||
|
||||
@@ -852,8 +647,8 @@ bool MergeCandidate::mergeWouldCreateCycle() const {
|
||||
: static_cast<const MTaskEdge*>(this)->mergeWouldCreateCycle();
|
||||
}
|
||||
|
||||
//######################################################################
|
||||
// Vertex utility classes
|
||||
// ######################################################################
|
||||
// Vertex utility classes
|
||||
|
||||
class OrderByPtrId final {
|
||||
PartPtrIdMap m_ids;
|
||||
@@ -1010,12 +805,174 @@ static void partCheckCriticalPaths(V3Graph* mtasksp) {
|
||||
}
|
||||
}
|
||||
|
||||
// Advance to nextp(way) and delete edge
|
||||
static V3GraphEdge* partBlastEdgep(GraphWay way, V3GraphEdge* edgep) {
|
||||
V3GraphEdge* const nextp = edgep->nextp(way);
|
||||
VL_DO_DANGLING(edgep->unlinkDelete(), edgep);
|
||||
return nextp;
|
||||
}
|
||||
// ######################################################################
|
||||
// PartPropagateCp
|
||||
|
||||
// Propagate increasing critical path (CP) costs through a graph.
|
||||
//
|
||||
// Usage:
|
||||
// * Client increases the cost and/or CP at a node or small set of nodes
|
||||
// (often a pair in practice, eg. edge contraction.)
|
||||
// * Client instances a PartPropagateCp object
|
||||
// * Client calls PartPropagateCp::cpHasIncreased() one or more times.
|
||||
// Each call indicates that the inclusive CP of some "seed" vertex
|
||||
// has increased to a given value.
|
||||
// * NOTE: PartPropagateCp will neither read nor modify the cost
|
||||
// or CPs at the seed vertices, it only accesses and modifies
|
||||
// vertices wayward from the seeds.
|
||||
// * Client calls PartPropagateCp::go(). Internally, this iteratively
|
||||
// propagates the new CPs wayward through the graph.
|
||||
//
|
||||
|
||||
class PartPropagateCp final : GraphAlg<> {
|
||||
private:
|
||||
// MEMBERS
|
||||
const GraphWay m_way; // CPs oriented in this direction: either FORWARD
|
||||
// // from graph-start to current node, or REVERSE
|
||||
// // from graph-end to current node.
|
||||
LogicMTask::CpCostAccessor m_access; // Access cost and CPs on V3GraphVertex's.
|
||||
// // confirm we only process each vertex once.
|
||||
const bool m_slowAsserts; // Enable nontrivial asserts
|
||||
// Pending rescores
|
||||
SortByValueMap<LogicMTask*, uint32_t, LogicMTask::CmpLogicMTask> m_pending;
|
||||
|
||||
std::set<LogicMTask*> m_seen; // Used only with slow asserts to check mtasks visited only once
|
||||
|
||||
public:
|
||||
// CONSTRUCTORS
|
||||
PartPropagateCp(V3Graph* graphp, GraphWay way, bool slowAsserts,
|
||||
V3EdgeFuncP edgeFuncp = &V3GraphEdge::followAlwaysTrue)
|
||||
: GraphAlg<>{graphp, edgeFuncp}
|
||||
, m_way{way}
|
||||
, m_slowAsserts{slowAsserts} {}
|
||||
|
||||
// METHODS
|
||||
void cpHasIncreased(V3GraphVertex* vxp, uint32_t newInclusiveCp) {
|
||||
// For *vxp, whose CP-inclusive has just increased to
|
||||
// newInclusiveCp, iterate to all wayward nodes, update the edges
|
||||
// of each, and add each to m_pending if its overall CP has grown.
|
||||
for (V3GraphEdge* edgep = vxp->beginp(m_way); edgep; edgep = edgep->nextp(m_way)) {
|
||||
if (!m_edgeFuncp(edgep)) continue;
|
||||
LogicMTask* const relativep = static_cast<LogicMTask*>(edgep->furtherp(m_way));
|
||||
m_access.notifyEdgeCp(relativep, m_way, vxp, newInclusiveCp);
|
||||
|
||||
if (m_access.critPathCost(relativep, m_way) < newInclusiveCp) {
|
||||
// relativep's critPathCost() is out of step with its
|
||||
// longest !wayward edge. Schedule that to be resolved.
|
||||
const uint32_t newPendingVal
|
||||
= newInclusiveCp - m_access.critPathCost(relativep, m_way);
|
||||
const auto pair = m_pending.emplace(relativep, newPendingVal);
|
||||
if (!pair.second && (newPendingVal > pair.first->second)) {
|
||||
m_pending.update(pair.first, newPendingVal);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void go() {
|
||||
// m_pending maps each pending vertex to the amount that it wayward
|
||||
// CP will grow.
|
||||
//
|
||||
// We can iterate over the pending set in reverse order, always
|
||||
// choosing the nodes with the largest pending CP-growth.
|
||||
//
|
||||
// The intuition is: if the original seed node had its CP grow by
|
||||
// 50, the most any wayward node can possibly grow is also 50. So
|
||||
// for anything pending to grow by 50, we know we can process it
|
||||
// once and we won't have to grow its CP again on the current pass.
|
||||
// After we're done with all the grow-by-50s, nothing else will
|
||||
// grow by 50 again on the current pass, and we can process the
|
||||
// grow-by-49s and we know we'll only have to process each one
|
||||
// once. And so on.
|
||||
//
|
||||
// This generalizes to multiple seed nodes also.
|
||||
while (!m_pending.empty()) {
|
||||
const auto it = m_pending.rbegin();
|
||||
LogicMTask* const updateMep = it->first;
|
||||
const uint32_t cpGrowBy = it->second;
|
||||
m_pending.erase(it);
|
||||
|
||||
// For *updateMep, whose critPathCost was out-of-date with respect
|
||||
// to its edges, update the critPathCost.
|
||||
const uint32_t startCp = m_access.critPathCost(updateMep, m_way);
|
||||
const uint32_t newCp = startCp + cpGrowBy;
|
||||
if (VL_UNLIKELY(m_slowAsserts)) {
|
||||
m_access.checkNewCpVersusEdges(updateMep, m_way, newCp);
|
||||
// Confirm that we only set each node's CP once. That's an
|
||||
// important property of PartPropagateCp which allows it to be far
|
||||
// faster than a recursive algorithm on some graphs.
|
||||
const bool first = m_seen.insert(updateMep).second;
|
||||
UASSERT_OBJ(first, updateMep, "Set CP on node twice");
|
||||
}
|
||||
m_access.setCritPathCost(updateMep, m_way, newCp);
|
||||
cpHasIncreased(updateMep, newCp + m_access.cost(updateMep));
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
VL_DEBUG_FUNC;
|
||||
VL_UNCOPYABLE(PartPropagateCp);
|
||||
};
|
||||
|
||||
class PartPropagateCpSelfTest final {
|
||||
private:
|
||||
// MEMBERS
|
||||
V3Graph m_graph; // A graph
|
||||
LogicMTask* m_vx[50]; // All vertices within the graph
|
||||
|
||||
// CONSTRUCTORS
|
||||
PartPropagateCpSelfTest() = default;
|
||||
~PartPropagateCpSelfTest() = default;
|
||||
|
||||
void go() {
|
||||
// Generate a pseudo-random graph
|
||||
std::array<uint64_t, 2> rngState
|
||||
= {{0x12345678ULL, 0x9abcdef0ULL}}; // GCC 3.8.0 wants {{}}
|
||||
// Create 50 vertices
|
||||
for (auto& i : m_vx) {
|
||||
i = new LogicMTask{&m_graph, nullptr};
|
||||
i->setCost(1);
|
||||
}
|
||||
// Create 250 edges at random. Edges must go from
|
||||
// lower-to-higher index vertices, so we get a DAG.
|
||||
for (unsigned i = 0; i < 250; ++i) {
|
||||
const unsigned idx1 = V3Os::rand64(rngState) % 50;
|
||||
const unsigned idx2 = V3Os::rand64(rngState) % 50;
|
||||
if (idx1 > idx2) {
|
||||
if (!m_vx[idx2]->hasRelative(GraphWay::FORWARD, m_vx[idx1])) {
|
||||
new MTaskEdge{&m_graph, m_vx[idx2], m_vx[idx1], 1};
|
||||
}
|
||||
} else if (idx2 > idx1) {
|
||||
if (!m_vx[idx1]->hasRelative(GraphWay::FORWARD, m_vx[idx2])) {
|
||||
new MTaskEdge{&m_graph, m_vx[idx1], m_vx[idx2], 1};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
partInitCriticalPaths(&m_graph);
|
||||
|
||||
// This SelfTest class is also the T_CostAccessor
|
||||
PartPropagateCp prop(&m_graph, GraphWay::FORWARD, true);
|
||||
|
||||
// Seed the propagator with every input node;
|
||||
// This should result in the complete graph getting all CP's assigned.
|
||||
for (const auto& i : m_vx) {
|
||||
if (!i->inBeginp()) prop.cpHasIncreased(i, 1 /* inclusive CP starts at 1 */);
|
||||
}
|
||||
|
||||
// Run the propagator.
|
||||
// * The setCritPathCost() routine checks that each node's CP changes
|
||||
// at most once.
|
||||
// * The notifyEdgeCp routine is also self checking.
|
||||
prop.go();
|
||||
|
||||
// Finally, confirm that the entire graph appears to have correct CPs.
|
||||
partCheckCriticalPaths(&m_graph);
|
||||
}
|
||||
|
||||
public:
|
||||
static void selfTest() { PartPropagateCpSelfTest().go(); }
|
||||
};
|
||||
|
||||
// Merge edges from a LogicMtask.
|
||||
//
|
||||
@@ -1050,31 +1007,48 @@ static V3GraphEdge* partBlastEdgep(GraphWay way, V3GraphEdge* edgep) {
|
||||
//
|
||||
// Another way of stating this: this code ensures that scores of
|
||||
// non-transitive edges only ever increase.
|
||||
static void partMergeEdgesFrom(V3Graph* mtasksp, LogicMTask* recipientp, LogicMTask* donorp,
|
||||
V3Scoreboard<MergeCandidate, uint32_t>* sbp) {
|
||||
static void partRedirectEdgesFrom(LogicMTask* recipientp, LogicMTask* donorp,
|
||||
V3Scoreboard<MergeCandidate, uint32_t>* sbp) {
|
||||
for (const auto& way : {GraphWay::FORWARD, GraphWay::REVERSE}) {
|
||||
for (V3GraphEdge* edgep = donorp->beginp(way); edgep; edgep = partBlastEdgep(way, edgep)) {
|
||||
const MTaskEdge* const tedgep = MTaskEdge::cast(edgep);
|
||||
if (sbp && !tedgep->removedFromSb()) sbp->removeElem(tedgep);
|
||||
// Existing edge; mark it in need of a rescore
|
||||
if (recipientp->hasRelative(way, tedgep->furtherMTaskp(way))) {
|
||||
for (V3GraphEdge *edgep = donorp->beginp(way), *nextp; edgep; edgep = nextp) {
|
||||
nextp = edgep->nextp(way);
|
||||
MTaskEdge* const tedgep = MTaskEdge::cast(edgep);
|
||||
LogicMTask* const relativep = tedgep->furtherMTaskp(way);
|
||||
if (recipientp->hasRelative(way, relativep)) {
|
||||
// An edge already exists between recipient and relative of donor.
|
||||
// Mark it in need of a rescore
|
||||
if (sbp) {
|
||||
const MTaskEdge* const existMTaskEdgep = MTaskEdge::cast(
|
||||
recipientp->findConnectingEdgep(way, tedgep->furtherMTaskp(way)));
|
||||
if (!tedgep->removedFromSb()) sbp->removeElem(tedgep);
|
||||
const MTaskEdge* const existMTaskEdgep
|
||||
= MTaskEdge::cast(recipientp->findConnectingEdgep(way, relativep));
|
||||
UASSERT(existMTaskEdgep, "findConnectingEdge didn't find edge");
|
||||
if (!existMTaskEdgep->removedFromSb()) {
|
||||
sbp->hintScoreChanged(existMTaskEdgep);
|
||||
}
|
||||
}
|
||||
VL_DO_DANGLING(edgep->unlinkDelete(), edgep);
|
||||
} else {
|
||||
// No existing edge into *this, make one.
|
||||
const MTaskEdge* newEdgep;
|
||||
// No existing edge between recipient and relative of donor.
|
||||
// Redirect the edge from donor<->relative to recipient<->relative.
|
||||
if (way == GraphWay::REVERSE) {
|
||||
newEdgep = new MTaskEdge(mtasksp, tedgep->fromMTaskp(), recipientp, 1);
|
||||
tedgep->relinkTop(recipientp);
|
||||
relativep->removeRelative(GraphWay::FORWARD, donorp);
|
||||
relativep->addRelative(GraphWay::FORWARD, recipientp);
|
||||
recipientp->addRelative(GraphWay::REVERSE, relativep);
|
||||
} else {
|
||||
newEdgep = new MTaskEdge(mtasksp, recipientp, tedgep->toMTaskp(), 1);
|
||||
tedgep->relinkFromp(recipientp);
|
||||
relativep->removeRelative(GraphWay::REVERSE, donorp);
|
||||
relativep->addRelative(GraphWay::REVERSE, recipientp);
|
||||
recipientp->addRelative(GraphWay::FORWARD, relativep);
|
||||
}
|
||||
if (sbp) {
|
||||
if (tedgep->removedFromSb()) {
|
||||
tedgep->clearRemovedFromSb();
|
||||
sbp->addElem(tedgep);
|
||||
} else {
|
||||
sbp->hintScoreChanged(tedgep);
|
||||
}
|
||||
}
|
||||
if (sbp) sbp->addElem(newEdgep);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1330,7 +1304,7 @@ private:
|
||||
}
|
||||
|
||||
// Merge the smaller mtask into the larger mtask. If one of them
|
||||
// is much larger, this will save time in partMergeEdgesFrom().
|
||||
// is much larger, this will save time in partRedirectEdgesFrom().
|
||||
// Assume the more costly mtask has more edges.
|
||||
//
|
||||
// [TODO: now that we have edge maps, we could count the edges
|
||||
@@ -1379,11 +1353,8 @@ private:
|
||||
<< (donorNewCpFwd.propagate ? " true " : " false ")
|
||||
<< donorNewCpFwd.propagateCp << endl);
|
||||
|
||||
LogicMTask::CpCostAccessor cpAccess;
|
||||
PartPropagateCp<LogicMTask::CpCostAccessor> forwardPropagator(m_mtasksp, GraphWay::FORWARD,
|
||||
&cpAccess, m_slowAsserts);
|
||||
PartPropagateCp<LogicMTask::CpCostAccessor> reversePropagator(m_mtasksp, GraphWay::REVERSE,
|
||||
&cpAccess, m_slowAsserts);
|
||||
PartPropagateCp forwardPropagator(m_mtasksp, GraphWay::FORWARD, m_slowAsserts);
|
||||
PartPropagateCp reversePropagator(m_mtasksp, GraphWay::REVERSE, m_slowAsserts);
|
||||
|
||||
recipientp->setCritPathCost(GraphWay::FORWARD, recipientNewCpFwd.cp);
|
||||
if (recipientNewCpFwd.propagate) {
|
||||
@@ -1410,8 +1381,8 @@ private:
|
||||
// to a bounded number.
|
||||
removeSiblingMCsWith(recipientp);
|
||||
|
||||
// Merge all edges
|
||||
partMergeEdgesFrom(m_mtasksp, recipientp, donorp, &m_sb);
|
||||
// Redirect all edges
|
||||
partRedirectEdgesFrom(recipientp, donorp, &m_sb);
|
||||
|
||||
// Delete the donorp mtask from the graph
|
||||
VL_DO_CLEAR(donorp->unlinkDelete(m_mtasksp), donorp = nullptr);
|
||||
@@ -1540,8 +1511,8 @@ private:
|
||||
if (shortestPrereqs.size() <= 1) return;
|
||||
|
||||
const auto cmp = [way](const LogicMTask* ap, const LogicMTask* bp) {
|
||||
const uint32_t aCp = ap->critPathCost(way) + ap->stepCost();
|
||||
const uint32_t bCp = bp->critPathCost(way) + bp->stepCost();
|
||||
const uint32_t aCp = ap->critPathCost(way) + ap->cost();
|
||||
const uint32_t bCp = bp->critPathCost(way) + bp->cost();
|
||||
if (aCp != bCp) return aCp < bCp;
|
||||
return ap->id() < bp->id();
|
||||
};
|
||||
@@ -1849,7 +1820,7 @@ private:
|
||||
++rankIt) {
|
||||
// Find the largest node at this rank, merge into it. (If we
|
||||
// happen to find a huge node, this saves time in
|
||||
// partMergeEdgesFrom() versus merging into an arbitrary node.)
|
||||
// partRedirectEdgesFrom() versus merging into an arbitrary node.)
|
||||
LogicMTask* mergedp = nullptr;
|
||||
for (LogicMTaskSet::iterator it = rankIt->second.begin(); it != rankIt->second.end();
|
||||
++it) {
|
||||
@@ -1877,8 +1848,8 @@ private:
|
||||
}
|
||||
// Move all vertices from donorp to mergedp
|
||||
mergedp->moveAllVerticesFrom(donorp);
|
||||
// Move edges from donorp to recipientp
|
||||
partMergeEdgesFrom(m_mtasksp, mergedp, donorp, nullptr);
|
||||
// Redirect edges from donorp to recipientp
|
||||
partRedirectEdgesFrom(mergedp, donorp, nullptr);
|
||||
// Remove donorp from the graph
|
||||
VL_DO_DANGLING(donorp->unlinkDelete(m_mtasksp), donorp);
|
||||
++m_mergesDone;
|
||||
|
||||
Reference in New Issue
Block a user