Merge remote-tracking branch 'parallax/master'
Signed-off-by: Matt Liberty <mliberty@precisioninno.com>
This commit is contained in:
commit
9e96eb85cc
|
|
@ -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"
|
||||
|
|
@ -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
|
||||
|
|
|
|||
17
README.md
17
README.md
|
|
@ -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.
|
||||
|
|
|
|||
|
|
@ -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')
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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_) {
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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));
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
-------------------------
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
-------------------------
|
||||
|
||||
|
|
|
|||
BIN
doc/OpenSTA.odt
BIN
doc/OpenSTA.odt
Binary file not shown.
BIN
doc/OpenSTA.pdf
BIN
doc/OpenSTA.pdf
Binary file not shown.
138
graph/Graph.cc
138
graph/Graph.cc
|
|
@ -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()
|
||||
|
|
|
|||
|
|
@ -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 "";
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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:
|
||||
|
|
|
|||
|
|
@ -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_;
|
||||
|
|
|
|||
|
|
@ -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_;
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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_;
|
||||
|
|
|
|||
|
|
@ -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_; }
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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_;
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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_; }
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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_;
|
||||
|
|
|
|||
|
|
@ -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_;
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -190,6 +190,8 @@ stringPrintTmp(const char *fmt,
|
|||
|
||||
char *
|
||||
makeTmpString(size_t length);
|
||||
char *
|
||||
makeTmpString(string &str);
|
||||
bool
|
||||
isTmpString(const char *str);
|
||||
|
||||
|
|
|
|||
|
|
@ -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_;
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -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_;
|
||||
|
|
|
|||
|
|
@ -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 ®_clk_q_; }
|
||||
static const TimingRole *regSetClr() { return ®_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;
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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_;
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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:
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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 *
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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()];
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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_)
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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(); }
|
||||
}
|
||||
|
|
|
|||
137
sdc/Sdc.tcl
137
sdc/Sdc.tcl
|
|
@ -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
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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";
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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";
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////
|
||||
|
|
|
|||
|
|
@ -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_;
|
||||
};
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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"
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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];
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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_;
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -30,7 +30,7 @@
|
|||
#include "StaState.hh"
|
||||
#include "Transition.hh"
|
||||
#include "SearchClass.hh"
|
||||
#include "PathVertex.hh"
|
||||
#include "Path.hh"
|
||||
#include "ClkDelays.hh"
|
||||
|
||||
namespace sta {
|
||||
|
|
|
|||
|
|
@ -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()
|
||||
|
|
|
|||
|
|
@ -32,7 +32,7 @@
|
|||
#include "Transition.hh"
|
||||
#include "SearchClass.hh"
|
||||
#include "SearchPred.hh"
|
||||
#include "PathVertex.hh"
|
||||
#include "Path.hh"
|
||||
|
||||
namespace sta {
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
{
|
||||
|
|
|
|||
191
search/Crpr.cc
191
search/Crpr.cc
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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())
|
||||
|
|
|
|||
|
|
@ -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:
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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
Loading…
Reference in New Issue