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:
parent
6a27390dd5
commit
0dfea7dfad
11
README.md
11
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
|
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
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
489
graph/Graph.cc
489
graph/Graph.cc
|
|
@ -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
|
||||||
|
|
|
||||||
|
|
@ -83,12 +83,6 @@ private:
|
||||||
|
|
||||||
%inline %{
|
%inline %{
|
||||||
|
|
||||||
int
|
|
||||||
graph_arc_count()
|
|
||||||
{
|
|
||||||
return Sta::sta()->ensureGraph()->arcCount();
|
|
||||||
}
|
|
||||||
|
|
||||||
VertexIterator *
|
VertexIterator *
|
||||||
vertex_iterator()
|
vertex_iterator()
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -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
|
|
||||||
|
|
@ -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;
|
||||||
|
|
|
||||||
|
|
@ -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;
|
||||||
|
|
|
||||||
|
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -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_;
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -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;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -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();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue