Skip to content

Commit

Permalink
thread speed
Browse files Browse the repository at this point in the history
  • Loading branch information
jjcherry56 committed Sep 7, 2019
1 parent f9bc74e commit 2bf8b78
Show file tree
Hide file tree
Showing 7 changed files with 60 additions and 40 deletions.
42 changes: 29 additions & 13 deletions dcalc/GraphDelayCalc1.cc
Expand Up @@ -359,6 +359,7 @@ class FindVertexDelays : public VertexVisitor
virtual ~FindVertexDelays();
virtual void visit(Vertex *vertex);
virtual VertexVisitor *copy();
virtual void levelFinished();

protected:
GraphDelayCalc1 *graph_delay_calc1_;
Expand Down Expand Up @@ -396,6 +397,24 @@ FindVertexDelays::visit(Vertex *vertex)
graph_delay_calc1_->findVertexDelay(vertex, arc_delay_calc_, true);
}

void
FindVertexDelays::levelFinished()
{
graph_delay_calc1_->mergeIdealClks();
}

void
GraphDelayCalc1::mergeIdealClks()
{
for (auto vertex_clks : ideal_clks_map_next_) {
const Vertex *vertex = vertex_clks.first;
ClockSet *prev_clks = ideal_clks_map_.findKey(vertex);
delete prev_clks;
ideal_clks_map_[vertex] = vertex_clks.second;
}
ideal_clks_map_next_.clear();
}

// The logical structure of incremental delay calculation closely
// resembles the incremental search arrival time algorithm
// (Search::findArrivals).
Expand All @@ -417,16 +436,14 @@ GraphDelayCalc1::findDelays(Level level)
if (incremental_)
seedInvalidDelays();

mergeIdealClks();
FindVertexDelays visitor(this, arc_delay_calc_, false);
dcalc_count += iter_->visitParallel(level, &visitor);

// Timing checks require slews at both ends of the arc,
// so find their delays after all slews are known.
VertexSet::Iterator check_iter(invalid_checks_);
while (check_iter.hasNext()) {
Vertex *check_vertex = check_iter.next();
for (Vertex *check_vertex : invalid_checks_)
findCheckDelays(check_vertex, arc_delay_calc_);
}
invalid_checks_.clear();

delays_exist_ = true;
Expand Down Expand Up @@ -1628,20 +1645,21 @@ void
GraphDelayCalc1::clearIdealClkMap()
{
ideal_clks_map_.deleteContentsClear();
ideal_clks_map_next_.deleteContentsClear();
}

bool
GraphDelayCalc1::setIdealClks(const Vertex *vertex,
ClockSet *clks)
{
bool changed = false;
UniqueLock lock(ideal_clks_map_lock_);
ClockSet *clks1 = ideal_clks_map_.findKey(vertex);
if (ClockSet::equal(clks, clks1))
delete clks;
else {
delete clks1;
ideal_clks_map_[vertex] = clks;
if (!ClockSet::equal(clks, clks1)) {
// Only lock for updates to vertex ideal clks.
// Finding ideal clks by level means only changes at the current
// delay calc level are changed.
UniqueLock lock(ideal_clks_map_next_lock_);
ideal_clks_map_next_[vertex] = clks;
changed = true;
}
return changed;
Expand All @@ -1650,9 +1668,7 @@ GraphDelayCalc1::setIdealClks(const Vertex *vertex,
ClockSet *
GraphDelayCalc1::idealClks(const Vertex *vertex)
{
UniqueLock lock(ideal_clks_map_lock_);
ClockSet *clks = ideal_clks_map_.findKey(vertex);
return clks;
return ideal_clks_map_.findKey(vertex);
}

bool
Expand Down
4 changes: 3 additions & 1 deletion dcalc/GraphDelayCalc1.hh
Expand Up @@ -213,6 +213,7 @@ protected:
Parasitic *drvr_parasitic,
const TransRiseFall *tr,
const DcalcAnalysisPt *dcalc_ap) const;
void mergeIdealClks();

// Observer for edge delay changes.
DelayCalcObserver *observer_;
Expand All @@ -234,7 +235,8 @@ protected:
// delays to be recomputed during incremental delay calculation.
float incremental_delay_tolerance_;
VertexIdealClksMap ideal_clks_map_;
std::mutex ideal_clks_map_lock_;
VertexIdealClksMap ideal_clks_map_next_;
std::mutex ideal_clks_map_next_lock_;

friend class FindVertexDelays;
friend class MultiDrvrNet;
Expand Down
35 changes: 18 additions & 17 deletions sdc/Sdc.cc
Expand Up @@ -2502,13 +2502,17 @@ Sdc::cycleAccting(const ClockEdge *src,
CycleAccting probe(src, tgt);
CycleAccting *acct = cycle_acctings_.findKey(&probe);
if (acct == nullptr) {
acct = new CycleAccting(src, tgt);
if (src == defaultArrivalClockEdge())
acct->findDefaultArrivalSrcDelays();
else
acct->findDelays(this);
UniqueLock lock(cycle_acctings_lock_);
cycle_acctings_.insert(acct);
// Recheck with lock.
acct = cycle_acctings_.findKey(&probe);
if (acct == nullptr) {
acct = new CycleAccting(src, tgt);
if (src == defaultArrivalClockEdge())
acct->findDefaultArrivalSrcDelays();
else
acct->findDelays(this);
cycle_acctings_.insert(acct);
}
}
return acct;
}
Expand All @@ -2520,7 +2524,9 @@ Sdc::reportClkToClkMaxCycleWarnings()
// duplicate warnings between different src/tgt clk edges.
ClockPairSet clk_warnings;
ClockPairSeq clk_warnings2;
for (auto acct : cycle_acctings_) {
CycleAcctingSet::Iterator acct_iter(cycle_acctings_);
while (acct_iter.hasNext()) {
CycleAccting *acct = acct_iter.next();
if (acct->maxCyclesExceeded()) {
Clock *src = acct->src()->clock();
Clock *tgt = acct->target()->clock();
Expand Down Expand Up @@ -3301,22 +3307,17 @@ Sdc::setNetWireCap(Net *net,
}
if (net_wire_cap_map_ == nullptr)
net_wire_cap_map_ = new NetWireCapMap[corners_->count()];
bool make_drvr_entry = net_wire_cap_map_[corner->index()].hasKey(net);
bool make_drvr_entry = !net_wire_cap_map_[corner->index()].hasKey(net);
MinMaxFloatValues &values = net_wire_cap_map_[corner->index()][net];
values.setValue(min_max, wire_cap);

// Only need to do this when there is new net_wire_cap_map_ entry.
if (make_drvr_entry) {
NetConnectedPinIterator *pin_iter = network_->connectedPinIterator(net);
while (pin_iter->hasNext()) {
Pin *pin = pin_iter->next();
if (network_->isDriver(pin)) {
if (drvr_pin_wire_cap_map_ == nullptr)
drvr_pin_wire_cap_map_ = new PinWireCapMap[corners_->count()];
drvr_pin_wire_cap_map_[corner->index()][pin] = &values;
}
for (Pin *pin : *network_->drivers(net)) {
if (drvr_pin_wire_cap_map_ == nullptr)
drvr_pin_wire_cap_map_ = new PinWireCapMap[corners_->count()];
drvr_pin_wire_cap_map_[corner->index()][pin] = &values;
}
delete pin_iter;
}
}

Expand Down
5 changes: 3 additions & 2 deletions sdc/Sdc.hh
Expand Up @@ -22,7 +22,7 @@
#include "StringUtil.hh"
#include "StringSet.hh"
#include "Map.hh"
#include "UnorderedSet.hh"
#include "HashSet.hh"
#include "UnorderedMap.hh"
#include "MinMax.hh"
#include "RiseFallValues.hh"
Expand Down Expand Up @@ -114,7 +114,8 @@ typedef Set<InputDelay*> InputDelaySet;
typedef Map<const Pin*,InputDelaySet*> InputDelayRefPinMap;
typedef Map<const Pin*,InputDelaySet*> InputDelayInternalPinMap;
typedef Map<const Pin*,OutputDelay*> OutputDelayMap;
typedef UnorderedSet<CycleAccting*, CycleAcctingHash, CycleAcctingEqual> CycleAcctingSet;
// Use HashSet so no read lock is required.
typedef HashSet<CycleAccting*, CycleAcctingHash, CycleAcctingEqual> CycleAcctingSet;
typedef Set<Instance*> InstanceSet;
typedef UnorderedMap<const Pin*,ExceptionPathSet*> PinExceptionsMap;
typedef Map<const Clock*,ExceptionPathSet*> ClockExceptionsMap;
Expand Down
4 changes: 3 additions & 1 deletion search/Bfs.cc
Expand Up @@ -153,6 +153,7 @@ BfsIterator::visit(Level to_level,
}
}
level_vertices.clear();
visitor->levelFinished();
}
}
return visit_count;
Expand Down Expand Up @@ -224,7 +225,7 @@ BfsIterator::visitParallel(Level to_level,

for (int i = 0; i < thread_count_; i++) {
ForEachArg<QueueIterator, VertexVisitor> arg(&iter, lock,
visitor->copy());
visitor->copy());
// Missing check for null vertex.
threads.push_back(std::thread(forEachBegin<QueueIterator,
VertexVisitor, Vertex*>, arg));
Expand All @@ -235,6 +236,7 @@ BfsIterator::visitParallel(Level to_level,
thread.join();

visit_count += iter.count();
visitor->levelFinished();
level = first_level_;
}
else {
Expand Down
5 changes: 1 addition & 4 deletions search/Sim.cc
Expand Up @@ -1079,12 +1079,9 @@ Sim::annotateVertexEdges(const Instance *inst,
InstancePinIterator *pin_iter = network_->pinIterator(inst);
while (pin_iter->hasNext()) {
Pin *pin = pin_iter->next();
Vertex *vertex, *bidirect_drvr_vertex;
graph_->pinVertices(pin, vertex, bidirect_drvr_vertex);
Vertex *vertex = graph_->pinDrvrVertex(pin);
if (vertex)
annotateVertexEdges(inst, pin, vertex, annotate);
if (bidirect_drvr_vertex)
annotateVertexEdges(inst, pin, bidirect_drvr_vertex, annotate);
}
delete pin_iter;
}
Expand Down
5 changes: 3 additions & 2 deletions search/VertexVisitor.hh
Expand Up @@ -32,19 +32,20 @@ public:
virtual VertexVisitor *copy() = 0;
virtual void visit(Vertex *vertex) = 0;
void operator()(Vertex *vertex) { visit(vertex); }
virtual void levelFinished() {}

private:
DISALLOW_COPY_AND_ASSIGN(VertexVisitor);
};

// Collector visited pins into a PinSet.
// Collect visited pins into a PinSet.
class VertexPinCollector : public VertexVisitor
{
public:
VertexPinCollector(PinSet *pins);
PinSet *pins() const { return pins_; }
void visit(Vertex *vertex);
VertexVisitor *copy();
virtual VertexVisitor *copy();

protected:
PinSet *pins_;
Expand Down

0 comments on commit 2bf8b78

Please sign in to comment.