parasitics api update
commit 5eb41d9304fe43d22dcf32b5346a6c9705c0d0b3
Author: James Cherry <cherry@parallaxsw.com>
Date: Thu Feb 8 11:49:16 2024 -0700
tcl endpoint_count
Signed-off-by: James Cherry <cherry@parallaxsw.com>
commit ffb0e0a083edbbdc3753b829641ba26730d3d882
Author: James Cherry <cherry@parallaxsw.com>
Date: Thu Feb 8 10:51:36 2024 -0700
ArcDelayCalc::reduceParasitic
Signed-off-by: James Cherry <cherry@parallaxsw.com>
commit ed167b218ed026b0b7427301ace67c3d22cc969a
Author: James Cherry <cherry@parallaxsw.com>
Date: Wed Feb 7 22:46:40 2024 -0700
parasitics makeResistor/capacitor rm network arg
Signed-off-by: James Cherry <cherry@parallaxsw.com>
commit 41244abfcfdee20ddc9aa8ac80cac2e3e7f68146
Author: James Cherry <cherry@parallaxsw.com>
Date: Wed Feb 7 17:08:04 2024 -0700
arnoldi coupling caps
Signed-off-by: James Cherry <cherry@parallaxsw.com>
commit a14d6880be0dc22bf008cae63ec93880c8347ccf
Author: James Cherry <cherry@parallaxsw.com>
Date: Wed Feb 7 07:28:31 2024 -0700
parasiticLoad
Signed-off-by: James Cherry <cherry@parallaxsw.com>
commit 1cacbd7da71c7f8c5ac311caabd03bb74b66e675
Author: James Cherry <cherry@parallaxsw.com>
Date: Wed Feb 7 07:21:49 2024 -0700
parasitic resistor/capacitor index -> id
Signed-off-by: James Cherry <cherry@parallaxsw.com>
commit 6c749158cc94e5a91376721a8ccb71a8a4d020d5
Author: James Cherry <cherry@parallaxsw.com>
Date: Tue Feb 6 21:42:03 2024 -0700
arnoldi
Signed-off-by: James Cherry <cherry@parallaxsw.com>
commit 4ffa6002224d76321287f64448929e5ef0ec6edd
Author: James Cherry <cherry@parallaxsw.com>
Date: Tue Feb 6 18:27:33 2024 -0700
arnoldi parasitic leak
Signed-off-by: James Cherry <cherry@parallaxsw.com>
commit a9666dd7c44126b262c7bd1170db69fafa5ef327
Author: James Cherry <cherry@parallaxsw.com>
Date: Tue Feb 6 17:05:24 2024 -0700
arnoldi parasitic leak
Signed-off-by: James Cherry <cherry@parallaxsw.com>
commit eca0e8b5ea3b4dbb22a1a2ed11018e6e40229b3f
Author: James Cherry <cherry@parallaxsw.com>
Date: Tue Feb 6 14:40:38 2024 -0700
comment
Signed-Off-by: James Cherry <cherry@parallaxsw.com>
commit 0263245b5e2412ebefbedc67babf23e1ac047c7b
Author: James Cherry <cherry@parallaxsw.com>
Date: Tue Feb 6 14:24:51 2024 -0700
CouplingCap -> Capacitor
Signed-off-by: James Cherry <cherry@parallaxsw.com>
commit f9da059814fb09c44cc3529a9a787c3c2192a4e9
Author: James Cherry <cherry@parallaxsw.com>
Date: Tue Feb 6 09:31:00 2024 -0700
rm parasitic network array if empty
Signed-off-by: James Cherry <cherry@parallaxsw.com>
commit 28c2728e5f2859839818ef228aac51fd0100ae65
Author: James Cherry <cherry@parallaxsw.com>
Date: Tue Feb 6 08:13:03 2024 -0700
parasitic resistor name -> id
Signed-off-by: James Cherry <cherry@parallaxsw.com>
commit 045fd7efa3ae8b1cf07c5aa421f3119022e3895a
Author: James Cherry <cherry@parallaxsw.com>
Date: Mon Feb 5 21:09:39 2024 -0700
Map -> map
Signed-off-by: James Cherry <cherry@parallaxsw.com>
commit 8f7d18eed14a8173d91fd98a4e345a16d168b0ee
Author: James Cherry <cherry@parallaxsw.com>
Date: Mon Feb 5 21:04:35 2024 -0700
ParasiticResistor, ParasiticCapacitor
Signed-off-by: James Cherry <cherry@parallaxsw.com>
commit e2df87a10febc573c77b51a22e82d2d1f6f52af9
Author: James Cherry <cherry@parallaxsw.com>
Date: Mon Feb 5 17:06:34 2024 -0700
rm ParasticNode::devices
Signed-off-by: James Cherry <cherry@parallaxsw.com>
commit 07133b72b73d204d16f964472c38907c18f9758d
Author: James Cherry <cherry@parallaxsw.com>
Date: Mon Feb 5 16:52:43 2024 -0700
Parsitic network nodes instead of nodeIterator
Signed-off-by: James Cherry <cherry@parallaxsw.com>
commit 48c08673b11d0c328ed7d70606b6c7a979d9d0b8
Author: James Cherry <cherry@parallaxsw.com>
Date: Mon Feb 5 16:34:31 2024 -0700
mv otherNode to Parasitics
Signed-off-by: James Cherry <cherry@parallaxsw.com>
commit 99fccc76937c25c68454d8db667306bff2a142ae
Author: James Cherry <cherry@parallaxsw.com>
Date: Mon Feb 5 16:29:23 2024 -0700
ParasiticNetwork resistor/capacitor array
Signed-off-by: James Cherry <cherry@parallaxsw.com>
commit 9de49992ad403d7bc3468c53201d50825d7b961c
Author: James Cherry <cherry@parallaxsw.com>
Date: Mon Feb 5 09:42:01 2024 -0700
SpefNameMap
Signed-off-by: James Cherry <cherry@parallaxsw.com>
commit f296850201debeb2cfe1fd0b9c61c3c196f00d65
Author: James Cherry <cherry@parallaxsw.com>
Date: Mon Feb 5 09:11:17 2024 -0700
comments
Signed-off-by: James Cherry <cherry@parallaxsw.com>
commit 86ca29b9bdeb732c1a596c196e0c4bf91de3ee37
Author: James Cherry <cherry@parallaxsw.com>
Date: Mon Feb 5 08:29:53 2024 -0700
rm Parasitics::reduceTo
Signed-off-by: James Cherry <cherry@parallaxsw.com>
commit 880bf458d473004ee5d3dc33baa62c9e643ddaec
Author: James Cherry <cherry@parallaxsw.com>
Date: Sun Feb 4 20:15:05 2024 -0700
loadCap
Signed-off-by: James Cherry <cherry@parallaxsw.com>
commit 67322e686f4703a2a5d9cdd1dd66534814662fe4
Author: James Cherry <cherry@parallaxsw.com>
Date: Sun Feb 4 09:39:21 2024 -0700
report_parasitic_annotation
Signed-off-by: James Cherry <cherry@parallaxsw.com>
commit 8ef4e9841bca62a5879e74da83cacee70fa50b2f
Author: James Cherry <cherry@parallaxsw.com>
Date: Sat Feb 3 19:13:27 2024 -0700
ParasiticAnalysisPt use string
Signed-off-by: James Cherry <cherry@parallaxsw.com>
commit 109a85ab37b5a869a72738ac6a6cd84e4a1d1ac4
Author: James Cherry <cherry@parallaxsw.com>
Date: Sat Feb 3 18:59:02 2024 -0700
rm ParasiticAnalysisPt::min_max_
Signed-off-by: James Cherry <cherry@parallaxsw.com>
commit bb7874537d20a1fe905779fe46d783dba14e2db6
Author: James Cherry <cherry@parallaxsw.com>
Date: Sat Feb 3 12:21:28 2024 -0700
parasitics rm pole_residue pointer
Signed-off-by: James Cherry <cherry@parallaxsw.com>
commit 9e1e2c484e5cd088a08afc278f25b9fcf2cc5dd9
Author: James Cherry <cherry@parallaxsw.com>
Date: Sat Feb 3 11:54:22 2024 -0700
parasitics rm loads pointer
Signed-off-by: James Cherry <cherry@parallaxsw.com>
commit cb4a7f870b2371a2ac6b3ce1d340bb5d3c24791a
Author: James Cherry <cherry@parallaxsw.com>
Date: Sat Feb 3 08:05:55 2024 -0700
parasitics use override
Signed-off-by: James Cherry <cherry@parallaxsw.com>
commit 8e0f84c4fec0411ad3626c836710545531ef219d
Author: James Cherry <cherry@parallaxsw.com>
Date: Sat Feb 3 07:53:59 2024 -0700
Parasitics::unannotatedLoads
Signed-off-by: James Cherry <cherry@parallaxsw.com>
commit 6b45e369e7be158616219258e6e9a675e87fd8ca
Author: James Cherry <cherry@parallaxsw.com>
Date: Fri Feb 2 12:27:23 2024 -0700
format
Signed-off-by: James Cherry <cherry@parallaxsw.com>
commit 27e820b36caf7867d20307c7045e86486819db6b
Author: James Cherry <cherry@parallaxsw.com>
Date: Thu Feb 1 18:01:51 2024 -0700
rm op_cond args
Signed-off-by: James Cherry <cherry@parallaxsw.com>
commit 351ed53925c7cc9815f75c34a0320b0dc50445d4
Author: James Cherry <cherry@parallaxsw.com>
Date: Wed Jan 31 17:35:15 2024 -0700
rm GraphDelayCalc::loadPins()
Signed-off-by: James Cherry <cherry@parallaxsw.com>
commit 3341c7caff595dab0b7519ab5103958aadfe1510
Author: James Cherry <cherry@parallaxsw.com>
Date: Wed Jan 31 17:31:56 2024 -0700
read_spef arg check
Signed-off-by: James Cherry <cherry@parallaxsw.com>
commit 7d0c1e78b42e33d5298efefa87a982f28f51bc57
Author: James Cherry <cherry@parallaxsw.com>
Date: Wed Jan 31 10:53:35 2024 -0700
arnoldi use parasitics api
Signed-off-by: James Cherry <cherry@parallaxsw.com>
commit 86b39ac10e5c6556a9b0b5b7bce016884cd935ee
Author: James Cherry <cherry@parallaxsw.com>
Date: Wed Jan 31 10:30:47 2024 -0700
range iter
Signed-off-by: James Cherry <cherry@parallaxsw.com>
commit 469fad36af69cc8b76e4dfc88a085962795d7c46
Author: James Cherry <cherry@parallaxsw.com>
Date: Tue Jan 30 16:43:46 2024 -0700
read_spef -reduce
Signed-off-by: James Cherry <cherry@parallaxsw.com>
commit 2b88aa471f083ae895f6277c2c844e308451fff9
Author: James Cherry <cherry@parallaxsw.com>
Date: Mon Jan 29 20:31:47 2024 -0700
Paraasitics::connectionPin() -> pin()
Signed-off-by: James Cherry <cherry@parallaxsw.com>
commit 7b9ff7e228b215b3121b7e7189d9c0c18ced3ef3
Author: James Cherry <cherry@parallaxsw.com>
Date: Mon Jan 29 17:12:32 2024 -0700
ParasiticNode::isExternal()
Signed-off-by: James Cherry <cherry@parallaxsw.com>
commit 889c27af846ed1cdf76295da5262836378ab9162
Author: James Cherry <cherry@parallaxsw.com>
Date: Mon Jan 29 11:17:59 2024 -0700
rm redundant op_cond arg
Signed-off-by: James Cherry <cherry@parallaxsw.com>
commit 7d7ce5e7809bc80f36dd81cb05615a87433ed315
Author: James Cherry <cherry@parallaxsw.com>
Date: Mon Jan 29 11:03:42 2024 -0700
mv estimatePiElmore to Parasitics
Signed-off-by: James Cherry <cherry@parallaxsw.com>
commit 04e1757b3c8b4e9f5cffbe3b03214fc065fb1c2c
Author: James Cherry <cherry@parallaxsw.com>
Date: Mon Jan 29 09:09:28 2024 -0700
ParasiticNode un-virtual
Signed-off-by: James Cherry <cherry@parallaxsw.com>
commit 016ce50f82cbb68f9536d3ed5fd511b2f82f4439
Author: James Cherry <cherry@parallaxsw.com>
Date: Sun Jan 28 17:26:04 2024 -0700
parasitics coupling cap api
Signed-off-by: James Cherry <cherry@parallaxsw.com>
commit 1748629fb462b24b43002ecd3fe1679d367752f4
Author: James Cherry <cherry@parallaxsw.com>
Date: Sun Jan 28 11:12:46 2024 -0700
Parasitics::value rm ap arg
Signed-off-by: James Cherry <cherry@parallaxsw.com>
commit 1272cb86bcae5960c9af7d589f99f1488aa0b322
Author: James Cherry <cherry@parallaxsw.com>
Date: Sun Jan 28 11:10:57 2024 -0700
read_spef rm -quiet arg
Signed-off-by: James Cherry <cherry@parallaxsw.com>
commit 3d86a9d86115dde5f20eb4bb8ca15f0c85de5810
Author: James Cherry <cherry@parallaxsw.com>
Date: Sun Jan 28 11:01:24 2024 -0700
reduce min_max arg
Signed-off-by: James Cherry <cherry@parallaxsw.com>
commit f7abfd5e72e0f74b9ffabf6306bbf809b62d4e98
Author: James Cherry <cherry@parallaxsw.com>
Date: Sun Jan 28 10:59:29 2024 -0700
rm spef_reader
Signed-off-by: James Cherry <cherry@parallaxsw.com>
commit e3550523b1964b2137419240f748a0b44c3322b6
Author: James Cherry <cherry@parallaxsw.com>
Date: Sun Jan 28 10:58:24 2024 -0700
reducers rm op_cond arg
Signed-off-by: James Cherry <cherry@parallaxsw.com>
commit cec793accb3db5c41cdb51f85c8530ffc1e085db
Author: James Cherry <cherry@parallaxsw.com>
Date: Sun Jan 28 10:08:45 2024 -0700
rm NullParastics
Signed-off-by: James Cherry <cherry@parallaxsw.com>
commit 6596d35f6da51cbacb2c21588715773d3b5edb64
Author: James Cherry <cherry@parallaxsw.com>
Date: Sun Jan 28 10:03:29 2024 -0700
ArcDelayCalc::reduceParasitic
Signed-off-by: James Cherry <cherry@parallaxsw.com>
Signed-off-by: James Cherry <cherry@parallaxsw.com>
This commit is contained in:
parent
cc9eb1f12a
commit
902a1bff86
|
|
@ -115,7 +115,6 @@ set(STA_SOURCE
|
|||
|
||||
parasitics/ConcreteParasitics.cc
|
||||
parasitics/EstimateParasitics.cc
|
||||
parasitics/NullParasitics.cc
|
||||
parasitics/Parasitics.cc
|
||||
parasitics/ReduceParasitics.cc
|
||||
parasitics/ReportParasiticAnnotation.cc
|
||||
|
|
|
|||
|
|
@ -64,6 +64,8 @@ public:
|
|||
rcmodel();
|
||||
virtual ~rcmodel();
|
||||
virtual float capacitance() const;
|
||||
virtual PinSet unannotatedLoads(const Pin *drvr_pin,
|
||||
const Parasitics *parasitics) const;
|
||||
|
||||
const Pin **pinV; // [n]
|
||||
};
|
||||
|
|
|
|||
|
|
@ -30,6 +30,7 @@
|
|||
#include "TimingModel.hh"
|
||||
#include "TimingArc.hh"
|
||||
#include "TableModel.hh"
|
||||
#include "PortDirection.hh"
|
||||
#include "Network.hh"
|
||||
#include "Graph.hh"
|
||||
#include "Parasitics.hh"
|
||||
|
|
@ -117,7 +118,10 @@ public:
|
|||
Parasitic *findParasitic(const Pin *drvr_pin,
|
||||
const RiseFall *rf,
|
||||
const DcalcAnalysisPt *dcalc_ap) override;
|
||||
ReducedParasiticType reducedParasiticType() const override;
|
||||
Parasitic *reduceParasitic(const Parasitic *parasitic_network,
|
||||
const Pin *drvr_pin,
|
||||
const RiseFall *rf,
|
||||
const DcalcAnalysisPt *dcalc_ap) override;
|
||||
ArcDcalcResult inputPortDelay(const Pin *port_pin,
|
||||
float in_slew,
|
||||
const RiseFall *rf,
|
||||
|
|
@ -140,6 +144,7 @@ public:
|
|||
const LoadPinIndexMap &load_pin_index_map,
|
||||
const DcalcAnalysisPt *dcalc_ap,
|
||||
int digits) override;
|
||||
void finishDrvrPin() override;
|
||||
void delay_work_set_thresholds(delay_work *D,
|
||||
double lo,
|
||||
double hi,
|
||||
|
|
@ -219,6 +224,7 @@ private:
|
|||
int pin_n_;
|
||||
ArnoldiReduce *reduce_;
|
||||
delay_work *delay_work_;
|
||||
vector<rcmodel*> unsaved_parasitics_;
|
||||
};
|
||||
|
||||
ArcDelayCalc *
|
||||
|
|
@ -259,49 +265,53 @@ ArnoldiDelayCalc::findParasitic(const Pin *drvr_pin,
|
|||
Parasitic *parasitic = nullptr;
|
||||
const Corner *corner = dcalc_ap->corner();
|
||||
// set_load net has precedence over parasitics.
|
||||
if (!sdc_->drvrPinHasWireCap(drvr_pin, corner)) {
|
||||
const ParasiticAnalysisPt *parasitic_ap = dcalc_ap->parasiticAnalysisPt();
|
||||
Parasitic *parasitic_network =
|
||||
parasitics_->findParasiticNetwork(drvr_pin, parasitic_ap);
|
||||
bool delete_parasitic_network = false;
|
||||
|
||||
const MinMax *cnst_min_max = dcalc_ap->constraintMinMax();
|
||||
const OperatingConditions *op_cond = dcalc_ap->operatingConditions();
|
||||
if (parasitic_network == nullptr) {
|
||||
Wireload *wireload = sdc_->wireload(cnst_min_max);
|
||||
if (wireload) {
|
||||
float pin_cap, wire_cap, fanout;
|
||||
bool has_wire_cap;
|
||||
graph_delay_calc_->netCaps(drvr_pin, drvr_rf, dcalc_ap,
|
||||
pin_cap, wire_cap, fanout, has_wire_cap);
|
||||
parasitic_network = parasitics_->makeWireloadNetwork(drvr_pin, wireload,
|
||||
fanout, op_cond,
|
||||
parasitic_ap);
|
||||
delete_parasitic_network = true;
|
||||
}
|
||||
if (sdc_->drvrPinHasWireCap(drvr_pin, corner)
|
||||
|| network_->direction(drvr_pin)->isInternal())
|
||||
return nullptr;
|
||||
const ParasiticAnalysisPt *parasitic_ap = dcalc_ap->parasiticAnalysisPt();
|
||||
Parasitic *parasitic_network =
|
||||
parasitics_->findParasiticNetwork(drvr_pin, parasitic_ap);
|
||||
const MinMax *min_max = dcalc_ap->constraintMinMax();
|
||||
if (parasitic_network == nullptr) {
|
||||
Wireload *wireload = sdc_->wireload(min_max);
|
||||
if (wireload) {
|
||||
float pin_cap, wire_cap, fanout;
|
||||
bool has_wire_cap;
|
||||
graph_delay_calc_->netCaps(drvr_pin, drvr_rf, dcalc_ap,
|
||||
pin_cap, wire_cap, fanout, has_wire_cap);
|
||||
parasitic_network = parasitics_->makeWireloadNetwork(drvr_pin, wireload,
|
||||
fanout, min_max,
|
||||
parasitic_ap);
|
||||
}
|
||||
}
|
||||
|
||||
if (parasitic_network) {
|
||||
parasitic = reduce_->reduceToArnoldi(parasitic_network,
|
||||
drvr_pin,
|
||||
parasitic_ap->couplingCapFactor(),
|
||||
drvr_rf, op_cond, corner,
|
||||
cnst_min_max, parasitic_ap);
|
||||
if (delete_parasitic_network) {
|
||||
Net *net = network_->net(drvr_pin);
|
||||
parasitics_->deleteParasiticNetwork(net, parasitic_ap);
|
||||
}
|
||||
// Arnoldi parasitics are their own class that are not saved in the parasitic db.
|
||||
unsaved_parasitics_.push_back(parasitic);
|
||||
}
|
||||
if (parasitic_network) {
|
||||
rcmodel *rcmodel = reduce_->reduceToArnoldi(parasitic_network, drvr_pin,
|
||||
parasitic_ap->couplingCapFactor(),
|
||||
drvr_rf, corner, min_max, parasitic_ap);
|
||||
// Arnoldi parasitics are their own class that are not saved in the parasitic db.
|
||||
unsaved_parasitics_.push_back(rcmodel);
|
||||
parasitic = rcmodel;
|
||||
}
|
||||
return parasitic;
|
||||
}
|
||||
|
||||
ReducedParasiticType
|
||||
ArnoldiDelayCalc::reducedParasiticType() const
|
||||
Parasitic *
|
||||
ArnoldiDelayCalc::reduceParasitic(const Parasitic *,
|
||||
const Pin *,
|
||||
const RiseFall *,
|
||||
const DcalcAnalysisPt *)
|
||||
{
|
||||
return ReducedParasiticType::arnoldi;
|
||||
// Decline because reduced arnoldi parasitics are not stored in the parasitics db.
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void
|
||||
ArnoldiDelayCalc::finishDrvrPin()
|
||||
{
|
||||
for (auto parasitic : unsaved_parasitics_)
|
||||
delete parasitic;
|
||||
unsaved_parasitics_.clear();
|
||||
}
|
||||
|
||||
ArcDcalcResult
|
||||
|
|
@ -1304,7 +1314,6 @@ ArnoldiDelayCalc::ra_get_r(delay_work *D,
|
|||
r = tlohi/(c_log*c1);
|
||||
if (rdelay>0.0 && r > rdelay)
|
||||
r = rdelay;
|
||||
// else printf("from rdelay %g to r %g\n",rdelay,r);
|
||||
return r;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -46,6 +46,14 @@ rcmodel::capacitance() const
|
|||
return ctot;
|
||||
}
|
||||
|
||||
PinSet
|
||||
rcmodel::unannotatedLoads(const Pin *,
|
||||
const Parasitics *) const
|
||||
{
|
||||
// This should never be called because the rcmodel is not saved in the Parasitics.
|
||||
return PinSet();
|
||||
}
|
||||
|
||||
struct ts_point
|
||||
{
|
||||
ParasiticNode *node_;
|
||||
|
|
@ -62,7 +70,7 @@ struct ts_point
|
|||
|
||||
struct ts_edge
|
||||
{
|
||||
ConcreteParasiticResistor *resistor_;
|
||||
ParasiticResistor *resistor_;
|
||||
ts_point *from;
|
||||
ts_point *to;
|
||||
};
|
||||
|
|
@ -131,23 +139,21 @@ ArnoldiReduce::~ArnoldiReduce()
|
|||
free(ts_pointV);
|
||||
}
|
||||
|
||||
Parasitic *
|
||||
rcmodel *
|
||||
ArnoldiReduce::reduceToArnoldi(Parasitic *parasitic,
|
||||
const Pin *drvr_pin,
|
||||
float coupling_cap_factor,
|
||||
const RiseFall *rf,
|
||||
const OperatingConditions *op_cond,
|
||||
const Corner *corner,
|
||||
const MinMax *cnst_min_max,
|
||||
const MinMax *min_max,
|
||||
const ParasiticAnalysisPt *ap)
|
||||
{
|
||||
parasitic_network_ = reinterpret_cast<ConcreteParasiticNetwork*>(parasitic);
|
||||
drvr_pin_ = drvr_pin;
|
||||
coupling_cap_factor_ = coupling_cap_factor;
|
||||
rf_ = rf;
|
||||
op_cond_ = op_cond;
|
||||
corner_ = corner;
|
||||
cnst_min_max_ = cnst_min_max;
|
||||
min_max_ = min_max;
|
||||
ap_ = ap;
|
||||
loadWork();
|
||||
return makeRcmodelDrv();
|
||||
|
|
@ -158,18 +164,21 @@ ArnoldiReduce::loadWork()
|
|||
{
|
||||
pt_map_.clear();
|
||||
|
||||
int resistor_count = 0;
|
||||
ConcreteParasiticDeviceSet devices;
|
||||
parasitic_network_->devices(&devices);
|
||||
ConcreteParasiticDeviceSet::Iterator device_iter(devices);
|
||||
while (device_iter.hasNext()) {
|
||||
ParasiticDevice *device = device_iter.next();
|
||||
if (parasitics_->isResistor(device))
|
||||
resistor_count++;
|
||||
}
|
||||
const ParasiticResistorSeq &resistors = parasitics_->resistors(parasitic_network_);
|
||||
int resistor_count = resistors.size();
|
||||
|
||||
termN = parasitic_network_->pinNodes()->size();
|
||||
int subnode_count = parasitic_network_->subNodes()->size();
|
||||
termN = 0;
|
||||
int subnode_count = 0;
|
||||
ParasiticNodeSeq nodes = parasitics_->nodes(parasitic_network_);
|
||||
for (ParasiticNode *node : nodes) {
|
||||
if (!parasitics_->isExternal(node)) {
|
||||
const Pin *pin = parasitics_->pin(node);
|
||||
if (pin)
|
||||
termN++;
|
||||
else
|
||||
subnode_count++;
|
||||
}
|
||||
}
|
||||
ts_pointN = subnode_count + 1 + termN;
|
||||
ts_edgeN = resistor_count;
|
||||
allocPoints();
|
||||
|
|
@ -191,50 +200,42 @@ ArnoldiReduce::loadWork()
|
|||
pend = pterm0;
|
||||
e = e0;
|
||||
int index = 0;
|
||||
ConcreteParasiticSubNodeMap::Iterator
|
||||
sub_node_iter(parasitic_network_->subNodes());
|
||||
while (sub_node_iter.hasNext()) {
|
||||
ConcreteParasiticSubNode *node = sub_node_iter.next();
|
||||
pt_map_[node] = index;
|
||||
p = p0 + index;
|
||||
p->node_ = node;
|
||||
p->eN = 0;
|
||||
p->is_term = false;
|
||||
index++;
|
||||
|
||||
for (ParasiticNode *node : nodes) {
|
||||
if (!parasitics_->isExternal(node)) {
|
||||
const Pin *pin = parasitics_->pin(node);
|
||||
if (pin) {
|
||||
p = pend++;
|
||||
pt_map_[node] = p - p0;
|
||||
p->node_ = node;
|
||||
p->eN = 0;
|
||||
p->is_term = true;
|
||||
tindex = p - pterm0;
|
||||
p->tindex = tindex;
|
||||
pinV[tindex] = pin;
|
||||
}
|
||||
else {
|
||||
pt_map_[node] = index;
|
||||
p = p0 + index;
|
||||
p->node_ = node;
|
||||
p->eN = 0;
|
||||
p->is_term = false;
|
||||
index++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ConcreteParasiticPinNodeMap::Iterator
|
||||
pin_node_iter(parasitic_network_->pinNodes());
|
||||
while (pin_node_iter.hasNext()) {
|
||||
ConcreteParasiticPinNode *node = pin_node_iter.next();
|
||||
p = pend++;
|
||||
pt_map_[node] = p - p0;
|
||||
p->node_ = node;
|
||||
p->eN = 0;
|
||||
p->is_term = true;
|
||||
tindex = p - pterm0;
|
||||
p->tindex = tindex;
|
||||
const Pin *pin = parasitics_->connectionPin(node);
|
||||
pinV[tindex] = pin;
|
||||
}
|
||||
|
||||
ts_edge **eV = ts_eV;
|
||||
ConcreteParasiticDeviceSet::Iterator device_iter2(devices);
|
||||
while (device_iter2.hasNext()) {
|
||||
ParasiticDevice *device = device_iter2.next();
|
||||
if (parasitics_->isResistor(device)) {
|
||||
ConcreteParasiticResistor *resistor =
|
||||
reinterpret_cast<ConcreteParasiticResistor*>(device);
|
||||
ts_point *pt1 = findPt(resistor->node1());
|
||||
ts_point *pt2 = findPt(resistor->node2());
|
||||
e->from = pt1;
|
||||
e->to = pt2;
|
||||
e->resistor_ = resistor;
|
||||
pt1->eN++;
|
||||
if (e->from != e->to)
|
||||
pt2->eN++;
|
||||
e++;
|
||||
}
|
||||
for (ParasiticResistor *resistor : resistors) {
|
||||
ts_point *pt1 = findPt(parasitics_->node1(resistor));
|
||||
ts_point *pt2 = findPt(parasitics_->node2(resistor));
|
||||
e->from = pt1;
|
||||
e->to = pt2;
|
||||
e->resistor_ = resistor;
|
||||
pt1->eN++;
|
||||
if (e->from != e->to)
|
||||
pt2->eN++;
|
||||
e++;
|
||||
}
|
||||
|
||||
for (p=p0;p!=pend;p++) {
|
||||
|
|
@ -313,8 +314,7 @@ ArnoldiReduce::findPt(ParasiticNode *node)
|
|||
rcmodel *
|
||||
ArnoldiReduce::makeRcmodelDrv()
|
||||
{
|
||||
ParasiticNode *drv_node = parasitics_->findNode(parasitic_network_,
|
||||
drvr_pin_);
|
||||
ParasiticNode *drv_node = parasitics_->findNode(parasitic_network_, drvr_pin_);
|
||||
ts_point *pdrv = findPt(drv_node);
|
||||
makeRcmodelDfs(pdrv);
|
||||
getRC();
|
||||
|
|
@ -322,8 +322,7 @@ ArnoldiReduce::makeRcmodelDrv()
|
|||
return nullptr;
|
||||
setTerms(pdrv);
|
||||
makeRcmodelFromTs();
|
||||
rcmodel *mod = makeRcmodelFromW();
|
||||
return mod;
|
||||
return makeRcmodelFromW();
|
||||
}
|
||||
|
||||
#define ts_orient( pp, ee) \
|
||||
|
|
@ -415,7 +414,7 @@ ArnoldiReduce::getRC()
|
|||
p->r = 0.0;
|
||||
if (p->node_) {
|
||||
ParasiticNode *node = p->node_;
|
||||
double cap = parasitics_->nodeGndCap(node, ap_)
|
||||
double cap = parasitics_->nodeGndCap(node)
|
||||
+ pinCapacitance(node);
|
||||
if (cap > 0.0) {
|
||||
p->c = cap;
|
||||
|
|
@ -424,7 +423,7 @@ ArnoldiReduce::getRC()
|
|||
else
|
||||
p->c = 0.0;
|
||||
if (p->in_edge && p->in_edge->resistor_)
|
||||
p->r = parasitics_->value(p->in_edge->resistor_, ap_);
|
||||
p->r = parasitics_->value(p->in_edge->resistor_);
|
||||
if (!(p->r>=0.0 && p->r<100e+3)) { // 0 < r < 100kohm
|
||||
debugPrint(debug_, "arnoldi", 1,
|
||||
"R value %g out of range, drvr pin %s",
|
||||
|
|
@ -433,20 +432,33 @@ ArnoldiReduce::getRC()
|
|||
}
|
||||
}
|
||||
}
|
||||
for (ParasiticCapacitor *capacitor : parasitics_->capacitors(parasitic_network_)) {
|
||||
float cap = parasitics_->value(capacitor) * ap_->couplingCapFactor();
|
||||
ParasiticNode *node1 = parasitics_->node1(capacitor);
|
||||
if (!parasitics_->isExternal(node1)) {
|
||||
ts_point *pt = findPt(node1);
|
||||
pt->c += cap;
|
||||
}
|
||||
ParasiticNode *node2 = parasitics_->node2(capacitor);
|
||||
if (!parasitics_->isExternal(node2)) {
|
||||
ts_point *pt = findPt(node2);
|
||||
pt->c += cap;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
float
|
||||
ArnoldiReduce::pinCapacitance(ParasiticNode *node)
|
||||
{
|
||||
const Pin *pin = parasitics_->connectionPin(node);
|
||||
const Pin *pin = parasitics_->pin(node);
|
||||
float pin_cap = 0.0;
|
||||
if (pin) {
|
||||
Port *port = network_->port(pin);
|
||||
LibertyPort *lib_port = network_->libertyPort(port);
|
||||
if (lib_port)
|
||||
pin_cap = sdc_->pinCapacitance(pin,rf_, op_cond_, corner_, cnst_min_max_);
|
||||
pin_cap = sdc_->pinCapacitance(pin,rf_, corner_, min_max_);
|
||||
else if (network_->isTopLevelPort(pin))
|
||||
pin_cap = sdc_->portExtCap(port, rf_, corner_, cnst_min_max_);
|
||||
pin_cap = sdc_->portExtCap(port, rf_, corner_, min_max_);
|
||||
}
|
||||
return pin_cap;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -37,21 +37,20 @@ class rcmodel;
|
|||
struct ts_edge;
|
||||
struct ts_point;
|
||||
|
||||
typedef Map<ConcreteParasiticNode*, int> ArnolidPtMap;
|
||||
typedef Map<ParasiticNode*, int> ArnolidPtMap;
|
||||
|
||||
class ArnoldiReduce : public StaState
|
||||
{
|
||||
public:
|
||||
ArnoldiReduce(StaState *sta);
|
||||
~ArnoldiReduce();
|
||||
Parasitic *reduceToArnoldi(Parasitic *parasitic,
|
||||
const Pin *drvr_pin,
|
||||
float coupling_cap_factor,
|
||||
const RiseFall *rf,
|
||||
const OperatingConditions *op_cond,
|
||||
const Corner *corner,
|
||||
const MinMax *cnst_min_max,
|
||||
const ParasiticAnalysisPt *ap);
|
||||
rcmodel *reduceToArnoldi(Parasitic *parasitic,
|
||||
const Pin *drvr_pin,
|
||||
float coupling_cap_factor,
|
||||
const RiseFall *rf,
|
||||
const Corner *corner,
|
||||
const MinMax *cnst_min_max,
|
||||
const ParasiticAnalysisPt *ap);
|
||||
|
||||
protected:
|
||||
void loadWork();
|
||||
|
|
@ -70,9 +69,8 @@ protected:
|
|||
const Pin *drvr_pin_;
|
||||
float coupling_cap_factor_;
|
||||
const RiseFall *rf_;
|
||||
const OperatingConditions *op_cond_;
|
||||
const Corner *corner_;
|
||||
const MinMax *cnst_min_max_;
|
||||
const MinMax *min_max_;
|
||||
const ParasiticAnalysisPt *ap_;
|
||||
// ParasiticNode -> ts_point index.
|
||||
ArnolidPtMap pt_map_;
|
||||
|
|
|
|||
|
|
@ -23,6 +23,7 @@
|
|||
#include "Network.hh"
|
||||
#include "Parasitics.hh"
|
||||
#include "Sdc.hh"
|
||||
#include "Corner.hh"
|
||||
#include "DcalcAnalysisPt.hh"
|
||||
|
||||
namespace sta {
|
||||
|
|
@ -34,6 +35,35 @@ DelayCalcBase::DelayCalcBase(StaState *sta) :
|
|||
{
|
||||
}
|
||||
|
||||
void
|
||||
DelayCalcBase::reduceParasitic(const Parasitic *parasitic_network,
|
||||
const Net *net,
|
||||
const Corner *corner,
|
||||
const MinMaxAll *min_max)
|
||||
{
|
||||
NetConnectedPinIterator *pin_iter = network_->connectedPinIterator(net);
|
||||
while (pin_iter->hasNext()) {
|
||||
const Pin *pin = pin_iter->next();
|
||||
if (network_->isDriver(pin)) {
|
||||
for (RiseFall *rf : RiseFall::range()) {
|
||||
for (const MinMax *min_max : min_max->range()) {
|
||||
if (corner == nullptr) {
|
||||
for (const Corner *corner1 : *corners_) {
|
||||
DcalcAnalysisPt *dcalc_ap = corner1->findDcalcAnalysisPt(min_max);
|
||||
reduceParasitic(parasitic_network, pin, rf, dcalc_ap);
|
||||
}
|
||||
}
|
||||
else {
|
||||
DcalcAnalysisPt *dcalc_ap = corner->findDcalcAnalysisPt(min_max);
|
||||
reduceParasitic(parasitic_network, pin, rf, dcalc_ap);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
delete pin_iter;
|
||||
}
|
||||
|
||||
TimingModel *
|
||||
DelayCalcBase::model(const TimingArc *arc,
|
||||
const DcalcAnalysisPt *dcalc_ap) const
|
||||
|
|
@ -67,12 +97,6 @@ DelayCalcBase::checkModel(const TimingArc *arc,
|
|||
void
|
||||
DelayCalcBase::finishDrvrPin()
|
||||
{
|
||||
for (auto parasitic : unsaved_parasitics_)
|
||||
parasitics_->deleteUnsavedParasitic(parasitic);
|
||||
unsaved_parasitics_.clear();
|
||||
for (auto drvr_pin : reduced_parasitic_drvrs_)
|
||||
parasitics_->deleteDrvrReducedParasitics(drvr_pin);
|
||||
reduced_parasitic_drvrs_.clear();
|
||||
}
|
||||
|
||||
// For DSPF on an input port the elmore delay is used as the time
|
||||
|
|
|
|||
|
|
@ -28,13 +28,18 @@ public:
|
|||
explicit DelayCalcBase(StaState *sta);
|
||||
void finishDrvrPin() override;
|
||||
|
||||
void reduceParasitic(const Parasitic *parasitic_network,
|
||||
const Net *net,
|
||||
const Corner *corner,
|
||||
const MinMaxAll *min_max) 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;
|
||||
|
||||
|
||||
string reportCheckDelay(const Pin *check_pin,
|
||||
const TimingArc *arc,
|
||||
const Slew &from_slew,
|
||||
|
|
@ -72,11 +77,7 @@ protected:
|
|||
const Pvt *pinPvt(const Pin *pin,
|
||||
const DcalcAnalysisPt *dcalc_ap);
|
||||
|
||||
// Parasitics returned by findParasitic that are reduced or estimated
|
||||
// that can be deleted after delay calculation for the driver pin
|
||||
// is finished.
|
||||
Vector<Parasitic*> unsaved_parasitics_;
|
||||
Vector<const Pin *> reduced_parasitic_drvrs_;
|
||||
using ArcDelayCalc::reduceParasitic;
|
||||
};
|
||||
|
||||
} // namespace
|
||||
|
|
|
|||
|
|
@ -19,12 +19,13 @@
|
|||
#include "TableModel.hh"
|
||||
#include "TimingArc.hh"
|
||||
#include "Liberty.hh"
|
||||
#include "PortDirection.hh"
|
||||
#include "Network.hh"
|
||||
#include "Sdc.hh"
|
||||
#include "Parasitics.hh"
|
||||
#include "DcalcAnalysisPt.hh"
|
||||
#include "GraphDelayCalc.hh"
|
||||
#include "DmpCeff.hh"
|
||||
#include "Network.hh"
|
||||
|
||||
namespace sta {
|
||||
|
||||
|
|
@ -132,7 +133,6 @@ public:
|
|||
Parasitic *findParasitic(const Pin *drvr_pin,
|
||||
const RiseFall *rf,
|
||||
const DcalcAnalysisPt *dcalc_ap) override;
|
||||
ReducedParasiticType reducedParasiticType() const override;
|
||||
ArcDcalcResult inputPortDelay(const Pin *port_pin,
|
||||
float in_slew,
|
||||
const RiseFall *rf,
|
||||
|
|
@ -210,58 +210,41 @@ DmpCeffTwoPoleDelayCalc::findParasitic(const Pin *drvr_pin,
|
|||
Parasitic *parasitic = nullptr;
|
||||
const Corner *corner = dcalc_ap->corner();
|
||||
// set_load net has precedence over parasitics.
|
||||
if (!sdc_->drvrPinHasWireCap(drvr_pin, corner)) {
|
||||
const ParasiticAnalysisPt *parasitic_ap = dcalc_ap->parasiticAnalysisPt();
|
||||
if (parasitics_->haveParasitics()) {
|
||||
// Prefer PiPoleResidue.
|
||||
parasitic = parasitics_->findPiPoleResidue(drvr_pin, rf, parasitic_ap);
|
||||
if (parasitic == nullptr) {
|
||||
parasitic = parasitics_->findPiElmore(drvr_pin, rf, parasitic_ap);
|
||||
if (parasitic == nullptr) {
|
||||
Parasitic *parasitic_network =
|
||||
parasitics_->findParasiticNetwork(drvr_pin, parasitic_ap);
|
||||
if (parasitic_network) {
|
||||
parasitics_->reduceToPiPoleResidue2(parasitic_network, drvr_pin,
|
||||
dcalc_ap->operatingConditions(),
|
||||
corner,
|
||||
dcalc_ap->constraintMinMax(),
|
||||
parasitic_ap);
|
||||
parasitic = parasitics_->findPiPoleResidue(drvr_pin, rf, parasitic_ap);
|
||||
reduced_parasitic_drvrs_.push_back(drvr_pin);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
const MinMax *cnst_min_max = dcalc_ap->constraintMinMax();
|
||||
Wireload *wireload = sdc_->wireload(cnst_min_max);
|
||||
if (wireload) {
|
||||
float pin_cap, wire_cap, fanout;
|
||||
bool has_wire_cap;
|
||||
graph_delay_calc_->netCaps(drvr_pin, rf, dcalc_ap,
|
||||
pin_cap, wire_cap, fanout, has_wire_cap);
|
||||
parasitic = parasitics_->estimatePiElmore(drvr_pin, rf, wireload,
|
||||
fanout, pin_cap,
|
||||
dcalc_ap->operatingConditions(),
|
||||
corner,
|
||||
cnst_min_max,
|
||||
parasitic_ap);
|
||||
// Estimated parasitics are not recorded in the "database", so
|
||||
// save it for deletion after the drvr pin delay calc is finished.
|
||||
if (parasitic)
|
||||
unsaved_parasitics_.push_back(parasitic);
|
||||
}
|
||||
}
|
||||
if (sdc_->drvrPinHasWireCap(drvr_pin, corner)
|
||||
|| network_->direction(drvr_pin)->isInternal())
|
||||
return nullptr;
|
||||
const ParasiticAnalysisPt *parasitic_ap = dcalc_ap->parasiticAnalysisPt();
|
||||
// Prefer PiPoleResidue.
|
||||
parasitic = parasitics_->findPiPoleResidue(drvr_pin, rf, parasitic_ap);
|
||||
if (parasitic)
|
||||
return parasitic;
|
||||
parasitic = parasitics_->findPiElmore(drvr_pin, rf, parasitic_ap);
|
||||
if (parasitic)
|
||||
return parasitic;
|
||||
Parasitic *parasitic_network =
|
||||
parasitics_->findParasiticNetwork(drvr_pin, parasitic_ap);
|
||||
if (parasitic_network) {
|
||||
parasitic = parasitics_->reduceToPiPoleResidue2(parasitic_network, drvr_pin, rf,
|
||||
corner,
|
||||
dcalc_ap->constraintMinMax(),
|
||||
parasitic_ap);
|
||||
if (parasitic)
|
||||
return parasitic;
|
||||
}
|
||||
const MinMax *cnst_min_max = dcalc_ap->constraintMinMax();
|
||||
Wireload *wireload = sdc_->wireload(cnst_min_max);
|
||||
if (wireload) {
|
||||
float pin_cap, wire_cap, fanout;
|
||||
bool has_wire_cap;
|
||||
graph_delay_calc_->netCaps(drvr_pin, rf, dcalc_ap, pin_cap, wire_cap,
|
||||
fanout, has_wire_cap);
|
||||
parasitic = parasitics_->estimatePiElmore(drvr_pin, rf, wireload,
|
||||
fanout, pin_cap, corner,
|
||||
cnst_min_max);
|
||||
}
|
||||
return parasitic;
|
||||
}
|
||||
|
||||
ReducedParasiticType
|
||||
DmpCeffTwoPoleDelayCalc::reducedParasiticType() const
|
||||
{
|
||||
return ReducedParasiticType::pi_pole_residue2;
|
||||
}
|
||||
|
||||
ArcDcalcResult
|
||||
DmpCeffTwoPoleDelayCalc::inputPortDelay(const Pin *,
|
||||
float in_slew,
|
||||
|
|
|
|||
|
|
@ -365,9 +365,11 @@ GraphDelayCalc::seedNoDrvrCellSlew(Vertex *drvr_vertex,
|
|||
Delay drive_delay = delay_zero;
|
||||
float drive_res;
|
||||
drive->driveResistance(rf, cnst_min_max, drive_res, exists);
|
||||
Parasitic *parasitic = arc_delay_calc->findParasitic(drvr_pin, rf, dcalc_ap);
|
||||
const Parasitic *parasitic;
|
||||
float cap;
|
||||
parasiticLoad(drvr_pin, rf, dcalc_ap, nullptr, arc_delay_calc,
|
||||
cap, parasitic);
|
||||
if (exists) {
|
||||
float cap = loadCap(drvr_pin, parasitic, rf, dcalc_ap);
|
||||
drive_delay = cap * drive_res;
|
||||
slew = cap * drive_res;
|
||||
}
|
||||
|
|
@ -408,7 +410,7 @@ GraphDelayCalc::seedNoDrvrSlew(Vertex *drvr_vertex,
|
|||
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();
|
||||
arc_delay_calc_->finishDrvrPin();
|
||||
}
|
||||
|
||||
void
|
||||
|
|
@ -500,6 +502,7 @@ GraphDelayCalc::findInputDriverDelay(const LibertyCell *drvr_cell,
|
|||
}
|
||||
}
|
||||
}
|
||||
arc_delay_calc_->finishDrvrPin();
|
||||
}
|
||||
|
||||
// Driving cell delay is the load dependent delay, which is the gate
|
||||
|
|
@ -521,8 +524,10 @@ GraphDelayCalc::findInputArcDelay(const Pin *drvr_pin,
|
|||
const RiseFall *drvr_rf = arc->toEdge()->asRiseFall();
|
||||
if (drvr_rf) {
|
||||
DcalcAPIndex ap_index = dcalc_ap->index();
|
||||
Parasitic *parasitic = arc_delay_calc_->findParasitic(drvr_pin, drvr_rf, dcalc_ap);
|
||||
float load_cap = loadCap(drvr_pin, parasitic, drvr_rf, dcalc_ap);
|
||||
const Parasitic *parasitic;
|
||||
float load_cap;
|
||||
parasiticLoad(drvr_pin, drvr_rf, dcalc_ap, nullptr, arc_delay_calc_,
|
||||
load_cap, parasitic);
|
||||
|
||||
LoadPinIndexMap load_pin_index_map = makeLoadPinIndexMap(drvr_vertex);
|
||||
ArcDcalcResult intrinsic_result =
|
||||
|
|
@ -547,6 +552,7 @@ GraphDelayCalc::findInputArcDelay(const Pin *drvr_pin,
|
|||
graph_->setSlew(drvr_vertex, drvr_rf, ap_index, gate_slew);
|
||||
annotateLoadDelays(drvr_vertex, drvr_rf, gate_result, load_pin_index_map,
|
||||
load_delay, false, dcalc_ap);
|
||||
arc_delay_calc_->finishDrvrPin();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -646,7 +652,7 @@ GraphDelayCalc::findDriverDelays(Vertex *drvr_vertex,
|
|||
initLoadSlews(drvr_vertex);
|
||||
delay_changed |= findDriverDelays1(drvr_vertex, multi_drvr, arc_delay_calc);
|
||||
}
|
||||
arc_delay_calc->finishDrvrPin();
|
||||
arc_delay_calc_->finishDrvrPin();
|
||||
return delay_changed;
|
||||
}
|
||||
|
||||
|
|
@ -849,7 +855,6 @@ GraphDelayCalc::findDriverEdgeDelays(Vertex *drvr_vertex,
|
|||
Vertex *from_vertex = edge->from(graph_);
|
||||
const TimingArcSet *arc_set = edge->timingArcSet();
|
||||
bool delay_changed = false;
|
||||
PinSeq load_pins = loadPins(drvr_vertex);
|
||||
LoadPinIndexMap load_pin_index_map = makeLoadPinIndexMap(drvr_vertex);
|
||||
for (auto dcalc_ap : corners_->dcalcAnalysisPts()) {
|
||||
for (const TimingArc *arc : arc_set->arcs())
|
||||
|
|
@ -892,9 +897,11 @@ GraphDelayCalc::findDriverArcDelays(Vertex *drvr_vertex,
|
|||
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);
|
||||
const Parasitic *parasitic;
|
||||
float load_cap;
|
||||
parasiticLoad(drvr_pin, drvr_rf, dcalc_ap, multi_drvr, arc_delay_calc,
|
||||
load_cap, parasitic);
|
||||
|
||||
if (multi_drvr
|
||||
&& multi_drvr->parallelGates(network_)) {
|
||||
ArcDcalcArgSeq dcalc_args = makeArcDcalcArgs(drvr_vertex, multi_drvr,
|
||||
|
|
@ -921,6 +928,7 @@ GraphDelayCalc::findDriverArcDelays(Vertex *drvr_vertex,
|
|||
delay_changed |= annotateDelaysSlews(edge, arc, dcalc_result,
|
||||
load_pin_index_map, dcalc_ap);
|
||||
}
|
||||
arc_delay_calc->finishDrvrPin();
|
||||
}
|
||||
return delay_changed;
|
||||
}
|
||||
|
|
@ -1126,21 +1134,6 @@ GraphDelayCalc::annotateLoadDelays(Vertex *drvr_vertex,
|
|||
}
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
|
|
@ -1159,6 +1152,7 @@ GraphDelayCalc::makeLoadPinIndexMap(Vertex *drvr_vertex)
|
|||
return load_pin_index_map;
|
||||
}
|
||||
|
||||
// External
|
||||
float
|
||||
GraphDelayCalc::loadCap(const Pin *drvr_pin,
|
||||
const DcalcAnalysisPt *dcalc_ap) const
|
||||
|
|
@ -1166,92 +1160,104 @@ 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 *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();
|
||||
float cap = loadCap(drvr_pin, drvr_rf, dcalc_ap);
|
||||
if (min_max->compare(cap, load_cap))
|
||||
load_cap = cap;
|
||||
}
|
||||
arc_delay_calc_->finishDrvrPin();
|
||||
return load_cap;
|
||||
}
|
||||
|
||||
// External
|
||||
float
|
||||
GraphDelayCalc::loadCap(const Pin *drvr_pin,
|
||||
const RiseFall *drvr_rf,
|
||||
const DcalcAnalysisPt *dcalc_ap) const
|
||||
{
|
||||
Parasitic *parasitic = arc_delay_calc_->findParasitic(drvr_pin, drvr_rf,
|
||||
dcalc_ap);
|
||||
float cap = loadCap(drvr_pin, parasitic, drvr_rf, dcalc_ap, nullptr);
|
||||
return cap;
|
||||
}
|
||||
|
||||
float
|
||||
GraphDelayCalc::loadCap(const Pin *drvr_pin,
|
||||
const Parasitic *parasitic,
|
||||
const RiseFall *rf,
|
||||
const DcalcAnalysisPt *dcalc_ap) const
|
||||
{
|
||||
return loadCap(drvr_pin, parasitic, rf, dcalc_ap, nullptr);
|
||||
}
|
||||
|
||||
float
|
||||
GraphDelayCalc::loadCap(const Pin *drvr_pin,
|
||||
const Parasitic *parasitic,
|
||||
const RiseFall *rf,
|
||||
const DcalcAnalysisPt *dcalc_ap,
|
||||
const MultiDrvrNet *multi_drvr) const
|
||||
{
|
||||
float pin_cap, wire_cap;
|
||||
bool has_net_load;
|
||||
float fanout;
|
||||
if (multi_drvr)
|
||||
multi_drvr->netCaps(rf, dcalc_ap,
|
||||
pin_cap, wire_cap, fanout, has_net_load);
|
||||
else
|
||||
netCaps(drvr_pin, rf, dcalc_ap,
|
||||
pin_cap, wire_cap, fanout, has_net_load);
|
||||
loadCap(parasitic, has_net_load, pin_cap, wire_cap);
|
||||
return wire_cap + pin_cap;
|
||||
loadCap(drvr_pin, rf, dcalc_ap, pin_cap, wire_cap);
|
||||
return pin_cap + wire_cap;
|
||||
}
|
||||
|
||||
// External
|
||||
void
|
||||
GraphDelayCalc::loadCap(const Pin *drvr_pin,
|
||||
const Parasitic *parasitic,
|
||||
const RiseFall *rf,
|
||||
const DcalcAnalysisPt *dcalc_ap,
|
||||
// Return values.
|
||||
float &pin_cap,
|
||||
float &wire_cap) const
|
||||
{
|
||||
bool has_net_load;
|
||||
float fanout;
|
||||
// Find pin and external pin/wire capacitance.
|
||||
netCaps(drvr_pin, rf, dcalc_ap,
|
||||
pin_cap, wire_cap, fanout, has_net_load);
|
||||
loadCap(parasitic, has_net_load, pin_cap, wire_cap);
|
||||
MultiDrvrNet *multi_drvr = nullptr;
|
||||
if (graph_) {
|
||||
Vertex *drvr_vertex = graph_->pinDrvrVertex(drvr_pin);
|
||||
multi_drvr = multiDrvrNet(drvr_vertex);
|
||||
}
|
||||
const Parasitic *parasitic;
|
||||
parasiticLoad(drvr_pin, rf, dcalc_ap, multi_drvr, arc_delay_calc_,
|
||||
pin_cap, wire_cap, parasitic);
|
||||
arc_delay_calc_->finishDrvrPin();
|
||||
}
|
||||
|
||||
float
|
||||
GraphDelayCalc::loadCap(const Pin *drvr_pin,
|
||||
const RiseFall *rf,
|
||||
const DcalcAnalysisPt *dcalc_ap,
|
||||
ArcDelayCalc *arc_delay_calc) const
|
||||
{
|
||||
const Parasitic *parasitic;
|
||||
float pin_cap, wire_cap;
|
||||
parasiticLoad(drvr_pin, rf, dcalc_ap, nullptr, arc_delay_calc,
|
||||
pin_cap, wire_cap, parasitic);
|
||||
return pin_cap + wire_cap;
|
||||
}
|
||||
|
||||
void
|
||||
GraphDelayCalc::loadCap(const Parasitic *parasitic,
|
||||
bool has_net_load,
|
||||
// Return values.
|
||||
float &pin_cap,
|
||||
float &wire_cap) const
|
||||
GraphDelayCalc::parasiticLoad(const Pin *drvr_pin,
|
||||
const RiseFall *rf,
|
||||
const DcalcAnalysisPt *dcalc_ap,
|
||||
const MultiDrvrNet *multi_drvr,
|
||||
ArcDelayCalc *arc_delay_calc,
|
||||
// Return values.
|
||||
float &load_cap,
|
||||
const Parasitic *¶sitic) const
|
||||
{
|
||||
float pin_cap, wire_cap;
|
||||
parasiticLoad(drvr_pin, rf, dcalc_ap, multi_drvr, arc_delay_calc,
|
||||
pin_cap, wire_cap, parasitic);
|
||||
load_cap = pin_cap + wire_cap;
|
||||
}
|
||||
|
||||
void
|
||||
GraphDelayCalc::parasiticLoad(const Pin *drvr_pin,
|
||||
const RiseFall *rf,
|
||||
const DcalcAnalysisPt *dcalc_ap,
|
||||
const MultiDrvrNet *multi_drvr,
|
||||
ArcDelayCalc *arc_delay_calc,
|
||||
// Return values.
|
||||
float &pin_cap,
|
||||
float &wire_cap,
|
||||
const Parasitic *¶sitic) const
|
||||
{
|
||||
bool has_net_load;
|
||||
float fanout;
|
||||
netCaps(drvr_pin, rf, dcalc_ap, multi_drvr,
|
||||
pin_cap, wire_cap, fanout, has_net_load);
|
||||
|
||||
parasitic = arc_delay_calc->findParasitic(drvr_pin, rf, dcalc_ap);
|
||||
// set_load net has precedence over parasitics.
|
||||
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(parasitic);
|
||||
if (pin_cap > cap) {
|
||||
pin_cap = 0.0;
|
||||
wire_cap = cap;
|
||||
float parasitic_cap = parasitics_->capacitance(parasitic);
|
||||
if (parasitic_cap >= pin_cap)
|
||||
wire_cap = parasitic_cap - pin_cap;
|
||||
else {
|
||||
wire_cap = 0.0;
|
||||
// Ignore parasitic if pin cap is greater.
|
||||
parasitic = nullptr;
|
||||
}
|
||||
else
|
||||
wire_cap = cap - pin_cap;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1271,15 +1277,29 @@ GraphDelayCalc::netCaps(const Pin *drvr_pin,
|
|||
Vertex *drvr_vertex = graph_->pinDrvrVertex(drvr_pin);
|
||||
multi_drvr = multiDrvrNet(drvr_vertex);
|
||||
}
|
||||
netCaps(drvr_pin, rf, dcalc_ap, multi_drvr,
|
||||
pin_cap, wire_cap, fanout, has_net_load);
|
||||
}
|
||||
|
||||
void
|
||||
GraphDelayCalc::netCaps(const Pin *drvr_pin,
|
||||
const RiseFall *rf,
|
||||
const DcalcAnalysisPt *dcalc_ap,
|
||||
const MultiDrvrNet *multi_drvr,
|
||||
// Return values.
|
||||
float &pin_cap,
|
||||
float &wire_cap,
|
||||
float &fanout,
|
||||
bool &has_net_load) const
|
||||
{
|
||||
if (multi_drvr)
|
||||
multi_drvr->netCaps(rf, dcalc_ap,
|
||||
pin_cap, wire_cap, fanout, has_net_load);
|
||||
else {
|
||||
const OperatingConditions *op_cond = dcalc_ap->operatingConditions();
|
||||
const Corner *corner = dcalc_ap->corner();
|
||||
const MinMax *min_max = dcalc_ap->constraintMinMax();
|
||||
// Find pin and external pin/wire capacitance.
|
||||
sdc_->connectedCap(drvr_pin, rf, op_cond, corner, min_max,
|
||||
sdc_->connectedCap(drvr_pin, rf, corner, min_max,
|
||||
pin_cap, wire_cap, fanout, has_net_load);
|
||||
}
|
||||
}
|
||||
|
|
@ -1405,13 +1425,8 @@ GraphDelayCalc::findCheckEdgeDelays(Edge *edge,
|
|||
delayAsString(from_slew, this),
|
||||
delayAsString(to_slew, this));
|
||||
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);
|
||||
}
|
||||
if (related_out_pin)
|
||||
related_out_cap = loadCap(related_out_pin, to_rf,dcalc_ap,arc_delay_calc);
|
||||
ArcDelay check_delay = arc_delay_calc->checkDelay(to_pin, arc, from_slew,
|
||||
to_slew, related_out_cap,
|
||||
dcalc_ap);
|
||||
|
|
@ -1420,6 +1435,7 @@ GraphDelayCalc::findCheckEdgeDelays(Edge *edge,
|
|||
delayAsString(check_delay, this));
|
||||
graph_->setArcDelay(edge, arc, ap_index, check_delay);
|
||||
delay_changed = true;
|
||||
arc_delay_calc_->finishDrvrPin();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1467,12 +1483,8 @@ GraphDelayCalc::reportDelayCalc(const Edge *edge,
|
|||
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);
|
||||
}
|
||||
if (related_out_pin)
|
||||
related_out_cap = loadCap(related_out_pin, to_rf, dcalc_ap, arc_delay_calc_);
|
||||
if (role->isTimingCheck()) {
|
||||
const Slew &from_slew = checkEdgeClkSlew(from_vertex, from_rf, dcalc_ap);
|
||||
int slew_index = dcalc_ap->checkDataSlewIndex();
|
||||
|
|
@ -1484,10 +1496,11 @@ GraphDelayCalc::reportDelayCalc(const Edge *edge,
|
|||
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);
|
||||
const Parasitic *to_parasitic;
|
||||
float load_cap;
|
||||
parasiticLoad(to_pin, to_rf, dcalc_ap, nullptr, arc_delay_calc_,
|
||||
load_cap, to_parasitic);
|
||||
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,
|
||||
|
|
@ -1591,7 +1604,6 @@ MultiDrvrNet::findCaps(const Sdc *sdc)
|
|||
for (auto dcalc_ap : corners->dcalcAnalysisPts()) {
|
||||
DcalcAPIndex ap_index = dcalc_ap->index();
|
||||
const Corner *corner = dcalc_ap->corner();
|
||||
const OperatingConditions *op_cond = dcalc_ap->operatingConditions();
|
||||
const MinMax *min_max = dcalc_ap->constraintMinMax();
|
||||
for (auto drvr_rf : RiseFall::range()) {
|
||||
int drvr_rf_index = drvr_rf->index();
|
||||
|
|
@ -1600,7 +1612,7 @@ MultiDrvrNet::findCaps(const Sdc *sdc)
|
|||
float pin_cap, wire_cap, fanout;
|
||||
bool has_net_load;
|
||||
// Find pin and external pin/wire capacitance.
|
||||
sdc->connectedCap(drvr_pin, drvr_rf, op_cond, corner, min_max,
|
||||
sdc->connectedCap(drvr_pin, drvr_rf, corner, min_max,
|
||||
pin_cap, wire_cap, fanout, has_net_load);
|
||||
net_caps.init(pin_cap, wire_cap, fanout, has_net_load);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -23,6 +23,7 @@
|
|||
#include "TimingArc.hh"
|
||||
#include "TimingModel.hh"
|
||||
#include "Liberty.hh"
|
||||
#include "PortDirection.hh"
|
||||
#include "Network.hh"
|
||||
#include "Sdc.hh"
|
||||
#include "Parasitics.hh"
|
||||
|
|
@ -58,53 +59,46 @@ LumpedCapDelayCalc::findParasitic(const Pin *drvr_pin,
|
|||
Parasitic *parasitic = nullptr;
|
||||
const Corner *corner = dcalc_ap->corner();
|
||||
// set_load net has precedence over parasitics.
|
||||
if (!sdc_->drvrPinHasWireCap(drvr_pin, corner)) {
|
||||
const ParasiticAnalysisPt *parasitic_ap = dcalc_ap->parasiticAnalysisPt();
|
||||
if (parasitics_->haveParasitics()) {
|
||||
// Prefer PiElmore.
|
||||
parasitic = parasitics_->findPiElmore(drvr_pin, rf, parasitic_ap);
|
||||
if (parasitic == nullptr) {
|
||||
Parasitic *parasitic_network =
|
||||
parasitics_->findParasiticNetwork(drvr_pin, parasitic_ap);
|
||||
if (parasitic_network) {
|
||||
parasitics_->reduceToPiElmore(parasitic_network, drvr_pin,
|
||||
dcalc_ap->operatingConditions(),
|
||||
corner,
|
||||
dcalc_ap->constraintMinMax(),
|
||||
parasitic_ap);
|
||||
parasitic = parasitics_->findPiElmore(drvr_pin, rf, parasitic_ap);
|
||||
reduced_parasitic_drvrs_.push_back(drvr_pin);
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
const MinMax *cnst_min_max = dcalc_ap->constraintMinMax();
|
||||
Wireload *wireload = sdc_->wireload(cnst_min_max);
|
||||
if (wireload) {
|
||||
float pin_cap, wire_cap, fanout;
|
||||
bool has_net_load;
|
||||
graph_delay_calc_->netCaps(drvr_pin, rf, dcalc_ap,
|
||||
pin_cap, wire_cap, fanout, has_net_load);
|
||||
parasitic = parasitics_->estimatePiElmore(drvr_pin, rf, wireload,
|
||||
fanout, pin_cap,
|
||||
dcalc_ap->operatingConditions(),
|
||||
corner,
|
||||
cnst_min_max,
|
||||
parasitic_ap);
|
||||
// Estimated parasitics are not recorded in the "database", so save
|
||||
// it for deletion after the drvr pin delay calc is finished.
|
||||
if (parasitic)
|
||||
unsaved_parasitics_.push_back(parasitic);
|
||||
}
|
||||
}
|
||||
if (sdc_->drvrPinHasWireCap(drvr_pin, corner)
|
||||
|| network_->direction(drvr_pin)->isInternal())
|
||||
return nullptr;
|
||||
const ParasiticAnalysisPt *parasitic_ap = dcalc_ap->parasiticAnalysisPt();
|
||||
// Prefer PiElmore.
|
||||
parasitic = parasitics_->findPiElmore(drvr_pin, rf, parasitic_ap);
|
||||
if (parasitic)
|
||||
return parasitic;
|
||||
Parasitic *parasitic_network = parasitics_->findParasiticNetwork(drvr_pin,
|
||||
parasitic_ap);
|
||||
if (parasitic_network) {
|
||||
parasitic = reduceParasitic(parasitic_network, drvr_pin, rf, dcalc_ap);
|
||||
if (parasitic)
|
||||
return parasitic;
|
||||
}
|
||||
const MinMax *min_max = dcalc_ap->constraintMinMax();
|
||||
Wireload *wireload = sdc_->wireload(min_max);
|
||||
if (wireload) {
|
||||
float pin_cap, wire_cap, fanout;
|
||||
bool has_net_load;
|
||||
graph_delay_calc_->netCaps(drvr_pin, rf, dcalc_ap,
|
||||
pin_cap, wire_cap, fanout, has_net_load);
|
||||
parasitic = parasitics_->estimatePiElmore(drvr_pin, rf, wireload, fanout,
|
||||
pin_cap, corner, min_max);
|
||||
}
|
||||
return parasitic;
|
||||
}
|
||||
|
||||
ReducedParasiticType
|
||||
LumpedCapDelayCalc::reducedParasiticType() const
|
||||
Parasitic *
|
||||
LumpedCapDelayCalc::reduceParasitic(const Parasitic *parasitic_network,
|
||||
const Pin *drvr_pin,
|
||||
const RiseFall *rf,
|
||||
const DcalcAnalysisPt *dcalc_ap)
|
||||
|
||||
{
|
||||
return ReducedParasiticType::pi_elmore;
|
||||
const Corner *corner = dcalc_ap->corner();
|
||||
const ParasiticAnalysisPt *parasitic_ap = dcalc_ap->parasiticAnalysisPt();
|
||||
return parasitics_->reduceToPiElmore(parasitic_network, drvr_pin, rf,
|
||||
corner, dcalc_ap->constraintMinMax(),
|
||||
parasitic_ap);
|
||||
}
|
||||
|
||||
ArcDcalcResult
|
||||
|
|
|
|||
|
|
@ -30,7 +30,10 @@ public:
|
|||
Parasitic *findParasitic(const Pin *drvr_pin,
|
||||
const RiseFall *rf,
|
||||
const DcalcAnalysisPt *dcalc_ap) override;
|
||||
ReducedParasiticType reducedParasiticType() const override;
|
||||
Parasitic *reduceParasitic(const Parasitic *parasitic_network,
|
||||
const Pin *drvr_pin,
|
||||
const RiseFall *rf,
|
||||
const DcalcAnalysisPt *dcalc_ap) override;
|
||||
ArcDcalcResult inputPortDelay(const Pin *port_pin,
|
||||
float in_slew,
|
||||
const RiseFall *rf,
|
||||
|
|
@ -59,6 +62,8 @@ protected:
|
|||
ArcDelay gate_delay,
|
||||
Slew drvr_slew,
|
||||
const LoadPinIndexMap &load_pin_index_map);
|
||||
|
||||
using ArcDelayCalc::reduceParasitic;
|
||||
};
|
||||
|
||||
ArcDelayCalc *
|
||||
|
|
|
|||
|
|
@ -45,10 +45,21 @@ UnitDelayCalc::findParasitic(const Pin *,
|
|||
return nullptr;
|
||||
}
|
||||
|
||||
ReducedParasiticType
|
||||
UnitDelayCalc::reducedParasiticType() const
|
||||
Parasitic *
|
||||
UnitDelayCalc::reduceParasitic(const Parasitic *,
|
||||
const Pin *,
|
||||
const RiseFall *,
|
||||
const DcalcAnalysisPt *)
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void
|
||||
UnitDelayCalc::reduceParasitic(const Parasitic *,
|
||||
const Net *,
|
||||
const Corner *,
|
||||
const MinMaxAll *)
|
||||
{
|
||||
return ReducedParasiticType::none;
|
||||
}
|
||||
|
||||
ArcDcalcResult
|
||||
|
|
|
|||
|
|
@ -29,7 +29,14 @@ public:
|
|||
Parasitic *findParasitic(const Pin *drvr_pin,
|
||||
const RiseFall *rf,
|
||||
const DcalcAnalysisPt *dcalc_ap) override;
|
||||
ReducedParasiticType reducedParasiticType() const override;
|
||||
Parasitic *reduceParasitic(const Parasitic *parasitic_network,
|
||||
const Pin *drvr_pin,
|
||||
const RiseFall *rf,
|
||||
const DcalcAnalysisPt *dcalc_ap) override;
|
||||
void reduceParasitic(const Parasitic *parasitic_network,
|
||||
const Net *net,
|
||||
const Corner *corner,
|
||||
const MinMaxAll *min_max) override;
|
||||
ArcDcalcResult inputPortDelay(const Pin *port_pin,
|
||||
float in_slew,
|
||||
const RiseFall *rf,
|
||||
|
|
|
|||
|
|
@ -10,6 +10,12 @@ The report_net -connections, -verbose and -hier_pins flags are deprecated.
|
|||
The report_instance -connections and -verbose flags are deprecated.
|
||||
The options are now enabled in all cases.
|
||||
|
||||
The read_spef parasitic reduction arguments have changed. The
|
||||
-reduce_to and -delete_after_reduce arguments are deprecated and
|
||||
replaced with the -reduce flag. With the -reduce flag, the current
|
||||
delay calculator reduces the parastic network to the appropriate type
|
||||
and deletes the parasitic network.
|
||||
|
||||
Release 2.4.0 2023/01/19
|
||||
-------------------------
|
||||
|
||||
|
|
|
|||
BIN
doc/OpenSTA.odt
BIN
doc/OpenSTA.odt
Binary file not shown.
BIN
doc/OpenSTA.pdf
BIN
doc/OpenSTA.pdf
Binary file not shown.
|
|
@ -124,7 +124,18 @@ public:
|
|||
virtual Parasitic *findParasitic(const Pin *drvr_pin,
|
||||
const RiseFall *rf,
|
||||
const DcalcAnalysisPt *dcalc_ap) = 0;
|
||||
virtual ReducedParasiticType reducedParasiticType() const = 0;
|
||||
// Reduce parasitic_network to a representation acceptable to the delay calculator.
|
||||
virtual Parasitic *reduceParasitic(const Parasitic *parasitic_network,
|
||||
const Pin *drvr_pin,
|
||||
const RiseFall *rf,
|
||||
const DcalcAnalysisPt *dcalc_ap) = 0;
|
||||
// Reduce parasitic_network to a representation acceptable to the delay calculator
|
||||
// for one or more corners and min/max rise/fall.
|
||||
// Null corner means reduce all corners.
|
||||
virtual void reduceParasitic(const Parasitic *parasitic_network,
|
||||
const Net *net,
|
||||
const Corner *corner,
|
||||
const MinMaxAll *min_max) = 0;
|
||||
// Find the wire delays and slews for an input port without a driving cell.
|
||||
// This call primarily initializes the load delay/slew iterator.
|
||||
virtual ArcDcalcResult inputPortDelay(const Pin *port_pin,
|
||||
|
|
|
|||
|
|
@ -55,8 +55,7 @@ public:
|
|||
void operatingConditionsChanged();
|
||||
|
||||
// Make one parasitic analysis points.
|
||||
void makeParasiticAnalysisPts(bool per_corner,
|
||||
bool per_min_max);
|
||||
void makeParasiticAnalysisPts(bool per_corner);
|
||||
int parasiticAnalysisPtCount() const;
|
||||
ParasiticAnalysisPtSeq ¶siticAnalysisPts();
|
||||
|
||||
|
|
@ -114,7 +113,7 @@ public:
|
|||
protected:
|
||||
void setParasiticAnalysisPtcount(int ap_count);
|
||||
void setParasiticAP(ParasiticAnalysisPt *path_ap,
|
||||
int ap_index);
|
||||
int mm_index);
|
||||
void setDcalcAnalysisPtcount(DcalcAPIndex ap_count);
|
||||
void addDcalcAP(DcalcAnalysisPt *dcalc_ap);
|
||||
void addPathAP(PathAnalysisPt *path_ap);
|
||||
|
|
|
|||
|
|
@ -72,41 +72,26 @@ public:
|
|||
// delays to be recomputed during incremental delay calculation.
|
||||
virtual float incrementalDelayTolerance();
|
||||
virtual void setIncrementalDelayTolerance(float tol);
|
||||
// Load pin_cap + wire_cap.
|
||||
virtual float loadCap(const Pin *drvr_pin,
|
||||
const RiseFall *drvr_rf,
|
||||
const DcalcAnalysisPt *dcalc_ap) const;
|
||||
// Load pin_cap + wire_cap including parasitic min/max for rise/fall.
|
||||
virtual float loadCap(const Pin *drvr_pin,
|
||||
const DcalcAnalysisPt *dcalc_ap) const;
|
||||
// pin_cap = net pin capacitances + port external pin capacitance,
|
||||
// wire_cap = annotated net capacitance + port external wire capacitance.
|
||||
virtual void loadCap(const Pin *drvr_pin,
|
||||
const Parasitic *parasitic,
|
||||
const RiseFall *rf,
|
||||
const DcalcAnalysisPt *dcalc_ap,
|
||||
// Return values.
|
||||
float &pin_cap,
|
||||
float &wire_cap) const;
|
||||
// Load pin_cap + wire_cap including parasitic.
|
||||
virtual float loadCap(const Pin *drvr_pin,
|
||||
const Parasitic *parasitic,
|
||||
const RiseFall *rf,
|
||||
const DcalcAnalysisPt *dcalc_ap) const;
|
||||
|
||||
float loadCap(const Pin *drvr_pin,
|
||||
const Parasitic *parasitic,
|
||||
const RiseFall *rf,
|
||||
const DcalcAnalysisPt *dcalc_ap,
|
||||
const MultiDrvrNet *multi_drvr) const;
|
||||
virtual void netCaps(const Pin *drvr_pin,
|
||||
const RiseFall *rf,
|
||||
const DcalcAnalysisPt *dcalc_ap,
|
||||
// Return values.
|
||||
float &pin_cap,
|
||||
float &wire_cap,
|
||||
float &fanout,
|
||||
bool &has_set_load) const;
|
||||
PinSeq loadPins(Vertex *drvr_vertex);
|
||||
const DcalcAnalysisPt *dcalc_ap) const;
|
||||
float loadCap(const Pin *drvr_pin,
|
||||
const RiseFall *rf,
|
||||
const DcalcAnalysisPt *dcalc_ap) const;
|
||||
void loadCap(const Pin *drvr_pin,
|
||||
const RiseFall *rf,
|
||||
const DcalcAnalysisPt *dcalc_ap,
|
||||
// Return values.
|
||||
float &pin_cap,
|
||||
float &wire_cap) const;
|
||||
void netCaps(const Pin *drvr_pin,
|
||||
const RiseFall *rf,
|
||||
const DcalcAnalysisPt *dcalc_ap,
|
||||
// Return values.
|
||||
float &pin_cap,
|
||||
float &wire_cap,
|
||||
float &fanout,
|
||||
bool &has_set_load) const;
|
||||
LoadPinIndexMap makeLoadPinIndexMap(Vertex *drvr_vertex);
|
||||
void findDriverArcDelays(Vertex *drvr_vertex,
|
||||
Edge *edge,
|
||||
|
|
@ -242,11 +227,36 @@ protected:
|
|||
const RiseFall *from_rf,
|
||||
const DcalcAnalysisPt *dcalc_ap);
|
||||
bool bidirectDrvrSlewFromLoad(const Vertex *vertex) const;
|
||||
void loadCap(const Parasitic *parasitic,
|
||||
bool has_set_load,
|
||||
// Return values.
|
||||
float &pin_cap,
|
||||
float &wire_cap) const;
|
||||
float loadCap(const Pin *drvr_pin,
|
||||
const RiseFall *rf,
|
||||
const DcalcAnalysisPt *dcalc_ap,
|
||||
ArcDelayCalc *arc_delay_calc) const;
|
||||
void parasiticLoad(const Pin *drvr_pin,
|
||||
const RiseFall *rf,
|
||||
const DcalcAnalysisPt *dcalc_ap,
|
||||
const MultiDrvrNet *multi_drvr,
|
||||
ArcDelayCalc *arc_delay_calc,
|
||||
// Return values.
|
||||
float &cap,
|
||||
const Parasitic *¶sitic) const;
|
||||
void parasiticLoad(const Pin *drvr_pin,
|
||||
const RiseFall *rf,
|
||||
const DcalcAnalysisPt *dcalc_ap,
|
||||
const MultiDrvrNet *multi_drvr,
|
||||
ArcDelayCalc *arc_delay_calc,
|
||||
// Return values.
|
||||
float &pin_cap,
|
||||
float &wire_cap,
|
||||
const Parasitic *¶sitic) const;
|
||||
void netCaps(const Pin *drvr_pin,
|
||||
const RiseFall *rf,
|
||||
const DcalcAnalysisPt *dcalc_ap,
|
||||
const MultiDrvrNet *multi_drvr,
|
||||
// Return values.
|
||||
float &pin_cap,
|
||||
float &wire_cap,
|
||||
float &fanout,
|
||||
bool &has_net_load) const;
|
||||
|
||||
// Observer for edge delay changes.
|
||||
DelayCalcObserver *observer_;
|
||||
|
|
|
|||
|
|
@ -1,198 +0,0 @@
|
|||
// OpenSTA, Static Timing Analyzer
|
||||
// Copyright (c) 2024, 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 <https://www.gnu.org/licenses/>.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "Parasitics.hh"
|
||||
|
||||
namespace sta {
|
||||
|
||||
// Parasitics that are not in the house.
|
||||
class NullParasitics : public Parasitics
|
||||
{
|
||||
public:
|
||||
NullParasitics(StaState *sta);
|
||||
virtual bool haveParasitics();
|
||||
virtual void clear();
|
||||
virtual void save();
|
||||
virtual void deleteParasitics();
|
||||
virtual void deleteParasitics(const Net *net,
|
||||
const ParasiticAnalysisPt *ap);
|
||||
virtual void deleteParasitics(const Pin *pin,
|
||||
const ParasiticAnalysisPt *ap);
|
||||
virtual void deleteUnsavedParasitic(Parasitic *parasitic);
|
||||
virtual void deleteReducedParasitics(const Net *net,
|
||||
const ParasiticAnalysisPt *ap);
|
||||
virtual void deleteDrvrReducedParasitics(const Pin *drvr_pin);
|
||||
|
||||
virtual float capacitance(const Parasitic *parasitic) const;
|
||||
|
||||
virtual Parasitic *
|
||||
findPiElmore(const Pin *drvr_pin,
|
||||
const RiseFall *rf,
|
||||
const ParasiticAnalysisPt *ap) const;
|
||||
virtual Parasitic *makePiElmore(const Pin *drvr_pin,
|
||||
const RiseFall *rf,
|
||||
const ParasiticAnalysisPt *ap,
|
||||
float c2,
|
||||
float rpi,
|
||||
float c1);
|
||||
virtual bool isPiElmore(const Parasitic *parasitic) const;
|
||||
virtual bool
|
||||
isReducedParasiticNetwork(const Parasitic *parasitic) const;
|
||||
virtual void setIsReducedParasiticNetwork(Parasitic *parasitic,
|
||||
bool is_reduced);
|
||||
virtual void piModel(const Parasitic *parasitic,
|
||||
float &c2,
|
||||
float &rpi,
|
||||
float &c1) const;
|
||||
virtual void setPiModel(Parasitic *parasitic,
|
||||
float c2,
|
||||
float rpi,
|
||||
float c1);
|
||||
virtual void findElmore(const Parasitic *parasitic,
|
||||
const Pin *load_pin,
|
||||
float &elmore,
|
||||
bool &exists) const;
|
||||
virtual void setElmore(Parasitic *parasitic, const Pin *load_pin,
|
||||
float elmore);
|
||||
|
||||
virtual bool isPiModel(const Parasitic* parasitic) const;
|
||||
virtual bool isPiPoleResidue(const Parasitic* parasitic) const;
|
||||
virtual Parasitic *
|
||||
findPiPoleResidue(const Pin *drvr_pin,
|
||||
const RiseFall *rf,
|
||||
const ParasiticAnalysisPt *ap) const;
|
||||
virtual Parasitic *makePiPoleResidue(const Pin *drvr_pin,
|
||||
const RiseFall *rf,
|
||||
const ParasiticAnalysisPt *ap,
|
||||
float c2, float rpi,
|
||||
float c1);
|
||||
virtual Parasitic *findPoleResidue(const Parasitic *parasitic,
|
||||
const Pin *load_pin) const;
|
||||
virtual void setPoleResidue(Parasitic *parasitic, const Pin *load_pin,
|
||||
ComplexFloatSeq *poles,
|
||||
ComplexFloatSeq *residues);
|
||||
virtual bool isPoleResidue(const Parasitic* parasitic) const;
|
||||
virtual size_t poleResidueCount(const Parasitic *parasitic) const;
|
||||
virtual void poleResidue(const Parasitic *parasitic, int pole_index,
|
||||
ComplexFloat &pole, ComplexFloat &residue) const;
|
||||
|
||||
virtual bool isParasiticNetwork(const Parasitic *parasitic) const;
|
||||
virtual Parasitic *findParasiticNetwork(const Net *net,
|
||||
const ParasiticAnalysisPt *ap) const;
|
||||
virtual Parasitic *
|
||||
findParasiticNetwork(const Pin *pin,
|
||||
const ParasiticAnalysisPt *ap) const;
|
||||
virtual Parasitic *
|
||||
makeParasiticNetwork(const Net *net,
|
||||
bool pin_cap_included,
|
||||
const ParasiticAnalysisPt *ap);
|
||||
virtual ParasiticDeviceIterator *deviceIterator(const Parasitic *) { return nullptr; }
|
||||
virtual ParasiticNodeIterator *nodeIterator(const Parasitic *) { return nullptr; }
|
||||
virtual bool includesPinCaps(const Parasitic *parasitic) const;
|
||||
virtual void deleteParasiticNetwork(const Net *net,
|
||||
const ParasiticAnalysisPt *ap);
|
||||
virtual void deleteParasiticNetworks(const Net *net);
|
||||
virtual ParasiticNode *ensureParasiticNode(Parasitic *parasitic,
|
||||
const Net *net,
|
||||
int id);
|
||||
virtual ParasiticNode *ensureParasiticNode(Parasitic *parasitic,
|
||||
const Pin *pin);
|
||||
virtual void incrCap(ParasiticNode *node, float cap,
|
||||
const ParasiticAnalysisPt *ap);
|
||||
virtual void makeCouplingCap(const char *name,
|
||||
ParasiticNode *node,
|
||||
ParasiticNode *other_node,
|
||||
float cap, const ParasiticAnalysisPt *ap);
|
||||
virtual void makeCouplingCap(const char *name,
|
||||
ParasiticNode *node,
|
||||
Net *other_node_net, int other_node_id,
|
||||
float cap, const ParasiticAnalysisPt *ap);
|
||||
virtual void makeCouplingCap(const char *name,
|
||||
ParasiticNode *node,
|
||||
Pin *other_node_pin,
|
||||
float cap, const ParasiticAnalysisPt *ap);
|
||||
virtual void makeResistor(const char *name, ParasiticNode *node1,
|
||||
ParasiticNode *node2, float res,
|
||||
const ParasiticAnalysisPt *ap);
|
||||
|
||||
virtual const char *name(const ParasiticNode *node);
|
||||
virtual const Pin *connectionPin(const ParasiticNode *node) const;
|
||||
virtual ParasiticNode *findNode(const Parasitic *parasitic,
|
||||
const Pin *pin) const;
|
||||
virtual float nodeGndCap(const ParasiticNode *node,
|
||||
const ParasiticAnalysisPt *ap) const;
|
||||
virtual ParasiticDeviceIterator *
|
||||
deviceIterator(ParasiticNode *node) const;
|
||||
virtual bool isResistor(const ParasiticDevice *device) const;
|
||||
virtual bool isCouplingCap(const ParasiticDevice *device)const;
|
||||
virtual const char *name(const ParasiticDevice *device) const;
|
||||
virtual float value(const ParasiticDevice *device,
|
||||
const ParasiticAnalysisPt *ap) const;
|
||||
virtual ParasiticNode *node1(const ParasiticDevice *device) const;
|
||||
virtual ParasiticNode *node2(const ParasiticDevice *device) const;
|
||||
virtual ParasiticNode *otherNode(const ParasiticDevice *device,
|
||||
ParasiticNode *node) const;
|
||||
// Reduce parasitic network to reduce_to model.
|
||||
virtual void reduceTo(const Parasitic *parasitic,
|
||||
const Net *net,
|
||||
ReducedParasiticType reduce_to,
|
||||
const OperatingConditions *op_cond,
|
||||
const Corner *corner,
|
||||
const MinMax *cnst_min_max,
|
||||
const ParasiticAnalysisPt *ap);
|
||||
virtual void reduceToPiElmore(const Parasitic *parasitic,
|
||||
const Net *net,
|
||||
const OperatingConditions *op_cond,
|
||||
const Corner *corner,
|
||||
const MinMax *cnst_min_max,
|
||||
const ParasiticAnalysisPt *ap);
|
||||
// Reduce parasitic network to pi elmore model for drvr_pin.
|
||||
virtual void reduceToPiElmore(const Parasitic *parasitic,
|
||||
const Pin *drvr_pin,
|
||||
const OperatingConditions *op_cond,
|
||||
const Corner *corner,
|
||||
const MinMax *cnst_min_max,
|
||||
const ParasiticAnalysisPt *ap);
|
||||
virtual void reduceToPiPoleResidue2(const Parasitic *parasitic,
|
||||
const Net *net,
|
||||
const OperatingConditions *op_cond,
|
||||
const Corner *corner,
|
||||
const MinMax *cnst_min_max,
|
||||
const ParasiticAnalysisPt *ap);
|
||||
virtual void reduceToPiPoleResidue2(const Parasitic *parasitic,
|
||||
const Pin *drvr_pin,
|
||||
const OperatingConditions *op_cond,
|
||||
const Corner *corner,
|
||||
const MinMax *cnst_min_max,
|
||||
const ParasiticAnalysisPt *ap);
|
||||
virtual Parasitic *
|
||||
estimatePiElmore(const Pin *drvr_pin,
|
||||
const RiseFall *rf,
|
||||
const Wireload *wireload,
|
||||
float fanout,
|
||||
float net_pin_cap,
|
||||
const OperatingConditions *op_cond,
|
||||
const Corner *corner,
|
||||
const MinMax *min_max,
|
||||
const ParasiticAnalysisPt *ap);
|
||||
|
||||
virtual void disconnectPinBefore(const Pin *pin);
|
||||
virtual void loadPinCapacitanceChanged(const Pin *pin);
|
||||
};
|
||||
|
||||
} // namespace
|
||||
|
|
@ -17,6 +17,8 @@
|
|||
#pragma once
|
||||
|
||||
#include <complex>
|
||||
#include <map>
|
||||
#include <vector>
|
||||
|
||||
#include "StaState.hh"
|
||||
#include "LibertyClass.hh"
|
||||
|
|
@ -31,16 +33,17 @@ class Corner;
|
|||
|
||||
typedef std::complex<float> ComplexFloat;
|
||||
typedef Vector<ComplexFloat> ComplexFloatSeq;
|
||||
typedef Iterator<ParasiticDevice*> ParasiticDeviceIterator;
|
||||
typedef Iterator<ParasiticNode*> ParasiticNodeIterator;
|
||||
typedef std::vector<ParasiticNode*> ParasiticNodeSeq;
|
||||
typedef std::vector<ParasiticResistor*> ParasiticResistorSeq;
|
||||
typedef std::vector<ParasiticCapacitor*> ParasiticCapacitorSeq;
|
||||
typedef std::map<ParasiticNode *, ParasiticResistorSeq> ParasiticNodeResistorMap;
|
||||
typedef std::map<ParasiticNode *, ParasiticCapacitorSeq> ParasiticNodeCapacitorMap;
|
||||
|
||||
// Parasitics API.
|
||||
// All parasitic parameters can have multiple values, each corresponding
|
||||
// to an analysis point.
|
||||
// Parasitic annotation for a pin or net may exist for one analysis point
|
||||
// and not another.
|
||||
// If there is only one parasitic for both rise and fall transitions
|
||||
// the parasitic readers will save it under the rise transition.
|
||||
class Parasitics : public StaState
|
||||
{
|
||||
public:
|
||||
|
|
@ -50,8 +53,6 @@ public:
|
|||
// Clear all state.
|
||||
virtual void clear() = 0;
|
||||
|
||||
// Save parasitics to database file.
|
||||
virtual void save() = 0;
|
||||
// Delete all parasitics.
|
||||
virtual void deleteParasitics() = 0;
|
||||
// Delete all parasitics on net at analysis point.
|
||||
|
|
@ -60,7 +61,6 @@ public:
|
|||
// Delete all parasitics on pin at analysis point.
|
||||
virtual void deleteParasitics(const Pin *pin,
|
||||
const ParasiticAnalysisPt *ap) = 0;
|
||||
virtual void deleteUnsavedParasitic(Parasitic *parasitic) = 0;
|
||||
virtual void deleteReducedParasitics(const Net *net,
|
||||
const ParasiticAnalysisPt *ap) = 0;
|
||||
virtual void deleteDrvrReducedParasitics(const Pin *drvr_pin) = 0;
|
||||
|
|
@ -153,8 +153,9 @@ public:
|
|||
virtual Parasitic *makeParasiticNetwork(const Net *net,
|
||||
bool includes_pin_caps,
|
||||
const ParasiticAnalysisPt *ap) = 0;
|
||||
virtual ParasiticDeviceIterator *deviceIterator(const Parasitic *parasitic) = 0;
|
||||
virtual ParasiticNodeIterator *nodeIterator(const Parasitic *parasitic) = 0;
|
||||
virtual ParasiticNodeSeq nodes(const Parasitic *parasitic) const = 0;
|
||||
virtual ParasiticResistorSeq resistors(const Parasitic *parasitic) const = 0;
|
||||
virtual ParasiticCapacitorSeq capacitors(const Parasitic *parasitic) const = 0;
|
||||
// Delete parasitic network if it exists.
|
||||
virtual void deleteParasiticNetwork(const Net *net,
|
||||
const ParasiticAnalysisPt *ap) = 0;
|
||||
|
|
@ -165,130 +166,98 @@ public:
|
|||
// Make a subnode of the parasitic network net.
|
||||
virtual ParasiticNode *ensureParasiticNode(Parasitic *parasitic,
|
||||
const Net *net,
|
||||
int id) = 0;
|
||||
int id,
|
||||
const Network *network) = 0;
|
||||
// Make a subnode of the parasitic network net connected to pin.
|
||||
virtual ParasiticNode *ensureParasiticNode(Parasitic *parasitic,
|
||||
const Pin *pin) = 0;
|
||||
const Pin *pin,
|
||||
const Network *network) = 0;
|
||||
// Increment the grounded capacitance on node.
|
||||
virtual void incrCap(ParasiticNode *node,
|
||||
float cap,
|
||||
const ParasiticAnalysisPt *ap) = 0;
|
||||
// Coupling capacitor between parasitic nodes on a net.
|
||||
// name is optional. The device takes ownership of the name string.
|
||||
virtual void makeCouplingCap(const char *name,
|
||||
ParasiticNode *node,
|
||||
ParasiticNode *other_node,
|
||||
float cap,
|
||||
const ParasiticAnalysisPt *ap) = 0;
|
||||
// Coupling capacitor to parasitic node on a different net.
|
||||
// name is optional. The device takes ownership of the name string.
|
||||
virtual void makeCouplingCap(const char *name,
|
||||
ParasiticNode *node,
|
||||
Net *other_node_net,
|
||||
int other_node_id,
|
||||
float cap,
|
||||
const ParasiticAnalysisPt *ap) = 0;
|
||||
// Coupling capacitor to pin on a different net.
|
||||
// name is optional. The device takes ownership of the name string.
|
||||
virtual void makeCouplingCap(const char *name,
|
||||
ParasiticNode *node,
|
||||
Pin *other_node_pin,
|
||||
float cap,
|
||||
const ParasiticAnalysisPt *ap) = 0;
|
||||
// name is optional. The device takes ownership of the name string.
|
||||
virtual void makeResistor(const char *name,
|
||||
ParasiticNode *node1,
|
||||
ParasiticNode *node2,
|
||||
float res,
|
||||
const ParasiticAnalysisPt *ap) = 0;
|
||||
// Check integrity of parasitic network.
|
||||
void check(Parasitic *parasitic) const;
|
||||
|
||||
float cap) = 0;
|
||||
virtual const char *name(const ParasiticNode *node) = 0;
|
||||
virtual const Pin *connectionPin(const ParasiticNode *node) const = 0;
|
||||
virtual const Pin *pin(const ParasiticNode *node) const = 0;
|
||||
virtual const Net *net(const ParasiticNode *node,
|
||||
const Network *network) const = 0;
|
||||
virtual bool isExternal(const ParasiticNode *node) const = 0;
|
||||
// Find the parasitic node connected to pin.
|
||||
virtual ParasiticNode *findNode(const Parasitic *parasitic,
|
||||
const Pin *pin) const = 0;
|
||||
// Node capacitance to ground.
|
||||
virtual float nodeGndCap(const ParasiticNode *node,
|
||||
const ParasiticAnalysisPt *ap) const = 0;
|
||||
virtual ParasiticDeviceIterator *
|
||||
deviceIterator(ParasiticNode *node) const = 0;
|
||||
virtual bool isResistor(const ParasiticDevice *device) const = 0;
|
||||
virtual bool isCouplingCap(const ParasiticDevice *device) const = 0;
|
||||
virtual const char *name(const ParasiticDevice *device) const = 0;
|
||||
// Device "value" (resistance, capacitance).
|
||||
virtual float value(const ParasiticDevice *device,
|
||||
const ParasiticAnalysisPt *ap) const = 0;
|
||||
virtual ParasiticNode *node1(const ParasiticDevice *device) const = 0;
|
||||
virtual ParasiticNode *node2(const ParasiticDevice *device) const = 0;
|
||||
virtual ParasiticNode *otherNode(const ParasiticDevice *device,
|
||||
ParasiticNode *node) const = 0;
|
||||
virtual float nodeGndCap(const ParasiticNode *node) const = 0;
|
||||
|
||||
// Return true if all loads are annoatated.
|
||||
virtual bool checkAnnotation(Parasitic *parasitic_network,
|
||||
const Pin *drvr_pin) = 0;
|
||||
virtual bool checkAnnotation(const Pin *drvr_pin,
|
||||
ParasiticNode *drvr_node) = 0;
|
||||
// Return loads missing path from driver.
|
||||
virtual PinSet unannotatedLoads(Parasitic *parasitic_network,
|
||||
const Pin *drvr_pin) = 0;
|
||||
// Coupling capacitor between parasitic nodes on a net.
|
||||
virtual void makeCapacitor(Parasitic *parasitic,
|
||||
size_t id,
|
||||
float cap,
|
||||
ParasiticNode *node1,
|
||||
ParasiticNode *node2) = 0;
|
||||
virtual size_t id(const ParasiticCapacitor *capacitor) const = 0;
|
||||
virtual float value(const ParasiticCapacitor *capacitor) const = 0;
|
||||
virtual ParasiticNode *node1(const ParasiticCapacitor *capacitor) const = 0;
|
||||
virtual ParasiticNode *node2(const ParasiticCapacitor *capacitor) const = 0;
|
||||
virtual ParasiticNode *otherNode(const ParasiticCapacitor *capacitor,
|
||||
ParasiticNode *node) const;
|
||||
|
||||
virtual void makeResistor(Parasitic *parasitic,
|
||||
size_t id,
|
||||
float res,
|
||||
ParasiticNode *node1,
|
||||
ParasiticNode *node2) = 0;
|
||||
virtual size_t id(const ParasiticResistor *resistor) const = 0;
|
||||
virtual float value(const ParasiticResistor *resistor) const = 0;
|
||||
virtual ParasiticNode *node1(const ParasiticResistor *resistor) const = 0;
|
||||
virtual ParasiticNode *node2(const ParasiticResistor *resistor) const = 0;
|
||||
virtual ParasiticNode *otherNode(const ParasiticResistor *capacitor,
|
||||
ParasiticNode *node) const;
|
||||
|
||||
// Iteration over resistors connected to a nodes.
|
||||
// ParasiticNodeResistorMap resistor_map =
|
||||
// parasitics_->parasiticNodeResistorMap(parasitic_network);
|
||||
// ParasiticResistorSeq &resistors = resistor_map_[node];
|
||||
// for (ParasiticResistor *resistor : resistors) {
|
||||
// }
|
||||
ParasiticNodeResistorMap parasiticNodeResistorMap(const Parasitic *parasitic) const;
|
||||
ParasiticNodeCapacitorMap parasiticNodeCapacitorMap(const Parasitic *parasitic) const;
|
||||
|
||||
// Filters loads that are missing path from driver.
|
||||
virtual PinSet unannotatedLoads(const Parasitic *parasitic,
|
||||
const Pin *drvr_pin) const = 0;
|
||||
// unannotatedLoads helper.
|
||||
PinSet loads(const Pin *drvr_pin) const;
|
||||
|
||||
// Reduce parasitic network to reduce_to model.
|
||||
virtual void reduceTo(const Parasitic *parasitic,
|
||||
const Net *net,
|
||||
ReducedParasiticType reduce_to,
|
||||
const OperatingConditions *op_cond,
|
||||
const Corner *corner,
|
||||
const MinMax *cnst_min_max,
|
||||
const ParasiticAnalysisPt *ap) = 0;
|
||||
// Reduce parasitic network to pi elmore models.
|
||||
virtual void reduceToPiElmore(const Parasitic *parasitic,
|
||||
const Net *net,
|
||||
const OperatingConditions *op_cond,
|
||||
const Corner *corner,
|
||||
const MinMax *cnst_min_max,
|
||||
const ParasiticAnalysisPt *ap) = 0;
|
||||
// Reduce parasitic network to pi elmore model for drvr_pin.
|
||||
virtual void reduceToPiElmore(const Parasitic *parasitic,
|
||||
const Pin *drvr_pin,
|
||||
const OperatingConditions *op_cond,
|
||||
const Corner *corner,
|
||||
const MinMax *cnst_min_max,
|
||||
const ParasiticAnalysisPt *ap) = 0;
|
||||
// Reduce parasitic network to pi and 2nd order pole/residue models.
|
||||
virtual void reduceToPiPoleResidue2(const Parasitic *parasitic,
|
||||
const Net *net,
|
||||
const OperatingConditions *op_cond,
|
||||
const Corner *corner,
|
||||
const MinMax *cnst_min_max,
|
||||
const ParasiticAnalysisPt *ap) = 0;
|
||||
Parasitic *reduceToPiElmore(const Parasitic *parasitic,
|
||||
const Pin *drvr_pin,
|
||||
const RiseFall *rf,
|
||||
const Corner *corner,
|
||||
const MinMax *cnst_min_max,
|
||||
const ParasiticAnalysisPt *ap);
|
||||
// Reduce parasitic network to pi and 2nd order pole/residue models
|
||||
// for drvr_pin.
|
||||
virtual void reduceToPiPoleResidue2(const Parasitic *parasitic,
|
||||
const Pin *drvr_pin,
|
||||
const OperatingConditions *op_cond,
|
||||
const Corner *corner,
|
||||
const MinMax *cnst_min_max,
|
||||
const ParasiticAnalysisPt *ap) = 0;
|
||||
Parasitic *reduceToPiPoleResidue2(const Parasitic *parasitic,
|
||||
const Pin *drvr_pin,
|
||||
const RiseFall *rf,
|
||||
const Corner *corner,
|
||||
const MinMax *cnst_min_max,
|
||||
const ParasiticAnalysisPt *ap);
|
||||
|
||||
// Estimate parasitic as pi elmore using wireload model.
|
||||
virtual Parasitic *estimatePiElmore(const Pin *drvr_pin,
|
||||
const RiseFall *rf,
|
||||
const Wireload *wireload,
|
||||
float fanout,
|
||||
float net_pin_cap,
|
||||
const OperatingConditions *op_cond,
|
||||
const Corner *corner,
|
||||
const MinMax *min_max,
|
||||
const ParasiticAnalysisPt *ap) = 0;
|
||||
Parasitic *estimatePiElmore(const Pin *drvr_pin,
|
||||
const RiseFall *rf,
|
||||
const Wireload *wireload,
|
||||
float fanout,
|
||||
float net_pin_cap,
|
||||
const Corner *corner,
|
||||
const MinMax *min_max);
|
||||
Parasitic *makeWireloadNetwork(const Pin *drvr_pin,
|
||||
const Wireload *wireload,
|
||||
float fanout,
|
||||
const OperatingConditions *op_cond,
|
||||
const MinMax *min_max,
|
||||
const ParasiticAnalysisPt *ap);
|
||||
// Network edit before/after methods.
|
||||
virtual void disconnectPinBefore(const Pin *pin) = 0;
|
||||
virtual void disconnectPinBefore(const Pin *pin,
|
||||
const Network *network) = 0;
|
||||
virtual void loadPinCapacitanceChanged(const Pin *pin) = 0;
|
||||
|
||||
protected:
|
||||
|
|
@ -296,20 +265,17 @@ protected:
|
|||
const Pin *drvr_pin,
|
||||
float wireload_cap,
|
||||
float wireload_res,
|
||||
float fanout,
|
||||
const ParasiticAnalysisPt *ap);
|
||||
float fanout);
|
||||
void makeWireloadNetworkBest(Parasitic *parasitic,
|
||||
const Pin *drvr_pin,
|
||||
float wireload_cap,
|
||||
float wireload_res,
|
||||
float fanout,
|
||||
const ParasiticAnalysisPt *ap);
|
||||
float fanout);
|
||||
void makeWireloadNetworkBalanced(Parasitic *parasitic,
|
||||
const Pin *drvr_pin,
|
||||
float wireload_cap,
|
||||
float wireload_res,
|
||||
float fanout,
|
||||
const ParasiticAnalysisPt *ap);
|
||||
float fanout);
|
||||
|
||||
const Net *findParasiticNet(const Pin *pin) const;
|
||||
};
|
||||
|
|
@ -320,19 +286,18 @@ class ParasiticAnalysisPt
|
|||
public:
|
||||
ParasiticAnalysisPt(const char *name,
|
||||
int index,
|
||||
const MinMax *min_max);
|
||||
~ParasiticAnalysisPt();
|
||||
const char *name() const { return name_; }
|
||||
int index_max);
|
||||
const char *name() const { return name_.c_str(); }
|
||||
int index() const { return index_; }
|
||||
const MinMax *minMax() const { return min_max_; }
|
||||
int indexMax() const { return index_max_; }
|
||||
// Coupling capacitor factor used by all reduction functions.
|
||||
float couplingCapFactor() const { return coupling_cap_factor_; }
|
||||
void setCouplingCapFactor(float factor);
|
||||
|
||||
private:
|
||||
const char *name_;
|
||||
string name_;
|
||||
int index_;
|
||||
const MinMax *min_max_;
|
||||
int index_max_;
|
||||
float coupling_cap_factor_;
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -20,10 +20,9 @@ namespace sta {
|
|||
|
||||
class Parasitics;
|
||||
class Parasitic;
|
||||
class ParasiticDevice;
|
||||
class ParasiticNode;
|
||||
class ParasiticAnalysisPt;
|
||||
|
||||
enum class ReducedParasiticType { pi_elmore, pi_pole_residue2, arnoldi, none };
|
||||
class ParasiticResistor;
|
||||
class ParasiticCapacitor;
|
||||
|
||||
} // namespace
|
||||
|
|
|
|||
|
|
@ -606,7 +606,6 @@ public:
|
|||
// Pin capacitance derated by operating conditions and instance pvt.
|
||||
float pinCapacitance(const Pin *pin,
|
||||
const RiseFall *rf,
|
||||
const OperatingConditions *op_cond,
|
||||
const Corner *corner,
|
||||
const MinMax *min_max);
|
||||
void setResistance(const Net *net,
|
||||
|
|
@ -825,7 +824,7 @@ public:
|
|||
LogicValueMap &logicValues() { return logic_value_map_; }
|
||||
LogicValueMap &caseLogicValues() { return case_value_map_; }
|
||||
// Returns nullptr if set_operating_conditions has not been called.
|
||||
OperatingConditions *operatingConditions(const MinMax *min_max);
|
||||
OperatingConditions *operatingConditions(const MinMax *min_max) const;
|
||||
// Instance specific process/voltage/temperature.
|
||||
const Pvt *pvt(const Instance *inst,
|
||||
const MinMax *min_max) const;
|
||||
|
|
@ -946,7 +945,6 @@ public:
|
|||
// wire_cap = port external wire capacitance + net wire capacitance
|
||||
void connectedCap(const Pin *pin,
|
||||
const RiseFall *rf,
|
||||
const OperatingConditions *op_cond,
|
||||
const Corner *corner,
|
||||
const MinMax *min_max,
|
||||
float &pin_cap,
|
||||
|
|
@ -1233,7 +1231,6 @@ protected:
|
|||
ClockLatency *latency);
|
||||
void pinCaps(const Pin *pin,
|
||||
const RiseFall *rf,
|
||||
const OperatingConditions *op_cond,
|
||||
const Corner *corner,
|
||||
const MinMax *min_max,
|
||||
float &pin_cap,
|
||||
|
|
@ -1241,7 +1238,6 @@ protected:
|
|||
float &fanout) const;
|
||||
void netCaps(const Pin *drvr_pin,
|
||||
const RiseFall *rf,
|
||||
const OperatingConditions *op_cond,
|
||||
const Corner *corner,
|
||||
const MinMax *min_max,
|
||||
// Return values.
|
||||
|
|
@ -1252,12 +1248,10 @@ protected:
|
|||
// connectedCap pin_cap.
|
||||
float connectedPinCap(const Pin *pin,
|
||||
const RiseFall *rf,
|
||||
const OperatingConditions *op_cond,
|
||||
const Corner *corner,
|
||||
const MinMax *min_max);
|
||||
float portCapacitance(Instance *inst, LibertyPort *port,
|
||||
const RiseFall *rf,
|
||||
const OperatingConditions *op_cond,
|
||||
const Corner *corner,
|
||||
const MinMax *min_max) const;
|
||||
void removeClockGroups(ClockGroups *groups);
|
||||
|
|
|
|||
|
|
@ -1111,13 +1111,10 @@ public:
|
|||
InstanceSeq slowDrivers(int count);
|
||||
|
||||
// Make parasitic analysis points.
|
||||
// per_corner per_min_max ap_count
|
||||
// false false 1
|
||||
// false true 2
|
||||
// true false corners
|
||||
// true true corners*2
|
||||
void setParasiticAnalysisPts(bool per_corner,
|
||||
bool per_min_max);
|
||||
// per_corner ap_count
|
||||
// false 2
|
||||
// true corners*2
|
||||
void setParasiticAnalysisPts(bool per_corner);
|
||||
// Annotate hierarchical "instance" with parasitics.
|
||||
// The parasitic analysis point is ap_name.
|
||||
// The parasitic memory footprint is much smaller if parasitic
|
||||
|
|
@ -1131,9 +1128,7 @@ public:
|
|||
bool pin_cap_included,
|
||||
bool keep_coupling_caps,
|
||||
float coupling_cap_factor,
|
||||
ReducedParasiticType reduce_to,
|
||||
bool delete_after_reduce,
|
||||
bool quiet);
|
||||
bool reduce);
|
||||
void reportParasiticAnnotation(bool report_unannotated,
|
||||
const Corner *corner);
|
||||
// Parasitics.
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load Diff
|
|
@ -21,203 +21,148 @@
|
|||
#include "Map.hh"
|
||||
#include "Set.hh"
|
||||
#include "MinMax.hh"
|
||||
#include "EstimateParasitics.hh"
|
||||
#include "Parasitics.hh"
|
||||
|
||||
namespace sta {
|
||||
|
||||
class ConcreteParasitic;
|
||||
class ConcretePiElmore;
|
||||
class ConcretePiPoleResidue;
|
||||
class ConcreteParasiticNetwork;
|
||||
class ConcreteParasiticNode;
|
||||
class ConcreteParasiticDevice;
|
||||
|
||||
typedef Map<const Pin*, ConcreteParasitic**> ConcreteParasiticMap;
|
||||
typedef Map<const Net*, ConcreteParasiticNetwork**> ConcreteParasiticNetworkMap;
|
||||
typedef Set<ParasiticNode*> ParasiticNodeSet;
|
||||
typedef Set<ParasiticDevice*> ParasiticDeviceSet;
|
||||
|
||||
// This class acts as a BUILDER for all parasitics.
|
||||
class ConcreteParasitics : public Parasitics, public EstimateParasitics
|
||||
// This class acts as a BUILDER for parasitics.
|
||||
class ConcreteParasitics : public Parasitics
|
||||
{
|
||||
public:
|
||||
ConcreteParasitics(StaState *sta);
|
||||
virtual ~ConcreteParasitics();
|
||||
virtual bool haveParasitics();
|
||||
virtual void clear();
|
||||
bool haveParasitics() override;
|
||||
void clear() override;
|
||||
|
||||
virtual void save();
|
||||
virtual void deleteParasitics();
|
||||
virtual void deleteParasitics(const Net *net,
|
||||
const ParasiticAnalysisPt *ap);
|
||||
virtual void deleteParasitics(const Pin *drvr_pin,
|
||||
const ParasiticAnalysisPt *ap);
|
||||
virtual void deleteUnsavedParasitic(Parasitic *parasitic);
|
||||
void deleteParasitics() override;
|
||||
void deleteParasitics(const Net *net,
|
||||
const ParasiticAnalysisPt *ap) override;
|
||||
void deleteParasitics(const Pin *drvr_pin,
|
||||
const ParasiticAnalysisPt *ap) override;
|
||||
|
||||
virtual bool isReducedParasiticNetwork(const Parasitic *parasitic) const;
|
||||
virtual void setIsReducedParasiticNetwork(Parasitic *parasitic,
|
||||
bool is_reduced);
|
||||
bool isReducedParasiticNetwork(const Parasitic *parasitic) const override;
|
||||
void setIsReducedParasiticNetwork(Parasitic *parasitic,
|
||||
bool is_reduced) override;
|
||||
|
||||
virtual float capacitance(const Parasitic *parasitic) const;
|
||||
float capacitance(const Parasitic *parasitic) const override;
|
||||
|
||||
virtual bool isPiElmore(const Parasitic *parasitic) const;
|
||||
virtual Parasitic *findPiElmore(const Pin *drvr_pin,
|
||||
const RiseFall *rf,
|
||||
const ParasiticAnalysisPt *ap) const;
|
||||
virtual Parasitic *makePiElmore(const Pin *drvr_pin,
|
||||
const RiseFall *rf,
|
||||
const ParasiticAnalysisPt *ap,
|
||||
float c2,
|
||||
float rpi,
|
||||
float c1);
|
||||
|
||||
virtual bool isPiModel(const Parasitic *parasitic) const;
|
||||
virtual void piModel(const Parasitic *parasitic,
|
||||
float &c2,
|
||||
float &rpi,
|
||||
float &c1) const;
|
||||
virtual void setPiModel(Parasitic *parasitic,
|
||||
bool isPiElmore(const Parasitic *parasitic) const override;
|
||||
Parasitic *findPiElmore(const Pin *drvr_pin,
|
||||
const RiseFall *rf,
|
||||
const ParasiticAnalysisPt *ap) const override;
|
||||
Parasitic *makePiElmore(const Pin *drvr_pin,
|
||||
const RiseFall *rf,
|
||||
const ParasiticAnalysisPt *ap,
|
||||
float c2,
|
||||
float rpi,
|
||||
float c1);
|
||||
float c1) override;
|
||||
|
||||
virtual void findElmore(const Parasitic *parasitic,
|
||||
const Pin *load_pin,
|
||||
float &elmore,
|
||||
bool &exists) const;
|
||||
virtual void setElmore(Parasitic *parasitic,
|
||||
const Pin *load_pin,
|
||||
float elmore);
|
||||
bool isPiModel(const Parasitic *parasitic) const override;
|
||||
void piModel(const Parasitic *parasitic,
|
||||
float &c2,
|
||||
float &rpi,
|
||||
float &c1) const override;
|
||||
void setPiModel(Parasitic *parasitic,
|
||||
float c2,
|
||||
float rpi,
|
||||
float c1) override;
|
||||
|
||||
virtual bool isPiPoleResidue(const Parasitic* parasitic) const;
|
||||
virtual Parasitic *findPiPoleResidue(const Pin *drvr_pin,
|
||||
const RiseFall *rf,
|
||||
const ParasiticAnalysisPt *ap) const;
|
||||
virtual Parasitic *findPoleResidue(const Parasitic *parasitic,
|
||||
const Pin *load_pin) const;
|
||||
virtual Parasitic *makePiPoleResidue(const Pin *drvr_pin,
|
||||
const RiseFall *rf,
|
||||
const ParasiticAnalysisPt *ap,
|
||||
float c2, float rpi, float c1);
|
||||
virtual void setPoleResidue(Parasitic *parasitic, const Pin *load_pin,
|
||||
ComplexFloatSeq *poles,
|
||||
ComplexFloatSeq *residues);
|
||||
virtual bool isPoleResidue(const Parasitic* parasitic) const;
|
||||
virtual size_t poleResidueCount(const Parasitic *parasitic) const;
|
||||
virtual void poleResidue(const Parasitic *parasitic, int pole_index,
|
||||
ComplexFloat &pole, ComplexFloat &residue) const;
|
||||
void findElmore(const Parasitic *parasitic,
|
||||
const Pin *load_pin,
|
||||
float &elmore,
|
||||
bool &exists) const override;
|
||||
void setElmore(Parasitic *parasitic,
|
||||
const Pin *load_pin,
|
||||
float elmore) override;
|
||||
|
||||
virtual bool isParasiticNetwork(const Parasitic *parasitic) const;
|
||||
virtual Parasitic *findParasiticNetwork(const Net *net,
|
||||
const ParasiticAnalysisPt *ap) const;
|
||||
virtual Parasitic *findParasiticNetwork(const Pin *pin,
|
||||
const ParasiticAnalysisPt *ap) const;
|
||||
virtual Parasitic *makeParasiticNetwork(const Net *net,
|
||||
bool includes_pin_caps,
|
||||
const ParasiticAnalysisPt *ap);
|
||||
virtual void deleteParasiticNetwork(const Net *net,
|
||||
const ParasiticAnalysisPt *ap);
|
||||
virtual void deleteParasiticNetworks(const Net *net);
|
||||
virtual bool includesPinCaps(const Parasitic *parasitic) const;
|
||||
virtual ParasiticNode *ensureParasiticNode(Parasitic *parasitic,
|
||||
const Net *net,
|
||||
int id);
|
||||
virtual ParasiticNode *ensureParasiticNode(Parasitic *parasitic,
|
||||
const Pin *pin);
|
||||
virtual void incrCap(ParasiticNode *node, float cap,
|
||||
const ParasiticAnalysisPt *ap);
|
||||
virtual void makeCouplingCap(const char *name,
|
||||
ParasiticNode *node,
|
||||
ParasiticNode *other_node,
|
||||
float cap, const ParasiticAnalysisPt *ap);
|
||||
virtual void makeCouplingCap(const char *name,
|
||||
ParasiticNode *node,
|
||||
Net *other_node_net, int other_node_id,
|
||||
float cap, const ParasiticAnalysisPt *ap);
|
||||
virtual void makeCouplingCap(const char *name,
|
||||
ParasiticNode *node,
|
||||
Pin *other_node_pin,
|
||||
float cap, const ParasiticAnalysisPt *ap);
|
||||
virtual void makeResistor(const char *name, ParasiticNode *node1,
|
||||
ParasiticNode *node2,
|
||||
float res, const ParasiticAnalysisPt *ap);
|
||||
virtual ParasiticDeviceIterator *deviceIterator(const Parasitic *parasitic);
|
||||
virtual ParasiticNodeIterator *nodeIterator(const Parasitic *parasitic);
|
||||
bool isPiPoleResidue(const Parasitic* parasitic) const override;
|
||||
Parasitic *findPiPoleResidue(const Pin *drvr_pin,
|
||||
const RiseFall *rf,
|
||||
const ParasiticAnalysisPt *ap) const override;
|
||||
Parasitic *findPoleResidue(const Parasitic *parasitic,
|
||||
const Pin *load_pin) const override;
|
||||
Parasitic *makePiPoleResidue(const Pin *drvr_pin,
|
||||
const RiseFall *rf,
|
||||
const ParasiticAnalysisPt *ap,
|
||||
float c2, float rpi, float c1) override;
|
||||
void setPoleResidue(Parasitic *parasitic, const Pin *load_pin,
|
||||
ComplexFloatSeq *poles,
|
||||
ComplexFloatSeq *residues) override;
|
||||
bool isPoleResidue(const Parasitic* parasitic) const override;
|
||||
size_t poleResidueCount(const Parasitic *parasitic) const override;
|
||||
void poleResidue(const Parasitic *parasitic,
|
||||
int pole_index,
|
||||
ComplexFloat &pole,
|
||||
ComplexFloat &residue) const override;
|
||||
|
||||
virtual const char *name(const ParasiticNode *node);
|
||||
virtual const Pin *connectionPin(const ParasiticNode *node) const;
|
||||
virtual ParasiticNode *findNode(const Parasitic *parasitic,
|
||||
const Pin *pin) const;
|
||||
virtual float nodeGndCap(const ParasiticNode *node,
|
||||
const ParasiticAnalysisPt *ap) const;
|
||||
virtual ParasiticDeviceIterator *
|
||||
deviceIterator(ParasiticNode *node) const;
|
||||
virtual bool isResistor(const ParasiticDevice *device) const;
|
||||
virtual bool isCouplingCap(const ParasiticDevice *device) const;
|
||||
virtual const char *name(const ParasiticDevice *device) const;
|
||||
virtual float value(const ParasiticDevice *device,
|
||||
const ParasiticAnalysisPt *ap) const;
|
||||
virtual ParasiticNode *node1(const ParasiticDevice *device) const;
|
||||
virtual ParasiticNode *node2(const ParasiticDevice *device) const;
|
||||
virtual ParasiticNode *otherNode(const ParasiticDevice *device,
|
||||
ParasiticNode *node) const;
|
||||
bool isParasiticNetwork(const Parasitic *parasitic) const override;
|
||||
Parasitic *findParasiticNetwork(const Net *net,
|
||||
const ParasiticAnalysisPt *ap) const override;
|
||||
Parasitic *findParasiticNetwork(const Pin *pin,
|
||||
const ParasiticAnalysisPt *ap) const override;
|
||||
Parasitic *makeParasiticNetwork(const Net *net,
|
||||
bool includes_pin_caps,
|
||||
const ParasiticAnalysisPt *ap) override;
|
||||
void deleteParasiticNetwork(const Net *net,
|
||||
const ParasiticAnalysisPt *ap) override;
|
||||
void deleteParasiticNetworks(const Net *net) override;
|
||||
bool includesPinCaps(const Parasitic *parasitic) const override;
|
||||
ParasiticNode *ensureParasiticNode(Parasitic *parasitic,
|
||||
const Net *net,
|
||||
int id,
|
||||
const Network *network) override;
|
||||
ParasiticNode *ensureParasiticNode(Parasitic *parasitic,
|
||||
const Pin *pin,
|
||||
const Network *network) override;
|
||||
ParasiticNodeSeq nodes(const Parasitic *parasitic) const override;
|
||||
void incrCap(ParasiticNode *node,
|
||||
float cap) override;
|
||||
const char *name(const ParasiticNode *node) override;
|
||||
ParasiticNode *findNode(const Parasitic *parasitic,
|
||||
const Pin *pin) const override;
|
||||
const Pin *pin(const ParasiticNode *node) const override;
|
||||
const Net *net(const ParasiticNode *node,
|
||||
const Network *network) const override;
|
||||
bool isExternal(const ParasiticNode *node) const override;
|
||||
float nodeGndCap(const ParasiticNode *node) const override;
|
||||
|
||||
// Return true if all loads are annoatated.
|
||||
virtual bool checkAnnotation(Parasitic *parasitic_network,
|
||||
const Pin *drvr_pin);
|
||||
virtual bool checkAnnotation(const Pin *drvr_pin,
|
||||
ParasiticNode *drvr_node);
|
||||
// Return loads missing path from driver.
|
||||
virtual PinSet unannotatedLoads(Parasitic *parasitic_network,
|
||||
const Pin *drvr_pin);
|
||||
ParasiticResistorSeq resistors(const Parasitic *parasitic) const override;
|
||||
void makeResistor(Parasitic *parasitic,
|
||||
size_t id,
|
||||
float res,
|
||||
ParasiticNode *node1,
|
||||
ParasiticNode *node2) override;
|
||||
size_t id(const ParasiticResistor *resistor) const override;
|
||||
float value(const ParasiticResistor *resistor) const override;
|
||||
ParasiticNode *node1(const ParasiticResistor *resistor) const override;
|
||||
ParasiticNode *node2(const ParasiticResistor *resistor) const override;
|
||||
ParasiticCapacitorSeq capacitors(const Parasitic *parasitic) const override;
|
||||
void makeCapacitor(Parasitic *parasitic,
|
||||
size_t id,
|
||||
float cap,
|
||||
ParasiticNode *node1,
|
||||
ParasiticNode *node2) override;
|
||||
size_t id(const ParasiticCapacitor *capacitor) const override;
|
||||
float value(const ParasiticCapacitor *capacitor) const override;
|
||||
ParasiticNode *node1(const ParasiticCapacitor *capacitor) const override;
|
||||
ParasiticNode *node2(const ParasiticCapacitor *capacitor) const override;
|
||||
|
||||
virtual Parasitic *estimatePiElmore(const Pin *drvr_pin,
|
||||
const RiseFall *rf,
|
||||
const Wireload *wireload,
|
||||
float fanout,
|
||||
float net_pin_cap,
|
||||
const OperatingConditions *op_cond,
|
||||
const Corner *corner,
|
||||
const MinMax *min_max,
|
||||
const ParasiticAnalysisPt *ap);
|
||||
virtual void disconnectPinBefore(const Pin *pin);
|
||||
virtual void loadPinCapacitanceChanged(const Pin *pin);
|
||||
PinSet unannotatedLoads(const Parasitic *parasitic,
|
||||
const Pin *drvr_pin) const override;
|
||||
|
||||
void disconnectPinBefore(const Pin *pin,
|
||||
const Network *network) override;
|
||||
void loadPinCapacitanceChanged(const Pin *pin) override;
|
||||
|
||||
virtual void reduceTo(const Parasitic *parasitic,
|
||||
const Net *net,
|
||||
ReducedParasiticType reduce_to,
|
||||
const OperatingConditions *op_cond,
|
||||
const Corner *corner,
|
||||
const MinMax *cnst_min_max,
|
||||
const ParasiticAnalysisPt *ap);
|
||||
virtual void reduceToPiElmore(const Parasitic *parasitic,
|
||||
const Net *net,
|
||||
const OperatingConditions *op_cond,
|
||||
const Corner *corner,
|
||||
const MinMax *cnst_min_max,
|
||||
const ParasiticAnalysisPt *ap);
|
||||
virtual void reduceToPiElmore(const Parasitic *parasitic,
|
||||
const Pin *drvr_pin,
|
||||
const OperatingConditions *op_cond,
|
||||
const Corner *corner,
|
||||
const MinMax *cnst_min_max,
|
||||
const ParasiticAnalysisPt *ap);
|
||||
virtual void reduceToPiPoleResidue2(const Parasitic *parasitic,
|
||||
const Net *net,
|
||||
const OperatingConditions *op_cond,
|
||||
const Corner *corner,
|
||||
const MinMax *cnst_min_max,
|
||||
const ParasiticAnalysisPt *ap);
|
||||
virtual void reduceToPiPoleResidue2(const Parasitic *parasitic,
|
||||
const Pin *drvr_pin,
|
||||
const OperatingConditions *op_cond,
|
||||
const Corner *corner,
|
||||
const MinMax *cnst_min_max,
|
||||
const ParasiticAnalysisPt *ap);
|
||||
void deleteReducedParasitics(const Net *net,
|
||||
const ParasiticAnalysisPt *ap);
|
||||
virtual void deleteDrvrReducedParasitics(const Pin *drvr_pin);
|
||||
const ParasiticAnalysisPt *ap) override;
|
||||
void deleteDrvrReducedParasitics(const Pin *drvr_pin) override;
|
||||
|
||||
protected:
|
||||
int parasiticAnalysisPtIndex(const ParasiticAnalysisPt *ap,
|
||||
|
|
@ -227,14 +172,6 @@ protected:
|
|||
void deleteReducedParasitics(const Pin *pin);
|
||||
void deleteDrvrReducedParasitics(const Pin *drvr_pin,
|
||||
const ParasiticAnalysisPt *ap);
|
||||
PinSet checkAnnotation1(const Pin *drvr_pin,
|
||||
ParasiticNode *drvr_node);
|
||||
void checkAnnotation2(const Pin *drvr_pin,
|
||||
ParasiticNode *node,
|
||||
ParasiticDevice *from_res,
|
||||
PinSet &loads,
|
||||
ParasiticNodeSet &visited_nodes,
|
||||
ParasiticDeviceSet &loop_resistors);
|
||||
|
||||
// Driver pin to array of parasitics indexed by analysis pt index
|
||||
// and transition.
|
||||
|
|
@ -242,10 +179,8 @@ protected:
|
|||
ConcreteParasiticNetworkMap parasitic_network_map_;
|
||||
mutable std::mutex lock_;
|
||||
|
||||
using EstimateParasitics::estimatePiElmore;
|
||||
friend class ConcretePiElmore;
|
||||
friend class ConcreteParasiticNode;
|
||||
friend class ConcreteParasiticResistor;
|
||||
friend class ConcreteParasiticNetwork;
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -16,38 +16,38 @@
|
|||
|
||||
#pragma once
|
||||
|
||||
#include <map>
|
||||
#include <set>
|
||||
|
||||
#include "Parasitics.hh"
|
||||
|
||||
namespace sta {
|
||||
|
||||
class ConcretePoleResidue;
|
||||
class ConcreteParasiticDevice;
|
||||
class ConcreteParasiticPinNode;
|
||||
class ConcreteParasiticSubNode;
|
||||
class ConcreteParasiticNode;
|
||||
|
||||
typedef Map<const Pin*, float> ConcreteElmoreLoadMap;
|
||||
typedef ConcreteElmoreLoadMap::Iterator ConcretePiElmoreLoadIterator;
|
||||
typedef Map<const Pin*, ConcretePoleResidue*> ConcretePoleResidueMap;
|
||||
typedef std::map<const Pin*, float> ConcreteElmoreLoadMap;
|
||||
typedef std::map<const Pin*, ConcretePoleResidue> ConcretePoleResidueMap;
|
||||
typedef std::pair<const Net*, int> NetIdPair;
|
||||
struct NetIdPairLess
|
||||
{
|
||||
bool operator()(const NetIdPair *net_id1,
|
||||
const NetIdPair *net_id2) const;
|
||||
bool operator()(const NetIdPair &net_id1,
|
||||
const NetIdPair &net_id2) const;
|
||||
};
|
||||
typedef Map<NetIdPair*, ConcreteParasiticSubNode*,
|
||||
NetIdPairLess > ConcreteParasiticSubNodeMap;
|
||||
typedef Map<const Pin*,
|
||||
ConcreteParasiticPinNode*> ConcreteParasiticPinNodeMap;
|
||||
typedef Vector<ConcreteParasiticDevice*> ConcreteParasiticDeviceSeq;
|
||||
typedef Set<ConcreteParasiticDevice*> ConcreteParasiticDeviceSet;
|
||||
typedef Vector<ConcreteParasiticNode*> ConcreteParasiticNodeSeq;
|
||||
typedef std::map<NetIdPair,ConcreteParasiticNode*,
|
||||
NetIdPairLess> ConcreteParasiticSubNodeMap;
|
||||
typedef std::map<const Pin*, ConcreteParasiticNode*> ConcreteParasiticPinNodeMap;
|
||||
typedef std::set<ParasiticNode*> ParasiticNodeSet;
|
||||
typedef std::set<ParasiticResistor*> ParasiticResistorSet;
|
||||
typedef std::vector<ParasiticResistor*> ParasiticResistorSeq;
|
||||
|
||||
// Empty base class definitions so casts are not required on returned
|
||||
// objects.
|
||||
class Parasitic {};
|
||||
class ParasiticNode {};
|
||||
class ParasiticDevice {};
|
||||
class ParasiticResistor {};
|
||||
class ParasiticCapacitor {};
|
||||
class ParasiticNetwork {};
|
||||
|
||||
// Base class for parasitics.
|
||||
|
|
@ -78,8 +78,8 @@ public:
|
|||
virtual void setPoleResidue(const Pin *load_pin,
|
||||
ComplexFloatSeq *poles,
|
||||
ComplexFloatSeq *residues);
|
||||
virtual ParasiticDeviceIterator *deviceIterator() const;
|
||||
virtual ParasiticNodeIterator *nodeIterator() const;
|
||||
virtual PinSet unannotatedLoads(const Pin *drvr_pin,
|
||||
const Parasitics *parasitics) const = 0;
|
||||
};
|
||||
|
||||
// Pi model for a driver pin.
|
||||
|
|
@ -114,70 +114,46 @@ public:
|
|||
ConcretePiElmore(float c2,
|
||||
float rpi,
|
||||
float c1);
|
||||
virtual ~ConcretePiElmore();
|
||||
virtual bool isPiElmore() const { return true; }
|
||||
virtual bool isPiModel() const { return true; }
|
||||
virtual float capacitance() const;
|
||||
virtual void piModel(float &c2, float &rpi, float &c1) const;
|
||||
virtual void setPiModel(float c2, float rpi, float c1);
|
||||
virtual bool isReducedParasiticNetwork() const;
|
||||
virtual void setIsReduced(bool reduced);
|
||||
virtual void findElmore(const Pin *load_pin, float &elmore,
|
||||
bool &exists) const;
|
||||
virtual void setElmore(const Pin *load_pin, float elmore);
|
||||
bool isPiElmore() const override { return true; }
|
||||
bool isPiModel() const override { return true; }
|
||||
float capacitance() const override;
|
||||
void piModel(float &c2,
|
||||
float &rpi,
|
||||
float &c1) const override;
|
||||
void setPiModel(float c2,
|
||||
float rpi,
|
||||
float c1) override;
|
||||
bool isReducedParasiticNetwork() const override;
|
||||
void setIsReduced(bool reduced) override;
|
||||
void findElmore(const Pin *load_pin,
|
||||
float &elmore,
|
||||
bool &exists) const override;
|
||||
void setElmore(const Pin *load_pin,
|
||||
float elmore) override;
|
||||
PinSet unannotatedLoads(const Pin *drvr_pin,
|
||||
const Parasitics *parasitics) const override;
|
||||
void deleteLoad(const Pin *load_pin);
|
||||
|
||||
private:
|
||||
ConcreteElmoreLoadMap *loads_;
|
||||
};
|
||||
|
||||
// PiElmore from wireload model estimate.
|
||||
class ConcretePiElmoreEstimated : public ConcretePi,
|
||||
public ConcreteParasitic
|
||||
{
|
||||
public:
|
||||
ConcretePiElmoreEstimated(float c2,
|
||||
float rpi,
|
||||
float c1,
|
||||
float elmore_res,
|
||||
float elmore_cap,
|
||||
bool elmore_use_load_cap,
|
||||
const RiseFall *rf,
|
||||
const OperatingConditions *op_cond,
|
||||
const Corner *corner,
|
||||
const MinMax *min_max,
|
||||
Sdc *sdc);
|
||||
virtual float capacitance() const;
|
||||
virtual bool isPiElmore() const { return true; }
|
||||
virtual bool isPiModel() const { return true; }
|
||||
virtual void piModel(float &c2, float &rpi, float &c1) const;
|
||||
virtual void findElmore(const Pin *load_pin, float &elmore,
|
||||
bool &exists) const;
|
||||
virtual void setElmore(const Pin *load_pin, float elmore);
|
||||
|
||||
private:
|
||||
float elmore_res_;
|
||||
float elmore_cap_;
|
||||
bool elmore_use_load_cap_;
|
||||
const RiseFall *rf_;
|
||||
const OperatingConditions *op_cond_;
|
||||
const Corner *corner_;
|
||||
const MinMax *min_max_;
|
||||
Sdc *sdc_;
|
||||
ConcreteElmoreLoadMap loads_;
|
||||
};
|
||||
|
||||
class ConcretePoleResidue : public ConcreteParasitic
|
||||
{
|
||||
public:
|
||||
ConcretePoleResidue(ComplexFloatSeq *poles,
|
||||
ComplexFloatSeq *residues);
|
||||
ConcretePoleResidue();
|
||||
virtual ~ConcretePoleResidue();
|
||||
virtual bool isPoleResidue() const { return true; }
|
||||
size_t poleResidueCount() const;
|
||||
void poleResidue(int index, ComplexFloat &pole, ComplexFloat &residue) const;
|
||||
void setPoleResidue(ComplexFloatSeq *poles, ComplexFloatSeq *residues);
|
||||
float capacitance() const { return 0.0; }
|
||||
virtual bool isPoleResidue() const override { return true; }
|
||||
float capacitance() const override { return 0.0; }
|
||||
PinSet unannotatedLoads(const Pin *drvr_pin,
|
||||
const Parasitics *parasitics) const override;
|
||||
|
||||
void setPoleResidue(ComplexFloatSeq *poles,
|
||||
ComplexFloatSeq *residues);
|
||||
void poleResidue(int index,
|
||||
ComplexFloat &pole,
|
||||
ComplexFloat &residue) const;
|
||||
size_t poleResidueCount() const;
|
||||
using ConcreteParasitic::setPoleResidue;
|
||||
|
||||
private:
|
||||
|
|
@ -193,240 +169,147 @@ public:
|
|||
ConcretePiPoleResidue(float c2,
|
||||
float rpi,
|
||||
float c1);
|
||||
virtual ~ConcretePiPoleResidue();
|
||||
virtual bool isPiPoleResidue() const { return true; }
|
||||
virtual bool isPiModel() const { return true; }
|
||||
virtual float capacitance() const;
|
||||
virtual bool isPiPoleResidue() const override { return true; }
|
||||
virtual bool isPiModel() const override { return true; }
|
||||
virtual float capacitance() const override;
|
||||
virtual void piModel(float &c2,
|
||||
float &rpi,
|
||||
float &c1) const;
|
||||
float &c1) const override;
|
||||
virtual void setPiModel(float c2,
|
||||
float rpi,
|
||||
float c1);
|
||||
virtual bool isReducedParasiticNetwork() const;
|
||||
virtual void setIsReduced(bool reduced);
|
||||
virtual Parasitic *findPoleResidue(const Pin *load_pin) const;
|
||||
float c1) override;
|
||||
virtual bool isReducedParasiticNetwork() const override;
|
||||
virtual void setIsReduced(bool reduced) override;
|
||||
virtual Parasitic *findPoleResidue(const Pin *load_pin) const override;
|
||||
virtual void setPoleResidue(const Pin *load_pin,
|
||||
ComplexFloatSeq *poles,
|
||||
ComplexFloatSeq *residues);
|
||||
ComplexFloatSeq *residues) override;
|
||||
virtual PinSet unannotatedLoads(const Pin *drvr_pin,
|
||||
const Parasitics *parasitics) const override;
|
||||
void deleteLoad(const Pin *load_pin);
|
||||
|
||||
private:
|
||||
ConcretePoleResidueMap *load_pole_residue_;
|
||||
};
|
||||
|
||||
class ConcreteParasiticNode : public ParasiticNode
|
||||
{
|
||||
public:
|
||||
virtual ~ConcreteParasiticNode() {}
|
||||
float capacitance() const;
|
||||
virtual const char *name(const Network *network) const = 0;
|
||||
virtual bool isPinNode() const { return false; }
|
||||
ConcreteParasiticDeviceSeq *devices() { return &devices_; }
|
||||
void incrCapacitance(float cap);
|
||||
void addDevice(ConcreteParasiticDevice *device);
|
||||
|
||||
protected:
|
||||
ConcreteParasiticNode();
|
||||
|
||||
float cap_;
|
||||
ConcreteParasiticDeviceSeq devices_;
|
||||
|
||||
friend class ConcreteParasiticNetwork;
|
||||
};
|
||||
|
||||
class ConcreteParasiticSubNode : public ConcreteParasiticNode
|
||||
{
|
||||
public:
|
||||
ConcreteParasiticSubNode(const Net *net,
|
||||
int id);
|
||||
virtual const char *name(const Network *network) const;
|
||||
|
||||
private:
|
||||
const Net *net_;
|
||||
int id_;
|
||||
};
|
||||
|
||||
class ConcreteParasiticPinNode : public ConcreteParasiticNode
|
||||
{
|
||||
public:
|
||||
ConcreteParasiticPinNode(const Pin *pin);
|
||||
const Pin *pin() const { return pin_; }
|
||||
virtual bool isPinNode() const { return true; }
|
||||
virtual const char *name(const Network *network) const;
|
||||
|
||||
private:
|
||||
const Pin *pin_;
|
||||
};
|
||||
|
||||
class ConcreteParasiticDevice : public ParasiticDevice
|
||||
{
|
||||
public:
|
||||
ConcreteParasiticDevice(const char *name,
|
||||
ConcreteParasiticNode *node,
|
||||
float value);
|
||||
virtual ~ConcreteParasiticDevice();
|
||||
virtual bool isResistor() const { return false; }
|
||||
virtual bool isCouplingCap() const { return false; }
|
||||
const char *name() const { return name_; }
|
||||
float value() const { return value_; }
|
||||
ConcreteParasiticNode *node1() const { return node_; }
|
||||
virtual ConcreteParasiticNode *node2() const = 0;
|
||||
virtual ParasiticNode *otherNode(ParasiticNode *node) const = 0;
|
||||
virtual void replaceNode(ConcreteParasiticNode *from_node,
|
||||
ConcreteParasiticNode *to_node) = 0;
|
||||
|
||||
protected:
|
||||
const char *name_;
|
||||
ConcreteParasiticNode *node_;
|
||||
float value_;
|
||||
|
||||
friend class ConcreteParasiticNetwork;
|
||||
};
|
||||
|
||||
class ConcreteParasiticResistor : public ConcreteParasiticDevice
|
||||
{
|
||||
public:
|
||||
ConcreteParasiticResistor(const char *name,
|
||||
ConcreteParasiticNode *node,
|
||||
ConcreteParasiticNode *other_node,
|
||||
float res);
|
||||
virtual bool isResistor() const { return true; }
|
||||
virtual ConcreteParasiticNode *node2() const { return other_node_; }
|
||||
virtual ParasiticNode *otherNode(ParasiticNode *node) const;
|
||||
virtual void replaceNode(ConcreteParasiticNode *from_node,
|
||||
ConcreteParasiticNode *to_node);
|
||||
|
||||
private:
|
||||
ConcreteParasiticNode *other_node_;
|
||||
};
|
||||
|
||||
// Base class for coupling capacitors.
|
||||
class ConcreteCouplingCap : public ConcreteParasiticDevice
|
||||
{
|
||||
public:
|
||||
ConcreteCouplingCap(const char *name,
|
||||
ConcreteParasiticNode *node,
|
||||
float cap);
|
||||
virtual bool isCouplingCap() const { return true; }
|
||||
virtual ConcreteParasiticNode *node2() const { return nullptr; }
|
||||
virtual void replaceNode(ConcreteParasiticNode *from_node,
|
||||
ConcreteParasiticNode *to_node);
|
||||
};
|
||||
|
||||
class ConcreteCouplingCapInt : public ConcreteCouplingCap
|
||||
{
|
||||
public:
|
||||
ConcreteCouplingCapInt(const char *name,
|
||||
ConcreteParasiticNode *node,
|
||||
ConcreteParasiticNode *other_node,
|
||||
float cap);
|
||||
virtual bool isCouplingCap() const { return true; }
|
||||
virtual ConcreteParasiticNode *node2() const { return other_node_; }
|
||||
virtual ParasiticNode *otherNode(ParasiticNode *node) const;
|
||||
virtual void replaceNode(ConcreteParasiticNode *from_node,
|
||||
ConcreteParasiticNode *to_node);
|
||||
|
||||
private:
|
||||
ConcreteParasiticNode *other_node_;
|
||||
};
|
||||
|
||||
class ConcreteCouplingCapExtNode : public ConcreteCouplingCap
|
||||
{
|
||||
public:
|
||||
ConcreteCouplingCapExtNode(const char *name,
|
||||
ConcreteParasiticNode *node,
|
||||
Net *other_node_net,
|
||||
int other_node_id,
|
||||
float cap);
|
||||
virtual bool isCouplingCap() const { return true; }
|
||||
virtual ParasiticNode *otherNode(ParasiticNode *node) const;
|
||||
virtual void replaceNode(ConcreteParasiticNode *from_node,
|
||||
ConcreteParasiticNode *to_node);
|
||||
|
||||
private:
|
||||
};
|
||||
|
||||
class ConcreteCouplingCapExtPin : public ConcreteCouplingCap
|
||||
{
|
||||
public:
|
||||
ConcreteCouplingCapExtPin(const char *name,
|
||||
ConcreteParasiticNode *node,
|
||||
Pin *other_node_pin,
|
||||
float cap);
|
||||
virtual bool isCouplingCap() const { return true; }
|
||||
virtual ParasiticNode *otherNode(ParasiticNode *node) const;
|
||||
virtual void replaceNode(ConcreteParasiticNode *from_node,
|
||||
ConcreteParasiticNode *to_node);
|
||||
|
||||
private:
|
||||
};
|
||||
|
||||
class ConcreteParasiticDeviceSetIterator : public ParasiticDeviceIterator
|
||||
{
|
||||
public:
|
||||
ConcreteParasiticDeviceSetIterator(ConcreteParasiticDeviceSet *devices);
|
||||
virtual ~ConcreteParasiticDeviceSetIterator();
|
||||
bool hasNext() { return iter_.hasNext(); }
|
||||
ParasiticDevice *next() { return iter_.next(); }
|
||||
|
||||
private:
|
||||
ConcreteParasiticDeviceSet::ConstIterator iter_;
|
||||
};
|
||||
|
||||
class ConcreteParasiticDeviceSeqIterator : public ParasiticDeviceIterator
|
||||
{
|
||||
public:
|
||||
ConcreteParasiticDeviceSeqIterator(ConcreteParasiticDeviceSeq *devices);
|
||||
bool hasNext() { return iter_.hasNext(); }
|
||||
ParasiticDevice *next() { return iter_.next(); }
|
||||
|
||||
private:
|
||||
ConcreteParasiticDeviceSeq::ConstIterator iter_;
|
||||
};
|
||||
|
||||
class ConcreteParasiticNodeSeqIterator : public ParasiticNodeIterator
|
||||
{
|
||||
public:
|
||||
ConcreteParasiticNodeSeqIterator(ConcreteParasiticNodeSeq *devices);
|
||||
virtual ~ConcreteParasiticNodeSeqIterator();
|
||||
bool hasNext() { return iter_.hasNext(); }
|
||||
ParasiticNode *next() { return iter_.next(); }
|
||||
|
||||
private:
|
||||
ConcreteParasiticNodeSeq::ConstIterator iter_;
|
||||
ConcretePoleResidueMap load_pole_residue_;
|
||||
};
|
||||
|
||||
class ConcreteParasiticNetwork : public ParasiticNetwork,
|
||||
public ConcreteParasitic
|
||||
{
|
||||
public:
|
||||
ConcreteParasiticNetwork(bool includes_pin_caps);
|
||||
ConcreteParasiticNetwork(const Net *net,
|
||||
bool includes_pin_caps);
|
||||
virtual ~ConcreteParasiticNetwork();
|
||||
virtual bool isParasiticNetwork() const { return true; }
|
||||
const Net *net() { return net_; }
|
||||
bool includesPinCaps() const { return includes_pin_caps_; }
|
||||
ConcreteParasiticNode *ensureParasiticNode(const Net *net,
|
||||
int id);
|
||||
int id,
|
||||
const Network *network);
|
||||
ConcreteParasiticNode *ensureParasiticNode(const Pin *pin,
|
||||
const Network *network);
|
||||
ConcreteParasiticNode *findNode(const Pin *pin) const;
|
||||
ConcreteParasiticNode *ensureParasiticNode(const Pin *pin);
|
||||
virtual float capacitance() const;
|
||||
ConcreteParasiticPinNodeMap *pinNodes() { return &pin_nodes_; }
|
||||
ConcreteParasiticSubNodeMap *subNodes() { return &sub_nodes_; }
|
||||
ParasiticNodeSeq nodes() const;
|
||||
void disconnectPin(const Pin *pin,
|
||||
const Net *net);
|
||||
virtual ParasiticDeviceIterator *deviceIterator() const;
|
||||
virtual ParasiticNodeIterator *nodeIterator() const;
|
||||
virtual void devices(// Return value.
|
||||
ConcreteParasiticDeviceSet *devices) const;
|
||||
const Net *net,
|
||||
const Network *network);
|
||||
ParasiticResistorSeq resistors() const { return resistors_; }
|
||||
void addResistor(ParasiticResistor *resistor);
|
||||
ParasiticCapacitorSeq capacitors() const { return capacitors_; }
|
||||
void addCapacitor(ParasiticCapacitor *capacitor);
|
||||
virtual PinSet unannotatedLoads(const Pin *drvr_pin,
|
||||
const Parasitics *parasitics) const;
|
||||
|
||||
private:
|
||||
void unannotatedLoads(ParasiticNode *node,
|
||||
ParasiticResistor *from_res,
|
||||
PinSet &loads,
|
||||
ParasiticNodeSet &visited_nodes,
|
||||
ParasiticResistorSet &loop_resistors,
|
||||
ParasiticNodeResistorMap &resistor_map,
|
||||
const Parasitics *parasitics) const;
|
||||
|
||||
void deleteNodes();
|
||||
void deleteDevices();
|
||||
|
||||
const Net *net_;
|
||||
ConcreteParasiticSubNodeMap sub_nodes_;
|
||||
ConcreteParasiticPinNodeMap pin_nodes_;
|
||||
ParasiticResistorSeq resistors_;
|
||||
ParasiticCapacitorSeq capacitors_;
|
||||
unsigned max_node_id_:31;
|
||||
bool includes_pin_caps_:1;
|
||||
};
|
||||
|
||||
class ConcreteParasiticNode : public ParasiticNode
|
||||
{
|
||||
public:
|
||||
ConcreteParasiticNode(const Net *net,
|
||||
int id,
|
||||
bool is_external);
|
||||
ConcreteParasiticNode(const Pin *pin,
|
||||
bool is_external);
|
||||
float capacitance() const { return cap_; }
|
||||
const char *name(const Network *network) const;
|
||||
const Net *net(const Network *network) const;
|
||||
bool isExternal() const { return is_external_; }
|
||||
const Pin *pin() const;
|
||||
void incrCapacitance(float cap);
|
||||
|
||||
protected:
|
||||
ConcreteParasiticNode();
|
||||
|
||||
union {
|
||||
const Net *net_;
|
||||
const Pin *pin_;
|
||||
} net_pin_;
|
||||
bool is_net_:1;
|
||||
bool is_external_:1;
|
||||
unsigned id_:30;
|
||||
float cap_;
|
||||
|
||||
friend class ConcreteParasiticNetwork;
|
||||
};
|
||||
|
||||
class ConcreteParasiticDevice
|
||||
{
|
||||
public:
|
||||
ConcreteParasiticDevice(size_t id,
|
||||
float value,
|
||||
ConcreteParasiticNode *node1,
|
||||
ConcreteParasiticNode *node2);
|
||||
int id() const { return id_; }
|
||||
float value() const { return value_; }
|
||||
ConcreteParasiticNode *node1() const { return node1_; }
|
||||
ConcreteParasiticNode *node2() const { return node2_; }
|
||||
void replaceNode(ConcreteParasiticNode *from_node,
|
||||
ConcreteParasiticNode *to_node);
|
||||
|
||||
protected:
|
||||
size_t id_;
|
||||
float value_;
|
||||
ConcreteParasiticNode *node1_;
|
||||
ConcreteParasiticNode *node2_;
|
||||
};
|
||||
|
||||
class ConcreteParasiticResistor : public ParasiticResistor,
|
||||
public ConcreteParasiticDevice
|
||||
{
|
||||
public:
|
||||
ConcreteParasiticResistor(size_t id,
|
||||
float value,
|
||||
ConcreteParasiticNode *node1,
|
||||
ConcreteParasiticNode *node2);
|
||||
};
|
||||
|
||||
class ConcreteParasiticCapacitor : public ParasiticCapacitor,
|
||||
public ConcreteParasiticDevice
|
||||
{
|
||||
public:
|
||||
ConcreteParasiticCapacitor(size_t id,
|
||||
float value,
|
||||
ConcreteParasiticNode *node1,
|
||||
ConcreteParasiticNode *node2);
|
||||
};
|
||||
|
||||
} // namespace
|
||||
|
|
|
|||
|
|
@ -24,6 +24,11 @@
|
|||
|
||||
namespace sta {
|
||||
|
||||
EstimateParasitics::EstimateParasitics(StaState *sta) :
|
||||
StaState(sta)
|
||||
{
|
||||
}
|
||||
|
||||
// For multiple driver nets, output pin capacitances are treated as
|
||||
// loads when driven by a different pin.
|
||||
void
|
||||
|
|
@ -32,10 +37,8 @@ EstimateParasitics::estimatePiElmore(const Pin *drvr_pin,
|
|||
const Wireload *wireload,
|
||||
float fanout,
|
||||
float net_pin_cap,
|
||||
const OperatingConditions *op_cond,
|
||||
const Corner *corner,
|
||||
const MinMax *min_max,
|
||||
const StaState *sta,
|
||||
float &c2,
|
||||
float &rpi,
|
||||
float &c1,
|
||||
|
|
@ -43,6 +46,7 @@ EstimateParasitics::estimatePiElmore(const Pin *drvr_pin,
|
|||
float &elmore_cap,
|
||||
bool &elmore_use_load_cap)
|
||||
{
|
||||
const OperatingConditions *op_cond = sdc_->operatingConditions(min_max);
|
||||
float wireload_cap, wireload_res;
|
||||
wireload->findWireload(fanout, op_cond, wireload_cap, wireload_res);
|
||||
|
||||
|
|
@ -52,22 +56,20 @@ EstimateParasitics::estimatePiElmore(const Pin *drvr_pin,
|
|||
switch (tree) {
|
||||
case WireloadTree::worst_case:
|
||||
estimatePiElmoreWorst(drvr_pin, wireload_cap, wireload_res,
|
||||
fanout, net_pin_cap, rf, op_cond, corner,
|
||||
min_max, sta,
|
||||
fanout, net_pin_cap, rf, corner, min_max,
|
||||
c2, rpi, c1, elmore_res,
|
||||
elmore_cap, elmore_use_load_cap);
|
||||
break;
|
||||
case WireloadTree::balanced:
|
||||
case WireloadTree::unknown:
|
||||
estimatePiElmoreBalanced(drvr_pin, wireload_cap, wireload_res,
|
||||
fanout, net_pin_cap, rf, op_cond,
|
||||
corner, min_max,sta,
|
||||
fanout, net_pin_cap, rf, corner, min_max,
|
||||
c2, rpi, c1, elmore_res,
|
||||
elmore_cap, elmore_use_load_cap);
|
||||
break;
|
||||
case WireloadTree::best_case:
|
||||
estimatePiElmoreBest(drvr_pin, wireload_cap, net_pin_cap, rf,
|
||||
op_cond, corner, min_max,
|
||||
estimatePiElmoreBest(drvr_pin, wireload_cap, net_pin_cap,
|
||||
rf, corner, min_max,
|
||||
c2, rpi, c1, elmore_res, elmore_cap,
|
||||
elmore_use_load_cap);
|
||||
break;
|
||||
|
|
@ -80,7 +82,6 @@ EstimateParasitics::estimatePiElmoreBest(const Pin *,
|
|||
float wireload_cap,
|
||||
float net_pin_cap,
|
||||
const RiseFall *,
|
||||
const OperatingConditions *,
|
||||
const Corner *,
|
||||
const MinMax *,
|
||||
float &c2,
|
||||
|
|
@ -107,10 +108,8 @@ EstimateParasitics::estimatePiElmoreWorst(const Pin *drvr_pin,
|
|||
float,
|
||||
float net_pin_cap,
|
||||
const RiseFall *rf,
|
||||
const OperatingConditions *op_cond,
|
||||
const Corner *corner,
|
||||
const MinMax *min_max,
|
||||
const StaState *sta,
|
||||
float &c2,
|
||||
float &rpi,
|
||||
float &c1,
|
||||
|
|
@ -118,9 +117,8 @@ EstimateParasitics::estimatePiElmoreWorst(const Pin *drvr_pin,
|
|||
float &elmore_cap,
|
||||
bool &elmore_use_load_cap)
|
||||
{
|
||||
Sdc *sdc = sta->sdc();
|
||||
float drvr_pin_cap = 0.0;
|
||||
drvr_pin_cap = sdc->pinCapacitance(drvr_pin, rf, op_cond, corner, min_max);
|
||||
drvr_pin_cap = sdc_->pinCapacitance(drvr_pin, rf, corner, min_max);
|
||||
c2 = drvr_pin_cap;
|
||||
rpi = wireload_res;
|
||||
c1 = net_pin_cap - drvr_pin_cap + wireload_cap;
|
||||
|
|
@ -139,10 +137,8 @@ EstimateParasitics::estimatePiElmoreBalanced(const Pin *drvr_pin,
|
|||
float fanout,
|
||||
float net_pin_cap,
|
||||
const RiseFall *rf,
|
||||
const OperatingConditions *op_cond,
|
||||
const Corner *corner,
|
||||
const MinMax *min_max,
|
||||
const StaState *sta,
|
||||
float &c2,
|
||||
float &rpi,
|
||||
float &c1,
|
||||
|
|
@ -161,31 +157,27 @@ EstimateParasitics::estimatePiElmoreBalanced(const Pin *drvr_pin,
|
|||
elmore_use_load_cap = false;
|
||||
}
|
||||
else {
|
||||
Sdc *sdc = sta->sdc();
|
||||
Network *network = sta->network();
|
||||
Report *report = sta->report();
|
||||
double res_fanout = wireload_res / fanout;
|
||||
double cap_fanout = wireload_cap / fanout;
|
||||
// Find admittance moments.
|
||||
double y1 = 0.0;
|
||||
double y2 = 0.0;
|
||||
double y3 = 0.0;
|
||||
y1 = sdc->pinCapacitance(drvr_pin, rf, op_cond, corner, min_max);
|
||||
y1 = sdc_->pinCapacitance(drvr_pin, rf, corner, min_max);
|
||||
PinConnectedPinIterator *load_iter =
|
||||
network->connectedPinIterator(drvr_pin);
|
||||
network_->connectedPinIterator(drvr_pin);
|
||||
while (load_iter->hasNext()) {
|
||||
const Pin *load_pin = load_iter->next();
|
||||
// Bidirects don't count themselves as loads.
|
||||
if (load_pin != drvr_pin && network->isLoad(load_pin)) {
|
||||
Port *port = network->port(load_pin);
|
||||
if (load_pin != drvr_pin && network_->isLoad(load_pin)) {
|
||||
Port *port = network_->port(load_pin);
|
||||
double load_cap = 0.0;
|
||||
if (network->isLeaf(load_pin))
|
||||
load_cap = sdc->pinCapacitance(load_pin, rf, op_cond,
|
||||
corner, min_max);
|
||||
else if (network->isTopLevelPort(load_pin))
|
||||
load_cap = sdc->portExtCap(port, rf, corner, min_max);
|
||||
if (network_->isLeaf(load_pin))
|
||||
load_cap = sdc_->pinCapacitance(load_pin, rf, corner, min_max);
|
||||
else if (network_->isTopLevelPort(load_pin))
|
||||
load_cap = sdc_->portExtCap(port, rf, corner, min_max);
|
||||
else
|
||||
report->critical(1050, "load pin not leaf or top level");
|
||||
report_->critical(1050, "load pin not leaf or top level");
|
||||
double cap = load_cap + cap_fanout;
|
||||
double y2_ = res_fanout * cap * cap;
|
||||
y1 += cap;
|
||||
|
|
|
|||
|
|
@ -16,6 +16,7 @@
|
|||
|
||||
#pragma once
|
||||
|
||||
#include "StaState.hh"
|
||||
#include "LibertyClass.hh"
|
||||
#include "NetworkClass.hh"
|
||||
#include "SdcClass.hh"
|
||||
|
|
@ -26,21 +27,18 @@ namespace sta {
|
|||
class Corner;
|
||||
class StaState;
|
||||
|
||||
class EstimateParasitics
|
||||
class EstimateParasitics : public StaState
|
||||
{
|
||||
public:
|
||||
|
||||
protected:
|
||||
EstimateParasitics(StaState *sta);
|
||||
// Helper function for wireload estimation.
|
||||
void estimatePiElmore(const Pin *drvr_pin,
|
||||
const RiseFall *rf,
|
||||
const Wireload *wireload,
|
||||
float fanout,
|
||||
float net_pin_cap,
|
||||
const OperatingConditions *op_cond,
|
||||
const Corner *corner,
|
||||
const MinMax *min_max,
|
||||
const StaState *sta,
|
||||
// Return values.
|
||||
float &c2,
|
||||
float &rpi,
|
||||
|
|
@ -48,11 +46,12 @@ protected:
|
|||
float &elmore_res,
|
||||
float &elmore_cap,
|
||||
bool &elmore_use_load_cap);
|
||||
|
||||
protected:
|
||||
void estimatePiElmoreBest(const Pin *drvr_pin,
|
||||
float net_pin_cap,
|
||||
float wireload_cap,
|
||||
const RiseFall *rf,
|
||||
const OperatingConditions *op_cond,
|
||||
const Corner *corner,
|
||||
const MinMax *min_max,
|
||||
// Return values.
|
||||
|
|
@ -68,10 +67,8 @@ protected:
|
|||
float fanout,
|
||||
float net_pin_cap,
|
||||
const RiseFall *rf,
|
||||
const OperatingConditions *op_cond,
|
||||
const Corner *corner,
|
||||
const MinMax *min_max,
|
||||
const StaState *sta,
|
||||
// Return values.
|
||||
float &c2, float &rpi, float &c1,
|
||||
float &elmore_res, float &elmore_cap,
|
||||
|
|
@ -82,10 +79,8 @@ protected:
|
|||
float fanout,
|
||||
float net_pin_cap,
|
||||
const RiseFall *rf,
|
||||
const OperatingConditions *op_cond,
|
||||
const Corner *corner,
|
||||
const MinMax *min_max,
|
||||
const StaState *sta,
|
||||
// Return values.
|
||||
float &c2, float &rpi, float &c1,
|
||||
float &elmore_res, float &elmore_cap,
|
||||
|
|
|
|||
|
|
@ -1,467 +0,0 @@
|
|||
// OpenSTA, Static Timing Analyzer
|
||||
// Copyright (c) 2024, 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 <https://www.gnu.org/licenses/>.
|
||||
|
||||
#include "NullParasitics.hh"
|
||||
|
||||
namespace sta {
|
||||
|
||||
NullParasitics::NullParasitics(StaState *sta) :
|
||||
Parasitics(sta)
|
||||
{
|
||||
}
|
||||
|
||||
bool
|
||||
NullParasitics::haveParasitics()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
void
|
||||
NullParasitics::clear()
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
NullParasitics::save()
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
NullParasitics::deleteParasitics()
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
NullParasitics::deleteParasitics(const Net *,
|
||||
const ParasiticAnalysisPt *)
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
NullParasitics::deleteParasitics(const Pin *, const ParasiticAnalysisPt *)
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
NullParasitics::deleteUnsavedParasitic(Parasitic *)
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
NullParasitics::deleteReducedParasitics(const Net *,
|
||||
const ParasiticAnalysisPt *)
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
NullParasitics::deleteDrvrReducedParasitics(const Pin *)
|
||||
{
|
||||
}
|
||||
|
||||
float
|
||||
NullParasitics::capacitance(const Parasitic *) const
|
||||
{
|
||||
return 0.0;
|
||||
}
|
||||
|
||||
Parasitic *
|
||||
NullParasitics::findPiElmore(const Pin *,
|
||||
const RiseFall *,
|
||||
const ParasiticAnalysisPt *) const
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
Parasitic *
|
||||
NullParasitics::makePiElmore(const Pin *,
|
||||
const RiseFall *,
|
||||
const ParasiticAnalysisPt *,
|
||||
float,
|
||||
float,
|
||||
float)
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
bool
|
||||
NullParasitics::isPiElmore(const Parasitic *) const
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
bool
|
||||
NullParasitics::isReducedParasiticNetwork(const Parasitic *) const
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
void
|
||||
NullParasitics::setIsReducedParasiticNetwork(Parasitic *,
|
||||
bool)
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
NullParasitics::piModel(const Parasitic *,
|
||||
float &,
|
||||
float &,
|
||||
float &) const
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
NullParasitics::setPiModel(Parasitic *,
|
||||
float,
|
||||
float,
|
||||
float)
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
NullParasitics::findElmore(const Parasitic *,
|
||||
const Pin *,
|
||||
float &,
|
||||
bool &) const
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
NullParasitics::setElmore(Parasitic *,
|
||||
const Pin *,
|
||||
float)
|
||||
{
|
||||
}
|
||||
|
||||
bool
|
||||
NullParasitics::isPiModel(const Parasitic*) const
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
bool
|
||||
NullParasitics::isPiPoleResidue(const Parasitic* ) const
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
Parasitic *
|
||||
NullParasitics::findPiPoleResidue(const Pin *,
|
||||
const RiseFall *,
|
||||
const ParasiticAnalysisPt *) const
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
Parasitic *
|
||||
NullParasitics::makePiPoleResidue(const Pin *,
|
||||
const RiseFall *,
|
||||
const ParasiticAnalysisPt *,
|
||||
float,
|
||||
float,
|
||||
float)
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
Parasitic *
|
||||
NullParasitics::findPoleResidue(const Parasitic *,
|
||||
const Pin *) const
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void
|
||||
NullParasitics::setPoleResidue(Parasitic *,
|
||||
const Pin *,
|
||||
ComplexFloatSeq *,
|
||||
ComplexFloatSeq *)
|
||||
{
|
||||
}
|
||||
|
||||
bool
|
||||
NullParasitics::isPoleResidue(const Parasitic *) const
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
size_t
|
||||
NullParasitics::poleResidueCount(const Parasitic *) const
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
void
|
||||
NullParasitics::poleResidue(const Parasitic *,
|
||||
int,
|
||||
ComplexFloat &,
|
||||
ComplexFloat &) const
|
||||
{
|
||||
}
|
||||
|
||||
bool
|
||||
NullParasitics::isParasiticNetwork(const Parasitic *) const
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
Parasitic *
|
||||
NullParasitics::findParasiticNetwork(const Net *,
|
||||
const ParasiticAnalysisPt *) const
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
Parasitic *
|
||||
NullParasitics::findParasiticNetwork(const Pin *,
|
||||
const ParasiticAnalysisPt *) const
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
Parasitic *
|
||||
NullParasitics::makeParasiticNetwork(const Net *,
|
||||
bool,
|
||||
const ParasiticAnalysisPt *)
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
bool
|
||||
NullParasitics::includesPinCaps(const Parasitic *) const
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
void
|
||||
NullParasitics::deleteParasiticNetwork(const Net *,
|
||||
const ParasiticAnalysisPt *)
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
NullParasitics::deleteParasiticNetworks(const Net *)
|
||||
{
|
||||
}
|
||||
|
||||
ParasiticNode *
|
||||
NullParasitics::ensureParasiticNode(Parasitic *,
|
||||
const Net *,
|
||||
int)
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
ParasiticNode *
|
||||
NullParasitics::ensureParasiticNode(Parasitic *,
|
||||
const Pin *)
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void
|
||||
NullParasitics::incrCap(ParasiticNode *,
|
||||
float,
|
||||
const ParasiticAnalysisPt *)
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
NullParasitics::makeCouplingCap(const char *,
|
||||
ParasiticNode *,
|
||||
ParasiticNode *,
|
||||
float,
|
||||
const ParasiticAnalysisPt *)
|
||||
{
|
||||
}
|
||||
|
||||
void NullParasitics::makeCouplingCap(const char *,
|
||||
ParasiticNode *,
|
||||
Net *,
|
||||
int,
|
||||
float,
|
||||
const ParasiticAnalysisPt *)
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
NullParasitics::makeCouplingCap(const char *,
|
||||
ParasiticNode *,
|
||||
Pin *,
|
||||
float,
|
||||
const ParasiticAnalysisPt *)
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
NullParasitics::makeResistor(const char *,
|
||||
ParasiticNode *,
|
||||
ParasiticNode *,
|
||||
float,
|
||||
const ParasiticAnalysisPt *)
|
||||
{
|
||||
}
|
||||
|
||||
const char *
|
||||
NullParasitics::name(const ParasiticNode *)
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
const Pin *
|
||||
NullParasitics::connectionPin(const ParasiticNode *) const
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
ParasiticNode *
|
||||
NullParasitics::findNode(const Parasitic *,
|
||||
const Pin *) const
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
float
|
||||
NullParasitics::nodeGndCap(const ParasiticNode *,
|
||||
const ParasiticAnalysisPt *) const
|
||||
{
|
||||
return 0.0;
|
||||
}
|
||||
|
||||
ParasiticDeviceIterator *
|
||||
NullParasitics::deviceIterator(ParasiticNode *) const
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
bool
|
||||
NullParasitics::isResistor(const ParasiticDevice *) const
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
bool
|
||||
NullParasitics::isCouplingCap(const ParasiticDevice *) const
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
const char *
|
||||
NullParasitics::name(const ParasiticDevice *) const
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
float
|
||||
NullParasitics::value(const ParasiticDevice *,
|
||||
const ParasiticAnalysisPt *) const
|
||||
{
|
||||
return 0.0;
|
||||
}
|
||||
|
||||
ParasiticNode *
|
||||
NullParasitics::node1(const ParasiticDevice *) const
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
ParasiticNode *
|
||||
NullParasitics::node2(const ParasiticDevice *) const
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
ParasiticNode *
|
||||
NullParasitics::otherNode(const ParasiticDevice *,
|
||||
ParasiticNode *) const
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void
|
||||
NullParasitics::reduceTo(const Parasitic *,
|
||||
const Net *,
|
||||
ReducedParasiticType ,
|
||||
const OperatingConditions *,
|
||||
const Corner *,
|
||||
const MinMax *,
|
||||
const ParasiticAnalysisPt *)
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
NullParasitics::reduceToPiElmore(const Parasitic *,
|
||||
const Net *,
|
||||
const OperatingConditions *,
|
||||
const Corner *,
|
||||
const MinMax *,
|
||||
const ParasiticAnalysisPt *)
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
NullParasitics::reduceToPiElmore(const Parasitic *,
|
||||
const Pin *,
|
||||
const OperatingConditions *,
|
||||
const Corner *,
|
||||
const MinMax *,
|
||||
const ParasiticAnalysisPt *)
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
NullParasitics::reduceToPiPoleResidue2(const Parasitic *, const Net *,
|
||||
const OperatingConditions *,
|
||||
const Corner *,
|
||||
const MinMax *,
|
||||
const ParasiticAnalysisPt *)
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
NullParasitics::reduceToPiPoleResidue2(const Parasitic *,
|
||||
const Pin *,
|
||||
const OperatingConditions *,
|
||||
const Corner *,
|
||||
const MinMax *,
|
||||
const ParasiticAnalysisPt *)
|
||||
{
|
||||
}
|
||||
|
||||
Parasitic *
|
||||
NullParasitics::estimatePiElmore(const Pin *,
|
||||
const RiseFall *,
|
||||
const Wireload *,
|
||||
float,
|
||||
float,
|
||||
const OperatingConditions *,
|
||||
const Corner *,
|
||||
const MinMax *,
|
||||
const ParasiticAnalysisPt *)
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void
|
||||
NullParasitics::disconnectPinBefore(const Pin *)
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
NullParasitics::loadPinCapacitanceChanged(const Pin *)
|
||||
{
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
|
@ -23,7 +23,9 @@
|
|||
#include "Network.hh"
|
||||
#include "PortDirection.hh"
|
||||
#include "Sdc.hh"
|
||||
#include "Corner.hh"
|
||||
#include "ReduceParasitics.hh"
|
||||
#include "EstimateParasitics.hh"
|
||||
|
||||
namespace sta {
|
||||
|
||||
|
|
@ -51,28 +53,138 @@ Parasitics::findParasiticNet(const Pin *pin) const
|
|||
return nullptr;
|
||||
}
|
||||
|
||||
void
|
||||
Parasitics::check(Parasitic *) const
|
||||
PinSet
|
||||
Parasitics::loads(const Pin *drvr_pin) const
|
||||
{
|
||||
#if 0
|
||||
ConcreteParasiticSubNodeMap::Iterator sub_node_iter(sub_nodes_);
|
||||
while (sub_node_iter.hasNext()) {
|
||||
ConcreteParasiticSubNode *node = sub_node_iter.next();
|
||||
ConcreteParasiticDeviceSeq::Iterator device_iter(node->devices());
|
||||
int res_count = 0;
|
||||
while (device_iter.hasNext()) {
|
||||
ConcreteParasiticDevice *device = device_iter.next();
|
||||
if (device->isResistor())
|
||||
res_count++;
|
||||
}
|
||||
if (res_count == 0)
|
||||
report->warn("sub node %s has no resistor connections",
|
||||
node->name(network));
|
||||
else if (res_count == 1)
|
||||
report->warn("sub node %s has one resistor connection",
|
||||
node->name(network));
|
||||
PinSet loads(network_);
|
||||
NetConnectedPinIterator *pin_iter = network_->connectedPinIterator(drvr_pin);
|
||||
while (pin_iter->hasNext()) {
|
||||
const Pin *pin = pin_iter->next();
|
||||
if (network_->isLoad(pin) && !network_->isHierarchical(pin))
|
||||
loads.insert(pin);
|
||||
}
|
||||
#endif
|
||||
delete pin_iter;
|
||||
return loads;
|
||||
}
|
||||
|
||||
ParasiticNodeResistorMap
|
||||
Parasitics::parasiticNodeResistorMap(const Parasitic *parasitic) const
|
||||
{
|
||||
ParasiticNodeResistorMap resistor_map;
|
||||
for (ParasiticResistor *resistor : resistors(parasitic)) {
|
||||
ParasiticNode *n1 = node1(resistor);
|
||||
ParasiticNode *n2 = node2(resistor);
|
||||
resistor_map[n1].push_back(resistor);
|
||||
resistor_map[n2].push_back(resistor);
|
||||
}
|
||||
return resistor_map;
|
||||
}
|
||||
|
||||
ParasiticNodeCapacitorMap
|
||||
Parasitics::parasiticNodeCapacitorMap(const Parasitic *parasitic) const
|
||||
{
|
||||
ParasiticNodeCapacitorMap capacitor_map;
|
||||
for (ParasiticCapacitor *capacitor : capacitors(parasitic)) {
|
||||
ParasiticNode *n1 = node1(capacitor);
|
||||
ParasiticNode *n2 = node2(capacitor);
|
||||
capacitor_map[n1].push_back(capacitor);
|
||||
capacitor_map[n2].push_back(capacitor);
|
||||
}
|
||||
return capacitor_map;
|
||||
}
|
||||
|
||||
ParasiticNode *
|
||||
Parasitics::otherNode(const ParasiticResistor *resistor,
|
||||
ParasiticNode *node) const
|
||||
{
|
||||
ParasiticNode *n1 = node1(resistor);
|
||||
if (node == n1)
|
||||
return node2(resistor);
|
||||
else if (node == node2(resistor))
|
||||
return n1;
|
||||
else
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
ParasiticNode *
|
||||
Parasitics::otherNode(const ParasiticCapacitor *capacitor,
|
||||
ParasiticNode *node) const
|
||||
{
|
||||
ParasiticNode *n1 = node1(capacitor);
|
||||
if (node == n1)
|
||||
return node2(capacitor);
|
||||
else if (node == node2(capacitor))
|
||||
return n1;
|
||||
else
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////
|
||||
|
||||
Parasitic *
|
||||
Parasitics::reduceToPiElmore(const Parasitic *parasitic,
|
||||
const Pin *drvr_pin,
|
||||
const RiseFall *rf,
|
||||
const Corner *corner,
|
||||
const MinMax *cnst_min_max,
|
||||
const ParasiticAnalysisPt *ap)
|
||||
{
|
||||
return sta::reduceToPiElmore(parasitic, drvr_pin, rf, ap->couplingCapFactor(),
|
||||
corner, cnst_min_max, ap, this);
|
||||
}
|
||||
|
||||
Parasitic *
|
||||
Parasitics::reduceToPiPoleResidue2(const Parasitic *parasitic,
|
||||
const Pin *drvr_pin,
|
||||
const RiseFall *rf,
|
||||
const Corner *corner,
|
||||
const MinMax *cnst_min_max,
|
||||
const ParasiticAnalysisPt *ap)
|
||||
{
|
||||
return sta::reduceToPiPoleResidue2(parasitic, drvr_pin, rf,
|
||||
ap->couplingCapFactor(),
|
||||
corner, cnst_min_max,
|
||||
ap, this);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////
|
||||
|
||||
Parasitic *
|
||||
Parasitics::estimatePiElmore(const Pin *drvr_pin,
|
||||
const RiseFall *rf,
|
||||
const Wireload *wireload,
|
||||
float fanout,
|
||||
float net_pin_cap,
|
||||
const Corner *corner,
|
||||
const MinMax *min_max)
|
||||
{
|
||||
EstimateParasitics estimate(this);
|
||||
float c2, rpi, c1, elmore_res, elmore_cap;
|
||||
bool elmore_use_load_cap;
|
||||
estimate.estimatePiElmore(drvr_pin, rf, wireload, fanout, net_pin_cap,
|
||||
corner, min_max,
|
||||
c2, rpi, c1,
|
||||
elmore_res, elmore_cap, elmore_use_load_cap);
|
||||
|
||||
if (c1 > 0.0 || c2 > 0.0) {
|
||||
ParasiticAnalysisPt *ap = corner->findParasiticAnalysisPt(min_max);
|
||||
Parasitic *parasitic = makePiElmore(drvr_pin, rf, ap, c2, rpi, c1);
|
||||
NetConnectedPinIterator *pin_iter = network_->connectedPinIterator(drvr_pin);
|
||||
while (pin_iter->hasNext()) {
|
||||
const Pin *pin = pin_iter->next();
|
||||
if (network_->isLoad(pin)) {
|
||||
float load_cap = 0.0;
|
||||
if (elmore_use_load_cap)
|
||||
load_cap = sdc_->pinCapacitance(pin, rf, corner, min_max);
|
||||
float elmore = elmore_res * (elmore_cap + load_cap);
|
||||
setElmore(parasitic, pin, elmore);
|
||||
}
|
||||
}
|
||||
delete pin_iter;
|
||||
return parasitic;
|
||||
}
|
||||
else
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////
|
||||
|
|
@ -81,11 +193,12 @@ Parasitic *
|
|||
Parasitics::makeWireloadNetwork(const Pin *drvr_pin,
|
||||
const Wireload *wireload,
|
||||
float fanout,
|
||||
const OperatingConditions *op_cond,
|
||||
const MinMax *min_max,
|
||||
const ParasiticAnalysisPt *ap)
|
||||
{
|
||||
Net *net = network_->net(drvr_pin);
|
||||
Parasitic *parasitic = makeParasiticNetwork(net, false, ap);
|
||||
const OperatingConditions *op_cond = sdc_->operatingConditions(min_max);
|
||||
float wireload_cap, wireload_res;
|
||||
wireload->findWireload(fanout, op_cond, wireload_cap, wireload_res);
|
||||
|
||||
|
|
@ -95,16 +208,16 @@ Parasitics::makeWireloadNetwork(const Pin *drvr_pin,
|
|||
switch (tree) {
|
||||
case WireloadTree::worst_case:
|
||||
makeWireloadNetworkWorst(parasitic, drvr_pin, wireload_cap,
|
||||
wireload_res, fanout, ap);
|
||||
wireload_res, fanout);
|
||||
break;
|
||||
case WireloadTree::balanced:
|
||||
makeWireloadNetworkBalanced(parasitic, drvr_pin, wireload_cap,
|
||||
wireload_res, fanout, ap);
|
||||
wireload_res, fanout);
|
||||
break;
|
||||
case WireloadTree::best_case:
|
||||
case WireloadTree::unknown:
|
||||
makeWireloadNetworkBest(parasitic, drvr_pin, wireload_cap,
|
||||
wireload_res, fanout, ap);
|
||||
wireload_res, fanout);
|
||||
break;
|
||||
}
|
||||
return parasitic;
|
||||
|
|
@ -117,22 +230,22 @@ Parasitics::makeWireloadNetworkWorst(Parasitic *parasitic,
|
|||
const Pin *drvr_pin,
|
||||
float wireload_cap,
|
||||
float wireload_res,
|
||||
float /* fanout */,
|
||||
const ParasiticAnalysisPt *ap)
|
||||
float /* fanout */)
|
||||
{
|
||||
ParasiticNode *drvr_node = ensureParasiticNode(parasitic, drvr_pin);
|
||||
ParasiticNode *drvr_node = ensureParasiticNode(parasitic, drvr_pin, network_);
|
||||
Net *net = network_->net(drvr_pin);
|
||||
ParasiticNode *load_node = ensureParasiticNode(parasitic, net, 0);
|
||||
makeResistor(nullptr, drvr_node, load_node, wireload_res, ap);
|
||||
parasitics_->incrCap(load_node, wireload_cap, ap);
|
||||
size_t resistor_index = 1;
|
||||
ParasiticNode *load_node = ensureParasiticNode(parasitic, net, 0, network_);
|
||||
makeResistor(parasitic, resistor_index++, wireload_res, drvr_node, load_node);
|
||||
parasitics_->incrCap(load_node, wireload_cap);
|
||||
PinConnectedPinIterator *load_iter =
|
||||
network_->connectedPinIterator(drvr_pin);
|
||||
while (load_iter->hasNext()) {
|
||||
const Pin *load_pin = load_iter->next();
|
||||
if (load_pin != drvr_pin
|
||||
&& network_->isLoad(load_pin)) {
|
||||
ParasiticNode *load_node1 = ensureParasiticNode(parasitic, load_pin);
|
||||
makeResistor(nullptr, load_node, load_node1, 0.0, ap);
|
||||
ParasiticNode *load_node1 = ensureParasiticNode(parasitic, load_pin, network_);
|
||||
makeResistor(parasitic, resistor_index++, 0.0, load_node, load_node1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -143,19 +256,19 @@ Parasitics::makeWireloadNetworkBest(Parasitic *parasitic,
|
|||
const Pin *drvr_pin,
|
||||
float wireload_cap,
|
||||
float /* wireload_res */,
|
||||
float /* fanout */,
|
||||
const ParasiticAnalysisPt *ap)
|
||||
float /* fanout */)
|
||||
{
|
||||
ParasiticNode *drvr_node = ensureParasiticNode(parasitic, drvr_pin);
|
||||
parasitics_->incrCap(drvr_node, wireload_cap, ap);
|
||||
ParasiticNode *drvr_node = ensureParasiticNode(parasitic, drvr_pin, network_);
|
||||
parasitics_->incrCap(drvr_node, wireload_cap);
|
||||
PinConnectedPinIterator *load_iter =
|
||||
network_->connectedPinIterator(drvr_pin);
|
||||
size_t resistor_index = 1;
|
||||
while (load_iter->hasNext()) {
|
||||
const Pin *load_pin = load_iter->next();
|
||||
if (load_pin != drvr_pin
|
||||
&& network_->isLoad(load_pin)) {
|
||||
ParasiticNode *load_node1 = ensureParasiticNode(parasitic, load_pin);
|
||||
makeResistor(nullptr, drvr_node, load_node1, 0.0, ap);
|
||||
ParasiticNode *load_node1 = ensureParasiticNode(parasitic, load_pin, network_);
|
||||
makeResistor(parasitic, resistor_index++, 0.0, drvr_node, load_node1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -167,21 +280,21 @@ Parasitics::makeWireloadNetworkBalanced(Parasitic *parasitic,
|
|||
const Pin *drvr_pin,
|
||||
float wireload_cap,
|
||||
float wireload_res,
|
||||
float fanout,
|
||||
const ParasiticAnalysisPt *ap)
|
||||
float fanout)
|
||||
{
|
||||
float fanout_cap = wireload_cap / fanout;
|
||||
float fanout_res = wireload_res / fanout;
|
||||
ParasiticNode *drvr_node = ensureParasiticNode(parasitic, drvr_pin);
|
||||
ParasiticNode *drvr_node = ensureParasiticNode(parasitic, drvr_pin, network_);
|
||||
PinConnectedPinIterator *load_iter =
|
||||
network_->connectedPinIterator(drvr_pin);
|
||||
size_t resistor_index = 1;
|
||||
while (load_iter->hasNext()) {
|
||||
const Pin *load_pin = load_iter->next();
|
||||
if (load_pin != drvr_pin
|
||||
&& network_->isLoad(load_pin)) {
|
||||
ParasiticNode *load_node1 = ensureParasiticNode(parasitic, load_pin);
|
||||
makeResistor(nullptr, drvr_node, load_node1, fanout_res, ap);
|
||||
parasitics_->incrCap(load_node1, fanout_cap, ap);
|
||||
ParasiticNode *load_node1 = ensureParasiticNode(parasitic, load_pin, network_);
|
||||
makeResistor(parasitic, resistor_index++, fanout_res, drvr_node, load_node1);
|
||||
parasitics_->incrCap(load_node1, fanout_cap);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -190,19 +303,14 @@ Parasitics::makeWireloadNetworkBalanced(Parasitic *parasitic,
|
|||
|
||||
ParasiticAnalysisPt::ParasiticAnalysisPt(const char *name,
|
||||
int index,
|
||||
const MinMax *min_max) :
|
||||
name_(stringCopy(name)),
|
||||
int index_max) :
|
||||
name_(name),
|
||||
index_(index),
|
||||
min_max_(min_max),
|
||||
index_max_(index_max),
|
||||
coupling_cap_factor_(1.0)
|
||||
{
|
||||
}
|
||||
|
||||
ParasiticAnalysisPt::~ParasiticAnalysisPt()
|
||||
{
|
||||
stringDelete(name_);
|
||||
}
|
||||
|
||||
void
|
||||
ParasiticAnalysisPt::setCouplingCapFactor(float factor)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -24,7 +24,6 @@ using sta::Sta;
|
|||
using sta::cmdLinkedNetwork;
|
||||
using sta::Instance;
|
||||
using sta::MinMaxAll;
|
||||
using sta::ReducedParasiticType;
|
||||
using sta::RiseFall;
|
||||
using sta::Pin;
|
||||
|
||||
|
|
@ -40,15 +39,12 @@ read_spef_cmd(const char *filename,
|
|||
bool pin_cap_included,
|
||||
bool keep_coupling_caps,
|
||||
float coupling_cap_factor,
|
||||
ReducedParasiticType reduce_to,
|
||||
bool delete_after_reduce,
|
||||
bool quiet)
|
||||
bool reduce)
|
||||
{
|
||||
cmdLinkedNetwork();
|
||||
return Sta::sta()->readSpef(filename, instance, corner, min_max,
|
||||
pin_cap_included, keep_coupling_caps,
|
||||
coupling_cap_factor, reduce_to,
|
||||
delete_after_reduce, quiet);
|
||||
coupling_cap_factor, reduce);
|
||||
}
|
||||
|
||||
void
|
||||
|
|
|
|||
|
|
@ -26,16 +26,29 @@ define_cmd_args "read_spef" \
|
|||
[-coupling_reduction_factor factor]\
|
||||
[-reduce_to pi_elmore|pi_pole_residue2]\
|
||||
[-delete_after_reduce]\
|
||||
[-quiet]\
|
||||
[-save]\
|
||||
filename}
|
||||
|
||||
proc_redirect read_spef {
|
||||
parse_key_args "read_spef" args \
|
||||
keys {-path -coupling_reduction_factor -reduce_to -corner} \
|
||||
flags {-min -max -increment -pin_cap_included -keep_capacitive_coupling \
|
||||
-delete_after_reduce -quiet -save}
|
||||
check_argc_eq1 "report_spef" $args
|
||||
-reduce -delete_after_reduce -quiet -save}
|
||||
check_argc_eq1 "read_spef" $args
|
||||
|
||||
set reduce [info exists flags(-reduce)]
|
||||
if { [info exists flags(-quiet)] } {
|
||||
sta_warn 272 "read_spef -quiet is deprecated."
|
||||
}
|
||||
if { [info exists keys(-reduce_to)] } {
|
||||
sta_warn 273 "read_spef -reduce_to is deprecated. Use -reduce instead."
|
||||
set reduce 1
|
||||
}
|
||||
if { [info exists flags(-delete_after_reduce)] } {
|
||||
sta_warn 274 "read_spef -delete_after_reduce is deprecated."
|
||||
}
|
||||
if { [info exists flags(-save)] } {
|
||||
sta_warn 275 "read_spef -save is deprecated."
|
||||
}
|
||||
|
||||
set instance [top_instance]
|
||||
if [info exists keys(-path)] {
|
||||
|
|
@ -55,20 +68,10 @@ proc_redirect read_spef {
|
|||
set keep_coupling_caps [info exists flags(-keep_capacitive_coupling)]
|
||||
set pin_cap_included [info exists flags(-pin_cap_included)]
|
||||
|
||||
set reduce_to "none"
|
||||
if [info exists keys(-reduce_to)] {
|
||||
set reduce_to $keys(-reduce_to)
|
||||
if { !($reduce_to == "pi_elmore" || $reduce_to == "pi_pole_residue2") } {
|
||||
sta_error 271 "-reduce_to must be pi_elmore or pi_pole_residue2."
|
||||
}
|
||||
}
|
||||
set delete_after_reduce [info exists flags(-delete_after_reduce)]
|
||||
set quiet [info exists flags(-quiet)]
|
||||
set save [info exists flags(-save)]
|
||||
set filename [file nativename [lindex $args 0]]
|
||||
return [read_spef_cmd $filename $instance $corner $min_max \
|
||||
$pin_cap_included $keep_coupling_caps $coupling_reduction_factor \
|
||||
$reduce_to $delete_after_reduce $quiet]
|
||||
$pin_cap_included $keep_coupling_caps \
|
||||
$coupling_reduction_factor $reduce]
|
||||
}
|
||||
|
||||
define_cmd_args "report_parasitic_annotation" {-report_unannotated}
|
||||
|
|
|
|||
|
|
@ -30,22 +30,21 @@ namespace sta {
|
|||
using std::max;
|
||||
|
||||
typedef Map<ParasiticNode*, double> ParasiticNodeValueMap;
|
||||
typedef Map<ParasiticDevice*, double> ParasiticDeviceValueMap;
|
||||
typedef Set<ParasiticDevice*> ParasiticDeviceSet;
|
||||
typedef Map<ParasiticResistor*, double> ResistorCurrentMap;
|
||||
typedef Set<ParasiticResistor*> ParasiticResistorSet;
|
||||
typedef Set<ParasiticNode*> ParasiticNodeSet;
|
||||
|
||||
class ReduceToPi : public StaState
|
||||
{
|
||||
public:
|
||||
ReduceToPi(StaState *sta);
|
||||
void reduceToPi(const Pin *drvr_pin,
|
||||
void reduceToPi(const Parasitic *parasitic_network,
|
||||
const Pin *drvr_pin,
|
||||
ParasiticNode *drvr_node,
|
||||
bool includes_pin_caps,
|
||||
float coupling_cap_factor,
|
||||
const RiseFall *rf,
|
||||
const OperatingConditions *op_cond,
|
||||
const Corner *corner,
|
||||
const MinMax *cnst_min_max,
|
||||
const MinMax *min_max,
|
||||
const ParasiticAnalysisPt *ap,
|
||||
float &c2,
|
||||
float &rpi,
|
||||
|
|
@ -55,8 +54,7 @@ public:
|
|||
protected:
|
||||
void reducePiDfs(const Pin *drvr_pin,
|
||||
ParasiticNode *node,
|
||||
ParasiticDevice *from_res,
|
||||
const ParasiticAnalysisPt *ap,
|
||||
ParasiticResistor *from_res,
|
||||
double src_resistance,
|
||||
double &y1,
|
||||
double &y2,
|
||||
|
|
@ -70,18 +68,21 @@ protected:
|
|||
float cap);
|
||||
float downstreamCap(ParasiticNode *node);
|
||||
float pinCapacitance(ParasiticNode *node);
|
||||
bool isLoopResistor(ParasiticDevice *device);
|
||||
void markLoopResistor(ParasiticDevice *device);
|
||||
bool isLoopResistor(ParasiticResistor *resistor);
|
||||
void markLoopResistor(ParasiticResistor *resistor);
|
||||
|
||||
bool includes_pin_caps_;
|
||||
float coupling_cap_multiplier_;
|
||||
const RiseFall *rf_;
|
||||
const OperatingConditions *op_cond_;
|
||||
const Corner *corner_;
|
||||
const MinMax *cnst_min_max_;
|
||||
const MinMax *min_max_;
|
||||
const ParasiticAnalysisPt *ap_;
|
||||
ParasiticNodeResistorMap resistor_map_;
|
||||
ParasiticNodeCapacitorMap capacitor_map_;
|
||||
|
||||
ParasiticNodeSet visited_nodes_;
|
||||
ParasiticNodeValueMap node_values_;
|
||||
ParasiticDeviceSet loop_resistors_;
|
||||
ParasiticResistorSet loop_resistors_;
|
||||
bool pin_caps_one_value_;
|
||||
};
|
||||
|
||||
|
|
@ -89,9 +90,8 @@ ReduceToPi::ReduceToPi(StaState *sta) :
|
|||
StaState(sta),
|
||||
coupling_cap_multiplier_(1.0),
|
||||
rf_(nullptr),
|
||||
op_cond_(nullptr),
|
||||
corner_(nullptr),
|
||||
cnst_min_max_(nullptr),
|
||||
min_max_(nullptr),
|
||||
pin_caps_one_value_(true)
|
||||
{
|
||||
}
|
||||
|
|
@ -101,29 +101,30 @@ ReduceToPi::ReduceToPi(StaState *sta) :
|
|||
// Thomas Savarino, Proceedings of the 1989 Design Automation
|
||||
// Conference.
|
||||
void
|
||||
ReduceToPi::reduceToPi(const Pin *drvr_pin,
|
||||
ReduceToPi::reduceToPi(const Parasitic *parasitic_network,
|
||||
const Pin *drvr_pin,
|
||||
ParasiticNode *drvr_node,
|
||||
bool includes_pin_caps,
|
||||
float coupling_cap_factor,
|
||||
const RiseFall *rf,
|
||||
const OperatingConditions *op_cond,
|
||||
const Corner *corner,
|
||||
const MinMax *cnst_min_max,
|
||||
const MinMax *min_max,
|
||||
const ParasiticAnalysisPt *ap,
|
||||
float &c2,
|
||||
float &rpi,
|
||||
float &c1)
|
||||
{
|
||||
includes_pin_caps_ = includes_pin_caps;
|
||||
includes_pin_caps_ = parasitics_->includesPinCaps(parasitic_network),
|
||||
coupling_cap_multiplier_ = coupling_cap_factor;
|
||||
rf_ = rf;
|
||||
op_cond_ = op_cond;
|
||||
corner_ = corner;
|
||||
cnst_min_max_ = cnst_min_max;
|
||||
min_max_ = min_max;
|
||||
ap_ = ap;
|
||||
resistor_map_ = parasitics_->parasiticNodeResistorMap(parasitic_network);
|
||||
capacitor_map_ = parasitics_->parasiticNodeCapacitorMap(parasitic_network);
|
||||
|
||||
double y1, y2, y3, dcap;
|
||||
double max_resistance = 0.0;
|
||||
reducePiDfs(drvr_pin, drvr_node, nullptr, ap, 0.0,
|
||||
reducePiDfs(drvr_pin, drvr_node, nullptr, 0.0,
|
||||
y1, y2, y3, dcap, max_resistance);
|
||||
|
||||
if (y2 == 0.0 && y3 == 0.0) {
|
||||
|
|
@ -146,8 +147,7 @@ ReduceToPi::reduceToPi(const Pin *drvr_pin,
|
|||
void
|
||||
ReduceToPi::reducePiDfs(const Pin *drvr_pin,
|
||||
ParasiticNode *node,
|
||||
ParasiticDevice *from_res,
|
||||
const ParasiticAnalysisPt *ap,
|
||||
ParasiticResistor *from_res,
|
||||
double src_resistance,
|
||||
double &y1,
|
||||
double &y2,
|
||||
|
|
@ -155,78 +155,78 @@ ReduceToPi::reducePiDfs(const Pin *drvr_pin,
|
|||
double &dwn_cap,
|
||||
double &max_resistance)
|
||||
{
|
||||
double coupling_cap = 0.0;
|
||||
ParasiticDeviceIterator *device_iter1 = parasitics_->deviceIterator(node);
|
||||
while (device_iter1->hasNext()) {
|
||||
ParasiticDevice *device = device_iter1->next();
|
||||
if (parasitics_->isCouplingCap(device))
|
||||
coupling_cap += parasitics_->value(device, ap);
|
||||
if (parasitics_->isExternal(node)) {
|
||||
y1 = y2 = y3 = 0.0;
|
||||
max_resistance = 0.0;
|
||||
dwn_cap = 0.0;
|
||||
}
|
||||
delete device_iter1;
|
||||
else {
|
||||
double coupling_cap = 0.0;
|
||||
ParasiticCapacitorSeq &capacitors = capacitor_map_[node];
|
||||
for (ParasiticCapacitor *capacitor : capacitors)
|
||||
coupling_cap += parasitics_->value(capacitor);
|
||||
|
||||
y1 = dwn_cap = parasitics_->nodeGndCap(node, ap)
|
||||
+ coupling_cap * coupling_cap_multiplier_
|
||||
+ pinCapacitance(node);
|
||||
y2 = y3 = 0.0;
|
||||
max_resistance = max(max_resistance, src_resistance);
|
||||
dwn_cap = parasitics_->nodeGndCap(node)
|
||||
+ coupling_cap * coupling_cap_multiplier_
|
||||
+ pinCapacitance(node);
|
||||
y1 = dwn_cap;
|
||||
y2 = y3 = 0.0;
|
||||
max_resistance = max(max_resistance, src_resistance);
|
||||
|
||||
visit(node);
|
||||
ParasiticDeviceIterator *device_iter2 = parasitics_->deviceIterator(node);
|
||||
while (device_iter2->hasNext()) {
|
||||
ParasiticDevice *device = device_iter2->next();
|
||||
if (parasitics_->isResistor(device)
|
||||
&& !isLoopResistor(device)) {
|
||||
ParasiticNode *onode = parasitics_->otherNode(device, node);
|
||||
// One commercial extractor creates resistors with identical from/to nodes.
|
||||
if (onode != node
|
||||
&& device != from_res) {
|
||||
if (isVisited(onode)) {
|
||||
// Resistor loop.
|
||||
debugPrint(debug_, "parasitic_reduce", 2, " loop detected thru resistor %s",
|
||||
parasitics_->name(device));
|
||||
markLoopResistor(device);
|
||||
}
|
||||
else {
|
||||
double r = parasitics_->value(device, ap);
|
||||
double yd1, yd2, yd3, dcap;
|
||||
reducePiDfs(drvr_pin, onode, device, ap, src_resistance + r,
|
||||
yd1, yd2, yd3, dcap, max_resistance);
|
||||
// Rule 3. Upstream traversal of a series resistor.
|
||||
// Rule 4. Parallel admittances add.
|
||||
y1 += yd1;
|
||||
y2 += yd2 - r * yd1 * yd1;
|
||||
y3 += yd3 - 2 * r * yd1 * yd2 + r * r * yd1 * yd1 * yd1;
|
||||
dwn_cap += dcap;
|
||||
visit(node);
|
||||
ParasiticResistorSeq &resistors = resistor_map_[node];
|
||||
for (ParasiticResistor *resistor : resistors) {
|
||||
if (!isLoopResistor(resistor)) {
|
||||
ParasiticNode *onode = parasitics_->otherNode(resistor, node);
|
||||
// One commercial extractor creates resistors with identical from/to nodes.
|
||||
if (onode != node
|
||||
&& resistor != from_res) {
|
||||
if (isVisited(onode)) {
|
||||
// Resistor loop.
|
||||
debugPrint(debug_, "parasitic_reduce", 2, " loop detected thru resistor %lu",
|
||||
parasitics_->id(resistor));
|
||||
markLoopResistor(resistor);
|
||||
}
|
||||
else {
|
||||
double r = parasitics_->value(resistor);
|
||||
double yd1, yd2, yd3, dcap;
|
||||
reducePiDfs(drvr_pin, onode, resistor, src_resistance + r,
|
||||
yd1, yd2, yd3, dcap, max_resistance);
|
||||
// Rule 3. Upstream traversal of a series resistor.
|
||||
// Rule 4. Parallel admittances add.
|
||||
y1 += yd1;
|
||||
y2 += yd2 - r * yd1 * yd1;
|
||||
y3 += yd3 - 2 * r * yd1 * yd2 + r * r * yd1 * yd1 * yd1;
|
||||
dwn_cap += dcap;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
delete device_iter2;
|
||||
|
||||
setDownstreamCap(node, dwn_cap);
|
||||
leave(node);
|
||||
debugPrint(debug_, "parasitic_reduce", 3,
|
||||
" node %s y1=%.3g y2=%.3g y3=%.3g cap=%.3g",
|
||||
parasitics_->name(node), y1, y2, y3, dwn_cap);
|
||||
setDownstreamCap(node, dwn_cap);
|
||||
leave(node);
|
||||
debugPrint(debug_, "parasitic_reduce", 3,
|
||||
" node %s y1=%.3g y2=%.3g y3=%.3g cap=%.3g",
|
||||
parasitics_->name(node), y1, y2, y3, dwn_cap);
|
||||
}
|
||||
}
|
||||
|
||||
float
|
||||
ReduceToPi::pinCapacitance(ParasiticNode *node)
|
||||
{
|
||||
const Pin *pin = parasitics_->connectionPin(node);
|
||||
const Pin *pin = parasitics_->pin(node);
|
||||
float pin_cap = 0.0;
|
||||
if (pin) {
|
||||
Port *port = network_->port(pin);
|
||||
LibertyPort *lib_port = network_->libertyPort(port);
|
||||
if (lib_port) {
|
||||
if (!includes_pin_caps_) {
|
||||
pin_cap = sdc_->pinCapacitance(pin, rf_, op_cond_, corner_,
|
||||
cnst_min_max_);
|
||||
pin_cap = sdc_->pinCapacitance(pin, rf_, corner_, min_max_);
|
||||
pin_caps_one_value_ &= lib_port->capacitanceIsOneValue();
|
||||
}
|
||||
}
|
||||
else if (network_->isTopLevelPort(pin))
|
||||
pin_cap = sdc_->portExtCap(port, rf_, corner_, cnst_min_max_);
|
||||
pin_cap = sdc_->portExtCap(port, rf_, corner_, min_max_);
|
||||
}
|
||||
return pin_cap;
|
||||
}
|
||||
|
|
@ -250,15 +250,15 @@ ReduceToPi::leave(ParasiticNode *node)
|
|||
}
|
||||
|
||||
bool
|
||||
ReduceToPi::isLoopResistor(ParasiticDevice *device)
|
||||
ReduceToPi::isLoopResistor(ParasiticResistor *resistor)
|
||||
{
|
||||
return loop_resistors_.hasKey(device);
|
||||
return loop_resistors_.hasKey(resistor);
|
||||
}
|
||||
|
||||
void
|
||||
ReduceToPi::markLoopResistor(ParasiticDevice *device)
|
||||
ReduceToPi::markLoopResistor(ParasiticResistor *resistor)
|
||||
{
|
||||
loop_resistors_.insert(device);
|
||||
loop_resistors_.insert(resistor);
|
||||
}
|
||||
|
||||
void
|
||||
|
|
@ -280,50 +280,44 @@ class ReduceToPiElmore : public ReduceToPi
|
|||
{
|
||||
public:
|
||||
ReduceToPiElmore(StaState *sta);
|
||||
void makePiElmore(const Parasitic *parasitic_network,
|
||||
const Pin *drvr_pin,
|
||||
ParasiticNode *drvr_node,
|
||||
float coupling_cap_factor,
|
||||
const RiseFall *rf,
|
||||
const OperatingConditions *op_cond,
|
||||
const Corner *corner,
|
||||
const MinMax *cnst_min_max,
|
||||
const ParasiticAnalysisPt *ap);
|
||||
Parasitic *makePiElmore(const Parasitic *parasitic_network,
|
||||
const Pin *drvr_pin,
|
||||
ParasiticNode *drvr_node,
|
||||
float coupling_cap_factor,
|
||||
const RiseFall *rf,
|
||||
const Corner *corner,
|
||||
const MinMax *min_max,
|
||||
const ParasiticAnalysisPt *ap);
|
||||
void reduceElmoreDfs(const Pin *drvr_pin,
|
||||
ParasiticNode *node,
|
||||
ParasiticDevice *from_res,
|
||||
ParasiticResistor *from_res,
|
||||
double elmore,
|
||||
Parasitic *pi_elmore,
|
||||
const ParasiticAnalysisPt *ap);
|
||||
Parasitic *pi_elmore);
|
||||
};
|
||||
|
||||
void
|
||||
Parasitic *
|
||||
reduceToPiElmore(const Parasitic *parasitic_network,
|
||||
const Pin *drvr_pin,
|
||||
float coupling_cap_factor,
|
||||
const OperatingConditions *op_cond,
|
||||
const RiseFall *rf,
|
||||
float coupling_cap_factor,
|
||||
const Corner *corner,
|
||||
const MinMax *cnst_min_max,
|
||||
const MinMax *min_max,
|
||||
const ParasiticAnalysisPt *ap,
|
||||
StaState *sta)
|
||||
{
|
||||
Parasitics *parasitics = sta->parasitics();
|
||||
ParasiticNode *drvr_node = parasitics->findNode(parasitic_network,
|
||||
drvr_pin);
|
||||
ParasiticNode *drvr_node = parasitics->findNode(parasitic_network, drvr_pin);
|
||||
if (drvr_node) {
|
||||
debugPrint(sta->debug(), "parasitic_reduce", 1, "Reduce driver %s",
|
||||
sta->network()->pathName(drvr_pin));
|
||||
debugPrint(sta->debug(), "parasitic_reduce", 1, "Reduce driver %s %s %s",
|
||||
sta->network()->pathName(drvr_pin),
|
||||
rf->asString(),
|
||||
min_max->asString());
|
||||
ReduceToPiElmore reducer(sta);
|
||||
if (parasitics->checkAnnotation(drvr_pin, drvr_node)) {
|
||||
reducer.makePiElmore(parasitic_network, drvr_pin, drvr_node,
|
||||
coupling_cap_factor, RiseFall::rise(),
|
||||
op_cond, corner, cnst_min_max, ap);
|
||||
if (!reducer.pinCapsOneValue())
|
||||
reducer.makePiElmore(parasitic_network, drvr_pin, drvr_node,
|
||||
coupling_cap_factor, RiseFall::fall(),
|
||||
op_cond, corner, cnst_min_max, ap);
|
||||
}
|
||||
return reducer.makePiElmore(parasitic_network, drvr_pin, drvr_node,
|
||||
coupling_cap_factor, rf, corner,
|
||||
min_max, ap);
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
ReduceToPiElmore::ReduceToPiElmore(StaState *sta) :
|
||||
|
|
@ -331,27 +325,24 @@ ReduceToPiElmore::ReduceToPiElmore(StaState *sta) :
|
|||
{
|
||||
}
|
||||
|
||||
void
|
||||
Parasitic *
|
||||
ReduceToPiElmore::makePiElmore(const Parasitic *parasitic_network,
|
||||
const Pin *drvr_pin,
|
||||
ParasiticNode *drvr_node,
|
||||
float coupling_cap_factor,
|
||||
const RiseFall *rf,
|
||||
const OperatingConditions *op_cond,
|
||||
const Corner *corner,
|
||||
const MinMax *cnst_min_max,
|
||||
const MinMax *min_max,
|
||||
const ParasiticAnalysisPt *ap)
|
||||
{
|
||||
float c2, rpi, c1;
|
||||
reduceToPi(drvr_pin, drvr_node,
|
||||
parasitics_->includesPinCaps(parasitic_network),
|
||||
coupling_cap_factor,
|
||||
rf, op_cond, corner, cnst_min_max, ap,
|
||||
c2, rpi, c1);
|
||||
reduceToPi(parasitic_network, drvr_pin, drvr_node, coupling_cap_factor,
|
||||
rf, corner, min_max, ap, c2, rpi, c1);
|
||||
Parasitic *pi_elmore = parasitics_->makePiElmore(drvr_pin, rf, ap,
|
||||
c2, rpi, c1);
|
||||
parasitics_->setIsReducedParasiticNetwork(pi_elmore, true);
|
||||
reduceElmoreDfs(drvr_pin, drvr_node, 0, 0.0, pi_elmore, ap);
|
||||
reduceElmoreDfs(drvr_pin, drvr_node, 0, 0.0, pi_elmore);
|
||||
return pi_elmore;
|
||||
}
|
||||
|
||||
// Find elmore delays on 2nd DFS search using downstream capacitances
|
||||
|
|
@ -359,12 +350,11 @@ ReduceToPiElmore::makePiElmore(const Parasitic *parasitic_network,
|
|||
void
|
||||
ReduceToPiElmore::reduceElmoreDfs(const Pin *drvr_pin,
|
||||
ParasiticNode *node,
|
||||
ParasiticDevice *from_res,
|
||||
ParasiticResistor *from_res,
|
||||
double elmore,
|
||||
Parasitic *pi_elmore,
|
||||
const ParasiticAnalysisPt *ap)
|
||||
Parasitic *pi_elmore)
|
||||
{
|
||||
const Pin *pin = parasitics_->connectionPin(node);
|
||||
const Pin *pin = parasitics_->pin(node);
|
||||
if (from_res && pin) {
|
||||
if (network_->isLoad(pin)) {
|
||||
debugPrint(debug_, "parasitic_reduce", 2, " Load %s elmore=%.3g",
|
||||
|
|
@ -374,22 +364,17 @@ ReduceToPiElmore::reduceElmoreDfs(const Pin *drvr_pin,
|
|||
}
|
||||
}
|
||||
visit(node);
|
||||
ParasiticDeviceIterator *device_iter = parasitics_->deviceIterator(node);
|
||||
while (device_iter->hasNext()) {
|
||||
ParasiticDevice *device = device_iter->next();
|
||||
if (parasitics_->isResistor(device)) {
|
||||
ParasiticNode *onode = parasitics_->otherNode(device, node);
|
||||
if (device != from_res
|
||||
&& !isVisited(onode)
|
||||
&& !isLoopResistor(device)) {
|
||||
float r = parasitics_->value(device, ap);
|
||||
double onode_elmore = elmore + r * downstreamCap(onode);
|
||||
reduceElmoreDfs(drvr_pin, onode, device, onode_elmore,
|
||||
pi_elmore, ap);
|
||||
}
|
||||
ParasiticResistorSeq &resistors = resistor_map_[node];
|
||||
for (ParasiticResistor *resistor : resistors) {
|
||||
ParasiticNode *onode = parasitics_->otherNode(resistor, node);
|
||||
if (resistor != from_res
|
||||
&& !isVisited(onode)
|
||||
&& !isLoopResistor(resistor)) {
|
||||
float r = parasitics_->value(resistor);
|
||||
double onode_elmore = elmore + r * downstreamCap(onode);
|
||||
reduceElmoreDfs(drvr_pin, onode, resistor, onode_elmore, pi_elmore);
|
||||
}
|
||||
}
|
||||
delete device_iter;
|
||||
leave(node);
|
||||
}
|
||||
|
||||
|
|
@ -401,43 +386,38 @@ public:
|
|||
ReduceToPiPoleResidue2(StaState *sta);
|
||||
~ReduceToPiPoleResidue2();
|
||||
void findPolesResidues(const Parasitic *parasitic_network,
|
||||
Parasitic *pi_pole_residue,
|
||||
Parasitic *pi_pole_residue,
|
||||
const Pin *drvr_pin,
|
||||
ParasiticNode *drvr_node,
|
||||
const ParasiticAnalysisPt *ap);
|
||||
void makePiPoleResidue2(const Parasitic *parasitic_network,
|
||||
const Pin *drvr_pin,
|
||||
ParasiticNode *drvr_node,
|
||||
float coupling_cap_factor,
|
||||
const RiseFall *rf,
|
||||
const OperatingConditions *op_cond,
|
||||
const Corner *corner,
|
||||
const MinMax *cnst_min_max,
|
||||
const ParasiticAnalysisPt *ap);
|
||||
ParasiticNode *drvr_node);
|
||||
Parasitic *makePiPoleResidue2(const Parasitic *parasitic_network,
|
||||
const Pin *drvr_pin,
|
||||
ParasiticNode *drvr_node,
|
||||
float coupling_cap_factor,
|
||||
const RiseFall *rf,
|
||||
const Corner *corner,
|
||||
const MinMax *min_max,
|
||||
const ParasiticAnalysisPt *ap);
|
||||
|
||||
private:
|
||||
void findMoments(const Pin *drvr_pin,
|
||||
ParasiticNode *drvr_node,
|
||||
int moment_count,
|
||||
const ParasiticAnalysisPt *ap);
|
||||
int moment_count);
|
||||
void findMoments(const Pin *drvr_pin,
|
||||
ParasiticNode *node,
|
||||
double from_volt,
|
||||
ParasiticDevice *from_res,
|
||||
int moment_index,
|
||||
const ParasiticAnalysisPt *ap);
|
||||
ParasiticResistor *from_res,
|
||||
int moment_index);
|
||||
double findBranchCurrents(const Pin *drvr_pin,
|
||||
ParasiticNode *node,
|
||||
ParasiticDevice *from_res,
|
||||
int moment_index,
|
||||
const ParasiticAnalysisPt *ap);
|
||||
ParasiticResistor *from_res,
|
||||
int moment_index);
|
||||
double moment(ParasiticNode *node,
|
||||
int moment_index);
|
||||
void setMoment(ParasiticNode *node,
|
||||
double moment,
|
||||
int moment_index);
|
||||
double current(ParasiticDevice *res);
|
||||
void setCurrent(ParasiticDevice *res,
|
||||
double current(ParasiticResistor *res);
|
||||
void setCurrent(ParasiticResistor *res,
|
||||
double i);
|
||||
void findPolesResidues(Parasitic *pi_pole_residue,
|
||||
const Pin *drvr_pin,
|
||||
|
|
@ -445,7 +425,7 @@ private:
|
|||
ParasiticNode *load_node);
|
||||
|
||||
// Resistor/capacitor currents.
|
||||
ParasiticDeviceValueMap currents_;
|
||||
ResistorCurrentMap currents_;
|
||||
ParasiticNodeValueMap *moments_;
|
||||
};
|
||||
|
||||
|
|
@ -465,13 +445,13 @@ ReduceToPiPoleResidue2::ReduceToPiPoleResidue2(StaState *sta) :
|
|||
// "An Explicit RC-Circuit Delay Approximation Based on the First
|
||||
// Three Moments of the Impulse Response", Proceedings of the 33rd
|
||||
// Design Automation Conference, 1996, pg 611-616.
|
||||
void
|
||||
Parasitic *
|
||||
reduceToPiPoleResidue2(const Parasitic *parasitic_network,
|
||||
const Pin *drvr_pin,
|
||||
const RiseFall *rf,
|
||||
float coupling_cap_factor,
|
||||
const OperatingConditions *op_cond,
|
||||
const Corner *corner,
|
||||
const MinMax *cnst_min_max,
|
||||
const MinMax *min_max,
|
||||
const ParasiticAnalysisPt *ap,
|
||||
StaState *sta)
|
||||
{
|
||||
|
|
@ -481,41 +461,33 @@ reduceToPiPoleResidue2(const Parasitic *parasitic_network,
|
|||
debugPrint(sta->debug(), "parasitic_reduce", 1, "Reduce driver %s",
|
||||
sta->network()->pathName(drvr_pin));
|
||||
ReduceToPiPoleResidue2 reducer(sta);
|
||||
if (parasitics->checkAnnotation(drvr_pin, drvr_node)) {
|
||||
reducer.makePiPoleResidue2(parasitic_network, drvr_pin, drvr_node,
|
||||
coupling_cap_factor, RiseFall::rise(),
|
||||
op_cond, corner, cnst_min_max, ap);
|
||||
if (!reducer.pinCapsOneValue())
|
||||
reducer.makePiPoleResidue2(parasitic_network, drvr_pin, drvr_node,
|
||||
coupling_cap_factor, RiseFall::fall(),
|
||||
op_cond, corner, cnst_min_max, ap);
|
||||
}
|
||||
return reducer.makePiPoleResidue2(parasitic_network, drvr_pin, drvr_node,
|
||||
coupling_cap_factor, rf,
|
||||
corner, min_max, ap);
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void
|
||||
Parasitic *
|
||||
ReduceToPiPoleResidue2::makePiPoleResidue2(const Parasitic *parasitic_network,
|
||||
const Pin *drvr_pin,
|
||||
ParasiticNode *drvr_node,
|
||||
float coupling_cap_factor,
|
||||
const RiseFall *rf,
|
||||
const OperatingConditions *op_cond,
|
||||
const Corner *corner,
|
||||
const MinMax *cnst_min_max,
|
||||
const MinMax *min_max,
|
||||
const ParasiticAnalysisPt *ap)
|
||||
{
|
||||
float c2, rpi, c1;
|
||||
reduceToPi(drvr_pin, drvr_node,
|
||||
parasitics_->includesPinCaps(parasitic_network),
|
||||
coupling_cap_factor,
|
||||
rf, op_cond, corner, cnst_min_max, ap,
|
||||
reduceToPi(parasitic_network, drvr_pin, drvr_node,
|
||||
coupling_cap_factor, rf, corner, min_max, ap,
|
||||
c2, rpi, c1);
|
||||
Parasitic *pi_pole_residue = parasitics_->makePiPoleResidue(drvr_pin,
|
||||
rf, ap,
|
||||
c2, rpi, c1);
|
||||
parasitics_->setIsReducedParasiticNetwork(pi_pole_residue, true);
|
||||
findPolesResidues(parasitic_network, pi_pole_residue,
|
||||
drvr_pin, drvr_node, ap);
|
||||
findPolesResidues(parasitic_network, pi_pole_residue, drvr_pin, drvr_node);
|
||||
return pi_pole_residue;
|
||||
}
|
||||
|
||||
ReduceToPiPoleResidue2::~ReduceToPiPoleResidue2()
|
||||
|
|
@ -525,13 +497,12 @@ ReduceToPiPoleResidue2::~ReduceToPiPoleResidue2()
|
|||
|
||||
void
|
||||
ReduceToPiPoleResidue2::findPolesResidues(const Parasitic *parasitic_network,
|
||||
Parasitic *pi_pole_residue,
|
||||
Parasitic *pi_pole_residue,
|
||||
const Pin *drvr_pin,
|
||||
ParasiticNode *drvr_node,
|
||||
const ParasiticAnalysisPt *ap)
|
||||
ParasiticNode *drvr_node)
|
||||
{
|
||||
moments_ = new ParasiticNodeValueMap[4];
|
||||
findMoments(drvr_pin, drvr_node, 4, ap);
|
||||
findMoments(drvr_pin, drvr_node, 4);
|
||||
|
||||
PinConnectedPinIterator *pin_iter = network_->connectedPinIterator(drvr_pin);
|
||||
while (pin_iter->hasNext()) {
|
||||
|
|
@ -549,8 +520,7 @@ ReduceToPiPoleResidue2::findPolesResidues(const Parasitic *parasitic_network,
|
|||
void
|
||||
ReduceToPiPoleResidue2::findMoments(const Pin *drvr_pin,
|
||||
ParasiticNode *drvr_node,
|
||||
int moment_count,
|
||||
const ParasiticAnalysisPt *ap)
|
||||
int moment_count)
|
||||
{
|
||||
// Driver model thevenin resistance.
|
||||
double rd = 0.0;
|
||||
|
|
@ -558,43 +528,38 @@ ReduceToPiPoleResidue2::findMoments(const Pin *drvr_pin,
|
|||
// current thru the resistors. Thus, there is no point in doing a
|
||||
// pass to find the zero'th moments.
|
||||
for (int moment_index = 1; moment_index < moment_count; moment_index++) {
|
||||
double rd_i = findBranchCurrents(drvr_pin, drvr_node, 0,
|
||||
moment_index, ap);
|
||||
double rd_i = findBranchCurrents(drvr_pin, drvr_node, 0, moment_index);
|
||||
double rd_volt = rd_i * rd;
|
||||
setMoment(drvr_node, 0.0, moment_index);
|
||||
findMoments(drvr_pin, drvr_node, -rd_volt, 0, moment_index, ap);
|
||||
findMoments(drvr_pin, drvr_node, -rd_volt, 0, moment_index);
|
||||
}
|
||||
}
|
||||
|
||||
double
|
||||
ReduceToPiPoleResidue2::findBranchCurrents(const Pin *drvr_pin,
|
||||
ParasiticNode *node,
|
||||
ParasiticDevice *from_res,
|
||||
int moment_index,
|
||||
const ParasiticAnalysisPt *ap)
|
||||
ParasiticResistor *from_res,
|
||||
int moment_index)
|
||||
{
|
||||
visit(node);
|
||||
double branch_i = 0.0;
|
||||
double coupling_cap = 0.0;
|
||||
ParasiticDeviceIterator *device_iter = parasitics_->deviceIterator(node);
|
||||
while (device_iter->hasNext()) {
|
||||
ParasiticDevice *device = device_iter->next();
|
||||
if (parasitics_->isResistor(device)) {
|
||||
ParasiticNode *onode = parasitics_->otherNode(device, node);
|
||||
// One commercial extractor creates resistors with identical from/to nodes.
|
||||
if (onode != node
|
||||
&& device != from_res
|
||||
&& !isVisited(onode)
|
||||
&& !isLoopResistor(device)) {
|
||||
branch_i += findBranchCurrents(drvr_pin, onode, device,
|
||||
moment_index, ap);
|
||||
}
|
||||
ParasiticResistorSeq &resistors = resistor_map_[node];
|
||||
for (ParasiticResistor *resistor : resistors) {
|
||||
ParasiticNode *onode = parasitics_->otherNode(resistor, node);
|
||||
// One commercial extractor creates resistors with identical from/to nodes.
|
||||
if (onode != node
|
||||
&& resistor != from_res
|
||||
&& !isVisited(onode)
|
||||
&& !isLoopResistor(resistor)) {
|
||||
branch_i += findBranchCurrents(drvr_pin, onode, resistor, moment_index);
|
||||
}
|
||||
else if (parasitics_->isCouplingCap(device))
|
||||
coupling_cap += parasitics_->value(device, ap);
|
||||
}
|
||||
delete device_iter;
|
||||
double cap = parasitics_->nodeGndCap(node, ap)
|
||||
ParasiticCapacitorSeq &capacitors = capacitor_map_[node];
|
||||
for (ParasiticCapacitor *capacitor : capacitors)
|
||||
coupling_cap += parasitics_->value(capacitor);
|
||||
|
||||
double cap = parasitics_->nodeGndCap(node)
|
||||
+ coupling_cap * coupling_cap_multiplier_
|
||||
+ pinCapacitance(node);
|
||||
branch_i += cap * moment(node, moment_index - 1);
|
||||
|
|
@ -610,34 +575,29 @@ void
|
|||
ReduceToPiPoleResidue2::findMoments(const Pin *drvr_pin,
|
||||
ParasiticNode *node,
|
||||
double from_volt,
|
||||
ParasiticDevice *from_res,
|
||||
int moment_index,
|
||||
const ParasiticAnalysisPt *ap)
|
||||
ParasiticResistor *from_res,
|
||||
int moment_index)
|
||||
{
|
||||
visit(node);
|
||||
ParasiticDeviceIterator *device_iter = parasitics_->deviceIterator(node);
|
||||
while (device_iter->hasNext()) {
|
||||
ParasiticDevice *device = device_iter->next();
|
||||
if (parasitics_->isResistor(device)) {
|
||||
ParasiticNode *onode = parasitics_->otherNode(device, node);
|
||||
// One commercial extractor creates resistors with identical from/to nodes.
|
||||
if (onode != node
|
||||
&& device != from_res
|
||||
&& !isVisited(onode)
|
||||
&& !isLoopResistor(device)) {
|
||||
double r = parasitics_->value(device, ap);
|
||||
double r_volt = r * current(device);
|
||||
double onode_volt = from_volt - r_volt;
|
||||
setMoment(onode, onode_volt, moment_index);
|
||||
debugPrint(debug_, "parasitic_reduce", 3, " moment %s %d %.3g",
|
||||
parasitics_->name(onode),
|
||||
moment_index,
|
||||
onode_volt);
|
||||
findMoments(drvr_pin, onode, onode_volt, device, moment_index, ap);
|
||||
}
|
||||
ParasiticResistorSeq &resistors = resistor_map_[node];
|
||||
for (ParasiticResistor *resistor : resistors) {
|
||||
ParasiticNode *onode = parasitics_->otherNode(resistor, node);
|
||||
// One commercial extractor creates resistors with identical from/to nodes.
|
||||
if (onode != node
|
||||
&& resistor != from_res
|
||||
&& !isVisited(onode)
|
||||
&& !isLoopResistor(resistor)) {
|
||||
double r = parasitics_->value(resistor);
|
||||
double r_volt = r * current(resistor);
|
||||
double onode_volt = from_volt - r_volt;
|
||||
setMoment(onode, onode_volt, moment_index);
|
||||
debugPrint(debug_, "parasitic_reduce", 3, " moment %s %d %.3g",
|
||||
parasitics_->name(onode),
|
||||
moment_index,
|
||||
onode_volt);
|
||||
findMoments(drvr_pin, onode, onode_volt, resistor, moment_index);
|
||||
}
|
||||
}
|
||||
delete device_iter;
|
||||
leave(node);
|
||||
}
|
||||
|
||||
|
|
@ -667,13 +627,13 @@ ReduceToPiPoleResidue2::setMoment(ParasiticNode *node,
|
|||
}
|
||||
|
||||
double
|
||||
ReduceToPiPoleResidue2::current(ParasiticDevice *res)
|
||||
ReduceToPiPoleResidue2::current(ParasiticResistor *res)
|
||||
{
|
||||
return currents_[res];
|
||||
}
|
||||
|
||||
void
|
||||
ReduceToPiPoleResidue2::setCurrent(ParasiticDevice *res,
|
||||
ReduceToPiPoleResidue2::setCurrent(ParasiticResistor *res,
|
||||
double i)
|
||||
{
|
||||
currents_[res] = i;
|
||||
|
|
|
|||
|
|
@ -27,25 +27,25 @@ class ParasiticAnalysisPt;
|
|||
class StaState;
|
||||
|
||||
// Reduce parasitic network to pi elmore model for drvr_pin.
|
||||
void
|
||||
Parasitic *
|
||||
reduceToPiElmore(const Parasitic *parasitic_network,
|
||||
const Pin *drvr_pin,
|
||||
const RiseFall *rf,
|
||||
float coupling_cap_factor,
|
||||
const OperatingConditions *op_cond,
|
||||
const Corner *corner,
|
||||
const MinMax *cnst_min_max,
|
||||
const MinMax *min_max,
|
||||
const ParasiticAnalysisPt *ap,
|
||||
StaState *sta);
|
||||
|
||||
// Reduce parasitic network to pi and 2nd order pole/residue models
|
||||
// for drvr_pin.
|
||||
void
|
||||
Parasitic *
|
||||
reduceToPiPoleResidue2(const Parasitic *parasitic_network,
|
||||
const Pin *drvr_pin,
|
||||
const RiseFall *rf,
|
||||
float coupling_cap_factor,
|
||||
const OperatingConditions *op_cond,
|
||||
const Corner *corner,
|
||||
const MinMax *cnst_min_max,
|
||||
const MinMax *min_max,
|
||||
const ParasiticAnalysisPt *ap,
|
||||
StaState *sta);
|
||||
|
||||
|
|
|
|||
|
|
@ -95,9 +95,11 @@ ReportParasiticAnnotation::reportAnnotationCounts()
|
|||
report_->reportLine(" %s", network_->pathName(drvr_pin));
|
||||
|
||||
Parasitic *parasitic = parasitics_->findParasiticNetwork(drvr_pin, parasitic_ap_);
|
||||
PinSet unannotated_loads = parasitics_->unannotatedLoads(parasitic, drvr_pin);
|
||||
for (const Pin *load_pin : unannotated_loads)
|
||||
report_->reportLine(" %s", network_->pathName(load_pin));
|
||||
if (parasitic) {
|
||||
PinSet unannotated_loads = parasitics_->unannotatedLoads(parasitic, drvr_pin);
|
||||
for (const Pin *load_pin : unannotated_loads)
|
||||
report_->reportLine(" %s", network_->pathName(load_pin));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -105,6 +107,7 @@ ReportParasiticAnnotation::reportAnnotationCounts()
|
|||
void
|
||||
ReportParasiticAnnotation::findCounts()
|
||||
{
|
||||
DcalcAnalysisPt *dcalc_ap = corner_->findDcalcAnalysisPt(min_max_);
|
||||
VertexIterator vertex_iter(graph_);
|
||||
while (vertex_iter.hasNext()) {
|
||||
Vertex *vertex = vertex_iter.next();
|
||||
|
|
@ -113,8 +116,11 @@ ReportParasiticAnnotation::findCounts()
|
|||
if (vertex->isDriver(network_)
|
||||
&& !dir->isInternal()) {
|
||||
Parasitic *parasitic = parasitics_->findParasiticNetwork(pin, parasitic_ap_);
|
||||
if (parasitic == nullptr)
|
||||
parasitic = arc_delay_calc_->findParasitic(pin, RiseFall::rise(), dcalc_ap);
|
||||
if (parasitic) {
|
||||
if (!parasitics_->checkAnnotation(parasitic, pin))
|
||||
PinSet unannotated_loads = parasitics_->unannotatedLoads(parasitic, pin);
|
||||
if (unannotated_loads.size() > 0)
|
||||
partially_annotated_.push_back(pin);
|
||||
}
|
||||
else
|
||||
|
|
|
|||
|
|
@ -27,6 +27,8 @@
|
|||
#include "PortDirection.hh"
|
||||
#include "Sdc.hh"
|
||||
#include "Parasitics.hh"
|
||||
#include "Corner.hh"
|
||||
#include "ArcDelayCalc.hh"
|
||||
#include "SpefReaderPvt.hh"
|
||||
#include "SpefNamespace.hh"
|
||||
|
||||
|
|
@ -37,6 +39,7 @@ spefResetScanner();
|
|||
|
||||
namespace sta {
|
||||
|
||||
// Referenced by parser.
|
||||
SpefReader *spef_reader;
|
||||
|
||||
bool
|
||||
|
|
@ -46,15 +49,10 @@ readSpefFile(const char *filename,
|
|||
bool pin_cap_included,
|
||||
bool keep_coupling_caps,
|
||||
float coupling_cap_factor,
|
||||
ReducedParasiticType reduce_to,
|
||||
bool delete_after_reduce,
|
||||
const OperatingConditions *op_cond,
|
||||
bool reduce,
|
||||
const Corner *corner,
|
||||
const MinMax *cnst_min_max,
|
||||
bool quiet,
|
||||
Report *report,
|
||||
Network *network,
|
||||
Parasitics *parasitics)
|
||||
const MinMaxAll *min_max,
|
||||
StaState *sta)
|
||||
{
|
||||
bool success = false;
|
||||
// Use zlib to uncompress gzip'd files automagically.
|
||||
|
|
@ -62,8 +60,7 @@ readSpefFile(const char *filename,
|
|||
if (stream) {
|
||||
SpefReader reader(filename, stream, instance, ap,
|
||||
pin_cap_included, keep_coupling_caps, coupling_cap_factor,
|
||||
reduce_to, delete_after_reduce, op_cond, corner,
|
||||
cnst_min_max, quiet, report, network, parasitics);
|
||||
reduce, corner, min_max, sta);
|
||||
spef_reader = &reader;
|
||||
::spefResetScanner();
|
||||
// yyparse returns 0 on success.
|
||||
|
|
@ -83,27 +80,19 @@ SpefReader::SpefReader(const char *filename,
|
|||
bool pin_cap_included,
|
||||
bool keep_coupling_caps,
|
||||
float coupling_cap_factor,
|
||||
ReducedParasiticType reduce_to,
|
||||
bool delete_after_reduce,
|
||||
const OperatingConditions *op_cond,
|
||||
bool reduce,
|
||||
const Corner *corner,
|
||||
const MinMax *cnst_min_max,
|
||||
bool quiet,
|
||||
Report *report,
|
||||
Network *network,
|
||||
Parasitics *parasitics) :
|
||||
const MinMaxAll *min_max,
|
||||
StaState *sta) :
|
||||
StaState(sta),
|
||||
filename_(filename),
|
||||
instance_(instance),
|
||||
ap_(ap),
|
||||
pin_cap_included_(pin_cap_included),
|
||||
keep_coupling_caps_(keep_coupling_caps),
|
||||
reduce_to_(reduce_to),
|
||||
delete_after_reduce_(delete_after_reduce),
|
||||
op_cond_(op_cond),
|
||||
reduce_(reduce),
|
||||
corner_(corner),
|
||||
cnst_min_max_(cnst_min_max),
|
||||
keep_device_names_(false),
|
||||
quiet_(quiet),
|
||||
min_max_(min_max),
|
||||
stream_(stream),
|
||||
line_(1),
|
||||
// defaults
|
||||
|
|
@ -112,9 +101,6 @@ SpefReader::SpefReader(const char *filename,
|
|||
bus_brkt_left_('\0'),
|
||||
bus_brkt_right_('\0'),
|
||||
net_(nullptr),
|
||||
report_(report),
|
||||
network_(network),
|
||||
parasitics_(parasitics),
|
||||
triple_index_(0),
|
||||
time_scale_(1.0),
|
||||
cap_scale_(1.0),
|
||||
|
|
@ -134,11 +120,8 @@ SpefReader::~SpefReader()
|
|||
design_flow_ = nullptr;
|
||||
}
|
||||
|
||||
SpefNameMap::Iterator map_iter(name_map_);
|
||||
while (map_iter.hasNext()) {
|
||||
int index;
|
||||
char *name;
|
||||
map_iter.next(index, name);
|
||||
for (auto index_name : name_map_) {
|
||||
char *name = index_name.second;
|
||||
stringDelete(name);
|
||||
}
|
||||
}
|
||||
|
|
@ -164,7 +147,7 @@ SpefReader::setBusBrackets(char left, char right)
|
|||
|| (left == '<' && right == '>')
|
||||
|| (left == ':' && right == '\0')
|
||||
|| (left == '.' && right == '\0')))
|
||||
warn(167, "illegal bus delimiters.");
|
||||
warn(1640, "illegal bus delimiters.");
|
||||
bus_brkt_left_ = left;
|
||||
bus_brkt_right_ = right;
|
||||
}
|
||||
|
|
@ -248,7 +231,7 @@ SpefReader::setTimeScale(float scale,
|
|||
else if (stringEq(units, "PS"))
|
||||
time_scale_ = scale * 1E-12F;
|
||||
else
|
||||
warn(168, "unknown units %s.", units);
|
||||
warn(1641, "unknown units %s.", units);
|
||||
stringDelete(units);
|
||||
}
|
||||
|
||||
|
|
@ -261,7 +244,7 @@ SpefReader::setCapScale(float scale,
|
|||
else if (stringEq(units, "FF"))
|
||||
cap_scale_ = scale * 1E-15F;
|
||||
else
|
||||
warn(168, "unknown units %s.", units);
|
||||
warn(1642, "unknown units %s.", units);
|
||||
stringDelete(units);
|
||||
}
|
||||
|
||||
|
|
@ -274,7 +257,7 @@ SpefReader::setResScale(float scale,
|
|||
else if (stringEq(units, "KOHM"))
|
||||
res_scale_ = scale * 1E+3F;
|
||||
else
|
||||
warn(170, "unknown units %s.", units);
|
||||
warn(1643, "unknown units %s.", units);
|
||||
stringDelete(units);
|
||||
}
|
||||
|
||||
|
|
@ -289,7 +272,7 @@ SpefReader::setInductScale(float scale,
|
|||
else if (stringEq(units, "UH"))
|
||||
induct_scale_ = scale * 1E-6F;
|
||||
else
|
||||
warn(168, "unknown units %s.", units);
|
||||
warn(1644, "unknown units %s.", units);
|
||||
stringDelete(units);
|
||||
}
|
||||
|
||||
|
|
@ -305,14 +288,12 @@ char *
|
|||
SpefReader::nameMapLookup(char *name)
|
||||
{
|
||||
if (name && name[0] == '*') {
|
||||
char *mapped_name;
|
||||
bool exists;
|
||||
int index = atoi(name + 1);
|
||||
name_map_.findKey(index, mapped_name, exists);
|
||||
if (exists)
|
||||
return mapped_name;
|
||||
auto itr = name_map_.find(index);
|
||||
if (itr != name_map_.end())
|
||||
return itr->second;
|
||||
else {
|
||||
warn(169, "no name map entry for %d.", index);
|
||||
warn(1645, "no name map entry for %d.", index);
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
|
@ -331,7 +312,7 @@ SpefReader::portDirection(char *spef_dir)
|
|||
else if (stringEq(spef_dir, "B"))
|
||||
direction = PortDirection::bidirect();
|
||||
else
|
||||
warn(170, "unknown port direction %s.", spef_dir);
|
||||
warn(1646, "unknown port direction %s.", spef_dir);
|
||||
return direction;
|
||||
}
|
||||
|
||||
|
|
@ -358,16 +339,16 @@ SpefReader::findPin(char *name)
|
|||
if (inst) {
|
||||
pin = network_->findPin(inst, port_name);
|
||||
if (pin == nullptr)
|
||||
warn(171, "pin %s not found.", name);
|
||||
warn(1647, "pin %s not found.", name);
|
||||
}
|
||||
else
|
||||
warn(172, "instance %s not found.", name);
|
||||
warn(1648, "instance %s not found.", name);
|
||||
}
|
||||
}
|
||||
else {
|
||||
pin = findPortPinRelative(name);
|
||||
if (pin == nullptr)
|
||||
warn(173, "pin %s not found.", name);
|
||||
warn(1649, "pin %s not found.", name);
|
||||
}
|
||||
}
|
||||
return pin;
|
||||
|
|
@ -381,7 +362,7 @@ SpefReader::findNet(char *name)
|
|||
if (name) {
|
||||
net = findNetRelative(name);
|
||||
if (net == nullptr)
|
||||
warn(174, "net %s not found.", name);
|
||||
warn(1650, "net %s not found.", name);
|
||||
}
|
||||
return net;
|
||||
}
|
||||
|
|
@ -409,12 +390,9 @@ SpefReader::rspfDrvrBegin(Pin *drvr_pin,
|
|||
float c2 = pi->c2()->value(triple_index_) * cap_scale_;
|
||||
float rpi = pi->r1()->value(triple_index_) * res_scale_;
|
||||
float c1 = pi->c1()->value(triple_index_) * cap_scale_;
|
||||
// Delete pi model and elmore delays.
|
||||
parasitics_->deleteParasitics(drvr_pin, ap_);
|
||||
// Only one parasitic, save it under rise transition.
|
||||
parasitic_ = parasitics_->makePiElmore(drvr_pin,
|
||||
RiseFall::rise(),
|
||||
ap_, c2, rpi, c1);
|
||||
parasitic_ = parasitics_->makePiElmore(drvr_pin, RiseFall::rise(), ap_,
|
||||
c2, rpi, c1);
|
||||
}
|
||||
delete pi;
|
||||
}
|
||||
|
|
@ -472,46 +450,18 @@ SpefReader::dspfBegin(Net *net,
|
|||
void
|
||||
SpefReader::dspfFinish()
|
||||
{
|
||||
if (parasitic_) {
|
||||
if (!quiet_)
|
||||
parasitics_->check(parasitic_);
|
||||
if (reduce_to_ != ReducedParasiticType::none) {
|
||||
parasitics_->reduceTo(parasitic_, net_, reduce_to_, op_cond_,
|
||||
corner_, cnst_min_max_, ap_);
|
||||
if (delete_after_reduce_)
|
||||
parasitics_->deleteParasiticNetwork(net_, ap_);
|
||||
}
|
||||
if (parasitic_ && reduce_) {
|
||||
arc_delay_calc_->reduceParasitic(parasitic_, net_, corner_, min_max_);
|
||||
parasitics_->deleteParasiticNetwork(net_, ap_);
|
||||
}
|
||||
parasitic_ = nullptr;
|
||||
net_ = nullptr;
|
||||
}
|
||||
|
||||
// Caller is only interested in nodes on net_.
|
||||
ParasiticNode *
|
||||
SpefReader::findParasiticNode(char *name)
|
||||
{
|
||||
ParasiticNode *node;
|
||||
Net *ext_net;
|
||||
int ext_node_id;
|
||||
Pin *ext_pin;
|
||||
findParasiticNode(name, node, ext_net, ext_node_id, ext_pin);
|
||||
if (node == nullptr
|
||||
&& (ext_net || ext_pin))
|
||||
warn(175, "%s not connected to net %s.", name, network_->pathName(net_));
|
||||
return node;
|
||||
}
|
||||
|
||||
void
|
||||
SpefReader::findParasiticNode(char *name,
|
||||
ParasiticNode *&node,
|
||||
Net *&ext_net,
|
||||
int &ext_node_id,
|
||||
Pin *&ext_pin)
|
||||
bool local_only)
|
||||
{
|
||||
node = nullptr;
|
||||
ext_net = nullptr;
|
||||
ext_node_id = 0;
|
||||
ext_pin = nullptr;
|
||||
if (name && parasitic_) {
|
||||
char *delim = strrchr(name, delimiter_);
|
||||
if (delim) {
|
||||
|
|
@ -523,15 +473,15 @@ SpefReader::findParasiticNode(char *name,
|
|||
// <instance>:<port>
|
||||
Pin *pin = network_->findPin(inst, name2);
|
||||
if (pin) {
|
||||
if (network_->isConnected(net_, pin))
|
||||
node = parasitics_->ensureParasiticNode(parasitic_, pin);
|
||||
else
|
||||
ext_pin = pin;
|
||||
if (local_only
|
||||
&& !network_->isConnected(net_, pin))
|
||||
warn(1651, "%s not connected to net %s.", name, network_->pathName(net_));
|
||||
return parasitics_->ensureParasiticNode(parasitic_, pin, network_);
|
||||
}
|
||||
else {
|
||||
// Replace delimiter for error message.
|
||||
*delim = delimiter_;
|
||||
warn(176, "pin %s not found.", name);
|
||||
warn(1652, "pin %s not found.", name);
|
||||
}
|
||||
}
|
||||
else {
|
||||
|
|
@ -543,15 +493,13 @@ SpefReader::findParasiticNode(char *name,
|
|||
const char *id_str = delim + 1;
|
||||
if (isDigits(id_str)) {
|
||||
int id = atoi(id_str);
|
||||
if (network_->isConnected(net, net_))
|
||||
node = parasitics_->ensureParasiticNode(parasitic_, net, id);
|
||||
else {
|
||||
ext_net = net;
|
||||
ext_node_id = id;
|
||||
}
|
||||
if (local_only
|
||||
&& !network_->isConnected(net, net_))
|
||||
warn(1653, "%s not connected to net %s.", name, network_->pathName(net_));
|
||||
return parasitics_->ensureParasiticNode(parasitic_, net, id, network_);
|
||||
}
|
||||
else
|
||||
warn(177, "node %s not a pin or net:number", name);
|
||||
warn(1654, "node %s not a pin or net:number", name);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -560,25 +508,26 @@ SpefReader::findParasiticNode(char *name,
|
|||
name = nameMapLookup(name);
|
||||
Pin *pin = findPortPinRelative(name);
|
||||
if (pin) {
|
||||
if (network_->isConnected(net_, pin))
|
||||
node = parasitics_->ensureParasiticNode(parasitic_, pin);
|
||||
else
|
||||
ext_pin = pin;
|
||||
if (local_only
|
||||
&& !network_->isConnected(net_, pin))
|
||||
warn(1655, "%s not connected to net %s.", name, network_->pathName(net_));
|
||||
return parasitics_->ensureParasiticNode(parasitic_, pin, network_);
|
||||
}
|
||||
else
|
||||
warn(178, "pin %s not found.", name);
|
||||
warn(1656, "pin %s not found.", name);
|
||||
}
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void
|
||||
SpefReader::makeCapacitor(int, char *node_name,
|
||||
SpefTriple *cap)
|
||||
{
|
||||
ParasiticNode *node = findParasiticNode(node_name);
|
||||
ParasiticNode *node = findParasiticNode(node_name, true);
|
||||
if (node) {
|
||||
float cap1 = cap->value(triple_index_) * cap_scale_;
|
||||
parasitics_->incrCap(node, cap1, ap_);
|
||||
parasitics_->incrCap(node, cap1);
|
||||
}
|
||||
delete cap;
|
||||
stringDelete(node_name);
|
||||
|
|
@ -590,81 +539,36 @@ SpefReader::makeCapacitor(int id,
|
|||
char *node_name2,
|
||||
SpefTriple *cap)
|
||||
{
|
||||
ParasiticNode *node1 = findParasiticNode(node_name1, false);
|
||||
ParasiticNode *node2 = findParasiticNode(node_name2, false);
|
||||
float cap1 = cap->value(triple_index_) * cap_scale_;
|
||||
if (keep_coupling_caps_)
|
||||
makeCouplingCap(id, node_name1, node_name2, cap1);
|
||||
else {
|
||||
ParasiticNode *node1, *node2;
|
||||
Net *ext_net1, *ext_net2;
|
||||
int ext_node_id1, ext_node_id2;
|
||||
Pin *ext_pin1, *ext_pin2;
|
||||
findParasiticNode(node_name1, node1, ext_net1, ext_node_id1, ext_pin1);
|
||||
findParasiticNode(node_name2, node2, ext_net2, ext_node_id2, ext_pin2);
|
||||
float scaled_cap = cap1 * ap_->couplingCapFactor();
|
||||
if (node1)
|
||||
parasitics_->incrCap(node1, scaled_cap, ap_);
|
||||
if (node2)
|
||||
parasitics_->incrCap(node2, scaled_cap, ap_);
|
||||
if (cap1 > 0.0) {
|
||||
if (keep_coupling_caps_)
|
||||
parasitics_->makeCapacitor(parasitic_, id, cap1, node1, node2);
|
||||
else {
|
||||
float scaled_cap = cap1 * ap_->couplingCapFactor();
|
||||
if (node1 && parasitics_->net(node1, network_) == net_)
|
||||
parasitics_->incrCap(node1, scaled_cap);
|
||||
if (node2 && parasitics_->net(node2, network_) == net_)
|
||||
parasitics_->incrCap(node2, scaled_cap);
|
||||
}
|
||||
}
|
||||
delete cap;
|
||||
stringDelete(node_name1);
|
||||
stringDelete(node_name2);
|
||||
}
|
||||
|
||||
void
|
||||
SpefReader::makeCouplingCap(int id,
|
||||
char *node_name1,
|
||||
char *node_name2,
|
||||
float cap)
|
||||
{
|
||||
const char *name = nullptr;
|
||||
const char *name_tmp = nullptr;
|
||||
if (keep_device_names_)
|
||||
// Prepend device type because OA uses one namespace for all devices.
|
||||
name = name_tmp = stringPrint("C%d", id);
|
||||
|
||||
ParasiticNode *node1, *node2;
|
||||
Net *ext_net1, *ext_net2;
|
||||
int ext_node_id1, ext_node_id2;
|
||||
Pin *ext_pin1, *ext_pin2;
|
||||
findParasiticNode(node_name1, node1, ext_net1, ext_node_id1, ext_pin1);
|
||||
findParasiticNode(node_name2, node2, ext_net2, ext_node_id2, ext_pin2);
|
||||
if (node1 && node2)
|
||||
parasitics_->makeCouplingCap(name, node1, node2, cap, ap_);
|
||||
if (node1 && node2 == nullptr) {
|
||||
if (ext_net2)
|
||||
parasitics_->makeCouplingCap(name, node1, ext_net2, ext_node_id2,
|
||||
cap, ap_);
|
||||
else if (ext_pin2)
|
||||
parasitics_->makeCouplingCap(name, node1, ext_pin2, cap, ap_);
|
||||
}
|
||||
else if (node1 == nullptr && node2) {
|
||||
if (ext_net1)
|
||||
parasitics_->makeCouplingCap(name, node2, ext_net1, ext_node_id1,
|
||||
cap, ap_);
|
||||
else if (ext_pin1)
|
||||
parasitics_->makeCouplingCap(name, node2, ext_pin1, cap, ap_);
|
||||
}
|
||||
stringDelete(name_tmp);
|
||||
}
|
||||
|
||||
void
|
||||
SpefReader::makeResistor(int id,
|
||||
char *node_name1,
|
||||
char *node_name2,
|
||||
SpefTriple *res)
|
||||
{
|
||||
ParasiticNode *node1 = findParasiticNode(node_name1);
|
||||
ParasiticNode *node2 = findParasiticNode(node_name2);
|
||||
ParasiticNode *node1 = findParasiticNode(node_name1, true);
|
||||
ParasiticNode *node2 = findParasiticNode(node_name2, true);
|
||||
if (node1 && node2) {
|
||||
float res1 = res->value(triple_index_) * res_scale_;
|
||||
const char *name = nullptr;
|
||||
const char *name_tmp = nullptr;
|
||||
if (keep_device_names_)
|
||||
// Prepend device type because OA uses one namespace for all devices.
|
||||
name = name_tmp = stringPrint("R%d", id);
|
||||
parasitics_->makeResistor(name, node1, node2, res1, ap_);
|
||||
stringDelete(name_tmp);
|
||||
parasitics_->makeResistor(parasitic_, id, res1, node1, node2);
|
||||
}
|
||||
delete res;
|
||||
stringDelete(node_name1);
|
||||
|
|
@ -727,6 +631,6 @@ int
|
|||
SpefParse_error(const char *msg)
|
||||
{
|
||||
spefFlushBuffer();
|
||||
sta::spef_reader->warn(1227, "%s.", msg);
|
||||
sta::spef_reader->warn(1657, "%s.", msg);
|
||||
return 0;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -22,13 +22,11 @@
|
|||
|
||||
namespace sta {
|
||||
|
||||
class Report;
|
||||
class Network;
|
||||
class Parasitics;
|
||||
class ParasiticAnalysisPt;
|
||||
class Instance;
|
||||
class Corner;
|
||||
class OperatingConditions;
|
||||
class StaState;
|
||||
|
||||
// Read a file single value parasitics into analysis point ap.
|
||||
// In a Spef file with triplet values the first value is used.
|
||||
|
|
@ -42,14 +40,9 @@ readSpefFile(const char *filename,
|
|||
bool pin_cap_included,
|
||||
bool keep_coupling_caps,
|
||||
float coupling_cap_factor,
|
||||
ReducedParasiticType reduce_to,
|
||||
bool delete_after_reduce,
|
||||
const OperatingConditions *op_cond,
|
||||
bool reduce,
|
||||
const Corner *corner,
|
||||
const MinMax *cnst_min_max,
|
||||
bool quiet,
|
||||
Report *report,
|
||||
Network *network,
|
||||
Parasitics *parasitics);
|
||||
const MinMaxAll *min_max,
|
||||
StaState *sta);
|
||||
|
||||
} // namespace
|
||||
|
|
|
|||
|
|
@ -16,11 +16,13 @@
|
|||
|
||||
#pragma once
|
||||
|
||||
#include <map>
|
||||
|
||||
#include "Zlib.hh"
|
||||
#include "Map.hh"
|
||||
#include "StringSeq.hh"
|
||||
#include "NetworkClass.hh"
|
||||
#include "ParasiticsClass.hh"
|
||||
#include "StaState.hh"
|
||||
|
||||
// Global namespace.
|
||||
#define YY_INPUT(buf,result,max_size) \
|
||||
|
|
@ -34,15 +36,14 @@ SpefParse_error(const char *msg);
|
|||
namespace sta {
|
||||
|
||||
class Report;
|
||||
class OperatingConditions;
|
||||
class MinMax;
|
||||
class MinMaxAll;
|
||||
class SpefRspfPi;
|
||||
class SpefTriple;
|
||||
class Corner;
|
||||
|
||||
typedef Map<int,char*,std::less<int> > SpefNameMap;
|
||||
typedef std::map<int, char*, std::less<int>> SpefNameMap;
|
||||
|
||||
class SpefReader
|
||||
class SpefReader : public StaState
|
||||
{
|
||||
public:
|
||||
SpefReader(const char *filename,
|
||||
|
|
@ -52,15 +53,10 @@ public:
|
|||
bool pin_cap_included,
|
||||
bool keep_coupling_caps,
|
||||
float coupling_cap_factor,
|
||||
ReducedParasiticType reduce_to,
|
||||
bool delete_after_reduce,
|
||||
const OperatingConditions *op_cond,
|
||||
bool reduce,
|
||||
const Corner *corner,
|
||||
const MinMax *cnst_min_max,
|
||||
bool quiet,
|
||||
Report *report,
|
||||
Network *network,
|
||||
Parasitics *parasitics);
|
||||
const MinMaxAll *min_max,
|
||||
StaState *sta);
|
||||
virtual ~SpefReader();
|
||||
char divider() const { return divider_; }
|
||||
void setDivider(char divider);
|
||||
|
|
@ -128,30 +124,18 @@ private:
|
|||
Pin *findPortPinRelative(const char *name);
|
||||
Net *findNetRelative(const char *name);
|
||||
Instance *findInstanceRelative(const char *name);
|
||||
void makeCouplingCap(int id,
|
||||
char *node_name1,
|
||||
char *node_name2,
|
||||
float cap);
|
||||
ParasiticNode *findParasiticNode(char *name);
|
||||
void findParasiticNode(char *name,
|
||||
ParasiticNode *&node,
|
||||
Net *&ext_net,
|
||||
int &ext_node_id,
|
||||
Pin *&ext_pin);
|
||||
ParasiticNode *findParasiticNode(char *name,
|
||||
bool local_only);
|
||||
|
||||
const char *filename_;
|
||||
Instance *instance_;
|
||||
const ParasiticAnalysisPt *ap_;
|
||||
bool pin_cap_included_;
|
||||
bool keep_coupling_caps_;
|
||||
ReducedParasiticType reduce_to_;
|
||||
bool delete_after_reduce_;
|
||||
const OperatingConditions *op_cond_;
|
||||
bool reduce_;
|
||||
const Corner *corner_;
|
||||
const MinMax *cnst_min_max_;
|
||||
const MinMaxAll *min_max_;
|
||||
// Normally no need to keep device names.
|
||||
bool keep_device_names_;
|
||||
bool quiet_;
|
||||
gzFile stream_;
|
||||
int line_;
|
||||
char divider_;
|
||||
|
|
@ -159,9 +143,6 @@ private:
|
|||
char bus_brkt_left_;
|
||||
char bus_brkt_right_;
|
||||
Net *net_;
|
||||
Report *report_;
|
||||
Network *network_;
|
||||
Parasitics *parasitics_;
|
||||
|
||||
int triple_index_;
|
||||
float time_scale_;
|
||||
|
|
|
|||
36
sdc/Sdc.cc
36
sdc/Sdc.cc
|
|
@ -465,7 +465,7 @@ Sdc::setOperatingConditions(OperatingConditions *op_cond,
|
|||
}
|
||||
|
||||
OperatingConditions *
|
||||
Sdc::operatingConditions(const MinMax *min_max)
|
||||
Sdc::operatingConditions(const MinMax *min_max) const
|
||||
{
|
||||
int mm_index = min_max->index();
|
||||
return operating_conditions_[mm_index];
|
||||
|
|
@ -2958,8 +2958,7 @@ Sdc::setPortExtWireCap(const Port *port,
|
|||
PortExtCap *port_cap = ensurePortExtPinCap(port, corner);
|
||||
if (subtract_pin_cap) {
|
||||
Pin *pin = network_->findPin(network_->name(port));
|
||||
const OperatingConditions *op_cond = operatingConditions(min_max);
|
||||
cap -= connectedPinCap(pin, rf, op_cond, corner, min_max);
|
||||
cap -= connectedPinCap(pin, rf, corner, min_max);
|
||||
if (cap < 0.0)
|
||||
cap = 0.0;
|
||||
}
|
||||
|
|
@ -3066,14 +3065,11 @@ Sdc::setNetWireCap(const Net *net,
|
|||
{
|
||||
float wire_cap = cap;
|
||||
if (subtract_pin_cap) {
|
||||
OperatingConditions *op_cond = operatingConditions(min_max);
|
||||
NetConnectedPinIterator *pin_iter = network_->connectedPinIterator(net);
|
||||
if (pin_iter->hasNext()) {
|
||||
const Pin *pin = pin_iter->next();
|
||||
float pin_cap_rise = connectedPinCap(pin, RiseFall::rise(),
|
||||
op_cond, corner, min_max);
|
||||
float pin_cap_fall = connectedPinCap(pin, RiseFall::fall(),
|
||||
op_cond, corner, min_max);
|
||||
float pin_cap_rise = connectedPinCap(pin, RiseFall::rise(), corner, min_max);
|
||||
float pin_cap_fall = connectedPinCap(pin, RiseFall::fall(), corner, min_max);
|
||||
float pin_cap = (pin_cap_rise + pin_cap_fall) / 2.0F;
|
||||
wire_cap -= pin_cap;
|
||||
if ((wire_cap + pin_cap) < 0.0)
|
||||
|
|
@ -3108,7 +3104,6 @@ Sdc::hasNetWireCap(const Net *net) const
|
|||
void
|
||||
Sdc::connectedCap(const Pin *pin,
|
||||
const RiseFall *rf,
|
||||
const OperatingConditions *op_cond,
|
||||
const Corner *corner,
|
||||
const MinMax *min_max,
|
||||
// Return values.
|
||||
|
|
@ -3117,8 +3112,7 @@ Sdc::connectedCap(const Pin *pin,
|
|||
float &fanout,
|
||||
bool &has_net_load) const
|
||||
{
|
||||
netCaps(pin, rf, op_cond, corner, min_max,
|
||||
pin_cap, wire_cap, fanout, has_net_load);
|
||||
netCaps(pin, rf, corner, min_max, pin_cap, wire_cap, fanout, has_net_load);
|
||||
float net_wire_cap;
|
||||
drvrPinWireCap(pin, corner, min_max, net_wire_cap, has_net_load);
|
||||
if (has_net_load)
|
||||
|
|
@ -3128,13 +3122,12 @@ Sdc::connectedCap(const Pin *pin,
|
|||
float
|
||||
Sdc::connectedPinCap(const Pin *pin,
|
||||
const RiseFall *rf,
|
||||
const OperatingConditions *op_cond,
|
||||
const Corner *corner,
|
||||
const MinMax *min_max)
|
||||
{
|
||||
float pin_cap, wire_cap, fanout;
|
||||
bool has_net_load;
|
||||
connectedCap(pin, rf, op_cond, corner, min_max,
|
||||
connectedCap(pin, rf, corner, min_max,
|
||||
pin_cap, wire_cap, fanout, has_net_load);
|
||||
return pin_cap;
|
||||
}
|
||||
|
|
@ -3143,7 +3136,6 @@ class FindNetCaps : public PinVisitor
|
|||
{
|
||||
public:
|
||||
FindNetCaps(const RiseFall *rf,
|
||||
const OperatingConditions *op_cond,
|
||||
const Corner *corner,
|
||||
const MinMax *min_max,
|
||||
float &pin_cap,
|
||||
|
|
@ -3155,7 +3147,6 @@ public:
|
|||
|
||||
protected:
|
||||
const RiseFall *rf_;
|
||||
const OperatingConditions *op_cond_;
|
||||
const Corner *corner_;
|
||||
const MinMax *min_max_;
|
||||
float &pin_cap_;
|
||||
|
|
@ -3166,7 +3157,6 @@ protected:
|
|||
};
|
||||
|
||||
FindNetCaps::FindNetCaps(const RiseFall *rf,
|
||||
const OperatingConditions *op_cond,
|
||||
const Corner *corner,
|
||||
const MinMax *min_max,
|
||||
float &pin_cap,
|
||||
|
|
@ -3176,7 +3166,6 @@ FindNetCaps::FindNetCaps(const RiseFall *rf,
|
|||
const Sdc *sdc) :
|
||||
PinVisitor(),
|
||||
rf_(rf),
|
||||
op_cond_(op_cond),
|
||||
corner_(corner),
|
||||
min_max_(min_max),
|
||||
pin_cap_(pin_cap),
|
||||
|
|
@ -3190,7 +3179,7 @@ FindNetCaps::FindNetCaps(const RiseFall *rf,
|
|||
void
|
||||
FindNetCaps::operator()(const Pin *pin)
|
||||
{
|
||||
sdc_->pinCaps(pin, rf_, op_cond_, corner_, min_max_,
|
||||
sdc_->pinCaps(pin, rf_, corner_, min_max_,
|
||||
pin_cap_, wire_cap_, fanout_);
|
||||
}
|
||||
|
||||
|
|
@ -3198,7 +3187,6 @@ FindNetCaps::operator()(const Pin *pin)
|
|||
void
|
||||
Sdc::netCaps(const Pin *drvr_pin,
|
||||
const RiseFall *rf,
|
||||
const OperatingConditions *op_cond,
|
||||
const Corner *corner,
|
||||
const MinMax *min_max,
|
||||
// Return values.
|
||||
|
|
@ -3211,7 +3199,7 @@ Sdc::netCaps(const Pin *drvr_pin,
|
|||
wire_cap = 0.0;
|
||||
fanout = 0.0;
|
||||
has_net_load = false;
|
||||
FindNetCaps visitor(rf, op_cond, corner, min_max, pin_cap,
|
||||
FindNetCaps visitor(rf, corner, min_max, pin_cap,
|
||||
wire_cap, fanout, has_net_load, this);
|
||||
network_->visitConnectedPins(drvr_pin, visitor);
|
||||
}
|
||||
|
|
@ -3219,7 +3207,6 @@ Sdc::netCaps(const Pin *drvr_pin,
|
|||
void
|
||||
Sdc::pinCaps(const Pin *pin,
|
||||
const RiseFall *rf,
|
||||
const OperatingConditions *op_cond,
|
||||
const Corner *corner,
|
||||
const MinMax *min_max,
|
||||
// Return values.
|
||||
|
|
@ -3252,7 +3239,7 @@ Sdc::pinCaps(const Pin *pin,
|
|||
LibertyPort *port = network_->libertyPort(pin);
|
||||
if (port) {
|
||||
Instance *inst = network_->instance(pin);
|
||||
pin_cap += portCapacitance(inst, port, rf, op_cond, corner, min_max);
|
||||
pin_cap += portCapacitance(inst, port, rf, corner, min_max);
|
||||
if (port->direction()->isAnyInput())
|
||||
fanout++;
|
||||
}
|
||||
|
|
@ -3263,7 +3250,6 @@ float
|
|||
Sdc::portCapacitance(Instance *inst,
|
||||
LibertyPort *port,
|
||||
const RiseFall *rf,
|
||||
const OperatingConditions *op_cond,
|
||||
const Corner *corner,
|
||||
const MinMax *min_max) const
|
||||
{
|
||||
|
|
@ -3271,20 +3257,20 @@ Sdc::portCapacitance(Instance *inst,
|
|||
if (inst)
|
||||
inst_pvt = pvt(inst, min_max);
|
||||
LibertyPort *corner_port = port->cornerPort(corner, min_max);
|
||||
OperatingConditions *op_cond = operatingConditions(min_max);
|
||||
return corner_port->capacitance(rf, min_max, op_cond, inst_pvt);
|
||||
}
|
||||
|
||||
float
|
||||
Sdc::pinCapacitance(const Pin *pin,
|
||||
const RiseFall *rf,
|
||||
const OperatingConditions *op_cond,
|
||||
const Corner *corner,
|
||||
const MinMax *min_max)
|
||||
{
|
||||
LibertyPort *port = network_->libertyPort(pin);
|
||||
if (port) {
|
||||
Instance *inst = network_->instance(pin);
|
||||
return portCapacitance(inst, port, rf, op_cond, corner, min_max);
|
||||
return portCapacitance(inst, port, rf, corner, min_max);
|
||||
}
|
||||
else
|
||||
return 0.0;
|
||||
|
|
|
|||
|
|
@ -114,8 +114,9 @@ Corners::copy(Corners *corners)
|
|||
makeAnalysisPts();
|
||||
|
||||
for (ParasiticAnalysisPt *orig_ap : corners->parasitic_analysis_pts_) {
|
||||
ParasiticAnalysisPt *ap = new ParasiticAnalysisPt(orig_ap->name(), orig_ap->index(),
|
||||
orig_ap->minMax());
|
||||
ParasiticAnalysisPt *ap = new ParasiticAnalysisPt(orig_ap->name(),
|
||||
orig_ap->index(),
|
||||
orig_ap->indexMax());
|
||||
parasitic_analysis_pts_.push_back(ap);
|
||||
}
|
||||
|
||||
|
|
@ -127,64 +128,46 @@ Corners::copy(Corners *corners)
|
|||
}
|
||||
|
||||
void
|
||||
Corners::makeParasiticAnalysisPts(bool per_corner,
|
||||
bool per_min_max)
|
||||
Corners::makeParasiticAnalysisPts(bool per_corner)
|
||||
{
|
||||
parasitic_analysis_pts_.deleteContentsClear();
|
||||
if (per_corner && per_min_max) {
|
||||
// each corner has min/max parasitics
|
||||
if (per_corner) {
|
||||
// per corner, per min/max
|
||||
parasitic_analysis_pts_.resize(corners_.size() * MinMax::index_count);
|
||||
for (Corner *corner : corners_) {
|
||||
corner->setParasiticAnalysisPtcount(MinMax::index_count);
|
||||
for (MinMax *min_max : MinMax::range()) {
|
||||
int mm_index = min_max->index();
|
||||
int ap_index = corner->index() * MinMax::index_count + mm_index;
|
||||
int ap_index_max = corner->index() * MinMax::index_count
|
||||
+ MinMax::max()->index();
|
||||
string ap_name = corner->name();
|
||||
ap_name += "_";
|
||||
ap_name += min_max->asString();
|
||||
ParasiticAnalysisPt *ap = new ParasiticAnalysisPt(ap_name.c_str(),
|
||||
ap_index,
|
||||
min_max);
|
||||
parasitic_analysis_pts_.push_back(ap);
|
||||
ap_index, ap_index_max);
|
||||
parasitic_analysis_pts_[ap_index] = ap;
|
||||
corner->setParasiticAP(ap, mm_index);
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (per_corner && !per_min_max) {
|
||||
// each corner has parasitics
|
||||
for (Corner *corner : corners_) {
|
||||
ParasiticAnalysisPt *ap = new ParasiticAnalysisPt(corner->name(),
|
||||
corner->index(),
|
||||
MinMax::max());
|
||||
parasitic_analysis_pts_.push_back(ap);
|
||||
corner->setParasiticAnalysisPtcount(1);
|
||||
corner->setParasiticAP(ap, 0);
|
||||
}
|
||||
}
|
||||
else if (!per_corner && per_min_max) {
|
||||
// min/max parasitics shared by all corners
|
||||
else {
|
||||
// shared corner, per min/max
|
||||
parasitic_analysis_pts_.resize(MinMax::index_count);
|
||||
int ap_index_max = MinMax::max()->index();
|
||||
for (MinMax *min_max : MinMax::range()) {
|
||||
int mm_index = min_max->index();
|
||||
int ap_index = mm_index;
|
||||
ParasiticAnalysisPt *ap = new ParasiticAnalysisPt(min_max->asString(),
|
||||
mm_index,
|
||||
min_max);
|
||||
parasitic_analysis_pts_[mm_index] = ap;
|
||||
ap_index,
|
||||
ap_index_max);
|
||||
parasitic_analysis_pts_[ap_index] = ap;
|
||||
for (Corner *corner : corners_) {
|
||||
corner->setParasiticAnalysisPtcount(MinMax::index_count);
|
||||
corner->setParasiticAP(ap, mm_index);
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (!per_corner && !per_min_max) {
|
||||
// single parasitics shared by all corners
|
||||
ParasiticAnalysisPt *ap = new ParasiticAnalysisPt("min_max", 0,
|
||||
MinMax::max());
|
||||
parasitic_analysis_pts_.push_back(ap);
|
||||
for (Corner *corner : corners_) {
|
||||
corner->setParasiticAnalysisPtcount(1);
|
||||
corner->setParasiticAP(ap, 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
|
|
@ -404,9 +387,9 @@ Corner::setParasiticAnalysisPtcount(int ap_count)
|
|||
|
||||
void
|
||||
Corner::setParasiticAP(ParasiticAnalysisPt *ap,
|
||||
int index)
|
||||
int mm_index)
|
||||
{
|
||||
parasitic_analysis_pts_[index] = ap;
|
||||
parasitic_analysis_pts_[mm_index] = ap;
|
||||
}
|
||||
|
||||
void
|
||||
|
|
|
|||
|
|
@ -2261,7 +2261,7 @@ ReportPath::reportPathLine(const Path *path,
|
|||
float cap = field_blank_;
|
||||
// Don't show capacitance field for input pins.
|
||||
if (is_driver && field_capacitance_->enabled())
|
||||
cap = loadCap(pin, rf, dcalc_ap);
|
||||
cap = graph_delay_calc_->loadCap(pin, rf, dcalc_ap);
|
||||
reportLine(what.c_str(), cap, slew, field_blank_,
|
||||
incr, time, false, early_late, rf, line_case);
|
||||
}
|
||||
|
|
@ -2653,7 +2653,7 @@ ReportPath::reportPath5(const Path *path,
|
|||
float fanout = field_blank_;
|
||||
// Don't show capacitance field for input pins.
|
||||
if (is_driver && field_capacitance_->enabled())
|
||||
cap = loadCap(pin, rf, dcalc_ap);
|
||||
cap = graph_delay_calc_->loadCap(pin, rf, dcalc_ap);
|
||||
// Don't show fanout field for input pins.
|
||||
if (is_driver && field_fanout_->enabled())
|
||||
fanout = drvrFanout(vertex, dcalc_ap->corner(), min_max);
|
||||
|
|
@ -2837,18 +2837,6 @@ ReportPath::pathInputDelayRefPath(const Path *path,
|
|||
}
|
||||
}
|
||||
|
||||
float
|
||||
ReportPath::loadCap(Pin *drvr_pin,
|
||||
const RiseFall *rf,
|
||||
DcalcAnalysisPt *dcalc_ap)
|
||||
{
|
||||
Parasitic *parasitic = nullptr;
|
||||
parasitic = arc_delay_calc_->findParasitic(drvr_pin, rf, dcalc_ap);
|
||||
float load_cap = graph_delay_calc_->loadCap(drvr_pin, parasitic, rf, dcalc_ap);
|
||||
arc_delay_calc_->finishDrvrPin();
|
||||
return load_cap;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////
|
||||
|
||||
void
|
||||
|
|
|
|||
|
|
@ -384,9 +384,6 @@ protected:
|
|||
bool hasExtInputDriver(const Pin *pin,
|
||||
const RiseFall *rf,
|
||||
const MinMax *min_max);
|
||||
float loadCap(Pin *drvr_pin,
|
||||
const RiseFall *rf,
|
||||
DcalcAnalysisPt *dcalc_ap);
|
||||
float drvrFanout(Vertex *drvr,
|
||||
const Corner *corner,
|
||||
const MinMax *min_max);
|
||||
|
|
|
|||
|
|
@ -271,9 +271,8 @@ Sta::Sta() :
|
|||
update_genclks_(false),
|
||||
equiv_cells_(nullptr),
|
||||
graph_sdc_annotated_(false),
|
||||
// Default to same parasitics for each corner min/max.
|
||||
parasitics_per_corner_(false),
|
||||
parasitics_per_min_max_(false)
|
||||
// Default to same parasitics for all corners.
|
||||
parasitics_per_corner_(false)
|
||||
{
|
||||
}
|
||||
|
||||
|
|
@ -3796,10 +3795,7 @@ Sta::connectedCap(const Pin *drvr_pin,
|
|||
float &wire_cap) const
|
||||
{
|
||||
const DcalcAnalysisPt *dcalc_ap = corner->findDcalcAnalysisPt(min_max);
|
||||
Parasitic *parasitic = arc_delay_calc_->findParasitic(drvr_pin, rf, dcalc_ap);
|
||||
graph_delay_calc_->loadCap(drvr_pin, parasitic, rf, dcalc_ap,
|
||||
pin_cap, wire_cap);
|
||||
arc_delay_calc_->finishDrvrPin();
|
||||
graph_delay_calc_->loadCap(drvr_pin, rf, dcalc_ap, pin_cap, wire_cap);
|
||||
}
|
||||
|
||||
void
|
||||
|
|
@ -3892,40 +3888,29 @@ Sta::readSpef(const char *filename,
|
|||
bool pin_cap_included,
|
||||
bool keep_coupling_caps,
|
||||
float coupling_cap_factor,
|
||||
ReducedParasiticType reduce_to,
|
||||
bool delete_after_reduce,
|
||||
bool quiet)
|
||||
bool reduce)
|
||||
{
|
||||
setParasiticAnalysisPts(corner != nullptr,
|
||||
min_max != MinMaxAll::all());
|
||||
if (corner == nullptr)
|
||||
corner = cmd_corner_;
|
||||
const MinMax *cnst_min_max = (min_max == MinMaxAll::all())
|
||||
setParasiticAnalysisPts(corner != nullptr);
|
||||
const MinMax *ap_min_max = (min_max == MinMaxAll::all())
|
||||
? MinMax::max()
|
||||
: min_max->asMinMax();
|
||||
ParasiticAnalysisPt *ap = corner->findParasiticAnalysisPt(cnst_min_max);
|
||||
const OperatingConditions *op_cond =
|
||||
sdc_->operatingConditions(cnst_min_max);
|
||||
const Corner *ap_corner = corner ? corner : corners_->corners()[0];
|
||||
ParasiticAnalysisPt *ap = ap_corner->findParasiticAnalysisPt(ap_min_max);
|
||||
bool success = readSpefFile(filename, instance, ap,
|
||||
pin_cap_included, keep_coupling_caps,
|
||||
coupling_cap_factor,
|
||||
reduce_to, delete_after_reduce,
|
||||
op_cond, corner, cnst_min_max, quiet,
|
||||
report_, network_, parasitics_);
|
||||
coupling_cap_factor, reduce,
|
||||
corner, min_max, this);
|
||||
graph_delay_calc_->delaysInvalid();
|
||||
search_->arrivalsInvalid();
|
||||
return success;
|
||||
}
|
||||
|
||||
void
|
||||
Sta::setParasiticAnalysisPts(bool per_corner,
|
||||
bool per_min_max)
|
||||
Sta::setParasiticAnalysisPts(bool per_corner)
|
||||
{
|
||||
if (per_corner != parasitics_per_corner_
|
||||
|| per_min_max != parasitics_per_min_max_) {
|
||||
if (per_corner != parasitics_per_corner_) {
|
||||
deleteParasitics();
|
||||
parasitics_per_corner_ = per_corner;
|
||||
parasitics_per_min_max_ = per_min_max;
|
||||
makeParasiticAnalysisPts();
|
||||
}
|
||||
}
|
||||
|
|
@ -3933,8 +3918,7 @@ Sta::setParasiticAnalysisPts(bool per_corner,
|
|||
void
|
||||
Sta::makeParasiticAnalysisPts()
|
||||
{
|
||||
corners_->makeParasiticAnalysisPts(parasitics_per_corner_,
|
||||
parasitics_per_min_max_);
|
||||
corners_->makeParasiticAnalysisPts(parasitics_per_corner_);
|
||||
}
|
||||
|
||||
void
|
||||
|
|
@ -4434,7 +4418,7 @@ Sta::connectLoadPinAfter(Vertex *vertex)
|
|||
void
|
||||
Sta::disconnectPinBefore(const Pin *pin)
|
||||
{
|
||||
parasitics_->disconnectPinBefore(pin);
|
||||
parasitics_->disconnectPinBefore(pin, network_);
|
||||
sdc_->disconnectPinBefore(pin);
|
||||
sim_->disconnectPinBefore(pin);
|
||||
if (graph_) {
|
||||
|
|
|
|||
|
|
@ -100,8 +100,7 @@ private:
|
|||
DcalcAPIndex dcalc_ap_index);
|
||||
void writeStageParasitics(Stage stage);
|
||||
void writeStageParasiticNetwork(Pin *drvr_pin,
|
||||
Parasitic *parasitic,
|
||||
ParasiticAnalysisPt *parasitic_ap);
|
||||
Parasitic *parasitic);
|
||||
void writeStagePiElmore(Pin *drvr_pin,
|
||||
Parasitic *parasitic);
|
||||
void writeNullParasitics(Pin *drvr_pin);
|
||||
|
|
@ -1298,54 +1297,6 @@ WritePathSpice::onePort(FuncExpr *expr)
|
|||
}
|
||||
}
|
||||
|
||||
// Sort predicate for ParasiticDevices.
|
||||
class ParasiticDeviceLess
|
||||
{
|
||||
public:
|
||||
ParasiticDeviceLess(Parasitics *parasitics) :
|
||||
parasitics_(parasitics)
|
||||
{
|
||||
}
|
||||
bool operator()(const ParasiticDevice *device1,
|
||||
const ParasiticDevice *device2) const
|
||||
{
|
||||
ParasiticNode *node1 = parasitics_->node1(device1);
|
||||
ParasiticNode *node2 = parasitics_->node1(device2);
|
||||
const char *name1 = parasitics_->name(node1);
|
||||
const char *name2 = parasitics_->name(node2);
|
||||
if (stringEq(name1, name2)) {
|
||||
ParasiticNode *node12 = parasitics_->node2(device1);
|
||||
ParasiticNode *node22 = parasitics_->node2(device2);
|
||||
const char *name12 = parasitics_->name(node12);
|
||||
const char *name22 = parasitics_->name(node22);
|
||||
return stringLess(name12, name22);
|
||||
}
|
||||
else
|
||||
return stringLess(name1, name2);
|
||||
}
|
||||
private:
|
||||
Parasitics *parasitics_;
|
||||
};
|
||||
|
||||
// Sort predicate for ParasiticDevices.
|
||||
class ParasiticNodeLess
|
||||
{
|
||||
public:
|
||||
ParasiticNodeLess(Parasitics *parasitics) :
|
||||
parasitics_(parasitics)
|
||||
{
|
||||
}
|
||||
bool operator()(const ParasiticNode *node1,
|
||||
const ParasiticNode *node2) const
|
||||
{
|
||||
const char *name1 = parasitics_->name(node1);
|
||||
const char *name2 = parasitics_->name(node2);
|
||||
return stringLess(name1, name2);
|
||||
}
|
||||
private:
|
||||
Parasitics *parasitics_;
|
||||
};
|
||||
|
||||
void
|
||||
WritePathSpice::writeStageParasitics(Stage stage)
|
||||
{
|
||||
|
|
@ -1361,7 +1312,7 @@ WritePathSpice::writeStageParasitics(Stage stage)
|
|||
ParasiticAnalysisPt *parasitic_ap = dcalc_ap->parasiticAnalysisPt();
|
||||
Parasitic *parasitic = parasitics_->findParasiticNetwork(drvr_pin, parasitic_ap);
|
||||
if (parasitic)
|
||||
writeStageParasiticNetwork(drvr_pin, parasitic, parasitic_ap);
|
||||
writeStageParasiticNetwork(drvr_pin, parasitic);
|
||||
else {
|
||||
const RiseFall *drvr_rf = drvr_path->transition(this);
|
||||
parasitic = parasitics_->findPiElmore(drvr_pin, drvr_rf, parasitic_ap);
|
||||
|
|
@ -1376,51 +1327,51 @@ WritePathSpice::writeStageParasitics(Stage stage)
|
|||
|
||||
void
|
||||
WritePathSpice::writeStageParasiticNetwork(Pin *drvr_pin,
|
||||
Parasitic *parasitic,
|
||||
ParasiticAnalysisPt *parasitic_ap)
|
||||
Parasitic *parasitic)
|
||||
{
|
||||
Set<const Pin*> reachable_pins;
|
||||
int res_index = 1;
|
||||
int cap_index = 1;
|
||||
|
||||
// Sort devices for consistent regression results.
|
||||
Vector<ParasiticDevice*> devices;
|
||||
ParasiticDeviceIterator *device_iter1 = parasitics_->deviceIterator(parasitic);
|
||||
while (device_iter1->hasNext()) {
|
||||
ParasiticDevice *device = device_iter1->next();
|
||||
devices.push_back(device);
|
||||
// Sort resistors for consistent regression results.
|
||||
ParasiticResistorSeq resistors = parasitics_->resistors(parasitic);
|
||||
sort(resistors.begin(), resistors.end(),
|
||||
[=] (const ParasiticResistor *r1,
|
||||
const ParasiticResistor *r2) {
|
||||
return parasitics_->id(r1) < parasitics_->id(r2);
|
||||
});
|
||||
for (ParasiticResistor *resistor : resistors) {
|
||||
float resistance = parasitics_->value(resistor);
|
||||
ParasiticNode *node1 = parasitics_->node1(resistor);
|
||||
ParasiticNode *node2 = parasitics_->node2(resistor);
|
||||
streamPrint(spice_stream_, "R%d %s %s %.3e\n",
|
||||
res_index,
|
||||
nodeName(node1),
|
||||
nodeName(node2),
|
||||
resistance);
|
||||
res_index++;
|
||||
|
||||
const Pin *pin1 = parasitics_->pin(node1);
|
||||
reachable_pins.insert(pin1);
|
||||
const Pin *pin2 = parasitics_->pin(node2);
|
||||
reachable_pins.insert(pin2);
|
||||
}
|
||||
delete device_iter1;
|
||||
|
||||
sort(devices, ParasiticDeviceLess(parasitics_));
|
||||
|
||||
for (ParasiticDevice *device : devices) {
|
||||
float resistance = parasitics_->value(device, parasitic_ap);
|
||||
if (parasitics_->isResistor(device)) {
|
||||
ParasiticNode *node1 = parasitics_->node1(device);
|
||||
ParasiticNode *node2 = parasitics_->node2(device);
|
||||
streamPrint(spice_stream_, "R%d %s %s %.3e\n",
|
||||
res_index,
|
||||
nodeName(node1),
|
||||
nodeName(node2),
|
||||
resistance);
|
||||
res_index++;
|
||||
|
||||
const Pin *pin1 = parasitics_->connectionPin(node1);
|
||||
reachable_pins.insert(pin1);
|
||||
const Pin *pin2 = parasitics_->connectionPin(node2);
|
||||
reachable_pins.insert(pin2);
|
||||
}
|
||||
else if (parasitics_->isCouplingCap(device)) {
|
||||
// Ground coupling caps for now.
|
||||
ParasiticNode *node1 = parasitics_->node1(device);
|
||||
float cap = parasitics_->value(device, parasitic_ap);
|
||||
streamPrint(spice_stream_, "C%d %s 0 %.3e\n",
|
||||
cap_index,
|
||||
nodeName(node1),
|
||||
cap);
|
||||
cap_index++;
|
||||
}
|
||||
ParasiticCapacitorSeq capacitors = parasitics_->capacitors(parasitic);
|
||||
sort(capacitors.begin(), capacitors.end(),
|
||||
[=] (const ParasiticCapacitor *c1,
|
||||
const ParasiticCapacitor *c2) {
|
||||
return parasitics_->id(c1) < parasitics_->id(c2);
|
||||
});
|
||||
for (ParasiticCapacitor *capacitor : capacitors) {
|
||||
// Ground coupling caps for now.
|
||||
ParasiticNode *node1 = parasitics_->node1(capacitor);
|
||||
float cap = parasitics_->value(capacitor);
|
||||
streamPrint(spice_stream_, "C%d %s 0 %.3e\n",
|
||||
cap_index,
|
||||
nodeName(node1),
|
||||
cap);
|
||||
cap_index++;
|
||||
}
|
||||
|
||||
// Add resistors from drvr to load for missing parasitic connections.
|
||||
|
|
@ -1442,17 +1393,17 @@ WritePathSpice::writeStageParasiticNetwork(Pin *drvr_pin,
|
|||
delete pin_iter;
|
||||
|
||||
// Sort node capacitors for consistent regression results.
|
||||
Vector<ParasiticNode*> nodes;
|
||||
ParasiticNodeIterator *node_iter = parasitics_->nodeIterator(parasitic);
|
||||
while (node_iter->hasNext()) {
|
||||
ParasiticNode *node = node_iter->next();
|
||||
nodes.push_back(node);
|
||||
}
|
||||
|
||||
sort(nodes, ParasiticNodeLess(parasitics_));
|
||||
ParasiticNodeSeq nodes = parasitics_->nodes(parasitic);
|
||||
sort(nodes.begin(), nodes.end(),
|
||||
[=] (const ParasiticNode *node1,
|
||||
const ParasiticNode *node2) {
|
||||
const char *name1 = parasitics_->name(node1);
|
||||
const char *name2 = parasitics_->name(node2);
|
||||
return stringLess(name1, name2);
|
||||
});
|
||||
|
||||
for (ParasiticNode *node : nodes) {
|
||||
float cap = parasitics_->nodeGndCap(node, parasitic_ap);
|
||||
float cap = parasitics_->nodeGndCap(node);
|
||||
// Spice has a cow over zero value caps.
|
||||
if (cap > 0.0) {
|
||||
streamPrint(spice_stream_, "C%d %s 0 %.3e\n",
|
||||
|
|
@ -1462,7 +1413,6 @@ WritePathSpice::writeStageParasiticNetwork(Pin *drvr_pin,
|
|||
cap_index++;
|
||||
}
|
||||
}
|
||||
delete node_iter;
|
||||
}
|
||||
|
||||
void
|
||||
|
|
@ -1556,7 +1506,7 @@ WritePathSpice::initNodeMap(const char *net_name)
|
|||
const char *
|
||||
WritePathSpice::nodeName(ParasiticNode *node)
|
||||
{
|
||||
const Pin *pin = parasitics_->connectionPin(node);
|
||||
const Pin *pin = parasitics_->pin(node);
|
||||
if (pin)
|
||||
return parasitics_->name(node);
|
||||
else {
|
||||
|
|
|
|||
|
|
@ -392,6 +392,7 @@ proc get_ports_or_pins { pattern } {
|
|||
|
||||
################################################################
|
||||
|
||||
# -corner keyword is optional.
|
||||
# If -corner keyword is missing:
|
||||
# one corner: return default
|
||||
# multiple corners: error
|
||||
|
|
@ -414,7 +415,6 @@ proc parse_corner { keys_var } {
|
|||
}
|
||||
|
||||
# -corner keyword is required.
|
||||
# Assumes caller checks for existence of -corner keyword arg.
|
||||
proc parse_corner_required { keys_var } {
|
||||
upvar 1 $keys_var keys
|
||||
|
||||
|
|
|
|||
|
|
@ -3064,6 +3064,12 @@ endpoints()
|
|||
return Sta::sta()->endpointPins();
|
||||
}
|
||||
|
||||
size_t
|
||||
endpoint_count()
|
||||
{
|
||||
return Sta::sta()->endpointPins().size();
|
||||
}
|
||||
|
||||
PinSet
|
||||
group_path_pins(const char *group_path_name)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -1168,21 +1168,6 @@ using namespace sta;
|
|||
Tcl_SetObjResult(interp, obj);
|
||||
}
|
||||
|
||||
%typemap(in) ReducedParasiticType {
|
||||
int length;
|
||||
char *arg = Tcl_GetStringFromObj($input, &length);
|
||||
if (stringEq(arg, "pi_elmore"))
|
||||
$1 = ReducedParasiticType::pi_elmore;
|
||||
else if (stringEq(arg, "pi_pole_residue2"))
|
||||
$1 = ReducedParasiticType::pi_pole_residue2;
|
||||
else if (stringEq(arg, "none"))
|
||||
$1 = ReducedParasiticType::none;
|
||||
else {
|
||||
tclArgError(interp, "%s pi_elmore, pi_pole_residue2, or none.", arg);
|
||||
return TCL_ERROR;
|
||||
}
|
||||
}
|
||||
|
||||
%typemap(out) Arrival {
|
||||
Tcl_SetObjResult(interp,Tcl_NewDoubleObj(delayAsFloat($1)));
|
||||
}
|
||||
|
|
|
|||
|
|
@ -157,7 +157,9 @@ RiseFallMinMax::setValues(RiseFallMinMax *values)
|
|||
void
|
||||
RiseFallMinMax::value(const RiseFall *rf,
|
||||
const MinMax *min_max,
|
||||
float &value, bool &exists) const
|
||||
// Return values.
|
||||
float &value,
|
||||
bool &exists) const
|
||||
{
|
||||
exists = exists_[rf->index()][min_max->index()];
|
||||
if (exists)
|
||||
|
|
|
|||
Loading…
Reference in New Issue