VertexSet use vertex id for comparison

Signed-off-by: James Cherry <cherry@parallaxsw.com>
This commit is contained in:
James Cherry 2022-03-01 06:55:25 -07:00
parent 783db41dfd
commit 61c0f9d73c
20 changed files with 265 additions and 240 deletions

View File

@ -214,6 +214,8 @@ GraphDelayCalc1::GraphDelayCalc1(StaState *sta) :
observer_(nullptr),
delays_seeded_(false),
incremental_(false),
delays_exist_(false),
invalid_delays_(new VertexSet(graph_)),
search_pred_(new SearchPred1(sta)),
search_non_latch_pred_(new SearchPredNonLatch2(sta)),
clk_pred_(new ClkTreeSearchPred(sta)),
@ -226,6 +228,7 @@ GraphDelayCalc1::GraphDelayCalc1(StaState *sta) :
GraphDelayCalc1::~GraphDelayCalc1()
{
delete search_pred_;
delete invalid_delays_;
delete search_non_latch_pred_;
delete clk_pred_;
delete iter_;
@ -293,7 +296,7 @@ GraphDelayCalc1::delaysInvalid()
incremental_ = false;
iter_->clear();
// No need to keep track of incremental updates any more.
invalid_delays_.clear();
invalid_delays_->clear();
invalid_check_edges_.clear();
invalid_latch_edges_.clear();
}
@ -326,11 +329,11 @@ GraphDelayCalc1::delayInvalid(Vertex *vertex)
debugPrint(debug_, "delay_calc", 2, "delay invalid %s",
vertex->name(sdc_network_));
if (graph_ && incremental_) {
invalid_delays_.insert(vertex);
invalid_delays_->insert(vertex);
// Invalidate driver that triggers dcalc for multi-driver nets.
MultiDrvrNet *multi_drvr = multiDrvrNet(vertex);
if (multi_drvr)
invalid_delays_.insert(multi_drvr->dcalcDrvr());
invalid_delays_->insert(multi_drvr->dcalcDrvr());
}
}
@ -339,7 +342,7 @@ GraphDelayCalc1::deleteVertexBefore(Vertex *vertex)
{
iter_->deleteVertexBefore(vertex);
if (incremental_)
invalid_delays_.erase(vertex);
invalid_delays_->erase(vertex);
MultiDrvrNet *multi_drvr = multiDrvrNet(vertex);
if (multi_drvr) {
multi_drvr->drvrs()->erase(vertex);
@ -432,9 +435,7 @@ GraphDelayCalc1::findDelays(Level level)
void
GraphDelayCalc1::seedInvalidDelays()
{
VertexSet::Iterator vertex_iter(invalid_delays_);
while (vertex_iter.hasNext()) {
Vertex *vertex = vertex_iter.next();
for (Vertex *vertex : *invalid_delays_) {
if (vertex->isRoot())
seedRootSlew(vertex, arc_delay_calc_);
else {
@ -442,7 +443,7 @@ GraphDelayCalc1::seedInvalidDelays()
iter_->enqueue(vertex);
}
}
invalid_delays_.clear();
invalid_delays_->clear();
}
class FindNetDrvrs : public PinVisitor
@ -508,7 +509,7 @@ void
GraphDelayCalc1::makeMultiDrvrNet(PinSet &drvr_pins)
{
debugPrint(debug_, "delay_calc", 3, "multi-driver net");
VertexSet *drvr_vertices = new VertexSet;
VertexSet *drvr_vertices = new VertexSet(graph_);
MultiDrvrNet *multi_drvr = new MultiDrvrNet(drvr_vertices);
Level max_drvr_level = 0;
Vertex *max_drvr = nullptr;
@ -549,11 +550,8 @@ GraphDelayCalc1::multiDrvrNet(const Vertex *drvr_vertex) const
void
GraphDelayCalc1::seedRootSlews()
{
VertexSet::Iterator root_iter(levelize_->roots());
while (root_iter.hasNext()) {
Vertex *vertex = root_iter.next();
for (Vertex *vertex : *levelize_->roots())
seedRootSlew(vertex, arc_delay_calc_);
}
}
void
@ -919,9 +917,7 @@ GraphDelayCalc1::findDriverDelays(Vertex *drvr_vertex,
Vertex *dcalc_drvr = multi_drvr->dcalcDrvr();
if (drvr_vertex == dcalc_drvr) {
bool init_load_slews = true;
VertexSet::Iterator drvr_iter(multi_drvr->drvrs());
while (drvr_iter.hasNext()) {
Vertex *drvr_vertex = drvr_iter.next();
for (Vertex *drvr_vertex : *multi_drvr->drvrs()) {
// Only init load slews once so previous driver dcalc results
// aren't clobbered.
delay_changed |= findDriverDelays1(drvr_vertex, init_load_slews,
@ -1381,9 +1377,7 @@ GraphDelayCalc1::findMultiDrvrGateDelay(MultiDrvrNet *multi_drvr,
{
ArcDelay delay_sum = 1.0;
Slew slew_sum = 1.0;
VertexSet::Iterator drvr_iter(multi_drvr->drvrs());
while (drvr_iter.hasNext()) {
Vertex *drvr_vertex1 = drvr_iter.next();
for (Vertex *drvr_vertex1 : *multi_drvr->drvrs()) {
Pin *drvr_pin1 = drvr_vertex1->pin();
Instance *drvr_inst1 = network_->instance(drvr_pin1);
LibertyCell *drvr_cell1 = network_->libertyCell(drvr_inst1);

View File

@ -212,7 +212,7 @@ protected:
bool incremental_;
bool delays_exist_;
// Vertices with invalid -to delays.
VertexSet invalid_delays_;
VertexSet *invalid_delays_;
// Timing check edges with invalid delays.
EdgeSet invalid_check_edges_;
// Latch D->Q edges with invalid delays.

View File

@ -48,14 +48,18 @@ Graph::Graph(StaState *sta,
have_arc_delays_(have_arc_delays),
ap_count_(ap_count),
width_check_annotations_(nullptr),
period_check_annotations_(nullptr)
period_check_annotations_(nullptr),
reg_clk_vertices_(new VertexSet(graph_))
{
// For the benifit of reg_clk_vertices_ that references graph_.
graph_ = this;
}
Graph::~Graph()
{
delete vertices_;
delete edges_;
delete reg_clk_vertices_;
deleteSlewTables();
deleteArcDelayTables();
removeWidthCheckAnnotations();
@ -396,7 +400,7 @@ Graph::makeVertex(Pin *pin,
vertex->init(pin, is_bidirect_drvr, is_reg_clk);
makeVertexSlews(vertex);
if (is_reg_clk)
reg_clk_vertices_.insert(vertex);
reg_clk_vertices_->insert(vertex);
return vertex;
}
@ -432,7 +436,7 @@ void
Graph::deleteVertex(Vertex *vertex)
{
if (vertex->isRegClk())
reg_clk_vertices_.erase(vertex);
reg_clk_vertices_->erase(vertex);
Pin *pin = vertex->pin_;
if (vertex->isBidirectDriver())
pin_bidirect_drvr_vertex_map_.erase(pin_bidirect_drvr_vertex_map_
@ -1599,4 +1603,23 @@ EdgesThruHierPinIterator::EdgesThruHierPinIterator(const Pin *hpin,
edge_iter_.init(edges_);
}
////////////////////////////////////////////////////////////////
VertexIdLess::VertexIdLess(Graph *&graph) :
graph_(graph)
{
}
bool
VertexIdLess::operator()(const Vertex *vertex1,
const Vertex *vertex2) const
{
return graph_->id(vertex1) < graph_->id(vertex2);
}
VertexSet::VertexSet(Graph *&graph) :
Set<Vertex*, VertexIdLess>(VertexIdLess(graph))
{
}
} // namespace

View File

@ -199,7 +199,7 @@ public:
float period);
// Remove all delay and slew annotations.
void removeDelaySlewAnnotations();
VertexSet *regClkVertices() { return &reg_clk_vertices_; }
VertexSet *regClkVertices() { return reg_clk_vertices_; }
static const int vertex_level_bits = 24;
static const int vertex_level_max = (1<<vertex_level_bits)-1;
@ -261,7 +261,7 @@ protected:
// Sdf period check annotations.
PeriodCheckAnnotations *period_check_annotations_;
// Register/latch clock vertices to search from.
VertexSet reg_clk_vertices_;
VertexSet *reg_clk_vertices_;
friend class Vertex;
friend class VertexIterator;
@ -526,4 +526,22 @@ private:
EdgeSet::Iterator edge_iter_;
};
class VertexIdLess
{
public:
VertexIdLess(Graph *&graph);
bool operator()(const Vertex *vertex1,
const Vertex *vertex2) const;
private:
Graph *&graph_;
};
class VertexSet : public Set<Vertex*, VertexIdLess>
{
public:
VertexSet(Graph *&graph);
VertexSet(const VertexSet &set);
};
} // namespace

View File

@ -32,11 +32,11 @@ class VertexIterator;
class VertexInEdgeIterator;
class VertexOutEdgeIterator;
class GraphLoop;
class VertexSet;
typedef ObjectId VertexId;
typedef ObjectId EdgeId;
typedef ObjectId ArcId;
typedef Set<Vertex*> VertexSet;
typedef Vector<Vertex*> VertexSeq;
typedef Vector<Edge*> EdgeSeq;
typedef Set<Edge*> EdgeSet;

View File

@ -548,15 +548,15 @@ protected:
// Requireds have been seeded by searching arrivals to all endpoints.
bool requireds_seeded_;
// Vertices with invalid arrival times to update and search from.
VertexSet invalid_arrivals_;
VertexSet *invalid_arrivals_;
std::mutex invalid_arrivals_lock_;
BfsFwdIterator *arrival_iter_;
// Vertices with invalid required times to update and search from.
VertexSet invalid_requireds_;
VertexSet *invalid_requireds_;
BfsBkwdIterator *required_iter_;
bool tns_exists_;
// Endpoint vertices with slacks that have changed since tns was found.
VertexSet invalid_tns_;
VertexSet *invalid_tns_;
// Indexed by path_ap->index().
SlackSeq tns_;
// Indexed by path_ap->index().
@ -585,7 +585,7 @@ protected:
TagGroupIndex tag_group_capacity_;
std::mutex tag_group_lock_;
// Latches data outputs to queue on the next search pass.
VertexSet pending_latch_outputs_;
VertexSet *pending_latch_outputs_;
std::mutex pending_latch_outputs_lock_;
VertexSet *endpoints_;
VertexSet *invalid_endpoints_;

View File

@ -984,6 +984,8 @@ public:
Arrival vertexArrival(Vertex *vertex,
const RiseFall *rf,
const PathAnalysisPt *path_ap);
Arrival vertexArrival(Vertex *vertex,
const MinMax *min_max);
Required vertexRequired(Vertex *vertex,
const MinMax *min_max);
Required vertexRequired(Vertex *vertex,

View File

@ -153,9 +153,7 @@ CheckTiming::checkRegClks(bool reg_multiple_clks,
bool reg_no_clks)
{
PinSet no_clk_pins, multiple_clk_pins;
VertexSet::ConstIterator reg_clk_iter(graph_->regClkVertices());
while (reg_clk_iter.hasNext()) {
Vertex *vertex = reg_clk_iter.next();
for (Vertex *vertex : *graph_->regClkVertices()) {
Pin *pin = vertex->pin();
ClockSet clks;
search_->clocks(vertex, clks);
@ -318,7 +316,7 @@ CheckTiming::checkGeneratedClocks()
if (clk->isGenerated()) {
search_->genclks()->checkMaster(clk);
bool found_clk = false;
VertexSet src_vertices;
VertexSet src_vertices(graph_);
clk->srcPinVertices(src_vertices, network_, graph_);
VertexSet::Iterator vertex_iter(src_vertices);
while (vertex_iter.hasNext()) {

View File

@ -190,9 +190,7 @@ ClkSkews::findClkSkew(ClockSet *clks,
const SetupHold *setup_hold,
ClkSkewMap &skews)
{
VertexSet::ConstIterator reg_clk_iter(graph_->regClkVertices());
while (reg_clk_iter.hasNext()) {
Vertex *src_vertex = reg_clk_iter.next();
for (Vertex *src_vertex : *graph_->regClkVertices()) {
if (hasClkPaths(src_vertex, clks)) {
VertexOutEdgeIterator edge_iter(src_vertex, graph_);
while (edge_iter.hasNext()) {
@ -343,7 +341,7 @@ ClkSkews::findFanout(Vertex *from)
{
debugPrint(debug_, "fanout", 1, "%s",
from->name(sdc_network_));
VertexSet endpoints;
VertexSet endpoints(graph_);
FanOutSrchPred pred(this);
BfsFwdIterator fanout_iter(BfsIndex::other, &pred, this);
fanout_iter.enqueue(from);

View File

@ -139,7 +139,7 @@ FindRegVisitor::visitRegs(ClockSet *clks,
while (clk_iter.hasNext()) {
Clock *clk = clk_iter.next();
FindRegClkPred clk_pred(clk, this);
VertexSet visited_vertices;
VertexSet visited_vertices(graph_);
for (Pin *pin : clk->leafPins()) {
Vertex *vertex, *bidirect_drvr_vertex;
graph_->pinVertices(pin, vertex, bidirect_drvr_vertex);
@ -158,9 +158,7 @@ FindRegVisitor::visitRegs(ClockSet *clks,
}
}
else {
VertexSet::ConstIterator reg_clk_iter(graph_->regClkVertices());
while (reg_clk_iter.hasNext()) {
Vertex *vertex = reg_clk_iter.next();
for (Vertex *vertex : *graph_->regClkVertices()) {
visitRegs(vertex->pin(), TimingSense::positive_unate,
RiseFallBoth::riseFall(),
edge_triggered, latches);

View File

@ -389,7 +389,7 @@ void
Genclks::seedSrcPins(Clock *clk,
BfsBkwdIterator &iter)
{
VertexSet src_vertices;
VertexSet src_vertices(graph_);
clk->srcPinVertices(src_vertices, network_, graph_);
VertexSet::Iterator vertex_iter(src_vertices);
while (vertex_iter.hasNext()) {
@ -583,7 +583,7 @@ Genclks::makeGenclkInfo(Clock *gclk)
{
FilterPath *src_filter = makeSrcFilter(gclk);
Level gclk_level = clkPinMaxLevel(gclk);
VertexSet *fanins = new VertexSet;
VertexSet *fanins = new VertexSet(graph_);
findFanin(gclk, fanins);
GenclkInfo *genclk_info = new GenclkInfo(gclk, gclk_level, fanins,
src_filter);
@ -643,8 +643,8 @@ Genclks::findLatchFdbkEdges(const Clock *gclk,
EdgeSet *fdbk_edges = nullptr;
for (Pin *pin : gclk->masterClk()->leafPins()) {
Vertex *vertex = graph_->pinDrvrVertex(pin);
VertexSet path_vertices;
VertexSet visited_vertices;
VertexSet path_vertices(graph_);
VertexSet visited_vertices(graph_);
SearchPred1 srch_pred(this);
findLatchFdbkEdges(vertex, gclk_level, srch_pred, path_vertices,
visited_vertices, fdbk_edges);

View File

@ -40,6 +40,8 @@ Levelize::Levelize(StaState *sta) :
levels_valid_(false),
max_level_(0),
level_space_(10),
roots_(new VertexSet(graph_)),
relevelize_from_(new VertexSet(graph_)),
loops_(nullptr),
observer_(nullptr)
{
@ -47,6 +49,8 @@ Levelize::Levelize(StaState *sta) :
Levelize::~Levelize()
{
delete roots_;
delete relevelize_from_;
delete search_pred_;
delete observer_;
deleteLoops();
@ -70,8 +74,8 @@ Levelize::clear()
{
levelized_ = false;
levels_valid_ = false;
roots_.clear();
relevelize_from_.clear();
roots_->clear();
relevelize_from_->clear();
clearLoopEdges();
deleteLoops();
}
@ -146,7 +150,7 @@ Levelize::findRoots()
setLevel(vertex, 0);
if (isRoot(vertex)) {
debugPrint(debug_, "levelize", 2, "root %s", vertex->name(sdc_network_));
roots_.insert(vertex);
roots_->insert(vertex);
if (hasFanout(vertex, search_pred_, graph_))
// Color roots with no fanout black so that they are
// not treated as degenerate loops by levelizeCycles().
@ -183,11 +187,8 @@ Levelize::sortRoots(VertexSeq &roots)
{
// roots_ is a set so insert/delete are fast for incremental changes.
// Copy the set into a vector for sorting.
VertexSet::Iterator root_iter(roots_);
while (root_iter.hasNext()) {
Vertex *root = root_iter.next();
for (Vertex *root : *roots_)
roots.push_back(root);
}
sort(roots, VertexNameLess(network_));
}
@ -362,7 +363,7 @@ Levelize::levelizeCycles()
// root".
if (vertex->color() == LevelColor::white) {
EdgeSeq path;
roots_.insert(vertex);
roots_->insert(vertex);
visit(vertex, 0, level_space_, path);
}
}
@ -384,17 +385,17 @@ Levelize::invalidFrom(Vertex *vertex)
while (edge_iter.hasNext()) {
Edge *edge = edge_iter.next();
Vertex *from_vertex = edge->from(graph_);
relevelize_from_.insert(from_vertex);
relevelize_from_->insert(from_vertex);
}
relevelize_from_.insert(vertex);
relevelize_from_->insert(vertex);
levels_valid_ = false;
}
void
Levelize::deleteVertexBefore(Vertex *vertex)
{
roots_.erase(vertex);
relevelize_from_.erase(vertex);
roots_->erase(vertex);
relevelize_from_->erase(vertex);
}
void
@ -402,7 +403,7 @@ Levelize::relevelizeFrom(Vertex *vertex)
{
debugPrint(debug_, "levelize", 1, "invalid relevelize from %s",
vertex->name(sdc_network_));
relevelize_from_.insert(vertex);
relevelize_from_->insert(vertex);
levels_valid_ = false;
}
@ -429,15 +430,13 @@ Levelize::deleteEdgeBefore(Edge *edge)
void
Levelize::relevelize()
{
VertexSet::Iterator vertex_iter(relevelize_from_);
while (vertex_iter.hasNext()) {
Vertex *vertex = vertex_iter.next();
for (Vertex *vertex : *relevelize_from_) {
debugPrint(debug_, "levelize", 1, "relevelize from %s",
vertex->name(sdc_network_));
if (search_pred_->searchFrom(vertex)) {
if (isRoot(vertex)) {
setLevel(vertex, 0);
roots_.insert(vertex);
roots_->insert(vertex);
}
EdgeSeq path;
visit(vertex, vertex->level(), 1, path);
@ -445,7 +444,7 @@ Levelize::relevelize()
}
ensureLatchLevels();
levels_valid_ = true;
relevelize_from_.clear();
relevelize_from_->clear();
}
bool

View File

@ -44,7 +44,7 @@ public:
void deleteEdgeBefore(Edge *edge);
int maxLevel() const { return max_level_; }
// Vertices with no fanin edges.
VertexSet &roots() { return roots_; }
VertexSet *roots() { return roots_; }
bool isRoot(Vertex *vertex);
// Reset to virgin state.
void clear();
@ -77,8 +77,8 @@ protected:
bool levels_valid_;
Level max_level_;
Level level_space_;
VertexSet roots_;
VertexSet relevelize_from_;
VertexSet *roots_;
VertexSet *relevelize_from_;
GraphLoopSeq *loops_;
EdgeSet loop_edges_;
EdgeSet disabled_loop_edges_;

View File

@ -808,7 +808,7 @@ PathGroups::makeGroupPathEnds(ExceptionTo *to,
makeGroupPathEnds(search->endpoints(), corner, min_max, visitor);
else {
// Only visit -to filter pins.
VertexSet endpoints;
VertexSet endpoints(graph_);
PinSet pins;
to->allPins(network, &pins);
PinSet::Iterator pin_iter(pins);

View File

@ -509,7 +509,7 @@ Power::ensureActivities()
void
Power::seedActivities(BfsFwdIterator &bfs)
{
for (Vertex *vertex : levelize_->roots()) {
for (Vertex *vertex : *levelize_->roots()) {
const Pin *pin = vertex->pin();
// Clock activities are baked in.
if (!sdc_->isLeafPinClock(pin)

View File

@ -225,6 +225,9 @@ Search::init(StaState *sta)
arrivals_seeded_ = false;
requireds_exist_ = false;
requireds_seeded_ = false;
invalid_arrivals_ = new VertexSet(graph_);
invalid_requireds_ = new VertexSet(graph_);
invalid_tns_ = new VertexSet(graph_);
tns_exists_ = false;
worst_slacks_ = nullptr;
arrival_iter_ = new BfsFwdIterator(BfsIndex::arrival, nullptr, sta);
@ -238,6 +241,7 @@ Search::init(StaState *sta)
tag_groups_ = new TagGroup*[tag_group_capacity_];
tag_group_next_ = 0;
tag_group_set_ = new TagGroupSet(tag_group_capacity_);
pending_latch_outputs_ = new VertexSet(graph_);
visit_path_ends_ = new VisitPathEnds(this);
gated_clk_ = new GatedClk(this);
path_groups_ = nullptr;
@ -273,7 +277,11 @@ Search::~Search()
delete arrival_iter_;
delete required_iter_;
delete endpoints_;
delete invalid_arrivals_;
delete invalid_requireds_;
delete invalid_tns_;
delete invalid_endpoints_;
delete pending_latch_outputs_;
delete visit_path_ends_;
delete gated_clk_;
delete worst_slacks_;
@ -295,10 +303,10 @@ Search::clear()
requireds_seeded_ = false;
tns_exists_ = false;
clearWorstSlack();
invalid_arrivals_.clear();
invalid_arrivals_->clear();
arrival_iter_->clear();
invalid_requireds_.clear();
invalid_tns_.clear();
invalid_requireds_->clear();
invalid_tns_->clear();
required_iter_->clear();
endpointsInvalid();
deletePathGroups();
@ -633,12 +641,12 @@ Search::deleteVertexBefore(Vertex *vertex)
if (arrivals_exist_) {
deletePaths(vertex);
arrival_iter_->deleteVertexBefore(vertex);
invalid_arrivals_.erase(vertex);
invalid_arrivals_->erase(vertex);
}
if (requireds_exist_) {
required_iter_->deleteVertexBefore(vertex);
invalid_requireds_.erase(vertex);
invalid_tns_.erase(vertex);
invalid_requireds_->erase(vertex);
invalid_tns_->erase(vertex);
}
if (endpoints_)
endpoints_->erase(vertex);
@ -650,7 +658,7 @@ bool
Search::arrivalsValid()
{
return arrivals_exist_
&& invalid_requireds_.empty();
&& invalid_requireds_->empty();
}
void
@ -673,11 +681,11 @@ Search::arrivalsInvalid()
arrival_iter_->clear();
required_iter_->clear();
// No need to keep track of incremental updates any more.
invalid_arrivals_.clear();
invalid_requireds_.clear();
invalid_arrivals_->clear();
invalid_requireds_->clear();
tns_exists_ = false;
clearWorstSlack();
invalid_tns_.clear();
invalid_tns_->clear();
}
}
@ -687,10 +695,10 @@ Search::requiredsInvalid()
debugPrint(debug_, "search", 1, "requireds invalid");
requireds_exist_ = false;
requireds_seeded_ = false;
invalid_requireds_.clear();
invalid_requireds_->clear();
tns_exists_ = false;
clearWorstSlack();
invalid_tns_.clear();
invalid_tns_->clear();
}
void
@ -702,7 +710,7 @@ Search::arrivalInvalid(Vertex *vertex)
if (!arrival_iter_->inQueue(vertex)) {
// Lock for StaDelayCalcObserver called by delay calc threads.
UniqueLock lock(invalid_arrivals_lock_);
invalid_arrivals_.insert(vertex);
invalid_arrivals_->insert(vertex);
}
tnsInvalid(vertex);
}
@ -772,7 +780,7 @@ Search::requiredInvalid(Vertex *vertex)
if (!required_iter_->inQueue(vertex)) {
// Lock for StaDelayCalcObserver called by delay calc threads.
UniqueLock lock(invalid_arrivals_lock_);
invalid_requireds_.insert(vertex);
invalid_requireds_->insert(vertex);
}
tnsInvalid(vertex);
}
@ -926,19 +934,19 @@ Search::findAllArrivals(VertexVisitor *arrival_visitor)
bool
Search::havePendingLatchOutputs()
{
return pending_latch_outputs_.size() > 0;
return !pending_latch_outputs_->empty();
}
void
Search::clearPendingLatchOutputs()
{
pending_latch_outputs_.clear();
pending_latch_outputs_->clear();
}
void
Search::enqueuePendingLatchOutputs()
{
for (Vertex *latch_vertex : pending_latch_outputs_)
for (Vertex *latch_vertex : *pending_latch_outputs_)
arrival_iter_->enqueue(latch_vertex);
clearPendingLatchOutputs();
}
@ -966,7 +974,7 @@ Search::findArrivals(Level level,
int arrival_count = arrival_iter_->visitParallel(level, arrival_visitor);
stats.report("Find arrivals");
if (arrival_iter_->empty()
&& invalid_arrivals_.empty()) {
&& invalid_arrivals_->empty()) {
clk_arrivals_valid_ = true;
arrivals_at_endpoints_exist_ = true;
}
@ -1360,7 +1368,7 @@ Search::enqueueLatchDataOutputs(Vertex *vertex)
if (latches_->isLatchDtoQ(out_edge)) {
Vertex *out_vertex = out_edge->to(graph_);
UniqueLock lock(pending_latch_outputs_lock_);
pending_latch_outputs_.insert(out_vertex);
pending_latch_outputs_->insert(out_vertex);
}
}
}
@ -1368,7 +1376,7 @@ Search::enqueueLatchDataOutputs(Vertex *vertex)
void
Search::seedArrivals()
{
VertexSet vertices;
VertexSet vertices(graph_);
findClockVertices(vertices);
findRootVertices(vertices);
findInputDrvrVertices(vertices);
@ -1394,9 +1402,9 @@ Search::findClockVertices(VertexSet &vertices)
void
Search::seedInvalidArrivals()
{
for (Vertex *vertex : invalid_arrivals_)
for (Vertex *vertex : *invalid_arrivals_)
seedArrival(vertex);
invalid_arrivals_.clear();
invalid_arrivals_->clear();
}
void
@ -1605,7 +1613,7 @@ Search::makeUnclkedPaths(Vertex *vertex,
void
Search::findRootVertices(VertexSet &vertices)
{
for (Vertex *vertex : levelize_->roots()) {
for (Vertex *vertex : *levelize_->roots()) {
const Pin *pin = vertex->pin();
if (!sdc_->isLeafPinClock(pin)
&& !sdc_->hasInputDelay(pin)
@ -3103,8 +3111,8 @@ VertexSet *
Search::endpoints()
{
if (endpoints_ == nullptr) {
endpoints_ = new VertexSet;
invalid_endpoints_ = new VertexSet;
endpoints_ = new VertexSet(graph_);
invalid_endpoints_ = new VertexSet(graph_);
VertexIterator vertex_iter(graph_);
while (vertex_iter.hasNext()) {
Vertex *vertex = vertex_iter.next();
@ -3193,9 +3201,9 @@ Search::endpointsInvalid()
void
Search::seedInvalidRequireds()
{
for (Vertex *vertex : invalid_requireds_)
for (Vertex *vertex : *invalid_requireds_)
required_iter_->enqueue(vertex);
invalid_requireds_.clear();
invalid_requireds_->clear();
}
////////////////////////////////////////////////////////////////
@ -3687,7 +3695,7 @@ Search::tnsInvalid(Vertex *vertex)
debugPrint(debug_, "tns", 2, "tns invalid %s",
vertex->name(sdc_network_));
UniqueLock lock(tns_lock_);
invalid_tns_.insert(vertex);
invalid_tns_->insert(vertex);
}
}
@ -3695,7 +3703,7 @@ void
Search::updateInvalidTns()
{
PathAPIndex path_ap_count = corners_->pathAnalysisPtCount();
for (Vertex *vertex : invalid_tns_) {
for (Vertex *vertex : *invalid_tns_) {
// Network edits can change endpointedness since tnsInvalid was called.
if (isEndpoint(vertex)) {
debugPrint(debug_, "tns", 2, "update tns %s",
@ -3709,7 +3717,7 @@ Search::updateInvalidTns()
worst_slacks_->updateWorstSlacks(vertex, slacks);
}
}
invalid_tns_.clear();
invalid_tns_->clear();
}
void
@ -3826,7 +3834,7 @@ Search::wnsTnsPreamble()
findAllArrivals();
// Required times are only needed at endpoints.
if (requireds_seeded_) {
for (Vertex *vertex : invalid_requireds_) {
for (Vertex *vertex : *invalid_requireds_) {
debugPrint(debug_, "search", 2, "tns update required %s",
vertex->name(sdc_network_));
if (isEndpoint(vertex)) {
@ -3839,7 +3847,7 @@ Search::wnsTnsPreamble()
required_iter_->enqueue(vertex);
}
}
invalid_requireds_.clear();
invalid_requireds_->clear();
}
else
seedRequireds();

View File

@ -2792,6 +2792,26 @@ Sta::vertexWorstSlackPath(Vertex *vertex,
return vertexWorstSlackPath(vertex, nullptr, min_max);
}
Arrival
Sta::vertexArrival(Vertex *vertex,
const MinMax *min_max)
{
searchPreamble();
search_->findArrivals(vertex->level());
Arrival arrival = min_max->initValue();
VertexPathIterator path_iter(vertex, this);
while (path_iter.hasNext()) {
Path *path = path_iter.next();
const Arrival &path_arrival = path->arrival(this);
ClkInfo *clk_info = path->clkInfo(search_);
if (path->minMax(this) == min_max
&& !clk_info->isGenClkSrcPath()
&& delayGreater(path->arrival(this), arrival, min_max, this))
arrival = path_arrival;
}
return arrival;
}
Arrival
Sta::vertexArrival(Vertex *vertex,
const RiseFall *rf,
@ -4813,7 +4833,7 @@ Sta::findFaninPins(Vertex *vertex,
PinSet *fanin,
SearchPred &pred)
{
VertexSet visited;
VertexSet visited(graph_);
findFaninPins(vertex, flat, inst_levels,
pin_levels, visited, &pred, 0, 0);
VertexSet::Iterator visited_iter(visited);
@ -4923,7 +4943,7 @@ Sta::findFanoutPins(Vertex *vertex,
PinSet *fanout,
SearchPred &pred)
{
VertexSet visited;
VertexSet visited(graph_);
findFanoutPins(vertex, flat, inst_levels,
pin_levels, visited, &pred, 0, 0);
VertexSet::Iterator visited_iter(visited);

View File

@ -118,11 +118,8 @@ visitPathGroupVertices(PathGroup *path_group,
VisitPathGroupEnds end_visitor(path_group, visitor, &matching_path_map,
&bkwd_iter, sta);
VisitPathEnds visit_path_ends(sta);
VertexSet::Iterator end_iter(search->endpoints());
while (end_iter.hasNext()) {
Vertex *vertex = end_iter.next();
for(Vertex *vertex : *search->endpoints())
visit_path_ends.visitPathEnds(vertex, &end_visitor);
}
// Search backward from the path ends thru vertices that have arrival tags
// that match path_group end paths.

View File

@ -29,9 +29,9 @@ namespace sta {
using std::min;
WorstSlacks::WorstSlacks(StaState *sta) :
worst_slacks_(sta->corners()->pathAnalysisPtCount(), sta),
sta_(sta)
{
worst_slacks_.resize(sta->corners()->pathAnalysisPtCount());
}
void
@ -46,7 +46,7 @@ WorstSlacks::worstSlack(const MinMax *min_max,
PathAPIndex path_ap_index = corner->findPathAnalysisPt(min_max)->index();
Slack worst_slack1;
Vertex *worst_vertex1;
worst_slacks_[path_ap_index].worstSlack(path_ap_index, sta_,
worst_slacks_[path_ap_index].worstSlack(path_ap_index,
worst_slack1, worst_vertex1);
if (delayLess(worst_slack1, worst_slack, sta_)) {
worst_slack = worst_slack1;
@ -63,7 +63,7 @@ WorstSlacks::worstSlack(const Corner *corner,
Vertex *&worst_vertex)
{
PathAPIndex path_ap_index = corner->findPathAnalysisPt(min_max)->index();
worst_slacks_[path_ap_index].worstSlack(path_ap_index, sta_,
worst_slacks_[path_ap_index].worstSlack(path_ap_index,
worst_slack, worst_vertex);
}
@ -73,7 +73,7 @@ WorstSlacks::updateWorstSlacks(Vertex *vertex,
{
PathAPIndex path_ap_count = sta_->corners()->pathAnalysisPtCount();
for (PathAPIndex i = 0; i < path_ap_count; i++)
worst_slacks_[i].updateWorstSlack(vertex, slacks, i, sta_);
worst_slacks_[i].updateWorstSlack(vertex, slacks, i);
}
void
@ -88,21 +88,30 @@ WorstSlacks::worstSlackNotifyBefore(Vertex *vertex)
////////////////////////////////////////////////////////////////
WorstSlack::WorstSlack() :
WorstSlack::WorstSlack(StaState *sta) :
StaState(sta),
slack_init_(MinMax::min()->initValue()),
worst_vertex_(nullptr),
worst_slack_(slack_init_),
slack_threshold_(slack_init_),
queue_(new VertexSet(graph_)),
min_queue_size_(10),
max_queue_size_(20)
{
}
WorstSlack::WorstSlack(const WorstSlack &) :
WorstSlack::~WorstSlack()
{
delete queue_;
}
WorstSlack::WorstSlack(const WorstSlack &worst_slack) :
StaState(worst_slack),
slack_init_(MinMax::min()->initValue()),
worst_vertex_(nullptr),
worst_slack_(slack_init_),
slack_threshold_(slack_init_),
queue_(new VertexSet(graph_)),
min_queue_size_(10),
max_queue_size_(20)
{
@ -116,214 +125,181 @@ WorstSlack::deleteVertexBefore(Vertex *vertex)
worst_vertex_ = nullptr;
worst_slack_ = slack_init_;
}
queue_.erase(vertex);
queue_->erase(vertex);
}
void
WorstSlack::worstSlack(PathAPIndex path_ap_index,
const StaState *sta,
// Return values.
Slack &worst_slack,
Vertex *&worst_vertex)
{
findWorstSlack(path_ap_index, sta);
findWorstSlack(path_ap_index);
worst_slack = worst_slack_;
worst_vertex = worst_vertex_;
}
void
WorstSlack::findWorstSlack(PathAPIndex path_ap_index,
const StaState *sta)
WorstSlack::findWorstSlack(PathAPIndex path_ap_index)
{
if (worst_vertex_ == nullptr) {
if (queue_.empty())
initQueue(path_ap_index, sta);
if (queue_->empty())
initQueue(path_ap_index);
else
findWorstInQueue(path_ap_index, sta);
findWorstInQueue(path_ap_index);
}
}
void
WorstSlack::initQueue(PathAPIndex path_ap_index,
const StaState *sta)
WorstSlack::initQueue(PathAPIndex path_ap_index)
{
Search *search = sta->search();
const Debug *debug = sta->debug();
debugPrint(debug, "wns", 3, "init queue");
debugPrint(debug_, "wns", 3, "init queue");
queue_.clear();
queue_->clear();
worst_vertex_ = nullptr;
worst_slack_ = slack_init_;
slack_threshold_ = slack_init_;
VertexSet::Iterator end_iter(search->endpoints());
while (end_iter.hasNext()) {
Vertex *vertex = end_iter.next();
Slack slack = search->wnsSlack(vertex, path_ap_index);
for(Vertex *vertex : *search_->endpoints()) {
Slack slack = search_->wnsSlack(vertex, path_ap_index);
if (!delayEqual(slack, slack_init_)) {
if (delayLess(slack, worst_slack_, sta))
setWorstSlack(vertex, slack, sta);
if (delayLessEqual(slack, slack_threshold_, sta))
queue_.insert(vertex);
int queue_size = queue_.size();
if (delayLess(slack, worst_slack_, this))
setWorstSlack(vertex, slack);
if (delayLessEqual(slack, slack_threshold_, this))
queue_->insert(vertex);
int queue_size = queue_->size();
if (queue_size >= max_queue_size_)
sortQueue(path_ap_index, sta);
sortQueue(path_ap_index);
}
}
debugPrint(debug, "wns", 3, "threshold %s",
delayAsString(slack_threshold_, sta));
debugPrint(debug_, "wns", 3, "threshold %s",
delayAsString(slack_threshold_, this));
// checkQueue();
}
void
WorstSlack::sortQueue(PathAPIndex path_ap_index,
const StaState *sta)
WorstSlack::sortQueue(PathAPIndex path_ap_index)
{
if (queue_.size() > 0) {
Search *search = sta->search();
const Debug *debug = sta->debug();
debugPrint(debug, "wns", 3, "sort queue");
if (queue_->size() > 0) {
debugPrint(debug_, "wns", 3, "sort queue");
VertexSeq vertices;
vertices.reserve(queue_.size());
VertexSet::Iterator queue_iter(queue_);
while (queue_iter.hasNext()) {
Vertex *vertex = queue_iter.next();
vertices.reserve(queue_->size());
for (Vertex *vertex : *queue_)
vertices.push_back(vertex);
}
WnsSlackLess slack_less(path_ap_index, sta);
WnsSlackLess slack_less(path_ap_index, this);
sort(vertices, slack_less);
int vertex_count = vertices.size();
int threshold_index = min(min_queue_size_, vertex_count - 1);
Vertex *threshold_vertex = vertices[threshold_index];
slack_threshold_ = search->wnsSlack(threshold_vertex, path_ap_index);
debugPrint(debug, "wns", 3, "threshold %s",
delayAsString(slack_threshold_, sta));
slack_threshold_ = search_->wnsSlack(threshold_vertex, path_ap_index);
debugPrint(debug_, "wns", 3, "threshold %s",
delayAsString(slack_threshold_, this));
// Reinsert vertices with slack < threshold.
queue_.clear();
queue_->clear();
VertexSeq::Iterator queue_iter2(vertices);
while (queue_iter2.hasNext()) {
Vertex *vertex = queue_iter2.next();
Slack slack = search->wnsSlack(vertex, path_ap_index);
if (delayGreater(slack, slack_threshold_, sta))
Slack slack = search_->wnsSlack(vertex, path_ap_index);
if (delayGreater(slack, slack_threshold_, this))
break;
queue_.insert(vertex);
queue_->insert(vertex);
}
max_queue_size_ = queue_.size() * 2;
max_queue_size_ = queue_->size() * 2;
Vertex *worst_slack_vertex = vertices[0];
Slack worst_slack_slack = search->wnsSlack(worst_slack_vertex, path_ap_index);
setWorstSlack(worst_slack_vertex, worst_slack_slack, sta);
Slack worst_slack_slack = search_->wnsSlack(worst_slack_vertex, path_ap_index);
setWorstSlack(worst_slack_vertex, worst_slack_slack);
}
}
void
WorstSlack::findWorstInQueue(PathAPIndex path_ap_index,
const StaState *sta)
WorstSlack::findWorstInQueue(PathAPIndex path_ap_index)
{
Search *search = sta->search();
const Debug *debug = sta->debug();
debugPrint(debug, "wns", 3, "find worst in queue");
debugPrint(debug_, "wns", 3, "find worst in queue");
worst_vertex_ = nullptr;
worst_slack_ = slack_init_;
VertexSet::Iterator queue_iter(queue_);
while (queue_iter.hasNext()) {
Vertex *vertex = queue_iter.next();
Slack slack = search->wnsSlack(vertex, path_ap_index);
if (delayLess(slack, worst_slack_, sta))
setWorstSlack(vertex, slack, sta);
for (Vertex *vertex : *queue_) {
Slack slack = search_->wnsSlack(vertex, path_ap_index);
if (delayLess(slack, worst_slack_, this))
setWorstSlack(vertex, slack);
}
}
void
WorstSlack::checkQueue(PathAPIndex path_ap_index,
const StaState *sta)
WorstSlack::checkQueue(PathAPIndex path_ap_index)
{
Search *search = sta->search();
Report *report = sta->report();
const Network *network = sta->network();
VertexSeq ends;
VertexSet::Iterator end_iter(search->endpoints());
while (end_iter.hasNext()) {
Vertex *end = end_iter.next();
if (delayLessEqual(search->wnsSlack(end, path_ap_index),
slack_threshold_, sta))
for(Vertex *end : *search_->endpoints()) {
if (delayLessEqual(search_->wnsSlack(end, path_ap_index),
slack_threshold_, this))
ends.push_back(end);
}
WnsSlackLess slack_less(path_ap_index, sta);
WnsSlackLess slack_less(path_ap_index, this);
sort(ends, slack_less);
VertexSet end_set;
VertexSeq::Iterator end_iter2(ends);
while (end_iter2.hasNext()) {
Vertex *end = end_iter2.next();
VertexSet end_set(graph_);
for (Vertex *end : ends) {
end_set.insert(end);
if (!queue_.hasKey(end)
&& delayLessEqual(search->wnsSlack(end, path_ap_index),
slack_threshold_, sta))
report->reportLine("WorstSlack queue missing %s %s < %s",
end->name(network),
delayAsString(search->wnsSlack(end, path_ap_index), sta),
delayAsString(slack_threshold_, sta));
if (!queue_->hasKey(end)
&& delayLessEqual(search_->wnsSlack(end, path_ap_index),
slack_threshold_, this))
report_->reportLine("WorstSlack queue missing %s %s < %s",
end->name(network_),
delayAsString(search_->wnsSlack(end, path_ap_index), this),
delayAsString(slack_threshold_, this));
}
VertexSet::Iterator queue_iter(queue_);
while (queue_iter.hasNext()) {
Vertex *end = queue_iter.next();
for (Vertex *end : *queue_) {
if (!end_set.hasKey(end))
report->reportLine("WorstSlack queue extra %s %s > %s",
end->name(network),
delayAsString(search->wnsSlack(end, path_ap_index), sta),
delayAsString(slack_threshold_, sta));
report_->reportLine("WorstSlack queue extra %s %s > %s",
end->name(network_),
delayAsString(search_->wnsSlack(end, path_ap_index), this),
delayAsString(slack_threshold_, this));
}
}
void
WorstSlack::updateWorstSlack(Vertex *vertex,
SlackSeq &slacks,
PathAPIndex path_ap_index,
const StaState *sta)
PathAPIndex path_ap_index)
{
const Debug *debug = sta->debug();
const Network *network = sta->network();
Slack slack = slacks[path_ap_index];
// Locking is required because ArrivalVisitor is called by multiple
// threads.
UniqueLock lock(lock_);
if (worst_vertex_
&& delayLess(slack, worst_slack_, sta))
setWorstSlack(vertex, slack, sta);
&& delayLess(slack, worst_slack_, this))
setWorstSlack(vertex, slack);
else if (vertex == worst_vertex_)
// Mark worst slack as unknown (updated by findWorstSlack().
worst_vertex_ = nullptr;
if (!delayEqual(slack, slack_init_)
&& delayLessEqual(slack, slack_threshold_, sta)) {
debugPrint(debug, "wns", 3, "insert %s %s",
vertex->name(network),
delayAsString(slack, sta));
queue_.insert(vertex);
&& delayLessEqual(slack, slack_threshold_, this)) {
debugPrint(debug_, "wns", 3, "insert %s %s",
vertex->name(network_),
delayAsString(slack, this));
queue_->insert(vertex);
}
else {
debugPrint(debug, "wns", 3, "delete %s %s",
vertex->name(network),
delayAsString(slack, sta));
queue_.erase(vertex);
debugPrint(debug_, "wns", 3, "delete %s %s",
vertex->name(network_),
delayAsString(slack, this));
queue_->erase(vertex);
}
// checkQueue();
}
void
WorstSlack::setWorstSlack(Vertex *vertex,
Slack slack,
const StaState *sta)
Slack slack)
{
debugPrint(sta->debug(), "wns", 3, "%s %s",
vertex->name(sta->network()),
delayAsString(slack, sta));
debugPrint(debug_, "wns", 3, "%s %s",
vertex->name(network_),
delayAsString(slack, this));
worst_vertex_ = vertex;
worst_slack_ = slack;
}

View File

@ -22,6 +22,7 @@
#include "Vector.hh"
#include "GraphClass.hh"
#include "SearchClass.hh"
#include "StaState.hh"
namespace sta {
@ -66,36 +67,29 @@ private:
Search *search_;
};
class WorstSlack
class WorstSlack : public StaState
{
public:
WorstSlack();
WorstSlack(StaState *sta);
~WorstSlack();
WorstSlack(const WorstSlack &);
void worstSlack(PathAPIndex path_ap_index,
const StaState *sta,
// Return values.
Slack &worst_slack,
Vertex *&worst_vertex);
void updateWorstSlack(Vertex *vertex,
SlackSeq &slacks,
PathAPIndex path_ap_index,
const StaState *sta);
PathAPIndex path_ap_index);
void deleteVertexBefore(Vertex *vertex);
protected:
void findWorstSlack(PathAPIndex path_ap_index,
const StaState *sta);
void initQueue(PathAPIndex path_ap_index,
const StaState *sta);
void findWorstInQueue(PathAPIndex path_ap_index,
const StaState *sta);
void findWorstSlack(PathAPIndex path_ap_index);
void initQueue(PathAPIndex path_ap_index);
void findWorstInQueue(PathAPIndex path_ap_index);
void setWorstSlack(Vertex *vertex,
Slack slack,
const StaState *sta);
void sortQueue(PathAPIndex path_ap_index,
const StaState *sta);
void checkQueue(PathAPIndex path_ap_index,
const StaState *sta);
Slack slack);
void sortQueue(PathAPIndex path_ap_index);
void checkQueue(PathAPIndex path_ap_index);
Slack slack_init_;
// Vertex with the worst slack.
@ -104,7 +98,7 @@ protected:
Slack worst_slack_;
Slack slack_threshold_;
// Vertices with slack < threshold_
VertexSet queue_;
VertexSet *queue_;
// Queue is sorted and pruned to min_queue_size_ vertices when it
// reaches max_queue_size_.
int min_queue_size_;