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/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

View File

@ -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)
{

View File

@ -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);

View File

@ -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;
}
////////////////////////////////////////////////////////////////

View File

@ -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);

View File

@ -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();

View File

@ -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

View File

@ -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;

View File

@ -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())

View File

@ -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()) {

View File

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

View File

@ -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

View File

@ -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];
}

View File

@ -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

View File

@ -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());

View File

@ -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);
}

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