replace Pool with ObjectTable

This commit is contained in:
James Cherry 2019-11-11 08:28:42 -07:00
parent 2e6de93870
commit 184d044b02
21 changed files with 706 additions and 578 deletions

View File

@ -372,9 +372,10 @@ set(STA_HEADERS
util/Map.hh util/Map.hh
util/MinMax.hh util/MinMax.hh
util/Mutex.hh util/Mutex.hh
util/ObjectId.hh
util/ObjectIndex.hh util/ObjectIndex.hh
util/ObjectTable.hh
util/PatternMatch.hh util/PatternMatch.hh
util/Pool.hh
util/Report.hh util/Report.hh
util/ReportStd.hh util/ReportStd.hh
util/ReportTcl.hh util/ReportTcl.hh

View File

@ -19,7 +19,6 @@
#include "Stats.hh" #include "Stats.hh"
#include "Error.hh" #include "Error.hh"
#include "Debug.hh" #include "Debug.hh"
#include "Pool.hh"
#include "MinMax.hh" #include "MinMax.hh"
#include "PortDirection.hh" #include "PortDirection.hh"
#include "Transition.hh" #include "Transition.hh"
@ -45,8 +44,6 @@ Graph::Graph(StaState *sta,
StaState(sta), StaState(sta),
vertices_(nullptr), vertices_(nullptr),
edges_(nullptr), edges_(nullptr),
vertex_count_(0),
edge_count_(0),
arc_count_(0), arc_count_(0),
slew_tr_count_(slew_tr_count), slew_tr_count_(slew_tr_count),
have_arc_delays_(have_arc_delays), have_arc_delays_(have_arc_delays),
@ -60,8 +57,8 @@ Graph::~Graph()
{ {
delete vertices_; delete vertices_;
delete edges_; delete edges_;
deleteSlewPools(); deleteSlewTables();
deleteArcDelayPools(); deleteArcDelayTables();
removeWidthCheckAnnotations(); removeWidthCheckAnnotations();
removePeriodCheckAnnotations(); removePeriodCheckAnnotations();
} }
@ -86,10 +83,10 @@ Graph::makeVerticesAndEdges()
EdgeIndex edge_count; EdgeIndex edge_count;
ArcIndex arc_count; ArcIndex arc_count;
vertexAndEdgeCounts(vertex_count, edge_count, arc_count); vertexAndEdgeCounts(vertex_count, edge_count, arc_count);
vertices_ = new VertexPool(vertex_count); vertices_ = new VertexTable;
edges_ = new EdgePool(edge_count); edges_ = new EdgeTable;
makeSlewPools(vertex_count, ap_count_); makeSlewTables(ap_count_);
makeArcDelayPools(arc_count, ap_count_); makeArcDelayTables(arc_count, ap_count_);
LeafInstanceIterator *leaf_iter = network_->leafInstanceIterator(); LeafInstanceIterator *leaf_iter = network_->leafInstanceIterator();
while (leaf_iter->hasNext()) { while (leaf_iter->hasNext()) {
@ -449,13 +446,13 @@ Graph::makeWireEdge(Pin *from_pin,
Vertex * Vertex *
Graph::vertex(VertexIndex vertex_index) const Graph::vertex(VertexIndex vertex_index) const
{ {
return vertices_->find(vertex_index); return vertices_->pointer(vertex_index);
} }
VertexIndex VertexIndex
Graph::index(const Vertex *vertex) const Graph::index(const Vertex *vertex) const
{ {
return vertices_->index(vertex); return vertices_->objectId(vertex);
} }
void void
@ -489,10 +486,9 @@ Graph::makeVertex(Pin *pin,
bool is_bidirect_drvr, bool is_bidirect_drvr,
bool is_reg_clk) bool is_reg_clk)
{ {
Vertex *vertex = vertices_->makeObject(); Vertex *vertex = vertices_->make();
vertex->init(pin, is_bidirect_drvr, is_reg_clk); vertex->init(pin, is_bidirect_drvr, is_reg_clk);
vertex_count_++; makeVertexSlews(vertex);
makeVertexSlews();
if (is_reg_clk) if (is_reg_clk)
reg_clk_vertices_.insert(vertex); reg_clk_vertices_.insert(vertex);
return vertex; return vertex;
@ -536,31 +532,25 @@ Graph::deleteVertex(Vertex *vertex)
pin_bidirect_drvr_vertex_map_.erase(pin_bidirect_drvr_vertex_map_ pin_bidirect_drvr_vertex_map_.erase(pin_bidirect_drvr_vertex_map_
.find(pin)); .find(pin));
else else
network_->setVertexIndex(pin, 0); network_->setVertexIndex(pin, vertex_id_null);
// Delete edges to vertex. // Delete edges to vertex.
EdgeIndex edge_index, next_index; EdgeIndex edge_index, next_index;
for (edge_index = vertex->in_edges_; edge_index; edge_index = next_index) { for (edge_index = vertex->in_edges_; edge_index; edge_index = next_index) {
Edge *edge = Graph::edge(edge_index); Edge *edge = Graph::edge(edge_index);
next_index = edge->vertex_in_link_; next_index = edge->vertex_in_link_;
deleteOutEdge(edge->from(this), edge); deleteOutEdge(edge->from(this), edge);
deleteEdgeArcDelays(edge);
edge_count_--;
arc_count_ -= edge->timingArcSet()->arcCount(); arc_count_ -= edge->timingArcSet()->arcCount();
edges_->deleteObject(edge); edges_->destroy(edge);
} }
// Delete edges from vertex. // Delete edges from vertex.
for (edge_index = vertex->out_edges_; edge_index; edge_index = next_index) { for (edge_index = vertex->out_edges_; edge_index; edge_index = next_index) {
Edge *edge = Graph::edge(edge_index); Edge *edge = Graph::edge(edge_index);
next_index = edge->vertex_out_next_; next_index = edge->vertex_out_next_;
deleteInEdge(edge->to(this), edge); deleteInEdge(edge->to(this), edge);
deleteEdgeArcDelays(edge);
edge_count_--;
arc_count_ -= edge->timingArcSet()->arcCount(); arc_count_ -= edge->timingArcSet()->arcCount();
edges_->deleteObject(edge); edges_->destroy(edge);
} }
deleteVertexSlews(vertex); vertices_->destroy(vertex);
vertices_->deleteObject(vertex);
vertex_count_--;
} }
bool bool
@ -600,17 +590,69 @@ Graph::deleteOutEdge(Vertex *vertex,
Graph::edge(next)->vertex_out_prev_ = prev; Graph::edge(next)->vertex_out_prev_ = prev;
} }
Arrival *
Graph::makeArrivals(Vertex *vertex,
uint32_t count)
{
Arrival *arrivals;
ArrivalId id;
{
UniqueLock lock(arrivals_lock_);
arrivals_.make(count, arrivals, id);
}
vertex->setArrivals(id);
return arrivals;
}
Arrival *
Graph::arrivals(Vertex *vertex) const
{
return arrivals_.pointer(vertex->arrivals());
}
void
Graph::clearArrivals()
{
arrivals_.clear();
}
PathVertexRep *
Graph::makePrevPaths(Vertex *vertex,
uint32_t count)
{
PathVertexRep *prev_paths;
PrevPathId id;
{
UniqueLock lock(prev_paths_lock_);
prev_paths_.make(count, prev_paths, id);
}
vertex->setPrevPaths(id);
return prev_paths;
}
PathVertexRep *
Graph::prevPaths(Vertex *vertex) const
{
return prev_paths_.pointer(vertex->prevPaths());
}
void
Graph::clearPrevPaths()
{
prev_paths_.clear();
}
const Slew & const Slew &
Graph::slew(const Vertex *vertex, Graph::slew(const Vertex *vertex,
const TransRiseFall *tr, const TransRiseFall *tr,
DcalcAPIndex ap_index) DcalcAPIndex ap_index)
{ {
if (slew_tr_count_) { if (slew_tr_count_) {
int pool_index = int table_index =
(slew_tr_count_ == 1) ? ap_index : ap_index*slew_tr_count_+tr->index(); (slew_tr_count_ == 1) ? ap_index : ap_index*slew_tr_count_+tr->index();
DelayPool *pool = slew_pools_[pool_index]; DelayTable *table = slew_tables_[table_index];
VertexIndex vertex_index = index(vertex); VertexIndex vertex_index = index(vertex);
return *pool->find(vertex_index); return table->ref(vertex_index);
} }
else { else {
static Slew slew(0.0); static Slew slew(0.0);
@ -625,11 +667,11 @@ Graph::setSlew(Vertex *vertex,
const Slew &slew) const Slew &slew)
{ {
if (slew_tr_count_) { if (slew_tr_count_) {
int pool_index = int table_index =
(slew_tr_count_ == 1) ? ap_index : ap_index*slew_tr_count_+tr->index(); (slew_tr_count_ == 1) ? ap_index : ap_index*slew_tr_count_+tr->index();
DelayPool *pool = slew_pools_[pool_index]; DelayTable *table = slew_tables_[table_index];
VertexIndex vertex_index = index(vertex); VertexIndex vertex_index = index(vertex);
Slew &vertex_slew = *pool->find(vertex_index); Slew &vertex_slew = table->ref(vertex_index);
vertex_slew = slew; vertex_slew = slew;
} }
} }
@ -639,13 +681,13 @@ Graph::setSlew(Vertex *vertex,
Edge * Edge *
Graph::edge(EdgeIndex edge_index) const Graph::edge(EdgeIndex edge_index) const
{ {
return edges_->find(edge_index); return edges_->pointer(edge_index);
} }
EdgeIndex EdgeIndex
Graph::index(const Edge *edge) const Graph::index(const Edge *edge) const
{ {
return edges_->index(edge); return edges_->objectId(edge);
} }
Edge * Edge *
@ -653,23 +695,22 @@ Graph::makeEdge(Vertex *from,
Vertex *to, Vertex *to,
TimingArcSet *arc_set) TimingArcSet *arc_set)
{ {
Edge *edge = edges_->makeObject(); Edge *edge = edges_->make();
EdgeIndex edge_index = edges_->index(edge); edge->init(index(from), index(to), arc_set);
edge->init(vertices_->index(from), vertices_->index(to), arc_set);
makeEdgeArcDelays(edge); makeEdgeArcDelays(edge);
edge_count_++;
arc_count_ += arc_set->arcCount(); arc_count_ += arc_set->arcCount();
// Add out edge to from vertex. // Add out edge to from vertex.
EdgeIndex next = from->out_edges_; EdgeId next = from->out_edges_;
edge->vertex_out_next_ = next; edge->vertex_out_next_ = next;
edge->vertex_out_prev_ = 0; edge->vertex_out_prev_ = edge_id_null;
EdgeId edge_id = edges_->objectId(edge);
if (next) if (next)
Graph::edge(next)->vertex_out_prev_ = edge_index; Graph::edge(next)->vertex_out_prev_ = edge_id;
from->out_edges_ = edge_index; from->out_edges_ = edge_id;
// Add in edge to to vertex. // Add in edge to to vertex.
edge->vertex_in_link_ = to->in_edges_; edge->vertex_in_link_ = to->in_edges_;
to->in_edges_ = edge_index; to->in_edges_ = edge_id;
return edge; return edge;
} }
@ -681,21 +722,19 @@ 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);
deleteEdgeArcDelays(edge);
arc_count_ -= edge->timingArcSet()->arcCount(); arc_count_ -= edge->timingArcSet()->arcCount();
edge_count_--; edges_->destroy(edge);
edges_->deleteObject(edge);
} }
void void
Graph::makeArcDelayPools(ArcIndex arc_count, Graph::makeArcDelayTables(ArcIndex arc_count,
DcalcAPIndex ap_count) DcalcAPIndex ap_count)
{ {
if (have_arc_delays_) { if (have_arc_delays_) {
arc_delays_.resize(ap_count); arc_delays_.resize(ap_count);
for (DcalcAPIndex i = 0; i < ap_count; i++) { for (DcalcAPIndex i = 0; i < ap_count; i++) {
DelayPool *pool = new DelayPool(arc_count); DelayTable *table = new DelayTable();
arc_delays_[i] = pool; arc_delays_[i] = table;
} }
// Leave some room for edits. // Leave some room for edits.
@ -705,15 +744,9 @@ Graph::makeArcDelayPools(ArcIndex arc_count,
} }
void void
Graph::deleteArcDelayPools() Graph::deleteArcDelayTables()
{ {
if (have_arc_delays_) { arc_delays_.deleteContentsClear();
for (DcalcAPIndex i = 0; i < ap_count_; i++) {
DelayPool *pool = arc_delays_[i];
delete pool;
}
arc_delays_.clear();
}
} }
void void
@ -723,11 +756,11 @@ Graph::makeEdgeArcDelays(Edge *edge)
int arc_count = edge->timingArcSet()->arcCount(); int arc_count = edge->timingArcSet()->arcCount();
ArcIndex arc_index = 0; ArcIndex arc_index = 0;
for (DcalcAPIndex i = 0; i < ap_count_; i++) { for (DcalcAPIndex i = 0; i < ap_count_; i++) {
DelayPool *pool = arc_delays_[i]; DelayTable *table = arc_delays_[i];
ArcDelay *arc_delays = pool->makeObjects(arc_count); ArcDelay *arc_delays;
arc_index = pool->index(arc_delays); table->make(arc_count, arc_delays, arc_index);
for (int j = 0; j < arc_count; j++) for (int j = 0; j < arc_count; j++)
*arc_delays++ = 0.0; arc_delays[j] = 0.0;
} }
edge->setArcDelays(arc_index); edge->setArcDelays(arc_index);
// Make sure there is room for delay_annotated flags. // Make sure there is room for delay_annotated flags.
@ -740,28 +773,15 @@ Graph::makeEdgeArcDelays(Edge *edge)
} }
} }
void
Graph::deleteEdgeArcDelays(Edge *edge)
{
if (have_arc_delays_) {
ArcIndex arc_count = edge->timingArcSet()->arcCount();
ArcIndex arc_index = edge->arcDelays();
for (DcalcAPIndex i = 0; i < ap_count_; i++) {
DelayPool *pool = arc_delays_[i];
pool->deleteObjects(arc_index, arc_count);
}
}
}
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_) { if (have_arc_delays_) {
DelayPool *pool = arc_delays_[ap_index]; DelayTable *table = arc_delays_[ap_index];
ArcIndex arc_index = edge->arcDelays() + arc->index(); ArcDelay *arc_delays = table->pointer(edge->arcDelays());
ArcDelay &arc_delay = *pool->find(arc_index); ArcDelay &arc_delay = arc_delays[arc->index()];
return arc_delay; return arc_delay;
} }
else else
@ -775,10 +795,9 @@ Graph::setArcDelay(Edge *edge,
ArcDelay delay) ArcDelay delay)
{ {
if (have_arc_delays_) { if (have_arc_delays_) {
DelayPool *pool = arc_delays_[ap_index]; DelayTable *table = arc_delays_[ap_index];
ArcIndex arc_index = edge->arcDelays() + arc->index(); ArcDelay *arc_delays = table->pointer(edge->arcDelays());
ArcDelay &arc_delay = *pool->find(arc_index); arc_delays[arc->index()] = delay;
arc_delay = delay;
} }
} }
@ -788,10 +807,9 @@ Graph::wireArcDelay(const Edge *edge,
DcalcAPIndex ap_index) DcalcAPIndex ap_index)
{ {
if (have_arc_delays_) { if (have_arc_delays_) {
DelayPool *pool = arc_delays_[ap_index]; DelayTable *table = arc_delays_[ap_index];
ArcIndex arc_index = edge->arcDelays() + tr->index(); ArcDelay *arc_delays = table->pointer(edge->arcDelays());
const ArcDelay &arc_delay = *pool->find(arc_index); return arc_delays[tr->index()];
return arc_delay;
} }
else else
return delay_zero; return delay_zero;
@ -804,10 +822,9 @@ Graph::setWireArcDelay(Edge *edge,
const ArcDelay &delay) const ArcDelay &delay)
{ {
if (have_arc_delays_) { if (have_arc_delays_) {
DelayPool *pool = arc_delays_[ap_index]; DelayTable *table = arc_delays_[ap_index];
ArcIndex arc_index = edge->arcDelays() + tr->index(); ArcDelay *arc_delays = table->pointer(edge->arcDelays());
ArcDelay &arc_delay = *pool->find(arc_index); arc_delays[tr->index()] = delay;
arc_delay = delay;
} }
} }
@ -870,12 +887,12 @@ Graph::setDelayCount(DcalcAPIndex ap_count)
{ {
if (ap_count != ap_count_) { if (ap_count != ap_count_) {
// Discard any existing delays. // Discard any existing delays.
deleteSlewPools(); deleteSlewTables();
deleteArcDelayPools(); deleteArcDelayTables();
removeWidthCheckAnnotations(); removeWidthCheckAnnotations();
removePeriodCheckAnnotations(); removePeriodCheckAnnotations();
makeSlewPools(vertex_count_, ap_count); makeSlewTables(ap_count);
makeArcDelayPools(arc_count_, ap_count); makeArcDelayTables(arc_count_, ap_count);
ap_count_ = ap_count; ap_count_ = ap_count;
removeDelays(); removeDelays();
} }
@ -887,7 +904,7 @@ Graph::removeDelays()
VertexIterator vertex_iter(this); VertexIterator vertex_iter(this);
while (vertex_iter.hasNext()) { while (vertex_iter.hasNext()) {
Vertex *vertex = vertex_iter.next(); Vertex *vertex = vertex_iter.next();
makeVertexSlews(); makeVertexSlews(vertex);
VertexOutEdgeIterator edge_iter(vertex, this); VertexOutEdgeIterator edge_iter(vertex, this);
while (edge_iter.hasNext()) { while (edge_iter.hasNext()) {
Edge *edge = edge_iter.next(); Edge *edge = edge_iter.next();
@ -927,54 +944,34 @@ Graph::delayAnnotated(Edge *edge)
} }
void void
Graph::makeSlewPools(VertexIndex vertex_count, Graph::makeSlewTables(DcalcAPIndex ap_count)
DcalcAPIndex ap_count)
{ {
DcalcAPIndex tr_ap_count = slew_tr_count_ * ap_count; DcalcAPIndex tr_ap_count = slew_tr_count_ * ap_count;
slew_pools_.resize(tr_ap_count); slew_tables_.resize(tr_ap_count);
for (DcalcAPIndex i = 0; i < tr_ap_count; i++) { for (DcalcAPIndex i = 0; i < tr_ap_count; i++) {
DelayPool *pool = new DelayPool(vertex_count); DelayTable *table = new DelayTable;
slew_pools_[i] = pool; slew_tables_[i] = table;
} }
} }
void void
Graph::deleteSlewPools() Graph::deleteSlewTables()
{ {
if (slew_tr_count_) { slew_tables_.deleteContentsClear();
DcalcAPIndex tr_ap_count = slew_tr_count_ * ap_count_;
for (DcalcAPIndex i = 0; i < tr_ap_count; i++) {
DelayPool *pool = slew_pools_[i];
delete pool;
}
slew_pools_.clear();
}
} }
void void
Graph::makeVertexSlews() Graph::makeVertexSlews(Vertex *vertex)
{ {
DcalcAPIndex tr_ap_count = slew_tr_count_ * ap_count_; DcalcAPIndex tr_ap_count = slew_tr_count_ * ap_count_;
slew_pools_.resize(tr_ap_count);
for (DcalcAPIndex i = 0; i < tr_ap_count; i++) { for (DcalcAPIndex i = 0; i < tr_ap_count; i++) {
DelayPool *pool = slew_pools_[i]; DelayTable *table = slew_tables_[i];
Slew *slew = pool->makeObject(); // Slews are 1:1 with vertices and use the same object id.
Slew *slew = table->ensureId(vertices_->objectId(vertex));
*slew = 0.0; *slew = 0.0;
} }
} }
void
Graph::deleteVertexSlews(Vertex *vertex)
{
VertexIndex vertex_index = index(vertex);
DcalcAPIndex tr_ap_count = slew_tr_count_ * ap_count_;
slew_pools_.resize(tr_ap_count);
for (DcalcAPIndex i = 0; i < tr_ap_count; i++) {
DelayPool *pool = slew_pools_[i];
pool->deleteObject(vertex_index);
}
}
//////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////
void void
@ -1109,6 +1106,7 @@ Graph::removeDelaySlewAnnotations()
Vertex::Vertex() Vertex::Vertex()
{ {
init(nullptr, false, false); init(nullptr, false, false);
object_idx_ = object_idx_null;
} }
void void
@ -1119,10 +1117,10 @@ Vertex::init(Pin *pin,
pin_ = pin; pin_ = pin;
is_reg_clk_ = is_reg_clk; is_reg_clk_ = is_reg_clk;
is_bidirect_drvr_ = is_bidirect_drvr; is_bidirect_drvr_ = is_bidirect_drvr;
in_edges_ = 0; in_edges_ = edge_id_null;
out_edges_ = 0; out_edges_ = edge_id_null;
arrivals_ = nullptr; arrivals_ = arrival_null;
prev_paths_ = nullptr; prev_paths_ = prev_path_null;
has_requireds_ = false; has_requireds_ = false;
tag_group_index_ = tag_group_index_max; tag_group_index_ = tag_group_index_max;
slew_annotated_ = false; slew_annotated_ = false;
@ -1140,6 +1138,12 @@ Vertex::init(Pin *pin,
requireds_pruned_ = false; requireds_pruned_ = false;
} }
void
Vertex::setObjectIdx(ObjectIdx idx)
{
object_idx_ = idx;
}
const char * const char *
Vertex::name(const Network *network) const Vertex::name(const Network *network) const
{ {
@ -1243,13 +1247,13 @@ Vertex::setTagGroupIndex(TagGroupIndex tag_index)
} }
void void
Vertex::setArrivals(Arrival *arrivals) Vertex::setArrivals(ArrivalId id)
{ {
arrivals_ = arrivals; arrivals_ = id;
} }
void void
Vertex::setPrevPaths(PathVertexRep *prev_paths) Vertex::setPrevPaths(PrevPathId prev_paths)
{ {
prev_paths_ = prev_paths; prev_paths_ = prev_paths;
} }
@ -1341,6 +1345,7 @@ Vertex::setBfsInQueue(BfsIndex index,
Edge::Edge() Edge::Edge()
{ {
init(0, 0, nullptr); init(0, 0, nullptr);
object_idx_ = object_idx_null;
} }
void void
@ -1353,9 +1358,9 @@ Edge::init(VertexIndex from,
arc_set_ = arc_set; arc_set_ = arc_set;
arc_delays_ = 0; arc_delays_ = 0;
vertex_in_link_ = 0; vertex_in_link_ = edge_id_null;
vertex_out_next_ = 0; vertex_out_next_ = edge_id_null;
vertex_out_prev_ = 0; 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;
delay_annotation_is_incremental_ = false; delay_annotation_is_incremental_ = false;
@ -1365,6 +1370,12 @@ Edge::init(VertexIndex from,
is_disabled_loop_ = false; is_disabled_loop_ = false;
} }
void
Edge::setObjectIdx(ObjectIdx idx)
{
object_idx_ = idx;
}
void void
Edge::setTimingArcSet(TimingArcSet *set) Edge::setTimingArcSet(TimingArcSet *set)
{ {

View File

@ -17,16 +17,20 @@
#ifndef STA_GRAPH_H #ifndef STA_GRAPH_H
#define STA_GRAPH_H #define STA_GRAPH_H
#include "Mutex.hh"
#include "DisallowCopyAssign.hh" #include "DisallowCopyAssign.hh"
#include "Iterator.hh" #include "Iterator.hh"
#include "Map.hh" #include "Map.hh"
#include "Vector.hh" #include "Vector.hh"
#include "Pool.hh" #include "ObjectTable.hh"
#include "ArrayTable.hh"
#include "StaState.hh" #include "StaState.hh"
#include "LibertyClass.hh" #include "LibertyClass.hh"
#include "NetworkClass.hh" #include "NetworkClass.hh"
#include "Delay.hh" #include "Delay.hh"
#include "GraphClass.hh" #include "GraphClass.hh"
#include "VertexId.hh"
#include "PathVertexRep.hh"
namespace sta { namespace sta {
@ -36,14 +40,25 @@ class PathVertexRep;
enum class LevelColor { white, gray, black }; enum class LevelColor { white, gray, black };
typedef Pool<Delay> DelayPool; typedef ArrayTable<Delay> DelayTable;
typedef Pool<Vertex> VertexPool; typedef ObjectTable<Vertex> VertexTable;
typedef Pool<Edge> EdgePool; typedef ObjectTable<Edge> EdgeTable;
typedef ArrayTable<Arrival> ArrivalsTable;
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*> WidthCheckAnnotations; typedef Map<const Pin*, float*> WidthCheckAnnotations;
typedef Map<const Pin*, float*> PeriodCheckAnnotations; typedef Map<const Pin*, float*> PeriodCheckAnnotations;
typedef Vector<DelayPool*> DelayPoolSeq; 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. // The graph acts as a BUILDER for the graph vertices and edges.
class Graph : public StaState class Graph : public StaState
@ -83,7 +98,15 @@ public:
Vertex *pinLoadVertex(const Pin *pin) const; Vertex *pinLoadVertex(const Pin *pin) const;
virtual void deleteVertex(Vertex *vertex); virtual void deleteVertex(Vertex *vertex);
bool hasFaninOne(Vertex *vertex) const; bool hasFaninOne(Vertex *vertex) const;
VertexIndex vertexCount() { return vertex_count_; } VertexIndex vertexCount() { return vertices_->size(); }
Arrival *makeArrivals(Vertex *vertex,
uint32_t count);
Arrival *arrivals(Vertex *vertex) const;
void clearArrivals();
PathVertexRep *makePrevPaths(Vertex *vertex,
uint32_t count);
PathVertexRep *prevPaths(Vertex *vertex) const;
void clearPrevPaths();
// Slews are reported slews in seconds. // Slews are reported slews in seconds.
// 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
@ -142,7 +165,7 @@ 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);
EdgeIndex edgeCount() { return edge_count_; } EdgeIndex edgeCount() { return edges_->size(); }
virtual ArcIndex arcCount() { return arc_count_; } virtual ArcIndex arcCount() { return arc_count_; }
// Sdf width check annotation. // Sdf width check annotation.
@ -202,15 +225,12 @@ protected:
LibertyPort *from_to_port); LibertyPort *from_to_port);
void removeWidthCheckAnnotations(); void removeWidthCheckAnnotations();
void removePeriodCheckAnnotations(); void removePeriodCheckAnnotations();
void makeSlewPools(VertexIndex vertex_count, void makeSlewTables(DcalcAPIndex count);
DcalcAPIndex count); void deleteSlewTables();
void deleteSlewPools(); void makeVertexSlews(Vertex *vertex);
void makeVertexSlews(); void makeArcDelayTables(ArcIndex arc_count,
void deleteVertexSlews(Vertex *vertex);
void makeArcDelayPools(ArcIndex arc_count,
DcalcAPIndex ap_count); DcalcAPIndex ap_count);
void deleteArcDelayPools(); void deleteArcDelayTables();
virtual void deleteEdgeArcDelays(Edge *edge);
void deleteInEdge(Vertex *vertex, void deleteInEdge(Vertex *vertex,
Edge *edge); Edge *edge);
void deleteOutEdge(Vertex *vertex, void deleteOutEdge(Vertex *vertex,
@ -220,29 +240,32 @@ protected:
// User defined predicate to filter graph edges for liberty timing arcs. // User defined predicate to filter graph edges for liberty timing arcs.
virtual bool filterEdge(TimingArcSet *) const { return true; } virtual bool filterEdge(TimingArcSet *) const { return true; }
VertexPool *vertices_; VertexTable *vertices_;
EdgePool *edges_; EdgeTable *edges_;
// Bidirect pins are split into two vertices: // Bidirect pins are split into two vertices:
// load/sink (top level output, instance pin input) vertex in pin_vertex_map // load/sink (top level output, instance pin input) vertex in pin_vertex_map
// 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_;
VertexIndex vertex_count_;
EdgeIndex edge_count_;
ArcIndex arc_count_; ArcIndex arc_count_;
ArrivalsTable arrivals_;
std::mutex arrivals_lock_;
PrevPathsTable prev_paths_;
std::mutex prev_paths_lock_;
Vector<bool> arc_delay_annotated_; Vector<bool> arc_delay_annotated_;
int slew_tr_count_; int slew_tr_count_;
bool have_arc_delays_; bool have_arc_delays_;
DcalcAPIndex ap_count_; DcalcAPIndex ap_count_;
DelayPoolSeq slew_pools_; // [ap_index][tr_index][vertex_index] DelayTableSeq slew_tables_; // [ap_index][tr_index][vertex_index]
VertexIndex slew_count_; VertexIndex slew_count_;
DelayPoolSeq arc_delays_; // [ap_index][edge_arc_index] DelayTableSeq arc_delays_; // [ap_index][edge_arc_index]
// Sdf width check annotations. // Sdf width check annotations.
WidthCheckAnnotations *width_check_annotations_; WidthCheckAnnotations *width_check_annotations_;
// 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.
VertexSet reg_clk_vertices_; VertexSet reg_clk_vertices_;
friend class Vertex; friend class Vertex;
friend class VertexIterator; friend class VertexIterator;
friend class VertexInEdgeIterator; friend class VertexInEdgeIterator;
@ -268,10 +291,10 @@ public:
bool isRoot() const{ return level_ == 0; } bool isRoot() const{ return level_ == 0; }
LevelColor color() const { return static_cast<LevelColor>(color_); } LevelColor color() const { return static_cast<LevelColor>(color_); }
void setColor(LevelColor color); void setColor(LevelColor color);
Arrival *arrivals() const { return arrivals_; } ArrivalId arrivals() const { return arrivals_; }
void setArrivals(Arrival *arrivals); void setArrivals(ArrivalId id);
PathVertexRep *prevPaths() const { return prev_paths_; } PrevPathId prevPaths() const { return prev_paths_; }
void setPrevPaths(PathVertexRep *prev_paths); void setPrevPaths(PrevPathId id);
// Requireds optionally follow arrivals in the same array. // Requireds optionally follow arrivals in the same array.
bool hasRequireds() const { return has_requireds_; } bool hasRequireds() const { return has_requireds_; }
void setHasRequireds(bool has_req); void setHasRequireds(bool has_req);
@ -316,6 +339,10 @@ public:
bool requiredsPruned() const { return requireds_pruned_; } bool requiredsPruned() const { return requireds_pruned_; }
void setRequiredsPruned(bool pruned); void setRequiredsPruned(bool pruned);
// ObjectTable interface.
ObjectIdx objectIdx() const { return object_idx_; }
void setObjectIdx(ObjectIdx idx);
static int transitionCount() { return 2; } // rise/fall static int transitionCount() { return 2; } // rise/fall
protected: protected:
@ -324,8 +351,8 @@ protected:
bool is_reg_clk); bool is_reg_clk);
Pin *pin_; Pin *pin_;
Arrival *arrivals_; ArrivalId arrivals_;
PathVertexRep *prev_paths_; PrevPathId prev_paths_;
EdgeIndex in_edges_; // Edges to this vertex. EdgeIndex in_edges_; // Edges to this vertex.
EdgeIndex out_edges_; // Edges from this vertex. EdgeIndex out_edges_; // Edges from this vertex.
@ -358,6 +385,8 @@ protected:
bool crpr_path_pruning_disabled_:1; bool crpr_path_pruning_disabled_:1;
bool requireds_pruned_:1; bool requireds_pruned_:1;
unsigned object_idx_:VertexTable::idx_bits;
private: private:
DISALLOW_COPY_AND_ASSIGN(Vertex); DISALLOW_COPY_AND_ASSIGN(Vertex);
@ -403,17 +432,21 @@ public:
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);
// ObjectTable interface.
ObjectIdx objectIdx() const { return object_idx_; }
void setObjectIdx(ObjectIdx idx);
protected: protected:
void init(VertexIndex from, void init(VertexIndex from,
VertexIndex to, VertexIndex to,
TimingArcSet *arc_set); TimingArcSet *arc_set);
TimingArcSet *arc_set_; TimingArcSet *arc_set_;
VertexIndex from_; VertexId from_;
VertexIndex to_; VertexId to_;
VertexIndex vertex_in_link_; // Vertex in edges list. EdgeId vertex_in_link_; // Vertex in edges list.
VertexIndex vertex_out_next_; // Vertex out edges doubly linked list. EdgeId vertex_out_next_; // Vertex out edges doubly linked list.
VertexIndex vertex_out_prev_; EdgeId vertex_out_prev_;
ArcIndex arc_delays_; ArcIndex arc_delays_;
bool delay_annotation_is_incremental_:1; bool delay_annotation_is_incremental_:1;
bool is_bidirect_inst_path_:1; bool is_bidirect_inst_path_:1;
@ -423,6 +456,7 @@ protected:
bool is_disabled_constraint_:1; bool is_disabled_constraint_:1;
bool is_disabled_cond_:1; bool is_disabled_cond_:1;
bool is_disabled_loop_:1; bool is_disabled_loop_:1;
unsigned object_idx_:VertexTable::idx_bits;
private: private:
DISALLOW_COPY_AND_ASSIGN(Edge); DISALLOW_COPY_AND_ASSIGN(Edge);

View File

@ -1032,19 +1032,19 @@ ConcreteNetwork::direction(const Pin *pin) const
return cport->direction(); return cport->direction();
} }
VertexIndex VertexId
ConcreteNetwork::vertexIndex(const Pin *pin) const ConcreteNetwork::vertexIndex(const Pin *pin) const
{ {
const ConcretePin *cpin = reinterpret_cast<const ConcretePin*>(pin); const ConcretePin *cpin = reinterpret_cast<const ConcretePin*>(pin);
return cpin->vertexIndex(); return cpin->vertexId();
} }
void void
ConcreteNetwork::setVertexIndex(Pin *pin, ConcreteNetwork::setVertexIndex(Pin *pin,
VertexIndex index) VertexId id)
{ {
ConcretePin *cpin = reinterpret_cast<ConcretePin*>(pin); ConcretePin *cpin = reinterpret_cast<ConcretePin*>(pin);
cpin->setVertexIndex(index); cpin->setVertexId(id);
} }
//////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////
@ -1666,7 +1666,7 @@ ConcretePin::ConcretePin(ConcreteInstance *instance,
term_(nullptr), term_(nullptr),
net_next_(nullptr), net_next_(nullptr),
net_prev_(nullptr), net_prev_(nullptr),
vertex_index_(0) vertex_id_(vertex_id_null)
{ {
} }
@ -1677,9 +1677,9 @@ ConcretePin::name() const
} }
void void
ConcretePin::setVertexIndex(VertexIndex index) ConcretePin::setVertexId(VertexId id)
{ {
vertex_index_ = index; vertex_id_ = id;
} }
//////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////

View File

@ -131,9 +131,9 @@ public:
virtual Term *term(const Pin *pin) const; virtual Term *term(const Pin *pin) const;
virtual Port *port(const Pin *pin) const; virtual Port *port(const Pin *pin) const;
virtual PortDirection *direction(const Pin *pin) const; virtual PortDirection *direction(const Pin *pin) const;
virtual VertexIndex vertexIndex(const Pin *pin) const; virtual VertexId vertexIndex(const Pin *pin) const;
virtual void setVertexIndex(Pin *pin, virtual void setVertexIndex(Pin *pin,
VertexIndex index); VertexId id);
virtual Net *net(const Term *term) const; virtual Net *net(const Term *term) const;
virtual Pin *pin(const Term *term) const; virtual Pin *pin(const Term *term) const;
@ -318,8 +318,8 @@ public:
ConcreteNet *net() const { return net_; } ConcreteNet *net() const { return net_; }
ConcretePort *port() const { return port_; } ConcretePort *port() const { return port_; }
ConcreteTerm *term() const { return term_; } ConcreteTerm *term() const { return term_; }
VertexIndex vertexIndex() const { return vertex_index_; } VertexId vertexId() const { return vertex_id_; }
void setVertexIndex(VertexIndex index); void setVertexId(VertexId id);
protected: protected:
~ConcretePin() {} ~ConcretePin() {}
@ -334,7 +334,7 @@ protected:
// Doubly linked list of net pins. // Doubly linked list of net pins.
ConcretePin *net_next_; ConcretePin *net_next_;
ConcretePin *net_prev_; ConcretePin *net_prev_;
VertexIndex vertex_index_; VertexId vertex_id_;
private: private:
DISALLOW_COPY_AND_ASSIGN(ConcretePin); DISALLOW_COPY_AND_ASSIGN(ConcretePin);

View File

@ -21,7 +21,7 @@
#include "Map.hh" #include "Map.hh"
#include "StringUtil.hh" #include "StringUtil.hh"
#include "LibertyClass.hh" #include "LibertyClass.hh"
#include "GraphClass.hh" #include "VertexId.hh"
#include "NetworkClass.hh" #include "NetworkClass.hh"
#include "StaState.hh" #include "StaState.hh"
@ -320,10 +320,10 @@ public:
virtual PinSet *drivers(const Pin *pin); virtual PinSet *drivers(const Pin *pin);
virtual bool pinLess(const Pin *pin1, virtual bool pinLess(const Pin *pin1,
const Pin *pin2) const; const Pin *pin2) const;
// Return the index of the pin graph vertex. // Return the id of the pin graph vertex.
virtual VertexIndex vertexIndex(const Pin *pin) const = 0; virtual VertexId vertexIndex(const Pin *pin) const = 0;
virtual void setVertexIndex(Pin *pin, virtual void setVertexIndex(Pin *pin,
VertexIndex index) = 0; VertexId id) = 0;
int pinCount(); int pinCount();
int pinCount(Instance *inst); int pinCount(Instance *inst);
int leafPinCount(); int leafPinCount();

View File

@ -210,7 +210,7 @@ NetworkNameAdapter::direction(const Port *port) const
return network_->direction(port); return network_->direction(port);
} }
VertexIndex VertexId
NetworkNameAdapter::vertexIndex(const Pin *pin) const NetworkNameAdapter::vertexIndex(const Pin *pin) const
{ {
return network_->vertexIndex(pin); return network_->vertexIndex(pin);
@ -218,9 +218,9 @@ NetworkNameAdapter::vertexIndex(const Pin *pin) const
void void
NetworkNameAdapter::setVertexIndex(Pin *pin, NetworkNameAdapter::setVertexIndex(Pin *pin,
VertexIndex index) VertexId id)
{ {
network_->setVertexIndex(pin, index); network_->setVertexIndex(pin, id);
} }
bool bool

View File

@ -100,9 +100,9 @@ public:
virtual Net *net(const Pin *pin) const; virtual Net *net(const Pin *pin) const;
virtual Term *term(const Pin *pin) const; virtual Term *term(const Pin *pin) const;
virtual PortDirection *direction(const Pin *pin) const; virtual PortDirection *direction(const Pin *pin) const;
virtual VertexIndex vertexIndex(const Pin *pin) const; virtual VertexId vertexIndex(const Pin *pin) const;
virtual void setVertexIndex(Pin *pin, virtual void setVertexIndex(Pin *pin,
VertexIndex index); VertexId id);
virtual Net *net(const Term *term) const; virtual Net *net(const Term *term) const;
virtual Pin *pin(const Term *term) const; virtual Pin *pin(const Term *term) const;

View File

@ -62,7 +62,7 @@ CheckCrpr::clkPathPrev(Vertex *vertex,
int arrival_index, int arrival_index,
PathVertex &tmp) PathVertex &tmp)
{ {
PathVertexRep *prevs = vertex->prevPaths(); PathVertexRep *prevs = graph_->prevPaths(vertex);
if (prevs) { if (prevs) {
PathVertexRep *prev = &prevs[arrival_index]; PathVertexRep *prev = &prevs[arrival_index];
if (prev->isNull()) if (prev->isNull())

View File

@ -37,6 +37,8 @@
namespace sta { namespace sta {
using std::max;
class GenclkInfo class GenclkInfo
{ {
public: public:
@ -896,9 +898,9 @@ void
Genclks::copyGenClkSrcPaths(Vertex *vertex, Genclks::copyGenClkSrcPaths(Vertex *vertex,
TagGroupBldr *tag_bldr) TagGroupBldr *tag_bldr)
{ {
Arrival *arrivals = vertex->arrivals(); Arrival *arrivals = graph_->arrivals(vertex);
if (arrivals) { if (arrivals) {
PathVertexRep *prev_paths = vertex->prevPaths(); PathVertexRep *prev_paths = graph_->prevPaths(vertex);
TagGroup *tag_group = search_->tagGroup(vertex); TagGroup *tag_group = search_->tagGroup(vertex);
ArrivalMap::Iterator arrival_iter(tag_group->arrivalMap()); ArrivalMap::Iterator arrival_iter(tag_group->arrivalMap());
while (arrival_iter.hasNext()) { while (arrival_iter.hasNext()) {

View File

@ -30,6 +30,8 @@
namespace sta { namespace sta {
using std::max;
Levelize::Levelize(StaState *sta) : Levelize::Levelize(StaState *sta) :
StaState(sta), StaState(sta),
search_pred_(new SearchPredNonLatch2(sta)), search_pred_(new SearchPredNonLatch2(sta)),

View File

@ -240,18 +240,18 @@ PathVertex::setArrivalIndex(int arrival_index)
} }
Arrival Arrival
PathVertex::arrival(const StaState *) const PathVertex::arrival(const StaState *sta) const
{ {
Arrival *arrivals = vertex_->arrivals(); Arrival *arrivals = sta->graph()->arrivals(vertex_);
return arrivals[arrival_index_]; return arrivals[arrival_index_];
} }
void void
PathVertex::setArrival(Arrival arrival, PathVertex::setArrival(Arrival arrival,
const StaState *) const StaState *sta)
{ {
if (tag_) { if (tag_) {
Arrival *arrivals = vertex_->arrivals(); Arrival *arrivals = sta->graph()->arrivals(vertex_);
arrivals[arrival_index_] = arrival; arrivals[arrival_index_] = arrival;
} }
} }
@ -263,7 +263,7 @@ PathVertex::required(const StaState *sta) const
const Search *search = sta->search(); const Search *search = sta->search();
TagGroup *tag_group = search->tagGroup(vertex_); TagGroup *tag_group = search->tagGroup(vertex_);
int req_index = tag_group->requiredIndex(arrival_index_); int req_index = tag_group->requiredIndex(arrival_index_);
Arrival *arrivals = vertex_->arrivals(); Arrival *arrivals = sta->graph()->arrivals(vertex_);
return arrivals[req_index]; return arrivals[req_index];
} }
else else
@ -274,16 +274,15 @@ void
PathVertex::setRequired(const Required &required, PathVertex::setRequired(const Required &required,
const StaState *sta) const StaState *sta)
{ {
Graph *graph = sta->graph();
const Search *search = sta->search(); const Search *search = sta->search();
TagGroup *tag_group = search->tagGroup(vertex_); TagGroup *tag_group = search->tagGroup(vertex_);
Arrival *arrivals = vertex_->arrivals(); Arrival *arrivals = graph->arrivals(vertex_);
int arrival_count = tag_group->arrivalCount(); int arrival_count = tag_group->arrivalCount();
if (!vertex_->hasRequireds()) { if (!vertex_->hasRequireds()) {
Arrival *new_arrivals = new Arrival[arrival_count * 2]; Arrival *new_arrivals = graph->makeArrivals(vertex_, arrival_count * 2);
memcpy(new_arrivals, arrivals, arrival_count * sizeof(Arrival)); memcpy(new_arrivals, arrivals, arrival_count * sizeof(Arrival));
vertex_->setArrivals(new_arrivals);
vertex_->setHasRequireds(true); vertex_->setHasRequireds(true);
delete [] arrivals;
arrivals = new_arrivals; arrivals = new_arrivals;
} }
int req_index = arrival_index_ + arrival_count; int req_index = arrival_index_ + arrival_count;
@ -292,19 +291,10 @@ PathVertex::setRequired(const Required &required,
void void
PathVertex::deleteRequireds(Vertex *vertex, PathVertex::deleteRequireds(Vertex *vertex,
const StaState *sta) const StaState *)
{ {
if (vertex->hasRequireds()) {
const Search *search = sta->search();
TagGroup *tag_group = search->tagGroup(vertex);
Arrival *arrivals = vertex->arrivals();
int arrival_count = tag_group->arrivalCount();
Arrival *new_arrivals = new Arrival[arrival_count];
memcpy(new_arrivals, arrivals, arrival_count * sizeof(Arrival));
vertex->setArrivals(new_arrivals);
vertex->setHasRequireds(false); vertex->setHasRequireds(false);
delete [] arrivals; // Don't bother reclaiming requieds from arrival table.
}
} }
bool bool

View File

@ -142,7 +142,7 @@ PathVertexRep::arrival(const StaState *sta) const
tag_group->arrivalIndex(tag, arrival_index, arrival_exists); tag_group->arrivalIndex(tag, arrival_index, arrival_exists);
if (!arrival_exists) if (!arrival_exists)
internalError("tag group missing tag"); internalError("tag group missing tag");
Arrival *arrivals = vertex->arrivals(); Arrival *arrivals = graph->arrivals(vertex);
return arrivals[arrival_index]; return arrivals[arrival_index];
} }

View File

@ -17,10 +17,9 @@
#ifndef STA_PATH_VERTEX_REP_H #ifndef STA_PATH_VERTEX_REP_H
#define STA_PATH_VERTEX_REP_H #define STA_PATH_VERTEX_REP_H
namespace sta { #include "SearchClass.hh"
class StaState; namespace sta {
class PathVertex;
// Path representation that references a vertex arrival via a tag. // Path representation that references a vertex arrival via a tag.
// This does not implement the Path API which uses virtual functions // This does not implement the Path API which uses virtual functions

View File

@ -399,6 +399,8 @@ Search::deletePaths()
Vertex *vertex = vertex_iter.next(); Vertex *vertex = vertex_iter.next();
deletePaths1(vertex); deletePaths1(vertex);
} }
graph_->clearArrivals();
graph_->clearPrevPaths();
arrivals_exist_ = false; arrivals_exist_ = false;
} }
} }
@ -406,12 +408,8 @@ Search::deletePaths()
void void
Search::deletePaths1(Vertex *vertex) Search::deletePaths1(Vertex *vertex)
{ {
Arrival *arrivals = vertex->arrivals(); vertex->setArrivals(arrival_null);
delete [] arrivals; vertex->setPrevPaths(prev_path_null);
vertex->setArrivals(nullptr);
PathVertexRep *prev_paths = vertex->prevPaths();
delete [] prev_paths;
vertex->setPrevPaths(nullptr);
vertex->setTagGroupIndex(tag_group_index_max); vertex->setTagGroupIndex(tag_group_index_max);
vertex->setHasRequireds(false); vertex->setHasRequireds(false);
vertex->setCrprPathPruningDisabled(false); vertex->setCrprPathPruningDisabled(false);
@ -1191,7 +1189,7 @@ bool
Search::arrivalsChanged(Vertex *vertex, Search::arrivalsChanged(Vertex *vertex,
TagGroupBldr *tag_bldr) TagGroupBldr *tag_bldr)
{ {
Arrival *arrivals1 = vertex->arrivals(); Arrival *arrivals1 = graph_->arrivals(vertex);
if (arrivals1) { if (arrivals1) {
TagGroup *tag_group = tagGroup(vertex); TagGroup *tag_group = tagGroup(vertex);
if (tag_group->arrivalMap()->size() != tag_bldr->arrivalMap()->size()) if (tag_group->arrivalMap()->size() != tag_bldr->arrivalMap()->size())
@ -2682,8 +2680,8 @@ Search::setVertexArrivals(Vertex *vertex,
deletePaths(vertex); deletePaths(vertex);
else { else {
TagGroup *prev_tag_group = tagGroup(vertex); TagGroup *prev_tag_group = tagGroup(vertex);
Arrival *prev_arrivals = vertex->arrivals(); Arrival *prev_arrivals = graph_->arrivals(vertex);
PathVertexRep *prev_paths = vertex->prevPaths(); PathVertexRep *prev_paths = graph_->prevPaths(vertex);
TagGroup *tag_group = findTagGroup(tag_bldr); TagGroup *tag_group = findTagGroup(tag_bldr);
int arrival_count = tag_group->arrivalCount(); int arrival_count = tag_group->arrivalCount();
@ -2696,30 +2694,24 @@ Search::setVertexArrivals(Vertex *vertex,
|| tag_group == prev_tag_group)) { || tag_group == prev_tag_group)) {
if (tag_bldr->hasClkTag() || tag_bldr->hasGenClkSrcTag()) { if (tag_bldr->hasClkTag() || tag_bldr->hasGenClkSrcTag()) {
if (prev_paths == nullptr) if (prev_paths == nullptr)
prev_paths = new PathVertexRep[arrival_count]; prev_paths = graph_->makePrevPaths(vertex, arrival_count);
} }
else { else {
// Prev paths not required, delete stale ones. // Prev paths not required.
delete [] prev_paths;
prev_paths = nullptr; prev_paths = nullptr;
vertex->setPrevPaths(nullptr); vertex->setPrevPaths(prev_path_null);
} }
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());
} }
else { else {
delete [] prev_arrivals; Arrival *arrivals = graph_->makeArrivals(vertex, arrival_count);
delete [] prev_paths;
Arrival *arrivals = new Arrival[arrival_count];
prev_paths = nullptr; prev_paths = nullptr;
if (tag_bldr->hasClkTag() || tag_bldr->hasGenClkSrcTag()) if (tag_bldr->hasClkTag() || tag_bldr->hasGenClkSrcTag())
prev_paths = new PathVertexRep[arrival_count]; prev_paths = graph_->makePrevPaths(vertex, arrival_count);
tag_bldr->copyArrivals(tag_group, arrivals, prev_paths); tag_bldr->copyArrivals(tag_group, arrivals, prev_paths);
vertex->setTagGroupIndex(tag_group->index()); vertex->setTagGroupIndex(tag_group->index());
vertex->setArrivals(arrivals);
vertex->setPrevPaths(prev_paths);
if (has_requireds) { if (has_requireds) {
requiredInvalid(vertex); requiredInvalid(vertex);
@ -2734,7 +2726,7 @@ Search::reportArrivals(Vertex *vertex) const
{ {
report_->print("Vertex %s\n", vertex->name(sdc_network_)); report_->print("Vertex %s\n", vertex->name(sdc_network_));
TagGroup *tag_group = tagGroup(vertex); TagGroup *tag_group = tagGroup(vertex);
Arrival *arrivals = vertex->arrivals(); Arrival *arrivals = graph_->arrivals(vertex);
if (tag_group) { if (tag_group) {
report_->print("Group %u\n", tag_group->index()); report_->print("Group %u\n", tag_group->index());
ArrivalMap::Iterator arrival_iter(tag_group->arrivalMap()); ArrivalMap::Iterator arrival_iter(tag_group->arrivalMap());

View File

@ -3915,7 +3915,7 @@ Sta::connectPinAfter(Pin *pin)
} }
else { else {
Vertex *vertex, *bidir_drvr_vertex; Vertex *vertex, *bidir_drvr_vertex;
if (network_->vertexIndex(pin) == 0) { if (network_->vertexIndex(pin) == vertex_id_null) {
graph_->makePinVertices(pin, vertex, bidir_drvr_vertex); graph_->makePinVertices(pin, vertex, bidir_drvr_vertex);
graph_->makePinInstanceEdges(pin); graph_->makePinInstanceEdges(pin);
} }

188
util/ArrayTable.hh Normal file
View File

@ -0,0 +1,188 @@
// Parallax Static Timing Analyzer
// Copyright (c) 2019, Parallax Software, Inc.
// All rights reserved.
//
// No part of this document may be copied, transmitted or
// disclosed in any form or fashion without the express
// written consent of Parallax Software, Inc.
#ifndef STA_ARRAY_TABLE_H
#define STA_ARRAY_TABLE_H
#include "Vector.hh"
#include "ObjectId.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);
// 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 ObjectId idx_bits = 10;
static constexpr ObjectId block_size = (1 << idx_bits);
private:
ArrayBlock<TYPE> *makeBlock(uint32_t size);
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_;
Vector<ArrayBlock<TYPE>*> blocks_;
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)
{
}
template <class TYPE>
ArrayTable<TYPE>::~ArrayTable()
{
blocks_.deleteContents();
}
template <class TYPE>
void
ArrayTable<TYPE>::make(uint32_t count,
TYPE *&array,
ObjectId &id)
{
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 = (count > block_size) ? count : block_size;
if (count > block_size)
printf("big block %d\n", 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);
blocks_.push_back(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>
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);
blocks_.push_back(block);
}
return blocks_[blk_idx]->pointer(obj_idx);
}
template <class TYPE>
TYPE &
ArrayTable<TYPE>::ref(ObjectId id) const
{
if (id == object_id_null)
internalError("null ObjectId reference is undefined.");
else {
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()
{
blocks_.deleteContentsClear();
size_ = 0;
free_block_idx_ = block_idx_null;
free_idx_ = object_idx_null;
}
////////////////////////////////////////////////////////////////
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
#endif

28
util/ObjectId.hh Normal file
View File

@ -0,0 +1,28 @@
// Parallax Static Timing Analyzer
// Copyright (c) 2019, Parallax Software, Inc.
// All rights reserved.
//
// No part of this document may be copied, transmitted or
// disclosed in any form or fashion without the express
// written consent of Parallax Software, Inc.
#ifndef STA_OBJECT_ID_H
#define STA_OBJECT_ID_H
#include <cstdint>
namespace sta {
// ObjectId is block index and object index within the block.
typedef uint32_t ObjectId;
// Block index.
typedef uint32_t BlockIdx;
// Object index within a block.
typedef uint32_t ObjectIdx;
static constexpr BlockIdx block_idx_null = 0;
static constexpr ObjectId object_id_null = 0;
static constexpr ObjectIdx object_idx_null = 0;
} // Namespace
#endif

198
util/ObjectTable.hh Normal file
View File

@ -0,0 +1,198 @@
// Parallax Static Timing Analyzer
// Copyright (c) 2019, Parallax Software, Inc.
// All rights reserved.
//
// No part of this document may be copied, transmitted or
// disclosed in any form or fashion without the express
// written consent of Parallax Software, Inc.
#ifndef STA_OBJECT_TABLE_H
#define STA_OBJECT_TABLE_H
#include "Vector.hh"
#include "Error.hh"
#include "ObjectId.hh"
namespace sta {
template <class OBJECT>
class TableBlock;
// Object tables allocate objects in blocks and use 32 bit IDs to
// reference an object. Paging performance is improved by allocating
// blocks instead of individual objects, and object sizes are reduced
// by using 32 bit references instead of 64 bit pointers.
//
// Class TYPE must define member functions
// ObjectIdx objectIdx() const
// void setObjectIdx(ObjectIdx idx)
// to get/set the index of the object in a block, which can be a bit
// field ObjectTable::idx_bits (7 bits) wide.
template <class TYPE>
class ObjectTable
{
public:
ObjectTable();
~ObjectTable();
TYPE *make();
void destroy(TYPE *object);
TYPE *pointer(ObjectId id) const;
TYPE &ref(ObjectId id) const;
ObjectId objectId(const TYPE *object);
size_t size() const { return size_; }
void clear();
// Objects are allocated in blocks of 128.
static constexpr ObjectId idx_bits = 7;
static constexpr ObjectId block_object_count = (1 << idx_bits);
private:
void makeBlock();
void freePush(TYPE *object,
ObjectId id);
size_t size_;
// Object ID of next free object.
ObjectId free_;
Vector<TableBlock<TYPE>*> blocks_;
static constexpr ObjectId idx_mask_ = block_object_count - 1;
};
template <class TYPE>
ObjectTable<TYPE>::ObjectTable() :
size_(0),
free_(object_id_null)
{
}
template <class TYPE>
ObjectTable<TYPE>::~ObjectTable()
{
blocks_.deleteContents();
}
template <class TYPE>
TYPE *
ObjectTable<TYPE>::make()
{
if (free_ == object_id_null)
makeBlock();
TYPE *object = pointer(free_);
ObjectIdx idx = free_ & idx_mask_;
object->setObjectIdx(idx);
ObjectId *free_next = reinterpret_cast<ObjectId*>(object);
free_ = *free_next;
size_++;
return object;
}
template <class TYPE>
void
ObjectTable<TYPE>::freePush(TYPE *object,
ObjectId id)
{
// Link free objects into a list linked by Object ID.
ObjectId *free_next = reinterpret_cast<ObjectId*>(object);
*free_next = free_;
free_ = id;
}
template <class TYPE>
void
ObjectTable<TYPE>::makeBlock()
{
BlockIdx block_index = blocks_.size();
TableBlock<TYPE> *block = new TableBlock<TYPE>(block_index, this);
blocks_.push_back(block);
// ObjectId zero is reserved for object_id_null.
int last = (block_index > 0) ? 0 : 1;
for (int i = block_object_count - 1; i >= last; i--) {
TYPE *obj = block->pointer(i);
ObjectId id = (block_index << idx_bits) + i;
freePush(obj, id);
}
}
template <class TYPE>
TYPE *
ObjectTable<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 &
ObjectTable<TYPE>::ref(ObjectId id) const
{
if (id == object_id_null)
internalError("null ObjectId reference is undefined.");
else {
BlockIdx blk_idx = id >> idx_bits;
ObjectIdx obj_idx = id & idx_mask_;
return blocks_[blk_idx]->ptr(obj_idx);
}
}
template <class TYPE>
ObjectId
ObjectTable<TYPE>::objectId(const TYPE *object)
{
ObjectIdx idx = object->objectIdx();
const TableBlock<TYPE> *blk =
reinterpret_cast<const TableBlock<TYPE>*>(object - idx);
return (blk->index() << idx_bits) + idx;
}
template <class TYPE>
void
ObjectTable<TYPE>::destroy(TYPE *object)
{
ObjectId object_id = objectId(object);
object->~TYPE();
size_--;
freePush(object, object_id);
}
template <class TYPE>
void
ObjectTable<TYPE>::clear()
{
blocks_.deleteContentsClear();
size_ = 0;
}
////////////////////////////////////////////////////////////////
template <class TYPE>
class TableBlock
{
public:
TableBlock(BlockIdx block_idx,
ObjectTable<TYPE> *table);
BlockIdx index() const { return block_idx_; }
TYPE &ref(ObjectIdx idx) { return objects_[idx]; }
TYPE *pointer(ObjectIdx idx) { return &objects_[idx]; }
private:
TYPE objects_[ObjectTable<TYPE>::block_object_count];
BlockIdx block_idx_;
ObjectTable<TYPE> *table_;
};
template <class TYPE>
TableBlock<TYPE>::TableBlock(BlockIdx block_idx,
ObjectTable<TYPE> *table) :
block_idx_(block_idx),
table_(table)
{
}
} // Namespace
#endif

View File

@ -1,340 +0,0 @@
// OpenSTA, Static Timing Analyzer
// Copyright (c) 2019, 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/>.
#ifndef STA_POOL_H
#define STA_POOL_H
#include <stddef.h>
#include <algorithm> // max
#include "DisallowCopyAssign.hh"
#include "Error.hh"
#include "Vector.hh"
#include "ObjectIndex.hh"
namespace sta {
using std::max;
typedef Vector<ObjectIndex> DeletedListHeads;
template <class OBJ>
class PoolBlock
{
public:
explicit PoolBlock(ObjectIndex size,
ObjectIndex begin_index);
OBJ *makeObject();
OBJ *makeObjects(ObjectIndex count);
ObjectIndex index(const OBJ *object);
OBJ *find(ObjectIndex index);
PoolBlock *nextBlock() const { return next_block_; }
void setNextBlock(PoolBlock *next);
ObjectIndex size() const { return objects_.size(); }
private:
DISALLOW_COPY_AND_ASSIGN(PoolBlock);
std::vector<OBJ> objects_;
ObjectIndex begin_index_;
ObjectIndex next_free_;
PoolBlock *next_block_;
static constexpr unsigned min_initial_size_ = 100;
};
template <class OBJ>
PoolBlock<OBJ>::PoolBlock(ObjectIndex size,
ObjectIndex begin_index) :
objects_(size),
begin_index_(begin_index),
next_free_(0),
next_block_(nullptr)
{
}
template <class OBJ>
OBJ *
PoolBlock<OBJ>::makeObject()
{
if (next_free_ < objects_.size())
return &objects_[next_free_++];
else
return nullptr;
}
template <class OBJ>
OBJ *
PoolBlock<OBJ>::makeObjects(ObjectIndex count)
{
if ((next_free_ + count - 1) < objects_.size()) {
OBJ *object = &objects_[next_free_];
next_free_ += count;
return object;
}
else
return nullptr;
}
template <class OBJ>
ObjectIndex
PoolBlock<OBJ>::index(const OBJ *object)
{
if (object >= &objects_[0] && object < &objects_[objects_.size()])
// Index==0 is reserved.
return begin_index_ + object - &objects_[0] + 1;
else
return 0;
}
template <class OBJ>
OBJ *
PoolBlock<OBJ>::find(ObjectIndex index)
{
// Index==0 is reserved.
ObjectIndex index1 = index - 1;
if (index1 >= begin_index_
&& index1 < begin_index_ + objects_.size())
return &objects_[index1 - begin_index_];
else
return nullptr;
}
template <class OBJ>
void
PoolBlock<OBJ>::setNextBlock(PoolBlock *next)
{
next_block_ = next;
}
////////////////////////////////////////////////////////////////
template <class OBJ>
class Pool
{
public:
Pool();
explicit Pool(ObjectIndex size);
explicit Pool(ObjectIndex size,
float growth_factor);
~Pool();
OBJ *makeObject();
OBJ *makeObjects(ObjectIndex count);
void deleteObject(OBJ *object);
void deleteObject(ObjectIndex index);
void deleteObjects(OBJ *objects,
ObjectIndex count);
void deleteObjects(ObjectIndex index,
ObjectIndex count);
// Index=0 is reserved for the nullptr object pointer.
ObjectIndex index(const OBJ *object) const;
OBJ *find(ObjectIndex index) const;
ObjectIndex size() const { return size_; }
void clear();
protected:
PoolBlock<OBJ> *makeBlock(ObjectIndex block_size);
OBJ *findDeletedObject(ObjectIndex count);
void deleteObjects(OBJ *object,
ObjectIndex index,
ObjectIndex count);
ObjectIndex size_;
float growth_factor_;
PoolBlock<OBJ> *blocks_;
PoolBlock<OBJ> *last_block_;
// Index of deleted objects that are the head of a list indexed by
// object array count.
DeletedListHeads deleted_list_heads_;
};
template <class OBJ>
Pool<OBJ>::Pool(ObjectIndex size) :
Pool(size, .2F)
{
}
template <class OBJ>
Pool<OBJ>::Pool(ObjectIndex size,
float growth_factor) :
size_(0),
growth_factor_(growth_factor),
blocks_(nullptr),
last_block_(nullptr)
{
makeBlock(size);
}
template <class OBJ>
Pool<OBJ>::~Pool()
{
PoolBlock<OBJ> *next;
for (PoolBlock<OBJ> *block = blocks_; block; block = next) {
next = block->nextBlock();
delete block;
}
}
template <class OBJ>
OBJ *
Pool<OBJ>::makeObject()
{
OBJ *object = findDeletedObject(1);
if (object == nullptr) {
object = last_block_->makeObject();
if (object == nullptr) {
ObjectIndex block_size=static_cast<ObjectIndex>(size_*growth_factor_+2);
PoolBlock<OBJ> *block = makeBlock(block_size);
object = block->makeObject();
}
}
return object;
}
template <class OBJ>
OBJ *
Pool<OBJ>::findDeletedObject(ObjectIndex count)
{
if (deleted_list_heads_.size() > count) {
ObjectIndex index = deleted_list_heads_[count];
if (index) {
OBJ *object = find(index);
ObjectIndex next_index = *reinterpret_cast<ObjectIndex*>(object);
deleted_list_heads_[count] = next_index;
return object;
}
}
return nullptr;
}
template <class OBJ>
OBJ *
Pool<OBJ>::makeObjects(ObjectIndex count)
{
OBJ *objects = findDeletedObject(count);
if (objects == nullptr) {
objects = last_block_->makeObjects(count);
if (objects == nullptr) {
ObjectIndex block_size=max(static_cast<ObjectIndex>(size_*growth_factor_+2),
count);
PoolBlock<OBJ> *block = makeBlock(block_size);
objects = block->makeObjects(count);
}
}
return objects;
}
template <class OBJ>
PoolBlock<OBJ> *
Pool<OBJ>::makeBlock(ObjectIndex block_size)
{
PoolBlock<OBJ> *block = new PoolBlock<OBJ>(block_size, size_);
// Add new block to end of block list so searches start with
// the first block.
if (last_block_)
last_block_->setNextBlock(block);
else
blocks_ = block;
last_block_ = block;
size_ += block_size;
return block;
}
template <class OBJ>
ObjectIndex
Pool<OBJ>::index(const OBJ *object) const
{
if (object) {
for (PoolBlock<OBJ> *block = blocks_; block; block = block->nextBlock()) {
ObjectIndex index = block->index(object);
if (index > 0)
return index;
}
internalError("object index not found in pool");
return 0;
}
else
return 0;
}
template <class OBJ>
OBJ *
Pool<OBJ>::find(ObjectIndex index) const
{
if (index) {
for (PoolBlock<OBJ> *block = blocks_; block; block = block->nextBlock()) {
OBJ *object = block->find(index);
if (object)
return object;
}
internalError("object index not found in pool");
return nullptr;
}
else
return nullptr;
}
template <class OBJ>
void
Pool<OBJ>::deleteObject(OBJ *object)
{
deleteObjects(object, index(object), 1);
}
template <class OBJ>
void
Pool<OBJ>::deleteObject(ObjectIndex index)
{
deleteObjects(find(index), index, 1);
}
template <class OBJ>
void
Pool<OBJ>::deleteObjects(OBJ *objects,
ObjectIndex count)
{
deleteObjects(objects, index(objects), count);
}
template <class OBJ>
void
Pool<OBJ>::deleteObjects(ObjectIndex index,
ObjectIndex count)
{
deleteObjects(find(index), index, count);
}
template <class OBJ>
void
Pool<OBJ>::deleteObjects(OBJ *object,
ObjectIndex index,
ObjectIndex count)
{
if (deleted_list_heads_.size() <= count)
deleted_list_heads_.resize(count + 1);
ObjectIndex next_index = deleted_list_heads_[count];
*reinterpret_cast<ObjectIndex*>(object) = next_index;
deleted_list_heads_[count] = index;
}
template <class OBJ>
void
Pool<OBJ>::clear()
{
last_block_ = blocks_;
last_block_->clear();
}
} // Namespace
#endif

23
util/VertexId.hh Normal file
View File

@ -0,0 +1,23 @@
// Parallax Static Timing Analyzer
// Copyright (c) 2019, Parallax Software, Inc.
// All rights reserved.
//
// No part of this document may be copied, transmitted or
// disclosed in any form or fashion without the express
// written consent of Parallax Software, Inc.
#ifndef STA_VERTEX_ID_H
#define STA_VERTEX_ID_H
#include "ObjectId.hh"
// VertexId typedef for Networks to get/set on pins.
namespace sta {
typedef ObjectId VertexId;
static constexpr VertexId vertex_id_null = object_id_null;
} // Namespace
#endif