replace Pool with ObjectTable
This commit is contained in:
parent
2e6de93870
commit
184d044b02
|
|
@ -372,9 +372,10 @@ set(STA_HEADERS
|
|||
util/Map.hh
|
||||
util/MinMax.hh
|
||||
util/Mutex.hh
|
||||
util/ObjectId.hh
|
||||
util/ObjectIndex.hh
|
||||
util/ObjectTable.hh
|
||||
util/PatternMatch.hh
|
||||
util/Pool.hh
|
||||
util/Report.hh
|
||||
util/ReportStd.hh
|
||||
util/ReportTcl.hh
|
||||
|
|
|
|||
277
graph/Graph.cc
277
graph/Graph.cc
|
|
@ -19,7 +19,6 @@
|
|||
#include "Stats.hh"
|
||||
#include "Error.hh"
|
||||
#include "Debug.hh"
|
||||
#include "Pool.hh"
|
||||
#include "MinMax.hh"
|
||||
#include "PortDirection.hh"
|
||||
#include "Transition.hh"
|
||||
|
|
@ -45,8 +44,6 @@ Graph::Graph(StaState *sta,
|
|||
StaState(sta),
|
||||
vertices_(nullptr),
|
||||
edges_(nullptr),
|
||||
vertex_count_(0),
|
||||
edge_count_(0),
|
||||
arc_count_(0),
|
||||
slew_tr_count_(slew_tr_count),
|
||||
have_arc_delays_(have_arc_delays),
|
||||
|
|
@ -60,8 +57,8 @@ Graph::~Graph()
|
|||
{
|
||||
delete vertices_;
|
||||
delete edges_;
|
||||
deleteSlewPools();
|
||||
deleteArcDelayPools();
|
||||
deleteSlewTables();
|
||||
deleteArcDelayTables();
|
||||
removeWidthCheckAnnotations();
|
||||
removePeriodCheckAnnotations();
|
||||
}
|
||||
|
|
@ -86,10 +83,10 @@ Graph::makeVerticesAndEdges()
|
|||
EdgeIndex edge_count;
|
||||
ArcIndex arc_count;
|
||||
vertexAndEdgeCounts(vertex_count, edge_count, arc_count);
|
||||
vertices_ = new VertexPool(vertex_count);
|
||||
edges_ = new EdgePool(edge_count);
|
||||
makeSlewPools(vertex_count, ap_count_);
|
||||
makeArcDelayPools(arc_count, ap_count_);
|
||||
vertices_ = new VertexTable;
|
||||
edges_ = new EdgeTable;
|
||||
makeSlewTables(ap_count_);
|
||||
makeArcDelayTables(arc_count, ap_count_);
|
||||
|
||||
LeafInstanceIterator *leaf_iter = network_->leafInstanceIterator();
|
||||
while (leaf_iter->hasNext()) {
|
||||
|
|
@ -449,13 +446,13 @@ Graph::makeWireEdge(Pin *from_pin,
|
|||
Vertex *
|
||||
Graph::vertex(VertexIndex vertex_index) const
|
||||
{
|
||||
return vertices_->find(vertex_index);
|
||||
return vertices_->pointer(vertex_index);
|
||||
}
|
||||
|
||||
VertexIndex
|
||||
Graph::index(const Vertex *vertex) const
|
||||
{
|
||||
return vertices_->index(vertex);
|
||||
return vertices_->objectId(vertex);
|
||||
}
|
||||
|
||||
void
|
||||
|
|
@ -489,10 +486,9 @@ Graph::makeVertex(Pin *pin,
|
|||
bool is_bidirect_drvr,
|
||||
bool is_reg_clk)
|
||||
{
|
||||
Vertex *vertex = vertices_->makeObject();
|
||||
Vertex *vertex = vertices_->make();
|
||||
vertex->init(pin, is_bidirect_drvr, is_reg_clk);
|
||||
vertex_count_++;
|
||||
makeVertexSlews();
|
||||
makeVertexSlews(vertex);
|
||||
if (is_reg_clk)
|
||||
reg_clk_vertices_.insert(vertex);
|
||||
return vertex;
|
||||
|
|
@ -536,31 +532,25 @@ Graph::deleteVertex(Vertex *vertex)
|
|||
pin_bidirect_drvr_vertex_map_.erase(pin_bidirect_drvr_vertex_map_
|
||||
.find(pin));
|
||||
else
|
||||
network_->setVertexIndex(pin, 0);
|
||||
network_->setVertexIndex(pin, vertex_id_null);
|
||||
// Delete edges to vertex.
|
||||
EdgeIndex edge_index, next_index;
|
||||
for (edge_index = vertex->in_edges_; edge_index; edge_index = next_index) {
|
||||
Edge *edge = Graph::edge(edge_index);
|
||||
next_index = edge->vertex_in_link_;
|
||||
deleteOutEdge(edge->from(this), edge);
|
||||
deleteEdgeArcDelays(edge);
|
||||
edge_count_--;
|
||||
arc_count_ -= edge->timingArcSet()->arcCount();
|
||||
edges_->deleteObject(edge);
|
||||
edges_->destroy(edge);
|
||||
}
|
||||
// Delete edges from vertex.
|
||||
for (edge_index = vertex->out_edges_; edge_index; edge_index = next_index) {
|
||||
Edge *edge = Graph::edge(edge_index);
|
||||
next_index = edge->vertex_out_next_;
|
||||
deleteInEdge(edge->to(this), edge);
|
||||
deleteEdgeArcDelays(edge);
|
||||
edge_count_--;
|
||||
arc_count_ -= edge->timingArcSet()->arcCount();
|
||||
edges_->deleteObject(edge);
|
||||
edges_->destroy(edge);
|
||||
}
|
||||
deleteVertexSlews(vertex);
|
||||
vertices_->deleteObject(vertex);
|
||||
vertex_count_--;
|
||||
vertices_->destroy(vertex);
|
||||
}
|
||||
|
||||
bool
|
||||
|
|
@ -600,17 +590,69 @@ Graph::deleteOutEdge(Vertex *vertex,
|
|||
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 &
|
||||
Graph::slew(const Vertex *vertex,
|
||||
const TransRiseFall *tr,
|
||||
DcalcAPIndex ap_index)
|
||||
{
|
||||
if (slew_tr_count_) {
|
||||
int pool_index =
|
||||
int table_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);
|
||||
return *pool->find(vertex_index);
|
||||
return table->ref(vertex_index);
|
||||
}
|
||||
else {
|
||||
static Slew slew(0.0);
|
||||
|
|
@ -625,11 +667,11 @@ Graph::setSlew(Vertex *vertex,
|
|||
const Slew &slew)
|
||||
{
|
||||
if (slew_tr_count_) {
|
||||
int pool_index =
|
||||
int table_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);
|
||||
Slew &vertex_slew = *pool->find(vertex_index);
|
||||
Slew &vertex_slew = table->ref(vertex_index);
|
||||
vertex_slew = slew;
|
||||
}
|
||||
}
|
||||
|
|
@ -639,13 +681,13 @@ Graph::setSlew(Vertex *vertex,
|
|||
Edge *
|
||||
Graph::edge(EdgeIndex edge_index) const
|
||||
{
|
||||
return edges_->find(edge_index);
|
||||
return edges_->pointer(edge_index);
|
||||
}
|
||||
|
||||
EdgeIndex
|
||||
Graph::index(const Edge *edge) const
|
||||
{
|
||||
return edges_->index(edge);
|
||||
return edges_->objectId(edge);
|
||||
}
|
||||
|
||||
Edge *
|
||||
|
|
@ -653,23 +695,22 @@ Graph::makeEdge(Vertex *from,
|
|||
Vertex *to,
|
||||
TimingArcSet *arc_set)
|
||||
{
|
||||
Edge *edge = edges_->makeObject();
|
||||
EdgeIndex edge_index = edges_->index(edge);
|
||||
edge->init(vertices_->index(from), vertices_->index(to), arc_set);
|
||||
Edge *edge = edges_->make();
|
||||
edge->init(index(from), index(to), arc_set);
|
||||
makeEdgeArcDelays(edge);
|
||||
edge_count_++;
|
||||
arc_count_ += arc_set->arcCount();
|
||||
// Add out edge to from vertex.
|
||||
EdgeIndex next = from->out_edges_;
|
||||
EdgeId next = from->out_edges_;
|
||||
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)
|
||||
Graph::edge(next)->vertex_out_prev_ = edge_index;
|
||||
from->out_edges_ = edge_index;
|
||||
Graph::edge(next)->vertex_out_prev_ = edge_id;
|
||||
from->out_edges_ = edge_id;
|
||||
|
||||
// Add in edge to to vertex.
|
||||
edge->vertex_in_link_ = to->in_edges_;
|
||||
to->in_edges_ = edge_index;
|
||||
to->in_edges_ = edge_id;
|
||||
|
||||
return edge;
|
||||
}
|
||||
|
|
@ -681,21 +722,19 @@ Graph::deleteEdge(Edge *edge)
|
|||
Vertex *to = edge->to(this);
|
||||
deleteOutEdge(from, edge);
|
||||
deleteInEdge(to, edge);
|
||||
deleteEdgeArcDelays(edge);
|
||||
arc_count_ -= edge->timingArcSet()->arcCount();
|
||||
edge_count_--;
|
||||
edges_->deleteObject(edge);
|
||||
edges_->destroy(edge);
|
||||
}
|
||||
|
||||
void
|
||||
Graph::makeArcDelayPools(ArcIndex arc_count,
|
||||
DcalcAPIndex ap_count)
|
||||
Graph::makeArcDelayTables(ArcIndex arc_count,
|
||||
DcalcAPIndex ap_count)
|
||||
{
|
||||
if (have_arc_delays_) {
|
||||
arc_delays_.resize(ap_count);
|
||||
for (DcalcAPIndex i = 0; i < ap_count; i++) {
|
||||
DelayPool *pool = new DelayPool(arc_count);
|
||||
arc_delays_[i] = pool;
|
||||
DelayTable *table = new DelayTable();
|
||||
arc_delays_[i] = table;
|
||||
}
|
||||
|
||||
// Leave some room for edits.
|
||||
|
|
@ -705,15 +744,9 @@ Graph::makeArcDelayPools(ArcIndex arc_count,
|
|||
}
|
||||
|
||||
void
|
||||
Graph::deleteArcDelayPools()
|
||||
Graph::deleteArcDelayTables()
|
||||
{
|
||||
if (have_arc_delays_) {
|
||||
for (DcalcAPIndex i = 0; i < ap_count_; i++) {
|
||||
DelayPool *pool = arc_delays_[i];
|
||||
delete pool;
|
||||
}
|
||||
arc_delays_.clear();
|
||||
}
|
||||
arc_delays_.deleteContentsClear();
|
||||
}
|
||||
|
||||
void
|
||||
|
|
@ -723,11 +756,11 @@ Graph::makeEdgeArcDelays(Edge *edge)
|
|||
int arc_count = edge->timingArcSet()->arcCount();
|
||||
ArcIndex arc_index = 0;
|
||||
for (DcalcAPIndex i = 0; i < ap_count_; i++) {
|
||||
DelayPool *pool = arc_delays_[i];
|
||||
ArcDelay *arc_delays = pool->makeObjects(arc_count);
|
||||
arc_index = pool->index(arc_delays);
|
||||
DelayTable *table = arc_delays_[i];
|
||||
ArcDelay *arc_delays;
|
||||
table->make(arc_count, arc_delays, arc_index);
|
||||
for (int j = 0; j < arc_count; j++)
|
||||
*arc_delays++ = 0.0;
|
||||
arc_delays[j] = 0.0;
|
||||
}
|
||||
edge->setArcDelays(arc_index);
|
||||
// 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
|
||||
Graph::arcDelay(const Edge *edge,
|
||||
const TimingArc *arc,
|
||||
DcalcAPIndex ap_index) const
|
||||
{
|
||||
if (have_arc_delays_) {
|
||||
DelayPool *pool = arc_delays_[ap_index];
|
||||
ArcIndex arc_index = edge->arcDelays() + arc->index();
|
||||
ArcDelay &arc_delay = *pool->find(arc_index);
|
||||
DelayTable *table = arc_delays_[ap_index];
|
||||
ArcDelay *arc_delays = table->pointer(edge->arcDelays());
|
||||
ArcDelay &arc_delay = arc_delays[arc->index()];
|
||||
return arc_delay;
|
||||
}
|
||||
else
|
||||
|
|
@ -775,10 +795,9 @@ Graph::setArcDelay(Edge *edge,
|
|||
ArcDelay delay)
|
||||
{
|
||||
if (have_arc_delays_) {
|
||||
DelayPool *pool = arc_delays_[ap_index];
|
||||
ArcIndex arc_index = edge->arcDelays() + arc->index();
|
||||
ArcDelay &arc_delay = *pool->find(arc_index);
|
||||
arc_delay = delay;
|
||||
DelayTable *table = arc_delays_[ap_index];
|
||||
ArcDelay *arc_delays = table->pointer(edge->arcDelays());
|
||||
arc_delays[arc->index()] = delay;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -788,10 +807,9 @@ Graph::wireArcDelay(const Edge *edge,
|
|||
DcalcAPIndex ap_index)
|
||||
{
|
||||
if (have_arc_delays_) {
|
||||
DelayPool *pool = arc_delays_[ap_index];
|
||||
ArcIndex arc_index = edge->arcDelays() + tr->index();
|
||||
const ArcDelay &arc_delay = *pool->find(arc_index);
|
||||
return arc_delay;
|
||||
DelayTable *table = arc_delays_[ap_index];
|
||||
ArcDelay *arc_delays = table->pointer(edge->arcDelays());
|
||||
return arc_delays[tr->index()];
|
||||
}
|
||||
else
|
||||
return delay_zero;
|
||||
|
|
@ -804,10 +822,9 @@ Graph::setWireArcDelay(Edge *edge,
|
|||
const ArcDelay &delay)
|
||||
{
|
||||
if (have_arc_delays_) {
|
||||
DelayPool *pool = arc_delays_[ap_index];
|
||||
ArcIndex arc_index = edge->arcDelays() + tr->index();
|
||||
ArcDelay &arc_delay = *pool->find(arc_index);
|
||||
arc_delay = delay;
|
||||
DelayTable *table = arc_delays_[ap_index];
|
||||
ArcDelay *arc_delays = table->pointer(edge->arcDelays());
|
||||
arc_delays[tr->index()] = delay;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -870,12 +887,12 @@ Graph::setDelayCount(DcalcAPIndex ap_count)
|
|||
{
|
||||
if (ap_count != ap_count_) {
|
||||
// Discard any existing delays.
|
||||
deleteSlewPools();
|
||||
deleteArcDelayPools();
|
||||
deleteSlewTables();
|
||||
deleteArcDelayTables();
|
||||
removeWidthCheckAnnotations();
|
||||
removePeriodCheckAnnotations();
|
||||
makeSlewPools(vertex_count_, ap_count);
|
||||
makeArcDelayPools(arc_count_, ap_count);
|
||||
makeSlewTables(ap_count);
|
||||
makeArcDelayTables(arc_count_, ap_count);
|
||||
ap_count_ = ap_count;
|
||||
removeDelays();
|
||||
}
|
||||
|
|
@ -887,7 +904,7 @@ Graph::removeDelays()
|
|||
VertexIterator vertex_iter(this);
|
||||
while (vertex_iter.hasNext()) {
|
||||
Vertex *vertex = vertex_iter.next();
|
||||
makeVertexSlews();
|
||||
makeVertexSlews(vertex);
|
||||
VertexOutEdgeIterator edge_iter(vertex, this);
|
||||
while (edge_iter.hasNext()) {
|
||||
Edge *edge = edge_iter.next();
|
||||
|
|
@ -927,54 +944,34 @@ Graph::delayAnnotated(Edge *edge)
|
|||
}
|
||||
|
||||
void
|
||||
Graph::makeSlewPools(VertexIndex vertex_count,
|
||||
DcalcAPIndex ap_count)
|
||||
Graph::makeSlewTables(DcalcAPIndex 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++) {
|
||||
DelayPool *pool = new DelayPool(vertex_count);
|
||||
slew_pools_[i] = pool;
|
||||
DelayTable *table = new DelayTable;
|
||||
slew_tables_[i] = table;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
Graph::deleteSlewPools()
|
||||
Graph::deleteSlewTables()
|
||||
{
|
||||
if (slew_tr_count_) {
|
||||
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();
|
||||
}
|
||||
slew_tables_.deleteContentsClear();
|
||||
}
|
||||
|
||||
void
|
||||
Graph::makeVertexSlews()
|
||||
Graph::makeVertexSlews(Vertex *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];
|
||||
Slew *slew = pool->makeObject();
|
||||
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
|
||||
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
|
||||
|
|
@ -1109,6 +1106,7 @@ Graph::removeDelaySlewAnnotations()
|
|||
Vertex::Vertex()
|
||||
{
|
||||
init(nullptr, false, false);
|
||||
object_idx_ = object_idx_null;
|
||||
}
|
||||
|
||||
void
|
||||
|
|
@ -1119,10 +1117,10 @@ Vertex::init(Pin *pin,
|
|||
pin_ = pin;
|
||||
is_reg_clk_ = is_reg_clk;
|
||||
is_bidirect_drvr_ = is_bidirect_drvr;
|
||||
in_edges_ = 0;
|
||||
out_edges_ = 0;
|
||||
arrivals_ = nullptr;
|
||||
prev_paths_ = nullptr;
|
||||
in_edges_ = edge_id_null;
|
||||
out_edges_ = edge_id_null;
|
||||
arrivals_ = arrival_null;
|
||||
prev_paths_ = prev_path_null;
|
||||
has_requireds_ = false;
|
||||
tag_group_index_ = tag_group_index_max;
|
||||
slew_annotated_ = false;
|
||||
|
|
@ -1140,6 +1138,12 @@ Vertex::init(Pin *pin,
|
|||
requireds_pruned_ = false;
|
||||
}
|
||||
|
||||
void
|
||||
Vertex::setObjectIdx(ObjectIdx idx)
|
||||
{
|
||||
object_idx_ = idx;
|
||||
}
|
||||
|
||||
const char *
|
||||
Vertex::name(const Network *network) const
|
||||
{
|
||||
|
|
@ -1243,13 +1247,13 @@ Vertex::setTagGroupIndex(TagGroupIndex tag_index)
|
|||
}
|
||||
|
||||
void
|
||||
Vertex::setArrivals(Arrival *arrivals)
|
||||
Vertex::setArrivals(ArrivalId id)
|
||||
{
|
||||
arrivals_ = arrivals;
|
||||
arrivals_ = id;
|
||||
}
|
||||
|
||||
void
|
||||
Vertex::setPrevPaths(PathVertexRep *prev_paths)
|
||||
Vertex::setPrevPaths(PrevPathId prev_paths)
|
||||
{
|
||||
prev_paths_ = prev_paths;
|
||||
}
|
||||
|
|
@ -1341,6 +1345,7 @@ Vertex::setBfsInQueue(BfsIndex index,
|
|||
Edge::Edge()
|
||||
{
|
||||
init(0, 0, nullptr);
|
||||
object_idx_ = object_idx_null;
|
||||
}
|
||||
|
||||
void
|
||||
|
|
@ -1353,9 +1358,9 @@ Edge::init(VertexIndex from,
|
|||
arc_set_ = arc_set;
|
||||
arc_delays_ = 0;
|
||||
|
||||
vertex_in_link_ = 0;
|
||||
vertex_out_next_ = 0;
|
||||
vertex_out_prev_ = 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;
|
||||
delay_annotation_is_incremental_ = false;
|
||||
|
|
@ -1365,6 +1370,12 @@ Edge::init(VertexIndex from,
|
|||
is_disabled_loop_ = false;
|
||||
}
|
||||
|
||||
void
|
||||
Edge::setObjectIdx(ObjectIdx idx)
|
||||
{
|
||||
object_idx_ = idx;
|
||||
}
|
||||
|
||||
void
|
||||
Edge::setTimingArcSet(TimingArcSet *set)
|
||||
{
|
||||
|
|
|
|||
100
graph/Graph.hh
100
graph/Graph.hh
|
|
@ -17,16 +17,20 @@
|
|||
#ifndef STA_GRAPH_H
|
||||
#define STA_GRAPH_H
|
||||
|
||||
#include "Mutex.hh"
|
||||
#include "DisallowCopyAssign.hh"
|
||||
#include "Iterator.hh"
|
||||
#include "Map.hh"
|
||||
#include "Vector.hh"
|
||||
#include "Pool.hh"
|
||||
#include "ObjectTable.hh"
|
||||
#include "ArrayTable.hh"
|
||||
#include "StaState.hh"
|
||||
#include "LibertyClass.hh"
|
||||
#include "NetworkClass.hh"
|
||||
#include "Delay.hh"
|
||||
#include "GraphClass.hh"
|
||||
#include "VertexId.hh"
|
||||
#include "PathVertexRep.hh"
|
||||
|
||||
namespace sta {
|
||||
|
||||
|
|
@ -36,14 +40,25 @@ class PathVertexRep;
|
|||
|
||||
enum class LevelColor { white, gray, black };
|
||||
|
||||
typedef Pool<Delay> DelayPool;
|
||||
typedef Pool<Vertex> VertexPool;
|
||||
typedef Pool<Edge> EdgePool;
|
||||
typedef ArrayTable<Delay> DelayTable;
|
||||
typedef ObjectTable<Vertex> VertexTable;
|
||||
typedef ObjectTable<Edge> EdgeTable;
|
||||
typedef ArrayTable<Arrival> ArrivalsTable;
|
||||
typedef ArrayTable<PathVertexRep> PrevPathsTable;
|
||||
typedef Map<const Pin*, Vertex*> PinVertexMap;
|
||||
typedef Iterator<Edge*> VertexEdgeIterator;
|
||||
typedef Map<const Pin*, float*> WidthCheckAnnotations;
|
||||
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.
|
||||
class Graph : public StaState
|
||||
|
|
@ -83,7 +98,15 @@ public:
|
|||
Vertex *pinLoadVertex(const Pin *pin) const;
|
||||
virtual void deleteVertex(Vertex *vertex);
|
||||
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.
|
||||
// Reported slew are the same as those in the liberty tables.
|
||||
// reported_slews = measured_slews / slew_derate_from_library
|
||||
|
|
@ -142,7 +165,7 @@ public:
|
|||
bool annotated);
|
||||
// True if any edge arc is annotated.
|
||||
bool delayAnnotated(Edge *edge);
|
||||
EdgeIndex edgeCount() { return edge_count_; }
|
||||
EdgeIndex edgeCount() { return edges_->size(); }
|
||||
virtual ArcIndex arcCount() { return arc_count_; }
|
||||
|
||||
// Sdf width check annotation.
|
||||
|
|
@ -202,15 +225,12 @@ protected:
|
|||
LibertyPort *from_to_port);
|
||||
void removeWidthCheckAnnotations();
|
||||
void removePeriodCheckAnnotations();
|
||||
void makeSlewPools(VertexIndex vertex_count,
|
||||
DcalcAPIndex count);
|
||||
void deleteSlewPools();
|
||||
void makeVertexSlews();
|
||||
void deleteVertexSlews(Vertex *vertex);
|
||||
void makeArcDelayPools(ArcIndex arc_count,
|
||||
DcalcAPIndex ap_count);
|
||||
void deleteArcDelayPools();
|
||||
virtual void deleteEdgeArcDelays(Edge *edge);
|
||||
void makeSlewTables(DcalcAPIndex count);
|
||||
void deleteSlewTables();
|
||||
void makeVertexSlews(Vertex *vertex);
|
||||
void makeArcDelayTables(ArcIndex arc_count,
|
||||
DcalcAPIndex ap_count);
|
||||
void deleteArcDelayTables();
|
||||
void deleteInEdge(Vertex *vertex,
|
||||
Edge *edge);
|
||||
void deleteOutEdge(Vertex *vertex,
|
||||
|
|
@ -220,29 +240,32 @@ protected:
|
|||
// User defined predicate to filter graph edges for liberty timing arcs.
|
||||
virtual bool filterEdge(TimingArcSet *) const { return true; }
|
||||
|
||||
VertexPool *vertices_;
|
||||
EdgePool *edges_;
|
||||
VertexTable *vertices_;
|
||||
EdgeTable *edges_;
|
||||
// Bidirect pins are split into two vertices:
|
||||
// load/sink (top level output, instance pin input) vertex in pin_vertex_map
|
||||
// driver/source (top level input, instance pin output) vertex
|
||||
// in pin_bidirect_drvr_vertex_map
|
||||
PinVertexMap pin_bidirect_drvr_vertex_map_;
|
||||
VertexIndex vertex_count_;
|
||||
EdgeIndex edge_count_;
|
||||
ArcIndex arc_count_;
|
||||
ArrivalsTable arrivals_;
|
||||
std::mutex arrivals_lock_;
|
||||
PrevPathsTable prev_paths_;
|
||||
std::mutex prev_paths_lock_;
|
||||
Vector<bool> arc_delay_annotated_;
|
||||
int slew_tr_count_;
|
||||
bool have_arc_delays_;
|
||||
DcalcAPIndex ap_count_;
|
||||
DelayPoolSeq slew_pools_; // [ap_index][tr_index][vertex_index]
|
||||
DelayTableSeq slew_tables_; // [ap_index][tr_index][vertex_index]
|
||||
VertexIndex slew_count_;
|
||||
DelayPoolSeq arc_delays_; // [ap_index][edge_arc_index]
|
||||
DelayTableSeq arc_delays_; // [ap_index][edge_arc_index]
|
||||
// Sdf width check annotations.
|
||||
WidthCheckAnnotations *width_check_annotations_;
|
||||
// Sdf period check annotations.
|
||||
PeriodCheckAnnotations *period_check_annotations_;
|
||||
// Register/latch clock vertices to search from.
|
||||
VertexSet reg_clk_vertices_;
|
||||
|
||||
friend class Vertex;
|
||||
friend class VertexIterator;
|
||||
friend class VertexInEdgeIterator;
|
||||
|
|
@ -268,10 +291,10 @@ public:
|
|||
bool isRoot() const{ return level_ == 0; }
|
||||
LevelColor color() const { return static_cast<LevelColor>(color_); }
|
||||
void setColor(LevelColor color);
|
||||
Arrival *arrivals() const { return arrivals_; }
|
||||
void setArrivals(Arrival *arrivals);
|
||||
PathVertexRep *prevPaths() const { return prev_paths_; }
|
||||
void setPrevPaths(PathVertexRep *prev_paths);
|
||||
ArrivalId arrivals() const { return arrivals_; }
|
||||
void setArrivals(ArrivalId id);
|
||||
PrevPathId prevPaths() const { return prev_paths_; }
|
||||
void setPrevPaths(PrevPathId id);
|
||||
// Requireds optionally follow arrivals in the same array.
|
||||
bool hasRequireds() const { return has_requireds_; }
|
||||
void setHasRequireds(bool has_req);
|
||||
|
|
@ -315,6 +338,10 @@ public:
|
|||
void setCrprPathPruningDisabled(bool disabled);
|
||||
bool requiredsPruned() const { return requireds_pruned_; }
|
||||
void setRequiredsPruned(bool pruned);
|
||||
|
||||
// ObjectTable interface.
|
||||
ObjectIdx objectIdx() const { return object_idx_; }
|
||||
void setObjectIdx(ObjectIdx idx);
|
||||
|
||||
static int transitionCount() { return 2; } // rise/fall
|
||||
|
||||
|
|
@ -324,8 +351,8 @@ protected:
|
|||
bool is_reg_clk);
|
||||
|
||||
Pin *pin_;
|
||||
Arrival *arrivals_;
|
||||
PathVertexRep *prev_paths_;
|
||||
ArrivalId arrivals_;
|
||||
PrevPathId prev_paths_;
|
||||
EdgeIndex in_edges_; // Edges to this vertex.
|
||||
EdgeIndex out_edges_; // Edges from this vertex.
|
||||
|
||||
|
|
@ -358,6 +385,8 @@ protected:
|
|||
bool crpr_path_pruning_disabled_:1;
|
||||
bool requireds_pruned_:1;
|
||||
|
||||
unsigned object_idx_:VertexTable::idx_bits;
|
||||
|
||||
private:
|
||||
DISALLOW_COPY_AND_ASSIGN(Vertex);
|
||||
|
||||
|
|
@ -403,17 +432,21 @@ public:
|
|||
bool isBidirectNetPath() const { return is_bidirect_net_path_; }
|
||||
void setIsBidirectNetPath(bool is_bidir);
|
||||
|
||||
// ObjectTable interface.
|
||||
ObjectIdx objectIdx() const { return object_idx_; }
|
||||
void setObjectIdx(ObjectIdx idx);
|
||||
|
||||
protected:
|
||||
void init(VertexIndex from,
|
||||
VertexIndex to,
|
||||
TimingArcSet *arc_set);
|
||||
|
||||
TimingArcSet *arc_set_;
|
||||
VertexIndex from_;
|
||||
VertexIndex to_;
|
||||
VertexIndex vertex_in_link_; // Vertex in edges list.
|
||||
VertexIndex vertex_out_next_; // Vertex out edges doubly linked list.
|
||||
VertexIndex vertex_out_prev_;
|
||||
VertexId from_;
|
||||
VertexId to_;
|
||||
EdgeId vertex_in_link_; // Vertex in edges list.
|
||||
EdgeId vertex_out_next_; // Vertex out edges doubly linked list.
|
||||
EdgeId vertex_out_prev_;
|
||||
ArcIndex arc_delays_;
|
||||
bool delay_annotation_is_incremental_:1;
|
||||
bool is_bidirect_inst_path_:1;
|
||||
|
|
@ -423,6 +456,7 @@ protected:
|
|||
bool is_disabled_constraint_:1;
|
||||
bool is_disabled_cond_:1;
|
||||
bool is_disabled_loop_:1;
|
||||
unsigned object_idx_:VertexTable::idx_bits;
|
||||
|
||||
private:
|
||||
DISALLOW_COPY_AND_ASSIGN(Edge);
|
||||
|
|
|
|||
|
|
@ -1032,19 +1032,19 @@ ConcreteNetwork::direction(const Pin *pin) const
|
|||
return cport->direction();
|
||||
}
|
||||
|
||||
VertexIndex
|
||||
VertexId
|
||||
ConcreteNetwork::vertexIndex(const Pin *pin) const
|
||||
{
|
||||
const ConcretePin *cpin = reinterpret_cast<const ConcretePin*>(pin);
|
||||
return cpin->vertexIndex();
|
||||
return cpin->vertexId();
|
||||
}
|
||||
|
||||
void
|
||||
ConcreteNetwork::setVertexIndex(Pin *pin,
|
||||
VertexIndex index)
|
||||
VertexId id)
|
||||
{
|
||||
ConcretePin *cpin = reinterpret_cast<ConcretePin*>(pin);
|
||||
cpin->setVertexIndex(index);
|
||||
cpin->setVertexId(id);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////
|
||||
|
|
@ -1666,7 +1666,7 @@ ConcretePin::ConcretePin(ConcreteInstance *instance,
|
|||
term_(nullptr),
|
||||
net_next_(nullptr),
|
||||
net_prev_(nullptr),
|
||||
vertex_index_(0)
|
||||
vertex_id_(vertex_id_null)
|
||||
{
|
||||
}
|
||||
|
||||
|
|
@ -1677,9 +1677,9 @@ ConcretePin::name() const
|
|||
}
|
||||
|
||||
void
|
||||
ConcretePin::setVertexIndex(VertexIndex index)
|
||||
ConcretePin::setVertexId(VertexId id)
|
||||
{
|
||||
vertex_index_ = index;
|
||||
vertex_id_ = id;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////
|
||||
|
|
|
|||
|
|
@ -131,9 +131,9 @@ public:
|
|||
virtual Term *term(const Pin *pin) const;
|
||||
virtual Port *port(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,
|
||||
VertexIndex index);
|
||||
VertexId id);
|
||||
|
||||
virtual Net *net(const Term *term) const;
|
||||
virtual Pin *pin(const Term *term) const;
|
||||
|
|
@ -318,8 +318,8 @@ public:
|
|||
ConcreteNet *net() const { return net_; }
|
||||
ConcretePort *port() const { return port_; }
|
||||
ConcreteTerm *term() const { return term_; }
|
||||
VertexIndex vertexIndex() const { return vertex_index_; }
|
||||
void setVertexIndex(VertexIndex index);
|
||||
VertexId vertexId() const { return vertex_id_; }
|
||||
void setVertexId(VertexId id);
|
||||
|
||||
protected:
|
||||
~ConcretePin() {}
|
||||
|
|
@ -334,7 +334,7 @@ protected:
|
|||
// Doubly linked list of net pins.
|
||||
ConcretePin *net_next_;
|
||||
ConcretePin *net_prev_;
|
||||
VertexIndex vertex_index_;
|
||||
VertexId vertex_id_;
|
||||
|
||||
private:
|
||||
DISALLOW_COPY_AND_ASSIGN(ConcretePin);
|
||||
|
|
|
|||
|
|
@ -21,7 +21,7 @@
|
|||
#include "Map.hh"
|
||||
#include "StringUtil.hh"
|
||||
#include "LibertyClass.hh"
|
||||
#include "GraphClass.hh"
|
||||
#include "VertexId.hh"
|
||||
#include "NetworkClass.hh"
|
||||
#include "StaState.hh"
|
||||
|
||||
|
|
@ -320,10 +320,10 @@ public:
|
|||
virtual PinSet *drivers(const Pin *pin);
|
||||
virtual bool pinLess(const Pin *pin1,
|
||||
const Pin *pin2) const;
|
||||
// Return the index of the pin graph vertex.
|
||||
virtual VertexIndex vertexIndex(const Pin *pin) const = 0;
|
||||
// Return the id of the pin graph vertex.
|
||||
virtual VertexId vertexIndex(const Pin *pin) const = 0;
|
||||
virtual void setVertexIndex(Pin *pin,
|
||||
VertexIndex index) = 0;
|
||||
VertexId id) = 0;
|
||||
int pinCount();
|
||||
int pinCount(Instance *inst);
|
||||
int leafPinCount();
|
||||
|
|
|
|||
|
|
@ -210,7 +210,7 @@ NetworkNameAdapter::direction(const Port *port) const
|
|||
return network_->direction(port);
|
||||
}
|
||||
|
||||
VertexIndex
|
||||
VertexId
|
||||
NetworkNameAdapter::vertexIndex(const Pin *pin) const
|
||||
{
|
||||
return network_->vertexIndex(pin);
|
||||
|
|
@ -218,9 +218,9 @@ NetworkNameAdapter::vertexIndex(const Pin *pin) const
|
|||
|
||||
void
|
||||
NetworkNameAdapter::setVertexIndex(Pin *pin,
|
||||
VertexIndex index)
|
||||
VertexId id)
|
||||
{
|
||||
network_->setVertexIndex(pin, index);
|
||||
network_->setVertexIndex(pin, id);
|
||||
}
|
||||
|
||||
bool
|
||||
|
|
|
|||
|
|
@ -100,9 +100,9 @@ public:
|
|||
virtual Net *net(const Pin *pin) const;
|
||||
virtual Term *term(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,
|
||||
VertexIndex index);
|
||||
VertexId id);
|
||||
|
||||
virtual Net *net(const Term *term) const;
|
||||
virtual Pin *pin(const Term *term) const;
|
||||
|
|
|
|||
|
|
@ -62,7 +62,7 @@ CheckCrpr::clkPathPrev(Vertex *vertex,
|
|||
int arrival_index,
|
||||
PathVertex &tmp)
|
||||
{
|
||||
PathVertexRep *prevs = vertex->prevPaths();
|
||||
PathVertexRep *prevs = graph_->prevPaths(vertex);
|
||||
if (prevs) {
|
||||
PathVertexRep *prev = &prevs[arrival_index];
|
||||
if (prev->isNull())
|
||||
|
|
|
|||
|
|
@ -37,6 +37,8 @@
|
|||
|
||||
namespace sta {
|
||||
|
||||
using std::max;
|
||||
|
||||
class GenclkInfo
|
||||
{
|
||||
public:
|
||||
|
|
@ -896,9 +898,9 @@ void
|
|||
Genclks::copyGenClkSrcPaths(Vertex *vertex,
|
||||
TagGroupBldr *tag_bldr)
|
||||
{
|
||||
Arrival *arrivals = vertex->arrivals();
|
||||
Arrival *arrivals = graph_->arrivals(vertex);
|
||||
if (arrivals) {
|
||||
PathVertexRep *prev_paths = vertex->prevPaths();
|
||||
PathVertexRep *prev_paths = graph_->prevPaths(vertex);
|
||||
TagGroup *tag_group = search_->tagGroup(vertex);
|
||||
ArrivalMap::Iterator arrival_iter(tag_group->arrivalMap());
|
||||
while (arrival_iter.hasNext()) {
|
||||
|
|
|
|||
|
|
@ -30,6 +30,8 @@
|
|||
|
||||
namespace sta {
|
||||
|
||||
using std::max;
|
||||
|
||||
Levelize::Levelize(StaState *sta) :
|
||||
StaState(sta),
|
||||
search_pred_(new SearchPredNonLatch2(sta)),
|
||||
|
|
|
|||
|
|
@ -240,18 +240,18 @@ PathVertex::setArrivalIndex(int arrival_index)
|
|||
}
|
||||
|
||||
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_];
|
||||
}
|
||||
|
||||
void
|
||||
PathVertex::setArrival(Arrival arrival,
|
||||
const StaState *)
|
||||
const StaState *sta)
|
||||
{
|
||||
if (tag_) {
|
||||
Arrival *arrivals = vertex_->arrivals();
|
||||
Arrival *arrivals = sta->graph()->arrivals(vertex_);
|
||||
arrivals[arrival_index_] = arrival;
|
||||
}
|
||||
}
|
||||
|
|
@ -263,7 +263,7 @@ PathVertex::required(const StaState *sta) const
|
|||
const Search *search = sta->search();
|
||||
TagGroup *tag_group = search->tagGroup(vertex_);
|
||||
int req_index = tag_group->requiredIndex(arrival_index_);
|
||||
Arrival *arrivals = vertex_->arrivals();
|
||||
Arrival *arrivals = sta->graph()->arrivals(vertex_);
|
||||
return arrivals[req_index];
|
||||
}
|
||||
else
|
||||
|
|
@ -274,16 +274,15 @@ void
|
|||
PathVertex::setRequired(const Required &required,
|
||||
const StaState *sta)
|
||||
{
|
||||
Graph *graph = sta->graph();
|
||||
const Search *search = sta->search();
|
||||
TagGroup *tag_group = search->tagGroup(vertex_);
|
||||
Arrival *arrivals = vertex_->arrivals();
|
||||
Arrival *arrivals = graph->arrivals(vertex_);
|
||||
int arrival_count = tag_group->arrivalCount();
|
||||
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));
|
||||
vertex_->setArrivals(new_arrivals);
|
||||
vertex_->setHasRequireds(true);
|
||||
delete [] arrivals;
|
||||
arrivals = new_arrivals;
|
||||
}
|
||||
int req_index = arrival_index_ + arrival_count;
|
||||
|
|
@ -292,19 +291,10 @@ PathVertex::setRequired(const Required &required,
|
|||
|
||||
void
|
||||
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);
|
||||
delete [] arrivals;
|
||||
}
|
||||
vertex->setHasRequireds(false);
|
||||
// Don't bother reclaiming requieds from arrival table.
|
||||
}
|
||||
|
||||
bool
|
||||
|
|
|
|||
|
|
@ -142,7 +142,7 @@ PathVertexRep::arrival(const StaState *sta) const
|
|||
tag_group->arrivalIndex(tag, arrival_index, arrival_exists);
|
||||
if (!arrival_exists)
|
||||
internalError("tag group missing tag");
|
||||
Arrival *arrivals = vertex->arrivals();
|
||||
Arrival *arrivals = graph->arrivals(vertex);
|
||||
return arrivals[arrival_index];
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -17,10 +17,9 @@
|
|||
#ifndef STA_PATH_VERTEX_REP_H
|
||||
#define STA_PATH_VERTEX_REP_H
|
||||
|
||||
namespace sta {
|
||||
#include "SearchClass.hh"
|
||||
|
||||
class StaState;
|
||||
class PathVertex;
|
||||
namespace sta {
|
||||
|
||||
// Path representation that references a vertex arrival via a tag.
|
||||
// This does not implement the Path API which uses virtual functions
|
||||
|
|
|
|||
|
|
@ -399,6 +399,8 @@ Search::deletePaths()
|
|||
Vertex *vertex = vertex_iter.next();
|
||||
deletePaths1(vertex);
|
||||
}
|
||||
graph_->clearArrivals();
|
||||
graph_->clearPrevPaths();
|
||||
arrivals_exist_ = false;
|
||||
}
|
||||
}
|
||||
|
|
@ -406,12 +408,8 @@ Search::deletePaths()
|
|||
void
|
||||
Search::deletePaths1(Vertex *vertex)
|
||||
{
|
||||
Arrival *arrivals = vertex->arrivals();
|
||||
delete [] arrivals;
|
||||
vertex->setArrivals(nullptr);
|
||||
PathVertexRep *prev_paths = vertex->prevPaths();
|
||||
delete [] prev_paths;
|
||||
vertex->setPrevPaths(nullptr);
|
||||
vertex->setArrivals(arrival_null);
|
||||
vertex->setPrevPaths(prev_path_null);
|
||||
vertex->setTagGroupIndex(tag_group_index_max);
|
||||
vertex->setHasRequireds(false);
|
||||
vertex->setCrprPathPruningDisabled(false);
|
||||
|
|
@ -1191,7 +1189,7 @@ bool
|
|||
Search::arrivalsChanged(Vertex *vertex,
|
||||
TagGroupBldr *tag_bldr)
|
||||
{
|
||||
Arrival *arrivals1 = vertex->arrivals();
|
||||
Arrival *arrivals1 = graph_->arrivals(vertex);
|
||||
if (arrivals1) {
|
||||
TagGroup *tag_group = tagGroup(vertex);
|
||||
if (tag_group->arrivalMap()->size() != tag_bldr->arrivalMap()->size())
|
||||
|
|
@ -2682,8 +2680,8 @@ Search::setVertexArrivals(Vertex *vertex,
|
|||
deletePaths(vertex);
|
||||
else {
|
||||
TagGroup *prev_tag_group = tagGroup(vertex);
|
||||
Arrival *prev_arrivals = vertex->arrivals();
|
||||
PathVertexRep *prev_paths = vertex->prevPaths();
|
||||
Arrival *prev_arrivals = graph_->arrivals(vertex);
|
||||
PathVertexRep *prev_paths = graph_->prevPaths(vertex);
|
||||
|
||||
TagGroup *tag_group = findTagGroup(tag_bldr);
|
||||
int arrival_count = tag_group->arrivalCount();
|
||||
|
|
@ -2696,30 +2694,24 @@ Search::setVertexArrivals(Vertex *vertex,
|
|||
|| tag_group == prev_tag_group)) {
|
||||
if (tag_bldr->hasClkTag() || tag_bldr->hasGenClkSrcTag()) {
|
||||
if (prev_paths == nullptr)
|
||||
prev_paths = new PathVertexRep[arrival_count];
|
||||
prev_paths = graph_->makePrevPaths(vertex, arrival_count);
|
||||
}
|
||||
else {
|
||||
// Prev paths not required, delete stale ones.
|
||||
delete [] prev_paths;
|
||||
// Prev paths not required.
|
||||
prev_paths = nullptr;
|
||||
vertex->setPrevPaths(nullptr);
|
||||
vertex->setPrevPaths(prev_path_null);
|
||||
}
|
||||
tag_bldr->copyArrivals(tag_group, prev_arrivals, prev_paths);
|
||||
vertex->setTagGroupIndex(tag_group->index());
|
||||
}
|
||||
else {
|
||||
delete [] prev_arrivals;
|
||||
delete [] prev_paths;
|
||||
|
||||
Arrival *arrivals = new Arrival[arrival_count];
|
||||
Arrival *arrivals = graph_->makeArrivals(vertex, arrival_count);
|
||||
prev_paths = nullptr;
|
||||
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);
|
||||
|
||||
vertex->setTagGroupIndex(tag_group->index());
|
||||
vertex->setArrivals(arrivals);
|
||||
vertex->setPrevPaths(prev_paths);
|
||||
|
||||
if (has_requireds) {
|
||||
requiredInvalid(vertex);
|
||||
|
|
@ -2734,7 +2726,7 @@ Search::reportArrivals(Vertex *vertex) const
|
|||
{
|
||||
report_->print("Vertex %s\n", vertex->name(sdc_network_));
|
||||
TagGroup *tag_group = tagGroup(vertex);
|
||||
Arrival *arrivals = vertex->arrivals();
|
||||
Arrival *arrivals = graph_->arrivals(vertex);
|
||||
if (tag_group) {
|
||||
report_->print("Group %u\n", tag_group->index());
|
||||
ArrivalMap::Iterator arrival_iter(tag_group->arrivalMap());
|
||||
|
|
|
|||
|
|
@ -3915,7 +3915,7 @@ Sta::connectPinAfter(Pin *pin)
|
|||
}
|
||||
else {
|
||||
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_->makePinInstanceEdges(pin);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
340
util/Pool.hh
340
util/Pool.hh
|
|
@ -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
|
||||
|
|
@ -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
|
||||
Loading…
Reference in New Issue