multi-thread delay calc missing lock

Signed-off-by: James Cherry <cherry@parallaxsw.com>
This commit is contained in:
James Cherry 2024-01-31 17:14:07 -07:00
parent 7bed384fce
commit cc9eb1f12a
2 changed files with 90 additions and 62 deletions

View File

@ -59,7 +59,6 @@ GraphDelayCalc::GraphDelayCalc(StaState *sta) :
search_non_latch_pred_(new SearchPredNonLatch2(sta)), search_non_latch_pred_(new SearchPredNonLatch2(sta)),
clk_pred_(new ClkTreeSearchPred(sta)), clk_pred_(new ClkTreeSearchPred(sta)),
iter_(new BfsFwdIterator(BfsIndex::dcalc, search_non_latch_pred_, sta)), iter_(new BfsFwdIterator(BfsIndex::dcalc, search_non_latch_pred_, sta)),
multi_drvr_nets_found_(false),
incremental_delay_tolerance_(0.0) incremental_delay_tolerance_(0.0)
{ {
} }
@ -103,7 +102,6 @@ GraphDelayCalc::clear()
{ {
delaysInvalid(); delaysInvalid();
deleteMultiDrvrNets(); deleteMultiDrvrNets();
multi_drvr_nets_found_ = false;
} }
float float
@ -184,7 +182,7 @@ GraphDelayCalc::deleteVertexBefore(Vertex *vertex)
MultiDrvrNet *multi_drvr = multiDrvrNet(vertex); MultiDrvrNet *multi_drvr = multiDrvrNet(vertex);
if (multi_drvr) { if (multi_drvr) {
// Don't bother incrementally updating MultiDrvrNet. // Don't bother incrementally updating MultiDrvrNet.
for (Vertex *drvr_vertex : *multi_drvr->drvrs()) for (Vertex *drvr_vertex : multi_drvr->drvrs())
multi_drvr_net_map_.erase(drvr_vertex); multi_drvr_net_map_.erase(drvr_vertex);
delete multi_drvr; delete multi_drvr;
} }
@ -477,7 +475,7 @@ GraphDelayCalc::findPortIndex(const LibertyCell *cell,
return index; return index;
index++; index++;
} }
report_->critical(1100, "port not found in cell"); report_->critical(1100, "port not found in cell.");
return 0; return 0;
} }
@ -655,26 +653,50 @@ GraphDelayCalc::findDriverDelays(Vertex *drvr_vertex,
MultiDrvrNet * MultiDrvrNet *
GraphDelayCalc::findMultiDrvrNet(Vertex *drvr_vertex) GraphDelayCalc::findMultiDrvrNet(Vertex *drvr_vertex)
{ {
MultiDrvrNet *multi_drvr = multiDrvrNet(drvr_vertex); // Avoid locking for single driver nets.
if (multi_drvr) if (hasMultiDrvrs(drvr_vertex)) {
UniqueLock lock(multi_drvr_lock_);
MultiDrvrNet *multi_drvr = multiDrvrNet(drvr_vertex);
if (multi_drvr)
return multi_drvr;
multi_drvr = makeMultiDrvrNet(drvr_vertex);
return multi_drvr; return multi_drvr;
else {
const PinSet *drvrs = network_->drivers(drvr_vertex->pin());
if (drvrs && drvrs->size() > 1) {
PinSet drvrs1(network_);
// Filter input ports and non-leaf drivers.
for (const Pin *pin : *drvrs) {
if (isLeafDriver(pin, network_))
drvrs1.insert(pin);
}
MultiDrvrNet *multi_drvr = nullptr;
if (drvrs1.size() > 1)
multi_drvr = makeMultiDrvrNet(drvrs1);
return multi_drvr;
}
else
return nullptr;
} }
return nullptr;
}
bool
GraphDelayCalc::hasMultiDrvrs(Vertex *drvr_vertex)
{
Vertex *load_vertex = firstLoad(drvr_vertex);
if (load_vertex) {
int drvr_count = 0;
VertexInEdgeIterator edge_iter(load_vertex, graph_);
while (edge_iter.hasNext()) {
Edge *edge = edge_iter.next();
if (edge->isWire()) {
Vertex *drvr = edge->from(graph_);
if (isLeafDriver(drvr->pin(), network_))
drvr_count++;
}
if (drvr_count > 1)
return true;
}
return false;
}
return false;
}
Vertex *
GraphDelayCalc::firstLoad(Vertex *drvr_vertex)
{
VertexOutEdgeIterator edge_iter(drvr_vertex, graph_);
while (edge_iter.hasNext()) {
Edge *wire_edge = edge_iter.next();
if (wire_edge->isWire())
return wire_edge->to(graph_);
}
return nullptr;
} }
static bool static bool
@ -693,31 +715,41 @@ GraphDelayCalc::multiDrvrNet(const Vertex *drvr_vertex) const
} }
MultiDrvrNet * MultiDrvrNet *
GraphDelayCalc::makeMultiDrvrNet(PinSet &drvr_pins) GraphDelayCalc::makeMultiDrvrNet(Vertex *drvr_vertex)
{ {
debugPrint(debug_, "delay_calc", 3, "multi-driver net"); Vertex *load_vertex = firstLoad(drvr_vertex);
VertexSet *drvr_vertices = new VertexSet(graph_); if (load_vertex) {
MultiDrvrNet *multi_drvr = new MultiDrvrNet(drvr_vertices); debugPrint(debug_, "delay_calc", 3, "multi-driver net");
Level max_drvr_level = 0; MultiDrvrNet *multi_drvr = new MultiDrvrNet;
Vertex *max_drvr = nullptr; VertexSeq &drvr_vertices = multi_drvr->drvrs();
PinSet::Iterator pin_iter(drvr_pins); Level max_drvr_level = 0;
while (pin_iter.hasNext()) { Vertex *max_drvr = nullptr;
const Pin *pin = pin_iter.next(); VertexInEdgeIterator edge_iter(load_vertex, graph_);
Vertex *drvr_vertex = graph_->pinDrvrVertex(pin); while (edge_iter.hasNext()) {
debugPrint(debug_, "delay_calc", 3, " %s", Edge *edge = edge_iter.next();
network_->pathName(pin)); if (edge->isWire()) {
multi_drvr_net_map_[drvr_vertex] = multi_drvr; Vertex *drvr = edge->from(graph_);
drvr_vertices->insert(drvr_vertex); const Pin *drvr_pin = drvr->pin();
Level drvr_level = drvr_vertex->level(); if (isLeafDriver(drvr_pin, network_)) {
if (max_drvr == nullptr debugPrint(debug_, "delay_calc", 3, " %s",
|| drvr_level > max_drvr_level) { network_->pathName(drvr_pin));
max_drvr = drvr_vertex; multi_drvr_net_map_[drvr] = multi_drvr;
max_drvr_level = drvr_level; drvr_vertices.push_back(drvr);
Level drvr_level = drvr->level();
if (max_drvr == nullptr
|| drvr_level > max_drvr_level) {
max_drvr = drvr;
max_drvr_level = drvr_level;
}
}
}
} }
multi_drvr->setDcalcDrvr(max_drvr);
multi_drvr->findCaps(sdc_);
return multi_drvr;
} }
multi_drvr->setDcalcDrvr(max_drvr); report_->critical(1101, "mult_drvr missing load.");
multi_drvr->findCaps(sdc_); return nullptr;
return multi_drvr;
} }
void void
@ -751,7 +783,7 @@ GraphDelayCalc::findDriverDelays1(Vertex *drvr_vertex,
&& multi_drvr->parallelGates(network_)) { && multi_drvr->parallelGates(network_)) {
// Only init on the trigger driver. // Only init on the trigger driver.
if (drvr_vertex == multi_drvr->dcalcDrvr()) { if (drvr_vertex == multi_drvr->dcalcDrvr()) {
for (auto vertex : *multi_drvr->drvrs()) for (auto vertex : multi_drvr->drvrs())
initWireDelays(vertex); initWireDelays(vertex);
} }
} }
@ -902,7 +934,7 @@ GraphDelayCalc::makeArcDcalcArgs(Vertex *drvr_vertex,
ArcDelayCalc *arc_delay_calc) ArcDelayCalc *arc_delay_calc)
{ {
ArcDcalcArgSeq dcalc_args; ArcDcalcArgSeq dcalc_args;
for (auto drvr_vertex1 : *multi_drvr->drvrs()) { for (auto drvr_vertex1 : multi_drvr->drvrs()) {
Edge *edge1 = nullptr; Edge *edge1 = nullptr;
const TimingArc *arc1 = nullptr; const TimingArc *arc1 = nullptr;
if (drvr_vertex1 == drvr_vertex) { if (drvr_vertex1 == drvr_vertex) {
@ -1526,17 +1558,11 @@ GraphDelayCalc::minPeriod(const Pin *pin,
//////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////
MultiDrvrNet::MultiDrvrNet(VertexSet *drvrs) : MultiDrvrNet::MultiDrvrNet() :
dcalc_drvr_(nullptr), dcalc_drvr_(nullptr)
drvrs_(drvrs)
{ {
} }
MultiDrvrNet::~MultiDrvrNet()
{
delete drvrs_;
}
void void
MultiDrvrNet::netCaps(const RiseFall *drvr_rf, MultiDrvrNet::netCaps(const RiseFall *drvr_rf,
const DcalcAnalysisPt *dcalc_ap, const DcalcAnalysisPt *dcalc_ap,

View File

@ -17,6 +17,7 @@
#pragma once #pragma once
#include <vector> #include <vector>
#include <mutex>
#include "Map.hh" #include "Map.hh"
#include "NetworkClass.hh" #include "NetworkClass.hh"
@ -176,8 +177,11 @@ protected:
const DcalcAnalysisPt *dcalc_ap); const DcalcAnalysisPt *dcalc_ap);
bool findDriverDelays(Vertex *drvr_vertex, bool findDriverDelays(Vertex *drvr_vertex,
ArcDelayCalc *arc_delay_calc); ArcDelayCalc *arc_delay_calc);
MultiDrvrNet *multiDrvrNet(const Vertex *drvr_vertex) const;
MultiDrvrNet *findMultiDrvrNet(Vertex *drvr_pin); MultiDrvrNet *findMultiDrvrNet(Vertex *drvr_pin);
MultiDrvrNet *makeMultiDrvrNet(PinSet &drvr_pins); MultiDrvrNet *makeMultiDrvrNet(Vertex *drvr_vertex);
bool hasMultiDrvrs(Vertex *drvr_vertex);
Vertex *firstLoad(Vertex *drvr_vertex);
bool findDriverDelays1(Vertex *drvr_vertex, bool findDriverDelays1(Vertex *drvr_vertex,
MultiDrvrNet *multi_drvr, MultiDrvrNet *multi_drvr,
ArcDelayCalc *arc_delay_calc); ArcDelayCalc *arc_delay_calc);
@ -238,7 +242,6 @@ protected:
const RiseFall *from_rf, const RiseFall *from_rf,
const DcalcAnalysisPt *dcalc_ap); const DcalcAnalysisPt *dcalc_ap);
bool bidirectDrvrSlewFromLoad(const Vertex *vertex) const; bool bidirectDrvrSlewFromLoad(const Vertex *vertex) const;
MultiDrvrNet *multiDrvrNet(const Vertex *drvr_vertex) const;
void loadCap(const Parasitic *parasitic, void loadCap(const Parasitic *parasitic,
bool has_set_load, bool has_set_load,
// Return values. // Return values.
@ -263,7 +266,7 @@ protected:
SearchPred *clk_pred_; SearchPred *clk_pred_;
BfsFwdIterator *iter_; BfsFwdIterator *iter_;
MultiDrvrNetMap multi_drvr_net_map_; MultiDrvrNetMap multi_drvr_net_map_;
bool multi_drvr_nets_found_; std::mutex multi_drvr_lock_;
// Percentage (0.0:1.0) change in delay that causes downstream // Percentage (0.0:1.0) change in delay that causes downstream
// delays to be recomputed during incremental delay calculation. // delays to be recomputed during incremental delay calculation.
float incremental_delay_tolerance_; float incremental_delay_tolerance_;
@ -288,10 +291,9 @@ public:
class MultiDrvrNet class MultiDrvrNet
{ {
public: public:
MultiDrvrNet(VertexSet *drvrs); MultiDrvrNet();
~MultiDrvrNet(); VertexSeq &drvrs() { return drvrs_; }
const VertexSet *drvrs() const { return drvrs_; } const VertexSeq &drvrs() const { return drvrs_; }
VertexSet *drvrs() { return drvrs_; }
bool parallelGates(const Network *network) const; bool parallelGates(const Network *network) const;
Vertex *dcalcDrvr() const { return dcalc_drvr_; } Vertex *dcalcDrvr() const { return dcalc_drvr_; }
void setDcalcDrvr(Vertex *drvr); void setDcalcDrvr(Vertex *drvr);
@ -307,7 +309,7 @@ public:
private: private:
// Driver that triggers delay calculation for all the drivers on the net. // Driver that triggers delay calculation for all the drivers on the net.
Vertex *dcalc_drvr_; Vertex *dcalc_drvr_;
VertexSet *drvrs_; VertexSeq drvrs_;
// [drvr_rf->index][dcalc_ap->index] // [drvr_rf->index][dcalc_ap->index]
vector<NetCaps> net_caps_; vector<NetCaps> net_caps_;
}; };