thread safety

commit 98fa3639bd0e07f4e315578b50266972bbb7ac7d
Author: James Cherry <cherry@parallaxsw.com>
Date:   Sat Feb 8 14:17:29 2025 -0800

    Edge::setArcDelayAnnotated

    Signed-off-by: James Cherry <cherry@parallaxsw.com>

commit d4628351d788c68ed948751374adee1bba6ca6ea
Author: James Cherry <cherry@parallaxsw.com>
Date:   Sat Feb 8 09:27:33 2025 -0800

    leaks

    Signed-off-by: James Cherry <cherry@parallaxsw.com>

commit cee843b81df89c0f7bc51a76a34422009f49b046
Author: James Cherry <cherry@parallaxsw.com>
Date:   Fri Feb 7 10:22:00 2025 -0800

    arcDelayAnnotated

    Signed-off-by: James Cherry <cherry@parallaxsw.com>

commit 2a080cb4a3425e9b0a98d90315d23b87c755ebaa
Author: James Cherry <cherry@parallaxsw.com>
Date:   Fri Feb 7 09:34:16 2025 -0800

    leak

    Signed-off-by: James Cherry <cherry@parallaxsw.com>

commit 6b85cebe290cb9f1c7fabe06fcec42dd7c060550
Author: James Cherry <cherry@parallaxsw.com>
Date:   Thu Feb 6 16:12:42 2025 -0800

    readme

    Signed-off-by: James Cherry <cherry@parallaxsw.com>

commit 01d4481280b08e98cc311dc37a3eeb1cfc928902
Author: James Cherry <cherry@parallaxsw.com>
Date:   Thu Feb 6 16:12:33 2025 -0800

    comment

    Signed-off-by: James Cherry <cherry@parallaxsw.com>

commit e7c62097f948450ed46c0ac577bd3636cf5be625
Author: James Cherry <cherry@parallaxsw.com>
Date:   Thu Feb 6 16:12:19 2025 -0800

    Search no virtuals

    Signed-off-by: James Cherry <cherry@parallaxsw.com>

commit 761212fc0a593d47422dc7716b7e28f593647a64
Author: James Cherry <cherry@parallaxsw.com>
Date:   Thu Feb 6 15:13:36 2025 -0800

    leak

    Signed-off-by: James Cherry <cherry@parallaxsw.com>

commit dd64f685c7fe2b3e85e3194008fae67a23650110
Author: James Cherry <cherry@parallaxsw.com>
Date:   Thu Feb 6 12:31:38 2025 -0800

    Graph::removeDelayAnnotated

    Signed-off-by: James Cherry <cherry@parallaxsw.com>

commit a1b79b09178ba8bdf0ec9486d84fcff68c2a1f2e
Author: James Cherry <cherry@parallaxsw.com>
Date:   Thu Feb 6 12:19:32 2025 -0800

    Edge::arc_annotated_delays_

    Signed-off-by: James Cherry <cherry@parallaxsw.com>

commit 6b8b44ebd1e3a483ccfaa08f08c5fa8b60c72f90
Author: James Cherry <cherry@parallaxsw.com>
Date:   Thu Feb 6 08:48:49 2025 -0800

    leak

    Signed-off-by: James Cherry <cherry@parallaxsw.com>

commit ee939bf4015fe3d78860b3e615ec7defa395b2bf
Author: James Cherry <cherry@parallaxsw.com>
Date:   Wed Feb 5 18:14:04 2025 -0800

    pass fast regressions

    Signed-off-by: James Cherry <cherry@parallaxsw.com>

commit f25b505d8507046638dbb30772d721547b3f8941
Author: James Cherry <cherry@parallaxsw.com>
Date:   Wed Feb 5 15:54:39 2025 -0800

    pass all but 1 regression

    Signed-off-by: James Cherry <cherry@parallaxsw.com>

commit acd3abf0512f5ecbe83025eb5facfa5a594ca9fa
Author: James Cherry <cherry@parallaxsw.com>
Date:   Wed Feb 5 12:23:02 2025 -0800

    rm ArrayTable compiles

    Signed-off-by: James Cherry <cherry@parallaxsw.com>

commit 1a65f9da1814b8664062fe7ecf684acc42ee6933
Author: James Cherry <cherry@parallaxsw.com>
Date:   Tue Feb 4 16:26:34 2025 -0800

    keep prev tag arrays until search is finsihed

    Signed-off-by: James Cherry <cherry@parallaxsw.com>

Signed-off-by: James Cherry <cherry@parallaxsw.com>
This commit is contained in:
James Cherry 2025-02-10 17:31:45 -07:00
parent 6a27390dd5
commit 0dfea7dfad
12 changed files with 373 additions and 705 deletions

View File

@ -63,8 +63,7 @@ compiled locally. Derivative works are supported as long as they
adhere to the GPL license requirements. However, OpenSTA is not adhere to the GPL license requirements. However, OpenSTA is not
supported by a public community of developers as many other open supported by a public community of developers as many other open
source projects are. The copyright and develpment are exclusive to source projects are. The copyright and develpment are exclusive to
Parallax Software. Contributors must signing the Contributor License Parallax Software.
Agreement (doc/CLA.txt) when submitting pull requests.
Removing copyright and license notices from OpenSTA sources (or any Removing copyright and license notices from OpenSTA sources (or any
other open source project for that matter) is illegal. This should be 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 scripts will largely be ignored. Small performance improvements
simply do not justify the time requied to audit and verify the changes. simply do not justify the time requied to audit and verify the changes.
Contributions that add dependencies on external libraries like boost Contributions that add dependencies on external libraries like boost,
will not be accepted. 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 ## Authors

View File

@ -621,10 +621,15 @@ GraphDelayCalc::findVertexDelay(Vertex *vertex,
DrvrLoadSlews DrvrLoadSlews
GraphDelayCalc::loadSlews(LoadPinIndexMap &load_pin_index_map) GraphDelayCalc::loadSlews(LoadPinIndexMap &load_pin_index_map)
{ {
size_t slew_count = graph_->slewCount();
DrvrLoadSlews load_slews(load_pin_index_map.size()); DrvrLoadSlews load_slews(load_pin_index_map.size());
for (auto const [pin, index] : load_pin_index_map) { for (auto const [pin, index] : load_pin_index_map) {
Vertex *load_vertex = graph_->pinLoadVertex(pin); 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; return load_slews;
} }
@ -633,11 +638,12 @@ bool
GraphDelayCalc::loadSlewsChanged(DrvrLoadSlews &load_slews_prev, GraphDelayCalc::loadSlewsChanged(DrvrLoadSlews &load_slews_prev,
LoadPinIndexMap &load_pin_index_map) LoadPinIndexMap &load_pin_index_map)
{ {
size_t slew_count = graph_->slewCount();
for (auto const [pin, index] : load_pin_index_map) { for (auto const [pin, index] : load_pin_index_map) {
Vertex *load_vertex = graph_->pinLoadVertex(pin); Vertex *load_vertex = graph_->pinLoadVertex(pin);
const SlewSeq slews = graph_->slews(load_vertex); SlewSeq &slews_prev = load_slews_prev[index];;
const SlewSeq &slews_prev = load_slews_prev[index]; const Slew *slews = load_vertex->slews();
for (size_t i = 0; i < slews.size(); i++) { for (size_t i = 0; i < slew_count; i++) {
if (!delayEqual(slews[i], slews_prev[i])) if (!delayEqual(slews[i], slews_prev[i]))
return true; return true;
} }

View File

@ -46,14 +46,11 @@ namespace sta {
Graph::Graph(StaState *sta, Graph::Graph(StaState *sta,
int slew_rf_count, int slew_rf_count,
bool have_arc_delays,
DcalcAPIndex ap_count) : DcalcAPIndex ap_count) :
StaState(sta), StaState(sta),
vertices_(nullptr), vertices_(nullptr),
edges_(nullptr), edges_(nullptr),
arc_count_(0),
slew_rf_count_(slew_rf_count), slew_rf_count_(slew_rf_count),
have_arc_delays_(have_arc_delays),
ap_count_(ap_count), ap_count_(ap_count),
period_check_annotations_(nullptr), period_check_annotations_(nullptr),
reg_clk_vertices_(new VertexSet(graph_)) reg_clk_vertices_(new VertexSet(graph_))
@ -64,11 +61,11 @@ Graph::Graph(StaState *sta,
Graph::~Graph() Graph::~Graph()
{ {
delete vertices_; edges_->clear();
delete edges_; delete edges_;
vertices_->clear();
delete vertices_;
delete reg_clk_vertices_; delete reg_clk_vertices_;
deleteSlewTables();
deleteArcDelayTables();
removePeriodCheckAnnotations(); removePeriodCheckAnnotations();
} }
@ -90,8 +87,6 @@ Graph::makeVerticesAndEdges()
{ {
vertices_ = new VertexTable; vertices_ = new VertexTable;
edges_ = new EdgeTable; edges_ = new EdgeTable;
makeSlewTables(ap_count_);
makeArcDelayTables(ap_count_);
LeafInstanceIterator *leaf_iter = network_->leafInstanceIterator(); LeafInstanceIterator *leaf_iter = network_->leafInstanceIterator();
while (leaf_iter->hasNext()) { while (leaf_iter->hasNext()) {
@ -440,7 +435,7 @@ Graph::makeVertex(Pin *pin,
{ {
Vertex *vertex = vertices_->make(); Vertex *vertex = vertices_->make();
vertex->init(pin, is_bidirect_drvr, is_reg_clk); vertex->init(pin, is_bidirect_drvr, is_reg_clk);
makeVertexSlews(vertex); initSlews(vertex);
if (is_reg_clk) if (is_reg_clk)
reg_clk_vertices_->insert(vertex); reg_clk_vertices_->insert(vertex);
return vertex; return vertex;
@ -491,7 +486,7 @@ Graph::deleteVertex(Vertex *vertex)
Edge *edge = Graph::edge(edge_id); Edge *edge = Graph::edge(edge_id);
next_id = edge->vertex_in_link_; next_id = edge->vertex_in_link_;
deleteOutEdge(edge->from(this), edge); deleteOutEdge(edge->from(this), edge);
arc_count_ -= edge->timingArcSet()->arcCount(); edge->clear();
edges_->destroy(edge); edges_->destroy(edge);
} }
// Delete edges from vertex. // Delete edges from vertex.
@ -499,9 +494,10 @@ Graph::deleteVertex(Vertex *vertex)
Edge *edge = Graph::edge(edge_id); Edge *edge = Graph::edge(edge_id);
next_id = edge->vertex_out_next_; next_id = edge->vertex_out_next_;
deleteInEdge(edge->to(this), edge); deleteInEdge(edge->to(this), edge);
arc_count_ -= edge->timingArcSet()->arcCount(); edge->clear();
edges_->destroy(edge); edges_->destroy(edge);
} }
vertex->clear();
vertices_->destroy(vertex); vertices_->destroy(vertex);
} }
@ -579,139 +575,74 @@ Arrival *
Graph::makeArrivals(Vertex *vertex, Graph::makeArrivals(Vertex *vertex,
uint32_t count) uint32_t count)
{ {
if (vertex->arrivals() != arrival_null) Arrival *arrivals = new Arrival[count];
debugPrint(debug_, "graph", 1, "arrival leak"); vertex->setArrivals(arrivals);
Arrival *arrivals;
ArrivalId id;
{
LockGuard lock(arrivals_lock_);
arrivals_.make(count, arrivals, id);
}
vertex->setArrivals(id);
return arrivals; return arrivals;
} }
Arrival * Arrival *
Graph::arrivals(Vertex *vertex) Graph::arrivals(const Vertex *vertex) const
{ {
return arrivals_.pointer(vertex->arrivals()); return vertex->arrivals();
} }
void void
Graph::deleteArrivals(Vertex *vertex, Graph::deleteArrivals(Vertex *vertex)
uint32_t count)
{ {
{ vertex->setArrivals(nullptr);
LockGuard lock(arrivals_lock_);
arrivals_.destroy(vertex->arrivals(), count);
} }
vertex->setArrivals(arrival_null);
Required *
Graph::requireds(const Vertex *vertex) const
{
return vertex->requireds();
} }
Required * Required *
Graph::makeRequireds(Vertex *vertex, Graph::makeRequireds(Vertex *vertex,
uint32_t count) uint32_t count)
{ {
if (vertex->requireds() != arrival_null) Required *requireds = new Arrival[count];
debugPrint(debug_, "graph", 1, "required leak"); vertex->setRequireds(requireds);
Required *requireds;
ArrivalId id;
{
LockGuard lock(requireds_lock_);
requireds_.make(count, requireds, id);
}
vertex->setRequireds(id);
return requireds; return requireds;
} }
Required * void
Graph::requireds(Vertex *vertex) Graph::deleteRequireds(Vertex *vertex)
{ {
return requireds_.pointer(vertex->requireds()); vertex->setRequireds(nullptr);
} }
void PathVertexRep *
Graph::deleteRequireds(Vertex *vertex, Graph::prevPaths(const Vertex *vertex) const
uint32_t count)
{ {
{ return vertex->prevPaths();
LockGuard lock(requireds_lock_);
requireds_.destroy(vertex->requireds(), count);
}
vertex->setRequireds(arrival_null);
} }
PathVertexRep * PathVertexRep *
Graph::makePrevPaths(Vertex *vertex, Graph::makePrevPaths(Vertex *vertex,
uint32_t count) uint32_t count)
{ {
PathVertexRep *prev_paths; PathVertexRep *prev_paths = new PathVertexRep[count];
PrevPathId id; vertex->setPrevPaths(prev_paths);
{
LockGuard lock(prev_paths_lock_);
prev_paths_.make(count, prev_paths, id);
}
vertex->setPrevPaths(id);
return prev_paths; return prev_paths;
} }
PathVertexRep * void
Graph::prevPaths(Vertex *vertex) const Graph::deletePrevPaths(Vertex *vertex)
{ {
return prev_paths_.pointer(vertex->prevPaths()); vertex->setPrevPaths(nullptr);
} }
void void
Graph::deletePrevPaths(Vertex *vertex, Graph::deletePaths(Vertex *vertex)
uint32_t count)
{ {
if (vertex->prevPaths() != object_id_null) { deleteArrivals(vertex);
{ deleteRequireds(vertex);
LockGuard lock(prev_paths_lock_); deletePrevPaths(vertex);
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->tag_group_index_ = tag_group_index_max;
vertex->crpr_path_pruning_disabled_ = false; 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);
}
}
//////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////
@ -721,11 +652,11 @@ Graph::slew(const Vertex *vertex,
DcalcAPIndex ap_index) DcalcAPIndex ap_index)
{ {
if (slew_rf_count_) { if (slew_rf_count_) {
int table_index = const Slew *slews = vertex->slews();
(slew_rf_count_ == 1) ? ap_index : ap_index*slew_rf_count_+rf->index(); size_t slew_index = (slew_rf_count_ == 1)
DelayTable *table = slew_tables_[table_index]; ? ap_index
VertexId vertex_id = id(vertex); : ap_index*slew_rf_count_+rf->index();
return table->ref(vertex_id); return slews[slew_index];
} }
else { else {
static Slew slew(0.0); static Slew slew(0.0);
@ -740,27 +671,17 @@ Graph::setSlew(Vertex *vertex,
const Slew &slew) const Slew &slew)
{ {
if (slew_rf_count_) { if (slew_rf_count_) {
int table_index = Slew *slews = vertex->slews();
(slew_rf_count_ == 1) ? ap_index : ap_index*slew_rf_count_+rf->index(); if (slews == nullptr) {
DelayTable *table = slew_tables_[table_index]; int slew_count = slew_rf_count_ * ap_count_;
VertexId vertex_id = id(vertex); slews = new Slew[slew_count];
Slew &vertex_slew = table->ref(vertex_id); vertex->setSlews(slews);
vertex_slew = slew;
} }
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;
} }
//////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////
@ -784,8 +705,6 @@ Graph::makeEdge(Vertex *from,
{ {
Edge *edge = edges_->make(); Edge *edge = edges_->make();
edge->init(id(from), id(to), arc_set); edge->init(id(from), id(to), arc_set);
makeEdgeArcDelays(edge);
arc_count_ += arc_set->arcCount();
// Add out edge to from vertex. // Add out edge to from vertex.
EdgeId next = from->out_edges_; EdgeId next = from->out_edges_;
edge->vertex_out_next_ = next; edge->vertex_out_next_ = next;
@ -799,6 +718,7 @@ Graph::makeEdge(Vertex *from,
edge->vertex_in_link_ = to->in_edges_; edge->vertex_in_link_ = to->in_edges_;
to->in_edges_ = edge_id; to->in_edges_ = edge_id;
initArcDelays(edge);
return edge; return edge;
} }
@ -809,63 +729,18 @@ Graph::deleteEdge(Edge *edge)
Vertex *to = edge->to(this); Vertex *to = edge->to(this);
deleteOutEdge(from, edge); deleteOutEdge(from, edge);
deleteInEdge(to, edge); deleteInEdge(to, edge);
arc_count_ -= edge->timingArcSet()->arcCount(); edge->clear();
edges_->destroy(edge); 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 ArcDelay
Graph::arcDelay(const Edge *edge, Graph::arcDelay(const Edge *edge,
const TimingArc *arc, const TimingArc *arc,
DcalcAPIndex ap_index) const DcalcAPIndex ap_index) const
{ {
if (have_arc_delays_) { ArcDelay *delays = edge->arcDelays();
DelayTable *table = arc_delays_[ap_index]; size_t index = arc->index() * ap_count_ + ap_index;
ArcDelay *arc_delays = table->pointer(edge->arcDelays()); return delays[index];
ArcDelay &arc_delay = arc_delays[arc->index()];
return arc_delay;
}
else
return delay_zero;
} }
void void
@ -874,11 +749,9 @@ Graph::setArcDelay(Edge *edge,
DcalcAPIndex ap_index, DcalcAPIndex ap_index,
ArcDelay delay) ArcDelay delay)
{ {
if (have_arc_delays_) { ArcDelay *arc_delays = edge->arcDelays();
DelayTable *table = arc_delays_[ap_index]; size_t index = arc->index() * ap_count_ + ap_index;
ArcDelay *arc_delays = table->pointer(edge->arcDelays()); arc_delays[index] = delay;
arc_delays[arc->index()] = delay;
}
} }
const ArcDelay & const ArcDelay &
@ -886,13 +759,9 @@ Graph::wireArcDelay(const Edge *edge,
const RiseFall *rf, const RiseFall *rf,
DcalcAPIndex ap_index) DcalcAPIndex ap_index)
{ {
if (have_arc_delays_) { ArcDelay *delays = edge->arcDelays();
DelayTable *table = arc_delays_[ap_index]; size_t index = rf->index() * ap_count_ + ap_index;
ArcDelay *arc_delays = table->pointer(edge->arcDelays()); return delays[index];
return arc_delays[rf->index()];
}
else
return delay_zero;
} }
void void
@ -901,26 +770,19 @@ Graph::setWireArcDelay(Edge *edge,
DcalcAPIndex ap_index, DcalcAPIndex ap_index,
const ArcDelay &delay) const ArcDelay &delay)
{ {
if (have_arc_delays_) { ArcDelay *delays = edge->arcDelays();
DelayTable *table = arc_delays_[ap_index]; size_t index = rf->index() * ap_count_ + ap_index;
ArcDelay *arc_delays = table->pointer(edge->arcDelays()); delays[index] = delay;
arc_delays[rf->index()] = delay;
}
} }
////////////////////////////////////////////////////////////////
bool bool
Graph::arcDelayAnnotated(const Edge *edge, Graph::arcDelayAnnotated(const Edge *edge,
const TimingArc *arc, const TimingArc *arc,
DcalcAPIndex ap_index) const DcalcAPIndex ap_index) const
{ {
if (!arc_delay_annotated_.empty()) { return edge->arcDelayAnnotated(arc, ap_index, ap_count_);
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;
} }
void void
@ -929,22 +791,17 @@ Graph::setArcDelayAnnotated(Edge *edge,
DcalcAPIndex ap_index, DcalcAPIndex ap_index,
bool annotated) bool annotated)
{ {
size_t index = (edge->arcDelays() + arc->index()) * ap_count_ + ap_index; return edge->setArcDelayAnnotated(arc, ap_index, ap_count_, annotated);
if (index >= arc_delay_annotated_.size())
report_->critical(1081, "arc_delay_annotated array bounds exceeded");
arc_delay_annotated_[index] = annotated;
} }
bool bool
Graph::wireDelayAnnotated(Edge *edge, Graph::wireDelayAnnotated(const Edge *edge,
const RiseFall *rf, const RiseFall *rf,
DcalcAPIndex ap_index) const DcalcAPIndex ap_index) const
{ {
size_t index = (edge->arcDelays() + TimingArcSet::wireArcIndex(rf)) * ap_count_ int arc_index = TimingArcSet::wireArcIndex(rf);
+ ap_index; TimingArc *arc = TimingArcSet::wireTimingArcSet()->findTimingArc(arc_index);
if (index >= arc_delay_annotated_.size()) return edge->arcDelayAnnotated(arc, ap_index, ap_count_);
report_->critical(1082, "arc_delay_annotated array bounds exceeded");
return arc_delay_annotated_[index];
} }
void void
@ -953,13 +810,19 @@ Graph::setWireDelayAnnotated(Edge *edge,
DcalcAPIndex ap_index, DcalcAPIndex ap_index,
bool annotated) bool annotated)
{ {
size_t index = (edge->arcDelays() + TimingArcSet::wireArcIndex(rf)) * ap_count_ int arc_index = TimingArcSet::wireArcIndex(rf);
+ ap_index; TimingArc *arc = TimingArcSet::wireTimingArcSet()->findTimingArc(arc_index);
if (index >= arc_delay_annotated_.size()) return edge->setArcDelayAnnotated(arc, ap_index, ap_count_, annotated);
report_->critical(1083, "arc_delay_annotated array bounds exceeded");
arc_delay_annotated_[index] = annotated;
} }
void
Graph::removeDelayAnnotated(Edge *edge)
{
edge->removeDelayAnnotated();
}
////////////////////////////////////////////////////////////////
// This only gets called if the analysis type changes from single // This only gets called if the analysis type changes from single
// to bc_wc/ocv or visa versa. // to bc_wc/ocv or visa versa.
void void
@ -967,42 +830,53 @@ Graph::setDelayCount(DcalcAPIndex ap_count)
{ {
if (ap_count != ap_count_) { if (ap_count != ap_count_) {
// Discard any existing delays. // Discard any existing delays.
deleteSlewTables();
deleteArcDelayTables();
removePeriodCheckAnnotations(); removePeriodCheckAnnotations();
makeSlewTables(ap_count);
makeArcDelayTables(ap_count);
ap_count_ = ap_count; ap_count_ = ap_count;
removeDelays(); initSlews();
} }
} }
void void
Graph::removeDelays() Graph::initSlews()
{ {
VertexIterator vertex_iter(this); VertexIterator vertex_iter(graph_);
while (vertex_iter.hasNext()) { while (vertex_iter.hasNext()) {
Vertex *vertex = vertex_iter.next(); Vertex *vertex = vertex_iter.next();
makeVertexSlews(vertex); initSlews(vertex);
VertexOutEdgeIterator edge_iter(vertex, this);
VertexOutEdgeIterator edge_iter(vertex, graph_);
while (edge_iter.hasNext()) { while (edge_iter.hasNext()) {
Edge *edge = edge_iter.next(); Edge *edge = edge_iter.next();
makeEdgeArcDelays(edge); initArcDelays(edge);
removeDelayAnnotated(edge);
} }
} }
} }
void void
Graph::removeDelayAnnotated(Edge *edge) Graph::initSlews(Vertex *vertex)
{ {
edge->setDelayAnnotationIsIncremental(false); size_t slew_count = slewCount();
TimingArcSet *arc_set = edge->timingArcSet(); Slew *slews = new Slew[slew_count];
for (TimingArc *arc : arc_set->arcs()) { vertex->setSlews(slews);
for (DcalcAPIndex ap_index = 0; ap_index < ap_count_; ap_index++) { for (size_t i = 0; i < slew_count; i++)
setArcDelayAnnotated(edge, arc, ap_index, false); 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 bool
@ -1018,35 +892,6 @@ Graph::delayAnnotated(Edge *edge)
return true; 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 void
@ -1161,9 +1006,10 @@ Vertex::init(Pin *pin,
is_bidirect_drvr_ = is_bidirect_drvr; is_bidirect_drvr_ = is_bidirect_drvr;
in_edges_ = edge_id_null; in_edges_ = edge_id_null;
out_edges_ = edge_id_null; out_edges_ = edge_id_null;
arrivals_ = arrival_null; slews_ = nullptr;
requireds_ = arrival_null; arrivals_ = nullptr;
prev_paths_ = prev_path_null; requireds_ = nullptr;
prev_paths_ = nullptr;
tag_group_index_ = tag_group_index_max; tag_group_index_ = tag_group_index_max;
slew_annotated_ = false; slew_annotated_ = false;
sim_value_ = unsigned(LogicValue::unknown); sim_value_ = unsigned(LogicValue::unknown);
@ -1180,6 +1026,24 @@ Vertex::init(Pin *pin,
requireds_pruned_ = false; 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 void
Vertex::setObjectIdx(ObjectIdx idx) Vertex::setObjectIdx(ObjectIdx idx)
{ {
@ -1228,6 +1092,13 @@ Vertex::setColor(LevelColor color)
color_ = unsigned(color); color_ = unsigned(color);
} }
void
Vertex::setSlews(Slew *slews)
{
delete [] slews_;
slews_ = slews;
}
bool bool
Vertex::slewAnnotated(const RiseFall *rf, Vertex::slewAnnotated(const RiseFall *rf,
const MinMax *min_max) const const MinMax *min_max) const
@ -1289,20 +1160,23 @@ Vertex::setTagGroupIndex(TagGroupIndex tag_index)
} }
void void
Vertex::setArrivals(ArrivalId id) Vertex::setArrivals(Arrival *arrivals)
{ {
arrivals_ = id; delete [] arrivals_;
arrivals_ = arrivals;
} }
void void
Vertex::setRequireds(ArrivalId id) Vertex::setRequireds(Required *requireds)
{ {
requireds_ = id; delete [] requireds_;
requireds_ = requireds;
} }
void void
Vertex::setPrevPaths(PrevPathId prev_paths) Vertex::setPrevPaths(PathVertexRep *prev_paths)
{ {
delete [] prev_paths_;
prev_paths_ = prev_paths; prev_paths_ = prev_paths;
} }
@ -1410,13 +1284,15 @@ Edge::init(VertexId from,
from_ = from; from_ = from;
to_ = to; to_ = to;
arc_set_ = arc_set; arc_set_ = arc_set;
arc_delays_ = 0;
vertex_in_link_ = edge_id_null; vertex_in_link_ = edge_id_null;
vertex_out_next_ = edge_id_null; vertex_out_next_ = edge_id_null;
vertex_out_prev_ = edge_id_null; vertex_out_prev_ = edge_id_null;
is_bidirect_inst_path_ = false; is_bidirect_inst_path_ = false;
is_bidirect_net_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; delay_annotation_is_incremental_ = false;
sim_timing_sense_ = unsigned(TimingSense::unknown); sim_timing_sense_ = unsigned(TimingSense::unknown);
is_disabled_constraint_ = false; is_disabled_constraint_ = false;
@ -1424,6 +1300,22 @@ Edge::init(VertexId from,
is_disabled_loop_ = false; 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 void
Edge::setObjectIdx(ObjectIdx idx) Edge::setObjectIdx(ObjectIdx idx)
{ {
@ -1437,15 +1329,56 @@ Edge::setTimingArcSet(TimingArcSet *set)
} }
void void
Edge::setArcDelays(ArcId arc_delays) Edge::setArcDelays(ArcDelay *arc_delays)
{ {
delete [] arc_delays_;
arc_delays_ = arc_delays; arc_delays_ = arc_delays;
} }
bool 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<bool>(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 void

View File

@ -83,12 +83,6 @@ private:
%inline %{ %inline %{
int
graph_arc_count()
{
return Sta::sta()->ensureGraph()->arcCount();
}
VertexIterator * VertexIterator *
vertex_iterator() vertex_iterator()
{ {

View File

@ -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 <https://www.gnu.org/licenses/>.
//
// 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 <cstring> // memcpy
#include <vector>
#include <atomic>
#include "ObjectId.hh"
#include "Error.hh"
namespace sta {
template <class TYPE>
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 TYPE>
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<TYPE> *makeBlock(uint32_t size);
void pushBlock(ArrayBlock<TYPE> *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<ArrayBlock<TYPE>**> blocks_;
// Linked list of free arrays indexed by array size.
std::vector<ObjectId> free_list_;
static constexpr ObjectId idx_mask_ = block_size - 1;
};
template <class TYPE>
ArrayTable<TYPE>::ArrayTable() :
size_(0),
free_block_idx_(block_idx_null),
free_idx_(object_idx_null),
blocks_size_(0),
blocks_capacity_(1024),
blocks_(new ArrayBlock<TYPE>*[blocks_capacity_])
{
}
template <class TYPE>
ArrayTable<TYPE>::~ArrayTable()
{
deleteBlocks();
delete [] blocks_;
}
template <class TYPE>
void
ArrayTable<TYPE>::deleteBlocks()
{
for (size_t i = 0; i < blocks_size_; i++)
delete blocks_[i];
}
template <class TYPE>
void
ArrayTable<TYPE>::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<ObjectId*>(array);
free_list_[count] = *head;
}
else {
ArrayBlock<TYPE> *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 <class TYPE>
ArrayBlock<TYPE> *
ArrayTable<TYPE>::makeBlock(uint32_t size)
{
BlockIdx block_idx = blocks_size_;
ArrayBlock<TYPE> *block = new ArrayBlock<TYPE>(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 <class TYPE>
void
ArrayTable<TYPE>::pushBlock(ArrayBlock<TYPE> *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<TYPE>** new_blocks = new ArrayBlock<TYPE>*[new_capacity];
memcpy(new_blocks, blocks_, blocks_capacity_ * sizeof(ArrayBlock<TYPE>*));
blocks_ = new_blocks;
blocks_capacity_ = new_capacity;
}
}
template <class TYPE>
void
ArrayTable<TYPE>::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<ObjectId*>(array);
*head = free_list_[count];
free_list_[count] = id;
size_ -= count;
}
template <class TYPE>
TYPE *
ArrayTable<TYPE>::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 <class TYPE>
TYPE *
ArrayTable<TYPE>::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<TYPE> *block = new ArrayBlock<TYPE>(block_size);
pushBlock(block);
}
return blocks_[blk_idx]->pointer(obj_idx);
}
template <class TYPE>
TYPE &
ArrayTable<TYPE>::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 <class TYPE>
void
ArrayTable<TYPE>::clear()
{
deleteBlocks();
blocks_size_ = 0;
size_ = 0;
free_block_idx_ = block_idx_null;
free_idx_ = object_idx_null;
free_list_.clear();
}
////////////////////////////////////////////////////////////////
template <class TYPE>
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 <class TYPE>
ArrayBlock<TYPE>::ArrayBlock(uint32_t size) :
size_(size),
objects_(new TYPE[size])
{
}
template <class TYPE>
ArrayBlock<TYPE>::~ArrayBlock()
{
delete [] objects_;
}
} // Namespace

View File

@ -31,7 +31,6 @@
#include "Map.hh" #include "Map.hh"
#include "Vector.hh" #include "Vector.hh"
#include "ObjectTable.hh" #include "ObjectTable.hh"
#include "ArrayTable.hh"
#include "LibertyClass.hh" #include "LibertyClass.hh"
#include "NetworkClass.hh" #include "NetworkClass.hh"
#include "Delay.hh" #include "Delay.hh"
@ -47,25 +46,16 @@ class Sdc;
enum class LevelColor { white, gray, black }; enum class LevelColor { white, gray, black };
typedef ArrayTable<Delay> DelayTable;
typedef ObjectTable<Vertex> VertexTable; typedef ObjectTable<Vertex> VertexTable;
typedef ObjectTable<Edge> EdgeTable; typedef ObjectTable<Edge> EdgeTable;
typedef ArrayTable<Arrival> ArrivalsTable;
typedef ArrayTable<Required> RequiredsTable;
typedef ArrayTable<PathVertexRep> PrevPathsTable;
typedef Map<const Pin*, Vertex*> PinVertexMap; typedef Map<const Pin*, Vertex*> PinVertexMap;
typedef Iterator<Edge*> VertexEdgeIterator; typedef Iterator<Edge*> VertexEdgeIterator;
typedef Map<const Pin*, float*, PinIdLess> PeriodCheckAnnotations; typedef Map<const Pin*, float*, PinIdLess> PeriodCheckAnnotations;
typedef Vector<DelayTable*> DelayTableSeq;
typedef ObjectId EdgeId; typedef ObjectId EdgeId;
typedef ObjectId ArrivalId;
typedef ObjectId PrevPathId;
static constexpr EdgeId edge_id_null = object_id_null; static constexpr EdgeId edge_id_null = object_id_null;
static constexpr ObjectIdx edge_idx_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 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. // The graph acts as a BUILDER for the graph vertices and edges.
class Graph : public StaState class Graph : public StaState
@ -78,17 +68,17 @@ public:
// ap_count is the dcalc analysis point count. // ap_count is the dcalc analysis point count.
Graph(StaState *sta, Graph(StaState *sta,
int slew_rf_count, int slew_rf_count,
bool have_arc_delays,
DcalcAPIndex ap_count); DcalcAPIndex ap_count);
void makeGraph(); void makeGraph();
virtual ~Graph(); ~Graph();
// Number of arc delays and slews from sdf or delay calculation. // 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. // Vertex functions.
// Bidirect pins have two vertices. // Bidirect pins have two vertices.
virtual Vertex *vertex(VertexId vertex_id) const; Vertex *vertex(VertexId vertex_id) const;
VertexId id(const Vertex *vertex) const; VertexId id(const Vertex *vertex) const;
void makePinVertices(Pin *pin); void makePinVertices(Pin *pin);
void makePinVertices(Pin *pin, void makePinVertices(Pin *pin,
@ -103,56 +93,49 @@ public:
Vertex *pinDrvrVertex(const Pin *pin) const; Vertex *pinDrvrVertex(const Pin *pin) const;
// Load vertex for bidirects. // Load vertex for bidirects.
Vertex *pinLoadVertex(const Pin *pin) const; Vertex *pinLoadVertex(const Pin *pin) const;
virtual void deleteVertex(Vertex *vertex); void deleteVertex(Vertex *vertex);
bool hasFaninOne(Vertex *vertex) const; bool hasFaninOne(Vertex *vertex) const;
VertexId vertexCount() { return vertices_->size(); } VertexId vertexCount() { return vertices_->size(); }
Arrival *makeArrivals(Vertex *vertex, Arrival *makeArrivals(Vertex *vertex,
uint32_t count); uint32_t count);
Arrival *arrivals(Vertex *vertex); Arrival *arrivals(const Vertex *vertex) const;
void deleteArrivals(Vertex *vertex, void deleteArrivals(Vertex *vertex);
uint32_t count);
Required *makeRequireds(Vertex *vertex, Required *makeRequireds(Vertex *vertex,
uint32_t count); uint32_t count);
Required *requireds(Vertex *vertex); Required *requireds(const Vertex *vertex) const;
void deleteRequireds(Vertex *vertex, void deleteRequireds(Vertex *vertex);
uint32_t count);
PathVertexRep *makePrevPaths(Vertex *vertex, PathVertexRep *makePrevPaths(Vertex *vertex,
uint32_t count); uint32_t count);
PathVertexRep *prevPaths(Vertex *vertex) const; PathVertexRep *prevPaths(const Vertex *vertex) const;
void deletePrevPaths(Vertex *vertex, void deletePrevPaths(Vertex *vertex);
uint32_t count);
// Private to Search::deletePaths().
void deletePaths();
// Private to Search::deletePaths(Vertex). // Private to Search::deletePaths(Vertex).
void deletePaths(Vertex *vertex, void deletePaths(Vertex *vertex);
uint32_t count);
// Reported slew are the same as those in the liberty tables. // Reported slew are the same as those in the liberty tables.
// reported_slews = measured_slews / slew_derate_from_library // reported_slews = measured_slews / slew_derate_from_library
// Measured slews are between slew_lower_threshold and slew_upper_threshold. // Measured slews are between slew_lower_threshold and slew_upper_threshold.
virtual const Slew &slew(const Vertex *vertex, const Slew &slew(const Vertex *vertex,
const RiseFall *rf, const RiseFall *rf,
DcalcAPIndex ap_index); DcalcAPIndex ap_index);
virtual void setSlew(Vertex *vertex, void setSlew(Vertex *vertex,
const RiseFall *rf, const RiseFall *rf,
DcalcAPIndex ap_index, DcalcAPIndex ap_index,
const Slew &slew); const Slew &slew);
SlewSeq slews(Vertex *vertex);
// Edge functions. // Edge functions.
virtual Edge *edge(EdgeId edge_index) const; Edge *edge(EdgeId edge_index) const;
EdgeId id(const Edge *edge) const; EdgeId id(const Edge *edge) const;
virtual Edge *makeEdge(Vertex *from, Edge *makeEdge(Vertex *from,
Vertex *to, Vertex *to,
TimingArcSet *arc_set); TimingArcSet *arc_set);
virtual void makeWireEdge(const Pin *from_pin, void makeWireEdge(const Pin *from_pin,
const Pin *to_pin); const Pin *to_pin);
void makePinInstanceEdges(const Pin *pin); void makePinInstanceEdges(const Pin *pin);
void makeInstanceEdges(const Instance *inst); void makeInstanceEdges(const Instance *inst);
void makeWireEdgesToPin(const Pin *to_pin); void makeWireEdgesToPin(const Pin *to_pin);
void makeWireEdgesThruPin(const Pin *hpin); void makeWireEdgesThruPin(const Pin *hpin);
virtual void makeWireEdgesFromPin(const Pin *drvr_pin); void makeWireEdgesFromPin(const Pin *drvr_pin);
virtual void deleteEdge(Edge *edge); void deleteEdge(Edge *edge);
// Find the edge and timing arc on a gate between in_pin and drvr_pin. // Find the edge and timing arc on a gate between in_pin and drvr_pin.
void gateEdgeArc(const Pin *in_pin, void gateEdgeArc(const Pin *in_pin,
const RiseFall *in_rf, const RiseFall *in_rf,
@ -162,18 +145,18 @@ public:
Edge *&edge, Edge *&edge,
const TimingArc *&arc) const; const TimingArc *&arc) const;
virtual ArcDelay arcDelay(const Edge *edge, ArcDelay arcDelay(const Edge *edge,
const TimingArc *arc, const TimingArc *arc,
DcalcAPIndex ap_index) const; DcalcAPIndex ap_index) const;
virtual void setArcDelay(Edge *edge, void setArcDelay(Edge *edge,
const TimingArc *arc, const TimingArc *arc,
DcalcAPIndex ap_index, DcalcAPIndex ap_index,
ArcDelay delay); ArcDelay delay);
// Alias for arcDelays using library wire arcs. // Alias for arcDelays using library wire arcs.
virtual const ArcDelay &wireArcDelay(const Edge *edge, const ArcDelay &wireArcDelay(const Edge *edge,
const RiseFall *rf, const RiseFall *rf,
DcalcAPIndex ap_index); DcalcAPIndex ap_index);
virtual void setWireArcDelay(Edge *edge, void setWireArcDelay(Edge *edge,
const RiseFall *rf, const RiseFall *rf,
DcalcAPIndex ap_index, DcalcAPIndex ap_index,
const ArcDelay &delay); const ArcDelay &delay);
@ -185,7 +168,7 @@ public:
const TimingArc *arc, const TimingArc *arc,
DcalcAPIndex ap_index, DcalcAPIndex ap_index,
bool annotated); bool annotated);
bool wireDelayAnnotated(Edge *edge, bool wireDelayAnnotated(const Edge *edge,
const RiseFall *rf, const RiseFall *rf,
DcalcAPIndex ap_index) const; DcalcAPIndex ap_index) const;
void setWireDelayAnnotated(Edge *edge, void setWireDelayAnnotated(Edge *edge,
@ -194,8 +177,6 @@ public:
bool annotated); bool annotated);
// True if any edge arc is annotated. // True if any edge arc is annotated.
bool delayAnnotated(Edge *edge); bool delayAnnotated(Edge *edge);
int edgeCount() { return edges_->size(); }
virtual int arcCount() { return arc_count_; }
void minPulseWidthArc(Vertex *vertex, void minPulseWidthArc(Vertex *vertex,
const RiseFall *hi_low, const RiseFall *hi_low,
@ -211,6 +192,7 @@ public:
void setPeriodCheckAnnotation(const Pin *pin, void setPeriodCheckAnnotation(const Pin *pin,
DcalcAPIndex ap_index, DcalcAPIndex ap_index,
float period); float period);
// Remove all delay and slew annotations. // Remove all delay and slew annotations.
void removeDelaySlewAnnotations(); void removeDelaySlewAnnotations();
VertexSet *regClkVertices() { return reg_clk_vertices_; } VertexSet *regClkVertices() { return reg_clk_vertices_; }
@ -223,29 +205,27 @@ protected:
Vertex *makeVertex(Pin *pin, Vertex *makeVertex(Pin *pin,
bool is_bidirect_drvr, bool is_bidirect_drvr,
bool is_reg_clk); bool is_reg_clk);
virtual void makeEdgeArcDelays(Edge *edge); void makeEdgeArcDelays(Edge *edge);
void makePinVertices(const Instance *inst); void makePinVertices(const Instance *inst);
void makeWireEdgesFromPin(const Pin *drvr_pin, void makeWireEdgesFromPin(const Pin *drvr_pin,
PinSet &visited_drvrs); PinSet &visited_drvrs);
bool isIsolatedNet(PinSeq &drvrs, bool isIsolatedNet(PinSeq &drvrs,
PinSeq &loads) const; PinSeq &loads) const;
void makeWireEdges(); void makeWireEdges();
virtual void makeInstDrvrWireEdges(const Instance *inst, void makeInstDrvrWireEdges(const Instance *inst,
PinSet &visited_drvrs); PinSet &visited_drvrs);
virtual void makePortInstanceEdges(const Instance *inst, void makePortInstanceEdges(const Instance *inst,
LibertyCell *cell, LibertyCell *cell,
LibertyPort *from_to_port); LibertyPort *from_to_port);
void removePeriodCheckAnnotations(); void removePeriodCheckAnnotations();
void makeSlewTables(DcalcAPIndex count);
void deleteSlewTables();
void makeVertexSlews(Vertex *vertex); void makeVertexSlews(Vertex *vertex);
void makeArcDelayTables(DcalcAPIndex ap_count);
void deleteArcDelayTables();
void deleteInEdge(Vertex *vertex, void deleteInEdge(Vertex *vertex,
Edge *edge); Edge *edge);
void deleteOutEdge(Vertex *vertex, void deleteOutEdge(Vertex *vertex,
Edge *edge); Edge *edge);
void removeDelays(); void initSlews();
void initSlews(Vertex *vertex);
void initArcDelays(Edge *edge);
void removeDelayAnnotated(Edge *edge); void removeDelayAnnotated(Edge *edge);
VertexTable *vertices_; VertexTable *vertices_;
@ -255,20 +235,8 @@ protected:
// driver/source (top level input, instance pin output) vertex // driver/source (top level input, instance pin output) vertex
// in pin_bidirect_drvr_vertex_map // in pin_bidirect_drvr_vertex_map
PinVertexMap 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<bool> arc_delay_annotated_;
int slew_rf_count_; int slew_rf_count_;
bool have_arc_delays_;
DcalcAPIndex ap_count_; 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. // Sdf period check annotations.
PeriodCheckAnnotations *period_check_annotations_; PeriodCheckAnnotations *period_check_annotations_;
// Register/latch clock vertices to search from. // Register/latch clock vertices to search from.
@ -286,6 +254,7 @@ class Vertex
{ {
public: public:
Vertex(); Vertex();
~Vertex();
Pin *pin() const { return pin_; } Pin *pin() const { return pin_; }
// Pin path with load/driver suffix for bidirects. // Pin path with load/driver suffix for bidirects.
const char *name(const Network *network) const; const char *name(const Network *network) const;
@ -298,11 +267,12 @@ public:
bool hasFanout() const; bool hasFanout() const;
LevelColor color() const { return static_cast<LevelColor>(color_); } LevelColor color() const { return static_cast<LevelColor>(color_); }
void setColor(LevelColor color); void setColor(LevelColor color);
ArrivalId arrivals() { return arrivals_; } Slew *slews() { return slews_; }
ArrivalId requireds() { return requireds_; } const Slew *slews() const { return slews_; }
bool hasRequireds() const { return requireds_ != arrival_null; } Arrival *arrivals() const { return arrivals_; }
PrevPathId prevPaths() const { return prev_paths_; } Arrival *requireds() const { return requireds_; }
void setPrevPaths(PrevPathId id); PathVertexRep *prevPaths() const { return prev_paths_; }
void setPrevPaths(PathVertexRep *prev_paths);
TagGroupIndex tagGroupIndex() const; TagGroupIndex tagGroupIndex() const;
void setTagGroupIndex(TagGroupIndex tag_index); void setTagGroupIndex(TagGroupIndex tag_index);
// Slew is annotated by sdc set_annotated_transition cmd. // Slew is annotated by sdc set_annotated_transition cmd.
@ -341,6 +311,7 @@ public:
bool isRegClk() const { return is_reg_clk_; } bool isRegClk() const { return is_reg_clk_; }
bool crprPathPruningDisabled() const { return crpr_path_pruning_disabled_;} bool crprPathPruningDisabled() const { return crpr_path_pruning_disabled_;}
void setCrprPathPruningDisabled(bool disabled); void setCrprPathPruningDisabled(bool disabled);
bool hasRequireds() const { return requireds_ != nullptr; }
bool requiredsPruned() const { return requireds_pruned_; } bool requiredsPruned() const { return requireds_pruned_; }
void setRequiredsPruned(bool pruned); void setRequiredsPruned(bool pruned);
@ -354,22 +325,30 @@ protected:
void init(Pin *pin, void init(Pin *pin,
bool is_bidirect_drvr, bool is_bidirect_drvr,
bool is_reg_clk); bool is_reg_clk);
void setArrivals(ArrivalId id); void clear();
void setRequireds(ArrivalId id); void setArrivals(Arrival *arrivals);
void setRequireds(Required *requireds);
void setSlews(Slew *slews);
Pin *pin_; Pin *pin_;
ArrivalId arrivals_;
ArrivalId requireds_;
PrevPathId prev_paths_;
EdgeId in_edges_; // Edges to this vertex. EdgeId in_edges_; // Edges to this vertex.
EdgeId out_edges_; // Edges from this vertex. EdgeId out_edges_; // Edges from this vertex.
// 28 bits // Delay calc
unsigned int tag_group_index_:tag_group_index_bits; // 24 Slew *slews_;
unsigned int slew_annotated_:slew_annotated_bits; // 4 // 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<uint8_t> bfs_in_queue_; // 4
// 32 bits
unsigned int level_:Graph::vertex_level_bits; // 24 unsigned int level_:Graph::vertex_level_bits; // 24
unsigned int slew_annotated_:slew_annotated_bits; // 4
// Levelization search state. // Levelization search state.
// LevelColor gcc barfs if this is dcl'd. // LevelColor gcc barfs if this is dcl'd.
unsigned color_:2; unsigned color_:2;
@ -379,11 +358,6 @@ protected:
// This flag distinguishes the driver and load vertices. // This flag distinguishes the driver and load vertices.
bool is_bidirect_drvr_:1; bool is_bidirect_drvr_:1;
bool is_reg_clk_:1; bool is_reg_clk_:1;
// Each bit corresponds to a different BFS queue.
std::atomic<uint8_t> bfs_in_queue_; // 4
// 15 bits
bool is_disabled_constraint_:1; bool is_disabled_constraint_:1;
bool is_gated_clk_enable_:1; bool is_gated_clk_enable_:1;
// Constrained by timing check edge. // Constrained by timing check edge.
@ -409,6 +383,7 @@ class Edge
{ {
public: public:
Edge(); Edge();
~Edge();
Vertex *to(const Graph *graph) const { return graph->vertex(to_); } Vertex *to(const Graph *graph) const { return graph->vertex(to_); }
Vertex *from(const Graph *graph) const { return graph->vertex(from_); } Vertex *from(const Graph *graph) const { return graph->vertex(from_); }
TimingRole *role() const; TimingRole *role() const;
@ -416,9 +391,9 @@ public:
TimingSense sense() const; TimingSense sense() const;
TimingArcSet *timingArcSet() const { return arc_set_; } TimingArcSet *timingArcSet() const { return arc_set_; }
void setTimingArcSet(TimingArcSet *set); void setTimingArcSet(TimingArcSet *set);
ArcId arcDelays() const { return arc_delays_; } ArcDelay *arcDelays() const { return arc_delays_; }
void setArcDelays(ArcId arc_delays); void setArcDelays(ArcDelay *arc_delays);
bool delayAnnotationIsIncremental() const; bool delay_Annotation_Is_Incremental() const {return delay_annotation_is_incremental_;};
void setDelayAnnotationIsIncremental(bool is_incr); void setDelayAnnotationIsIncremental(bool is_incr);
// Edge is disabled by set_disable_timing constraint. // Edge is disabled by set_disable_timing constraint.
bool isDisabledConstraint() const; bool isDisabledConstraint() const;
@ -438,6 +413,7 @@ public:
void setIsBidirectInstPath(bool is_bidir); void setIsBidirectInstPath(bool is_bidir);
bool isBidirectNetPath() const { return is_bidirect_net_path_; } bool isBidirectNetPath() const { return is_bidirect_net_path_; }
void setIsBidirectNetPath(bool is_bidir); void setIsBidirectNetPath(bool is_bidir);
void removeDelayAnnotated();
// ObjectTable interface. // ObjectTable interface.
ObjectIdx objectIdx() const { return object_idx_; } ObjectIdx objectIdx() const { return object_idx_; }
@ -447,6 +423,14 @@ protected:
void init(VertexId from, void init(VertexId from,
VertexId to, VertexId to,
TimingArcSet *arc_set); 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_; TimingArcSet *arc_set_;
VertexId from_; VertexId from_;
@ -454,8 +438,12 @@ protected:
EdgeId vertex_in_link_; // Vertex in edges list. EdgeId vertex_in_link_; // Vertex in edges list.
EdgeId vertex_out_next_; // Vertex out edges doubly linked list. EdgeId vertex_out_next_; // Vertex out edges doubly linked list.
EdgeId vertex_out_prev_; EdgeId vertex_out_prev_;
ArcId arc_delays_; ArcDelay *arc_delays_;
// 16 bits union {
uintptr_t bits_;
vector<bool> *seq_;
} arc_delay_annotated_;
bool arc_delay_annotated_is_bits_:1;
bool delay_annotation_is_incremental_:1; bool delay_annotation_is_incremental_:1;
bool is_bidirect_inst_path_:1; bool is_bidirect_inst_path_:1;
bool is_bidirect_net_path_:1; bool is_bidirect_net_path_:1;

View File

@ -49,7 +49,6 @@ class VertexSet;
typedef ObjectId VertexId; typedef ObjectId VertexId;
typedef ObjectId EdgeId; typedef ObjectId EdgeId;
typedef ObjectId ArcId;
typedef Vector<Vertex*> VertexSeq; typedef Vector<Vertex*> VertexSeq;
typedef Vector<Edge*> EdgeSeq; typedef Vector<Edge*> EdgeSeq;
typedef Set<Edge*> EdgeSet; typedef Set<Edge*> EdgeSet;

View File

@ -173,7 +173,6 @@ void
ObjectTable<TYPE>::destroy(TYPE *object) ObjectTable<TYPE>::destroy(TYPE *object)
{ {
ObjectId object_id = objectId(object); ObjectId object_id = objectId(object);
object->~TYPE();
size_--; size_--;
freePush(object, object_id); freePush(object, object_id);
} }

View File

@ -383,7 +383,8 @@ protected:
bool report_max, bool report_max,
DcalcAnalysisPt *dcalc_ap_min, DcalcAnalysisPt *dcalc_ap_min,
DcalcAnalysisPt *dcalc_ap_max); DcalcAnalysisPt *dcalc_ap_max);
virtual void deleteTags(); void deleteTags();
void deleteTagsPrev();
void seedInvalidArrivals(); void seedInvalidArrivals();
void seedArrivals(); void seedArrivals();
void findClockVertices(VertexSet &vertices); void findClockVertices(VertexSet &vertices);
@ -593,12 +594,14 @@ protected:
// Entries in tags_ may be missing where previous filter tags were deleted. // Entries in tags_ may be missing where previous filter tags were deleted.
TagIndex tag_capacity_; TagIndex tag_capacity_;
std::atomic<Tag **> tags_; std::atomic<Tag **> tags_;
vector<Tag **> tags_prev_;
TagIndex tag_next_; TagIndex tag_next_;
// Holes in tags_ left by deleting filter tags. // Holes in tags_ left by deleting filter tags.
std::vector<TagIndex> tag_free_indices_; std::vector<TagIndex> tag_free_indices_;
std::mutex tag_lock_; std::mutex tag_lock_;
TagGroupSet *tag_group_set_; TagGroupSet *tag_group_set_;
std::atomic<TagGroup **> tag_groups_; std::atomic<TagGroup **> tag_groups_;
vector<TagGroup **> tag_groups_prev_;
TagGroupIndex tag_group_next_; TagGroupIndex tag_group_next_;
// Holes in tag_groups_ left by deleting filter tag groups. // Holes in tag_groups_ left by deleting filter tag groups.
std::vector<TagIndex> tag_group_free_indices_; std::vector<TagIndex> tag_group_free_indices_;

View File

@ -269,7 +269,6 @@ proc check_unit { unit key suffix key_var } {
if { [string match -nocase $arg_suffix $suffix] } { if { [string match -nocase $arg_suffix $suffix] } {
set arg_prefix [string range $value 0 end-$suffix_length] set arg_prefix [string range $value 0 end-$suffix_length]
if { [regexp "^(10*)?(\[Mkmunpf\])?$" $arg_prefix ignore mult prefix] } { if { [regexp "^(10*)?(\[Mkmunpf\])?$" $arg_prefix ignore mult prefix] } {
#puts "$arg_prefix '$mult' '$prefix'"
if { $mult == "" } { if { $mult == "" } {
set mult 1 set mult 1
} }

View File

@ -408,7 +408,11 @@ Search::deletePaths()
{ {
debugPrint(debug_, "search", 1, "delete paths"); debugPrint(debug_, "search", 1, "delete paths");
if (arrivals_exist_) { if (arrivals_exist_) {
graph_->deletePaths(); VertexIterator vertex_iter(graph_);
while (vertex_iter.hasNext()) {
Vertex *vertex = vertex_iter.next();
deletePaths(vertex);
}
filtered_arrivals_->clear(); filtered_arrivals_->clear();
arrivals_exist_ = false; arrivals_exist_ = false;
} }
@ -428,10 +432,8 @@ void
Search::deletePaths(Vertex *vertex) Search::deletePaths(Vertex *vertex)
{ {
TagGroup *tag_group = tagGroup(vertex); TagGroup *tag_group = tagGroup(vertex);
if (tag_group) { if (tag_group)
int arrival_count = tag_group->arrivalCount(); graph_->deletePaths(vertex);
graph_->deletePaths(vertex, arrival_count);
}
} }
//////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////
@ -613,11 +615,25 @@ Search::findFilteredArrivals(bool thru_latches)
debugPrint(debug_, "search", 1, "find arrivals pass %d", pass); debugPrint(debug_, "search", 1, "find arrivals pass %d", pass);
int arrival_count = arrival_iter_->visitParallel(max_level, int arrival_count = arrival_iter_->visitParallel(max_level,
arrival_visitor_); arrival_visitor_);
deleteTagsPrev();
debugPrint(debug_, "search", 1, "found %d arrivals", arrival_count); debugPrint(debug_, "search", 1, "found %d arrivals", arrival_count);
} }
arrivals_exist_ = true; 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 VertexSeq
Search::filteredEndpoints() Search::filteredEndpoints()
{ {
@ -853,6 +869,7 @@ Search::findClkArrivals()
ClkArrivalSearchPred search_clk(this); ClkArrivalSearchPred search_clk(this);
arrival_visitor_->init(false, &search_clk); arrival_visitor_->init(false, &search_clk);
arrival_iter_->visitParallel(levelize_->maxLevel(), arrival_visitor_); arrival_iter_->visitParallel(levelize_->maxLevel(), arrival_visitor_);
deleteTagsPrev();
arrivals_exist_ = true; arrivals_exist_ = true;
stats.report("Find clk arrivals"); stats.report("Find clk arrivals");
} }
@ -1023,6 +1040,7 @@ Search::findArrivals1(Level level)
findArrivalsSeed(); findArrivalsSeed();
Stats stats(debug_, report_); Stats stats(debug_, report_);
int arrival_count = arrival_iter_->visitParallel(level, arrival_visitor_); int arrival_count = arrival_iter_->visitParallel(level, arrival_visitor_);
deleteTagsPrev();
stats.report("Find arrivals"); stats.report("Find arrivals");
if (arrival_iter_->empty() if (arrival_iter_->empty()
&& invalid_arrivals_->empty()) { && invalid_arrivals_->empty()) {
@ -2671,6 +2689,7 @@ Search::findTagGroup(TagGroupBldr *tag_bldr)
TagGroup **tag_groups = new TagGroup*[tag_capacity]; TagGroup **tag_groups = new TagGroup*[tag_capacity];
memcpy(tag_groups, tag_groups_, memcpy(tag_groups, tag_groups_,
tag_group_capacity_ * sizeof(TagGroup*)); tag_group_capacity_ * sizeof(TagGroup*));
tag_groups_prev_.push_back(tag_groups_);
tag_groups_ = tag_groups; tag_groups_ = tag_groups;
tag_group_capacity_ = tag_capacity; tag_group_capacity_ = tag_capacity;
tag_group_set_->reserve(tag_capacity); tag_group_set_->reserve(tag_capacity);
@ -2705,7 +2724,7 @@ Search::setVertexArrivals(Vertex *vertex,
else { else {
// Prev paths not required. // Prev paths not required.
prev_paths = nullptr; prev_paths = nullptr;
graph_->deletePrevPaths(vertex, arrival_count); graph_->deletePrevPaths(vertex);
} }
tag_bldr->copyArrivals(tag_group, prev_arrivals, prev_paths); tag_bldr->copyArrivals(tag_group, prev_arrivals, prev_paths);
vertex->setTagGroupIndex(tag_group->index()); vertex->setTagGroupIndex(tag_group->index());
@ -2718,16 +2737,15 @@ Search::setVertexArrivals(Vertex *vertex,
requiredInvalid(vertex); requiredInvalid(vertex);
if (tag_group != prev_tag_group) if (tag_group != prev_tag_group)
// Requireds can only be reused if the tag group is unchanged. // Requireds can only be reused if the tag group is unchanged.
graph_->deleteRequireds(vertex, prev_tag_group->arrivalCount()); graph_->deleteRequireds(vertex);
} }
} }
else { else {
if (prev_tag_group) { if (prev_tag_group) {
uint32_t prev_arrival_count = prev_tag_group->arrivalCount(); graph_->deleteArrivals(vertex);
graph_->deleteArrivals(vertex, prev_arrival_count);
if (has_requireds) { if (has_requireds) {
requiredInvalid(vertex); requiredInvalid(vertex);
graph_->deleteRequireds(vertex, prev_arrival_count); graph_->deleteRequireds(vertex);
} }
} }
Arrival *arrivals = graph_->makeArrivals(vertex, arrival_count); Arrival *arrivals = graph_->makeArrivals(vertex, arrival_count);
@ -2907,6 +2925,7 @@ Search::findTag(const RiseFall *rf,
TagIndex tag_capacity = tag_capacity_ * 2; TagIndex tag_capacity = tag_capacity_ * 2;
Tag **tags = new Tag*[tag_capacity]; Tag **tags = new Tag*[tag_capacity];
memcpy(tags, tags_, tag_capacity_ * sizeof(Tag*)); memcpy(tags, tags_, tag_capacity_ * sizeof(Tag*));
tags_prev_.push_back(tags_);
tags_ = tags; tags_ = tags;
tag_capacity_ = tag_capacity; tag_capacity_ = tag_capacity;
tag_set_->reserve(tag_capacity); tag_set_->reserve(tag_capacity);
@ -3151,6 +3170,7 @@ Search::findRequireds(Level level)
seedRequireds(); seedRequireds();
seedInvalidRequireds(); seedInvalidRequireds();
int required_count = required_iter_->visitParallel(level, &req_visitor); int required_count = required_iter_->visitParallel(level, &req_visitor);
deleteTagsPrev();
requireds_exist_ = true; requireds_exist_ = true;
debugPrint(debug_, "search", 1, "found %d requireds", required_count); debugPrint(debug_, "search", 1, "found %d requireds", required_count);
stats.report("Find requireds"); stats.report("Find requireds");
@ -3436,8 +3456,7 @@ RequiredCmp::requiredsSave(Vertex *vertex,
if (tag_group == nullptr) if (tag_group == nullptr)
requireds_changed = true; requireds_changed = true;
else { else {
int arrival_count = tag_group->arrivalCount(); graph->deleteRequireds(vertex);
graph->deleteRequireds(vertex, arrival_count);
requireds_changed = true; requireds_changed = true;
} }
} }

View File

@ -3475,7 +3475,7 @@ Sta::ensureGraph()
void void
Sta::makeGraph() Sta::makeGraph()
{ {
graph_ = new Graph(this, 2, true, corners_->dcalcAnalysisPtCount()); graph_ = new Graph(this, 2, corners_->dcalcAnalysisPtCount());
graph_->makeGraph(); graph_->makeGraph();
} }