2.0.6
This commit is contained in:
parent
ca231b29cc
commit
3f65204717
|
|
@ -16,7 +16,7 @@
|
|||
|
||||
cmake_minimum_required (VERSION 3.9)
|
||||
|
||||
project(STA VERSION 2.0.5)
|
||||
project(STA VERSION 2.0.6)
|
||||
|
||||
set(CMAKE_VERBOSE_MAKEFILE ON)
|
||||
set(CMAKE_CXX_STANDARD 11)
|
||||
|
|
|
|||
|
|
@ -16,7 +16,7 @@
|
|||
|
||||
# Process this file with autoconf to produce a configure script.
|
||||
|
||||
AC_INIT(sta, 2.0.5)
|
||||
AC_INIT(sta, 2.0.6)
|
||||
AM_INIT_AUTOMAKE
|
||||
AC_CONFIG_MACRO_DIR([m4])
|
||||
AC_CONFIG_HEADERS(config.h)
|
||||
|
|
|
|||
|
|
@ -84,7 +84,8 @@ public:
|
|||
float load_cap,
|
||||
Parasitic *drvr_parasitic,
|
||||
float related_out_cap,
|
||||
const Pvt *pvt, const DcalcAnalysisPt *dcalc_ap,
|
||||
const Pvt *pvt,
|
||||
const DcalcAnalysisPt *dcalc_ap,
|
||||
// Return values.
|
||||
ArcDelay &gate_delay,
|
||||
Slew &drvr_slew) = 0;
|
||||
|
|
|
|||
|
|
@ -1309,7 +1309,8 @@ ArnoldiDelayCalc::ra_get_r(delay_work *D,
|
|||
ArcDelay d1;
|
||||
Slew s1;
|
||||
tab->table->gateDelay(tab->cell, tab->pvt, tab->in_slew,
|
||||
c1, tab->relcap, d1, s1);
|
||||
c1, tab->relcap, pocv_enabled_,
|
||||
d1, s1);
|
||||
tlohi = slew_derate*delayAsFloat(s1);
|
||||
r = tlohi/(c_log*c1);
|
||||
if (rdelay>0.0 && r > rdelay)
|
||||
|
|
@ -1332,7 +1333,7 @@ ArnoldiDelayCalc::ra_get_s(delay_work *D,
|
|||
ArcDelay d1;
|
||||
Slew s1;
|
||||
tab->table->gateDelay(tab->cell, tab->pvt, tab->in_slew,
|
||||
c, tab->relcap, d1, s1);
|
||||
c, tab->relcap, pocv_enabled_, d1, s1);
|
||||
tlohi = slew_derate*delayAsFloat(s1);
|
||||
smin = r*c*c_smin; // c_smin = ra_hinv((1-vhi)/vhi-log(vhi)) + log(vhi);
|
||||
if (c_log*r*c >= tlohi) {
|
||||
|
|
@ -1366,9 +1367,9 @@ ArnoldiDelayCalc::ra_rdelay_1(timing_table *tab,
|
|||
ArcDelay d1, d2;
|
||||
Slew s1, s2;
|
||||
tab->table->gateDelay(tab->cell, tab->pvt, tab->in_slew,
|
||||
c1, tab->relcap, d1, s1);
|
||||
c1, tab->relcap, pocv_enabled_, d1, s1);
|
||||
tab->table->gateDelay(tab->cell, tab->pvt, tab->in_slew,
|
||||
c2, tab->relcap, d2, s2);
|
||||
c2, tab->relcap, pocv_enabled_, d2, s2);
|
||||
double dt50 = delayAsFloat(d1)-delayAsFloat(d2);
|
||||
if (dt50 <= 0.0)
|
||||
return 0.0;
|
||||
|
|
@ -1421,12 +1422,12 @@ ArnoldiDelayCalc::ar1_ceff_delay(delay_work *D,
|
|||
thix = ra_solve_for_t(p,s,vhi);
|
||||
tlox = ra_solve_for_t(p,s,vlo);
|
||||
tab->table->gateDelay(tab->cell, tab->pvt,tab->in_slew,
|
||||
ctot, tab->relcap, df, sf);
|
||||
ctot, tab->relcap, pocv_enabled_, df, sf);
|
||||
debugPrint3(debug_, "arnoldi", 1,
|
||||
"table slew (in_slew %s ctot %s) = %s\n",
|
||||
units_->timeUnit()->asString(tab->in_slew),
|
||||
units_->capacitanceUnit()->asString(ctot),
|
||||
delayAsString(sf, units_));
|
||||
delayAsString(sf, this));
|
||||
tlohi = slew_derate*delayAsFloat(sf);
|
||||
debugPrint2(debug_, "arnoldi", 1, "tlohi %s %s\n",
|
||||
units_->timeUnit()->asString(tlohi),
|
||||
|
|
@ -1434,7 +1435,7 @@ ArnoldiDelayCalc::ar1_ceff_delay(delay_work *D,
|
|||
}
|
||||
ceff = ctot;
|
||||
tab->table->gateDelay(tab->cell, tab->pvt, tab->in_slew,
|
||||
ceff, tab->relcap, df, sf);
|
||||
ceff, tab->relcap, pocv_enabled_, df, sf);
|
||||
t50_sy = delayAsFloat(df);
|
||||
t50_sr = ra_solve_for_t(1.0/(r*ceff),s,0.5);
|
||||
|
||||
|
|
@ -1476,7 +1477,7 @@ ArnoldiDelayCalc::ar1_ceff_delay(delay_work *D,
|
|||
units_->capacitanceUnit()->asString(ceff));
|
||||
|
||||
tab->table->gateDelay(tab->cell, tab->pvt, tab->in_slew, ceff,
|
||||
tab->relcap, df, sf);
|
||||
tab->relcap, pocv_enabled_, df, sf);
|
||||
t50_sy = delayAsFloat(df);
|
||||
t50_sr = ra_solve_for_t(1.0/(r*ceff),s,0.5);
|
||||
for (j=0;j<mod->n;j++) {
|
||||
|
|
|
|||
|
|
@ -77,7 +77,8 @@ gateModelRd(const LibertyCell *cell,
|
|||
double c2,
|
||||
double c1,
|
||||
float related_out_cap,
|
||||
const Pvt *pvt);
|
||||
const Pvt *pvt,
|
||||
bool pocv_enabled);
|
||||
static bool
|
||||
evalDmpEqnsState(void *state);
|
||||
static void
|
||||
|
|
@ -378,6 +379,7 @@ DmpAlg::gateCapDelaySlew(double ceff,
|
|||
static_cast<float>(in_slew_),
|
||||
static_cast<float>(ceff),
|
||||
related_out_cap_,
|
||||
pocv_enabled_,
|
||||
model_delay, model_slew);
|
||||
delay = delayAsFloat(model_delay);
|
||||
slew = delayAsFloat(model_slew);
|
||||
|
|
@ -1640,7 +1642,7 @@ DmpCeffDelayCalc::setCeffAlgorithm(const LibertyLibrary *drvr_library,
|
|||
{
|
||||
double rd = gate_model
|
||||
? gateModelRd(drvr_cell, gate_model, in_slew, c2, c1,
|
||||
related_out_cap, pvt)
|
||||
related_out_cap, pvt, pocv_enabled_)
|
||||
: 0.0;
|
||||
// Zero Rd means the table is constant and thus independent of load cap.
|
||||
if (rd < 1e-2
|
||||
|
|
@ -1726,7 +1728,8 @@ DmpCeffDelayCalc::reportGateDelay(const LibertyCell *drvr_cell,
|
|||
if (model) {
|
||||
float in_slew1 = delayAsFloat(in_slew);
|
||||
model->reportGateDelay(drvr_cell, pvt, in_slew1, c_eff,
|
||||
related_out_cap, digits, result);
|
||||
related_out_cap, pocv_enabled_,
|
||||
digits, result);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -1737,15 +1740,18 @@ gateModelRd(const LibertyCell *cell,
|
|||
double c2,
|
||||
double c1,
|
||||
float related_out_cap,
|
||||
const Pvt *pvt)
|
||||
const Pvt *pvt,
|
||||
bool pocv_enabled)
|
||||
{
|
||||
float cap1 = static_cast<float>((c1 + c2) * .75);
|
||||
float cap2 = cap1 * 1.1F;
|
||||
float in_slew1 = static_cast<float>(in_slew);
|
||||
ArcDelay d1, d2;
|
||||
Slew s1, s2;
|
||||
gate_model->gateDelay(cell, pvt, in_slew1, cap1, related_out_cap, d1, s1);
|
||||
gate_model->gateDelay(cell, pvt, in_slew1, cap2, related_out_cap, d2, s2);
|
||||
gate_model->gateDelay(cell, pvt, in_slew1, cap1, related_out_cap, pocv_enabled,
|
||||
d1, s1);
|
||||
gate_model->gateDelay(cell, pvt, in_slew1, cap2, related_out_cap, pocv_enabled,
|
||||
d2, s2);
|
||||
return abs(delayAsFloat(d1) - delayAsFloat(d2)) / (cap2 - cap1);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -846,9 +846,9 @@ GraphDelayCalc1::findInputArcDelay(LibertyCell *drvr_cell,
|
|||
ArcDelay load_delay = gate_delay - intrinsic_delay;
|
||||
debugPrint3(debug_, "delay_calc", 3,
|
||||
" gate delay = %s intrinsic = %s slew = %s\n",
|
||||
delayAsString(gate_delay, units_),
|
||||
delayAsString(intrinsic_delay, units_),
|
||||
delayAsString(gate_slew, units_));
|
||||
delayAsString(gate_delay, this),
|
||||
delayAsString(intrinsic_delay, this),
|
||||
delayAsString(gate_slew, this));
|
||||
graph_->setSlew(drvr_vertex, drvr_tr, ap_index, gate_slew);
|
||||
annotateLoadDelays(drvr_vertex, drvr_tr, load_delay, false, dcalc_ap,
|
||||
arc_delay_calc_);
|
||||
|
|
@ -1274,8 +1274,8 @@ GraphDelayCalc1::findArcDelay(LibertyCell *drvr_cell,
|
|||
}
|
||||
debugPrint2(debug_, "delay_calc", 3,
|
||||
" gate delay = %s slew = %s\n",
|
||||
delayAsString(gate_delay, units_),
|
||||
delayAsString(gate_slew, units_));
|
||||
delayAsString(gate_delay, this),
|
||||
delayAsString(gate_slew, this));
|
||||
// Merge slews.
|
||||
const Slew &drvr_slew = graph_->slew(drvr_vertex, drvr_tr, ap_index);
|
||||
if (delayFuzzyGreater(gate_slew, drvr_slew, dcalc_ap->slewMinMax())
|
||||
|
|
@ -1477,8 +1477,8 @@ GraphDelayCalc1::annotateLoadDelays(Vertex *drvr_vertex,
|
|||
debugPrint3(debug_, "delay_calc", 3,
|
||||
" %s load delay = %s slew = %s\n",
|
||||
load_vertex->name(sdc_network_),
|
||||
delayAsString(wire_delay, units_),
|
||||
delayAsString(load_slew, units_));
|
||||
delayAsString(wire_delay, this),
|
||||
delayAsString(load_slew, this));
|
||||
if (!load_vertex->slewAnnotated(drvr_tr, ap_index)) {
|
||||
if (drvr_vertex->slewAnnotated(drvr_tr, ap_index)) {
|
||||
// Copy the driver slew to the load if it is annotated.
|
||||
|
|
@ -1593,8 +1593,8 @@ GraphDelayCalc1::findCheckEdgeDelays(Edge *edge,
|
|||
arc_set->role()->asString());
|
||||
debugPrint2(debug_, "delay_calc", 3,
|
||||
" from_slew = %s to_slew = %s\n",
|
||||
delayAsString(from_slew, units_),
|
||||
delayAsString(to_slew, units_));
|
||||
delayAsString(from_slew, this),
|
||||
delayAsString(to_slew, this));
|
||||
float related_out_cap = 0.0;
|
||||
if (related_out_pin) {
|
||||
Parasitic *related_out_parasitic;
|
||||
|
|
@ -1616,7 +1616,7 @@ GraphDelayCalc1::findCheckEdgeDelays(Edge *edge,
|
|||
check_delay);
|
||||
debugPrint1(debug_, "delay_calc", 3,
|
||||
" check_delay = %s\n",
|
||||
delayAsString(check_delay, units_));
|
||||
delayAsString(check_delay, this));
|
||||
graph_->setArcDelay(edge, arc, ap_index, check_delay);
|
||||
delay_changed = true;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -151,7 +151,7 @@ LumpedCapDelayCalc::gateDelay(const LibertyCell *drvr_cell,
|
|||
GateTimingModel *model = gateModel(arc, dcalc_ap);
|
||||
debugPrint3(debug_, "delay_calc", 3,
|
||||
" in_slew = %s load_cap = %s related_load_cap = %s lumped\n",
|
||||
delayAsString(in_slew, units()),
|
||||
delayAsString(in_slew, this),
|
||||
units()->capacitanceUnit()->asString(load_cap),
|
||||
units()->capacitanceUnit()->asString(related_out_cap));
|
||||
if (model) {
|
||||
|
|
@ -159,7 +159,7 @@ LumpedCapDelayCalc::gateDelay(const LibertyCell *drvr_cell,
|
|||
Slew drvr_slew1;
|
||||
float in_slew1 = delayAsFloat(in_slew);
|
||||
model->gateDelay(drvr_cell, pvt, in_slew1, load_cap, related_out_cap,
|
||||
gate_delay1, drvr_slew1);
|
||||
pocv_enabled_, gate_delay1, drvr_slew1);
|
||||
gate_delay = gate_delay1;
|
||||
drvr_slew = drvr_slew1;
|
||||
drvr_slew_ = drvr_slew1;
|
||||
|
|
@ -245,7 +245,7 @@ LumpedCapDelayCalc::reportGateDelay(const LibertyCell *drvr_cell,
|
|||
if (model) {
|
||||
float in_slew1 = delayAsFloat(in_slew);
|
||||
model->reportGateDelay(drvr_cell, pvt, in_slew1, load_cap,
|
||||
related_out_cap, digits, result);
|
||||
related_out_cap, false, digits, result);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -264,7 +264,8 @@ LumpedCapDelayCalc::checkDelay(const LibertyCell *cell,
|
|||
if (model) {
|
||||
float from_slew1 = delayAsFloat(from_slew);
|
||||
float to_slew1 = delayAsFloat(to_slew);
|
||||
model->checkDelay(cell, pvt, from_slew1, to_slew1, related_out_cap, margin);
|
||||
model->checkDelay(cell, pvt, from_slew1, to_slew1, related_out_cap,
|
||||
false, margin);
|
||||
}
|
||||
else
|
||||
margin = delay_zero;
|
||||
|
|
@ -287,7 +288,7 @@ LumpedCapDelayCalc::reportCheckDelay(const LibertyCell *cell,
|
|||
float from_slew1 = delayAsFloat(from_slew);
|
||||
float to_slew1 = delayAsFloat(to_slew);
|
||||
model->reportCheckDelay(cell, pvt, from_slew1, from_slew_annotation, to_slew1,
|
||||
related_out_cap, digits, result);
|
||||
related_out_cap, false, digits, result);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -22,18 +22,11 @@
|
|||
|
||||
namespace sta {
|
||||
|
||||
const char *
|
||||
delayAsString(const Delay &delay,
|
||||
const Units *units)
|
||||
{
|
||||
return delayAsString(delay, units, units->timeUnit()->digits());
|
||||
}
|
||||
|
||||
const char *
|
||||
delayAsString(const Delay &delay,
|
||||
const StaState *sta)
|
||||
{
|
||||
return delayAsString(delay, sta->units(), sta->units()->timeUnit()->digits());
|
||||
return delayAsString(delay, sta, sta->units()->timeUnit()->digits());
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
|
|
|||
|
|
@ -63,19 +63,16 @@ float
|
|||
delaySigma2(const Delay &delay,
|
||||
const EarlyLate *early_late);
|
||||
const char *
|
||||
delayAsString(const Delay &delay,
|
||||
const Units *units);
|
||||
const char *
|
||||
delayAsString(const Delay &delay,
|
||||
const StaState *sta);
|
||||
const char *
|
||||
delayAsString(const Delay &delay,
|
||||
const Units *units,
|
||||
const StaState *sta,
|
||||
int digits);
|
||||
const char *
|
||||
delayAsString(const Delay &delay,
|
||||
const EarlyLate *early_late,
|
||||
const Units *units,
|
||||
const StaState *sta,
|
||||
int digits);
|
||||
const Delay &
|
||||
delayInitValue(const MinMax *min_max);
|
||||
|
|
|
|||
|
|
@ -148,10 +148,20 @@ delayRatio(const Delay &delay1,
|
|||
|
||||
const char *
|
||||
delayAsString(const Delay &delay,
|
||||
const Units *units,
|
||||
const StaState *sta,
|
||||
int digits)
|
||||
{
|
||||
return units->timeUnit()->asString(delay, digits);
|
||||
return sta->units()->timeUnit()->asString(delay, digits);
|
||||
}
|
||||
|
||||
const char *
|
||||
delayAsString(const Delay &delay,
|
||||
const EarlyLate *,
|
||||
const StaState *sta,
|
||||
int digits)
|
||||
{
|
||||
const Unit *unit = sta->units()->timeUnit();
|
||||
return unit->asString(delay, digits);
|
||||
}
|
||||
|
||||
float
|
||||
|
|
@ -161,16 +171,6 @@ delayAsFloat(const Delay &delay,
|
|||
return delay;
|
||||
}
|
||||
|
||||
const char *
|
||||
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 *)
|
||||
|
|
|
|||
|
|
@ -167,7 +167,15 @@ Delay::operator-() const
|
|||
void
|
||||
Delay::operator-=(float delay)
|
||||
{
|
||||
mean_ -= - delay;
|
||||
mean_ -= delay;
|
||||
}
|
||||
|
||||
void
|
||||
Delay::operator-=(const Delay &delay)
|
||||
{
|
||||
mean_ -= delay.mean_;
|
||||
sigma2_[early_index] -= delay.sigma2_[early_index];
|
||||
sigma2_[late_index] -= delay.sigma2_[late_index];
|
||||
}
|
||||
|
||||
bool
|
||||
|
|
@ -409,31 +417,35 @@ delaySigma2(const Delay &delay,
|
|||
|
||||
const char *
|
||||
delayAsString(const Delay &delay,
|
||||
const Units *units,
|
||||
const StaState *sta,
|
||||
int digits)
|
||||
{
|
||||
const Unit *unit = units->timeUnit();
|
||||
float sigma_early = delay.sigma(EarlyLate::early());
|
||||
float sigma_late = delay.sigma(EarlyLate::late());
|
||||
if (fuzzyEqual(sigma_early, sigma_late))
|
||||
return stringPrintTmp("%s|%s",
|
||||
unit->asString(delay.mean(), digits),
|
||||
unit->asString(sigma_early, digits));
|
||||
const Unit *unit = sta->units()->timeUnit();
|
||||
if (sta->pocvEnabled()) {
|
||||
float sigma_early = delay.sigma(EarlyLate::early());
|
||||
float sigma_late = delay.sigma(EarlyLate::late());
|
||||
if (fuzzyEqual(sigma_early, sigma_late))
|
||||
return stringPrintTmp("%s|%s",
|
||||
unit->asString(delay.mean(), digits),
|
||||
unit->asString(sigma_early, digits));
|
||||
else
|
||||
return stringPrintTmp("%s|%s:%s",
|
||||
unit->asString(delay.mean(), digits),
|
||||
unit->asString(sigma_early, digits),
|
||||
unit->asString(sigma_late, digits));
|
||||
}
|
||||
else
|
||||
return stringPrintTmp("%s|%s:%s",
|
||||
unit->asString(delay.mean(), digits),
|
||||
unit->asString(sigma_early, digits),
|
||||
unit->asString(sigma_late, digits));
|
||||
return unit->asString(delay.mean(), digits);
|
||||
}
|
||||
|
||||
const char *
|
||||
delayAsString(const Delay &delay,
|
||||
const EarlyLate *early_late,
|
||||
const Units *units,
|
||||
const StaState *sta,
|
||||
int digits)
|
||||
{
|
||||
float mean_sigma = delayAsFloat(delay, early_late);
|
||||
return units->timeUnit()->asString(mean_sigma, digits);
|
||||
return sta->units()->timeUnit()->asString(mean_sigma, digits);
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
|
|
|||
|
|
@ -50,6 +50,7 @@ public:
|
|||
Delay operator-(float delay) const;
|
||||
Delay operator-() const;
|
||||
void operator-=(float delay);
|
||||
void operator-=(const Delay &delay);
|
||||
bool operator==(const Delay &delay) const;
|
||||
bool operator>(const Delay &delay) const;
|
||||
bool operator>=(const Delay &delay) const;
|
||||
|
|
|
|||
|
|
@ -34,6 +34,7 @@ GateLinearModel::gateDelay(const LibertyCell *,
|
|||
float,
|
||||
float load_cap,
|
||||
float,
|
||||
bool,
|
||||
// return values
|
||||
ArcDelay &gate_delay,
|
||||
Slew &drvr_slew) const
|
||||
|
|
@ -48,6 +49,7 @@ GateLinearModel::reportGateDelay(const LibertyCell *cell,
|
|||
float,
|
||||
float load_cap,
|
||||
float,
|
||||
bool,
|
||||
int digits,
|
||||
string *result) const
|
||||
{
|
||||
|
|
@ -90,6 +92,7 @@ CheckLinearModel::checkDelay(const LibertyCell *,
|
|||
float,
|
||||
float,
|
||||
float,
|
||||
bool,
|
||||
ArcDelay &margin) const
|
||||
{
|
||||
margin = intrinsic_;
|
||||
|
|
@ -102,6 +105,7 @@ CheckLinearModel::reportCheckDelay(const LibertyCell *cell,
|
|||
const char *,
|
||||
float,
|
||||
float,
|
||||
bool,
|
||||
int digits,
|
||||
string *result) const
|
||||
{
|
||||
|
|
|
|||
|
|
@ -31,14 +31,18 @@ public:
|
|||
const Pvt *pvt,
|
||||
float load_cap, float in_slew,
|
||||
float related_out_cap,
|
||||
bool pocv_enabled,
|
||||
// return values
|
||||
ArcDelay &gate_delay,
|
||||
Slew &drvr_slew) const;
|
||||
virtual void reportGateDelay(const LibertyCell *cell,
|
||||
const Pvt *pvt,
|
||||
float load_cap, float in_slew,
|
||||
float load_cap,
|
||||
float in_slew,
|
||||
float related_out_cap,
|
||||
int digits, string *result) const;
|
||||
bool pocv_enabled,
|
||||
int digits,
|
||||
string *result) const;
|
||||
virtual float driveResistance(const LibertyCell *cell,
|
||||
const Pvt *pvt) const;
|
||||
|
||||
|
|
@ -59,8 +63,10 @@ public:
|
|||
// Timing check margin delay calculation.
|
||||
virtual void checkDelay(const LibertyCell *cell,
|
||||
const Pvt *pvt,
|
||||
float from_slew, float to_slew,
|
||||
float from_slew,
|
||||
float to_slew,
|
||||
float related_out_cap,
|
||||
bool pocv_enabled,
|
||||
ArcDelay &margin) const;
|
||||
virtual void reportCheckDelay(const LibertyCell *cell,
|
||||
const Pvt *pvt,
|
||||
|
|
@ -68,7 +74,9 @@ public:
|
|||
const char *from_slew_annotation,
|
||||
float to_slew,
|
||||
float related_out_cap,
|
||||
int digits, string *result) const;
|
||||
bool pocv_enabled,
|
||||
int digits,
|
||||
string *result) const;
|
||||
|
||||
protected:
|
||||
virtual void setIsScaled(bool is_scaled);
|
||||
|
|
|
|||
|
|
@ -76,6 +76,7 @@ GateTableModel::gateDelay(const LibertyCell *cell,
|
|||
float in_slew,
|
||||
float load_cap,
|
||||
float related_out_cap,
|
||||
bool pocv_enabled,
|
||||
// return values
|
||||
ArcDelay &gate_delay,
|
||||
Slew &drvr_slew) const
|
||||
|
|
@ -85,11 +86,11 @@ GateTableModel::gateDelay(const LibertyCell *cell,
|
|||
load_cap, related_out_cap);
|
||||
float sigma_early = 0.0;
|
||||
float sigma_late = 0.0;
|
||||
if (delay_sigma_models_[EarlyLate::earlyIndex()])
|
||||
if (pocv_enabled && delay_sigma_models_[EarlyLate::earlyIndex()])
|
||||
sigma_early = findValue(library, cell, pvt,
|
||||
delay_sigma_models_[EarlyLate::earlyIndex()],
|
||||
in_slew, load_cap, related_out_cap);
|
||||
if (delay_sigma_models_[EarlyLate::lateIndex()])
|
||||
if (pocv_enabled && delay_sigma_models_[EarlyLate::lateIndex()])
|
||||
sigma_late = findValue(library, cell, pvt,
|
||||
delay_sigma_models_[EarlyLate::earlyIndex()],
|
||||
in_slew, load_cap, related_out_cap);
|
||||
|
|
@ -97,16 +98,14 @@ GateTableModel::gateDelay(const LibertyCell *cell,
|
|||
|
||||
float slew = findValue(library, cell, pvt, slew_model_, in_slew,
|
||||
load_cap, related_out_cap);
|
||||
if (slew_sigma_models_[EarlyLate::earlyIndex()])
|
||||
if (pocv_enabled && slew_sigma_models_[EarlyLate::earlyIndex()])
|
||||
sigma_early = findValue(library, cell, pvt,
|
||||
slew_sigma_models_[EarlyLate::earlyIndex()],
|
||||
in_slew, load_cap, related_out_cap);
|
||||
if (slew_sigma_models_[EarlyLate::lateIndex()])
|
||||
if (pocv_enabled && slew_sigma_models_[EarlyLate::lateIndex()])
|
||||
sigma_late = findValue(library, cell, pvt,
|
||||
slew_sigma_models_[EarlyLate::earlyIndex()],
|
||||
in_slew, load_cap, related_out_cap);
|
||||
sigma_early = 0.0;
|
||||
sigma_late = 0.0;
|
||||
// Clip negative slews to zero.
|
||||
if (slew < 0.0)
|
||||
slew = 0.0;
|
||||
|
|
@ -119,6 +118,7 @@ GateTableModel::reportGateDelay(const LibertyCell *cell,
|
|||
float in_slew,
|
||||
float load_cap,
|
||||
float related_out_cap,
|
||||
bool pocv_enabled,
|
||||
int digits,
|
||||
string *result) const
|
||||
{
|
||||
|
|
@ -126,22 +126,22 @@ GateTableModel::reportGateDelay(const LibertyCell *cell,
|
|||
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()])
|
||||
if (pocv_enabled && delay_sigma_models_[EarlyLate::earlyIndex()])
|
||||
reportTableLookup("Delay sigma(early)", library, cell, pvt,
|
||||
delay_sigma_models_[EarlyLate::earlyIndex()],
|
||||
in_slew, load_cap, related_out_cap, digits, result);
|
||||
if (delay_sigma_models_[EarlyLate::lateIndex()])
|
||||
if (pocv_enabled && delay_sigma_models_[EarlyLate::lateIndex()])
|
||||
reportTableLookup("Delay sigma(late)", library, cell, pvt,
|
||||
delay_sigma_models_[EarlyLate::lateIndex()],
|
||||
in_slew, load_cap, related_out_cap, digits, result);
|
||||
*result += '\n';
|
||||
reportTableLookup("Slew", library, cell, pvt, slew_model_, in_slew,
|
||||
load_cap, related_out_cap, digits, result);
|
||||
if (slew_sigma_models_[EarlyLate::earlyIndex()])
|
||||
if (pocv_enabled && slew_sigma_models_[EarlyLate::earlyIndex()])
|
||||
reportTableLookup("Slew sigma(early)", library, cell, pvt,
|
||||
slew_sigma_models_[EarlyLate::earlyIndex()],
|
||||
in_slew, load_cap, related_out_cap, digits, result);
|
||||
if (slew_sigma_models_[EarlyLate::lateIndex()])
|
||||
if (pocv_enabled && slew_sigma_models_[EarlyLate::lateIndex()])
|
||||
reportTableLookup("Slew sigma(late)", library, cell, pvt,
|
||||
slew_sigma_models_[EarlyLate::lateIndex()],
|
||||
in_slew, load_cap, related_out_cap, digits, result);
|
||||
|
|
@ -355,21 +355,50 @@ CheckTableModel::checkDelay(const LibertyCell *cell,
|
|||
float from_slew,
|
||||
float to_slew,
|
||||
float related_out_cap,
|
||||
bool pocv_enabled,
|
||||
// Return values.
|
||||
ArcDelay &margin) const
|
||||
{
|
||||
if (model_) {
|
||||
float axis_value1, axis_value2, axis_value3;
|
||||
findAxisValues(from_slew, to_slew, related_out_cap,
|
||||
axis_value1, axis_value2, axis_value3);
|
||||
const LibertyLibrary *library = cell->libertyLibrary();
|
||||
margin = model_->findValue(library, cell, pvt,
|
||||
axis_value1, axis_value2, axis_value3);
|
||||
float mean = findValue(library, cell, pvt, model_,
|
||||
from_slew, to_slew, related_out_cap);
|
||||
float sigma_early = 0.0;
|
||||
float sigma_late = 0.0;
|
||||
if (pocv_enabled && sigma_models_[EarlyLate::earlyIndex()])
|
||||
sigma_early = findValue(library, cell, pvt,
|
||||
sigma_models_[EarlyLate::earlyIndex()],
|
||||
from_slew, to_slew, related_out_cap);
|
||||
if (pocv_enabled && sigma_models_[EarlyLate::lateIndex()])
|
||||
sigma_late = findValue(library, cell, pvt,
|
||||
sigma_models_[EarlyLate::earlyIndex()],
|
||||
from_slew, to_slew, related_out_cap);
|
||||
margin = makeDelay(mean, sigma_early, sigma_late);
|
||||
}
|
||||
else
|
||||
margin = 0.0;
|
||||
}
|
||||
|
||||
float
|
||||
CheckTableModel::findValue(const LibertyLibrary *library,
|
||||
const LibertyCell *cell,
|
||||
const Pvt *pvt,
|
||||
const TableModel *model,
|
||||
float from_slew,
|
||||
float to_slew,
|
||||
float related_out_cap) const
|
||||
{
|
||||
if (model) {
|
||||
float axis_value1, axis_value2, axis_value3;
|
||||
findAxisValues(from_slew, to_slew, related_out_cap,
|
||||
axis_value1, axis_value2, axis_value3);
|
||||
return model->findValue(library, cell, pvt,
|
||||
axis_value1, axis_value2, axis_value3);
|
||||
}
|
||||
else
|
||||
return 0.0;
|
||||
}
|
||||
|
||||
void
|
||||
CheckTableModel::reportCheckDelay(const LibertyCell *cell,
|
||||
const Pvt *pvt,
|
||||
|
|
@ -377,16 +406,45 @@ CheckTableModel::reportCheckDelay(const LibertyCell *cell,
|
|||
const char *from_slew_annotation,
|
||||
float to_slew,
|
||||
float related_out_cap,
|
||||
bool pocv_enabled,
|
||||
int digits,
|
||||
string *result) const
|
||||
{
|
||||
if (model_) {
|
||||
const LibertyLibrary *library = cell->libertyLibrary();
|
||||
reportTableDelay("Check", library, cell, pvt, model_,
|
||||
from_slew, from_slew_annotation, to_slew,
|
||||
related_out_cap, digits, result);
|
||||
if (pocv_enabled && sigma_models_[EarlyLate::earlyIndex()])
|
||||
reportTableDelay("Check sigma early", library, cell, pvt,
|
||||
sigma_models_[EarlyLate::earlyIndex()],
|
||||
from_slew, from_slew_annotation, to_slew,
|
||||
related_out_cap, digits, result);
|
||||
if (pocv_enabled && sigma_models_[EarlyLate::lateIndex()])
|
||||
reportTableDelay("Check sigma late", library, cell, pvt,
|
||||
sigma_models_[EarlyLate::lateIndex()],
|
||||
from_slew, from_slew_annotation, to_slew,
|
||||
related_out_cap, digits, result);
|
||||
}
|
||||
|
||||
void
|
||||
CheckTableModel::reportTableDelay(const char *result_name,
|
||||
const LibertyLibrary *library,
|
||||
const LibertyCell *cell,
|
||||
const Pvt *pvt,
|
||||
const TableModel *model,
|
||||
float from_slew,
|
||||
const char *from_slew_annotation,
|
||||
float to_slew,
|
||||
float related_out_cap,
|
||||
int digits,
|
||||
string *result) const
|
||||
{
|
||||
if (model) {
|
||||
float axis_value1, axis_value2, axis_value3;
|
||||
findAxisValues(from_slew, to_slew, related_out_cap,
|
||||
axis_value1, axis_value2, axis_value3);
|
||||
const LibertyLibrary *library = cell->libertyLibrary();
|
||||
reportPvt(library, pvt, digits, result);
|
||||
model_->reportValue("Check", library, cell, pvt,
|
||||
model_->reportValue(result_name, library, cell, pvt,
|
||||
axis_value1, from_slew_annotation, axis_value2,
|
||||
axis_value3, digits, result);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -55,6 +55,7 @@ public:
|
|||
float in_slew,
|
||||
float load_cap,
|
||||
float related_out_cap,
|
||||
bool pocv_enabled,
|
||||
// Return values.
|
||||
ArcDelay &gate_delay,
|
||||
Slew &drvr_slew) const;
|
||||
|
|
@ -63,6 +64,7 @@ public:
|
|||
float in_slew,
|
||||
float load_cap,
|
||||
float related_out_cap,
|
||||
bool pocv_enabled,
|
||||
int digits,
|
||||
string *result) const;
|
||||
virtual float driveResistance(const LibertyCell *cell,
|
||||
|
|
@ -131,6 +133,7 @@ public:
|
|||
float from_slew,
|
||||
float to_slew,
|
||||
float related_out_cap,
|
||||
bool pocv_enabled,
|
||||
// Return values.
|
||||
ArcDelay &margin) const;
|
||||
virtual void reportCheckDelay(const LibertyCell *cell,
|
||||
|
|
@ -139,6 +142,7 @@ public:
|
|||
const char *from_slew_annotation,
|
||||
float to_slew,
|
||||
float related_out_cap,
|
||||
bool pocv_enabled,
|
||||
int digits,
|
||||
string *result) const;
|
||||
|
||||
|
|
@ -148,6 +152,13 @@ public:
|
|||
|
||||
protected:
|
||||
virtual void setIsScaled(bool is_scaled);
|
||||
float findValue(const LibertyLibrary *library,
|
||||
const LibertyCell *cell,
|
||||
const Pvt *pvt,
|
||||
const TableModel *model,
|
||||
float from_slew,
|
||||
float to_slew,
|
||||
float related_out_cap) const;
|
||||
void findAxisValues(float from_slew,
|
||||
float to_slew,
|
||||
float related_out_cap,
|
||||
|
|
@ -159,9 +170,21 @@ protected:
|
|||
float load_cap,
|
||||
float in_slew,
|
||||
float related_out_cap) const;
|
||||
void reportTableDelay(const char *result_name,
|
||||
const LibertyLibrary *library,
|
||||
const LibertyCell *cell,
|
||||
const Pvt *pvt,
|
||||
const TableModel *model,
|
||||
float from_slew,
|
||||
const char *from_slew_annotation,
|
||||
float to_slew,
|
||||
float related_out_cap,
|
||||
int digits,
|
||||
string *result) const;
|
||||
static bool checkAxis(TableAxis *axis);
|
||||
|
||||
TableModel *model_;
|
||||
TableModel *sigma_models_[EarlyLate::index_count];
|
||||
|
||||
private:
|
||||
DISALLOW_COPY_AND_ASSIGN(CheckTableModel);
|
||||
|
|
|
|||
|
|
@ -47,6 +47,7 @@ public:
|
|||
float in_slew,
|
||||
float load_cap,
|
||||
float related_out_cap,
|
||||
bool pocv_enabled,
|
||||
// Return values.
|
||||
ArcDelay &gate_delay,
|
||||
Slew &drvr_slew) const = 0;
|
||||
|
|
@ -55,6 +56,7 @@ public:
|
|||
float in_slew,
|
||||
float load_cap,
|
||||
float related_out_cap,
|
||||
bool pocv_enabled,
|
||||
int digits,
|
||||
string *result) const = 0;
|
||||
virtual float driveResistance(const LibertyCell *cell,
|
||||
|
|
@ -71,6 +73,7 @@ public:
|
|||
float from_slew,
|
||||
float to_slew,
|
||||
float related_out_cap,
|
||||
bool pocv_enabled,
|
||||
// Return values.
|
||||
ArcDelay &margin) const = 0;
|
||||
virtual void reportCheckDelay(const LibertyCell *cell,
|
||||
|
|
@ -79,6 +82,7 @@ public:
|
|||
const char *from_slew_annotation,
|
||||
float to_slew,
|
||||
float related_out_cap,
|
||||
bool pocv_enabled,
|
||||
int digits,
|
||||
string *result) const = 0;
|
||||
};
|
||||
|
|
|
|||
|
|
@ -1400,6 +1400,7 @@ protected:
|
|||
WireloadSelection *wireload_selection_[MinMax::index_count];
|
||||
bool crpr_enabled_;
|
||||
CrprMode crpr_mode_;
|
||||
bool pocv_enabled_;
|
||||
bool propagate_gated_clock_enable_;
|
||||
bool preset_clr_arcs_enabled_;
|
||||
bool cond_default_arcs_enabled_;
|
||||
|
|
|
|||
|
|
@ -155,7 +155,7 @@ ClkSkews::reportClkSkew(ClockSet *clks,
|
|||
tgt_path->transition(this)->asString());
|
||||
report_->print("%7s %7s %7s\n",
|
||||
time_unit->asString(clk_skew->tgtLatency(this), digits),
|
||||
delayAsString(-clk_skew->crpr(this), units_, digits),
|
||||
time_unit->asString(delayAsFloat(-clk_skew->crpr(this)), digits),
|
||||
time_unit->asString(clk_skew->skew(), digits));
|
||||
}
|
||||
else
|
||||
|
|
|
|||
|
|
@ -283,40 +283,36 @@ CheckCrpr::genClkSrcPaths(const PathVertex *path,
|
|||
}
|
||||
}
|
||||
|
||||
#if SSTA
|
||||
Crpr
|
||||
CheckCrpr::findCrpr1(const PathVertex *src_clk_path,
|
||||
const PathVertex *tgt_clk_path)
|
||||
{
|
||||
// Remove variation on the common path.
|
||||
// Note that the crpr sigma is negative to offset the
|
||||
// sigma of the common clock path.
|
||||
const EarlyLate *src_el = src_clk_path->minMax(this);
|
||||
const EarlyLate *tgt_el = tgt_clk_path->minMax(this);
|
||||
float crpr_sigma2 = delaySigma2(src_clk_path->arrival(this), src_el)
|
||||
+ delaySigma2(src_clk_path->arrival(this), tgt_el);
|
||||
return makeDelay2(0.0, -crpr_sigma2, -crpr_sigma2);
|
||||
if (pocv_enabled_) {
|
||||
// Remove variation on the common path.
|
||||
// Note that the crpr sigma is negative to offset the
|
||||
// sigma of the common clock path.
|
||||
const EarlyLate *src_el = src_clk_path->minMax(this);
|
||||
const EarlyLate *tgt_el = tgt_clk_path->minMax(this);
|
||||
float crpr_sigma2 = delaySigma2(src_clk_path->arrival(this), src_el)
|
||||
+ delaySigma2(src_clk_path->arrival(this), tgt_el);
|
||||
return makeDelay2(0.0, -crpr_sigma2, -crpr_sigma2);
|
||||
}
|
||||
else {
|
||||
// The source and target edges are different so the crpr
|
||||
// is the min of the source and target max-min delay.
|
||||
float src_delta = crprArrivalDiff(src_clk_path);
|
||||
float tgt_delta = crprArrivalDiff(tgt_clk_path);
|
||||
debugPrint1(debug_, "crpr", 2, " src delta %s\n",
|
||||
delayAsString(src_delta, this));
|
||||
debugPrint1(debug_, "crpr", 2, " tgt delta %s\n",
|
||||
delayAsString(tgt_delta, this));
|
||||
float common_delay = min(src_delta, tgt_delta);
|
||||
debugPrint2(debug_, "crpr", 2, " %s delta %s\n",
|
||||
network_->pathName(src_clk_path->pin(this)),
|
||||
delayAsString(common_delay, this));
|
||||
return common_delay;
|
||||
}
|
||||
}
|
||||
#else
|
||||
Crpr
|
||||
CheckCrpr::findCrpr1(const PathVertex *src_clk_path,
|
||||
const PathVertex *tgt_clk_path)
|
||||
{
|
||||
// The source and target edges are different so the crpr
|
||||
// is the min of the source and target max-min delay.
|
||||
float src_delta = crprArrivalDiff(src_clk_path);
|
||||
float tgt_delta = crprArrivalDiff(tgt_clk_path);
|
||||
debugPrint1(debug_, "crpr", 2, " src delta %s\n",
|
||||
delayAsString(src_delta, units_));
|
||||
debugPrint1(debug_, "crpr", 2, " tgt delta %s\n",
|
||||
delayAsString(tgt_delta, units_));
|
||||
float common_delay = min(src_delta, tgt_delta);
|
||||
debugPrint2(debug_, "crpr", 2, " %s delta %s\n",
|
||||
network_->pathName(src_clk_path->pin(this)),
|
||||
delayAsString(common_delay, units_));
|
||||
return common_delay;
|
||||
}
|
||||
#endif
|
||||
|
||||
Crpr
|
||||
CheckCrpr::outputDelayCrpr(const Path *src_clk_path,
|
||||
|
|
|
|||
|
|
@ -990,7 +990,7 @@ Genclks::recordSrcPaths(Clock *gclk)
|
|||
network_->pathName(gclk_pin),
|
||||
early_late->asString(),
|
||||
tr->asString(),
|
||||
delayAsString(path->arrival(this), units_));
|
||||
delayAsString(path->arrival(this), this));
|
||||
src_path.init(path, this);
|
||||
found_src_paths = true;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -96,8 +96,8 @@ Latches::latchRequired(const Path *data_path,
|
|||
+ open_crpr;
|
||||
debugPrint3(debug_, "latch", 1, "latch data %s %s enable %s\n",
|
||||
network_->pathName(data_path->pin(this)),
|
||||
delayAsString(data_arrival, units_),
|
||||
delayAsString(enable_arrival, units_));
|
||||
delayAsString(data_arrival, this),
|
||||
delayAsString(enable_arrival, this));
|
||||
if (data_arrival <= enable_arrival) {
|
||||
// Data arrives before latch opens.
|
||||
required = enable_arrival;
|
||||
|
|
|
|||
|
|
@ -125,7 +125,7 @@ PathEnum::insert(PathEnd *path_end)
|
|||
path_end->path()->name(this),
|
||||
cmp_slack_ ? "slack" : "delay",
|
||||
delayAsString(cmp_slack_ ? path_end->slack(this) :
|
||||
path_end->dataArrivalTime(this), units_));
|
||||
path_end->dataArrivalTime(this), this));
|
||||
Diversion *div = new Diversion(path_end, path_end->path());
|
||||
div_queue_.push(div);
|
||||
div_count_++;
|
||||
|
|
@ -178,8 +178,8 @@ PathEnum::findNext()
|
|||
Path *path = path_end->path();
|
||||
debug_->print("path_enum: next path %s delay %s slack %s\n",
|
||||
path->name(this),
|
||||
delayAsString(path_end->dataArrivalTime(this), units_),
|
||||
delayAsString(path_end->slack(this), units_));
|
||||
delayAsString(path_end->dataArrivalTime(this), this),
|
||||
delayAsString(path_end->slack(this), this));
|
||||
reportDiversionPath(div);
|
||||
}
|
||||
|
||||
|
|
@ -213,7 +213,7 @@ PathEnum::reportDiversionPath(Diversion *div)
|
|||
while (!p.isNull()) {
|
||||
debug_->print("path_enum: %s %s%s\n",
|
||||
p.name(this),
|
||||
delayAsString(p.arrival(this), units_),
|
||||
delayAsString(p.arrival(this), this),
|
||||
Path::equal(&p, after_div, this) ? " <-diversion" : "");
|
||||
if (network_->isLatchData(p.pin(this)))
|
||||
break;
|
||||
|
|
@ -387,7 +387,6 @@ PathEnumFaninVisitor::reportDiversion(TimingArc *div_arc,
|
|||
{
|
||||
Debug *debug = sta_->debug();
|
||||
if (debug->check("path_enum", 3)) {
|
||||
Units *units = sta_->units();
|
||||
Path *path = path_end_->path();
|
||||
const PathAnalysisPt *path_ap = path->pathAnalysisPt(sta_);
|
||||
Arrival path_delay = path_enum_->cmp_slack_
|
||||
|
|
@ -401,8 +400,8 @@ PathEnumFaninVisitor::reportDiversion(TimingArc *div_arc,
|
|||
debug->print("path_enum: diversion %s %s %s -> %s\n",
|
||||
path->name(sta_),
|
||||
path_enum_->cmp_slack_ ? "slack" : "delay",
|
||||
delayAsString(path_delay, units),
|
||||
delayAsString(div_delay, units));
|
||||
delayAsString(path_delay, sta_),
|
||||
delayAsString(div_delay, sta_));
|
||||
debug->print("path_enum: from %s -> %s\n",
|
||||
div_prev.name(sta_),
|
||||
before_div_.name(sta_));
|
||||
|
|
@ -592,8 +591,8 @@ PathEnum::updatePathHeadDelays(PathEnumedSeq &paths,
|
|||
Arrival arrival = prev_arrival + arc_delay;
|
||||
debugPrint3(debug_, "path_enum", 3, "update arrival %s %s -> %s\n",
|
||||
path->name(this),
|
||||
delayAsString(path->arrival(this), units_),
|
||||
delayAsString(arrival, units_));
|
||||
delayAsString(path->arrival(this), this),
|
||||
delayAsString(arrival, this));
|
||||
path->setArrival(arrival, this);
|
||||
prev_arrival = arrival;
|
||||
if (sdc_->crprActive()) {
|
||||
|
|
|
|||
|
|
@ -1936,6 +1936,7 @@ ReportPath::reportSrcClkAndPath(const Path *path,
|
|||
string &result)
|
||||
{
|
||||
ClockEdge *clk_edge = path->clkEdge(this);
|
||||
const MinMax *min_max = path->minMax(this);
|
||||
if (clk_edge) {
|
||||
Clock *clk = clk_edge->clock();
|
||||
TransRiseFall *clk_tr = clk_edge->transition();
|
||||
|
|
@ -1943,9 +1944,11 @@ ReportPath::reportSrcClkAndPath(const Path *path,
|
|||
if (clk == sdc_->defaultArrivalClock()) {
|
||||
if (!is_path_delay) {
|
||||
float clk_end_time = clk_time + time_offset;
|
||||
const EarlyLate *early_late = min_max;
|
||||
reportLine("clock (input port clock) (rise edge)",
|
||||
clk_end_time, clk_end_time, result);
|
||||
reportLine(clkNetworkDelayIdealProp(false), 0.0, clk_end_time, result);
|
||||
clk_end_time, clk_end_time, early_late, result);
|
||||
reportLine(clkNetworkDelayIdealProp(false), 0.0, clk_end_time,
|
||||
early_late, result);
|
||||
}
|
||||
reportPath1(path, expanded, false, time_offset, result);
|
||||
}
|
||||
|
|
@ -1953,7 +1956,6 @@ ReportPath::reportSrcClkAndPath(const Path *path,
|
|||
bool path_from_input = false;
|
||||
bool input_has_ref_path = false;
|
||||
Arrival clk_delay, clk_end_time;
|
||||
const MinMax *min_max = path->minMax(this);
|
||||
PathRef clk_path;
|
||||
expanded.clkPath(clk_path);
|
||||
const TransRiseFall *clk_end_tr;
|
||||
|
|
@ -2929,16 +2931,6 @@ ReportPath::reportLine(const char *what,
|
|||
}
|
||||
|
||||
// Report increment, and total.
|
||||
void
|
||||
ReportPath::reportLine(const char *what,
|
||||
float incr,
|
||||
float total,
|
||||
string &result)
|
||||
{
|
||||
reportLine(what, field_blank_, field_blank_, field_blank_,
|
||||
incr, total, false, NULL, NULL, NULL, result);
|
||||
}
|
||||
|
||||
void
|
||||
ReportPath::reportLine(const char *what,
|
||||
Delay incr,
|
||||
|
|
@ -3143,7 +3135,7 @@ ReportPath::reportTotalDelay(Delay value,
|
|||
const EarlyLate *early_late,
|
||||
string &result)
|
||||
{
|
||||
const char *str = delayAsString(value, early_late, units_, digits_);
|
||||
const char *str = delayAsString(value, early_late, this, digits_);
|
||||
if (stringEq(str, minus_zero_))
|
||||
// Filter "-0.00" fields.
|
||||
str = plus_zero_;
|
||||
|
|
@ -3178,7 +3170,7 @@ ReportPath::reportFieldDelay(Delay value,
|
|||
if (delayAsFloat(value) == field_blank_)
|
||||
reportFieldBlank(field, result);
|
||||
else {
|
||||
const char *str = delayAsString(value, early_late, units_, digits_);
|
||||
const char *str = delayAsString(value, early_late, this, digits_);
|
||||
if (stringEq(str, minus_zero_))
|
||||
// Filter "-0.00" fields.
|
||||
str = plus_zero_;
|
||||
|
|
|
|||
|
|
@ -407,10 +407,6 @@ protected:
|
|||
const EarlyLate *early_late,
|
||||
const TransRiseFall *tr,
|
||||
string &result);
|
||||
void reportLine(const char *what,
|
||||
float incr,
|
||||
float total,
|
||||
string &result);
|
||||
void reportLine(const char *what,
|
||||
Delay incr,
|
||||
Delay total,
|
||||
|
|
|
|||
|
|
@ -2797,13 +2797,13 @@ Search::reportArrivals(Vertex *vertex) const
|
|||
arrival_index,
|
||||
tr->asString(),
|
||||
path_ap->pathMinMax()->asString(),
|
||||
delayAsString(arrivals[arrival_index], units_));
|
||||
delayAsString(arrivals[arrival_index], this));
|
||||
if (vertex->hasRequireds()) {
|
||||
int req_index;
|
||||
bool exists;
|
||||
tag_group->requiredIndex(tag, req_index, exists);
|
||||
if (exists)
|
||||
report_->print(" / %s", delayAsString(arrivals[req_index], units_));
|
||||
report_->print(" / %s", delayAsString(arrivals[req_index], this));
|
||||
}
|
||||
report_->print(" %s", tag->asString(this));
|
||||
if (tag_group->hasClkTag()) {
|
||||
|
|
@ -3417,15 +3417,15 @@ RequiredCmp::requiredsSave(Vertex *vertex,
|
|||
Required prev_req = path->required(sta);
|
||||
if (!delayFuzzyEqual(prev_req, req)) {
|
||||
debugPrint2(debug, "search", 3, "required save %s -> %s\n",
|
||||
delayAsString(prev_req, sta->units()),
|
||||
delayAsString(req, sta->units()));
|
||||
delayAsString(prev_req, sta),
|
||||
delayAsString(req, sta));
|
||||
path->setRequired(req, sta);
|
||||
requireds_changed = true;
|
||||
}
|
||||
}
|
||||
else {
|
||||
debugPrint1(debug, "search", 3, "required save MIA -> %s\n",
|
||||
delayAsString(req, sta->units()));
|
||||
delayAsString(req, sta));
|
||||
path->setRequired(req, sta);
|
||||
}
|
||||
}
|
||||
|
|
@ -3811,7 +3811,7 @@ Search::tnsIncr(Vertex *vertex,
|
|||
{
|
||||
if (delayFuzzyLess(slack, 0.0)) {
|
||||
debugPrint2(debug_, "tns", 3, "tns+ %s %s\n",
|
||||
delayAsString(slack, units_),
|
||||
delayAsString(slack, this),
|
||||
vertex->name(sdc_network_));
|
||||
tns_[path_ap_index] += slack;
|
||||
if (tns_slacks_[path_ap_index].hasKey(vertex))
|
||||
|
|
@ -3830,9 +3830,9 @@ Search::tnsDecr(Vertex *vertex,
|
|||
if (found
|
||||
&& delayFuzzyLess(slack, 0.0)) {
|
||||
debugPrint2(debug_, "tns", 3, "tns- %s %s\n",
|
||||
delayAsString(slack, units_),
|
||||
delayAsString(slack, this),
|
||||
vertex->name(sdc_network_));
|
||||
tns_[path_ap_index] -= delayAsFloat(slack);
|
||||
tns_[path_ap_index] -= slack;
|
||||
tns_slacks_[path_ap_index].eraseKey(vertex);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2142,6 +2142,23 @@ Sta::setCrprMode(CrprMode mode)
|
|||
sdc_->setCrprMode(mode);
|
||||
}
|
||||
|
||||
bool
|
||||
Sta::pocvEnabled() const
|
||||
{
|
||||
return pocv_enabled_;
|
||||
}
|
||||
|
||||
void
|
||||
Sta::setPocvEnabled(bool enabled)
|
||||
{
|
||||
if (enabled != pocv_enabled_) {
|
||||
graph_delay_calc_->delaysInvalid();
|
||||
search_->arrivalsInvalid();
|
||||
}
|
||||
pocv_enabled_ = enabled;
|
||||
updateComponentsState();
|
||||
}
|
||||
|
||||
bool
|
||||
Sta::propagateGatedClockEnable() const
|
||||
{
|
||||
|
|
|
|||
|
|
@ -730,6 +730,10 @@ public:
|
|||
// TCL variable sta_crpr_mode.
|
||||
CrprMode crprMode() const;
|
||||
void setCrprMode(CrprMode mode);
|
||||
// TCL variable sta_pocv_enabled.
|
||||
// Parametric on chip variation (statisical sta).
|
||||
bool pocvEnabled() const;
|
||||
void setPocvEnabled(bool enabled);
|
||||
// TCL variable sta_propagate_gated_clock_enable.
|
||||
// Propagate gated clock enable arrivals.
|
||||
bool propagateGatedClockEnable() const;
|
||||
|
|
|
|||
|
|
@ -36,7 +36,8 @@ StaState::StaState() :
|
|||
sim_(NULL),
|
||||
search_(NULL),
|
||||
latches_(NULL),
|
||||
thread_count_(1)
|
||||
thread_count_(1),
|
||||
pocv_enabled_(false)
|
||||
{
|
||||
}
|
||||
|
||||
|
|
@ -57,7 +58,8 @@ StaState::StaState(const StaState *sta) :
|
|||
sim_(sta->sim_),
|
||||
search_(sta->search_),
|
||||
latches_(sta->latches_),
|
||||
thread_count_(sta->thread_count_)
|
||||
thread_count_(sta->thread_count_),
|
||||
pocv_enabled_(sta->pocv_enabled_)
|
||||
{
|
||||
}
|
||||
|
||||
|
|
@ -81,6 +83,7 @@ StaState::copyState(const StaState *sta)
|
|||
search_ = sta->search_;
|
||||
latches_ = sta->latches_;
|
||||
thread_count_ = sta->thread_count_;
|
||||
pocv_enabled_ = sta->pocv_enabled_;
|
||||
}
|
||||
|
||||
NetworkEdit *
|
||||
|
|
|
|||
|
|
@ -90,6 +90,7 @@ public:
|
|||
Latches *latches() { return latches_; }
|
||||
Latches *latches() const { return latches_; }
|
||||
unsigned threadCount() const { return thread_count_; }
|
||||
bool pocvEnabled() const { return pocv_enabled_; }
|
||||
|
||||
protected:
|
||||
Report *report_;
|
||||
|
|
@ -110,6 +111,7 @@ protected:
|
|||
Search *search_;
|
||||
Latches *latches_;
|
||||
int thread_count_;
|
||||
bool pocv_enabled_;
|
||||
|
||||
private:
|
||||
DISALLOW_COPY_AND_ASSIGN(StaState);
|
||||
|
|
|
|||
|
|
@ -173,7 +173,7 @@ WorstSlack::initQueue(PathAPIndex path_ap_index,
|
|||
}
|
||||
}
|
||||
debugPrint1(debug, "wns", 3, "threshold %s\n",
|
||||
delayAsString(slack_threshold_, sta->units()));
|
||||
delayAsString(slack_threshold_, sta));
|
||||
// checkQueue();
|
||||
}
|
||||
|
||||
|
|
@ -200,7 +200,7 @@ WorstSlack::sortQueue(PathAPIndex path_ap_index,
|
|||
Vertex *threshold_vertex = vertices[threshold_index];
|
||||
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));
|
||||
|
||||
// Reinsert vertices with slack < threshold.
|
||||
queue_.clear();
|
||||
|
|
@ -243,7 +243,6 @@ WorstSlack::checkQueue(PathAPIndex path_ap_index,
|
|||
{
|
||||
Search *search = sta->search();
|
||||
Report *report = sta->report();
|
||||
Units *units = sta->units();
|
||||
const Network *network = sta->network();
|
||||
|
||||
VertexSeq ends;
|
||||
|
|
@ -267,8 +266,8 @@ WorstSlack::checkQueue(PathAPIndex path_ap_index,
|
|||
slack_threshold_))
|
||||
report->print("WorstSlack queue missing %s %s < %s\n",
|
||||
end->name(network),
|
||||
delayAsString(search->wnsSlack(end, path_ap_index), units),
|
||||
delayAsString(slack_threshold_, units));
|
||||
delayAsString(search->wnsSlack(end, path_ap_index), sta),
|
||||
delayAsString(slack_threshold_, sta));
|
||||
}
|
||||
|
||||
VertexSet::Iterator queue_iter(queue_);
|
||||
|
|
@ -277,9 +276,8 @@ WorstSlack::checkQueue(PathAPIndex path_ap_index,
|
|||
if (!end_set.hasKey(end))
|
||||
report->print("WorstSlack queue extra %s %s > %s\n",
|
||||
end->name(network),
|
||||
delayAsString(search->wnsSlack(end, path_ap_index),
|
||||
units),
|
||||
delayAsString(slack_threshold_, units));
|
||||
delayAsString(search->wnsSlack(end, path_ap_index), sta),
|
||||
delayAsString(slack_threshold_, sta));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -307,13 +305,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));
|
||||
queue_.insert(vertex);
|
||||
}
|
||||
else {
|
||||
debugPrint2(debug, "wns", 3, "delete %s %s\n",
|
||||
vertex->name(network),
|
||||
delayAsString(slack, sta->units()));
|
||||
delayAsString(slack, sta));
|
||||
queue_.eraseKey(vertex);
|
||||
}
|
||||
lock_.unlock();
|
||||
|
|
@ -327,7 +325,7 @@ WorstSlack::setWorstSlack(Vertex *vertex,
|
|||
{
|
||||
debugPrint2(sta->debug(), "wns", 3, "%s %s\n",
|
||||
vertex->name(sta->network()),
|
||||
delayAsString(slack, sta->units()));
|
||||
delayAsString(slack, sta));
|
||||
worst_vertex_ = vertex;
|
||||
worst_slack_ = slack;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -26,6 +26,7 @@
|
|||
#include "FuncExpr.hh"
|
||||
#include "Units.hh"
|
||||
#include "Sequential.hh"
|
||||
#include "TableModel.hh"
|
||||
#include "Liberty.hh"
|
||||
#include "TimingArc.hh"
|
||||
#include "Network.hh"
|
||||
|
|
@ -136,9 +137,11 @@ private:
|
|||
float clkWaveformTImeOffset(const Clock *clk);
|
||||
float findSlew(Path *path);
|
||||
float findSlew(Path *path,
|
||||
const TransRiseFall *tr);
|
||||
const TransRiseFall *tr,
|
||||
TimingArc *next_arc);
|
||||
float findSlew(Vertex *vertex,
|
||||
const TransRiseFall *tr,
|
||||
TimingArc *next_arc,
|
||||
DcalcAPIndex dcalc_ap_index);
|
||||
LibertyPort *onePort(FuncExpr *expr);
|
||||
void writeVoltageSource(LibertyCell *cell,
|
||||
|
|
@ -146,6 +149,7 @@ private:
|
|||
const char *subckt_port_name,
|
||||
const char *pg_port_name,
|
||||
int &volt_index);
|
||||
float slewAxisMinValue(TimingArc *arc);
|
||||
|
||||
// Stage "accessors".
|
||||
//
|
||||
|
|
@ -324,7 +328,9 @@ WritePathSpice::maxTime()
|
|||
{
|
||||
auto input_stage = stageFirst();
|
||||
auto input_path = stageDrvrPath(input_stage);
|
||||
auto input_slew = findSlew(input_path);
|
||||
auto tr = input_path->transition(this);
|
||||
auto next_arc = stageGateArc(input_stage + 1);
|
||||
auto input_slew = findSlew(input_path, tr, next_arc);
|
||||
if (input_path->isClock(this)) {
|
||||
auto clk = input_path->clock(this);
|
||||
auto period = clk->period();
|
||||
|
|
@ -407,11 +413,13 @@ WritePathSpice::writeInputWaveform()
|
|||
auto input_stage = stageFirst();
|
||||
auto input_path = stageDrvrPath(input_stage);
|
||||
auto tr = input_path->transition(this);
|
||||
auto slew0 = findSlew(input_path, tr);
|
||||
auto next_arc = stageGateArc(input_stage + 1);
|
||||
auto slew0 = findSlew(input_path, tr, next_arc);
|
||||
// Arbitrary offset.
|
||||
auto time0 = slew0;
|
||||
int volt_index = 1;
|
||||
writeStepVoltSource(stageDrvrPin(input_stage), tr, slew0, time0, volt_index);
|
||||
auto drvr_pin = stageDrvrPin(input_stage);
|
||||
writeStepVoltSource(drvr_pin, tr, slew0, time0, volt_index);
|
||||
}
|
||||
|
||||
void
|
||||
|
|
@ -445,6 +453,7 @@ WritePathSpice::writeClkWaveform()
|
|||
{
|
||||
auto input_stage = stageFirst();
|
||||
auto input_path = stageDrvrPath(input_stage);
|
||||
auto next_arc = stageGateArc(input_stage + 1);
|
||||
auto clk_edge = input_path->clkEdge(this);
|
||||
auto clk = clk_edge->clock();
|
||||
auto period = clk->period();
|
||||
|
|
@ -461,8 +470,8 @@ WritePathSpice::writeClkWaveform()
|
|||
tr1 = TransRiseFall::rise();
|
||||
volt0 = power_voltage_;
|
||||
}
|
||||
auto slew0 = findSlew(input_path, tr0);
|
||||
auto slew1 = findSlew(input_path, tr1);
|
||||
auto slew0 = findSlew(input_path, tr0, next_arc);
|
||||
auto slew1 = findSlew(input_path, tr1, next_arc);
|
||||
streamPrint(spice_stream_, "v1 %s 0 pwl(\n",
|
||||
stageDrvrPinName(input_stage));
|
||||
streamPrint(spice_stream_, "+%.3e %.3e\n", 0.0, volt0);
|
||||
|
|
@ -488,29 +497,63 @@ WritePathSpice::findSlew(Path *path)
|
|||
auto vertex = path->vertex(this);
|
||||
auto dcalc_ap_index = path->dcalcAnalysisPt(this)->index();
|
||||
auto tr = path->transition(this);
|
||||
return findSlew(vertex, tr, dcalc_ap_index);
|
||||
return findSlew(vertex, tr, NULL, dcalc_ap_index);
|
||||
}
|
||||
|
||||
float
|
||||
WritePathSpice::findSlew(Path *path,
|
||||
const TransRiseFall *tr)
|
||||
const TransRiseFall *tr,
|
||||
TimingArc *next_arc)
|
||||
{
|
||||
auto vertex = path->vertex(this);
|
||||
auto dcalc_ap_index = path->dcalcAnalysisPt(this)->index();
|
||||
return findSlew(vertex, tr, dcalc_ap_index);
|
||||
return findSlew(vertex, tr, next_arc, dcalc_ap_index);
|
||||
}
|
||||
|
||||
float
|
||||
WritePathSpice::findSlew(Vertex *vertex,
|
||||
const TransRiseFall *tr,
|
||||
TimingArc *next_arc,
|
||||
DcalcAPIndex dcalc_ap_index)
|
||||
{
|
||||
auto slew = delayAsFloat(graph_->slew(vertex, tr, dcalc_ap_index));
|
||||
if (slew == 0.0 && next_arc)
|
||||
slew = slewAxisMinValue(next_arc);
|
||||
if (slew == 0.0)
|
||||
slew = units_->timeUnit()->scale();
|
||||
return slew;
|
||||
}
|
||||
|
||||
// Look up the smallest slew axis value in the timing arc delay table.
|
||||
float
|
||||
WritePathSpice::slewAxisMinValue(TimingArc *arc)
|
||||
{
|
||||
GateTableModel *gate_model = dynamic_cast<GateTableModel*>(arc->model());
|
||||
if (gate_model) {
|
||||
const TableModel *model = gate_model->delayModel();
|
||||
TableAxis *axis;
|
||||
TableAxisVariable var;
|
||||
axis = model->axis1();
|
||||
var = axis->variable();
|
||||
if (var == table_axis_input_transition_time
|
||||
|| var == table_axis_input_net_transition)
|
||||
return axis->axisValue(0);
|
||||
|
||||
axis = model->axis2();
|
||||
var = axis->variable();
|
||||
if (var == table_axis_input_transition_time
|
||||
|| var == table_axis_input_net_transition)
|
||||
return axis->axisValue(0);
|
||||
|
||||
axis = model->axis3();
|
||||
var = axis->variable();
|
||||
if (var == table_axis_input_transition_time
|
||||
|| var == table_axis_input_net_transition)
|
||||
return axis->axisValue(0);
|
||||
}
|
||||
return 0.0;
|
||||
}
|
||||
|
||||
// Write PWL rise/fall edge that crosses threshold at time.
|
||||
void
|
||||
WritePathSpice::writeWaveformEdge(const TransRiseFall *tr,
|
||||
|
|
@ -807,6 +850,7 @@ WritePathSpice::writeStageVoltageSources(Stage stage,
|
|||
}
|
||||
}
|
||||
|
||||
// PWL voltage source that rises half way into the first clock cycle.
|
||||
void
|
||||
WritePathSpice::writeClkedStepSource(const Pin *pin,
|
||||
const TransRiseFall *tr,
|
||||
|
|
@ -815,7 +859,7 @@ WritePathSpice::writeClkedStepSource(const Pin *pin,
|
|||
int &volt_index)
|
||||
{
|
||||
auto vertex = graph_->pinLoadVertex(pin);
|
||||
auto slew = findSlew(vertex, tr, dcalc_ap_index);
|
||||
auto slew = findSlew(vertex, tr, NULL, dcalc_ap_index);
|
||||
auto time = clkWaveformTImeOffset(clk) + clk->period() / 2.0;
|
||||
writeStepVoltSource(pin, tr, slew, time, volt_index);
|
||||
}
|
||||
|
|
|
|||
20
tcl/StaTcl.i
20
tcl/StaTcl.i
|
|
@ -4011,6 +4011,18 @@ set_crpr_mode(const char *mode)
|
|||
internalError("unknown common clk pessimism mode.");
|
||||
}
|
||||
|
||||
bool
|
||||
pocv_enabled()
|
||||
{
|
||||
return Sta::sta()->pocvEnabled();
|
||||
}
|
||||
|
||||
void
|
||||
set_pocv_enabled(bool enabled)
|
||||
{
|
||||
return Sta::sta()->setPocvEnabled(enabled);
|
||||
}
|
||||
|
||||
bool
|
||||
propagate_gated_clock_enable()
|
||||
{
|
||||
|
|
@ -5699,7 +5711,7 @@ arrivals_clk_delays(const TransRiseFall *tr,
|
|||
PathAnalysisPt *path_ap = ap_iter.next();
|
||||
arrivals->push_back(delayAsString(sta->vertexArrival(self, tr, clk_edge,
|
||||
path_ap),
|
||||
sta->units(), digits));
|
||||
sta, digits));
|
||||
}
|
||||
return arrivals;
|
||||
}
|
||||
|
|
@ -5739,7 +5751,7 @@ requireds_clk_delays(const TransRiseFall *tr,
|
|||
PathAnalysisPt *path_ap = ap_iter.next();
|
||||
requireds->push_back(delayAsString(sta->vertexRequired(self, tr, clk_edge,
|
||||
path_ap),
|
||||
sta->units(), digits));
|
||||
sta, digits));
|
||||
}
|
||||
return requireds;
|
||||
}
|
||||
|
|
@ -5793,7 +5805,7 @@ slacks_clk_delays(const TransRiseFall *tr,
|
|||
PathAnalysisPt *path_ap = ap_iter.next();
|
||||
slacks->push_back(delayAsString(sta->vertexSlack(self, tr, clk_edge,
|
||||
path_ap),
|
||||
sta->units(), digits));
|
||||
sta, digits));
|
||||
}
|
||||
return slacks;
|
||||
}
|
||||
|
|
@ -5869,7 +5881,7 @@ arc_delay_strings(TimingArc *arc,
|
|||
while (ap_iter.hasNext()) {
|
||||
DcalcAnalysisPt *dcalc_ap = ap_iter.next();
|
||||
delays->push_back(delayAsString(sta->arcDelay(self, arc, dcalc_ap),
|
||||
sta->units(), digits));
|
||||
sta, digits));
|
||||
}
|
||||
return delays;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -160,6 +160,14 @@ proc trace_propagate_gated_clock_enable { name1 name2 op } {
|
|||
propagate_gated_clock_enable set_propagate_gated_clock_enable
|
||||
}
|
||||
|
||||
trace variable ::sta_pocv_enabled "rw" \
|
||||
sta::trace_pocv_enabled
|
||||
|
||||
proc trace_pocv_enabled { name1 name2 op } {
|
||||
trace_boolean_var $op ::sta_pocv_enabled \
|
||||
pocv_enabled set_pocv_enabled
|
||||
}
|
||||
|
||||
################################################################
|
||||
|
||||
proc trace_boolean_var { op var_name get_proc set_proc } {
|
||||
|
|
|
|||
Loading…
Reference in New Issue