sync
This commit is contained in:
parent
c3b1679bd7
commit
f49dc75d32
21
configure.ac
21
configure.ac
|
|
@ -148,6 +148,15 @@ AC_ARG_ENABLE(asan,
|
|||
esac],
|
||||
[asan=false])
|
||||
|
||||
AC_ARG_ENABLE(ssta,
|
||||
[AS_HELP_STRING([--enable-ssta],[enable ssta])],
|
||||
[case "${enableval}" in
|
||||
yes) ssta=true ;;
|
||||
no) ssta=false ;;
|
||||
*) AC_MSG_ERROR(bad value ${enableval} for --enable-ssta) ;;
|
||||
esac],
|
||||
[ssta=false])
|
||||
|
||||
AC_ARG_WITH(include,
|
||||
[AS_HELP_STRING([--with-include=dirs],[directories to search for include files])],
|
||||
[INCLUDE_DIRS="${withval}"],
|
||||
|
|
@ -188,6 +197,14 @@ AC_ARG_WITH(optimize,
|
|||
[],
|
||||
[])
|
||||
|
||||
#--------------------------------------------------------------------
|
||||
|
||||
if test x$ssta = xtrue; then
|
||||
AC_DEFINE(SSTA, 1, "SSTA support")
|
||||
else
|
||||
AC_DEFINE(SSTA, 0, "SSTA support")
|
||||
fi
|
||||
|
||||
#--------------------------------------------------------------------
|
||||
# Locate the Tcl package
|
||||
#--------------------------------------------------------------------
|
||||
|
|
@ -411,8 +428,8 @@ AC_FUNC_ERROR_AT_LINE
|
|||
#--------------------------------------------------------------------
|
||||
|
||||
if test $CXX = clang++; then
|
||||
# -Wno-deprecated-register to suppress warnings in flex files
|
||||
CXXFLAGS="-std=c++11 -Wall -Wno-deprecated-register -Wcast-qual"
|
||||
# suppress deprecated-register warnings in flex files.
|
||||
CXXFLAGS="-std=c++11 -Wall -Wcast-qual -Wunused-parameter -Wno-deprecated-register"
|
||||
CXX_OPT="-O3"
|
||||
CXX_DEBUG="-g"
|
||||
CXX_ASAN="-fsanitize=address -O1 -fno-omit-frame-pointer"
|
||||
|
|
|
|||
|
|
@ -739,9 +739,9 @@ GraphDelayCalc1::driveCellDefaultFromPort(LibertyCell *cell,
|
|||
{
|
||||
LibertyPort *from_port = 0;
|
||||
int from_port_index = 0;
|
||||
CellTimingArcSetIterator *set_iter = cell->timingArcSetIterator();
|
||||
while (set_iter->hasNext()) {
|
||||
TimingArcSet *arc_set = set_iter->next();
|
||||
LibertyCellTimingArcSetIterator set_iter(cell);
|
||||
while (set_iter.hasNext()) {
|
||||
TimingArcSet *arc_set = set_iter.next();
|
||||
if (arc_set->to() == to_port) {
|
||||
LibertyPort *set_from_port = arc_set->from();
|
||||
int set_from_port_index = findPortIndex(cell, set_from_port);
|
||||
|
|
@ -752,7 +752,6 @@ GraphDelayCalc1::driveCellDefaultFromPort(LibertyCell *cell,
|
|||
}
|
||||
}
|
||||
}
|
||||
delete set_iter;
|
||||
return from_port;
|
||||
}
|
||||
|
||||
|
|
@ -762,16 +761,13 @@ GraphDelayCalc1::findPortIndex(LibertyCell *cell,
|
|||
LibertyPort *port)
|
||||
{
|
||||
int index = 0;
|
||||
LibertyCellPortIterator *port_iter = cell->libertyPortIterator();
|
||||
while (port_iter->hasNext()) {
|
||||
LibertyPort *cell_port = port_iter->next();
|
||||
if (cell_port == port) {
|
||||
delete port_iter;
|
||||
LibertyCellPortIterator port_iter(cell);
|
||||
while (port_iter.hasNext()) {
|
||||
LibertyPort *cell_port = port_iter.next();
|
||||
if (cell_port == port)
|
||||
return index;
|
||||
}
|
||||
index++;
|
||||
}
|
||||
delete port_iter;
|
||||
internalError("port not found in cell");
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -789,24 +785,22 @@ GraphDelayCalc1::findInputDriverDelay(LibertyCell *drvr_cell,
|
|||
debugPrint2(debug_, "delay_calc", 2, " driver cell %s %s\n",
|
||||
drvr_cell->name(),
|
||||
tr->asString());
|
||||
CellTimingArcSetIterator *set_iter = drvr_cell->timingArcSetIterator();
|
||||
while (set_iter->hasNext()) {
|
||||
TimingArcSet *arc_set = set_iter->next();
|
||||
LibertyCellTimingArcSetIterator set_iter(drvr_cell);
|
||||
while (set_iter.hasNext()) {
|
||||
TimingArcSet *arc_set = set_iter.next();
|
||||
if (arc_set->from() == from_port
|
||||
&& arc_set->to() == to_port) {
|
||||
TimingArcSetArcIterator *arc_iter = arc_set->timingArcIterator();
|
||||
while (arc_iter->hasNext()) {
|
||||
TimingArc *arc = arc_iter->next();
|
||||
TimingArcSetArcIterator arc_iter(arc_set);
|
||||
while (arc_iter.hasNext()) {
|
||||
TimingArc *arc = arc_iter.next();
|
||||
if (arc->toTrans()->asRiseFall() == tr) {
|
||||
float from_slew = from_slews[arc->fromTrans()->index()];
|
||||
findInputArcDelay(drvr_cell, drvr_pin, drvr_vertex,
|
||||
arc, from_slew, dcalc_ap);
|
||||
}
|
||||
}
|
||||
delete arc_iter;
|
||||
}
|
||||
}
|
||||
delete set_iter;
|
||||
}
|
||||
|
||||
// Driving cell delay is the load dependent delay, which is the gate
|
||||
|
|
@ -1026,9 +1020,9 @@ GraphDelayCalc1::findDriverEdgeDelays(LibertyCell *drvr_cell,
|
|||
const Pvt *pvt = sdc_->pvt(drvr_inst, dcalc_ap->constraintMinMax());
|
||||
if (pvt == NULL)
|
||||
pvt = dcalc_ap->operatingConditions();
|
||||
TimingArcSetArcIterator *arc_iter = arc_set->timingArcIterator();
|
||||
while (arc_iter->hasNext()) {
|
||||
TimingArc *arc = arc_iter->next();
|
||||
TimingArcSetArcIterator arc_iter(arc_set);
|
||||
while (arc_iter.hasNext()) {
|
||||
TimingArc *arc = arc_iter.next();
|
||||
const TransRiseFall *tr = arc->toTrans()->asRiseFall();
|
||||
Parasitic *parasitic;
|
||||
bool delete_parasitic;
|
||||
|
|
@ -1054,7 +1048,6 @@ GraphDelayCalc1::findDriverEdgeDelays(LibertyCell *drvr_cell,
|
|||
arc_delay_calc->finish(drvr_pin, tr, dcalc_ap,
|
||||
parasitic, delete_parasitic);
|
||||
}
|
||||
delete arc_iter;
|
||||
}
|
||||
|
||||
if (delay_changed && observer_) {
|
||||
|
|
@ -1369,9 +1362,9 @@ GraphDelayCalc1::findMultiDrvrGateDelay(MultiDrvrNet *multi_drvr,
|
|||
Edge *edge1 = edge_iter.next();
|
||||
TimingArcSet *arc_set1 = edge1->timingArcSet();
|
||||
const LibertyPort *related_out_port = arc_set1->relatedOut();
|
||||
TimingArcSetArcIterator *arc_iter = arc_set1->timingArcIterator();
|
||||
while (arc_iter->hasNext()) {
|
||||
TimingArc *arc1 = arc_iter->next();
|
||||
TimingArcSetArcIterator arc_iter(arc_set1);
|
||||
while (arc_iter.hasNext()) {
|
||||
TimingArc *arc1 = arc_iter.next();
|
||||
TransRiseFall *drvr_tr1 = arc1->toTrans()->asRiseFall();
|
||||
if (drvr_tr1 == drvr_tr) {
|
||||
Vertex *from_vertex1 = edge1->from(graph_);
|
||||
|
|
@ -1420,7 +1413,6 @@ GraphDelayCalc1::findMultiDrvrGateDelay(MultiDrvrNet *multi_drvr,
|
|||
parasitic1, delete_parasitic1);
|
||||
}
|
||||
}
|
||||
delete arc_iter;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1570,9 +1562,9 @@ GraphDelayCalc1::findCheckEdgeDelays(Edge *edge,
|
|||
Instance *inst = network_->instance(to_pin);
|
||||
const LibertyCell *cell = network_->libertyCell(inst);
|
||||
bool delay_changed = false;
|
||||
TimingArcSetArcIterator *arc_iter = arc_set->timingArcIterator();
|
||||
while (arc_iter->hasNext()) {
|
||||
TimingArc *arc = arc_iter->next();
|
||||
TimingArcSetArcIterator arc_iter(arc_set);
|
||||
while (arc_iter.hasNext()) {
|
||||
TimingArc *arc = arc_iter.next();
|
||||
TransRiseFall *from_tr = arc->fromTrans()->asRiseFall();
|
||||
TransRiseFall *to_tr = arc->toTrans()->asRiseFall();
|
||||
if (from_tr && to_tr) {
|
||||
|
|
@ -1631,7 +1623,6 @@ GraphDelayCalc1::findCheckEdgeDelays(Edge *edge,
|
|||
}
|
||||
}
|
||||
}
|
||||
delete arc_iter;
|
||||
if (delay_changed && observer_)
|
||||
observer_->checkDelayChangedTo(to_vertex);
|
||||
}
|
||||
|
|
|
|||
BIN
doc/OpenSTA.odt
BIN
doc/OpenSTA.odt
Binary file not shown.
BIN
doc/OpenSTA.pdf
BIN
doc/OpenSTA.pdf
Binary file not shown.
|
|
@ -14,32 +14,20 @@
|
|||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#ifndef STA_DELAY_H
|
||||
#define STA_DELAY_H
|
||||
|
||||
// Define one of the following:
|
||||
|
||||
// Define DELAY_FLOAT to use the float definitions.
|
||||
#define DELAY_FLOAT
|
||||
|
||||
// Define DELAY_FLOAT_CLASS to use the DelayClass definitions.
|
||||
//#define DELAY_FLOAT_CLASS
|
||||
|
||||
// Define DELAY_NORMAL2 to use the DelayNormal2 definitions.
|
||||
//#define DELAY_NORMAL2
|
||||
|
||||
#ifdef DELAY_FLOAT
|
||||
#if SSTA
|
||||
// Delays are Normal PDFs with early/late sigma.
|
||||
#include "DelayNormal2.hh"
|
||||
#else
|
||||
// Delays are floats.
|
||||
#include "DelayFloat.hh"
|
||||
#endif
|
||||
|
||||
#ifdef DELAY_FLOAT_CLASS
|
||||
#include "DelayFloatClass.hh"
|
||||
#endif
|
||||
|
||||
#ifdef DELAY_NORMAL2
|
||||
#include "DelayNormal2.hh"
|
||||
#endif
|
||||
|
||||
// API common to DelayFloat and DelayNormal2.
|
||||
namespace sta {
|
||||
|
||||
class Units;
|
||||
|
|
@ -59,6 +47,13 @@ makeDelay(float delay,
|
|||
float sigma_late);
|
||||
float
|
||||
delayAsFloat(const Delay &delay);
|
||||
// mean late+/early- sigma
|
||||
float
|
||||
delayAsFloat(const Delay &delay,
|
||||
const EarlyLate *early_late);
|
||||
float
|
||||
delaySigma(const Delay &delay,
|
||||
const EarlyLate *early_late);
|
||||
const char *
|
||||
delayAsString(const Delay &delay,
|
||||
const Units *units);
|
||||
|
|
@ -69,16 +64,11 @@ const char *
|
|||
delayAsString(const Delay &delay,
|
||||
const Units *units,
|
||||
int digits);
|
||||
// mean late+/early- sigma
|
||||
// early_late = NULL returns mean.
|
||||
float
|
||||
delayMeanSigma(const Delay &delay,
|
||||
const EarlyLate *early_late);
|
||||
const char *
|
||||
delayMeanSigmaString(const Delay &delay,
|
||||
const EarlyLate *early_late,
|
||||
const Units *units,
|
||||
int digits);
|
||||
delayAsString(const Delay &delay,
|
||||
const EarlyLate *early_late,
|
||||
const Units *units,
|
||||
int digits);
|
||||
const Delay &
|
||||
delayInitValue(const MinMax *min_max);
|
||||
bool
|
||||
|
|
|
|||
|
|
@ -14,14 +14,15 @@
|
|||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
#include "config.h"
|
||||
#include "Machine.hh"
|
||||
#include "Fuzzy.hh"
|
||||
#include "Units.hh"
|
||||
#include "StaState.hh"
|
||||
#include "Delay.hh"
|
||||
|
||||
// Conditional compilation based on delay abstraction from Delay.hh.
|
||||
#ifdef DELAY_FLOAT
|
||||
// Non-SSTA compilation.
|
||||
#if !SSTA
|
||||
|
||||
namespace sta {
|
||||
|
||||
|
|
@ -154,21 +155,28 @@ delayAsString(const Delay &delay,
|
|||
}
|
||||
|
||||
float
|
||||
delayMeanSigma(const Delay &delay,
|
||||
const EarlyLate *)
|
||||
delayAsFloat(const Delay &delay,
|
||||
const EarlyLate *)
|
||||
{
|
||||
return delay;
|
||||
}
|
||||
|
||||
const char *
|
||||
delayMeanSigmaString(const Delay &delay,
|
||||
const EarlyLate *,
|
||||
const Units *units,
|
||||
int digits)
|
||||
delayAsString(const Delay &delay,
|
||||
const EarlyLate *,
|
||||
const Units *units,
|
||||
int digits)
|
||||
{
|
||||
const Unit *unit = units->timeUnit();
|
||||
return unit->asString(delay, digits);
|
||||
}
|
||||
|
||||
float
|
||||
delaySigma(const Delay &,
|
||||
const EarlyLate *)
|
||||
{
|
||||
return 0.0;
|
||||
}
|
||||
|
||||
} // namespace
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -14,16 +14,18 @@
|
|||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
#include "config.h"
|
||||
#include <cmath> // sqrt
|
||||
#include "Machine.hh"
|
||||
#include "Error.hh"
|
||||
#include "StringUtil.hh"
|
||||
#include "Fuzzy.hh"
|
||||
#include "Units.hh"
|
||||
#include "StaState.hh"
|
||||
#include "Delay.hh"
|
||||
|
||||
// Conditional compilation based on delay abstraction from Delay.hh.
|
||||
#ifdef DELAY_NORMAL2
|
||||
// SSTA compilation.
|
||||
#if SSTA
|
||||
|
||||
namespace sta {
|
||||
|
||||
|
|
@ -338,6 +340,25 @@ delayRatio(const Delay &delay1,
|
|||
return delay1.mean() / delay2.mean();
|
||||
}
|
||||
|
||||
float
|
||||
delayAsFloat(const Delay &delay,
|
||||
const EarlyLate *early_late)
|
||||
{
|
||||
if (early_late == EarlyLate::early())
|
||||
return delay.mean() - delay.sigmaEarly();
|
||||
else if (early_late == EarlyLate::late())
|
||||
return delay.mean() + delay.sigmaLate();
|
||||
else
|
||||
internalError("unknown early/late value.");
|
||||
}
|
||||
|
||||
float
|
||||
delaySigma(const Delay &delay,
|
||||
const EarlyLate *early_late)
|
||||
{
|
||||
return delay.sigma(early_late);
|
||||
}
|
||||
|
||||
const char *
|
||||
delayAsString(const Delay &delay,
|
||||
const Units *units,
|
||||
|
|
@ -360,10 +381,10 @@ delayAsString(const Delay &delay,
|
|||
}
|
||||
|
||||
const char *
|
||||
delayMeanSigmaString(const Delay &delay,
|
||||
const EarlyLate *early_late,
|
||||
const Units *units,
|
||||
int digits)
|
||||
delayAsString(const Delay &delay,
|
||||
const EarlyLate *early_late,
|
||||
const Units *units,
|
||||
int digits)
|
||||
{
|
||||
float mean_sigma = delay.mean();
|
||||
if (early_late == EarlyLate::early())
|
||||
|
|
@ -373,17 +394,5 @@ delayMeanSigmaString(const Delay &delay,
|
|||
return units->timeUnit()->asString(mean_sigma, digits);
|
||||
}
|
||||
|
||||
float
|
||||
delayMeanSigma(const Delay &delay,
|
||||
const EarlyLate *early_late)
|
||||
{
|
||||
if (early_late == EarlyLate::early())
|
||||
return delay.mean() - delay.sigmaEarly();
|
||||
else if (early_late == EarlyLate::late())
|
||||
return delay.mean() + delay.sigmaLate();
|
||||
else
|
||||
return delay.mean();
|
||||
}
|
||||
|
||||
} // namespace
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -144,10 +144,9 @@ Graph::vertexAndEdgeCounts(const Instance *inst,
|
|||
vertex_count++;
|
||||
if (cell) {
|
||||
LibertyPort *port = network_->libertyPort(pin);
|
||||
CellTimingArcSetIterator *set_iter =
|
||||
cell->timingArcSetFromIterator(port);
|
||||
while (set_iter->hasNext()) {
|
||||
TimingArcSet *arc_set = set_iter->next();
|
||||
LibertyCellTimingArcSetIterator set_iter(cell, port, NULL);
|
||||
while (set_iter.hasNext()) {
|
||||
TimingArcSet *arc_set = set_iter.next();
|
||||
LibertyPort *to_port = arc_set->to();
|
||||
if (network_->findPin(inst, to_port)) {
|
||||
if (dir->isBidirect()) {
|
||||
|
|
@ -161,7 +160,6 @@ Graph::vertexAndEdgeCounts(const Instance *inst,
|
|||
}
|
||||
}
|
||||
}
|
||||
delete set_iter;
|
||||
}
|
||||
// Count wire edges from driver pins.
|
||||
if (network_->isDriver(pin))
|
||||
|
|
@ -284,9 +282,9 @@ Graph::makePortInstanceEdges(const Instance *inst,
|
|||
LibertyCell *cell,
|
||||
LibertyPort *from_to_port)
|
||||
{
|
||||
CellTimingArcSetIterator *timing_iter = cell->timingArcSetIterator();
|
||||
while (timing_iter->hasNext()) {
|
||||
TimingArcSet *arc_set = timing_iter->next();
|
||||
LibertyCellTimingArcSetIterator timing_iter(cell);
|
||||
while (timing_iter.hasNext()) {
|
||||
TimingArcSet *arc_set = timing_iter.next();
|
||||
LibertyPort *from_port = arc_set->from();
|
||||
LibertyPort *to_port = arc_set->to();
|
||||
if (from_to_port == NULL
|
||||
|
|
@ -327,7 +325,6 @@ Graph::makePortInstanceEdges(const Instance *inst,
|
|||
}
|
||||
}
|
||||
}
|
||||
delete timing_iter;
|
||||
}
|
||||
|
||||
void
|
||||
|
|
@ -915,31 +912,27 @@ Graph::removeDelayAnnotated(Edge *edge)
|
|||
{
|
||||
edge->setDelayAnnotationIsIncremental(false);
|
||||
TimingArcSet *arc_set = edge->timingArcSet();
|
||||
TimingArcSetArcIterator *arc_iter = arc_set->timingArcIterator();
|
||||
while (arc_iter->hasNext()) {
|
||||
TimingArc *arc = arc_iter->next();
|
||||
TimingArcSetArcIterator arc_iter(arc_set);
|
||||
while (arc_iter.hasNext()) {
|
||||
TimingArc *arc = arc_iter.next();
|
||||
for (DcalcAPIndex ap_index = 0; ap_index < ap_count_; ap_index++) {
|
||||
setArcDelayAnnotated(edge, arc, ap_index, false);
|
||||
}
|
||||
}
|
||||
delete arc_iter;
|
||||
}
|
||||
|
||||
bool
|
||||
Graph::delayAnnotated(Edge *edge)
|
||||
{
|
||||
TimingArcSet *arc_set = edge->timingArcSet();
|
||||
TimingArcSetArcIterator *arc_iter = arc_set->timingArcIterator();
|
||||
while (arc_iter->hasNext()) {
|
||||
TimingArc *arc = arc_iter->next();
|
||||
TimingArcSetArcIterator arc_iter(arc_set);
|
||||
while (arc_iter.hasNext()) {
|
||||
TimingArc *arc = arc_iter.next();
|
||||
for (DcalcAPIndex ap_index = 0; ap_index < ap_count_; ap_index++) {
|
||||
if (arcDelayAnnotated(edge, arc, ap_index)) {
|
||||
delete arc_iter;
|
||||
if (arcDelayAnnotated(edge, arc, ap_index))
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
delete arc_iter;
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -19,7 +19,6 @@ lib_LTLIBRARIES = libgraph.la
|
|||
include_HEADERS = \
|
||||
Delay.hh \
|
||||
DelayFloat.hh \
|
||||
DelayFloatClass.hh \
|
||||
DelayNormal2.hh \
|
||||
Graph.hh \
|
||||
GraphClass.hh \
|
||||
|
|
@ -28,7 +27,6 @@ include_HEADERS = \
|
|||
libgraph_la_SOURCES = \
|
||||
Delay.cc \
|
||||
DelayFloat.cc \
|
||||
DelayFloatClass.cc \
|
||||
DelayNormal2.cc \
|
||||
Graph.cc \
|
||||
GraphCmp.cc
|
||||
|
|
|
|||
|
|
@ -87,9 +87,9 @@ findEquivCells1(const LibertyLibrary *library)
|
|||
{
|
||||
LibertyCellHashMap cell_hash;
|
||||
LibertyCellEquivMap *cell_equivs = new LibertyCellEquivMap;
|
||||
LibertyLibraryCellIterator *cell_iter = library->libertyCellIterator();
|
||||
while (cell_iter->hasNext()) {
|
||||
LibertyCell *cell = cell_iter->next();
|
||||
LibertyCellIterator cell_iter(library);
|
||||
while (cell_iter.hasNext()) {
|
||||
LibertyCell *cell = cell_iter.next();
|
||||
if (!cell->dontUse()) {
|
||||
bool found_equiv = false;
|
||||
unsigned hash = hashCell(cell);
|
||||
|
|
@ -121,7 +121,6 @@ findEquivCells1(const LibertyLibrary *library)
|
|||
}
|
||||
}
|
||||
}
|
||||
delete cell_iter;
|
||||
|
||||
LibertyCellHashMap::Iterator hash_iter(cell_hash);
|
||||
while (hash_iter.hasNext()) {
|
||||
|
|
@ -159,13 +158,13 @@ float
|
|||
cellDriveResistance(const LibertyCell *cell)
|
||||
{
|
||||
float max_drive = 0.0;
|
||||
CellTimingArcSetIterator *set_iter = cell->timingArcSetIterator();
|
||||
while (set_iter->hasNext()) {
|
||||
TimingArcSet *set = set_iter->next();
|
||||
LibertyCellTimingArcSetIterator set_iter(cell);
|
||||
while (set_iter.hasNext()) {
|
||||
TimingArcSet *set = set_iter.next();
|
||||
if (!set->role()->isTimingCheck()) {
|
||||
TimingArcSetArcIterator *arc_iter = set->timingArcIterator();
|
||||
while (arc_iter->hasNext()) {
|
||||
TimingArc *arc = arc_iter->next();
|
||||
TimingArcSetArcIterator arc_iter(set);
|
||||
while (arc_iter.hasNext()) {
|
||||
TimingArc *arc = arc_iter.next();
|
||||
GateTimingModel *model = dynamic_cast<GateTimingModel*>(arc->model());
|
||||
if (model) {
|
||||
float drive = model->driveResistance(cell, NULL);
|
||||
|
|
@ -173,10 +172,8 @@ cellDriveResistance(const LibertyCell *cell)
|
|||
max_drive = drive;
|
||||
}
|
||||
}
|
||||
delete arc_iter;
|
||||
}
|
||||
}
|
||||
delete set_iter;
|
||||
return max_drive;
|
||||
}
|
||||
|
||||
|
|
@ -190,14 +187,13 @@ static unsigned
|
|||
hashCellPorts(const LibertyCell *cell)
|
||||
{
|
||||
unsigned hash = 0;
|
||||
LibertyCellPortIterator *port_iter = cell->libertyPortIterator();
|
||||
while (port_iter->hasNext()) {
|
||||
LibertyPort *port = port_iter->next();
|
||||
LibertyCellPortIterator port_iter(cell);
|
||||
while (port_iter.hasNext()) {
|
||||
LibertyPort *port = port_iter.next();
|
||||
hash += hashPort(port);
|
||||
hash += hashFuncExpr(port->function()) * 3;
|
||||
hash += hashFuncExpr(port->tristateEnable()) * 5;
|
||||
}
|
||||
delete port_iter;
|
||||
return hash;
|
||||
}
|
||||
|
||||
|
|
@ -212,9 +208,9 @@ static unsigned
|
|||
hashCellSequentials(const LibertyCell *cell)
|
||||
{
|
||||
unsigned hash = 0;
|
||||
CellSequentialIterator *seq_iter = cell->sequentialIterator();
|
||||
while (seq_iter->hasNext()) {
|
||||
Sequential *seq = seq_iter->next();
|
||||
LibertyCellSequentialIterator seq_iter(cell);
|
||||
while (seq_iter.hasNext()) {
|
||||
Sequential *seq = seq_iter.next();
|
||||
hash += hashFuncExpr(seq->clock()) * 3;
|
||||
hash += hashFuncExpr(seq->data()) * 5;
|
||||
hash += hashPort(seq->output()) * 7;
|
||||
|
|
@ -224,7 +220,6 @@ hashCellSequentials(const LibertyCell *cell)
|
|||
hash += seq->clearPresetOutput() * 17;
|
||||
hash += seq->clearPresetOutputInv() * 19;
|
||||
}
|
||||
delete seq_iter;
|
||||
return hash;
|
||||
}
|
||||
|
||||
|
|
@ -275,9 +270,9 @@ equivCellPortsAndFuncs(const LibertyCell *cell1,
|
|||
if (cell1->portCount() != cell2->portCount())
|
||||
return false;
|
||||
else {
|
||||
LibertyCellPortIterator *port_iter1 = cell1->libertyPortIterator();
|
||||
while (port_iter1->hasNext()) {
|
||||
LibertyPort *port1 = port_iter1->next();
|
||||
LibertyCellPortIterator port_iter1(cell1);
|
||||
while (port_iter1.hasNext()) {
|
||||
LibertyPort *port1 = port_iter1.next();
|
||||
const char *name = port1->name();
|
||||
LibertyPort *port2 = cell2->findLibertyPort(name);
|
||||
if (!(port2
|
||||
|
|
@ -285,11 +280,9 @@ equivCellPortsAndFuncs(const LibertyCell *cell1,
|
|||
&& FuncExpr::equiv(port1->function(), port2->function())
|
||||
&& FuncExpr::equiv(port1->tristateEnable(),
|
||||
port2->tristateEnable()))){
|
||||
delete port_iter1;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
delete port_iter1;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
|
@ -301,17 +294,14 @@ equivCellPorts(const LibertyCell *cell1,
|
|||
if (cell1->portCount() != cell2->portCount())
|
||||
return false;
|
||||
else {
|
||||
LibertyCellPortIterator *port_iter1 = cell1->libertyPortIterator();
|
||||
while (port_iter1->hasNext()) {
|
||||
LibertyPort *port1 = port_iter1->next();
|
||||
LibertyCellPortIterator port_iter1(cell1);
|
||||
while (port_iter1.hasNext()) {
|
||||
LibertyPort *port1 = port_iter1.next();
|
||||
const char* name = port1->name();
|
||||
LibertyPort *port2 = cell2->findLibertyPort(name);
|
||||
if (!(port2 && LibertyPort::equiv(port1, port2))) {
|
||||
delete port_iter1;
|
||||
if (!(port2 && LibertyPort::equiv(port1, port2)))
|
||||
return false;
|
||||
}
|
||||
}
|
||||
delete port_iter1;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
|
@ -320,27 +310,20 @@ static bool
|
|||
equivCellSequentials(const LibertyCell *cell1,
|
||||
const LibertyCell *cell2)
|
||||
{
|
||||
bool eq = true;
|
||||
CellSequentialIterator *seq_iter1 = cell1->sequentialIterator();
|
||||
CellSequentialIterator *seq_iter2 = cell2->sequentialIterator();
|
||||
while (seq_iter1->hasNext() && seq_iter2->hasNext()) {
|
||||
Sequential *seq1 = seq_iter1->next();
|
||||
Sequential *seq2 = seq_iter2->next();
|
||||
LibertyCellSequentialIterator seq_iter1(cell1);
|
||||
LibertyCellSequentialIterator seq_iter2(cell2);
|
||||
while (seq_iter1.hasNext() && seq_iter2.hasNext()) {
|
||||
Sequential *seq1 = seq_iter1.next();
|
||||
Sequential *seq2 = seq_iter2.next();
|
||||
if (!(FuncExpr::equiv(seq1->clock(), seq2->clock())
|
||||
&& FuncExpr::equiv(seq1->data(), seq2->data())
|
||||
&& LibertyPort::equiv(seq1->output(), seq2->output())
|
||||
&& LibertyPort::equiv(seq1->outputInv(), seq2->outputInv())
|
||||
&& FuncExpr::equiv(seq1->clear(), seq2->clear())
|
||||
&& FuncExpr::equiv(seq1->preset(), seq2->preset()))) {
|
||||
eq = false;
|
||||
break;
|
||||
}
|
||||
&& FuncExpr::equiv(seq1->preset(), seq2->preset())))
|
||||
return false;
|
||||
}
|
||||
if (seq_iter1->hasNext() || seq_iter2->hasNext())
|
||||
eq = false;
|
||||
delete seq_iter1;
|
||||
delete seq_iter2;
|
||||
return eq;
|
||||
return !seq_iter1.hasNext() && !seq_iter2.hasNext();
|
||||
}
|
||||
|
||||
bool
|
||||
|
|
@ -350,16 +333,13 @@ equivCellTimingArcSets(const LibertyCell *cell1,
|
|||
if (cell1->timingArcSetCount() != cell2->timingArcSetCount())
|
||||
return false;
|
||||
else {
|
||||
CellTimingArcSetIterator *set_iter1 = cell1->timingArcSetIterator();
|
||||
while (set_iter1->hasNext()) {
|
||||
TimingArcSet *set1 = set_iter1->next();
|
||||
LibertyCellTimingArcSetIterator set_iter1(cell1);
|
||||
while (set_iter1.hasNext()) {
|
||||
TimingArcSet *set1 = set_iter1.next();
|
||||
TimingArcSet *set2 = cell2->findTimingArcSet(set1);
|
||||
if (!(set2 && TimingArcSet::equiv(set1, set2))) {
|
||||
delete set_iter1;
|
||||
if (!(set2 && TimingArcSet::equiv(set1, set2)))
|
||||
return false;
|
||||
}
|
||||
}
|
||||
delete set_iter1;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -31,6 +31,21 @@ InternalPowerAttrs::InternalPowerAttrs() :
|
|||
|
||||
InternalPowerAttrs::~InternalPowerAttrs()
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
InternalPowerAttrs::deleteContents()
|
||||
{
|
||||
TransRiseFallIterator tr_iter;
|
||||
while (tr_iter.hasNext()) {
|
||||
TransRiseFall *tr = tr_iter.next();
|
||||
int tr_index = tr->index();
|
||||
InternalPowerModel *model = models_[tr_index];
|
||||
if (model)
|
||||
delete model;
|
||||
}
|
||||
if (when_)
|
||||
when_->deleteSubexprs();
|
||||
stringDelete(related_pg_pin_);
|
||||
}
|
||||
|
||||
|
|
@ -63,7 +78,7 @@ InternalPower::InternalPower(LibertyCell *cell,
|
|||
port_(port),
|
||||
related_port_(related_port),
|
||||
when_(attrs->when()),
|
||||
related_pg_pin_(stringCopy(attrs->relatedPgPin()))
|
||||
related_pg_pin_(attrs->relatedPgPin())
|
||||
{
|
||||
TransRiseFallIterator tr_iter;
|
||||
while (tr_iter.hasNext()) {
|
||||
|
|
@ -76,17 +91,7 @@ InternalPower::InternalPower(LibertyCell *cell,
|
|||
|
||||
InternalPower::~InternalPower()
|
||||
{
|
||||
TransRiseFallIterator tr_iter;
|
||||
while (tr_iter.hasNext()) {
|
||||
TransRiseFall *tr = tr_iter.next();
|
||||
int tr_index = tr->index();
|
||||
InternalPowerModel *model = models_[tr_index];
|
||||
if (model)
|
||||
delete model;
|
||||
}
|
||||
if (when_)
|
||||
when_->deleteSubexprs();
|
||||
stringDelete(related_pg_pin_);
|
||||
// models_, when_ and related_pg_pin_ are owned by InternalPowerAttrs.
|
||||
}
|
||||
|
||||
LibertyCell *
|
||||
|
|
|
|||
|
|
@ -30,7 +30,8 @@ class InternalPowerAttrs
|
|||
{
|
||||
public:
|
||||
InternalPowerAttrs();
|
||||
~InternalPowerAttrs();
|
||||
virtual ~InternalPowerAttrs();
|
||||
void deleteContents();
|
||||
FuncExpr *when() const { return when_; }
|
||||
FuncExpr *&whenRef() { return when_; }
|
||||
void setModel(TransRiseFall *tr,
|
||||
|
|
|
|||
|
|
@ -117,7 +117,7 @@ LibertyLibrary::LibertyLibrary(const char *name,
|
|||
LibertyLibrary::~LibertyLibrary()
|
||||
{
|
||||
bus_dcls_.deleteContents();
|
||||
templates_.deleteContents();
|
||||
template_map_.deleteContents();
|
||||
scale_factors_map_.deleteContents();
|
||||
delete scale_factors_;
|
||||
|
||||
|
|
@ -147,7 +147,7 @@ void
|
|||
LibertyLibrary::findLibertyCellsMatching(PatternMatch *pattern,
|
||||
LibertyCellSeq *cells)
|
||||
{
|
||||
LibertyLibraryCellIterator cell_iter(this);
|
||||
LibertyCellIterator cell_iter(this);
|
||||
while (cell_iter.hasNext()) {
|
||||
LibertyCell *cell = cell_iter.next();
|
||||
if (pattern->match(cell->name()))
|
||||
|
|
@ -155,12 +155,6 @@ LibertyLibrary::findLibertyCellsMatching(PatternMatch *pattern,
|
|||
}
|
||||
}
|
||||
|
||||
LibertyLibraryCellIterator *
|
||||
LibertyLibrary::libertyCellIterator() const
|
||||
{
|
||||
return new LibertyLibraryCellIterator(this);
|
||||
}
|
||||
|
||||
void
|
||||
LibertyLibrary::setDelayModelType(DelayModelType type)
|
||||
{
|
||||
|
|
@ -182,25 +176,19 @@ LibertyLibrary::findBusDcl(const char *name) const
|
|||
void
|
||||
LibertyLibrary::addTableTemplate(TableTemplate *tbl_template)
|
||||
{
|
||||
templates_[tbl_template->name()] = tbl_template;
|
||||
template_map_[tbl_template->name()] = tbl_template;
|
||||
}
|
||||
|
||||
void
|
||||
LibertyLibrary::deleteTableTemplate(TableTemplate *tbl_template)
|
||||
{
|
||||
templates_.eraseKey(tbl_template->name());
|
||||
template_map_.eraseKey(tbl_template->name());
|
||||
}
|
||||
|
||||
TableTemplate *
|
||||
LibertyLibrary::findTableTemplate(const char *name)
|
||||
{
|
||||
return templates_[name];
|
||||
}
|
||||
|
||||
TableTemplateIterator *
|
||||
LibertyLibrary::tableTemplateIterator()
|
||||
{
|
||||
return new TableTemplateIterator(templates_);
|
||||
return template_map_[name];
|
||||
}
|
||||
|
||||
void
|
||||
|
|
@ -600,12 +588,6 @@ LibertyLibrary::findOperatingConditions(const char *name)
|
|||
return operating_conditions_.findKey(name);
|
||||
}
|
||||
|
||||
OperatingConditionsIterator *
|
||||
LibertyLibrary::operatingConditionsIterator()
|
||||
{
|
||||
return new OperatingConditionsIterator(operating_conditions_);
|
||||
}
|
||||
|
||||
OperatingConditions *
|
||||
LibertyLibrary::defaultOperatingConditions() const
|
||||
{
|
||||
|
|
@ -697,15 +679,14 @@ LibertyLibrary::makeCornerMap(LibertyLibrary *lib,
|
|||
int ap_index,
|
||||
Network *network)
|
||||
{
|
||||
LibertyLibraryCellIterator *cell_iter = lib->libertyCellIterator();
|
||||
while (cell_iter->hasNext()) {
|
||||
LibertyCell *cell = cell_iter->next();
|
||||
LibertyCellIterator cell_iter(lib);
|
||||
while (cell_iter.hasNext()) {
|
||||
LibertyCell *cell = cell_iter.next();
|
||||
const char *name = cell->name();
|
||||
LibertyCell *link_cell = network->findLibertyCell(name);
|
||||
if (link_cell)
|
||||
makeCornerMap(link_cell, cell, ap_index);
|
||||
}
|
||||
delete cell_iter;
|
||||
}
|
||||
|
||||
// Map a cell linked in the network to the corresponding liberty cell
|
||||
|
|
@ -717,35 +698,30 @@ LibertyLibrary::makeCornerMap(LibertyCell *link_cell,
|
|||
{
|
||||
link_cell->setCornerCell(corner_cell, ap_index);
|
||||
|
||||
LibertyCellPortBitIterator *port_iter = link_cell->libertyPortBitIterator();
|
||||
while (port_iter->hasNext()) {
|
||||
LibertyPort *link_port = port_iter->next();
|
||||
LibertyCellPortBitIterator port_iter(link_cell);
|
||||
while (port_iter.hasNext()) {
|
||||
LibertyPort *link_port = port_iter.next();
|
||||
const char *port_name = link_port->name();
|
||||
LibertyPort *corner_port = corner_cell->findLibertyPort(port_name);
|
||||
if (corner_port)
|
||||
link_port->setCornerPort(corner_port, ap_index);
|
||||
}
|
||||
delete port_iter;
|
||||
|
||||
CellTimingArcSetIterator *set_iter = link_cell->timingArcSetIterator();
|
||||
while (set_iter->hasNext()) {
|
||||
TimingArcSet *link_arc_set = set_iter->next();
|
||||
LibertyCellTimingArcSetIterator set_iter(link_cell);
|
||||
while (set_iter.hasNext()) {
|
||||
TimingArcSet *link_arc_set = set_iter.next();
|
||||
TimingArcSet *corner_arc_set = corner_cell->findTimingArcSet(link_arc_set);
|
||||
if (corner_arc_set) {
|
||||
TimingArcSetArcIterator *arc_iter = link_arc_set->timingArcIterator();
|
||||
TimingArcSetArcIterator *corner_arc_iter =
|
||||
corner_arc_set->timingArcIterator();
|
||||
while (arc_iter->hasNext() && corner_arc_iter->hasNext()) {
|
||||
TimingArc *link_arc = arc_iter->next();
|
||||
TimingArc *corner_arc = corner_arc_iter->next();
|
||||
TimingArcSetArcIterator arc_iter(link_arc_set);
|
||||
TimingArcSetArcIterator corner_arc_iter(corner_arc_set);
|
||||
while (arc_iter.hasNext() && corner_arc_iter.hasNext()) {
|
||||
TimingArc *link_arc = arc_iter.next();
|
||||
TimingArc *corner_arc = corner_arc_iter.next();
|
||||
if (TimingArc::equiv(link_arc, corner_arc))
|
||||
link_arc->setCornerArc(corner_arc, ap_index);
|
||||
}
|
||||
delete arc_iter;
|
||||
delete corner_arc_iter;
|
||||
}
|
||||
}
|
||||
delete set_iter;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////
|
||||
|
|
@ -788,20 +764,20 @@ LibertyLibrary::addOcvDerate(OcvDerate *derate)
|
|||
|
||||
////////////////////////////////////////////////////////////////
|
||||
|
||||
LibertyLibraryCellIterator::LibertyLibraryCellIterator(const LibertyLibrary *
|
||||
LibertyCellIterator::LibertyCellIterator(const LibertyLibrary *
|
||||
library):
|
||||
iter_(library->cell_map_)
|
||||
{
|
||||
}
|
||||
|
||||
bool
|
||||
LibertyLibraryCellIterator::hasNext()
|
||||
LibertyCellIterator::hasNext()
|
||||
{
|
||||
return iter_.hasNext();
|
||||
}
|
||||
|
||||
LibertyCell *
|
||||
LibertyLibraryCellIterator::next()
|
||||
LibertyCellIterator::next()
|
||||
{
|
||||
return dynamic_cast<LibertyCell*>(iter_.next());
|
||||
}
|
||||
|
|
@ -849,13 +825,13 @@ LibertyCell::~LibertyCell()
|
|||
|
||||
latch_d_to_q_map_.deleteContents();
|
||||
|
||||
deleteTimingArcAttrs();
|
||||
if (timing_arc_sets_) {
|
||||
deleteTimingModels();
|
||||
timing_arc_sets_->deleteContents();
|
||||
delete timing_arc_sets_;
|
||||
delete timing_arc_set_map_;
|
||||
|
||||
LibertyPortTimingArcSetMap::Iterator port_map_iter(port_timing_arc_set_map_);
|
||||
LibertyPortPairTimingArcMap::Iterator port_map_iter(port_timing_arc_set_map_);
|
||||
while (port_map_iter.hasNext()) {
|
||||
LibertyPortPair *port_pair;
|
||||
TimingArcSetSeq *sets;
|
||||
|
|
@ -872,6 +848,7 @@ LibertyCell::~LibertyCell()
|
|||
delete timing_arc_set_to_map_;
|
||||
}
|
||||
|
||||
deleteInternalPowerAttrs();
|
||||
if (internal_powers_) {
|
||||
internal_powers_->deleteContents();
|
||||
delete internal_powers_;
|
||||
|
|
@ -900,68 +877,17 @@ LibertyCell::~LibertyCell()
|
|||
}
|
||||
|
||||
// Multiple timing arc sets (buses bits or a related_ports list)
|
||||
// can share the same model, cond, and sdf_conds, so collect them
|
||||
// into a set so they are only deleted once.
|
||||
// can share the same TimingAttrs values (model, cond, and sdf_conds),
|
||||
// so collect them into a set so they are only deleted once.
|
||||
void
|
||||
LibertyCell::deleteTimingModels()
|
||||
LibertyCell::deleteTimingArcAttrs()
|
||||
{
|
||||
TimingModelSet models;
|
||||
FuncExprSet exprs;
|
||||
StringSetEq strings;
|
||||
|
||||
TimingArcSetSeq::Iterator set_iter(timing_arc_sets_);
|
||||
while (set_iter.hasNext()) {
|
||||
TimingArcSet *set = set_iter.next();
|
||||
TimingArcSetArcIterator *arc_iter = set->timingArcIterator();
|
||||
while (arc_iter->hasNext()) {
|
||||
TimingArc *arc = arc_iter->next();
|
||||
TimingModel *model = arc->model();
|
||||
if (model)
|
||||
models.insert(model);
|
||||
}
|
||||
delete arc_iter;
|
||||
|
||||
FuncExpr *cond = set->cond();
|
||||
if (cond)
|
||||
exprs.insert(cond);
|
||||
|
||||
const char *str = set->sdfCondStart();
|
||||
if (str)
|
||||
strings.insert(str);
|
||||
|
||||
str = set->sdfCondEnd();
|
||||
if (str)
|
||||
strings.insert(str);
|
||||
|
||||
str = set->modeName();
|
||||
if (str)
|
||||
strings.insert(str);
|
||||
|
||||
str = set->modeValue();
|
||||
if (str)
|
||||
strings.insert(str);
|
||||
|
||||
TimingArcAttrsSeq::Iterator attr_iter(timing_arc_attrs_);
|
||||
while (attr_iter.hasNext()) {
|
||||
TimingArcAttrs *attrs = attr_iter.next();
|
||||
attrs->deleteContents();
|
||||
delete attrs;
|
||||
}
|
||||
models.deleteContents();
|
||||
|
||||
FuncExprSet::Iterator expr_iter(exprs);
|
||||
while (expr_iter.hasNext()) {
|
||||
FuncExpr *expr = expr_iter.next();
|
||||
expr->deleteSubexprs();
|
||||
}
|
||||
deleteContents(&strings);
|
||||
}
|
||||
|
||||
LibertyCellPortIterator *
|
||||
LibertyCell::libertyPortIterator() const
|
||||
{
|
||||
return new LibertyCellPortIterator(this);
|
||||
}
|
||||
|
||||
LibertyCellPortBitIterator *
|
||||
LibertyCell::libertyPortBitIterator() const
|
||||
{
|
||||
return new LibertyCellPortBitIterator(this);
|
||||
}
|
||||
|
||||
LibertyPort *
|
||||
|
|
@ -1097,9 +1023,9 @@ LibertyCell::addTimingArcSet(TimingArcSet *arc_set)
|
|||
if (timing_arc_sets_ == NULL) {
|
||||
timing_arc_sets_ = new TimingArcSetSeq;
|
||||
timing_arc_set_map_ = new TimingArcSetMap;
|
||||
port_timing_arc_set_map_ = new LibertyPortTimingArcSetMap;
|
||||
timing_arc_set_from_map_ = new LibertyPortTimingArcSetSeqMap;
|
||||
timing_arc_set_to_map_ = new LibertyPortTimingArcSetSeqMap;
|
||||
port_timing_arc_set_map_ = new LibertyPortPairTimingArcMap;
|
||||
timing_arc_set_from_map_ = new LibertyPortTimingArcMap;
|
||||
timing_arc_set_to_map_ = new LibertyPortTimingArcMap;
|
||||
}
|
||||
int set_index = timing_arc_sets_->size();
|
||||
if (set_index > timing_arc_set_index_max)
|
||||
|
|
@ -1142,6 +1068,12 @@ LibertyCell::addTimingArcSet(TimingArcSet *arc_set)
|
|||
return set_index;
|
||||
}
|
||||
|
||||
void
|
||||
LibertyCell::addTimingArcAttrs(TimingArcAttrs *attrs)
|
||||
{
|
||||
timing_arc_attrs_.push_back(attrs);
|
||||
}
|
||||
|
||||
void
|
||||
LibertyCell::addInternalPower(InternalPower *power)
|
||||
{
|
||||
|
|
@ -1150,10 +1082,22 @@ LibertyCell::addInternalPower(InternalPower *power)
|
|||
internal_powers_->push_back(power);
|
||||
}
|
||||
|
||||
LibertyCellInternalPowerIterator *
|
||||
LibertyCell::internalPowerIterator()
|
||||
{
|
||||
return new LibertyCellInternalPowerIterator(internal_powers_);
|
||||
void
|
||||
LibertyCell::addInternalPowerAttrs(InternalPowerAttrs *attrs)
|
||||
{
|
||||
internal_power_attrs_.push_back(attrs);
|
||||
}
|
||||
|
||||
void
|
||||
LibertyCell::deleteInternalPowerAttrs()
|
||||
{
|
||||
InternalPowerAttrsSeq::Iterator attr_iter(internal_power_attrs_);
|
||||
while (attr_iter.hasNext()) {
|
||||
InternalPowerAttrs *attrs = attr_iter.next();
|
||||
attrs->deleteContents();
|
||||
delete attrs;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void
|
||||
|
|
@ -1164,18 +1108,6 @@ LibertyCell::addLeakagePower(LeakagePower *power)
|
|||
leakage_powers_->push_back(power);
|
||||
}
|
||||
|
||||
LibertyCellLeakagePowerIterator *
|
||||
LibertyCell::leakagePowerIterator()
|
||||
{
|
||||
return new LibertyCellLeakagePowerIterator(leakage_powers_);
|
||||
}
|
||||
|
||||
float
|
||||
LibertyCell::leakagePower() const
|
||||
{
|
||||
return leakage_power_;
|
||||
}
|
||||
|
||||
void
|
||||
LibertyCell::setLeakagePower(float leakage)
|
||||
{
|
||||
|
|
@ -1198,7 +1130,7 @@ LibertyCell::finish(bool infer_latches,
|
|||
void
|
||||
LibertyCell::findDefaultCondArcs()
|
||||
{
|
||||
LibertyPortTimingArcSetMap::Iterator set_iter1(port_timing_arc_set_map_);
|
||||
LibertyPortPairTimingArcMap::Iterator set_iter1(port_timing_arc_set_map_);
|
||||
while (set_iter1.hasNext()) {
|
||||
LibertyPortPair *port_pair;
|
||||
TimingArcSetSeq *sets;
|
||||
|
|
@ -1230,18 +1162,17 @@ void
|
|||
LibertyCell::translatePresetClrCheckRoles()
|
||||
{
|
||||
LibertyPortSet pre_clr_ports;
|
||||
CellTimingArcSetIterator *set_iter = timingArcSetIterator();
|
||||
while (set_iter->hasNext()) {
|
||||
TimingArcSet *set = set_iter->next();
|
||||
LibertyCellTimingArcSetIterator set_iter(this);
|
||||
while (set_iter.hasNext()) {
|
||||
TimingArcSet *set = set_iter.next();
|
||||
if (set->role() == TimingRole::regSetClr())
|
||||
pre_clr_ports.insert(set->from());
|
||||
}
|
||||
delete set_iter;
|
||||
|
||||
if (!pre_clr_ports.empty()) {
|
||||
set_iter = timingArcSetIterator();
|
||||
while (set_iter->hasNext()) {
|
||||
TimingArcSet *set = set_iter->next();
|
||||
LibertyCellTimingArcSetIterator set_iter(this);
|
||||
while (set_iter.hasNext()) {
|
||||
TimingArcSet *set = set_iter.next();
|
||||
if (pre_clr_ports.findKey(set->to())) {
|
||||
if (set->role() == TimingRole::setup())
|
||||
set->setRole(TimingRole::recovery());
|
||||
|
|
@ -1249,10 +1180,26 @@ LibertyCell::translatePresetClrCheckRoles()
|
|||
set->setRole(TimingRole::removal());
|
||||
}
|
||||
}
|
||||
delete set_iter;
|
||||
}
|
||||
}
|
||||
|
||||
TimingArcSetSeq *
|
||||
LibertyCell::timingArcSets(const LibertyPort *from,
|
||||
const LibertyPort *to) const
|
||||
{
|
||||
if (timing_arc_sets_) {
|
||||
if (from && to) {
|
||||
LibertyPortPair port_pair(from, to);
|
||||
return port_timing_arc_set_map_->findKey(&port_pair);
|
||||
}
|
||||
else if (from)
|
||||
return timing_arc_set_from_map_->findKey(from);
|
||||
else if (to)
|
||||
return timing_arc_set_to_map_->findKey(to);
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
TimingArcSet *
|
||||
LibertyCell::findTimingArcSet(TimingArcSet *key) const
|
||||
{
|
||||
|
|
@ -1277,36 +1224,6 @@ LibertyCell::timingArcSetCount() const
|
|||
return 0;
|
||||
}
|
||||
|
||||
CellTimingArcSetIterator *
|
||||
LibertyCell::timingArcSetIterator() const
|
||||
{
|
||||
return new CellTimingArcSetIterator(timing_arc_sets_);
|
||||
}
|
||||
|
||||
CellTimingArcSetIterator *
|
||||
LibertyCell::timingArcSetIterator(LibertyPort *from,
|
||||
LibertyPort *to) const
|
||||
{
|
||||
if (timing_arc_sets_) {
|
||||
LibertyPortPair port_pair(from, to);
|
||||
TimingArcSetSeq *sets = port_timing_arc_set_map_->findKey(&port_pair);
|
||||
return new CellTimingArcSetIterator(sets);
|
||||
}
|
||||
else
|
||||
return new CellTimingArcSetIterator(NULL);
|
||||
}
|
||||
|
||||
CellTimingArcSetIterator *
|
||||
LibertyCell::timingArcSetFromIterator(LibertyPort *from) const
|
||||
{
|
||||
if (timing_arc_sets_) {
|
||||
TimingArcSetSeq *sets = timing_arc_set_from_map_->findKey(from);
|
||||
return new CellTimingArcSetIterator(sets);
|
||||
}
|
||||
else
|
||||
return new CellTimingArcSetIterator(NULL);
|
||||
}
|
||||
|
||||
bool
|
||||
LibertyCell::hasTimingArcs(LibertyPort *port) const
|
||||
{
|
||||
|
|
@ -1315,17 +1232,6 @@ LibertyCell::hasTimingArcs(LibertyPort *port) const
|
|||
|| timing_arc_set_to_map_->findKey(port));
|
||||
}
|
||||
|
||||
CellTimingArcSetIterator *
|
||||
LibertyCell::timingArcSetToIterator(LibertyPort *to) const
|
||||
{
|
||||
if (timing_arc_sets_) {
|
||||
TimingArcSetSeq *sets = timing_arc_set_to_map_->findKey(to);
|
||||
return new CellTimingArcSetIterator(sets);
|
||||
}
|
||||
else
|
||||
return new CellTimingArcSetIterator(NULL);
|
||||
}
|
||||
|
||||
void
|
||||
LibertyCell::makeSequential(int size,
|
||||
bool is_register,
|
||||
|
|
@ -1386,12 +1292,6 @@ LibertyCell::hasSequentials() const
|
|||
return sequentials_ && !sequentials_->empty();
|
||||
}
|
||||
|
||||
CellSequentialIterator *
|
||||
LibertyCell::sequentialIterator() const
|
||||
{
|
||||
return new CellSequentialIterator(sequentials_);
|
||||
}
|
||||
|
||||
void
|
||||
LibertyCell::addScaledCell(OperatingConditions *op_cond,
|
||||
LibertyCell *scaled_cell)
|
||||
|
|
@ -1400,37 +1300,31 @@ LibertyCell::addScaledCell(OperatingConditions *op_cond,
|
|||
scaled_cells_ = new ScaledCellMap;
|
||||
(*scaled_cells_)[op_cond] = scaled_cell;
|
||||
|
||||
LibertyCellPortBitIterator *port_iter1 = libertyPortBitIterator();
|
||||
LibertyCellPortBitIterator *port_iter2=scaled_cell->libertyPortBitIterator();
|
||||
while (port_iter1->hasNext() && port_iter2->hasNext()) {
|
||||
LibertyPort *port = port_iter1->next();
|
||||
LibertyPort *scaled_port = port_iter2->next();
|
||||
LibertyCellPortBitIterator port_iter1(this);
|
||||
LibertyCellPortBitIterator port_iter2(scaled_cell);
|
||||
while (port_iter1.hasNext() && port_iter2.hasNext()) {
|
||||
LibertyPort *port = port_iter1.next();
|
||||
LibertyPort *scaled_port = port_iter2.next();
|
||||
port->addScaledPort(op_cond, scaled_port);
|
||||
}
|
||||
delete port_iter1;
|
||||
delete port_iter2;
|
||||
|
||||
CellTimingArcSetIterator *set_iter1 = timingArcSetIterator();
|
||||
CellTimingArcSetIterator *set_iter2 = scaled_cell->timingArcSetIterator();
|
||||
while (set_iter1->hasNext() && set_iter2->hasNext()) {
|
||||
TimingArcSet *arc_set1 = set_iter1->next();
|
||||
TimingArcSet *arc_set2 = set_iter2->next();
|
||||
TimingArcSetArcIterator *arc_iter1 = arc_set1->timingArcIterator();
|
||||
TimingArcSetArcIterator *arc_iter2 = arc_set2->timingArcIterator();
|
||||
while (arc_iter1->hasNext() && arc_iter2->hasNext()) {
|
||||
TimingArc *arc = arc_iter1->next();
|
||||
TimingArc *scaled_arc = arc_iter2->next();
|
||||
LibertyCellTimingArcSetIterator set_iter1(this);
|
||||
LibertyCellTimingArcSetIterator set_iter2(scaled_cell);
|
||||
while (set_iter1.hasNext() && set_iter2.hasNext()) {
|
||||
TimingArcSet *arc_set1 = set_iter1.next();
|
||||
TimingArcSet *arc_set2 = set_iter2.next();
|
||||
TimingArcSetArcIterator arc_iter1(arc_set1);
|
||||
TimingArcSetArcIterator arc_iter2(arc_set2);
|
||||
while (arc_iter1.hasNext() && arc_iter2.hasNext()) {
|
||||
TimingArc *arc = arc_iter1.next();
|
||||
TimingArc *scaled_arc = arc_iter2.next();
|
||||
if (TimingArc::equiv(arc, scaled_arc)) {
|
||||
TimingModel *model = scaled_arc->model();
|
||||
model->setIsScaled(true);
|
||||
arc->addScaledModel(op_cond, model);
|
||||
}
|
||||
}
|
||||
delete arc_iter1;
|
||||
delete arc_iter2;
|
||||
}
|
||||
delete set_iter1;
|
||||
delete set_iter2;
|
||||
}
|
||||
|
||||
void
|
||||
|
|
@ -1519,6 +1413,20 @@ LibertyCell::addOcvDerate(OcvDerate *derate)
|
|||
|
||||
////////////////////////////////////////////////////////////////
|
||||
|
||||
LibertyCellTimingArcSetIterator::LibertyCellTimingArcSetIterator(const LibertyCell *cell) :
|
||||
TimingArcSetSeq::Iterator(cell->timing_arc_sets_)
|
||||
{
|
||||
}
|
||||
|
||||
LibertyCellTimingArcSetIterator::LibertyCellTimingArcSetIterator(const LibertyCell *cell,
|
||||
const LibertyPort *from,
|
||||
const LibertyPort *to):
|
||||
TimingArcSetSeq::Iterator(cell->timingArcSets(from, to))
|
||||
{
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////
|
||||
|
||||
// Latch enable port/function for a latch D->Q timing arc set.
|
||||
class LatchEnable
|
||||
{
|
||||
|
|
@ -1581,30 +1489,28 @@ LibertyCell::makeLatchEnables(Report *report,
|
|||
{
|
||||
if (hasSequentials()
|
||||
|| hasInferedRegTimingArcs()) {
|
||||
CellTimingArcSetIterator *set_iter = timingArcSetIterator();
|
||||
while (set_iter->hasNext()) {
|
||||
TimingArcSet *en_to_q = set_iter->next();
|
||||
LibertyCellTimingArcSetIterator set_iter(this);
|
||||
while (set_iter.hasNext()) {
|
||||
TimingArcSet *en_to_q = set_iter.next();
|
||||
if (en_to_q->role() == TimingRole::latchEnToQ()) {
|
||||
LibertyPort *en = en_to_q->from();
|
||||
LibertyPort *q = en_to_q->to();
|
||||
CellTimingArcSetIterator *to_iter = timingArcSetToIterator(q);
|
||||
while (to_iter->hasNext()) {
|
||||
TimingArcSet *d_to_q = to_iter->next();
|
||||
LibertyCellTimingArcSetIterator to_iter(this, NULL, q);
|
||||
while (to_iter.hasNext()) {
|
||||
TimingArcSet *d_to_q = to_iter.next();
|
||||
if (d_to_q->role() == TimingRole::latchDtoQ()) {
|
||||
LibertyPort *d = d_to_q->from();
|
||||
CellTimingArcSetIterator *check_iter = timingArcSetIterator(en, d);
|
||||
while (check_iter->hasNext()) {
|
||||
TimingArcSet *setup_check = check_iter->next();
|
||||
LibertyCellTimingArcSetIterator check_iter(this, en, d);
|
||||
while (check_iter.hasNext()) {
|
||||
TimingArcSet *setup_check = check_iter.next();
|
||||
if (setup_check->role() == TimingRole::setup()) {
|
||||
LatchEnable *latch_enable = makeLatchEnable(d, en, q, d_to_q,
|
||||
en_to_q,
|
||||
setup_check,
|
||||
debug);
|
||||
TimingArcSetArcIterator *check_arc_iter =
|
||||
setup_check->timingArcIterator();
|
||||
if (check_arc_iter->hasNext()) {
|
||||
TimingArc *check_arc = check_arc_iter->next();
|
||||
delete check_arc_iter;
|
||||
TimingArcSetArcIterator check_arc_iter( setup_check);
|
||||
if (check_arc_iter.hasNext()) {
|
||||
TimingArc *check_arc = check_arc_iter.next();
|
||||
TransRiseFall *en_tr = latch_enable->enableTransition();
|
||||
TransRiseFall *check_tr = check_arc->fromTrans()->asRiseFall();
|
||||
if (check_tr == en_tr) {
|
||||
|
|
@ -1640,16 +1546,12 @@ LibertyCell::makeLatchEnables(Report *report,
|
|||
}
|
||||
break;
|
||||
}
|
||||
delete check_arc_iter;
|
||||
}
|
||||
}
|
||||
delete check_iter;
|
||||
}
|
||||
}
|
||||
delete to_iter;
|
||||
}
|
||||
}
|
||||
delete set_iter;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -1657,19 +1559,16 @@ FuncExpr *
|
|||
LibertyCell::findLatchEnableFunc(LibertyPort *data,
|
||||
LibertyPort *enable) const
|
||||
{
|
||||
CellSequentialIterator *iter = sequentialIterator();
|
||||
while (iter->hasNext()) {
|
||||
Sequential *seq = iter->next();
|
||||
LibertyCellSequentialIterator iter(this);
|
||||
while (iter.hasNext()) {
|
||||
Sequential *seq = iter.next();
|
||||
if (seq->isLatch()
|
||||
&& seq->data()
|
||||
&& seq->data()->hasPort(data)
|
||||
&& seq->clock()
|
||||
&& seq->clock()->hasPort(enable)) {
|
||||
delete iter;
|
||||
&& seq->clock()->hasPort(enable))
|
||||
return seq->clock();
|
||||
}
|
||||
}
|
||||
delete iter;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
|
@ -1703,16 +1602,16 @@ LibertyCell::inferLatchRoles(Debug *debug)
|
|||
if (hasInferedRegTimingArcs()) {
|
||||
// Hunt down potential latch D/EN/Q triples.
|
||||
LatchEnableSet latch_enables;
|
||||
CellTimingArcSetIterator *set_iter = timingArcSetIterator();
|
||||
while (set_iter->hasNext()) {
|
||||
TimingArcSet *en_to_q = set_iter->next();
|
||||
LibertyCellTimingArcSetIterator set_iter(this);
|
||||
while (set_iter.hasNext()) {
|
||||
TimingArcSet *en_to_q = set_iter.next();
|
||||
// Locate potential d->q arcs from reg clk->q arcs.
|
||||
if (en_to_q->role() == TimingRole::regClkToQ()) {
|
||||
LibertyPort *en = en_to_q->from();
|
||||
LibertyPort *q = en_to_q->to();
|
||||
CellTimingArcSetIterator *to_iter = timingArcSetToIterator(q);
|
||||
while (to_iter->hasNext()) {
|
||||
TimingArcSet *d_to_q = to_iter->next();
|
||||
LibertyCellTimingArcSetIterator to_iter(this, NULL, q);
|
||||
while (to_iter.hasNext()) {
|
||||
TimingArcSet *d_to_q = to_iter.next();
|
||||
// Look for combinational d->q arcs.
|
||||
TimingRole *d_to_q_role = d_to_q->role();
|
||||
if ((d_to_q_role == TimingRole::combinational()
|
||||
|
|
@ -1724,22 +1623,19 @@ LibertyCell::inferLatchRoles(Debug *debug)
|
|||
|| d_to_q_role == TimingRole::latchDtoQ()) {
|
||||
LibertyPort *d = d_to_q->from();
|
||||
// Check for setup check from en -> d.
|
||||
CellTimingArcSetIterator *check_iter = timingArcSetIterator(en, d);
|
||||
while (check_iter->hasNext()) {
|
||||
TimingArcSet *setup_check = check_iter->next();
|
||||
LibertyCellTimingArcSetIterator check_iter(this, en, d);
|
||||
while (check_iter.hasNext()) {
|
||||
TimingArcSet *setup_check = check_iter.next();
|
||||
if (setup_check->role() == TimingRole::setup()) {
|
||||
makeLatchEnable(d, en, q, d_to_q, en_to_q, setup_check, debug);
|
||||
d_to_q->setRole(TimingRole::latchDtoQ());
|
||||
en_to_q->setRole(TimingRole::latchEnToQ());
|
||||
}
|
||||
}
|
||||
delete check_iter;
|
||||
}
|
||||
}
|
||||
delete to_iter;
|
||||
}
|
||||
}
|
||||
delete set_iter;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -1869,12 +1765,6 @@ LibertyPort::setDirection(PortDirection *dir)
|
|||
liberty_cell_->setHasInternalPorts(true);
|
||||
}
|
||||
|
||||
LibertyPortMemberIterator *
|
||||
LibertyPort::libertyMemberIterator() const
|
||||
{
|
||||
return new LibertyPortMemberIterator(this);
|
||||
}
|
||||
|
||||
LibertyPort *
|
||||
LibertyPort::findLibertyMember(int index) const
|
||||
{
|
||||
|
|
@ -1903,12 +1793,11 @@ LibertyPort::setCapacitance(const TransRiseFall *tr,
|
|||
{
|
||||
capacitance_.setValue(tr, min_max, cap);
|
||||
if (hasMembers()) {
|
||||
LibertyPortMemberIterator *member_iter = libertyMemberIterator();
|
||||
while (member_iter->hasNext()) {
|
||||
LibertyPort *port_bit = member_iter->next();
|
||||
LibertyPortMemberIterator member_iter(this);
|
||||
while (member_iter.hasNext()) {
|
||||
LibertyPort *port_bit = member_iter.next();
|
||||
port_bit->setCapacitance(tr, min_max, cap);
|
||||
}
|
||||
delete member_iter;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -1958,15 +1847,14 @@ LibertyPort::setFunction(FuncExpr *func)
|
|||
{
|
||||
function_ = func;
|
||||
if (is_bus_ || is_bundle_) {
|
||||
LibertyPortMemberIterator *member_iter = libertyMemberIterator();
|
||||
LibertyPortMemberIterator member_iter(this);
|
||||
int bit_offset = 0;
|
||||
while (member_iter->hasNext()) {
|
||||
LibertyPort *port_bit = member_iter->next();
|
||||
while (member_iter.hasNext()) {
|
||||
LibertyPort *port_bit = member_iter.next();
|
||||
FuncExpr *sub_expr = (func) ? func->bitSubExpr(bit_offset) : NULL;
|
||||
port_bit->setFunction(sub_expr);
|
||||
bit_offset++;
|
||||
}
|
||||
delete member_iter;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -1975,14 +1863,13 @@ LibertyPort::setTristateEnable(FuncExpr *enable)
|
|||
{
|
||||
tristate_enable_ = enable;
|
||||
if (hasMembers()) {
|
||||
LibertyPortMemberIterator *member_iter = libertyMemberIterator();
|
||||
while (member_iter->hasNext()) {
|
||||
LibertyPort *port_bit = member_iter->next();
|
||||
LibertyPortMemberIterator member_iter(this);
|
||||
while (member_iter.hasNext()) {
|
||||
LibertyPort *port_bit = member_iter.next();
|
||||
FuncExpr *sub_expr =
|
||||
(enable) ? enable->bitSubExpr(port_bit->busBitIndex()) : NULL;
|
||||
port_bit->setTristateEnable(sub_expr);
|
||||
}
|
||||
delete member_iter;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -28,7 +28,7 @@
|
|||
|
||||
namespace sta {
|
||||
|
||||
class LibertyLibraryCellIterator;
|
||||
class LibertyCellIterator;
|
||||
class LibertyCellPortIterator;
|
||||
class LibertyCellPortBitIterator;
|
||||
class LibertyPortMemberIterator;
|
||||
|
|
@ -41,34 +41,33 @@ class Debug;
|
|||
class LibertyBuilder;
|
||||
class LibertyReader;
|
||||
class OcvDerate;
|
||||
class TimingArcAttrs;
|
||||
class InternalPowerAttrs;
|
||||
|
||||
typedef Set<Library*> LibrarySet;
|
||||
typedef Map<const char*, TableTemplate*, CharPtrLess> TableTemplateMap;
|
||||
typedef TableTemplateMap::Iterator TableTemplateIterator;
|
||||
typedef Map<const char*, BusDcl *, CharPtrLess> BusDclMap;
|
||||
typedef Map<const char*, ScaleFactors*, CharPtrLess> ScaleFactorsMap;
|
||||
typedef Map<const char*, Wireload*, CharPtrLess> WireloadMap;
|
||||
typedef Map<const char*, WireloadSelection*, CharPtrLess> WireloadSelectionMap;
|
||||
typedef Map<const char*, OperatingConditions*,
|
||||
CharPtrLess> OperatingConditionsMap;
|
||||
typedef OperatingConditionsMap::Iterator OperatingConditionsIterator;
|
||||
typedef Map<LibertyPort*, Sequential*> PortToSequentialMap;
|
||||
typedef Vector<TimingArcSet*> TimingArcSetSeq;
|
||||
typedef TimingArcSetSeq::ConstIterator CellTimingArcSetIterator;
|
||||
typedef Set<TimingArcSet*, TimingArcSetLess> TimingArcSetMap;
|
||||
typedef Map<LibertyPortPair*, TimingArcSetSeq*,
|
||||
LibertyPortPairLess> LibertyPortPairTimingArcMap;
|
||||
typedef Vector<InternalPower*> InternalPowerSeq;
|
||||
typedef InternalPowerSeq::Iterator LibertyCellInternalPowerIterator;
|
||||
typedef Vector<LeakagePower*> LeakagePowerSeq;
|
||||
typedef LeakagePowerSeq::Iterator LibertyCellLeakagePowerIterator;
|
||||
typedef Map<LibertyPort*, TimingArcSetSeq*> LibertyPortTimingArcSetSeqMap;
|
||||
typedef Map<const LibertyPort*, TimingArcSetSeq*> LibertyPortTimingArcMap;
|
||||
typedef Map<const OperatingConditions*, LibertyCell*> ScaledCellMap;
|
||||
typedef Map<const OperatingConditions*, LibertyPort*> ScaledPortMap;
|
||||
typedef Map<const char *, ModeDef*, CharPtrLess> ModeDefMap;
|
||||
typedef Map<const char *, ModeValueDef*, CharPtrLess> ModeValueMap;
|
||||
typedef Map<TimingArcSet*, LatchEnable*> LatchEnableMap;
|
||||
typedef Map<const char *, OcvDerate*, CharPtrLess> OcvDerateMap;
|
||||
typedef Map<LibertyPortPair*, TimingArcSetSeq*,
|
||||
LibertyPortPairLess> LibertyPortTimingArcSetMap;
|
||||
typedef Vector<TimingArcAttrs*> TimingArcAttrsSeq;
|
||||
typedef Vector<InternalPowerAttrs*> InternalPowerAttrsSeq;
|
||||
|
||||
typedef enum {
|
||||
clock_gate_none,
|
||||
|
|
@ -132,14 +131,12 @@ public:
|
|||
LibertyCell *findLibertyCell(const char *name) const;
|
||||
void findLibertyCellsMatching(PatternMatch *pattern,
|
||||
LibertyCellSeq *cells);
|
||||
LibertyLibraryCellIterator *libertyCellIterator() const;
|
||||
DelayModelType delayModelType() const { return delay_model_type_; }
|
||||
void setDelayModelType(DelayModelType type);
|
||||
void addBusDcl(BusDcl *bus_dcl);
|
||||
BusDcl *findBusDcl(const char *name) const;
|
||||
void addTableTemplate(TableTemplate *tbl_template);
|
||||
TableTemplate *findTableTemplate(const char *name);
|
||||
TableTemplateIterator *tableTemplateIterator();
|
||||
float nominalProcess() { return nominal_process_; }
|
||||
void setNominalProcess(float process);
|
||||
float nominalVoltage() const { return nominal_voltage_; }
|
||||
|
|
@ -254,7 +251,6 @@ public:
|
|||
void setDefaultWireloadSelection(WireloadSelection *selection);
|
||||
|
||||
OperatingConditions *findOperatingConditions(const char *name);
|
||||
OperatingConditionsIterator *operatingConditionsIterator();
|
||||
OperatingConditions *defaultOperatingConditions() const;
|
||||
void addOperatingConditions(OperatingConditions *op_cond);
|
||||
void setDefaultOperatingConditions(OperatingConditions *op_cond);
|
||||
|
|
@ -291,7 +287,7 @@ protected:
|
|||
Units *units_;
|
||||
DelayModelType delay_model_type_;
|
||||
BusDclMap bus_dcls_;
|
||||
TableTemplateMap templates_;
|
||||
TableTemplateMap template_map_;
|
||||
float nominal_process_;
|
||||
float nominal_voltage_;
|
||||
float nominal_temperature_;
|
||||
|
|
@ -340,22 +336,40 @@ protected:
|
|||
private:
|
||||
DISALLOW_COPY_AND_ASSIGN(LibertyLibrary);
|
||||
|
||||
friend class LibertyLibraryCellIterator;
|
||||
friend class LibertyCellIterator;
|
||||
friend class TableTemplateIterator;
|
||||
friend class OperatingConditionsIterator;
|
||||
};
|
||||
|
||||
class LibertyLibraryCellIterator : public Iterator<LibertyCell*>
|
||||
class LibertyCellIterator : public Iterator<LibertyCell*>
|
||||
{
|
||||
public:
|
||||
explicit LibertyLibraryCellIterator(const LibertyLibrary *library);
|
||||
explicit LibertyCellIterator(const LibertyLibrary *library);
|
||||
bool hasNext();
|
||||
LibertyCell *next();
|
||||
|
||||
private:
|
||||
DISALLOW_COPY_AND_ASSIGN(LibertyLibraryCellIterator);
|
||||
DISALLOW_COPY_AND_ASSIGN(LibertyCellIterator);
|
||||
|
||||
ConcreteCellMap::ConstIterator iter_;
|
||||
};
|
||||
|
||||
class TableTemplateIterator : public TableTemplateMap::ConstIterator
|
||||
{
|
||||
public:
|
||||
TableTemplateIterator(const LibertyLibrary *library) :
|
||||
TableTemplateMap::ConstIterator(library->template_map_) {}
|
||||
};
|
||||
|
||||
class OperatingConditionsIterator : public OperatingConditionsMap::ConstIterator
|
||||
{
|
||||
public:
|
||||
OperatingConditionsIterator(const LibertyLibrary *library) :
|
||||
OperatingConditionsMap::ConstIterator(library->operating_conditions_) {}
|
||||
};
|
||||
|
||||
////////////////////////////////////////////////////////////////
|
||||
|
||||
class LibertyCell : public ConcreteCell
|
||||
{
|
||||
public:
|
||||
|
|
@ -365,8 +379,6 @@ public:
|
|||
virtual ~LibertyCell();
|
||||
const LibertyLibrary *libertyLibrary() const { return liberty_library_; }
|
||||
LibertyLibrary *libertyLibrary() { return liberty_library_; }
|
||||
LibertyCellPortIterator *libertyPortIterator() const;
|
||||
LibertyCellPortBitIterator *libertyPortBitIterator() const;
|
||||
LibertyPort *findLibertyPort(const char *name) const;
|
||||
void findLibertyPortsMatching(PatternMatch *pattern,
|
||||
LibertyPortSeq *ports) const;
|
||||
|
|
@ -395,27 +407,26 @@ public:
|
|||
bool isClockGate() const;
|
||||
void setClockGateType(ClockGateType clock_gate_type);
|
||||
virtual unsigned addTimingArcSet(TimingArcSet *set);
|
||||
void addTimingArcAttrs(TimingArcAttrs *attrs);
|
||||
virtual void addInternalPower(InternalPower *power);
|
||||
void addInternalPowerAttrs(InternalPowerAttrs *attrs);
|
||||
virtual void addLeakagePower(LeakagePower *power);
|
||||
// Call after cell is finished being constructed.
|
||||
virtual void finish(bool infer_latches,
|
||||
Report *report,
|
||||
Debug *debug);
|
||||
// Internal to LibertyCellTimingArcSetIterator.
|
||||
TimingArcSetSeq *timingArcSets(const LibertyPort *from,
|
||||
const LibertyPort *to) const;
|
||||
size_t timingArcSetCount() const;
|
||||
// Find a timing arc set equivalent to key.
|
||||
TimingArcSet *findTimingArcSet(TimingArcSet *key) const;
|
||||
TimingArcSet *findTimingArcSet(unsigned arc_set_index) const;
|
||||
CellTimingArcSetIterator *timingArcSetIterator() const;
|
||||
CellTimingArcSetIterator *timingArcSetIterator(LibertyPort *from,
|
||||
LibertyPort *to) const;
|
||||
CellTimingArcSetIterator *timingArcSetFromIterator(LibertyPort *from) const;
|
||||
CellTimingArcSetIterator *timingArcSetToIterator(LibertyPort *to) const;
|
||||
bool hasTimingArcs(LibertyPort *port) const;
|
||||
LibertyCellInternalPowerIterator *internalPowerIterator();
|
||||
LibertyCellLeakagePowerIterator *leakagePowerIterator();
|
||||
float leakagePower() const;
|
||||
InternalPowerSeq *internalPowers() const { return internal_powers_; }
|
||||
LeakagePowerSeq *leakagePowers() const { return leakage_powers_; }
|
||||
float leakagePower() const { return leakage_power_; }
|
||||
bool hasSequentials() const;
|
||||
CellSequentialIterator *sequentialIterator() const;
|
||||
void makeSequential(int size,
|
||||
bool is_register,
|
||||
FuncExpr *clk,
|
||||
|
|
@ -463,7 +474,7 @@ protected:
|
|||
virtual void addPort(ConcretePort *port);
|
||||
void setHasInternalPorts(bool has_internal);
|
||||
void setLibertyLibrary(LibertyLibrary *library);
|
||||
void deleteTimingModels();
|
||||
void deleteTimingArcAttrs();
|
||||
void makeLatchEnables(Report *report,
|
||||
Debug *debug);
|
||||
FuncExpr *findLatchEnableFunc(LibertyPort *data,
|
||||
|
|
@ -478,6 +489,7 @@ protected:
|
|||
void findDefaultCondArcs();
|
||||
virtual void translatePresetClrCheckRoles();
|
||||
virtual void inferLatchRoles(Debug *debug);
|
||||
void deleteInternalPowerAttrs();
|
||||
|
||||
LibertyLibrary *liberty_library_;
|
||||
float area_;
|
||||
|
|
@ -488,12 +500,15 @@ protected:
|
|||
bool interface_timing_;
|
||||
ClockGateType clock_gate_type_;
|
||||
TimingArcSetSeq *timing_arc_sets_;
|
||||
// Used to find matching arc sets in equivalent cells.
|
||||
TimingArcSetMap *timing_arc_set_map_;
|
||||
LibertyPortTimingArcSetMap *port_timing_arc_set_map_;
|
||||
LibertyPortTimingArcSetSeqMap *timing_arc_set_from_map_;
|
||||
LibertyPortTimingArcSetSeqMap *timing_arc_set_to_map_;
|
||||
LibertyPortPairTimingArcMap *port_timing_arc_set_map_;
|
||||
LibertyPortTimingArcMap *timing_arc_set_from_map_;
|
||||
LibertyPortTimingArcMap *timing_arc_set_to_map_;
|
||||
TimingArcAttrsSeq timing_arc_attrs_;
|
||||
bool has_infered_reg_timing_arcs_;
|
||||
InternalPowerSeq *internal_powers_;
|
||||
InternalPowerAttrsSeq internal_power_attrs_;
|
||||
LeakagePowerSeq *leakage_powers_;
|
||||
SequentialSeq *sequentials_;
|
||||
PortToSequentialMap *port_to_seq_map_;
|
||||
|
|
@ -522,6 +537,8 @@ private:
|
|||
friend class LibertyCellPortIterator;
|
||||
friend class LibertyPort;
|
||||
friend class LibertyBuilder;
|
||||
friend class LibertyCellTimingArcSetIterator;
|
||||
friend class LibertyCellSequentialIterator;
|
||||
};
|
||||
|
||||
class LibertyCellPortIterator : public Iterator<LibertyPort*>
|
||||
|
|
@ -551,11 +568,42 @@ private:
|
|||
ConcreteCellPortBitIterator *iter_;
|
||||
};
|
||||
|
||||
class LibertyCellTimingArcSetIterator : public TimingArcSetSeq::Iterator
|
||||
{
|
||||
public:
|
||||
LibertyCellTimingArcSetIterator(const LibertyCell *cell);
|
||||
LibertyCellTimingArcSetIterator(const LibertyCell *cell,
|
||||
const LibertyPort *from,
|
||||
const LibertyPort *to);
|
||||
};
|
||||
|
||||
class LibertyCellSequentialIterator : public SequentialSeq::ConstIterator
|
||||
{
|
||||
public:
|
||||
LibertyCellSequentialIterator(const LibertyCell *cell) :
|
||||
SequentialSeq::ConstIterator(cell->sequentials_) {}
|
||||
};
|
||||
|
||||
class LibertyCellLeakagePowerIterator : public LeakagePowerSeq::Iterator
|
||||
{
|
||||
public:
|
||||
LibertyCellLeakagePowerIterator(const LibertyCell *cell) :
|
||||
LeakagePowerSeq::Iterator(cell->leakagePowers()) {}
|
||||
};
|
||||
|
||||
class LibertyCellInternalPowerIterator : public InternalPowerSeq::Iterator
|
||||
{
|
||||
public:
|
||||
LibertyCellInternalPowerIterator(const LibertyCell *cell) :
|
||||
InternalPowerSeq::Iterator(cell->internalPowers()) {}
|
||||
};
|
||||
|
||||
////////////////////////////////////////////////////////////////
|
||||
|
||||
class LibertyPort : public ConcretePort
|
||||
{
|
||||
public:
|
||||
LibertyCell *libertyCell() const { return liberty_cell_; }
|
||||
LibertyPortMemberIterator *libertyMemberIterator() const;
|
||||
LibertyPort *findLibertyMember(int index) const;
|
||||
LibertyPort *findLibertyBusBit(int index) const;
|
||||
float capacitance(const TransRiseFall *tr,
|
||||
|
|
|
|||
|
|
@ -276,36 +276,28 @@ LibertyBuilder::makeCombinationalArcs(LibertyCell *cell,
|
|||
if (to_rise) {
|
||||
to_tr = TransRiseFall::rise();
|
||||
model = attrs->model(to_tr);
|
||||
if (model) {
|
||||
if (model)
|
||||
makeTimingArc(arc_set, TransRiseFall::rise(), to_tr, model);
|
||||
attrs->setModelRef(to_tr, true);
|
||||
}
|
||||
}
|
||||
if (to_fall) {
|
||||
to_tr = TransRiseFall::fall();
|
||||
model = attrs->model(to_tr);
|
||||
if (model) {
|
||||
if (model)
|
||||
makeTimingArc(arc_set, TransRiseFall::fall(), to_tr, model);
|
||||
attrs->setModelRef(to_tr, true);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case timing_sense_negative_unate:
|
||||
if (to_fall) {
|
||||
to_tr = TransRiseFall::fall();
|
||||
model = attrs->model(to_tr);
|
||||
if (model) {
|
||||
if (model)
|
||||
makeTimingArc(arc_set, TransRiseFall::rise(), to_tr, model);
|
||||
attrs->setModelRef(to_tr, true);
|
||||
}
|
||||
}
|
||||
if (to_rise) {
|
||||
to_tr = TransRiseFall::rise();
|
||||
model = attrs->model(to_tr);
|
||||
if (model) {
|
||||
if (model)
|
||||
makeTimingArc(arc_set, TransRiseFall::fall(), to_tr, model);
|
||||
attrs->setModelRef(to_tr, true);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case timing_sense_non_unate:
|
||||
|
|
@ -320,7 +312,6 @@ LibertyBuilder::makeCombinationalArcs(LibertyCell *cell,
|
|||
if (model) {
|
||||
makeTimingArc(arc_set, TransRiseFall::fall(), to_tr, model);
|
||||
makeTimingArc(arc_set, TransRiseFall::rise(), to_tr, model);
|
||||
attrs->setModelRef(to_tr, true);
|
||||
}
|
||||
}
|
||||
if (to_rise) {
|
||||
|
|
@ -329,7 +320,6 @@ LibertyBuilder::makeCombinationalArcs(LibertyCell *cell,
|
|||
if (model) {
|
||||
makeTimingArc(arc_set, TransRiseFall::rise(), to_tr, model);
|
||||
makeTimingArc(arc_set, TransRiseFall::fall(), to_tr, model);
|
||||
attrs->setModelRef(to_tr, true);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
|
@ -355,7 +345,6 @@ LibertyBuilder::makeLatchDtoQArcs(LibertyCell *cell,
|
|||
TransRiseFall *from_tr = (sense == timing_sense_negative_unate) ?
|
||||
to_tr->opposite() : to_tr;
|
||||
makeTimingArc(arc_set, from_tr, to_tr, model);
|
||||
attrs->setModelRef(to_tr, true);
|
||||
}
|
||||
to_tr = TransRiseFall::fall();
|
||||
model = attrs->model(to_tr);
|
||||
|
|
@ -363,7 +352,6 @@ LibertyBuilder::makeLatchDtoQArcs(LibertyCell *cell,
|
|||
TransRiseFall *from_tr = (sense == timing_sense_negative_unate) ?
|
||||
to_tr->opposite() : to_tr;
|
||||
makeTimingArc(arc_set, from_tr, to_tr, model);
|
||||
attrs->setModelRef(to_tr, true);
|
||||
}
|
||||
return arc_set;
|
||||
}
|
||||
|
|
@ -420,16 +408,12 @@ LibertyBuilder::makeFromTransitionArcs(LibertyCell *cell,
|
|||
TransRiseFall *to_tr;
|
||||
to_tr = TransRiseFall::rise();
|
||||
model = attrs->model(to_tr);
|
||||
if (model) {
|
||||
if (model)
|
||||
makeTimingArc(arc_set, from_tr, to_tr, model);
|
||||
attrs->setModelRef(to_tr, true);
|
||||
}
|
||||
to_tr = TransRiseFall::fall();
|
||||
model = attrs->model(to_tr);
|
||||
if (model) {
|
||||
if (model)
|
||||
makeTimingArc(arc_set, from_tr, to_tr, model);
|
||||
attrs->setModelRef(to_tr, true);
|
||||
}
|
||||
return arc_set;
|
||||
}
|
||||
|
||||
|
|
@ -450,17 +434,14 @@ LibertyBuilder::makePresetClrArcs(LibertyCell *cell,
|
|||
switch (attrs->timingSense()) {
|
||||
case timing_sense_positive_unate:
|
||||
makeTimingArc(arc_set, to_tr, to_tr, model);
|
||||
attrs->setModelRef(to_tr, true);
|
||||
break;
|
||||
case timing_sense_negative_unate:
|
||||
makeTimingArc(arc_set, opp_tr, to_tr, model);
|
||||
attrs->setModelRef(to_tr, true);
|
||||
break;
|
||||
case timing_sense_non_unate:
|
||||
case timing_sense_unknown:
|
||||
makeTimingArc(arc_set, to_tr, to_tr, model);
|
||||
makeTimingArc(arc_set, opp_tr, to_tr, model);
|
||||
attrs->setModelRef(to_tr, true);
|
||||
break;
|
||||
case timing_sense_none:
|
||||
break;
|
||||
|
|
@ -494,36 +475,28 @@ LibertyBuilder::makeTristateEnableArcs(LibertyCell *cell,
|
|||
if (to_rise) {
|
||||
to_tr = TransRiseFall::rise();
|
||||
model = attrs->model(to_tr);
|
||||
if (model) {
|
||||
if (model)
|
||||
makeTimingArc(arc_set, Transition::rise(), Transition::trZ1(), model);
|
||||
attrs->setModelRef(to_tr, true);
|
||||
}
|
||||
}
|
||||
if (to_fall) {
|
||||
to_tr = TransRiseFall::fall();
|
||||
model = attrs->model(to_tr);
|
||||
if (model) {
|
||||
if (model)
|
||||
makeTimingArc(arc_set, Transition::rise(), Transition::trZ0(), model);
|
||||
attrs->setModelRef(to_tr, true);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case timing_sense_negative_unate:
|
||||
if (to_rise) {
|
||||
to_tr = TransRiseFall::rise();
|
||||
model = attrs->model(to_tr);
|
||||
if (model) {
|
||||
if (model)
|
||||
makeTimingArc(arc_set, Transition::fall(), Transition::trZ1(), model);
|
||||
attrs->setModelRef(to_tr, true);
|
||||
}
|
||||
}
|
||||
if (to_fall) {
|
||||
to_tr = TransRiseFall::fall();
|
||||
model = attrs->model(to_tr);
|
||||
if (model) {
|
||||
if (model)
|
||||
makeTimingArc(arc_set, Transition::fall(), Transition::trZ0(), model);
|
||||
attrs->setModelRef(to_tr, true);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case timing_sense_non_unate:
|
||||
|
|
@ -534,7 +507,6 @@ LibertyBuilder::makeTristateEnableArcs(LibertyCell *cell,
|
|||
if (model) {
|
||||
makeTimingArc(arc_set, Transition::rise(), Transition::trZ1(), model);
|
||||
makeTimingArc(arc_set, Transition::fall(), Transition::trZ1(), model);
|
||||
attrs->setModelRef(to_tr, true);
|
||||
}
|
||||
}
|
||||
if (to_fall) {
|
||||
|
|
@ -543,7 +515,6 @@ LibertyBuilder::makeTristateEnableArcs(LibertyCell *cell,
|
|||
if (model) {
|
||||
makeTimingArc(arc_set, Transition::rise(), Transition::trZ0(), model);
|
||||
makeTimingArc(arc_set, Transition::fall(), Transition::trZ0(), model);
|
||||
attrs->setModelRef(to_tr, true);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
|
@ -577,36 +548,28 @@ LibertyBuilder::makeTristateDisableArcs(LibertyCell *cell,
|
|||
if (to_rise) {
|
||||
to_tr = TransRiseFall::rise();
|
||||
model = attrs->model(to_tr);
|
||||
if (model) {
|
||||
if (model)
|
||||
makeTimingArc(arc_set, Transition::rise(), Transition::tr0Z(), model);
|
||||
attrs->setModelRef(to_tr, true);
|
||||
}
|
||||
}
|
||||
if (to_fall) {
|
||||
to_tr = TransRiseFall::fall();
|
||||
model = attrs->model(to_tr);
|
||||
if (model) {
|
||||
if (model)
|
||||
makeTimingArc(arc_set, Transition::rise(), Transition::tr1Z(), model);
|
||||
attrs->setModelRef(to_tr, true);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case timing_sense_negative_unate:
|
||||
if (to_rise) {
|
||||
to_tr = TransRiseFall::rise();
|
||||
model = attrs->model(to_tr);
|
||||
if (model) {
|
||||
if (model)
|
||||
makeTimingArc(arc_set, Transition::fall(), Transition::tr0Z(), model);
|
||||
attrs->setModelRef(to_tr, true);
|
||||
}
|
||||
}
|
||||
if (to_fall) {
|
||||
to_tr = TransRiseFall::fall();
|
||||
model = attrs->model(to_tr);
|
||||
if (model) {
|
||||
if (model)
|
||||
makeTimingArc(arc_set, Transition::fall(), Transition::tr1Z(), model);
|
||||
attrs->setModelRef(to_tr, true);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case timing_sense_non_unate:
|
||||
|
|
@ -617,7 +580,6 @@ LibertyBuilder::makeTristateDisableArcs(LibertyCell *cell,
|
|||
if (model) {
|
||||
makeTimingArc(arc_set, Transition::fall(), Transition::tr0Z(), model);
|
||||
makeTimingArc(arc_set, Transition::rise(), Transition::tr0Z(), model);
|
||||
attrs->setModelRef(to_tr, true);
|
||||
}
|
||||
}
|
||||
if (to_fall) {
|
||||
|
|
@ -626,7 +588,6 @@ LibertyBuilder::makeTristateDisableArcs(LibertyCell *cell,
|
|||
if (model) {
|
||||
makeTimingArc(arc_set, Transition::fall(), Transition::tr1Z(), model);
|
||||
makeTimingArc(arc_set, Transition::rise(), Transition::tr1Z(), model);
|
||||
attrs->setModelRef(to_tr, true);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
|
|
|||
|
|
@ -55,14 +55,14 @@ class TimingRole;
|
|||
class Transition;
|
||||
class TransRiseFall;
|
||||
class TransRiseFallBoth;
|
||||
class LibertyCellSequentialIterator;
|
||||
|
||||
typedef Vector<LibertyCell*> LibertyCellSeq;
|
||||
typedef Vector<Sequential*> SequentialSeq;
|
||||
typedef SequentialSeq::ConstIterator CellSequentialIterator;
|
||||
typedef Map<LibertyCell*, LibertyCellSeq*> LibertyCellEquivMap;
|
||||
typedef Vector<LibertyPort*> LibertyPortSeq;
|
||||
typedef Set<LibertyPort*> LibertyPortSet;
|
||||
typedef std::pair<LibertyPort*,LibertyPort*> LibertyPortPair;
|
||||
typedef std::pair<const LibertyPort*,const LibertyPort*> LibertyPortPair;
|
||||
typedef Set<LibertyCell*> LibertyCellSet;
|
||||
typedef Vector<float> FloatSeq;
|
||||
typedef Vector<FloatSeq*> FloatTable;
|
||||
|
|
|
|||
|
|
@ -131,6 +131,7 @@ LibertyReader::readLibertyFile(const char *filename,
|
|||
mode_def_ = NULL;
|
||||
mode_value_ = NULL;
|
||||
ocv_derate_ = NULL;
|
||||
have_resistance_unit_ = false;
|
||||
|
||||
TransRiseFallIterator tr_iter;
|
||||
while (tr_iter.hasNext()) {
|
||||
|
|
@ -169,6 +170,7 @@ LibertyReader::defineVisitors()
|
|||
defineAttrVisitor("time_unit", &LibertyReader::visitTimeUnit);
|
||||
defineAttrVisitor("pulling_resistance_unit",
|
||||
&LibertyReader::visitPullingResistanceUnit);
|
||||
defineAttrVisitor("resistance_unit", &LibertyReader::visitResistanceUnit);
|
||||
defineAttrVisitor("capacitive_load_unit",
|
||||
&LibertyReader::visitCapacitiveLoadUnit);
|
||||
defineAttrVisitor("voltage_unit", &LibertyReader::visitVoltageUnit);
|
||||
|
|
@ -580,6 +582,12 @@ LibertyReader::endLibrary(LibertyGroup *group)
|
|||
void
|
||||
LibertyReader::endLibraryAttrs(LibertyGroup *group)
|
||||
{
|
||||
// Default resistance_unit to pulling_resistance_unit.
|
||||
if (!have_resistance_unit_) {
|
||||
Units *units = library_->units();
|
||||
units->resistanceUnit()->copy(units->pullingResistanceUnit());
|
||||
}
|
||||
|
||||
// These attributes reference named groups in the library so
|
||||
// wait until the end of the library to resolve them.
|
||||
if (default_wireload_) {
|
||||
|
|
@ -640,7 +648,17 @@ void
|
|||
LibertyReader::visitPullingResistanceUnit(LibertyAttr *attr)
|
||||
{
|
||||
if (library_)
|
||||
parseUnits(attr, "ohm", res_scale_,
|
||||
library_->units()->pullingResistanceUnit());
|
||||
}
|
||||
|
||||
void
|
||||
LibertyReader::visitResistanceUnit(LibertyAttr *attr)
|
||||
{
|
||||
if (library_) {
|
||||
parseUnits(attr, "ohm", res_scale_, library_->units()->resistanceUnit());
|
||||
have_resistance_unit_ = true;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
|
|
@ -700,8 +718,8 @@ LibertyReader::parseUnits(LibertyAttr *attr,
|
|||
}
|
||||
|
||||
float scale_mult = 1.0F;
|
||||
if (stringEq(s + 1, unit_suffix)) {
|
||||
char scale_char = *s;
|
||||
if (*s && stringEqual(s + 1, unit_suffix)) {
|
||||
char scale_char = tolower(*s);
|
||||
if (scale_char == 'k')
|
||||
scale_mult = 1E+3F;
|
||||
else if (scale_char == 'm')
|
||||
|
|
@ -717,7 +735,7 @@ LibertyReader::parseUnits(LibertyAttr *attr,
|
|||
else
|
||||
libWarn(attr, "unknown unit scale %c.\n", scale_char);
|
||||
}
|
||||
else if (!stringEq(s, unit_suffix))
|
||||
else if (!stringEqual(s, unit_suffix))
|
||||
libWarn(attr, "unknown unit suffix %s.\n", s + 1);
|
||||
|
||||
scale_var = scale_mult * mult;
|
||||
|
|
@ -738,9 +756,9 @@ LibertyReader::visitCapacitiveLoadUnit(LibertyAttr *attr)
|
|||
value = value_iter.next();
|
||||
if (value->isString()) {
|
||||
const char *suffix = value->stringValue();
|
||||
if (stringEq(suffix, "ff"))
|
||||
if (stringEqual(suffix, "ff"))
|
||||
cap_scale_ = scale * 1E-15F;
|
||||
else if (stringEq(suffix, "pf"))
|
||||
else if (stringEqual(suffix, "pf"))
|
||||
cap_scale_ = scale * 1E-12F;
|
||||
else
|
||||
libWarn(attr, "capacitive_load_units are not ff or pf.\n");
|
||||
|
|
@ -1814,15 +1832,7 @@ LibertyReader::makeTimingArcs(PortGroup *port_group)
|
|||
LibertyPort *port = port_iter.next();
|
||||
makeTimingArcs(port, timing);
|
||||
}
|
||||
|
||||
// Delete unreferenced models to prevent memory leak.
|
||||
TransRiseFallIterator tr_iter;
|
||||
while (tr_iter.hasNext()) {
|
||||
TransRiseFall *tr = tr_iter.next();
|
||||
TimingModel *model = timing->model(tr);
|
||||
if (model && !timing->modelRef(tr))
|
||||
delete model;
|
||||
}
|
||||
cell_->addTimingArcAttrs(timing);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -1837,6 +1847,7 @@ LibertyReader::makeInternalPowers(PortGroup *port_group)
|
|||
LibertyPort *port = port_iter.next();
|
||||
makeInternalPowers(port, power_group);
|
||||
}
|
||||
cell_->addInternalPowerAttrs(power_group);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -2205,27 +2216,25 @@ LibertyReader::makeTimingArcs(const char *from_port_name,
|
|||
// one -> bus
|
||||
if (from_port_iter.hasNext()) {
|
||||
LibertyPort *from_port = from_port_iter.next();
|
||||
LibertyPortMemberIterator *bit_iter = to_port->libertyMemberIterator();
|
||||
while (bit_iter->hasNext()) {
|
||||
LibertyPort *to_port_bit = bit_iter->next();
|
||||
LibertyPortMemberIterator bit_iter(to_port);
|
||||
while (bit_iter.hasNext()) {
|
||||
LibertyPort *to_port_bit = bit_iter.next();
|
||||
builder_->makeTimingArcs(cell_, from_port, to_port_bit,
|
||||
related_out_port, timing);
|
||||
}
|
||||
delete bit_iter;
|
||||
}
|
||||
}
|
||||
else {
|
||||
// bus -> bus
|
||||
if (timing->isOneToOne()) {
|
||||
if (static_cast<int>(from_port_iter.size()) == to_port->size()) {
|
||||
LibertyPortMemberIterator *to_iter = to_port->libertyMemberIterator();
|
||||
while (from_port_iter.hasNext() && to_iter->hasNext()) {
|
||||
LibertyPortMemberIterator to_iter(to_port);
|
||||
while (from_port_iter.hasNext() && to_iter.hasNext()) {
|
||||
LibertyPort *from_port_bit = from_port_iter.next();
|
||||
LibertyPort *to_port_bit = to_iter->next();
|
||||
LibertyPort *to_port_bit = to_iter.next();
|
||||
builder_->makeTimingArcs(cell_, from_port_bit, to_port_bit,
|
||||
related_out_port, timing);
|
||||
}
|
||||
delete to_iter;
|
||||
}
|
||||
else
|
||||
libWarn(timing->line(),
|
||||
|
|
@ -2236,13 +2245,12 @@ LibertyReader::makeTimingArcs(const char *from_port_name,
|
|||
else {
|
||||
while (from_port_iter.hasNext()) {
|
||||
LibertyPort *from_port_bit = from_port_iter.next();
|
||||
LibertyPortMemberIterator *to_iter = to_port->libertyMemberIterator();
|
||||
while (to_iter->hasNext()) {
|
||||
LibertyPort *to_port_bit = to_iter->next();
|
||||
LibertyPortMemberIterator to_iter(to_port);
|
||||
while (to_iter.hasNext()) {
|
||||
LibertyPort *to_port_bit = to_iter.next();
|
||||
builder_->makeTimingArcs(cell_, from_port_bit, to_port_bit,
|
||||
related_out_port, timing);
|
||||
}
|
||||
delete to_iter;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -2270,12 +2278,11 @@ LibertyReader::makeInternalPowers(LibertyPort *port,
|
|||
}
|
||||
else {
|
||||
if (port->hasMembers()) {
|
||||
LibertyPortMemberIterator *bit_iter = port->libertyMemberIterator();
|
||||
while (bit_iter->hasNext()) {
|
||||
LibertyPort *port_bit = bit_iter->next();
|
||||
LibertyPortMemberIterator bit_iter(port);
|
||||
while (bit_iter.hasNext()) {
|
||||
LibertyPort *port_bit = bit_iter.next();
|
||||
builder_->makeInternalPower(cell_, port_bit, NULL, power_group);
|
||||
}
|
||||
delete bit_iter;
|
||||
}
|
||||
else
|
||||
builder_->makeInternalPower(cell_, port, NULL, power_group);
|
||||
|
|
@ -2306,25 +2313,23 @@ LibertyReader::makeInternalPowers(LibertyPort *port,
|
|||
// one -> bus
|
||||
if (related_port_iter.hasNext()) {
|
||||
LibertyPort *related_port = related_port_iter.next();
|
||||
LibertyPortMemberIterator *bit_iter = port->libertyMemberIterator();
|
||||
while (bit_iter->hasNext()) {
|
||||
LibertyPort *port_bit = bit_iter->next();
|
||||
LibertyPortMemberIterator bit_iter(port);
|
||||
while (bit_iter.hasNext()) {
|
||||
LibertyPort *port_bit = bit_iter.next();
|
||||
builder_->makeInternalPower(cell_, port_bit, related_port, power_group);
|
||||
}
|
||||
delete bit_iter;
|
||||
}
|
||||
}
|
||||
else {
|
||||
// bus -> bus
|
||||
if (power_group->isOneToOne()) {
|
||||
if (static_cast<int>(related_port_iter.size()) == port->size()) {
|
||||
LibertyPortMemberIterator *to_iter = port->libertyMemberIterator();
|
||||
while (related_port_iter.hasNext() && to_iter->hasNext()) {
|
||||
LibertyPortMemberIterator to_iter(port);
|
||||
while (related_port_iter.hasNext() && to_iter.hasNext()) {
|
||||
LibertyPort *related_port_bit = related_port_iter.next();
|
||||
LibertyPort *port_bit = to_iter->next();
|
||||
LibertyPort *port_bit = to_iter.next();
|
||||
builder_->makeInternalPower(cell_, port_bit, related_port_bit, power_group);
|
||||
}
|
||||
delete to_iter;
|
||||
}
|
||||
else
|
||||
libWarn(power_group->line(),
|
||||
|
|
@ -2335,12 +2340,11 @@ LibertyReader::makeInternalPowers(LibertyPort *port,
|
|||
else {
|
||||
while (related_port_iter.hasNext()) {
|
||||
LibertyPort *related_port_bit = related_port_iter.next();
|
||||
LibertyPortMemberIterator *to_iter = port->libertyMemberIterator();
|
||||
while (to_iter->hasNext()) {
|
||||
LibertyPort *port_bit = to_iter->next();
|
||||
LibertyPortMemberIterator to_iter(port);
|
||||
while (to_iter.hasNext()) {
|
||||
LibertyPort *port_bit = to_iter.next();
|
||||
builder_->makeInternalPower(cell_, port_bit, related_port_bit, power_group);
|
||||
}
|
||||
delete to_iter;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -2562,12 +2566,11 @@ LibertyReader::endPorts(LibertyGroup *)
|
|||
if (in_bus_ || in_bundle_) {
|
||||
// Do not clobber member port capacitances by setting the capacitance
|
||||
// on a bus or bundle.
|
||||
LibertyPortMemberIterator *member_iter = port->libertyMemberIterator();
|
||||
while (member_iter->hasNext()) {
|
||||
LibertyPort *member = member_iter->next();
|
||||
LibertyPortMemberIterator member_iter(port);
|
||||
while (member_iter.hasNext()) {
|
||||
LibertyPort *member = member_iter.next();
|
||||
setPortCapDefault(member);
|
||||
}
|
||||
delete member_iter;
|
||||
}
|
||||
else
|
||||
setPortCapDefault(port);
|
||||
|
|
@ -4447,7 +4450,7 @@ LibertyReader::visitRelatedPowerPin(LibertyAttr *attr)
|
|||
LibertyPortSeq::Iterator port_iter(ports_);
|
||||
while (port_iter.hasNext()) {
|
||||
LibertyPort *port = port_iter.next();
|
||||
port->setRelatedPowerPin(stringCopy(related_power_pin));
|
||||
port->setRelatedPowerPin(related_power_pin);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -4699,8 +4702,8 @@ PortGroup::PortGroup(LibertyPortSeq *ports,
|
|||
|
||||
PortGroup::~PortGroup()
|
||||
{
|
||||
timings_.deleteContents();
|
||||
internal_power_groups_.deleteContents();
|
||||
// TimingGroups and IntternalPower are NOT deleted because ownership is transfered
|
||||
// to LibertyCell::timing_arc_attrs_ by LibertyReader::makeTimingArcs.
|
||||
delete ports_;
|
||||
}
|
||||
|
||||
|
|
@ -4846,6 +4849,8 @@ TimingGroup::TimingGroup(int line) :
|
|||
|
||||
TimingGroup::~TimingGroup()
|
||||
{
|
||||
// TimingAttrs contents are not deleted because they are referenced
|
||||
// by TimingArcSets.
|
||||
if (related_output_port_name_)
|
||||
stringDelete(related_output_port_name_);
|
||||
}
|
||||
|
|
@ -5000,7 +5005,7 @@ PortNameBitIterator::init(const char *port_name)
|
|||
LibertyPort *port = visitor_->findPort(cell_, port_name);
|
||||
if (port) {
|
||||
if (port->isBus())
|
||||
bit_iterator_ = port->libertyMemberIterator();
|
||||
bit_iterator_ = new LibertyPortMemberIterator(port);
|
||||
else
|
||||
port_ = port;
|
||||
size_ = port->size();
|
||||
|
|
|
|||
|
|
@ -78,6 +78,7 @@ public:
|
|||
virtual void visitAttr(LibertyAttr *attr);
|
||||
virtual void visitTimeUnit(LibertyAttr *attr);
|
||||
virtual void visitCapacitiveLoadUnit(LibertyAttr *attr);
|
||||
virtual void visitResistanceUnit(LibertyAttr *attr);
|
||||
virtual void visitPullingResistanceUnit(LibertyAttr *attr);
|
||||
virtual void visitVoltageUnit(LibertyAttr *attr);
|
||||
virtual void visitCurrentUnit(LibertyAttr *attr);
|
||||
|
|
@ -546,6 +547,7 @@ protected:
|
|||
float curr_scale_;
|
||||
float power_scale_;
|
||||
float energy_scale_;
|
||||
bool have_resistance_unit_;
|
||||
|
||||
private:
|
||||
DISALLOW_COPY_AND_ASSIGN(LibertyReader);
|
||||
|
|
|
|||
|
|
@ -25,7 +25,6 @@ namespace sta {
|
|||
|
||||
static void
|
||||
reportPvt(const LibertyLibrary *library,
|
||||
const LibertyCell *cell,
|
||||
const Pvt *pvt,
|
||||
int digits,
|
||||
string *result);
|
||||
|
|
@ -124,7 +123,7 @@ GateTableModel::reportGateDelay(const LibertyCell *cell,
|
|||
string *result) const
|
||||
{
|
||||
const LibertyLibrary *library = cell->libertyLibrary();
|
||||
reportPvt(library, cell, pvt, digits, result);
|
||||
reportPvt(library, pvt, digits, result);
|
||||
reportTableLookup("Delay", library, cell, pvt, delay_model_, in_slew,
|
||||
load_cap, related_out_cap, digits, result);
|
||||
if (delay_sigma_models_[EarlyLate::earlyIndex()])
|
||||
|
|
@ -386,7 +385,7 @@ CheckTableModel::reportCheckDelay(const LibertyCell *cell,
|
|||
findAxisValues(from_slew, to_slew, related_out_cap,
|
||||
axis_value1, axis_value2, axis_value3);
|
||||
const LibertyLibrary *library = cell->libertyLibrary();
|
||||
reportPvt(library, cell, pvt, digits, result);
|
||||
reportPvt(library, pvt, digits, result);
|
||||
model_->reportValue("Check", library, cell, pvt,
|
||||
axis_value1, from_slew_annotation, axis_value2,
|
||||
axis_value3, digits, result);
|
||||
|
|
@ -586,7 +585,6 @@ TableModel::reportValue(const char *result_name,
|
|||
|
||||
static void
|
||||
reportPvt(const LibertyLibrary *library,
|
||||
const LibertyCell *cell,
|
||||
const Pvt *pvt,
|
||||
int digits,
|
||||
string *result)
|
||||
|
|
|
|||
|
|
@ -18,6 +18,7 @@
|
|||
#include "FuncExpr.hh"
|
||||
#include "TimingRole.hh"
|
||||
#include "Liberty.hh"
|
||||
#include "TimingModel.hh"
|
||||
#include "TimingArc.hh"
|
||||
|
||||
namespace sta {
|
||||
|
|
@ -41,18 +42,29 @@ TimingArcAttrs::TimingArcAttrs() :
|
|||
mode_name_(NULL),
|
||||
mode_value_(NULL),
|
||||
ocv_arc_depth_(0.0),
|
||||
models_{NULL, NULL},
|
||||
model_refs_{false, false}
|
||||
models_{NULL, NULL}
|
||||
{
|
||||
}
|
||||
|
||||
// Destructor does NOT delete contents because it is a component
|
||||
// of TimingGroup (that is deleted after building the LibertyCell)
|
||||
// and (potentially) multiple TimingArcSets.
|
||||
TimingArcAttrs::~TimingArcAttrs()
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
TimingArcAttrs::deleteContents()
|
||||
{
|
||||
if (cond_)
|
||||
cond_->deleteSubexprs();
|
||||
stringDelete(sdf_cond_);
|
||||
stringDelete(sdf_cond_start_);
|
||||
stringDelete(sdf_cond_end_);
|
||||
stringDelete(mode_name_);
|
||||
stringDelete(mode_value_);
|
||||
delete models_[0];
|
||||
delete models_[1];
|
||||
}
|
||||
|
||||
void
|
||||
|
|
@ -115,19 +127,6 @@ TimingArcAttrs::setModel(TransRiseFall *tr,
|
|||
models_[tr->index()] = model;
|
||||
}
|
||||
|
||||
bool
|
||||
TimingArcAttrs::modelRef(TransRiseFall *tr) const
|
||||
{
|
||||
return model_refs_[tr->index()];
|
||||
}
|
||||
|
||||
void
|
||||
TimingArcAttrs::setModelRef(TransRiseFall *tr,
|
||||
bool ref)
|
||||
{
|
||||
model_refs_[tr->index()] = ref;
|
||||
}
|
||||
|
||||
void
|
||||
TimingArcAttrs::setOcvArcDepth(float depth)
|
||||
{
|
||||
|
|
@ -150,51 +149,36 @@ TimingArcSet::TimingArcSet(LibertyCell *cell,
|
|||
role_(role),
|
||||
cond_(attrs->cond()),
|
||||
is_cond_default_(false),
|
||||
sdf_cond_start_(NULL),
|
||||
sdf_cond_end_(NULL),
|
||||
mode_name_(stringCopy(attrs->modeName())),
|
||||
mode_value_(stringCopy(attrs->modeValue())),
|
||||
sdf_cond_start_(attrs->sdfCondStart()),
|
||||
sdf_cond_end_(attrs->sdfCondEnd()),
|
||||
mode_name_(attrs->modeName()),
|
||||
mode_value_(attrs->modeValue()),
|
||||
ocv_arc_depth_(attrs->ocvArcDepth()),
|
||||
index_(0),
|
||||
is_disabled_constraint_(false)
|
||||
{
|
||||
const char *sdf_cond = attrs->sdfCond();
|
||||
const char *sdf_cond_start = attrs->sdfCondStart();
|
||||
const char *sdf_cond_end = attrs->sdfCondEnd();
|
||||
if (sdf_cond)
|
||||
sdf_cond_start = sdf_cond_end = sdf_cond;
|
||||
if (sdf_cond_start)
|
||||
sdf_cond_start_ = stringCopy(sdf_cond_start);
|
||||
if (sdf_cond_end)
|
||||
sdf_cond_end_ = stringCopy(sdf_cond_end);
|
||||
sdf_cond_start_ = sdf_cond_end_ = sdf_cond;
|
||||
|
||||
init(cell);
|
||||
}
|
||||
|
||||
TimingArcSet::TimingArcSet(LibertyCell *cell,
|
||||
LibertyPort *from,
|
||||
LibertyPort *to,
|
||||
LibertyPort *related_out,
|
||||
TimingRole *role,
|
||||
FuncExpr *cond,
|
||||
const char *sdf_cond_start,
|
||||
const char *sdf_cond_end,
|
||||
const char *mode_name,
|
||||
const char *mode_value) :
|
||||
from_(from),
|
||||
to_(to),
|
||||
related_out_(related_out),
|
||||
TimingArcSet::TimingArcSet(TimingRole *role) :
|
||||
from_(NULL),
|
||||
to_(NULL),
|
||||
related_out_(NULL),
|
||||
role_(role),
|
||||
cond_(cond),
|
||||
cond_(NULL),
|
||||
is_cond_default_(false),
|
||||
sdf_cond_start_(stringCopy(sdf_cond_start)),
|
||||
sdf_cond_end_(stringCopy(sdf_cond_end)),
|
||||
mode_name_(stringCopy(mode_name)),
|
||||
mode_value_(stringCopy(mode_value)),
|
||||
sdf_cond_start_(NULL),
|
||||
sdf_cond_end_(NULL),
|
||||
mode_name_(NULL),
|
||||
mode_value_(NULL),
|
||||
index_(0),
|
||||
is_disabled_constraint_(false)
|
||||
{
|
||||
init(cell);
|
||||
init(NULL);
|
||||
}
|
||||
|
||||
void
|
||||
|
|
@ -283,12 +267,6 @@ TimingArcSet::setIsCondDefault(bool is_default)
|
|||
is_cond_default_ = is_default;
|
||||
}
|
||||
|
||||
TimingArcSetArcIterator *
|
||||
TimingArcSet::timingArcIterator() const
|
||||
{
|
||||
return new TimingArcSetArcIterator(this);
|
||||
}
|
||||
|
||||
void
|
||||
TimingArcSet::arcsFrom(const TransRiseFall *from_tr,
|
||||
// Return values.
|
||||
|
|
@ -373,21 +351,15 @@ static bool
|
|||
timingArcsEquiv(const TimingArcSet *set1,
|
||||
const TimingArcSet *set2)
|
||||
{
|
||||
TimingArcSetArcIterator *arc_iter1 = set1->timingArcIterator();
|
||||
TimingArcSetArcIterator *arc_iter2 = set2->timingArcIterator();
|
||||
while (arc_iter1->hasNext() && arc_iter2->hasNext()) {
|
||||
TimingArc *arc1 = arc_iter1->next();
|
||||
TimingArc *arc2 = arc_iter2->next();
|
||||
if (!TimingArc::equiv(arc1, arc2)) {
|
||||
delete arc_iter1;
|
||||
delete arc_iter2;
|
||||
TimingArcSetArcIterator arc_iter1(set1);
|
||||
TimingArcSetArcIterator arc_iter2(set2);
|
||||
while (arc_iter1.hasNext() && arc_iter2.hasNext()) {
|
||||
TimingArc *arc1 = arc_iter1.next();
|
||||
TimingArc *arc2 = arc_iter2.next();
|
||||
if (!TimingArc::equiv(arc1, arc2))
|
||||
return false;
|
||||
}
|
||||
}
|
||||
bool eq = !arc_iter1->hasNext() && !arc_iter2->hasNext();
|
||||
delete arc_iter1;
|
||||
delete arc_iter2;
|
||||
return eq;
|
||||
return !arc_iter1.hasNext() && !arc_iter2.hasNext();
|
||||
}
|
||||
|
||||
bool
|
||||
|
|
@ -461,42 +433,27 @@ static bool
|
|||
timingArcsLess(const TimingArcSet *set1,
|
||||
const TimingArcSet *set2)
|
||||
{
|
||||
TimingArcSetArcIterator *arc_iter1 = set1->timingArcIterator();
|
||||
TimingArcSetArcIterator *arc_iter2 = set2->timingArcIterator();
|
||||
while (arc_iter1->hasNext() && arc_iter2->hasNext()) {
|
||||
TimingArc *arc1 = arc_iter1->next();
|
||||
TimingArc *arc2 = arc_iter2->next();
|
||||
TimingArcSetArcIterator arc_iter1(set1);
|
||||
TimingArcSetArcIterator arc_iter2(set2);
|
||||
while (arc_iter1.hasNext() && arc_iter2.hasNext()) {
|
||||
TimingArc *arc1 = arc_iter1.next();
|
||||
TimingArc *arc2 = arc_iter2.next();
|
||||
int from_index1 = arc1->fromTrans()->index();
|
||||
int from_index2 = arc2->fromTrans()->index();
|
||||
if (from_index1 < from_index2) {
|
||||
delete arc_iter1;
|
||||
delete arc_iter2;
|
||||
if (from_index1 < from_index2)
|
||||
return true;
|
||||
}
|
||||
if (from_index1 > from_index2) {
|
||||
delete arc_iter1;
|
||||
delete arc_iter2;
|
||||
if (from_index1 > from_index2)
|
||||
return false;
|
||||
}
|
||||
// from_index1 == from_index2
|
||||
int to_index1 = arc1->toTrans()->index();
|
||||
int to_index2 = arc2->toTrans()->index();
|
||||
if (to_index1 < to_index2) {
|
||||
delete arc_iter1;
|
||||
delete arc_iter2;
|
||||
if (to_index1 < to_index2)
|
||||
return true;
|
||||
}
|
||||
if (to_index1 > to_index2) {
|
||||
delete arc_iter1;
|
||||
delete arc_iter2;
|
||||
if (to_index1 > to_index2)
|
||||
return false;
|
||||
}
|
||||
// Continue if arc transitions are equal.
|
||||
}
|
||||
bool less = !arc_iter1->hasNext() && arc_iter2->hasNext();
|
||||
delete arc_iter1;
|
||||
delete arc_iter2;
|
||||
return less;
|
||||
return !arc_iter1.hasNext() && arc_iter2.hasNext();
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////
|
||||
|
|
@ -510,9 +467,7 @@ TimingArcSet::wireArcIndex(const TransRiseFall *tr)
|
|||
void
|
||||
TimingArcSet::init()
|
||||
{
|
||||
wire_timing_arc_set_ = new TimingArcSet(NULL,NULL,NULL,NULL,
|
||||
TimingRole::wire(),
|
||||
NULL, NULL, NULL, NULL, NULL);
|
||||
wire_timing_arc_set_ = new TimingArcSet(TimingRole::wire());
|
||||
new TimingArc(wire_timing_arc_set_, Transition::rise(),
|
||||
Transition::rise(), NULL);
|
||||
new TimingArc(wire_timing_arc_set_, Transition::fall(),
|
||||
|
|
|
|||
|
|
@ -94,6 +94,7 @@ class TimingArcAttrs
|
|||
public:
|
||||
TimingArcAttrs();
|
||||
virtual ~TimingArcAttrs();
|
||||
void deleteContents();
|
||||
TimingType timingType() const { return timing_type_; }
|
||||
void setTimingType(TimingType type);
|
||||
TimingSense timingSense() const { return timing_sense_; }
|
||||
|
|
@ -113,9 +114,6 @@ public:
|
|||
TimingModel *model(TransRiseFall *tr) const;
|
||||
void setModel(TransRiseFall *tr,
|
||||
TimingModel *model);
|
||||
bool modelRef(TransRiseFall *tr) const;
|
||||
void setModelRef(TransRiseFall *tr,
|
||||
bool ref);
|
||||
float ocvArcDepth() const { return ocv_arc_depth_; }
|
||||
void setOcvArcDepth(float depth);
|
||||
|
||||
|
|
@ -130,7 +128,6 @@ protected:
|
|||
const char *mode_value_;
|
||||
float ocv_arc_depth_;
|
||||
TimingModel *models_[TransRiseFall::index_count];
|
||||
bool model_refs_[TransRiseFall::index_count];
|
||||
|
||||
private:
|
||||
DISALLOW_COPY_AND_ASSIGN(TimingArcAttrs);
|
||||
|
|
@ -150,16 +147,6 @@ public:
|
|||
LibertyPort *related_out,
|
||||
TimingRole *role,
|
||||
TimingArcAttrs *attrs);
|
||||
TimingArcSet(LibertyCell *cell,
|
||||
LibertyPort *from,
|
||||
LibertyPort *to,
|
||||
LibertyPort *related_out,
|
||||
TimingRole *role,
|
||||
FuncExpr *cond,
|
||||
const char *sdf_cond_start,
|
||||
const char *sdf_cond_end,
|
||||
const char *mode_name,
|
||||
const char *mode_value);
|
||||
virtual ~TimingArcSet();
|
||||
LibertyCell *libertyCell() const;
|
||||
LibertyPort *from() const { return from_; }
|
||||
|
|
@ -170,7 +157,6 @@ public:
|
|||
// Rise/fall if the arc set is rising_edge or falling_edge.
|
||||
TransRiseFall *isRisingFallingEdge() const;
|
||||
size_t arcCount() const { return arcs_.size(); }
|
||||
TimingArcSetArcIterator *timingArcIterator() const;
|
||||
TimingArcSeq &arcs() { return arcs_; }
|
||||
// Return 1 or 2 arcs matching from transition.
|
||||
void arcsFrom(const TransRiseFall *from_tr,
|
||||
|
|
@ -217,6 +203,7 @@ public:
|
|||
|
||||
protected:
|
||||
void init(LibertyCell *cell);
|
||||
TimingArcSet(TimingRole *role);
|
||||
|
||||
LibertyPort *from_;
|
||||
LibertyPort *to_;
|
||||
|
|
|
|||
|
|
@ -66,6 +66,8 @@ public:
|
|||
const Unit *voltageUnit() const { return &voltage_unit_; }
|
||||
Unit *resistanceUnit() { return &resistance_unit_; }
|
||||
const Unit *resistanceUnit() const { return &resistance_unit_; }
|
||||
Unit *pullingResistanceUnit() { return &pulling_resistance_unit_; }
|
||||
const Unit *pullingResistanceUnit() const {return &pulling_resistance_unit_;}
|
||||
Unit *currentUnit() { return ¤t_unit_; }
|
||||
const Unit *currentUnit() const { return ¤t_unit_; }
|
||||
Unit *powerUnit() { return &power_unit_; }
|
||||
|
|
@ -82,6 +84,7 @@ private:
|
|||
Unit capacitance_unit_;
|
||||
Unit voltage_unit_;
|
||||
Unit resistance_unit_;
|
||||
Unit pulling_resistance_unit_;
|
||||
Unit current_unit_;
|
||||
Unit power_unit_;
|
||||
Unit distance_unit_;
|
||||
|
|
|
|||
51
sdc/Sdc.cc
51
sdc/Sdc.cc
|
|
@ -401,14 +401,13 @@ Sdc::removeLibertyAnnotations()
|
|||
LibertyPortPairSet::Iterator from_to_iter(disable->fromTo());
|
||||
while (from_to_iter.hasNext()) {
|
||||
LibertyPortPair *pair = from_to_iter.next();
|
||||
LibertyPort *from = pair->first;
|
||||
LibertyPort *to = pair->second;
|
||||
CellTimingArcSetIterator *arc_iter = cell->timingArcSetIterator(from, to);
|
||||
while (arc_iter->hasNext()) {
|
||||
TimingArcSet *arc_set = arc_iter->next();
|
||||
const LibertyPort *from = pair->first;
|
||||
const LibertyPort *to = pair->second;
|
||||
LibertyCellTimingArcSetIterator arc_iter(cell, from, to);
|
||||
while (arc_iter.hasNext()) {
|
||||
TimingArcSet *arc_set = arc_iter.next();
|
||||
arc_set->setIsDisabledConstraint(false);
|
||||
}
|
||||
delete arc_iter;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -3704,12 +3703,11 @@ Sdc::disable(LibertyCell *cell,
|
|||
}
|
||||
if (from && to) {
|
||||
disabled_cell->setDisabledFromTo(from, to);
|
||||
CellTimingArcSetIterator *arc_iter = cell->timingArcSetIterator(from, to);
|
||||
while (arc_iter->hasNext()) {
|
||||
TimingArcSet *arc_set = arc_iter->next();
|
||||
LibertyCellTimingArcSetIterator arc_iter(cell, from, to);
|
||||
while (arc_iter.hasNext()) {
|
||||
TimingArcSet *arc_set = arc_iter.next();
|
||||
arc_set->setIsDisabledConstraint(true);
|
||||
}
|
||||
delete arc_iter;
|
||||
}
|
||||
else if (from) {
|
||||
disabled_cell->setDisabledFrom(from);
|
||||
|
|
@ -3734,12 +3732,11 @@ Sdc::removeDisable(LibertyCell *cell,
|
|||
if (disabled_cell) {
|
||||
if (from && to) {
|
||||
disabled_cell->removeDisabledFromTo(from, to);
|
||||
CellTimingArcSetIterator *arc_iter = cell->timingArcSetIterator(from, to);
|
||||
while (arc_iter->hasNext()) {
|
||||
TimingArcSet *arc_set = arc_iter->next();
|
||||
LibertyCellTimingArcSetIterator arc_iter(cell, from, to);
|
||||
while (arc_iter.hasNext()) {
|
||||
TimingArcSet *arc_set = arc_iter.next();
|
||||
arc_set->setIsDisabledConstraint(false);
|
||||
}
|
||||
delete arc_iter;
|
||||
}
|
||||
else if (from) {
|
||||
disabled_cell->removeDisabledFrom(from);
|
||||
|
|
@ -4212,16 +4209,13 @@ Sdc::exceptionToInvalid(const Pin *pin)
|
|||
LibertyPort *port = network_->libertyPort(pin);
|
||||
if (port) {
|
||||
LibertyCell *cell = port->libertyCell();
|
||||
CellTimingArcSetIterator *set_iter = cell->timingArcSetToIterator(port);
|
||||
while (set_iter->hasNext()) {
|
||||
TimingArcSet *set = set_iter->next();
|
||||
LibertyCellTimingArcSetIterator set_iter(cell, NULL, port);
|
||||
while (set_iter.hasNext()) {
|
||||
TimingArcSet *set = set_iter.next();
|
||||
TimingRole *role = set->role();
|
||||
if (role->genericRole() == TimingRole::regClkToQ()) {
|
||||
delete set_iter;
|
||||
if (role->genericRole() == TimingRole::regClkToQ())
|
||||
return true;
|
||||
}
|
||||
}
|
||||
delete set_iter;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
|
@ -4381,15 +4375,12 @@ Sdc::hasLibertyChecks(const Pin *pin)
|
|||
if (cell) {
|
||||
LibertyPort *port = network_->libertyPort(pin);
|
||||
if (port) {
|
||||
CellTimingArcSetIterator *timing_iter=cell->timingArcSetToIterator(port);
|
||||
while (timing_iter->hasNext()) {
|
||||
TimingArcSet *arc_set = timing_iter->next();
|
||||
if (arc_set->role()->isTimingCheck()) {
|
||||
delete timing_iter;
|
||||
LibertyCellTimingArcSetIterator timing_iter(cell, NULL, port);
|
||||
while (timing_iter.hasNext()) {
|
||||
TimingArcSet *arc_set = timing_iter.next();
|
||||
if (arc_set->role()->isTimingCheck())
|
||||
return true;
|
||||
}
|
||||
}
|
||||
delete timing_iter;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
|
|
@ -6463,8 +6454,8 @@ Sdc::setEdgeDisabledInstPorts(DisabledPorts *disabled_port,
|
|||
LibertyPortPairSet::Iterator from_to_iter(disabled_port->fromTo());
|
||||
while (from_to_iter.hasNext()) {
|
||||
LibertyPortPair *pair = from_to_iter.next();
|
||||
LibertyPort *from_port = pair->first;
|
||||
LibertyPort *to_port = pair->second;
|
||||
const LibertyPort *from_port = pair->first;
|
||||
const LibertyPort *to_port = pair->second;
|
||||
Pin *from_pin = network_->findPin(inst, from_port);
|
||||
Pin *to_pin = network_->findPin(inst, to_port);
|
||||
if (from_pin && network_->direction(from_pin)->isAnyInput()
|
||||
|
|
|
|||
|
|
@ -1059,8 +1059,8 @@ WriteSdc::writeDisabledCells() const
|
|||
LibertyPortPairSeq::Iterator pair_iter(pairs);
|
||||
while (pair_iter.hasNext()) {
|
||||
LibertyPortPair *from_to = pair_iter.next();
|
||||
LibertyPort *from = from_to->first;
|
||||
LibertyPort *to = from_to->second;
|
||||
const LibertyPort *from = from_to->first;
|
||||
const LibertyPort *to = from_to->second;
|
||||
fprintf(stream_, "set_disable_timing -from {%s} -to {%s} ",
|
||||
from->name(),
|
||||
to->name());
|
||||
|
|
@ -1151,8 +1151,8 @@ WriteSdc::writeDisabledInstances() const
|
|||
LibertyPortPairSeq::Iterator pair_iter(pairs);
|
||||
while (pair_iter.hasNext()) {
|
||||
LibertyPortPair *from_to = pair_iter.next();
|
||||
LibertyPort *from_port = from_to->first;
|
||||
LibertyPort *to_port = from_to->second;
|
||||
const LibertyPort *from_port = from_to->first;
|
||||
const LibertyPort *to_port = from_to->second;
|
||||
fprintf(stream_, "set_disable_timing -from {%s} -to {%s} ",
|
||||
from_port->name(),
|
||||
to_port->name());
|
||||
|
|
|
|||
|
|
@ -295,9 +295,9 @@ SdfReader::setEdgeDelays(Edge *edge,
|
|||
if (triple_count == 1
|
||||
|| triple_count == 2) {
|
||||
TimingArcSet *arc_set = edge->timingArcSet();
|
||||
TimingArcSetArcIterator *arc_iter = arc_set->timingArcIterator();
|
||||
while (arc_iter->hasNext()) {
|
||||
TimingArc *arc = arc_iter->next();
|
||||
TimingArcSetArcIterator arc_iter(arc_set);
|
||||
while (arc_iter.hasNext()) {
|
||||
TimingArc *arc = arc_iter.next();
|
||||
size_t triple_index;
|
||||
if (triple_count == 1)
|
||||
triple_index = 0;
|
||||
|
|
@ -306,7 +306,6 @@ SdfReader::setEdgeDelays(Edge *edge,
|
|||
SdfTriple *triple = (*triples)[triple_index];
|
||||
setEdgeArcDelays(edge, arc, triple);
|
||||
}
|
||||
delete arc_iter;
|
||||
}
|
||||
else if (triple_count == 0)
|
||||
sdfError("%s with no triples.\n", sdf_cmd);
|
||||
|
|
@ -404,9 +403,9 @@ SdfReader::iopath(SdfPortSpec *from_edge,
|
|||
// condelse matches the default (unconditional) arc.
|
||||
|| (condelse && lib_cond == NULL))) {
|
||||
matched = true;
|
||||
TimingArcSetArcIterator *arc_iter = arc_set->timingArcIterator();
|
||||
while (arc_iter->hasNext()) {
|
||||
TimingArc *arc = arc_iter->next();
|
||||
TimingArcSetArcIterator arc_iter(arc_set);
|
||||
while (arc_iter.hasNext()) {
|
||||
TimingArc *arc = arc_iter.next();
|
||||
if ((from_edge->transition() == Transition::riseFall())
|
||||
|| (arc->fromTrans() == from_edge->transition())) {
|
||||
size_t triple_index = arc->toTrans()->sdfTripleIndex();
|
||||
|
|
@ -425,7 +424,6 @@ SdfReader::iopath(SdfPortSpec *from_edge,
|
|||
}
|
||||
}
|
||||
}
|
||||
delete arc_iter;
|
||||
}
|
||||
}
|
||||
if (!matched)
|
||||
|
|
@ -551,9 +549,9 @@ SdfReader::annotateCheckEdges(Pin *data_pin,
|
|||
&& edge_role->genericRole() == sdf_role->genericRole()))
|
||||
&& cond_matches) {
|
||||
TimingArcSet *arc_set = edge->timingArcSet();
|
||||
TimingArcSetArcIterator *arc_iter = arc_set->timingArcIterator();
|
||||
while (arc_iter->hasNext()) {
|
||||
TimingArc *arc = arc_iter->next();
|
||||
TimingArcSetArcIterator arc_iter(arc_set);
|
||||
while (arc_iter.hasNext()) {
|
||||
TimingArc *arc = arc_iter.next();
|
||||
if (((data_edge->transition() == Transition::riseFall())
|
||||
|| (arc->toTrans() == data_edge->transition()))
|
||||
&& ((clk_edge->transition() == Transition::riseFall())
|
||||
|
|
@ -561,7 +559,6 @@ SdfReader::annotateCheckEdges(Pin *data_pin,
|
|||
setEdgeArcDelays(edge, arc, triple);
|
||||
}
|
||||
}
|
||||
delete arc_iter;
|
||||
matched = true;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -414,9 +414,9 @@ SdfWriter::writeArcDelays(Edge *edge)
|
|||
{
|
||||
RiseFallMinMax delays;
|
||||
TimingArcSet *arc_set = edge->timingArcSet();
|
||||
TimingArcSetArcIterator *arc_iter = arc_set->timingArcIterator();
|
||||
while (arc_iter->hasNext()) {
|
||||
TimingArc *arc = arc_iter->next();
|
||||
TimingArcSetArcIterator arc_iter(arc_set);
|
||||
while (arc_iter.hasNext()) {
|
||||
TimingArc *arc = arc_iter.next();
|
||||
TransRiseFall *tr = arc->toTrans()->asRiseFall();
|
||||
ArcDelay min_delay = graph_->arcDelay(edge, arc, arc_delay_min_index_);
|
||||
delays.setValue(tr, MinMax::min(), delayAsFloat(min_delay));
|
||||
|
|
@ -424,7 +424,6 @@ SdfWriter::writeArcDelays(Edge *edge)
|
|||
ArcDelay max_delay = graph_->arcDelay(edge, arc, arc_delay_max_index_);
|
||||
delays.setValue(tr, MinMax::max(), delayAsFloat(max_delay));
|
||||
}
|
||||
delete arc_iter;
|
||||
|
||||
if (delays.hasValue(TransRiseFall::rise(), MinMax::min())
|
||||
&& delays.hasValue(TransRiseFall::fall(), MinMax::min())) {
|
||||
|
|
@ -570,14 +569,13 @@ SdfWriter::writeCheck(Edge *edge,
|
|||
// Examine the arcs to see if the check requires clk or data edge specifiers.
|
||||
TimingArc *arcs[TransRiseFall::index_count][TransRiseFall::index_count] =
|
||||
{{NULL, NULL}, {NULL, NULL}};
|
||||
TimingArcSetArcIterator *arc_iter = arc_set->timingArcIterator();
|
||||
while (arc_iter->hasNext()) {
|
||||
TimingArc *arc = arc_iter->next();
|
||||
TimingArcSetArcIterator arc_iter(arc_set);
|
||||
while (arc_iter.hasNext()) {
|
||||
TimingArc *arc = arc_iter.next();
|
||||
TransRiseFall *clk_tr = arc->fromTrans()->asRiseFall();
|
||||
TransRiseFall *data_tr = arc->toTrans()->asRiseFall();;
|
||||
arcs[clk_tr->index()][data_tr->index()] = arc;
|
||||
}
|
||||
delete arc_iter;
|
||||
|
||||
if (arcs[TransRiseFall::fallIndex()][TransRiseFall::riseIndex()] == NULL
|
||||
&& arcs[TransRiseFall::fallIndex()][TransRiseFall::fallIndex()] == NULL)
|
||||
|
|
@ -587,12 +585,11 @@ SdfWriter::writeCheck(Edge *edge,
|
|||
writeEdgeCheck(edge, sdf_check, TransRiseFall::fallIndex(), arcs);
|
||||
else {
|
||||
// No special case; write all the checks with data and clock edge specifiers.
|
||||
arc_iter = arc_set->timingArcIterator();
|
||||
while (arc_iter->hasNext()) {
|
||||
TimingArc *arc = arc_iter->next();
|
||||
TimingArcSetArcIterator arc_iter(arc_set);
|
||||
while (arc_iter.hasNext()) {
|
||||
TimingArc *arc = arc_iter.next();
|
||||
writeCheck(edge, arc, sdf_check, true, true);
|
||||
}
|
||||
delete arc_iter;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -196,9 +196,9 @@ CheckMaxSkews:: visitMaxSkewChecks(Vertex *vertex,
|
|||
if (edge->role() == TimingRole::skew()) {
|
||||
Vertex *ref_vertex = edge->from(graph);
|
||||
TimingArcSet *arc_set = edge->timingArcSet();
|
||||
TimingArcSetArcIterator *arc_iter = arc_set->timingArcIterator();
|
||||
while (arc_iter->hasNext()) {
|
||||
TimingArc *arc = arc_iter->next();
|
||||
TimingArcSetArcIterator arc_iter(arc_set);
|
||||
while (arc_iter.hasNext()) {
|
||||
TimingArc *arc = arc_iter.next();
|
||||
TransRiseFall *clk_tr = arc->fromTrans()->asRiseFall();
|
||||
TransRiseFall *ref_tr = arc->toTrans()->asRiseFall();
|
||||
VertexPathIterator clk_path_iter(vertex, clk_tr, clk_min_max, search);
|
||||
|
|
@ -218,7 +218,6 @@ CheckMaxSkews:: visitMaxSkewChecks(Vertex *vertex,
|
|||
}
|
||||
}
|
||||
}
|
||||
delete arc_iter;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -109,6 +109,8 @@ CheckSlewLimits::checkSlews(const Pin *pin,
|
|||
{
|
||||
corner1 = NULL;
|
||||
tr = NULL;
|
||||
slew = 0.0;
|
||||
limit = 0.0;
|
||||
slack = MinMax::min()->initValue();
|
||||
if (corner)
|
||||
checkSlews1(pin, corner, min_max,
|
||||
|
|
|
|||
|
|
@ -420,17 +420,7 @@ Corner::findDcalcAnalysisPt(const MinMax *min_max) const
|
|||
PathAnalysisPt *
|
||||
Corner::findPathAnalysisPt(const MinMax *min_max) const
|
||||
{
|
||||
int ap_count = path_analysis_pts_.size();
|
||||
if (ap_count == 0)
|
||||
return NULL;
|
||||
else if (ap_count == 1)
|
||||
return path_analysis_pts_[0];
|
||||
else if (ap_count == 2)
|
||||
return path_analysis_pts_[min_max->index()];
|
||||
else {
|
||||
internalError("unknown analysis point count");
|
||||
return NULL;
|
||||
}
|
||||
return path_analysis_pts_[min_max->index()];
|
||||
}
|
||||
|
||||
void
|
||||
|
|
|
|||
|
|
@ -88,8 +88,9 @@ Crpr::maxCrpr(ClkInfo *clk_info)
|
|||
if (!crpr_clk_path.isNull()) {
|
||||
PathVertex crpr_clk_vpath(crpr_clk_path, this);
|
||||
Arrival other_arrival = otherMinMaxArrival(&crpr_clk_vpath);
|
||||
float crpr_diff = abs(delayAsFloat(crpr_clk_vpath.arrival(this)
|
||||
- other_arrival));
|
||||
float crpr_diff = abs(delayAsFloat(crpr_clk_vpath.arrival(this),
|
||||
EarlyLate::late())
|
||||
- delayAsFloat(other_arrival, EarlyLate::early()));
|
||||
return crpr_diff;
|
||||
}
|
||||
else
|
||||
|
|
@ -371,7 +372,8 @@ float
|
|||
Crpr::crprArrivalDiff(const PathVertex *path)
|
||||
{
|
||||
Arrival other_arrival = otherMinMaxArrival(path);
|
||||
float crpr_diff = abs(delayAsFloat(path->arrival(this)-other_arrival));
|
||||
float crpr_diff = abs(delayAsFloat(path->arrival(this), EarlyLate::late())
|
||||
- delayAsFloat(other_arrival, EarlyLate::early()));
|
||||
return crpr_diff;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -243,10 +243,10 @@ FindRegVisitor::findSequential(const Pin *clk_pin,
|
|||
{
|
||||
has_seqs = false;
|
||||
matches = false;
|
||||
CellSequentialIterator *seq_iter = cell->sequentialIterator();
|
||||
while (seq_iter->hasNext()) {
|
||||
LibertyCellSequentialIterator seq_iter(cell);
|
||||
while (seq_iter.hasNext()) {
|
||||
has_seqs = true;
|
||||
Sequential *seq = seq_iter->next();
|
||||
Sequential *seq = seq_iter.next();
|
||||
if ((seq->isRegister() && edge_triggered)
|
||||
|| (seq->isLatch() && latches)) {
|
||||
if (clk_tr == TransRiseFallBoth::riseFall()) {
|
||||
|
|
@ -270,7 +270,6 @@ FindRegVisitor::findSequential(const Pin *clk_pin,
|
|||
}
|
||||
}
|
||||
}
|
||||
delete seq_iter;
|
||||
}
|
||||
|
||||
bool
|
||||
|
|
@ -281,13 +280,12 @@ FindRegVisitor::findInferedSequential(LibertyCell *cell,
|
|||
bool latches)
|
||||
{
|
||||
bool matches = false;
|
||||
CellTimingArcSetIterator *set_iter = cell->timingArcSetIterator();
|
||||
const TransRiseFall *clk_tr1 = clk_tr->asRiseFall();
|
||||
while (set_iter->hasNext()) {
|
||||
TimingArcSet *set = set_iter->next();
|
||||
TimingArcSetArcIterator *arc_iter = set->timingArcIterator();
|
||||
TimingArc *arc = arc_iter->next();
|
||||
delete arc_iter;
|
||||
LibertyCellTimingArcSetIterator set_iter(cell);
|
||||
while (set_iter.hasNext()) {
|
||||
TimingArcSet *set = set_iter.next();
|
||||
TimingArcSetArcIterator arc_iter(set);
|
||||
TimingArc *arc = arc_iter.next();
|
||||
TransRiseFall *arc_clk_tr = arc->fromTrans()->asRiseFall();
|
||||
bool tr_matches = (clk_tr == TransRiseFallBoth::riseFall()
|
||||
|| (arc_clk_tr == clk_tr1
|
||||
|
|
@ -304,7 +302,6 @@ FindRegVisitor::findInferedSequential(LibertyCell *cell,
|
|||
break;
|
||||
}
|
||||
}
|
||||
delete set_iter;
|
||||
return matches;
|
||||
}
|
||||
|
||||
|
|
@ -313,18 +310,14 @@ FindRegVisitor::hasTimingCheck(LibertyCell *cell,
|
|||
LibertyPort *clk,
|
||||
LibertyPort *d)
|
||||
{
|
||||
bool has_check = false;
|
||||
CellTimingArcSetIterator *set_iter = cell->timingArcSetIterator(clk, d);
|
||||
while (set_iter->hasNext()) {
|
||||
TimingArcSet *set = set_iter->next();
|
||||
LibertyCellTimingArcSetIterator set_iter(cell, clk, d);
|
||||
while (set_iter.hasNext()) {
|
||||
TimingArcSet *set = set_iter.next();
|
||||
TimingRole *role = set->role();
|
||||
if (role->isTimingCheck()) {
|
||||
has_check = true;
|
||||
break;
|
||||
}
|
||||
if (role->isTimingCheck())
|
||||
return true;
|
||||
}
|
||||
delete set_iter;
|
||||
return has_check;
|
||||
return false;
|
||||
}
|
||||
|
||||
class FindRegInstances : public FindRegVisitor
|
||||
|
|
@ -560,18 +553,14 @@ FindRegClkPins::matchPin(Pin *pin)
|
|||
{
|
||||
LibertyPort *port = network_->libertyPort(pin);
|
||||
LibertyCell *cell = port->libertyCell();
|
||||
CellTimingArcSetIterator *set_iter = cell->timingArcSetFromIterator(port);
|
||||
bool match = false;
|
||||
while (set_iter->hasNext()) {
|
||||
TimingArcSet *set = set_iter->next();
|
||||
LibertyCellTimingArcSetIterator set_iter(cell, port, NULL);
|
||||
while (set_iter.hasNext()) {
|
||||
TimingArcSet *set = set_iter.next();
|
||||
TimingRole *role = set->role();
|
||||
if (role->isTimingCheck()) {
|
||||
match = true;
|
||||
break;
|
||||
}
|
||||
if (role->isTimingCheck())
|
||||
return true;
|
||||
}
|
||||
delete set_iter;
|
||||
return match;
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -622,18 +611,14 @@ FindRegAsyncPins::matchPin(Pin *pin)
|
|||
{
|
||||
LibertyPort *port = network_->libertyPort(pin);
|
||||
LibertyCell *cell = port->libertyCell();
|
||||
CellTimingArcSetIterator *set_iter = cell->timingArcSetFromIterator(port);
|
||||
bool match = false;
|
||||
while (set_iter->hasNext()) {
|
||||
TimingArcSet *set = set_iter->next();
|
||||
LibertyCellTimingArcSetIterator set_iter(cell, port, NULL);
|
||||
while (set_iter.hasNext()) {
|
||||
TimingArcSet *set = set_iter.next();
|
||||
TimingRole *role = set->role();
|
||||
if (role == TimingRole::regSetClr()) {
|
||||
match = true;
|
||||
break;
|
||||
}
|
||||
if (role == TimingRole::regSetClr())
|
||||
return true;
|
||||
}
|
||||
delete set_iter;
|
||||
return match;
|
||||
return false;
|
||||
}
|
||||
|
||||
PinSet *
|
||||
|
|
@ -676,20 +661,16 @@ FindRegOutputPins::matchPin(Pin *pin)
|
|||
{
|
||||
LibertyPort *port = network_->libertyPort(pin);
|
||||
LibertyCell *cell = port->libertyCell();
|
||||
CellTimingArcSetIterator *set_iter = cell->timingArcSetToIterator(port);
|
||||
bool match = false;
|
||||
while (set_iter->hasNext()) {
|
||||
TimingArcSet *set = set_iter->next();
|
||||
LibertyCellTimingArcSetIterator set_iter(cell, NULL, port);
|
||||
while (set_iter.hasNext()) {
|
||||
TimingArcSet *set = set_iter.next();
|
||||
TimingRole *role = set->role();
|
||||
if (role == TimingRole::regClkToQ()
|
||||
|| role == TimingRole::latchEnToQ()
|
||||
|| role == TimingRole::latchDtoQ()) {
|
||||
match = true;
|
||||
break;
|
||||
}
|
||||
|| role == TimingRole::latchDtoQ())
|
||||
return true;
|
||||
}
|
||||
delete set_iter;
|
||||
return match;
|
||||
return false;
|
||||
}
|
||||
|
||||
void
|
||||
|
|
|
|||
|
|
@ -75,7 +75,7 @@ PathEnd::pathEarlyLate(const StaState *sta) const
|
|||
}
|
||||
|
||||
const EarlyLate *
|
||||
PathEnd::clkEarlyLate(const StaState *sta) const
|
||||
PathEnd::clkEarlyLate(const StaState *) const
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -103,7 +103,6 @@ PathEnum::PathEnum(int group_count,
|
|||
int endpoint_count,
|
||||
bool unique_pins,
|
||||
bool cmp_slack,
|
||||
const MinMax *min_max,
|
||||
const StaState *sta) :
|
||||
StaState(sta),
|
||||
cmp_slack_(cmp_slack),
|
||||
|
|
|
|||
|
|
@ -57,7 +57,6 @@ public:
|
|||
int endpoint_count,
|
||||
bool unique_pins,
|
||||
bool cmp_slack,
|
||||
const MinMax *min_max,
|
||||
const StaState *sta);
|
||||
// Insert path ends that are enumerated in slack/arrival order.
|
||||
void insert(PathEnd *path_end);
|
||||
|
|
|
|||
|
|
@ -757,7 +757,7 @@ PathGroups::makeGroupPathEnds(ExceptionTo *to,
|
|||
group_path_iter->next(name, groups);
|
||||
PathGroup *group = findPathGroup(name, path_min_max);
|
||||
if (group)
|
||||
enumPathEnds(group, group_count, endpoint_count, unique_pins, true, path_min_max);
|
||||
enumPathEnds(group, group_count, endpoint_count, unique_pins, true);
|
||||
}
|
||||
delete group_path_iter;
|
||||
|
||||
|
|
@ -766,22 +766,22 @@ PathGroups::makeGroupPathEnds(ExceptionTo *to,
|
|||
Clock *clk = clk_iter->next();
|
||||
PathGroup *group = findPathGroup(clk, path_min_max);
|
||||
if (group)
|
||||
enumPathEnds(group, group_count, endpoint_count, unique_pins, true, path_min_max);
|
||||
enumPathEnds(group, group_count, endpoint_count, unique_pins, true);
|
||||
}
|
||||
delete clk_iter;
|
||||
|
||||
PathGroup *group = unconstrained_[mm_index];
|
||||
if (group)
|
||||
enumPathEnds(group, group_count, endpoint_count, unique_pins, false, path_min_max);
|
||||
enumPathEnds(group, group_count, endpoint_count, unique_pins, false);
|
||||
group = path_delay_[mm_index];
|
||||
if (group)
|
||||
enumPathEnds(group, group_count, endpoint_count, unique_pins, true, path_min_max);
|
||||
enumPathEnds(group, group_count, endpoint_count, unique_pins, true);
|
||||
group = gated_clk_[mm_index];
|
||||
if (group)
|
||||
enumPathEnds(group, group_count, endpoint_count, unique_pins, true, path_min_max);
|
||||
enumPathEnds(group, group_count, endpoint_count, unique_pins, true);
|
||||
group = async_[mm_index];
|
||||
if (group)
|
||||
enumPathEnds(group, group_count, endpoint_count, unique_pins, true, path_min_max);
|
||||
enumPathEnds(group, group_count, endpoint_count, unique_pins, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -791,12 +791,11 @@ PathGroups::enumPathEnds(PathGroup *group,
|
|||
int group_count,
|
||||
int endpoint_count,
|
||||
bool unique_pins,
|
||||
bool cmp_slack,
|
||||
const MinMax *min_max)
|
||||
bool cmp_slack)
|
||||
{
|
||||
// Insert the worst max_path path ends in the group into a path
|
||||
// enumerator.
|
||||
PathEnum path_enum(group_count, endpoint_count, unique_pins, cmp_slack, min_max, this);
|
||||
PathEnum path_enum(group_count, endpoint_count, unique_pins, cmp_slack, this);
|
||||
PathGroupIterator *end_iter = group->iterator();
|
||||
while (end_iter->hasNext()) {
|
||||
PathEnd *end = end_iter->next();
|
||||
|
|
|
|||
|
|
@ -149,8 +149,7 @@ protected:
|
|||
int group_count,
|
||||
int endpoint_count,
|
||||
bool unique_pins,
|
||||
bool cmp_slack,
|
||||
const MinMax *min_max);
|
||||
bool cmp_slack);
|
||||
|
||||
void pushGroupPathEnds(PathEndSeq *path_ends);
|
||||
void pushUnconstrainedPathEnds(PathEndSeq *path_ends,
|
||||
|
|
|
|||
|
|
@ -23,7 +23,6 @@
|
|||
#include "Liberty.hh"
|
||||
#include "InternalPower.hh"
|
||||
#include "LeakagePower.hh"
|
||||
#include "InternalPower.hh"
|
||||
#include "TimingArc.hh"
|
||||
#include "FuncExpr.hh"
|
||||
#include "PortDirection.hh"
|
||||
|
|
@ -103,6 +102,7 @@ Power::power(const Corner *corner,
|
|||
total.incr(inst_power);
|
||||
}
|
||||
}
|
||||
delete inst_iter;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////
|
||||
|
|
@ -138,10 +138,10 @@ Power::power(const Instance *inst,
|
|||
bool is_clk;
|
||||
activity(to_pin, activity1, is_clk);
|
||||
if (to_port->direction()->isAnyOutput()) {
|
||||
findSwitchingPower(inst, cell, to_pin, to_port, activity1, load_cap,
|
||||
findSwitchingPower(cell, to_port, activity1, load_cap,
|
||||
dcalc_ap, result);
|
||||
}
|
||||
findInternalPower(inst, cell, to_pin, to_port, activity1, is_clk,
|
||||
findInternalPower(inst, cell, to_port, activity1, is_clk,
|
||||
load_cap, dcalc_ap, result);
|
||||
}
|
||||
delete pin_iter;
|
||||
|
|
@ -151,7 +151,6 @@ Power::power(const Instance *inst,
|
|||
void
|
||||
Power::findInternalPower(const Instance *inst,
|
||||
LibertyCell *cell,
|
||||
const Pin *to_pin,
|
||||
const LibertyPort *to_port,
|
||||
float activity,
|
||||
bool is_clk,
|
||||
|
|
@ -173,9 +172,9 @@ Power::findInternalPower(const Instance *inst,
|
|||
units_->capacitanceUnit()->asString(load_cap),
|
||||
activity * 1e-9,
|
||||
duty);
|
||||
LibertyCellInternalPowerIterator *pwr_iter = cell->internalPowerIterator();
|
||||
while (pwr_iter->hasNext()) {
|
||||
InternalPower *pwr = pwr_iter->next();
|
||||
LibertyCellInternalPowerIterator pwr_iter(cell);
|
||||
while (pwr_iter.hasNext()) {
|
||||
InternalPower *pwr = pwr_iter.next();
|
||||
const char *related_pg_pin = pwr->relatedPgPin();
|
||||
if (pwr->port() == to_port
|
||||
&& ((related_pg_pin == NULL || pwr_pin == NULL)
|
||||
|
|
@ -189,7 +188,7 @@ Power::findInternalPower(const Instance *inst,
|
|||
while (tr_iter.hasNext()) {
|
||||
TransRiseFall *to_tr = tr_iter.next();
|
||||
// Need unateness to find from_tr.
|
||||
float slew = sta_->vertexSlew(from_vertex, to_tr, dcalc_ap);
|
||||
float slew = delayAsFloat(sta_->vertexSlew(from_vertex, to_tr, dcalc_ap));
|
||||
float energy, tr_internal;
|
||||
if (from_port) {
|
||||
float energy1 = pwr->power(to_tr, pvt, slew, load_cap);
|
||||
|
|
@ -216,7 +215,6 @@ Power::findInternalPower(const Instance *inst,
|
|||
}
|
||||
}
|
||||
}
|
||||
delete pwr_iter;
|
||||
debugPrint1(debug_, "power", 2, " internal = %.5g\n", port_internal);
|
||||
result.setInternal(result.internal() + port_internal);
|
||||
}
|
||||
|
|
@ -232,13 +230,12 @@ Power::loadCap(const Pin *to_pin,
|
|||
while (edge_iter.hasNext()) {
|
||||
Edge *edge = edge_iter.next();
|
||||
TimingArcSet *arc_set = edge->timingArcSet();
|
||||
TimingArcSetArcIterator *arc_iter = arc_set->timingArcIterator();
|
||||
while (arc_iter->hasNext()) {
|
||||
TimingArc *arc = arc_iter->next();
|
||||
TimingArcSetArcIterator arc_iter(arc_set);
|
||||
while (arc_iter.hasNext()) {
|
||||
TimingArc *arc = arc_iter.next();
|
||||
ceff_sum += graph_delay_calc_->ceff(edge, arc, dcalc_ap);
|
||||
ceff_count++;
|
||||
}
|
||||
delete arc_iter;
|
||||
}
|
||||
return ceff_sum / ceff_count;
|
||||
}
|
||||
|
|
@ -250,9 +247,9 @@ Power::findLeakagePower(const Instance *inst,
|
|||
PowerResult &result)
|
||||
{
|
||||
float leakage = cell->leakagePower();
|
||||
LibertyCellLeakagePowerIterator *pwr_iter = cell->leakagePowerIterator();
|
||||
while (pwr_iter->hasNext()) {
|
||||
LeakagePower *leak = pwr_iter->next();
|
||||
LibertyCellLeakagePowerIterator pwr_iter(cell);
|
||||
while (pwr_iter.hasNext()) {
|
||||
LeakagePower *leak = pwr_iter.next();
|
||||
FuncExpr *when = leak->when();
|
||||
if (when) {
|
||||
LogicValue when_value = sim_->evalExpr(when, inst);
|
||||
|
|
@ -267,14 +264,11 @@ Power::findLeakagePower(const Instance *inst,
|
|||
}
|
||||
}
|
||||
}
|
||||
delete pwr_iter;
|
||||
result.setLeakage(leakage);
|
||||
}
|
||||
|
||||
void
|
||||
Power::findSwitchingPower(const Instance *inst,
|
||||
LibertyCell *cell,
|
||||
const Pin *to_pin,
|
||||
Power::findSwitchingPower(LibertyCell *cell,
|
||||
const LibertyPort *to_port,
|
||||
float activity,
|
||||
float load_cap,
|
||||
|
|
@ -307,7 +301,7 @@ Power::activity(const Pin *pin,
|
|||
|
||||
float
|
||||
Power::voltage(LibertyCell *cell,
|
||||
const LibertyPort *port,
|
||||
const LibertyPort *,
|
||||
const DcalcAnalysisPt *dcalc_ap)
|
||||
{
|
||||
// Should use cell pg_pin voltage name to voltage.
|
||||
|
|
|
|||
|
|
@ -51,7 +51,6 @@ protected:
|
|||
PowerResult &result);
|
||||
void findInternalPower(const Instance *inst,
|
||||
LibertyCell *cell,
|
||||
const Pin *to_pin,
|
||||
const LibertyPort *to_port,
|
||||
float activity,
|
||||
bool is_clk,
|
||||
|
|
@ -63,9 +62,7 @@ protected:
|
|||
LibertyCell *cell,
|
||||
// Return values.
|
||||
PowerResult &result);
|
||||
void findSwitchingPower(const Instance *inst,
|
||||
LibertyCell *cell,
|
||||
const Pin *to_pin,
|
||||
void findSwitchingPower(LibertyCell *cell,
|
||||
const LibertyPort *to_port,
|
||||
float activity,
|
||||
float load_cap,
|
||||
|
|
|
|||
|
|
@ -2713,8 +2713,8 @@ ReportPath::reportPath5(const Path *path,
|
|||
// from the input to the loads. Report the wire delay on the
|
||||
// input pin instead.
|
||||
Arrival next_time = next_path->arrival(this) + time_offset;
|
||||
incr = delayMeanSigma(next_time, min_max)
|
||||
- delayMeanSigma(time, min_max);
|
||||
incr = delayAsFloat(next_time, min_max)
|
||||
- delayAsFloat(time, min_max);
|
||||
time = next_time;
|
||||
line_case = "input_drive";
|
||||
}
|
||||
|
|
@ -2761,13 +2761,13 @@ ReportPath::reportPath5(const Path *path,
|
|||
line_case = "clk_ideal";
|
||||
}
|
||||
else if (is_clk && !is_clk_start) {
|
||||
incr = delayMeanSigma(time, min_max)
|
||||
- delayMeanSigma(prev_time, min_max);
|
||||
incr = delayAsFloat(time, min_max)
|
||||
- delayAsFloat(prev_time, min_max);
|
||||
line_case = "clk_prop";
|
||||
}
|
||||
else {
|
||||
incr = delayMeanSigma(time, min_max)
|
||||
- delayMeanSigma(prev_time, min_max);
|
||||
incr = delayAsFloat(time, min_max)
|
||||
- delayAsFloat(prev_time, min_max);
|
||||
line_case = "normal";
|
||||
}
|
||||
if (report_input_pin_
|
||||
|
|
@ -3264,7 +3264,7 @@ ReportPath::reportTotalDelay(Delay value,
|
|||
const EarlyLate *early_late,
|
||||
string &result)
|
||||
{
|
||||
const char *str = delayMeanSigmaString(value, early_late, units_, digits_);
|
||||
const char *str = delayAsString(value, early_late, units_, digits_);
|
||||
if (stringEq(str, minus_zero_))
|
||||
// Filter "-0.00" fields.
|
||||
str = plus_zero_;
|
||||
|
|
@ -3281,7 +3281,7 @@ ReportPath::reportFieldDelayMinus(Delay value,
|
|||
if (delayAsFloat(value) == field_blank_)
|
||||
reportFieldBlank(field, result);
|
||||
else {
|
||||
float mean_sigma = delayMeanSigma(value, early_late);
|
||||
float mean_sigma = delayAsFloat(value, early_late);
|
||||
const char *str = units_->timeUnit()->asString(-mean_sigma, digits_);
|
||||
if (stringEq(str, plus_zero_))
|
||||
// Force leading minus sign.
|
||||
|
|
@ -3299,7 +3299,7 @@ ReportPath::reportFieldDelay(Delay value,
|
|||
if (delayAsFloat(value) == field_blank_)
|
||||
reportFieldBlank(field, result);
|
||||
else {
|
||||
const char *str = delayMeanSigmaString(value, early_late, units_, digits_);
|
||||
const char *str = delayAsString(value, early_late, units_, digits_);
|
||||
if (stringEq(str, minus_zero_))
|
||||
// Filter "-0.00" fields.
|
||||
str = plus_zero_;
|
||||
|
|
|
|||
165
search/Search.cc
165
search/Search.cc
|
|
@ -3052,7 +3052,7 @@ Search::deratedDelay(Vertex *from_vertex,
|
|||
DcalcAPIndex ap_index = dcalc_ap->index();
|
||||
float derate = timingDerate(from_vertex, arc, edge, is_clk, path_ap);
|
||||
ArcDelay delay = graph_->arcDelay(edge, arc, ap_index);
|
||||
return delay + Delay((derate - 1.0) * delayAsFloat(delay));
|
||||
return delay * derate;
|
||||
}
|
||||
|
||||
float
|
||||
|
|
@ -3706,13 +3706,40 @@ Search::exceptionTo(ExceptionPathType type,
|
|||
|
||||
Slack
|
||||
Search::totalNegativeSlack(const MinMax *min_max)
|
||||
{
|
||||
tnsPreamble();
|
||||
Slack tns = 0.0;
|
||||
CornerIterator corner_iter(this);
|
||||
while (corner_iter.hasNext()) {
|
||||
Corner *corner = corner_iter.next();
|
||||
PathAPIndex path_ap_index = corner->findPathAnalysisPt(min_max)->index();
|
||||
Slack tns1 = tns_[path_ap_index];
|
||||
if (tns1 < tns)
|
||||
tns = tns1;
|
||||
}
|
||||
return tns;
|
||||
}
|
||||
|
||||
Slack
|
||||
Search::totalNegativeSlack(const Corner *corner,
|
||||
const MinMax *min_max)
|
||||
{
|
||||
tnsPreamble();
|
||||
PathAPIndex path_ap_index = corner->findPathAnalysisPt(min_max)->index();
|
||||
return tns_[path_ap_index];
|
||||
}
|
||||
|
||||
void
|
||||
Search::tnsPreamble()
|
||||
{
|
||||
wnsTnsPreamble();
|
||||
PathAPIndex path_ap_count = corners_->pathAnalysisPtCount();
|
||||
tns_.resize(path_ap_count);
|
||||
tns_slacks_.resize(path_ap_count);
|
||||
if (tns_exists_)
|
||||
updateInvalidTns();
|
||||
else
|
||||
findTotalNegativeSlacks();
|
||||
return static_cast<Slack>(tns_[min_max->index()]);
|
||||
}
|
||||
|
||||
void
|
||||
|
|
@ -3731,6 +3758,7 @@ Search::tnsInvalid(Vertex *vertex)
|
|||
void
|
||||
Search::updateInvalidTns()
|
||||
{
|
||||
PathAPIndex path_ap_count = corners_->pathAnalysisPtCount();
|
||||
VertexSet::Iterator vertex_iter(invalid_tns_);
|
||||
while (vertex_iter.hasNext()) {
|
||||
Vertex *vertex = vertex_iter.next();
|
||||
|
|
@ -3738,7 +3766,7 @@ Search::updateInvalidTns()
|
|||
if (isEndpoint(vertex)) {
|
||||
debugPrint1(debug_, "tns", 2, "update tns %s\n",
|
||||
vertex->name(sdc_network_));
|
||||
Slack slacks[MinMax::index_count];
|
||||
SlackSeq slacks(path_ap_count);
|
||||
wnsSlacks(vertex, slacks);
|
||||
|
||||
if (tns_exists_)
|
||||
|
|
@ -3753,67 +3781,64 @@ Search::updateInvalidTns()
|
|||
void
|
||||
Search::findTotalNegativeSlacks()
|
||||
{
|
||||
int min_index = MinMax::minIndex();
|
||||
int max_index = MinMax::maxIndex();
|
||||
tns_[min_index] = 0.0;
|
||||
tns_[max_index] = 0.0;
|
||||
tns_slacks_[min_index].clear();
|
||||
tns_slacks_[max_index].clear();
|
||||
PathAPIndex path_ap_count = corners_->pathAnalysisPtCount();
|
||||
for (PathAPIndex i = 0; i < path_ap_count; i++) {
|
||||
tns_[i] = 0.0;
|
||||
tns_slacks_[i].clear();
|
||||
}
|
||||
VertexSet::Iterator end_iter(endpoints());
|
||||
while (end_iter.hasNext()) {
|
||||
Vertex *vertex = end_iter.next();
|
||||
// No locking required.
|
||||
Slack slacks[MinMax::index_count];
|
||||
SlackSeq slacks(path_ap_count);
|
||||
wnsSlacks(vertex, slacks);
|
||||
tnsIncr(vertex, delayAsFloat(slacks[min_index]), min_index);
|
||||
tnsIncr(vertex, delayAsFloat(slacks[max_index]), max_index);
|
||||
for (PathAPIndex i = 0; i < path_ap_count; i++)
|
||||
tnsIncr(vertex, slacks[i], i);
|
||||
}
|
||||
tns_exists_ = true;
|
||||
}
|
||||
|
||||
void
|
||||
Search::updateTns(Vertex *vertex,
|
||||
Slack *slacks)
|
||||
SlackSeq &slacks)
|
||||
{
|
||||
int min_index = MinMax::minIndex();
|
||||
int max_index = MinMax::maxIndex();
|
||||
tnsDecr(vertex, min_index);
|
||||
tnsIncr(vertex, delayAsFloat(slacks[min_index]), min_index);
|
||||
|
||||
tnsDecr(vertex, max_index);
|
||||
tnsIncr(vertex, delayAsFloat(slacks[max_index]), max_index);
|
||||
PathAPIndex path_ap_count = corners_->pathAnalysisPtCount();
|
||||
for (PathAPIndex i = 0; i < path_ap_count; i++) {
|
||||
tnsDecr(vertex, i);
|
||||
tnsIncr(vertex, slacks[i], i);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
Search::tnsIncr(Vertex *vertex,
|
||||
float slack,
|
||||
int min_max_index)
|
||||
Slack slack,
|
||||
PathAPIndex path_ap_index)
|
||||
{
|
||||
if (fuzzyLess(slack, 0.0)) {
|
||||
if (delayFuzzyLess(slack, 0.0)) {
|
||||
debugPrint2(debug_, "tns", 3, "tns+ %s %s\n",
|
||||
delayAsString(slack, units_),
|
||||
vertex->name(sdc_network_));
|
||||
tns_[min_max_index] += slack;
|
||||
if (tns_slacks_[min_max_index].hasKey(vertex))
|
||||
tns_[path_ap_index] += slack;
|
||||
if (tns_slacks_[path_ap_index].hasKey(vertex))
|
||||
internalError("tns incr existing vertex");
|
||||
tns_slacks_[min_max_index][vertex] = slack;
|
||||
tns_slacks_[path_ap_index][vertex] = slack;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
Search::tnsDecr(Vertex *vertex,
|
||||
int min_max_index)
|
||||
PathAPIndex path_ap_index)
|
||||
{
|
||||
Slack slack;
|
||||
bool found;
|
||||
tns_slacks_[min_max_index].findKey(vertex, slack, found);
|
||||
tns_slacks_[path_ap_index].findKey(vertex, slack, found);
|
||||
if (found
|
||||
&& delayFuzzyLess(slack, 0.0)) {
|
||||
debugPrint2(debug_, "tns", 3, "tns- %s %s\n",
|
||||
delayAsString(slack, units_),
|
||||
vertex->name(sdc_network_));
|
||||
tns_[min_max_index] -= delayAsFloat(slack);
|
||||
tns_slacks_[min_max_index].eraseKey(vertex);
|
||||
tns_[path_ap_index] -= delayAsFloat(slack);
|
||||
tns_slacks_[path_ap_index].eraseKey(vertex);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -3823,27 +3848,44 @@ Search::tnsNotifyBefore(Vertex *vertex)
|
|||
{
|
||||
if (tns_exists_
|
||||
&& isEndpoint(vertex)) {
|
||||
int min_index = MinMax::minIndex();
|
||||
int max_index = MinMax::maxIndex();
|
||||
tnsDecr(vertex, min_index);
|
||||
tnsDecr(vertex, max_index);
|
||||
int ap_count = corners_->pathAnalysisPtCount();
|
||||
for (int i = 0; i < ap_count; i++) {
|
||||
tnsDecr(vertex, i);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////
|
||||
|
||||
Slack
|
||||
Search::worstSlack(const MinMax *min_max)
|
||||
void
|
||||
Search::worstSlack(const MinMax *min_max,
|
||||
// Return values.
|
||||
Slack &worst_slack,
|
||||
Vertex *&worst_vertex)
|
||||
{
|
||||
worstSlackPreamble();
|
||||
return worst_slacks_->worstSlack(min_max);
|
||||
worst_slacks_->worstSlack(min_max, worst_slack, worst_vertex);
|
||||
}
|
||||
|
||||
Vertex *
|
||||
Search::worstSlackVertex(const MinMax *min_max)
|
||||
void
|
||||
Search::worstSlack(const Corner *corner,
|
||||
const MinMax *min_max,
|
||||
// Return values.
|
||||
Slack &worst_slack,
|
||||
Vertex *&worst_vertex)
|
||||
{
|
||||
worstSlackPreamble();
|
||||
return worst_slacks_->worstSlackVertex(min_max);
|
||||
worst_slacks_->worstSlack(corner, min_max, worst_slack, worst_vertex);
|
||||
}
|
||||
|
||||
void
|
||||
Search::worstSlackPreamble()
|
||||
{
|
||||
wnsTnsPreamble();
|
||||
if (worst_slacks_)
|
||||
updateInvalidTns();
|
||||
else
|
||||
worst_slacks_ = new WorstSlacks(this);
|
||||
}
|
||||
|
||||
void
|
||||
|
|
@ -3873,16 +3915,6 @@ Search::wnsTnsPreamble()
|
|||
seedRequireds();
|
||||
}
|
||||
|
||||
void
|
||||
Search::worstSlackPreamble()
|
||||
{
|
||||
wnsTnsPreamble();
|
||||
if (worst_slacks_)
|
||||
updateInvalidTns();
|
||||
else
|
||||
worst_slacks_ = new WorstSlacks(this);
|
||||
}
|
||||
|
||||
void
|
||||
Search::clearWorstSlack()
|
||||
{
|
||||
|
|
@ -3898,17 +3930,17 @@ Search::clearWorstSlack()
|
|||
class FindEndSlackVisitor : public PathEndVisitor
|
||||
{
|
||||
public:
|
||||
FindEndSlackVisitor(Slack *slacks,
|
||||
FindEndSlackVisitor(SlackSeq &slacks,
|
||||
const StaState *sta);
|
||||
virtual PathEndVisitor *copy();
|
||||
virtual void visit(PathEnd *path_end);
|
||||
|
||||
protected:
|
||||
Slack *slacks_;
|
||||
SlackSeq &slacks_;
|
||||
const StaState *sta_;
|
||||
};
|
||||
|
||||
FindEndSlackVisitor::FindEndSlackVisitor(Slack *slacks,
|
||||
FindEndSlackVisitor::FindEndSlackVisitor(SlackSeq &slacks,
|
||||
const StaState *sta) :
|
||||
slacks_(slacks),
|
||||
sta_(sta)
|
||||
|
|
@ -3927,21 +3959,22 @@ FindEndSlackVisitor::visit(PathEnd *path_end)
|
|||
{
|
||||
if (!path_end->isUnconstrained()) {
|
||||
PathRef &path = path_end->pathRef();
|
||||
int mm_index = path.minMax(sta_)->index();
|
||||
PathAPIndex path_ap_index = path.pathAnalysisPtIndex(sta_);
|
||||
Slack slack = path_end->slack(sta_);
|
||||
if (delayFuzzyLess(slack, slacks_[mm_index]))
|
||||
slacks_[mm_index] = slack;
|
||||
if (delayFuzzyLess(slack, slacks_[path_ap_index]))
|
||||
slacks_[path_ap_index] = slack;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
Search::wnsSlacks(Vertex *vertex,
|
||||
// Return values.
|
||||
Slack *slacks)
|
||||
SlackSeq &slacks)
|
||||
{
|
||||
Slack slack_init = MinMax::min()->initValue();
|
||||
slacks[MinMax::minIndex()] = slack_init;
|
||||
slacks[MinMax::maxIndex()] = slack_init;
|
||||
PathAPIndex path_ap_count = corners_->pathAnalysisPtCount();
|
||||
for (PathAPIndex i = 0; i < path_ap_count; i++)
|
||||
slacks[i] = slack_init;
|
||||
if (hasFanout(vertex, search_adj_, graph_)) {
|
||||
// If the vertex has fanout the path slacks include downstream
|
||||
// PathEnd slacks so find the endpoint slack directly.
|
||||
|
|
@ -3952,23 +3985,23 @@ Search::wnsSlacks(Vertex *vertex,
|
|||
VertexPathIterator path_iter(vertex, this);
|
||||
while (path_iter.hasNext()) {
|
||||
Path *path = path_iter.next();
|
||||
const MinMax *path_min_max = path->minMax(this);
|
||||
int path_mm_index = path_min_max->index();
|
||||
PathAPIndex path_ap_index = path->pathAnalysisPtIndex(this);
|
||||
const Slack path_slack = path->slack(this);
|
||||
if (!path->tag(this)->isFilter()
|
||||
&& delayFuzzyLess(path_slack, slacks[path_mm_index]))
|
||||
slacks[path_mm_index] = path_slack;
|
||||
&& delayFuzzyLess(path_slack, slacks[path_ap_index]))
|
||||
slacks[path_ap_index] = path_slack;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Slack
|
||||
Search::wnsSlack(Vertex *vertex,
|
||||
const MinMax *min_max)
|
||||
PathAPIndex path_ap_index)
|
||||
{
|
||||
Slack slacks[MinMax::index_count];
|
||||
PathAPIndex path_ap_count = corners_->pathAnalysisPtCount();
|
||||
SlackSeq slacks(path_ap_count);
|
||||
wnsSlacks(vertex, slacks);
|
||||
return slacks[min_max->index()];
|
||||
return slacks[path_ap_index];
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////
|
||||
|
|
|
|||
|
|
@ -59,6 +59,8 @@ typedef Set<ClkInfo*, ClkInfoLess> ClkInfoSet;
|
|||
typedef HashSet<Tag*, TagHash, TagEqual> TagHashSet;
|
||||
typedef HashSet<TagGroup*, TagGroupHash, TagGroupEqual> TagGroupSet;
|
||||
typedef Map<Vertex*, Slack> VertexSlackMap;
|
||||
typedef Vector<VertexSlackMap> VertexSlackMapSeq;
|
||||
typedef Vector<WorstSlacks> WorstSlacksSeq;
|
||||
|
||||
class Search : public StaState
|
||||
{
|
||||
|
|
@ -124,11 +126,22 @@ public:
|
|||
void findRequireds(Level level);
|
||||
bool requiredsSeeded() const { return requireds_seeded_; }
|
||||
bool requiredsExist() const { return requireds_exist_; }
|
||||
// The sum of all negative endpoints slacks.
|
||||
// Incrementally updated.
|
||||
Slack totalNegativeSlack(const MinMax *min_max);
|
||||
// Worst endpoint slack.
|
||||
Slack worstSlack(const MinMax *min_max);
|
||||
// Worst endpoint slack vertex.
|
||||
Vertex *worstSlackVertex(const MinMax *min_max);
|
||||
Slack totalNegativeSlack(const Corner *corner,
|
||||
const MinMax *min_max);
|
||||
// Worst endpoint slack and vertex.
|
||||
// Incrementally updated.
|
||||
void worstSlack(const MinMax *min_max,
|
||||
// Return values.
|
||||
Slack &worst_slack,
|
||||
Vertex *&worst_vertex);
|
||||
void worstSlack(const Corner *corner,
|
||||
const MinMax *min_max,
|
||||
// Return values.
|
||||
Slack &worst_slack,
|
||||
Vertex *&worst_vertex);
|
||||
// Clock arrival respecting ideal clock insertion delay and latency.
|
||||
Arrival clkPathArrival(const Path *clk_path) const;
|
||||
Arrival clkPathArrival(const Path *clk_path,
|
||||
|
|
@ -313,7 +326,7 @@ public:
|
|||
TagGroup *tagGroup(TagGroupIndex index) const;
|
||||
void reportArrivals(Vertex *vertex) const;
|
||||
Slack wnsSlack(Vertex *vertex,
|
||||
const MinMax *min_max);
|
||||
PathAPIndex path_ap_index);
|
||||
void levelChangedBefore(Vertex *vertex);
|
||||
void seedInputArrival(const Pin *pin,
|
||||
Vertex *vertex,
|
||||
|
|
@ -471,24 +484,25 @@ protected:
|
|||
void deleteFilterTagGroups();
|
||||
void deleteFilterClkInfos();
|
||||
|
||||
void tnsPreamble();
|
||||
void findTotalNegativeSlacks();
|
||||
void updateInvalidTns();
|
||||
void clearWorstSlack();
|
||||
void wnsSlacks(Vertex *vertex,
|
||||
// Return values.
|
||||
Slack *slacks);
|
||||
SlackSeq &slacks);
|
||||
void wnsTnsPreamble();
|
||||
void worstSlackPreamble();
|
||||
void deleteWorstSlacks();
|
||||
void updateWorstSlacks(Vertex *vertex,
|
||||
Slack *slacks);
|
||||
Slack slacks);
|
||||
void updateTns(Vertex *vertex,
|
||||
Slack *slacks);
|
||||
SlackSeq &slacks);
|
||||
void tnsIncr(Vertex *vertex,
|
||||
float slack,
|
||||
int min_max_index);
|
||||
Slack slack,
|
||||
PathAPIndex path_ap_index);
|
||||
void tnsDecr(Vertex *vertex,
|
||||
int min_max_index);
|
||||
PathAPIndex path_ap_index);
|
||||
void tnsNotifyBefore(Vertex *vertex);
|
||||
PathGroups *makePathGroups(int group_count,
|
||||
int endpoint_count,
|
||||
|
|
@ -539,9 +553,12 @@ protected:
|
|||
bool tns_exists_;
|
||||
// Endpoint vertices with slacks that have changed since tns was found.
|
||||
VertexSet invalid_tns_;
|
||||
double tns_[MinMax::index_count];
|
||||
VertexSlackMap tns_slacks_[MinMax::index_count];
|
||||
// Indexed by path_ap->index().
|
||||
SlackSeq tns_;
|
||||
// Indexed by path_ap->index().
|
||||
VertexSlackMapSeq tns_slacks_;
|
||||
mutable Mutex tns_lock_;
|
||||
// Indexed by path_ap->index().
|
||||
WorstSlacks *worst_slacks_;
|
||||
// Use pointer to clk_info set so Tag.hh does not need to be included.
|
||||
ClkInfoSet *clk_info_set_;
|
||||
|
|
|
|||
|
|
@ -110,6 +110,7 @@ typedef Vector<Arrival> ArrivalSeq;
|
|||
typedef Map<Vertex*, int> VertexPathCountMap;
|
||||
typedef UnorderedMap<Tag*, int, TagMatchHash, TagMatchEqual> ArrivalMap;
|
||||
typedef Vector<PathVertex> PathVertexSeq;
|
||||
typedef Vector<Slack> SlackSeq;
|
||||
|
||||
typedef enum {
|
||||
report_path_full,
|
||||
|
|
|
|||
|
|
@ -1114,11 +1114,10 @@ isCondDisabled(Edge *edge,
|
|||
LibertyCell *cell = network->libertyCell(inst);
|
||||
LibertyPort *from_port = network->libertyPort(from_pin);
|
||||
LibertyPort *to_port = network->libertyPort(to_pin);
|
||||
CellTimingArcSetIterator *cond_iter =
|
||||
cell->timingArcSetIterator(from_port, to_port);
|
||||
LibertyCellTimingArcSetIterator cond_iter(cell, from_port, to_port);
|
||||
is_disabled = false;
|
||||
while (cond_iter->hasNext()) {
|
||||
TimingArcSet *cond_set = cond_iter->next();
|
||||
while (cond_iter.hasNext()) {
|
||||
TimingArcSet *cond_set = cond_iter.next();
|
||||
FuncExpr *cond = cond_set->cond();
|
||||
if (cond && sim->evalExpr(cond, inst) == logic_one) {
|
||||
disable_cond = cond;
|
||||
|
|
@ -1126,7 +1125,6 @@ isCondDisabled(Edge *edge,
|
|||
break;
|
||||
}
|
||||
}
|
||||
delete cond_iter;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -515,6 +515,7 @@ Sta::~Sta()
|
|||
delete debug_;
|
||||
delete units_;
|
||||
delete report_;
|
||||
delete power_;
|
||||
}
|
||||
|
||||
void
|
||||
|
|
@ -1624,15 +1625,12 @@ hasDisabledArcs(Edge *edge,
|
|||
Graph *graph)
|
||||
{
|
||||
TimingArcSet *arc_set = edge->timingArcSet();
|
||||
TimingArcSetArcIterator *arc_iter = arc_set->timingArcIterator();
|
||||
while (arc_iter->hasNext()) {
|
||||
TimingArc *arc = arc_iter->next();
|
||||
if (!searchThru(edge, arc, graph)) {
|
||||
delete arc_iter;
|
||||
TimingArcSetArcIterator arc_iter(arc_set);
|
||||
while (arc_iter.hasNext()) {
|
||||
TimingArc *arc = arc_iter.next();
|
||||
if (!searchThru(edge, arc, graph))
|
||||
return true;
|
||||
}
|
||||
}
|
||||
delete arc_iter;
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
@ -2847,17 +2845,32 @@ Sta::totalNegativeSlack(const MinMax *min_max)
|
|||
}
|
||||
|
||||
Slack
|
||||
Sta::worstSlack(const MinMax *min_max)
|
||||
Sta::totalNegativeSlack(const Corner *corner,
|
||||
const MinMax *min_max)
|
||||
{
|
||||
searchPreamble();
|
||||
return search_->worstSlack(min_max);
|
||||
return search_->totalNegativeSlack(corner, min_max);
|
||||
}
|
||||
|
||||
Vertex *
|
||||
Sta::worstSlackVertex(const MinMax *min_max)
|
||||
void
|
||||
Sta::worstSlack(const MinMax *min_max,
|
||||
// Return values.
|
||||
Slack &worst_slack,
|
||||
Vertex *&worst_vertex)
|
||||
{
|
||||
searchPreamble();
|
||||
return search_->worstSlackVertex(min_max);
|
||||
return search_->worstSlack(min_max, worst_slack, worst_vertex);
|
||||
}
|
||||
|
||||
void
|
||||
Sta::worstSlack(const Corner *corner,
|
||||
const MinMax *min_max,
|
||||
// Return values.
|
||||
Slack &worst_slack,
|
||||
Vertex *&worst_vertex)
|
||||
{
|
||||
searchPreamble();
|
||||
return search_->worstSlack(corner, min_max, worst_slack, worst_vertex);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////
|
||||
|
|
@ -3623,16 +3636,15 @@ Sta::makeInstanceAfter(Instance *inst)
|
|||
{
|
||||
LibertyCell *lib_cell = network_->libertyCell(inst);
|
||||
if (lib_cell && lib_cell->hasInternalPorts()) {
|
||||
LibertyCellPortBitIterator *port_iter = lib_cell->libertyPortBitIterator();
|
||||
while (port_iter->hasNext()) {
|
||||
LibertyPort *lib_port = port_iter->next();
|
||||
LibertyCellPortBitIterator port_iter(lib_cell);
|
||||
while (port_iter.hasNext()) {
|
||||
LibertyPort *lib_port = port_iter.next();
|
||||
if (lib_port->direction()->isInternal()
|
||||
&& lib_cell->hasTimingArcs(lib_port)) {
|
||||
Pin *pin = network_->findPin(inst, lib_port);
|
||||
connectPinAfter(pin);
|
||||
}
|
||||
}
|
||||
delete port_iter;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -4719,7 +4731,7 @@ Sta::reportSlewLimitVerbose(Pin *pin,
|
|||
Slew slew;
|
||||
float limit, slack;
|
||||
check_slew_limits_->checkSlews(pin, corner, min_max,
|
||||
corner, tr, slew, limit, slack);
|
||||
corner1, tr, slew, limit, slack);
|
||||
report_path_->reportSlewLimitVerbose(pin, corner1, tr, slew,
|
||||
limit, slack, min_max);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -903,12 +903,19 @@ public:
|
|||
// The sum of all negative endpoints slacks.
|
||||
// Incrementally updated.
|
||||
Slack totalNegativeSlack(const MinMax *min_max);
|
||||
// Worst endpoint slack.
|
||||
Slack totalNegativeSlack(const Corner *corner,
|
||||
const MinMax *min_max);
|
||||
// Worst endpoint slack and vertex.
|
||||
// Incrementally updated.
|
||||
Slack worstSlack(const MinMax *min_max);
|
||||
// Worst endpoint slack vertex.
|
||||
// Incrementally updated.
|
||||
Vertex *worstSlackVertex(const MinMax *min_max);
|
||||
void worstSlack(const MinMax *min_max,
|
||||
// Return values.
|
||||
Slack &worst_slack,
|
||||
Vertex *&worst_vertex);
|
||||
void worstSlack(const Corner *corner,
|
||||
const MinMax *min_max,
|
||||
// Return values.
|
||||
Slack &worst_slack,
|
||||
Vertex *&worst_vertex);
|
||||
VertexPathIterator *vertexPathIterator(Vertex *vertex,
|
||||
const TransRiseFall *tr,
|
||||
const PathAnalysisPt *path_ap);
|
||||
|
|
|
|||
|
|
@ -19,155 +19,95 @@
|
|||
#include "Debug.hh"
|
||||
#include "Report.hh"
|
||||
#include "Graph.hh"
|
||||
#include "Corner.hh"
|
||||
#include "Search.hh"
|
||||
#include "PathAnalysisPt.hh"
|
||||
#include "WorstSlack.hh"
|
||||
|
||||
namespace sta {
|
||||
|
||||
using std::min;
|
||||
|
||||
////////////////////////////////////////////////////////////////
|
||||
|
||||
class WnsSlackLess
|
||||
WorstSlacks::WorstSlacks(StaState *sta) :
|
||||
sta_(sta)
|
||||
{
|
||||
public:
|
||||
WnsSlackLess(const MinMax *min_max,
|
||||
Search *search);
|
||||
bool operator()(Vertex *vertex1,
|
||||
Vertex *vertex2);
|
||||
|
||||
private:
|
||||
const MinMax *min_max_;
|
||||
Search *search_;
|
||||
};
|
||||
|
||||
WnsSlackLess::WnsSlackLess(const MinMax *min_max,
|
||||
Search *search) :
|
||||
min_max_(min_max),
|
||||
search_(search)
|
||||
{
|
||||
}
|
||||
|
||||
bool
|
||||
WnsSlackLess::operator()(Vertex *vertex1,
|
||||
Vertex *vertex2)
|
||||
{
|
||||
return delayFuzzyLess(search_->wnsSlack(vertex1, min_max_),
|
||||
search_->wnsSlack(vertex2, min_max_));
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////
|
||||
|
||||
class WorstSlack
|
||||
{
|
||||
public:
|
||||
WorstSlack(const MinMax *min_max,
|
||||
StaState *sta);
|
||||
Vertex *worstVertex();
|
||||
Slack worstSlack();
|
||||
void clear();
|
||||
void updateWorstSlack(Vertex *vertex,
|
||||
Slack *slacks);
|
||||
void deleteVertexBefore(Vertex *vertex);
|
||||
|
||||
protected:
|
||||
void findWorstSlack();
|
||||
void initQueue();
|
||||
void findWorstInQueue();
|
||||
void setWorstSlack(Vertex *vertex,
|
||||
Slack slack);
|
||||
void sortQueue();
|
||||
void checkQueue();
|
||||
|
||||
Slack slack_init_;
|
||||
// Vertex with the worst slack.
|
||||
// When NULL the worst slack is unknown but in the queue.
|
||||
Vertex *worst_vertex_;
|
||||
Slack worst_slack_;
|
||||
Slack slack_threshold_;
|
||||
// Vertices with slack < threshold_
|
||||
VertexSet queue_;
|
||||
// Queue is sorted and pruned to min_queue_size_ vertices when it
|
||||
// reaches max_queue_size_.
|
||||
int min_queue_size_;
|
||||
int max_queue_size_;
|
||||
Mutex lock_;
|
||||
const MinMax *min_max_;
|
||||
WnsSlackLess slack_less_;
|
||||
StaState *sta_;
|
||||
};
|
||||
|
||||
////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
WorstSlacks::WorstSlacks(StaState *sta)
|
||||
{
|
||||
worst_slacks_[MinMax::minIndex()] = new WorstSlack(MinMax::min(), sta);
|
||||
worst_slacks_[MinMax::maxIndex()] = new WorstSlack(MinMax::max(), sta);
|
||||
}
|
||||
|
||||
WorstSlacks::~WorstSlacks()
|
||||
{
|
||||
delete worst_slacks_[MinMax::minIndex()];
|
||||
delete worst_slacks_[MinMax::maxIndex()];
|
||||
worst_slacks_.resize(sta->corners()->pathAnalysisPtCount());
|
||||
}
|
||||
|
||||
void
|
||||
WorstSlacks::clear()
|
||||
WorstSlacks::worstSlack(const MinMax *min_max,
|
||||
// Return values.
|
||||
Slack &worst_slack,
|
||||
Vertex *&worst_vertex)
|
||||
{
|
||||
worst_slacks_[MinMax::minIndex()]->clear();
|
||||
worst_slacks_[MinMax::maxIndex()]->clear();
|
||||
worst_slack = MinMax::min()->initValue();
|
||||
worst_vertex = NULL;
|
||||
CornerIterator corner_iter(sta_);
|
||||
while (corner_iter.hasNext()) {
|
||||
Corner *corner = corner_iter.next();
|
||||
PathAPIndex path_ap_index = corner->findPathAnalysisPt(min_max)->index();
|
||||
Slack worst_slack1;
|
||||
Vertex *worst_vertex1;
|
||||
worst_slacks_[path_ap_index].worstSlack(path_ap_index, sta_,
|
||||
worst_slack1, worst_vertex1);
|
||||
if (delayFuzzyLess(worst_slack1, worst_slack)) {
|
||||
worst_slack = worst_slack1;
|
||||
worst_vertex = worst_vertex1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Slack
|
||||
WorstSlacks::worstSlack(const MinMax *min_max)
|
||||
void
|
||||
WorstSlacks::worstSlack(const Corner *corner,
|
||||
const MinMax *min_max,
|
||||
// Return values.
|
||||
Slack &worst_slack,
|
||||
Vertex *&worst_vertex)
|
||||
{
|
||||
return worst_slacks_[min_max->index()]->worstSlack();
|
||||
}
|
||||
|
||||
Vertex *
|
||||
WorstSlacks::worstSlackVertex(const MinMax *min_max)
|
||||
{
|
||||
return worst_slacks_[min_max->index()]->worstVertex();
|
||||
PathAPIndex path_ap_index = corner->findPathAnalysisPt(min_max)->index();
|
||||
worst_slacks_[path_ap_index].worstSlack(path_ap_index, sta_,
|
||||
worst_slack, worst_vertex);
|
||||
}
|
||||
|
||||
void
|
||||
WorstSlacks::updateWorstSlacks(Vertex *vertex,
|
||||
Slack *slacks)
|
||||
SlackSeq &slacks)
|
||||
{
|
||||
worst_slacks_[MinMax::minIndex()]->updateWorstSlack(vertex, slacks);
|
||||
worst_slacks_[MinMax::maxIndex()]->updateWorstSlack(vertex, slacks);
|
||||
PathAPIndex path_ap_count = sta_->corners()->pathAnalysisPtCount();
|
||||
for (PathAPIndex i = 0; i < path_ap_count; i++)
|
||||
worst_slacks_[i].updateWorstSlack(vertex, slacks, i, sta_);
|
||||
}
|
||||
|
||||
void
|
||||
WorstSlacks::worstSlackNotifyBefore(Vertex *vertex)
|
||||
{
|
||||
worst_slacks_[MinMax::minIndex()]->deleteVertexBefore(vertex);
|
||||
worst_slacks_[MinMax::maxIndex()]->deleteVertexBefore(vertex);
|
||||
WorstSlackSeq::Iterator worst_iter(worst_slacks_);
|
||||
while (worst_iter.hasNext()) {
|
||||
WorstSlack &worst_slack = worst_iter.next();
|
||||
worst_slack.deleteVertexBefore(vertex);
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////
|
||||
|
||||
WorstSlack::WorstSlack(const MinMax *min_max,
|
||||
StaState *sta) :
|
||||
WorstSlack::WorstSlack() :
|
||||
slack_init_(MinMax::min()->initValue()),
|
||||
worst_vertex_(NULL),
|
||||
worst_slack_(slack_init_),
|
||||
slack_threshold_(slack_init_),
|
||||
min_queue_size_(10),
|
||||
max_queue_size_(20),
|
||||
min_max_(min_max),
|
||||
slack_less_(min_max, sta->search()),
|
||||
sta_(sta)
|
||||
max_queue_size_(20)
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
WorstSlack::clear()
|
||||
WorstSlack::WorstSlack(const WorstSlack &) :
|
||||
slack_init_(MinMax::min()->initValue()),
|
||||
worst_vertex_(NULL),
|
||||
worst_slack_(slack_init_),
|
||||
slack_threshold_(slack_init_),
|
||||
min_queue_size_(10),
|
||||
max_queue_size_(20)
|
||||
{
|
||||
queue_.clear();
|
||||
worst_vertex_ = NULL;
|
||||
worst_slack_ = slack_init_;
|
||||
}
|
||||
|
||||
void
|
||||
|
|
@ -182,36 +122,36 @@ WorstSlack::deleteVertexBefore(Vertex *vertex)
|
|||
lock_.unlock();
|
||||
}
|
||||
|
||||
Vertex *
|
||||
WorstSlack::worstVertex()
|
||||
void
|
||||
WorstSlack::worstSlack(PathAPIndex path_ap_index,
|
||||
const StaState *sta,
|
||||
// Return values.
|
||||
Slack &worst_slack,
|
||||
Vertex *&worst_vertex)
|
||||
{
|
||||
findWorstSlack();
|
||||
return worst_vertex_;
|
||||
}
|
||||
|
||||
Slack
|
||||
WorstSlack::worstSlack()
|
||||
{
|
||||
findWorstSlack();
|
||||
return worst_slack_;
|
||||
findWorstSlack(path_ap_index, sta);
|
||||
worst_slack = worst_slack_;
|
||||
worst_vertex = worst_vertex_;
|
||||
}
|
||||
|
||||
void
|
||||
WorstSlack::findWorstSlack()
|
||||
WorstSlack::findWorstSlack(PathAPIndex path_ap_index,
|
||||
const StaState *sta)
|
||||
{
|
||||
if (worst_vertex_ == NULL) {
|
||||
if (queue_.empty())
|
||||
initQueue();
|
||||
initQueue(path_ap_index, sta);
|
||||
else
|
||||
findWorstInQueue();
|
||||
findWorstInQueue(path_ap_index, sta);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
WorstSlack::initQueue()
|
||||
WorstSlack::initQueue(PathAPIndex path_ap_index,
|
||||
const StaState *sta)
|
||||
{
|
||||
Search *search = sta_->search();
|
||||
const Debug *debug = sta_->debug();
|
||||
Search *search = sta->search();
|
||||
const Debug *debug = sta->debug();
|
||||
debugPrint0(debug, "wns", 3, "init queue\n");
|
||||
|
||||
queue_.clear();
|
||||
|
|
@ -221,27 +161,28 @@ WorstSlack::initQueue()
|
|||
VertexSet::Iterator end_iter(search->endpoints());
|
||||
while (end_iter.hasNext()) {
|
||||
Vertex *vertex = end_iter.next();
|
||||
Slack slack = search->wnsSlack(vertex, min_max_);
|
||||
Slack slack = search->wnsSlack(vertex, path_ap_index);
|
||||
if (!delayFuzzyEqual(slack, slack_init_)) {
|
||||
if (delayFuzzyLess(slack, worst_slack_))
|
||||
setWorstSlack(vertex, slack);
|
||||
setWorstSlack(vertex, slack, sta);
|
||||
if (delayFuzzyLessEqual(slack, slack_threshold_))
|
||||
queue_.insert(vertex);
|
||||
int queue_size = queue_.size();
|
||||
if (queue_size >= max_queue_size_)
|
||||
sortQueue();
|
||||
sortQueue(path_ap_index, sta);
|
||||
}
|
||||
}
|
||||
debugPrint1(debug, "wns", 3, "threshold %s\n",
|
||||
delayAsString(slack_threshold_, sta_->units()));
|
||||
delayAsString(slack_threshold_, sta->units()));
|
||||
// checkQueue();
|
||||
}
|
||||
|
||||
void
|
||||
WorstSlack::sortQueue()
|
||||
WorstSlack::sortQueue(PathAPIndex path_ap_index,
|
||||
const StaState *sta)
|
||||
{
|
||||
Search *search = sta_->search();
|
||||
const Debug *debug = sta_->debug();
|
||||
Search *search = sta->search();
|
||||
const Debug *debug = sta->debug();
|
||||
debugPrint0(debug, "wns", 3, "sort queue\n");
|
||||
|
||||
VertexSeq vertices;
|
||||
|
|
@ -251,36 +192,38 @@ WorstSlack::sortQueue()
|
|||
Vertex *vertex = queue_iter.next();
|
||||
vertices.push_back(vertex);
|
||||
}
|
||||
sort(vertices, slack_less_);
|
||||
WnsSlackLess slack_less(path_ap_index, sta);
|
||||
sort(vertices, slack_less);
|
||||
|
||||
int vertex_count = vertices.size();
|
||||
int threshold_index = min(min_queue_size_, vertex_count - 1);
|
||||
Vertex *threshold_vertex = vertices[threshold_index];
|
||||
slack_threshold_ = search->wnsSlack(threshold_vertex, min_max_);
|
||||
slack_threshold_ = search->wnsSlack(threshold_vertex, path_ap_index);
|
||||
debugPrint1(debug, "wns", 3, "threshold %s\n",
|
||||
delayAsString(slack_threshold_, sta_->units()));
|
||||
delayAsString(slack_threshold_, sta->units()));
|
||||
|
||||
// Reinsert vertices with slack < threshold.
|
||||
queue_.clear();
|
||||
VertexSeq::Iterator queue_iter2(vertices);
|
||||
while (queue_iter2.hasNext()) {
|
||||
Vertex *vertex = queue_iter2.next();
|
||||
Slack slack = search->wnsSlack(vertex, min_max_);
|
||||
Slack slack = search->wnsSlack(vertex, path_ap_index);
|
||||
if (delayFuzzyGreater(slack, slack_threshold_))
|
||||
break;
|
||||
queue_.insert(vertex);
|
||||
}
|
||||
max_queue_size_ = queue_.size() * 2;
|
||||
Vertex *worst_slack_vertex = vertices[0];
|
||||
Slack worst_slack_slack = search->wnsSlack(worst_slack_vertex, min_max_);
|
||||
setWorstSlack(worst_slack_vertex, worst_slack_slack);
|
||||
Slack worst_slack_slack = search->wnsSlack(worst_slack_vertex, path_ap_index);
|
||||
setWorstSlack(worst_slack_vertex, worst_slack_slack, sta);
|
||||
}
|
||||
|
||||
void
|
||||
WorstSlack::findWorstInQueue()
|
||||
WorstSlack::findWorstInQueue(PathAPIndex path_ap_index,
|
||||
const StaState *sta)
|
||||
{
|
||||
Search *search = sta_->search();
|
||||
const Debug *debug = sta_->debug();
|
||||
Search *search = sta->search();
|
||||
const Debug *debug = sta->debug();
|
||||
debugPrint0(debug, "wns", 3, "find worst in queue\n");
|
||||
|
||||
worst_vertex_ = NULL;
|
||||
|
|
@ -288,29 +231,31 @@ WorstSlack::findWorstInQueue()
|
|||
VertexSet::Iterator queue_iter(queue_);
|
||||
while (queue_iter.hasNext()) {
|
||||
Vertex *vertex = queue_iter.next();
|
||||
Slack slack = search->wnsSlack(vertex, min_max_);
|
||||
Slack slack = search->wnsSlack(vertex, path_ap_index);
|
||||
if (slack < worst_slack_)
|
||||
setWorstSlack(vertex, slack);
|
||||
setWorstSlack(vertex, slack, sta);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
WorstSlack::checkQueue()
|
||||
WorstSlack::checkQueue(PathAPIndex path_ap_index,
|
||||
const StaState *sta)
|
||||
{
|
||||
Search *search = sta_->search();
|
||||
Report *report = sta_->report();
|
||||
Units *units = sta_->units();
|
||||
const Network *network = sta_->network();
|
||||
Search *search = sta->search();
|
||||
Report *report = sta->report();
|
||||
Units *units = sta->units();
|
||||
const Network *network = sta->network();
|
||||
|
||||
VertexSeq ends;
|
||||
VertexSet::Iterator end_iter(search->endpoints());
|
||||
while (end_iter.hasNext()) {
|
||||
Vertex *end = end_iter.next();
|
||||
if (delayFuzzyLessEqual(search->wnsSlack(end, min_max_),
|
||||
if (delayFuzzyLessEqual(search->wnsSlack(end, path_ap_index),
|
||||
slack_threshold_))
|
||||
ends.push_back(end);
|
||||
}
|
||||
sort(ends, slack_less_);
|
||||
WnsSlackLess slack_less(path_ap_index, sta);
|
||||
sort(ends, slack_less);
|
||||
|
||||
VertexSet end_set;
|
||||
VertexSeq::Iterator end_iter2(ends);
|
||||
|
|
@ -318,11 +263,11 @@ WorstSlack::checkQueue()
|
|||
Vertex *end = end_iter2.next();
|
||||
end_set.insert(end);
|
||||
if (!queue_.hasKey(end)
|
||||
&& delayFuzzyLessEqual(search->wnsSlack(end, min_max_),
|
||||
&& delayFuzzyLessEqual(search->wnsSlack(end, path_ap_index),
|
||||
slack_threshold_))
|
||||
report->print("WorstSlack queue missing %s %s < %s\n",
|
||||
end->name(network),
|
||||
delayAsString(search->wnsSlack(end, min_max_), units),
|
||||
delayAsString(search->wnsSlack(end, path_ap_index), units),
|
||||
delayAsString(slack_threshold_, units));
|
||||
}
|
||||
|
||||
|
|
@ -332,7 +277,7 @@ WorstSlack::checkQueue()
|
|||
if (!end_set.hasKey(end))
|
||||
report->print("WorstSlack queue extra %s %s > %s\n",
|
||||
end->name(network),
|
||||
delayAsString(search->wnsSlack(end, min_max_),
|
||||
delayAsString(search->wnsSlack(end, path_ap_index),
|
||||
units),
|
||||
delayAsString(slack_threshold_, units));
|
||||
}
|
||||
|
|
@ -340,18 +285,20 @@ WorstSlack::checkQueue()
|
|||
|
||||
void
|
||||
WorstSlack::updateWorstSlack(Vertex *vertex,
|
||||
Slack *slacks)
|
||||
SlackSeq &slacks,
|
||||
PathAPIndex path_ap_index,
|
||||
const StaState *sta)
|
||||
{
|
||||
const Debug *debug = sta_->debug();
|
||||
const Network *network = sta_->network();
|
||||
Slack slack = slacks[min_max_->index()];
|
||||
const Debug *debug = sta->debug();
|
||||
const Network *network = sta->network();
|
||||
Slack slack = slacks[path_ap_index];
|
||||
|
||||
// Locking is required because ArrivalVisitor called by multiple
|
||||
// Locking is required because ArrivalVisitor is called by multiple
|
||||
// threads.
|
||||
lock_.lock();
|
||||
if (worst_vertex_
|
||||
&& delayFuzzyLess(slack, worst_slack_))
|
||||
setWorstSlack(vertex, slack);
|
||||
setWorstSlack(vertex, slack, sta);
|
||||
else if (vertex == worst_vertex_)
|
||||
// Mark worst slack as unknown (updated by findWorstSlack().
|
||||
worst_vertex_ = NULL;
|
||||
|
|
@ -360,13 +307,13 @@ WorstSlack::updateWorstSlack(Vertex *vertex,
|
|||
&& delayFuzzyLessEqual(slack, slack_threshold_)) {
|
||||
debugPrint2(debug, "wns", 3, "insert %s %s\n",
|
||||
vertex->name(network),
|
||||
delayAsString(slack, sta_->units()));
|
||||
delayAsString(slack, sta->units()));
|
||||
queue_.insert(vertex);
|
||||
}
|
||||
else {
|
||||
debugPrint2(debug, "wns", 3, "delete %s %s\n",
|
||||
vertex->name(network),
|
||||
delayAsString(slack, sta_->units()));
|
||||
delayAsString(slack, sta->units()));
|
||||
queue_.eraseKey(vertex);
|
||||
}
|
||||
lock_.unlock();
|
||||
|
|
@ -375,13 +322,31 @@ WorstSlack::updateWorstSlack(Vertex *vertex,
|
|||
|
||||
void
|
||||
WorstSlack::setWorstSlack(Vertex *vertex,
|
||||
Slack slack)
|
||||
Slack slack,
|
||||
const StaState *sta)
|
||||
{
|
||||
debugPrint2(sta_->debug(), "wns", 3, "%s %s\n",
|
||||
vertex->name(sta_->network()),
|
||||
delayAsString(slack, sta_->units()));
|
||||
debugPrint2(sta->debug(), "wns", 3, "%s %s\n",
|
||||
vertex->name(sta->network()),
|
||||
delayAsString(slack, sta->units()));
|
||||
worst_vertex_ = vertex;
|
||||
worst_slack_ = slack;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////
|
||||
|
||||
WnsSlackLess::WnsSlackLess(PathAPIndex path_ap_index,
|
||||
const StaState *sta) :
|
||||
path_ap_index_(path_ap_index),
|
||||
search_(sta->search())
|
||||
{
|
||||
}
|
||||
|
||||
bool
|
||||
WnsSlackLess::operator()(Vertex *vertex1,
|
||||
Vertex *vertex2)
|
||||
{
|
||||
return delayFuzzyLess(search_->wnsSlack(vertex1, path_ap_index_),
|
||||
search_->wnsSlack(vertex2, path_ap_index_));
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
|
|
|||
|
|
@ -20,25 +20,95 @@
|
|||
namespace sta {
|
||||
|
||||
#include "MinMax.hh"
|
||||
#include "Vector.hh"
|
||||
#include "GraphClass.hh"
|
||||
#include "SearchClass.hh"
|
||||
|
||||
class StaState;
|
||||
class WorstSlack;
|
||||
class WnsSlackLess;
|
||||
|
||||
typedef Vector<WorstSlack> WorstSlackSeq;
|
||||
|
||||
class WorstSlacks
|
||||
{
|
||||
public:
|
||||
WorstSlacks(StaState *sta);
|
||||
~WorstSlacks();
|
||||
void clear();
|
||||
Slack worstSlack(const MinMax *min_max);
|
||||
Vertex *worstSlackVertex(const MinMax *min_max);
|
||||
void worstSlack(const MinMax *min_max,
|
||||
// Return values.
|
||||
Slack &worst_slack,
|
||||
Vertex *&worst_vertex);
|
||||
void worstSlack(const Corner *corner,
|
||||
const MinMax *min_max,
|
||||
// Return values.
|
||||
Slack &worst_slack,
|
||||
Vertex *&worst_vertex);
|
||||
void updateWorstSlacks(Vertex *vertex,
|
||||
Slack *slacks);
|
||||
SlackSeq &slacks);
|
||||
void worstSlackNotifyBefore(Vertex *vertex);
|
||||
|
||||
protected:
|
||||
WorstSlack *worst_slacks_[MinMax::index_count];
|
||||
WorstSlackSeq worst_slacks_;
|
||||
const StaState *sta_;
|
||||
};
|
||||
|
||||
class WnsSlackLess
|
||||
{
|
||||
public:
|
||||
WnsSlackLess(PathAPIndex path_ap_index,
|
||||
const StaState *sta);
|
||||
bool operator()(Vertex *vertex1,
|
||||
Vertex *vertex2);
|
||||
|
||||
private:
|
||||
PathAPIndex path_ap_index_;
|
||||
Search *search_;
|
||||
};
|
||||
|
||||
class WorstSlack
|
||||
{
|
||||
public:
|
||||
WorstSlack();
|
||||
WorstSlack(const WorstSlack &);
|
||||
void worstSlack(PathAPIndex path_ap_index,
|
||||
const StaState *sta,
|
||||
// Return values.
|
||||
Slack &worst_slack,
|
||||
Vertex *&worst_vertex);
|
||||
void updateWorstSlack(Vertex *vertex,
|
||||
SlackSeq &slacks,
|
||||
PathAPIndex path_ap_index,
|
||||
const StaState *sta);
|
||||
void deleteVertexBefore(Vertex *vertex);
|
||||
|
||||
protected:
|
||||
void findWorstSlack(PathAPIndex path_ap_index,
|
||||
const StaState *sta);
|
||||
void initQueue(PathAPIndex path_ap_index,
|
||||
const StaState *sta);
|
||||
void findWorstInQueue(PathAPIndex path_ap_index,
|
||||
const StaState *sta);
|
||||
void setWorstSlack(Vertex *vertex,
|
||||
Slack slack,
|
||||
const StaState *sta);
|
||||
void sortQueue(PathAPIndex path_ap_index,
|
||||
const StaState *sta);
|
||||
void checkQueue(PathAPIndex path_ap_index,
|
||||
const StaState *sta);
|
||||
|
||||
Slack slack_init_;
|
||||
// Vertex with the worst slack.
|
||||
// When NULL the worst slack is unknown but in the queue.
|
||||
Vertex *worst_vertex_;
|
||||
Slack worst_slack_;
|
||||
Slack slack_threshold_;
|
||||
// Vertices with slack < threshold_
|
||||
VertexSet queue_;
|
||||
// Queue is sorted and pruned to min_queue_size_ vertices when it
|
||||
// reaches max_queue_size_.
|
||||
int min_queue_size_;
|
||||
int max_queue_size_;
|
||||
Mutex lock_;
|
||||
};
|
||||
|
||||
} // namespace
|
||||
|
|
|
|||
20
tcl/Cmds.tcl
20
tcl/Cmds.tcl
|
|
@ -1228,6 +1228,9 @@ proc get_ports_or_pins { pattern } {
|
|||
|
||||
################################################################
|
||||
|
||||
# If -corner keyword is missing:
|
||||
# one corner, return default
|
||||
# multiple corner, error
|
||||
proc parse_corner { keys_var } {
|
||||
upvar 1 $keys_var keys
|
||||
|
||||
|
|
@ -1246,6 +1249,23 @@ proc parse_corner { keys_var } {
|
|||
}
|
||||
}
|
||||
|
||||
# Assumes caller checks for existence of -corner keyword arg.
|
||||
proc parse_corner_required { keys_var } {
|
||||
upvar 1 $keys_var keys
|
||||
|
||||
if { [info exists keys(-corner)] } {
|
||||
set corner_name $keys(-corner)
|
||||
set corner [find_corner $corner_name]
|
||||
if { $corner == "NULL" } {
|
||||
sta_error "$corner_name is not the name of process corner."
|
||||
} else {
|
||||
return $corner
|
||||
}
|
||||
} else {
|
||||
sta_error "missing -corner arg."
|
||||
}
|
||||
}
|
||||
|
||||
proc parse_corner_or_default { keys_var } {
|
||||
upvar 1 $keys_var keys
|
||||
|
||||
|
|
|
|||
|
|
@ -289,25 +289,39 @@ proc report_tag_arrivals { pin } {
|
|||
|
||||
################################################################
|
||||
|
||||
define_hidden_cmd_args "total_negative_slack" {[-min]|[-max]}
|
||||
define_hidden_cmd_args "total_negative_slack" \
|
||||
{[-corner corner] [-min]|[-max]}
|
||||
|
||||
proc total_negative_slack { args } {
|
||||
parse_key_args "total_negative_slack" args keys {} flags {-min -max}
|
||||
parse_key_args "total_negative_slack" args \
|
||||
keys {-corner} flags {-min -max}
|
||||
check_argc_eq0 "total_negative_slack" $args
|
||||
set min_max [parse_min_max_flags flags]
|
||||
set tns [total_negative_slack_cmd $min_max]
|
||||
if { [info exists keys(-corner)] } {
|
||||
set corner [parse_corner_required keys]
|
||||
set tns [total_negative_slack_corner_cmd $corner $min_max]
|
||||
} else {
|
||||
set tns [total_negative_slack_cmd $min_max]
|
||||
}
|
||||
return [time_sta_ui $tns]
|
||||
}
|
||||
|
||||
################################################################
|
||||
|
||||
define_hidden_cmd_args "worst_negative_slack" {[-min]|[-max]}
|
||||
define_hidden_cmd_args "worst_negative_slack" \
|
||||
{[-corner corner] [-min]|[-max]}
|
||||
|
||||
proc worst_negative_slack { args } {
|
||||
parse_key_args "total_negative_slack" args keys {} flags {-min -max}
|
||||
parse_key_args "total_negative_slack" args \
|
||||
keys {-corner} flags {-min -max}
|
||||
check_argc_eq0 "worst_negative_slack" $args
|
||||
set min_max [parse_min_max_flags flags]
|
||||
set worst_slack [worst_slack $min_max]
|
||||
if { [info exists keys(-corner)] } {
|
||||
set corner [parse_corner_required keys]
|
||||
set worst_slack [worst_slack_corner $corner $min_max]
|
||||
} else {
|
||||
set worst_slack [worst_slack $min_max]
|
||||
}
|
||||
if { $worst_slack < 0.0 } {
|
||||
return [time_sta_ui $worst_slack]
|
||||
} else {
|
||||
|
|
|
|||
61
tcl/StaTcl.i
61
tcl/StaTcl.i
|
|
@ -681,9 +681,9 @@ edgeDelayProperty(Edge *edge,
|
|||
ArcDelay delay = 0.0;
|
||||
bool delay_exists = false;
|
||||
TimingArcSet *arc_set = edge->timingArcSet();
|
||||
TimingArcSetArcIterator *arc_iter = arc_set->timingArcIterator();
|
||||
while (arc_iter->hasNext()) {
|
||||
TimingArc *arc = arc_iter->next();
|
||||
TimingArcSetArcIterator arc_iter(arc_set);
|
||||
while (arc_iter.hasNext()) {
|
||||
TimingArc *arc = arc_iter.next();
|
||||
TransRiseFall *to_tr = arc->toTrans()->asRiseFall();
|
||||
if (to_tr == tr) {
|
||||
CornerIterator corner_iter(sta);
|
||||
|
|
@ -700,7 +700,6 @@ edgeDelayProperty(Edge *edge,
|
|||
}
|
||||
}
|
||||
}
|
||||
delete arc_iter;
|
||||
return sta->units()->timeUnit()->asString(delayAsFloat(delay), 8);
|
||||
}
|
||||
|
||||
|
|
@ -1747,7 +1746,7 @@ using namespace sta;
|
|||
Tcl_SetObjResult(interp, obj);
|
||||
}
|
||||
|
||||
%typemap(out) CellTimingArcSetIterator* {
|
||||
%typemap(out) LibertyCellTimingArcSetIterator* {
|
||||
Tcl_Obj *obj=SWIG_NewInstanceObj($1, $1_descriptor, false);
|
||||
Tcl_SetObjResult(interp, obj);
|
||||
}
|
||||
|
|
@ -1994,11 +1993,11 @@ private:
|
|||
~TimingArcSet();
|
||||
};
|
||||
|
||||
class CellTimingArcSetIterator
|
||||
class LibertyCellTimingArcSetIterator
|
||||
{
|
||||
private:
|
||||
CellTimingArcSetIterator();
|
||||
~CellTimingArcSetIterator();
|
||||
LibertyCellTimingArcSetIterator();
|
||||
~LibertyCellTimingArcSetIterator();
|
||||
};
|
||||
|
||||
class TimingArcSetArcIterator
|
||||
|
|
@ -4666,27 +4665,43 @@ find_delays()
|
|||
}
|
||||
|
||||
Slack
|
||||
total_negative_slack_cmd(MinMax *min_max)
|
||||
total_negative_slack_cmd(const MinMax *min_max)
|
||||
{
|
||||
cmdLinkedNetwork();
|
||||
Sta *sta = Sta::sta();
|
||||
return sta->totalNegativeSlack(min_max);
|
||||
}
|
||||
|
||||
Slack
|
||||
total_negative_slack_corner_cmd(const Corner *corner,
|
||||
const MinMax *min_max)
|
||||
{
|
||||
cmdLinkedNetwork();
|
||||
Sta *sta = Sta::sta();
|
||||
return sta->totalNegativeSlack(corner, min_max);
|
||||
}
|
||||
|
||||
Slack
|
||||
worst_slack(const MinMax *min_max)
|
||||
{
|
||||
cmdLinkedNetwork();
|
||||
Sta *sta = Sta::sta();
|
||||
return sta->worstSlack(min_max);
|
||||
Slack worst_slack;
|
||||
Vertex *worst_vertex;
|
||||
sta->worstSlack(min_max, worst_slack, worst_vertex);
|
||||
return worst_slack;
|
||||
}
|
||||
|
||||
Vertex *
|
||||
worst_slack_vertex(const MinMax *min_max)
|
||||
Slack
|
||||
worst_slack_corner(const Corner *corner,
|
||||
const MinMax *min_max)
|
||||
{
|
||||
cmdLinkedNetwork();
|
||||
Sta *sta = Sta::sta();
|
||||
return sta->worstSlackVertex(min_max);
|
||||
Slack worst_slack;
|
||||
Vertex *worst_vertex;
|
||||
sta->worstSlack(corner, min_max, worst_slack, worst_vertex);
|
||||
return worst_slack;
|
||||
}
|
||||
|
||||
PathRef *
|
||||
|
|
@ -5460,10 +5475,10 @@ find_liberty_ports_matching(const char *pattern,
|
|||
}
|
||||
|
||||
LibertyCellPortIterator *
|
||||
liberty_port_iterator() { return self->libertyPortIterator(); }
|
||||
liberty_port_iterator() { return new LibertyCellPortIterator(self); }
|
||||
|
||||
CellTimingArcSetIterator *
|
||||
timing_arc_set_iterator() { return self->timingArcSetIterator(); }
|
||||
LibertyCellTimingArcSetIterator *
|
||||
timing_arc_set_iterator() { return new LibertyCellTimingArcSetIterator(self); }
|
||||
|
||||
} // LibertyCell methods
|
||||
|
||||
|
|
@ -5500,7 +5515,7 @@ Cell *cell() { return self->cell(); }
|
|||
const char *object_name() { return self->name(); }
|
||||
bool is_bus() { return self->isBus(); }
|
||||
LibertyPortMemberIterator *
|
||||
member_iterator() { return self->libertyMemberIterator(); }
|
||||
member_iterator() { return new LibertyPortMemberIterator(self); }
|
||||
const char *
|
||||
direction() { return self->direction()->name(); }
|
||||
|
||||
|
|
@ -5575,7 +5590,7 @@ object_name()
|
|||
|
||||
} // TimingArcSet methods
|
||||
|
||||
%extend CellTimingArcSetIterator {
|
||||
%extend LibertyCellTimingArcSetIterator {
|
||||
bool has_next() { return self->hasNext(); }
|
||||
TimingArcSet *next() { return self->next(); }
|
||||
void finish() { delete self; }
|
||||
|
|
@ -5908,7 +5923,7 @@ arrivals_clk(const TransRiseFall *tr,
|
|||
return floats;
|
||||
}
|
||||
|
||||
StringSeq *
|
||||
TmpStringSeq *
|
||||
arrivals_clk_delays(const TransRiseFall *tr,
|
||||
Clock *clk,
|
||||
const TransRiseFall *clk_tr,
|
||||
|
|
@ -5948,7 +5963,7 @@ requireds_clk(const TransRiseFall *tr,
|
|||
return floats;
|
||||
}
|
||||
|
||||
StringSeq *
|
||||
TmpStringSeq *
|
||||
requireds_clk_delays(const TransRiseFall *tr,
|
||||
Clock *clk,
|
||||
const TransRiseFall *clk_tr,
|
||||
|
|
@ -6002,7 +6017,7 @@ slacks_clk(const TransRiseFall *tr,
|
|||
return floats;
|
||||
}
|
||||
|
||||
StringSeq *
|
||||
TmpStringSeq *
|
||||
slacks_clk_delays(const TransRiseFall *tr,
|
||||
Clock *clk,
|
||||
const TransRiseFall *clk_tr,
|
||||
|
|
@ -6054,7 +6069,7 @@ Pin *to_pin() { return self->to(Sta::sta()->graph())->pin(); }
|
|||
TimingRole *role() { return self->role(); }
|
||||
const char *sense() { return timingSenseString(self->sense()); }
|
||||
TimingArcSetArcIterator *
|
||||
timing_arc_iterator() { return self->timingArcSet()->timingArcIterator(); }
|
||||
timing_arc_iterator() { return new TimingArcSetArcIterator(self->timingArcSet()); }
|
||||
bool is_disabled_loop() { return Sta::sta()->isDisabledLoop(self); }
|
||||
bool is_disabled_constraint() { return Sta::sta()->isDisabledConstraint(self);}
|
||||
bool is_disabled_constant() { return Sta::sta()->isDisabledConstant(self); }
|
||||
|
|
@ -6084,7 +6099,7 @@ arc_delays(TimingArc *arc)
|
|||
return floats;
|
||||
}
|
||||
|
||||
StringSeq *
|
||||
TmpStringSeq *
|
||||
arc_delay_strings(TimingArc *arc,
|
||||
int digits)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -560,9 +560,8 @@ VerilogReader::makeModuleInst(const char *module_name,
|
|||
Port *port = network_->findPort(cell, port_name);
|
||||
LibertyPort *lport = network_->libertyPort(port);
|
||||
if (lport->isBus()) {
|
||||
LibertyPortMemberIterator *member_iter=lport->libertyMemberIterator();
|
||||
lport = member_iter->next();
|
||||
delete member_iter;
|
||||
LibertyPortMemberIterator member_iter(lport);
|
||||
lport = member_iter.next();
|
||||
}
|
||||
int pin_index = lport->pinIndex();
|
||||
const char *prev_net_name = net_names[pin_index];
|
||||
|
|
@ -1969,9 +1968,9 @@ VerilogReader::makeLibertyInst(VerilogLibertyInst *lib_inst,
|
|||
Instance *inst = network_->makeInstance(cell, lib_inst->instanceName(),
|
||||
parent);
|
||||
const char **net_names = lib_inst->netNames();
|
||||
LibertyCellPortBitIterator *port_iter = lib_cell->libertyPortBitIterator();
|
||||
while (port_iter->hasNext()) {
|
||||
LibertyPort *port = port_iter->next();
|
||||
LibertyCellPortBitIterator port_iter(lib_cell);
|
||||
while (port_iter.hasNext()) {
|
||||
LibertyPort *port = port_iter.next();
|
||||
const char *net_name = net_names[port->pinIndex()];
|
||||
// net_name may be the name of a single bit bus.
|
||||
if (net_name) {
|
||||
|
|
@ -1997,7 +1996,6 @@ VerilogReader::makeLibertyInst(VerilogLibertyInst *lib_inst,
|
|||
&& lib_cell->hasTimingArcs(port))
|
||||
network_->makePin(inst, reinterpret_cast<Port*>(port), NULL);
|
||||
}
|
||||
delete port_iter;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////
|
||||
|
|
|
|||
Loading…
Reference in New Issue