Merge remote-tracking branch 'parallax/master'

Signed-off-by: Matt Liberty <mliberty@precisioninno.com>
This commit is contained in:
Matt Liberty 2025-04-01 23:23:25 +00:00
commit 9e96eb85cc
149 changed files with 3651 additions and 5522 deletions

9
Brewfile Normal file
View File

@ -0,0 +1,9 @@
brew "bison"
brew "cmake"
brew "eigen"
brew "flex"
brew "swig"
brew "tcl-tk@8"
tap "mht208/formal"
brew "mht208/formal/cudd"

View File

@ -32,7 +32,7 @@ if(CMAKE_VERSION VERSION_GREATER_EQUAL 3.14)
cmake_policy(SET CMP0086 NEW)
endif()
project(STA VERSION 2.6.0
project(STA VERSION 2.6.2
LANGUAGES CXX
)
@ -184,15 +184,11 @@ set(STA_SOURCE
search/MakeTimingModel.cc
search/Path.cc
search/PathAnalysisPt.cc
search/Path.cc
search/PathEnd.cc
search/PathEnum.cc
search/PathEnumed.cc
search/PathExpanded.cc
search/PathGroup.cc
search/PathPrev.cc
search/PathRef.cc
search/PathVertex.cc
search/PathVertexPtr.cc
search/Property.cc
search/ReportPath.cc
search/Search.cc

View File

@ -66,7 +66,7 @@ OpenSTA is open source, meaning the sources are published and can be
compiled locally. Derivative works are supported as long as they
adhere to the GPL license requirements. However, OpenSTA is not
supported by a public community of developers as many other open
source projects are. The copyright and develpment are exclusive to
source projects are. The copyright and development are exclusive to
Parallax Software.
Removing copyright and license notices from OpenSTA sources (or any
@ -86,7 +86,7 @@ OpenSTA is built with CMake.
### Prerequisites
The build dependency versions are show below. Other versions may
The build dependency versions are shown below. Other versions may
work, but these are the versions used for development.
```
@ -207,10 +207,13 @@ docker run -i -v $HOME:/data OpenSTA
## Build on Macos/Darwin
THe XCode versions of Tcl, Flex and Bison cannot be used to build OpenSTA.
Use Homebrew to install them.
The XCode versions of Tcl, Flex and Bison cannot be used to build OpenSTA.
Use Homebrew to install them. The following command installs the tools
required to build OpenSTA in the Brewfile.
brew install cmake swig flex bison tcl-tk zlib
```
brew bundle install
```
Set these variables before using cmake to cirumvent the Xcode versions.
@ -255,12 +258,12 @@ case directory.
Contributors must sign the Contributor License Agreement (doc/CLA.txt)
when submitting pull requests.
All contributors should read doc/CodingGuidelines.txt for nodes on
All contributors should read doc/CodingGuidelines.txt for notes on
making code that adheres to the existing naming and formatting style.
Contributions that claim 4% performance improvements in OpenROAD flow
scripts will largely be ignored. Small performance improvements
simply do not justify the time requied to audit and verify the changes.
simply do not justify the time required to audit and verify the changes.
Contributions that add dependencies on external libraries like boost,
abseil and Intel TBB will not be accepted.

View File

@ -98,10 +98,10 @@ sourceTclFile(const char *filename,
Tcl_Interp *interp)
{
string cmd;
stringPrint(cmd, "source %s%s%s",
echo ? "-echo " : "",
verbose ? "-verbose " : "",
filename);
stringPrint(cmd, "sta::include_file %s %s %s",
filename,
echo ? "1" : "0",
verbose ? "1" : "0");
int code = Tcl_Eval(interp, cmd.c_str());
const char *result = Tcl_GetStringResult(interp);
if (result[0] != '\0')

View File

@ -119,7 +119,7 @@ CcsCeffDelayCalc::gateDelay(const Pin *drvr_pin,
ref_time_ = output_waveforms_->referenceTime(in_slew_);
debugPrint(debug_, "ccs_dcalc", 1, "%s %s",
drvr_cell->name(),
drvr_rf_->asString());
drvr_rf_->to_string().c_str());
ArcDelay gate_delay;
Slew drvr_slew;
gateDelaySlew(drvr_library, drvr_rf_, gate_delay, drvr_slew);

View File

@ -55,7 +55,7 @@ DelayCalcBase::reduceParasitic(const Parasitic *parasitic_network,
while (pin_iter->hasNext()) {
const Pin *pin = pin_iter->next();
if (network_->isDriver(pin)) {
for (RiseFall *rf : RiseFall::range()) {
for (const RiseFall *rf : RiseFall::range()) {
for (const MinMax *min_max : min_max->range()) {
if (corner == nullptr) {
for (const Corner *corner1 : *corners_) {

View File

@ -1600,17 +1600,18 @@ DmpCeffDelayCalc::reportGateDelay(const Pin *drvr_pin,
const DcalcAnalysisPt *dcalc_ap,
int digits)
{
gateDelay(drvr_pin, arc, in_slew, load_cap, parasitic, load_pin_index_map, dcalc_ap);
ArcDcalcResult dcalc_result = gateDelay(drvr_pin, arc, in_slew, load_cap,
parasitic, load_pin_index_map, dcalc_ap);
GateTableModel *model = arc->gateTableModel(dcalc_ap);
float c_eff = 0.0;
string result;
const LibertyCell *drvr_cell = arc->to()->libertyCell();
const LibertyLibrary *drvr_library = drvr_cell->libertyLibrary();
const Units *units = drvr_library->units();
const Unit *cap_unit = units->capacitanceUnit();
const Unit *res_unit = units->resistanceUnit();
if (parasitic && dmp_alg_) {
c_eff = dmp_alg_->ceff();
const LibertyCell *drvr_cell = arc->to()->libertyCell();
const LibertyLibrary *drvr_library = drvr_cell->libertyLibrary();
const Units *units = drvr_library->units();
const Unit *cap_unit = units->capacitanceUnit();
const Unit *res_unit = units->resistanceUnit();
float c2, rpi, c1;
parasitics_->piModel(parasitic, c2, rpi, c1);
result += "Pi model C2=";
@ -1626,9 +1627,13 @@ DmpCeffDelayCalc::reportGateDelay(const Pin *drvr_pin,
else
c_eff = load_cap;
if (model) {
const Unit *time_unit = units->timeUnit();
float in_slew1 = delayAsFloat(in_slew);
result += model->reportGateDelay(pinPvt(drvr_pin, dcalc_ap), in_slew1, c_eff,
pocv_enabled_, digits);
result += "Driver waveform slew = ";
result += time_unit->asString(dcalc_result.drvrSlew(), digits);
result += '\n';
}
return result;
}

View File

@ -171,7 +171,7 @@ void
GraphDelayCalc::delayInvalid(Vertex *vertex)
{
debugPrint(debug_, "delay_calc", 2, "delay invalid %s",
vertex->name(sdc_network_));
vertex->to_string(this).c_str());
if (graph_ && incremental_) {
invalid_delays_->insert(vertex);
// Invalidate driver that triggers dcalc for multi-driver nets.
@ -315,7 +315,7 @@ GraphDelayCalc::seedDrvrSlew(Vertex *drvr_vertex,
{
const Pin *drvr_pin = drvr_vertex->pin();
debugPrint(debug_, "delay_calc", 2, "seed driver slew %s",
drvr_vertex->name(sdc_network_));
drvr_vertex->to_string(this).c_str());
InputDrive *drive = 0;
if (network_->isTopLevelPort(drvr_pin)) {
Port *port = network_->port(drvr_pin);
@ -426,7 +426,7 @@ GraphDelayCalc::seedLoadSlew(Vertex *vertex)
{
const Pin *pin = vertex->pin();
debugPrint(debug_, "delay_calc", 2, "seed load slew %s",
vertex->name(sdc_network_));
vertex->to_string(this).c_str());
ClockSet *clks = sdc_->findLeafPinClocks(pin);
initSlew(vertex);
for (const RiseFall *rf : RiseFall::range()) {
@ -501,7 +501,7 @@ GraphDelayCalc::findInputDriverDelay(const LibertyCell *drvr_cell,
{
debugPrint(debug_, "delay_calc", 2, " driver cell %s %s",
drvr_cell->name(),
rf->asString());
rf->to_string().c_str());
for (TimingArcSet *arc_set : drvr_cell->timingArcSets(from_port, to_port)) {
for (TimingArc *arc : arc_set->arcs()) {
if (arc->toEdge()->asRiseFall() == rf) {
@ -525,10 +525,10 @@ GraphDelayCalc::findInputArcDelay(const Pin *drvr_pin,
{
debugPrint(debug_, "delay_calc", 3, " %s %s -> %s %s (%s)",
arc->from()->name(),
arc->fromEdge()->asString(),
arc->fromEdge()->to_string().c_str(),
arc->to()->name(),
arc->toEdge()->asString(),
arc->role()->asString());
arc->toEdge()->to_string().c_str(),
arc->role()->to_string().c_str());
const RiseFall *drvr_rf = arc->toEdge()->asRiseFall();
if (drvr_rf) {
DcalcAPIndex ap_index = dcalc_ap->index();
@ -577,7 +577,7 @@ GraphDelayCalc::findVertexDelay(Vertex *vertex,
{
const Pin *pin = vertex->pin();
debugPrint(debug_, "delay_calc", 2, "find delays %s (%s)",
vertex->name(sdc_network_),
vertex->to_string(this).c_str(),
network_->cellName(network_->instance(pin)));
if (vertex->isRoot()) {
seedRootSlew(vertex, arc_delay_calc);
@ -1091,12 +1091,12 @@ GraphDelayCalc::annotateDelaySlew(Edge *edge,
debugPrint(debug_, "delay_calc", 3,
" %s %s -> %s %s (%s) corner:%s/%s",
arc->from()->name(),
arc->fromEdge()->asString(),
arc->fromEdge()->to_string().c_str(),
arc->to()->name(),
arc->toEdge()->asString(),
arc->role()->asString(),
arc->toEdge()->to_string().c_str(),
arc->role()->to_string().c_str(),
dcalc_ap->corner()->name(),
dcalc_ap->delayMinMax()->asString());
dcalc_ap->delayMinMax()->to_string().c_str());
debugPrint(debug_, "delay_calc", 3,
" gate delay = %s slew = %s",
delayAsString(gate_delay, this),
@ -1149,7 +1149,7 @@ GraphDelayCalc::annotateLoadDelays(Vertex *drvr_vertex,
Slew load_slew = dcalc_result.loadSlew(load_idx);
debugPrint(debug_, "delay_calc", 3,
" %s load delay = %s slew = %s",
load_vertex->name(sdc_network_),
load_vertex->to_string(this).c_str(),
delayAsString(wire_delay, this),
delayAsString(load_slew, this));
bool load_changed = false;
@ -1465,8 +1465,8 @@ GraphDelayCalc::findCheckEdgeDelays(Edge *edge,
network_->portName(to_pin));
bool delay_changed = false;
for (TimingArc *arc : arc_set->arcs()) {
RiseFall *from_rf = arc->fromEdge()->asRiseFall();
RiseFall *to_rf = arc->toEdge()->asRiseFall();
const RiseFall *from_rf = arc->fromEdge()->asRiseFall();
const RiseFall *to_rf = arc->toEdge()->asRiseFall();
if (from_rf && to_rf) {
const LibertyPort *related_out_port = arc_set->relatedOut();
const Pin *related_out_pin = 0;
@ -1482,12 +1482,12 @@ GraphDelayCalc::findCheckEdgeDelays(Edge *edge,
debugPrint(debug_, "delay_calc", 3,
" %s %s -> %s %s (%s) corner:%s/%s",
arc_set->from()->name(),
arc->fromEdge()->asString(),
arc->fromEdge()->to_string().c_str(),
arc_set->to()->name(),
arc->toEdge()->asString(),
arc_set->role()->asString(),
arc->toEdge()->to_string().c_str(),
arc_set->role()->to_string().c_str(),
dcalc_ap->corner()->name(),
dcalc_ap->delayMinMax()->asString());
dcalc_ap->delayMinMax()->to_string().c_str());
debugPrint(debug_, "delay_calc", 3,
" from_slew = %s to_slew = %s",
delayAsString(from_slew, this),
@ -1538,13 +1538,13 @@ GraphDelayCalc::reportDelayCalc(const Edge *edge,
Vertex *from_vertex = edge->from(graph_);
Vertex *to_vertex = edge->to(graph_);
Pin *to_pin = to_vertex->pin();
TimingRole *role = arc->role();
const TimingRole *role = arc->role();
const Instance *inst = network_->instance(to_pin);
const TimingArcSet *arc_set = edge->timingArcSet();
string result;
DcalcAnalysisPt *dcalc_ap = corner->findDcalcAnalysisPt(min_max);
RiseFall *from_rf = arc->fromEdge()->asRiseFall();
RiseFall *to_rf = arc->toEdge()->asRiseFall();
const RiseFall *from_rf = arc->fromEdge()->asRiseFall();
const RiseFall *to_rf = arc->toEdge()->asRiseFall();
if (from_rf && to_rf) {
const LibertyPort *related_out_port = arc_set->relatedOut();
const Pin *related_out_pin = 0;

View File

@ -228,7 +228,7 @@ PrimaDelayCalc::gateDelays(ArcDcalcArgSeq &dcalc_args,
output_waveforms_[drvr_idx] = output_waveforms;
debugPrint(debug_, "ccs_dcalc", 1, "%s %s",
dcalc_arg.drvrCell()->name(),
drvr_rf_->asString());
drvr_rf_->to_string().c_str());
LibertyCell *drvr_cell = dcalc_arg.drvrCell();
const LibertyLibrary *drvr_library = drvr_cell->libertyLibrary();
bool vdd_exists;
@ -741,7 +741,7 @@ PrimaDelayCalc::dcalcResults()
debugPrint(debug_, "ccs_dcalc", 2,
"load %s %s delay %s slew %s",
network_->pathName(load_pin),
drvr_rf_->asString(),
drvr_rf_->to_string().c_str(),
delayAsString(wire_delay, this),
delayAsString(load_slew, this));

View File

@ -24,6 +24,45 @@
This file summarizes STA API changes for each release.
Release 2.6.2 2024/03/30
------------------------
The following functions have been renamed to to_string and return std::string
instead of "const char*"
Vertex::name
FuncExpr::asString
TimingRole::name
MinMax::asString
MinMaxAll::asString
RiseFall::asString
RiseFallBoth::asString
Transition::asString
Tag::asString
timingSenseString
The following classes now return const objects.
MinMax
MinMaxAll
RiseFall
RiseFallBoth
Transition
TimingRole
Release 2.6.1 2025/03/??
-------------------------
The following classes have been replaced by the class Path.
PathEnumed
PathPrev
PathRef
PathVertex
PathVertexPtr
PathVertexRep
The PathExpanded::prevArc function has been removed. Use Path::prevArc instead.
Release 2.4.0 2023/01/19
-------------------------

View File

@ -3,6 +3,19 @@ OpenSTA Timing Analyzer Release Notes
This file summarizes user visible changes for each release.
Realase 2.6.1 2025/03/30
-------------------------
The Tcl "source" command is no longer redefined to support "-echo" and
"-verbose" arguments and redirecton. Use the "include" command instead.
include [-echo] [-verbose] filename [> filename] [>> filename]
-echo echos commands as they are read
-verbose prints command results as they are evaluated
Unlike the Tcl source command, "include" expands filenames with tilda '~'
and respects sta_continue_on_error.
Release 2.6.0 2024/07/22
-------------------------

Binary file not shown.

Binary file not shown.

View File

@ -206,7 +206,7 @@ Graph::makePortInstanceEdges(const Instance *inst,
// Vertices can be missing from the graph if the pins
// are power or ground.
if (from_vertex) {
TimingRole *role = arc_set->role();
const TimingRole *role = arc_set->role();
bool is_check = role->isTimingCheckBetween();
if (to_bidirect_drvr_vertex && !is_check)
makeEdge(from_vertex, to_bidirect_drvr_vertex, arc_set);
@ -571,75 +571,25 @@ Graph::gateEdgeArc(const Pin *in_pin,
////////////////////////////////////////////////////////////////
Arrival *
Graph::makeArrivals(Vertex *vertex,
uint32_t count)
Path *
Graph::makePaths(Vertex *vertex,
uint32_t count)
{
Arrival *arrivals = new Arrival[count];
vertex->setArrivals(arrivals);
return arrivals;
Path *paths = new Path[count];
vertex->setPaths(paths);
return paths;
}
Arrival *
Graph::arrivals(const Vertex *vertex) const
Path *
Graph::paths(const Vertex *vertex) const
{
return vertex->arrivals();
}
void
Graph::deleteArrivals(Vertex *vertex)
{
vertex->setArrivals(nullptr);
}
Required *
Graph::requireds(const Vertex *vertex) const
{
return vertex->requireds();
}
Required *
Graph::makeRequireds(Vertex *vertex,
uint32_t count)
{
Required *requireds = new Arrival[count];
vertex->setRequireds(requireds);
return requireds;
}
void
Graph::deleteRequireds(Vertex *vertex)
{
vertex->setRequireds(nullptr);
}
PathPrev *
Graph::prevPaths(const Vertex *vertex) const
{
return vertex->prevPaths();
}
PathPrev *
Graph::makePrevPaths(Vertex *vertex,
uint32_t count)
{
PathPrev *prev_paths = new PathPrev[count];
vertex->setPrevPaths(prev_paths);
return prev_paths;
}
void
Graph::deletePrevPaths(Vertex *vertex)
{
vertex->setPrevPaths(nullptr);
return vertex->paths();
}
void
Graph::deletePaths(Vertex *vertex)
{
deleteArrivals(vertex);
deleteRequireds(vertex);
deletePrevPaths(vertex);
vertex->setPaths(nullptr);
vertex->tag_group_index_ = tag_group_index_max;
vertex->crpr_path_pruning_disabled_ = false;
}
@ -1007,9 +957,7 @@ Vertex::init(Pin *pin,
in_edges_ = edge_id_null;
out_edges_ = edge_id_null;
slews_ = nullptr;
arrivals_ = nullptr;
requireds_ = nullptr;
prev_paths_ = nullptr;
paths_ = nullptr;
tag_group_index_ = tag_group_index_max;
slew_annotated_ = false;
sim_value_ = unsigned(LogicValue::unknown);
@ -1035,12 +983,8 @@ Vertex::clear()
{
delete [] slews_;
slews_ = nullptr;
delete [] arrivals_;
arrivals_ = nullptr;
delete [] requireds_;
requireds_ = nullptr;
delete [] prev_paths_;
prev_paths_ = nullptr;
delete [] paths_;
paths_ = nullptr;
}
void
@ -1049,19 +993,27 @@ Vertex::setObjectIdx(ObjectIdx idx)
object_idx_ = idx;
}
const char *
Vertex::name(const Network *network) const
string
Vertex::to_string(const StaState *sta) const
{
const Network *network = sta->network();
if (network->direction(pin_)->isBidirect()) {
const char *pin_name = network->pathName(pin_);
return stringPrintTmp("%s %s",
pin_name,
is_bidirect_drvr_ ? "driver" : "load");
string str = network->pathName(pin_);
str += ' ';
str += is_bidirect_drvr_ ? "driver" : "load";
return str;
}
else
return network->pathName(pin_);
}
const char *
Vertex::name(const Network *network) const
{
string name = to_string(network);
return makeTmpString(name);
}
bool
Vertex::isDriver(const Network *network) const
{
@ -1153,24 +1105,10 @@ Vertex::setTagGroupIndex(TagGroupIndex tag_index)
}
void
Vertex::setArrivals(Arrival *arrivals)
Vertex::setPaths(Path *paths)
{
delete [] arrivals_;
arrivals_ = arrivals;
}
void
Vertex::setRequireds(Required *requireds)
{
delete [] requireds_;
requireds_ = requireds;
}
void
Vertex::setPrevPaths(PathPrev *prev_paths)
{
delete [] prev_paths_;
prev_paths_ = prev_paths;
delete [] paths_;
paths_ = paths;
}
LogicValue
@ -1315,6 +1253,16 @@ Edge::setObjectIdx(ObjectIdx idx)
object_idx_ = idx;
}
string
Edge::to_string(const StaState *sta) const
{
const Graph *graph = sta->graph();
string str = from(graph)->to_string(sta);
str += " -> ";
str += to(graph)->to_string(sta);
return str;
}
void
Edge::setTimingArcSet(TimingArcSet *set)
{
@ -1380,7 +1328,7 @@ Edge::setDelayAnnotationIsIncremental(bool is_incr)
delay_annotation_is_incremental_ = is_incr;
}
TimingRole *
const TimingRole *
Edge::role() const
{
return arc_set_->role();
@ -1414,7 +1362,7 @@ Edge::setSimTimingSense(TimingSense sense)
bool
Edge::isDisabledConstraint() const
{
TimingRole *role = arc_set_->role();
const TimingRole *role = arc_set_->role();
bool is_wire = role->isWire();
return is_disabled_constraint_
|| arc_set_->isDisabledConstraint()

View File

@ -316,8 +316,8 @@ Vertex *from() { return self->from(Sta::sta()->graph()); }
Vertex *to() { return self->to(Sta::sta()->graph()); }
Pin *from_pin() { return self->from(Sta::sta()->graph())->pin(); }
Pin *to_pin() { return self->to(Sta::sta()->graph())->pin(); }
TimingRole *role() { return self->role(); }
const char *sense() { return timingSenseString(self->sense()); }
const TimingRole *role() { return self->role(); }
const char *sense() { return to_string(self->sense()); }
TimingArcSeq &
timing_arcs() { return self->timingArcSet()->arcs(); }
bool is_disabled_loop() { return Sta::sta()->isDisabledLoop(self); }
@ -334,7 +334,7 @@ bool is_disabled_bidirect_net_path()
bool is_disabled_preset_clear()
{ return Sta::sta()->isDisabledPresetClr(self); }
const char *
sim_timing_sense(){return timingSenseString(Sta::sta()->simTimingSense(self));}
sim_timing_sense(){return to_string(Sta::sta()->simTimingSense(self));}
FloatSeq
arc_delays(TimingArc *arc)
@ -376,14 +376,14 @@ arc_delay(TimingArc *arc,
return delayAsFloat(Sta::sta()->arcDelay(self, arc, dcalc_ap));
}
const char *
string
cond()
{
FuncExpr *cond = self->timingArcSet()->cond();
if (cond)
return cond->asString();
return cond->to_string();
else
return nullptr;
return "";
}
const char *
@ -414,7 +414,9 @@ latch_d_to_q_en()
const RiseFall *enable_rf;
lib_cell->latchEnable(d_q_set, enable_port, enable_func, enable_rf);
if (enable_port)
return stringPrintTmp("%s %s", enable_port->name(), enable_rf->asString());
return stringPrintTmp("%s %s",
enable_port->name(),
enable_rf->to_string().c_str());
}
return "";
}

View File

@ -75,7 +75,7 @@ public:
// Notify iterator that vertex will be deleted.
void deleteVertexBefore(Vertex *vertex);
void remove(Vertex *vertex);
void reportEntries(const Network *network);
void reportEntries();
virtual bool hasNext();
bool hasNext(Level to_level);

View File

@ -203,7 +203,7 @@ class ClockEdge
public:
Clock *clock() const { return clock_; }
~ClockEdge();
RiseFall *transition() const { return rf_; }
const RiseFall *transition() const { return rf_; }
float time() const { return time_; }
const char *name() const { return name_; }
int index() const { return index_; }
@ -213,11 +213,12 @@ public:
friend class Clock; // builder
private:
ClockEdge(Clock *clock, RiseFall *rf);
ClockEdge(Clock *clock,
const RiseFall *rf);
void setTime(float time);
Clock *clock_;
RiseFall *rf_;
const RiseFall *rf_;
const char *name_;
float time_;
int index_;
@ -262,7 +263,7 @@ public:
void removeUncertainty(const RiseFallBoth *src_rf,
const RiseFallBoth *tgt_rf,
const SetupHoldAll *setup_hold);
const RiseFallMinMax *uncertainties(RiseFall *src_rf) const;
const RiseFallMinMax *uncertainties(const RiseFall *src_rf) const;
bool empty() const;
private:

View File

@ -45,10 +45,10 @@ class PatternMatch;
class LibertyCell;
class LibertyPort;
typedef Map<const char*, ConcreteCell*, CharPtrLess> ConcreteCellMap;
typedef Map<string, ConcreteCell*> ConcreteCellMap;
typedef std::map<string, string> AttributeMap;
typedef Vector<ConcretePort*> ConcretePortSeq;
typedef Map<const char*, ConcretePort*, CharPtrLess> ConcretePortMap;
typedef Map<string, ConcretePort*> ConcretePortMap;
typedef ConcreteCellMap::ConstIterator ConcreteLibraryCellIterator;
typedef ConcretePortSeq::ConstIterator ConcreteCellPortIterator;
typedef ConcretePortSeq::ConstIterator ConcretePortMemberIterator;
@ -60,11 +60,11 @@ public:
const char *filename,
bool is_liberty);
virtual ~ConcreteLibrary();
const char *name() const { return name_; }
const char *name() const { return name_.c_str(); }
void setName(const char *name);
ObjectId id() const { return id_; }
bool isLiberty() const { return is_liberty_; }
const char *filename() const { return filename_; }
const char *filename() const { return filename_.c_str(); }
void addCell(ConcreteCell *cell);
ConcreteCell *makeCell(const char *name,
bool is_leaf,
@ -82,9 +82,9 @@ protected:
void renameCell(ConcreteCell *cell,
const char *cell_name);
const char *name_;
string name_;
ObjectId id_;
const char *filename_;
string filename_;
bool is_liberty_;
char bus_brkt_left_;
char bus_brkt_right_;
@ -99,9 +99,9 @@ class ConcreteCell
public:
// Use ConcreteLibrary::deleteCell.
virtual ~ConcreteCell();
const char *name() const { return name_; }
const char *name() const { return name_.c_str(); }
ObjectId id() const { return id_; }
const char *filename() const { return filename_; }
const char *filename() const { return filename_.c_str(); }
ConcreteLibrary *library() const { return library_; }
LibertyCell *libertyCell() const { return liberty_cell_; }
void setLibertyCell(LibertyCell *cell);
@ -156,10 +156,10 @@ protected:
const char *name,
int index);
const char *name_;
string name_;
ObjectId id_;
// Filename is optional.
const char *filename_;
string filename_;
ConcreteLibrary *library_;
LibertyCell *liberty_cell_;
// External application cell.
@ -181,7 +181,7 @@ class ConcretePort
{
public:
virtual ~ConcretePort();
const char *name() const { return name_; }
const char *name() const { return name_.c_str(); }
ObjectId id() const { return id_; }
const char *busName() const;
Cell *cell() const;
@ -236,7 +236,7 @@ protected:
ConcretePortSeq *member_ports,
ConcreteCell *cell);
const char *name_;
string name_;
ObjectId id_;
ConcreteCell *cell_;
PortDirection *direction_;

View File

@ -51,7 +51,7 @@ class Corners : public StaState
{
public:
explicit Corners(StaState *sta);
virtual ~Corners();
~Corners();
void clear();
int count() const;
void copy(Corners *corners);
@ -106,8 +106,7 @@ class Corner
public:
Corner(const char *name,
int index);
~Corner();
const char *name() const { return name_; }
const char *name() const { return name_.c_str(); }
int index() const { return index_; }
ParasiticAnalysisPt *findParasiticAnalysisPt(const MinMax *min_max) const;
int parasiticAnalysisPtcount();
@ -127,7 +126,7 @@ protected:
void addPathAP(PathAnalysisPt *path_ap);
private:
const char *name_;
string name_;
int index_;
ParasiticAnalysisPtSeq parasitic_analysis_pts_;
DcalcAnalysisPtSeq dcalc_analysis_pts_;

View File

@ -95,7 +95,7 @@ private:
int tgt_cycle,
float delay,
float req);
void setAccting(TimingRole *role,
void setAccting(const TimingRole *role,
int src_cycle,
int tgt_cycle,
float delay,

View File

@ -56,7 +56,7 @@ public:
const RiseFallBoth *to_rf,
const SetupHoldAll *setup_hold);
bool empty() const;
void marginIsOneValue(SetupHold *setup_hold,
void marginIsOneValue(const SetupHold *setup_hold,
// Return values.
float &value,
bool &one_value) const;

View File

@ -24,12 +24,16 @@
#pragma once
#include <string>
#include "Set.hh"
#include "NetworkClass.hh"
#include "LibertyClass.hh"
namespace sta {
using std::string;
class FuncExpr
{
public:
@ -75,7 +79,7 @@ public:
TimingSense portTimingSense(const LibertyPort *port) const;
// Return true if expression has port as an input.
bool hasPort(const LibertyPort *port) const;
const char *asString() const;
string to_string() const;
// Sub expression for a bus function (bit_offset is 0 to bus->size()-1).
FuncExpr *bitSubExpr(int bit_offset);
// Check to make sure the function and port size are compatible.
@ -84,9 +88,9 @@ public:
bool checkSize(LibertyPort *port);
private:
const char *asString(bool with_parens) const;
const char *asStringSubexpr(bool with_parens,
char op) const;
string to_string(bool with_parens) const;
string to_string(bool with_parens,
char op) const;
Operator op_;
FuncExpr *left_;

View File

@ -36,7 +36,7 @@
#include "Delay.hh"
#include "GraphClass.hh"
#include "VertexId.hh"
#include "PathPrev.hh"
#include "Path.hh"
#include "StaState.hh"
namespace sta {
@ -96,19 +96,9 @@ public:
void deleteVertex(Vertex *vertex);
bool hasFaninOne(Vertex *vertex) const;
VertexId vertexCount() { return vertices_->size(); }
Arrival *makeArrivals(Vertex *vertex,
uint32_t count);
Arrival *arrivals(const Vertex *vertex) const;
void deleteArrivals(Vertex *vertex);
Required *makeRequireds(Vertex *vertex,
uint32_t count);
Required *requireds(const Vertex *vertex) const;
void deleteRequireds(Vertex *vertex);
PathPrev *makePrevPaths(Vertex *vertex,
uint32_t count);
PathPrev *prevPaths(const Vertex *vertex) const;
void deletePrevPaths(Vertex *vertex);
// Private to Search::deletePaths(Vertex).
Path *makePaths(Vertex *vertex,
uint32_t count);
Path *paths(const Vertex *vertex) const;
void deletePaths(Vertex *vertex);
// Reported slew are the same as those in the liberty tables.
@ -257,6 +247,8 @@ public:
~Vertex();
Pin *pin() const { return pin_; }
// Pin path with load/driver suffix for bidirects.
string to_string(const StaState *sta) const;
// compatibility
const char *name(const Network *network) const;
bool isBidirectDriver() const { return is_bidirect_drvr_; }
bool isDriver(const Network *network) const;
@ -269,10 +261,8 @@ public:
void setColor(LevelColor color);
Slew *slews() { return slews_; }
const Slew *slews() const { return slews_; }
Arrival *arrivals() const { return arrivals_; }
Arrival *requireds() const { return requireds_; }
PathPrev *prevPaths() const { return prev_paths_; }
void setPrevPaths(PathPrev *prev_paths);
Path *paths() const { return paths_; }
void setPaths(Path *paths);
TagGroupIndex tagGroupIndex() const;
void setTagGroupIndex(TagGroupIndex tag_index);
// Slew is annotated by sdc set_annotated_transition cmd.
@ -311,7 +301,6 @@ public:
bool isRegClk() const { return is_reg_clk_; }
bool crprPathPruningDisabled() const { return crpr_path_pruning_disabled_;}
void setCrprPathPruningDisabled(bool disabled);
bool hasRequireds() const { return requireds_ != nullptr; }
// ObjectTable interface.
ObjectIdx objectIdx() const { return object_idx_; }
@ -324,8 +313,6 @@ protected:
bool is_bidirect_drvr,
bool is_reg_clk);
void clear();
void setArrivals(Arrival *arrivals);
void setRequireds(Required *requireds);
void setSlews(Slew *slews);
Pin *pin_;
@ -335,9 +322,7 @@ protected:
// Delay calc
Slew *slews_;
// Search
Arrival *arrivals_;
Arrival *requireds_;
PathPrev *prev_paths_;
Path *paths_;
// These fields are written by multiple threads, so they
// cannot share the same word as the following bit fields.
@ -381,11 +366,12 @@ class Edge
public:
Edge();
~Edge();
string to_string(const StaState *sta) const;
Vertex *to(const Graph *graph) const { return graph->vertex(to_); }
VertexId to() const { return to_; }
Vertex *from(const Graph *graph) const { return graph->vertex(from_); }
VertexId from() const { return from_; }
TimingRole *role() const;
const TimingRole *role() const;
bool isWire() const;
TimingSense sense() const;
TimingArcSet *timingArcSet() const { return arc_set_; }

View File

@ -40,9 +40,9 @@ public:
void deleteContents();
FuncExpr *when() const { return when_; }
FuncExpr *&whenRef() { return when_; }
void setModel(RiseFall *rf,
void setModel(const RiseFall *rf,
InternalPowerModel *model);
InternalPowerModel *model(RiseFall *rf) const;
InternalPowerModel *model(const RiseFall *rf) const;
const char *relatedPgPin() const { return related_pg_pin_; }
void setRelatedPgPin(const char *related_pg_pin);
@ -65,7 +65,7 @@ public:
LibertyPort *relatedPort() const { return related_port_; }
FuncExpr *when() const { return when_; }
const char *relatedPgPin() const { return related_pg_pin_; }
float power(RiseFall *rf,
float power(const RiseFall *rf,
const Pvt *pvt,
float in_slew,
float load_cap);

View File

@ -88,9 +88,9 @@ typedef Map<const TimingArcSet*, LatchEnable*> LatchEnableMap;
typedef Vector<LatchEnable*> LatchEnableSeq;
typedef Map<const char *, OcvDerate*, CharPtrLess> OcvDerateMap;
typedef Vector<InternalPowerAttrs*> InternalPowerAttrsSeq;
typedef Map<const char *, float, CharPtrLess> SupplyVoltageMap;
typedef Map<const char *, LibertyPgPort*, CharPtrLess> LibertyPgPortMap;
typedef Map<const char *, DriverWaveform*, CharPtrLess> DriverWaveformMap;
typedef Map<string, float> SupplyVoltageMap;
typedef Map<string, LibertyPgPort*> LibertyPgPortMap;
typedef Map<string, DriverWaveform*> DriverWaveformMap;
typedef Vector<DcalcAnalysisPt*> DcalcAnalysisPtSeq;
enum class ClockGateType { none, latch_posedge, latch_negedge, other };
@ -135,7 +135,7 @@ scaleFactorTypeLowHighSuffix(ScaleFactorType type);
// Timing sense as a string.
const char *
timingSenseString(TimingSense sense);
to_string(TimingSense sense);
// Opposite timing sense.
TimingSense
@ -188,7 +188,7 @@ public:
const Pvt *pvt) const;
void setWireSlewDegradationTable(TableModel *model,
RiseFall *rf);
const RiseFall *rf);
TableModel *wireSlewDegradationTable(const RiseFall *rf) const;
float degradeWireSlew(const RiseFall *rf,
float in_slew,
@ -647,8 +647,8 @@ protected:
bool has_internal_ports_;
std::atomic<bool> have_voltage_waveforms_;
std::mutex waveform_lock_;
const char *footprint_;
const char *user_function_class_;
string footprint_;
string user_function_class_;
private:
friend class LibertyLibrary;
@ -809,11 +809,11 @@ public:
void setIsCheckClk(bool is_clk);
bool isPad() const { return is_pad_; }
void setIsPad(bool is_pad);
RiseFall *pulseClkTrigger() const { return pulse_clk_trigger_; }
const RiseFall *pulseClkTrigger() const { return pulse_clk_trigger_; }
// Rise for high, fall for low.
RiseFall *pulseClkSense() const { return pulse_clk_sense_; }
void setPulseClk(RiseFall *rfigger,
RiseFall *sense);
const RiseFall *pulseClkSense() const { return pulse_clk_sense_; }
void setPulseClk(const RiseFall *rfigger,
const RiseFall *sense);
bool isDisabledConstraint() const { return is_disabled_constraint_; }
void setIsDisabledConstraint(bool is_disabled);
LibertyPort *cornerPort(const Corner *corner,
@ -826,9 +826,9 @@ public:
const LibertyPort *cornerPort(int ap_index) const;
void setCornerPort(LibertyPort *corner_port,
int ap_index);
const char *relatedGroundPin() const { return related_ground_pin_; }
const char *relatedGroundPin() const;
void setRelatedGroundPin(const char *related_ground_pin);
const char *relatedPowerPin() const { return related_power_pin_; }
const char *relatedPowerPin() const;
void setRelatedPowerPin(const char *related_power_pin);
const ReceiverModel *receiverModel() const { return receiver_model_.get(); }
void setReceiverModel(ReceiverModelPtr receiver_model);
@ -886,10 +886,10 @@ protected:
MinMaxFloatValues fanout_limit_; // outputs
float min_period_;
float min_pulse_width_[RiseFall::index_count];
RiseFall *pulse_clk_trigger_;
RiseFall *pulse_clk_sense_;
const char *related_ground_pin_;
const char *related_power_pin_;
const RiseFall *pulse_clk_trigger_;
const RiseFall *pulse_clk_sense_;
string related_ground_pin_;
string related_power_pin_;
Vector<LibertyPort*> corner_ports_;
ReceiverModelPtr receiver_model_;
DriverWaveform *driver_waveform_[RiseFall::index_count];
@ -958,19 +958,18 @@ protected:
class OperatingConditions : public Pvt
{
public:
explicit OperatingConditions(const char *name);
OperatingConditions(const char *name);
OperatingConditions(const char *name,
float process,
float voltage,
float temperature,
WireloadTree wire_load_tree);
virtual ~OperatingConditions();
const char *name() const { return name_; }
const char *name() const { return name_.c_str(); }
WireloadTree wireloadTree() const { return wire_load_tree_; }
void setWireloadTree(WireloadTree tree);
protected:
const char *name_;
string name_;
WireloadTree wire_load_tree_;
};
@ -978,11 +977,10 @@ class ScaleFactors
{
public:
explicit ScaleFactors(const char *name);
~ScaleFactors();
const char *name() const { return name_; }
const char *name() const { return name_.c_str(); }
float scale(ScaleFactorType type,
ScaleFactorPvt pvt,
RiseFall *rf);
const RiseFall *rf);
float scale(ScaleFactorType type,
ScaleFactorPvt pvt,
int rf_index);
@ -990,7 +988,7 @@ public:
ScaleFactorPvt pvt);
void setScale(ScaleFactorType type,
ScaleFactorPvt pvt,
RiseFall *rf,
const RiseFall *rf,
float scale);
void setScale(ScaleFactorType type,
ScaleFactorPvt pvt,
@ -998,7 +996,7 @@ public:
void print();
protected:
const char *name_;
string name_;
float scales_[scale_factor_type_count][scale_factor_pvt_count][RiseFall::index_count];
};
@ -1008,13 +1006,12 @@ public:
BusDcl(const char *name,
int from,
int to);
~BusDcl();
const char *name() const { return name_; }
const char *name() const { return name_.c_str(); }
int from() const { return from_; }
int to() const { return to_; }
protected:
const char *name_;
string name_;
int from_;
int to_;
};
@ -1024,7 +1021,7 @@ class ModeDef
{
public:
~ModeDef();
const char *name() const { return name_; }
const char *name() const { return name_.c_str(); }
ModeValueDef *defineValue(const char *value,
FuncExpr *cond,
const char *sdf_cond);
@ -1033,9 +1030,9 @@ public:
protected:
// Private to LibertyCell::makeModeDef.
explicit ModeDef(const char *name);
ModeDef(const char *name);
const char *name_;
string name_;
ModeValueMap values_;
private:
@ -1047,10 +1044,10 @@ class ModeValueDef
{
public:
~ModeValueDef();
const char *value() const { return value_; }
const char *value() const { return value_.c_str(); }
FuncExpr *cond() const { return cond_; }
FuncExpr *&condRef() { return cond_; }
const char *sdfCond() const { return sdf_cond_; }
const char *sdfCond() const { return sdf_cond_.c_str(); }
void setSdfCond(const char *sdf_cond);
protected:
@ -1059,9 +1056,9 @@ protected:
FuncExpr *cond,
const char *sdf_cond);
const char *value_;
string value_;
FuncExpr *cond_;
const char *sdf_cond_;
string sdf_cond_;
private:
friend class ModeDef;
@ -1070,13 +1067,12 @@ private:
class TableTemplate
{
public:
explicit TableTemplate(const char *name);
TableTemplate(const char *name);
TableTemplate(const char *name,
TableAxisPtr axis1,
TableAxisPtr axis2,
TableAxisPtr axis3);
~TableTemplate();
const char *name() const { return name_; }
const char *name() const { return name_.c_str(); }
void setName(const char *name);
const TableAxis *axis1() const { return axis1_.get(); }
TableAxisPtr axis1ptr() const { return axis1_; }
@ -1089,7 +1085,7 @@ public:
void setAxis3(TableAxisPtr axis);
protected:
const char *name_;
string name_;
TableAxisPtr axis1_;
TableAxisPtr axis2_;
TableAxisPtr axis3_;
@ -1137,20 +1133,19 @@ public:
deepnwell, deeppwell};
LibertyPgPort(const char *name,
LibertyCell *cell);
~LibertyPgPort();
const char *name() const { return name_; }
const char *name() const { return name_.c_str(); }
LibertyCell *cell() const { return cell_; }
PgType pgType() const { return pg_type_; }
void setPgType(PgType type);
const char *voltageName() const { return voltage_name_; }
const char *voltageName() const { return voltage_name_.c_str(); }
void setVoltageName(const char *voltage_name);
static bool equiv(const LibertyPgPort *port1,
const LibertyPgPort *port2);
private:
const char *name_;
string name_;
PgType pg_type_;
const char *voltage_name_;
string voltage_name_;
LibertyCell *cell_;
};

View File

@ -26,10 +26,14 @@
#include <array>
#include <vector>
#include <string>
#include "Iterator.hh"
namespace sta {
using std::string;
class MinMax;
class MinMaxAll;
@ -46,15 +50,15 @@ public:
static void init();
static void destroy();
// Singleton accessors.
static MinMax *min() { return &min_; }
static MinMax *max() { return &max_; }
static EarlyLate *early() { return &min_; }
static EarlyLate *late() { return &max_; }
static const MinMax *min() { return &min_; }
static const MinMax *max() { return &max_; }
static const EarlyLate *early() { return &min_; }
static const EarlyLate *late() { return &max_; }
static int minIndex() { return min_.index_; }
static int earlyIndex() { return min_.index_; }
static int maxIndex() { return max_.index_; }
static int lateIndex() { return max_.index_; }
const char *asString() const { return name_; }
const string &to_string() const { return name_; }
int index() const { return index_; }
float initValue() const { return init_value_; }
int initValueInt() const { return init_value_int_; }
@ -64,17 +68,17 @@ public:
// min/max(value1, value2)
float minMax(float value1,
float value2) const;
MinMaxAll *asMinMaxAll() const;
MinMax *opposite() const;
const MinMaxAll *asMinMaxAll() const;
const MinMax *opposite() const;
// for range support.
// for (auto min_max : MinMax::range()) {}
static const std::array<MinMax*, 2> &range() { return range_; }
static const std::array<const MinMax*, 2> &range() { return range_; }
// for (auto mm_index : MinMax::rangeIndex()) {}
static const std::array<int, 2> &rangeIndex() { return range_index_; }
// Find MinMax from name.
static MinMax *find(const char *min_max);
static const MinMax *find(const char *min_max);
// Find MinMax from index.
static MinMax *find(int index);
static const MinMax *find(int index);
static const int index_max = 1;
static const int index_count = 2;
static const int index_bit_count = 1;
@ -87,16 +91,16 @@ private:
bool (*compare)(float value1,
float value2));
const char *name_;
const string name_;
int index_;
float init_value_;
int init_value_int_;
bool (*compare_)(float value1,
float value2);
static MinMax min_;
static MinMax max_;
static const std::array<MinMax*, 2> range_;
static const MinMax min_;
static const MinMax max_;
static const std::array<const MinMax*, 2> range_;
static const std::array<int, 2> range_index_;
};
@ -105,36 +109,36 @@ class MinMaxAll
{
public:
// Singleton accessors.
static MinMaxAll *min() { return &min_; }
static MinMaxAll *early() { return &min_; }
static MinMaxAll *max() { return &max_; }
static MinMaxAll *late() { return &max_; }
static MinMaxAll *all() { return &all_; }
const char *asString() const { return name_; }
static const MinMaxAll *min() { return &min_; }
static const MinMaxAll *early() { return &min_; }
static const MinMaxAll *max() { return &max_; }
static const MinMaxAll *late() { return &max_; }
static const MinMaxAll *all() { return &all_; }
const string &to_string() const { return name_; }
int index() const { return index_; }
MinMax *asMinMax() const;
const MinMax *asMinMax() const;
bool matches(const MinMax *min_max) const;
bool matches(const MinMaxAll *min_max) const;
static MinMaxAll *find(const char *min_max);
static const MinMaxAll *find(const char *min_max);
// for (const auto min_max : min_max->range()) {}
const std::vector<MinMax*> &range() const { return range_; }
const std::vector<const MinMax*> &range() const { return range_; }
// for (const auto mm_index : min_max->rangeIndex()) {}
const std::vector<int> &rangeIndex() const { return range_index_; }
private:
MinMaxAll(const char *name,
int index,
std::vector<MinMax*> range,
std::vector<const MinMax*> range,
std::vector<int> range_index);
const char *name_;
const string name_;
int index_;
const std::vector<MinMax*> range_;
const std::vector<const MinMax*> range_;
const std::vector<int> range_index_;
static MinMaxAll min_;
static MinMaxAll max_;
static MinMaxAll all_;
static const MinMaxAll min_;
static const MinMaxAll max_;
static const MinMaxAll all_;
};
} // namespace

View File

@ -37,57 +37,96 @@ namespace sta {
class DcalcAnalysisPt;
// Abstract base class for Path API.
class Path
{
public:
Path() {}
virtual ~Path() {}
virtual const char *name(const StaState *sta) const;
virtual bool isNull() const = 0;
virtual Path *path() { return isNull() ? nullptr : this; }
virtual const Path *path() const { return isNull() ? nullptr : this; }
virtual void setRef(PathRef *ref) const = 0;
virtual void setRef(PathRef &ref) const { setRef(&ref); }
virtual Vertex *vertex(const StaState *sta) const = 0;
virtual VertexId vertexId(const StaState *sta) const = 0;
virtual Pin *pin(const StaState *sta) const;
virtual Tag *tag(const StaState *sta) const = 0;
virtual TagIndex tagIndex(const StaState *sta) const;
virtual ClkInfo *clkInfo(const StaState *sta) const;
virtual const ClockEdge *clkEdge(const StaState *sta) const;
virtual const Clock *clock(const StaState *sta) const;
virtual bool isClock(const StaState *sta) const;
virtual const RiseFall *transition(const StaState *sta) const = 0;
virtual int rfIndex(const StaState *sta) const;
virtual const MinMax *minMax(const StaState *sta) const;
virtual PathAnalysisPt *pathAnalysisPt(const StaState *sta) const = 0;
virtual PathAPIndex pathAnalysisPtIndex(const StaState *sta) const;
virtual DcalcAnalysisPt *dcalcAnalysisPt(const StaState *sta) const;
virtual Arrival arrival(const StaState *sta) const = 0;
virtual void setArrival(Arrival arrival,
const StaState *sta) = 0;
virtual void initArrival(const StaState *sta);
virtual bool arrivalIsInitValue(const StaState *sta) const;
virtual const Required &required(const StaState *sta) const = 0;
virtual void setRequired(const Required &required,
const StaState *sta) = 0;
virtual void initRequired(const StaState *sta);
virtual bool requiredIsInitValue(const StaState *sta) const;
virtual Slack slack(const StaState *sta) const;
virtual Slew slew(const StaState *sta) const;
Path();
Path(Path *path);
Path(Vertex *vertex,
Tag *tag,
const StaState *sta);
Path(Vertex *vertex,
Tag *tag,
Arrival arrival,
Path *prev_path,
Edge *prev_edge,
TimingArc *prev_arc,
const StaState *sta);
Path(Vertex *vertex,
Tag *tag,
Arrival arrival,
Path *prev_path,
Edge *prev_edge,
TimingArc *prev_arc,
bool is_enum,
const StaState *sta);
~Path();
string to_string(const StaState *sta) const;
bool isNull() const;
// prev_path null
void init(Vertex *vertex,
Arrival arrival,
const StaState *sta);
void init(Vertex *vertex,
Tag *tag,
Arrival arrival,
Path *prev_path,
Edge *prev_edge,
TimingArc *prev_arc,
const StaState *sta);
void init(Vertex *vertex,
Tag *tag,
const StaState *sta);
void init(Vertex *vertex,
Tag *tag,
Arrival arrival,
const StaState *sta);
Vertex *vertex(const StaState *sta) const;
VertexId vertexId(const StaState *sta) const;
Pin *pin(const StaState *sta) const;
Tag *tag(const StaState *sta) const;
TagIndex tagIndex(const StaState *sta) const;
void setTag(Tag *tag);
size_t pathIndex(const StaState *sta) const;
ClkInfo *clkInfo(const StaState *sta) const;
const ClockEdge *clkEdge(const StaState *sta) const;
const Clock *clock(const StaState *sta) const;
bool isClock(const StaState *sta) const;
const RiseFall *transition(const StaState *sta) const;
int rfIndex(const StaState *sta) const;
const MinMax *minMax(const StaState *sta) const;
PathAnalysisPt *pathAnalysisPt(const StaState *sta) const;
PathAPIndex pathAnalysisPtIndex(const StaState *sta) const;
DcalcAnalysisPt *dcalcAnalysisPt(const StaState *sta) const;
Arrival &arrival() { return arrival_; }
const Arrival &arrival() const { return arrival_; }
void setArrival(Arrival arrival);
Required &required() { return required_; }
const Required &required() const {return required_; }
void setRequired(const Required &required);
Slack slack(const StaState *sta) const;
Slew slew(const StaState *sta) const;
// This takes the same time as prevPath and prevArc combined.
virtual void prevPath(const StaState *sta,
// Return values.
PathRef &prev_path,
TimingArc *&prev_arc) const = 0;
virtual void prevPath(const StaState *sta,
// Return values.
PathRef &prev_path) const;
virtual TimingArc *prevArc(const StaState *sta) const;
// Find the previous edge given the previous arc found above.
Edge *prevEdge(const TimingArc *prev_arc,
const StaState *sta) const;
Path *prevPath() const;
void setPrevPath(Path *prev_path);
void clearPrevPath(const StaState *sta);
TimingArc *prevArc(const StaState *sta) const;
Edge *prevEdge(const StaState *sta) const;
Vertex *prevVertex(const StaState *sta) const;
void setPrevEdgeArc(Edge *prev_edge,
TimingArc *prev_arc,
const StaState *sta);
bool isEnum() const { return is_enum_; }
void setIsEnum(bool is_enum);
void checkPrevPath(const StaState *sta) const;
void checkPrevPaths(const StaState *sta) const;
static Path *vertexPath(const Path &path,
const StaState *sta);
static Path *vertexPath(const Vertex *vertex,
Tag *tag,
const StaState *sta);
static bool less(const Path *path1,
const Path *path2,
@ -118,6 +157,18 @@ public:
static bool lessAll(const Path *path1,
const Path *path2,
const StaState *sta);
protected:
Path *prev_path_;
Arrival arrival_;
Required required_;
union {
VertexId vertex_id_;
EdgeId prev_edge_id_;
};
TagIndex tag_index_:tag_index_bit_count;
bool is_enum_:1;
unsigned prev_arc_idx_:2;
};
// Compare all path attributes (vertex, transition, tag, analysis point).
@ -132,4 +183,47 @@ protected:
const StaState *sta_;
};
// Iterator for paths on a vertex.
class VertexPathIterator : public Iterator<Path*>
{
public:
// Iterate over all vertex paths.
VertexPathIterator(Vertex *vertex,
const StaState *sta);
// Iterate over vertex paths with the same transition and
// analysis pt but different tags.
VertexPathIterator(Vertex *vertex,
const RiseFall *rf,
const PathAnalysisPt *path_ap,
const StaState *sta);
// Iterate over vertex paths with the same transition and
// analysis pt min/max but different tags.
VertexPathIterator(Vertex *vertex,
const RiseFall *rf,
const MinMax *min_max,
const StaState *sta);
VertexPathIterator(Vertex *vertex,
const RiseFall *rf,
const PathAnalysisPt *path_ap,
const MinMax *min_max,
const StaState *sta);
virtual ~VertexPathIterator();
virtual bool hasNext();
virtual Path *next();
private:
void findNext();
const Search *search_;
//bool filtered_;
const RiseFall *rf_;
const PathAnalysisPt *path_ap_;
const MinMax *min_max_;
Path *paths_;
size_t path_count_;
//size_t path_index_;
Path *next_;
PathIndexMap::Iterator path_iter_;
};
} // namespace

View File

@ -24,6 +24,8 @@
#pragma once
#include <string>
#include "Iterator.hh"
#include "MinMax.hh"
#include "SdcClass.hh"
@ -35,6 +37,8 @@ class MinMax;
class DcalcAnalysisPt;
class Corner;
using std::string;
class PathAnalysisPt
{
public:
@ -42,6 +46,7 @@ public:
PathAPIndex index,
const MinMax *path_min_max,
DcalcAnalysisPt *dcalc_ap);
string to_string() const;
Corner *corner() const { return corner_; }
PathAPIndex index() const { return index_; }
const MinMax *pathMinMax() const { return path_min_max_; }

View File

@ -30,7 +30,7 @@
#include "GraphClass.hh"
#include "SdcClass.hh"
#include "SearchClass.hh"
#include "PathRef.hh"
#include "Path.hh"
#include "StaState.hh"
namespace sta {
@ -73,10 +73,9 @@ public:
virtual PathEnd *copy() = 0;
virtual ~PathEnd();
void deletePath();
Path *path() { return &path_; }
const Path *path() const { return &path_; }
PathRef &pathRef() { return path_; }
virtual void setPath(const Path *path);
Path *path() { return path_; }
const Path *path() const { return path_; }
virtual void setPath(Path *path);
Vertex *vertex(const StaState *sta) const;
const MinMax *minMax(const StaState *sta) const;
// Synonym for minMax().
@ -118,8 +117,8 @@ public:
virtual float sourceClkOffset(const StaState *sta) const = 0;
virtual Delay sourceClkLatency(const StaState *sta) const;
virtual Delay sourceClkInsertionDelay(const StaState *sta) const;
virtual PathVertex *targetClkPath();
virtual const PathVertex *targetClkPath() const;
virtual Path *targetClkPath();
virtual const Path *targetClkPath() const;
virtual const Clock *targetClk(const StaState *sta) const;
virtual const ClockEdge *targetClkEdge(const StaState *sta) const;
const RiseFall *targetClkEndTrans(const StaState *sta) const;
@ -138,7 +137,7 @@ public:
// Target clock uncertainty + inter-clk uncertainty.
virtual float targetClkUncertainty(const StaState *sta) const;
virtual float targetClkMcpAdjustment(const StaState *sta) const;
virtual TimingRole *checkRole(const StaState *sta) const;
virtual const TimingRole *checkRole(const StaState *sta) const;
const TimingRole *checkGenericRole(const StaState *sta) const;
virtual bool pathDelayMarginIsExternal() const;
virtual PathDelay *pathDelay() const;
@ -149,7 +148,7 @@ public:
virtual MultiCyclePath *multiCyclePath() const;
virtual TimingArc *checkArc() const { return nullptr; }
// PathEndDataCheck data clock path.
virtual const PathVertex *dataClkPath() const { return nullptr; }
virtual const Path *dataClkPath() const { return nullptr; }
virtual int setupDefaultCycles() const { return 1; }
virtual Delay clkSkew(const StaState *sta);
virtual bool ignoreClkLatency(const StaState * /* sta */) const { return false; }
@ -173,11 +172,11 @@ public:
// Helper common to multiple PathEnd classes and used
// externally.
// Target clock insertion delay + latency.
static Delay checkTgtClkDelay(const PathVertex *tgt_clk_path,
static Delay checkTgtClkDelay(const Path *tgt_clk_path,
const ClockEdge *tgt_clk_edge,
const TimingRole *check_role,
const StaState *sta);
static void checkTgtClkDelay(const PathVertex *tgt_clk_path,
static void checkTgtClkDelay(const Path *tgt_clk_path,
const ClockEdge *tgt_clk_edge,
const TimingRole *check_role,
const StaState *sta,
@ -186,11 +185,11 @@ public:
Delay &latency);
static float checkClkUncertainty(const ClockEdge *src_clk_edge,
const ClockEdge *tgt_clk_edge,
const PathVertex *tgt_clk_path,
const Path *tgt_clk_path,
const TimingRole *check_role,
const StaState *sta);
// Non inter-clock uncertainty.
static float checkTgtClkUncertainty(const PathVertex *tgt_clk_path,
static float checkTgtClkUncertainty(const Path *tgt_clk_path,
const ClockEdge *tgt_clk_edge,
const TimingRole *check_role,
const StaState *sta);
@ -211,14 +210,14 @@ protected:
static float outputDelayMargin(OutputDelay *output_delay,
const Path *path,
const StaState *sta);
static float pathDelaySrcClkOffset(const PathRef &path,
static float pathDelaySrcClkOffset(const Path *path,
PathDelay *path_delay,
Arrival src_clk_arrival,
const StaState *sta);
static bool ignoreClkLatency(const PathRef &path,
static bool ignoreClkLatency(const Path *path,
PathDelay *path_delay,
const StaState *sta);
PathRef path_;
Path *path_;
};
class PathEndUnconstrained : public PathEnd
@ -247,8 +246,8 @@ public:
virtual Delay sourceClkInsertionDelay(const StaState *sta) const;
virtual const Clock *targetClk(const StaState *sta) const;
virtual const ClockEdge *targetClkEdge(const StaState *sta) const;
virtual PathVertex *targetClkPath();
virtual const PathVertex *targetClkPath() const;
virtual Path *targetClkPath();
virtual const Path *targetClkPath() const;
virtual float targetClkTime(const StaState *sta) const;
virtual float targetClkOffset(const StaState *sta) const;
virtual Arrival targetClkArrival(const StaState *sta) const;
@ -263,13 +262,13 @@ public:
virtual Slack slackNoCrpr(const StaState *sta) const;
virtual int exceptPathCmp(const PathEnd *path_end,
const StaState *sta) const;
virtual void setPath(const Path *path);
virtual void setPath(Path *path);
protected:
PathEndClkConstrained(Path *path,
PathVertex *clk_path);
Path *clk_path);
PathEndClkConstrained(Path *path,
PathVertex *clk_path,
Path *clk_path,
Crpr crpr,
bool crpr_valid);
@ -281,7 +280,7 @@ protected:
virtual Arrival targetClkArrivalNoCrpr(const StaState *sta) const;
virtual Required requiredTimeNoCrpr(const StaState *sta) const;
PathVertex clk_path_;
Path *clk_path_;
mutable Crpr crpr_;
mutable bool crpr_valid_;
};
@ -296,10 +295,10 @@ public:
protected:
PathEndClkConstrainedMcp(Path *path,
PathVertex *clk_path,
Path *clk_path,
MultiCyclePath *mcp);
PathEndClkConstrainedMcp(Path *path,
PathVertex *clk_path,
Path *clk_path,
MultiCyclePath *mcp,
Crpr crpr,
bool crpr_valid);
@ -321,7 +320,7 @@ public:
PathEndCheck(Path *path,
TimingArc *check_arc,
Edge *check_edge,
PathVertex *clk_path,
Path *clk_path,
MultiCyclePath *mcp,
const StaState *sta);
virtual PathEnd *copy();
@ -332,7 +331,7 @@ public:
virtual bool isCheck() const { return true; }
virtual ArcDelay margin(const StaState *sta) const;
virtual float macroClkTreeDelay(const StaState *sta) const;
virtual TimingRole *checkRole(const StaState *sta) const;
virtual const TimingRole *checkRole(const StaState *sta) const;
virtual TimingArc *checkArc() const { return check_arc_; }
virtual int exceptPathCmp(const PathEnd *path_end,
const StaState *sta) const;
@ -342,7 +341,7 @@ protected:
PathEndCheck(Path *path,
TimingArc *check_arc,
Edge *check_edge,
PathVertex *clk_path,
Path *clk_path,
MultiCyclePath *mcp,
Crpr crpr,
bool crpr_valid);
@ -360,7 +359,7 @@ public:
PathEndLatchCheck(Path *path,
TimingArc *check_arc,
Edge *check_edge,
PathVertex *disable_path,
Path *disable_path,
MultiCyclePath *mcp,
PathDelay *path_delay,
const StaState *sta);
@ -371,11 +370,11 @@ public:
virtual bool isLatchCheck() const { return true; }
virtual PathDelay *pathDelay() const { return path_delay_; }
virtual PathEnd *copy();
PathVertex *latchDisable();
const PathVertex *latchDisable() const;
Path *latchDisable();
const Path *latchDisable() const;
virtual void reportShort(const ReportPath *report) const;
virtual void reportFull(const ReportPath *report) const;
virtual TimingRole *checkRole(const StaState *sta) const;
virtual const TimingRole *checkRole(const StaState *sta) const;
virtual Required requiredTime(const StaState *sta) const;
virtual Arrival borrow(const StaState *sta) const;
Arrival targetClkWidth(const StaState *sta) const;
@ -403,8 +402,8 @@ protected:
PathEndLatchCheck(Path *path,
TimingArc *check_arc,
Edge *check_edge,
PathVertex *clk_path,
PathVertex *disable,
Path *clk_path,
Path *disable,
MultiCyclePath *mcp,
PathDelay *path_delay,
Delay src_clk_arrival,
@ -412,7 +411,7 @@ protected:
bool crpr_valid);
private:
PathVertex disable_path_;
Path *disable_path_;
PathDelay *path_delay_;
// Source clk arrival for set_max_delay -ignore_clk_latency.
Arrival src_clk_arrival_;
@ -426,7 +425,7 @@ class PathEndOutputDelay : public PathEndClkConstrainedMcp
public:
PathEndOutputDelay(OutputDelay *output_delay,
Path *path,
PathVertex *clk_path,
Path *clk_path,
MultiCyclePath *mcp,
const StaState *sta);
virtual PathEnd *copy();
@ -436,7 +435,7 @@ public:
virtual void reportFull(const ReportPath *report) const;
virtual bool isOutputDelay() const { return true; }
virtual ArcDelay margin(const StaState *sta) const;
virtual TimingRole *checkRole(const StaState *sta) const;
virtual const TimingRole *checkRole(const StaState *sta) const;
virtual const ClockEdge *targetClkEdge(const StaState *sta) const;
virtual Arrival targetClkArrivalNoCrpr(const StaState *sta) const;
virtual Delay targetClkDelay(const StaState *sta) const;
@ -448,7 +447,7 @@ public:
protected:
PathEndOutputDelay(OutputDelay *output_delay,
Path *path,
PathVertex *clk_path,
Path *clk_path,
MultiCyclePath *mcp,
Crpr crpr,
bool crpr_valid);
@ -470,8 +469,8 @@ class PathEndGatedClock : public PathEndClkConstrainedMcp
{
public:
PathEndGatedClock(Path *gating_ref,
PathVertex *clk_path,
TimingRole *check_role,
Path *clk_path,
const TimingRole *check_role,
MultiCyclePath *mcp,
ArcDelay margin,
const StaState *sta);
@ -482,20 +481,20 @@ public:
virtual void reportFull(const ReportPath *report) const;
virtual bool isGatedClock() const { return true; }
virtual ArcDelay margin(const StaState *) const { return margin_; }
virtual TimingRole *checkRole(const StaState *sta) const;
virtual const TimingRole *checkRole(const StaState *sta) const;
virtual int exceptPathCmp(const PathEnd *path_end,
const StaState *sta) const;
protected:
PathEndGatedClock(Path *gating_ref,
PathVertex *clk_path,
TimingRole *check_role,
Path *clk_path,
const TimingRole *check_role,
MultiCyclePath *mcp,
ArcDelay margin,
Crpr crpr,
bool crpr_valid);
TimingRole *check_role_;
const TimingRole *check_role_;
ArcDelay margin_;
};
@ -504,7 +503,7 @@ class PathEndDataCheck : public PathEndClkConstrainedMcp
public:
PathEndDataCheck(DataCheck *check,
Path *data_path,
PathVertex *data_clk_path,
Path *data_clk_path,
MultiCyclePath *mcp,
const StaState *sta);
virtual PathEnd *copy();
@ -514,30 +513,28 @@ public:
virtual void reportFull(const ReportPath *report) const;
virtual bool isDataCheck() const { return true; }
virtual const ClockEdge *targetClkEdge(const StaState *sta) const;
virtual TimingRole *checkRole(const StaState *sta) const;
virtual const TimingRole *checkRole(const StaState *sta) const;
virtual ArcDelay margin(const StaState *sta) const;
virtual int exceptPathCmp(const PathEnd *path_end,
const StaState *sta) const;
virtual const PathVertex *dataClkPath() const { return &data_clk_path_; }
virtual const Path *dataClkPath() const { return data_clk_path_; }
protected:
PathEndDataCheck(DataCheck *check,
Path *data_path,
PathVertex *data_clk_path,
PathVertex *clk_path,
Path *data_clk_path,
Path *clk_path,
MultiCyclePath *mcp,
Crpr crpr,
bool crpr_valid);
void clkPath(PathVertex *path,
const StaState *sta,
// Return value.
PathVertex &clk_path);
Path *clkPath(Path *path,
const StaState *sta);
Arrival requiredTimeNoCrpr(const StaState *sta) const;
// setup uses zero cycle default
virtual int setupDefaultCycles() const { return 0; }
private:
PathVertex data_clk_path_;
Path *data_clk_path_;
DataCheck *check_;
};
@ -554,7 +551,7 @@ public:
// Path delay to timing check.
PathEndPathDelay(PathDelay *path_delay,
Path *path,
PathVertex *clk_path,
Path *clk_path,
TimingArc *check_arc,
Edge *check_edge,
const StaState *sta);
@ -569,7 +566,7 @@ public:
virtual void reportShort(const ReportPath *report) const;
virtual void reportFull(const ReportPath *report) const;
virtual bool isPathDelay() const { return true; }
virtual TimingRole *checkRole(const StaState *sta) const;
virtual const TimingRole *checkRole(const StaState *sta) const;
virtual bool pathDelayMarginIsExternal() const;
virtual PathDelay *pathDelay() const { return path_delay_; }
virtual ArcDelay margin(const StaState *sta) const;
@ -588,7 +585,7 @@ public:
protected:
PathEndPathDelay(PathDelay *path_delay,
Path *path,
PathVertex *clk_path,
Path *clk_path,
TimingArc *check_arc,
Edge *check_edge,
OutputDelay *output_delay,

View File

@ -27,7 +27,7 @@
#include "TimingArc.hh"
#include "GraphClass.hh"
#include "SearchClass.hh"
#include "PathRef.hh"
#include "Path.hh"
#include "StaState.hh"
namespace sta {
@ -48,33 +48,31 @@ public:
size_t size() const { return paths_.size(); }
// path(0) is the startpoint.
// path(size()-1) is the endpoint.
const PathRef *path(size_t index) const;
TimingArc *prevArc(size_t index) const;
const Path *path(size_t index) const;
// Returns the path start point.
// Register/Latch Q pin
// Input pin
const PathRef *startPath() const;
const PathRef *startPrevPath() const;
const PathRef *endPath() const;
TimingArc *startPrevArc() const;
const Path *startPath() const;
const Path *startPrevPath() const;
const Path *endPath() const;
const TimingArc *startPrevArc() const;
size_t startIndex() const;
void clkPath(PathRef &clk_path) const;
const Path *clkPath() const;
void latchPaths(// Return values.
const PathRef *&d_path,
const PathRef *&q_path,
const Path *&d_path,
const Path *&q_path,
Edge *&d_q_edge) const;
protected:
void expandGenclk(PathRef *clk_path);
void expandGenclk(const Path *clk_path);
// Convert external index that starts at the path root
// and increases to an index for paths_ (reversed).
size_t pathsIndex(size_t index) const;
// The PathRefs in paths_ are in reverse order.
// The Paths in paths_ are in reverse order.
// paths_[0] is the endpoint.
// paths_[size-1] is the beginning of the path.
PathRefSeq paths_;
TimingArcSeq prev_arcs_;
ConstPathSeq paths_;
// Index of the startpoint.
size_t start_index_;
const StaState *sta_;

View File

@ -74,12 +74,12 @@ public:
PathGroupIterator *iterator();
// This does NOT delete the path ends.
void clear();
static int group_path_count_max;
static size_t group_path_count_max;
protected:
PathGroup(const char *name,
int group_path_count,
int endpoint_path_count,
size_t group_path_count,
size_t endpoint_path_count,
bool unique_pins,
float min_slack,
float max_slack,
@ -91,8 +91,8 @@ protected:
void sort();
const char *name_;
int group_path_count_;
int endpoint_path_count_;
size_t group_path_count_;
size_t endpoint_path_count_;
bool unique_pins_;
float slack_min_;
float slack_max_;

View File

@ -1,75 +0,0 @@
// OpenSTA, Static Timing Analyzer
// Copyright (c) 2025, Parallax Software, Inc.
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <https://www.gnu.org/licenses/>.
//
// The origin of this software must not be misrepresented; you must not
// claim that you wrote the original software.
//
// Altered source versions must be plainly marked as such, and must not be
// misrepresented as being the original software.
//
// This notice may not be removed or altered from any source distribution.
#pragma once
#include "SdcClass.hh"
#include "SearchClass.hh"
namespace sta {
// "Pointer" to a previous path on a vertex (PathVertex) thru an edge/arc.
class PathPrev
{
public:
PathPrev();
PathPrev(const PathVertex *path,
const Edge *prev_edge,
const TimingArc *prev_arc,
const StaState *sta);
void init();
void init(const PathPrev *path);
void init(const PathPrev &path);
void init(const PathVertex *path,
const Edge *prev_edge,
const TimingArc *prev_arc,
const StaState *sta);
bool isNull() const;
const char *name(const StaState *sta) const;
Vertex *vertex(const StaState *sta) const;
VertexId vertexId(const StaState *sta) const;
Edge *prevEdge(const StaState *sta) const;
TimingArc *prevArc(const StaState *sta) const;
Tag *tag(const StaState *sta) const;
TagIndex tagIndex() const { return prev_tag_index_; }
Arrival arrival(const StaState *sta) const;
void prevPath(const StaState *sta,
// Return values.
PathRef &prev_path,
TimingArc *&prev_arc) const;
static bool equal(const PathPrev *path1,
const PathPrev *path2);
static bool equal(const PathPrev &path1,
const PathPrev &path2);
static int cmp(const PathPrev &path1,
const PathPrev &path2);
protected:
EdgeId prev_edge_id_;
TagIndex prev_tag_index_:tag_index_bit_count;
unsigned prev_arc_idx_:2;
};
} // namespace

View File

@ -1,94 +0,0 @@
// OpenSTA, Static Timing Analyzer
// Copyright (c) 2025, Parallax Software, Inc.
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <https://www.gnu.org/licenses/>.
//
// The origin of this software must not be misrepresented; you must not
// claim that you wrote the original software.
//
// Altered source versions must be plainly marked as such, and must not be
// misrepresented as being the original software.
//
// This notice may not be removed or altered from any source distribution.
#pragma once
#include "Vector.hh"
#include "SearchClass.hh"
#include "Path.hh"
#include "PathVertex.hh"
namespace sta {
// Path reference to either a PathVertex or PathEnum.
// This "could" be made smaller by using a union for
// path_vertex_.vertex_ and path_enumed_ and a non-legal
// value for path_vertex_.arrival_index_ (because a nullptr tag
// in PathVertex is valid).
class PathRef : public Path
{
public:
PathRef();
PathRef(const Path *path);
PathRef(const PathRef &path);
PathRef(const PathRef *path);
PathRef(const PathVertex &path);
void init();
void init(const PathRef &path);
void init(const PathRef *path);
void init(const PathVertex &path);
void init(const PathVertex *path);
void init(const PathPrev &path,
const StaState *sta);
void init(Vertex *vertex,
Tag *tag,
int arrival_index);
void init(PathEnumed *path);
virtual void setRef(PathRef *ref) const;
virtual bool isNull() const;
virtual Vertex *vertex(const StaState *sta) const;
virtual VertexId vertexId(const StaState *sta) const;
virtual Tag *tag(const StaState *sta) const;
virtual TagIndex tagIndex(const StaState *sta) const;
virtual const RiseFall *transition(const StaState *sta) const;
virtual int rfIndex(const StaState *sta) const;
virtual PathAnalysisPt *pathAnalysisPt(const StaState *sta) const;
virtual PathAPIndex pathAnalysisPtIndex(const StaState *sta) const;
void arrivalIndex(int &arrival_index,
bool &arrival_exists) const;
virtual Arrival arrival(const StaState *sta) const;
virtual void setArrival(Arrival arrival,
const StaState *sta);
virtual const Required &required(const StaState *sta) const;
virtual void setRequired(const Required &required,
const StaState *sta);
virtual void prevPath(const StaState *sta,
// Return values.
PathRef &prev_path,
TimingArc *&prev_arc) const;
void deleteRep();
using Path::setRef;
using Path::prevPath;
protected:
PathVertex path_vertex_;
PathEnumed *path_enumed_;
private:
friend class PathVertex;
friend class PathEnumed;
};
} // namespace

View File

@ -1,158 +0,0 @@
// OpenSTA, Static Timing Analyzer
// Copyright (c) 2025, Parallax Software, Inc.
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <https://www.gnu.org/licenses/>.
//
// The origin of this software must not be misrepresented; you must not
// claim that you wrote the original software.
//
// Altered source versions must be plainly marked as such, and must not be
// misrepresented as being the original software.
//
// This notice may not be removed or altered from any source distribution.
#pragma once
#include "SearchClass.hh"
#include "Path.hh"
namespace sta {
class PathPrev;
class PathVertexPtr;
// Implements Path API for a vertex.
class PathVertex : public Path
{
public:
PathVertex();
PathVertex(const PathVertex &path);
PathVertex(const PathVertex *path);
PathVertex(const PathPrev *path,
const StaState *sta);
PathVertex(const PathPrev &path,
const StaState *sta);
PathVertex(const PathVertexPtr &path,
const StaState *sta);
// If tag is not in the vertex tag group isNull() is true.
PathVertex(Vertex *vertex,
Tag *tag,
const StaState *sta);
PathVertex(Vertex *vertex,
Tag *tag,
int arrival_index);
void init();
void init(const PathPrev *path,
const StaState *sta);
void init(const PathPrev &path,
const StaState *sta);
void init(const PathVertexPtr &path,
const StaState *sta);
void init(Vertex *vertex,
Tag *tag,
const StaState *sta);
void init(Vertex *vertex,
Tag *tag,
int arrival_index);
void operator=(const PathVertex &path);
virtual bool isNull() const;
virtual void setRef(PathRef *ref) const;
virtual Vertex *vertex(const StaState *) const { return vertex_; }
virtual VertexId vertexId(const StaState *sta) const;
virtual Tag *tag(const StaState *) const { return tag_; }
virtual TagIndex tagIndex(const StaState *sta) const;
virtual const RiseFall *transition(const StaState *) const;
virtual int rfIndex(const StaState *sta) const;
virtual PathAnalysisPt *pathAnalysisPt(const StaState *sta) const;
virtual PathAPIndex pathAnalysisPtIndex(const StaState *sta) const;
void arrivalIndex(int &arrival_index,
bool &arrival_exists) const;
void setArrivalIndex(int arrival_index);
virtual Arrival arrival(const StaState *sta) const;
virtual void setArrival(Arrival arrival,
const StaState *sta);
virtual const Required &required(const StaState *sta) const;
virtual void setRequired(const Required &required,
const StaState *sta);
virtual void prevPath(const StaState *sta,
// Return values.
PathRef &prev_path,
TimingArc *&prev_arc) const;
void prevPath(const StaState *sta,
// Return values.
PathVertex &prev_path) const;
void prevPath(const StaState *sta,
// Return values.
PathVertex &prev_path,
TimingArc *&prev_arc) const;
static bool equal(const PathVertex *path1,
const PathVertex *path2);
using Path::setRef;
using Path::prevPath;
protected:
Vertex *vertex_;
Tag *tag_;
int arrival_index_;
private:
friend class PathRef;
friend class VertexPathIterator;
friend bool pathVertexEqual(const PathVertex *path1,
const PathVertex *path2);
};
// Iterator for vertex paths.
class VertexPathIterator : public Iterator<PathVertex*>
{
public:
// Iterate over all vertex paths.
VertexPathIterator(Vertex *vertex,
const StaState *sta);
// Iterate over vertex paths with the same transition and
// analysis pt but different tags.
VertexPathIterator(Vertex *vertex,
const RiseFall *rf,
const PathAnalysisPt *path_ap,
const StaState *sta);
// Iterate over vertex paths with the same transition and
// analysis pt min/max but different tags.
VertexPathIterator(Vertex *vertex,
const RiseFall *rf,
const MinMax *min_max,
const StaState *sta);
VertexPathIterator(Vertex *vertex,
const RiseFall *rf,
const PathAnalysisPt *path_ap,
const MinMax *min_max,
const StaState *sta);
virtual ~VertexPathIterator();
virtual bool hasNext();
virtual PathVertex *next();
private:
void findNext();
const Search *search_;
Vertex *vertex_;
const RiseFall *rf_;
const PathAnalysisPt *path_ap_;
const MinMax *min_max_;
ArrivalMap::Iterator arrival_iter_;
PathVertex path_;
PathVertex next_;
};
} // namespace

View File

@ -1,63 +0,0 @@
// OpenSTA, Static Timing Analyzer
// Copyright (c) 2025, Parallax Software, Inc.
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <https://www.gnu.org/licenses/>.
//
// The origin of this software must not be misrepresented; you must not
// claim that you wrote the original software.
//
// Altered source versions must be plainly marked as such, and must not be
// misrepresented as being the original software.
//
// This notice may not be removed or altered from any source distribution.
#pragma once
#include "SearchClass.hh"
namespace sta {
// "Pointer" to a vertex path because there is no real path object to point to.
class PathVertexPtr
{
public:
PathVertexPtr();
PathVertexPtr(const PathVertex *path,
const StaState *sta);
void init();
void init(const PathVertexPtr *path);
void init(const PathVertexPtr &path);
void init(const PathVertex *path,
const StaState *sta);
bool isNull() const;
const char *name(const StaState *sta) const;
Vertex *vertex(const StaState *sta) const;
VertexId vertexId() const { return vertex_id_; }
Tag *tag(const StaState *sta) const;
TagIndex tagIndex() const { return tag_index_; }
Arrival arrival(const StaState *sta) const;
static bool equal(const PathVertexPtr *path1,
const PathVertexPtr *path2);
static bool equal(const PathVertexPtr &path1,
const PathVertexPtr &path2);
static int cmp(const PathVertexPtr &path1,
const PathVertexPtr &path2);
protected:
VertexId vertex_id_;
TagIndex tag_index_;
};
} // namespace

View File

@ -1,75 +0,0 @@
// OpenSTA, Static Timing Analyzer
// Copyright (c) 2025, Parallax Software, Inc.
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <https://www.gnu.org/licenses/>.
//
// The origin of this software must not be misrepresented; you must not
// claim that you wrote the original software.
//
// Altered source versions must be plainly marked as such, and must not be
// misrepresented as being the original software.
//
// This notice may not be removed or altered from any source distribution.
#pragma once
#include "SdcClass.hh"
#include "SearchClass.hh"
namespace sta {
// "Pointer" to a previous path on a vertex (PathVertex) thru an edge/arc.
class PathVertexRep
{
public:
PathVertexRep();
PathVertexRep(const PathVertex *path,
const Edge *prev_edge,
const TimingArc *prev_arc,
const StaState *sta);
void init();
void init(const PathVertexRep *path);
void init(const PathVertexRep &path);
void init(const PathVertex *path,
const Edge *prev_edge,
const TimingArc *prev_arc,
const StaState *sta);
bool isNull() const;
const char *name(const StaState *sta) const;
Vertex *vertex(const StaState *sta) const;
VertexId vertexId(const StaState *sta) const;
Edge *prevEdge(const StaState *sta) const;
TimingArc *prevArc(const StaState *sta) const;
Tag *tag(const StaState *sta) const;
TagIndex tagIndex() const { return prev_tag_index_; }
Arrival arrival(const StaState *sta) const;
void prevPath(const StaState *sta,
// Return values.
PathRef &prev_path,
TimingArc *&prev_arc) const;
static bool equal(const PathVertexRep *path1,
const PathVertexRep *path2);
static bool equal(const PathVertexRep &path1,
const PathVertexRep &path2);
static int cmp(const PathVertexRep &path1,
const PathVertexRep &path2);
protected:
EdgeId prev_edge_id_;
TagIndex prev_tag_index_:tag_index_bit_count;
unsigned prev_arc_idx_:2;
};
} // namespace

View File

@ -48,7 +48,7 @@ public:
void setNetworkLatencyIncluded(bool included);
const Pin *refPin() const { return ref_pin_; }
void setRefPin(const Pin *ref_pin);
RiseFall *refTransition() const;
const RiseFall *refTransition() const;
protected:
PortDelay(const Pin *pin,

View File

@ -55,7 +55,7 @@ public:
type_library, type_cell, type_port,
type_liberty_library, type_liberty_cell, type_liberty_port,
type_instance, type_pin, type_pins, type_net,
type_clk, type_clks, type_path_refs, type_pwr_activity };
type_clk, type_clks, type_paths, type_pwr_activity };
PropertyValue();
PropertyValue(const char *value);
PropertyValue(string &value);
@ -77,7 +77,7 @@ public:
PropertyValue(const Clock *value);
PropertyValue(ClockSeq *value);
PropertyValue(ClockSet *value);
PropertyValue(PathRefSeq *value);
PropertyValue(ConstPathSeq *value);
PropertyValue(PwrActivity *value);
// Copy constructor.
PropertyValue(const PropertyValue &props);
@ -103,7 +103,7 @@ public:
const Net *net() const { return net_; }
const Clock *clock() const { return clk_; }
ClockSeq *clocks() const { return clks_; }
PathRefSeq *pathRefs() const { return path_refs_; }
ConstPathSeq *paths() const { return paths_; }
PwrActivity pwrActivity() const { return pwr_activity_; }
// Copy assignment.
@ -129,7 +129,7 @@ private:
const Net *net_;
const Clock *clk_;
ClockSeq *clks_;
PathRefSeq *path_refs_;
ConstPathSeq *paths_;
PwrActivity pwr_activity_;
};
const Unit *unit_;
@ -196,7 +196,7 @@ getProperty(PathEnd *end,
Sta *sta);
PropertyValue
getProperty(PathRef *end,
getProperty(Path *end,
const char *property,
Sta *sta);

View File

@ -1,4 +1,4 @@
// OpenSTA, Static Timing Analyzer
// opensta, Static Timing Analyzer
// Copyright (c) 2025, Parallax Software, Inc.
//
// This program is free software: you can redistribute it and/or modify
@ -39,6 +39,7 @@
#include "SearchClass.hh"
#include "SearchPred.hh"
#include "VertexVisitor.hh"
#include "Path.hh"
namespace sta {
@ -99,8 +100,8 @@ public:
bool unconstrained,
const Corner *corner,
const MinMaxAll *min_max,
int group_path_count,
int endpoint_path_count,
size_t group_path_count,
size_t endpoint_path_count,
bool unique_pins,
float slack_min,
float slack_max,
@ -126,6 +127,7 @@ public:
void requiredInvalid(const Pin *pin);
// Vertex will be deleted.
void deleteVertexBefore(Vertex *vertex);
void deleteEdgeBefore(Edge *edge);
// Find all arrival times (propatating thru latches).
void findAllArrivals();
// Find all arrivals (without latch propagation).
@ -226,7 +228,7 @@ public:
TagIndex tagCount() const;
TagGroupIndex tagGroupCount() const;
void reportTagGroups() const;
void reportArrivalCountHistogram() const;
void reportPathCountHistogram() const;
virtual int clkInfoCount() const;
virtual bool isEndpoint(Vertex *vertex) const;
virtual bool isEndpoint(Vertex *vertex,
@ -252,22 +254,28 @@ public:
const RiseFall *to_rf,
const MinMax *min_max,
const PathAnalysisPt *path_ap);
Tag *thruClkTag(PathVertex *from_path,
Tag *thruClkTag(Path *from_path,
Vertex *from_vertex,
Tag *from_tag,
bool to_propagates_clk,
Edge *edge,
const RiseFall *to_rf,
bool arc_delay_min_max_eq,
const MinMax *min_max,
const PathAnalysisPt *path_ap);
ClkInfo *thruClkInfo(PathVertex *from_path,
ClkInfo *thruClkInfo(Path *from_path,
Vertex *from_vertex,
ClkInfo *from_clk_info,
bool from_is_clk,
Edge *edge,
Vertex *to_vertex,
const Pin *to_pin,
bool to_is_clk,
bool arc_delay_min_max_eq,
const MinMax *min_max,
const PathAnalysisPt *path_ap);
ClkInfo *clkInfoWithCrprClkPath(ClkInfo *from_clk_info,
PathVertex *from_path,
Path *from_path,
const PathAnalysisPt *path_ap);
void seedClkArrivals(const Pin *pin,
Vertex *vertex,
@ -333,7 +341,7 @@ public:
float latency,
ClockUncertainties *uncertainties,
const PathAnalysisPt *path_ap,
PathVertex *crpr_clk_path);
Path *crpr_clk_path);
ClkInfo *findClkInfo(const ClockEdge *clk_edge,
const Pin *clk_src,
bool is_propagated,
@ -372,7 +380,33 @@ public:
bool unconstrained,
bool thru_latches);
VertexSeq filteredEndpoints();
bool alwaysSavePrevPaths() const { return always_save_prev_paths_; }
Arrival *arrivals(const Vertex *vertex) const;
Arrival *makeArrivals(const Vertex *vertex,
uint32_t count);
void deleteArrivals(const Vertex *vertex);
Required *requireds(const Vertex *vertex) const;
bool hasRequireds(const Vertex *vertex) const;
Required *makeRequireds(const Vertex *vertex,
uint32_t count);
void deleteRequireds(const Vertex *vertex);
size_t arrivalCount() const;
size_t requiredCount() const;
Path *prevPaths(const Vertex *vertex) const;
Path *makePrevPaths(const Vertex *vertex,
uint32_t count);
void deletePrevPaths(Vertex *vertex);
bool crprPathPruningDisabled(const Vertex *vertex) const;
void setCrprPathPruningDisabled(const Vertex *vertex,
bool disabled);
bool bfsInQueue(const Vertex *vertex,
BfsIndex index) const;
void setBfsInQueue(const Vertex *vertex,
BfsIndex index,
bool value);
TagGroupIndex tagGroupIndex(const Vertex *vertex) const;
void setTagGroupIndex(const Vertex *vertex,
TagGroupIndex tag_index);
protected:
void init(StaState *sta);
@ -538,7 +572,8 @@ protected:
void tnsNotifyBefore(Vertex *vertex);
bool matchesFilterTo(Path *path,
const ClockEdge *to_clk_edge) const;
PathRef pathClkPathArrival1(const Path *path) const;
const Path *pathClkPathArrival1(const Path *path) const;
void deletePathsState(const Vertex *vertex) const;
void clocks(const Vertex *vertex,
// Return value.
ClockSet &clks) const;
@ -613,7 +648,6 @@ protected:
std::mutex pending_latch_outputs_lock_;
VertexSet *endpoints_;
VertexSet *invalid_endpoints_;
bool always_save_prev_paths_;
// Filter exception to tag arrivals for
// report_timing -from pin|inst -through.
// -to is always nullptr.
@ -676,7 +710,7 @@ protected:
bool visitArc(const Pin *from_pin,
Vertex *from_vertex,
const RiseFall *from_rf,
PathVertex *from_path,
Path *from_path,
Edge *edge,
TimingArc *arc,
const Pin *to_pin,
@ -688,7 +722,7 @@ protected:
virtual bool visitFromPath(const Pin *from_pin,
Vertex *from_vertex,
const RiseFall *from_rf,
PathVertex *from_path,
Path *from_path,
Edge *edge,
TimingArc *arc,
const Pin *to_pin,
@ -701,7 +735,7 @@ protected:
Vertex *from_vertex,
const RiseFall *from_rf,
Tag *from_tag,
PathVertex *from_path,
Path *from_path,
const Arrival &from_arrival,
Edge *edge,
TimingArc *arc,
@ -734,7 +768,7 @@ public:
Vertex *from_vertex,
const RiseFall *from_rf,
Tag *from_tag,
PathVertex *from_path,
Path *from_path,
const Arrival &from_arrival,
Edge *edge,
TimingArc *arc,
@ -775,14 +809,14 @@ public:
RequiredCmp();
void requiredsInit(Vertex *vertex,
const StaState *sta);
void requiredSet(int arrival_index,
Required required,
void requiredSet(size_t path_index,
Required &required,
const MinMax *min_max,
const StaState *sta);
// Return true if the requireds changed.
bool requiredsSave(Vertex *vertex,
const StaState *sta);
Required required(int arrival_index);
Required required(size_t path_index);
protected:
ArrivalSeq requireds_;
@ -805,7 +839,7 @@ protected:
Vertex *from_vertex,
const RiseFall *from_rf,
Tag *from_tag,
PathVertex *from_path,
Path *from_path,
const Arrival &from_arrival,
Edge *edge,
TimingArc *arc,

View File

@ -41,12 +41,6 @@ namespace sta {
class Search;
class Corner;
class Path;
class PathRep;
class PathVertex;
class PathPrev;
class PathVertexPtr;
class PathRef;
class PathEnumed;
class PathEnd;
class PathGroup;
class Tag;
@ -120,12 +114,12 @@ typedef Vector<MaxSkewCheck*> MaxSkewCheckSeq;
typedef StringSet PathGroupNameSet;
typedef Vector<PathEnd*> PathEndSeq;
typedef Vector<Arrival> ArrivalSeq;
typedef Map<Vertex*, int> VertexPathCountMap;
typedef UnorderedMap<Tag*, int, TagMatchHash, TagMatchEqual> ArrivalMap;
typedef Vector<PathVertex> PathVertexSeq;
typedef Map<Vertex*, size_t> VertexPathCountMap;
typedef UnorderedMap<Tag*, size_t, TagMatchHash, TagMatchEqual> PathIndexMap;
typedef Vector<Slack> SlackSeq;
typedef Delay Crpr;
typedef Vector<PathRef> PathRefSeq;
typedef Vector<Path*> PathSeq;
typedef vector<const Path*> ConstPathSeq;
enum class ReportPathFormat { full,
full_clock,

View File

@ -1000,21 +1000,21 @@ public:
VertexPathIterator *vertexPathIterator(Vertex *vertex,
const RiseFall *rf,
const MinMax *min_max);
PathRef vertexWorstArrivalPath(Vertex *vertex,
const RiseFall *rf,
const MinMax *min_max);
PathRef vertexWorstArrivalPath(Vertex *vertex,
const MinMax *min_max);
PathRef vertexWorstRequiredPath(Vertex *vertex,
const RiseFall *rf,
const MinMax *min_max);
PathRef vertexWorstRequiredPath(Vertex *vertex,
const MinMax *min_max);
PathRef vertexWorstSlackPath(Vertex *vertex,
const MinMax *min_max);
PathRef vertexWorstSlackPath(Vertex *vertex,
Path *vertexWorstArrivalPath(Vertex *vertex,
const RiseFall *rf,
const MinMax *min_max);
Path *vertexWorstArrivalPath(Vertex *vertex,
const MinMax *min_max);
Path *vertexWorstRequiredPath(Vertex *vertex,
const RiseFall *rf,
const MinMax *min_max);
Path *vertexWorstRequiredPath(Vertex *vertex,
const MinMax *min_max);
Path *vertexWorstSlackPath(Vertex *vertex,
const MinMax *min_max);
Path *vertexWorstSlackPath(Vertex *vertex,
const RiseFall *rf,
const MinMax *min_max);
// Find the min clock period for rise/rise and fall/fall paths of a clock
// using the slack. This does NOT correctly predict min period when there
@ -1112,10 +1112,9 @@ public:
TagIndex tagCount() const;
TagGroupIndex tagGroupCount() const;
int clkInfoCount() const;
int arrivalCount() const;
int requiredCount() const;
int vertexArrivalCount(Vertex *vertex) const;
Vertex *maxArrivalCountVertex() const;
int pathCount() const;
int vertexPathCount(Vertex *vertex) const;
Vertex *maxPathCountVertex() const;
LogicValue simLogicValue(const Pin *pin);
// Propagate liberty constant functions and pins tied high/low through
@ -1314,7 +1313,7 @@ public:
LibertyLibrarySeq *map_libs);
LibertyCellSeq *equivCells(LibertyCell *cell);
void writePathSpice(PathRef *path,
void writePathSpice(Path *path,
const char *spice_filename,
const char *subckt_filename,
const char *lib_subckt_filename,

View File

@ -190,6 +190,8 @@ stringPrintTmp(const char *fmt,
char *
makeTmpString(size_t length);
char *
makeTmpString(string &str);
bool
isTmpString(const char *str);

View File

@ -483,7 +483,7 @@ public:
~ReceiverModel();
void setCapacitanceModel(TableModel *table_model,
size_t segment,
RiseFall *rf);
const RiseFall *rf);
static bool checkAxes(TablePtr table);
private:
@ -576,14 +576,13 @@ private:
class DriverWaveform
{
public:
DriverWaveform(const char *name,
DriverWaveform(const string &name,
TablePtr waveforms);
~DriverWaveform();
const char *name() const { return name_; }
const char *name() const { return name_.c_str(); }
Table1 waveform(float slew);
private:
const char *name_;
string name_;
TablePtr waveforms_;
};

View File

@ -83,7 +83,7 @@ enum class TimingType {
};
const char *
timingTypeString(TimingType type);
to_string(TimingType type);
TimingType
findTimingType(const char *string);
bool
@ -146,7 +146,7 @@ public:
LibertyPort *from,
LibertyPort *to,
LibertyPort *related_out,
TimingRole *role,
const TimingRole *role,
TimingArcAttrsPtr attrs);
virtual ~TimingArcSet();
LibertyCell *libertyCell() const;
@ -154,7 +154,7 @@ public:
LibertyPort *to() const { return to_; }
bool isWire() const;
LibertyPort *relatedOut() const { return related_out_; }
TimingRole *role() const { return role_; };
const TimingRole *role() const { return role_; };
TimingSense sense() const;
// Rise/fall if the arc set is rising_edge or falling_edge.
const RiseFall *isRisingFallingEdge() const;
@ -170,7 +170,7 @@ public:
TimingArcIndex addTimingArc(TimingArc *arc);
void deleteTimingArc(TimingArc *arc);
TimingArc *findTimingArc(unsigned arc_index);
void setRole(TimingRole *role);
void setRole(const TimingRole *role);
FuncExpr *cond() const { return attrs_->cond(); }
// Cond default is the timing arcs with no condition when there are
// other conditional timing arcs between the same pins.
@ -205,13 +205,13 @@ public:
static int wireArcCount() { return 2; }
protected:
TimingArcSet(TimingRole *role,
TimingArcSet(const TimingRole *role,
TimingArcAttrsPtr attrs);
LibertyPort *from_;
LibertyPort *to_;
LibertyPort *related_out_;
TimingRole *role_;
const TimingRole *role_;
// TimingArcAttrs are shared by TimingArcSets in a bus with timing groups.
TimingArcAttrsPtr attrs_;
TimingArcSeq arcs_;
@ -232,15 +232,15 @@ class TimingArc
{
public:
TimingArc(TimingArcSet *set,
Transition *from_rf,
Transition *to_rf,
const Transition *from_rf,
const Transition *to_rf,
TimingModel *model);
~TimingArc();
LibertyPort *from() const { return set_->from(); }
LibertyPort *to() const { return set_->to(); }
Transition *fromEdge() const { return from_rf_; }
Transition *toEdge() const { return to_rf_; }
TimingRole *role() const { return set_->role(); }
const Transition *fromEdge() const { return from_rf_; }
const Transition *toEdge() const { return to_rf_; }
const TimingRole *role() const { return set_->role(); }
TimingArcSet *set() const { return set_; }
TimingSense sense() const;
// Index in TimingArcSet.
@ -266,8 +266,8 @@ protected:
TimingModel *scaled_model);
TimingArcSet *set_;
Transition *from_rf_;
Transition *to_rf_;
const Transition *from_rf_;
const Transition *to_rf_;
unsigned index_;
TimingModel *model_;
ScaledTimingModelMap *scaled_models_;

View File

@ -24,52 +24,51 @@
#pragma once
#include <map>
#include "MinMax.hh"
#include "Map.hh"
#include "StringUtil.hh"
namespace sta {
class TimingRole;
typedef Map<const char*, TimingRole*, CharPtrLess> TimingRoleMap;
typedef std::map<string, const TimingRole*> TimingRoleMap;
class TimingRole
{
public:
static void init();
static void destroy();
static TimingRole *find(const char *name);
static const TimingRole *find(const char *name);
// Singleton accessors.
static TimingRole *wire() { return wire_; }
static TimingRole *combinational() { return combinational_; }
static TimingRole *tristateEnable() { return tristate_enable_; }
static TimingRole *tristateDisable() { return tristate_disable_; }
static TimingRole *regClkToQ() { return reg_clk_q_; }
static TimingRole *regSetClr() { return reg_set_clr_; }
static TimingRole *latchEnToQ() { return latch_en_q_; }
static TimingRole *latchDtoQ() { return latch_d_q_; }
static TimingRole *setup() { return setup_; }
static TimingRole *hold() { return hold_; }
static TimingRole *recovery() { return recovery_; }
static TimingRole *removal() { return removal_; }
static TimingRole *width() { return width_; }
static TimingRole *period() { return period_; }
static TimingRole *skew() { return skew_; }
static TimingRole *nochange() { return nochange_; }
static TimingRole *outputSetup() { return output_setup_; }
static TimingRole *outputHold() { return output_hold_; }
static TimingRole *gatedClockSetup() { return gated_clk_setup_; }
static TimingRole *gatedClockHold() { return gated_clk_hold_; }
static TimingRole *latchSetup() { return latch_setup_; }
static TimingRole *latchHold() { return latch_hold_; }
static TimingRole *dataCheckSetup() { return data_check_setup_; }
static TimingRole *dataCheckHold() { return data_check_hold_; }
static TimingRole *nonSeqSetup() { return non_seq_setup_; }
static TimingRole *nonSeqHold() { return non_seq_hold_; }
static TimingRole *clockTreePathMin() { return clock_tree_path_min_; }
static TimingRole *clockTreePathMax() { return clock_tree_path_max_; }
const char *asString() const { return name_; }
static const TimingRole *wire() { return &wire_; }
static const TimingRole *combinational() { return &combinational_; }
static const TimingRole *tristateEnable() { return &tristate_enable_; }
static const TimingRole *tristateDisable() { return &tristate_disable_; }
static const TimingRole *regClkToQ() { return &reg_clk_q_; }
static const TimingRole *regSetClr() { return &reg_set_clr_; }
static const TimingRole *latchEnToQ() { return &latch_en_q_; }
static const TimingRole *latchDtoQ() { return &latch_d_q_; }
static const TimingRole *setup() { return &setup_; }
static const TimingRole *hold() { return &hold_; }
static const TimingRole *recovery() { return &recovery_; }
static const TimingRole *removal() { return &removal_; }
static const TimingRole *width() { return &width_; }
static const TimingRole *period() { return &period_; }
static const TimingRole *skew() { return &skew_; }
static const TimingRole *nochange() { return &nochange_; }
static const TimingRole *outputSetup() { return &output_setup_; }
static const TimingRole *outputHold() { return &output_hold_; }
static const TimingRole *gatedClockSetup() { return &gated_clk_setup_; }
static const TimingRole *gatedClockHold() { return &gated_clk_hold_; }
static const TimingRole *latchSetup() { return &latch_setup_; }
static const TimingRole *latchHold() { return &latch_hold_; }
static const TimingRole *dataCheckSetup() { return &data_check_setup_; }
static const TimingRole *dataCheckHold() { return &data_check_hold_; }
static const TimingRole *nonSeqSetup() { return &non_seq_setup_; }
static const TimingRole *nonSeqHold() { return &non_seq_hold_; }
static const TimingRole *clockTreePathMin() { return &clock_tree_path_min_; }
static const TimingRole *clockTreePathMax() { return &clock_tree_path_max_; }
const string &to_string() const { return name_; }
int index() const { return index_; }
bool isWire() const;
bool isTimingCheck() const { return is_timing_check_; }
@ -82,12 +81,12 @@ public:
const TimingRole *genericRole() const;
const TimingRole *sdfRole() const;
// Timing check data path min/max.
MinMax *pathMinMax() const { return path_min_max_; }
const MinMax *pathMinMax() const { return path_min_max_; }
// Timing check target clock path insertion delay early/late.
const EarlyLate *tgtClkEarlyLate() const;
// Pseudo role to match sdf IOPATH.
static TimingRole *sdfIopath() { return sdf_iopath_; }
static const TimingRole *sdfIopath() { return &sdf_iopath_; }
static bool less(const TimingRole *role1,
const TimingRole *role2);
static const int index_max = 26;
@ -97,48 +96,48 @@ private:
bool is_sdf_iopath,
bool is_timing_check,
bool is_non_seq_check,
MinMax *path_min_max,
const MinMax *path_min_max,
// generic_type = nullptr means type is the same as this.
TimingRole *generic_role,
const TimingRole *generic_role,
int index);
const char *name_;
const string name_;
bool is_timing_check_;
bool is_sdf_iopath_;
bool is_non_seq_check_;
TimingRole *generic_role_;
const TimingRole *generic_role_;
unsigned index_;
MinMax *path_min_max_;
const MinMax *path_min_max_;
static TimingRole *wire_;
static TimingRole *combinational_;
static TimingRole *tristate_enable_;
static TimingRole *tristate_disable_;
static TimingRole *reg_clk_q_;
static TimingRole *reg_set_clr_;
static TimingRole *latch_en_q_;
static TimingRole *latch_d_q_;
static TimingRole *setup_;
static TimingRole *hold_;
static TimingRole *recovery_;
static TimingRole *removal_;
static TimingRole *width_;
static TimingRole *period_;
static TimingRole *skew_;
static TimingRole *nochange_;
static TimingRole *sdf_iopath_;
static TimingRole *output_setup_;
static TimingRole *output_hold_;
static TimingRole *gated_clk_setup_;
static TimingRole *gated_clk_hold_;
static TimingRole *latch_setup_;
static TimingRole *latch_hold_;
static TimingRole *data_check_setup_;
static TimingRole *data_check_hold_;
static TimingRole *non_seq_setup_;
static TimingRole *non_seq_hold_;
static TimingRole *clock_tree_path_min_;
static TimingRole *clock_tree_path_max_;
static const TimingRole wire_;
static const TimingRole combinational_;
static const TimingRole tristate_enable_;
static const TimingRole tristate_disable_;
static const TimingRole reg_clk_q_;
static const TimingRole reg_set_clr_;
static const TimingRole latch_en_q_;
static const TimingRole latch_d_q_;
static const TimingRole setup_;
static const TimingRole hold_;
static const TimingRole recovery_;
static const TimingRole removal_;
static const TimingRole width_;
static const TimingRole period_;
static const TimingRole skew_;
static const TimingRole nochange_;
static const TimingRole sdf_iopath_;
static const TimingRole output_setup_;
static const TimingRole output_hold_;
static const TimingRole gated_clk_setup_;
static const TimingRole gated_clk_hold_;
static const TimingRole latch_setup_;
static const TimingRole latch_hold_;
static const TimingRole data_check_setup_;
static const TimingRole data_check_hold_;
static const TimingRole non_seq_setup_;
static const TimingRole non_seq_hold_;
static const TimingRole clock_tree_path_min_;
static const TimingRole clock_tree_path_max_;
static TimingRoleMap timing_roles_;
friend class TimingRoleLess;

View File

@ -37,34 +37,33 @@ class Transition;
class RiseFall;
class RiseFallBoth;
typedef Map<const char*, Transition*, CharPtrLess> TransitionMap;
typedef Map<const string, const Transition*> TransitionMap;
// Rise/fall transition.
class RiseFall
{
public:
// Singleton accessors.
static RiseFall *rise() { return &rise_; }
static RiseFall *fall() { return &fall_; }
static const RiseFall *rise() { return &rise_; }
static const RiseFall *fall() { return &fall_; }
static int riseIndex() { return rise_.sdf_triple_index_; }
static int fallIndex() { return fall_.sdf_triple_index_; }
const char *asString() const { return short_name_; }
const char *name() const { return name_; }
const char *shortName() const { return short_name_; }
void setShortName(const char *short_name);
const string &to_string() const { return short_name_; }
const char *name() const { return name_.c_str(); }
const char *shortName() const { return short_name_.c_str(); }
int index() const { return sdf_triple_index_; }
RiseFallBoth *asRiseFallBoth();
const RiseFallBoth *asRiseFallBoth();
const RiseFallBoth *asRiseFallBoth() const;
Transition *asTransition() const;
// Find transition corresponding to tr_str.
static RiseFall *find(const char *tr_str);
const Transition *asTransition() const;
// Find transition corresponding to rf_str.
static const RiseFall *find(const char *rf_str);
// Find transition from index.
static RiseFall *find(int index);
RiseFall *opposite() const;
static const RiseFall *find(int index);
const RiseFall *opposite() const;
// for range support.
// for (auto rf : RiseFall::range()) {}
static const std::array<RiseFall*, 2> &range() { return range_; }
static const std::array<const RiseFall*, 2> &range() { return range_; }
// for (auto rf_index : RiseFall::rangeIndex()) {}
static const std::array<int, 2> &rangeIndex() { return range_index_; }
static const int index_count = 2;
@ -73,17 +72,16 @@ public:
protected:
RiseFall(const char *name,
const char *short_name,
int sdf_triple_index);
~RiseFall();
const char *short_name,
int sdf_triple_index);
const char *name_;
const char *short_name_;
const string name_;
const string short_name_;
const int sdf_triple_index_;
static RiseFall rise_;
static RiseFall fall_;
static const std::array<RiseFall*, 2> range_;
static const RiseFall rise_;
static const RiseFall fall_;
static const std::array<const RiseFall*, 2> range_;
static const std::array<int, 2> range_index_;
};
@ -92,21 +90,20 @@ class RiseFallBoth
{
public:
// Singleton accessors.
static RiseFallBoth *rise() { return &rise_; }
static RiseFallBoth *fall() { return &fall_; }
static RiseFallBoth *riseFall() { return &rise_fall_; }
const char *asString() const { return short_name_; }
const char *name() const { return name_; }
const char *shortName() const { return short_name_; }
void setShortName(const char *short_name);
static const RiseFallBoth *rise() { return &rise_; }
static const RiseFallBoth *fall() { return &fall_; }
static const RiseFallBoth *riseFall() { return &rise_fall_; }
const string &to_string() const { return short_name_; }
const char *name() const { return name_.c_str(); }
const char *shortName() const { return short_name_.c_str(); }
int index() const { return sdf_triple_index_; }
bool matches(const RiseFall *rf) const;
bool matches(const Transition *tr) const;
RiseFall *asRiseFall() const { return as_rise_fall_; }
const RiseFall *asRiseFall() const { return as_rise_fall_; }
// Find transition corresponding to string.
static RiseFallBoth *find(const char *tr_str);
static const RiseFallBoth *find(const char *tr_str);
// for (const auto rf : rf->range()) {}
const std::vector<RiseFall*> &range() const { return range_; }
const std::vector<const RiseFall*> &range() const { return range_; }
// for (const auto rf_index : rf->rangeIndex()) {}
const std::vector<int> &rangeIndex() const { return range_index_; }
@ -116,23 +113,22 @@ public:
protected:
RiseFallBoth(const char *name,
const char *short_name,
int sdf_triple_index,
RiseFall *as_rise_fall,
std::vector<RiseFall*> range,
std::vector<int> range_index);
~RiseFallBoth();
const char *short_name,
int sdf_triple_index,
const RiseFall *as_rise_fall,
std::vector<const RiseFall*> range,
std::vector<int> range_index);
const char *name_;
const char *short_name_;
const string name_;
const string short_name_;
const int sdf_triple_index_;
RiseFall *as_rise_fall_;
const std::vector<RiseFall*> range_;
const RiseFall *as_rise_fall_;
const std::vector<const RiseFall*> range_;
const std::vector<int> range_index_;
static RiseFallBoth rise_;
static RiseFallBoth fall_;
static RiseFallBoth rise_fall_;
static const RiseFallBoth rise_;
static const RiseFallBoth fall_;
static const RiseFallBoth rise_fall_;
};
// General SDF transition.
@ -140,58 +136,56 @@ class Transition
{
public:
// Singleton accessors.
static Transition *rise() { return &rise_; }
static Transition *fall() { return &fall_; }
static Transition *tr0Z() { return &tr_0Z_; }
static Transition *trZ1() { return &tr_Z1_; }
static Transition *tr1Z() { return &tr_1Z_; }
static Transition *trZ0() { return &tr_Z0_; }
static Transition *tr0X() { return &tr_0X_; }
static Transition *trX1() { return &tr_X1_; }
static Transition *tr1X() { return &tr_1X_; }
static Transition *trX0() { return &tr_X0_; }
static Transition *trXZ() { return &tr_XZ_; }
static Transition *trZX() { return &tr_ZX_; }
void setName(const char *name);
static const Transition *rise() { return &rise_; }
static const Transition *fall() { return &fall_; }
static const Transition *tr0Z() { return &tr_0Z_; }
static const Transition *trZ1() { return &tr_Z1_; }
static const Transition *tr1Z() { return &tr_1Z_; }
static const Transition *trZ0() { return &tr_Z0_; }
static const Transition *tr0X() { return &tr_0X_; }
static const Transition *trX1() { return &tr_X1_; }
static const Transition *tr1X() { return &tr_1X_; }
static const Transition *trX0() { return &tr_X0_; }
static const Transition *trXZ() { return &tr_XZ_; }
static const Transition *trZX() { return &tr_ZX_; }
// Matches rise and fall.
static Transition *riseFall() { return &rise_fall_; }
const char *asString() const { return name_; }
static const Transition *riseFall() { return &rise_fall_; }
const string &to_string() const { return name_; }
// As initial/final value pair.
const char *asInitFinalString() const { return init_final_; }
const char *asInitFinalString() const { return init_final_.c_str(); }
int sdfTripleIndex() const { return sdf_triple_index_; }
int index() const { return sdf_triple_index_; }
RiseFall *asRiseFall() const { return as_rise_fall_; }
const RiseFall *asRiseFall() const { return as_rise_fall_; }
const RiseFallBoth *asRiseFallBoth() const;
bool matches(const Transition *tr) const;
// Find transition corresponding to string.
static Transition *find(const char *tr_str);
static const Transition *find(const char *tr_str);
static int maxIndex() { return max_index_; }
private:
Transition(const char *name,
const char *init_final,
RiseFall *as_rise_fall,
const RiseFall *as_rise_fall,
int sdf_triple_index);
~Transition();
const char *name_;
const char *init_final_;
RiseFall *as_rise_fall_;
const string name_;
const string init_final_;
const RiseFall *as_rise_fall_;
const int sdf_triple_index_;
static Transition rise_;
static Transition fall_;
static Transition tr_0Z_;
static Transition tr_Z1_;
static Transition tr_1Z_;
static Transition tr_Z0_;
static Transition tr_0X_;
static Transition tr_X1_;
static Transition tr_1X_;
static Transition tr_X0_;
static Transition tr_XZ_;
static Transition tr_ZX_;
static Transition rise_fall_;
static const Transition rise_;
static const Transition fall_;
static const Transition tr_0Z_;
static const Transition tr_Z1_;
static const Transition tr_1Z_;
static const Transition tr_Z0_;
static const Transition tr_0X_;
static const Transition tr_X1_;
static const Transition tr_1X_;
static const Transition tr_X0_;
static const Transition tr_XZ_;
static const Transition tr_ZX_;
static const Transition rise_fall_;
static const int index_count = 13;
static const int index_max = (index_count - 1);
static const int index_bit_count = 4;

View File

@ -85,7 +85,7 @@ protected:
Path *path,
const RiseFall *end_rf,
const ClockEdge *tgt_clk_edge,
PathVertex *ref_path,
Path *ref_path,
const MinMax *min_max,
PathEndVisitor *visitor,
bool &is_constrained);
@ -118,7 +118,7 @@ protected:
const PathAnalysisPt *clk_ap,
const Pin *from_pin,
Vertex *from_vertex,
RiseFall *from_rf,
const RiseFall *from_rf,
bool filtered,
PathEndVisitor *visitor,
bool &is_constrained);

View File

@ -193,34 +193,29 @@ FuncExpr::portTimingSense(const LibertyPort *port) const
return TimingSense::unknown;
}
const char *
FuncExpr::asString() const
string
FuncExpr::to_string() const
{
return asString(false);
return to_string(false);
}
const char *
FuncExpr::asString(bool with_parens) const
string
FuncExpr::to_string(bool with_parens) const
{
switch (op_) {
case op_port:
return port_->name();
case op_not: {
const char *left = left_->asString(true);
size_t left_length = strlen(left);
size_t length = left_length + 2;
char *result = makeTmpString(length);
char *ptr = result;
*ptr++ = '!';
strcpy(ptr, left);
string result = "!";
result += left_->to_string(true);
return result;
}
case op_or:
return asStringSubexpr(with_parens, '+');
return to_string(with_parens, '+');
case op_and:
return asStringSubexpr(with_parens, '*');
return to_string(with_parens, '*');
case op_xor:
return asStringSubexpr(with_parens, '^');
return to_string(with_parens, '^');
case op_one:
return "1";
case op_zero:
@ -230,25 +225,19 @@ FuncExpr::asString(bool with_parens) const
}
}
const char *
FuncExpr::asStringSubexpr(bool with_parens,
char op) const
string
FuncExpr::to_string(bool with_parens,
char op) const
{
const char *left = left_->asString(true);
const char *right = right_->asString(true);
size_t length = strlen(left) + 1 + strlen(right) + 1;
string right = right_->to_string(true);
string result;
if (with_parens)
length += 2;
char *result = makeTmpString(length);
char *r = result;
result += '(';
result += left_->to_string(true);
result += op;
result += right_->to_string(true);
if (with_parens)
*r++= '(';
stringAppend(r, left);
*r++ = op;
stringAppend(r, right);
if (with_parens)
*r++ = ')';
*r = '\0';
result += ')';
return result;
}

View File

@ -56,13 +56,13 @@ InternalPowerAttrs::deleteContents()
}
InternalPowerModel *
InternalPowerAttrs::model(RiseFall *rf) const
InternalPowerAttrs::model(const RiseFall *rf) const
{
return models_[rf->index()];
}
void
InternalPowerAttrs::setModel(RiseFall *rf,
InternalPowerAttrs::setModel(const RiseFall *rf,
InternalPowerModel *model)
{
models_[rf->index()] = model;
@ -86,9 +86,9 @@ InternalPower::InternalPower(LibertyCell *cell,
when_(attrs->when()),
related_pg_pin_(attrs->relatedPgPin())
{
for (auto tr : RiseFall::range()) {
int tr_index = tr->index();
models_[tr_index] = attrs->model(tr);
for (auto rf : RiseFall::range()) {
int rf_index = rf->index();
models_[rf_index] = attrs->model(rf);
}
cell->addInternalPower(this);
}
@ -105,7 +105,7 @@ InternalPower::libertyCell() const
}
float
InternalPower::power(RiseFall *rf,
InternalPower::power(const RiseFall *rf,
const Pvt *pvt,
float in_slew,
float load_cap)

View File

@ -130,8 +130,6 @@ LibertyLibrary::~LibertyLibrary()
delete units_;
ocv_derate_map_.deleteContents();
for (auto [supply_name, volt] : supply_voltage_map_)
stringDelete(supply_name);
delete buffers_;
delete inverters_;
driver_waveform_map_.deleteContents();
@ -325,7 +323,7 @@ LibertyLibrary::scaleFactor(ScaleFactorType type,
void
LibertyLibrary::setWireSlewDegradationTable(TableModel *model,
RiseFall *rf)
const RiseFall *rf)
{
int rf_index = rf->index();
if (wire_slew_degradation_tbls_[rf_index])
@ -799,7 +797,7 @@ LibertyLibrary::makeCornerMap(LibertyCell *cell1,
cell1->name(),
arc_set1->from() ? arc_set1->from()->name() : "",
arc_set1->to()->name(),
arc_set1->role()->asString(),
arc_set1->role()->to_string().c_str(),
cell2->library()->name(),
cell2->name());
}
@ -817,7 +815,7 @@ LibertyLibrary::checkCorners(LibertyCell *cell,
cell->libertyLibrary()->name(),
cell->name(),
corner->name(),
min_max->asString());
min_max->to_string().c_str());
}
}
}
@ -864,7 +862,7 @@ void
LibertyLibrary::addSupplyVoltage(const char *supply_name,
float voltage)
{
supply_voltage_map_[stringCopy(supply_name)] = voltage;
supply_voltage_map_[supply_name] = voltage;
}
void
@ -948,9 +946,7 @@ LibertyCell::LibertyCell(LibertyLibrary *library,
leakage_power_(0.0),
leakage_power_exists_(false),
has_internal_ports_(false),
have_voltage_waveforms_(false),
footprint_(nullptr),
user_function_class_(nullptr)
have_voltage_waveforms_(false)
{
liberty_cell_ = this;
}
@ -978,9 +974,6 @@ LibertyCell::~LibertyCell()
ocv_derate_map_.deleteContents();
pg_port_map_.deleteContents();
stringDelete(footprint_);
stringDelete(user_function_class_);
}
LibertyPort *
@ -1248,7 +1241,7 @@ LibertyCell::addTimingArcSet(TimingArcSet *arc_set)
timing_arc_sets_.push_back(arc_set);
LibertyPort *from = arc_set->from();
TimingRole *role = arc_set->role();
const TimingRole *role = arc_set->role();
if (role == TimingRole::regClkToQ()
|| role == TimingRole::latchEnToQ())
from->setIsRegClk(true);
@ -1772,7 +1765,7 @@ LibertyCell::makeLatchEnables(Report *report,
&& en_rf != RiseFall::rise())
report->warn(1114, "cell %s/%s %s -> %s latch enable %s_edge is inconsistent with latch group enable function positive sense.",
library_->name(),
name_,
name(),
en->name(),
q->name(),
en_rf == RiseFall::rise()?"rising":"falling");
@ -1780,7 +1773,7 @@ LibertyCell::makeLatchEnables(Report *report,
&& en_rf != RiseFall::fall())
report->warn(1115, "cell %s/%s %s -> %s latch enable %s_edge is inconsistent with latch group enable function negative sense.",
library_->name(),
name_,
name(),
en->name(),
q->name(),
en_rf == RiseFall::rise()?"rising":"falling");
@ -1831,7 +1824,7 @@ LibertyCell::findLatchSetup(const LibertyPort *d,
if (from_rf == en_rf) {
report->warn(1113, "cell %s/%s %s -> %s latch enable %s_edge is inconsistent with %s -> %s setup_%s check.",
library_->name(),
name_,
name(),
en->name(),
q->name(),
en_rf == RiseFall::rise() ? "rising" : "falling",
@ -1913,7 +1906,7 @@ LibertyCell::inferLatchRoles(Report *report,
LibertyPort *q = en_to_q->to();
for (TimingArcSet *d_to_q : timingArcSets(nullptr, q)) {
// Look for combinational d->q arcs.
TimingRole *d_to_q_role = d_to_q->role();
const TimingRole *d_to_q_role = d_to_q->role();
if (((d_to_q_role == TimingRole::combinational()
&& d_to_q->arcCount() == 2
&& (d_to_q->sense() == TimingSense::positive_unate
@ -2002,28 +1995,35 @@ LibertyCell::ensureVoltageWaveforms(const DcalcAnalysisPtSeq &dcalc_aps)
}
}
const char *
LibertyCell::footprint() const
{
if (footprint_.empty())
return nullptr;
else
return footprint_.c_str();
}
void
LibertyCell::setFootprint(const char *footprint)
{
footprint_ = stringCopy(footprint);
footprint_ = footprint;
}
const char*
LibertyCell::footprint() const
const char *
LibertyCell::userFunctionClass() const
{
return footprint_;
if (user_function_class_.empty())
return nullptr;
else
return user_function_class_.c_str();
}
void
LibertyCell::setUserFunctionClass(const char *user_function_class)
{
user_function_class_ = stringCopy(user_function_class);
}
const char*
LibertyCell::userFunctionClass() const
{
return user_function_class_;
user_function_class_ = user_function_class;
}
////////////////////////////////////////////////////////////////
@ -2091,8 +2091,6 @@ LibertyPort::LibertyPort(LibertyCell *cell,
min_period_(0.0),
pulse_clk_trigger_(nullptr),
pulse_clk_sense_(nullptr),
related_ground_pin_(nullptr),
related_power_pin_(nullptr),
receiver_model_(nullptr),
driver_waveform_{nullptr, nullptr},
min_pulse_width_exists_(false),
@ -2129,8 +2127,6 @@ LibertyPort::~LibertyPort()
if (tristate_enable_)
tristate_enable_->deleteSubexprs();
delete scaled_ports_;
stringDelete(related_ground_pin_);
stringDelete(related_power_pin_);
}
void
@ -2597,8 +2593,8 @@ LibertyPort::setIsSwitch(bool is_switch)
}
void
LibertyPort::setPulseClk(RiseFall *trigger,
RiseFall *sense)
LibertyPort::setPulseClk(const RiseFall *trigger,
const RiseFall *sense)
{
pulse_clk_trigger_ = trigger;
pulse_clk_sense_ = sense;
@ -2673,16 +2669,34 @@ LibertyPort::setCornerPort(LibertyPort *corner_port,
corner_ports_[ap_index] = corner_port;
}
const char *
LibertyPort::relatedGroundPin() const
{
if (related_ground_pin_.empty())
return nullptr;
else
return related_ground_pin_.c_str();
}
void
LibertyPort::setRelatedGroundPin(const char *related_ground_pin)
{
related_ground_pin_ = stringCopy(related_ground_pin);
related_ground_pin_ = related_ground_pin;
}
const char *
LibertyPort::relatedPowerPin() const
{
if (related_power_pin_.empty())
return nullptr;
else
return related_power_pin_.c_str();
}
void
LibertyPort::setRelatedPowerPin(const char *related_power_pin)
{
related_power_pin_ = stringCopy(related_power_pin);
related_power_pin_ = related_power_pin;
}
void
@ -2846,28 +2860,22 @@ LibertyPortMemberIterator::next()
BusDcl::BusDcl(const char *name,
int from,
int to) :
name_(stringCopy(name)),
name_(name),
from_(from),
to_(to)
{
}
BusDcl::~BusDcl()
{
stringDelete(name_);
}
////////////////////////////////////////////////////////////////
ModeDef::ModeDef(const char *name) :
name_(stringCopy(name))
name_(name)
{
}
ModeDef::~ModeDef()
{
values_.deleteContents();
stringDelete(name_);
}
ModeValueDef *
@ -2891,31 +2899,28 @@ ModeDef::findValueDef(const char *value)
ModeValueDef::ModeValueDef(const char *value,
FuncExpr *cond,
const char *sdf_cond) :
value_(stringCopy(value)),
value_(value),
cond_(cond),
sdf_cond_(stringCopy(sdf_cond))
sdf_cond_(sdf_cond ? sdf_cond : "")
{
}
ModeValueDef::~ModeValueDef()
{
stringDelete(value_);
if (cond_)
cond_->deleteSubexprs();
if (sdf_cond_)
stringDelete(sdf_cond_);
}
void
ModeValueDef::setSdfCond(const char *sdf_cond)
{
sdf_cond_ = stringCopy(sdf_cond);
sdf_cond_ = sdf_cond;
}
////////////////////////////////////////////////////////////////
TableTemplate::TableTemplate(const char *name) :
name_(stringCopy(name)),
name_(name),
axis1_(nullptr),
axis2_(nullptr),
axis3_(nullptr)
@ -2926,23 +2931,17 @@ TableTemplate::TableTemplate(const char *name,
TableAxisPtr axis1,
TableAxisPtr axis2,
TableAxisPtr axis3) :
name_(stringCopy(name)),
name_(name),
axis1_(axis1),
axis2_(axis2),
axis3_(axis3)
{
}
TableTemplate::~TableTemplate()
{
stringDelete(name_);
}
void
TableTemplate::setName(const char *name)
{
stringDelete(name_);
name_ = stringCopy(name);
name_ = name;
}
void
@ -2994,7 +2993,7 @@ Pvt::setTemperature(float temp)
OperatingConditions::OperatingConditions(const char *name) :
Pvt(0.0, 0.0, 0.0),
name_(stringCopy(name)),
name_(name),
// Default wireload tree.
wire_load_tree_(WireloadTree::balanced)
{
@ -3006,16 +3005,11 @@ OperatingConditions::OperatingConditions(const char *name,
float temperature,
WireloadTree wire_load_tree) :
Pvt(process, voltage, temperature),
name_(stringCopy(name)),
name_(name),
wire_load_tree_(wire_load_tree)
{
}
OperatingConditions::~OperatingConditions()
{
stringDelete(name_);
}
void
OperatingConditions::setWireloadTree(WireloadTree tree)
{
@ -3101,7 +3095,7 @@ scaleFactorPvtName(ScaleFactorPvt pvt)
////////////////////////////////////////////////////////////////
ScaleFactors::ScaleFactors(const char *name) :
name_(stringCopy(name))
name_(name)
{
for (int type = 0; type < scale_factor_type_count; type++) {
for (int pvt = 0; pvt < scale_factor_pvt_count; pvt++) {
@ -3112,15 +3106,10 @@ ScaleFactors::ScaleFactors(const char *name) :
}
}
ScaleFactors::~ScaleFactors()
{
stringDelete(name_);
}
void
ScaleFactors::setScale(ScaleFactorType type,
ScaleFactorPvt pvt,
RiseFall *rf,
const RiseFall *rf,
float scale)
{
scales_[int(type)][int(pvt)][rf->index()] = scale;
@ -3137,7 +3126,7 @@ ScaleFactors::setScale(ScaleFactorType type,
float
ScaleFactors::scale(ScaleFactorType type,
ScaleFactorPvt pvt,
RiseFall *rf)
const RiseFall *rf)
{
return scales_[int(type)][int(pvt)][rf->index()];
}
@ -3232,19 +3221,12 @@ OcvDerate::setDerateTable(const RiseFall *rf,
LibertyPgPort::LibertyPgPort(const char *name,
LibertyCell *cell) :
name_(stringCopy(name)),
name_(name),
pg_type_(unknown),
voltage_name_(nullptr),
cell_(cell)
{
}
LibertyPgPort::~LibertyPgPort()
{
stringDelete(name_);
stringDelete(voltage_name_);
}
void
LibertyPgPort::setPgType(PgType type)
{
@ -3254,14 +3236,14 @@ LibertyPgPort::setPgType(PgType type)
void
LibertyPgPort::setVoltageName(const char *voltage_name)
{
voltage_name_ = stringCopy(voltage_name);
voltage_name_ = voltage_name;
}
bool
LibertyPgPort::equiv(const LibertyPgPort *port1,
const LibertyPgPort *port2)
{
return stringEq(port1->name_, port2->name_)
return port1->name_ == port2->name_
&& port1->pg_type_ == port2->pg_type_;
}
@ -3281,7 +3263,7 @@ LibertyCellPgPortIterator::hasNext()
LibertyPgPort *
LibertyCellPgPortIterator::next()
{
const char *name;
string name;
LibertyPgPort *port;
iter_.next(name, port);
return port;

View File

@ -206,7 +206,7 @@ find_liberty_cell(const char *name)
}
bool
timing_role_is_check(TimingRole *role)
timing_role_is_check(const TimingRole *role)
{
return role->isTimingCheck();
}
@ -313,24 +313,24 @@ bool is_bus() { return self->isBus(); }
LibertyPortMemberIterator *
member_iterator() { return new LibertyPortMemberIterator(self); }
const char *
string
function()
{
FuncExpr *func = self->function();
if (func)
return func->asString();
return func->to_string();
else
return nullptr;
return "";
}
const char *
string
tristate_enable()
{
FuncExpr *enable = self->tristateEnable();
if (enable)
return enable->asString();
return enable->to_string();
else
return nullptr;
return "";
}
float
@ -358,7 +358,7 @@ scan_signal_type()
%extend TimingArcSet {
LibertyPort *from() { return self->from(); }
LibertyPort *to() { return self->to(); }
TimingRole *role() { return self->role(); }
const TimingRole *role() { return self->role(); }
const char *sdf_cond() { return self->sdfCond(); }
const char *
@ -381,11 +381,11 @@ timing_arcs() { return self->arcs(); }
%extend TimingArc {
LibertyPort *from() { return self->from(); }
LibertyPort *to() { return self->to(); }
Transition *from_edge() { return self->fromEdge(); }
const Transition *from_edge() { return self->fromEdge(); }
const char *from_edge_name() { return self->fromEdge()->asRiseFall()->name(); }
Transition *to_edge() { return self->toEdge(); }
const Transition *to_edge() { return self->toEdge(); }
const char *to_edge_name() { return self->toEdge()->asRiseFall()->name(); }
TimingRole *role() { return self->role(); }
const TimingRole *role() { return self->role(); }
float
time_voltage(float in_slew,

View File

@ -59,8 +59,7 @@ LibertyPort *
LibertyBuilder::makePort(LibertyCell *cell,
const char *port_name)
{
string sta_name = portLibertyToSta(port_name);
LibertyPort *port = new LibertyPort(cell, sta_name.c_str(), false, nullptr,
LibertyPort *port = new LibertyPort(cell, port_name, false, nullptr,
-1, -1, false, nullptr);
cell->addPort(port);
return port;
@ -73,12 +72,11 @@ LibertyBuilder::makeBusPort(LibertyCell *cell,
int to_index,
BusDcl *bus_dcl)
{
string sta_name = portLibertyToSta(bus_name);
LibertyPort *port = new LibertyPort(cell, sta_name.c_str(), true, bus_dcl,
LibertyPort *port = new LibertyPort(cell, bus_name, true, bus_dcl,
from_index, to_index,
false, new ConcretePortSeq);
cell->addPort(port);
makeBusPortBits(cell->library(), cell, port, sta_name.c_str(), from_index, to_index);
makeBusPortBits(cell->library(), cell, port, bus_name, from_index, to_index);
return port;
}
@ -329,7 +327,7 @@ LibertyBuilder::makeCombinationalArcs(LibertyCell *cell,
}
TimingModel *model;
RiseFall *to_rf;
const RiseFall *to_rf;
switch (sense) {
case TimingSense::positive_unate:
if (to_rise) {
@ -393,18 +391,20 @@ LibertyBuilder::makeLatchDtoQArcs(LibertyCell *cell,
TimingArcSet *arc_set = makeTimingArcSet(cell, from_port, to_port,
TimingRole::latchDtoQ(), attrs);
TimingModel *model;
RiseFall *to_rf = RiseFall::rise();
const RiseFall *to_rf = RiseFall::rise();
model = attrs->model(to_rf);
if (model) {
RiseFall *from_rf = (sense == TimingSense::negative_unate) ?
to_rf->opposite() : to_rf;
const RiseFall *from_rf = (sense == TimingSense::negative_unate)
? to_rf->opposite()
: to_rf;
makeTimingArc(arc_set, from_rf, to_rf, model);
}
to_rf = RiseFall::fall();
model = attrs->model(to_rf);
if (model) {
RiseFall *from_rf = (sense == TimingSense::negative_unate) ?
to_rf->opposite() : to_rf;
const RiseFall *from_rf = (sense == TimingSense::negative_unate)
? to_rf->opposite()
: to_rf;
makeTimingArc(arc_set, from_rf, to_rf, model);
}
return arc_set;
@ -414,7 +414,7 @@ TimingArcSet *
LibertyBuilder::makeRegLatchArcs(LibertyCell *cell,
LibertyPort *from_port,
LibertyPort *to_port,
RiseFall *from_rf,
const RiseFall *from_rf,
TimingArcAttrsPtr attrs)
{
FuncExpr *to_func = to_port->function();
@ -424,7 +424,7 @@ LibertyBuilder::makeRegLatchArcs(LibertyCell *cell,
Sequential *seq = cell->outputPortSequential(func_port);
if (seq) {
if (seq->clock() && seq->clock()->hasPort(from_port)) {
TimingRole *role = seq->isRegister() ?
const TimingRole *role = seq->isRegister() ?
TimingRole::regClkToQ() : TimingRole::latchEnToQ();
return makeFromTransitionArcs(cell, from_port, to_port, nullptr,
from_rf, role, attrs);
@ -451,8 +451,8 @@ LibertyBuilder::makeFromTransitionArcs(LibertyCell *cell,
LibertyPort *from_port,
LibertyPort *to_port,
LibertyPort *related_out,
RiseFall *from_rf,
TimingRole *role,
const RiseFall *from_rf,
const TimingRole *role,
TimingArcAttrsPtr attrs)
{
TimingArcSet *arc_set = makeTimingArcSet(cell, from_port, to_port,
@ -469,7 +469,7 @@ TimingArcSet *
LibertyBuilder::makePresetClrArcs(LibertyCell *cell,
LibertyPort *from_port,
LibertyPort *to_port,
RiseFall *to_rf,
const RiseFall *to_rf,
TimingArcAttrsPtr attrs)
{
TimingArcSet *arc_set = nullptr;
@ -477,7 +477,7 @@ LibertyBuilder::makePresetClrArcs(LibertyCell *cell,
if (model) {
arc_set = makeTimingArcSet(cell, from_port, to_port,
TimingRole::regSetClr(), attrs);
RiseFall *opp_rf = to_rf->opposite();
const RiseFall *opp_rf = to_rf->opposite();
switch (attrs->timingSense()) {
case TimingSense::positive_unate:
makeTimingArc(arc_set, to_rf, to_rf, model);
@ -515,7 +515,7 @@ LibertyBuilder::makeTristateEnableArcs(LibertyCell *cell,
if (sense == TimingSense::unknown && tristate_enable)
sense = tristate_enable->portTimingSense(from_port);
TimingModel *model;
RiseFall *to_rf;
const RiseFall *to_rf;
switch (sense) {
case TimingSense::positive_unate:
if (to_rise) {
@ -586,7 +586,7 @@ LibertyBuilder::makeTristateDisableArcs(LibertyCell *cell,
if (sense == TimingSense::unknown && tristate_enable)
sense = timingSenseOpposite(tristate_enable->portTimingSense(from_port));
TimingModel *model;
RiseFall *to_rf;
const RiseFall *to_rf;
switch (sense) {
case TimingSense::positive_unate:
if (to_rise) {
@ -644,7 +644,7 @@ LibertyBuilder::makeTristateDisableArcs(LibertyCell *cell,
TimingArcSet *
LibertyBuilder::makeClockTreePathArcs(LibertyCell *cell,
LibertyPort *to_port,
TimingRole *role,
const TimingRole *role,
const MinMax *min_max,
TimingArcAttrsPtr attrs)
{
@ -653,7 +653,7 @@ LibertyBuilder::makeClockTreePathArcs(LibertyCell *cell,
TimingModel *model = attrs->model(to_rf);
if (model) {
const GateTableModel *gate_model = dynamic_cast<GateTableModel *>(model);
RiseFall *opp_rf = to_rf->opposite();
const RiseFall *opp_rf = to_rf->opposite();
switch (attrs->timingSense()) {
case TimingSense::positive_unate:
makeTimingArc(arc_set, to_rf, to_rf, model);
@ -683,7 +683,7 @@ LibertyBuilder::makeMinPulseWidthArcs(LibertyCell *cell,
LibertyPort *from_port,
LibertyPort *to_port,
LibertyPort *related_out,
TimingRole *role,
const TimingRole *role,
TimingArcAttrsPtr attrs)
{
if (from_port == nullptr)
@ -704,7 +704,7 @@ TimingArcSet *
LibertyBuilder::makeTimingArcSet(LibertyCell *cell,
LibertyPort *from,
LibertyPort *to,
TimingRole *role,
const TimingRole *role,
TimingArcAttrsPtr attrs)
{
return new TimingArcSet(cell, from, to, nullptr, role, attrs);
@ -715,7 +715,7 @@ LibertyBuilder::makeTimingArcSet(LibertyCell *cell,
LibertyPort *from,
LibertyPort *to,
LibertyPort *related_out,
TimingRole *role,
const TimingRole *role,
TimingArcAttrsPtr attrs)
{
return new TimingArcSet(cell, from, to, related_out, role, attrs);
@ -723,8 +723,8 @@ LibertyBuilder::makeTimingArcSet(LibertyCell *cell,
TimingArc *
LibertyBuilder::makeTimingArc(TimingArcSet *set,
RiseFall *from_rf,
RiseFall *to_rf,
const RiseFall *from_rf,
const RiseFall *to_rf,
TimingModel *model)
{
return new TimingArc(set, from_rf->asTransition(),
@ -733,8 +733,8 @@ LibertyBuilder::makeTimingArc(TimingArcSet *set,
TimingArc *
LibertyBuilder::makeTimingArc(TimingArcSet *set,
Transition *from_rf,
Transition *to_rf,
const Transition *from_rf,
const Transition *to_rf,
TimingModel *model)
{
return new TimingArc(set, from_rf, to_rf, model);

View File

@ -78,8 +78,8 @@ public:
LibertyPort *from_port,
LibertyPort *to_port,
LibertyPort *related_out,
RiseFall *from_rf,
TimingRole *role,
const RiseFall *from_rf,
const TimingRole *role,
TimingArcAttrsPtr attrs);
TimingArcSet *makeCombinationalArcs(LibertyCell *cell,
LibertyPort *from_port,
@ -89,14 +89,14 @@ public:
TimingArcAttrsPtr attrs);
TimingArcSet *makeClockTreePathArcs(LibertyCell *cell,
LibertyPort *to_port,
TimingRole *role,
const TimingRole *role,
const MinMax *min_max,
TimingArcAttrsPtr attrs);
TimingArcSet *makeMinPulseWidthArcs(LibertyCell *cell,
LibertyPort *from_port,
LibertyPort *to_port,
LibertyPort *related_out,
TimingRole *role,
const TimingRole *role,
TimingArcAttrsPtr attrs);
protected:
@ -122,21 +122,21 @@ protected:
virtual TimingArcSet *makeTimingArcSet(LibertyCell *cell,
LibertyPort *from,
LibertyPort *to,
TimingRole *role,
const TimingRole *role,
TimingArcAttrsPtr attrs);
virtual TimingArcSet *makeTimingArcSet(LibertyCell *cell,
LibertyPort *from,
LibertyPort *to,
LibertyPort *related_out,
TimingRole *role,
const TimingRole *role,
TimingArcAttrsPtr attrs);
virtual TimingArc *makeTimingArc(TimingArcSet *set,
Transition *from_rf,
Transition *to_rf,
const Transition *from_rf,
const Transition *to_rf,
TimingModel *model);
TimingArc *makeTimingArc(TimingArcSet *set,
RiseFall *from_rf,
RiseFall *to_rf,
const RiseFall *from_rf,
const RiseFall *to_rf,
TimingModel *model);
TimingArcSet *makeLatchDtoQArcs(LibertyCell *cell,
LibertyPort *from_port,
@ -146,12 +146,12 @@ protected:
TimingArcSet *makeRegLatchArcs(LibertyCell *cell,
LibertyPort *from_port,
LibertyPort *to_port,
RiseFall *from_rf,
const RiseFall *from_rf,
TimingArcAttrsPtr attrs);
TimingArcSet *makePresetClrArcs(LibertyCell *cell,
LibertyPort *from_port,
LibertyPort *to_port,
RiseFall *to_rf,
const RiseFall *to_rf,
TimingArcAttrsPtr attrs);
TimingArcSet *makeTristateEnableArcs(LibertyCell *cell,
LibertyPort *from_port,

View File

@ -78,7 +78,7 @@ LibertyParser::makeDefine(LibertyAttrValueSeq *values,
const char *value_type_name = (*values)[2]->stringValue();
LibertyAttrType value_type = attrValueType(value_type_name);
LibertyGroupType group_type = groupType(group_type_name);
define = new LibertyDefine(stringCopy(define_name), group_type,
define = new LibertyDefine(define_name, group_type,
value_type, line);
LibertyGroup *group = this->group();
group->addDefine(define);
@ -128,6 +128,7 @@ LibertyParser::groupBegin(const char *type,
int line)
{
LibertyGroup *group = new LibertyGroup(type, params, line);
stringDelete(type);
group_visitor_->begin(group);
group_stack_.push_back(group);
}
@ -168,6 +169,7 @@ LibertyParser::makeSimpleAttr(const char *name,
int line)
{
LibertyAttr *attr = new LibertySimpleAttr(name, value, line);
stringDelete(name);
group_visitor_->visitAttr(attr);
LibertyGroup *group = this->group();
if (group && group_visitor_->save(attr)) {
@ -198,6 +200,7 @@ LibertyParser::makeComplexAttr(const char *name,
}
else {
LibertyAttr *attr = new LibertyComplexAttr(name, values, line);
stringDelete(name);
group_visitor_->visitAttr(attr);
if (group_visitor_->save(attr)) {
LibertyGroup *group = this->group();
@ -210,11 +213,12 @@ LibertyParser::makeComplexAttr(const char *name,
}
LibertyStmt *
LibertyParser::makeVariable(char *var,
LibertyParser::makeVariable(const char *var,
float value,
int line)
{
LibertyVariable *variable = new LibertyVariable(var, value, line);
stringDelete(var);
group_visitor_->visitVariable(variable);
if (group_visitor_->save(variable))
return variable;
@ -227,7 +231,9 @@ LibertyParser::makeVariable(char *var,
LibertyAttrValue *
LibertyParser::makeStringAttrValue(char *value)
{
return new LibertyStringAttrValue(value);
LibertyAttrValue *attr = new LibertyStringAttrValue(value);
stringDelete(value);
return attr;
}
LibertyAttrValue *
@ -290,7 +296,6 @@ LibertyGroup::addAttribute(LibertyAttr *attr)
LibertyGroup::~LibertyGroup()
{
stringDelete(type_);
if (params_) {
params_->deleteContents();
delete params_;
@ -370,11 +375,6 @@ LibertyAttr::LibertyAttr(const char *name,
{
}
LibertyAttr::~LibertyAttr()
{
stringDelete(name_);
}
LibertySimpleAttr::LibertySimpleAttr(const char *name,
LibertyAttrValue *value,
int line) :
@ -426,11 +426,6 @@ LibertyStringAttrValue::LibertyStringAttrValue(const char *value) :
{
}
LibertyStringAttrValue::~LibertyStringAttrValue()
{
stringDelete(value_);
}
float
LibertyStringAttrValue::floatValue()
{
@ -441,7 +436,7 @@ LibertyStringAttrValue::floatValue()
const char *
LibertyStringAttrValue::stringValue()
{
return value_;
return value_.c_str();
}
LibertyFloatAttrValue::LibertyFloatAttrValue(float value) :
@ -475,11 +470,6 @@ LibertyDefine::LibertyDefine(const char *name,
{
}
LibertyDefine::~LibertyDefine()
{
stringDelete(name_);
}
////////////////////////////////////////////////////////////////
LibertyVariable::LibertyVariable(const char *var,
@ -491,11 +481,6 @@ LibertyVariable::LibertyVariable(const char *var,
{
}
LibertyVariable::~LibertyVariable()
{
stringDelete(var_);
}
////////////////////////////////////////////////////////////////
LibertyScanner::LibertyScanner(std::istream *stream,

View File

@ -48,11 +48,11 @@ class LibertyScanner;
typedef Vector<LibertyStmt*> LibertyStmtSeq;
typedef Vector<LibertyGroup*> LibertyGroupSeq;
typedef Vector<LibertyAttr*> LibertyAttrSeq;
typedef Map<const char *, LibertyAttr*, CharPtrLess> LibertyAttrMap;
typedef Map<const char *, LibertyDefine*, CharPtrLess> LibertyDefineMap;
typedef Map<string, LibertyAttr*> LibertyAttrMap;
typedef Map<string, LibertyDefine*> LibertyDefineMap;
typedef Vector<LibertyAttrValue*> LibertyAttrValueSeq;
typedef Map<const char *, float, CharPtrLess> LibertyVariableMap;
typedef Map<const char*,LibertyGroupVisitor*,CharPtrLess>LibertyGroupVisitorMap;
typedef Map<string, float> LibertyVariableMap;
typedef Map<string, LibertyGroupVisitor*>LibertyGroupVisitorMap;
typedef LibertyAttrValueSeq::Iterator LibertyAttrValueIterator;
typedef Vector<LibertyGroup*> LibertyGroupSeq;
@ -88,7 +88,7 @@ public:
int line);
LibertyAttrValue *makeStringAttrValue(char *value);
LibertyAttrValue *makeFloatAttrValue(float value);
LibertyStmt *makeVariable(char *var,
LibertyStmt *makeVariable(const char *var,
float value,
int line);
@ -103,7 +103,7 @@ private:
class LibertyStmt
{
public:
explicit LibertyStmt(int line);
LibertyStmt(int line);
virtual ~LibertyStmt() {}
int line() const { return line_; }
virtual bool isGroup() const { return false; }
@ -126,7 +126,7 @@ public:
int line);
virtual ~LibertyGroup();
virtual bool isGroup() const { return true; }
const char *type() const { return type_; }
const char *type() const { return type_.c_str(); }
// First param as a string.
const char *firstName();
// Second param as a string.
@ -143,7 +143,7 @@ public:
protected:
void parseNames(LibertyAttrValueSeq *values);
const char *type_;
string type_;
LibertyAttrValueSeq *params_;
LibertyAttrSeq *attrs_;
LibertyAttrMap *attr_map_;
@ -154,13 +154,13 @@ protected:
class LibertySubgroupIterator : public LibertyGroupSeq::Iterator
{
public:
explicit LibertySubgroupIterator(LibertyGroup *group);
LibertySubgroupIterator(LibertyGroup *group);
};
class LibertyAttrIterator : public LibertyAttrSeq::Iterator
{
public:
explicit LibertyAttrIterator(LibertyGroup *group);
LibertyAttrIterator(LibertyGroup *group);
};
// Abstract base class for attributes.
@ -169,8 +169,7 @@ class LibertyAttr : public LibertyStmt
public:
LibertyAttr(const char *name,
int line);
virtual ~LibertyAttr();
const char *name() const { return name_; }
const char *name() const { return name_.c_str(); }
virtual bool isAttribute() const { return true; }
virtual bool isSimple() const = 0;
virtual bool isComplex() const = 0;
@ -178,7 +177,7 @@ public:
virtual LibertyAttrValue *firstValue() = 0;
protected:
const char *name_;
string name_;
};
// Abstract base class for simple attributes.
@ -232,21 +231,22 @@ public:
class LibertyStringAttrValue : public LibertyAttrValue
{
public:
explicit LibertyStringAttrValue(const char *value);
virtual ~LibertyStringAttrValue();
LibertyStringAttrValue(const char *value);
virtual ~LibertyStringAttrValue() {}
virtual bool isFloat() { return false; }
virtual bool isString() { return true; }
virtual float floatValue();
virtual const char *stringValue();
private:
const char *value_;
string value_;
};
class LibertyFloatAttrValue : public LibertyAttrValue
{
public:
explicit LibertyFloatAttrValue(float value);
LibertyFloatAttrValue(float value);
virtual ~LibertyFloatAttrValue() {}
virtual bool isString() { return false; }
virtual bool isFloat() { return true; }
virtual float floatValue();
@ -266,14 +266,13 @@ public:
LibertyGroupType group_type,
LibertyAttrType value_type,
int line);
virtual ~LibertyDefine();
virtual bool isDefine() const { return true; }
const char *name() const { return name_; }
const char *name() const { return name_.c_str(); }
LibertyGroupType groupType() const { return group_type_; }
LibertyAttrType valueType() const { return value_type_; }
private:
const char *name_;
string name_;
LibertyGroupType group_type_;
LibertyAttrType value_type_;
};
@ -288,15 +287,12 @@ public:
LibertyVariable(const char *var,
float value,
int line);
// var_ is NOT deleted by ~LibertyVariable because the group
// variable map ref's it.
virtual ~LibertyVariable();
virtual bool isVariable() const { return true; }
const char *variable() const { return var_; }
const char *variable() const { return var_.c_str(); }
float value() const { return value_; }
private:
const char *var_;
string var_;
float value_;
};

View File

@ -141,25 +141,7 @@ LibertyReader::init(const char *filename,
LibertyReader::~LibertyReader()
{
if (var_map_) {
LibertyVariableMap::Iterator iter(var_map_);
while (iter.hasNext()) {
const char *var;
float value;
iter.next(var, value);
stringDelete(var);
}
delete var_map_;
}
// Scaling factor attribute names are allocated, so delete them.
LibraryAttrMap::Iterator attr_iter(attr_visitor_map_);
while (attr_iter.hasNext()) {
const char *attr_name;
LibraryAttrVisitor visitor;
attr_iter.next(attr_name, visitor);
stringDelete(attr_name);
}
delete var_map_;
}
LibertyLibrary *
@ -183,7 +165,7 @@ void
LibertyReader::defineAttrVisitor(const char *attr_name,
LibraryAttrVisitor visitor)
{
attr_visitor_map_[stringCopy(attr_name)] = visitor;
attr_visitor_map_[attr_name] = visitor;
}
void
@ -1125,7 +1107,7 @@ LibertyReader::visitDefaultIntrinsicFall(LibertyAttr *attr)
void
LibertyReader::visitDefaultIntrinsic(LibertyAttr *attr,
RiseFall *rf)
const RiseFall *rf)
{
if (library_) {
float value;
@ -1150,7 +1132,7 @@ LibertyReader::visitDefaultInoutPinFallRes(LibertyAttr *attr)
void
LibertyReader::visitDefaultInoutPinRes(LibertyAttr *attr,
RiseFall *rf)
const RiseFall *rf)
{
if (library_) {
float value;
@ -1175,7 +1157,7 @@ LibertyReader::visitDefaultOutputPinFallRes(LibertyAttr *attr)
void
LibertyReader::visitDefaultOutputPinRes(LibertyAttr *attr,
RiseFall *rf)
const RiseFall *rf)
{
if (library_) {
float value;
@ -1267,7 +1249,7 @@ LibertyReader::visitInputThresholdPctRise(LibertyAttr *attr)
void
LibertyReader::visitInputThresholdPct(LibertyAttr *attr,
RiseFall *rf)
const RiseFall *rf)
{
if (library_) {
float value;
@ -1293,7 +1275,7 @@ LibertyReader::visitOutputThresholdPctRise(LibertyAttr *attr)
void
LibertyReader::visitOutputThresholdPct(LibertyAttr *attr,
RiseFall *rf)
const RiseFall *rf)
{
if (library_) {
float value;
@ -1319,7 +1301,7 @@ LibertyReader::visitSlewLowerThresholdPctRise(LibertyAttr *attr)
void
LibertyReader::visitSlewLowerThresholdPct(LibertyAttr *attr,
RiseFall *rf)
const RiseFall *rf)
{
if (library_) {
float value;
@ -1345,7 +1327,7 @@ LibertyReader::visitSlewUpperThresholdPctRise(LibertyAttr *attr)
void
LibertyReader::visitSlewUpperThresholdPct(LibertyAttr *attr,
RiseFall *rf)
const RiseFall *rf)
{
if (library_) {
float value;
@ -1616,7 +1598,7 @@ LibertyReader::visitScaleFactorSuffix(LibertyAttr *attr)
if (scale_factors_) {
ScaleFactorPvt pvt = ScaleFactorPvt::unknown;
ScaleFactorType type = ScaleFactorType::unknown;
RiseFall *rf = nullptr;
const RiseFall *rf = nullptr;
// Parse the attribute name.
TokenParser parser(attr->name(), "_");
if (parser.hasNext())
@ -1654,7 +1636,7 @@ LibertyReader::visitScaleFactorPrefix(LibertyAttr *attr)
if (scale_factors_) {
ScaleFactorPvt pvt = ScaleFactorPvt::unknown;
ScaleFactorType type = ScaleFactorType::unknown;
RiseFall *rf = nullptr;
const RiseFall *rf = nullptr;
// Parse the attribute name.
TokenParser parser(attr->name(), "_");
if (parser.hasNext())
@ -1692,7 +1674,7 @@ LibertyReader::visitScaleFactorHiLow(LibertyAttr *attr)
if (scale_factors_) {
ScaleFactorPvt pvt = ScaleFactorPvt::unknown;
ScaleFactorType type = ScaleFactorType::unknown;
RiseFall *rf = nullptr;
const RiseFall *rf = nullptr;
const char *pvt_name = nullptr;
const char *type_name = nullptr;
const char *tr_name = nullptr;
@ -2217,7 +2199,7 @@ LibertyReader::makeStatetable()
for (const string &internal : statetable_->internalPorts()) {
LibertyPort *port = cell_->findLibertyPort(internal.c_str());
if (port == nullptr)
port = builder_.makePort(cell_, internal.c_str());
port = makePort(cell_, internal.c_str());
internal_ports.push_back(port);
}
cell_->makeStatetable(input_ports, internal_ports, statetable_->table());
@ -2630,7 +2612,7 @@ LibertyReader::beginReceiverCapacitance2Fall(LibertyGroup *group)
void
LibertyReader::beginReceiverCapacitance(LibertyGroup *group,
int index,
RiseFall *rf)
const RiseFall *rf)
{
if (timing_ || ports_) {
beginTableModel(group, TableTemplateType::delay, rf, 1.0,
@ -2676,7 +2658,7 @@ LibertyReader::beginOutputCurrentFall(LibertyGroup *group)
}
void
LibertyReader::beginOutputCurrent(RiseFall *rf,
LibertyReader::beginOutputCurrent(const RiseFall *rf,
LibertyGroup *group)
{
if (timing_) {
@ -2802,13 +2784,13 @@ void
LibertyReader::beginNormalizedDriverWaveform(LibertyGroup *group)
{
beginTable(group, TableTemplateType::delay, time_scale_);
driver_waveform_name_ = nullptr;
driver_waveform_name_.clear();
}
void
LibertyReader::visitDriverWaveformName(LibertyAttr *attr)
{
driver_waveform_name_ = stringCopy(getAttrString(attr));
driver_waveform_name_ = getAttrString(attr);
}
void
@ -3183,7 +3165,7 @@ LibertyReader::beginPin(LibertyGroup *group)
debugPrint(debug_, "liberty", 1, " port %s", name);
LibertyPort *port = findPort(name);
if (port == nullptr)
port = builder_.makePort(cell_, name);
port = makePort(cell_, name);
ports_->push_back(port);
}
else
@ -3197,7 +3179,7 @@ LibertyReader::beginPin(LibertyGroup *group)
if (param->isString()) {
const char *name = param->stringValue();
debugPrint(debug_, "liberty", 1, " port %s", name);
LibertyPort *port = builder_.makePort(cell_, name);
LibertyPort *port = makePort(cell_, name);
ports_->push_back(port);
}
else
@ -3216,6 +3198,25 @@ LibertyReader::beginPin(LibertyGroup *group)
}
}
LibertyPort *
LibertyReader::makePort(LibertyCell *cell,
const char *port_name)
{
string sta_name = portLibertyToSta(port_name);
return builder_.makePort(cell, sta_name.c_str());
}
LibertyPort *
LibertyReader::makeBusPort(LibertyCell *cell,
const char *bus_name,
int from_index,
int to_index,
BusDcl *bus_dcl)
{
string sta_name = portLibertyToSta(bus_name);
return builder_.makeBusPort(cell, bus_name, from_index, to_index, bus_dcl);
}
void
LibertyReader::endPin(LibertyGroup *)
{
@ -3328,8 +3329,8 @@ LibertyReader::visitBusType(LibertyAttr *attr)
if (bus_dcl) {
for (const char *name : bus_names_) {
debugPrint(debug_, "liberty", 1, " bus %s", name);
LibertyPort *port = builder_.makeBusPort(cell_, name, bus_dcl->from(),
bus_dcl->to(), bus_dcl);
LibertyPort *port = makeBusPort(cell_, name, bus_dcl->from(),
bus_dcl->to(), bus_dcl);
ports_->push_back(port);
}
}
@ -3374,7 +3375,7 @@ LibertyReader::visitMembers(LibertyAttr *attr)
const char *port_name = value->stringValue();
LibertyPort *port = findPort(port_name);
if (port == nullptr)
port = builder_.makePort(cell_, port_name);
port = makePort(cell_, port_name);
members->push_back(port);
}
else
@ -3648,7 +3649,7 @@ LibertyReader::visitMinFanout(LibertyAttr *attr)
void
LibertyReader::visitFanout(LibertyAttr *attr,
MinMax *min_max)
const MinMax *min_max)
{
if (ports_) {
float fanout;
@ -3675,7 +3676,8 @@ LibertyReader::visitMinTransition(LibertyAttr *attr)
}
void
LibertyReader::visitMinMaxTransition(LibertyAttr *attr, MinMax *min_max)
LibertyReader::visitMinMaxTransition(LibertyAttr *attr,
const MinMax *min_max)
{
if (cell_) {
float value;
@ -3706,7 +3708,7 @@ LibertyReader::visitMinCapacitance(LibertyAttr *attr)
void
LibertyReader::visitMinMaxCapacitance(LibertyAttr *attr,
MinMax *min_max)
const MinMax *min_max)
{
if (cell_) {
float value;
@ -3770,8 +3772,8 @@ LibertyReader::visitPulseClock(LibertyAttr *attr)
if (cell_) {
const char *pulse_clk = getAttrString(attr);
if (pulse_clk) {
RiseFall *trigger = nullptr;
RiseFall *sense = nullptr;
const RiseFall *trigger = nullptr;
const RiseFall *sense = nullptr;
if (stringEq(pulse_clk, "rise_triggered_high_pulse")) {
trigger = RiseFall::rise();
sense = RiseFall::rise();
@ -3980,16 +3982,16 @@ LibertyReader::beginSequential(LibertyGroup *group,
LibertyPort *out_port_inv = nullptr;
if (out_name) {
if (has_size)
out_port = builder_.makeBusPort(cell_, out_name, size - 1, 0, nullptr);
out_port = makeBusPort(cell_, out_name, size - 1, 0, nullptr);
else
out_port = builder_.makePort(cell_, out_name);
out_port = makePort(cell_, out_name);
out_port->setDirection(PortDirection::internal());
}
if (out_inv_name) {
if (has_size)
out_port_inv = builder_.makeBusPort(cell_, out_inv_name, size - 1, 0, nullptr);
out_port_inv = makeBusPort(cell_, out_inv_name, size - 1, 0, nullptr);
else
out_port_inv = builder_.makePort(cell_, out_inv_name);
out_port_inv = makePort(cell_, out_inv_name);
out_port_inv->setDirection(PortDirection::internal());
}
sequential_ = new SequentialGroup(is_register, is_bank,
@ -4435,7 +4437,7 @@ LibertyReader::visitIntrinsicFall(LibertyAttr *attr)
void
LibertyReader::visitIntrinsic(LibertyAttr *attr,
RiseFall *rf)
const RiseFall *rf)
{
if (timing_) {
float value;
@ -4460,7 +4462,7 @@ LibertyReader::visitFallResistance(LibertyAttr *attr)
void
LibertyReader::visitRiseFallResistance(LibertyAttr *attr,
RiseFall *rf)
const RiseFall *rf)
{
if (timing_) {
float value;
@ -4593,7 +4595,7 @@ LibertyReader::endRiseFallTransitionDegredation(LibertyGroup *group)
void
LibertyReader::beginTimingTableModel(LibertyGroup *group,
RiseFall *rf,
const RiseFall *rf,
ScaleFactorType scale_factor_type)
{
if (timing_)
@ -4606,7 +4608,7 @@ LibertyReader::beginTimingTableModel(LibertyGroup *group,
void
LibertyReader::beginTableModel(LibertyGroup *group,
TableTemplateType type,
RiseFall *rf,
const RiseFall *rf,
float scale,
ScaleFactorType scale_factor_type)
{
@ -4807,7 +4809,7 @@ LibertyReader::beginLut(LibertyGroup *group)
while (parser.hasNext()) {
char *name = parser.next();
if (name[0] != '\0') {
LibertyPort *port = builder_.makePort(cell_, name);
LibertyPort *port = makePort(cell_, name);
port->setDirection(PortDirection::internal());
}
}
@ -5186,7 +5188,7 @@ LibertyReader::parseFunc(const char *func,
return parseFuncExpr(func, cell_, error_msg.c_str(), report_);
}
EarlyLateAll *
const EarlyLateAll *
LibertyReader::getAttrEarlyLate(LibertyAttr *attr)
{
const char *value = getAttrString(attr);
@ -5210,7 +5212,7 @@ LibertyReader::visitVariable(LibertyVariable *var)
if (var_map_ == nullptr)
var_map_ = new LibertyVariableMap;
const char *var_name = var->variable();
const char *key;
string key;
float value;
bool exists;
var_map_->findKey(var_name, key, value, exists);
@ -5219,7 +5221,7 @@ LibertyReader::visitVariable(LibertyVariable *var)
(*var_map_)[key] = var->value();
}
else
(*var_map_)[stringCopy(var_name)] = var->value();
(*var_map_)[var_name] = var->value();
}
void
@ -5918,7 +5920,7 @@ TimingGroup::setRelatedOutputPortName(const char *name)
}
void
TimingGroup::setIntrinsic(RiseFall *rf,
TimingGroup::setIntrinsic(const RiseFall *rf,
float value)
{
int rf_index = rf->index();
@ -5927,7 +5929,7 @@ TimingGroup::setIntrinsic(RiseFall *rf,
}
void
TimingGroup::intrinsic(RiseFall *rf,
TimingGroup::intrinsic(const RiseFall *rf,
// Return values.
float &value,
bool &exists)
@ -5938,7 +5940,7 @@ TimingGroup::intrinsic(RiseFall *rf,
}
void
TimingGroup::setResistance(RiseFall *rf,
TimingGroup::setResistance(const RiseFall *rf,
float value)
{
int rf_index = rf->index();
@ -5947,7 +5949,7 @@ TimingGroup::setResistance(RiseFall *rf,
}
void
TimingGroup::resistance(RiseFall *rf,
TimingGroup::resistance(const RiseFall *rf,
// Return values.
float &value,
bool &exists)
@ -5958,63 +5960,63 @@ TimingGroup::resistance(RiseFall *rf,
}
TableModel *
TimingGroup::cell(RiseFall *rf)
TimingGroup::cell(const RiseFall *rf)
{
return cell_[rf->index()];
}
void
TimingGroup::setCell(RiseFall *rf,
TimingGroup::setCell(const RiseFall *rf,
TableModel *model)
{
cell_[rf->index()] = model;
}
TableModel *
TimingGroup::constraint(RiseFall *rf)
TimingGroup::constraint(const RiseFall *rf)
{
return constraint_[rf->index()];
}
void
TimingGroup::setConstraint(RiseFall *rf,
TimingGroup::setConstraint(const RiseFall *rf,
TableModel *model)
{
constraint_[rf->index()] = model;
}
TableModel *
TimingGroup::transition(RiseFall *rf)
TimingGroup::transition(const RiseFall *rf)
{
return transition_[rf->index()];
}
void
TimingGroup::setTransition(RiseFall *rf,
TimingGroup::setTransition(const RiseFall *rf,
TableModel *model)
{
transition_[rf->index()] = model;
}
void
TimingGroup::setDelaySigma(RiseFall *rf,
EarlyLate *early_late,
TimingGroup::setDelaySigma(const RiseFall *rf,
const EarlyLate *early_late,
TableModel *model)
{
delay_sigma_[rf->index()][early_late->index()] = model;
}
void
TimingGroup::setSlewSigma(RiseFall *rf,
EarlyLate *early_late,
TimingGroup::setSlewSigma(const RiseFall *rf,
const EarlyLate *early_late,
TableModel *model)
{
slew_sigma_[rf->index()][early_late->index()] = model;
}
void
TimingGroup::setConstraintSigma(RiseFall *rf,
EarlyLate *early_late,
TimingGroup::setConstraintSigma(const RiseFall *rf,
const EarlyLate *early_late,
TableModel *model)
{
constraint_sigma_[rf->index()][early_late->index()] = model;
@ -6027,13 +6029,13 @@ TimingGroup::setReceiverModel(ReceiverModelPtr receiver_model)
}
OutputWaveforms *
TimingGroup::outputWaveforms(RiseFall *rf)
TimingGroup::outputWaveforms(const RiseFall *rf)
{
return output_waveforms_[rf->index()];
}
void
TimingGroup::setOutputWaveforms(RiseFall *rf,
TimingGroup::setOutputWaveforms(const RiseFall *rf,
OutputWaveforms *output_waveforms)
{
output_waveforms_[rf->index()] = output_waveforms;

View File

@ -64,8 +64,8 @@ using std::vector;
typedef void (LibertyReader::*LibraryAttrVisitor)(LibertyAttr *attr);
typedef void (LibertyReader::*LibraryGroupVisitor)(LibertyGroup *group);
typedef Map<const char*,LibraryAttrVisitor,CharPtrLess> LibraryAttrMap;
typedef Map<const char*,LibraryGroupVisitor,CharPtrLess> LibraryGroupMap;
typedef Map<string, LibraryAttrVisitor> LibraryAttrMap;
typedef Map<string ,LibraryGroupVisitor> LibraryGroupMap;
typedef Vector<PortGroup*> PortGroupSeq;
typedef Vector<SequentialGroup*> SequentialGroupSeq;
typedef Vector<LibertyFunc*> LibertyFuncSeq;
@ -122,15 +122,15 @@ public:
virtual void visitDefaultIntrinsicRise(LibertyAttr *attr);
virtual void visitDefaultIntrinsicFall(LibertyAttr *attr);
virtual void visitDefaultIntrinsic(LibertyAttr *attr,
RiseFall *rf);
const RiseFall *rf);
virtual void visitDefaultInoutPinRiseRes(LibertyAttr *attr);
virtual void visitDefaultInoutPinFallRes(LibertyAttr *attr);
virtual void visitDefaultInoutPinRes(LibertyAttr *attr,
RiseFall *rf);
const RiseFall *rf);
virtual void visitDefaultOutputPinRiseRes(LibertyAttr *attr);
virtual void visitDefaultOutputPinFallRes(LibertyAttr *attr);
virtual void visitDefaultOutputPinRes(LibertyAttr *attr,
RiseFall *rf);
const RiseFall *rf);
virtual void visitDefaultFanoutLoad(LibertyAttr *attr);
virtual void visitDefaultWireLoad(LibertyAttr *attr);
virtual void visitDefaultWireLoadMode(LibertyAttr *attr);
@ -139,19 +139,19 @@ public:
virtual void visitInputThresholdPctFall(LibertyAttr *attr);
virtual void visitInputThresholdPctRise(LibertyAttr *attr);
virtual void visitInputThresholdPct(LibertyAttr *attr,
RiseFall *rf);
const RiseFall *rf);
virtual void visitOutputThresholdPctFall(LibertyAttr *attr);
virtual void visitOutputThresholdPctRise(LibertyAttr *attr);
virtual void visitOutputThresholdPct(LibertyAttr *attr,
RiseFall *rf);
const RiseFall *rf);
virtual void visitSlewLowerThresholdPctFall(LibertyAttr *attr);
virtual void visitSlewLowerThresholdPctRise(LibertyAttr *attr);
virtual void visitSlewLowerThresholdPct(LibertyAttr *attr,
RiseFall *rf);
const RiseFall *rf);
virtual void visitSlewUpperThresholdPctFall(LibertyAttr *attr);
virtual void visitSlewUpperThresholdPctRise(LibertyAttr *attr);
virtual void visitSlewUpperThresholdPct(LibertyAttr *attr,
RiseFall *rf);
const RiseFall *rf);
virtual void visitSlewDerateFromLibrary(LibertyAttr *attr);
virtual void beginTechnology(LibertyGroup *group);
@ -247,15 +247,15 @@ public:
virtual void visitMaxFanout(LibertyAttr *attr);
virtual void visitMinFanout(LibertyAttr *attr);
virtual void visitFanout(LibertyAttr *attr,
MinMax *min_max);
const MinMax *min_max);
virtual void visitMaxTransition(LibertyAttr *attr);
virtual void visitMinTransition(LibertyAttr *attr);
virtual void visitMinMaxTransition(LibertyAttr *attr,
MinMax *min_max);
const MinMax *min_max);
virtual void visitMaxCapacitance(LibertyAttr *attr);
virtual void visitMinCapacitance(LibertyAttr *attr);
virtual void visitMinMaxCapacitance(LibertyAttr *attr,
MinMax *min_max);
const MinMax *min_max);
virtual void visitMinPeriod(LibertyAttr *attr);
virtual void visitMinPulseWidthLow(LibertyAttr *attr);
virtual void visitMinPulseWidthHigh(LibertyAttr *attr);
@ -267,7 +267,7 @@ public:
virtual void visitClockGateOutPin(LibertyAttr *attr);
void visitIsPllFeedbackPin(LibertyAttr *attr);
virtual void visitSignalType(LibertyAttr *attr);
EarlyLateAll *getAttrEarlyLate(LibertyAttr *attr);
const EarlyLateAll *getAttrEarlyLate(LibertyAttr *attr);
virtual void visitClock(LibertyAttr *attr);
virtual void visitIsolationCellDataPin(LibertyAttr *attr);
virtual void visitIsolationCellEnablePin(LibertyAttr *attr);
@ -350,11 +350,11 @@ public:
virtual void visitIntrinsicRise(LibertyAttr *attr);
virtual void visitIntrinsicFall(LibertyAttr *attr);
virtual void visitIntrinsic(LibertyAttr *attr,
RiseFall *rf);
const RiseFall *rf);
virtual void visitRiseResistance(LibertyAttr *attr);
virtual void visitFallResistance(LibertyAttr *attr);
virtual void visitRiseFallResistance(LibertyAttr *attr,
RiseFall *rf);
const RiseFall *rf);
virtual void visitValue(LibertyAttr *attr);
virtual void visitValues(LibertyAttr *attr);
virtual void beginCellRise(LibertyGroup *group);
@ -373,12 +373,12 @@ public:
virtual void beginTableModel(LibertyGroup *group,
TableTemplateType type,
RiseFall *rf,
const RiseFall *rf,
float scale,
ScaleFactorType scale_factor_type);
virtual void endTableModel();
virtual void beginTimingTableModel(LibertyGroup *group,
RiseFall *rf,
const RiseFall *rf,
ScaleFactorType scale_factor_type);
virtual void beginTable(LibertyGroup *group,
TableTemplateType type,
@ -469,14 +469,14 @@ public:
virtual void beginReceiverCapacitance2Fall(LibertyGroup *group);
void beginReceiverCapacitance(LibertyGroup *group,
int index,
RiseFall *rf);
const RiseFall *rf);
void endReceiverCapacitance(LibertyGroup *group,
int index,
RiseFall *rf);
const RiseFall *rf);
// ccs
void beginOutputCurrentRise(LibertyGroup *group);
void beginOutputCurrentFall(LibertyGroup *group);
void beginOutputCurrent(RiseFall *rf,
void beginOutputCurrent(const RiseFall *rf,
LibertyGroup *group);
void endOutputCurrentRiseFall(LibertyGroup *group);
void beginVector(LibertyGroup *group);
@ -500,6 +500,14 @@ public:
const char *port_name);
protected:
LibertyPort *makePort(LibertyCell *cell,
const char *port_name);
LibertyPort *makeBusPort(LibertyCell *cell,
const char *bus_name,
int from_index,
int to_index,
BusDcl *bus_dcl);
TimingModel *makeScalarCheckModel(float value,
ScaleFactorType scale_factor_type,
const RiseFall *rf);
@ -639,12 +647,12 @@ protected:
InternalPowerGroup *internal_power_;
LeakagePowerGroup *leakage_power_;
LeakagePowerGroupSeq leakage_powers_;
RiseFall *rf_;
const RiseFall *rf_;
int index_;
OcvDerate *ocv_derate_;
RiseFallBoth *rf_type_;
EarlyLateAll *derate_type_;
EarlyLateAll *sigma_type_;
const RiseFallBoth *rf_type_;
const EarlyLateAll *derate_type_;
const EarlyLateAll *sigma_type_;
PathType path_type_;
LibertyPgPort *pg_port_;
ScaleFactorType scale_factor_type_;
@ -668,7 +676,7 @@ protected:
OutputWaveforms *output_waveforms_;
float reference_time_;
bool reference_time_exists_;
const char *driver_waveform_name_;
string driver_waveform_name_;
TestCell *test_cell_;
// Saved state while parsing test_cell.
@ -827,41 +835,41 @@ public:
TimingArcAttrsPtr attrs() { return attrs_; }
const char *relatedOutputPortName()const {return related_output_port_name_;}
void setRelatedOutputPortName(const char *name);
void intrinsic(RiseFall *rf,
void intrinsic(const RiseFall *rf,
// Return values.
float &value,
bool &exists);
void setIntrinsic(RiseFall *rf,
void setIntrinsic(const RiseFall *rf,
float value);
void resistance(RiseFall *rf,
void resistance(const RiseFall *rf,
// Return values.
float &value,
bool &exists);
void setResistance(RiseFall *rf,
void setResistance(const RiseFall *rf,
float value);
TableModel *cell(RiseFall *rf);
void setCell(RiseFall *rf,
TableModel *cell(const RiseFall *rf);
void setCell(const RiseFall *rf,
TableModel *model);
TableModel *constraint(RiseFall *rf);
void setConstraint(RiseFall *rf,
TableModel *constraint(const RiseFall *rf);
void setConstraint(const RiseFall *rf,
TableModel *model);
TableModel *transition(RiseFall *rf);
void setTransition(RiseFall *rf,
TableModel *transition(const RiseFall *rf);
void setTransition(const RiseFall *rf,
TableModel *model);
void makeTimingModels(LibertyCell *cell,
LibertyReader *visitor);
void setDelaySigma(RiseFall *rf,
EarlyLate *early_late,
void setDelaySigma(const RiseFall *rf,
const EarlyLate *early_late,
TableModel *model);
void setSlewSigma(RiseFall *rf,
EarlyLate *early_late,
void setSlewSigma(const RiseFall *rf,
const EarlyLate *early_late,
TableModel *model);
void setConstraintSigma(RiseFall *rf,
EarlyLate *early_late,
void setConstraintSigma(const RiseFall *rf,
const EarlyLate *early_late,
TableModel *model);
void setReceiverModel(ReceiverModelPtr receiver_model);
OutputWaveforms *outputWaveforms(RiseFall *rf);
void setOutputWaveforms(RiseFall *rf,
OutputWaveforms *outputWaveforms(const RiseFall *rf);
void setOutputWaveforms(const RiseFall *rf,
OutputWaveforms *output_current);
protected:

View File

@ -358,16 +358,18 @@ LibertyWriter::writePortAttrs(const LibertyPort *port)
// cannot ref internal ports until sequentials are written
&& !(func->port()
&& func->port()->direction()->isInternal()))
fprintf(stream_, " function : \"%s\";\n", func->asString());
fprintf(stream_, " function : \"%s\";\n", func->to_string().c_str());
auto tristate_enable = port->tristateEnable();
if (tristate_enable) {
if (tristate_enable->op() == FuncExpr::op_not) {
FuncExpr *three_state = tristate_enable->left();
fprintf(stream_, " three_state : \"%s\";\n", three_state->asString());
fprintf(stream_, " three_state : \"%s\";\n",
three_state->to_string().c_str());
}
else {
FuncExpr three_state(FuncExpr::op_not, tristate_enable, nullptr, nullptr);
fprintf(stream_, " three_state : \"%s\";\n", three_state.asString());
fprintf(stream_, " three_state : \"%s\";\n",
three_state.to_string().c_str());
}
}
if (port->isClock())
@ -417,12 +419,12 @@ LibertyWriter::writeTimingArcSet(const TimingArcSet *arc_set)
if (sense != TimingSense::unknown
&& sense != TimingSense::non_unate)
fprintf(stream_, " timing_sense : %s;\n",
timingSenseString(sense));
to_string(sense));
const char *timing_type = timingTypeString(arc_set);
if (timing_type)
fprintf(stream_, " timing_type : %s;\n", timing_type);
for (RiseFall *rf : RiseFall::range()) {
for (const RiseFall *rf : RiseFall::range()) {
TimingArc *arc = arc_set->arcTo(rf);
if (arc)
writeTimingModels(arc, rf);
@ -634,7 +636,7 @@ LibertyWriter::timingTypeString(const TimingArcSet *arc_set)
library_->name(),
arc_set->to()->libertyCell()->name(),
arc_set->to()->name(),
role->asString());
role->to_string().c_str());
return nullptr;
}
}

View File

@ -375,7 +375,7 @@ ReceiverModel::~ReceiverModel()
void
ReceiverModel::setCapacitanceModel(TableModel *table_model,
size_t segment,
RiseFall *rf)
const RiseFall *rf)
{
if ((segment + 1) * RiseFall::index_count > capacitance_models_.size())
capacitance_models_.resize((segment + 1) * RiseFall::index_count);
@ -2062,18 +2062,13 @@ OutputWaveforms::finalResistance()
////////////////////////////////////////////////////////////////
DriverWaveform::DriverWaveform(const char *name,
DriverWaveform::DriverWaveform(const string &name,
TablePtr waveforms) :
name_(name),
waveforms_(waveforms)
{
}
DriverWaveform::~DriverWaveform()
{
stringDelete(name_);
}
Table1
DriverWaveform::waveform(float slew)
{

View File

@ -188,7 +188,7 @@ TimingArcSet::TimingArcSet(LibertyCell *cell,
LibertyPort *from,
LibertyPort *to,
LibertyPort *related_out,
TimingRole *role,
const TimingRole *role,
TimingArcAttrsPtr attrs) :
from_(from),
to_(to),
@ -204,7 +204,7 @@ TimingArcSet::TimingArcSet(LibertyCell *cell,
{
}
TimingArcSet::TimingArcSet(TimingRole *role,
TimingArcSet::TimingArcSet(const TimingRole *role,
TimingArcAttrsPtr attrs) :
from_(nullptr),
to_(nullptr),
@ -292,7 +292,7 @@ TimingArcSet::findTimingArc(unsigned arc_index)
}
void
TimingArcSet::setRole(TimingRole *role)
TimingArcSet::setRole(const TimingRole *role)
{
role_ = role;
}
@ -422,8 +422,8 @@ timingArcSetLess(const TimingArcSet *set1,
LibertyPort *to1 = set1->to();
LibertyPort *to2 = set2->to();
if (LibertyPort::equiv(to1, to2)) {
TimingRole *role1 = set1->role();
TimingRole *role2 = set2->role();
const TimingRole *role1 = set1->role();
const TimingRole *role2 = set2->role();
if (role1 == role2) {
const FuncExpr *cond1 = set1->cond();
const FuncExpr *cond2 = set2->cond();
@ -536,8 +536,8 @@ TimingArcSet::destroy()
////////////////////////////////////////////////////////////////
TimingArc::TimingArc(TimingArcSet *set,
Transition *from_rf,
Transition *to_rf,
const Transition *from_rf,
const Transition *to_rf,
TimingModel *model) :
set_(set),
from_rf_(from_rf),
@ -664,7 +664,7 @@ static EnumNameMap<TimingSense> timing_sense_name_map =
};
const char *
timingSenseString(TimingSense sense)
to_string(TimingSense sense)
{
return timing_sense_name_map.find(sense);
}

View File

@ -26,178 +26,75 @@
namespace sta {
TimingRole *TimingRole::wire_;
TimingRole *TimingRole::combinational_;
TimingRole *TimingRole::tristate_enable_;
TimingRole *TimingRole::tristate_disable_;
TimingRole *TimingRole::reg_clk_q_;
TimingRole *TimingRole::reg_set_clr_;
TimingRole *TimingRole::latch_en_q_;
TimingRole *TimingRole::latch_d_q_;
TimingRole *TimingRole::sdf_iopath_;
TimingRole *TimingRole::setup_;
TimingRole *TimingRole::hold_;
TimingRole *TimingRole::recovery_;
TimingRole *TimingRole::removal_;
TimingRole *TimingRole::width_;
TimingRole *TimingRole::period_;
TimingRole *TimingRole::skew_;
TimingRole *TimingRole::nochange_;
TimingRole *TimingRole::output_setup_;
TimingRole *TimingRole::output_hold_;
TimingRole *TimingRole::gated_clk_setup_;
TimingRole *TimingRole::gated_clk_hold_;
TimingRole *TimingRole::latch_setup_;
TimingRole *TimingRole::latch_hold_;
TimingRole *TimingRole::data_check_setup_;
TimingRole *TimingRole::data_check_hold_;
TimingRole *TimingRole::non_seq_setup_;
TimingRole *TimingRole::non_seq_hold_;
TimingRole *TimingRole::clock_tree_path_min_;
TimingRole *TimingRole::clock_tree_path_max_;
TimingRoleMap TimingRole::timing_roles_;
void
TimingRole::init()
{
wire_ = new TimingRole("wire", false, false, false, nullptr, nullptr, 0);
combinational_ = new TimingRole("combinational", true, false, false,
nullptr, nullptr, 1);
tristate_enable_ = new TimingRole("tristate enable",
true, false, false,
nullptr, nullptr, 2);
tristate_disable_ = new TimingRole("tristate disable",
true, false, false,
nullptr, nullptr, 3);
reg_clk_q_ = new TimingRole("Reg Clk to Q", true, false, false,
nullptr, nullptr, 4);
reg_set_clr_ = new TimingRole("Reg Set/Clr", true, false, false,
nullptr, nullptr, 5);
latch_en_q_ = new TimingRole("Latch En to Q", true, false, false,
nullptr, TimingRole::regClkToQ(), 6);
latch_d_q_ = new TimingRole("Latch D to Q", true, false, false,
nullptr, nullptr, 7);
sdf_iopath_ = new TimingRole("sdf IOPATH", true, false, false,
nullptr, nullptr, 8);
setup_ = new TimingRole("setup", false, true, false,
MinMax::max(), nullptr, 9);
hold_ = new TimingRole("hold", false, true, false,
MinMax::min(), nullptr, 10);
recovery_ = new TimingRole("recovery", false, true, false,
MinMax::max(), TimingRole::setup(), 11);
removal_ = new TimingRole("removal", false, true, false,
MinMax::min(), TimingRole::hold(), 12);
width_ = new TimingRole("width", false, true, false,
nullptr, nullptr, 13);
period_ = new TimingRole("period", false, true, false,
nullptr, nullptr, 14);
skew_ = new TimingRole("skew", false, true, false,
nullptr, nullptr, 15);
nochange_ = new TimingRole("nochange", true, false, false,
nullptr, nullptr, 16);
output_setup_ = new TimingRole("output setup", false, true, false,
MinMax::max(), TimingRole::setup(), 17);
output_hold_ = new TimingRole("output hold", false, true, false,
MinMax::min(), TimingRole::hold(), 18);
gated_clk_setup_ = new TimingRole("clock gating setup",
false, true, false,
MinMax::max(), TimingRole::setup(),19);
gated_clk_hold_ = new TimingRole("clock gating hold", false, true, false,
MinMax::min(), TimingRole::hold(),20);
latch_setup_ = new TimingRole("latch setup", false, true, false,
MinMax::max(), TimingRole::setup(),21);
latch_hold_ = new TimingRole("latch hold", false, true, false,
MinMax::min(), TimingRole::hold(),22);
data_check_setup_ = new TimingRole("data check setup",
false, true, false,
MinMax::max(),TimingRole::setup(),23);
data_check_hold_ = new TimingRole("data check hold", false, true, false,
MinMax::min(), TimingRole::hold(), 24);
non_seq_setup_ = new TimingRole("non-sequential setup", false, true, true,
MinMax::max(), TimingRole::setup(), 25);
non_seq_hold_ = new TimingRole("non-sequential hold", false, true, true,
MinMax::min(), TimingRole::hold(), 26);
clock_tree_path_min_ = new TimingRole("min clock tree path", false, false, false,
MinMax::min(), nullptr, 27);
clock_tree_path_max_ = new TimingRole("max clock tree path", false, false, false,
MinMax::max(), nullptr, 28);
}
void
TimingRole::destroy()
{
delete wire_;
wire_ = nullptr;
delete combinational_;
combinational_ = nullptr;
delete tristate_enable_;
tristate_enable_ = nullptr;
delete tristate_disable_;
tristate_disable_ = nullptr;
delete reg_clk_q_;
reg_clk_q_ = nullptr;
delete reg_set_clr_;
reg_set_clr_ = nullptr;
delete latch_en_q_;
latch_en_q_ = nullptr;
delete latch_d_q_;
latch_d_q_ = nullptr;
delete sdf_iopath_;
sdf_iopath_ = nullptr;
delete setup_;
setup_ = nullptr;
delete hold_;
hold_ = nullptr;
delete recovery_;
recovery_ = nullptr;
delete removal_;
removal_ = nullptr;
delete width_;
width_ = nullptr;
delete period_;
period_ = nullptr;
delete skew_;
skew_ = nullptr;
delete nochange_;
nochange_ = nullptr;
delete output_setup_;
output_setup_ = nullptr;
delete output_hold_;
output_hold_ = nullptr;
delete gated_clk_setup_;
gated_clk_setup_ = nullptr;
delete gated_clk_hold_;
gated_clk_hold_ = nullptr;
delete latch_setup_;
latch_setup_ = nullptr;
delete latch_hold_;
latch_hold_ = nullptr;
delete data_check_setup_;
data_check_setup_ = nullptr;
delete data_check_hold_;
data_check_hold_ = nullptr;
delete non_seq_setup_;
non_seq_setup_ = nullptr;
delete non_seq_hold_;
non_seq_hold_ = nullptr;
delete clock_tree_path_min_;
clock_tree_path_min_ = nullptr;
delete clock_tree_path_max_;
clock_tree_path_max_ = nullptr;
timing_roles_.clear();
}
const TimingRole TimingRole::wire_("wire", false, false, false, nullptr, nullptr, 0);
const TimingRole TimingRole::combinational_("combinational", true, false, false,
nullptr, nullptr, 1);
const TimingRole TimingRole::tristate_enable_("tristate enable",
true, false, false,
nullptr, nullptr, 2);
const TimingRole TimingRole::tristate_disable_("tristate disable",
true, false, false,
nullptr, nullptr, 3);
const TimingRole TimingRole::reg_clk_q_("Reg Clk to Q", true, false, false,
nullptr, nullptr, 4);
const TimingRole TimingRole::reg_set_clr_("Reg Set/Clr", true, false, false,
nullptr, nullptr, 5);
const TimingRole TimingRole::latch_en_q_("Latch En to Q", true, false, false,
nullptr, TimingRole::regClkToQ(), 6);
const TimingRole TimingRole::latch_d_q_("Latch D to Q", true, false, false,
nullptr, nullptr, 7);
const TimingRole TimingRole::sdf_iopath_("sdf IOPATH", true, false, false,
nullptr, nullptr, 8);
const TimingRole TimingRole::setup_("setup", false, true, false,
MinMax::max(), nullptr, 9);
const TimingRole TimingRole::hold_("hold", false, true, false,
MinMax::min(), nullptr, 10);
const TimingRole TimingRole::recovery_("recovery", false, true, false,
MinMax::max(), TimingRole::setup(), 11);
const TimingRole TimingRole::removal_("removal", false, true, false,
MinMax::min(), TimingRole::hold(), 12);
const TimingRole TimingRole::width_("width", false, true, false,
nullptr, nullptr, 13);
const TimingRole TimingRole::period_("period", false, true, false,
nullptr, nullptr, 14);
const TimingRole TimingRole::skew_("skew", false, true, false,
nullptr, nullptr, 15);
const TimingRole TimingRole::nochange_("nochange", true, false, false,
nullptr, nullptr, 16);
const TimingRole TimingRole::output_setup_("output setup", false, true, false,
MinMax::max(), TimingRole::setup(), 17);
const TimingRole TimingRole::output_hold_("output hold", false, true, false,
MinMax::min(), TimingRole::hold(), 18);
const TimingRole TimingRole::gated_clk_setup_("clock gating setup",
false, true, false,
MinMax::max(), TimingRole::setup(),19);
const TimingRole TimingRole::gated_clk_hold_("clock gating hold", false, true, false,
MinMax::min(), TimingRole::hold(),20);
const TimingRole TimingRole::latch_setup_("latch setup", false, true, false,
MinMax::max(), TimingRole::setup(),21);
const TimingRole TimingRole::latch_hold_("latch hold", false, true, false,
MinMax::min(), TimingRole::hold(),22);
const TimingRole TimingRole::data_check_setup_("data check setup",
false, true, false,
MinMax::max(),TimingRole::setup(),23);
const TimingRole TimingRole::data_check_hold_("data check hold", false, true, false,
MinMax::min(), TimingRole::hold(), 24);
const TimingRole TimingRole::non_seq_setup_("non-sequential setup", false, true, true,
MinMax::max(), TimingRole::setup(), 25);
const TimingRole TimingRole::non_seq_hold_("non-sequential hold", false, true, true,
MinMax::min(), TimingRole::hold(), 26);
const TimingRole TimingRole::clock_tree_path_min_("min clock tree path", false, false,
false, MinMax::min(), nullptr, 27);
const TimingRole TimingRole::clock_tree_path_max_("max clock tree path", false, false,
false, MinMax::max(), nullptr, 28);
TimingRole::TimingRole(const char *name,
bool is_sdf_iopath,
bool is_timing_check,
bool is_non_seq_check,
MinMax *path_min_max,
TimingRole *generic_role,
const MinMax *path_min_max,
const TimingRole *generic_role,
int index) :
name_(name),
is_timing_check_(is_timing_check),
@ -210,7 +107,7 @@ TimingRole::TimingRole(const char *name,
timing_roles_[name] = this;
}
TimingRole *
const TimingRole *
TimingRole::find(const char *name)
{
return timing_roles_[name];
@ -220,7 +117,7 @@ const TimingRole *
TimingRole::sdfRole() const
{
if (is_sdf_iopath_)
return sdf_iopath_;
return &sdf_iopath_;
else
return this;
}
@ -243,35 +140,35 @@ TimingRole::tgtClkEarlyLate() const
bool
TimingRole::isWire() const
{
return this == wire_;
return this == &wire_;
}
bool
TimingRole::isAsyncTimingCheck() const
{
return this == recovery_
|| this == removal_;
return this == &recovery_
|| this == &removal_;
}
bool
TimingRole::isDataCheck() const
{
return this == data_check_setup_
|| this == data_check_hold_;
return this == &data_check_setup_
|| this == &data_check_hold_;
}
bool
TimingRole::isLatchDtoQ() const
{
return this == latch_d_q_;
return this == &latch_d_q_;
}
bool
TimingRole::isTimingCheckBetween() const
{
return is_timing_check_
&& this != width_
&& this != period_;
&& this != &width_
&& this != &period_;
}
bool

View File

@ -45,9 +45,9 @@ static constexpr char escape_ = '\\';
ConcreteLibrary::ConcreteLibrary(const char *name,
const char *filename,
bool is_liberty) :
name_(stringCopy(name)),
name_(name),
id_(ConcreteNetwork::nextObjectId()),
filename_(stringCopy(filename)),
filename_(filename ? filename : ""),
is_liberty_(is_liberty),
bus_brkt_left_('['),
bus_brkt_right_(']')
@ -56,8 +56,6 @@ ConcreteLibrary::ConcreteLibrary(const char *name,
ConcreteLibrary::~ConcreteLibrary()
{
stringDelete(name_);
stringDelete(filename_);
cell_map_.deleteContents();
}
@ -131,9 +129,9 @@ ConcreteCell::ConcreteCell(const char *name,
const char *filename,
bool is_leaf,
ConcreteLibrary *library) :
name_(stringCopy(name)),
name_(name),
id_(ConcreteNetwork::nextObjectId()),
filename_(stringCopy(filename)),
filename_(filename ? filename : ""),
library_(library),
liberty_cell_(nullptr),
ext_cell_(nullptr),
@ -144,19 +142,14 @@ ConcreteCell::ConcreteCell(const char *name,
ConcreteCell::~ConcreteCell()
{
stringDelete(name_);
if (filename_)
stringDelete(filename_);
ports_.deleteContents();
}
void
ConcreteCell::setName(const char *name)
{
const char *name_cpy = stringCopy(name);
library_->renameCell(this, name_cpy);
stringDelete(name_);
name_ = name_cpy;
library_->renameCell(this, name);
name_ = name;
}
void
@ -422,7 +415,7 @@ ConcretePort::ConcretePort(const char *name,
bool is_bundle,
ConcretePortSeq *member_ports,
ConcreteCell *cell) :
name_(stringCopy(name)),
name_(name),
id_(ConcreteNetwork::nextObjectId()),
cell_(cell),
direction_(PortDirection::unknown()),
@ -444,7 +437,6 @@ ConcretePort::~ConcretePort()
if (is_bus_)
member_ports_->deleteContents();
delete member_ports_;
stringDelete(name_);
}
Cell *
@ -471,14 +463,14 @@ ConcretePort::busName() const
if (is_bus_) {
ConcreteLibrary *lib = cell_->library();
return stringPrintTmp("%s%c%d:%d%c",
name_,
name(),
lib->busBrktLeft(),
from_index_,
to_index_,
lib->busBrktRight());
}
else
return name_;
return name();
}
ConcretePort *

View File

@ -312,8 +312,8 @@ reduceToPiElmore(const Parasitic *parasitic_network,
if (drvr_node) {
debugPrint(sta->debug(), "parasitic_reduce", 1, "Reduce driver %s %s %s",
sta->network()->pathName(drvr_pin),
rf->asString(),
min_max->asString());
rf->to_string().c_str(),
min_max->to_string().c_str());
ReduceToPiElmore reducer(sta);
return reducer.makePiElmore(parasitic_network, drvr_pin, drvr_node,
coupling_cap_factor, rf, corner,

View File

@ -50,7 +50,7 @@
#include "DcalcAnalysisPt.hh"
#include "GraphDelayCalc.hh"
#include "Corner.hh"
#include "PathVertex.hh"
#include "Path.hh"
#include "search/Levelize.hh"
#include "search/Sim.hh"
#include "Search.hh"
@ -364,7 +364,7 @@ ActivitySrchPred::ActivitySrchPred(const StaState *sta) :
bool
ActivitySrchPred::searchThru(Edge *edge)
{
TimingRole *role = edge->role();
const TimingRole *role = edge->role();
return SearchPredNonLatch2::searchThru(edge)
&& role != TimingRole::regClkToQ();
}
@ -421,7 +421,7 @@ PropActivityVisitor::visit(Vertex *vertex)
Pin *pin = vertex->pin();
Instance *inst = network_->instance(pin);
debugPrint(debug_, "power_activity", 3, "visit %s",
vertex->name(network_));
vertex->to_string(this).c_str());
bool changed = false;
if (power_->hasUserActivity(pin)) {
PwrActivity &activity = power_->userActivity(pin);
@ -709,7 +709,7 @@ Power::seedActivities(BfsFwdIterator &bfs)
if (!sdc_->isLeafPinClock(pin)
&& !network_->direction(pin)->isInternal()) {
debugPrint(debug_, "power_activity", 3, "seed %s",
vertex->name(network_));
vertex->to_string(this).c_str());
if (hasUserActivity(pin))
setActivity(pin, userActivity(pin));
else
@ -743,7 +743,7 @@ Power::seedRegOutputActivities(const Instance *inst,
&& (func->port() == seq->output()
|| func->port() == seq->outputInv())) {
debugPrint(debug_, "power_reg", 1, "enqueue reg output %s",
vertex->name(network_));
vertex->to_string(this).c_str());
bfs.enqueue(vertex);
}
}
@ -870,7 +870,7 @@ Power::findInputInternalPower(const Pin *pin,
const char *related_pg_pin = pwr->relatedPgPin();
float energy = 0.0;
int rf_count = 0;
for (RiseFall *rf : RiseFall::range()) {
for (const RiseFall *rf : RiseFall::range()) {
float slew = getSlew(vertex, rf, corner);
if (!delayInf(slew)) {
float table_energy = pwr->power(rf, pvt, slew, load_cap);
@ -900,7 +900,7 @@ Power::findInputInternalPower(const Pin *pin,
float port_internal = energy * duty * activity.density();
debugPrint(debug_, "power", 2, " %3s %6s %.2f %.2f %9.2e %9.2e %s",
port->name(),
when ? when->asString() : "",
when ? when->to_string().c_str() : "",
activity.density() * 1e-9,
duty,
energy,
@ -1031,9 +1031,9 @@ Power::findOutputInternalPower(const LibertyPort *to_port,
}
float energy = 0.0;
int rf_count = 0;
for (RiseFall *to_rf : RiseFall::range()) {
for (const RiseFall *to_rf : RiseFall::range()) {
// Use unateness to find from_rf.
RiseFall *from_rf = positive_unate ? to_rf : to_rf->opposite();
const RiseFall *from_rf = positive_unate ? to_rf : to_rf->opposite();
float slew = from_vertex
? getSlew(from_vertex, from_rf, corner)
: 0.0;
@ -1058,7 +1058,7 @@ Power::findOutputInternalPower(const LibertyPort *to_port,
debugPrint(debug_, "power", 2, "%3s -> %-3s %6s %.3f %.3f %.3f %9.2e %9.2e %s",
from_corner_port ? from_corner_port->name() : "-" ,
to_port->name(),
when ? when->asString() : "",
when ? when->to_string().c_str() : "",
to_activity.density() * 1e-9,
duty,
weight,
@ -1189,7 +1189,7 @@ Power::findLeakagePower(const Instance *inst,
float cond_duty = cond_activity.duty();
debugPrint(debug_, "power", 2, "leakage %s %s %.3e * %.2f",
cell->name(),
when->asString(),
when->to_string().c_str(),
leak->power(),
cond_duty);
cond_leakage += leak->power() * cond_duty;
@ -1339,7 +1339,7 @@ Power::findClk(const Pin *to_pin)
if (to_vertex) {
VertexPathIterator path_iter(to_vertex, this);
while (path_iter.hasNext()) {
PathVertex *path = path_iter.next();
Path *path = path_iter.next();
const Clock *path_clk = path->clock(this);
if (path_clk
&& (clk == nullptr

View File

@ -535,10 +535,10 @@ Clock::isDivideByOneCombinational() const
////////////////////////////////////////////////////////////////
ClockEdge::ClockEdge(Clock *clock,
RiseFall *rf) :
const RiseFall *rf) :
clock_(clock),
rf_(rf),
name_(stringPrint("%s %s", clock_->name(), rf_->asString())),
name_(stringPrint("%s %s", clock_->name(), rf_->to_string().c_str())),
time_(0.0),
index_(clock_->index() * RiseFall::index_count + rf_->index())
{
@ -671,7 +671,7 @@ InterClockUncertainty::removeUncertainty(const RiseFallBoth *src_rf,
}
const RiseFallMinMax *
InterClockUncertainty::uncertainties(RiseFall *src_rf) const
InterClockUncertainty::uncertainties(const RiseFall *src_rf) const
{
return &uncertainties_[src_rf->index()];
}

View File

@ -79,10 +79,10 @@ CycleAcctings::reportClkToClkMaxCycleWarnings(Report *report)
// duplicate warnings between different src/tgt clk edges.
ClockPairSet clk_warnings;
for (Clock *src_clk : *sdc_->clocks()) {
for (RiseFall *src_rf : RiseFall::range()) {
for (const RiseFall *src_rf : RiseFall::range()) {
ClockEdge *src = src_clk->edge(src_rf);
for (Clock *tgt_clk : *sdc_->clocks()) {
for (RiseFall *tgt_rf : RiseFall::range()) {
for (const RiseFall *tgt_rf : RiseFall::range()) {
ClockEdge *tgt = tgt_clk->edge(tgt_rf);
CycleAccting probe(src, tgt);
CycleAccting *acct = cycle_acctings_.findKey(&probe);
@ -320,7 +320,7 @@ CycleAccting::setHoldAccting(int src_cycle,
}
void
CycleAccting::setAccting(TimingRole *role,
CycleAccting::setAccting(const TimingRole *role,
int src_cycle,
int tgt_cycle,
float delay,

View File

@ -80,7 +80,7 @@ DataCheck::empty() const
}
void
DataCheck::marginIsOneValue(SetupHold *setup_hold,
DataCheck::marginIsOneValue(const SetupHold *setup_hold,
// Return values.
float &value,
bool &one_value) const

View File

@ -320,7 +320,7 @@ ExceptionPath::fromThruToString(const Network *network) const
string str;
if (min_max_ != MinMaxAll::all()) {
str += " -";
str += min_max_->asString();
str += min_max_->to_string();
}
if (from_)

View File

@ -81,7 +81,7 @@ PortDelay::setNetworkLatencyIncluded(bool included)
network_latency_included_ = included;
}
RiseFall *
const RiseFall *
PortDelay::refTransition() const
{
// Reference pin transition is the clock transition.

View File

@ -3836,7 +3836,7 @@ Sdc::exceptionToInvalid(const Pin *pin)
if (port) {
LibertyCell *cell = port->libertyCell();
for (TimingArcSet *arc_set : cell->timingArcSets(nullptr, port)) {
TimingRole *role = arc_set->role();
const TimingRole *role = arc_set->role();
if (role->genericRole() == TimingRole::regClkToQ())
return true;
}

View File

@ -1433,6 +1433,6 @@ slew(const RiseFall *rf,
%extend ClockEdge {
Clock *clock() { return self->clock(); }
RiseFall *transition() { return self->transition(); }
const RiseFall *transition() { return self->transition(); }
float time() { return self->time(); }
}

View File

@ -43,131 +43,7 @@ proc_redirect read_sdc {
set echo [info exists flags(-echo)]
set filename [file nativename [lindex $args 0]]
set prev_filename [info script]
try {
info script $filename
source_ $filename $echo 0
} finally {
info script $prev_filename
}
}
################################################################
# The builtin Tcl "source" command is redefined by sta.
# This rename provides a mechanism to refer to the original TCL
# command.
# Protected so this file can be reloaded without blowing up.
if { ![info exists renamed_source] } {
rename source builtin_source
set renamed_source 1
}
set ::sta_continue_on_error 0
define_cmd_args "source" \
{[-echo] [-verbose] filename [> filename] [>> filename]}
# Override source to support -echo and return codes.
proc_redirect source {
parse_key_args "source" args keys {-encoding} flags {-echo -verbose}
if { [llength $args] != 1 } {
cmd_usage_error "source"
}
set echo [info exists flags(-echo)]
set verbose [info exists flags(-verbose)]
set filename [file nativename [lindex $args 0]]
set prev_filename [info script]
try {
info script $filename
source_ $filename $echo $verbose
} finally {
info script $prev_filename
}
}
proc source_ { filename echo verbose } {
global sta_continue_on_error
variable sdc_file
variable sdc_line
if [catch {open $filename r} stream] {
sta_error 340 "cannot open '$filename'."
} else {
if { [file extension $filename] == ".gz" } {
if { [info commands zlib] == "" } {
sta_error 339 "tcl version > 8.6 required for zlib support."
}
zlib push gunzip $stream
}
# Save file and line in recursive call to source.
if { [info exists sdc_file] } {
set sdc_file_save $sdc_file
set sdc_line_save $sdc_line
}
set sdc_file $filename
set sdc_line 1
set cmd ""
set error {}
while {![eof $stream]} {
gets $stream line
if { $line != "" } {
if {$echo} {
report_line $line
}
}
append cmd $line "\n"
if { [string index $line end] != "\\" \
&& [info complete $cmd] } {
set error {}
set error_code [catch {uplevel \#0 $cmd} result]
# cmd consumed
set cmd ""
# Flush results printed outside tcl to stdout/stderr.
fflush
switch $error_code {
0 { if { $verbose && $result != "" } { report_line $result } }
1 { set error $result }
2 { set error {invoked "return" outside of a proc.} }
3 { set error {invoked "break" outside of a loop.} }
4 { set error {invoked "continue" outside of a loop.} }
}
if { $error != {} } {
if { $sta_continue_on_error } {
# Only prepend error message with file/line once.
if { [string first "Error" $error] == 0 } {
report_line $error
} else {
report_line "Error: [file tail $sdc_file], $sdc_line $error"
}
set error {}
} else {
break
}
}
}
incr sdc_line
}
close $stream
if { $cmd != {} } {
sta_error 341 "incomplete command at end of file."
}
set error_sdc_file $sdc_file
set error_sdc_line $sdc_line
if { [info exists sdc_file_save] } {
set sdc_file $sdc_file_save
set sdc_line $sdc_line_save
} else {
unset sdc_file
unset sdc_line
}
if { $error != {} } {
# Only prepend error message with file/line once.
if { [string first "Error" $error] == 0 } {
error $error
} else {
error "Error: [file tail $error_sdc_file], $error_sdc_line $error"
}
}
}
include_file $filename $echo 0
}
################################################################
@ -1355,15 +1231,8 @@ proc group_path { args } {
}
proc check_exception_pins { from to } {
variable sdc_file
variable sdc_line
if { [info exists sdc_file] } {
set file $sdc_file
set line $sdc_line
} else {
set file ""
set line 0
}
set file [sdc_filename]
set line [sdc_file_line]
check_exception_from_pins $from $file $line
check_exception_to_pins $to $file $line
}

View File

@ -1180,7 +1180,7 @@ void
WriteSdc::writeDisabledEdgeSense(Edge *edge) const
{
gzprintf(stream_, "set_disable_timing ");
const char *sense = timingSenseString(edge->sense());
const char *sense = to_string(edge->sense());
string filter;
stringPrint(filter, "sense == %s", sense);
writeGetTimingArcs(edge, filter.c_str());
@ -1451,9 +1451,9 @@ WriteSdc::writeDataCheck(DataCheck *check) const
void
WriteSdc::writeDataCheck(DataCheck *check,
RiseFallBoth *from_rf,
RiseFallBoth *to_rf,
SetupHold *setup_hold,
const RiseFallBoth *from_rf,
const RiseFallBoth *to_rf,
const SetupHold *setup_hold,
float margin) const
{
const char *from_key = "-from";

View File

@ -121,9 +121,9 @@ public:
void writeDataChecks() const;
void writeDataCheck(DataCheck *check) const;
void writeDataCheck(DataCheck *check,
RiseFallBoth *from_rf,
RiseFallBoth *to_rf,
SetupHold *setup_hold,
const RiseFallBoth *from_rf,
const RiseFallBoth *to_rf,
const SetupHold *setup_hold,
float margin) const;
void writeEnvironment() const;
void writeOperatingConditions() const;

View File

@ -93,7 +93,7 @@ protected:
int index,
int &total,
int &annotated_total);
void reportCheckCount(TimingRole *role,
void reportCheckCount(const TimingRole *role,
int &total,
int &annotated_total);
int roleIndex(const TimingRole *role,
@ -284,14 +284,14 @@ ReportAnnotated::reportCheckCounts()
}
void
ReportAnnotated::reportCheckCount(TimingRole *role,
ReportAnnotated::reportCheckCount(const TimingRole *role,
int &total,
int &annotated_total)
{
int index = role->index();
if (edge_count_[index] > 0) {
string title;
stringPrint(title, "cell %s arcs", role->asString());
stringPrint(title, "cell %s arcs", role->to_string().c_str());
reportCount(title.c_str(), index, total, annotated_total);
}
}
@ -478,13 +478,13 @@ ReportAnnotated::reportArcs(Vertex *vertex,
while (edge_iter.hasNext()
&& (max_lines_ == 0 || i < max_lines_)) {
Edge *edge = edge_iter.next();
TimingRole *role = edge->role();
const TimingRole *role = edge->role();
const Pin *to_pin = edge->to(graph_)->pin();
if (graph_->delayAnnotated(edge) == report_annotated
&& report_role_[roleIndex(role, from_pin, to_pin)]) {
const char *role_name;
if (role->isTimingCheck())
role_name = role->asString();
role_name = role->to_string().c_str();
else if (role->isWire()) {
if (network_->isTopLevelPort(from_pin))
role_name = "primary input net";

View File

@ -66,7 +66,7 @@ sta::SdfParse::error(const location_type &loc,
sta::SdfTriple *triple;
sta::SdfTripleSeq *delval_list;
sta::SdfPortSpec *port_spec;
sta::Transition *transition;
const sta::Transition *transition;
}
%token DELAYFILE SDFVERSION DESIGN DATE VENDOR PROGRAM PVERSION

View File

@ -430,7 +430,7 @@ SdfReader::findPort(const Cell *cell,
}
void
SdfReader::timingCheck(TimingRole *role,
SdfReader::timingCheck(const TimingRole *role,
SdfPortSpec *data_edge,
SdfPortSpec *clk_edge,
SdfTriple *triple)
@ -450,7 +450,7 @@ SdfReader::timingCheck(TimingRole *role,
}
void
SdfReader::timingCheck1(TimingRole *role,
SdfReader::timingCheck1(const TimingRole *role,
Port *data_port,
SdfPortSpec *data_edge,
Port *clk_port,
@ -498,7 +498,7 @@ SdfReader::timingCheck1(TimingRole *role,
network_->cellName(instance_),
network_->name(data_port),
network_->name(clk_port),
role->asString());
role->to_string().c_str());
}
}
}
@ -509,7 +509,7 @@ SdfReader::annotateCheckEdges(Pin *data_pin,
SdfPortSpec *data_edge,
Pin *clk_pin,
SdfPortSpec *clk_edge,
TimingRole *sdf_role,
const TimingRole *sdf_role,
SdfTriple *triple,
bool match_generic)
{
@ -600,8 +600,8 @@ SdfReader::timingCheckSetupHold1(SdfPortSpec *data_edge,
SdfPortSpec *clk_edge,
SdfTriple *setup_triple,
SdfTriple *hold_triple,
TimingRole *setup_role,
TimingRole *hold_role)
const TimingRole *setup_role,
const TimingRole *hold_role)
{
const string *data_port_name = data_edge->port();
const string *clk_port_name = clk_edge->port();
@ -754,7 +754,7 @@ SdfReader::setEdgeArcDelaysCondUse(Edge *edge,
float **values = triple->values();
float *value_min = values[triple_min_index_];
float *value_max = values[triple_max_index_];
MinMax *min, *max;
const MinMax *min, *max;
if (cond_use_ == MinMaxAll::min()) {
min = MinMax::min();
max = MinMax::min();
@ -826,7 +826,7 @@ SdfReader::condMatch(const string *sdf_cond,
}
SdfPortSpec *
SdfReader::makePortSpec(Transition *tr,
SdfReader::makePortSpec(const Transition *tr,
const string *port,
const string *cond)
{

View File

@ -92,7 +92,7 @@ public:
SdfTripleSeq *triples,
const string *cond,
bool condelse);
void timingCheck(TimingRole *role,
void timingCheck(const TimingRole *role,
SdfPortSpec *data_edge,
SdfPortSpec *clk_edge,
SdfTriple *triple);
@ -112,8 +112,8 @@ public:
SdfPortSpec *clk_edge,
SdfTriple *setup_triple,
SdfTriple *hold_triple,
TimingRole *setup_role,
TimingRole *hold_role);
const TimingRole *setup_role,
const TimingRole *hold_role);
void timingCheckNochange(SdfPortSpec *data_edge,
SdfPortSpec *clk_edge,
SdfTriple *before_triple,
@ -132,7 +132,7 @@ public:
void deleteTriple(SdfTriple *triple);
SdfTripleSeq *makeTripleSeq();
void deleteTripleSeq(SdfTripleSeq *triples);
SdfPortSpec *makePortSpec(Transition *tr,
SdfPortSpec *makePortSpec(const Transition *tr,
const string *port,
const string *cond);
SdfPortSpec *makeCondPortSpec(const string *cond_port);
@ -160,14 +160,14 @@ private:
const char *filename);
Edge *findCheckEdge(Pin *from_pin,
Pin *to_pin,
TimingRole *sdf_role,
const TimingRole *sdf_role,
const string *cond_start,
const string *cond_end);
Edge *findWireEdge(Pin *from_pin,
Pin *to_pin);
bool condMatch(const string *sdf_cond,
const char *lib_cond);
void timingCheck1(TimingRole *role,
void timingCheck1(const TimingRole *role,
Port *data_port,
SdfPortSpec *data_edge,
Port *clk_port,
@ -177,7 +177,7 @@ private:
SdfPortSpec *data_edge,
Pin *clk_pin,
SdfPortSpec *clk_edge,
TimingRole *sdf_role,
const TimingRole *sdf_role,
SdfTriple *triple,
bool match_generic);
Pin *findPin(const string *name);

View File

@ -104,7 +104,7 @@ protected:
const char *sdfEdge(const Transition *tr);
void writeArcDelays(Edge *edge);
void writeSdfTriple(RiseFallMinMax &delays,
RiseFall *rf);
const RiseFall *rf);
void writeSdfTriple(float min,
float max);
void writeSdfDelay(double delay);
@ -176,11 +176,13 @@ SdfWriter::write(const char *filename,
timescale_ = default_lib->units()->timeUnit()->scale();
corner_ = corner;
MinMax *min_max;
const MinMax *min_max;
const DcalcAnalysisPt *dcalc_ap;
min_max = MinMax::min();
dcalc_ap = corner_->findDcalcAnalysisPt(min_max);
arc_delay_min_index_ = dcalc_ap->index();
min_max = MinMax::max();
dcalc_ap = corner_->findDcalcAnalysisPt(min_max);
arc_delay_max_index_ = dcalc_ap->index();
@ -376,7 +378,7 @@ SdfWriter::writeIopaths(const Instance *inst,
VertexOutEdgeIterator edge_iter(from_vertex, graph_);
while (edge_iter.hasNext()) {
Edge *edge = edge_iter.next();
TimingRole *role = edge->role();
const TimingRole *role = edge->role();
if (role == TimingRole::combinational()
|| role == TimingRole::tristateEnable()
|| role == TimingRole::regClkToQ()
@ -437,7 +439,7 @@ SdfWriter::writeArcDelays(Edge *edge)
RiseFallMinMax delays;
TimingArcSet *arc_set = edge->timingArcSet();
for (TimingArc *arc : arc_set->arcs()) {
RiseFall *rf = arc->toEdge()->asRiseFall();
const RiseFall *rf = arc->toEdge()->asRiseFall();
ArcDelay min_delay = graph_->arcDelay(edge, arc, arc_delay_min_index_);
delays.setValue(rf, MinMax::min(), delayAsFloat(min_delay));
@ -470,7 +472,7 @@ SdfWriter::writeArcDelays(Edge *edge)
void
SdfWriter::writeSdfTriple(RiseFallMinMax &delays,
RiseFall *rf)
const RiseFall *rf)
{
float min = delays.value(rf, MinMax::min());
float max = delays.value(rf, MinMax::max());
@ -513,7 +515,7 @@ SdfWriter::writeTimingChecks(const Instance *inst,
VertexOutEdgeIterator edge_iter(vertex, graph_);
while (edge_iter.hasNext()) {
Edge *edge = edge_iter.next();
TimingRole *role = edge->role();
const TimingRole *role = edge->role();
const char *sdf_check = nullptr;
if (role == TimingRole::setup())
sdf_check = "SETUP";
@ -590,8 +592,8 @@ SdfWriter::writeCheck(Edge *edge,
TimingArc *arcs[RiseFall::index_count][RiseFall::index_count] =
{{nullptr, nullptr}, {nullptr, nullptr}};
for (TimingArc *arc : arc_set->arcs()) {
RiseFall *clk_rf = arc->fromEdge()->asRiseFall();
RiseFall *data_rf = arc->toEdge()->asRiseFall();;
const RiseFall *clk_rf = arc->fromEdge()->asRiseFall();
const RiseFall *data_rf = arc->toEdge()->asRiseFall();;
arcs[clk_rf->index()][data_rf->index()] = arc;
}

View File

@ -89,7 +89,7 @@ BfsIterator::clear()
}
void
BfsIterator::reportEntries(const Network *network)
BfsIterator::reportEntries()
{
Level level = first_level_;
while (levelLessOrEqual(level, last_level_)) {
@ -98,7 +98,7 @@ BfsIterator::reportEntries(const Network *network)
report_->reportLine("Level %d", level);
for (Vertex *vertex : level_vertices) {
if (vertex)
report_->reportLine(" %s", vertex->name(network));
report_->reportLine(" %s", vertex->to_string(this).c_str());
}
}
incrLevel(level);
@ -262,7 +262,8 @@ BfsIterator::findNext(Level to_level)
void
BfsIterator::enqueue(Vertex *vertex)
{
debugPrint(debug_, "bfs", 2, "enqueue %s", vertex->name(sdc_network_));
debugPrint(debug_, "bfs", 2, "enqueue %s",
vertex->to_string(this).c_str());
if (!vertex->bfsInQueue(bfs_index_)) {
Level level = vertex->level();
LockGuard lock(queue_lock_);
@ -295,12 +296,12 @@ BfsIterator::checkInQueue(Vertex *vertex)
if (vertex->bfsInQueue(bfs_index_))
return;
else
printf("extra %s\n", vertex->name(sdc_network_));
printf("extra %s\n", vertex->to_string(this).c_str());
}
}
}
if (vertex->bfsInQueue(bfs_index_))
printf("missing %s\n", vertex->name(sdc_network_));
printf("missing %s\n", vertex->to_string(this).c_str());
}
void

View File

@ -30,7 +30,7 @@
#include "Network.hh"
#include "Graph.hh"
#include "Clock.hh"
#include "PathVertex.hh"
#include "Path.hh"
#include "PathAnalysisPt.hh"
#include "Search.hh"
@ -195,17 +195,17 @@ CheckMaxSkews:: visitMaxSkewChecks(Vertex *vertex,
Vertex *ref_vertex = edge->from(graph);
TimingArcSet *arc_set = edge->timingArcSet();
for (TimingArc *arc : arc_set->arcs()) {
RiseFall *clk_rf = arc->fromEdge()->asRiseFall();
RiseFall *ref_rf = arc->toEdge()->asRiseFall();
const RiseFall *clk_rf = arc->fromEdge()->asRiseFall();
const RiseFall *ref_rf = arc->toEdge()->asRiseFall();
VertexPathIterator clk_path_iter(vertex, clk_rf, clk_min_max, search);
while (clk_path_iter.hasNext()) {
PathVertex *clk_path = clk_path_iter.next();
Path *clk_path = clk_path_iter.next();
if (clk_path->isClock(search)) {
const PathAnalysisPt *clk_ap = clk_path->pathAnalysisPt(sta_);
PathAnalysisPt *ref_ap = clk_ap->tgtClkAnalysisPt();
VertexPathIterator ref_path_iter(ref_vertex, ref_rf, ref_ap, sta_);
while (ref_path_iter.hasNext()) {
PathVertex *ref_path = ref_path_iter.next();
Path *ref_path = ref_path_iter.next();
if (ref_path->isClock(search)) {
MaxSkewCheck check(clk_path, ref_path, arc, edge);
visitor->visit(check, sta_);
@ -220,8 +220,8 @@ CheckMaxSkews:: visitMaxSkewChecks(Vertex *vertex,
////////////////////////////////////////////////////////////////
MaxSkewCheck::MaxSkewCheck(PathVertex *clk_path,
PathVertex *ref_path,
MaxSkewCheck::MaxSkewCheck(Path *clk_path,
Path *ref_path,
TimingArc *check_arc,
Edge *check_edge) :
clk_path_(clk_path),
@ -234,34 +234,34 @@ MaxSkewCheck::MaxSkewCheck(PathVertex *clk_path,
Pin *
MaxSkewCheck::clkPin(const StaState *sta) const
{
return clk_path_.pin(sta);
return clk_path_->pin(sta);
}
Pin *
MaxSkewCheck::refPin(const StaState *sta) const
{
return ref_path_.pin(sta);
return ref_path_->pin(sta);
}
ArcDelay
MaxSkewCheck::maxSkew(const StaState *sta) const
{
Search *search = sta->search();
return search->deratedDelay(ref_path_.vertex(sta),
return search->deratedDelay(ref_path_->vertex(sta),
check_arc_, check_edge_, false,
clk_path_.pathAnalysisPt(sta));
clk_path_->pathAnalysisPt(sta));
}
Delay
MaxSkewCheck::skew(const StaState *sta) const
MaxSkewCheck::skew() const
{
return Delay(clk_path_.arrival(sta) - ref_path_.arrival(sta));
return Delay(clk_path_->arrival() - ref_path_->arrival());
}
Slack
MaxSkewCheck::slack(const StaState *sta) const
{
return maxSkew(sta) - skew(sta);
return maxSkew(sta) - skew();
}
////////////////////////////////////////////////////////////////

View File

@ -28,7 +28,7 @@
#include "Delay.hh"
#include "StaState.hh"
#include "SearchClass.hh"
#include "PathRef.hh"
#include "Path.hh"
namespace sta {
@ -57,22 +57,22 @@ protected:
class MaxSkewCheck
{
public:
MaxSkewCheck(PathVertex *clk_path,
PathVertex *ref_path,
MaxSkewCheck(Path *clk_path,
Path *ref_path,
TimingArc *check_arc,
Edge *check_edge);
const PathVertex *clkPath() const { return &clk_path_; }
const Path *clkPath() const { return clk_path_; }
Pin *clkPin(const StaState *sta) const;
const PathVertex *refPath() const { return &ref_path_; }
const Path *refPath() const { return ref_path_; }
Pin *refPin(const StaState *sta) const;
Delay skew(const StaState *sta) const;
Delay skew() const;
ArcDelay maxSkew(const StaState *sta) const;
Slack slack(const StaState *sta) const;
TimingArc *checkArc() const { return check_arc_; }
private:
PathVertex clk_path_;
PathVertex ref_path_;
Path *clk_path_;
Path *ref_path_;
TimingArc *check_arc_;
Edge *check_edge_;
};

View File

@ -35,8 +35,7 @@
#include "GraphDelayCalc.hh"
#include "ClkInfo.hh"
#include "Tag.hh"
#include "PathVertex.hh"
#include "PathRef.hh"
#include "Path.hh"
#include "Corner.hh"
#include "PathAnalysisPt.hh"
#include "SearchPred.hh"
@ -246,12 +245,12 @@ visitMinPulseWidthChecks(MinPulseWidthCheckVisitor *visitor)
{
Graph *graph = sta_->graph();
Debug *debug = sta_->debug();
Network *sdc_network = sta_->network();
VertexIterator vertex_iter(graph);
while (vertex_iter.hasNext()) {
Vertex *vertex = vertex_iter.next();
if (isClkEnd(vertex, graph)) {
debugPrint(debug, "mpw", 1, "check mpw %s", vertex->name(sdc_network));
debugPrint(debug, "mpw", 1, "check mpw %s",
vertex->to_string(sta_).c_str());
visitMinPulseWidthChecks(vertex, visitor);
}
}
@ -275,10 +274,9 @@ visitMinPulseWidthChecks(Vertex *vertex,
minPulseWidth(path, sta_, min_width, exists);
if (exists) {
MinPulseWidthCheck check(path);
PathVertex close_path;
check.closePath(sta_, close_path);
Path *close_path = check.closePath(sta_);
// Don't bother visiting if nobody is home.
if (!close_path.isNull())
if (close_path)
visitor->visit(check, sta_);
}
}
@ -289,7 +287,7 @@ visitMinPulseWidthChecks(Vertex *vertex,
////////////////////////////////////////////////////////////////
MinPulseWidthCheck::MinPulseWidthCheck() :
open_path_()
open_path_(nullptr)
{
}
@ -301,31 +299,29 @@ MinPulseWidthCheck::MinPulseWidthCheck(Path *open_path) :
MinPulseWidthCheck *
MinPulseWidthCheck::copy()
{
return new MinPulseWidthCheck(&open_path_);
return new MinPulseWidthCheck(open_path_);
}
Pin *
MinPulseWidthCheck::pin(const StaState *sta) const
{
return open_path_.pin(sta);
return open_path_->pin(sta);
}
const RiseFall *
MinPulseWidthCheck::openTransition(const StaState *sta) const
{
return open_path_.transition(sta);
return open_path_->transition(sta);
}
void
MinPulseWidthCheck::closePath(const StaState *sta,
// Return value.
PathVertex &close) const
Path *
MinPulseWidthCheck::closePath(const StaState *sta) const
{
PathAnalysisPt *open_ap = open_path_.pathAnalysisPt(sta);
PathAnalysisPt *open_ap = open_path_->pathAnalysisPt(sta);
PathAnalysisPt *close_ap = open_ap->tgtClkAnalysisPt();
const RiseFall *open_rf = open_path_.transition(sta);
const RiseFall *open_rf = open_path_->transition(sta);
const RiseFall *close_rf = open_rf->opposite();
Tag *open_tag = open_path_.tag(sta);
Tag *open_tag = open_path_->tag(sta);
ClkInfo *open_clk_info = open_tag->clkInfo();
ClkInfo close_clk_info(open_clk_info->clkEdge()->opposite(),
open_clk_info->clkSrc(),
@ -335,7 +331,7 @@ MinPulseWidthCheck::closePath(const StaState *sta,
open_clk_info->pulseClkSense(),
delay_zero, 0.0, nullptr,
open_clk_info->pathAPIndex(),
open_clk_info->crprClkPath(),
open_clk_info->crprClkPath(sta),
sta);
Tag close_tag(0,
close_rf->index(),
@ -347,34 +343,33 @@ MinPulseWidthCheck::closePath(const StaState *sta,
open_tag->states(),
false, sta);
debugPrint(sta->debug(), "mpw", 3, " open %s",
open_tag->asString(sta));
open_tag->to_string(sta).c_str());
debugPrint(sta->debug(), "mpw", 3, " close %s",
close_tag.asString(sta));
VertexPathIterator close_iter(open_path_.vertex(sta), close_rf,
close_tag.to_string(sta).c_str());
VertexPathIterator close_iter(open_path_->vertex(sta), close_rf,
close_ap, sta);
while (close_iter.hasNext()) {
PathVertex *close_path = close_iter.next();
Path *close_path = close_iter.next();
if (tagMatchNoPathAp(close_path->tag(sta), &close_tag)) {
debugPrint(sta->debug(), "mpw", 3, " match %s",
close_path->tag(sta)->asString(sta));
close = close_path;
break;
close_path->tag(sta)->to_string(sta).c_str());
return close_path;
}
}
return nullptr;
}
Arrival
MinPulseWidthCheck::openArrival(const StaState *sta) const
MinPulseWidthCheck::openArrival(const StaState *) const
{
return open_path_.arrival(sta);
return open_path_->arrival();
}
Arrival
MinPulseWidthCheck::closeArrival(const StaState *sta) const
{
PathVertex close;
closePath(sta, close);
return close.arrival(sta);
Path *close = closePath(sta);
return close->arrival();
}
Arrival
@ -392,13 +387,13 @@ MinPulseWidthCheck::closeDelay(const StaState *sta) const
const ClockEdge *
MinPulseWidthCheck::openClkEdge(const StaState *sta) const
{
return open_path_.clkEdge(sta->search());
return open_path_->clkEdge(sta->search());
}
const ClockEdge *
MinPulseWidthCheck::closeClkEdge(const StaState *sta) const
{
Tag *open_tag = open_path_.tag(sta);
Tag *open_tag = open_path_->tag(sta);
ClkInfo *open_clk_info = open_tag->clkInfo();
return open_clk_info->clkEdge()->opposite();
}
@ -418,7 +413,7 @@ Arrival
MinPulseWidthCheck::width(const StaState *sta) const
{
return closeArrival(sta) + closeOffset(sta)
- open_path_.arrival(sta)
- open_path_->arrival()
+ checkCrpr(sta);
}
@ -427,7 +422,7 @@ MinPulseWidthCheck::minWidth(const StaState *sta) const
{
float min_width;
bool exists;
minPulseWidth(&open_path_, sta, min_width, exists);
minPulseWidth(open_path_, sta, min_width, exists);
return min_width;
}
@ -469,10 +464,9 @@ Crpr
MinPulseWidthCheck::checkCrpr(const StaState *sta) const
{
CheckCrpr *check_crpr = sta->search()->checkCrpr();
PathVertex close;
closePath(sta, close);
if (!close.isNull())
return check_crpr->checkCrpr(openPath(), &close);
Path *close = closePath(sta);
if (close)
return check_crpr->checkCrpr(openPath(), close);
else
return 0.0;
}
@ -486,7 +480,7 @@ MinPulseWidthCheck::slack(const StaState *sta) const
Corner *
MinPulseWidthCheck::corner(const StaState *sta) const
{
return open_path_.pathAnalysisPt(sta)->corner();
return open_path_->pathAnalysisPt(sta)->corner();
}
////////////////////////////////////////////////////////////////

View File

@ -27,7 +27,7 @@
#include "SdcClass.hh"
#include "SearchClass.hh"
#include "StaState.hh"
#include "PathRef.hh"
#include "Path.hh"
namespace sta {
@ -75,13 +75,11 @@ public:
Arrival width(const StaState *sta) const;
float minWidth(const StaState *sta) const;
Slack slack(const StaState *sta) const;
Path *openPath() { return &open_path_; }
Path *openPath() { return open_path_; }
Corner *corner(const StaState *sta) const;
const Path *openPath() const { return &open_path_; }
const Path *openPath() const { return open_path_; }
Arrival openArrival(const StaState *sta) const;
void closePath(const StaState *sta,
// Return value.
PathVertex &close) const;
Path *closePath(const StaState *sta) const;
Arrival closeArrival(const StaState *sta) const;
Arrival openDelay(const StaState *sta) const;
Arrival closeDelay(const StaState *sta) const;
@ -92,7 +90,7 @@ public:
protected:
// Open path of the pulse.
PathRef open_path_;
Path *open_path_;
};
class MinPulseWidthSlackLess

View File

@ -34,7 +34,7 @@
#include "GraphDelayCalc.hh"
#include "StaState.hh"
#include "Corner.hh"
#include "PathVertex.hh"
#include "Path.hh"
#include "PortDirection.hh"
#include "Search.hh"
#include "ClkNetwork.hh"

View File

@ -38,7 +38,7 @@
#include "Bfs.hh"
#include "Search.hh"
#include "Genclks.hh"
#include "PathVertex.hh"
#include "Path.hh"
#include "Sim.hh"
namespace sta {
@ -246,9 +246,11 @@ CheckTiming::checkUnconstraintedOutputs(PinSet &unconstrained_ends)
while (pin_iter->hasNext()) {
Pin *pin = pin_iter->next();
PortDirection *dir = network_->direction(pin);
Vertex *vertex = graph_->pinLoadVertex(pin);
if (dir->isAnyOutput()
&& !((hasClkedDepature(pin)
&& hasClkedArrival(graph_->pinLoadVertex(pin)))
&& !vertex->isConstant()
&& !((hasClkedDepature(pin)
&& hasClkedArrival(vertex))
|| hasMaxDelay(pin)))
unconstrained_ends.insert(pin);
}
@ -294,14 +296,16 @@ CheckTiming::checkUnconstrainedSetups(PinSet &unconstrained_ends)
VertexIterator vertex_iter(graph_);
while (vertex_iter.hasNext()) {
Vertex *vertex = vertex_iter.next();
VertexInEdgeIterator edge_iter(vertex, graph_);
while (edge_iter.hasNext()) {
Edge *edge = edge_iter.next();
if (edge->role() == TimingRole::setup()
&& (!search_->isClock(edge->from(graph_))
|| !hasClkedArrival(edge->to(graph_)))) {
unconstrained_ends.insert(vertex->pin());
break;
if (!vertex->isConstant()) {
VertexInEdgeIterator edge_iter(vertex, graph_);
while (edge_iter.hasNext()) {
Edge *edge = edge_iter.next();
if (edge->role() == TimingRole::setup()
&& (!search_->isClock(edge->from(graph_))
|| !hasClkedArrival(edge->to(graph_)))) {
unconstrained_ends.insert(vertex->pin());
break;
}
}
}
}
@ -312,7 +316,7 @@ CheckTiming::hasClkedArrival(Vertex *vertex)
{
VertexPathIterator path_iter(vertex, this);
while (path_iter.hasNext()) {
PathVertex *path = path_iter.next();
Path *path = path_iter.next();
if (path->clock(this))
return true;
}

View File

@ -27,7 +27,7 @@
#include "MinMax.hh"
#include "StaState.hh"
#include "Transition.hh"
#include "PathVertex.hh"
#include "Path.hh"
namespace sta {
@ -43,7 +43,7 @@ public:
Delay &delay,
float &internal_latency,
Delay &latency,
PathVertex &path,
Path &path,
bool &exists) const;
void latency(const RiseFall *src_rf,
const RiseFall *end_rf,
@ -51,28 +51,28 @@ public:
// Return values.
Delay &delay,
bool &exists) const;
static Delay latency(PathVertex *clk_path,
static Delay latency(Path *clk_path,
StaState *sta);
void setLatency(const RiseFall *src_rf,
const RiseFall *end_rf,
const MinMax *min_max,
PathVertex *path,
Path *path,
bool include_internal_latency,
StaState *sta);
private:
static float insertionDelay(PathVertex *clk_path,
static float insertionDelay(Path *clk_path,
StaState *sta);
static float delay(PathVertex *clk_path,
static float delay(Path *clk_path,
StaState *sta);
static float clkTreeDelay(PathVertex *clk_path,
static float clkTreeDelay(Path *clk_path,
StaState *sta);
Delay insertion_[RiseFall::index_count][RiseFall::index_count][MinMax::index_count];
Delay delay_[RiseFall::index_count][RiseFall::index_count][MinMax::index_count];
float internal_latency_[RiseFall::index_count][RiseFall::index_count][MinMax::index_count];
Delay latency_[RiseFall::index_count][RiseFall::index_count][MinMax::index_count];
PathVertex path_[RiseFall::index_count][RiseFall::index_count][MinMax::index_count];
Path path_[RiseFall::index_count][RiseFall::index_count][MinMax::index_count];
bool exists_[RiseFall::index_count][RiseFall::index_count][MinMax::index_count];
};

View File

@ -53,12 +53,12 @@ ClkInfo::ClkInfo(const ClockEdge *clk_edge,
float latency,
ClockUncertainties *uncertainties,
PathAPIndex path_ap_index,
PathVertexPtr &crpr_clk_path,
Path *crpr_clk_path,
const StaState *sta) :
clk_edge_(clk_edge),
clk_src_(clk_src),
gen_clk_src_(gen_clk_src),
crpr_clk_path_(crpr_clk_path),
crpr_clk_path_(is_propagated ? crpr_clk_path : nullptr),
uncertainties_(uncertainties),
insertion_(insertion),
latency_(latency),
@ -87,7 +87,7 @@ ClkInfo::findHash(const StaState *sta)
hashIncr(hash_, network->vertexId(clk_src_));
if (gen_clk_src_)
hashIncr(hash_, network->vertexId(gen_clk_src_));
hashIncr(hash_, crprClkVertexId());
hashIncr(hash_, crprClkVertexId(sta));
if (uncertainties_) {
float uncertainty;
bool exists;
@ -108,12 +108,24 @@ ClkInfo::findHash(const StaState *sta)
}
VertexId
ClkInfo::crprClkVertexId() const
ClkInfo::crprClkVertexId(const StaState *sta) const
{
if (crpr_clk_path_.isNull())
return 0;
return vertex_id_null;
else
return crpr_clk_path_.vertexId();
return crpr_clk_path_.vertexId(sta);
}
Path *
ClkInfo::crprClkPath(const StaState *sta)
{
return Path::vertexPath(crpr_clk_path_, sta);
}
const Path *
ClkInfo::crprClkPath(const StaState *sta) const
{
return Path::vertexPath(crpr_clk_path_, sta);
}
const char *
@ -124,7 +136,7 @@ ClkInfo::asString(const StaState *sta) const
string result;
PathAnalysisPt *path_ap = corners->findPathAnalysisPt(path_ap_index_);
result += path_ap->pathMinMax()->asString();
result += path_ap->pathMinMax()->to_string();
result += "/";
result += std::to_string(path_ap_index_);
@ -162,7 +174,7 @@ ClkInfo::clock() const
return nullptr;
}
RiseFall *
const RiseFall *
ClkInfo::pulseClkSense() const
{
if (is_pulse_clk_)
@ -213,8 +225,9 @@ clkInfoEqual(const ClkInfo *clk_info1,
&& clk_info1->clkSrc() == clk_info2->clkSrc()
&& clk_info1->genClkSrc() == clk_info2->genClkSrc()
&& (!crpr_on
|| (PathVertexPtr::equal(clk_info1->crprClkPath(),
clk_info2->crprClkPath())))
|| Path::equal(clk_info1->crprClkPath(sta),
clk_info2->crprClkPath(sta),
sta))
&& ((uncertainties1 == nullptr
&& uncertainties2 == nullptr)
|| (uncertainties1 && uncertainties2
@ -279,9 +292,9 @@ clkInfoCmp(const ClkInfo *clk_info1,
bool crpr_on = sta->sdc()->crprActive();
if (crpr_on) {
const PathVertexPtr &crpr_path1 = clk_info1->crprClkPath();
const PathVertexPtr &crpr_path2 = clk_info2->crprClkPath();
int path_cmp = PathVertexPtr::cmp(crpr_path1, crpr_path2);
const Path *crpr_path1 = clk_info1->crprClkPath(sta);
const Path *crpr_path2 = clk_info2->crprClkPath(sta);
int path_cmp = Path::cmp(crpr_path1, crpr_path2, sta);
if (path_cmp != 0)
return path_cmp;
}

View File

@ -26,12 +26,12 @@
#include "Transition.hh"
#include "SearchClass.hh"
#include "PathVertexPtr.hh"
#include "Sdc.hh"
#include "Path.hh"
namespace sta {
class PathVertex;
class Path;
class ClkInfo
{
@ -46,7 +46,7 @@ public:
float latency,
ClockUncertainties *uncertainties,
PathAPIndex path_ap_index,
PathVertexPtr &crpr_clk_path,
Path *crpr_clk_path,
const StaState *sta);
~ClkInfo();
const char *asString(const StaState *sta) const;
@ -56,7 +56,7 @@ public:
bool isPropagated() const { return is_propagated_; }
const Pin *genClkSrc() const { return gen_clk_src_; }
bool isPulseClk() const { return is_pulse_clk_; }
RiseFall *pulseClkSense() const;
const RiseFall *pulseClkSense() const;
int pulseClkSenseTrIndex() const { return pulse_clk_sense_; }
float latency() const { return latency_; }
Arrival &insertion() { return insertion_; }
@ -65,9 +65,9 @@ public:
PathAPIndex pathAPIndex() const { return path_ap_index_; }
// Clock path used for crpr resolution.
// Null for clocks because the path cannot point to itself.
PathVertexPtr &crprClkPath() { return crpr_clk_path_; }
const PathVertexPtr &crprClkPath() const { return crpr_clk_path_; }
VertexId crprClkVertexId() const;
Path *crprClkPath(const StaState *sta);
const Path *crprClkPath(const StaState *sta) const;
VertexId crprClkVertexId(const StaState *sta) const;
bool hasCrprClkPin() const { return !crpr_clk_path_.isNull(); }
bool refsFilter(const StaState *sta) const;
// This clk_info/tag is used for a generated clock source path.
@ -81,7 +81,7 @@ private:
const ClockEdge *clk_edge_;
const Pin *clk_src_;
const Pin *gen_clk_src_;
PathVertexPtr crpr_clk_path_;
Path crpr_clk_path_;
ClockUncertainties *uncertainties_;
Arrival insertion_;
float latency_;

View File

@ -33,7 +33,7 @@
#include "Network.hh"
#include "Clock.hh"
#include "Graph.hh"
#include "PathVertex.hh"
#include "Path.hh"
#include "StaState.hh"
#include "Search.hh"
#include "PathAnalysisPt.hh"
@ -88,7 +88,7 @@ ClkLatency::reportClkLatency(const Clock *clk,
report_->reportLine("Clock %s", clk->name());
for (const RiseFall *src_rf : RiseFall::range()) {
for (const RiseFall *end_rf : RiseFall::range()) {
PathVertex path_min;
Path path_min;
Delay insertion_min;
Delay delay_min;
float internal_latency_min;
@ -97,7 +97,7 @@ ClkLatency::reportClkLatency(const Clock *clk,
clk_delays.delay(src_rf, end_rf, MinMax::min(), insertion_min,
delay_min, internal_latency_min, latency_min,
path_min, exists_min);
PathVertex path_max;
Path path_max;
Delay insertion_max;
Delay delay_max;
float internal_latency_max;
@ -153,7 +153,7 @@ ClkLatency::findClkDelays(ConstClockSeq &clks,
for (Vertex *clk_vertex : *graph_->regClkVertices()) {
VertexPathIterator path_iter(clk_vertex, this);
while (path_iter.hasNext()) {
PathVertex *path = path_iter.next();
Path *path = path_iter.next();
const ClockEdge *path_clk_edge = path->clkEdge(this);
const PathAnalysisPt *path_ap = path->pathAnalysisPt(this);
if (path_clk_edge
@ -206,7 +206,7 @@ ClkDelays::delay(const RiseFall *src_rf,
Delay &delay,
float &lib_clk_delay,
Delay &latency,
PathVertex &path,
Path &path,
bool &exists) const
{
int src_rf_index = src_rf->index();
@ -239,7 +239,7 @@ void
ClkDelays::setLatency(const RiseFall *src_rf,
const RiseFall *end_rf,
const MinMax *min_max,
PathVertex *path,
Path *path,
bool include_internal_latency,
StaState *sta)
{
@ -267,7 +267,7 @@ ClkDelays::setLatency(const RiseFall *src_rf,
}
Delay
ClkDelays::latency(PathVertex *clk_path,
ClkDelays::latency(Path *clk_path,
StaState *sta)
{
@ -278,16 +278,16 @@ ClkDelays::latency(PathVertex *clk_path,
}
float
ClkDelays::delay(PathVertex *clk_path,
ClkDelays::delay(Path *clk_path,
StaState *sta)
{
Arrival arrival = clk_path->arrival(sta);
Arrival arrival = clk_path->arrival();
const ClockEdge *path_clk_edge = clk_path->clkEdge(sta);
return delayAsFloat(arrival) - path_clk_edge->time();
}
float
ClkDelays::insertionDelay(PathVertex *clk_path,
ClkDelays::insertionDelay(Path *clk_path,
StaState *sta)
{
const ClockEdge *clk_edge = clk_path->clkEdge(sta);
@ -302,7 +302,7 @@ ClkDelays::insertionDelay(PathVertex *clk_path,
}
float
ClkDelays::clkTreeDelay(PathVertex *clk_path,
ClkDelays::clkTreeDelay(Path *clk_path,
StaState *sta)
{
const Vertex *vertex = clk_path->vertex(sta);

View File

@ -30,7 +30,7 @@
#include "StaState.hh"
#include "Transition.hh"
#include "SearchClass.hh"
#include "PathVertex.hh"
#include "Path.hh"
#include "ClkDelays.hh"
namespace sta {

View File

@ -38,7 +38,7 @@
#include "Graph.hh"
#include "Sdc.hh"
#include "Bfs.hh"
#include "PathVertex.hh"
#include "Path.hh"
#include "StaState.hh"
#include "PathAnalysisPt.hh"
#include "SearchPred.hh"
@ -55,14 +55,14 @@ class ClkSkew
{
public:
ClkSkew();
ClkSkew(PathVertex *src_path,
PathVertex *tgt_path,
ClkSkew(Path *src_path,
Path *tgt_path,
bool include_internal_latency,
StaState *sta);
ClkSkew(const ClkSkew &clk_skew);
void operator=(const ClkSkew &clk_skew);
PathVertex *srcPath() { return &src_path_; }
PathVertex *tgtPath() { return &tgt_path_; }
Path *srcPath() { return src_path_; }
Path *tgtPath() { return tgt_path_; }
float srcLatency(const StaState *sta);
float tgtLatency(const StaState *sta);
float srcInternalClkLatency(const StaState *sta);
@ -75,23 +75,25 @@ public:
const StaState *sta);
private:
float clkTreeDelay(PathVertex &clk_path,
float clkTreeDelay(Path *clk_path,
const StaState *sta);
PathVertex src_path_;
PathVertex tgt_path_;
Path *src_path_;
Path *tgt_path_;
bool include_internal_latency_;
float skew_;
};
ClkSkew::ClkSkew() :
src_path_(nullptr),
tgt_path_(nullptr),
include_internal_latency_(false),
skew_(0.0)
{
}
ClkSkew::ClkSkew(PathVertex *src_path,
PathVertex *tgt_path,
ClkSkew::ClkSkew(Path *src_path,
Path *tgt_path,
bool include_internal_latency,
StaState *sta) :
src_path_(src_path),
@ -124,8 +126,8 @@ ClkSkew::operator=(const ClkSkew &clk_skew)
float
ClkSkew::srcLatency(const StaState *sta)
{
Arrival src_arrival = src_path_.arrival(sta);
return delayAsFloat(src_arrival) - src_path_.clkEdge(sta)->time()
Arrival src_arrival = src_path_->arrival();
return delayAsFloat(src_arrival) - src_path_->clkEdge(sta)->time()
+ clkTreeDelay(src_path_, sta);
}
@ -138,8 +140,8 @@ ClkSkew::srcInternalClkLatency(const StaState *sta)
float
ClkSkew::tgtLatency(const StaState *sta)
{
Arrival tgt_arrival = tgt_path_.arrival(sta);
return delayAsFloat(tgt_arrival) - tgt_path_.clkEdge(sta)->time()
Arrival tgt_arrival = tgt_path_->arrival();
return delayAsFloat(tgt_arrival) - tgt_path_->clkEdge(sta)->time()
+ clkTreeDelay(tgt_path_, sta);
}
@ -150,16 +152,16 @@ ClkSkew::tgtInternalClkLatency(const StaState *sta)
}
float
ClkSkew::clkTreeDelay(PathVertex &clk_path,
ClkSkew::clkTreeDelay(Path *clk_path,
const StaState *sta)
{
if (include_internal_latency_) {
const Vertex *vertex = clk_path.vertex(sta);
const Vertex *vertex = clk_path->vertex(sta);
const Pin *pin = vertex->pin();
const LibertyPort *port = sta->network()->libertyPort(pin);
const MinMax *min_max = clk_path.minMax(sta);
const RiseFall *rf = clk_path.transition(sta);
float slew = delayAsFloat(clk_path.slew(sta));
const MinMax *min_max = clk_path->minMax(sta);
const RiseFall *rf = clk_path->transition(sta);
float slew = delayAsFloat(clk_path->slew(sta));
return port->clkTreeDelay(slew, rf, min_max);
}
else
@ -170,17 +172,17 @@ Crpr
ClkSkew::crpr(const StaState *sta)
{
CheckCrpr *check_crpr = sta->search()->checkCrpr();
return check_crpr->checkCrpr(&src_path_, &tgt_path_);
return check_crpr->checkCrpr(src_path_, tgt_path_);
}
float
ClkSkew::uncertainty(const StaState *sta)
{
TimingRole *check_role = (src_path_.minMax(sta) == SetupHold::max())
const TimingRole *check_role = (src_path_->minMax(sta) == SetupHold::max())
? TimingRole::setup()
: TimingRole::hold();
// Uncertainty decreases slack, but increases skew.
return -PathEnd::checkTgtClkUncertainty(&tgt_path_, tgt_path_.clkEdge(sta),
return -PathEnd::checkTgtClkUncertainty(tgt_path_, tgt_path_->clkEdge(sta),
check_role, sta);
}
@ -240,8 +242,8 @@ ClkSkews::reportClkSkew(ClkSkew &clk_skew,
int digits)
{
Unit *time_unit = units_->timeUnit();
PathVertex *src_path = clk_skew.srcPath();
PathVertex *tgt_path = clk_skew.tgtPath();
Path *src_path = clk_skew.srcPath();
Path *tgt_path = clk_skew.tgtPath();
float src_latency = clk_skew.srcLatency(this);
float tgt_latency = clk_skew.tgtLatency(this);
float src_internal_clk_latency = clk_skew.srcInternalClkLatency(this);
@ -253,7 +255,7 @@ ClkSkews::reportClkSkew(ClkSkew &clk_skew,
report_->reportLine("%7s source latency %s %s",
time_unit->asString(src_latency, digits),
sdc_network_->pathName(src_path->pin(this)),
src_path->transition(this)->asString());
src_path->transition(this)->to_string().c_str());
if (src_internal_clk_latency != 0.0)
report_->reportLine("%7s source internal clock delay",
time_unit->asString(src_internal_clk_latency, digits));
@ -263,7 +265,7 @@ ClkSkews::reportClkSkew(ClkSkew &clk_skew,
report_->reportLine("%7s target latency %s %s",
time_unit->asString(-tgt_latency, digits),
sdc_network_->pathName(tgt_path->pin(this)),
tgt_path->transition(this)->asString());
tgt_path->transition(this)->to_string().c_str());
if (tgt_internal_clk_latency != 0.0)
report_->reportLine("%7s target internal clock delay",
time_unit->asString(-tgt_internal_clk_latency, digits));
@ -352,7 +354,7 @@ ClkSkews::hasClkPaths(Vertex *vertex)
{
VertexPathIterator path_iter(vertex, this);
while (path_iter.hasNext()) {
PathVertex *path = path_iter.next();
Path *path = path_iter.next();
const Clock *path_clk = path->clock(this);
if (clk_set_.find(path_clk) != clk_set_.end())
return true;
@ -389,7 +391,7 @@ ClkSkews::findClkSkewFrom(Vertex *src_vertex,
VertexInEdgeIterator edge_iter(end, graph_);
while (edge_iter.hasNext()) {
Edge *edge = edge_iter.next();
TimingRole *role = edge->role();
const TimingRole *role = edge->role();
if (role->isTimingCheck()
&& ((setup_hold_ == SetupHold::max()
&& role->genericRole() == TimingRole::setup())
@ -417,7 +419,7 @@ ClkSkews::findClkSkew(Vertex *src_vertex,
const SetupHold *tgt_min_max = setup_hold_->opposite();
VertexPathIterator src_iter(src_vertex, this);
while (src_iter.hasNext()) {
PathVertex *src_path = src_iter.next();
Path *src_path = src_iter.next();
const Clock *src_clk = src_path->clock(this);
if (src_rf->matches(src_path->transition(this))
&& src_path->minMax(this) == setup_hold_
@ -427,7 +429,7 @@ ClkSkews::findClkSkew(Vertex *src_vertex,
|| src_corner == corner_) {
VertexPathIterator tgt_iter(tgt_vertex, this);
while (tgt_iter.hasNext()) {
PathVertex *tgt_path = tgt_iter.next();
Path *tgt_path = tgt_iter.next();
const Clock *tgt_clk = tgt_path->clock(this);
if (tgt_clk == src_clk
&& tgt_path->isClock(this)
@ -439,14 +441,14 @@ ClkSkews::findClkSkew(Vertex *src_vertex,
debugPrint(debug_, "clk_skew", 2,
"%s %s %s -> %s %s %s crpr = %s skew = %s",
network_->pathName(src_path->pin(this)),
src_path->transition(this)->asString(),
src_path->transition(this)->to_string().c_str(),
time_unit->asString(probe.srcLatency(this)),
network_->pathName(tgt_path->pin(this)),
tgt_path->transition(this)->asString(),
tgt_path->transition(this)->to_string().c_str(),
time_unit->asString(probe.tgtLatency(this)),
delayAsString(probe.crpr(this), this),
time_unit->asString(probe.skew()));
if (clk_skew.srcPath()->isNull()
if (clk_skew.srcPath() == nullptr
|| abs(probe.skew()) > abs(clk_skew.skew()))
clk_skew = probe;
}
@ -497,7 +499,7 @@ FanOutSrchPred::FanOutSrchPred(const StaState *sta) :
bool
FanOutSrchPred::searchThru(Edge *edge)
{
TimingRole *role = edge->role();
const TimingRole *role = edge->role();
return SearchPred1::searchThru(edge)
&& (role == TimingRole::wire()
|| role == TimingRole::combinational()

View File

@ -32,7 +32,7 @@
#include "Transition.hh"
#include "SearchClass.hh"
#include "SearchPred.hh"
#include "PathVertex.hh"
#include "Path.hh"
namespace sta {

View File

@ -144,14 +144,14 @@ Corners::makeParasiticAnalysisPts(bool per_corner)
parasitic_analysis_pts_.resize(corners_.size() * MinMax::index_count);
for (Corner *corner : corners_) {
corner->setParasiticAnalysisPtcount(MinMax::index_count);
for (MinMax *min_max : MinMax::range()) {
for (const MinMax *min_max : MinMax::range()) {
int mm_index = min_max->index();
int ap_index = corner->index() * MinMax::index_count + mm_index;
int ap_index_max = corner->index() * MinMax::index_count
+ MinMax::max()->index();
string ap_name = corner->name();
ap_name += "_";
ap_name += min_max->asString();
ap_name += min_max->to_string();
ParasiticAnalysisPt *ap = new ParasiticAnalysisPt(ap_name.c_str(),
ap_index, ap_index_max);
parasitic_analysis_pts_[ap_index] = ap;
@ -163,10 +163,10 @@ Corners::makeParasiticAnalysisPts(bool per_corner)
// shared corner, per min/max
parasitic_analysis_pts_.resize(MinMax::index_count);
int ap_index_max = MinMax::max()->index();
for (MinMax *min_max : MinMax::range()) {
for (const MinMax *min_max : MinMax::range()) {
int mm_index = min_max->index();
int ap_index = mm_index;
ParasiticAnalysisPt *ap = new ParasiticAnalysisPt(min_max->asString(),
ParasiticAnalysisPt *ap = new ParasiticAnalysisPt(min_max->to_string().c_str(),
ap_index,
ap_index_max);
parasitic_analysis_pts_[ap_index] = ap;
@ -360,17 +360,12 @@ Corners::findPathAnalysisPt(PathAPIndex path_index) const
Corner::Corner(const char *name,
int index) :
name_(stringCopy(name)),
name_(name),
index_(index),
path_analysis_pts_(MinMax::index_count)
{
}
Corner::~Corner()
{
stringDelete(name_);
}
ParasiticAnalysisPt *
Corner::findParasiticAnalysisPt(const MinMax *min_max) const
{

View File

@ -32,8 +32,6 @@
#include "Network.hh"
#include "Graph.hh"
#include "Sdc.hh"
#include "PathVertex.hh"
#include "PathPrev.hh"
#include "Path.hh"
#include "PathAnalysisPt.hh"
#include "ClkInfo.hh"
@ -54,60 +52,26 @@ CheckCrpr::CheckCrpr(StaState *sta) :
{
}
void
CheckCrpr::clkPathPrev(const PathVertex *path,
PathVertex &prev)
{
Vertex *vertex = path->vertex(this);
int arrival_index;
bool exists;
path->arrivalIndex(arrival_index, exists);
PathPrev *prevs = graph_->prevPaths(vertex);
if (prevs)
prev.init(prevs[arrival_index], this);
else
criticalError(2200, "missing prev paths");
}
PathVertex
CheckCrpr::clkPathPrev(Vertex *vertex,
int arrival_index)
{
PathPrev *prevs = graph_->prevPaths(vertex);
if (prevs)
return PathVertex(prevs[arrival_index], this);
else {
criticalError(2201, "missing prev paths");
return PathVertex();
}
}
////////////////////////////////////////////////////////////////
// Find the maximum possible crpr (clock min/max delta delay) for a
// path from it's ClkInfo.
Arrival
CheckCrpr::maxCrpr(ClkInfo *clk_info)
{
const PathVertexPtr &crpr_clk_path = clk_info->crprClkPath();
if (!crpr_clk_path.isNull()) {
PathVertex crpr_clk_vpath(crpr_clk_path, this);
if (!crpr_clk_vpath.isNull()) {
Arrival other_arrival = otherMinMaxArrival(&crpr_clk_vpath);
float crpr_diff = abs(delayAsFloat(crpr_clk_vpath.arrival(this),
EarlyLate::late(),
this)
- delayAsFloat(other_arrival, EarlyLate::early(),
this));
return crpr_diff;
}
const Path *crpr_clk_path = clk_info->crprClkPath(this);
if (crpr_clk_path) {
Arrival other_arrival = otherMinMaxArrival(crpr_clk_path);
float crpr_diff = abs(delayAsFloat(crpr_clk_path->arrival(),
EarlyLate::late(),
this)
- delayAsFloat(other_arrival, EarlyLate::early(),
this));
return crpr_diff;
}
return 0.0F;
}
Arrival
CheckCrpr::otherMinMaxArrival(const PathVertex *path)
CheckCrpr::otherMinMaxArrival(const Path *path)
{
PathAnalysisPt *other_ap = path->pathAnalysisPt(this)->tgtClkAnalysisPt();
Tag *tag = path->tag(this);
@ -115,18 +79,18 @@ CheckCrpr::otherMinMaxArrival(const PathVertex *path)
path->transition(this),
other_ap, this);
while (other_iter.hasNext()) {
PathVertex *other = other_iter.next();
Path *other = other_iter.next();
if (tagMatchCrpr(other->tag(this), tag))
return other->arrival(this);
return other->arrival();
}
// No corresponding path found.
// Match the arrival so the difference is zero.
return path->arrival(this);
return path->arrival();
}
Crpr
CheckCrpr::checkCrpr(const Path *src_path,
const PathVertex *tgt_clk_path)
const Path *tgt_clk_path)
{
Crpr crpr;
Pin *crpr_pin;
@ -136,7 +100,7 @@ CheckCrpr::checkCrpr(const Path *src_path,
void
CheckCrpr::checkCrpr(const Path *src_path,
const PathVertex *tgt_clk_path,
const Path *tgt_clk_path,
// Return values.
Crpr &crpr,
Pin *&crpr_pin)
@ -152,7 +116,7 @@ CheckCrpr::checkCrpr(const Path *src_path,
void
CheckCrpr::checkCrpr1(const Path *src_path,
const PathVertex *tgt_clk_path,
const Path *tgt_clk_path,
bool same_pin,
// Return values.
Crpr &crpr,
@ -165,17 +129,11 @@ CheckCrpr::checkCrpr1(const Path *src_path,
ClkInfo *tgt_clk_info = tgt_clk_path->tag(this)->clkInfo();
const Clock *src_clk = src_clk_info->clock();
const Clock *tgt_clk = tgt_clk_info->clock();
PathVertex src_clk_path1;
const PathVertexPtr &src_crpr_clk_path = src_clk_info->crprClkPath();
const PathVertex *src_clk_path = nullptr;
if (src_tag->isClock()) {
src_clk_path1.init(src_path->vertex(this), src_path->tag(this), this);
src_clk_path = &src_clk_path1;
}
else if (!src_crpr_clk_path.isNull()) {
src_clk_path1.init(src_crpr_clk_path, this);
src_clk_path = &src_clk_path1;
}
const Path *src_clk_path = nullptr;
if (src_tag->isClock())
src_clk_path = src_path;
else
src_clk_path = src_clk_info->crprClkPath(this);
const MinMax *src_clk_min_max =
src_clk_path ? src_clk_path->minMax(this) : src_path->minMax(this);
if (src_clk && tgt_clk
@ -186,45 +144,40 @@ CheckCrpr::checkCrpr1(const Path *src_path,
// For path from latches that are borrowing the enable path
// is from the opposite min/max of the data.
&& src_clk_min_max != tgt_clk_path->minMax(this)
&& (src_clk_path != nullptr
&& (src_clk_path
|| src_clk->isGenerated())) {
// Src path from input port clk path can only be from generated clk path.
PathVertex port_clk_path;
if (src_clk_path == nullptr) {
portClkPath(src_clk_info->clkEdge(),
src_clk_info->clkSrc(),
src_path->pathAnalysisPt(this),
port_clk_path);
src_clk_path = &port_clk_path;
src_clk_path = portClkPath(src_clk_info->clkEdge(),
src_clk_info->clkSrc(),
src_path->pathAnalysisPt(this));
}
findCrpr(src_clk_path, tgt_clk_path, same_pin, crpr, crpr_pin);
}
}
// Find the clk path for an input/output port.
void
Path *
CheckCrpr::portClkPath(const ClockEdge *clk_edge,
const Pin *clk_src_pin,
const PathAnalysisPt *path_ap,
// Return value.
PathVertex &genclk_path)
const PathAnalysisPt *path_ap)
{
Vertex *clk_vertex = graph_->pinDrvrVertex(clk_src_pin);
VertexPathIterator path_iter(clk_vertex, clk_edge->transition(),
path_ap, this);
while (path_iter.hasNext()) {
PathVertex *path = path_iter.next();
Path *path = path_iter.next();
if (path->clkEdge(this) == clk_edge
&& path->isClock(this)) {
genclk_path = path;
break;
return path;
}
}
return nullptr;
}
void
CheckCrpr::findCrpr(const PathVertex *src_clk_path,
const PathVertex *tgt_clk_path,
CheckCrpr::findCrpr(const Path *src_clk_path,
const Path *tgt_clk_path,
bool same_pin,
// Return values.
Crpr &crpr,
@ -232,35 +185,33 @@ CheckCrpr::findCrpr(const PathVertex *src_clk_path,
{
crpr = 0.0;
crpr_pin = nullptr;
const PathVertex *src_clk_path1 = src_clk_path;
const PathVertex *tgt_clk_path1 = tgt_clk_path;
PathVertexSeq src_gclk_paths, tgt_gclk_paths;
const Path *src_clk_path1 = src_clk_path;
const Path *tgt_clk_path1 = tgt_clk_path;
if (src_clk_path1->clkInfo(this)->clkSrc()
!= tgt_clk_path1->clkInfo(this)->clkSrc()) {
// Push src/tgt genclk src paths into a vector,
// The last genclk src path is at index 0.
genClkSrcPaths(src_clk_path1, src_gclk_paths);
genClkSrcPaths(tgt_clk_path1, tgt_gclk_paths);
ConstPathSeq src_gclk_paths = genClkSrcPaths(src_clk_path1);
ConstPathSeq tgt_gclk_paths = genClkSrcPaths(tgt_clk_path1);
// Search from the first gen clk toward the end
// of the path to find a common root pin.
int i = src_gclk_paths.size() - 1;
int j = tgt_gclk_paths.size() - 1;
for (; i >= 0 && j >= 0; i--, j--) {
PathVertex &src_path = src_gclk_paths[i];
PathVertex &tgt_path = tgt_gclk_paths[j];
if (src_path.clkInfo(this)->clkSrc()
== tgt_path.clkInfo(this)->clkSrc()) {
src_clk_path1 = &src_gclk_paths[i];
tgt_clk_path1 = &tgt_gclk_paths[j];
const Path *src_path = src_gclk_paths[i];
const Path *tgt_path = tgt_gclk_paths[j];
if (src_path->clkInfo(this)->clkSrc()
== tgt_path->clkInfo(this)->clkSrc()) {
src_clk_path1 = src_gclk_paths[i];
tgt_clk_path1 = tgt_gclk_paths[j];
}
else
break;
}
}
const PathVertex *src_clk_path2 = src_clk_path1;
const PathVertex *tgt_clk_path2 = tgt_clk_path1;
PathVertex src_prev, tgt_prev;
// src_clk_path and tgt_clk_path are now in the same (gen)clk src path.
const Path *src_clk_path2 = src_clk_path1;
const Path *tgt_clk_path2 = tgt_clk_path1;
// src_clk_path2 and tgt_clk_path2 are now in the same (gen)clk src path.
// Use the vertex levels to back up the deeper path to see if they
// overlap.
int src_level = src_clk_path2->vertex(this)->level();
@ -268,21 +219,19 @@ CheckCrpr::findCrpr(const PathVertex *src_clk_path,
while (src_clk_path2->pin(this) != tgt_clk_path2->pin(this)) {
int level_diff = src_level - tgt_level;
if (level_diff >= 0) {
clkPathPrev(src_clk_path2, src_prev);
if (src_prev.isNull())
src_clk_path2 = src_clk_path2->prevPath();
if (src_clk_path2 == nullptr)
break;
src_clk_path2 = &src_prev;
src_level = src_clk_path2->vertex(this)->level();
}
if (level_diff <= 0) {
clkPathPrev(tgt_clk_path2, tgt_prev);
if (tgt_prev.isNull())
tgt_clk_path2 = tgt_clk_path2->prevPath();
if (tgt_clk_path2 == nullptr)
break;
tgt_clk_path2 = &tgt_prev;
tgt_level = tgt_clk_path2->vertex(this)->level();
}
}
if (!src_clk_path2->isNull() && !tgt_clk_path2->isNull()
if (src_clk_path2 && tgt_clk_path2
&& (src_clk_path2->transition(this) == tgt_clk_path2->transition(this)
|| same_pin)) {
debugPrint(debug_, "crpr", 2, "crpr pin %s",
@ -292,30 +241,31 @@ CheckCrpr::findCrpr(const PathVertex *src_clk_path,
}
}
void
CheckCrpr::genClkSrcPaths(const PathVertex *path,
PathVertexSeq &gclk_paths)
ConstPathSeq
CheckCrpr::genClkSrcPaths(const Path *path)
{
ConstPathSeq gclk_paths;
ClkInfo *clk_info = path->clkInfo(this);
const ClockEdge *clk_edge = clk_info->clkEdge();
const Pin *clk_src = clk_info->clkSrc();
PathAnalysisPt *path_ap = path->pathAnalysisPt(this);
gclk_paths.push_back(path);
Genclks *genclks = search_->genclks();
while (clk_edge->clock()->isGenerated()) {
PathVertex genclk_path =
search_->genclks()->srcPath(clk_edge, clk_src, path_ap);
if (genclk_path.isNull())
Path *genclk_path = genclks->srcPath(clk_edge, clk_src, path_ap);
if (genclk_path == nullptr)
break;
clk_info = genclk_path.clkInfo(this);
clk_info = genclk_path->clkInfo(this);
clk_src = clk_info->clkSrc();
clk_edge = clk_info->clkEdge();
gclk_paths.push_back(genclk_path);
}
return gclk_paths;
}
Crpr
CheckCrpr::findCrpr1(const PathVertex *src_clk_path,
const PathVertex *tgt_clk_path)
CheckCrpr::findCrpr1(const Path *src_clk_path,
const Path *tgt_clk_path)
{
if (pocv_enabled_) {
// Remove variation on the common path.
@ -323,8 +273,8 @@ CheckCrpr::findCrpr1(const PathVertex *src_clk_path,
// sigma of the common clock path.
const EarlyLate *src_el = src_clk_path->minMax(this);
const EarlyLate *tgt_el = tgt_clk_path->minMax(this);
Arrival src_arrival = src_clk_path->arrival(this);
Arrival tgt_arrival = tgt_clk_path->arrival(this);
Arrival src_arrival = src_clk_path->arrival();
Arrival tgt_arrival = tgt_clk_path->arrival();
float src_clk_time = src_clk_path->clkEdge(this)->time();
float tgt_clk_time = tgt_clk_path->clkEdge(this)->time();
float crpr_mean = abs(delayAsFloat(src_arrival) - src_clk_time
@ -352,10 +302,10 @@ CheckCrpr::findCrpr1(const PathVertex *src_clk_path,
}
float
CheckCrpr::crprArrivalDiff(const PathVertex *path)
CheckCrpr::crprArrivalDiff(const Path *path)
{
Arrival other_arrival = otherMinMaxArrival(path);
float crpr_diff = abs(delayAsFloat(path->arrival(this))
float crpr_diff = abs(delayAsFloat(path->arrival())
- delayAsFloat(other_arrival));
return crpr_diff;
}
@ -407,13 +357,12 @@ CheckCrpr::outputDelayCrpr1(const Path *src_path,
&& tgt_clk->isGenerated()
&& tgt_clk->isPropagated()
&& crprPossible(src_clk, tgt_clk)) {
PathVertex tgt_genclk_path;
portClkPath(tgt_clk_edge, tgt_clk_edge->clock()->defaultPin(), tgt_path_ap,
tgt_genclk_path);
PathVertex src_clk_path(src_path->clkInfo(this)->crprClkPath(), this);
if (!src_clk_path.isNull()) {
findCrpr(&src_clk_path, &tgt_genclk_path, same_pin, crpr, crpr_pin);
}
Path *tgt_genclk_path = portClkPath(tgt_clk_edge,
tgt_clk_edge->clock()->defaultPin(),
tgt_path_ap);
Path *src_clk_path = src_path->clkInfo(this)->crprClkPath(this);
if (src_clk_path)
findCrpr(src_clk_path, tgt_genclk_path, same_pin, crpr, crpr_pin);
}
}

View File

@ -42,9 +42,9 @@ public:
Arrival maxCrpr(ClkInfo *clk_info);
// Timing check CRPR.
Crpr checkCrpr(const Path *src_clk_path,
const PathVertex *tgt_clk_path);
const Path *tgt_clk_path);
void checkCrpr(const Path *src_path,
const PathVertex *tgt_clk_path,
const Path *tgt_clk_path,
// Return values.
Crpr &crpr,
Pin *&crpr_pin);
@ -57,18 +57,12 @@ public:
Crpr &crpr,
Pin *&crpr_pin);
// Previous clk path when crpr is enabled.
PathVertex clkPathPrev(const PathVertex *path);
// For Search::reportArrivals.
PathVertex clkPathPrev(Vertex *vertex,
int arrival_index);
private:
void clkPathPrev(const PathVertex *path,
PathVertex &prev);
Arrival otherMinMaxArrival(const PathVertex *path);
void clkPathPrev(const Path *path,
Path &prev);
Arrival otherMinMaxArrival(const Path *path);
void checkCrpr1(const Path *src_path,
const PathVertex *tgt_clk_path,
const Path *tgt_clk_path,
bool same_pin,
// Return values.
Crpr &crpr,
@ -82,22 +76,19 @@ private:
Pin *&crpr_pin);
bool crprPossible(const Clock *clk1,
const Clock *clk2);
void genClkSrcPaths(const PathVertex *path,
PathVertexSeq &gclk_paths);
void findCrpr(const PathVertex *src_clk_path,
const PathVertex *tgt_clk_path,
ConstPathSeq genClkSrcPaths(const Path *path);
void findCrpr(const Path *src_clk_path,
const Path *tgt_clk_path,
bool same_pin,
// Return values.
Crpr &crpr,
Pin *&common_pin);
void portClkPath(const ClockEdge *clk_edge,
const Pin *clk_src_pin,
const PathAnalysisPt *path_ap,
// Return value.
PathVertex &port_clk_path);
Crpr findCrpr1(const PathVertex *src_clk_path,
const PathVertex *tgt_clk_path);
float crprArrivalDiff(const PathVertex *path);
Path *portClkPath(const ClockEdge *clk_edge,
const Pin *clk_src_pin,
const PathAnalysisPt *path_ap);
Crpr findCrpr1(const Path *src_clk_path,
const Path *tgt_clk_path);
float crprArrivalDiff(const Path *path);
};
} // namespace

View File

@ -76,7 +76,7 @@ FindRegClkPred::searchFrom(const Vertex *from_vertex)
bool
FindRegClkPred::searchThru(Edge *edge)
{
TimingRole *role = edge->role();
const TimingRole *role = edge->role();
return (role->isWire()
|| role == TimingRole::combinational())
&& SearchPred1::searchThru(edge);
@ -281,13 +281,13 @@ FindRegVisitor::findInferedSequential(LibertyCell *cell,
const RiseFall *clk_rf1 = clk_rf->asRiseFall();
for (TimingArcSet *arc_set : cell->timingArcSets()) {
TimingArc *arc = *arc_set->arcs().begin();
RiseFall *arc_clk_rf = arc->fromEdge()->asRiseFall();
const RiseFall *arc_clk_rf = arc->fromEdge()->asRiseFall();
bool tr_matches = (clk_rf == RiseFallBoth::riseFall()
|| (arc_clk_rf == clk_rf1
&& clk_sense == TimingSense::positive_unate)
|| (arc_clk_rf == clk_rf1->opposite()
&& clk_sense == TimingSense::negative_unate));
TimingRole *role = arc_set->role();
const TimingRole *role = arc_set->role();
if (tr_matches
&& ((role == TimingRole::regClkToQ()
&& edge_triggered)
@ -306,7 +306,7 @@ FindRegVisitor::hasTimingCheck(LibertyCell *cell,
LibertyPort *d)
{
for (TimingArcSet *arc_set : cell->timingArcSets(clk, d)) {
TimingRole *role = arc_set->role();
const TimingRole *role = arc_set->role();
if (role->isTimingCheck())
return true;
}
@ -542,7 +542,7 @@ FindRegClkPins::matchPin(Pin *pin)
LibertyPort *port = network_->libertyPort(pin);
LibertyCell *cell = port->libertyCell();
for (TimingArcSet *arc_set : cell->timingArcSets(port, nullptr)) {
TimingRole *role = arc_set->role();
const TimingRole *role = arc_set->role();
if (role == TimingRole::regClkToQ()
|| role == TimingRole::latchEnToQ())
return true;
@ -598,7 +598,7 @@ FindRegAsyncPins::matchPin(Pin *pin)
LibertyPort *port = network_->libertyPort(pin);
LibertyCell *cell = port->libertyCell();
for (TimingArcSet *arc_set : cell->timingArcSets(port, nullptr)) {
TimingRole *role = arc_set->role();
const TimingRole *role = arc_set->role();
if (role == TimingRole::regSetClr())
return true;
}
@ -645,7 +645,7 @@ FindRegOutputPins::matchPin(Pin *pin)
LibertyPort *port = network_->libertyPort(pin);
LibertyCell *cell = port->libertyCell();
for (TimingArcSet *arc_set : cell->timingArcSets(nullptr, port)) {
TimingRole *role = arc_set->role();
const TimingRole *role = arc_set->role();
if (role == TimingRole::regClkToQ()
|| role == TimingRole::latchEnToQ()
|| role == TimingRole::latchDtoQ())

View File

@ -238,11 +238,11 @@ GatedClk::functionClkOperands(FuncExpr *root_expr,
}
}
RiseFall *
const RiseFall *
GatedClk::gatedClkActiveTrans(LogicValue active_value,
const MinMax *min_max) const
{
RiseFall *leading_rf;
const RiseFall *leading_rf;
switch (active_value) {
case LogicValue::one:
case LogicValue::unknown:

View File

@ -46,8 +46,8 @@ public:
void gatedClkEnables(Vertex *clk_vertex,
// Return value.
PinSet &enable_pins);
RiseFall *gatedClkActiveTrans(LogicValue active_value,
const MinMax *min_max) const;
const RiseFall *gatedClkActiveTrans(LogicValue active_value,
const MinMax *min_max) const;
protected:
void isClkGatingFunc(FuncExpr *func,

View File

@ -40,7 +40,7 @@
#include "Corner.hh"
#include "PathAnalysisPt.hh"
#include "Levelize.hh"
#include "PathVertexPtr.hh"
#include "Path.hh"
#include "Search.hh"
namespace sta {
@ -137,7 +137,7 @@ Genclks::fanins(const Clock *clk)
}
Vertex *
Genclks::srcPathVertex(const Pin *pin) const
Genclks::srcPath(const Pin *pin) const
{
bool is_bidirect = network_->direction(pin)->isBidirect();
// Insertion delay is to the driver vertex for clks defined on
@ -155,7 +155,7 @@ Genclks::clkPinMaxLevel(const Clock *clk) const
{
Level max_level = 0;
for (const Pin *pin : clk->leafPins()) {
Vertex *vertex = srcPathVertex(pin);
Vertex *vertex = srcPath(pin);
max_level = max(max_level, vertex->level());
}
return max_level;
@ -209,9 +209,7 @@ Genclks::ensureInsertionDelays()
// insertion delay, so sort the clocks by source pin level.
sort(gclks, ClockPinMaxLevelLess(this));
ClockSeq::Iterator gclk_iter(gclks);
while (gclk_iter.hasNext()) {
Clock *gclk = gclk_iter.next();
for (Clock *gclk : gclks) {
if (gclk->masterClk()) {
findInsertionDelays(gclk);
recordSrcPaths(gclk);
@ -252,7 +250,7 @@ bool
GenClkMasterSearchPred::searchThru(Edge *edge)
{
const Sdc *sdc = sta_->sdc();
TimingRole *role = edge->role();
const TimingRole *role = edge->role();
// Propagate clocks through constants.
return !(edge->role()->isTimingCheck()
|| edge->isDisabledLoop()
@ -420,7 +418,7 @@ Genclks::findFanin(Clock *gclk,
if (!fanins->hasKey(vertex)) {
fanins->insert(vertex);
debugPrint(debug_, "genclk", 2, "gen clk %s fanin %s",
gclk->name(), vertex->name(sdc_network_));
gclk->name(), vertex->to_string(this).c_str());
iter.enqueueAdjacentVertices(vertex);
}
}
@ -546,7 +544,7 @@ Genclks::makeGenclkInfo(Clock *gclk)
VertexSet *fanins = new VertexSet(graph_);
findFanin(gclk, fanins);
GenclkInfo *genclk_info = new GenclkInfo(gclk, gclk_level, fanins,
src_filter);
src_filter);
genclk_info_map_.insert(gclk, genclk_info);
return genclk_info;
}
@ -629,9 +627,8 @@ Genclks::findLatchFdbkEdges(Vertex *from_vertex,
Edge *edge = edge_iter.next();
Vertex *to_vertex = edge->to(graph_);
if (path_vertices.hasKey(to_vertex)) {
debugPrint(debug_, "genclk", 2, " found feedback edge %s -> %s",
from_vertex->name(sdc_network_),
to_vertex->name(sdc_network_));
debugPrint(debug_, "genclk", 2, " found feedback edge %s",
edge->to_string(this).c_str());
if (fdbk_edges == nullptr)
fdbk_edges = new EdgeSet;
fdbk_edges->insert(edge);
@ -684,12 +681,12 @@ Genclks::seedSrcPins(Clock *gclk,
for (auto path_ap : corners_->pathAnalysisPts()) {
const MinMax *min_max = path_ap->pathMinMax();
const EarlyLate *early_late = min_max;
for (auto rf : RiseFall::range()) {
Tag *tag = makeTag(gclk, master_clk, master_pin, rf, src_filter,
path_ap);
for (const RiseFall *rf : RiseFall::range()) {
Tag *tag = makeTag(gclk, master_clk, master_pin, rf,
src_filter, path_ap);
Arrival insert = search_->clockInsertion(master_clk, master_pin, rf,
min_max, early_late, path_ap);
tag_bldr.setArrival(tag, insert, nullptr);
tag_bldr.setArrival(tag, insert);
}
}
search_->setVertexArrivals(vertex, &tag_bldr);
@ -824,7 +821,7 @@ GenclkSrcArrivalVisitor::visit(Vertex *vertex)
{
Genclks *genclks = search_->genclks();
debugPrint(debug_, "genclk", 2, "find gen clk insert arrival %s",
vertex->name(sdc_network_));
vertex->to_string(this).c_str());
tag_bldr_->init(vertex);
has_fanin_one_ = graph_->hasFaninOne(vertex);
genclks->copyGenClkSrcPaths(vertex, tag_bldr_);
@ -854,22 +851,14 @@ void
Genclks::copyGenClkSrcPaths(Vertex *vertex,
TagGroupBldr *tag_bldr)
{
Arrival *arrivals = graph_->arrivals(vertex);
if (arrivals) {
PathPrev *prev_paths = graph_->prevPaths(vertex);
Path *paths = graph_->paths(vertex);
if (paths) {
TagGroup *tag_group = search_->tagGroup(vertex);
if (tag_group) {
ArrivalMap::Iterator arrival_iter(tag_group->arrivalMap());
while (arrival_iter.hasNext()) {
Tag *tag;
int arrival_index;
arrival_iter.next(tag, arrival_index);
for (auto const [tag, path_index] : *tag_group->pathIndexMap()) {
if (tag->isGenClkSrcPath()) {
Arrival arrival = arrivals[arrival_index];
PathPrev *prev_path = prev_paths
? &prev_paths[arrival_index]
: nullptr;
tag_bldr->setArrival(tag, arrival, prev_path);
Path &path = paths[path_index];
tag_bldr->insertPath(path);
}
}
}
@ -881,11 +870,14 @@ Genclks::copyGenClkSrcPaths(Vertex *vertex,
void
Genclks::clearSrcPaths()
{
genclk_src_paths_.deleteArrayContents();
for (auto const & [clk_pin, src_paths] : genclk_src_paths_) {
for (const Path &src_path : src_paths)
delete src_path.prevPath();
}
genclk_src_paths_.clear();
}
int
size_t
Genclks::srcPathIndex(const RiseFall *clk_rf,
const PathAnalysisPt *path_ap) const
{
@ -903,40 +895,49 @@ Genclks::recordSrcPaths(Clock *gclk)
bool has_edges = gclk->edges() != nullptr;
for (const Pin *gclk_pin : gclk->leafPins()) {
PathVertexPtr *src_paths = new PathVertexPtr[path_count];
genclk_src_paths_.insert(ClockPinPair(gclk, gclk_pin), src_paths);
Vertex *gclk_vertex = srcPathVertex(gclk_pin);
vector<Path> &src_paths = genclk_src_paths_[ClockPinPair(gclk, gclk_pin)];
src_paths.resize(path_count);
Vertex *gclk_vertex = srcPath(gclk_pin);
bool found_src_paths = false;
VertexPathIterator path_iter(gclk_vertex, this);
while (path_iter.hasNext()) {
PathVertex *path = path_iter.next();
Path *path = path_iter.next();
const ClockEdge *src_clk_edge = path->clkEdge(this);
if (src_clk_edge
&& matchesSrcFilter(path, gclk)) {
const EarlyLate *early_late = path->minMax(this);
RiseFall *src_clk_rf = src_clk_edge->transition();
const RiseFall *src_clk_rf = src_clk_edge->transition();
const RiseFall *rf = path->transition(this);
bool inverting_path = (rf != src_clk_rf);
const PathAnalysisPt *path_ap = path->pathAnalysisPt(this);
int path_index = srcPathIndex(rf, path_ap);
PathVertexPtr &src_path = src_paths[path_index];
size_t path_index = srcPathIndex(rf, path_ap);
Path &src_path = src_paths[path_index];
if ((!divide_by_1
|| (inverting_path == invert))
&& (!has_edges
|| src_clk_rf == gclk->masterClkEdgeTr(rf))
&& (src_path.isNull()
|| delayGreater(path->arrival(this),
src_path.arrival(this),
|| delayGreater(path->arrival(),
src_path.arrival(),
early_late,
this))) {
debugPrint(debug_, "genclk", 2, " %s insertion %s %s %s",
network_->pathName(gclk_pin),
early_late->asString(),
rf->asString(),
delayAsString(path->arrival(this), this));
src_path.init(path, this);
found_src_paths = true;
early_late->to_string().c_str(),
rf->to_string().c_str(),
delayAsString(path->arrival(), this));
delete src_path.prevPath();
src_path = *path;
Path *prev_copy = &src_path;
Path *p = path->prevPath();
while (p) {
Path *copy = new Path(p);
copy->setIsEnum(true);
prev_copy->setPrevPath(copy);
prev_copy = copy;
p = p->prevPath();
}
found_src_paths = true;
}
}
}
@ -973,8 +974,8 @@ Genclks::matchesSrcFilter(Path *path,
return false;
}
PathVertex
Genclks::srcPath(Path *clk_path) const
Path *
Genclks::srcPath(const Path *clk_path) const
{
const Pin *src_pin = clk_path->pin(this);
const ClockEdge *clk_edge = clk_path->clkEdge(this);
@ -985,7 +986,7 @@ Genclks::srcPath(Path *clk_path) const
insert_ap);
}
PathVertex
Path *
Genclks::srcPath(const ClockEdge *clk_edge,
const Pin *src_pin,
const PathAnalysisPt *path_ap) const
@ -993,20 +994,52 @@ Genclks::srcPath(const ClockEdge *clk_edge,
return srcPath(clk_edge->clock(), src_pin, clk_edge->transition(), path_ap);
}
PathVertex
Path *
Genclks::srcPath(const Clock *gclk,
const Pin *src_pin,
const RiseFall *rf,
const PathAnalysisPt *path_ap) const
{
PathVertexPtr *src_paths =
genclk_src_paths_.findKey(ClockPinPair(gclk, src_pin));
if (src_paths) {
int path_index = srcPathIndex(rf, path_ap);
return PathVertex(src_paths[path_index], this);
auto itr = genclk_src_paths_.find(ClockPinPair(gclk, src_pin));
if (itr != genclk_src_paths_.end()) {
vector<Path> src_paths = itr->second;
if (!src_paths.empty()) {
size_t path_index = srcPathIndex(rf, path_ap);
Path &src_path = src_paths[path_index];
if (!src_path.isNull()) {
Path *src_vpath = Path::vertexPath(src_path, this);
return src_vpath;
}
}
}
return nullptr;
}
void
Genclks::updateSrcPathPrevs()
{
for (auto const & [clk_pin, src_paths] : genclk_src_paths_) {
for (const Path &src_path : src_paths) {
if (!src_path.isNull()) {
const Path *p = &src_path;
while (p) {
Path *src_vpath = Path::vertexPath(p->vertex(this),
p->tag(this), this);
Path *prev_path = p->prevPath();
if (prev_path) {
Path *prev_vpath = Path::vertexPath(prev_path->vertex(this),
prev_path->tag(this), this);
src_vpath->setPrevPath(prev_vpath);
src_vpath->setPrevEdgeArc(p->prevEdge(this),
p->prevArc(this), this);
}
p = p->prevPath();
}
debugPrint(debug_, "genclk", 3, "repaired src path prev %s",
src_path.to_string(this).c_str());
}
}
}
else
return PathVertex();
}
Arrival
@ -1017,9 +1050,9 @@ Genclks::insertionDelay(const Clock *clk,
const PathAnalysisPt *path_ap) const
{
PathAnalysisPt *insert_ap = path_ap->insertionAnalysisPt(early_late);
PathVertex src_path = srcPath(clk, pin, rf, insert_ap);
if (!src_path.isNull())
return src_path.arrival(this);
Path *src_path = srcPath(clk, pin, rf, insert_ap);
if (src_path)
return src_path->arrival();
else
return 0.0;
}

Some files were not shown because too many files have changed in this diff Show More