Dmp delay calc inline algs
Signed-off-by: James Cherry <cherry@parallaxsw.com>
This commit is contained in:
parent
7fca318611
commit
801d621d6b
317
dcalc/DmpCeff.cc
317
dcalc/DmpCeff.cc
|
|
@ -68,6 +68,17 @@ static const char *dmp_func_index_strings[] = {"y20", "y50", "Ipi"};
|
|||
static double
|
||||
exp2(double x);
|
||||
|
||||
static double
|
||||
gateModelRd(const LibertyCell *cell,
|
||||
const GateTableModel *gate_model,
|
||||
const RiseFall *rf,
|
||||
double in_slew,
|
||||
double c2,
|
||||
double c1,
|
||||
const Pvt *pvt);
|
||||
|
||||
////////////////////////////////////////////////////////////////
|
||||
|
||||
class DmpError : public Exception
|
||||
{
|
||||
public:
|
||||
|
|
@ -78,156 +89,13 @@ private:
|
|||
std::string what_;
|
||||
};
|
||||
|
||||
static double
|
||||
gateModelRd(const LibertyCell *cell,
|
||||
const GateTableModel *gate_model,
|
||||
const RiseFall *rf,
|
||||
double in_slew,
|
||||
double c2,
|
||||
double c1,
|
||||
const Pvt *pvt);
|
||||
////////////////////////////////////////////////////////////////
|
||||
|
||||
// Base class for Dartu/Menezes/Pileggi algorithm.
|
||||
// Derived classes handle different cases of zero values in the Pi model.
|
||||
class DmpAlg : public StaState
|
||||
DmpError::DmpError(std::string_view what) :
|
||||
what_(what)
|
||||
{
|
||||
public:
|
||||
DmpAlg(int nr_order,
|
||||
StaState *sta);
|
||||
~DmpAlg() override = default;
|
||||
virtual std::string_view name() = 0;
|
||||
// Set driver model and pi model parameters for delay calculation.
|
||||
virtual void init(const LibertyLibrary *library,
|
||||
const LibertyCell *drvr_cell,
|
||||
const Pvt *pvt,
|
||||
const GateTableModel *gate_model,
|
||||
const RiseFall *rf,
|
||||
double rd,
|
||||
double in_slew,
|
||||
double c2,
|
||||
double rpi,
|
||||
double c1);
|
||||
virtual std::pair<double, double> gateDelaySlew() = 0;
|
||||
virtual std::pair<double, double> loadDelaySlew(const Pin *load_pin,
|
||||
double elmore);
|
||||
double ceff() { return ceff_; }
|
||||
//sta::print(stdout, "DmpError {}\n", what);
|
||||
}
|
||||
|
||||
// Given x_ as a vector of input parameters, fill fvec_ with the
|
||||
// equations evaluated at x_ and fjac_ with the jabobian evaluated at x_.
|
||||
virtual void evalDmpEqns() = 0;
|
||||
// Output response to vs(t) ramp driving pi model load (vo, dvo_dt).
|
||||
std::pair<double, double> Vo(double t);
|
||||
// Load response to driver waveform (vl, dvl/dt).
|
||||
std::pair<double, double> Vl(double t);
|
||||
|
||||
protected:
|
||||
void luDecomp();
|
||||
void luSolve();
|
||||
void newtonRaphson();
|
||||
// Find driver parameters t0, delta_t, Ceff.
|
||||
void findDriverParams(double ceff);
|
||||
std::pair<double, double> gateCapDelaySlew(double ceff);
|
||||
std::tuple<double, double, double> gateDelays(double ceff);
|
||||
// Partial derivatives of y(t) jacobian (dydt0, dyddt, dydcl).
|
||||
std::tuple<double, double, double> dy(double t,
|
||||
double t0,
|
||||
double dt,
|
||||
double cl);
|
||||
double y0dt(double t,
|
||||
double cl);
|
||||
double y0dcl(double t,
|
||||
double cl);
|
||||
void showX();
|
||||
void showFvec();
|
||||
void showJacobian();
|
||||
std::pair<double, double> findDriverDelaySlew();
|
||||
double findVoCrossing(double vth,
|
||||
double t_lower,
|
||||
double t_upper);
|
||||
void showVo();
|
||||
double findVlCrossing(double vth,
|
||||
double t_lower,
|
||||
double t_upper);
|
||||
void showVl();
|
||||
void fail(std::string_view reason);
|
||||
|
||||
// Output response to vs(t) ramp driving capacitive load (y, t1).
|
||||
std::pair<double, double> y(double t,
|
||||
double t0,
|
||||
double dt,
|
||||
double cl);
|
||||
// Output response to unit ramp driving capacitive load.
|
||||
double y0(double t,
|
||||
double cl);
|
||||
// Output response to unit ramp driving pi model load.
|
||||
// Unit ramp output at pi load (vo, dvo_dt).
|
||||
virtual std::pair<double, double> V0(double t) = 0;
|
||||
// Upper bound on time that vo crosses vh.
|
||||
virtual double voCrossingUpperBound() = 0;
|
||||
// Load responce to driver unit ramp.
|
||||
// Unit ramp load response (vl, dvl_dt).
|
||||
virtual std::pair<double, double> Vl0(double t) = 0;
|
||||
// Upper bound on time that vl crosses vh.
|
||||
double vlCrossingUpperBound();
|
||||
|
||||
// Inputs to the delay calculator.
|
||||
const LibertyCell *drvr_cell_;
|
||||
const LibertyLibrary *drvr_library_;
|
||||
const Pvt *pvt_;
|
||||
const GateTableModel *gate_model_;
|
||||
double in_slew_;
|
||||
double c2_{0.0};
|
||||
double rpi_{0.0};
|
||||
double c1_{0.0};
|
||||
|
||||
double rd_;
|
||||
// Logic threshold (percentage of supply voltage).
|
||||
double vth_;
|
||||
// Slew lower limit (percentage of supply voltage).
|
||||
double vl_;
|
||||
// Slew upper limit (percentage of supply voltage).
|
||||
double vh_;
|
||||
// Table slews are scaled by slew_derate to get
|
||||
// measured slews from vl to vh.
|
||||
double slew_derate_;
|
||||
|
||||
// Driver parameters calculated by this algorithm.
|
||||
double t0_;
|
||||
double dt_;
|
||||
double ceff_;
|
||||
|
||||
// Driver parameter Newton-Raphson state.
|
||||
int nr_order_;
|
||||
|
||||
static constexpr int max_nr_order_ = 3;
|
||||
|
||||
std::array<double, max_nr_order_> x_;
|
||||
std::array<double, max_nr_order_> fvec_;
|
||||
std::array<std::array<double, max_nr_order_>, max_nr_order_> fjac_;
|
||||
std::array<double, max_nr_order_> scale_;
|
||||
std::array<double, max_nr_order_> p_;
|
||||
std::array<int, max_nr_order_> index_;
|
||||
|
||||
// Driver slew used to check load delay.
|
||||
double drvr_slew_;
|
||||
double vo_delay_;
|
||||
// True if the driver parameters are valid for finding the load delays.
|
||||
bool driver_valid_;
|
||||
// Load rspf elmore delay.
|
||||
double elmore_;
|
||||
double p3_;
|
||||
|
||||
// Tolerance (as a scale of value) for driver parameters (Ceff, delta t, t0).
|
||||
static constexpr double driver_param_tol_ = .01;
|
||||
// Waveform threshold crossing time tolerance (1.0 = 100%).
|
||||
static constexpr double vth_time_tol_ = .01;
|
||||
// Max iterations for findRoot.
|
||||
static constexpr int find_root_max_iter_ = 20;
|
||||
static inline int newton_raphson_max_iter_ = 100;
|
||||
// A small number used by luDecomp.
|
||||
static constexpr double tiny_double_ = 1.0e-20;
|
||||
};
|
||||
////////////////////////////////////////////////////////////////
|
||||
|
||||
DmpAlg::DmpAlg(int nr_order,
|
||||
StaState *sta) :
|
||||
|
|
@ -593,33 +461,6 @@ DmpAlg::fail(std::string_view reason)
|
|||
|
||||
////////////////////////////////////////////////////////////////
|
||||
|
||||
// Capacitive load.
|
||||
class DmpCap : public DmpAlg
|
||||
{
|
||||
public:
|
||||
DmpCap(StaState *sta);
|
||||
std::string_view name() override { return "cap"; }
|
||||
void init(const LibertyLibrary *library,
|
||||
const LibertyCell *drvr_cell,
|
||||
const Pvt *pvt,
|
||||
const GateTableModel *gate_model,
|
||||
const RiseFall *rf,
|
||||
double rd,
|
||||
double in_slew,
|
||||
double c2,
|
||||
double rpi,
|
||||
double c1) override;
|
||||
std::pair<double, double> gateDelaySlew() override;
|
||||
std::pair<double, double> loadDelaySlew(const Pin *,
|
||||
double elmore) override;
|
||||
void evalDmpEqns() override;
|
||||
|
||||
protected:
|
||||
double voCrossingUpperBound() override;
|
||||
std::pair<double, double> V0(double t) override;
|
||||
std::pair<double, double> Vl0(double t) override;
|
||||
};
|
||||
|
||||
DmpCap::DmpCap(StaState *sta) :
|
||||
DmpAlg(1,
|
||||
sta)
|
||||
|
|
@ -692,53 +533,6 @@ DmpCap::Vl0(double)
|
|||
|
||||
////////////////////////////////////////////////////////////////
|
||||
|
||||
// No non-zero pi model parameters, two poles, one zero
|
||||
class DmpPi : public DmpAlg
|
||||
{
|
||||
public:
|
||||
DmpPi(StaState *sta);
|
||||
std::string_view name() override { return "Pi"; }
|
||||
void init(const LibertyLibrary *library,
|
||||
const LibertyCell *drvr_cell,
|
||||
const Pvt *pvt,
|
||||
const GateTableModel *gate_model,
|
||||
const RiseFall *rf,
|
||||
double rd,
|
||||
double in_slew,
|
||||
double c2,
|
||||
double rpi,
|
||||
double c1) override;
|
||||
std::pair<double, double> gateDelaySlew() override;
|
||||
void evalDmpEqns() override;
|
||||
|
||||
protected:
|
||||
double voCrossingUpperBound() override;
|
||||
std::pair<double, double> V0(double t) override;
|
||||
std::pair<double, double> Vl0(double t) override;
|
||||
|
||||
private:
|
||||
void findDriverParamsPi();
|
||||
double ipiIceff(double t0,
|
||||
double dt,
|
||||
double ceff_time,
|
||||
double ceff);
|
||||
|
||||
// Poles/zero.
|
||||
double p1_{0.0};
|
||||
double p2_{0.0};
|
||||
double z1_{0.0};
|
||||
// Residues.
|
||||
double k0_{0.0};
|
||||
double k1_{0.0};
|
||||
double k2_{0.0};
|
||||
double k3_{0.0};
|
||||
double k4_{0.0};
|
||||
// Ipi coefficients.
|
||||
double A_{0.0};
|
||||
double B_{0.0};
|
||||
double D_{0.0};
|
||||
};
|
||||
|
||||
DmpPi::DmpPi(StaState *sta) :
|
||||
DmpAlg(3,
|
||||
sta)
|
||||
|
|
@ -940,18 +734,6 @@ DmpPi::voCrossingUpperBound()
|
|||
|
||||
////////////////////////////////////////////////////////////////
|
||||
|
||||
// Capacitive load, so Ceff is known.
|
||||
// Solve for t0, delta t.
|
||||
class DmpOnePole : public DmpAlg
|
||||
{
|
||||
public:
|
||||
DmpOnePole(StaState *sta);
|
||||
void evalDmpEqns() override;
|
||||
|
||||
protected:
|
||||
double voCrossingUpperBound() override;
|
||||
};
|
||||
|
||||
DmpOnePole::DmpOnePole(StaState *sta) :
|
||||
DmpAlg(2,
|
||||
sta)
|
||||
|
|
@ -1000,40 +782,6 @@ DmpOnePole::voCrossingUpperBound()
|
|||
|
||||
////////////////////////////////////////////////////////////////
|
||||
|
||||
// C2 = 0, one pole, one zero.
|
||||
class DmpZeroC2 : public DmpOnePole
|
||||
{
|
||||
public:
|
||||
DmpZeroC2(StaState *sta);
|
||||
std::string_view name() override { return "c2=0"; }
|
||||
void init(const LibertyLibrary *drvr_library,
|
||||
const LibertyCell *drvr_cell,
|
||||
const Pvt *pvt,
|
||||
const GateTableModel *gate_model,
|
||||
const RiseFall *rf,
|
||||
double rd,
|
||||
double in_slew,
|
||||
double c2,
|
||||
double rpi,
|
||||
double c1) override;
|
||||
std::pair<double, double> gateDelaySlew() override;
|
||||
|
||||
protected:
|
||||
std::pair<double, double> V0(double t) override;
|
||||
std::pair<double, double> Vl0(double t) override;
|
||||
double voCrossingUpperBound() override;
|
||||
|
||||
private:
|
||||
// Pole/zero.
|
||||
double p1_{0.0};
|
||||
double z1_{0.0};
|
||||
// Residues.
|
||||
double k0_{0.0};
|
||||
double k1_{0.0};
|
||||
double k2_{0.0};
|
||||
double k3_{0.0};
|
||||
};
|
||||
|
||||
DmpZeroC2::DmpZeroC2(StaState *sta) :
|
||||
DmpOnePole(sta)
|
||||
{
|
||||
|
|
@ -1260,19 +1008,12 @@ bool DmpCeffDelayCalc::unsuppored_model_warned_ = false;
|
|||
|
||||
DmpCeffDelayCalc::DmpCeffDelayCalc(StaState *sta) :
|
||||
LumpedCapDelayCalc(sta),
|
||||
dmp_cap_(new DmpCap(sta)),
|
||||
dmp_pi_(new DmpPi(sta)),
|
||||
dmp_zero_c2_(new DmpZeroC2(sta))
|
||||
dmp_cap_(sta),
|
||||
dmp_pi_(sta),
|
||||
dmp_zero_c2_(sta)
|
||||
{
|
||||
}
|
||||
|
||||
DmpCeffDelayCalc::~DmpCeffDelayCalc()
|
||||
{
|
||||
delete dmp_cap_;
|
||||
delete dmp_pi_;
|
||||
delete dmp_zero_c2_;
|
||||
}
|
||||
|
||||
ArcDcalcResult
|
||||
DmpCeffDelayCalc::gateDelay(const Pin *drvr_pin,
|
||||
const TimingArc *arc,
|
||||
|
|
@ -1362,15 +1103,15 @@ DmpCeffDelayCalc::setCeffAlgorithm(const LibertyLibrary *drvr_library,
|
|||
|| rpi < rd * 1e-3
|
||||
// c1/Rpi can be ignored.
|
||||
|| (c1 == 0.0 || c1 < c2 * 1e-3 || rpi == 0.0))
|
||||
dmp_alg_ = dmp_cap_;
|
||||
dmp_alg_ = &dmp_cap_;
|
||||
else if (c2 < c1 * 1e-3)
|
||||
dmp_alg_ = dmp_zero_c2_;
|
||||
dmp_alg_ = &dmp_zero_c2_;
|
||||
else
|
||||
// The full monty.
|
||||
dmp_alg_ = dmp_pi_;
|
||||
dmp_alg_ = &dmp_pi_;
|
||||
}
|
||||
else
|
||||
dmp_alg_ = dmp_cap_;
|
||||
dmp_alg_ = &dmp_cap_;
|
||||
dmp_alg_->init(drvr_library, drvr_cell, pvt, gate_model, rf, rd, in_slew,
|
||||
c2, rpi, c1);
|
||||
debugPrint(debug_, "dmp_ceff", 3,
|
||||
|
|
@ -1473,15 +1214,9 @@ void
|
|||
DmpCeffDelayCalc::copyState(const StaState *sta)
|
||||
{
|
||||
StaState::copyState(sta);
|
||||
dmp_cap_->copyState(sta);
|
||||
dmp_pi_->copyState(sta);
|
||||
dmp_zero_c2_->copyState(sta);
|
||||
}
|
||||
|
||||
DmpError::DmpError(std::string_view what) :
|
||||
what_(what)
|
||||
{
|
||||
//sta::print(stdout, "DmpError {}\n", what);
|
||||
dmp_cap_.copyState(sta);
|
||||
dmp_pi_.copyState(sta);
|
||||
dmp_zero_c2_.copyState(sta);
|
||||
}
|
||||
|
||||
// This saves about 2.5% in overall run time on designs with SPEF.
|
||||
|
|
|
|||
273
dcalc/DmpCeff.hh
273
dcalc/DmpCeff.hh
|
|
@ -32,19 +32,275 @@
|
|||
|
||||
namespace sta {
|
||||
|
||||
class DmpAlg;
|
||||
class DmpCap;
|
||||
class DmpPi;
|
||||
class DmpZeroC2;
|
||||
class GateTableModel;
|
||||
|
||||
// Base class for Dartu/Menezes/Pileggi algorithm.
|
||||
// Derived classes handle different cases of zero values in the Pi model.
|
||||
class DmpAlg : public StaState
|
||||
{
|
||||
public:
|
||||
DmpAlg(int nr_order,
|
||||
StaState *sta);
|
||||
~DmpAlg() override = default;
|
||||
virtual std::string_view name() = 0;
|
||||
// Set driver model and pi model parameters for delay calculation.
|
||||
virtual void init(const LibertyLibrary *library,
|
||||
const LibertyCell *drvr_cell,
|
||||
const Pvt *pvt,
|
||||
const GateTableModel *gate_model,
|
||||
const RiseFall *rf,
|
||||
double rd,
|
||||
double in_slew,
|
||||
double c2,
|
||||
double rpi,
|
||||
double c1);
|
||||
virtual std::pair<double, double> gateDelaySlew() = 0;
|
||||
virtual std::pair<double, double> loadDelaySlew(const Pin *load_pin,
|
||||
double elmore);
|
||||
double ceff() { return ceff_; }
|
||||
|
||||
// Given x_ as a vector of input parameters, fill fvec_ with the
|
||||
// equations evaluated at x_ and fjac_ with the jabobian evaluated at x_.
|
||||
virtual void evalDmpEqns() = 0;
|
||||
// Output response to vs(t) ramp driving pi model load (vo, dvo_dt).
|
||||
std::pair<double, double> Vo(double t);
|
||||
// Load response to driver waveform (vl, dvl/dt).
|
||||
std::pair<double, double> Vl(double t);
|
||||
|
||||
protected:
|
||||
void luDecomp();
|
||||
void luSolve();
|
||||
void newtonRaphson();
|
||||
// Find driver parameters t0, delta_t, Ceff.
|
||||
void findDriverParams(double ceff);
|
||||
std::pair<double, double> gateCapDelaySlew(double ceff);
|
||||
std::tuple<double, double, double> gateDelays(double ceff);
|
||||
// Partial derivatives of y(t) jacobian (dydt0, dyddt, dydcl).
|
||||
std::tuple<double, double, double> dy(double t,
|
||||
double t0,
|
||||
double dt,
|
||||
double cl);
|
||||
double y0dt(double t,
|
||||
double cl);
|
||||
double y0dcl(double t,
|
||||
double cl);
|
||||
void showX();
|
||||
void showFvec();
|
||||
void showJacobian();
|
||||
std::pair<double, double> findDriverDelaySlew();
|
||||
double findVoCrossing(double vth,
|
||||
double t_lower,
|
||||
double t_upper);
|
||||
void showVo();
|
||||
double findVlCrossing(double vth,
|
||||
double t_lower,
|
||||
double t_upper);
|
||||
void showVl();
|
||||
void fail(std::string_view reason);
|
||||
|
||||
// Output response to vs(t) ramp driving capacitive load (y, t1).
|
||||
std::pair<double, double> y(double t,
|
||||
double t0,
|
||||
double dt,
|
||||
double cl);
|
||||
// Output response to unit ramp driving capacitive load.
|
||||
double y0(double t,
|
||||
double cl);
|
||||
// Output response to unit ramp driving pi model load.
|
||||
// Unit ramp output at pi load (vo, dvo_dt).
|
||||
virtual std::pair<double, double> V0(double t) = 0;
|
||||
// Upper bound on time that vo crosses vh.
|
||||
virtual double voCrossingUpperBound() = 0;
|
||||
// Load responce to driver unit ramp.
|
||||
// Unit ramp load response (vl, dvl_dt).
|
||||
virtual std::pair<double, double> Vl0(double t) = 0;
|
||||
// Upper bound on time that vl crosses vh.
|
||||
double vlCrossingUpperBound();
|
||||
|
||||
// Inputs to the delay calculator.
|
||||
const LibertyCell *drvr_cell_;
|
||||
const LibertyLibrary *drvr_library_;
|
||||
const Pvt *pvt_;
|
||||
const GateTableModel *gate_model_;
|
||||
double in_slew_;
|
||||
double c2_{0.0};
|
||||
double rpi_{0.0};
|
||||
double c1_{0.0};
|
||||
|
||||
double rd_;
|
||||
// Logic threshold (percentage of supply voltage).
|
||||
double vth_;
|
||||
// Slew lower limit (percentage of supply voltage).
|
||||
double vl_;
|
||||
// Slew upper limit (percentage of supply voltage).
|
||||
double vh_;
|
||||
// Table slews are scaled by slew_derate to get
|
||||
// measured slews from vl to vh.
|
||||
double slew_derate_;
|
||||
|
||||
// Driver parameters calculated by this algorithm.
|
||||
double t0_;
|
||||
double dt_;
|
||||
double ceff_;
|
||||
|
||||
// Driver parameter Newton-Raphson state.
|
||||
int nr_order_;
|
||||
|
||||
static constexpr int max_nr_order_ = 3;
|
||||
|
||||
std::array<double, max_nr_order_> x_;
|
||||
std::array<double, max_nr_order_> fvec_;
|
||||
std::array<std::array<double, max_nr_order_>, max_nr_order_> fjac_;
|
||||
std::array<double, max_nr_order_> scale_;
|
||||
std::array<double, max_nr_order_> p_;
|
||||
std::array<int, max_nr_order_> index_;
|
||||
|
||||
// Driver slew used to check load delay.
|
||||
double drvr_slew_;
|
||||
double vo_delay_;
|
||||
// True if the driver parameters are valid for finding the load delays.
|
||||
bool driver_valid_;
|
||||
// Load rspf elmore delay.
|
||||
double elmore_;
|
||||
double p3_;
|
||||
|
||||
// Tolerance (as a scale of value) for driver parameters (Ceff, delta t, t0).
|
||||
static constexpr double driver_param_tol_ = .01;
|
||||
// Waveform threshold crossing time tolerance (1.0 = 100%).
|
||||
static constexpr double vth_time_tol_ = .01;
|
||||
// Max iterations for findRoot.
|
||||
static constexpr int find_root_max_iter_ = 20;
|
||||
static inline int newton_raphson_max_iter_ = 100;
|
||||
// A small number used by luDecomp.
|
||||
static constexpr double tiny_double_ = 1.0e-20;
|
||||
};
|
||||
|
||||
// Capacitive load.
|
||||
class DmpCap : public DmpAlg
|
||||
{
|
||||
public:
|
||||
DmpCap(StaState *sta);
|
||||
std::string_view name() override { return "cap"; }
|
||||
void init(const LibertyLibrary *library,
|
||||
const LibertyCell *drvr_cell,
|
||||
const Pvt *pvt,
|
||||
const GateTableModel *gate_model,
|
||||
const RiseFall *rf,
|
||||
double rd,
|
||||
double in_slew,
|
||||
double c2,
|
||||
double rpi,
|
||||
double c1) override;
|
||||
std::pair<double, double> gateDelaySlew() override;
|
||||
std::pair<double, double> loadDelaySlew(const Pin *,
|
||||
double elmore) override;
|
||||
void evalDmpEqns() override;
|
||||
|
||||
protected:
|
||||
double voCrossingUpperBound() override;
|
||||
std::pair<double, double> V0(double t) override;
|
||||
std::pair<double, double> Vl0(double t) override;
|
||||
};
|
||||
|
||||
// No non-zero pi model parameters, two poles, one zero
|
||||
class DmpPi : public DmpAlg
|
||||
{
|
||||
public:
|
||||
DmpPi(StaState *sta);
|
||||
std::string_view name() override { return "Pi"; }
|
||||
void init(const LibertyLibrary *library,
|
||||
const LibertyCell *drvr_cell,
|
||||
const Pvt *pvt,
|
||||
const GateTableModel *gate_model,
|
||||
const RiseFall *rf,
|
||||
double rd,
|
||||
double in_slew,
|
||||
double c2,
|
||||
double rpi,
|
||||
double c1) override;
|
||||
std::pair<double, double> gateDelaySlew() override;
|
||||
void evalDmpEqns() override;
|
||||
|
||||
protected:
|
||||
double voCrossingUpperBound() override;
|
||||
std::pair<double, double> V0(double t) override;
|
||||
std::pair<double, double> Vl0(double t) override;
|
||||
|
||||
private:
|
||||
void findDriverParamsPi();
|
||||
double ipiIceff(double t0,
|
||||
double dt,
|
||||
double ceff_time,
|
||||
double ceff);
|
||||
|
||||
// Poles/zero.
|
||||
double p1_{0.0};
|
||||
double p2_{0.0};
|
||||
double z1_{0.0};
|
||||
// Residues.
|
||||
double k0_{0.0};
|
||||
double k1_{0.0};
|
||||
double k2_{0.0};
|
||||
double k3_{0.0};
|
||||
double k4_{0.0};
|
||||
// Ipi coefficients.
|
||||
double A_{0.0};
|
||||
double B_{0.0};
|
||||
double D_{0.0};
|
||||
};
|
||||
|
||||
// Capacitive load, so Ceff is known.
|
||||
// Solve for t0, delta t.
|
||||
class DmpOnePole : public DmpAlg
|
||||
{
|
||||
public:
|
||||
DmpOnePole(StaState *sta);
|
||||
void evalDmpEqns() override;
|
||||
|
||||
protected:
|
||||
double voCrossingUpperBound() override;
|
||||
};
|
||||
|
||||
// C2 = 0, one pole, one zero.
|
||||
class DmpZeroC2 : public DmpOnePole
|
||||
{
|
||||
public:
|
||||
DmpZeroC2(StaState *sta);
|
||||
std::string_view name() override { return "c2=0"; }
|
||||
void init(const LibertyLibrary *drvr_library,
|
||||
const LibertyCell *drvr_cell,
|
||||
const Pvt *pvt,
|
||||
const GateTableModel *gate_model,
|
||||
const RiseFall *rf,
|
||||
double rd,
|
||||
double in_slew,
|
||||
double c2,
|
||||
double rpi,
|
||||
double c1) override;
|
||||
std::pair<double, double> gateDelaySlew() override;
|
||||
|
||||
protected:
|
||||
std::pair<double, double> V0(double t) override;
|
||||
std::pair<double, double> Vl0(double t) override;
|
||||
double voCrossingUpperBound() override;
|
||||
|
||||
private:
|
||||
// Pole/zero.
|
||||
double p1_{0.0};
|
||||
double z1_{0.0};
|
||||
// Residues.
|
||||
double k0_{0.0};
|
||||
double k1_{0.0};
|
||||
double k2_{0.0};
|
||||
double k3_{0.0};
|
||||
};
|
||||
|
||||
// Delay calculator using Dartu/Menezes/Pileggi effective capacitance
|
||||
// algorithm for RSPF loads.
|
||||
class DmpCeffDelayCalc : public LumpedCapDelayCalc
|
||||
{
|
||||
public:
|
||||
DmpCeffDelayCalc(StaState *sta);
|
||||
~DmpCeffDelayCalc() override;
|
||||
bool reduceSupported() const override { return true; }
|
||||
ArcDcalcResult gateDelay(const Pin *drvr_pin,
|
||||
const TimingArc *arc,
|
||||
|
|
@ -94,10 +350,9 @@ protected:
|
|||
|
||||
private:
|
||||
// Dmp algorithms for each special pi model case.
|
||||
// These objects are reused to minimize make/deletes.
|
||||
DmpCap *dmp_cap_;
|
||||
DmpPi *dmp_pi_;
|
||||
DmpZeroC2 *dmp_zero_c2_;
|
||||
DmpCap dmp_cap_;
|
||||
DmpPi dmp_pi_;
|
||||
DmpZeroC2 dmp_zero_c2_;
|
||||
DmpAlg *dmp_alg_{nullptr};
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -77,7 +77,7 @@ DmpCeffElmoreDelayCalc::DmpCeffElmoreDelayCalc(StaState *sta) :
|
|||
ArcDelayCalc *
|
||||
DmpCeffElmoreDelayCalc::copy()
|
||||
{
|
||||
return new DmpCeffElmoreDelayCalc(this);
|
||||
return new DmpCeffElmoreDelayCalc(*this);
|
||||
}
|
||||
|
||||
ArcDcalcResult
|
||||
|
|
@ -213,7 +213,7 @@ DmpCeffTwoPoleDelayCalc::DmpCeffTwoPoleDelayCalc(StaState *sta) :
|
|||
ArcDelayCalc *
|
||||
DmpCeffTwoPoleDelayCalc::copy()
|
||||
{
|
||||
return new DmpCeffTwoPoleDelayCalc(this);
|
||||
return new DmpCeffTwoPoleDelayCalc(*this);
|
||||
}
|
||||
|
||||
Parasitic *
|
||||
|
|
|
|||
Loading…
Reference in New Issue