This commit is contained in:
James Cherry 2019-01-26 23:03:01 -08:00
parent ca231b29cc
commit 3f65204717
34 changed files with 371 additions and 190 deletions

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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