diff --git a/CMakeLists.txt b/CMakeLists.txt
index f706de89..83457ea8 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -62,6 +62,7 @@ set(STA_SOURCE
app/StaMain.cc
dcalc/ArcDelayCalc.cc
+ dcalc/ArcDcalcWaveforms.cc
dcalc/ArnoldiDelayCalc.cc
dcalc/ArnoldiReduce.cc
dcalc/DcalcAnalysisPt.cc
@@ -73,7 +74,6 @@ set(STA_SOURCE
dcalc/LumpedCapDelayCalc.cc
dcalc/NetCaps.cc
dcalc/ParallelDelayCalc.cc
- dcalc/SlewDegradeDelayCalc.cc
dcalc/UnitDelayCalc.cc
graph/DelayFloat.cc
diff --git a/dcalc/SlewDegradeDelayCalc.hh b/dcalc/ArcDcalcWaveforms.cc
similarity index 54%
rename from dcalc/SlewDegradeDelayCalc.hh
rename to dcalc/ArcDcalcWaveforms.cc
index 7195985d..6b282596 100644
--- a/dcalc/SlewDegradeDelayCalc.hh
+++ b/dcalc/ArcDcalcWaveforms.cc
@@ -14,14 +14,30 @@
// You should have received a copy of the GNU General Public License
// along with this program. If not, see .
-#pragma once
+#include "ArcDcalcWaveforms.hh"
+
namespace sta {
-class ArcDelayCalc;
-class StaState;
+Table1
+ArcDcalcWaveforms::inputWaveform(const Pin *,
+ const RiseFall *,
+ const Corner *,
+ const MinMax *)
+{
+ return Table1();
+}
-ArcDelayCalc *
-makeSlewDegradeDelayCalc(StaState *sta);
+Table1
+ArcDcalcWaveforms::drvrRampWaveform(const Pin *,
+ const RiseFall *,
+ const Pin *,
+ const RiseFall *,
+ const Pin *,
+ const Corner *,
+ const MinMax *)
+{
+ return Table1();
+}
} // namespace
diff --git a/dcalc/ArcDcalcWaveforms.hh b/dcalc/ArcDcalcWaveforms.hh
new file mode 100644
index 00000000..a47eff0b
--- /dev/null
+++ b/dcalc/ArcDcalcWaveforms.hh
@@ -0,0 +1,59 @@
+// OpenSTA, Static Timing Analyzer
+// Copyright (c) 2023, Parallax Software, Inc.
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program. If not, see .
+
+#pragma once
+
+#include "MinMax.hh"
+#include "TableModel.hh"
+#include "NetworkClass.hh"
+
+namespace sta {
+
+class Corner;
+class DcalcAnalysisPt;
+
+// Abstract class for the graph delay calculator traversal to interface
+class ArcDcalcWaveforms
+{
+public:
+ virtual Table1 inputWaveform(const Pin *in_pin,
+ const RiseFall *in_rf,
+ const Corner *corner,
+ const MinMax *min_max);
+ virtual Table1 drvrWaveform(const Pin *in_pin,
+ const RiseFall *in_rf,
+ const Pin *drvr_pin,
+ const RiseFall *drvr_rf,
+ const Corner *corner,
+ const MinMax *min_max) = 0;
+ virtual Table1 loadWaveform(const Pin *in_pin,
+ const RiseFall *in_rf,
+ const Pin *drvr_pin,
+ const RiseFall *drvr_rf,
+ const Pin *load_pin,
+ const Corner *corner,
+ const MinMax *min_max) = 0;
+ virtual Table1 drvrRampWaveform(const Pin *in_pin,
+ const RiseFall *in_rf,
+ const Pin *drvr_pin,
+ const RiseFall *drvr_rf,
+ const Pin *load_pin,
+ const Corner *corner,
+ const MinMax *min_max);
+};
+
+} // namespace
+
diff --git a/dcalc/ArcDelayCalc.cc b/dcalc/ArcDelayCalc.cc
index 56825b3b..8999a3af 100644
--- a/dcalc/ArcDelayCalc.cc
+++ b/dcalc/ArcDelayCalc.cc
@@ -16,10 +16,6 @@
#include "ArcDelayCalc.hh"
-#include "TimingModel.hh"
-#include "TimingArc.hh"
-#include "GraphDelayCalc.hh"
-
namespace sta {
ArcDelayCalc::ArcDelayCalc(StaState *sta):
@@ -27,27 +23,114 @@ ArcDelayCalc::ArcDelayCalc(StaState *sta):
{
}
-TimingModel *
-ArcDelayCalc::model(const TimingArc *arc,
- const DcalcAnalysisPt *dcalc_ap) const
+void
+ArcDelayCalc::gateDelay(const TimingArc *arc,
+ const Slew &in_slew,
+ float load_cap,
+ const Parasitic *parasitic,
+ float,
+ const Pvt *,
+ const DcalcAnalysisPt *dcalc_ap,
+ // Return values.
+ ArcDelay &gate_delay,
+ Slew &drvr_slew)
{
- const OperatingConditions *op_cond = dcalc_ap->operatingConditions();
- const TimingArc *corner_arc = arc->cornerArc(dcalc_ap->libertyIndex());
- return corner_arc->model(op_cond);
+ LoadPinIndexMap load_pin_index_map(network_);
+ ArcDcalcResult dcalc_result = gateDelay(nullptr, arc, in_slew, load_cap, parasitic,
+ load_pin_index_map, dcalc_ap);
+ gate_delay = dcalc_result.gateDelay();
+ drvr_slew = dcalc_result.drvrSlew();
}
-GateTimingModel *
-ArcDelayCalc::gateModel(const TimingArc *arc,
- const DcalcAnalysisPt *dcalc_ap) const
+////////////////////////////////////////////////////////////////
+
+ArcDcalcArg::ArcDcalcArg() :
+ drvr_pin_(nullptr),
+ edge_(nullptr),
+ arc_(nullptr),
+ in_slew_(0.0),
+ parasitic_(nullptr)
{
- return dynamic_cast(model(arc, dcalc_ap));
}
-CheckTimingModel *
-ArcDelayCalc::checkModel(const TimingArc *arc,
- const DcalcAnalysisPt *dcalc_ap) const
+ArcDcalcArg::ArcDcalcArg(const Pin *drvr_pin,
+ Edge *edge,
+ const TimingArc *arc,
+ const Slew in_slew,
+ const Parasitic *parasitic) :
+ drvr_pin_(drvr_pin),
+ edge_(edge),
+ arc_(arc),
+ in_slew_(in_slew),
+ parasitic_(parasitic)
{
- return dynamic_cast(model(arc, dcalc_ap));
+}
+
+void
+ArcDcalcArg::setParasitic(const Parasitic *parasitic)
+{
+ parasitic_ = parasitic;
+}
+
+////////////////////////////////////////////////////////////////
+
+ArcDcalcResult::ArcDcalcResult() :
+ gate_delay_(0.0),
+ drvr_slew_(0.0)
+{
+}
+
+ArcDcalcResult::ArcDcalcResult(size_t load_count) :
+ gate_delay_(0.0),
+ drvr_slew_(0.0)
+{
+ wire_delays_.resize(load_count);
+ load_slews_.resize(load_count);
+}
+
+void
+ArcDcalcResult::setGateDelay(ArcDelay gate_delay)
+{
+ gate_delay_ = gate_delay;
+}
+
+void
+ArcDcalcResult::setDrvrSlew(Slew drvr_slew)
+{
+ drvr_slew_ = drvr_slew;
+}
+
+ArcDelay
+ArcDcalcResult::wireDelay(size_t load_idx) const
+{
+ return wire_delays_[load_idx];
+}
+
+void
+ArcDcalcResult::setWireDelay(size_t load_idx,
+ ArcDelay wire_delay)
+{
+ wire_delays_[load_idx] = wire_delay;
+}
+
+void
+ArcDcalcResult::setLoadCount(size_t load_count)
+{
+ wire_delays_.resize(load_count);
+ load_slews_.resize(load_count);
+}
+
+Slew
+ArcDcalcResult::loadSlew(size_t load_idx) const
+{
+ return load_slews_[load_idx];
+}
+
+void
+ArcDcalcResult::setLoadSlew(size_t load_idx,
+ Slew load_slew)
+{
+ load_slews_[load_idx] = load_slew;
}
} // namespace
diff --git a/dcalc/Arnoldi.hh b/dcalc/Arnoldi.hh
index 0437e914..79f3a77a 100644
--- a/dcalc/Arnoldi.hh
+++ b/dcalc/Arnoldi.hh
@@ -74,7 +74,6 @@ struct timing_table
const LibertyCell *cell;
const Pvt *pvt;
float in_slew;
- float relcap;
};
} // namespace
diff --git a/dcalc/ArnoldiDelayCalc.cc b/dcalc/ArnoldiDelayCalc.cc
index 15610b41..11f8d775 100644
--- a/dcalc/ArnoldiDelayCalc.cc
+++ b/dcalc/ArnoldiDelayCalc.cc
@@ -117,32 +117,26 @@ public:
Parasitic *findParasitic(const Pin *drvr_pin,
const RiseFall *rf,
const DcalcAnalysisPt *dcalc_ap) override;
- ReducedParasiticType reducedParasiticType() const override;
- void inputPortDelay(const Pin *port_pin,
- float in_slew,
- const RiseFall *rf,
- const Parasitic *parasitic,
- const DcalcAnalysisPt *dcalc_ap) override;
- void gateDelay(const TimingArc *arc,
- const Slew &in_slew,
- float load_cap,
- const Parasitic *drvr_parasitic,
- float related_out_cap,
- const Pvt *pvt,
- const DcalcAnalysisPt *dcalc_ap,
- // Return values.
- ArcDelay &gate_delay,
- Slew &drvr_slew) override;
- void loadDelay(const Pin *load_pin,
- // Return values.
- ArcDelay &wire_delay,
- Slew &load_slew) override;
- string reportGateDelay(const TimingArc *arc,
+ ArcDcalcResult inputPortDelay(const Pin *port_pin,
+ float in_slew,
+ const RiseFall *rf,
+ const Parasitic *parasitic,
+ const LoadPinIndexMap &load_pin_index_map,
+ const DcalcAnalysisPt *dcalc_ap) override;
+ ArcDcalcResult gateDelay(const Pin *drvr_pin,
+ const TimingArc *arc,
+ const Slew &in_slew,
+ // Pass in load_cap or parasitic.
+ float load_cap,
+ const Parasitic *parasitic,
+ const LoadPinIndexMap &load_pin_index_map,
+ const DcalcAnalysisPt *dcalc_ap) override;
+ string reportGateDelay(const Pin *drvr_pin,
+ const TimingArc *arc,
const Slew &in_slew,
float load_cap,
- const Parasitic *drvr_parasitic,
- float related_out_cap,
- const Pvt *pvt,
+ const Parasitic *parasitic,
+ const LoadPinIndexMap &load_pin_index_map,
const DcalcAnalysisPt *dcalc_ap,
int digits) override;
void delay_work_set_thresholds(delay_work *D,
@@ -152,14 +146,12 @@ public:
double derate);
private:
- void gateDelaySlew(const LibertyCell *drvr_cell,
- const GateTableModel *table_model,
- const Slew &in_slew,
- float related_out_cap,
- const Pvt *pvt,
- // Return values.
- ArcDelay &gate_delay,
- Slew &drvr_slew);
+ ArcDcalcResult gateDelaySlew(const LibertyCell *drvr_cell,
+ const TimingArc *arc,
+ const GateTableModel *table_model,
+ const Slew &in_slew,
+ const LoadPinIndexMap &load_pin_index_map,
+ const Pvt *pvt);
void ar1_ceff_delay(delay_work *D,
timing_table *tab,
arnoldi1 *mod,
@@ -224,7 +216,6 @@ private:
double *_delayV;
double *_slewV;
int pin_n_;
- bool input_port_;
ArnoldiReduce *reduce_;
delay_work *delay_work_;
};
@@ -306,25 +297,20 @@ ArnoldiDelayCalc::findParasitic(const Pin *drvr_pin,
return parasitic;
}
-ReducedParasiticType
-ArnoldiDelayCalc::reducedParasiticType() const
+ArcDcalcResult
+ArnoldiDelayCalc::inputPortDelay(const Pin *,
+ float in_slew,
+ const RiseFall *rf,
+ const Parasitic *parasitic,
+ const LoadPinIndexMap &load_pin_index_map,
+ const DcalcAnalysisPt *)
{
- return ReducedParasiticType::arnoldi;
-}
-
-void
-ArnoldiDelayCalc::inputPortDelay(const Pin *drvr_pin,
- float in_slew,
- const RiseFall *rf,
- const Parasitic *parasitic,
- const DcalcAnalysisPt *dcalc_ap)
-{
- LumpedCapDelayCalc::inputPortDelay(drvr_pin, in_slew, rf, parasitic, dcalc_ap);
rcmodel_ = nullptr;
_delayV[0] = 0.0;
_slewV[0] = in_slew;
- int j;
+ LibertyLibrary *drvr_library = network_->defaultLibertyLibrary();
+ ArcDcalcResult dcalc_result(load_pin_index_map.size());
if (parasitic) {
rcmodel_ = reinterpret_cast(const_cast(parasitic));
pin_n_ = rcmodel_->n;
@@ -335,69 +321,67 @@ ArnoldiDelayCalc::inputPortDelay(const Pin *drvr_pin,
_delayV = (double*)realloc(_delayV,_pinNmax * sizeof(double));
_slewV = (double*)realloc(_slewV,_pinNmax * sizeof(double));
}
- pin_n_ = 1;
pin_n_ = rcmodel_->n;
- double slew_derate = drvr_library_->slewDerateFromLibrary();
- double lo_thresh = drvr_library_->slewLowerThreshold(drvr_rf_);
- double hi_thresh = drvr_library_->slewUpperThreshold(drvr_rf_);
- bool rising = (drvr_rf_ == RiseFall::rise());
- delay_work_set_thresholds(delay_work_, lo_thresh, hi_thresh, rising,
- slew_derate);
+ double slew_derate = drvr_library->slewDerateFromLibrary();
+ double lo_thresh = drvr_library->slewLowerThreshold(rf);
+ double hi_thresh = drvr_library->slewUpperThreshold(rf);
+ bool rising = (rf == RiseFall::rise());
+ delay_work_set_thresholds(delay_work_, lo_thresh, hi_thresh, rising, slew_derate);
delay_c *c = delay_work_->c;
double c_log = c->vlg;
- for (j=1;jelmore(j);
- _delayV[j] = 0.6931472*elmore;
- _slewV[j] = in_slew + c_log*elmore/slew_derate;
+ double wire_delay = 0.6931472*elmore;
+ double load_slew = in_slew + c_log*elmore/slew_derate;
+ _delayV[j] = wire_delay;
+ _slewV[j] = load_slew;
+
+ const Pin *load_pin = rcmodel_->pinV[j];
+ auto load_idx_itr = load_pin_index_map.find(load_pin);
+ if (load_idx_itr != load_pin_index_map.end()) {
+ size_t load_idx = load_idx_itr->second;
+ dcalc_result.setWireDelay(load_idx, wire_delay);
+ dcalc_result.setLoadSlew(load_idx, load_slew);
+ }
}
}
-}
-
-void
-ArnoldiDelayCalc::gateDelay(const TimingArc *arc,
- const Slew &in_slew,
- float load_cap,
- const Parasitic *drvr_parasitic,
- float related_out_cap,
- const Pvt *pvt,
- const DcalcAnalysisPt *dcalc_ap,
- // Return values.
- ArcDelay &gate_delay,
- Slew &drvr_slew)
-{
- input_port_ = false;
- drvr_rf_ = arc->toEdge()->asRiseFall();
- const LibertyCell *drvr_cell = arc->from()->libertyCell();
- drvr_library_ = drvr_cell->libertyLibrary();
- drvr_parasitic_ = drvr_parasitic;
- ConcreteParasitic *drvr_cparasitic =
- reinterpret_cast(const_cast(drvr_parasitic));
- rcmodel_ = dynamic_cast(drvr_cparasitic);
- GateTimingModel *model = gateModel(arc, dcalc_ap);
- GateTableModel *table_model = dynamic_cast(model);
- if (table_model && rcmodel_)
- gateDelaySlew(drvr_cell, table_model, in_slew,
- related_out_cap, pvt,
- gate_delay, drvr_slew);
else
- LumpedCapDelayCalc::gateDelay(arc, in_slew, load_cap, drvr_parasitic,
- related_out_cap, pvt, dcalc_ap,
- gate_delay, drvr_slew);
- drvr_slew_ = drvr_slew;
- multi_drvr_slew_factor_ = 1.0F;
+ dcalc_result = makeResult(drvr_library, rf, 0.0, in_slew, load_pin_index_map);
+ return dcalc_result;
}
-void
+ArcDcalcResult
+ArnoldiDelayCalc::gateDelay(const Pin *drvr_pin,
+ const TimingArc *arc,
+ const Slew &in_slew,
+ float load_cap,
+ const Parasitic *parasitic,
+ const LoadPinIndexMap &load_pin_index_map,
+ const DcalcAnalysisPt *dcalc_ap)
+{
+ const LibertyCell *drvr_cell = arc->from()->libertyCell();
+ ConcreteParasitic *cparasitic =
+ reinterpret_cast(const_cast(parasitic));
+ rcmodel_ = dynamic_cast(cparasitic);
+ GateTableModel *table_model = gateTableModel(arc, dcalc_ap);
+ if (table_model && rcmodel_) {
+ const Pvt *pvt = pinPvt(drvr_pin, dcalc_ap);
+ return gateDelaySlew(drvr_cell, arc, table_model, in_slew, load_pin_index_map, pvt);
+ }
+ else
+ return LumpedCapDelayCalc::gateDelay(drvr_pin, arc, in_slew, load_cap,
+ parasitic, load_pin_index_map, dcalc_ap);
+}
+
+ArcDcalcResult
ArnoldiDelayCalc::gateDelaySlew(const LibertyCell *drvr_cell,
+ const TimingArc *arc,
const GateTableModel *table_model,
const Slew &in_slew,
- float related_out_cap,
- const Pvt *pvt,
- // Return values.
- ArcDelay &gate_delay,
- Slew &drvr_slew)
+ const LoadPinIndexMap &load_pin_index_map,
+ const Pvt *pvt)
{
pin_n_ = rcmodel_->n;
if (pin_n_ >= _pinNmax) {
@@ -407,12 +391,15 @@ ArnoldiDelayCalc::gateDelaySlew(const LibertyCell *drvr_cell,
_slewV = (double*)realloc(_slewV,_pinNmax * sizeof(double));
}
+ ArcDcalcResult dcalc_result(load_pin_index_map.size());
pin_n_ = rcmodel_->n;
- if (table_model) {
- double slew_derate = drvr_library_->slewDerateFromLibrary();
- double lo_thresh = drvr_library_->slewLowerThreshold(drvr_rf_);
- double hi_thresh = drvr_library_->slewUpperThreshold(drvr_rf_);
- bool rising = (drvr_rf_ == RiseFall::rise());
+ const RiseFall *rf = arc->toEdge()->asRiseFall();
+ if (table_model && rf) {
+ const LibertyLibrary *drvr_library = drvr_cell->libertyLibrary();
+ double slew_derate = drvr_library->slewDerateFromLibrary();
+ double lo_thresh = drvr_library->slewLowerThreshold(rf);
+ double hi_thresh = drvr_library->slewUpperThreshold(rf);
+ bool rising = (rf == RiseFall::rise());
delay_work_set_thresholds(delay_work_, lo_thresh, hi_thresh, rising,
slew_derate);
if (rcmodel_->order > 0) {
@@ -421,48 +408,43 @@ ArnoldiDelayCalc::gateDelaySlew(const LibertyCell *drvr_cell,
tab.cell = drvr_cell;
tab.pvt = pvt;
tab.in_slew = delayAsFloat(in_slew);
- tab.relcap = related_out_cap;
ar1_ceff_delay(delay_work_, &tab, rcmodel_,
_delayV, _slewV);
}
- gate_delay = _delayV[0];
- drvr_slew = _slewV[0];
- }
-}
+ dcalc_result.setGateDelay(_delayV[0]);
+ dcalc_result.setDrvrSlew(_slewV[0]);
-void
-ArnoldiDelayCalc::loadDelay(const Pin *load_pin,
- // Return values.
- ArcDelay &wire_delay,
- Slew &load_slew)
-{
- // This does not appear to handle input port parasitics correctly.
- wire_delay = 0.0;
- load_slew = drvr_slew_ * multi_drvr_slew_factor_;
- if (rcmodel_) {
- // HACK
- for (int i = 0; i < rcmodel_->n; i++) {
- if (rcmodel_->pinV[i] == load_pin) {
- wire_delay = _delayV[i] - _delayV[0];
- load_slew = _slewV[i] * multi_drvr_slew_factor_;
- break;
+ if (rcmodel_) {
+ for (int i = 0; i < rcmodel_->n; i++) {
+ const Pin *load_pin = rcmodel_->pinV[i];
+ auto load_idx_itr = load_pin_index_map.find(load_pin);
+ if (load_idx_itr != load_pin_index_map.end()) {
+ size_t load_idx = load_idx_itr->second;
+ ArcDelay wire_delay = _delayV[i] - _delayV[0];
+ Slew load_slew = _slewV[i];
+ thresholdAdjust(load_pin, drvr_library, rf, wire_delay, load_slew);
+ dcalc_result.setWireDelay(load_idx, wire_delay);
+ dcalc_result.setLoadSlew(load_idx, load_slew);
+ }
}
}
}
- thresholdAdjust(load_pin, wire_delay, load_slew);
+ return dcalc_result;
}
string
-ArnoldiDelayCalc::reportGateDelay(const TimingArc *,
- const Slew &,
- float,
- const Parasitic *,
- float,
- const Pvt *,
- const DcalcAnalysisPt *,
- int)
+ArnoldiDelayCalc::reportGateDelay(const Pin *drvr_pin,
+ const TimingArc *arc,
+ const Slew &in_slew,
+ float load_cap,
+ const Parasitic *parasitic,
+ const LoadPinIndexMap &load_pin_index_map,
+ const DcalcAnalysisPt *dcalc_ap,
+ int digits)
{
- return "";
+ return LumpedCapDelayCalc::reportGateDelay(drvr_pin, arc, in_slew, load_cap,
+ parasitic, load_pin_index_map,
+ dcalc_ap, digits);
}
////////////////////////////////////////////////////////////////
@@ -1310,7 +1292,7 @@ ArnoldiDelayCalc::ra_get_r(delay_work *D,
c1 = ctot;
ArcDelay d1;
Slew s1;
- tab->table->gateDelay(tab->pvt, tab->in_slew, c1, tab->relcap, pocv_enabled_, d1, s1);
+ tab->table->gateDelay(tab->pvt, tab->in_slew, c1, pocv_enabled_, d1, s1);
tlohi = slew_derate*delayAsFloat(s1);
r = tlohi/(c_log*c1);
if (rdelay>0.0 && r > rdelay)
@@ -1332,7 +1314,7 @@ ArnoldiDelayCalc::ra_get_s(delay_work *D,
double tlohi,smin,s;
ArcDelay d1;
Slew s1;
- tab->table->gateDelay(tab->pvt, tab->in_slew, c, tab->relcap, pocv_enabled_, d1, s1);
+ tab->table->gateDelay(tab->pvt, tab->in_slew, c, 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) {
@@ -1365,8 +1347,8 @@ ArnoldiDelayCalc::ra_rdelay_1(timing_table *tab,
return 0.0;
ArcDelay d1, d2;
Slew s1, s2;
- tab->table->gateDelay(tab->pvt, tab->in_slew, c1, tab->relcap, pocv_enabled_, d1, s1);
- tab->table->gateDelay(tab->pvt, tab->in_slew, c2, tab->relcap, pocv_enabled_, d2, s2);
+ tab->table->gateDelay(tab->pvt, tab->in_slew, c1, pocv_enabled_, d1, s1);
+ tab->table->gateDelay(tab->pvt, tab->in_slew, c2, pocv_enabled_, d2, s2);
double dt50 = delayAsFloat(d1)-delayAsFloat(d2);
if (dt50 <= 0.0)
return 0.0;
@@ -1418,8 +1400,7 @@ ArnoldiDelayCalc::ar1_ceff_delay(delay_work *D,
units_->timeUnit()->asString(s));
thix = ra_solve_for_t(p,s,vhi);
tlox = ra_solve_for_t(p,s,vlo);
- tab->table->gateDelay(tab->pvt,tab->in_slew, ctot, tab->relcap, pocv_enabled_,
- df, sf);
+ tab->table->gateDelay(tab->pvt,tab->in_slew, ctot, pocv_enabled_, df, sf);
debugPrint(debug_, "arnoldi", 1, "table slew (in_slew %s ctot %s) = %s",
units_->timeUnit()->asString(tab->in_slew),
units_->capacitanceUnit()->asString(ctot),
@@ -1430,7 +1411,7 @@ ArnoldiDelayCalc::ar1_ceff_delay(delay_work *D,
units_->timeUnit()->asString(tlox-thix));
}
ceff = ctot;
- tab->table->gateDelay(tab->pvt, tab->in_slew, ceff, tab->relcap, pocv_enabled_,
+ tab->table->gateDelay(tab->pvt, tab->in_slew, ceff, pocv_enabled_,
df, sf);
t50_sy = delayAsFloat(df);
t50_sr = ra_solve_for_t(1.0/(r*ceff),s,0.5);
@@ -1472,7 +1453,7 @@ ArnoldiDelayCalc::ar1_ceff_delay(delay_work *D,
units_->timeUnit()->asString(ceff_time),
units_->capacitanceUnit()->asString(ceff));
- tab->table->gateDelay(tab->pvt, tab->in_slew, ceff, tab->relcap, pocv_enabled_, df, sf);
+ tab->table->gateDelay(tab->pvt, tab->in_slew, ceff, pocv_enabled_, df, sf);
t50_sy = delayAsFloat(df);
t50_sr = ra_solve_for_t(1.0/(r*ceff),s,0.5);
for (j=0;jn;j++) {
diff --git a/dcalc/DelayCalc.cc b/dcalc/DelayCalc.cc
index 2c5c1ba0..cfb940de 100644
--- a/dcalc/DelayCalc.cc
+++ b/dcalc/DelayCalc.cc
@@ -20,7 +20,6 @@
#include "StringUtil.hh"
#include "UnitDelayCalc.hh"
#include "LumpedCapDelayCalc.hh"
-#include "SlewDegradeDelayCalc.hh"
#include "DmpDelayCalc.hh"
#include "ArnoldiDelayCalc.hh"
@@ -35,7 +34,6 @@ registerDelayCalcs()
{
registerDelayCalc("unit", makeUnitDelayCalc);
registerDelayCalc("lumped_cap", makeLumpedCapDelayCalc);
- registerDelayCalc("slew_degrade", makeSlewDegradeDelayCalc);
registerDelayCalc("dmp_ceff_elmore", makeDmpCeffElmoreDelayCalc);
registerDelayCalc("dmp_ceff_two_pole", makeDmpCeffTwoPoleDelayCalc);
registerDelayCalc("arnoldi", makeArnoldiDelayCalc);
diff --git a/dcalc/DelayCalc.i b/dcalc/DelayCalc.i
index 52711847..b96b0470 100644
--- a/dcalc/DelayCalc.i
+++ b/dcalc/DelayCalc.i
@@ -19,6 +19,8 @@
// along with this program. If not, see .
#include "Sta.hh"
+#include "ArcDelayCalc.hh"
+#include "dcalc/ArcDcalcWaveforms.hh"
%}
@@ -59,4 +61,76 @@ report_delay_calc_cmd(Edge *edge,
return Sta::sta()->reportDelayCalc(edge, arc, corner, min_max, digits);
}
+////////////////////////////////////////////////////////////////
+
+Table1
+ccs_input_waveform(const Pin *in_pin,
+ const RiseFall *in_rf,
+ const Corner *corner,
+ const MinMax *min_max)
+{
+ cmdLinkedNetwork();
+ Sta *sta = Sta::sta();
+ ArcDcalcWaveforms *arc_dcalc = dynamic_cast(sta->arcDelayCalc());
+ if (arc_dcalc)
+ return arc_dcalc->inputWaveform(in_pin, in_rf, corner, min_max);
+ else
+ return Table1();
+}
+
+Table1
+ccs_driver_waveform(const Pin *in_pin,
+ const RiseFall *in_rf,
+ const Pin *drvr_pin,
+ const RiseFall *drvr_rf,
+ const Corner *corner,
+ const MinMax *min_max)
+{
+ cmdLinkedNetwork();
+ Sta *sta = Sta::sta();
+ ArcDcalcWaveforms *arc_dcalc = dynamic_cast(sta->arcDelayCalc());
+ if (arc_dcalc)
+ return arc_dcalc->drvrWaveform(in_pin, in_rf, drvr_pin, drvr_rf, corner, min_max);
+ else
+ return Table1();
+}
+
+Table1
+ccs_driver_ramp_waveform(const Pin *in_pin,
+ const RiseFall *in_rf,
+ const Pin *drvr_pin,
+ const RiseFall *drvr_rf,
+ const Pin *load_pin,
+ const Corner *corner,
+ const MinMax *min_max)
+{
+ cmdLinkedNetwork();
+ Sta *sta = Sta::sta();
+ ArcDcalcWaveforms *arc_dcalc = dynamic_cast(sta->arcDelayCalc());
+ if (arc_dcalc)
+ return arc_dcalc->drvrRampWaveform(in_pin, in_rf, drvr_pin, drvr_rf,
+ load_pin, corner, min_max);
+ else
+ return Table1();
+}
+
+Table1
+ccs_load_waveform(const Pin *in_pin,
+ const RiseFall *in_rf,
+ const Pin *drvr_pin,
+ const RiseFall *drvr_rf,
+ const Pin *load_pin,
+ const Corner *corner,
+ const MinMax *min_max)
+{
+ cmdLinkedNetwork();
+ Sta *sta = Sta::sta();
+ ArcDcalcWaveforms *arc_dcalc = dynamic_cast(sta->arcDelayCalc());
+ if (arc_dcalc)
+ return arc_dcalc->loadWaveform(in_pin, in_rf, drvr_pin, drvr_rf,
+ load_pin, corner, min_max);
+ else
+ return Table1();
+}
+
%} // inline
diff --git a/dcalc/DelayCalcBase.cc b/dcalc/DelayCalcBase.cc
index c2639664..d4adc760 100644
--- a/dcalc/DelayCalcBase.cc
+++ b/dcalc/DelayCalcBase.cc
@@ -18,16 +18,52 @@
#include "Liberty.hh"
#include "TimingArc.hh"
+#include "TimingModel.hh"
+#include "TableModel.hh"
#include "Network.hh"
#include "Parasitics.hh"
+#include "Sdc.hh"
+#include "DcalcAnalysisPt.hh"
namespace sta {
+using std::log;
+
DelayCalcBase::DelayCalcBase(StaState *sta) :
ArcDelayCalc(sta)
{
}
+TimingModel *
+DelayCalcBase::model(const TimingArc *arc,
+ const DcalcAnalysisPt *dcalc_ap) const
+{
+ const OperatingConditions *op_cond = dcalc_ap->operatingConditions();
+ const TimingArc *corner_arc = arc->cornerArc(dcalc_ap->libertyIndex());
+ return corner_arc->model(op_cond);
+}
+
+GateTimingModel *
+DelayCalcBase::gateModel(const TimingArc *arc,
+ const DcalcAnalysisPt *dcalc_ap) const
+{
+ return dynamic_cast(model(arc, dcalc_ap));
+}
+
+GateTableModel *
+DelayCalcBase::gateTableModel(const TimingArc *arc,
+ const DcalcAnalysisPt *dcalc_ap) const
+{
+ return dynamic_cast(model(arc, dcalc_ap));
+}
+
+CheckTimingModel *
+DelayCalcBase::checkModel(const TimingArc *arc,
+ const DcalcAnalysisPt *dcalc_ap) const
+{
+ return dynamic_cast(model(arc, dcalc_ap));
+}
+
void
DelayCalcBase::finishDrvrPin()
{
@@ -39,74 +75,53 @@ DelayCalcBase::finishDrvrPin()
reduced_parasitic_drvrs_.clear();
}
-void
-DelayCalcBase::inputPortDelay(const Pin *,
- float in_slew,
- const RiseFall *rf,
- const Parasitic *parasitic,
- const DcalcAnalysisPt *)
-{
- drvr_cell_ = nullptr;
- drvr_library_ = network_->defaultLibertyLibrary();
- drvr_slew_ = in_slew;
- drvr_rf_ = rf;
- drvr_parasitic_ = parasitic;
- input_port_ = true;
-}
-
-void
-DelayCalcBase::gateDelayInit(const TimingArc *arc,
- const Slew &in_slew,
- const Parasitic *drvr_parasitic)
-{
- drvr_cell_ = arc->from()->libertyCell();
- drvr_library_ = drvr_cell_->libertyLibrary();
- drvr_rf_ = arc->toEdge()->asRiseFall();
- drvr_slew_ = in_slew;
- drvr_parasitic_ = drvr_parasitic;
- input_port_ = false;
-}
-
// For DSPF on an input port the elmore delay is used as the time
// constant of an exponential waveform. The delay to the logic
// threshold and slew are computed for the exponential waveform.
// Note that this uses the driver thresholds and relies on
// thresholdAdjust to convert the delay and slew to the load's thresholds.
void
-DelayCalcBase::dspfWireDelaySlew(const Pin *,
+DelayCalcBase::dspfWireDelaySlew(const Pin *load_pin,
+ const RiseFall *rf,
+ Slew drvr_slew,
float elmore,
ArcDelay &wire_delay,
Slew &load_slew)
{
- float vth = drvr_library_->inputThreshold(drvr_rf_);
- float vl = drvr_library_->slewLowerThreshold(drvr_rf_);
- float vh = drvr_library_->slewUpperThreshold(drvr_rf_);
- float slew_derate = drvr_library_->slewDerateFromLibrary();
+
+ LibertyLibrary *load_library = thresholdLibrary(load_pin);
+ float vth = load_library->inputThreshold(rf);
+ float vl = load_library->slewLowerThreshold(rf);
+ float vh = load_library->slewUpperThreshold(rf);
+ float slew_derate = load_library->slewDerateFromLibrary();
wire_delay = -elmore * log(1.0 - vth);
- load_slew = drvr_slew_ + elmore * log((1.0 - vl) / (1.0 - vh)) / slew_derate;
+ load_slew = drvr_slew + elmore * log((1.0 - vl) / (1.0 - vh)) / slew_derate;
+ load_slew = drvr_slew + elmore * log((1.0 - vl) / (1.0 - vh)) / slew_derate;
}
void
DelayCalcBase::thresholdAdjust(const Pin *load_pin,
+ const LibertyLibrary *drvr_library,
+ const RiseFall *rf,
ArcDelay &load_delay,
Slew &load_slew)
{
LibertyLibrary *load_library = thresholdLibrary(load_pin);
if (load_library
- && drvr_library_
- && load_library != drvr_library_) {
- float drvr_vth = drvr_library_->outputThreshold(drvr_rf_);
- float load_vth = load_library->inputThreshold(drvr_rf_);
- float drvr_slew_delta = drvr_library_->slewUpperThreshold(drvr_rf_)
- - drvr_library_->slewLowerThreshold(drvr_rf_);
+ && drvr_library
+ && load_library != drvr_library) {
+ float drvr_vth = drvr_library->outputThreshold(rf);
+ float load_vth = load_library->inputThreshold(rf);
+ float drvr_slew_delta = drvr_library->slewUpperThreshold(rf)
+ - drvr_library->slewLowerThreshold(rf);
float load_delay_delta =
delayAsFloat(load_slew) * ((load_vth - drvr_vth) / drvr_slew_delta);
- load_delay += (drvr_rf_ == RiseFall::rise())
+ load_delay += (rf == RiseFall::rise())
? load_delay_delta
: -load_delay_delta;
- float load_slew_delta = load_library->slewUpperThreshold(drvr_rf_)
- - load_library->slewLowerThreshold(drvr_rf_);
- float drvr_slew_derate = drvr_library_->slewDerateFromLibrary();
+ float load_slew_delta = load_library->slewUpperThreshold(rf)
+ - load_library->slewLowerThreshold(rf);
+ float drvr_slew_derate = drvr_library->slewDerateFromLibrary();
float load_slew_derate = load_library->slewDerateFromLibrary();
load_slew = load_slew * ((load_slew_delta / load_slew_derate)
/ (drvr_slew_delta / drvr_slew_derate));
@@ -129,4 +144,55 @@ DelayCalcBase::thresholdLibrary(const Pin *load_pin)
}
}
+ArcDelay
+DelayCalcBase::checkDelay(const Pin *check_pin,
+ const TimingArc *arc,
+ const Slew &from_slew,
+ const Slew &to_slew,
+ float related_out_cap,
+ const DcalcAnalysisPt *dcalc_ap)
+{
+ CheckTimingModel *model = checkModel(arc, dcalc_ap);
+ if (model) {
+ float from_slew1 = delayAsFloat(from_slew);
+ float to_slew1 = delayAsFloat(to_slew);
+ return model->checkDelay(pinPvt(check_pin, dcalc_ap), from_slew1, to_slew1,
+ related_out_cap, pocv_enabled_);
+ }
+ else
+ return delay_zero;
+}
+
+string
+DelayCalcBase::reportCheckDelay(const Pin *check_pin,
+ const TimingArc *arc,
+ const Slew &from_slew,
+ const char *from_slew_annotation,
+ const Slew &to_slew,
+ float related_out_cap,
+ const DcalcAnalysisPt *dcalc_ap,
+ int digits)
+{
+ CheckTimingModel *model = checkModel(arc, dcalc_ap);
+ if (model) {
+ float from_slew1 = delayAsFloat(from_slew);
+ float to_slew1 = delayAsFloat(to_slew);
+ return model->reportCheckDelay(pinPvt(check_pin, dcalc_ap), from_slew1,
+ from_slew_annotation, to_slew1,
+ related_out_cap, false, digits);
+ }
+ return "";
+}
+
+const Pvt *
+DelayCalcBase::pinPvt(const Pin *pin,
+ const DcalcAnalysisPt *dcalc_ap)
+{
+ const Instance *drvr_inst = network_->instance(pin);
+ const Pvt *pvt = sdc_->pvt(drvr_inst, dcalc_ap->constraintMinMax());
+ if (pvt == nullptr)
+ pvt = dcalc_ap->operatingConditions();
+ return pvt;
+}
+
} // namespace
diff --git a/dcalc/DelayCalcBase.hh b/dcalc/DelayCalcBase.hh
index 248e8e5a..973f758c 100644
--- a/dcalc/DelayCalcBase.hh
+++ b/dcalc/DelayCalcBase.hh
@@ -20,39 +20,58 @@
namespace sta {
+class GateTableModel;
+
class DelayCalcBase : public ArcDelayCalc
{
public:
explicit DelayCalcBase(StaState *sta);
- void inputPortDelay(const Pin *port_pin,
- float in_slew,
- const RiseFall *rf,
- const Parasitic *parasitic,
+ void finishDrvrPin() override;
+
+ ArcDelay checkDelay(const Pin *check_pin,
+ const TimingArc *arc,
+ const Slew &from_slew,
+ const Slew &to_slew,
+ float related_out_cap,
const DcalcAnalysisPt *dcalc_ap) override;
- void finishDrvrPin() override;
+
+ string reportCheckDelay(const Pin *check_pin,
+ const TimingArc *arc,
+ const Slew &from_slew,
+ const char *from_slew_annotation,
+ const Slew &to_slew,
+ float related_out_cap,
+ const DcalcAnalysisPt *dcalc_ap,
+ int digits) override;
protected:
- void gateDelayInit(const TimingArc *arc,
- const Slew &in_slew,
- const Parasitic *drvr_parasitic);
+ GateTimingModel *gateModel(const TimingArc *arc,
+ const DcalcAnalysisPt *dcalc_ap) const;
+ GateTableModel *gateTableModel(const TimingArc *arc,
+ const DcalcAnalysisPt *dcalc_ap) const;
+ CheckTimingModel *checkModel(const TimingArc *arc,
+ const DcalcAnalysisPt *dcalc_ap) const;
+ TimingModel *model(const TimingArc *arc,
+ const DcalcAnalysisPt *dcalc_ap) const;
// Find the liberty library to use for logic/slew thresholds.
LibertyLibrary *thresholdLibrary(const Pin *load_pin);
// Adjust load_delay and load_slew from driver thresholds to load thresholds.
void thresholdAdjust(const Pin *load_pin,
+ const LibertyLibrary *drvr_library,
+ const RiseFall *rf,
ArcDelay &load_delay,
Slew &load_slew);
// Helper function for input ports driving dspf parasitic.
void dspfWireDelaySlew(const Pin *load_pin,
- float elmore,
+ const RiseFall *rf,
+ Slew drvr_slew,
+ float elmore,
+ // Return values.
ArcDelay &wire_delay,
Slew &load_slew);
+ const Pvt *pinPvt(const Pin *pin,
+ const DcalcAnalysisPt *dcalc_ap);
- Slew drvr_slew_;
- const LibertyCell *drvr_cell_;
- const LibertyLibrary *drvr_library_;
- const Parasitic *drvr_parasitic_;
- bool input_port_;
- const RiseFall *drvr_rf_;
// Parasitics returned by findParasitic that are reduced or estimated
// that can be deleted after delay calculation for the driver pin
// is finished.
diff --git a/dcalc/DmpCeff.cc b/dcalc/DmpCeff.cc
index 0d298a78..da9351a6 100644
--- a/dcalc/DmpCeff.cc
+++ b/dcalc/DmpCeff.cc
@@ -88,7 +88,6 @@ gateModelRd(const LibertyCell *cell,
double in_slew,
double c2,
double c1,
- float related_out_cap,
const Pvt *pvt,
bool pocv_enabled);
static void
@@ -155,7 +154,6 @@ public:
const RiseFall *rf,
double rd,
double in_slew,
- float related_out_cap,
double c2,
double rpi,
double c1);
@@ -235,7 +233,6 @@ protected:
const Pvt *pvt_;
const GateTableModel *gate_model_;
double in_slew_;
- float related_out_cap_;
double c2_;
double rpi_;
double c1_;
@@ -319,7 +316,6 @@ DmpAlg::init(const LibertyLibrary *drvr_library,
const RiseFall *rf,
double rd,
double in_slew,
- float related_out_cap,
// Pi model.
double c2,
double rpi,
@@ -331,7 +327,6 @@ DmpAlg::init(const LibertyLibrary *drvr_library,
gate_model_ = gate_model;
rd_ = rd;
in_slew_ = in_slew;
- related_out_cap_ = related_out_cap;
c2_ = c2;
rpi_ = rpi;
c1_ = c1;
@@ -381,8 +376,8 @@ DmpAlg::gateCapDelaySlew(double ceff,
{
ArcDelay model_delay;
Slew model_slew;
- gate_model_->gateDelay(pvt_, in_slew_, ceff, related_out_cap_,
- pocv_enabled_, model_delay, model_slew);
+ gate_model_->gateDelay(pvt_, in_slew_, ceff, pocv_enabled_,
+ model_delay, model_slew);
delay = delayAsFloat(model_delay);
slew = delayAsFloat(model_slew);
}
@@ -696,7 +691,6 @@ public:
const RiseFall *rf,
double rd,
double in_slew,
- float related_out_cap,
double c2,
double rpi,
double c1);
@@ -729,14 +723,13 @@ DmpCap::init(const LibertyLibrary *drvr_library,
const RiseFall *rf,
double rd,
double in_slew,
- float related_out_cap,
double c2,
double rpi,
double c1)
{
debugPrint(debug_, "dmp_ceff", 3, "Using DMP cap");
DmpAlg::init(drvr_library, drvr_cell, pvt, gate_model, rf,
- rd, in_slew, related_out_cap, c2, rpi, c1);
+ rd, in_slew, c2, rpi, c1);
ceff_ = c1 + c2;
}
@@ -810,7 +803,6 @@ public:
const RiseFall *rf,
double rd,
double in_slew,
- float related_out_cap,
double c2,
double rpi,
double c1);
@@ -870,14 +862,13 @@ DmpPi::init(const LibertyLibrary *drvr_library,
const RiseFall *rf,
double rd,
double in_slew,
- float related_out_cap,
double c2,
double rpi,
double c1)
{
debugPrint(debug_, "dmp_ceff", 3, "Using DMP Pi");
DmpAlg::init(drvr_library, drvr_cell, pvt, gate_model, rf, rd,
- in_slew, related_out_cap, c2, rpi, c1);
+ in_slew, c2, rpi, c1);
// Find poles/zeros.
z1_ = 1.0 / (rpi_ * c1_);
@@ -1144,7 +1135,6 @@ public:
const RiseFall *rf,
double rd,
double in_slew,
- float related_out_cap,
double c2,
double rpi,
double c1);
@@ -1187,14 +1177,13 @@ DmpZeroC2::init(const LibertyLibrary *drvr_library,
const RiseFall *rf,
double rd,
double in_slew,
- float related_out_cap,
double c2,
double rpi,
double c1)
{
debugPrint(debug_, "dmp_ceff", 3, "Using DMP C2=0");
DmpAlg::init(drvr_library, drvr_cell, pvt, gate_model, rf, rd,
- in_slew, related_out_cap, c2, rpi, c1);
+ in_slew, c2, rpi, c1);
ceff_ = c1;
z1_ = 1.0 / (rpi_ * c1_);
@@ -1543,64 +1532,58 @@ DmpCeffDelayCalc::~DmpCeffDelayCalc()
delete dmp_zero_c2_;
}
-void
-DmpCeffDelayCalc::inputPortDelay(const Pin *port_pin,
- float in_slew,
- const RiseFall *rf,
- const Parasitic *parasitic,
- const DcalcAnalysisPt *dcalc_ap)
+ArcDcalcResult
+DmpCeffDelayCalc::gateDelay(const Pin *drvr_pin,
+ const TimingArc *arc,
+ const Slew &in_slew,
+ float load_cap,
+ const Parasitic *parasitic,
+ const LoadPinIndexMap &load_pin_index_map,
+ const DcalcAnalysisPt *dcalc_ap)
{
- dmp_alg_ = nullptr;
- LumpedCapDelayCalc::inputPortDelay(port_pin, in_slew, rf, parasitic, dcalc_ap);
-}
-
-void
-DmpCeffDelayCalc::gateDelay(const TimingArc *arc,
- const Slew &in_slew,
- float load_cap,
- const Parasitic *drvr_parasitic,
- float related_out_cap,
- const Pvt *pvt,
- const DcalcAnalysisPt *dcalc_ap,
- // Return values.
- ArcDelay &gate_delay,
- Slew &drvr_slew)
-{
- input_port_ = false;
- drvr_rf_ = arc->toEdge()->asRiseFall();
+ const RiseFall *rf = arc->toEdge()->asRiseFall();
const LibertyCell *drvr_cell = arc->from()->libertyCell();
- drvr_library_ = drvr_cell->libertyLibrary();
- drvr_parasitic_ = drvr_parasitic;
+ const LibertyLibrary *drvr_library = drvr_cell->libertyLibrary();
- GateTimingModel *model = gateModel(arc, dcalc_ap);
- GateTableModel *table_model = dynamic_cast(model);
- if (table_model && drvr_parasitic) {
+ GateTableModel *table_model = gateTableModel(arc, dcalc_ap);
+ if (table_model && parasitic) {
float in_slew1 = delayAsFloat(in_slew);
float c2, rpi, c1;
- parasitics_->piModel(drvr_parasitic, c2, rpi, c1);
+ parasitics_->piModel(parasitic, c2, rpi, c1);
if (isnan(c2) || isnan(c1) || isnan(rpi))
report_->error(618, "parasitic Pi model has NaNs.");
- setCeffAlgorithm(drvr_library_, drvr_cell, pvt, table_model,
- drvr_rf_, in_slew1, related_out_cap,
- c2, rpi, c1);
- double dmp_gate_delay, dmp_drvr_slew;
- gateDelaySlew(dmp_gate_delay, dmp_drvr_slew);
- gate_delay = dmp_gate_delay;
- drvr_slew = dmp_drvr_slew;
+ setCeffAlgorithm(drvr_library, drvr_cell, pinPvt(drvr_pin, dcalc_ap),
+ table_model, rf, in_slew1, c2, rpi, c1);
+ double gate_delay, drvr_slew;
+ gateDelaySlew(gate_delay, drvr_slew);
+ ArcDcalcResult dcalc_result(load_pin_index_map.size());
+ dcalc_result.setGateDelay(gate_delay);
+ dcalc_result.setDrvrSlew(drvr_slew);
+
+ for (auto load_pin_index : load_pin_index_map) {
+ const Pin *load_pin = load_pin_index.first;
+ size_t load_idx = load_pin_index.second;
+ ArcDelay wire_delay;
+ Slew load_slew;
+ loadDelaySlew(load_pin, drvr_slew, rf, drvr_library, parasitic,
+ wire_delay, load_slew);
+ dcalc_result.setWireDelay(load_idx, wire_delay);
+ dcalc_result.setLoadSlew(load_idx, load_slew);
+ }
+ return dcalc_result;
}
else {
- LumpedCapDelayCalc::gateDelay(arc, in_slew, load_cap, drvr_parasitic,
- related_out_cap, pvt, dcalc_ap,
- gate_delay, drvr_slew);
- if (drvr_parasitic
+ ArcDcalcResult dcalc_result =
+ LumpedCapDelayCalc::gateDelay(drvr_pin, arc, in_slew, load_cap, parasitic,
+ load_pin_index_map, dcalc_ap);
+ if (parasitic
&& !unsuppored_model_warned_) {
unsuppored_model_warned_ = true;
report_->warn(1, "cell %s delay model not supported on SPF parasitics by DMP delay calculator",
drvr_cell->name());
}
+ return dcalc_result;
}
- drvr_slew_ = drvr_slew;
- multi_drvr_slew_factor_ = 1.0F;
}
void
@@ -1610,7 +1593,6 @@ DmpCeffDelayCalc::setCeffAlgorithm(const LibertyLibrary *drvr_library,
const GateTableModel *gate_model,
const RiseFall *rf,
double in_slew,
- float related_out_cap,
double c2,
double rpi,
double c1)
@@ -1618,7 +1600,7 @@ DmpCeffDelayCalc::setCeffAlgorithm(const LibertyLibrary *drvr_library,
double rd = 0.0;
if (gate_model) {
rd = gateModelRd(drvr_cell, gate_model, rf, in_slew, c2, c1,
- related_out_cap, pvt, pocv_enabled_);
+ pvt, pocv_enabled_);
// Zero Rd means the table is constant and thus independent of load cap.
if (rd < 1e-2
// Rpi is small compared to Rd, which makes the load capacitive.
@@ -1635,7 +1617,7 @@ DmpCeffDelayCalc::setCeffAlgorithm(const LibertyLibrary *drvr_library,
else
dmp_alg_ = dmp_cap_;
dmp_alg_->init(drvr_library, drvr_cell, pvt, gate_model,
- drvr_rf_, rd, in_slew, related_out_cap, c2, rpi, c1);
+ rf, rd, in_slew, c2, rpi, c1);
debugPrint(debug_, "dmp_ceff", 3,
" DMP in_slew = %s c2 = %s rpi = %s c1 = %s Rd = %s (%s alg)",
units_->timeUnit()->asString(in_slew),
@@ -1646,51 +1628,29 @@ DmpCeffDelayCalc::setCeffAlgorithm(const LibertyLibrary *drvr_library,
dmp_alg_->name());
}
-float
-DmpCeffDelayCalc::ceff(const TimingArc *arc,
- const Slew &in_slew,
- float load_cap,
- const Parasitic *drvr_parasitic,
- float related_out_cap,
- const Pvt *pvt,
- const DcalcAnalysisPt *dcalc_ap)
-{
- ArcDelay gate_delay;
- Slew drvr_slew;
- gateDelay(arc, in_slew, load_cap, drvr_parasitic, related_out_cap, pvt, dcalc_ap,
- gate_delay, drvr_slew);
- if (dmp_alg_)
- return dmp_alg_->ceff();
- else
- return load_cap;
-}
-
string
-DmpCeffDelayCalc::reportGateDelay(const TimingArc *arc,
+DmpCeffDelayCalc::reportGateDelay(const Pin *drvr_pin,
+ const TimingArc *arc,
const Slew &in_slew,
float load_cap,
- const Parasitic *drvr_parasitic,
- float related_out_cap,
- const Pvt *pvt,
+ const Parasitic *parasitic,
+ const LoadPinIndexMap &load_pin_index_map,
const DcalcAnalysisPt *dcalc_ap,
int digits)
{
- ArcDelay gate_delay;
- Slew drvr_slew;
- gateDelay(arc, in_slew, load_cap, drvr_parasitic, related_out_cap, pvt, dcalc_ap,
- gate_delay, drvr_slew);
+ gateDelay(drvr_pin, arc, in_slew, load_cap, parasitic, load_pin_index_map, dcalc_ap);
GateTimingModel *model = gateModel(arc, dcalc_ap);
float c_eff = 0.0;
string result;
- if (drvr_parasitic_ && dmp_alg_) {
+ if (parasitic && dmp_alg_) {
c_eff = dmp_alg_->ceff();
- const LibertyCell *drvr_cell = arc->from()->libertyCell();
+ const LibertyCell *drvr_cell = arc->to()->libertyCell();
const LibertyLibrary *drvr_library = drvr_cell->libertyLibrary();
const Units *units = drvr_library->units();
const Unit *cap_unit = units->capacitanceUnit();
const Unit *res_unit = units->resistanceUnit();
float c2, rpi, c1;
- parasitics_->piModel(drvr_parasitic_, c2, rpi, c1);
+ parasitics_->piModel(parasitic, c2, rpi, c1);
result += "Pi model C2=";
result += cap_unit->asString(c2, digits);
result += " Rpi=";
@@ -1705,7 +1665,7 @@ DmpCeffDelayCalc::reportGateDelay(const TimingArc *arc,
c_eff = load_cap;
if (model) {
float in_slew1 = delayAsFloat(in_slew);
- result += model->reportGateDelay(pvt, in_slew1, c_eff, related_out_cap,
+ result += model->reportGateDelay(pinPvt(drvr_pin, dcalc_ap), in_slew1, c_eff,
pocv_enabled_, digits);
}
return result;
@@ -1718,7 +1678,6 @@ gateModelRd(const LibertyCell *cell,
double in_slew,
double c2,
double c1,
- float related_out_cap,
const Pvt *pvt,
bool pocv_enabled)
{
@@ -1726,8 +1685,8 @@ gateModelRd(const LibertyCell *cell,
float cap2 = cap1 + 1e-15;
ArcDelay d1, d2;
Slew s1, s2;
- gate_model->gateDelay(pvt, in_slew, cap1, related_out_cap, pocv_enabled, d1, s1);
- gate_model->gateDelay(pvt, in_slew, cap2, related_out_cap, pocv_enabled, d2, s2);
+ gate_model->gateDelay(pvt, in_slew, cap1, pocv_enabled, d1, s1);
+ gate_model->gateDelay(pvt, in_slew, cap2, pocv_enabled, d2, s2);
double vth = cell->libertyLibrary()->outputThreshold(rf);
float rd = -log(vth) * abs(delayAsFloat(d1) - delayAsFloat(d2)) / (cap2 - cap1);
return rd;
@@ -1741,10 +1700,10 @@ DmpCeffDelayCalc::gateDelaySlew(double &delay,
}
void
-DmpCeffDelayCalc::loadDelaySlew(const Pin *load_pin,
- double elmore,
- ArcDelay &delay,
- Slew &slew)
+DmpCeffDelayCalc::loadDelaySlewElmore(const Pin *load_pin,
+ double elmore,
+ ArcDelay &delay,
+ Slew &slew)
{
if (dmp_alg_)
dmp_alg_->loadDelaySlew(load_pin, elmore, delay, slew);
diff --git a/dcalc/DmpCeff.hh b/dcalc/DmpCeff.hh
index b79dbdc6..960b8336 100644
--- a/dcalc/DmpCeff.hh
+++ b/dcalc/DmpCeff.hh
@@ -34,45 +34,39 @@ class DmpCeffDelayCalc : public LumpedCapDelayCalc
public:
DmpCeffDelayCalc(StaState *sta);
virtual ~DmpCeffDelayCalc();
- virtual void inputPortDelay(const Pin *port_pin,
- float in_slew,
- const RiseFall *rf,
- const Parasitic *parasitic,
- const DcalcAnalysisPt *dcalc_ap);
- virtual void gateDelay(const TimingArc *arc,
- const Slew &in_slew,
- float load_cap,
- const Parasitic *drvr_parasitic,
- float related_out_cap,
- const Pvt *pvt,
- const DcalcAnalysisPt *dcalc_ap,
- // return values
- ArcDelay &gate_delay,
- Slew &drvr_slew);
- virtual float ceff(const TimingArc *arc,
- const Slew &in_slew,
- float load_cap,
- const Parasitic *drvr_parasitic,
- float related_out_cap,
- const Pvt *pvt,
- const DcalcAnalysisPt *dcalc_ap);
- virtual string reportGateDelay(const TimingArc *arc,
- const Slew &in_slew,
- float load_cap,
- const Parasitic *drvr_parasitic,
- float related_out_cap,
- const Pvt *pvt,
- const DcalcAnalysisPt *dcalc_ap,
- int digits);
- virtual void copyState(const StaState *sta);
+ ArcDcalcResult gateDelay(const Pin *drvr_pin,
+ const TimingArc *arc,
+ const Slew &in_slew,
+ float load_cap,
+ const Parasitic *parasitic,
+ const LoadPinIndexMap &load_pin_index_map,
+ const DcalcAnalysisPt *dcalc_ap) override;
+ string reportGateDelay(const Pin *drvr_pin,
+ const TimingArc *arc,
+ const Slew &in_slew,
+ float load_cap,
+ const Parasitic *parasitic,
+ const LoadPinIndexMap &load_pin_index_map,
+ const DcalcAnalysisPt *dcalc_ap,
+ int digits) override;
+ void copyState(const StaState *sta) override;
protected:
- void gateDelaySlew(double &delay,
+ virtual void loadDelaySlew(const Pin *load_pin,
+ double drvr_slew,
+ const RiseFall *rf,
+ const LibertyLibrary *drvr_library,
+ const Parasitic *parasitic,
+ // Return values.
+ ArcDelay &wire_delay,
+ Slew &load_slew) = 0;
+ void gateDelaySlew(// Return values.
+ double &delay,
double &slew);
- void loadDelaySlew(const Pin *load_pin,
- double elmore,
- ArcDelay &delay,
- Slew &slew);
+ void loadDelaySlewElmore(const Pin *load_pin,
+ double elmore,
+ ArcDelay &delay,
+ Slew &slew);
// Select the appropriate special case Dartu/Menezes/Pileggi algorithm.
void setCeffAlgorithm(const LibertyLibrary *library,
const LibertyCell *cell,
@@ -80,7 +74,6 @@ protected:
const GateTableModel *gate_model,
const RiseFall *rf,
double in_slew,
- float related_out_cap,
double c2,
double rpi,
double c1);
diff --git a/dcalc/DmpDelayCalc.cc b/dcalc/DmpDelayCalc.cc
index ed97468a..bf0c7802 100644
--- a/dcalc/DmpDelayCalc.cc
+++ b/dcalc/DmpDelayCalc.cc
@@ -35,9 +35,22 @@ class DmpCeffElmoreDelayCalc : public DmpCeffDelayCalc
public:
DmpCeffElmoreDelayCalc(StaState *sta);
ArcDelayCalc *copy() override;
- void loadDelay(const Pin *load_pin,
- ArcDelay &wire_delay,
- Slew &load_slew) override;
+ ArcDcalcResult inputPortDelay(const Pin *port_pin,
+ float in_slew,
+ const RiseFall *rf,
+ const Parasitic *parasitic,
+ const LoadPinIndexMap &load_pin_index_map,
+ const DcalcAnalysisPt *dcalc_ap) override;
+
+protected:
+ void loadDelaySlew(const Pin *load_pin,
+ double drvr_slew,
+ const RiseFall *rf,
+ const LibertyLibrary *drvr_library,
+ const Parasitic *parasitic,
+ // Return values.
+ ArcDelay &wire_delay,
+ Slew &load_slew) override;
};
ArcDelayCalc *
@@ -57,26 +70,54 @@ DmpCeffElmoreDelayCalc::copy()
return new DmpCeffElmoreDelayCalc(this);
}
-void
-DmpCeffElmoreDelayCalc::loadDelay(const Pin *load_pin,
- ArcDelay &wire_delay,
- Slew &load_slew)
+ArcDcalcResult
+DmpCeffElmoreDelayCalc::inputPortDelay(const Pin *,
+ float in_slew,
+ const RiseFall *rf,
+ const Parasitic *parasitic,
+ const LoadPinIndexMap &load_pin_index_map,
+ const DcalcAnalysisPt *)
{
- ArcDelay wire_delay1 = 0.0;
- Slew load_slew1 = drvr_slew_;
+ ArcDcalcResult dcalc_result(load_pin_index_map.size());
+ LibertyLibrary *drvr_library = network_->defaultLibertyLibrary();
+ for (auto load_pin_index : load_pin_index_map) {
+ const Pin *load_pin = load_pin_index.first;
+ size_t load_idx = load_pin_index.second;
+ ArcDelay wire_delay = 0.0;
+ Slew load_slew = in_slew;
+ bool elmore_exists = false;
+ float elmore = 0.0;
+ if (parasitic)
+ parasitics_->findElmore(parasitic, load_pin, elmore, elmore_exists);
+ if (elmore_exists)
+ // Input port with no external driver.
+ dspfWireDelaySlew(load_pin, rf, in_slew, elmore, wire_delay, load_slew);
+ thresholdAdjust(load_pin, drvr_library, rf, wire_delay, load_slew);
+ dcalc_result.setWireDelay(load_idx, wire_delay);
+ dcalc_result.setLoadSlew(load_idx, load_slew);
+ }
+ return dcalc_result;
+}
+
+void
+DmpCeffElmoreDelayCalc::loadDelaySlew(const Pin *load_pin,
+ double drvr_slew,
+ const RiseFall *rf,
+ const LibertyLibrary *drvr_library,
+ const Parasitic *parasitic,
+ // Return values.
+ ArcDelay &wire_delay,
+ Slew &load_slew)
+{
+ wire_delay = 0.0;
+ load_slew = drvr_slew;
bool elmore_exists = false;
float elmore = 0.0;
- if (drvr_parasitic_)
- parasitics_->findElmore(drvr_parasitic_, load_pin, elmore, elmore_exists);
- if (elmore_exists) {
- if (input_port_)
- dspfWireDelaySlew(load_pin, elmore, wire_delay1, load_slew1);
- else
- loadDelaySlew(load_pin, elmore, wire_delay1, load_slew1);
- }
- thresholdAdjust(load_pin, wire_delay1, load_slew1);
- wire_delay = wire_delay1;
- load_slew = load_slew1 * multi_drvr_slew_factor_;
+ if (parasitic)
+ parasitics_->findElmore(parasitic, load_pin, elmore, elmore_exists);
+ if (elmore_exists)
+ loadDelaySlewElmore(load_pin, elmore, wire_delay, load_slew);
+ thresholdAdjust(load_pin, drvr_library, rf, wire_delay, load_slew);
}
////////////////////////////////////////////////////////////////
@@ -91,28 +132,31 @@ public:
Parasitic *findParasitic(const Pin *drvr_pin,
const RiseFall *rf,
const DcalcAnalysisPt *dcalc_ap) override;
- ReducedParasiticType reducedParasiticType() const override;
- void inputPortDelay(const Pin *port_pin,
- float in_slew,
- const RiseFall *rf,
- const Parasitic *parasitic,
- const DcalcAnalysisPt *dcalc_ap) override;
- void gateDelay(const TimingArc *arc,
- const Slew &in_slew,
- float load_cap,
- const Parasitic *drvr_parasitic,
- float related_out_cap,
- const Pvt *pvt,
- const DcalcAnalysisPt *dcalc_ap,
- // Return values.
- ArcDelay &gate_delay,
- Slew &drvr_slew) override;
- void loadDelay(const Pin *load_pin,
- ArcDelay &wire_delay,
- Slew &load_slew) override;
+ ArcDcalcResult inputPortDelay(const Pin *port_pin,
+ float in_slew,
+ const RiseFall *rf,
+ const Parasitic *parasitic,
+ const LoadPinIndexMap &load_pin_index_map,
+ const DcalcAnalysisPt *dcalc_ap) override;
+ ArcDcalcResult gateDelay(const Pin *drvr_pin,
+ const TimingArc *arc,
+ const Slew &in_slew,
+ float load_cap,
+ const Parasitic *parasitic,
+ const LoadPinIndexMap &load_pin_index_map,
+ const DcalcAnalysisPt *dcalc_ap) override;
private:
- void loadDelay(Parasitic *pole_residue,
+ void loadDelaySlew(const Pin *load_pin,
+ double drvr_slew,
+ const RiseFall *rf,
+ const LibertyLibrary *drvr_library,
+ const Parasitic *parasitic,
+ // Return values.
+ ArcDelay &wire_delay,
+ Slew &load_slew) override;
+ void loadDelay(double drvr_slew,
+ Parasitic *pole_residue,
double p1,
double k1,
ArcDelay &wire_delay,
@@ -211,57 +255,81 @@ DmpCeffTwoPoleDelayCalc::findParasitic(const Pin *drvr_pin,
return parasitic;
}
-ReducedParasiticType
-DmpCeffTwoPoleDelayCalc::reducedParasiticType() const
+ArcDcalcResult
+DmpCeffTwoPoleDelayCalc::inputPortDelay(const Pin *,
+ float in_slew,
+ const RiseFall *rf,
+ const Parasitic *parasitic,
+ const LoadPinIndexMap &load_pin_index_map,
+ const DcalcAnalysisPt *)
{
- return ReducedParasiticType::pi_pole_residue2;
+ ArcDcalcResult dcalc_result(load_pin_index_map.size());
+ ArcDelay wire_delay = 0.0;
+ Slew load_slew = in_slew;
+ LibertyLibrary *drvr_library = network_->defaultLibertyLibrary();
+ for (auto load_pin_index : load_pin_index_map) {
+ const Pin *load_pin = load_pin_index.first;
+ size_t load_idx = load_pin_index.second;
+ if (parasitics_->isPiPoleResidue(parasitic)) {
+ const Parasitic *pole_residue = parasitics_->findPoleResidue(parasitic, load_pin);
+ if (pole_residue) {
+ size_t pole_count = parasitics_->poleResidueCount(pole_residue);
+ if (pole_count >= 1) {
+ ComplexFloat pole1, residue1;
+ // Find the 1st (elmore) pole.
+ parasitics_->poleResidue(pole_residue, 0, pole1, residue1);
+ if (pole1.imag() == 0.0
+ && residue1.imag() == 0.0) {
+ float p1 = pole1.real();
+ float elmore = 1.0F / p1;
+ dspfWireDelaySlew(load_pin, rf, in_slew, elmore, wire_delay, load_slew);
+ thresholdAdjust(load_pin, drvr_library, rf, wire_delay, load_slew);
+ }
+ }
+ }
+ }
+ dcalc_result.setWireDelay(load_idx, wire_delay);
+ dcalc_result.setLoadSlew(load_idx, load_slew);
+ }
+ return dcalc_result;
+}
+
+ArcDcalcResult
+DmpCeffTwoPoleDelayCalc::gateDelay(const Pin *drvr_pin,
+ const TimingArc *arc,
+ const Slew &in_slew,
+ float load_cap,
+ const Parasitic *parasitic,
+ const LoadPinIndexMap &load_pin_index_map,
+ const DcalcAnalysisPt *dcalc_ap)
+{
+ const LibertyLibrary *drvr_library = arc->to()->libertyLibrary();
+ const RiseFall *rf = arc->toEdge()->asRiseFall();
+ vth_ = drvr_library->outputThreshold(rf);
+ vl_ = drvr_library->slewLowerThreshold(rf);
+ vh_ = drvr_library->slewUpperThreshold(rf);
+ slew_derate_ = drvr_library->slewDerateFromLibrary();
+ return DmpCeffDelayCalc::gateDelay(drvr_pin, arc, in_slew, load_cap, parasitic,
+ load_pin_index_map, dcalc_ap) ;
}
void
-DmpCeffTwoPoleDelayCalc::inputPortDelay(const Pin *port_pin,
- float in_slew,
- const RiseFall *rf,
- const Parasitic *parasitic,
- const DcalcAnalysisPt *dcalc_ap)
+DmpCeffTwoPoleDelayCalc::loadDelaySlew(const Pin *load_pin,
+ double drvr_slew,
+ const RiseFall *rf,
+ const LibertyLibrary *drvr_library,
+ const Parasitic *parasitic,
+ // Return values.
+ ArcDelay &wire_delay,
+ Slew &load_slew)
{
parasitic_is_pole_residue_ = parasitics_->isPiPoleResidue(parasitic);
- DmpCeffDelayCalc::inputPortDelay(port_pin, in_slew, rf, parasitic, dcalc_ap);
-}
-
-void
-DmpCeffTwoPoleDelayCalc::gateDelay(const TimingArc *arc,
- const Slew &in_slew,
- float load_cap,
- const Parasitic *drvr_parasitic,
- float related_out_cap,
- const Pvt *pvt,
- const DcalcAnalysisPt *dcalc_ap,
- // Return values.
- ArcDelay &gate_delay,
- Slew &drvr_slew)
-{
- gateDelayInit(arc, in_slew, drvr_parasitic);
- parasitic_is_pole_residue_ = parasitics_->isPiPoleResidue(drvr_parasitic);
- vth_ = drvr_library_->outputThreshold(drvr_rf_);
- vl_ = drvr_library_->slewLowerThreshold(drvr_rf_);
- vh_ = drvr_library_->slewUpperThreshold(drvr_rf_);
- slew_derate_ = drvr_library_->slewDerateFromLibrary();
- DmpCeffDelayCalc::gateDelay(arc, in_slew, load_cap, drvr_parasitic,
- related_out_cap, pvt, dcalc_ap,
- gate_delay, drvr_slew);
-}
-
-void
-DmpCeffTwoPoleDelayCalc::loadDelay(const Pin *load_pin,
- ArcDelay &wire_delay,
- Slew &load_slew)
-{
// Should handle PiElmore parasitic.
- ArcDelay wire_delay1 = 0.0;
- Slew load_slew1 = drvr_slew_;
+ wire_delay = 0.0;
+ load_slew = drvr_slew;
Parasitic *pole_residue = 0;
if (parasitic_is_pole_residue_)
- pole_residue = parasitics_->findPoleResidue(drvr_parasitic_, load_pin);
+ pole_residue = parasitics_->findPoleResidue(parasitic, load_pin);
if (pole_residue) {
size_t pole_count = parasitics_->poleResidueCount(pole_residue);
if (pole_count >= 1) {
@@ -272,37 +340,31 @@ DmpCeffTwoPoleDelayCalc::loadDelay(const Pin *load_pin,
&& residue1.imag() == 0.0) {
float p1 = pole1.real();
float k1 = residue1.real();
- if (input_port_) {
- float elmore = 1.0F / p1;
- // Input port with no external driver.
- dspfWireDelaySlew(load_pin, elmore, wire_delay1, load_slew1);
- }
- else {
- if (pole_count >= 2)
- loadDelay(pole_residue, p1, k1, wire_delay1, load_slew1);
- else {
- float elmore = 1.0F / p1;
- wire_delay1 = elmore;
- load_slew1 = drvr_slew_;
- }
- }
+ if (pole_count >= 2)
+ loadDelay(drvr_slew, pole_residue, p1, k1, wire_delay, load_slew);
+ else {
+ float elmore = 1.0F / p1;
+ wire_delay = elmore;
+ load_slew = drvr_slew;
+ }
}
}
}
- thresholdAdjust(load_pin, wire_delay1, load_slew1);
- wire_delay = wire_delay1;
- load_slew = load_slew1 * multi_drvr_slew_factor_;
+ thresholdAdjust(load_pin, drvr_library, rf, wire_delay, load_slew);
}
void
-DmpCeffTwoPoleDelayCalc::loadDelay(Parasitic *pole_residue,
- double p1, double k1,
- ArcDelay &wire_delay,
+DmpCeffTwoPoleDelayCalc::loadDelay(double drvr_slew,
+ Parasitic *pole_residue,
+ double p1,
+ double k1,
+ // Return values.
+ ArcDelay &wire_delay,
Slew &load_slew)
{
ComplexFloat pole2, residue2;
parasitics_->poleResidue(pole_residue, 1, pole2, residue2);
- if (!delayZero(drvr_slew_)
+ if (!delayZero(drvr_slew)
&& pole2.imag() == 0.0
&& residue2.imag() == 0.0) {
double p2 = pole2.real();
@@ -311,7 +373,7 @@ DmpCeffTwoPoleDelayCalc::loadDelay(Parasitic *pole_residue,
double k2_p2_2 = k2 / (p2 * p2);
double B = k1_p1_2 + k2_p2_2;
// Convert tt to 0:1 range.
- float tt = delayAsFloat(drvr_slew_) * slew_derate_ / (vh_ - vl_);
+ float tt = delayAsFloat(drvr_slew) * slew_derate_ / (vh_ - vl_);
double y_tt = (tt - B + k1_p1_2 * exp(-p1 * tt)
+ k2_p2_2 * exp(-p2 * tt)) / tt;
wire_delay = loadDelay(vth_, p1, p2, k1, k2, B, k1_p1_2, k2_p2_2, tt, y_tt)
diff --git a/dcalc/GraphDelayCalc.cc b/dcalc/GraphDelayCalc.cc
index 3f18bd2f..f0414b98 100644
--- a/dcalc/GraphDelayCalc.cc
+++ b/dcalc/GraphDelayCalc.cc
@@ -183,25 +183,10 @@ GraphDelayCalc::deleteVertexBefore(Vertex *vertex)
invalid_delays_->erase(vertex);
MultiDrvrNet *multi_drvr = multiDrvrNet(vertex);
if (multi_drvr) {
- VertexSet *drvrs = multi_drvr->drvrs();
- drvrs->erase(vertex);
- multi_drvr_net_map_.erase(vertex);
- if (drvrs->empty())
- delete multi_drvr;
- else {
- Level max_drvr_level = 0;
- Vertex *max_drvr = nullptr;
- for (Vertex *drvr_vertex : *drvrs) {
- Level drvr_level = drvr_vertex->level();
- if (max_drvr == nullptr
- || drvr_level > max_drvr_level) {
- max_drvr = drvr_vertex;
- max_drvr_level = drvr_level;
- }
- }
- multi_drvr->setDcalcDrvr(max_drvr);
- multi_drvr->findCaps(sdc_);
- }
+ // Don't bother incrementally updating MultiDrvrNet.
+ for (Vertex *drvr_vertex : *multi_drvr->drvrs())
+ multi_drvr_net_map_.erase(drvr_vertex);
+ delete multi_drvr;
}
}
@@ -391,10 +376,12 @@ GraphDelayCalc::seedNoDrvrCellSlew(Vertex *drvr_vertex,
const MinMax *slew_min_max = dcalc_ap->slewMinMax();
if (!drvr_vertex->slewAnnotated(rf, slew_min_max))
graph_->setSlew(drvr_vertex, rf, ap_index, slew);
- arc_delay_calc->inputPortDelay(drvr_pin, delayAsFloat(slew), rf,
- parasitic, dcalc_ap);
- annotateLoadDelays(drvr_vertex, rf, drive_delay, false, dcalc_ap,
- arc_delay_calc);
+ LoadPinIndexMap load_pin_index_map = makeLoadPinIndexMap(drvr_vertex);
+ ArcDcalcResult dcalc_result =
+ arc_delay_calc->inputPortDelay(drvr_pin, delayAsFloat(slew), rf, parasitic,
+ load_pin_index_map, dcalc_ap);
+ annotateLoadDelays(drvr_vertex, rf, dcalc_result, load_pin_index_map,
+ drive_delay, false, dcalc_ap);
arc_delay_calc->finishDrvrPin();
}
@@ -417,10 +404,12 @@ GraphDelayCalc::seedNoDrvrSlew(Vertex *drvr_vertex,
if (!drvr_vertex->slewAnnotated(rf, slew_min_max))
graph_->setSlew(drvr_vertex, rf, ap_index, slew);
Parasitic *parasitic = arc_delay_calc->findParasitic(drvr_pin, rf, dcalc_ap);
- arc_delay_calc->inputPortDelay(drvr_pin, delayAsFloat(slew), rf,
- parasitic, dcalc_ap);
- annotateLoadDelays(drvr_vertex, rf, delay_zero, false, dcalc_ap,
- arc_delay_calc);
+ LoadPinIndexMap load_pin_index_map = makeLoadPinIndexMap(drvr_vertex);
+ ArcDcalcResult dcalc_result =
+ arc_delay_calc->inputPortDelay(drvr_pin, delayAsFloat(slew), rf, parasitic,
+ load_pin_index_map, dcalc_ap);
+ annotateLoadDelays(drvr_vertex, rf, dcalc_result, load_pin_index_map, delay_zero,
+ false, dcalc_ap);
arc_delay_calc->finishDrvrPin();
}
@@ -531,25 +520,26 @@ GraphDelayCalc::findInputArcDelay(const Pin *drvr_pin,
arc->to()->name(),
arc->toEdge()->asString(),
arc->role()->asString());
- RiseFall *drvr_rf = arc->toEdge()->asRiseFall();
+ const RiseFall *drvr_rf = arc->toEdge()->asRiseFall();
if (drvr_rf) {
DcalcAPIndex ap_index = dcalc_ap->index();
- const Pvt *pvt = dcalc_ap->operatingConditions();
- Parasitic *drvr_parasitic = arc_delay_calc_->findParasitic(drvr_pin, drvr_rf,
- dcalc_ap);
- float load_cap = loadCap(drvr_pin, drvr_parasitic, drvr_rf, dcalc_ap);
+ Parasitic *parasitic = arc_delay_calc_->findParasitic(drvr_pin, drvr_rf, dcalc_ap);
+ float load_cap = loadCap(drvr_pin, parasitic, drvr_rf, dcalc_ap);
- ArcDelay intrinsic_delay;
- Slew intrinsic_slew;
- arc_delay_calc_->gateDelay(arc, Slew(from_slew), 0.0, 0, 0.0, pvt, dcalc_ap,
- intrinsic_delay, intrinsic_slew);
+ LoadPinIndexMap load_pin_index_map = makeLoadPinIndexMap(drvr_vertex);
+ ArcDcalcResult intrinsic_result =
+ arc_delay_calc_->gateDelay(drvr_pin, arc, Slew(from_slew), 0.0, nullptr,
+ load_pin_index_map, dcalc_ap);
+ ArcDelay intrinsic_delay = intrinsic_result.gateDelay();
+
+ ArcDcalcResult gate_result = arc_delay_calc_->gateDelay(drvr_pin, arc,
+ Slew(from_slew), load_cap,
+ parasitic,
+ load_pin_index_map,
+ dcalc_ap);
+ ArcDelay gate_delay = gate_result.gateDelay();
+ Slew gate_slew = gate_result.drvrSlew();
- // For input drivers there is no instance to find a related_output_pin.
- ArcDelay gate_delay;
- Slew gate_slew;
- arc_delay_calc_->gateDelay(arc, Slew(from_slew), load_cap,
- drvr_parasitic, 0.0, pvt, dcalc_ap,
- gate_delay, gate_slew);
ArcDelay load_delay = gate_delay - intrinsic_delay;
debugPrint(debug_, "delay_calc", 3,
" gate delay = %s intrinsic = %s slew = %s",
@@ -557,8 +547,8 @@ GraphDelayCalc::findInputArcDelay(const Pin *drvr_pin,
delayAsString(intrinsic_delay, this),
delayAsString(gate_slew, this));
graph_->setSlew(drvr_vertex, drvr_rf, ap_index, gate_slew);
- annotateLoadDelays(drvr_vertex, drvr_rf, load_delay, false, dcalc_ap,
- arc_delay_calc_);
+ annotateLoadDelays(drvr_vertex, drvr_rf, gate_result, load_pin_index_map,
+ load_delay, false, dcalc_ap);
}
}
@@ -651,19 +641,12 @@ GraphDelayCalc::findDriverDelays(Vertex *drvr_vertex,
{
bool delay_changed = false;
MultiDrvrNet *multi_drvr = findMultiDrvrNet(drvr_vertex);
- if (multi_drvr
- && multi_drvr->parallelGates(network_)) {
- Vertex *dcalc_drvr = multi_drvr->dcalcDrvr();
- if (drvr_vertex == dcalc_drvr) {
- initLoadSlews(drvr_vertex);
- arc_delay_calc->findParallelGateDelays(multi_drvr, this);
- for (Vertex *drvr_vertex : *multi_drvr->drvrs())
- delay_changed |= findDriverDelays1(drvr_vertex, multi_drvr, arc_delay_calc);
- }
- }
- else {
+ if (multi_drvr == nullptr
+ || (multi_drvr
+ && (!multi_drvr->parallelGates(network_)
+ || drvr_vertex == multi_drvr->dcalcDrvr()))) {
initLoadSlews(drvr_vertex);
- delay_changed = findDriverDelays1(drvr_vertex, nullptr, arc_delay_calc);
+ delay_changed |= findDriverDelays1(drvr_vertex, multi_drvr, arc_delay_calc);
}
arc_delay_calc->finishDrvrPin();
return delay_changed;
@@ -763,10 +746,17 @@ GraphDelayCalc::findDriverDelays1(Vertex *drvr_vertex,
MultiDrvrNet *multi_drvr,
ArcDelayCalc *arc_delay_calc)
{
- const Pin *drvr_pin = drvr_vertex->pin();
- Instance *drvr_inst = network_->instance(drvr_pin);
initSlew(drvr_vertex);
- initWireDelays(drvr_vertex);
+ if (multi_drvr
+ && multi_drvr->parallelGates(network_)) {
+ // Only init on the trigger driver.
+ if (drvr_vertex == multi_drvr->dcalcDrvr()) {
+ for (auto vertex : *multi_drvr->drvrs())
+ initWireDelays(vertex);
+ }
+ }
+ else
+ initWireDelays(drvr_vertex);
bool delay_changed = false;
bool has_delays = false;
VertexInEdgeIterator edge_iter(drvr_vertex, graph_);
@@ -777,8 +767,8 @@ GraphDelayCalc::findDriverDelays1(Vertex *drvr_vertex,
if (search_pred_->searchFrom(from_vertex)
&& search_pred_->searchThru(edge)
&& !edge->role()->isLatchDtoQ()) {
- delay_changed |= findDriverEdgeDelays(drvr_inst, drvr_pin, drvr_vertex,
- multi_drvr, edge, arc_delay_calc);
+ delay_changed |= findDriverEdgeDelays(drvr_vertex, multi_drvr, edge,
+ arc_delay_calc);
has_delays = true;
}
}
@@ -812,53 +802,329 @@ GraphDelayCalc::findLatchEdgeDelays(Edge *edge)
Instance *drvr_inst = network_->instance(drvr_pin);
debugPrint(debug_, "delay_calc", 2, "find latch D->Q %s",
sdc_network_->pathName(drvr_inst));
- bool delay_changed = findDriverEdgeDelays(drvr_inst, drvr_pin, drvr_vertex,
- nullptr, edge, arc_delay_calc_);
+ bool delay_changed = findDriverEdgeDelays(drvr_vertex, nullptr, edge,
+ arc_delay_calc_);
if (delay_changed && observer_)
observer_->delayChangedTo(drvr_vertex);
}
bool
-GraphDelayCalc::findDriverEdgeDelays(const Instance *drvr_inst,
- const Pin *drvr_pin,
- Vertex *drvr_vertex,
+GraphDelayCalc::findDriverEdgeDelays(Vertex *drvr_vertex,
const MultiDrvrNet *multi_drvr,
Edge *edge,
ArcDelayCalc *arc_delay_calc)
{
- Vertex *in_vertex = edge->from(graph_);
+ Vertex *from_vertex = edge->from(graph_);
const TimingArcSet *arc_set = edge->timingArcSet();
- const LibertyPort *related_out_port = arc_set->relatedOut();
- const Pin *related_out_pin = 0;
bool delay_changed = false;
- if (related_out_port)
- related_out_pin = network_->findPin(drvr_inst, related_out_port);
+ PinSeq load_pins = loadPins(drvr_vertex);
+ LoadPinIndexMap load_pin_index_map = makeLoadPinIndexMap(drvr_vertex);
for (auto dcalc_ap : corners_->dcalcAnalysisPts()) {
- const Pvt *pvt = sdc_->pvt(drvr_inst, dcalc_ap->constraintMinMax());
- if (pvt == nullptr)
- pvt = dcalc_ap->operatingConditions();
- for (TimingArc *arc : arc_set->arcs()) {
- const RiseFall *rf = arc->toEdge()->asRiseFall();
- Parasitic *parasitic = arc_delay_calc->findParasitic(drvr_pin, rf, dcalc_ap);
- float related_out_cap = 0.0;
- if (related_out_pin) {
- Parasitic *related_out_parasitic =
- arc_delay_calc->findParasitic(related_out_pin, rf, dcalc_ap);
- related_out_cap = loadCap(related_out_pin, related_out_parasitic, rf, dcalc_ap);
- }
- delay_changed |= findArcDelay(drvr_pin, drvr_vertex, arc, parasitic,
- related_out_cap, in_vertex, edge, pvt, dcalc_ap,
- multi_drvr, arc_delay_calc);
- }
+ for (const TimingArc *arc : arc_set->arcs())
+ delay_changed |= findDriverArcDelays(drvr_vertex, multi_drvr, edge, arc,
+ load_pin_index_map, dcalc_ap,
+ arc_delay_calc);
}
-
if (delay_changed && observer_) {
- observer_->delayChangedFrom(in_vertex);
+ observer_->delayChangedFrom(from_vertex);
observer_->delayChangedFrom(drvr_vertex);
}
return delay_changed;
}
+void
+GraphDelayCalc::findDriverArcDelays(Vertex *drvr_vertex,
+ Edge *edge,
+ const TimingArc *arc,
+ const DcalcAnalysisPt *dcalc_ap,
+ ArcDelayCalc *arc_delay_calc)
+{
+ MultiDrvrNet *multi_drvr = multiDrvrNet(drvr_vertex);
+ LoadPinIndexMap load_pin_index_map = makeLoadPinIndexMap(drvr_vertex);
+ findDriverArcDelays(drvr_vertex, multi_drvr, edge, arc,
+ load_pin_index_map, dcalc_ap,
+ arc_delay_calc);
+}
+
+bool
+GraphDelayCalc::findDriverArcDelays(Vertex *drvr_vertex,
+ const MultiDrvrNet *multi_drvr,
+ Edge *edge,
+ const TimingArc *arc,
+ LoadPinIndexMap &load_pin_index_map,
+ const DcalcAnalysisPt *dcalc_ap,
+ ArcDelayCalc *arc_delay_calc)
+{
+ bool delay_changed = false;
+ const RiseFall *from_rf = arc->fromEdge()->asRiseFall();
+ const RiseFall *drvr_rf = arc->toEdge()->asRiseFall();
+ if (from_rf && drvr_rf) {
+ const Pin *drvr_pin = drvr_vertex->pin();
+ Parasitic *parasitic = arc_delay_calc->findParasitic(drvr_pin, drvr_rf,
+ dcalc_ap);
+ float load_cap = loadCap(drvr_pin, parasitic, drvr_rf, dcalc_ap, multi_drvr);
+ if (multi_drvr
+ && multi_drvr->parallelGates(network_)) {
+ ArcDcalcArgSeq dcalc_args = makeArcDcalcArgs(drvr_vertex, multi_drvr,
+ edge, arc, dcalc_ap,
+ arc_delay_calc);
+ ArcDcalcResultSeq dcalc_results =
+ arc_delay_calc->gateDelays(dcalc_args, load_cap, load_pin_index_map,
+ dcalc_ap);
+ size_t drvr_count = multi_drvr->drvrs()->size();
+ for (size_t drvr_idx = 0; drvr_idx < drvr_count; drvr_idx++) {
+ ArcDcalcArg &dcalc_arg = dcalc_args[drvr_idx];
+ ArcDcalcResult &dcalc_result = dcalc_results[drvr_idx];
+ delay_changed |= annotateDelaysSlews(dcalc_arg.edge(), dcalc_arg.arc(),
+ dcalc_result, load_pin_index_map,
+ dcalc_ap);
+ }
+ }
+ else {
+ Vertex *from_vertex = edge->from(graph_);
+ const Slew in_slew = edgeFromSlew(from_vertex, from_rf, edge, dcalc_ap);
+ ArcDcalcResult dcalc_result = arc_delay_calc->gateDelay(drvr_pin, arc, in_slew,
+ load_cap, parasitic,
+ load_pin_index_map,
+ dcalc_ap);
+ delay_changed |= annotateDelaysSlews(edge, arc, dcalc_result,
+ load_pin_index_map, dcalc_ap);
+ }
+ }
+ return delay_changed;
+}
+
+ArcDcalcArgSeq
+GraphDelayCalc::makeArcDcalcArgs(Vertex *drvr_vertex,
+ const MultiDrvrNet *multi_drvr,
+ Edge *edge,
+ const TimingArc *arc,
+ const DcalcAnalysisPt *dcalc_ap,
+ ArcDelayCalc *arc_delay_calc)
+{
+ ArcDcalcArgSeq dcalc_args;
+ for (auto drvr_vertex1 : *multi_drvr->drvrs()) {
+ Edge *edge1;
+ const TimingArc *arc1;
+ if (drvr_vertex1 == drvr_vertex) {
+ edge1 = edge;
+ arc1 = arc;
+ }
+ else
+ findParallelEdge(drvr_vertex1, edge, arc, edge1, arc1);
+ Vertex *from_vertex = edge1->from(graph_);
+ const RiseFall *from_rf = arc1->fromEdge()->asRiseFall();
+ const RiseFall *drvr_rf = arc1->toEdge()->asRiseFall();
+ const Slew in_slew = edgeFromSlew(from_vertex, from_rf, edge1, dcalc_ap);
+ const Pin *drvr_pin1 = drvr_vertex1->pin();
+ Parasitic *parasitic = arc_delay_calc->findParasitic(drvr_pin1, drvr_rf,
+ dcalc_ap);
+ dcalc_args.push_back(ArcDcalcArg(drvr_pin1, edge1, arc1, in_slew,
+ parasitic));
+ }
+ return dcalc_args;
+}
+
+// Find an edge/arc for parallel driver vertex to go along with the
+// primary driver drvr_edge/drvr_arc.
+void
+GraphDelayCalc::findParallelEdge(Vertex *vertex,
+ Edge *drvr_edge,
+ const TimingArc *drvr_arc,
+ // Return values.
+ Edge *&edge,
+ const TimingArc *&arc)
+{
+ LibertyCell *drvr_cell = network_->libertyCell(network_->instance(drvr_edge->to(graph_)->pin()));
+ LibertyCell *vertex_cell = network_->libertyCell(network_->instance(vertex->pin()));
+ if (vertex_cell == drvr_cell) {
+ // Homogeneous drivers.
+ arc = drvr_arc;
+ LibertyPort *from_port = network_->libertyPort(edge->from(graph_)->pin());
+ VertexInEdgeIterator edge_iter(vertex, graph_);
+ while (edge_iter.hasNext()) {
+ edge = edge_iter.next();
+ if (network_->libertyPort(edge->from(graph_)->pin()) == from_port)
+ return;
+ }
+ }
+ else {
+ VertexInEdgeIterator edge_iter(vertex, graph_);
+ while (edge_iter.hasNext()) {
+ edge = edge_iter.next();
+ for (TimingArc *arc1 : edge->timingArcSet()->arcs()) {
+ if (arc1->fromEdge() == drvr_arc->fromEdge()
+ && arc1->toEdge() == drvr_arc->toEdge()) {
+ arc = arc1;
+ return;
+ }
+ }
+ }
+ }
+ edge = nullptr;
+ arc = nullptr;
+}
+
+bool
+GraphDelayCalc::annotateDelaysSlews(Edge *edge,
+ const TimingArc *arc,
+ ArcDcalcResult &dcalc_result,
+ LoadPinIndexMap &load_pin_index_map,
+ const DcalcAnalysisPt *dcalc_ap)
+{
+ bool delay_changed = annotateDelaySlew(edge, arc,
+ dcalc_result.gateDelay(),
+ dcalc_result.drvrSlew(), dcalc_ap);
+ if (!edge->role()->isLatchDtoQ()) {
+ Vertex *drvr_vertex = edge->to(graph_);
+ annotateLoadDelays(drvr_vertex, arc->toEdge()->asRiseFall(), dcalc_result,
+ load_pin_index_map, delay_zero, true, dcalc_ap);
+ }
+ return delay_changed;
+}
+
+// Annotate the gate delay and merge the slew at the driver pin.
+// Annotate the wire delays from the gate output to
+// each load pin, and the merge the slews at each load pin.
+bool
+GraphDelayCalc::annotateDelaySlew(Edge *edge,
+ const TimingArc *arc,
+ ArcDelay &gate_delay,
+ Slew &gate_slew,
+ const DcalcAnalysisPt *dcalc_ap)
+{
+ bool delay_changed = false;
+ DcalcAPIndex ap_index = dcalc_ap->index();
+ debugPrint(debug_, "delay_calc", 3,
+ " %s %s -> %s %s (%s) corner:%s/%s",
+ arc->from()->name(),
+ arc->fromEdge()->asString(),
+ arc->to()->name(),
+ arc->toEdge()->asString(),
+ arc->role()->asString(),
+ dcalc_ap->corner()->name(),
+ dcalc_ap->delayMinMax()->asString());
+ debugPrint(debug_, "delay_calc", 3,
+ " gate delay = %s slew = %s",
+ delayAsString(gate_delay, this),
+ delayAsString(gate_slew, this));
+ Vertex *drvr_vertex = edge->to(graph_);
+ const RiseFall *drvr_rf = arc->toEdge()->asRiseFall();
+ // Merge slews.
+ const Slew &drvr_slew = graph_->slew(drvr_vertex, drvr_rf, ap_index);
+ const MinMax *slew_min_max = dcalc_ap->slewMinMax();
+ if (delayGreater(gate_slew, drvr_slew, dcalc_ap->slewMinMax(), this)
+ && !drvr_vertex->slewAnnotated(drvr_rf, slew_min_max)
+ && !edge->role()->isLatchDtoQ())
+ graph_->setSlew(drvr_vertex, drvr_rf, ap_index, gate_slew);
+ if (!graph_->arcDelayAnnotated(edge, arc, ap_index)) {
+ const ArcDelay &prev_gate_delay = graph_->arcDelay(edge,arc,ap_index);
+ float gate_delay1 = delayAsFloat(gate_delay);
+ float prev_gate_delay1 = delayAsFloat(prev_gate_delay);
+ if (prev_gate_delay1 == 0.0
+ || (abs(gate_delay1 - prev_gate_delay1) / prev_gate_delay1
+ > incremental_delay_tolerance_))
+ delay_changed = true;
+ graph_->setArcDelay(edge, arc, ap_index, gate_delay);
+ }
+ return delay_changed;
+}
+
+// Annotate wire arc delays and load pin slews.
+// extra_delay is additional wire delay to add to delay returned
+// by the delay calculator.
+void
+GraphDelayCalc::annotateLoadDelays(Vertex *drvr_vertex,
+ const RiseFall *drvr_rf,
+ ArcDcalcResult &dcalc_result,
+ LoadPinIndexMap &load_pin_index_map,
+ const ArcDelay &extra_delay,
+ bool merge,
+ const DcalcAnalysisPt *dcalc_ap)
+{
+ DcalcAPIndex ap_index = dcalc_ap->index();
+ const MinMax *slew_min_max = dcalc_ap->slewMinMax();
+ VertexOutEdgeIterator edge_iter(drvr_vertex, graph_);
+ while (edge_iter.hasNext()) {
+ Edge *wire_edge = edge_iter.next();
+ if (wire_edge->isWire()) {
+ Vertex *load_vertex = wire_edge->to(graph_);
+ Pin *load_pin = load_vertex->pin();
+ size_t load_idx = load_pin_index_map[load_pin];
+ ArcDelay wire_delay = dcalc_result.wireDelay(load_idx);
+ Slew load_slew = dcalc_result.loadSlew(load_idx);
+ debugPrint(debug_, "delay_calc", 3,
+ " %s load delay = %s slew = %s",
+ load_vertex->name(sdc_network_),
+ delayAsString(wire_delay, this),
+ delayAsString(load_slew, this));
+ if (!load_vertex->slewAnnotated(drvr_rf, slew_min_max)) {
+ if (drvr_vertex->slewAnnotated(drvr_rf, slew_min_max)) {
+ // Copy the driver slew to the load if it is annotated.
+ const Slew &drvr_slew = graph_->slew(drvr_vertex,drvr_rf,ap_index);
+ graph_->setSlew(load_vertex, drvr_rf, ap_index, drvr_slew);
+ }
+ else {
+ const Slew &slew = graph_->slew(load_vertex, drvr_rf, ap_index);
+ if (!merge
+ || delayGreater(load_slew, slew, slew_min_max, this))
+ graph_->setSlew(load_vertex, drvr_rf, ap_index, load_slew);
+ }
+ }
+ if (!graph_->wireDelayAnnotated(wire_edge, drvr_rf, ap_index)) {
+ // Multiple timing arcs with the same output transition
+ // annotate the same wire edges so they must be combined
+ // rather than set.
+ const ArcDelay &delay = graph_->wireArcDelay(wire_edge, drvr_rf, ap_index);
+ Delay wire_delay_extra = extra_delay + wire_delay;
+ const MinMax *delay_min_max = dcalc_ap->delayMinMax();
+ if (!merge
+ || delayGreater(wire_delay_extra, delay, delay_min_max, this)) {
+ graph_->setWireArcDelay(wire_edge, drvr_rf, ap_index, wire_delay_extra);
+ if (observer_)
+ observer_->delayChangedTo(load_vertex);
+ }
+ }
+ // Enqueue bidirect driver from load vertex.
+ if (sdc_->bidirectDrvrSlewFromLoad(load_pin))
+ iter_->enqueue(graph_->pinDrvrVertex(load_pin));
+ }
+ }
+}
+
+PinSeq
+GraphDelayCalc::loadPins(Vertex *drvr_vertex)
+{
+ PinSeq load_pins;
+ VertexOutEdgeIterator edge_iter(drvr_vertex, graph_);
+ while (edge_iter.hasNext()) {
+ Edge *wire_edge = edge_iter.next();
+ if (wire_edge->isWire()) {
+ Vertex *load_vertex = wire_edge->to(graph_);
+ load_pins.push_back(load_vertex->pin());
+ }
+ }
+ return load_pins;
+}
+
+LoadPinIndexMap
+GraphDelayCalc::makeLoadPinIndexMap(Vertex *drvr_vertex)
+{
+ LoadPinIndexMap load_pin_index_map(network_);
+ size_t load_idx = 0;
+ VertexOutEdgeIterator edge_iter(drvr_vertex, graph_);
+ while (edge_iter.hasNext()) {
+ Edge *wire_edge = edge_iter.next();
+ if (wire_edge->isWire()) {
+ Vertex *load_vertex = wire_edge->to(graph_);
+ const Pin *load_pin = load_vertex->pin();
+ load_pin_index_map[load_pin] = load_idx;
+ load_idx++;
+ }
+ }
+ return load_pin_index_map;
+}
+
float
GraphDelayCalc::loadCap(const Pin *drvr_pin,
const DcalcAnalysisPt *dcalc_ap) const
@@ -866,9 +1132,8 @@ GraphDelayCalc::loadCap(const Pin *drvr_pin,
const MinMax *min_max = dcalc_ap->constraintMinMax();
float load_cap = 0.0;
for (auto drvr_rf : RiseFall::range()) {
- Parasitic *drvr_parasitic = arc_delay_calc_->findParasitic(drvr_pin, drvr_rf,
- dcalc_ap);
- float cap = loadCap(drvr_pin, drvr_parasitic, drvr_rf, dcalc_ap, nullptr);
+ Parasitic *parasitic = arc_delay_calc_->findParasitic(drvr_pin, drvr_rf, dcalc_ap);
+ float cap = loadCap(drvr_pin, parasitic, drvr_rf, dcalc_ap, nullptr);
arc_delay_calc_->finishDrvrPin();
if (min_max->compare(cap, load_cap))
load_cap = cap;
@@ -881,24 +1146,24 @@ GraphDelayCalc::loadCap(const Pin *drvr_pin,
const RiseFall *drvr_rf,
const DcalcAnalysisPt *dcalc_ap) const
{
- Parasitic *drvr_parasitic = arc_delay_calc_->findParasitic(drvr_pin, drvr_rf,
+ Parasitic *parasitic = arc_delay_calc_->findParasitic(drvr_pin, drvr_rf,
dcalc_ap);
- float cap = loadCap(drvr_pin, drvr_parasitic, drvr_rf, dcalc_ap, nullptr);
+ float cap = loadCap(drvr_pin, parasitic, drvr_rf, dcalc_ap, nullptr);
return cap;
}
float
GraphDelayCalc::loadCap(const Pin *drvr_pin,
- const Parasitic *drvr_parasitic,
+ const Parasitic *parasitic,
const RiseFall *rf,
const DcalcAnalysisPt *dcalc_ap) const
{
- return loadCap(drvr_pin, drvr_parasitic, rf, dcalc_ap, nullptr);
+ return loadCap(drvr_pin, parasitic, rf, dcalc_ap, nullptr);
}
float
GraphDelayCalc::loadCap(const Pin *drvr_pin,
- const Parasitic *drvr_parasitic,
+ const Parasitic *parasitic,
const RiseFall *rf,
const DcalcAnalysisPt *dcalc_ap,
const MultiDrvrNet *multi_drvr) const
@@ -912,13 +1177,13 @@ GraphDelayCalc::loadCap(const Pin *drvr_pin,
else
netCaps(drvr_pin, rf, dcalc_ap,
pin_cap, wire_cap, fanout, has_net_load);
- loadCap(drvr_parasitic, has_net_load, pin_cap, wire_cap);
+ loadCap(parasitic, has_net_load, pin_cap, wire_cap);
return wire_cap + pin_cap;
}
void
GraphDelayCalc::loadCap(const Pin *drvr_pin,
- const Parasitic *drvr_parasitic,
+ const Parasitic *parasitic,
const RiseFall *rf,
const DcalcAnalysisPt *dcalc_ap,
// Return values.
@@ -930,23 +1195,23 @@ GraphDelayCalc::loadCap(const Pin *drvr_pin,
// Find pin and external pin/wire capacitance.
netCaps(drvr_pin, rf, dcalc_ap,
pin_cap, wire_cap, fanout, has_net_load);
- loadCap(drvr_parasitic, has_net_load, pin_cap, wire_cap);
+ loadCap(parasitic, has_net_load, pin_cap, wire_cap);
}
void
-GraphDelayCalc::loadCap(const Parasitic *drvr_parasitic,
+GraphDelayCalc::loadCap(const Parasitic *parasitic,
bool has_net_load,
// Return values.
float &pin_cap,
float &wire_cap) const
{
// set_load net has precidence over parasitics.
- if (!has_net_load && drvr_parasitic) {
- if (parasitics_->isParasiticNetwork(drvr_parasitic))
- wire_cap += parasitics_->capacitance(drvr_parasitic);
+ if (!has_net_load && parasitic) {
+ if (parasitics_->isParasiticNetwork(parasitic))
+ wire_cap += parasitics_->capacitance(parasitic);
else {
// PiModel includes both pin and external caps.
- float cap = parasitics_->capacitance(drvr_parasitic);
+ float cap = parasitics_->capacitance(parasitic);
if (pin_cap > cap) {
pin_cap = 0.0;
wire_cap = cap;
@@ -1049,80 +1314,6 @@ GraphDelayCalc::initWireDelays(Vertex *drvr_vertex)
}
}
-// Call the arc delay calculator to find the delay thru a single gate
-// input to output timing arc, The wire delays from the gate output to
-// each load pin, and the slew at each load pin. Annotate the graph
-// with the results.
-bool
-GraphDelayCalc::findArcDelay(const Pin *drvr_pin,
- Vertex *drvr_vertex,
- const TimingArc *arc,
- const Parasitic *drvr_parasitic,
- float related_out_cap,
- Vertex *from_vertex,
- Edge *edge,
- const Pvt *pvt,
- const DcalcAnalysisPt *dcalc_ap,
- const MultiDrvrNet *multi_drvr,
- ArcDelayCalc *arc_delay_calc)
-{
- bool delay_changed = false;
- RiseFall *from_rf = arc->fromEdge()->asRiseFall();
- RiseFall *drvr_rf = arc->toEdge()->asRiseFall();
- if (from_rf && drvr_rf) {
- DcalcAPIndex ap_index = dcalc_ap->index();
- debugPrint(debug_, "delay_calc", 3,
- " %s %s -> %s %s (%s) corner:%s/%s",
- arc->from()->name(),
- arc->fromEdge()->asString(),
- arc->to()->name(),
- arc->toEdge()->asString(),
- arc->role()->asString(),
- dcalc_ap->corner()->name(),
- dcalc_ap->delayMinMax()->asString());
- // Delay calculation is done even when the gate delays/slews are
- // annotated because the wire delays may not be annotated.
- const Slew from_slew = edgeFromSlew(from_vertex, from_rf, edge, dcalc_ap);
- ArcDelay gate_delay;
- Slew gate_slew;
- float load_cap = loadCap(drvr_pin, drvr_parasitic, drvr_rf, dcalc_ap, multi_drvr);
- if (multi_drvr
- && multi_drvr->parallelGates(network_))
- arc_delay_calc->parallelGateDelay(drvr_pin, arc, from_slew, load_cap,
- drvr_parasitic, related_out_cap, pvt, dcalc_ap,
- gate_delay, gate_slew);
- else
- arc_delay_calc->gateDelay(arc, from_slew, load_cap, drvr_parasitic,
- related_out_cap, pvt, dcalc_ap,
- gate_delay, gate_slew);
- debugPrint(debug_, "delay_calc", 3,
- " gate delay = %s slew = %s",
- delayAsString(gate_delay, this),
- delayAsString(gate_slew, this));
- // Merge slews.
- const Slew &drvr_slew = graph_->slew(drvr_vertex, drvr_rf, ap_index);
- const MinMax *slew_min_max = dcalc_ap->slewMinMax();
- if (delayGreater(gate_slew, drvr_slew, dcalc_ap->slewMinMax(), this)
- && !drvr_vertex->slewAnnotated(drvr_rf, slew_min_max)
- && !edge->role()->isLatchDtoQ())
- graph_->setSlew(drvr_vertex, drvr_rf, ap_index, gate_slew);
- if (!graph_->arcDelayAnnotated(edge, arc, ap_index)) {
- const ArcDelay &prev_gate_delay = graph_->arcDelay(edge,arc,ap_index);
- float gate_delay1 = delayAsFloat(gate_delay);
- float prev_gate_delay1 = delayAsFloat(prev_gate_delay);
- if (prev_gate_delay1 == 0.0
- || (abs(gate_delay1 - prev_gate_delay1) / prev_gate_delay1
- > incremental_delay_tolerance_))
- delay_changed = true;
- graph_->setArcDelay(edge, arc, ap_index, gate_delay);
- }
- if (!edge->role()->isLatchDtoQ())
- annotateLoadDelays(drvr_vertex, drvr_rf, delay_zero, true, dcalc_ap,
- arc_delay_calc);
- }
- return delay_changed;
-}
-
// Use clock slew for register/latch clk->q edges.
Slew
GraphDelayCalc::edgeFromSlew(const Vertex *from_vertex,
@@ -1139,69 +1330,6 @@ GraphDelayCalc::edgeFromSlew(const Vertex *from_vertex,
return graph_->slew(from_vertex, from_rf, dcalc_ap->index());
}
-// Annotate wire arc delays and load pin slews.
-// extra_delay is additional wire delay to add to delay returned
-// by the delay calculator.
-void
-GraphDelayCalc::annotateLoadDelays(Vertex *drvr_vertex,
- const RiseFall *drvr_rf,
- const ArcDelay &extra_delay,
- bool merge,
- const DcalcAnalysisPt *dcalc_ap,
- ArcDelayCalc *arc_delay_calc)
-{
- DcalcAPIndex ap_index = dcalc_ap->index();
- const MinMax *slew_min_max = dcalc_ap->slewMinMax();
- VertexOutEdgeIterator edge_iter(drvr_vertex, graph_);
- while (edge_iter.hasNext()) {
- Edge *wire_edge = edge_iter.next();
- if (wire_edge->isWire()) {
- Vertex *load_vertex = wire_edge->to(graph_);
- Pin *load_pin = load_vertex->pin();
- ArcDelay wire_delay;
- Slew load_slew;
- arc_delay_calc->loadDelay(load_pin, wire_delay, load_slew);
- debugPrint(debug_, "delay_calc", 3,
- " %s load delay = %s slew = %s",
- load_vertex->name(sdc_network_),
- delayAsString(wire_delay, this),
- delayAsString(load_slew, this));
- if (!load_vertex->slewAnnotated(drvr_rf, slew_min_max)) {
- if (drvr_vertex->slewAnnotated(drvr_rf, slew_min_max)) {
- // Copy the driver slew to the load if it is annotated.
- const Slew &drvr_slew = graph_->slew(drvr_vertex,drvr_rf,ap_index);
- graph_->setSlew(load_vertex, drvr_rf, ap_index, drvr_slew);
- }
- else {
- const Slew &slew = graph_->slew(load_vertex, drvr_rf, ap_index);
- if (!merge
- || delayGreater(load_slew, slew, slew_min_max, this))
- graph_->setSlew(load_vertex, drvr_rf, ap_index, load_slew);
- }
- }
- if (!graph_->wireDelayAnnotated(wire_edge, drvr_rf, ap_index)) {
- // Multiple timing arcs with the same output transition
- // annotate the same wire edges so they must be combined
- // rather than set.
- const ArcDelay &delay = graph_->wireArcDelay(wire_edge, drvr_rf,
- ap_index);
- Delay wire_delay_extra = extra_delay + wire_delay;
- const MinMax *delay_min_max = dcalc_ap->delayMinMax();
- if (!merge
- || delayGreater(wire_delay_extra, delay, delay_min_max, this)) {
- graph_->setWireArcDelay(wire_edge, drvr_rf, ap_index,
- wire_delay_extra);
- if (observer_)
- observer_->delayChangedTo(load_vertex);
- }
- }
- // Enqueue bidirect driver from load vertex.
- if (sdc_->bidirectDrvrSlewFromLoad(load_pin))
- iter_->enqueue(graph_->pinDrvrVertex(load_pin));
- }
- }
-}
-
void
GraphDelayCalc::findCheckEdgeDelays(Edge *edge,
ArcDelayCalc *arc_delay_calc)
@@ -1227,9 +1355,6 @@ GraphDelayCalc::findCheckEdgeDelays(Edge *edge,
for (auto dcalc_ap : corners_->dcalcAnalysisPts()) {
DcalcAPIndex ap_index = dcalc_ap->index();
if (!graph_->arcDelayAnnotated(edge, arc, ap_index)) {
- const Pvt *pvt = sdc_->pvt(inst,dcalc_ap->constraintMinMax());
- if (pvt == nullptr)
- pvt = dcalc_ap->operatingConditions();
const Slew &from_slew = checkEdgeClkSlew(from_vertex, from_rf,
dcalc_ap);
int slew_index = dcalc_ap->checkDataSlewIndex();
@@ -1253,9 +1378,9 @@ GraphDelayCalc::findCheckEdgeDelays(Edge *edge,
related_out_parasitic,
to_rf, dcalc_ap);
}
- ArcDelay check_delay;
- arc_delay_calc->checkDelay(arc, from_slew, to_slew, related_out_cap,
- pvt, dcalc_ap, check_delay);
+ ArcDelay check_delay = arc_delay_calc->checkDelay(to_pin, arc, from_slew,
+ to_slew, related_out_cap,
+ dcalc_ap);
debugPrint(debug_, "delay_calc", 3,
" check_delay = %s",
delayAsString(check_delay, this));
@@ -1285,47 +1410,6 @@ GraphDelayCalc::checkEdgeClkSlew(const Vertex *from_vertex,
////////////////////////////////////////////////////////////////
-float
-GraphDelayCalc::ceff(Edge *edge,
- TimingArc *arc,
- const DcalcAnalysisPt *dcalc_ap)
-{
- Vertex *from_vertex = edge->from(graph_);
- Vertex *to_vertex = edge->to(graph_);
- Pin *to_pin = to_vertex->pin();
- Instance *inst = network_->instance(to_pin);
- const TimingArcSet *arc_set = edge->timingArcSet();
- float ceff = 0.0;
- const Pvt *pvt = sdc_->pvt(inst, dcalc_ap->constraintMinMax());
- if (pvt == nullptr)
- pvt = dcalc_ap->operatingConditions();
- RiseFall *from_rf = arc->fromEdge()->asRiseFall();
- RiseFall *to_rf = arc->toEdge()->asRiseFall();
- if (from_rf && to_rf) {
- const LibertyPort *related_out_port = arc_set->relatedOut();
- const Pin *related_out_pin = 0;
- if (related_out_port)
- related_out_pin = network_->findPin(inst, related_out_port);
- float related_out_cap = 0.0;
- if (related_out_pin) {
- Parasitic *related_out_parasitic =
- arc_delay_calc_->findParasitic(related_out_pin, to_rf, dcalc_ap);
- related_out_cap = loadCap(related_out_pin, related_out_parasitic,
- to_rf, dcalc_ap);
- }
- Parasitic *to_parasitic = arc_delay_calc_->findParasitic(to_pin, to_rf,
- dcalc_ap);
- const Slew &from_slew = edgeFromSlew(from_vertex, from_rf, edge, dcalc_ap);
- float load_cap = loadCap(to_pin, to_parasitic, to_rf, dcalc_ap);
- ceff = arc_delay_calc_->ceff(arc, from_slew, load_cap, to_parasitic,
- related_out_cap, pvt, dcalc_ap);
- arc_delay_calc_->finishDrvrPin();
- }
- return ceff;
-}
-
-////////////////////////////////////////////////////////////////
-
string
GraphDelayCalc::reportDelayCalc(const Edge *edge,
const TimingArc *arc,
@@ -1341,9 +1425,6 @@ GraphDelayCalc::reportDelayCalc(const Edge *edge,
const TimingArcSet *arc_set = edge->timingArcSet();
string result;
DcalcAnalysisPt *dcalc_ap = corner->findDcalcAnalysisPt(min_max);
- const Pvt *pvt = sdc_->pvt(inst, dcalc_ap->constraintMinMax());
- if (pvt == nullptr)
- pvt = dcalc_ap->operatingConditions();
RiseFall *from_rf = arc->fromEdge()->asRiseFall();
RiseFall *to_rf = arc->toEdge()->asRiseFall();
if (from_rf && to_rf) {
@@ -1364,17 +1445,19 @@ GraphDelayCalc::reportDelayCalc(const Edge *edge,
const Slew &to_slew = graph_->slew(to_vertex, to_rf, slew_index);
bool from_ideal_clk = clk_network_->isIdealClock(from_vertex->pin());
const char *from_slew_annotation = from_ideal_clk ? " (ideal clock)" : nullptr;
- result = arc_delay_calc_->reportCheckDelay(arc, from_slew, from_slew_annotation,
- to_slew, related_out_cap, pvt,
- dcalc_ap, digits);
+ result = arc_delay_calc_->reportCheckDelay(to_pin, arc, from_slew,
+ from_slew_annotation, to_slew,
+ related_out_cap, dcalc_ap, digits);
}
else {
Parasitic *to_parasitic =
arc_delay_calc_->findParasitic(to_pin, to_rf, dcalc_ap);
const Slew &from_slew = edgeFromSlew(from_vertex, from_rf, edge, dcalc_ap);
float load_cap = loadCap(to_pin, to_parasitic, to_rf, dcalc_ap);
- result = arc_delay_calc_->reportGateDelay(arc, from_slew, load_cap, to_parasitic,
- related_out_cap, pvt, dcalc_ap, digits);
+ LoadPinIndexMap load_pin_index_map = makeLoadPinIndexMap(to_vertex);
+ result = arc_delay_calc_->reportGateDelay(to_pin, arc, from_slew, load_cap,
+ to_parasitic, load_pin_index_map,
+ dcalc_ap, digits);
}
arc_delay_calc_->finishDrvrPin();
}
diff --git a/dcalc/LumpedCapDelayCalc.cc b/dcalc/LumpedCapDelayCalc.cc
index 5e99dd7a..3f91a37f 100644
--- a/dcalc/LumpedCapDelayCalc.cc
+++ b/dcalc/LumpedCapDelayCalc.cc
@@ -101,132 +101,88 @@ LumpedCapDelayCalc::findParasitic(const Pin *drvr_pin,
return parasitic;
}
-ReducedParasiticType
-LumpedCapDelayCalc::reducedParasiticType() const
+ArcDcalcResult
+LumpedCapDelayCalc::inputPortDelay(const Pin *,
+ float in_slew,
+ const RiseFall *rf,
+ const Parasitic *,
+ const LoadPinIndexMap &load_pin_index_map,
+ const DcalcAnalysisPt *)
{
- return ReducedParasiticType::pi_elmore;
+ const LibertyLibrary *drvr_library = network_->defaultLibertyLibrary();
+ return makeResult(drvr_library,rf, 0.0, in_slew, load_pin_index_map);
}
-float
-LumpedCapDelayCalc::ceff(const TimingArc *,
- const Slew &,
- float load_cap,
- const Parasitic *,
- float,
- const Pvt *,
- const DcalcAnalysisPt *)
-{
- return load_cap;
-}
-
-void
-LumpedCapDelayCalc::gateDelay(const TimingArc *arc,
+ArcDcalcResult
+LumpedCapDelayCalc::gateDelay(const Pin *drvr_pin,
+ const TimingArc *arc,
const Slew &in_slew,
float load_cap,
- const Parasitic *drvr_parasitic,
- float related_out_cap,
- const Pvt *pvt,
- const DcalcAnalysisPt *dcalc_ap,
- // Return values.
- ArcDelay &gate_delay,
- Slew &drvr_slew)
+ const Parasitic *,
+ const LoadPinIndexMap &load_pin_index_map,
+ const DcalcAnalysisPt *dcalc_ap)
{
- gateDelayInit(arc, in_slew, drvr_parasitic);
GateTimingModel *model = gateModel(arc, dcalc_ap);
debugPrint(debug_, "delay_calc", 3,
- " in_slew = %s load_cap = %s related_load_cap = %s lumped",
+ " in_slew = %s load_cap = %s lumped",
delayAsString(in_slew, this),
- units()->capacitanceUnit()->asString(load_cap),
- units()->capacitanceUnit()->asString(related_out_cap));
+ units()->capacitanceUnit()->asString(load_cap));
+ const RiseFall *rf = arc->toEdge()->asRiseFall();
+ const LibertyLibrary *drvr_library = arc->to()->libertyLibrary();
if (model) {
- ArcDelay gate_delay1;
- Slew drvr_slew1;
+ ArcDelay gate_delay;
+ Slew drvr_slew;
float in_slew1 = delayAsFloat(in_slew);
// NaNs cause seg faults during table lookup.
- if (isnan(load_cap) || isnan(related_out_cap) || isnan(delayAsFloat(in_slew)))
+ if (isnan(load_cap) || isnan(delayAsFloat(in_slew)))
report_->error(710, "gate delay input variable is NaN");
- model->gateDelay(pvt, in_slew1, load_cap, related_out_cap,
- pocv_enabled_, gate_delay1, drvr_slew1);
- gate_delay = gate_delay1;
- drvr_slew = drvr_slew1;
- drvr_slew_ = drvr_slew1;
- }
- else {
- gate_delay = delay_zero;
- drvr_slew = delay_zero;
- drvr_slew_ = 0.0;
+ model->gateDelay(pinPvt(drvr_pin, dcalc_ap), in_slew1, load_cap, pocv_enabled_,
+ gate_delay, drvr_slew);
+ return makeResult(drvr_library, rf, gate_delay, drvr_slew, load_pin_index_map);
}
+ else
+ return makeResult(drvr_library, rf, delay_zero, delay_zero, load_pin_index_map);
}
-void
-LumpedCapDelayCalc::loadDelay(const Pin *load_pin,
- ArcDelay &wire_delay,
- Slew &load_slew)
+ArcDcalcResult
+LumpedCapDelayCalc::makeResult(const LibertyLibrary *drvr_library,
+ const RiseFall *rf,
+ ArcDelay gate_delay,
+ Slew drvr_slew,
+ const LoadPinIndexMap &load_pin_index_map)
{
- Delay wire_delay1 = 0.0;
- Slew load_slew1 = drvr_slew_ * multi_drvr_slew_factor_;
- thresholdAdjust(load_pin, wire_delay1, load_slew1);
- wire_delay = wire_delay1;
- load_slew = load_slew1;
+ ArcDcalcResult dcalc_result(load_pin_index_map.size());
+ dcalc_result.setGateDelay(gate_delay);
+ dcalc_result.setDrvrSlew(drvr_slew);
+
+ for (auto load_pin_index : load_pin_index_map) {
+ const Pin *load_pin = load_pin_index.first;
+ size_t load_idx = load_pin_index.second;
+ ArcDelay wire_delay = 0.0;
+ thresholdAdjust(load_pin, drvr_library, rf, wire_delay, drvr_slew);
+ dcalc_result.setWireDelay(load_idx, wire_delay);
+ dcalc_result.setLoadSlew(load_idx, drvr_slew);
+ }
+ return dcalc_result;
}
string
-LumpedCapDelayCalc::reportGateDelay(const TimingArc *arc,
- const Slew &in_slew,
- float load_cap,
- const Parasitic *,
- float related_out_cap,
- const Pvt *pvt,
- const DcalcAnalysisPt *dcalc_ap,
- int digits)
+LumpedCapDelayCalc::reportGateDelay(const Pin *check_pin,
+ const TimingArc *arc,
+ const Slew &in_slew,
+ float load_cap,
+ const Parasitic *,
+ const LoadPinIndexMap &,
+ const DcalcAnalysisPt *dcalc_ap,
+ int digits)
{
GateTimingModel *model = gateModel(arc, dcalc_ap);
if (model) {
float in_slew1 = delayAsFloat(in_slew);
- return model->reportGateDelay(pvt, in_slew1, load_cap, related_out_cap,
+ return model->reportGateDelay(pinPvt(check_pin, dcalc_ap), in_slew1, load_cap,
false, digits);
}
return "";
}
-void
-LumpedCapDelayCalc::checkDelay(const TimingArc *arc,
- const Slew &from_slew,
- const Slew &to_slew,
- float related_out_cap,
- const Pvt *pvt,
- const DcalcAnalysisPt *dcalc_ap,
- // Return values.
- ArcDelay &margin)
-{
- CheckTimingModel *model = checkModel(arc, dcalc_ap);
- if (model) {
- float from_slew1 = delayAsFloat(from_slew);
- float to_slew1 = delayAsFloat(to_slew);
- model->checkDelay(pvt, from_slew1, to_slew1, related_out_cap, pocv_enabled_, margin);
- }
- else
- margin = delay_zero;
-}
-
-string
-LumpedCapDelayCalc::reportCheckDelay(const TimingArc *arc,
- const Slew &from_slew,
- const char *from_slew_annotation,
- const Slew &to_slew,
- float related_out_cap,
- const Pvt *pvt,
- const DcalcAnalysisPt *dcalc_ap,
- int digits)
-{
- CheckTimingModel *model = checkModel(arc, dcalc_ap);
- if (model) {
- float from_slew1 = delayAsFloat(from_slew);
- float to_slew1 = delayAsFloat(to_slew);
- return model->reportCheckDelay(pvt, from_slew1, from_slew_annotation,
- to_slew1, related_out_cap, false, digits);
- }
- return "";
-}
-
} // namespace
diff --git a/dcalc/LumpedCapDelayCalc.hh b/dcalc/LumpedCapDelayCalc.hh
index db7473c0..3ac111c3 100644
--- a/dcalc/LumpedCapDelayCalc.hh
+++ b/dcalc/LumpedCapDelayCalc.hh
@@ -30,54 +30,34 @@ public:
Parasitic *findParasitic(const Pin *drvr_pin,
const RiseFall *rf,
const DcalcAnalysisPt *dcalc_ap) override;
- ReducedParasiticType reducedParasiticType() const override;
- void gateDelay(const TimingArc *arc,
- const Slew &in_slew,
- float load_cap,
- const Parasitic *drvr_parasitic,
- float related_out_cap,
- const Pvt *pvt,
- const DcalcAnalysisPt *dcalc_ap,
- // Return values.
- ArcDelay &gate_delay,
- Slew &drvr_slew) override;
- float ceff(const TimingArc *arc,
- const Slew &in_slew,
- float load_cap,
- const Parasitic *drvr_parasitic,
- float related_out_cap,
- const Pvt *pvt,
- const DcalcAnalysisPt *dcalc_ap) override;
- void loadDelay(const Pin *load_pin,
- // Return values.
- ArcDelay &wire_delay,
- Slew &load_slew) override;
- void checkDelay(const TimingArc *arc,
- const Slew &from_slew,
- const Slew &to_slew,
- float related_out_cap,
- const Pvt *pvt,
- const DcalcAnalysisPt *dcalc_ap,
- // Return values.
- ArcDelay &margin) override;
- string reportGateDelay(const TimingArc *arc,
+ ArcDcalcResult inputPortDelay(const Pin *port_pin,
+ float in_slew,
+ const RiseFall *rf,
+ const Parasitic *parasitic,
+ const LoadPinIndexMap &load_pin_index_map,
+ const DcalcAnalysisPt *dcalc_ap) override;
+ ArcDcalcResult gateDelay(const Pin *drvr_pin,
+ const TimingArc *arc,
+ const Slew &in_slew,
+ float load_cap,
+ const Parasitic *parasitic,
+ const LoadPinIndexMap &load_pin_index_map,
+ const DcalcAnalysisPt *dcalc_ap) override;
+ string reportGateDelay(const Pin *drvr_pin,
+ const TimingArc *arc,
const Slew &in_slew,
float load_cap,
- const Parasitic *drvr_parasitic,
- float related_out_cap,
- const Pvt *pvt,
+ const Parasitic *parasitic,
+ const LoadPinIndexMap &load_pin_index_map,
const DcalcAnalysisPt *dcalc_ap,
int digits) override;
- string reportCheckDelay(const TimingArc *arc,
- const Slew &from_slew,
- const char *from_slew_annotation,
- const Slew &to_slew,
- float related_out_cap,
- const Pvt *pvt,
- const DcalcAnalysisPt *dcalc_ap,
- int digits) override;
protected:
+ ArcDcalcResult makeResult(const LibertyLibrary *drvr_library,
+ const RiseFall *rf,
+ ArcDelay gate_delay,
+ Slew drvr_slew,
+ const LoadPinIndexMap &load_pin_index_map);
};
ArcDelayCalc *
diff --git a/dcalc/ParallelDelayCalc.cc b/dcalc/ParallelDelayCalc.cc
index 62fd90a6..db352812 100644
--- a/dcalc/ParallelDelayCalc.cc
+++ b/dcalc/ParallelDelayCalc.cc
@@ -31,141 +31,65 @@ ParallelDelayCalc::ParallelDelayCalc(StaState *sta):
{
}
-void
-ParallelDelayCalc::inputPortDelay(const Pin *drvr_pin,
- float in_slew,
- const RiseFall *rf,
- const Parasitic *parasitic,
- const DcalcAnalysisPt *dcalc_ap)
+ArcDcalcResultSeq
+ParallelDelayCalc::gateDelays(ArcDcalcArgSeq &dcalc_args,
+ float load_cap,
+ const LoadPinIndexMap &load_pin_index_map,
+ const DcalcAnalysisPt *dcalc_ap)
{
- DelayCalcBase::inputPortDelay(drvr_pin, in_slew, rf, parasitic, dcalc_ap);
- multi_drvr_slew_factor_ = 1.0;
-}
-
-void
-ParallelDelayCalc::gateDelayInit(const TimingArc *arc,
- const Slew &in_slew,
- const Parasitic *drvr_parasitic)
-{
- DelayCalcBase::gateDelayInit(arc, in_slew, drvr_parasitic);
- multi_drvr_slew_factor_ = 1.0F;
-}
-
-void
-ParallelDelayCalc::findParallelGateDelays(const MultiDrvrNet *multi_drvr,
- GraphDelayCalc *dcalc)
-{
- int count = RiseFall::index_count * corners_->dcalcAnalysisPtCount();
- parallel_delays_.resize(count);
- parallel_slews_.resize(count);
- for (auto dcalc_ap : corners_->dcalcAnalysisPts()) {
- for (auto drvr_rf : RiseFall::range()) {
- DcalcAPIndex ap_index = dcalc_ap->index();
- int drvr_rf_index = drvr_rf->index();
- int index = ap_index * RiseFall::index_count + drvr_rf_index;
- findMultiDrvrGateDelay(multi_drvr, drvr_rf, dcalc_ap, dcalc,
- parallel_delays_[index],
- parallel_slews_[index]);
- }
- }
-}
-
-void
-ParallelDelayCalc::findMultiDrvrGateDelay(const MultiDrvrNet *multi_drvr,
- const RiseFall *drvr_rf,
- const DcalcAnalysisPt *dcalc_ap,
- GraphDelayCalc *dcalc,
- // Return values.
- ArcDelay ¶llel_delay,
- Slew ¶llel_slew)
-{
- ArcDelay delay_sum = 0.0;
+ size_t drvr_count = dcalc_args.size();
+ ArcDcalcResultSeq dcalc_results(drvr_count);
Slew slew_sum = 0.0;
- for (Vertex *drvr_vertex : *multi_drvr->drvrs()) {
- Pin *drvr_pin = drvr_vertex->pin();
- Instance *drvr_inst = network_->instance(drvr_pin);
- const Pvt *pvt = sdc_->pvt(drvr_inst, dcalc_ap->constraintMinMax());
- if (pvt == nullptr)
- pvt = dcalc_ap->operatingConditions();
- VertexInEdgeIterator edge_iter(drvr_vertex, graph_);
- while (edge_iter.hasNext()) {
- Edge *edge = edge_iter.next();
- TimingArcSet *arc_set = edge->timingArcSet();
- const LibertyPort *related_out_port = arc_set->relatedOut();
- for (TimingArc *arc : arc_set->arcs()) {
- RiseFall *arc_rf = arc->toEdge()->asRiseFall();
- if (arc_rf == drvr_rf) {
- Vertex *from_vertex = edge->from(graph_);
- RiseFall *from_rf = arc->fromEdge()->asRiseFall();
- Slew from_slew = dcalc->edgeFromSlew(from_vertex, from_rf,
- edge, dcalc_ap);
- ArcDelay intrinsic_delay;
- Slew intrinsic_slew;
- gateDelay(arc, from_slew, 0.0, 0, 0.0, pvt, dcalc_ap,
- intrinsic_delay, intrinsic_slew);
- Parasitic *parasitic = findParasitic(drvr_pin, drvr_rf, dcalc_ap);
- const Pin *related_out_pin = 0;
- float related_out_cap = 0.0;
- if (related_out_port) {
- Instance *inst = network_->instance(drvr_pin);
- related_out_pin = network_->findPin(inst, related_out_port);
- if (related_out_pin) {
- Parasitic *related_out_parasitic = findParasitic(related_out_pin,
- drvr_rf,
- dcalc_ap);
- related_out_cap = dcalc->loadCap(related_out_pin,
- related_out_parasitic,
- drvr_rf, dcalc_ap);
- }
- }
- float load_cap = dcalc->loadCap(drvr_pin, parasitic,
- drvr_rf, dcalc_ap);
- ArcDelay gate_delay;
- Slew gate_slew;
- gateDelay(arc, from_slew, load_cap, parasitic,
- related_out_cap, pvt, dcalc_ap,
- gate_delay, gate_slew);
- delay_sum += 1.0F / (gate_delay - intrinsic_delay);
- slew_sum += 1.0F / gate_slew;
- }
- }
+ ArcDelay load_delay_sum = 0.0;
+ vector intrinsic_delays(dcalc_args.size());
+ vector load_delays(dcalc_args.size());
+ for (size_t drvr_idx = 0; drvr_idx < drvr_count; drvr_idx++) {
+ ArcDcalcArg &dcalc_arg = dcalc_args[drvr_idx];
+ ArcDcalcResult &dcalc_result = dcalc_results[drvr_idx];
+ const Pin *drvr_pin = dcalc_arg.drvrPin();
+ const TimingArc *arc = dcalc_arg.arc();
+ Slew in_slew = dcalc_arg.inSlew();
+
+ ArcDcalcResult intrinsic_result =
+ arc_delay_calc_->gateDelay(drvr_pin, arc, in_slew, 0.0, nullptr,
+ load_pin_index_map, dcalc_ap);
+ ArcDelay intrinsic_delay = intrinsic_result.gateDelay();
+ intrinsic_delays[drvr_idx] = intrinsic_result.gateDelay();
+
+ ArcDcalcResult gate_result = arc_delay_calc_->gateDelay(drvr_pin, arc,
+ in_slew, load_cap,
+ dcalc_arg.parasitic(),
+ load_pin_index_map,
+ dcalc_ap);
+ ArcDelay gate_delay = gate_result.gateDelay();
+ Slew drvr_slew = gate_result.drvrSlew();
+ ArcDelay load_delay = gate_delay - intrinsic_delay;
+ load_delays[drvr_idx] = load_delay;
+
+ if (!delayZero(load_delay))
+ load_delay_sum += 1.0 / load_delay;
+ if (!delayZero(drvr_slew))
+ slew_sum += 1.0 / drvr_slew;
+
+ dcalc_result.setLoadCount(load_pin_index_map.size());
+ for (auto load_pin_index : load_pin_index_map) {
+ size_t load_idx = load_pin_index.second;
+ dcalc_result.setWireDelay(load_idx, gate_result.wireDelay(load_idx));
+ dcalc_result.setLoadSlew(load_idx, gate_result.loadSlew(load_idx));
}
}
- parallel_delay = 1.0F / delay_sum;
- parallel_slew = 1.0F / slew_sum;
-}
-void
-ParallelDelayCalc::parallelGateDelay(const Pin *,
- const TimingArc *arc,
- const Slew &from_slew,
- float load_cap,
- const Parasitic *drvr_parasitic,
- float related_out_cap,
- const Pvt *pvt,
- const DcalcAnalysisPt *dcalc_ap,
- // Return values.
- ArcDelay &gate_delay,
- Slew &gate_slew)
-{
- ArcDelay intrinsic_delay;
- Slew intrinsic_slew;
- gateDelay(arc, from_slew, 0.0, 0, 0.0, pvt, dcalc_ap,
- intrinsic_delay, intrinsic_slew);
- const RiseFall *drvr_rf = arc->toEdge()->asRiseFall();
- int index = dcalc_ap->index() * RiseFall::index_count + drvr_rf->index();
- ArcDelay parallel_delay = parallel_delays_[index];
- Slew parallel_slew = parallel_slews_[index];
- gate_delay = parallel_delay + intrinsic_delay;
- gate_slew = parallel_slew;
+ ArcDelay gate_load_delay = delayZero(load_delay_sum)
+ ? delay_zero
+ : 1.0 / load_delay_sum;
+ ArcDelay drvr_slew = delayZero(slew_sum) ? delay_zero : 1.0 / slew_sum;
- Delay gate_delay1;
- Slew gate_slew1;
- gateDelay(arc, from_slew, load_cap, drvr_parasitic,
- related_out_cap, pvt, dcalc_ap,
- gate_delay1, gate_slew1);
- float factor = delayRatio(gate_slew, gate_slew1);
- multi_drvr_slew_factor_ = factor;
+ for (size_t drvr_idx = 0; drvr_idx < drvr_count; drvr_idx++) {
+ ArcDcalcResult &dcalc_result = dcalc_results[drvr_idx];
+ dcalc_result.setGateDelay(intrinsic_delays[drvr_idx] + gate_load_delay);
+ dcalc_result.setDrvrSlew(drvr_slew);
+ }
+ return dcalc_results;
}
} // namespace
diff --git a/dcalc/ParallelDelayCalc.hh b/dcalc/ParallelDelayCalc.hh
index 68510e99..8079c31d 100644
--- a/dcalc/ParallelDelayCalc.hh
+++ b/dcalc/ParallelDelayCalc.hh
@@ -17,52 +17,21 @@
#pragma once
#include
+#include