Merge remote-tracking branch 'parallax/master'
Signed-off-by: Matt Liberty <mliberty@precisioninno.com>
This commit is contained in:
commit
6e95d93a44
11
README.md
11
README.md
|
|
@ -65,8 +65,7 @@ compiled locally. Derivative works are supported as long as they
|
|||
adhere to the GPL license requirements. However, OpenSTA is not
|
||||
supported by a public community of developers as many other open
|
||||
source projects are. The copyright and develpment are exclusive to
|
||||
Parallax Software. Contributors must signing the Contributor License
|
||||
Agreement (doc/CLA.txt) when submitting pull requests.
|
||||
Parallax Software.
|
||||
|
||||
Removing copyright and license notices from OpenSTA sources (or any
|
||||
other open source project for that matter) is illegal. This should be
|
||||
|
|
@ -259,8 +258,12 @@ Contributions that claim 4% performance improvements in OpenROAD flow
|
|||
scripts will largely be ignored. Small performance improvements
|
||||
simply do not justify the time requied to audit and verify the changes.
|
||||
|
||||
Contributions that add dependencies on external libraries like boost
|
||||
will not be accepted.
|
||||
Contributions that add dependencies on external libraries like boost,
|
||||
abseil and Intel TBB will not be accepted.
|
||||
|
||||
As the author of OpenSTA I vastly prefer writing code to reviewing
|
||||
code. I don't have the patience to go round after round to correct
|
||||
code formatting that is not consistent with the rest of the code.
|
||||
|
||||
## Authors
|
||||
|
||||
|
|
|
|||
|
|
@ -621,10 +621,15 @@ GraphDelayCalc::findVertexDelay(Vertex *vertex,
|
|||
DrvrLoadSlews
|
||||
GraphDelayCalc::loadSlews(LoadPinIndexMap &load_pin_index_map)
|
||||
{
|
||||
size_t slew_count = graph_->slewCount();
|
||||
DrvrLoadSlews load_slews(load_pin_index_map.size());
|
||||
for (auto const [pin, index] : load_pin_index_map) {
|
||||
Vertex *load_vertex = graph_->pinLoadVertex(pin);
|
||||
load_slews[index] = graph_->slews(load_vertex);
|
||||
SlewSeq &slews = load_slews[index];;
|
||||
slews.resize(slew_count);
|
||||
Slew *vertex_slews = load_vertex->slews();
|
||||
for (size_t i = 0; i < slew_count; i++)
|
||||
slews[i] = vertex_slews[i];
|
||||
}
|
||||
return load_slews;
|
||||
}
|
||||
|
|
@ -633,11 +638,12 @@ bool
|
|||
GraphDelayCalc::loadSlewsChanged(DrvrLoadSlews &load_slews_prev,
|
||||
LoadPinIndexMap &load_pin_index_map)
|
||||
{
|
||||
size_t slew_count = graph_->slewCount();
|
||||
for (auto const [pin, index] : load_pin_index_map) {
|
||||
Vertex *load_vertex = graph_->pinLoadVertex(pin);
|
||||
const SlewSeq slews = graph_->slews(load_vertex);
|
||||
const SlewSeq &slews_prev = load_slews_prev[index];
|
||||
for (size_t i = 0; i < slews.size(); i++) {
|
||||
SlewSeq &slews_prev = load_slews_prev[index];;
|
||||
const Slew *slews = load_vertex->slews();
|
||||
for (size_t i = 0; i < slew_count; i++) {
|
||||
if (!delayEqual(slews[i], slews_prev[i]))
|
||||
return true;
|
||||
}
|
||||
|
|
|
|||
515
graph/Graph.cc
515
graph/Graph.cc
|
|
@ -46,14 +46,11 @@ namespace sta {
|
|||
|
||||
Graph::Graph(StaState *sta,
|
||||
int slew_rf_count,
|
||||
bool have_arc_delays,
|
||||
DcalcAPIndex ap_count) :
|
||||
StaState(sta),
|
||||
vertices_(nullptr),
|
||||
edges_(nullptr),
|
||||
arc_count_(0),
|
||||
slew_rf_count_(slew_rf_count),
|
||||
have_arc_delays_(have_arc_delays),
|
||||
ap_count_(ap_count),
|
||||
period_check_annotations_(nullptr),
|
||||
reg_clk_vertices_(new VertexSet(graph_))
|
||||
|
|
@ -64,11 +61,11 @@ Graph::Graph(StaState *sta,
|
|||
|
||||
Graph::~Graph()
|
||||
{
|
||||
delete vertices_;
|
||||
edges_->clear();
|
||||
delete edges_;
|
||||
vertices_->clear();
|
||||
delete vertices_;
|
||||
delete reg_clk_vertices_;
|
||||
deleteSlewTables();
|
||||
deleteArcDelayTables();
|
||||
removePeriodCheckAnnotations();
|
||||
}
|
||||
|
||||
|
|
@ -90,8 +87,6 @@ Graph::makeVerticesAndEdges()
|
|||
{
|
||||
vertices_ = new VertexTable;
|
||||
edges_ = new EdgeTable;
|
||||
makeSlewTables(ap_count_);
|
||||
makeArcDelayTables(ap_count_);
|
||||
|
||||
LeafInstanceIterator *leaf_iter = network_->leafInstanceIterator();
|
||||
while (leaf_iter->hasNext()) {
|
||||
|
|
@ -440,7 +435,7 @@ Graph::makeVertex(Pin *pin,
|
|||
{
|
||||
Vertex *vertex = vertices_->make();
|
||||
vertex->init(pin, is_bidirect_drvr, is_reg_clk);
|
||||
makeVertexSlews(vertex);
|
||||
initSlews(vertex);
|
||||
if (is_reg_clk)
|
||||
reg_clk_vertices_->insert(vertex);
|
||||
return vertex;
|
||||
|
|
@ -491,7 +486,7 @@ Graph::deleteVertex(Vertex *vertex)
|
|||
Edge *edge = Graph::edge(edge_id);
|
||||
next_id = edge->vertex_in_link_;
|
||||
deleteOutEdge(edge->from(this), edge);
|
||||
arc_count_ -= edge->timingArcSet()->arcCount();
|
||||
edge->clear();
|
||||
edges_->destroy(edge);
|
||||
}
|
||||
// Delete edges from vertex.
|
||||
|
|
@ -499,9 +494,10 @@ Graph::deleteVertex(Vertex *vertex)
|
|||
Edge *edge = Graph::edge(edge_id);
|
||||
next_id = edge->vertex_out_next_;
|
||||
deleteInEdge(edge->to(this), edge);
|
||||
arc_count_ -= edge->timingArcSet()->arcCount();
|
||||
edge->clear();
|
||||
edges_->destroy(edge);
|
||||
}
|
||||
vertex->clear();
|
||||
vertices_->destroy(vertex);
|
||||
}
|
||||
|
||||
|
|
@ -577,155 +573,90 @@ Graph::gateEdgeArc(const Pin *in_pin,
|
|||
|
||||
Arrival *
|
||||
Graph::makeArrivals(Vertex *vertex,
|
||||
uint32_t count)
|
||||
uint32_t count)
|
||||
{
|
||||
if (vertex->arrivals() != arrival_null)
|
||||
debugPrint(debug_, "graph", 1, "arrival leak");
|
||||
Arrival *arrivals;
|
||||
ArrivalId id;
|
||||
{
|
||||
LockGuard lock(arrivals_lock_);
|
||||
arrivals_.make(count, arrivals, id);
|
||||
}
|
||||
vertex->setArrivals(id);
|
||||
Arrival *arrivals = new Arrival[count];
|
||||
vertex->setArrivals(arrivals);
|
||||
return arrivals;
|
||||
}
|
||||
|
||||
Arrival *
|
||||
Graph::arrivals(Vertex *vertex)
|
||||
Graph::arrivals(const Vertex *vertex) const
|
||||
{
|
||||
return arrivals_.pointer(vertex->arrivals());
|
||||
return vertex->arrivals();
|
||||
}
|
||||
|
||||
void
|
||||
Graph::deleteArrivals(Vertex *vertex,
|
||||
uint32_t count)
|
||||
Graph::deleteArrivals(Vertex *vertex)
|
||||
{
|
||||
{
|
||||
LockGuard lock(arrivals_lock_);
|
||||
arrivals_.destroy(vertex->arrivals(), count);
|
||||
}
|
||||
vertex->setArrivals(arrival_null);
|
||||
vertex->setArrivals(nullptr);
|
||||
}
|
||||
|
||||
Required *
|
||||
Graph::requireds(const Vertex *vertex) const
|
||||
{
|
||||
return vertex->requireds();
|
||||
}
|
||||
|
||||
Required *
|
||||
Graph::makeRequireds(Vertex *vertex,
|
||||
uint32_t count)
|
||||
{
|
||||
if (vertex->requireds() != arrival_null)
|
||||
debugPrint(debug_, "graph", 1, "required leak");
|
||||
Required *requireds;
|
||||
ArrivalId id;
|
||||
{
|
||||
LockGuard lock(requireds_lock_);
|
||||
requireds_.make(count, requireds, id);
|
||||
}
|
||||
vertex->setRequireds(id);
|
||||
Required *requireds = new Arrival[count];
|
||||
vertex->setRequireds(requireds);
|
||||
return requireds;
|
||||
}
|
||||
|
||||
Required *
|
||||
Graph::requireds(Vertex *vertex)
|
||||
void
|
||||
Graph::deleteRequireds(Vertex *vertex)
|
||||
{
|
||||
return requireds_.pointer(vertex->requireds());
|
||||
vertex->setRequireds(nullptr);
|
||||
}
|
||||
|
||||
void
|
||||
Graph::deleteRequireds(Vertex *vertex,
|
||||
uint32_t count)
|
||||
PathVertexRep *
|
||||
Graph::prevPaths(const Vertex *vertex) const
|
||||
{
|
||||
{
|
||||
LockGuard lock(requireds_lock_);
|
||||
requireds_.destroy(vertex->requireds(), count);
|
||||
}
|
||||
vertex->setRequireds(arrival_null);
|
||||
return vertex->prevPaths();
|
||||
}
|
||||
|
||||
PathVertexRep *
|
||||
Graph::makePrevPaths(Vertex *vertex,
|
||||
uint32_t count)
|
||||
uint32_t count)
|
||||
{
|
||||
PathVertexRep *prev_paths;
|
||||
PrevPathId id;
|
||||
{
|
||||
LockGuard lock(prev_paths_lock_);
|
||||
prev_paths_.make(count, prev_paths, id);
|
||||
}
|
||||
vertex->setPrevPaths(id);
|
||||
PathVertexRep *prev_paths = new PathVertexRep[count];
|
||||
vertex->setPrevPaths(prev_paths);
|
||||
return prev_paths;
|
||||
}
|
||||
|
||||
PathVertexRep *
|
||||
Graph::prevPaths(Vertex *vertex) const
|
||||
void
|
||||
Graph::deletePrevPaths(Vertex *vertex)
|
||||
{
|
||||
return prev_paths_.pointer(vertex->prevPaths());
|
||||
vertex->setPrevPaths(nullptr);
|
||||
}
|
||||
|
||||
void
|
||||
Graph::deletePrevPaths(Vertex *vertex,
|
||||
uint32_t count)
|
||||
Graph::deletePaths(Vertex *vertex)
|
||||
{
|
||||
if (vertex->prevPaths() != object_id_null) {
|
||||
{
|
||||
LockGuard lock(prev_paths_lock_);
|
||||
prev_paths_.destroy(vertex->prevPaths(), count);
|
||||
}
|
||||
vertex->setPrevPaths(object_id_null);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
Graph::deletePaths()
|
||||
{
|
||||
arrivals_.clear();
|
||||
requireds_.clear();
|
||||
prev_paths_.clear();
|
||||
VertexIterator vertex_iter(graph_);
|
||||
while (vertex_iter.hasNext()) {
|
||||
Vertex *vertex = vertex_iter.next();
|
||||
vertex->setArrivals(arrival_null);
|
||||
vertex->setRequireds(arrival_null);
|
||||
vertex->setPrevPaths(object_id_null);
|
||||
vertex->tag_group_index_ = tag_group_index_max;
|
||||
vertex->crpr_path_pruning_disabled_ = false;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
Graph::deletePaths(Vertex *vertex,
|
||||
uint32_t count)
|
||||
{
|
||||
if (vertex->arrivals() != arrival_null) {
|
||||
LockGuard lock(arrivals_lock_);
|
||||
arrivals_.destroy(vertex->arrivals(), count);
|
||||
vertex->setArrivals(arrival_null);
|
||||
vertex->tag_group_index_ = tag_group_index_max;
|
||||
vertex->crpr_path_pruning_disabled_ = false;
|
||||
}
|
||||
if (vertex->requireds() != arrival_null) {
|
||||
requireds_.destroy(vertex->requireds(), count);
|
||||
vertex->setRequireds(arrival_null);
|
||||
}
|
||||
|
||||
if (vertex->prevPaths() != object_id_null) {
|
||||
prev_paths_.destroy(vertex->prevPaths(), count);
|
||||
vertex->setPrevPaths(object_id_null);
|
||||
}
|
||||
deleteArrivals(vertex);
|
||||
deleteRequireds(vertex);
|
||||
deletePrevPaths(vertex);
|
||||
vertex->tag_group_index_ = tag_group_index_max;
|
||||
vertex->crpr_path_pruning_disabled_ = false;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////
|
||||
|
||||
const Slew &
|
||||
Graph::slew(const Vertex *vertex,
|
||||
const RiseFall *rf,
|
||||
DcalcAPIndex ap_index)
|
||||
const RiseFall *rf,
|
||||
DcalcAPIndex ap_index)
|
||||
{
|
||||
if (slew_rf_count_) {
|
||||
int table_index =
|
||||
(slew_rf_count_ == 1) ? ap_index : ap_index*slew_rf_count_+rf->index();
|
||||
DelayTable *table = slew_tables_[table_index];
|
||||
VertexId vertex_id = id(vertex);
|
||||
return table->ref(vertex_id);
|
||||
const Slew *slews = vertex->slews();
|
||||
size_t slew_index = (slew_rf_count_ == 1)
|
||||
? ap_index
|
||||
: ap_index*slew_rf_count_+rf->index();
|
||||
return slews[slew_index];
|
||||
}
|
||||
else {
|
||||
static Slew slew(0.0);
|
||||
|
|
@ -735,34 +666,24 @@ Graph::slew(const Vertex *vertex,
|
|||
|
||||
void
|
||||
Graph::setSlew(Vertex *vertex,
|
||||
const RiseFall *rf,
|
||||
DcalcAPIndex ap_index,
|
||||
const Slew &slew)
|
||||
const RiseFall *rf,
|
||||
DcalcAPIndex ap_index,
|
||||
const Slew &slew)
|
||||
{
|
||||
if (slew_rf_count_) {
|
||||
int table_index =
|
||||
(slew_rf_count_ == 1) ? ap_index : ap_index*slew_rf_count_+rf->index();
|
||||
DelayTable *table = slew_tables_[table_index];
|
||||
VertexId vertex_id = id(vertex);
|
||||
Slew &vertex_slew = table->ref(vertex_id);
|
||||
vertex_slew = slew;
|
||||
Slew *slews = vertex->slews();
|
||||
if (slews == nullptr) {
|
||||
int slew_count = slew_rf_count_ * ap_count_;
|
||||
slews = new Slew[slew_count];
|
||||
vertex->setSlews(slews);
|
||||
}
|
||||
size_t slew_index = (slew_rf_count_ == 1)
|
||||
? ap_index
|
||||
: ap_index*slew_rf_count_+rf->index();
|
||||
slews[slew_index] = slew;
|
||||
}
|
||||
}
|
||||
|
||||
SlewSeq
|
||||
Graph::slews(Vertex *vertex)
|
||||
{
|
||||
SlewSeq slews;
|
||||
VertexId vertex_id = id(vertex);
|
||||
DcalcAPIndex rf_ap_count = slew_rf_count_ * ap_count_;
|
||||
for (DcalcAPIndex i = 0; i < rf_ap_count; i++) {
|
||||
DelayTable *table = slew_tables_[i];
|
||||
Slew &slew = table->ref(vertex_id);
|
||||
slews.push_back(slew);
|
||||
}
|
||||
return slews;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////
|
||||
|
||||
Edge *
|
||||
|
|
@ -784,8 +705,6 @@ Graph::makeEdge(Vertex *from,
|
|||
{
|
||||
Edge *edge = edges_->make();
|
||||
edge->init(id(from), id(to), arc_set);
|
||||
makeEdgeArcDelays(edge);
|
||||
arc_count_ += arc_set->arcCount();
|
||||
// Add out edge to from vertex.
|
||||
EdgeId next = from->out_edges_;
|
||||
edge->vertex_out_next_ = next;
|
||||
|
|
@ -799,6 +718,7 @@ Graph::makeEdge(Vertex *from,
|
|||
edge->vertex_in_link_ = to->in_edges_;
|
||||
to->in_edges_ = edge_id;
|
||||
|
||||
initArcDelays(edge);
|
||||
return edge;
|
||||
}
|
||||
|
||||
|
|
@ -809,63 +729,18 @@ Graph::deleteEdge(Edge *edge)
|
|||
Vertex *to = edge->to(this);
|
||||
deleteOutEdge(from, edge);
|
||||
deleteInEdge(to, edge);
|
||||
arc_count_ -= edge->timingArcSet()->arcCount();
|
||||
edge->clear();
|
||||
edges_->destroy(edge);
|
||||
}
|
||||
|
||||
void
|
||||
Graph::makeArcDelayTables(DcalcAPIndex ap_count)
|
||||
{
|
||||
if (have_arc_delays_) {
|
||||
arc_delays_.resize(ap_count);
|
||||
for (DcalcAPIndex i = 0; i < ap_count; i++)
|
||||
arc_delays_[i] = new DelayTable();
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
Graph::deleteArcDelayTables()
|
||||
{
|
||||
arc_delays_.deleteContentsClear();
|
||||
}
|
||||
|
||||
void
|
||||
Graph::makeEdgeArcDelays(Edge *edge)
|
||||
{
|
||||
if (have_arc_delays_) {
|
||||
int arc_count = edge->timingArcSet()->arcCount();
|
||||
ArcId arc_id = 0;
|
||||
for (DcalcAPIndex i = 0; i < ap_count_; i++) {
|
||||
DelayTable *table = arc_delays_[i];
|
||||
ArcDelay *arc_delays;
|
||||
table->make(arc_count, arc_delays, arc_id);
|
||||
for (int j = 0; j < arc_count; j++)
|
||||
arc_delays[j] = 0.0;
|
||||
}
|
||||
edge->setArcDelays(arc_id);
|
||||
// Make sure there is room for delay_annotated flags.
|
||||
size_t max_annot_index = (arc_id + arc_count) * ap_count_;
|
||||
if (max_annot_index >= arc_delay_annotated_.size()) {
|
||||
size_t size = max_annot_index * 1.2;
|
||||
arc_delay_annotated_.resize(size);
|
||||
}
|
||||
removeDelayAnnotated(edge);
|
||||
}
|
||||
}
|
||||
|
||||
ArcDelay
|
||||
Graph::arcDelay(const Edge *edge,
|
||||
const TimingArc *arc,
|
||||
DcalcAPIndex ap_index) const
|
||||
{
|
||||
if (have_arc_delays_) {
|
||||
DelayTable *table = arc_delays_[ap_index];
|
||||
ArcDelay *arc_delays = table->pointer(edge->arcDelays());
|
||||
ArcDelay &arc_delay = arc_delays[arc->index()];
|
||||
return arc_delay;
|
||||
}
|
||||
else
|
||||
return delay_zero;
|
||||
ArcDelay *delays = edge->arcDelays();
|
||||
size_t index = arc->index() * ap_count_ + ap_index;
|
||||
return delays[index];
|
||||
}
|
||||
|
||||
void
|
||||
|
|
@ -874,11 +749,9 @@ Graph::setArcDelay(Edge *edge,
|
|||
DcalcAPIndex ap_index,
|
||||
ArcDelay delay)
|
||||
{
|
||||
if (have_arc_delays_) {
|
||||
DelayTable *table = arc_delays_[ap_index];
|
||||
ArcDelay *arc_delays = table->pointer(edge->arcDelays());
|
||||
arc_delays[arc->index()] = delay;
|
||||
}
|
||||
ArcDelay *arc_delays = edge->arcDelays();
|
||||
size_t index = arc->index() * ap_count_ + ap_index;
|
||||
arc_delays[index] = delay;
|
||||
}
|
||||
|
||||
const ArcDelay &
|
||||
|
|
@ -886,13 +759,9 @@ Graph::wireArcDelay(const Edge *edge,
|
|||
const RiseFall *rf,
|
||||
DcalcAPIndex ap_index)
|
||||
{
|
||||
if (have_arc_delays_) {
|
||||
DelayTable *table = arc_delays_[ap_index];
|
||||
ArcDelay *arc_delays = table->pointer(edge->arcDelays());
|
||||
return arc_delays[rf->index()];
|
||||
}
|
||||
else
|
||||
return delay_zero;
|
||||
ArcDelay *delays = edge->arcDelays();
|
||||
size_t index = rf->index() * ap_count_ + ap_index;
|
||||
return delays[index];
|
||||
}
|
||||
|
||||
void
|
||||
|
|
@ -901,26 +770,19 @@ Graph::setWireArcDelay(Edge *edge,
|
|||
DcalcAPIndex ap_index,
|
||||
const ArcDelay &delay)
|
||||
{
|
||||
if (have_arc_delays_) {
|
||||
DelayTable *table = arc_delays_[ap_index];
|
||||
ArcDelay *arc_delays = table->pointer(edge->arcDelays());
|
||||
arc_delays[rf->index()] = delay;
|
||||
}
|
||||
ArcDelay *delays = edge->arcDelays();
|
||||
size_t index = rf->index() * ap_count_ + ap_index;
|
||||
delays[index] = delay;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////
|
||||
|
||||
bool
|
||||
Graph::arcDelayAnnotated(const Edge *edge,
|
||||
const TimingArc *arc,
|
||||
DcalcAPIndex ap_index) const
|
||||
{
|
||||
if (!arc_delay_annotated_.empty()) {
|
||||
size_t index = (edge->arcDelays() + arc->index()) * ap_count_ + ap_index;
|
||||
if (index >= arc_delay_annotated_.size())
|
||||
report_->critical(1080, "arc_delay_annotated array bounds exceeded");
|
||||
return arc_delay_annotated_[index];
|
||||
}
|
||||
else
|
||||
return false;
|
||||
return edge->arcDelayAnnotated(arc, ap_index, ap_count_);
|
||||
}
|
||||
|
||||
void
|
||||
|
|
@ -929,22 +791,17 @@ Graph::setArcDelayAnnotated(Edge *edge,
|
|||
DcalcAPIndex ap_index,
|
||||
bool annotated)
|
||||
{
|
||||
size_t index = (edge->arcDelays() + arc->index()) * ap_count_ + ap_index;
|
||||
if (index >= arc_delay_annotated_.size())
|
||||
report_->critical(1081, "arc_delay_annotated array bounds exceeded");
|
||||
arc_delay_annotated_[index] = annotated;
|
||||
return edge->setArcDelayAnnotated(arc, ap_index, ap_count_, annotated);
|
||||
}
|
||||
|
||||
bool
|
||||
Graph::wireDelayAnnotated(Edge *edge,
|
||||
Graph::wireDelayAnnotated(const Edge *edge,
|
||||
const RiseFall *rf,
|
||||
DcalcAPIndex ap_index) const
|
||||
{
|
||||
size_t index = (edge->arcDelays() + TimingArcSet::wireArcIndex(rf)) * ap_count_
|
||||
+ ap_index;
|
||||
if (index >= arc_delay_annotated_.size())
|
||||
report_->critical(1082, "arc_delay_annotated array bounds exceeded");
|
||||
return arc_delay_annotated_[index];
|
||||
int arc_index = TimingArcSet::wireArcIndex(rf);
|
||||
TimingArc *arc = TimingArcSet::wireTimingArcSet()->findTimingArc(arc_index);
|
||||
return edge->arcDelayAnnotated(arc, ap_index, ap_count_);
|
||||
}
|
||||
|
||||
void
|
||||
|
|
@ -953,13 +810,19 @@ Graph::setWireDelayAnnotated(Edge *edge,
|
|||
DcalcAPIndex ap_index,
|
||||
bool annotated)
|
||||
{
|
||||
size_t index = (edge->arcDelays() + TimingArcSet::wireArcIndex(rf)) * ap_count_
|
||||
+ ap_index;
|
||||
if (index >= arc_delay_annotated_.size())
|
||||
report_->critical(1083, "arc_delay_annotated array bounds exceeded");
|
||||
arc_delay_annotated_[index] = annotated;
|
||||
int arc_index = TimingArcSet::wireArcIndex(rf);
|
||||
TimingArc *arc = TimingArcSet::wireTimingArcSet()->findTimingArc(arc_index);
|
||||
return edge->setArcDelayAnnotated(arc, ap_index, ap_count_, annotated);
|
||||
}
|
||||
|
||||
void
|
||||
Graph::removeDelayAnnotated(Edge *edge)
|
||||
{
|
||||
edge->removeDelayAnnotated();
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////
|
||||
|
||||
// This only gets called if the analysis type changes from single
|
||||
// to bc_wc/ocv or visa versa.
|
||||
void
|
||||
|
|
@ -967,42 +830,53 @@ Graph::setDelayCount(DcalcAPIndex ap_count)
|
|||
{
|
||||
if (ap_count != ap_count_) {
|
||||
// Discard any existing delays.
|
||||
deleteSlewTables();
|
||||
deleteArcDelayTables();
|
||||
removePeriodCheckAnnotations();
|
||||
makeSlewTables(ap_count);
|
||||
makeArcDelayTables(ap_count);
|
||||
ap_count_ = ap_count;
|
||||
removeDelays();
|
||||
initSlews();
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
Graph::removeDelays()
|
||||
Graph::initSlews()
|
||||
{
|
||||
VertexIterator vertex_iter(this);
|
||||
VertexIterator vertex_iter(graph_);
|
||||
while (vertex_iter.hasNext()) {
|
||||
Vertex *vertex = vertex_iter.next();
|
||||
makeVertexSlews(vertex);
|
||||
VertexOutEdgeIterator edge_iter(vertex, this);
|
||||
initSlews(vertex);
|
||||
|
||||
VertexOutEdgeIterator edge_iter(vertex, graph_);
|
||||
while (edge_iter.hasNext()) {
|
||||
Edge *edge = edge_iter.next();
|
||||
makeEdgeArcDelays(edge);
|
||||
removeDelayAnnotated(edge);
|
||||
initArcDelays(edge);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
Graph::removeDelayAnnotated(Edge *edge)
|
||||
Graph::initSlews(Vertex *vertex)
|
||||
{
|
||||
edge->setDelayAnnotationIsIncremental(false);
|
||||
TimingArcSet *arc_set = edge->timingArcSet();
|
||||
for (TimingArc *arc : arc_set->arcs()) {
|
||||
for (DcalcAPIndex ap_index = 0; ap_index < ap_count_; ap_index++) {
|
||||
setArcDelayAnnotated(edge, arc, ap_index, false);
|
||||
}
|
||||
}
|
||||
size_t slew_count = slewCount();
|
||||
Slew *slews = new Slew[slew_count];
|
||||
vertex->setSlews(slews);
|
||||
for (size_t i = 0; i < slew_count; i++)
|
||||
slews[i] = 0.0;
|
||||
}
|
||||
|
||||
size_t
|
||||
Graph::slewCount()
|
||||
{
|
||||
return slew_rf_count_ * ap_count_;
|
||||
}
|
||||
|
||||
void
|
||||
Graph::initArcDelays(Edge *edge)
|
||||
{
|
||||
size_t arc_count = edge->timingArcSet()->arcCount();
|
||||
size_t delay_count = arc_count * ap_count_;
|
||||
ArcDelay *arc_delays = new ArcDelay[delay_count];
|
||||
edge->setArcDelays(arc_delays);
|
||||
for (size_t i = 0; i < delay_count; i++)
|
||||
arc_delays[i] = 0.0;
|
||||
}
|
||||
|
||||
bool
|
||||
|
|
@ -1018,35 +892,6 @@ Graph::delayAnnotated(Edge *edge)
|
|||
return true;
|
||||
}
|
||||
|
||||
void
|
||||
Graph::makeSlewTables(DcalcAPIndex ap_count)
|
||||
{
|
||||
DcalcAPIndex tr_ap_count = slew_rf_count_ * ap_count;
|
||||
slew_tables_.resize(tr_ap_count);
|
||||
for (DcalcAPIndex i = 0; i < tr_ap_count; i++) {
|
||||
DelayTable *table = new DelayTable;
|
||||
slew_tables_[i] = table;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
Graph::deleteSlewTables()
|
||||
{
|
||||
slew_tables_.deleteContentsClear();
|
||||
}
|
||||
|
||||
void
|
||||
Graph::makeVertexSlews(Vertex *vertex)
|
||||
{
|
||||
DcalcAPIndex tr_ap_count = slew_rf_count_ * ap_count_;
|
||||
for (DcalcAPIndex i = 0; i < tr_ap_count; i++) {
|
||||
DelayTable *table = slew_tables_[i];
|
||||
// Slews are 1:1 with vertices and use the same object id.
|
||||
Slew *slew = table->ensureId(vertices_->objectId(vertex));
|
||||
*slew = 0.0;
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////
|
||||
|
||||
void
|
||||
|
|
@ -1161,9 +1006,10 @@ Vertex::init(Pin *pin,
|
|||
is_bidirect_drvr_ = is_bidirect_drvr;
|
||||
in_edges_ = edge_id_null;
|
||||
out_edges_ = edge_id_null;
|
||||
arrivals_ = arrival_null;
|
||||
requireds_ = arrival_null;
|
||||
prev_paths_ = prev_path_null;
|
||||
slews_ = nullptr;
|
||||
arrivals_ = nullptr;
|
||||
requireds_ = nullptr;
|
||||
prev_paths_ = nullptr;
|
||||
tag_group_index_ = tag_group_index_max;
|
||||
slew_annotated_ = false;
|
||||
sim_value_ = unsigned(LogicValue::unknown);
|
||||
|
|
@ -1180,6 +1026,24 @@ Vertex::init(Pin *pin,
|
|||
requireds_pruned_ = false;
|
||||
}
|
||||
|
||||
Vertex::~Vertex()
|
||||
{
|
||||
clear();
|
||||
}
|
||||
|
||||
void
|
||||
Vertex::clear()
|
||||
{
|
||||
delete [] slews_;
|
||||
slews_ = nullptr;
|
||||
delete [] arrivals_;
|
||||
arrivals_ = nullptr;
|
||||
delete [] requireds_;
|
||||
requireds_ = nullptr;
|
||||
delete [] prev_paths_;
|
||||
prev_paths_ = nullptr;
|
||||
}
|
||||
|
||||
void
|
||||
Vertex::setObjectIdx(ObjectIdx idx)
|
||||
{
|
||||
|
|
@ -1228,6 +1092,13 @@ Vertex::setColor(LevelColor color)
|
|||
color_ = unsigned(color);
|
||||
}
|
||||
|
||||
void
|
||||
Vertex::setSlews(Slew *slews)
|
||||
{
|
||||
delete [] slews_;
|
||||
slews_ = slews;
|
||||
}
|
||||
|
||||
bool
|
||||
Vertex::slewAnnotated(const RiseFall *rf,
|
||||
const MinMax *min_max) const
|
||||
|
|
@ -1289,20 +1160,23 @@ Vertex::setTagGroupIndex(TagGroupIndex tag_index)
|
|||
}
|
||||
|
||||
void
|
||||
Vertex::setArrivals(ArrivalId id)
|
||||
Vertex::setArrivals(Arrival *arrivals)
|
||||
{
|
||||
arrivals_ = id;
|
||||
delete [] arrivals_;
|
||||
arrivals_ = arrivals;
|
||||
}
|
||||
|
||||
void
|
||||
Vertex::setRequireds(ArrivalId id)
|
||||
Vertex::setRequireds(Required *requireds)
|
||||
{
|
||||
requireds_ = id;
|
||||
delete [] requireds_;
|
||||
requireds_ = requireds;
|
||||
}
|
||||
|
||||
void
|
||||
Vertex::setPrevPaths(PrevPathId prev_paths)
|
||||
Vertex::setPrevPaths(PathVertexRep *prev_paths)
|
||||
{
|
||||
delete [] prev_paths_;
|
||||
prev_paths_ = prev_paths;
|
||||
}
|
||||
|
||||
|
|
@ -1410,13 +1284,15 @@ Edge::init(VertexId from,
|
|||
from_ = from;
|
||||
to_ = to;
|
||||
arc_set_ = arc_set;
|
||||
arc_delays_ = 0;
|
||||
|
||||
vertex_in_link_ = edge_id_null;
|
||||
vertex_out_next_ = edge_id_null;
|
||||
vertex_out_prev_ = edge_id_null;
|
||||
is_bidirect_inst_path_ = false;
|
||||
is_bidirect_net_path_ = false;
|
||||
|
||||
arc_delays_ = nullptr;
|
||||
arc_delay_annotated_is_bits_ = true;
|
||||
arc_delay_annotated_.bits_ = 0;
|
||||
delay_annotation_is_incremental_ = false;
|
||||
sim_timing_sense_ = unsigned(TimingSense::unknown);
|
||||
is_disabled_constraint_ = false;
|
||||
|
|
@ -1424,6 +1300,22 @@ Edge::init(VertexId from,
|
|||
is_disabled_loop_ = false;
|
||||
}
|
||||
|
||||
Edge::~Edge()
|
||||
{
|
||||
clear();
|
||||
}
|
||||
|
||||
void
|
||||
Edge::clear()
|
||||
{
|
||||
delete [] arc_delays_;
|
||||
arc_delays_ = nullptr;
|
||||
if (!arc_delay_annotated_is_bits_)
|
||||
delete arc_delay_annotated_.seq_;
|
||||
arc_delay_annotated_is_bits_ = true;
|
||||
arc_delay_annotated_.seq_ = nullptr;
|
||||
}
|
||||
|
||||
void
|
||||
Edge::setObjectIdx(ObjectIdx idx)
|
||||
{
|
||||
|
|
@ -1437,15 +1329,56 @@ Edge::setTimingArcSet(TimingArcSet *set)
|
|||
}
|
||||
|
||||
void
|
||||
Edge::setArcDelays(ArcId arc_delays)
|
||||
Edge::setArcDelays(ArcDelay *arc_delays)
|
||||
{
|
||||
delete [] arc_delays_;
|
||||
arc_delays_ = arc_delays;
|
||||
}
|
||||
|
||||
bool
|
||||
Edge::delayAnnotationIsIncremental() const
|
||||
Edge::arcDelayAnnotated(const TimingArc *arc,
|
||||
DcalcAPIndex ap_index,
|
||||
DcalcAPIndex ap_count) const
|
||||
{
|
||||
return delay_annotation_is_incremental_;
|
||||
size_t index = arc->index() * ap_count + ap_index;
|
||||
if (arc_delay_annotated_is_bits_)
|
||||
return arc_delay_annotated_.bits_ & (1 << index);
|
||||
else
|
||||
return (*arc_delay_annotated_.seq_)[index];
|
||||
}
|
||||
|
||||
void
|
||||
Edge::setArcDelayAnnotated(const TimingArc *arc,
|
||||
DcalcAPIndex ap_index,
|
||||
DcalcAPIndex ap_count,
|
||||
bool annotated)
|
||||
{
|
||||
size_t index = arc->index() * ap_count + ap_index;
|
||||
if (index > sizeof(intptr_t) * 8
|
||||
&& arc_delay_annotated_is_bits_) {
|
||||
arc_delay_annotated_is_bits_ = false;
|
||||
arc_delay_annotated_.seq_ = new vector<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
|
||||
|
|
|
|||
|
|
@ -83,12 +83,6 @@ private:
|
|||
|
||||
%inline %{
|
||||
|
||||
int
|
||||
graph_arc_count()
|
||||
{
|
||||
return Sta::sta()->ensureGraph()->arcCount();
|
||||
}
|
||||
|
||||
VertexIterator *
|
||||
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 "Vector.hh"
|
||||
#include "ObjectTable.hh"
|
||||
#include "ArrayTable.hh"
|
||||
#include "LibertyClass.hh"
|
||||
#include "NetworkClass.hh"
|
||||
#include "Delay.hh"
|
||||
|
|
@ -47,25 +46,16 @@ class Sdc;
|
|||
|
||||
enum class LevelColor { white, gray, black };
|
||||
|
||||
typedef ArrayTable<Delay> DelayTable;
|
||||
typedef ObjectTable<Vertex> VertexTable;
|
||||
typedef ObjectTable<Edge> EdgeTable;
|
||||
typedef ArrayTable<Arrival> ArrivalsTable;
|
||||
typedef ArrayTable<Required> RequiredsTable;
|
||||
typedef ArrayTable<PathVertexRep> PrevPathsTable;
|
||||
typedef Map<const Pin*, Vertex*> PinVertexMap;
|
||||
typedef Iterator<Edge*> VertexEdgeIterator;
|
||||
typedef Map<const Pin*, float*, PinIdLess> PeriodCheckAnnotations;
|
||||
typedef Vector<DelayTable*> DelayTableSeq;
|
||||
typedef ObjectId EdgeId;
|
||||
typedef ObjectId ArrivalId;
|
||||
typedef ObjectId PrevPathId;
|
||||
|
||||
static constexpr EdgeId edge_id_null = object_id_null;
|
||||
static constexpr ObjectIdx edge_idx_null = object_id_null;
|
||||
static constexpr ObjectIdx vertex_idx_null = object_id_null;
|
||||
static constexpr ObjectIdx arrival_null = object_id_null;
|
||||
static constexpr ObjectIdx prev_path_null = object_id_null;
|
||||
|
||||
// The graph acts as a BUILDER for the graph vertices and edges.
|
||||
class Graph : public StaState
|
||||
|
|
@ -78,17 +68,17 @@ public:
|
|||
// ap_count is the dcalc analysis point count.
|
||||
Graph(StaState *sta,
|
||||
int slew_rf_count,
|
||||
bool have_arc_delays,
|
||||
DcalcAPIndex ap_count);
|
||||
void makeGraph();
|
||||
virtual ~Graph();
|
||||
~Graph();
|
||||
|
||||
// Number of arc delays and slews from sdf or delay calculation.
|
||||
virtual void setDelayCount(DcalcAPIndex ap_count);
|
||||
void setDelayCount(DcalcAPIndex ap_count);
|
||||
size_t slewCount();
|
||||
|
||||
// Vertex functions.
|
||||
// Bidirect pins have two vertices.
|
||||
virtual Vertex *vertex(VertexId vertex_id) const;
|
||||
Vertex *vertex(VertexId vertex_id) const;
|
||||
VertexId id(const Vertex *vertex) const;
|
||||
void makePinVertices(Pin *pin);
|
||||
void makePinVertices(Pin *pin,
|
||||
|
|
@ -103,56 +93,49 @@ public:
|
|||
Vertex *pinDrvrVertex(const Pin *pin) const;
|
||||
// Load vertex for bidirects.
|
||||
Vertex *pinLoadVertex(const Pin *pin) const;
|
||||
virtual void deleteVertex(Vertex *vertex);
|
||||
void deleteVertex(Vertex *vertex);
|
||||
bool hasFaninOne(Vertex *vertex) const;
|
||||
VertexId vertexCount() { return vertices_->size(); }
|
||||
Arrival *makeArrivals(Vertex *vertex,
|
||||
uint32_t count);
|
||||
Arrival *arrivals(Vertex *vertex);
|
||||
void deleteArrivals(Vertex *vertex,
|
||||
uint32_t count);
|
||||
Arrival *arrivals(const Vertex *vertex) const;
|
||||
void deleteArrivals(Vertex *vertex);
|
||||
Required *makeRequireds(Vertex *vertex,
|
||||
uint32_t count);
|
||||
Required *requireds(Vertex *vertex);
|
||||
void deleteRequireds(Vertex *vertex,
|
||||
uint32_t count);
|
||||
Required *requireds(const Vertex *vertex) const;
|
||||
void deleteRequireds(Vertex *vertex);
|
||||
PathVertexRep *makePrevPaths(Vertex *vertex,
|
||||
uint32_t count);
|
||||
PathVertexRep *prevPaths(Vertex *vertex) const;
|
||||
void deletePrevPaths(Vertex *vertex,
|
||||
uint32_t count);
|
||||
// Private to Search::deletePaths().
|
||||
void deletePaths();
|
||||
PathVertexRep *prevPaths(const Vertex *vertex) const;
|
||||
void deletePrevPaths(Vertex *vertex);
|
||||
// Private to Search::deletePaths(Vertex).
|
||||
void deletePaths(Vertex *vertex,
|
||||
uint32_t count);
|
||||
void deletePaths(Vertex *vertex);
|
||||
|
||||
// Reported slew are the same as those in the liberty tables.
|
||||
// reported_slews = measured_slews / slew_derate_from_library
|
||||
// Measured slews are between slew_lower_threshold and slew_upper_threshold.
|
||||
virtual const Slew &slew(const Vertex *vertex,
|
||||
const RiseFall *rf,
|
||||
DcalcAPIndex ap_index);
|
||||
virtual void setSlew(Vertex *vertex,
|
||||
const RiseFall *rf,
|
||||
DcalcAPIndex ap_index,
|
||||
const Slew &slew);
|
||||
SlewSeq slews(Vertex *vertex);
|
||||
const Slew &slew(const Vertex *vertex,
|
||||
const RiseFall *rf,
|
||||
DcalcAPIndex ap_index);
|
||||
void setSlew(Vertex *vertex,
|
||||
const RiseFall *rf,
|
||||
DcalcAPIndex ap_index,
|
||||
const Slew &slew);
|
||||
|
||||
// Edge functions.
|
||||
virtual Edge *edge(EdgeId edge_index) const;
|
||||
Edge *edge(EdgeId edge_index) const;
|
||||
EdgeId id(const Edge *edge) const;
|
||||
virtual Edge *makeEdge(Vertex *from,
|
||||
Vertex *to,
|
||||
TimingArcSet *arc_set);
|
||||
virtual void makeWireEdge(const Pin *from_pin,
|
||||
const Pin *to_pin);
|
||||
Edge *makeEdge(Vertex *from,
|
||||
Vertex *to,
|
||||
TimingArcSet *arc_set);
|
||||
void makeWireEdge(const Pin *from_pin,
|
||||
const Pin *to_pin);
|
||||
void makePinInstanceEdges(const Pin *pin);
|
||||
void makeInstanceEdges(const Instance *inst);
|
||||
void makeWireEdgesToPin(const Pin *to_pin);
|
||||
void makeWireEdgesThruPin(const Pin *hpin);
|
||||
virtual void makeWireEdgesFromPin(const Pin *drvr_pin);
|
||||
virtual void deleteEdge(Edge *edge);
|
||||
void makeWireEdgesFromPin(const Pin *drvr_pin);
|
||||
void deleteEdge(Edge *edge);
|
||||
// Find the edge and timing arc on a gate between in_pin and drvr_pin.
|
||||
void gateEdgeArc(const Pin *in_pin,
|
||||
const RiseFall *in_rf,
|
||||
|
|
@ -162,21 +145,21 @@ public:
|
|||
Edge *&edge,
|
||||
const TimingArc *&arc) const;
|
||||
|
||||
virtual ArcDelay arcDelay(const Edge *edge,
|
||||
const TimingArc *arc,
|
||||
DcalcAPIndex ap_index) const;
|
||||
virtual void setArcDelay(Edge *edge,
|
||||
const TimingArc *arc,
|
||||
DcalcAPIndex ap_index,
|
||||
ArcDelay delay);
|
||||
ArcDelay arcDelay(const Edge *edge,
|
||||
const TimingArc *arc,
|
||||
DcalcAPIndex ap_index) const;
|
||||
void setArcDelay(Edge *edge,
|
||||
const TimingArc *arc,
|
||||
DcalcAPIndex ap_index,
|
||||
ArcDelay delay);
|
||||
// Alias for arcDelays using library wire arcs.
|
||||
virtual const ArcDelay &wireArcDelay(const Edge *edge,
|
||||
const RiseFall *rf,
|
||||
DcalcAPIndex ap_index);
|
||||
virtual void setWireArcDelay(Edge *edge,
|
||||
const RiseFall *rf,
|
||||
DcalcAPIndex ap_index,
|
||||
const ArcDelay &delay);
|
||||
const ArcDelay &wireArcDelay(const Edge *edge,
|
||||
const RiseFall *rf,
|
||||
DcalcAPIndex ap_index);
|
||||
void setWireArcDelay(Edge *edge,
|
||||
const RiseFall *rf,
|
||||
DcalcAPIndex ap_index,
|
||||
const ArcDelay &delay);
|
||||
// Is timing arc delay annotated.
|
||||
bool arcDelayAnnotated(const Edge *edge,
|
||||
const TimingArc *arc,
|
||||
|
|
@ -185,7 +168,7 @@ public:
|
|||
const TimingArc *arc,
|
||||
DcalcAPIndex ap_index,
|
||||
bool annotated);
|
||||
bool wireDelayAnnotated(Edge *edge,
|
||||
bool wireDelayAnnotated(const Edge *edge,
|
||||
const RiseFall *rf,
|
||||
DcalcAPIndex ap_index) const;
|
||||
void setWireDelayAnnotated(Edge *edge,
|
||||
|
|
@ -194,8 +177,6 @@ public:
|
|||
bool annotated);
|
||||
// True if any edge arc is annotated.
|
||||
bool delayAnnotated(Edge *edge);
|
||||
int edgeCount() { return edges_->size(); }
|
||||
virtual int arcCount() { return arc_count_; }
|
||||
|
||||
void minPulseWidthArc(Vertex *vertex,
|
||||
const RiseFall *hi_low,
|
||||
|
|
@ -211,6 +192,7 @@ public:
|
|||
void setPeriodCheckAnnotation(const Pin *pin,
|
||||
DcalcAPIndex ap_index,
|
||||
float period);
|
||||
|
||||
// Remove all delay and slew annotations.
|
||||
void removeDelaySlewAnnotations();
|
||||
VertexSet *regClkVertices() { return reg_clk_vertices_; }
|
||||
|
|
@ -223,29 +205,27 @@ protected:
|
|||
Vertex *makeVertex(Pin *pin,
|
||||
bool is_bidirect_drvr,
|
||||
bool is_reg_clk);
|
||||
virtual void makeEdgeArcDelays(Edge *edge);
|
||||
void makeEdgeArcDelays(Edge *edge);
|
||||
void makePinVertices(const Instance *inst);
|
||||
void makeWireEdgesFromPin(const Pin *drvr_pin,
|
||||
PinSet &visited_drvrs);
|
||||
bool isIsolatedNet(PinSeq &drvrs,
|
||||
PinSeq &loads) const;
|
||||
void makeWireEdges();
|
||||
virtual void makeInstDrvrWireEdges(const Instance *inst,
|
||||
PinSet &visited_drvrs);
|
||||
virtual void makePortInstanceEdges(const Instance *inst,
|
||||
LibertyCell *cell,
|
||||
LibertyPort *from_to_port);
|
||||
void makeInstDrvrWireEdges(const Instance *inst,
|
||||
PinSet &visited_drvrs);
|
||||
void makePortInstanceEdges(const Instance *inst,
|
||||
LibertyCell *cell,
|
||||
LibertyPort *from_to_port);
|
||||
void removePeriodCheckAnnotations();
|
||||
void makeSlewTables(DcalcAPIndex count);
|
||||
void deleteSlewTables();
|
||||
void makeVertexSlews(Vertex *vertex);
|
||||
void makeArcDelayTables(DcalcAPIndex ap_count);
|
||||
void deleteArcDelayTables();
|
||||
void deleteInEdge(Vertex *vertex,
|
||||
Edge *edge);
|
||||
void deleteOutEdge(Vertex *vertex,
|
||||
Edge *edge);
|
||||
void removeDelays();
|
||||
void initSlews();
|
||||
void initSlews(Vertex *vertex);
|
||||
void initArcDelays(Edge *edge);
|
||||
void removeDelayAnnotated(Edge *edge);
|
||||
|
||||
VertexTable *vertices_;
|
||||
|
|
@ -255,20 +235,8 @@ protected:
|
|||
// driver/source (top level input, instance pin output) vertex
|
||||
// in pin_bidirect_drvr_vertex_map
|
||||
PinVertexMap pin_bidirect_drvr_vertex_map_;
|
||||
int arc_count_;
|
||||
ArrivalsTable arrivals_;
|
||||
std::mutex arrivals_lock_;
|
||||
RequiredsTable requireds_;
|
||||
std::mutex requireds_lock_;
|
||||
PrevPathsTable prev_paths_;
|
||||
std::mutex prev_paths_lock_;
|
||||
Vector<bool> arc_delay_annotated_;
|
||||
int slew_rf_count_;
|
||||
bool have_arc_delays_;
|
||||
DcalcAPIndex ap_count_;
|
||||
DelayTableSeq slew_tables_; // [ap_index][tr_index][vertex_id]
|
||||
VertexId slew_count_;
|
||||
DelayTableSeq arc_delays_; // [ap_index][edge_arc_index]
|
||||
// Sdf period check annotations.
|
||||
PeriodCheckAnnotations *period_check_annotations_;
|
||||
// Register/latch clock vertices to search from.
|
||||
|
|
@ -286,6 +254,7 @@ class Vertex
|
|||
{
|
||||
public:
|
||||
Vertex();
|
||||
~Vertex();
|
||||
Pin *pin() const { return pin_; }
|
||||
// Pin path with load/driver suffix for bidirects.
|
||||
const char *name(const Network *network) const;
|
||||
|
|
@ -298,11 +267,12 @@ public:
|
|||
bool hasFanout() const;
|
||||
LevelColor color() const { return static_cast<LevelColor>(color_); }
|
||||
void setColor(LevelColor color);
|
||||
ArrivalId arrivals() { return arrivals_; }
|
||||
ArrivalId requireds() { return requireds_; }
|
||||
bool hasRequireds() const { return requireds_ != arrival_null; }
|
||||
PrevPathId prevPaths() const { return prev_paths_; }
|
||||
void setPrevPaths(PrevPathId id);
|
||||
Slew *slews() { return slews_; }
|
||||
const Slew *slews() const { return slews_; }
|
||||
Arrival *arrivals() const { return arrivals_; }
|
||||
Arrival *requireds() const { return requireds_; }
|
||||
PathVertexRep *prevPaths() const { return prev_paths_; }
|
||||
void setPrevPaths(PathVertexRep *prev_paths);
|
||||
TagGroupIndex tagGroupIndex() const;
|
||||
void setTagGroupIndex(TagGroupIndex tag_index);
|
||||
// Slew is annotated by sdc set_annotated_transition cmd.
|
||||
|
|
@ -341,6 +311,7 @@ public:
|
|||
bool isRegClk() const { return is_reg_clk_; }
|
||||
bool crprPathPruningDisabled() const { return crpr_path_pruning_disabled_;}
|
||||
void setCrprPathPruningDisabled(bool disabled);
|
||||
bool hasRequireds() const { return requireds_ != nullptr; }
|
||||
bool requiredsPruned() const { return requireds_pruned_; }
|
||||
void setRequiredsPruned(bool pruned);
|
||||
|
||||
|
|
@ -354,22 +325,30 @@ protected:
|
|||
void init(Pin *pin,
|
||||
bool is_bidirect_drvr,
|
||||
bool is_reg_clk);
|
||||
void setArrivals(ArrivalId id);
|
||||
void setRequireds(ArrivalId id);
|
||||
void clear();
|
||||
void setArrivals(Arrival *arrivals);
|
||||
void setRequireds(Required *requireds);
|
||||
void setSlews(Slew *slews);
|
||||
|
||||
Pin *pin_;
|
||||
ArrivalId arrivals_;
|
||||
ArrivalId requireds_;
|
||||
PrevPathId prev_paths_;
|
||||
EdgeId in_edges_; // Edges to this vertex.
|
||||
EdgeId out_edges_; // Edges from this vertex.
|
||||
|
||||
// 28 bits
|
||||
unsigned int tag_group_index_:tag_group_index_bits; // 24
|
||||
unsigned int slew_annotated_:slew_annotated_bits; // 4
|
||||
// Delay calc
|
||||
Slew *slews_;
|
||||
// Search
|
||||
Arrival *arrivals_;
|
||||
Arrival *requireds_;
|
||||
PathVertexRep *prev_paths_;
|
||||
|
||||
// These fields are written by multiple threads, so they
|
||||
// cannot share the same word as the following bit fields.
|
||||
uint32_t tag_group_index_;
|
||||
// Each bit corresponds to a different BFS queue.
|
||||
std::atomic<uint8_t> bfs_in_queue_; // 4
|
||||
|
||||
// 32 bits
|
||||
unsigned int level_:Graph::vertex_level_bits; // 24
|
||||
unsigned int slew_annotated_:slew_annotated_bits; // 4
|
||||
// Levelization search state.
|
||||
// LevelColor gcc barfs if this is dcl'd.
|
||||
unsigned color_:2;
|
||||
|
|
@ -379,11 +358,6 @@ protected:
|
|||
// This flag distinguishes the driver and load vertices.
|
||||
bool is_bidirect_drvr_:1;
|
||||
bool is_reg_clk_:1;
|
||||
|
||||
// Each bit corresponds to a different BFS queue.
|
||||
std::atomic<uint8_t> bfs_in_queue_; // 4
|
||||
|
||||
// 15 bits
|
||||
bool is_disabled_constraint_:1;
|
||||
bool is_gated_clk_enable_:1;
|
||||
// Constrained by timing check edge.
|
||||
|
|
@ -409,6 +383,7 @@ class Edge
|
|||
{
|
||||
public:
|
||||
Edge();
|
||||
~Edge();
|
||||
Vertex *to(const Graph *graph) const { return graph->vertex(to_); }
|
||||
Vertex *from(const Graph *graph) const { return graph->vertex(from_); }
|
||||
TimingRole *role() const;
|
||||
|
|
@ -416,9 +391,9 @@ public:
|
|||
TimingSense sense() const;
|
||||
TimingArcSet *timingArcSet() const { return arc_set_; }
|
||||
void setTimingArcSet(TimingArcSet *set);
|
||||
ArcId arcDelays() const { return arc_delays_; }
|
||||
void setArcDelays(ArcId arc_delays);
|
||||
bool delayAnnotationIsIncremental() const;
|
||||
ArcDelay *arcDelays() const { return arc_delays_; }
|
||||
void setArcDelays(ArcDelay *arc_delays);
|
||||
bool delay_Annotation_Is_Incremental() const {return delay_annotation_is_incremental_;};
|
||||
void setDelayAnnotationIsIncremental(bool is_incr);
|
||||
// Edge is disabled by set_disable_timing constraint.
|
||||
bool isDisabledConstraint() const;
|
||||
|
|
@ -438,6 +413,7 @@ public:
|
|||
void setIsBidirectInstPath(bool is_bidir);
|
||||
bool isBidirectNetPath() const { return is_bidirect_net_path_; }
|
||||
void setIsBidirectNetPath(bool is_bidir);
|
||||
void removeDelayAnnotated();
|
||||
|
||||
// ObjectTable interface.
|
||||
ObjectIdx objectIdx() const { return object_idx_; }
|
||||
|
|
@ -447,6 +423,14 @@ protected:
|
|||
void init(VertexId from,
|
||||
VertexId to,
|
||||
TimingArcSet *arc_set);
|
||||
void clear();
|
||||
bool arcDelayAnnotated(const TimingArc *arc,
|
||||
DcalcAPIndex ap_index,
|
||||
DcalcAPIndex ap_count) const;
|
||||
void setArcDelayAnnotated(const TimingArc *arc,
|
||||
DcalcAPIndex ap_index,
|
||||
DcalcAPIndex ap_count,
|
||||
bool annotated);
|
||||
|
||||
TimingArcSet *arc_set_;
|
||||
VertexId from_;
|
||||
|
|
@ -454,8 +438,12 @@ protected:
|
|||
EdgeId vertex_in_link_; // Vertex in edges list.
|
||||
EdgeId vertex_out_next_; // Vertex out edges doubly linked list.
|
||||
EdgeId vertex_out_prev_;
|
||||
ArcId arc_delays_;
|
||||
// 16 bits
|
||||
ArcDelay *arc_delays_;
|
||||
union {
|
||||
uintptr_t bits_;
|
||||
vector<bool> *seq_;
|
||||
} arc_delay_annotated_;
|
||||
bool arc_delay_annotated_is_bits_:1;
|
||||
bool delay_annotation_is_incremental_:1;
|
||||
bool is_bidirect_inst_path_:1;
|
||||
bool is_bidirect_net_path_:1;
|
||||
|
|
|
|||
|
|
@ -49,7 +49,6 @@ class VertexSet;
|
|||
|
||||
typedef ObjectId VertexId;
|
||||
typedef ObjectId EdgeId;
|
||||
typedef ObjectId ArcId;
|
||||
typedef Vector<Vertex*> VertexSeq;
|
||||
typedef Vector<Edge*> EdgeSeq;
|
||||
typedef Set<Edge*> EdgeSet;
|
||||
|
|
|
|||
|
|
@ -210,8 +210,8 @@ public:
|
|||
virtual bool isTopInstance(const Instance *inst) const;
|
||||
virtual Instance *findInstance(const char *path_name) const;
|
||||
// Find instance relative to hierarchical instance.
|
||||
Instance *findInstanceRelative(const Instance *inst,
|
||||
const char *path_name) const;
|
||||
virtual Instance *findInstanceRelative(const Instance *inst,
|
||||
const char *path_name) const;
|
||||
// Default implementation uses linear search.
|
||||
virtual InstanceSeq findInstancesMatching(const Instance *context,
|
||||
const PatternMatch *pattern) const;
|
||||
|
|
@ -363,8 +363,8 @@ public:
|
|||
virtual ObjectId id(const Net *net) const = 0;
|
||||
virtual Net *findNet(const char *path_name) const;
|
||||
// Find net relative to hierarchical instance.
|
||||
Net *findNetRelative(const Instance *inst,
|
||||
const char *path_name) const;
|
||||
virtual Net *findNetRelative(const Instance *inst,
|
||||
const char *path_name) const;
|
||||
// Default implementation uses linear search.
|
||||
virtual NetSeq findNetsMatching(const Instance *context,
|
||||
const PatternMatch *pattern) const;
|
||||
|
|
|
|||
|
|
@ -173,7 +173,6 @@ void
|
|||
ObjectTable<TYPE>::destroy(TYPE *object)
|
||||
{
|
||||
ObjectId object_id = objectId(object);
|
||||
object->~TYPE();
|
||||
size_--;
|
||||
freePush(object, object_id);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -208,9 +208,13 @@ public:
|
|||
const char *pathName(const Net *net) const override;
|
||||
|
||||
Instance *findInstance(const char *path_name) const override;
|
||||
Instance *findInstanceRelative(const Instance *inst,
|
||||
const char *path_name) const override;
|
||||
InstanceSeq findInstancesMatching(const Instance *context,
|
||||
const PatternMatch *pattern) const override;
|
||||
Net *findNet(const char *path_name) const override;
|
||||
Net *findNetRelative(const Instance *instance,
|
||||
const char *net_name) const override;
|
||||
Net *findNet(const Instance *instance,
|
||||
const char *net_name) const override;
|
||||
NetSeq findNetsMatching(const Instance *parent,
|
||||
|
|
|
|||
|
|
@ -383,7 +383,8 @@ protected:
|
|||
bool report_max,
|
||||
DcalcAnalysisPt *dcalc_ap_min,
|
||||
DcalcAnalysisPt *dcalc_ap_max);
|
||||
virtual void deleteTags();
|
||||
void deleteTags();
|
||||
void deleteTagsPrev();
|
||||
void seedInvalidArrivals();
|
||||
void seedArrivals();
|
||||
void findClockVertices(VertexSet &vertices);
|
||||
|
|
@ -593,12 +594,14 @@ protected:
|
|||
// Entries in tags_ may be missing where previous filter tags were deleted.
|
||||
TagIndex tag_capacity_;
|
||||
std::atomic<Tag **> tags_;
|
||||
vector<Tag **> tags_prev_;
|
||||
TagIndex tag_next_;
|
||||
// Holes in tags_ left by deleting filter tags.
|
||||
std::vector<TagIndex> tag_free_indices_;
|
||||
std::mutex tag_lock_;
|
||||
TagGroupSet *tag_group_set_;
|
||||
std::atomic<TagGroup **> tag_groups_;
|
||||
vector<TagGroup **> tag_groups_prev_;
|
||||
TagGroupIndex tag_group_next_;
|
||||
// Holes in tag_groups_ left by deleting filter tag groups.
|
||||
std::vector<TagIndex> tag_group_free_indices_;
|
||||
|
|
|
|||
|
|
@ -789,6 +789,22 @@ SdcNetwork::findInstance(const char *path_name) const
|
|||
return child;
|
||||
}
|
||||
|
||||
Instance *
|
||||
SdcNetwork::findInstanceRelative(const Instance *inst,
|
||||
const char *path_name) const
|
||||
{
|
||||
Instance *inst1 = network_->findInstanceRelative(inst, path_name);
|
||||
if (inst1 == nullptr) {
|
||||
string path_name1 = escapeBrackets(path_name, this);
|
||||
inst1 = network_->findInstanceRelative(inst, path_name1.c_str());
|
||||
if (inst1 == nullptr) {
|
||||
string path_name2 = escapeDividers(path_name1.c_str(), network_);
|
||||
inst1 = network_->findInstanceRelative(inst, path_name2.c_str());
|
||||
}
|
||||
}
|
||||
return inst1;
|
||||
}
|
||||
|
||||
InstanceSeq
|
||||
SdcNetwork::findInstancesMatching(const Instance *context,
|
||||
const PatternMatch *pattern) const
|
||||
|
|
@ -835,17 +851,34 @@ SdcNetwork::findNet(const char *path_name) const
|
|||
parsePath(path_name, inst, net_name);
|
||||
if (inst == nullptr)
|
||||
inst = network_->topInstance();
|
||||
return findNet(inst, net_name);
|
||||
return findNetRelative(inst, net_name);
|
||||
}
|
||||
|
||||
Net *
|
||||
SdcNetwork::findNet(const Instance *instance,
|
||||
const char *net_name) const
|
||||
const char *net_name) const
|
||||
{
|
||||
Net *net = network_->findNet(instance, net_name);
|
||||
if (net == nullptr) {
|
||||
string net_name1 = escapeBrackets(net_name, this);
|
||||
net = network_->findNet(instance, net_name1.c_str());
|
||||
string net_name2 = escapeDividers(net_name1.c_str(), network_);
|
||||
net = network_->findNet(instance, net_name2.c_str());
|
||||
}
|
||||
return net;
|
||||
}
|
||||
|
||||
Net *
|
||||
SdcNetwork::findNetRelative(const Instance *inst,
|
||||
const char *path_name) const
|
||||
{
|
||||
Net *net = network_->findNetRelative(inst, path_name);
|
||||
if (net == nullptr) {
|
||||
string path_name1 = escapeBrackets(path_name, this);
|
||||
net = network_->findNetRelative(inst, path_name1.c_str());
|
||||
if (net == nullptr) {
|
||||
string path_name2 = escapeDividers(path_name1.c_str(), network_);
|
||||
net = network_->findNetRelative(inst, path_name2.c_str());
|
||||
}
|
||||
}
|
||||
return net;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -51,7 +51,7 @@ typedef sta::SpefParse::token token;
|
|||
%option never-interactive
|
||||
%option stack
|
||||
%option yylineno
|
||||
/* %option debug */
|
||||
%option debug
|
||||
|
||||
%x COMMENT
|
||||
%x QUOTE
|
||||
|
|
|
|||
|
|
@ -287,9 +287,7 @@ name_map_entries:
|
|||
|
||||
name_map_entry:
|
||||
INDEX mapped_item
|
||||
{ reader->makeNameMapEntry($1, $2);
|
||||
sta::stringDelete($1);
|
||||
}
|
||||
{ reader->makeNameMapEntry($1, $2); }
|
||||
;
|
||||
|
||||
mapped_item:
|
||||
|
|
|
|||
|
|
@ -106,9 +106,6 @@ SpefReader::~SpefReader()
|
|||
delete design_flow_;
|
||||
design_flow_ = nullptr;
|
||||
}
|
||||
|
||||
for (const auto [index, name] : name_map_)
|
||||
stringDelete(name);
|
||||
}
|
||||
|
||||
bool
|
||||
|
|
@ -121,6 +118,7 @@ SpefReader::read()
|
|||
SpefScanner scanner(&stream, filename_, this, report_);
|
||||
scanner_ = &scanner;
|
||||
SpefParse parser(&scanner, this);
|
||||
//parser.set_debug_level(1);
|
||||
// yyparse returns 0 on success.
|
||||
success = (parser.parse() == 0);
|
||||
stats.report("Read spef");
|
||||
|
|
@ -160,7 +158,7 @@ SpefReader::setBusBrackets(char left,
|
|||
Instance *
|
||||
SpefReader::findInstanceRelative(const char *name)
|
||||
{
|
||||
return network_->findInstanceRelative(instance_, name);
|
||||
return sdc_network_->findInstanceRelative(instance_, name);
|
||||
}
|
||||
|
||||
Net *
|
||||
|
|
@ -257,21 +255,23 @@ SpefReader::setInductScale(float scale,
|
|||
}
|
||||
|
||||
void
|
||||
SpefReader::makeNameMapEntry(char *index,
|
||||
char *name)
|
||||
SpefReader::makeNameMapEntry(const char *index,
|
||||
const char *name)
|
||||
{
|
||||
int i = atoi(index + 1);
|
||||
name_map_[i] = name;
|
||||
stringDelete(index);
|
||||
stringDelete(name);
|
||||
}
|
||||
|
||||
char *
|
||||
SpefReader::nameMapLookup(char *name)
|
||||
const char *
|
||||
SpefReader::nameMapLookup(const char *name)
|
||||
{
|
||||
if (name && name[0] == '*') {
|
||||
int index = atoi(name + 1);
|
||||
auto itr = name_map_.find(index);
|
||||
const auto &itr = name_map_.find(index);
|
||||
if (itr != name_map_.end())
|
||||
return itr->second;
|
||||
return itr->second.c_str();
|
||||
else {
|
||||
warn(1645, "no name map entry for %d.", index);
|
||||
return nullptr;
|
||||
|
|
@ -310,19 +310,19 @@ SpefReader::findPin(char *name)
|
|||
char *delim = strrchr(name, delimiter_);
|
||||
if (delim) {
|
||||
*delim = '\0';
|
||||
name = nameMapLookup(name);
|
||||
if (name) {
|
||||
Instance *inst = findInstanceRelative(name);
|
||||
const char *name1 = nameMapLookup(name);
|
||||
if (name1) {
|
||||
Instance *inst = findInstanceRelative(name1);
|
||||
// Replace delimiter for error messages.
|
||||
*delim = delimiter_;
|
||||
const char *port_name = delim + 1;
|
||||
if (inst) {
|
||||
pin = network_->findPin(inst, port_name);
|
||||
if (pin == nullptr)
|
||||
warn(1647, "pin %s not found.", name);
|
||||
warn(1647, "pin %s not found.", name1);
|
||||
}
|
||||
else
|
||||
warn(1648, "instance %s not found.", name);
|
||||
warn(1648, "instance %s not found.", name1);
|
||||
}
|
||||
}
|
||||
else {
|
||||
|
|
@ -335,14 +335,14 @@ SpefReader::findPin(char *name)
|
|||
}
|
||||
|
||||
Net *
|
||||
SpefReader::findNet(char *name)
|
||||
SpefReader::findNet(const char *name)
|
||||
{
|
||||
Net *net = nullptr;
|
||||
name = nameMapLookup(name);
|
||||
if (name) {
|
||||
net = findNetRelative(name);
|
||||
const char *name1 = nameMapLookup(name);
|
||||
if (name1) {
|
||||
net = findNetRelative(name1);
|
||||
if (net == nullptr)
|
||||
warn(1650, "net %s not found.", name);
|
||||
warn(1650, "net %s not found.", name1);
|
||||
}
|
||||
return net;
|
||||
}
|
||||
|
|
@ -447,26 +447,26 @@ SpefReader::findParasiticNode(char *name,
|
|||
if (delim) {
|
||||
*delim = '\0';
|
||||
char *name2 = delim + 1;
|
||||
name = nameMapLookup(name);
|
||||
if (name) {
|
||||
Instance *inst = findInstanceRelative(name);
|
||||
const char *name1 = nameMapLookup(name);
|
||||
if (name1) {
|
||||
Instance *inst = findInstanceRelative(name1);
|
||||
if (inst) {
|
||||
// <instance>:<port>
|
||||
Pin *pin = network_->findPin(inst, name2);
|
||||
if (pin) {
|
||||
if (local_only
|
||||
&& !network_->isConnected(net_, pin))
|
||||
warn(1651, "%s not connected to net %s.", name, network_->pathName(net_));
|
||||
warn(1651, "%s not connected to net %s.", name1, network_->pathName(net_));
|
||||
return parasitics_->ensureParasiticNode(parasitic_, pin, network_);
|
||||
}
|
||||
else {
|
||||
// Replace delimiter for error message.
|
||||
*delim = delimiter_;
|
||||
warn(1652, "pin %s not found.", name);
|
||||
warn(1652, "pin %s not found.", name1);
|
||||
}
|
||||
}
|
||||
else {
|
||||
Net *net = findNet(name);
|
||||
Net *net = findNet(name1);
|
||||
// Replace delimiter for error messages.
|
||||
*delim = delimiter_;
|
||||
if (net) {
|
||||
|
|
@ -477,25 +477,29 @@ SpefReader::findParasiticNode(char *name,
|
|||
if (local_only
|
||||
&& !network_->isConnected(net, net_))
|
||||
warn(1653, "%s not connected to net %s.",
|
||||
name,
|
||||
name1,
|
||||
network_->pathName(net_));
|
||||
return parasitics_->ensureParasiticNode(parasitic_, net, id, network_);
|
||||
}
|
||||
else
|
||||
warn(1654, "node %s not a pin or net:number", name);
|
||||
warn(1654, "node %s not a pin or net:number", name1);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
// <top_level_port>
|
||||
name = nameMapLookup(name);
|
||||
Pin *pin = findPortPinRelative(name);
|
||||
if (pin) {
|
||||
if (local_only
|
||||
&& !network_->isConnected(net_, pin))
|
||||
warn(1655, "%s not connected to net %s.", name, network_->pathName(net_));
|
||||
return parasitics_->ensureParasiticNode(parasitic_, pin, network_);
|
||||
const char *name1 = nameMapLookup(name);
|
||||
if (name1) {
|
||||
Pin *pin = findPortPinRelative(name1);
|
||||
if (pin) {
|
||||
if (local_only
|
||||
&& !network_->isConnected(net_, pin))
|
||||
warn(1655, "%s not connected to net %s.", name1, network_->pathName(net_));
|
||||
return parasitics_->ensureParasiticNode(parasitic_, pin, network_);
|
||||
}
|
||||
else
|
||||
warn(1656, "pin %s not found.", name1);
|
||||
}
|
||||
else
|
||||
warn(1656, "pin %s not found.", name);
|
||||
|
|
|
|||
|
|
@ -41,7 +41,9 @@ class SpefTriple;
|
|||
class Corner;
|
||||
class SpefScanner;
|
||||
|
||||
typedef std::map<int, char*, std::less<int>> SpefNameMap;
|
||||
using std::string;
|
||||
|
||||
typedef std::map<int, string> SpefNameMap;
|
||||
|
||||
class SpefReader : public StaState
|
||||
{
|
||||
|
|
@ -79,12 +81,12 @@ public:
|
|||
const char *units);
|
||||
void setInductScale(float scale,
|
||||
const char *units);
|
||||
void makeNameMapEntry(char *index,
|
||||
char *name);
|
||||
char *nameMapLookup(char *index);
|
||||
void makeNameMapEntry(const char *index,
|
||||
const char *name);
|
||||
const char *nameMapLookup(const char *index);
|
||||
void setDesignFlow(StringSeq *flow_keys);
|
||||
Pin *findPin(char *name);
|
||||
Net *findNet(char *name);
|
||||
Net *findNet(const char *name);
|
||||
void rspfBegin(Net *net,
|
||||
SpefTriple *total_cap);
|
||||
void rspfFinish();
|
||||
|
|
|
|||
|
|
@ -269,7 +269,6 @@ proc check_unit { unit key suffix key_var } {
|
|||
if { [string match -nocase $arg_suffix $suffix] } {
|
||||
set arg_prefix [string range $value 0 end-$suffix_length]
|
||||
if { [regexp "^(10*)?(\[Mkmunpf\])?$" $arg_prefix ignore mult prefix] } {
|
||||
#puts "$arg_prefix '$mult' '$prefix'"
|
||||
if { $mult == "" } {
|
||||
set mult 1
|
||||
}
|
||||
|
|
|
|||
|
|
@ -368,6 +368,7 @@ Search::deleteTags()
|
|||
tag_free_indices_.clear();
|
||||
|
||||
clk_info_set_->deleteContentsClear();
|
||||
deleteTagsPrev();
|
||||
}
|
||||
|
||||
void
|
||||
|
|
@ -408,7 +409,11 @@ Search::deletePaths()
|
|||
{
|
||||
debugPrint(debug_, "search", 1, "delete paths");
|
||||
if (arrivals_exist_) {
|
||||
graph_->deletePaths();
|
||||
VertexIterator vertex_iter(graph_);
|
||||
while (vertex_iter.hasNext()) {
|
||||
Vertex *vertex = vertex_iter.next();
|
||||
deletePaths(vertex);
|
||||
}
|
||||
filtered_arrivals_->clear();
|
||||
arrivals_exist_ = false;
|
||||
}
|
||||
|
|
@ -428,10 +433,8 @@ void
|
|||
Search::deletePaths(Vertex *vertex)
|
||||
{
|
||||
TagGroup *tag_group = tagGroup(vertex);
|
||||
if (tag_group) {
|
||||
int arrival_count = tag_group->arrivalCount();
|
||||
graph_->deletePaths(vertex, arrival_count);
|
||||
}
|
||||
if (tag_group)
|
||||
graph_->deletePaths(vertex);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////
|
||||
|
|
@ -613,11 +616,25 @@ Search::findFilteredArrivals(bool thru_latches)
|
|||
debugPrint(debug_, "search", 1, "find arrivals pass %d", pass);
|
||||
int arrival_count = arrival_iter_->visitParallel(max_level,
|
||||
arrival_visitor_);
|
||||
deleteTagsPrev();
|
||||
debugPrint(debug_, "search", 1, "found %d arrivals", arrival_count);
|
||||
}
|
||||
arrivals_exist_ = true;
|
||||
}
|
||||
|
||||
// Delete stale tag arrarys.
|
||||
void
|
||||
Search::deleteTagsPrev()
|
||||
{
|
||||
for (Tag** tags: tags_prev_)
|
||||
delete [] tags;
|
||||
tags_prev_.clear();
|
||||
|
||||
for (TagGroup** tag_groups: tag_groups_prev_)
|
||||
delete [] tag_groups;
|
||||
tag_groups_prev_.clear();
|
||||
}
|
||||
|
||||
VertexSeq
|
||||
Search::filteredEndpoints()
|
||||
{
|
||||
|
|
@ -853,6 +870,7 @@ Search::findClkArrivals()
|
|||
ClkArrivalSearchPred search_clk(this);
|
||||
arrival_visitor_->init(false, &search_clk);
|
||||
arrival_iter_->visitParallel(levelize_->maxLevel(), arrival_visitor_);
|
||||
deleteTagsPrev();
|
||||
arrivals_exist_ = true;
|
||||
stats.report("Find clk arrivals");
|
||||
}
|
||||
|
|
@ -1023,6 +1041,7 @@ Search::findArrivals1(Level level)
|
|||
findArrivalsSeed();
|
||||
Stats stats(debug_, report_);
|
||||
int arrival_count = arrival_iter_->visitParallel(level, arrival_visitor_);
|
||||
deleteTagsPrev();
|
||||
stats.report("Find arrivals");
|
||||
if (arrival_iter_->empty()
|
||||
&& invalid_arrivals_->empty()) {
|
||||
|
|
@ -2671,6 +2690,7 @@ Search::findTagGroup(TagGroupBldr *tag_bldr)
|
|||
TagGroup **tag_groups = new TagGroup*[tag_capacity];
|
||||
memcpy(tag_groups, tag_groups_,
|
||||
tag_group_capacity_ * sizeof(TagGroup*));
|
||||
tag_groups_prev_.push_back(tag_groups_);
|
||||
tag_groups_ = tag_groups;
|
||||
tag_group_capacity_ = tag_capacity;
|
||||
tag_group_set_->reserve(tag_capacity);
|
||||
|
|
@ -2705,7 +2725,7 @@ Search::setVertexArrivals(Vertex *vertex,
|
|||
else {
|
||||
// Prev paths not required.
|
||||
prev_paths = nullptr;
|
||||
graph_->deletePrevPaths(vertex, arrival_count);
|
||||
graph_->deletePrevPaths(vertex);
|
||||
}
|
||||
tag_bldr->copyArrivals(tag_group, prev_arrivals, prev_paths);
|
||||
vertex->setTagGroupIndex(tag_group->index());
|
||||
|
|
@ -2718,16 +2738,15 @@ Search::setVertexArrivals(Vertex *vertex,
|
|||
requiredInvalid(vertex);
|
||||
if (tag_group != prev_tag_group)
|
||||
// Requireds can only be reused if the tag group is unchanged.
|
||||
graph_->deleteRequireds(vertex, prev_tag_group->arrivalCount());
|
||||
graph_->deleteRequireds(vertex);
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (prev_tag_group) {
|
||||
uint32_t prev_arrival_count = prev_tag_group->arrivalCount();
|
||||
graph_->deleteArrivals(vertex, prev_arrival_count);
|
||||
graph_->deleteArrivals(vertex);
|
||||
if (has_requireds) {
|
||||
requiredInvalid(vertex);
|
||||
graph_->deleteRequireds(vertex, prev_arrival_count);
|
||||
graph_->deleteRequireds(vertex);
|
||||
}
|
||||
}
|
||||
Arrival *arrivals = graph_->makeArrivals(vertex, arrival_count);
|
||||
|
|
@ -2907,6 +2926,7 @@ Search::findTag(const RiseFall *rf,
|
|||
TagIndex tag_capacity = tag_capacity_ * 2;
|
||||
Tag **tags = new Tag*[tag_capacity];
|
||||
memcpy(tags, tags_, tag_capacity_ * sizeof(Tag*));
|
||||
tags_prev_.push_back(tags_);
|
||||
tags_ = tags;
|
||||
tag_capacity_ = tag_capacity;
|
||||
tag_set_->reserve(tag_capacity);
|
||||
|
|
@ -3151,6 +3171,7 @@ Search::findRequireds(Level level)
|
|||
seedRequireds();
|
||||
seedInvalidRequireds();
|
||||
int required_count = required_iter_->visitParallel(level, &req_visitor);
|
||||
deleteTagsPrev();
|
||||
requireds_exist_ = true;
|
||||
debugPrint(debug_, "search", 1, "found %d requireds", required_count);
|
||||
stats.report("Find requireds");
|
||||
|
|
@ -3436,8 +3457,7 @@ RequiredCmp::requiredsSave(Vertex *vertex,
|
|||
if (tag_group == nullptr)
|
||||
requireds_changed = true;
|
||||
else {
|
||||
int arrival_count = tag_group->arrivalCount();
|
||||
graph->deleteRequireds(vertex, arrival_count);
|
||||
graph->deleteRequireds(vertex);
|
||||
requireds_changed = true;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -792,7 +792,7 @@ proc_redirect report_pulse_width_checks {
|
|||
define_cmd_args "report_path" \
|
||||
{[-min|-max]\
|
||||
[-format full|full_clock|full_clock_expanded|short|end|summary]\
|
||||
[-fields [capacitance|slew|input_pin|net]\
|
||||
[-fields capacitance|slew|input_pin|net|src_attr]\
|
||||
[-digits digits] [-no_line_splits]\
|
||||
[> filename] [>> filename]\
|
||||
pin ^|r|rise|v|f|fall}
|
||||
|
|
|
|||
|
|
@ -3475,7 +3475,7 @@ Sta::ensureGraph()
|
|||
void
|
||||
Sta::makeGraph()
|
||||
{
|
||||
graph_ = new Graph(this, 2, true, corners_->dcalcAnalysisPtCount());
|
||||
graph_ = new Graph(this, 2, corners_->dcalcAnalysisPtCount());
|
||||
graph_->makeGraph();
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue