From 0dfea7dfadcef60966abc1fad4023df789b56103 Mon Sep 17 00:00:00 2001 From: James Cherry Date: Mon, 10 Feb 2025 17:31:45 -0700 Subject: [PATCH] thread safety commit 98fa3639bd0e07f4e315578b50266972bbb7ac7d Author: James Cherry Date: Sat Feb 8 14:17:29 2025 -0800 Edge::setArcDelayAnnotated Signed-off-by: James Cherry commit d4628351d788c68ed948751374adee1bba6ca6ea Author: James Cherry Date: Sat Feb 8 09:27:33 2025 -0800 leaks Signed-off-by: James Cherry commit cee843b81df89c0f7bc51a76a34422009f49b046 Author: James Cherry Date: Fri Feb 7 10:22:00 2025 -0800 arcDelayAnnotated Signed-off-by: James Cherry commit 2a080cb4a3425e9b0a98d90315d23b87c755ebaa Author: James Cherry Date: Fri Feb 7 09:34:16 2025 -0800 leak Signed-off-by: James Cherry commit 6b85cebe290cb9f1c7fabe06fcec42dd7c060550 Author: James Cherry Date: Thu Feb 6 16:12:42 2025 -0800 readme Signed-off-by: James Cherry commit 01d4481280b08e98cc311dc37a3eeb1cfc928902 Author: James Cherry Date: Thu Feb 6 16:12:33 2025 -0800 comment Signed-off-by: James Cherry commit e7c62097f948450ed46c0ac577bd3636cf5be625 Author: James Cherry Date: Thu Feb 6 16:12:19 2025 -0800 Search no virtuals Signed-off-by: James Cherry commit 761212fc0a593d47422dc7716b7e28f593647a64 Author: James Cherry Date: Thu Feb 6 15:13:36 2025 -0800 leak Signed-off-by: James Cherry commit dd64f685c7fe2b3e85e3194008fae67a23650110 Author: James Cherry Date: Thu Feb 6 12:31:38 2025 -0800 Graph::removeDelayAnnotated Signed-off-by: James Cherry commit a1b79b09178ba8bdf0ec9486d84fcff68c2a1f2e Author: James Cherry Date: Thu Feb 6 12:19:32 2025 -0800 Edge::arc_annotated_delays_ Signed-off-by: James Cherry commit 6b8b44ebd1e3a483ccfaa08f08c5fa8b60c72f90 Author: James Cherry Date: Thu Feb 6 08:48:49 2025 -0800 leak Signed-off-by: James Cherry commit ee939bf4015fe3d78860b3e615ec7defa395b2bf Author: James Cherry Date: Wed Feb 5 18:14:04 2025 -0800 pass fast regressions Signed-off-by: James Cherry commit f25b505d8507046638dbb30772d721547b3f8941 Author: James Cherry Date: Wed Feb 5 15:54:39 2025 -0800 pass all but 1 regression Signed-off-by: James Cherry commit acd3abf0512f5ecbe83025eb5facfa5a594ca9fa Author: James Cherry Date: Wed Feb 5 12:23:02 2025 -0800 rm ArrayTable compiles Signed-off-by: James Cherry commit 1a65f9da1814b8664062fe7ecf684acc42ee6933 Author: James Cherry Date: Tue Feb 4 16:26:34 2025 -0800 keep prev tag arrays until search is finsihed Signed-off-by: James Cherry Signed-off-by: James Cherry --- README.md | 11 +- dcalc/GraphDelayCalc.cc | 14 +- graph/Graph.cc | 515 ++++++++++++++++--------------------- graph/Graph.i | 6 - include/sta/ArrayTable.hh | 275 -------------------- include/sta/Graph.hh | 204 +++++++-------- include/sta/GraphClass.hh | 1 - include/sta/ObjectTable.hh | 1 - include/sta/Search.hh | 5 +- sdc/Sdc.tcl | 1 - search/Search.cc | 43 +++- search/Sta.cc | 2 +- 12 files changed, 373 insertions(+), 705 deletions(-) delete mode 100644 include/sta/ArrayTable.hh diff --git a/README.md b/README.md index 8cc16e05..e098e5bf 100644 --- a/README.md +++ b/README.md @@ -63,8 +63,7 @@ compiled locally. Derivative works are supported as long as they adhere to the GPL license requirements. However, OpenSTA is not supported by a public community of developers as many other open source projects are. The copyright and develpment are exclusive to -Parallax Software. Contributors must signing the Contributor License -Agreement (doc/CLA.txt) when submitting pull requests. +Parallax Software. Removing copyright and license notices from OpenSTA sources (or any other open source project for that matter) is illegal. This should be @@ -257,8 +256,12 @@ Contributions that claim 4% performance improvements in OpenROAD flow scripts will largely be ignored. Small performance improvements simply do not justify the time requied to audit and verify the changes. -Contributions that add dependencies on external libraries like boost -will not be accepted. +Contributions that add dependencies on external libraries like boost, +abseil and Intel TBB will not be accepted. + +As the author of OpenSTA I vastly prefer writing code to reviewing +code. I don't have the patience to go round after round to correct +code formatting that is not consistent with the rest of the code. ## Authors diff --git a/dcalc/GraphDelayCalc.cc b/dcalc/GraphDelayCalc.cc index a1f17f80..cdf1a997 100644 --- a/dcalc/GraphDelayCalc.cc +++ b/dcalc/GraphDelayCalc.cc @@ -621,10 +621,15 @@ GraphDelayCalc::findVertexDelay(Vertex *vertex, DrvrLoadSlews GraphDelayCalc::loadSlews(LoadPinIndexMap &load_pin_index_map) { + size_t slew_count = graph_->slewCount(); DrvrLoadSlews load_slews(load_pin_index_map.size()); for (auto const [pin, index] : load_pin_index_map) { Vertex *load_vertex = graph_->pinLoadVertex(pin); - load_slews[index] = graph_->slews(load_vertex); + SlewSeq &slews = load_slews[index];; + slews.resize(slew_count); + Slew *vertex_slews = load_vertex->slews(); + for (size_t i = 0; i < slew_count; i++) + slews[i] = vertex_slews[i]; } return load_slews; } @@ -633,11 +638,12 @@ bool GraphDelayCalc::loadSlewsChanged(DrvrLoadSlews &load_slews_prev, LoadPinIndexMap &load_pin_index_map) { + size_t slew_count = graph_->slewCount(); for (auto const [pin, index] : load_pin_index_map) { Vertex *load_vertex = graph_->pinLoadVertex(pin); - const SlewSeq slews = graph_->slews(load_vertex); - const SlewSeq &slews_prev = load_slews_prev[index]; - for (size_t i = 0; i < slews.size(); i++) { + SlewSeq &slews_prev = load_slews_prev[index];; + const Slew *slews = load_vertex->slews(); + for (size_t i = 0; i < slew_count; i++) { if (!delayEqual(slews[i], slews_prev[i])) return true; } diff --git a/graph/Graph.cc b/graph/Graph.cc index 1b6f3249..091c1a58 100644 --- a/graph/Graph.cc +++ b/graph/Graph.cc @@ -46,14 +46,11 @@ namespace sta { Graph::Graph(StaState *sta, int slew_rf_count, - bool have_arc_delays, DcalcAPIndex ap_count) : StaState(sta), vertices_(nullptr), edges_(nullptr), - arc_count_(0), slew_rf_count_(slew_rf_count), - have_arc_delays_(have_arc_delays), ap_count_(ap_count), period_check_annotations_(nullptr), reg_clk_vertices_(new VertexSet(graph_)) @@ -64,11 +61,11 @@ Graph::Graph(StaState *sta, Graph::~Graph() { - delete vertices_; + edges_->clear(); delete edges_; + vertices_->clear(); + delete vertices_; delete reg_clk_vertices_; - deleteSlewTables(); - deleteArcDelayTables(); removePeriodCheckAnnotations(); } @@ -90,8 +87,6 @@ Graph::makeVerticesAndEdges() { vertices_ = new VertexTable; edges_ = new EdgeTable; - makeSlewTables(ap_count_); - makeArcDelayTables(ap_count_); LeafInstanceIterator *leaf_iter = network_->leafInstanceIterator(); while (leaf_iter->hasNext()) { @@ -440,7 +435,7 @@ Graph::makeVertex(Pin *pin, { Vertex *vertex = vertices_->make(); vertex->init(pin, is_bidirect_drvr, is_reg_clk); - makeVertexSlews(vertex); + initSlews(vertex); if (is_reg_clk) reg_clk_vertices_->insert(vertex); return vertex; @@ -491,7 +486,7 @@ Graph::deleteVertex(Vertex *vertex) Edge *edge = Graph::edge(edge_id); next_id = edge->vertex_in_link_; deleteOutEdge(edge->from(this), edge); - arc_count_ -= edge->timingArcSet()->arcCount(); + edge->clear(); edges_->destroy(edge); } // Delete edges from vertex. @@ -499,9 +494,10 @@ Graph::deleteVertex(Vertex *vertex) Edge *edge = Graph::edge(edge_id); next_id = edge->vertex_out_next_; deleteInEdge(edge->to(this), edge); - arc_count_ -= edge->timingArcSet()->arcCount(); + edge->clear(); edges_->destroy(edge); } + vertex->clear(); vertices_->destroy(vertex); } @@ -577,155 +573,90 @@ Graph::gateEdgeArc(const Pin *in_pin, Arrival * Graph::makeArrivals(Vertex *vertex, - uint32_t count) + uint32_t count) { - if (vertex->arrivals() != arrival_null) - debugPrint(debug_, "graph", 1, "arrival leak"); - Arrival *arrivals; - ArrivalId id; - { - LockGuard lock(arrivals_lock_); - arrivals_.make(count, arrivals, id); - } - vertex->setArrivals(id); + Arrival *arrivals = new Arrival[count]; + vertex->setArrivals(arrivals); return arrivals; } Arrival * -Graph::arrivals(Vertex *vertex) +Graph::arrivals(const Vertex *vertex) const { - return arrivals_.pointer(vertex->arrivals()); + return vertex->arrivals(); } void -Graph::deleteArrivals(Vertex *vertex, - uint32_t count) +Graph::deleteArrivals(Vertex *vertex) { - { - LockGuard lock(arrivals_lock_); - arrivals_.destroy(vertex->arrivals(), count); - } - vertex->setArrivals(arrival_null); + vertex->setArrivals(nullptr); +} + +Required * +Graph::requireds(const Vertex *vertex) const +{ + return vertex->requireds(); } Required * Graph::makeRequireds(Vertex *vertex, uint32_t count) { - if (vertex->requireds() != arrival_null) - debugPrint(debug_, "graph", 1, "required leak"); - Required *requireds; - ArrivalId id; - { - LockGuard lock(requireds_lock_); - requireds_.make(count, requireds, id); - } - vertex->setRequireds(id); + Required *requireds = new Arrival[count]; + vertex->setRequireds(requireds); return requireds; } -Required * -Graph::requireds(Vertex *vertex) +void +Graph::deleteRequireds(Vertex *vertex) { - return requireds_.pointer(vertex->requireds()); + vertex->setRequireds(nullptr); } -void -Graph::deleteRequireds(Vertex *vertex, - uint32_t count) +PathVertexRep * +Graph::prevPaths(const Vertex *vertex) const { - { - LockGuard lock(requireds_lock_); - requireds_.destroy(vertex->requireds(), count); - } - vertex->setRequireds(arrival_null); + return vertex->prevPaths(); } PathVertexRep * Graph::makePrevPaths(Vertex *vertex, - uint32_t count) + uint32_t count) { - PathVertexRep *prev_paths; - PrevPathId id; - { - LockGuard lock(prev_paths_lock_); - prev_paths_.make(count, prev_paths, id); - } - vertex->setPrevPaths(id); + PathVertexRep *prev_paths = new PathVertexRep[count]; + vertex->setPrevPaths(prev_paths); return prev_paths; } -PathVertexRep * -Graph::prevPaths(Vertex *vertex) const +void +Graph::deletePrevPaths(Vertex *vertex) { - return prev_paths_.pointer(vertex->prevPaths()); + vertex->setPrevPaths(nullptr); } void -Graph::deletePrevPaths(Vertex *vertex, - uint32_t count) +Graph::deletePaths(Vertex *vertex) { - if (vertex->prevPaths() != object_id_null) { - { - LockGuard lock(prev_paths_lock_); - prev_paths_.destroy(vertex->prevPaths(), count); - } - vertex->setPrevPaths(object_id_null); - } -} - -void -Graph::deletePaths() -{ - arrivals_.clear(); - requireds_.clear(); - prev_paths_.clear(); - VertexIterator vertex_iter(graph_); - while (vertex_iter.hasNext()) { - Vertex *vertex = vertex_iter.next(); - vertex->setArrivals(arrival_null); - vertex->setRequireds(arrival_null); - vertex->setPrevPaths(object_id_null); - vertex->tag_group_index_ = tag_group_index_max; - vertex->crpr_path_pruning_disabled_ = false; - } -} - -void -Graph::deletePaths(Vertex *vertex, - uint32_t count) -{ - if (vertex->arrivals() != arrival_null) { - LockGuard lock(arrivals_lock_); - arrivals_.destroy(vertex->arrivals(), count); - vertex->setArrivals(arrival_null); - vertex->tag_group_index_ = tag_group_index_max; - vertex->crpr_path_pruning_disabled_ = false; - } - if (vertex->requireds() != arrival_null) { - requireds_.destroy(vertex->requireds(), count); - vertex->setRequireds(arrival_null); - } - - if (vertex->prevPaths() != object_id_null) { - prev_paths_.destroy(vertex->prevPaths(), count); - vertex->setPrevPaths(object_id_null); - } + deleteArrivals(vertex); + deleteRequireds(vertex); + deletePrevPaths(vertex); + vertex->tag_group_index_ = tag_group_index_max; + vertex->crpr_path_pruning_disabled_ = false; } //////////////////////////////////////////////////////////////// const Slew & Graph::slew(const Vertex *vertex, - const RiseFall *rf, - DcalcAPIndex ap_index) + const RiseFall *rf, + DcalcAPIndex ap_index) { if (slew_rf_count_) { - int table_index = - (slew_rf_count_ == 1) ? ap_index : ap_index*slew_rf_count_+rf->index(); - DelayTable *table = slew_tables_[table_index]; - VertexId vertex_id = id(vertex); - return table->ref(vertex_id); + const Slew *slews = vertex->slews(); + size_t slew_index = (slew_rf_count_ == 1) + ? ap_index + : ap_index*slew_rf_count_+rf->index(); + return slews[slew_index]; } else { static Slew slew(0.0); @@ -735,34 +666,24 @@ Graph::slew(const Vertex *vertex, void Graph::setSlew(Vertex *vertex, - const RiseFall *rf, - DcalcAPIndex ap_index, - const Slew &slew) + const RiseFall *rf, + DcalcAPIndex ap_index, + const Slew &slew) { if (slew_rf_count_) { - int table_index = - (slew_rf_count_ == 1) ? ap_index : ap_index*slew_rf_count_+rf->index(); - DelayTable *table = slew_tables_[table_index]; - VertexId vertex_id = id(vertex); - Slew &vertex_slew = table->ref(vertex_id); - vertex_slew = slew; + Slew *slews = vertex->slews(); + if (slews == nullptr) { + int slew_count = slew_rf_count_ * ap_count_; + slews = new Slew[slew_count]; + vertex->setSlews(slews); + } + size_t slew_index = (slew_rf_count_ == 1) + ? ap_index + : ap_index*slew_rf_count_+rf->index(); + slews[slew_index] = slew; } } -SlewSeq -Graph::slews(Vertex *vertex) -{ - SlewSeq slews; - VertexId vertex_id = id(vertex); - DcalcAPIndex rf_ap_count = slew_rf_count_ * ap_count_; - for (DcalcAPIndex i = 0; i < rf_ap_count; i++) { - DelayTable *table = slew_tables_[i]; - Slew &slew = table->ref(vertex_id); - slews.push_back(slew); - } - return slews; -} - //////////////////////////////////////////////////////////////// Edge * @@ -784,8 +705,6 @@ Graph::makeEdge(Vertex *from, { Edge *edge = edges_->make(); edge->init(id(from), id(to), arc_set); - makeEdgeArcDelays(edge); - arc_count_ += arc_set->arcCount(); // Add out edge to from vertex. EdgeId next = from->out_edges_; edge->vertex_out_next_ = next; @@ -799,6 +718,7 @@ Graph::makeEdge(Vertex *from, edge->vertex_in_link_ = to->in_edges_; to->in_edges_ = edge_id; + initArcDelays(edge); return edge; } @@ -809,63 +729,18 @@ Graph::deleteEdge(Edge *edge) Vertex *to = edge->to(this); deleteOutEdge(from, edge); deleteInEdge(to, edge); - arc_count_ -= edge->timingArcSet()->arcCount(); + edge->clear(); edges_->destroy(edge); } -void -Graph::makeArcDelayTables(DcalcAPIndex ap_count) -{ - if (have_arc_delays_) { - arc_delays_.resize(ap_count); - for (DcalcAPIndex i = 0; i < ap_count; i++) - arc_delays_[i] = new DelayTable(); - } -} - -void -Graph::deleteArcDelayTables() -{ - arc_delays_.deleteContentsClear(); -} - -void -Graph::makeEdgeArcDelays(Edge *edge) -{ - if (have_arc_delays_) { - int arc_count = edge->timingArcSet()->arcCount(); - ArcId arc_id = 0; - for (DcalcAPIndex i = 0; i < ap_count_; i++) { - DelayTable *table = arc_delays_[i]; - ArcDelay *arc_delays; - table->make(arc_count, arc_delays, arc_id); - for (int j = 0; j < arc_count; j++) - arc_delays[j] = 0.0; - } - edge->setArcDelays(arc_id); - // Make sure there is room for delay_annotated flags. - size_t max_annot_index = (arc_id + arc_count) * ap_count_; - if (max_annot_index >= arc_delay_annotated_.size()) { - size_t size = max_annot_index * 1.2; - arc_delay_annotated_.resize(size); - } - removeDelayAnnotated(edge); - } -} - ArcDelay Graph::arcDelay(const Edge *edge, const TimingArc *arc, DcalcAPIndex ap_index) const { - if (have_arc_delays_) { - DelayTable *table = arc_delays_[ap_index]; - ArcDelay *arc_delays = table->pointer(edge->arcDelays()); - ArcDelay &arc_delay = arc_delays[arc->index()]; - return arc_delay; - } - else - return delay_zero; + ArcDelay *delays = edge->arcDelays(); + size_t index = arc->index() * ap_count_ + ap_index; + return delays[index]; } void @@ -874,11 +749,9 @@ Graph::setArcDelay(Edge *edge, DcalcAPIndex ap_index, ArcDelay delay) { - if (have_arc_delays_) { - DelayTable *table = arc_delays_[ap_index]; - ArcDelay *arc_delays = table->pointer(edge->arcDelays()); - arc_delays[arc->index()] = delay; - } + ArcDelay *arc_delays = edge->arcDelays(); + size_t index = arc->index() * ap_count_ + ap_index; + arc_delays[index] = delay; } const ArcDelay & @@ -886,13 +759,9 @@ Graph::wireArcDelay(const Edge *edge, const RiseFall *rf, DcalcAPIndex ap_index) { - if (have_arc_delays_) { - DelayTable *table = arc_delays_[ap_index]; - ArcDelay *arc_delays = table->pointer(edge->arcDelays()); - return arc_delays[rf->index()]; - } - else - return delay_zero; + ArcDelay *delays = edge->arcDelays(); + size_t index = rf->index() * ap_count_ + ap_index; + return delays[index]; } void @@ -901,26 +770,19 @@ Graph::setWireArcDelay(Edge *edge, DcalcAPIndex ap_index, const ArcDelay &delay) { - if (have_arc_delays_) { - DelayTable *table = arc_delays_[ap_index]; - ArcDelay *arc_delays = table->pointer(edge->arcDelays()); - arc_delays[rf->index()] = delay; - } + ArcDelay *delays = edge->arcDelays(); + size_t index = rf->index() * ap_count_ + ap_index; + delays[index] = delay; } +//////////////////////////////////////////////////////////////// + bool Graph::arcDelayAnnotated(const Edge *edge, const TimingArc *arc, DcalcAPIndex ap_index) const { - if (!arc_delay_annotated_.empty()) { - size_t index = (edge->arcDelays() + arc->index()) * ap_count_ + ap_index; - if (index >= arc_delay_annotated_.size()) - report_->critical(1080, "arc_delay_annotated array bounds exceeded"); - return arc_delay_annotated_[index]; - } - else - return false; + return edge->arcDelayAnnotated(arc, ap_index, ap_count_); } void @@ -929,22 +791,17 @@ Graph::setArcDelayAnnotated(Edge *edge, DcalcAPIndex ap_index, bool annotated) { - size_t index = (edge->arcDelays() + arc->index()) * ap_count_ + ap_index; - if (index >= arc_delay_annotated_.size()) - report_->critical(1081, "arc_delay_annotated array bounds exceeded"); - arc_delay_annotated_[index] = annotated; + return edge->setArcDelayAnnotated(arc, ap_index, ap_count_, annotated); } bool -Graph::wireDelayAnnotated(Edge *edge, +Graph::wireDelayAnnotated(const Edge *edge, const RiseFall *rf, DcalcAPIndex ap_index) const { - size_t index = (edge->arcDelays() + TimingArcSet::wireArcIndex(rf)) * ap_count_ - + ap_index; - if (index >= arc_delay_annotated_.size()) - report_->critical(1082, "arc_delay_annotated array bounds exceeded"); - return arc_delay_annotated_[index]; + int arc_index = TimingArcSet::wireArcIndex(rf); + TimingArc *arc = TimingArcSet::wireTimingArcSet()->findTimingArc(arc_index); + return edge->arcDelayAnnotated(arc, ap_index, ap_count_); } void @@ -953,13 +810,19 @@ Graph::setWireDelayAnnotated(Edge *edge, DcalcAPIndex ap_index, bool annotated) { - size_t index = (edge->arcDelays() + TimingArcSet::wireArcIndex(rf)) * ap_count_ - + ap_index; - if (index >= arc_delay_annotated_.size()) - report_->critical(1083, "arc_delay_annotated array bounds exceeded"); - arc_delay_annotated_[index] = annotated; + int arc_index = TimingArcSet::wireArcIndex(rf); + TimingArc *arc = TimingArcSet::wireTimingArcSet()->findTimingArc(arc_index); + return edge->setArcDelayAnnotated(arc, ap_index, ap_count_, annotated); } +void +Graph::removeDelayAnnotated(Edge *edge) +{ + edge->removeDelayAnnotated(); +} + +//////////////////////////////////////////////////////////////// + // This only gets called if the analysis type changes from single // to bc_wc/ocv or visa versa. void @@ -967,42 +830,53 @@ Graph::setDelayCount(DcalcAPIndex ap_count) { if (ap_count != ap_count_) { // Discard any existing delays. - deleteSlewTables(); - deleteArcDelayTables(); removePeriodCheckAnnotations(); - makeSlewTables(ap_count); - makeArcDelayTables(ap_count); ap_count_ = ap_count; - removeDelays(); + initSlews(); } } void -Graph::removeDelays() +Graph::initSlews() { - VertexIterator vertex_iter(this); + VertexIterator vertex_iter(graph_); while (vertex_iter.hasNext()) { Vertex *vertex = vertex_iter.next(); - makeVertexSlews(vertex); - VertexOutEdgeIterator edge_iter(vertex, this); + initSlews(vertex); + + VertexOutEdgeIterator edge_iter(vertex, graph_); while (edge_iter.hasNext()) { Edge *edge = edge_iter.next(); - makeEdgeArcDelays(edge); - removeDelayAnnotated(edge); + initArcDelays(edge); } } } void -Graph::removeDelayAnnotated(Edge *edge) +Graph::initSlews(Vertex *vertex) { - edge->setDelayAnnotationIsIncremental(false); - TimingArcSet *arc_set = edge->timingArcSet(); - for (TimingArc *arc : arc_set->arcs()) { - for (DcalcAPIndex ap_index = 0; ap_index < ap_count_; ap_index++) { - setArcDelayAnnotated(edge, arc, ap_index, false); - } - } + size_t slew_count = slewCount(); + Slew *slews = new Slew[slew_count]; + vertex->setSlews(slews); + for (size_t i = 0; i < slew_count; i++) + slews[i] = 0.0; +} + +size_t +Graph::slewCount() +{ + return slew_rf_count_ * ap_count_; +} + +void +Graph::initArcDelays(Edge *edge) +{ + size_t arc_count = edge->timingArcSet()->arcCount(); + size_t delay_count = arc_count * ap_count_; + ArcDelay *arc_delays = new ArcDelay[delay_count]; + edge->setArcDelays(arc_delays); + for (size_t i = 0; i < delay_count; i++) + arc_delays[i] = 0.0; } bool @@ -1018,35 +892,6 @@ Graph::delayAnnotated(Edge *edge) return true; } -void -Graph::makeSlewTables(DcalcAPIndex ap_count) -{ - DcalcAPIndex tr_ap_count = slew_rf_count_ * ap_count; - slew_tables_.resize(tr_ap_count); - for (DcalcAPIndex i = 0; i < tr_ap_count; i++) { - DelayTable *table = new DelayTable; - slew_tables_[i] = table; - } -} - -void -Graph::deleteSlewTables() -{ - slew_tables_.deleteContentsClear(); -} - -void -Graph::makeVertexSlews(Vertex *vertex) -{ - DcalcAPIndex tr_ap_count = slew_rf_count_ * ap_count_; - for (DcalcAPIndex i = 0; i < tr_ap_count; i++) { - DelayTable *table = slew_tables_[i]; - // Slews are 1:1 with vertices and use the same object id. - Slew *slew = table->ensureId(vertices_->objectId(vertex)); - *slew = 0.0; - } -} - //////////////////////////////////////////////////////////////// void @@ -1161,9 +1006,10 @@ Vertex::init(Pin *pin, is_bidirect_drvr_ = is_bidirect_drvr; in_edges_ = edge_id_null; out_edges_ = edge_id_null; - arrivals_ = arrival_null; - requireds_ = arrival_null; - prev_paths_ = prev_path_null; + slews_ = nullptr; + arrivals_ = nullptr; + requireds_ = nullptr; + prev_paths_ = nullptr; tag_group_index_ = tag_group_index_max; slew_annotated_ = false; sim_value_ = unsigned(LogicValue::unknown); @@ -1180,6 +1026,24 @@ Vertex::init(Pin *pin, requireds_pruned_ = false; } +Vertex::~Vertex() +{ + clear(); +} + +void +Vertex::clear() +{ + delete [] slews_; + slews_ = nullptr; + delete [] arrivals_; + arrivals_ = nullptr; + delete [] requireds_; + requireds_ = nullptr; + delete [] prev_paths_; + prev_paths_ = nullptr; +} + void Vertex::setObjectIdx(ObjectIdx idx) { @@ -1228,6 +1092,13 @@ Vertex::setColor(LevelColor color) color_ = unsigned(color); } +void +Vertex::setSlews(Slew *slews) +{ + delete [] slews_; + slews_ = slews; +} + bool Vertex::slewAnnotated(const RiseFall *rf, const MinMax *min_max) const @@ -1289,20 +1160,23 @@ Vertex::setTagGroupIndex(TagGroupIndex tag_index) } void -Vertex::setArrivals(ArrivalId id) +Vertex::setArrivals(Arrival *arrivals) { - arrivals_ = id; + delete [] arrivals_; + arrivals_ = arrivals; } void -Vertex::setRequireds(ArrivalId id) +Vertex::setRequireds(Required *requireds) { - requireds_ = id; + delete [] requireds_; + requireds_ = requireds; } void -Vertex::setPrevPaths(PrevPathId prev_paths) +Vertex::setPrevPaths(PathVertexRep *prev_paths) { + delete [] prev_paths_; prev_paths_ = prev_paths; } @@ -1410,13 +1284,15 @@ Edge::init(VertexId from, from_ = from; to_ = to; arc_set_ = arc_set; - arc_delays_ = 0; - vertex_in_link_ = edge_id_null; vertex_out_next_ = edge_id_null; vertex_out_prev_ = edge_id_null; is_bidirect_inst_path_ = false; is_bidirect_net_path_ = false; + + arc_delays_ = nullptr; + arc_delay_annotated_is_bits_ = true; + arc_delay_annotated_.bits_ = 0; delay_annotation_is_incremental_ = false; sim_timing_sense_ = unsigned(TimingSense::unknown); is_disabled_constraint_ = false; @@ -1424,6 +1300,22 @@ Edge::init(VertexId from, is_disabled_loop_ = false; } +Edge::~Edge() +{ + clear(); +} + +void +Edge::clear() +{ + delete [] arc_delays_; + arc_delays_ = nullptr; + if (!arc_delay_annotated_is_bits_) + delete arc_delay_annotated_.seq_; + arc_delay_annotated_is_bits_ = true; + arc_delay_annotated_.seq_ = nullptr; +} + void Edge::setObjectIdx(ObjectIdx idx) { @@ -1437,15 +1329,56 @@ Edge::setTimingArcSet(TimingArcSet *set) } void -Edge::setArcDelays(ArcId arc_delays) +Edge::setArcDelays(ArcDelay *arc_delays) { + delete [] arc_delays_; arc_delays_ = arc_delays; } bool -Edge::delayAnnotationIsIncremental() const +Edge::arcDelayAnnotated(const TimingArc *arc, + DcalcAPIndex ap_index, + DcalcAPIndex ap_count) const { - return delay_annotation_is_incremental_; + size_t index = arc->index() * ap_count + ap_index; + if (arc_delay_annotated_is_bits_) + return arc_delay_annotated_.bits_ & (1 << index); + else + return (*arc_delay_annotated_.seq_)[index]; +} + +void +Edge::setArcDelayAnnotated(const TimingArc *arc, + DcalcAPIndex ap_index, + DcalcAPIndex ap_count, + bool annotated) +{ + size_t index = arc->index() * ap_count + ap_index; + if (index > sizeof(intptr_t) * 8 + && arc_delay_annotated_is_bits_) { + arc_delay_annotated_is_bits_ = false; + arc_delay_annotated_.seq_ = new vector(ap_count * RiseFall::index_count * 2); + } + if (arc_delay_annotated_is_bits_) { + if (annotated) + arc_delay_annotated_.bits_ |= (1 << index); + else + arc_delay_annotated_.bits_ &= ~(1 << index); + } + else + (*arc_delay_annotated_.seq_)[index] = annotated; +} + +void +Edge::removeDelayAnnotated() +{ + delay_annotation_is_incremental_ = false; + if (arc_delay_annotated_is_bits_) + arc_delay_annotated_.bits_ = 0; + else { + delete arc_delay_annotated_.seq_; + arc_delay_annotated_.seq_ = nullptr; + } } void diff --git a/graph/Graph.i b/graph/Graph.i index e7c7c352..0db3793e 100644 --- a/graph/Graph.i +++ b/graph/Graph.i @@ -83,12 +83,6 @@ private: %inline %{ -int -graph_arc_count() -{ - return Sta::sta()->ensureGraph()->arcCount(); -} - VertexIterator * vertex_iterator() { diff --git a/include/sta/ArrayTable.hh b/include/sta/ArrayTable.hh deleted file mode 100644 index 33a6c3da..00000000 --- a/include/sta/ArrayTable.hh +++ /dev/null @@ -1,275 +0,0 @@ -// OpenSTA, Static Timing Analyzer -// Copyright (c) 2025, Parallax Software, Inc. -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program. If not, see . -// -// The origin of this software must not be misrepresented; you must not -// claim that you wrote the original software. -// -// Altered source versions must be plainly marked as such, and must not be -// misrepresented as being the original software. -// -// This notice may not be removed or altered from any source distribution. - -#pragma once - -#include // memcpy -#include -#include - -#include "ObjectId.hh" -#include "Error.hh" - -namespace sta { - -template -class ArrayBlock; - -// Array tables allocate arrays of objects in blocks and use 32 bit IDs to -// reference the array. Paging performance is improved by allocating -// blocks instead of individual arrays, and object sizes are reduced -// by using 32 bit references instead of 64 bit pointers. -// They are similar to ObjectTables but do not support delete/destroy or -// reclaiming deleted arrays. - -template -class ArrayTable -{ -public: - ArrayTable(); - ~ArrayTable(); - void make(uint32_t count, - TYPE *&array, - ObjectId &id); - void destroy(ObjectId id, - uint32_t count); - // Grow as necessary and return pointer for id. - TYPE *ensureId(ObjectId id); - TYPE *pointer(ObjectId id) const; - TYPE &ref(ObjectId id) const; - size_t size() const { return size_; } - void clear(); - - static constexpr int idx_bits = 7; - static constexpr int block_size = (1 << idx_bits); - static constexpr int block_id_max = 1 << (object_id_bits - idx_bits); - -private: - ArrayBlock *makeBlock(uint32_t size); - void pushBlock(ArrayBlock *block); - void deleteBlocks(); - - size_t size_; - // Block index of free block (blocks_[size - 1]). - BlockIdx free_block_idx_; - // Index of next free object in free_block_idx_. - ObjectIdx free_idx_; - // Don't use std::vector so growing blocks_ can be thread safe. - size_t blocks_size_; - size_t blocks_capacity_; - std::atomic**> blocks_; - // Linked list of free arrays indexed by array size. - std::vector free_list_; - static constexpr ObjectId idx_mask_ = block_size - 1; -}; - -template -ArrayTable::ArrayTable() : - size_(0), - free_block_idx_(block_idx_null), - free_idx_(object_idx_null), - blocks_size_(0), - blocks_capacity_(1024), - blocks_(new ArrayBlock*[blocks_capacity_]) -{ -} - -template -ArrayTable::~ArrayTable() -{ - deleteBlocks(); - delete [] blocks_; -} - -template -void -ArrayTable::deleteBlocks() -{ - for (size_t i = 0; i < blocks_size_; i++) - delete blocks_[i]; -} - -template -void -ArrayTable::make(uint32_t count, - TYPE *&array, - ObjectId &id) -{ - // Check the free list for a previously destroyed array with the right size. - if (count < free_list_.size() - && free_list_[count] != object_id_null) { - id = free_list_[count]; - array = pointer(id); - - ObjectId *head = reinterpret_cast(array); - free_list_[count] = *head; - } - else { - ArrayBlock *block = blocks_size_ ? blocks_[free_block_idx_] : nullptr; - if ((free_idx_ == object_idx_null - && free_block_idx_ == block_idx_null) - || free_idx_ + count >= block->size()) { - uint32_t size = block_size; - if (blocks_size_ == 0 - // First block starts at idx 1. - && count > block_size - 1) - size = count + 1; - else if (count > block_size) - size = count; - block = makeBlock(size); - } - // makeId(free_block_idx_, idx_bits) - id = (free_block_idx_ << idx_bits) + free_idx_; - array = block->pointer(free_idx_); - free_idx_ += count; - } - size_ += count; -} - -template -ArrayBlock * -ArrayTable::makeBlock(uint32_t size) -{ - BlockIdx block_idx = blocks_size_; - ArrayBlock *block = new ArrayBlock(size); - pushBlock(block); - free_block_idx_ = block_idx; - // ObjectId zero is reserved for object_id_null. - free_idx_ = (block_idx > 0) ? 0 : 1; - return block; -} - -template -void -ArrayTable::pushBlock(ArrayBlock *block) -{ - blocks_[blocks_size_++] = block; - if (blocks_size_ >= block_id_max) - criticalError(223, "max array table block count exceeded."); - if (blocks_size_ == blocks_capacity_) { - size_t new_capacity = blocks_capacity_ * 1.5; - ArrayBlock** new_blocks = new ArrayBlock*[new_capacity]; - memcpy(new_blocks, blocks_, blocks_capacity_ * sizeof(ArrayBlock*)); - blocks_ = new_blocks; - blocks_capacity_ = new_capacity; - } -} - -template -void -ArrayTable::destroy(ObjectId id, - uint32_t count) -{ - if (count >= free_list_.size()) - free_list_.resize(count + 1); - TYPE *array = pointer(id); - // Prepend id to the free list. - ObjectId *head = reinterpret_cast(array); - *head = free_list_[count]; - free_list_[count] = id; - size_ -= count; -} - -template -TYPE * -ArrayTable::pointer(ObjectId id) const -{ - if (id == object_id_null) - return nullptr; - else { - BlockIdx blk_idx = id >> idx_bits; - ObjectIdx obj_idx = id & idx_mask_; - return blocks_[blk_idx]->pointer(obj_idx); - } -} - -template -TYPE * -ArrayTable::ensureId(ObjectId id) -{ - BlockIdx blk_idx = id >> idx_bits; - ObjectIdx obj_idx = id & idx_mask_; - // Make enough blocks for blk_idx to be valid. - for (BlockIdx i = blocks_size_; i <= blk_idx; i++) { - ArrayBlock *block = new ArrayBlock(block_size); - pushBlock(block); - } - return blocks_[blk_idx]->pointer(obj_idx); -} - -template -TYPE & -ArrayTable::ref(ObjectId id) const -{ - if (id == object_id_null) - criticalError(222, "null ObjectId reference is undefined."); - - BlockIdx blk_idx = id >> idx_bits; - ObjectIdx obj_idx = id & idx_mask_; - return blocks_[blk_idx]->ref(obj_idx); -} - -template -void -ArrayTable::clear() -{ - deleteBlocks(); - blocks_size_ = 0; - size_ = 0; - free_block_idx_ = block_idx_null; - free_idx_ = object_idx_null; - free_list_.clear(); -} - -//////////////////////////////////////////////////////////////// - -template -class ArrayBlock -{ -public: - ArrayBlock(uint32_t size); - ~ArrayBlock(); - uint32_t size() const { return size_; } - TYPE &ref(ObjectIdx idx) { return objects_[idx]; } - TYPE *pointer(ObjectIdx idx) { return &objects_[idx]; } - -private: - uint32_t size_; - TYPE *objects_; -}; - -template -ArrayBlock::ArrayBlock(uint32_t size) : - size_(size), - objects_(new TYPE[size]) -{ -} - -template -ArrayBlock::~ArrayBlock() -{ - delete [] objects_; -} - -} // Namespace diff --git a/include/sta/Graph.hh b/include/sta/Graph.hh index 8cdd7131..d718e725 100644 --- a/include/sta/Graph.hh +++ b/include/sta/Graph.hh @@ -31,7 +31,6 @@ #include "Map.hh" #include "Vector.hh" #include "ObjectTable.hh" -#include "ArrayTable.hh" #include "LibertyClass.hh" #include "NetworkClass.hh" #include "Delay.hh" @@ -47,25 +46,16 @@ class Sdc; enum class LevelColor { white, gray, black }; -typedef ArrayTable DelayTable; typedef ObjectTable VertexTable; typedef ObjectTable EdgeTable; -typedef ArrayTable ArrivalsTable; -typedef ArrayTable RequiredsTable; -typedef ArrayTable PrevPathsTable; typedef Map PinVertexMap; typedef Iterator VertexEdgeIterator; typedef Map PeriodCheckAnnotations; -typedef Vector DelayTableSeq; typedef ObjectId EdgeId; -typedef ObjectId ArrivalId; -typedef ObjectId PrevPathId; static constexpr EdgeId edge_id_null = object_id_null; static constexpr ObjectIdx edge_idx_null = object_id_null; static constexpr ObjectIdx vertex_idx_null = object_id_null; -static constexpr ObjectIdx arrival_null = object_id_null; -static constexpr ObjectIdx prev_path_null = object_id_null; // The graph acts as a BUILDER for the graph vertices and edges. class Graph : public StaState @@ -78,17 +68,17 @@ public: // ap_count is the dcalc analysis point count. Graph(StaState *sta, int slew_rf_count, - bool have_arc_delays, DcalcAPIndex ap_count); void makeGraph(); - virtual ~Graph(); + ~Graph(); // Number of arc delays and slews from sdf or delay calculation. - virtual void setDelayCount(DcalcAPIndex ap_count); + void setDelayCount(DcalcAPIndex ap_count); + size_t slewCount(); // Vertex functions. // Bidirect pins have two vertices. - virtual Vertex *vertex(VertexId vertex_id) const; + Vertex *vertex(VertexId vertex_id) const; VertexId id(const Vertex *vertex) const; void makePinVertices(Pin *pin); void makePinVertices(Pin *pin, @@ -103,56 +93,49 @@ public: Vertex *pinDrvrVertex(const Pin *pin) const; // Load vertex for bidirects. Vertex *pinLoadVertex(const Pin *pin) const; - virtual void deleteVertex(Vertex *vertex); + void deleteVertex(Vertex *vertex); bool hasFaninOne(Vertex *vertex) const; VertexId vertexCount() { return vertices_->size(); } Arrival *makeArrivals(Vertex *vertex, uint32_t count); - Arrival *arrivals(Vertex *vertex); - void deleteArrivals(Vertex *vertex, - uint32_t count); + Arrival *arrivals(const Vertex *vertex) const; + void deleteArrivals(Vertex *vertex); Required *makeRequireds(Vertex *vertex, uint32_t count); - Required *requireds(Vertex *vertex); - void deleteRequireds(Vertex *vertex, - uint32_t count); + Required *requireds(const Vertex *vertex) const; + void deleteRequireds(Vertex *vertex); PathVertexRep *makePrevPaths(Vertex *vertex, uint32_t count); - PathVertexRep *prevPaths(Vertex *vertex) const; - void deletePrevPaths(Vertex *vertex, - uint32_t count); - // Private to Search::deletePaths(). - void deletePaths(); + PathVertexRep *prevPaths(const Vertex *vertex) const; + void deletePrevPaths(Vertex *vertex); // Private to Search::deletePaths(Vertex). - void deletePaths(Vertex *vertex, - uint32_t count); + void deletePaths(Vertex *vertex); // Reported slew are the same as those in the liberty tables. // reported_slews = measured_slews / slew_derate_from_library // Measured slews are between slew_lower_threshold and slew_upper_threshold. - virtual const Slew &slew(const Vertex *vertex, - const RiseFall *rf, - DcalcAPIndex ap_index); - virtual void setSlew(Vertex *vertex, - const RiseFall *rf, - DcalcAPIndex ap_index, - const Slew &slew); - SlewSeq slews(Vertex *vertex); + const Slew &slew(const Vertex *vertex, + const RiseFall *rf, + DcalcAPIndex ap_index); + void setSlew(Vertex *vertex, + const RiseFall *rf, + DcalcAPIndex ap_index, + const Slew &slew); // Edge functions. - virtual Edge *edge(EdgeId edge_index) const; + Edge *edge(EdgeId edge_index) const; EdgeId id(const Edge *edge) const; - virtual Edge *makeEdge(Vertex *from, - Vertex *to, - TimingArcSet *arc_set); - virtual void makeWireEdge(const Pin *from_pin, - const Pin *to_pin); + Edge *makeEdge(Vertex *from, + Vertex *to, + TimingArcSet *arc_set); + void makeWireEdge(const Pin *from_pin, + const Pin *to_pin); void makePinInstanceEdges(const Pin *pin); void makeInstanceEdges(const Instance *inst); void makeWireEdgesToPin(const Pin *to_pin); void makeWireEdgesThruPin(const Pin *hpin); - virtual void makeWireEdgesFromPin(const Pin *drvr_pin); - virtual void deleteEdge(Edge *edge); + void makeWireEdgesFromPin(const Pin *drvr_pin); + void deleteEdge(Edge *edge); // Find the edge and timing arc on a gate between in_pin and drvr_pin. void gateEdgeArc(const Pin *in_pin, const RiseFall *in_rf, @@ -162,21 +145,21 @@ public: Edge *&edge, const TimingArc *&arc) const; - virtual ArcDelay arcDelay(const Edge *edge, - const TimingArc *arc, - DcalcAPIndex ap_index) const; - virtual void setArcDelay(Edge *edge, - const TimingArc *arc, - DcalcAPIndex ap_index, - ArcDelay delay); + ArcDelay arcDelay(const Edge *edge, + const TimingArc *arc, + DcalcAPIndex ap_index) const; + void setArcDelay(Edge *edge, + const TimingArc *arc, + DcalcAPIndex ap_index, + ArcDelay delay); // Alias for arcDelays using library wire arcs. - virtual const ArcDelay &wireArcDelay(const Edge *edge, - const RiseFall *rf, - DcalcAPIndex ap_index); - virtual void setWireArcDelay(Edge *edge, - const RiseFall *rf, - DcalcAPIndex ap_index, - const ArcDelay &delay); + const ArcDelay &wireArcDelay(const Edge *edge, + const RiseFall *rf, + DcalcAPIndex ap_index); + void setWireArcDelay(Edge *edge, + const RiseFall *rf, + DcalcAPIndex ap_index, + const ArcDelay &delay); // Is timing arc delay annotated. bool arcDelayAnnotated(const Edge *edge, const TimingArc *arc, @@ -185,7 +168,7 @@ public: const TimingArc *arc, DcalcAPIndex ap_index, bool annotated); - bool wireDelayAnnotated(Edge *edge, + bool wireDelayAnnotated(const Edge *edge, const RiseFall *rf, DcalcAPIndex ap_index) const; void setWireDelayAnnotated(Edge *edge, @@ -194,8 +177,6 @@ public: bool annotated); // True if any edge arc is annotated. bool delayAnnotated(Edge *edge); - int edgeCount() { return edges_->size(); } - virtual int arcCount() { return arc_count_; } void minPulseWidthArc(Vertex *vertex, const RiseFall *hi_low, @@ -211,6 +192,7 @@ public: void setPeriodCheckAnnotation(const Pin *pin, DcalcAPIndex ap_index, float period); + // Remove all delay and slew annotations. void removeDelaySlewAnnotations(); VertexSet *regClkVertices() { return reg_clk_vertices_; } @@ -223,29 +205,27 @@ protected: Vertex *makeVertex(Pin *pin, bool is_bidirect_drvr, bool is_reg_clk); - virtual void makeEdgeArcDelays(Edge *edge); + void makeEdgeArcDelays(Edge *edge); void makePinVertices(const Instance *inst); void makeWireEdgesFromPin(const Pin *drvr_pin, PinSet &visited_drvrs); bool isIsolatedNet(PinSeq &drvrs, PinSeq &loads) const; void makeWireEdges(); - virtual void makeInstDrvrWireEdges(const Instance *inst, - PinSet &visited_drvrs); - virtual void makePortInstanceEdges(const Instance *inst, - LibertyCell *cell, - LibertyPort *from_to_port); + void makeInstDrvrWireEdges(const Instance *inst, + PinSet &visited_drvrs); + void makePortInstanceEdges(const Instance *inst, + LibertyCell *cell, + LibertyPort *from_to_port); void removePeriodCheckAnnotations(); - void makeSlewTables(DcalcAPIndex count); - void deleteSlewTables(); void makeVertexSlews(Vertex *vertex); - void makeArcDelayTables(DcalcAPIndex ap_count); - void deleteArcDelayTables(); void deleteInEdge(Vertex *vertex, Edge *edge); void deleteOutEdge(Vertex *vertex, Edge *edge); - void removeDelays(); + void initSlews(); + void initSlews(Vertex *vertex); + void initArcDelays(Edge *edge); void removeDelayAnnotated(Edge *edge); VertexTable *vertices_; @@ -255,20 +235,8 @@ protected: // driver/source (top level input, instance pin output) vertex // in pin_bidirect_drvr_vertex_map PinVertexMap pin_bidirect_drvr_vertex_map_; - int arc_count_; - ArrivalsTable arrivals_; - std::mutex arrivals_lock_; - RequiredsTable requireds_; - std::mutex requireds_lock_; - PrevPathsTable prev_paths_; - std::mutex prev_paths_lock_; - Vector arc_delay_annotated_; int slew_rf_count_; - bool have_arc_delays_; DcalcAPIndex ap_count_; - DelayTableSeq slew_tables_; // [ap_index][tr_index][vertex_id] - VertexId slew_count_; - DelayTableSeq arc_delays_; // [ap_index][edge_arc_index] // Sdf period check annotations. PeriodCheckAnnotations *period_check_annotations_; // Register/latch clock vertices to search from. @@ -286,6 +254,7 @@ class Vertex { public: Vertex(); + ~Vertex(); Pin *pin() const { return pin_; } // Pin path with load/driver suffix for bidirects. const char *name(const Network *network) const; @@ -298,11 +267,12 @@ public: bool hasFanout() const; LevelColor color() const { return static_cast(color_); } void setColor(LevelColor color); - ArrivalId arrivals() { return arrivals_; } - ArrivalId requireds() { return requireds_; } - bool hasRequireds() const { return requireds_ != arrival_null; } - PrevPathId prevPaths() const { return prev_paths_; } - void setPrevPaths(PrevPathId id); + Slew *slews() { return slews_; } + const Slew *slews() const { return slews_; } + Arrival *arrivals() const { return arrivals_; } + Arrival *requireds() const { return requireds_; } + PathVertexRep *prevPaths() const { return prev_paths_; } + void setPrevPaths(PathVertexRep *prev_paths); TagGroupIndex tagGroupIndex() const; void setTagGroupIndex(TagGroupIndex tag_index); // Slew is annotated by sdc set_annotated_transition cmd. @@ -341,6 +311,7 @@ public: bool isRegClk() const { return is_reg_clk_; } bool crprPathPruningDisabled() const { return crpr_path_pruning_disabled_;} void setCrprPathPruningDisabled(bool disabled); + bool hasRequireds() const { return requireds_ != nullptr; } bool requiredsPruned() const { return requireds_pruned_; } void setRequiredsPruned(bool pruned); @@ -354,22 +325,30 @@ protected: void init(Pin *pin, bool is_bidirect_drvr, bool is_reg_clk); - void setArrivals(ArrivalId id); - void setRequireds(ArrivalId id); + void clear(); + void setArrivals(Arrival *arrivals); + void setRequireds(Required *requireds); + void setSlews(Slew *slews); Pin *pin_; - ArrivalId arrivals_; - ArrivalId requireds_; - PrevPathId prev_paths_; EdgeId in_edges_; // Edges to this vertex. EdgeId out_edges_; // Edges from this vertex. - // 28 bits - unsigned int tag_group_index_:tag_group_index_bits; // 24 - unsigned int slew_annotated_:slew_annotated_bits; // 4 + // Delay calc + Slew *slews_; + // Search + Arrival *arrivals_; + Arrival *requireds_; + PathVertexRep *prev_paths_; + + // These fields are written by multiple threads, so they + // cannot share the same word as the following bit fields. + uint32_t tag_group_index_; + // Each bit corresponds to a different BFS queue. + std::atomic bfs_in_queue_; // 4 - // 32 bits unsigned int level_:Graph::vertex_level_bits; // 24 + unsigned int slew_annotated_:slew_annotated_bits; // 4 // Levelization search state. // LevelColor gcc barfs if this is dcl'd. unsigned color_:2; @@ -379,11 +358,6 @@ protected: // This flag distinguishes the driver and load vertices. bool is_bidirect_drvr_:1; bool is_reg_clk_:1; - - // Each bit corresponds to a different BFS queue. - std::atomic bfs_in_queue_; // 4 - - // 15 bits bool is_disabled_constraint_:1; bool is_gated_clk_enable_:1; // Constrained by timing check edge. @@ -409,6 +383,7 @@ class Edge { public: Edge(); + ~Edge(); Vertex *to(const Graph *graph) const { return graph->vertex(to_); } Vertex *from(const Graph *graph) const { return graph->vertex(from_); } TimingRole *role() const; @@ -416,9 +391,9 @@ public: TimingSense sense() const; TimingArcSet *timingArcSet() const { return arc_set_; } void setTimingArcSet(TimingArcSet *set); - ArcId arcDelays() const { return arc_delays_; } - void setArcDelays(ArcId arc_delays); - bool delayAnnotationIsIncremental() const; + ArcDelay *arcDelays() const { return arc_delays_; } + void setArcDelays(ArcDelay *arc_delays); + bool delay_Annotation_Is_Incremental() const {return delay_annotation_is_incremental_;}; void setDelayAnnotationIsIncremental(bool is_incr); // Edge is disabled by set_disable_timing constraint. bool isDisabledConstraint() const; @@ -438,6 +413,7 @@ public: void setIsBidirectInstPath(bool is_bidir); bool isBidirectNetPath() const { return is_bidirect_net_path_; } void setIsBidirectNetPath(bool is_bidir); + void removeDelayAnnotated(); // ObjectTable interface. ObjectIdx objectIdx() const { return object_idx_; } @@ -447,6 +423,14 @@ protected: void init(VertexId from, VertexId to, TimingArcSet *arc_set); + void clear(); + bool arcDelayAnnotated(const TimingArc *arc, + DcalcAPIndex ap_index, + DcalcAPIndex ap_count) const; + void setArcDelayAnnotated(const TimingArc *arc, + DcalcAPIndex ap_index, + DcalcAPIndex ap_count, + bool annotated); TimingArcSet *arc_set_; VertexId from_; @@ -454,8 +438,12 @@ protected: EdgeId vertex_in_link_; // Vertex in edges list. EdgeId vertex_out_next_; // Vertex out edges doubly linked list. EdgeId vertex_out_prev_; - ArcId arc_delays_; - // 16 bits + ArcDelay *arc_delays_; + union { + uintptr_t bits_; + vector *seq_; + } arc_delay_annotated_; + bool arc_delay_annotated_is_bits_:1; bool delay_annotation_is_incremental_:1; bool is_bidirect_inst_path_:1; bool is_bidirect_net_path_:1; diff --git a/include/sta/GraphClass.hh b/include/sta/GraphClass.hh index f105f045..1f381f37 100644 --- a/include/sta/GraphClass.hh +++ b/include/sta/GraphClass.hh @@ -49,7 +49,6 @@ class VertexSet; typedef ObjectId VertexId; typedef ObjectId EdgeId; -typedef ObjectId ArcId; typedef Vector VertexSeq; typedef Vector EdgeSeq; typedef Set EdgeSet; diff --git a/include/sta/ObjectTable.hh b/include/sta/ObjectTable.hh index 50b8533e..3c752178 100644 --- a/include/sta/ObjectTable.hh +++ b/include/sta/ObjectTable.hh @@ -173,7 +173,6 @@ void ObjectTable::destroy(TYPE *object) { ObjectId object_id = objectId(object); - object->~TYPE(); size_--; freePush(object, object_id); } diff --git a/include/sta/Search.hh b/include/sta/Search.hh index f39decaf..efa08c19 100644 --- a/include/sta/Search.hh +++ b/include/sta/Search.hh @@ -383,7 +383,8 @@ protected: bool report_max, DcalcAnalysisPt *dcalc_ap_min, DcalcAnalysisPt *dcalc_ap_max); - virtual void deleteTags(); + void deleteTags(); + void deleteTagsPrev(); void seedInvalidArrivals(); void seedArrivals(); void findClockVertices(VertexSet &vertices); @@ -593,12 +594,14 @@ protected: // Entries in tags_ may be missing where previous filter tags were deleted. TagIndex tag_capacity_; std::atomic tags_; + vector tags_prev_; TagIndex tag_next_; // Holes in tags_ left by deleting filter tags. std::vector tag_free_indices_; std::mutex tag_lock_; TagGroupSet *tag_group_set_; std::atomic tag_groups_; + vector tag_groups_prev_; TagGroupIndex tag_group_next_; // Holes in tag_groups_ left by deleting filter tag groups. std::vector tag_group_free_indices_; diff --git a/sdc/Sdc.tcl b/sdc/Sdc.tcl index 7e4b3e04..6cb745fc 100644 --- a/sdc/Sdc.tcl +++ b/sdc/Sdc.tcl @@ -269,7 +269,6 @@ proc check_unit { unit key suffix key_var } { if { [string match -nocase $arg_suffix $suffix] } { set arg_prefix [string range $value 0 end-$suffix_length] if { [regexp "^(10*)?(\[Mkmunpf\])?$" $arg_prefix ignore mult prefix] } { - #puts "$arg_prefix '$mult' '$prefix'" if { $mult == "" } { set mult 1 } diff --git a/search/Search.cc b/search/Search.cc index 96589391..14c6fb77 100644 --- a/search/Search.cc +++ b/search/Search.cc @@ -408,7 +408,11 @@ Search::deletePaths() { debugPrint(debug_, "search", 1, "delete paths"); if (arrivals_exist_) { - graph_->deletePaths(); + VertexIterator vertex_iter(graph_); + while (vertex_iter.hasNext()) { + Vertex *vertex = vertex_iter.next(); + deletePaths(vertex); + } filtered_arrivals_->clear(); arrivals_exist_ = false; } @@ -428,10 +432,8 @@ void Search::deletePaths(Vertex *vertex) { TagGroup *tag_group = tagGroup(vertex); - if (tag_group) { - int arrival_count = tag_group->arrivalCount(); - graph_->deletePaths(vertex, arrival_count); - } + if (tag_group) + graph_->deletePaths(vertex); } //////////////////////////////////////////////////////////////// @@ -613,11 +615,25 @@ Search::findFilteredArrivals(bool thru_latches) debugPrint(debug_, "search", 1, "find arrivals pass %d", pass); int arrival_count = arrival_iter_->visitParallel(max_level, arrival_visitor_); + deleteTagsPrev(); debugPrint(debug_, "search", 1, "found %d arrivals", arrival_count); } arrivals_exist_ = true; } +// Delete stale tag arrarys. +void +Search::deleteTagsPrev() +{ + for (Tag** tags: tags_prev_) + delete [] tags; + tags_prev_.clear(); + + for (TagGroup** tag_groups: tag_groups_prev_) + delete [] tag_groups; + tag_groups_prev_.clear(); +} + VertexSeq Search::filteredEndpoints() { @@ -853,6 +869,7 @@ Search::findClkArrivals() ClkArrivalSearchPred search_clk(this); arrival_visitor_->init(false, &search_clk); arrival_iter_->visitParallel(levelize_->maxLevel(), arrival_visitor_); + deleteTagsPrev(); arrivals_exist_ = true; stats.report("Find clk arrivals"); } @@ -1023,6 +1040,7 @@ Search::findArrivals1(Level level) findArrivalsSeed(); Stats stats(debug_, report_); int arrival_count = arrival_iter_->visitParallel(level, arrival_visitor_); + deleteTagsPrev(); stats.report("Find arrivals"); if (arrival_iter_->empty() && invalid_arrivals_->empty()) { @@ -2671,6 +2689,7 @@ Search::findTagGroup(TagGroupBldr *tag_bldr) TagGroup **tag_groups = new TagGroup*[tag_capacity]; memcpy(tag_groups, tag_groups_, tag_group_capacity_ * sizeof(TagGroup*)); + tag_groups_prev_.push_back(tag_groups_); tag_groups_ = tag_groups; tag_group_capacity_ = tag_capacity; tag_group_set_->reserve(tag_capacity); @@ -2705,7 +2724,7 @@ Search::setVertexArrivals(Vertex *vertex, else { // Prev paths not required. prev_paths = nullptr; - graph_->deletePrevPaths(vertex, arrival_count); + graph_->deletePrevPaths(vertex); } tag_bldr->copyArrivals(tag_group, prev_arrivals, prev_paths); vertex->setTagGroupIndex(tag_group->index()); @@ -2718,16 +2737,15 @@ Search::setVertexArrivals(Vertex *vertex, requiredInvalid(vertex); if (tag_group != prev_tag_group) // Requireds can only be reused if the tag group is unchanged. - graph_->deleteRequireds(vertex, prev_tag_group->arrivalCount()); + graph_->deleteRequireds(vertex); } } else { if (prev_tag_group) { - uint32_t prev_arrival_count = prev_tag_group->arrivalCount(); - graph_->deleteArrivals(vertex, prev_arrival_count); + graph_->deleteArrivals(vertex); if (has_requireds) { requiredInvalid(vertex); - graph_->deleteRequireds(vertex, prev_arrival_count); + graph_->deleteRequireds(vertex); } } Arrival *arrivals = graph_->makeArrivals(vertex, arrival_count); @@ -2907,6 +2925,7 @@ Search::findTag(const RiseFall *rf, TagIndex tag_capacity = tag_capacity_ * 2; Tag **tags = new Tag*[tag_capacity]; memcpy(tags, tags_, tag_capacity_ * sizeof(Tag*)); + tags_prev_.push_back(tags_); tags_ = tags; tag_capacity_ = tag_capacity; tag_set_->reserve(tag_capacity); @@ -3151,6 +3170,7 @@ Search::findRequireds(Level level) seedRequireds(); seedInvalidRequireds(); int required_count = required_iter_->visitParallel(level, &req_visitor); + deleteTagsPrev(); requireds_exist_ = true; debugPrint(debug_, "search", 1, "found %d requireds", required_count); stats.report("Find requireds"); @@ -3436,8 +3456,7 @@ RequiredCmp::requiredsSave(Vertex *vertex, if (tag_group == nullptr) requireds_changed = true; else { - int arrival_count = tag_group->arrivalCount(); - graph->deleteRequireds(vertex, arrival_count); + graph->deleteRequireds(vertex); requireds_changed = true; } } diff --git a/search/Sta.cc b/search/Sta.cc index 56503d56..35e2e644 100644 --- a/search/Sta.cc +++ b/search/Sta.cc @@ -3475,7 +3475,7 @@ Sta::ensureGraph() void Sta::makeGraph() { - graph_ = new Graph(this, 2, true, corners_->dcalcAnalysisPtCount()); + graph_ = new Graph(this, 2, corners_->dcalcAnalysisPtCount()); graph_->makeGraph(); }