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:
James Cherry 2024-02-08 13:54:52 -07:00
parent cc9eb1f12a
commit 902a1bff86
49 changed files with 1886 additions and 3199 deletions

View File

@ -115,7 +115,6 @@ set(STA_SOURCE
parasitics/ConcreteParasitics.cc parasitics/ConcreteParasitics.cc
parasitics/EstimateParasitics.cc parasitics/EstimateParasitics.cc
parasitics/NullParasitics.cc
parasitics/Parasitics.cc parasitics/Parasitics.cc
parasitics/ReduceParasitics.cc parasitics/ReduceParasitics.cc
parasitics/ReportParasiticAnnotation.cc parasitics/ReportParasiticAnnotation.cc

View File

@ -64,6 +64,8 @@ public:
rcmodel(); rcmodel();
virtual ~rcmodel(); virtual ~rcmodel();
virtual float capacitance() const; virtual float capacitance() const;
virtual PinSet unannotatedLoads(const Pin *drvr_pin,
const Parasitics *parasitics) const;
const Pin **pinV; // [n] const Pin **pinV; // [n]
}; };

View File

@ -30,6 +30,7 @@
#include "TimingModel.hh" #include "TimingModel.hh"
#include "TimingArc.hh" #include "TimingArc.hh"
#include "TableModel.hh" #include "TableModel.hh"
#include "PortDirection.hh"
#include "Network.hh" #include "Network.hh"
#include "Graph.hh" #include "Graph.hh"
#include "Parasitics.hh" #include "Parasitics.hh"
@ -117,7 +118,10 @@ public:
Parasitic *findParasitic(const Pin *drvr_pin, Parasitic *findParasitic(const Pin *drvr_pin,
const RiseFall *rf, const RiseFall *rf,
const DcalcAnalysisPt *dcalc_ap) override; 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, ArcDcalcResult inputPortDelay(const Pin *port_pin,
float in_slew, float in_slew,
const RiseFall *rf, const RiseFall *rf,
@ -140,6 +144,7 @@ public:
const LoadPinIndexMap &load_pin_index_map, const LoadPinIndexMap &load_pin_index_map,
const DcalcAnalysisPt *dcalc_ap, const DcalcAnalysisPt *dcalc_ap,
int digits) override; int digits) override;
void finishDrvrPin() override;
void delay_work_set_thresholds(delay_work *D, void delay_work_set_thresholds(delay_work *D,
double lo, double lo,
double hi, double hi,
@ -219,6 +224,7 @@ private:
int pin_n_; int pin_n_;
ArnoldiReduce *reduce_; ArnoldiReduce *reduce_;
delay_work *delay_work_; delay_work *delay_work_;
vector<rcmodel*> unsaved_parasitics_;
}; };
ArcDelayCalc * ArcDelayCalc *
@ -259,49 +265,53 @@ ArnoldiDelayCalc::findParasitic(const Pin *drvr_pin,
Parasitic *parasitic = nullptr; Parasitic *parasitic = nullptr;
const Corner *corner = dcalc_ap->corner(); const Corner *corner = dcalc_ap->corner();
// set_load net has precedence over parasitics. // set_load net has precedence over parasitics.
if (!sdc_->drvrPinHasWireCap(drvr_pin, corner)) { if (sdc_->drvrPinHasWireCap(drvr_pin, corner)
const ParasiticAnalysisPt *parasitic_ap = dcalc_ap->parasiticAnalysisPt(); || network_->direction(drvr_pin)->isInternal())
Parasitic *parasitic_network = return nullptr;
parasitics_->findParasiticNetwork(drvr_pin, parasitic_ap); const ParasiticAnalysisPt *parasitic_ap = dcalc_ap->parasiticAnalysisPt();
bool delete_parasitic_network = false; Parasitic *parasitic_network =
parasitics_->findParasiticNetwork(drvr_pin, parasitic_ap);
const MinMax *cnst_min_max = dcalc_ap->constraintMinMax(); const MinMax *min_max = dcalc_ap->constraintMinMax();
const OperatingConditions *op_cond = dcalc_ap->operatingConditions(); if (parasitic_network == nullptr) {
if (parasitic_network == nullptr) { Wireload *wireload = sdc_->wireload(min_max);
Wireload *wireload = sdc_->wireload(cnst_min_max); if (wireload) {
if (wireload) { float pin_cap, wire_cap, fanout;
float pin_cap, wire_cap, fanout; bool has_wire_cap;
bool has_wire_cap; graph_delay_calc_->netCaps(drvr_pin, drvr_rf, dcalc_ap,
graph_delay_calc_->netCaps(drvr_pin, drvr_rf, dcalc_ap, pin_cap, wire_cap, fanout, has_wire_cap);
pin_cap, wire_cap, fanout, has_wire_cap); parasitic_network = parasitics_->makeWireloadNetwork(drvr_pin, wireload,
parasitic_network = parasitics_->makeWireloadNetwork(drvr_pin, wireload, fanout, min_max,
fanout, op_cond, parasitic_ap);
parasitic_ap);
delete_parasitic_network = true;
}
} }
}
if (parasitic_network) { if (parasitic_network) {
parasitic = reduce_->reduceToArnoldi(parasitic_network, rcmodel *rcmodel = reduce_->reduceToArnoldi(parasitic_network, drvr_pin,
drvr_pin, parasitic_ap->couplingCapFactor(),
parasitic_ap->couplingCapFactor(), drvr_rf, corner, min_max, parasitic_ap);
drvr_rf, op_cond, corner, // Arnoldi parasitics are their own class that are not saved in the parasitic db.
cnst_min_max, parasitic_ap); unsaved_parasitics_.push_back(rcmodel);
if (delete_parasitic_network) { parasitic = rcmodel;
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);
}
} }
return parasitic; return parasitic;
} }
ReducedParasiticType Parasitic *
ArnoldiDelayCalc::reducedParasiticType() const 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 ArcDcalcResult
@ -1304,7 +1314,6 @@ ArnoldiDelayCalc::ra_get_r(delay_work *D,
r = tlohi/(c_log*c1); r = tlohi/(c_log*c1);
if (rdelay>0.0 && r > rdelay) if (rdelay>0.0 && r > rdelay)
r = rdelay; r = rdelay;
// else printf("from rdelay %g to r %g\n",rdelay,r);
return r; return r;
} }

View File

@ -46,6 +46,14 @@ rcmodel::capacitance() const
return ctot; 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 struct ts_point
{ {
ParasiticNode *node_; ParasiticNode *node_;
@ -62,7 +70,7 @@ struct ts_point
struct ts_edge struct ts_edge
{ {
ConcreteParasiticResistor *resistor_; ParasiticResistor *resistor_;
ts_point *from; ts_point *from;
ts_point *to; ts_point *to;
}; };
@ -131,23 +139,21 @@ ArnoldiReduce::~ArnoldiReduce()
free(ts_pointV); free(ts_pointV);
} }
Parasitic * rcmodel *
ArnoldiReduce::reduceToArnoldi(Parasitic *parasitic, ArnoldiReduce::reduceToArnoldi(Parasitic *parasitic,
const Pin *drvr_pin, const Pin *drvr_pin,
float coupling_cap_factor, float coupling_cap_factor,
const RiseFall *rf, const RiseFall *rf,
const OperatingConditions *op_cond,
const Corner *corner, const Corner *corner,
const MinMax *cnst_min_max, const MinMax *min_max,
const ParasiticAnalysisPt *ap) const ParasiticAnalysisPt *ap)
{ {
parasitic_network_ = reinterpret_cast<ConcreteParasiticNetwork*>(parasitic); parasitic_network_ = reinterpret_cast<ConcreteParasiticNetwork*>(parasitic);
drvr_pin_ = drvr_pin; drvr_pin_ = drvr_pin;
coupling_cap_factor_ = coupling_cap_factor; coupling_cap_factor_ = coupling_cap_factor;
rf_ = rf; rf_ = rf;
op_cond_ = op_cond;
corner_ = corner; corner_ = corner;
cnst_min_max_ = cnst_min_max; min_max_ = min_max;
ap_ = ap; ap_ = ap;
loadWork(); loadWork();
return makeRcmodelDrv(); return makeRcmodelDrv();
@ -158,18 +164,21 @@ ArnoldiReduce::loadWork()
{ {
pt_map_.clear(); pt_map_.clear();
int resistor_count = 0; const ParasiticResistorSeq &resistors = parasitics_->resistors(parasitic_network_);
ConcreteParasiticDeviceSet devices; int resistor_count = resistors.size();
parasitic_network_->devices(&devices);
ConcreteParasiticDeviceSet::Iterator device_iter(devices);
while (device_iter.hasNext()) {
ParasiticDevice *device = device_iter.next();
if (parasitics_->isResistor(device))
resistor_count++;
}
termN = parasitic_network_->pinNodes()->size(); termN = 0;
int subnode_count = parasitic_network_->subNodes()->size(); 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_pointN = subnode_count + 1 + termN;
ts_edgeN = resistor_count; ts_edgeN = resistor_count;
allocPoints(); allocPoints();
@ -191,50 +200,42 @@ ArnoldiReduce::loadWork()
pend = pterm0; pend = pterm0;
e = e0; e = e0;
int index = 0; 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++;
}
ConcreteParasiticPinNodeMap::Iterator for (ParasiticNode *node : nodes) {
pin_node_iter(parasitic_network_->pinNodes()); if (!parasitics_->isExternal(node)) {
while (pin_node_iter.hasNext()) { const Pin *pin = parasitics_->pin(node);
ConcreteParasiticPinNode *node = pin_node_iter.next(); if (pin) {
p = pend++; p = pend++;
pt_map_[node] = p - p0; pt_map_[node] = p - p0;
p->node_ = node; p->node_ = node;
p->eN = 0; p->eN = 0;
p->is_term = true; p->is_term = true;
tindex = p - pterm0; tindex = p - pterm0;
p->tindex = tindex; p->tindex = tindex;
const Pin *pin = parasitics_->connectionPin(node); pinV[tindex] = pin;
pinV[tindex] = pin; }
else {
pt_map_[node] = index;
p = p0 + index;
p->node_ = node;
p->eN = 0;
p->is_term = false;
index++;
}
}
} }
ts_edge **eV = ts_eV; ts_edge **eV = ts_eV;
ConcreteParasiticDeviceSet::Iterator device_iter2(devices); for (ParasiticResistor *resistor : resistors) {
while (device_iter2.hasNext()) { ts_point *pt1 = findPt(parasitics_->node1(resistor));
ParasiticDevice *device = device_iter2.next(); ts_point *pt2 = findPt(parasitics_->node2(resistor));
if (parasitics_->isResistor(device)) { e->from = pt1;
ConcreteParasiticResistor *resistor = e->to = pt2;
reinterpret_cast<ConcreteParasiticResistor*>(device); e->resistor_ = resistor;
ts_point *pt1 = findPt(resistor->node1()); pt1->eN++;
ts_point *pt2 = findPt(resistor->node2()); if (e->from != e->to)
e->from = pt1; pt2->eN++;
e->to = pt2; e++;
e->resistor_ = resistor;
pt1->eN++;
if (e->from != e->to)
pt2->eN++;
e++;
}
} }
for (p=p0;p!=pend;p++) { for (p=p0;p!=pend;p++) {
@ -313,8 +314,7 @@ ArnoldiReduce::findPt(ParasiticNode *node)
rcmodel * rcmodel *
ArnoldiReduce::makeRcmodelDrv() ArnoldiReduce::makeRcmodelDrv()
{ {
ParasiticNode *drv_node = parasitics_->findNode(parasitic_network_, ParasiticNode *drv_node = parasitics_->findNode(parasitic_network_, drvr_pin_);
drvr_pin_);
ts_point *pdrv = findPt(drv_node); ts_point *pdrv = findPt(drv_node);
makeRcmodelDfs(pdrv); makeRcmodelDfs(pdrv);
getRC(); getRC();
@ -322,8 +322,7 @@ ArnoldiReduce::makeRcmodelDrv()
return nullptr; return nullptr;
setTerms(pdrv); setTerms(pdrv);
makeRcmodelFromTs(); makeRcmodelFromTs();
rcmodel *mod = makeRcmodelFromW(); return makeRcmodelFromW();
return mod;
} }
#define ts_orient( pp, ee) \ #define ts_orient( pp, ee) \
@ -415,7 +414,7 @@ ArnoldiReduce::getRC()
p->r = 0.0; p->r = 0.0;
if (p->node_) { if (p->node_) {
ParasiticNode *node = p->node_; ParasiticNode *node = p->node_;
double cap = parasitics_->nodeGndCap(node, ap_) double cap = parasitics_->nodeGndCap(node)
+ pinCapacitance(node); + pinCapacitance(node);
if (cap > 0.0) { if (cap > 0.0) {
p->c = cap; p->c = cap;
@ -424,7 +423,7 @@ ArnoldiReduce::getRC()
else else
p->c = 0.0; p->c = 0.0;
if (p->in_edge && p->in_edge->resistor_) 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 if (!(p->r>=0.0 && p->r<100e+3)) { // 0 < r < 100kohm
debugPrint(debug_, "arnoldi", 1, debugPrint(debug_, "arnoldi", 1,
"R value %g out of range, drvr pin %s", "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 float
ArnoldiReduce::pinCapacitance(ParasiticNode *node) ArnoldiReduce::pinCapacitance(ParasiticNode *node)
{ {
const Pin *pin = parasitics_->connectionPin(node); const Pin *pin = parasitics_->pin(node);
float pin_cap = 0.0; float pin_cap = 0.0;
if (pin) { if (pin) {
Port *port = network_->port(pin); Port *port = network_->port(pin);
LibertyPort *lib_port = network_->libertyPort(port); LibertyPort *lib_port = network_->libertyPort(port);
if (lib_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)) 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; return pin_cap;
} }

View File

@ -37,21 +37,20 @@ class rcmodel;
struct ts_edge; struct ts_edge;
struct ts_point; struct ts_point;
typedef Map<ConcreteParasiticNode*, int> ArnolidPtMap; typedef Map<ParasiticNode*, int> ArnolidPtMap;
class ArnoldiReduce : public StaState class ArnoldiReduce : public StaState
{ {
public: public:
ArnoldiReduce(StaState *sta); ArnoldiReduce(StaState *sta);
~ArnoldiReduce(); ~ArnoldiReduce();
Parasitic *reduceToArnoldi(Parasitic *parasitic, rcmodel *reduceToArnoldi(Parasitic *parasitic,
const Pin *drvr_pin, const Pin *drvr_pin,
float coupling_cap_factor, float coupling_cap_factor,
const RiseFall *rf, const RiseFall *rf,
const OperatingConditions *op_cond, const Corner *corner,
const Corner *corner, const MinMax *cnst_min_max,
const MinMax *cnst_min_max, const ParasiticAnalysisPt *ap);
const ParasiticAnalysisPt *ap);
protected: protected:
void loadWork(); void loadWork();
@ -70,9 +69,8 @@ protected:
const Pin *drvr_pin_; const Pin *drvr_pin_;
float coupling_cap_factor_; float coupling_cap_factor_;
const RiseFall *rf_; const RiseFall *rf_;
const OperatingConditions *op_cond_;
const Corner *corner_; const Corner *corner_;
const MinMax *cnst_min_max_; const MinMax *min_max_;
const ParasiticAnalysisPt *ap_; const ParasiticAnalysisPt *ap_;
// ParasiticNode -> ts_point index. // ParasiticNode -> ts_point index.
ArnolidPtMap pt_map_; ArnolidPtMap pt_map_;

View File

@ -23,6 +23,7 @@
#include "Network.hh" #include "Network.hh"
#include "Parasitics.hh" #include "Parasitics.hh"
#include "Sdc.hh" #include "Sdc.hh"
#include "Corner.hh"
#include "DcalcAnalysisPt.hh" #include "DcalcAnalysisPt.hh"
namespace sta { 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 * TimingModel *
DelayCalcBase::model(const TimingArc *arc, DelayCalcBase::model(const TimingArc *arc,
const DcalcAnalysisPt *dcalc_ap) const const DcalcAnalysisPt *dcalc_ap) const
@ -67,12 +97,6 @@ DelayCalcBase::checkModel(const TimingArc *arc,
void void
DelayCalcBase::finishDrvrPin() 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 // For DSPF on an input port the elmore delay is used as the time

View File

@ -28,6 +28,11 @@ public:
explicit DelayCalcBase(StaState *sta); explicit DelayCalcBase(StaState *sta);
void finishDrvrPin() override; 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, ArcDelay checkDelay(const Pin *check_pin,
const TimingArc *arc, const TimingArc *arc,
const Slew &from_slew, const Slew &from_slew,
@ -72,11 +77,7 @@ protected:
const Pvt *pinPvt(const Pin *pin, const Pvt *pinPvt(const Pin *pin,
const DcalcAnalysisPt *dcalc_ap); const DcalcAnalysisPt *dcalc_ap);
// Parasitics returned by findParasitic that are reduced or estimated using ArcDelayCalc::reduceParasitic;
// that can be deleted after delay calculation for the driver pin
// is finished.
Vector<Parasitic*> unsaved_parasitics_;
Vector<const Pin *> reduced_parasitic_drvrs_;
}; };
} // namespace } // namespace

View File

@ -19,12 +19,13 @@
#include "TableModel.hh" #include "TableModel.hh"
#include "TimingArc.hh" #include "TimingArc.hh"
#include "Liberty.hh" #include "Liberty.hh"
#include "PortDirection.hh"
#include "Network.hh"
#include "Sdc.hh" #include "Sdc.hh"
#include "Parasitics.hh" #include "Parasitics.hh"
#include "DcalcAnalysisPt.hh" #include "DcalcAnalysisPt.hh"
#include "GraphDelayCalc.hh" #include "GraphDelayCalc.hh"
#include "DmpCeff.hh" #include "DmpCeff.hh"
#include "Network.hh"
namespace sta { namespace sta {
@ -132,7 +133,6 @@ public:
Parasitic *findParasitic(const Pin *drvr_pin, Parasitic *findParasitic(const Pin *drvr_pin,
const RiseFall *rf, const RiseFall *rf,
const DcalcAnalysisPt *dcalc_ap) override; const DcalcAnalysisPt *dcalc_ap) override;
ReducedParasiticType reducedParasiticType() const override;
ArcDcalcResult inputPortDelay(const Pin *port_pin, ArcDcalcResult inputPortDelay(const Pin *port_pin,
float in_slew, float in_slew,
const RiseFall *rf, const RiseFall *rf,
@ -210,58 +210,41 @@ DmpCeffTwoPoleDelayCalc::findParasitic(const Pin *drvr_pin,
Parasitic *parasitic = nullptr; Parasitic *parasitic = nullptr;
const Corner *corner = dcalc_ap->corner(); const Corner *corner = dcalc_ap->corner();
// set_load net has precedence over parasitics. // set_load net has precedence over parasitics.
if (!sdc_->drvrPinHasWireCap(drvr_pin, corner)) { if (sdc_->drvrPinHasWireCap(drvr_pin, corner)
const ParasiticAnalysisPt *parasitic_ap = dcalc_ap->parasiticAnalysisPt(); || network_->direction(drvr_pin)->isInternal())
if (parasitics_->haveParasitics()) { return nullptr;
// Prefer PiPoleResidue. const ParasiticAnalysisPt *parasitic_ap = dcalc_ap->parasiticAnalysisPt();
parasitic = parasitics_->findPiPoleResidue(drvr_pin, rf, parasitic_ap); // Prefer PiPoleResidue.
if (parasitic == nullptr) { parasitic = parasitics_->findPiPoleResidue(drvr_pin, rf, parasitic_ap);
parasitic = parasitics_->findPiElmore(drvr_pin, rf, parasitic_ap); if (parasitic)
if (parasitic == nullptr) { return parasitic;
Parasitic *parasitic_network = parasitic = parasitics_->findPiElmore(drvr_pin, rf, parasitic_ap);
parasitics_->findParasiticNetwork(drvr_pin, parasitic_ap); if (parasitic)
if (parasitic_network) { return parasitic;
parasitics_->reduceToPiPoleResidue2(parasitic_network, drvr_pin, Parasitic *parasitic_network =
dcalc_ap->operatingConditions(), parasitics_->findParasiticNetwork(drvr_pin, parasitic_ap);
corner, if (parasitic_network) {
dcalc_ap->constraintMinMax(), parasitic = parasitics_->reduceToPiPoleResidue2(parasitic_network, drvr_pin, rf,
parasitic_ap); corner,
parasitic = parasitics_->findPiPoleResidue(drvr_pin, rf, parasitic_ap); dcalc_ap->constraintMinMax(),
reduced_parasitic_drvrs_.push_back(drvr_pin); parasitic_ap);
} if (parasitic)
} return parasitic;
} }
} const MinMax *cnst_min_max = dcalc_ap->constraintMinMax();
else { Wireload *wireload = sdc_->wireload(cnst_min_max);
const MinMax *cnst_min_max = dcalc_ap->constraintMinMax(); if (wireload) {
Wireload *wireload = sdc_->wireload(cnst_min_max); float pin_cap, wire_cap, fanout;
if (wireload) { bool has_wire_cap;
float pin_cap, wire_cap, fanout; graph_delay_calc_->netCaps(drvr_pin, rf, dcalc_ap, pin_cap, wire_cap,
bool has_wire_cap; fanout, has_wire_cap);
graph_delay_calc_->netCaps(drvr_pin, rf, dcalc_ap, parasitic = parasitics_->estimatePiElmore(drvr_pin, rf, wireload,
pin_cap, wire_cap, fanout, has_wire_cap); fanout, pin_cap, corner,
parasitic = parasitics_->estimatePiElmore(drvr_pin, rf, wireload, cnst_min_max);
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);
}
}
} }
return parasitic; return parasitic;
} }
ReducedParasiticType
DmpCeffTwoPoleDelayCalc::reducedParasiticType() const
{
return ReducedParasiticType::pi_pole_residue2;
}
ArcDcalcResult ArcDcalcResult
DmpCeffTwoPoleDelayCalc::inputPortDelay(const Pin *, DmpCeffTwoPoleDelayCalc::inputPortDelay(const Pin *,
float in_slew, float in_slew,

View File

@ -365,9 +365,11 @@ GraphDelayCalc::seedNoDrvrCellSlew(Vertex *drvr_vertex,
Delay drive_delay = delay_zero; Delay drive_delay = delay_zero;
float drive_res; float drive_res;
drive->driveResistance(rf, cnst_min_max, drive_res, exists); 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) { if (exists) {
float cap = loadCap(drvr_pin, parasitic, rf, dcalc_ap);
drive_delay = cap * drive_res; drive_delay = cap * drive_res;
slew = cap * drive_res; slew = cap * drive_res;
} }
@ -408,7 +410,7 @@ GraphDelayCalc::seedNoDrvrSlew(Vertex *drvr_vertex,
load_pin_index_map, dcalc_ap); load_pin_index_map, dcalc_ap);
annotateLoadDelays(drvr_vertex, rf, dcalc_result, load_pin_index_map, delay_zero, annotateLoadDelays(drvr_vertex, rf, dcalc_result, load_pin_index_map, delay_zero,
false, dcalc_ap); false, dcalc_ap);
arc_delay_calc->finishDrvrPin(); arc_delay_calc_->finishDrvrPin();
} }
void 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 // 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(); const RiseFall *drvr_rf = arc->toEdge()->asRiseFall();
if (drvr_rf) { if (drvr_rf) {
DcalcAPIndex ap_index = dcalc_ap->index(); DcalcAPIndex ap_index = dcalc_ap->index();
Parasitic *parasitic = arc_delay_calc_->findParasitic(drvr_pin, drvr_rf, dcalc_ap); const Parasitic *parasitic;
float load_cap = loadCap(drvr_pin, parasitic, drvr_rf, dcalc_ap); 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); LoadPinIndexMap load_pin_index_map = makeLoadPinIndexMap(drvr_vertex);
ArcDcalcResult intrinsic_result = ArcDcalcResult intrinsic_result =
@ -547,6 +552,7 @@ GraphDelayCalc::findInputArcDelay(const Pin *drvr_pin,
graph_->setSlew(drvr_vertex, drvr_rf, ap_index, gate_slew); graph_->setSlew(drvr_vertex, drvr_rf, ap_index, gate_slew);
annotateLoadDelays(drvr_vertex, drvr_rf, gate_result, load_pin_index_map, annotateLoadDelays(drvr_vertex, drvr_rf, gate_result, load_pin_index_map,
load_delay, false, dcalc_ap); load_delay, false, dcalc_ap);
arc_delay_calc_->finishDrvrPin();
} }
} }
@ -646,7 +652,7 @@ GraphDelayCalc::findDriverDelays(Vertex *drvr_vertex,
initLoadSlews(drvr_vertex); initLoadSlews(drvr_vertex);
delay_changed |= findDriverDelays1(drvr_vertex, multi_drvr, arc_delay_calc); delay_changed |= findDriverDelays1(drvr_vertex, multi_drvr, arc_delay_calc);
} }
arc_delay_calc->finishDrvrPin(); arc_delay_calc_->finishDrvrPin();
return delay_changed; return delay_changed;
} }
@ -849,7 +855,6 @@ GraphDelayCalc::findDriverEdgeDelays(Vertex *drvr_vertex,
Vertex *from_vertex = edge->from(graph_); Vertex *from_vertex = edge->from(graph_);
const TimingArcSet *arc_set = edge->timingArcSet(); const TimingArcSet *arc_set = edge->timingArcSet();
bool delay_changed = false; bool delay_changed = false;
PinSeq load_pins = loadPins(drvr_vertex);
LoadPinIndexMap load_pin_index_map = makeLoadPinIndexMap(drvr_vertex); LoadPinIndexMap load_pin_index_map = makeLoadPinIndexMap(drvr_vertex);
for (auto dcalc_ap : corners_->dcalcAnalysisPts()) { for (auto dcalc_ap : corners_->dcalcAnalysisPts()) {
for (const TimingArc *arc : arc_set->arcs()) for (const TimingArc *arc : arc_set->arcs())
@ -892,9 +897,11 @@ GraphDelayCalc::findDriverArcDelays(Vertex *drvr_vertex,
const RiseFall *drvr_rf = arc->toEdge()->asRiseFall(); const RiseFall *drvr_rf = arc->toEdge()->asRiseFall();
if (from_rf && drvr_rf) { if (from_rf && drvr_rf) {
const Pin *drvr_pin = drvr_vertex->pin(); const Pin *drvr_pin = drvr_vertex->pin();
Parasitic *parasitic = arc_delay_calc->findParasitic(drvr_pin, drvr_rf, const Parasitic *parasitic;
dcalc_ap); float load_cap;
float load_cap = loadCap(drvr_pin, parasitic, drvr_rf, dcalc_ap, multi_drvr); parasiticLoad(drvr_pin, drvr_rf, dcalc_ap, multi_drvr, arc_delay_calc,
load_cap, parasitic);
if (multi_drvr if (multi_drvr
&& multi_drvr->parallelGates(network_)) { && multi_drvr->parallelGates(network_)) {
ArcDcalcArgSeq dcalc_args = makeArcDcalcArgs(drvr_vertex, multi_drvr, ArcDcalcArgSeq dcalc_args = makeArcDcalcArgs(drvr_vertex, multi_drvr,
@ -921,6 +928,7 @@ GraphDelayCalc::findDriverArcDelays(Vertex *drvr_vertex,
delay_changed |= annotateDelaysSlews(edge, arc, dcalc_result, delay_changed |= annotateDelaysSlews(edge, arc, dcalc_result,
load_pin_index_map, dcalc_ap); load_pin_index_map, dcalc_ap);
} }
arc_delay_calc->finishDrvrPin();
} }
return delay_changed; 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 LoadPinIndexMap
GraphDelayCalc::makeLoadPinIndexMap(Vertex *drvr_vertex) GraphDelayCalc::makeLoadPinIndexMap(Vertex *drvr_vertex)
{ {
@ -1159,6 +1152,7 @@ GraphDelayCalc::makeLoadPinIndexMap(Vertex *drvr_vertex)
return load_pin_index_map; return load_pin_index_map;
} }
// External
float float
GraphDelayCalc::loadCap(const Pin *drvr_pin, GraphDelayCalc::loadCap(const Pin *drvr_pin,
const DcalcAnalysisPt *dcalc_ap) const const DcalcAnalysisPt *dcalc_ap) const
@ -1166,92 +1160,104 @@ GraphDelayCalc::loadCap(const Pin *drvr_pin,
const MinMax *min_max = dcalc_ap->constraintMinMax(); const MinMax *min_max = dcalc_ap->constraintMinMax();
float load_cap = 0.0; float load_cap = 0.0;
for (auto drvr_rf : RiseFall::range()) { for (auto drvr_rf : RiseFall::range()) {
Parasitic *parasitic = arc_delay_calc_->findParasitic(drvr_pin, drvr_rf, dcalc_ap); float cap = loadCap(drvr_pin, drvr_rf, dcalc_ap);
float cap = loadCap(drvr_pin, parasitic, drvr_rf, dcalc_ap, nullptr);
arc_delay_calc_->finishDrvrPin();
if (min_max->compare(cap, load_cap)) if (min_max->compare(cap, load_cap))
load_cap = cap; load_cap = cap;
} }
arc_delay_calc_->finishDrvrPin();
return load_cap; return load_cap;
} }
// External
float float
GraphDelayCalc::loadCap(const Pin *drvr_pin, 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 RiseFall *rf,
const DcalcAnalysisPt *dcalc_ap) const 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; float pin_cap, wire_cap;
bool has_net_load; loadCap(drvr_pin, rf, dcalc_ap, pin_cap, wire_cap);
float fanout; return pin_cap + wire_cap;
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;
} }
// External
void void
GraphDelayCalc::loadCap(const Pin *drvr_pin, GraphDelayCalc::loadCap(const Pin *drvr_pin,
const Parasitic *parasitic,
const RiseFall *rf, const RiseFall *rf,
const DcalcAnalysisPt *dcalc_ap, const DcalcAnalysisPt *dcalc_ap,
// Return values.
float &pin_cap, float &pin_cap,
float &wire_cap) const float &wire_cap) const
{ {
bool has_net_load; MultiDrvrNet *multi_drvr = nullptr;
float fanout; if (graph_) {
// Find pin and external pin/wire capacitance. Vertex *drvr_vertex = graph_->pinDrvrVertex(drvr_pin);
netCaps(drvr_pin, rf, dcalc_ap, multi_drvr = multiDrvrNet(drvr_vertex);
pin_cap, wire_cap, fanout, has_net_load); }
loadCap(parasitic, has_net_load, pin_cap, wire_cap); 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 void
GraphDelayCalc::loadCap(const Parasitic *parasitic, GraphDelayCalc::parasiticLoad(const Pin *drvr_pin,
bool has_net_load, const RiseFall *rf,
// Return values. const DcalcAnalysisPt *dcalc_ap,
float &pin_cap, const MultiDrvrNet *multi_drvr,
float &wire_cap) const ArcDelayCalc *arc_delay_calc,
// Return values.
float &load_cap,
const Parasitic *&parasitic) 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 *&parasitic) 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. // set_load net has precedence over parasitics.
if (!has_net_load && parasitic) { if (!has_net_load && parasitic) {
if (parasitics_->isParasiticNetwork(parasitic)) if (parasitics_->isParasiticNetwork(parasitic))
wire_cap += parasitics_->capacitance(parasitic); wire_cap += parasitics_->capacitance(parasitic);
else { else {
// PiModel includes both pin and external caps. // PiModel includes both pin and external caps.
float cap = parasitics_->capacitance(parasitic); float parasitic_cap = parasitics_->capacitance(parasitic);
if (pin_cap > cap) { if (parasitic_cap >= pin_cap)
pin_cap = 0.0; wire_cap = parasitic_cap - pin_cap;
wire_cap = 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); Vertex *drvr_vertex = graph_->pinDrvrVertex(drvr_pin);
multi_drvr = multiDrvrNet(drvr_vertex); 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) if (multi_drvr)
multi_drvr->netCaps(rf, dcalc_ap, multi_drvr->netCaps(rf, dcalc_ap,
pin_cap, wire_cap, fanout, has_net_load); pin_cap, wire_cap, fanout, has_net_load);
else { else {
const OperatingConditions *op_cond = dcalc_ap->operatingConditions();
const Corner *corner = dcalc_ap->corner(); const Corner *corner = dcalc_ap->corner();
const MinMax *min_max = dcalc_ap->constraintMinMax(); const MinMax *min_max = dcalc_ap->constraintMinMax();
// Find pin and external pin/wire capacitance. // 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); pin_cap, wire_cap, fanout, has_net_load);
} }
} }
@ -1405,13 +1425,8 @@ GraphDelayCalc::findCheckEdgeDelays(Edge *edge,
delayAsString(from_slew, this), delayAsString(from_slew, this),
delayAsString(to_slew, this)); delayAsString(to_slew, this));
float related_out_cap = 0.0; float related_out_cap = 0.0;
if (related_out_pin) { if (related_out_pin)
Parasitic *related_out_parasitic = related_out_cap = loadCap(related_out_pin, to_rf,dcalc_ap,arc_delay_calc);
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);
}
ArcDelay check_delay = arc_delay_calc->checkDelay(to_pin, arc, from_slew, ArcDelay check_delay = arc_delay_calc->checkDelay(to_pin, arc, from_slew,
to_slew, related_out_cap, to_slew, related_out_cap,
dcalc_ap); dcalc_ap);
@ -1420,6 +1435,7 @@ GraphDelayCalc::findCheckEdgeDelays(Edge *edge,
delayAsString(check_delay, this)); delayAsString(check_delay, this));
graph_->setArcDelay(edge, arc, ap_index, check_delay); graph_->setArcDelay(edge, arc, ap_index, check_delay);
delay_changed = true; delay_changed = true;
arc_delay_calc_->finishDrvrPin();
} }
} }
} }
@ -1467,12 +1483,8 @@ GraphDelayCalc::reportDelayCalc(const Edge *edge,
if (related_out_port) if (related_out_port)
related_out_pin = network_->findPin(inst, related_out_port); related_out_pin = network_->findPin(inst, related_out_port);
float related_out_cap = 0.0; float related_out_cap = 0.0;
if (related_out_pin) { if (related_out_pin)
Parasitic *related_out_parasitic = related_out_cap = loadCap(related_out_pin, to_rf, dcalc_ap, arc_delay_calc_);
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 (role->isTimingCheck()) { if (role->isTimingCheck()) {
const Slew &from_slew = checkEdgeClkSlew(from_vertex, from_rf, dcalc_ap); const Slew &from_slew = checkEdgeClkSlew(from_vertex, from_rf, dcalc_ap);
int slew_index = dcalc_ap->checkDataSlewIndex(); int slew_index = dcalc_ap->checkDataSlewIndex();
@ -1484,10 +1496,11 @@ GraphDelayCalc::reportDelayCalc(const Edge *edge,
related_out_cap, dcalc_ap, digits); related_out_cap, dcalc_ap, digits);
} }
else { 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); 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); LoadPinIndexMap load_pin_index_map = makeLoadPinIndexMap(to_vertex);
result = arc_delay_calc_->reportGateDelay(to_pin, arc, from_slew, load_cap, result = arc_delay_calc_->reportGateDelay(to_pin, arc, from_slew, load_cap,
to_parasitic, load_pin_index_map, to_parasitic, load_pin_index_map,
@ -1591,7 +1604,6 @@ MultiDrvrNet::findCaps(const Sdc *sdc)
for (auto dcalc_ap : corners->dcalcAnalysisPts()) { for (auto dcalc_ap : corners->dcalcAnalysisPts()) {
DcalcAPIndex ap_index = dcalc_ap->index(); DcalcAPIndex ap_index = dcalc_ap->index();
const Corner *corner = dcalc_ap->corner(); const Corner *corner = dcalc_ap->corner();
const OperatingConditions *op_cond = dcalc_ap->operatingConditions();
const MinMax *min_max = dcalc_ap->constraintMinMax(); const MinMax *min_max = dcalc_ap->constraintMinMax();
for (auto drvr_rf : RiseFall::range()) { for (auto drvr_rf : RiseFall::range()) {
int drvr_rf_index = drvr_rf->index(); int drvr_rf_index = drvr_rf->index();
@ -1600,7 +1612,7 @@ MultiDrvrNet::findCaps(const Sdc *sdc)
float pin_cap, wire_cap, fanout; float pin_cap, wire_cap, fanout;
bool has_net_load; bool has_net_load;
// Find pin and external pin/wire capacitance. // 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); pin_cap, wire_cap, fanout, has_net_load);
net_caps.init(pin_cap, wire_cap, fanout, has_net_load); net_caps.init(pin_cap, wire_cap, fanout, has_net_load);
} }

View File

@ -23,6 +23,7 @@
#include "TimingArc.hh" #include "TimingArc.hh"
#include "TimingModel.hh" #include "TimingModel.hh"
#include "Liberty.hh" #include "Liberty.hh"
#include "PortDirection.hh"
#include "Network.hh" #include "Network.hh"
#include "Sdc.hh" #include "Sdc.hh"
#include "Parasitics.hh" #include "Parasitics.hh"
@ -58,53 +59,46 @@ LumpedCapDelayCalc::findParasitic(const Pin *drvr_pin,
Parasitic *parasitic = nullptr; Parasitic *parasitic = nullptr;
const Corner *corner = dcalc_ap->corner(); const Corner *corner = dcalc_ap->corner();
// set_load net has precedence over parasitics. // set_load net has precedence over parasitics.
if (!sdc_->drvrPinHasWireCap(drvr_pin, corner)) { if (sdc_->drvrPinHasWireCap(drvr_pin, corner)
const ParasiticAnalysisPt *parasitic_ap = dcalc_ap->parasiticAnalysisPt(); || network_->direction(drvr_pin)->isInternal())
if (parasitics_->haveParasitics()) { return nullptr;
// Prefer PiElmore. const ParasiticAnalysisPt *parasitic_ap = dcalc_ap->parasiticAnalysisPt();
parasitic = parasitics_->findPiElmore(drvr_pin, rf, parasitic_ap); // Prefer PiElmore.
if (parasitic == nullptr) { parasitic = parasitics_->findPiElmore(drvr_pin, rf, parasitic_ap);
Parasitic *parasitic_network = if (parasitic)
parasitics_->findParasiticNetwork(drvr_pin, parasitic_ap); return parasitic;
if (parasitic_network) { Parasitic *parasitic_network = parasitics_->findParasiticNetwork(drvr_pin,
parasitics_->reduceToPiElmore(parasitic_network, drvr_pin, parasitic_ap);
dcalc_ap->operatingConditions(), if (parasitic_network) {
corner, parasitic = reduceParasitic(parasitic_network, drvr_pin, rf, dcalc_ap);
dcalc_ap->constraintMinMax(), if (parasitic)
parasitic_ap); return parasitic;
parasitic = parasitics_->findPiElmore(drvr_pin, rf, parasitic_ap); }
reduced_parasitic_drvrs_.push_back(drvr_pin); const MinMax *min_max = dcalc_ap->constraintMinMax();
} Wireload *wireload = sdc_->wireload(min_max);
} if (wireload) {
} float pin_cap, wire_cap, fanout;
else { bool has_net_load;
const MinMax *cnst_min_max = dcalc_ap->constraintMinMax(); graph_delay_calc_->netCaps(drvr_pin, rf, dcalc_ap,
Wireload *wireload = sdc_->wireload(cnst_min_max); pin_cap, wire_cap, fanout, has_net_load);
if (wireload) { parasitic = parasitics_->estimatePiElmore(drvr_pin, rf, wireload, fanout,
float pin_cap, wire_cap, fanout; pin_cap, corner, min_max);
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);
}
}
} }
return parasitic; return parasitic;
} }
ReducedParasiticType Parasitic *
LumpedCapDelayCalc::reducedParasiticType() const 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 ArcDcalcResult

View File

@ -30,7 +30,10 @@ public:
Parasitic *findParasitic(const Pin *drvr_pin, Parasitic *findParasitic(const Pin *drvr_pin,
const RiseFall *rf, const RiseFall *rf,
const DcalcAnalysisPt *dcalc_ap) override; 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, ArcDcalcResult inputPortDelay(const Pin *port_pin,
float in_slew, float in_slew,
const RiseFall *rf, const RiseFall *rf,
@ -59,6 +62,8 @@ protected:
ArcDelay gate_delay, ArcDelay gate_delay,
Slew drvr_slew, Slew drvr_slew,
const LoadPinIndexMap &load_pin_index_map); const LoadPinIndexMap &load_pin_index_map);
using ArcDelayCalc::reduceParasitic;
}; };
ArcDelayCalc * ArcDelayCalc *

View File

@ -45,10 +45,21 @@ UnitDelayCalc::findParasitic(const Pin *,
return nullptr; return nullptr;
} }
ReducedParasiticType Parasitic *
UnitDelayCalc::reducedParasiticType() const 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 ArcDcalcResult

View File

@ -29,7 +29,14 @@ public:
Parasitic *findParasitic(const Pin *drvr_pin, Parasitic *findParasitic(const Pin *drvr_pin,
const RiseFall *rf, const RiseFall *rf,
const DcalcAnalysisPt *dcalc_ap) override; 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, ArcDcalcResult inputPortDelay(const Pin *port_pin,
float in_slew, float in_slew,
const RiseFall *rf, const RiseFall *rf,

View File

@ -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 report_instance -connections and -verbose flags are deprecated.
The options are now enabled in all cases. 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 Release 2.4.0 2023/01/19
------------------------- -------------------------

Binary file not shown.

Binary file not shown.

View File

@ -124,7 +124,18 @@ public:
virtual Parasitic *findParasitic(const Pin *drvr_pin, virtual Parasitic *findParasitic(const Pin *drvr_pin,
const RiseFall *rf, const RiseFall *rf,
const DcalcAnalysisPt *dcalc_ap) = 0; 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. // Find the wire delays and slews for an input port without a driving cell.
// This call primarily initializes the load delay/slew iterator. // This call primarily initializes the load delay/slew iterator.
virtual ArcDcalcResult inputPortDelay(const Pin *port_pin, virtual ArcDcalcResult inputPortDelay(const Pin *port_pin,

View File

@ -55,8 +55,7 @@ public:
void operatingConditionsChanged(); void operatingConditionsChanged();
// Make one parasitic analysis points. // Make one parasitic analysis points.
void makeParasiticAnalysisPts(bool per_corner, void makeParasiticAnalysisPts(bool per_corner);
bool per_min_max);
int parasiticAnalysisPtCount() const; int parasiticAnalysisPtCount() const;
ParasiticAnalysisPtSeq &parasiticAnalysisPts(); ParasiticAnalysisPtSeq &parasiticAnalysisPts();
@ -114,7 +113,7 @@ public:
protected: protected:
void setParasiticAnalysisPtcount(int ap_count); void setParasiticAnalysisPtcount(int ap_count);
void setParasiticAP(ParasiticAnalysisPt *path_ap, void setParasiticAP(ParasiticAnalysisPt *path_ap,
int ap_index); int mm_index);
void setDcalcAnalysisPtcount(DcalcAPIndex ap_count); void setDcalcAnalysisPtcount(DcalcAPIndex ap_count);
void addDcalcAP(DcalcAnalysisPt *dcalc_ap); void addDcalcAP(DcalcAnalysisPt *dcalc_ap);
void addPathAP(PathAnalysisPt *path_ap); void addPathAP(PathAnalysisPt *path_ap);

View File

@ -72,41 +72,26 @@ public:
// delays to be recomputed during incremental delay calculation. // delays to be recomputed during incremental delay calculation.
virtual float incrementalDelayTolerance(); virtual float incrementalDelayTolerance();
virtual void setIncrementalDelayTolerance(float tol); 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, float loadCap(const Pin *drvr_pin,
const Parasitic *parasitic, const DcalcAnalysisPt *dcalc_ap) const;
const RiseFall *rf, float loadCap(const Pin *drvr_pin,
const DcalcAnalysisPt *dcalc_ap, const RiseFall *rf,
const MultiDrvrNet *multi_drvr) const; const DcalcAnalysisPt *dcalc_ap) const;
virtual void netCaps(const Pin *drvr_pin, void loadCap(const Pin *drvr_pin,
const RiseFall *rf, const RiseFall *rf,
const DcalcAnalysisPt *dcalc_ap, const DcalcAnalysisPt *dcalc_ap,
// Return values. // Return values.
float &pin_cap, float &pin_cap,
float &wire_cap, float &wire_cap) const;
float &fanout, void netCaps(const Pin *drvr_pin,
bool &has_set_load) const; const RiseFall *rf,
PinSeq loadPins(Vertex *drvr_vertex); const DcalcAnalysisPt *dcalc_ap,
// Return values.
float &pin_cap,
float &wire_cap,
float &fanout,
bool &has_set_load) const;
LoadPinIndexMap makeLoadPinIndexMap(Vertex *drvr_vertex); LoadPinIndexMap makeLoadPinIndexMap(Vertex *drvr_vertex);
void findDriverArcDelays(Vertex *drvr_vertex, void findDriverArcDelays(Vertex *drvr_vertex,
Edge *edge, Edge *edge,
@ -242,11 +227,36 @@ protected:
const RiseFall *from_rf, const RiseFall *from_rf,
const DcalcAnalysisPt *dcalc_ap); const DcalcAnalysisPt *dcalc_ap);
bool bidirectDrvrSlewFromLoad(const Vertex *vertex) const; bool bidirectDrvrSlewFromLoad(const Vertex *vertex) const;
void loadCap(const Parasitic *parasitic, float loadCap(const Pin *drvr_pin,
bool has_set_load, const RiseFall *rf,
// Return values. const DcalcAnalysisPt *dcalc_ap,
float &pin_cap, ArcDelayCalc *arc_delay_calc) const;
float &wire_cap) 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 *&parasitic) 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 *&parasitic) 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. // Observer for edge delay changes.
DelayCalcObserver *observer_; DelayCalcObserver *observer_;

View File

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

View File

@ -17,6 +17,8 @@
#pragma once #pragma once
#include <complex> #include <complex>
#include <map>
#include <vector>
#include "StaState.hh" #include "StaState.hh"
#include "LibertyClass.hh" #include "LibertyClass.hh"
@ -31,16 +33,17 @@ class Corner;
typedef std::complex<float> ComplexFloat; typedef std::complex<float> ComplexFloat;
typedef Vector<ComplexFloat> ComplexFloatSeq; typedef Vector<ComplexFloat> ComplexFloatSeq;
typedef Iterator<ParasiticDevice*> ParasiticDeviceIterator; typedef std::vector<ParasiticNode*> ParasiticNodeSeq;
typedef Iterator<ParasiticNode*> ParasiticNodeIterator; typedef std::vector<ParasiticResistor*> ParasiticResistorSeq;
typedef std::vector<ParasiticCapacitor*> ParasiticCapacitorSeq;
typedef std::map<ParasiticNode *, ParasiticResistorSeq> ParasiticNodeResistorMap;
typedef std::map<ParasiticNode *, ParasiticCapacitorSeq> ParasiticNodeCapacitorMap;
// Parasitics API. // Parasitics API.
// All parasitic parameters can have multiple values, each corresponding // All parasitic parameters can have multiple values, each corresponding
// to an analysis point. // to an analysis point.
// Parasitic annotation for a pin or net may exist for one analysis point // Parasitic annotation for a pin or net may exist for one analysis point
// and not another. // 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 class Parasitics : public StaState
{ {
public: public:
@ -50,8 +53,6 @@ public:
// Clear all state. // Clear all state.
virtual void clear() = 0; virtual void clear() = 0;
// Save parasitics to database file.
virtual void save() = 0;
// Delete all parasitics. // Delete all parasitics.
virtual void deleteParasitics() = 0; virtual void deleteParasitics() = 0;
// Delete all parasitics on net at analysis point. // Delete all parasitics on net at analysis point.
@ -60,7 +61,6 @@ public:
// Delete all parasitics on pin at analysis point. // Delete all parasitics on pin at analysis point.
virtual void deleteParasitics(const Pin *pin, virtual void deleteParasitics(const Pin *pin,
const ParasiticAnalysisPt *ap) = 0; const ParasiticAnalysisPt *ap) = 0;
virtual void deleteUnsavedParasitic(Parasitic *parasitic) = 0;
virtual void deleteReducedParasitics(const Net *net, virtual void deleteReducedParasitics(const Net *net,
const ParasiticAnalysisPt *ap) = 0; const ParasiticAnalysisPt *ap) = 0;
virtual void deleteDrvrReducedParasitics(const Pin *drvr_pin) = 0; virtual void deleteDrvrReducedParasitics(const Pin *drvr_pin) = 0;
@ -153,8 +153,9 @@ public:
virtual Parasitic *makeParasiticNetwork(const Net *net, virtual Parasitic *makeParasiticNetwork(const Net *net,
bool includes_pin_caps, bool includes_pin_caps,
const ParasiticAnalysisPt *ap) = 0; const ParasiticAnalysisPt *ap) = 0;
virtual ParasiticDeviceIterator *deviceIterator(const Parasitic *parasitic) = 0; virtual ParasiticNodeSeq nodes(const Parasitic *parasitic) const = 0;
virtual ParasiticNodeIterator *nodeIterator(const Parasitic *parasitic) = 0; virtual ParasiticResistorSeq resistors(const Parasitic *parasitic) const = 0;
virtual ParasiticCapacitorSeq capacitors(const Parasitic *parasitic) const = 0;
// Delete parasitic network if it exists. // Delete parasitic network if it exists.
virtual void deleteParasiticNetwork(const Net *net, virtual void deleteParasiticNetwork(const Net *net,
const ParasiticAnalysisPt *ap) = 0; const ParasiticAnalysisPt *ap) = 0;
@ -165,130 +166,98 @@ public:
// Make a subnode of the parasitic network net. // Make a subnode of the parasitic network net.
virtual ParasiticNode *ensureParasiticNode(Parasitic *parasitic, virtual ParasiticNode *ensureParasiticNode(Parasitic *parasitic,
const Net *net, const Net *net,
int id) = 0; int id,
const Network *network) = 0;
// Make a subnode of the parasitic network net connected to pin. // Make a subnode of the parasitic network net connected to pin.
virtual ParasiticNode *ensureParasiticNode(Parasitic *parasitic, virtual ParasiticNode *ensureParasiticNode(Parasitic *parasitic,
const Pin *pin) = 0; const Pin *pin,
const Network *network) = 0;
// Increment the grounded capacitance on node. // Increment the grounded capacitance on node.
virtual void incrCap(ParasiticNode *node, virtual void incrCap(ParasiticNode *node,
float cap, float cap) = 0;
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;
virtual const char *name(const ParasiticNode *node) = 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. // Find the parasitic node connected to pin.
virtual ParasiticNode *findNode(const Parasitic *parasitic, virtual ParasiticNode *findNode(const Parasitic *parasitic,
const Pin *pin) const = 0; const Pin *pin) const = 0;
// Node capacitance to ground. // Node capacitance to ground.
virtual float nodeGndCap(const ParasiticNode *node, virtual float nodeGndCap(const ParasiticNode *node) const = 0;
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;
// Return true if all loads are annoatated. // Coupling capacitor between parasitic nodes on a net.
virtual bool checkAnnotation(Parasitic *parasitic_network, virtual void makeCapacitor(Parasitic *parasitic,
const Pin *drvr_pin) = 0; size_t id,
virtual bool checkAnnotation(const Pin *drvr_pin, float cap,
ParasiticNode *drvr_node) = 0; ParasiticNode *node1,
// Return loads missing path from driver. ParasiticNode *node2) = 0;
virtual PinSet unannotatedLoads(Parasitic *parasitic_network, virtual size_t id(const ParasiticCapacitor *capacitor) const = 0;
const Pin *drvr_pin) = 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. // Reduce parasitic network to pi elmore model for drvr_pin.
virtual void reduceToPiElmore(const Parasitic *parasitic, Parasitic *reduceToPiElmore(const Parasitic *parasitic,
const Pin *drvr_pin, const Pin *drvr_pin,
const OperatingConditions *op_cond, const RiseFall *rf,
const Corner *corner, const Corner *corner,
const MinMax *cnst_min_max, const MinMax *cnst_min_max,
const ParasiticAnalysisPt *ap) = 0; const ParasiticAnalysisPt *ap);
// 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;
// Reduce parasitic network to pi and 2nd order pole/residue models // Reduce parasitic network to pi and 2nd order pole/residue models
// for drvr_pin. // for drvr_pin.
virtual void reduceToPiPoleResidue2(const Parasitic *parasitic, Parasitic *reduceToPiPoleResidue2(const Parasitic *parasitic,
const Pin *drvr_pin, const Pin *drvr_pin,
const OperatingConditions *op_cond, const RiseFall *rf,
const Corner *corner, const Corner *corner,
const MinMax *cnst_min_max, const MinMax *cnst_min_max,
const ParasiticAnalysisPt *ap) = 0; const ParasiticAnalysisPt *ap);
// Estimate parasitic as pi elmore using wireload model. // Estimate parasitic as pi elmore using wireload model.
virtual Parasitic *estimatePiElmore(const Pin *drvr_pin, Parasitic *estimatePiElmore(const Pin *drvr_pin,
const RiseFall *rf, const RiseFall *rf,
const Wireload *wireload, const Wireload *wireload,
float fanout, float fanout,
float net_pin_cap, float net_pin_cap,
const OperatingConditions *op_cond, const Corner *corner,
const Corner *corner, const MinMax *min_max);
const MinMax *min_max,
const ParasiticAnalysisPt *ap) = 0;
Parasitic *makeWireloadNetwork(const Pin *drvr_pin, Parasitic *makeWireloadNetwork(const Pin *drvr_pin,
const Wireload *wireload, const Wireload *wireload,
float fanout, float fanout,
const OperatingConditions *op_cond, const MinMax *min_max,
const ParasiticAnalysisPt *ap); const ParasiticAnalysisPt *ap);
// Network edit before/after methods. // 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; virtual void loadPinCapacitanceChanged(const Pin *pin) = 0;
protected: protected:
@ -296,20 +265,17 @@ protected:
const Pin *drvr_pin, const Pin *drvr_pin,
float wireload_cap, float wireload_cap,
float wireload_res, float wireload_res,
float fanout, float fanout);
const ParasiticAnalysisPt *ap);
void makeWireloadNetworkBest(Parasitic *parasitic, void makeWireloadNetworkBest(Parasitic *parasitic,
const Pin *drvr_pin, const Pin *drvr_pin,
float wireload_cap, float wireload_cap,
float wireload_res, float wireload_res,
float fanout, float fanout);
const ParasiticAnalysisPt *ap);
void makeWireloadNetworkBalanced(Parasitic *parasitic, void makeWireloadNetworkBalanced(Parasitic *parasitic,
const Pin *drvr_pin, const Pin *drvr_pin,
float wireload_cap, float wireload_cap,
float wireload_res, float wireload_res,
float fanout, float fanout);
const ParasiticAnalysisPt *ap);
const Net *findParasiticNet(const Pin *pin) const; const Net *findParasiticNet(const Pin *pin) const;
}; };
@ -320,19 +286,18 @@ class ParasiticAnalysisPt
public: public:
ParasiticAnalysisPt(const char *name, ParasiticAnalysisPt(const char *name,
int index, int index,
const MinMax *min_max); int index_max);
~ParasiticAnalysisPt(); const char *name() const { return name_.c_str(); }
const char *name() const { return name_; }
int index() const { return index_; } 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. // Coupling capacitor factor used by all reduction functions.
float couplingCapFactor() const { return coupling_cap_factor_; } float couplingCapFactor() const { return coupling_cap_factor_; }
void setCouplingCapFactor(float factor); void setCouplingCapFactor(float factor);
private: private:
const char *name_; string name_;
int index_; int index_;
const MinMax *min_max_; int index_max_;
float coupling_cap_factor_; float coupling_cap_factor_;
}; };

View File

@ -20,10 +20,9 @@ namespace sta {
class Parasitics; class Parasitics;
class Parasitic; class Parasitic;
class ParasiticDevice;
class ParasiticNode; class ParasiticNode;
class ParasiticAnalysisPt; class ParasiticAnalysisPt;
class ParasiticResistor;
enum class ReducedParasiticType { pi_elmore, pi_pole_residue2, arnoldi, none }; class ParasiticCapacitor;
} // namespace } // namespace

View File

@ -606,7 +606,6 @@ public:
// Pin capacitance derated by operating conditions and instance pvt. // Pin capacitance derated by operating conditions and instance pvt.
float pinCapacitance(const Pin *pin, float pinCapacitance(const Pin *pin,
const RiseFall *rf, const RiseFall *rf,
const OperatingConditions *op_cond,
const Corner *corner, const Corner *corner,
const MinMax *min_max); const MinMax *min_max);
void setResistance(const Net *net, void setResistance(const Net *net,
@ -825,7 +824,7 @@ public:
LogicValueMap &logicValues() { return logic_value_map_; } LogicValueMap &logicValues() { return logic_value_map_; }
LogicValueMap &caseLogicValues() { return case_value_map_; } LogicValueMap &caseLogicValues() { return case_value_map_; }
// Returns nullptr if set_operating_conditions has not been called. // 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. // Instance specific process/voltage/temperature.
const Pvt *pvt(const Instance *inst, const Pvt *pvt(const Instance *inst,
const MinMax *min_max) const; const MinMax *min_max) const;
@ -946,7 +945,6 @@ public:
// wire_cap = port external wire capacitance + net wire capacitance // wire_cap = port external wire capacitance + net wire capacitance
void connectedCap(const Pin *pin, void connectedCap(const Pin *pin,
const RiseFall *rf, const RiseFall *rf,
const OperatingConditions *op_cond,
const Corner *corner, const Corner *corner,
const MinMax *min_max, const MinMax *min_max,
float &pin_cap, float &pin_cap,
@ -1233,7 +1231,6 @@ protected:
ClockLatency *latency); ClockLatency *latency);
void pinCaps(const Pin *pin, void pinCaps(const Pin *pin,
const RiseFall *rf, const RiseFall *rf,
const OperatingConditions *op_cond,
const Corner *corner, const Corner *corner,
const MinMax *min_max, const MinMax *min_max,
float &pin_cap, float &pin_cap,
@ -1241,7 +1238,6 @@ protected:
float &fanout) const; float &fanout) const;
void netCaps(const Pin *drvr_pin, void netCaps(const Pin *drvr_pin,
const RiseFall *rf, const RiseFall *rf,
const OperatingConditions *op_cond,
const Corner *corner, const Corner *corner,
const MinMax *min_max, const MinMax *min_max,
// Return values. // Return values.
@ -1252,12 +1248,10 @@ protected:
// connectedCap pin_cap. // connectedCap pin_cap.
float connectedPinCap(const Pin *pin, float connectedPinCap(const Pin *pin,
const RiseFall *rf, const RiseFall *rf,
const OperatingConditions *op_cond,
const Corner *corner, const Corner *corner,
const MinMax *min_max); const MinMax *min_max);
float portCapacitance(Instance *inst, LibertyPort *port, float portCapacitance(Instance *inst, LibertyPort *port,
const RiseFall *rf, const RiseFall *rf,
const OperatingConditions *op_cond,
const Corner *corner, const Corner *corner,
const MinMax *min_max) const; const MinMax *min_max) const;
void removeClockGroups(ClockGroups *groups); void removeClockGroups(ClockGroups *groups);

View File

@ -1111,13 +1111,10 @@ public:
InstanceSeq slowDrivers(int count); InstanceSeq slowDrivers(int count);
// Make parasitic analysis points. // Make parasitic analysis points.
// per_corner per_min_max ap_count // per_corner ap_count
// false false 1 // false 2
// false true 2 // true corners*2
// true false corners void setParasiticAnalysisPts(bool per_corner);
// true true corners*2
void setParasiticAnalysisPts(bool per_corner,
bool per_min_max);
// Annotate hierarchical "instance" with parasitics. // Annotate hierarchical "instance" with parasitics.
// The parasitic analysis point is ap_name. // The parasitic analysis point is ap_name.
// The parasitic memory footprint is much smaller if parasitic // The parasitic memory footprint is much smaller if parasitic
@ -1131,9 +1128,7 @@ public:
bool pin_cap_included, bool pin_cap_included,
bool keep_coupling_caps, bool keep_coupling_caps,
float coupling_cap_factor, float coupling_cap_factor,
ReducedParasiticType reduce_to, bool reduce);
bool delete_after_reduce,
bool quiet);
void reportParasiticAnnotation(bool report_unannotated, void reportParasiticAnnotation(bool report_unannotated,
const Corner *corner); const Corner *corner);
// Parasitics. // Parasitics.

File diff suppressed because it is too large Load Diff

View File

@ -21,203 +21,148 @@
#include "Map.hh" #include "Map.hh"
#include "Set.hh" #include "Set.hh"
#include "MinMax.hh" #include "MinMax.hh"
#include "EstimateParasitics.hh"
#include "Parasitics.hh" #include "Parasitics.hh"
namespace sta { namespace sta {
class ConcreteParasitic; class ConcreteParasitic;
class ConcretePiElmore;
class ConcretePiPoleResidue;
class ConcreteParasiticNetwork; class ConcreteParasiticNetwork;
class ConcreteParasiticNode;
class ConcreteParasiticDevice;
typedef Map<const Pin*, ConcreteParasitic**> ConcreteParasiticMap; typedef Map<const Pin*, ConcreteParasitic**> ConcreteParasiticMap;
typedef Map<const Net*, ConcreteParasiticNetwork**> ConcreteParasiticNetworkMap; typedef Map<const Net*, ConcreteParasiticNetwork**> ConcreteParasiticNetworkMap;
typedef Set<ParasiticNode*> ParasiticNodeSet;
typedef Set<ParasiticDevice*> ParasiticDeviceSet;
// This class acts as a BUILDER for all parasitics. // This class acts as a BUILDER for parasitics.
class ConcreteParasitics : public Parasitics, public EstimateParasitics class ConcreteParasitics : public Parasitics
{ {
public: public:
ConcreteParasitics(StaState *sta); ConcreteParasitics(StaState *sta);
virtual ~ConcreteParasitics(); virtual ~ConcreteParasitics();
virtual bool haveParasitics(); bool haveParasitics() override;
virtual void clear(); void clear() override;
virtual void save(); void deleteParasitics() override;
virtual void deleteParasitics(); void deleteParasitics(const Net *net,
virtual void deleteParasitics(const Net *net, const ParasiticAnalysisPt *ap) override;
const ParasiticAnalysisPt *ap); void deleteParasitics(const Pin *drvr_pin,
virtual void deleteParasitics(const Pin *drvr_pin, const ParasiticAnalysisPt *ap) override;
const ParasiticAnalysisPt *ap);
virtual void deleteUnsavedParasitic(Parasitic *parasitic);
virtual bool isReducedParasiticNetwork(const Parasitic *parasitic) const; bool isReducedParasiticNetwork(const Parasitic *parasitic) const override;
virtual void setIsReducedParasiticNetwork(Parasitic *parasitic, void setIsReducedParasiticNetwork(Parasitic *parasitic,
bool is_reduced); 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; bool isPiElmore(const Parasitic *parasitic) const override;
virtual Parasitic *findPiElmore(const Pin *drvr_pin, Parasitic *findPiElmore(const Pin *drvr_pin,
const RiseFall *rf, const RiseFall *rf,
const ParasiticAnalysisPt *ap) const; const ParasiticAnalysisPt *ap) const override;
virtual Parasitic *makePiElmore(const Pin *drvr_pin, Parasitic *makePiElmore(const Pin *drvr_pin,
const RiseFall *rf, const RiseFall *rf,
const ParasiticAnalysisPt *ap, 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,
float c2, float c2,
float rpi, float rpi,
float c1); float c1) override;
virtual void findElmore(const Parasitic *parasitic, bool isPiModel(const Parasitic *parasitic) const override;
const Pin *load_pin, void piModel(const Parasitic *parasitic,
float &elmore, float &c2,
bool &exists) const; float &rpi,
virtual void setElmore(Parasitic *parasitic, float &c1) const override;
const Pin *load_pin, void setPiModel(Parasitic *parasitic,
float elmore); float c2,
float rpi,
float c1) override;
virtual bool isPiPoleResidue(const Parasitic* parasitic) const; void findElmore(const Parasitic *parasitic,
virtual Parasitic *findPiPoleResidue(const Pin *drvr_pin, const Pin *load_pin,
const RiseFall *rf, float &elmore,
const ParasiticAnalysisPt *ap) const; bool &exists) const override;
virtual Parasitic *findPoleResidue(const Parasitic *parasitic, void setElmore(Parasitic *parasitic,
const Pin *load_pin) const; const Pin *load_pin,
virtual Parasitic *makePiPoleResidue(const Pin *drvr_pin, float elmore) override;
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;
virtual bool isParasiticNetwork(const Parasitic *parasitic) const; bool isPiPoleResidue(const Parasitic* parasitic) const override;
virtual Parasitic *findParasiticNetwork(const Net *net, Parasitic *findPiPoleResidue(const Pin *drvr_pin,
const ParasiticAnalysisPt *ap) const; const RiseFall *rf,
virtual Parasitic *findParasiticNetwork(const Pin *pin, const ParasiticAnalysisPt *ap) const override;
const ParasiticAnalysisPt *ap) const; Parasitic *findPoleResidue(const Parasitic *parasitic,
virtual Parasitic *makeParasiticNetwork(const Net *net, const Pin *load_pin) const override;
bool includes_pin_caps, Parasitic *makePiPoleResidue(const Pin *drvr_pin,
const ParasiticAnalysisPt *ap); const RiseFall *rf,
virtual void deleteParasiticNetwork(const Net *net, const ParasiticAnalysisPt *ap,
const ParasiticAnalysisPt *ap); float c2, float rpi, float c1) override;
virtual void deleteParasiticNetworks(const Net *net); void setPoleResidue(Parasitic *parasitic, const Pin *load_pin,
virtual bool includesPinCaps(const Parasitic *parasitic) const; ComplexFloatSeq *poles,
virtual ParasiticNode *ensureParasiticNode(Parasitic *parasitic, ComplexFloatSeq *residues) override;
const Net *net, bool isPoleResidue(const Parasitic* parasitic) const override;
int id); size_t poleResidueCount(const Parasitic *parasitic) const override;
virtual ParasiticNode *ensureParasiticNode(Parasitic *parasitic, void poleResidue(const Parasitic *parasitic,
const Pin *pin); int pole_index,
virtual void incrCap(ParasiticNode *node, float cap, ComplexFloat &pole,
const ParasiticAnalysisPt *ap); ComplexFloat &residue) const override;
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);
virtual const char *name(const ParasiticNode *node); bool isParasiticNetwork(const Parasitic *parasitic) const override;
virtual const Pin *connectionPin(const ParasiticNode *node) const; Parasitic *findParasiticNetwork(const Net *net,
virtual ParasiticNode *findNode(const Parasitic *parasitic, const ParasiticAnalysisPt *ap) const override;
const Pin *pin) const; Parasitic *findParasiticNetwork(const Pin *pin,
virtual float nodeGndCap(const ParasiticNode *node, const ParasiticAnalysisPt *ap) const override;
const ParasiticAnalysisPt *ap) const; Parasitic *makeParasiticNetwork(const Net *net,
virtual ParasiticDeviceIterator * bool includes_pin_caps,
deviceIterator(ParasiticNode *node) const; const ParasiticAnalysisPt *ap) override;
virtual bool isResistor(const ParasiticDevice *device) const; void deleteParasiticNetwork(const Net *net,
virtual bool isCouplingCap(const ParasiticDevice *device) const; const ParasiticAnalysisPt *ap) override;
virtual const char *name(const ParasiticDevice *device) const; void deleteParasiticNetworks(const Net *net) override;
virtual float value(const ParasiticDevice *device, bool includesPinCaps(const Parasitic *parasitic) const override;
const ParasiticAnalysisPt *ap) const; ParasiticNode *ensureParasiticNode(Parasitic *parasitic,
virtual ParasiticNode *node1(const ParasiticDevice *device) const; const Net *net,
virtual ParasiticNode *node2(const ParasiticDevice *device) const; int id,
virtual ParasiticNode *otherNode(const ParasiticDevice *device, const Network *network) override;
ParasiticNode *node) const; 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. ParasiticResistorSeq resistors(const Parasitic *parasitic) const override;
virtual bool checkAnnotation(Parasitic *parasitic_network, void makeResistor(Parasitic *parasitic,
const Pin *drvr_pin); size_t id,
virtual bool checkAnnotation(const Pin *drvr_pin, float res,
ParasiticNode *drvr_node); ParasiticNode *node1,
// Return loads missing path from driver. ParasiticNode *node2) override;
virtual PinSet unannotatedLoads(Parasitic *parasitic_network, size_t id(const ParasiticResistor *resistor) const override;
const Pin *drvr_pin); 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, PinSet unannotatedLoads(const Parasitic *parasitic,
const RiseFall *rf, const Pin *drvr_pin) const override;
const Wireload *wireload,
float fanout, void disconnectPinBefore(const Pin *pin,
float net_pin_cap, const Network *network) override;
const OperatingConditions *op_cond, void loadPinCapacitanceChanged(const Pin *pin) override;
const Corner *corner,
const MinMax *min_max,
const ParasiticAnalysisPt *ap);
virtual void disconnectPinBefore(const Pin *pin);
virtual void loadPinCapacitanceChanged(const Pin *pin);
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, void deleteReducedParasitics(const Net *net,
const ParasiticAnalysisPt *ap); const ParasiticAnalysisPt *ap) override;
virtual void deleteDrvrReducedParasitics(const Pin *drvr_pin); void deleteDrvrReducedParasitics(const Pin *drvr_pin) override;
protected: protected:
int parasiticAnalysisPtIndex(const ParasiticAnalysisPt *ap, int parasiticAnalysisPtIndex(const ParasiticAnalysisPt *ap,
@ -227,14 +172,6 @@ protected:
void deleteReducedParasitics(const Pin *pin); void deleteReducedParasitics(const Pin *pin);
void deleteDrvrReducedParasitics(const Pin *drvr_pin, void deleteDrvrReducedParasitics(const Pin *drvr_pin,
const ParasiticAnalysisPt *ap); 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 // Driver pin to array of parasitics indexed by analysis pt index
// and transition. // and transition.
@ -242,10 +179,8 @@ protected:
ConcreteParasiticNetworkMap parasitic_network_map_; ConcreteParasiticNetworkMap parasitic_network_map_;
mutable std::mutex lock_; mutable std::mutex lock_;
using EstimateParasitics::estimatePiElmore;
friend class ConcretePiElmore; friend class ConcretePiElmore;
friend class ConcreteParasiticNode; friend class ConcreteParasiticNode;
friend class ConcreteParasiticResistor;
friend class ConcreteParasiticNetwork; friend class ConcreteParasiticNetwork;
}; };

View File

@ -16,38 +16,38 @@
#pragma once #pragma once
#include <map>
#include <set>
#include "Parasitics.hh" #include "Parasitics.hh"
namespace sta { namespace sta {
class ConcretePoleResidue; class ConcretePoleResidue;
class ConcreteParasiticDevice; class ConcreteParasiticDevice;
class ConcreteParasiticPinNode;
class ConcreteParasiticSubNode;
class ConcreteParasiticNode; class ConcreteParasiticNode;
typedef Map<const Pin*, float> ConcreteElmoreLoadMap; typedef std::map<const Pin*, float> ConcreteElmoreLoadMap;
typedef ConcreteElmoreLoadMap::Iterator ConcretePiElmoreLoadIterator; typedef std::map<const Pin*, ConcretePoleResidue> ConcretePoleResidueMap;
typedef Map<const Pin*, ConcretePoleResidue*> ConcretePoleResidueMap;
typedef std::pair<const Net*, int> NetIdPair; typedef std::pair<const Net*, int> NetIdPair;
struct NetIdPairLess struct NetIdPairLess
{ {
bool operator()(const NetIdPair *net_id1, bool operator()(const NetIdPair &net_id1,
const NetIdPair *net_id2) const; const NetIdPair &net_id2) const;
}; };
typedef Map<NetIdPair*, ConcreteParasiticSubNode*, typedef std::map<NetIdPair,ConcreteParasiticNode*,
NetIdPairLess > ConcreteParasiticSubNodeMap; NetIdPairLess> ConcreteParasiticSubNodeMap;
typedef Map<const Pin*, typedef std::map<const Pin*, ConcreteParasiticNode*> ConcreteParasiticPinNodeMap;
ConcreteParasiticPinNode*> ConcreteParasiticPinNodeMap; typedef std::set<ParasiticNode*> ParasiticNodeSet;
typedef Vector<ConcreteParasiticDevice*> ConcreteParasiticDeviceSeq; typedef std::set<ParasiticResistor*> ParasiticResistorSet;
typedef Set<ConcreteParasiticDevice*> ConcreteParasiticDeviceSet; typedef std::vector<ParasiticResistor*> ParasiticResistorSeq;
typedef Vector<ConcreteParasiticNode*> ConcreteParasiticNodeSeq;
// Empty base class definitions so casts are not required on returned // Empty base class definitions so casts are not required on returned
// objects. // objects.
class Parasitic {}; class Parasitic {};
class ParasiticNode {}; class ParasiticNode {};
class ParasiticDevice {}; class ParasiticResistor {};
class ParasiticCapacitor {};
class ParasiticNetwork {}; class ParasiticNetwork {};
// Base class for parasitics. // Base class for parasitics.
@ -78,8 +78,8 @@ public:
virtual void setPoleResidue(const Pin *load_pin, virtual void setPoleResidue(const Pin *load_pin,
ComplexFloatSeq *poles, ComplexFloatSeq *poles,
ComplexFloatSeq *residues); ComplexFloatSeq *residues);
virtual ParasiticDeviceIterator *deviceIterator() const; virtual PinSet unannotatedLoads(const Pin *drvr_pin,
virtual ParasiticNodeIterator *nodeIterator() const; const Parasitics *parasitics) const = 0;
}; };
// Pi model for a driver pin. // Pi model for a driver pin.
@ -114,70 +114,46 @@ public:
ConcretePiElmore(float c2, ConcretePiElmore(float c2,
float rpi, float rpi,
float c1); float c1);
virtual ~ConcretePiElmore(); bool isPiElmore() const override { return true; }
virtual bool isPiElmore() const { return true; } bool isPiModel() const override { return true; }
virtual bool isPiModel() const { return true; } float capacitance() const override;
virtual float capacitance() const; void piModel(float &c2,
virtual void piModel(float &c2, float &rpi, float &c1) const; float &rpi,
virtual void setPiModel(float c2, float rpi, float c1); float &c1) const override;
virtual bool isReducedParasiticNetwork() const; void setPiModel(float c2,
virtual void setIsReduced(bool reduced); float rpi,
virtual void findElmore(const Pin *load_pin, float &elmore, float c1) override;
bool &exists) const; bool isReducedParasiticNetwork() const override;
virtual void setElmore(const Pin *load_pin, float elmore); 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); void deleteLoad(const Pin *load_pin);
private: private:
ConcreteElmoreLoadMap *loads_; 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_;
}; };
class ConcretePoleResidue : public ConcreteParasitic class ConcretePoleResidue : public ConcreteParasitic
{ {
public: public:
ConcretePoleResidue(ComplexFloatSeq *poles, ConcretePoleResidue();
ComplexFloatSeq *residues);
virtual ~ConcretePoleResidue(); virtual ~ConcretePoleResidue();
virtual bool isPoleResidue() const { return true; } virtual bool isPoleResidue() const override { return true; }
size_t poleResidueCount() const; float capacitance() const override { return 0.0; }
void poleResidue(int index, ComplexFloat &pole, ComplexFloat &residue) const; PinSet unannotatedLoads(const Pin *drvr_pin,
void setPoleResidue(ComplexFloatSeq *poles, ComplexFloatSeq *residues); const Parasitics *parasitics) const override;
float capacitance() const { return 0.0; }
void setPoleResidue(ComplexFloatSeq *poles,
ComplexFloatSeq *residues);
void poleResidue(int index,
ComplexFloat &pole,
ComplexFloat &residue) const;
size_t poleResidueCount() const;
using ConcreteParasitic::setPoleResidue; using ConcreteParasitic::setPoleResidue;
private: private:
@ -193,240 +169,147 @@ public:
ConcretePiPoleResidue(float c2, ConcretePiPoleResidue(float c2,
float rpi, float rpi,
float c1); float c1);
virtual ~ConcretePiPoleResidue(); virtual bool isPiPoleResidue() const override { return true; }
virtual bool isPiPoleResidue() const { return true; } virtual bool isPiModel() const override { return true; }
virtual bool isPiModel() const { return true; } virtual float capacitance() const override;
virtual float capacitance() const;
virtual void piModel(float &c2, virtual void piModel(float &c2,
float &rpi, float &rpi,
float &c1) const; float &c1) const override;
virtual void setPiModel(float c2, virtual void setPiModel(float c2,
float rpi, float rpi,
float c1); float c1) override;
virtual bool isReducedParasiticNetwork() const; virtual bool isReducedParasiticNetwork() const override;
virtual void setIsReduced(bool reduced); virtual void setIsReduced(bool reduced) override;
virtual Parasitic *findPoleResidue(const Pin *load_pin) const; virtual Parasitic *findPoleResidue(const Pin *load_pin) const override;
virtual void setPoleResidue(const Pin *load_pin, virtual void setPoleResidue(const Pin *load_pin,
ComplexFloatSeq *poles, 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); void deleteLoad(const Pin *load_pin);
private: private:
ConcretePoleResidueMap *load_pole_residue_; 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_;
}; };
class ConcreteParasiticNetwork : public ParasiticNetwork, class ConcreteParasiticNetwork : public ParasiticNetwork,
public ConcreteParasitic public ConcreteParasitic
{ {
public: public:
ConcreteParasiticNetwork(bool includes_pin_caps); ConcreteParasiticNetwork(const Net *net,
bool includes_pin_caps);
virtual ~ConcreteParasiticNetwork(); virtual ~ConcreteParasiticNetwork();
virtual bool isParasiticNetwork() const { return true; } virtual bool isParasiticNetwork() const { return true; }
const Net *net() { return net_; }
bool includesPinCaps() const { return includes_pin_caps_; } bool includesPinCaps() const { return includes_pin_caps_; }
ConcreteParasiticNode *ensureParasiticNode(const Net *net, 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 *findNode(const Pin *pin) const;
ConcreteParasiticNode *ensureParasiticNode(const Pin *pin);
virtual float capacitance() const; virtual float capacitance() const;
ConcreteParasiticPinNodeMap *pinNodes() { return &pin_nodes_; } ParasiticNodeSeq nodes() const;
ConcreteParasiticSubNodeMap *subNodes() { return &sub_nodes_; }
void disconnectPin(const Pin *pin, void disconnectPin(const Pin *pin,
const Net *net); const Net *net,
virtual ParasiticDeviceIterator *deviceIterator() const; const Network *network);
virtual ParasiticNodeIterator *nodeIterator() const; ParasiticResistorSeq resistors() const { return resistors_; }
virtual void devices(// Return value. void addResistor(ParasiticResistor *resistor);
ConcreteParasiticDeviceSet *devices) const; ParasiticCapacitorSeq capacitors() const { return capacitors_; }
void addCapacitor(ParasiticCapacitor *capacitor);
virtual PinSet unannotatedLoads(const Pin *drvr_pin,
const Parasitics *parasitics) const;
private: 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 deleteNodes();
void deleteDevices(); void deleteDevices();
const Net *net_;
ConcreteParasiticSubNodeMap sub_nodes_; ConcreteParasiticSubNodeMap sub_nodes_;
ConcreteParasiticPinNodeMap pin_nodes_; ConcreteParasiticPinNodeMap pin_nodes_;
ParasiticResistorSeq resistors_;
ParasiticCapacitorSeq capacitors_;
unsigned max_node_id_:31; unsigned max_node_id_:31;
bool includes_pin_caps_:1; 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 } // namespace

View File

@ -24,6 +24,11 @@
namespace sta { namespace sta {
EstimateParasitics::EstimateParasitics(StaState *sta) :
StaState(sta)
{
}
// For multiple driver nets, output pin capacitances are treated as // For multiple driver nets, output pin capacitances are treated as
// loads when driven by a different pin. // loads when driven by a different pin.
void void
@ -32,10 +37,8 @@ EstimateParasitics::estimatePiElmore(const Pin *drvr_pin,
const Wireload *wireload, const Wireload *wireload,
float fanout, float fanout,
float net_pin_cap, float net_pin_cap,
const OperatingConditions *op_cond,
const Corner *corner, const Corner *corner,
const MinMax *min_max, const MinMax *min_max,
const StaState *sta,
float &c2, float &c2,
float &rpi, float &rpi,
float &c1, float &c1,
@ -43,6 +46,7 @@ EstimateParasitics::estimatePiElmore(const Pin *drvr_pin,
float &elmore_cap, float &elmore_cap,
bool &elmore_use_load_cap) bool &elmore_use_load_cap)
{ {
const OperatingConditions *op_cond = sdc_->operatingConditions(min_max);
float wireload_cap, wireload_res; float wireload_cap, wireload_res;
wireload->findWireload(fanout, op_cond, 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) { switch (tree) {
case WireloadTree::worst_case: case WireloadTree::worst_case:
estimatePiElmoreWorst(drvr_pin, wireload_cap, wireload_res, estimatePiElmoreWorst(drvr_pin, wireload_cap, wireload_res,
fanout, net_pin_cap, rf, op_cond, corner, fanout, net_pin_cap, rf, corner, min_max,
min_max, sta,
c2, rpi, c1, elmore_res, c2, rpi, c1, elmore_res,
elmore_cap, elmore_use_load_cap); elmore_cap, elmore_use_load_cap);
break; break;
case WireloadTree::balanced: case WireloadTree::balanced:
case WireloadTree::unknown: case WireloadTree::unknown:
estimatePiElmoreBalanced(drvr_pin, wireload_cap, wireload_res, estimatePiElmoreBalanced(drvr_pin, wireload_cap, wireload_res,
fanout, net_pin_cap, rf, op_cond, fanout, net_pin_cap, rf, corner, min_max,
corner, min_max,sta,
c2, rpi, c1, elmore_res, c2, rpi, c1, elmore_res,
elmore_cap, elmore_use_load_cap); elmore_cap, elmore_use_load_cap);
break; break;
case WireloadTree::best_case: case WireloadTree::best_case:
estimatePiElmoreBest(drvr_pin, wireload_cap, net_pin_cap, rf, estimatePiElmoreBest(drvr_pin, wireload_cap, net_pin_cap,
op_cond, corner, min_max, rf, corner, min_max,
c2, rpi, c1, elmore_res, elmore_cap, c2, rpi, c1, elmore_res, elmore_cap,
elmore_use_load_cap); elmore_use_load_cap);
break; break;
@ -80,7 +82,6 @@ EstimateParasitics::estimatePiElmoreBest(const Pin *,
float wireload_cap, float wireload_cap,
float net_pin_cap, float net_pin_cap,
const RiseFall *, const RiseFall *,
const OperatingConditions *,
const Corner *, const Corner *,
const MinMax *, const MinMax *,
float &c2, float &c2,
@ -107,10 +108,8 @@ EstimateParasitics::estimatePiElmoreWorst(const Pin *drvr_pin,
float, float,
float net_pin_cap, float net_pin_cap,
const RiseFall *rf, const RiseFall *rf,
const OperatingConditions *op_cond,
const Corner *corner, const Corner *corner,
const MinMax *min_max, const MinMax *min_max,
const StaState *sta,
float &c2, float &c2,
float &rpi, float &rpi,
float &c1, float &c1,
@ -118,9 +117,8 @@ EstimateParasitics::estimatePiElmoreWorst(const Pin *drvr_pin,
float &elmore_cap, float &elmore_cap,
bool &elmore_use_load_cap) bool &elmore_use_load_cap)
{ {
Sdc *sdc = sta->sdc();
float drvr_pin_cap = 0.0; 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; c2 = drvr_pin_cap;
rpi = wireload_res; rpi = wireload_res;
c1 = net_pin_cap - drvr_pin_cap + wireload_cap; c1 = net_pin_cap - drvr_pin_cap + wireload_cap;
@ -139,10 +137,8 @@ EstimateParasitics::estimatePiElmoreBalanced(const Pin *drvr_pin,
float fanout, float fanout,
float net_pin_cap, float net_pin_cap,
const RiseFall *rf, const RiseFall *rf,
const OperatingConditions *op_cond,
const Corner *corner, const Corner *corner,
const MinMax *min_max, const MinMax *min_max,
const StaState *sta,
float &c2, float &c2,
float &rpi, float &rpi,
float &c1, float &c1,
@ -161,31 +157,27 @@ EstimateParasitics::estimatePiElmoreBalanced(const Pin *drvr_pin,
elmore_use_load_cap = false; elmore_use_load_cap = false;
} }
else { else {
Sdc *sdc = sta->sdc();
Network *network = sta->network();
Report *report = sta->report();
double res_fanout = wireload_res / fanout; double res_fanout = wireload_res / fanout;
double cap_fanout = wireload_cap / fanout; double cap_fanout = wireload_cap / fanout;
// Find admittance moments. // Find admittance moments.
double y1 = 0.0; double y1 = 0.0;
double y2 = 0.0; double y2 = 0.0;
double y3 = 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 = PinConnectedPinIterator *load_iter =
network->connectedPinIterator(drvr_pin); network_->connectedPinIterator(drvr_pin);
while (load_iter->hasNext()) { while (load_iter->hasNext()) {
const Pin *load_pin = load_iter->next(); const Pin *load_pin = load_iter->next();
// Bidirects don't count themselves as loads. // Bidirects don't count themselves as loads.
if (load_pin != drvr_pin && network->isLoad(load_pin)) { if (load_pin != drvr_pin && network_->isLoad(load_pin)) {
Port *port = network->port(load_pin); Port *port = network_->port(load_pin);
double load_cap = 0.0; double load_cap = 0.0;
if (network->isLeaf(load_pin)) if (network_->isLeaf(load_pin))
load_cap = sdc->pinCapacitance(load_pin, rf, op_cond, load_cap = sdc_->pinCapacitance(load_pin, rf, corner, min_max);
corner, min_max); else if (network_->isTopLevelPort(load_pin))
else if (network->isTopLevelPort(load_pin)) load_cap = sdc_->portExtCap(port, rf, corner, min_max);
load_cap = sdc->portExtCap(port, rf, corner, min_max);
else 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 cap = load_cap + cap_fanout;
double y2_ = res_fanout * cap * cap; double y2_ = res_fanout * cap * cap;
y1 += cap; y1 += cap;

View File

@ -16,6 +16,7 @@
#pragma once #pragma once
#include "StaState.hh"
#include "LibertyClass.hh" #include "LibertyClass.hh"
#include "NetworkClass.hh" #include "NetworkClass.hh"
#include "SdcClass.hh" #include "SdcClass.hh"
@ -26,21 +27,18 @@ namespace sta {
class Corner; class Corner;
class StaState; class StaState;
class EstimateParasitics class EstimateParasitics : public StaState
{ {
public: public:
EstimateParasitics(StaState *sta);
protected:
// Helper function for wireload estimation. // Helper function for wireload estimation.
void estimatePiElmore(const Pin *drvr_pin, void estimatePiElmore(const Pin *drvr_pin,
const RiseFall *rf, const RiseFall *rf,
const Wireload *wireload, const Wireload *wireload,
float fanout, float fanout,
float net_pin_cap, float net_pin_cap,
const OperatingConditions *op_cond,
const Corner *corner, const Corner *corner,
const MinMax *min_max, const MinMax *min_max,
const StaState *sta,
// Return values. // Return values.
float &c2, float &c2,
float &rpi, float &rpi,
@ -48,11 +46,12 @@ protected:
float &elmore_res, float &elmore_res,
float &elmore_cap, float &elmore_cap,
bool &elmore_use_load_cap); bool &elmore_use_load_cap);
protected:
void estimatePiElmoreBest(const Pin *drvr_pin, void estimatePiElmoreBest(const Pin *drvr_pin,
float net_pin_cap, float net_pin_cap,
float wireload_cap, float wireload_cap,
const RiseFall *rf, const RiseFall *rf,
const OperatingConditions *op_cond,
const Corner *corner, const Corner *corner,
const MinMax *min_max, const MinMax *min_max,
// Return values. // Return values.
@ -68,10 +67,8 @@ protected:
float fanout, float fanout,
float net_pin_cap, float net_pin_cap,
const RiseFall *rf, const RiseFall *rf,
const OperatingConditions *op_cond,
const Corner *corner, const Corner *corner,
const MinMax *min_max, const MinMax *min_max,
const StaState *sta,
// Return values. // Return values.
float &c2, float &rpi, float &c1, float &c2, float &rpi, float &c1,
float &elmore_res, float &elmore_cap, float &elmore_res, float &elmore_cap,
@ -82,10 +79,8 @@ protected:
float fanout, float fanout,
float net_pin_cap, float net_pin_cap,
const RiseFall *rf, const RiseFall *rf,
const OperatingConditions *op_cond,
const Corner *corner, const Corner *corner,
const MinMax *min_max, const MinMax *min_max,
const StaState *sta,
// Return values. // Return values.
float &c2, float &rpi, float &c1, float &c2, float &rpi, float &c1,
float &elmore_res, float &elmore_cap, float &elmore_res, float &elmore_cap,

View File

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

View File

@ -23,7 +23,9 @@
#include "Network.hh" #include "Network.hh"
#include "PortDirection.hh" #include "PortDirection.hh"
#include "Sdc.hh" #include "Sdc.hh"
#include "Corner.hh"
#include "ReduceParasitics.hh" #include "ReduceParasitics.hh"
#include "EstimateParasitics.hh"
namespace sta { namespace sta {
@ -51,28 +53,138 @@ Parasitics::findParasiticNet(const Pin *pin) const
return nullptr; return nullptr;
} }
void PinSet
Parasitics::check(Parasitic *) const Parasitics::loads(const Pin *drvr_pin) const
{ {
#if 0 PinSet loads(network_);
ConcreteParasiticSubNodeMap::Iterator sub_node_iter(sub_nodes_); NetConnectedPinIterator *pin_iter = network_->connectedPinIterator(drvr_pin);
while (sub_node_iter.hasNext()) { while (pin_iter->hasNext()) {
ConcreteParasiticSubNode *node = sub_node_iter.next(); const Pin *pin = pin_iter->next();
ConcreteParasiticDeviceSeq::Iterator device_iter(node->devices()); if (network_->isLoad(pin) && !network_->isHierarchical(pin))
int res_count = 0; loads.insert(pin);
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));
} }
#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, Parasitics::makeWireloadNetwork(const Pin *drvr_pin,
const Wireload *wireload, const Wireload *wireload,
float fanout, float fanout,
const OperatingConditions *op_cond, const MinMax *min_max,
const ParasiticAnalysisPt *ap) const ParasiticAnalysisPt *ap)
{ {
Net *net = network_->net(drvr_pin); Net *net = network_->net(drvr_pin);
Parasitic *parasitic = makeParasiticNetwork(net, false, ap); Parasitic *parasitic = makeParasiticNetwork(net, false, ap);
const OperatingConditions *op_cond = sdc_->operatingConditions(min_max);
float wireload_cap, wireload_res; float wireload_cap, wireload_res;
wireload->findWireload(fanout, op_cond, 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) { switch (tree) {
case WireloadTree::worst_case: case WireloadTree::worst_case:
makeWireloadNetworkWorst(parasitic, drvr_pin, wireload_cap, makeWireloadNetworkWorst(parasitic, drvr_pin, wireload_cap,
wireload_res, fanout, ap); wireload_res, fanout);
break; break;
case WireloadTree::balanced: case WireloadTree::balanced:
makeWireloadNetworkBalanced(parasitic, drvr_pin, wireload_cap, makeWireloadNetworkBalanced(parasitic, drvr_pin, wireload_cap,
wireload_res, fanout, ap); wireload_res, fanout);
break; break;
case WireloadTree::best_case: case WireloadTree::best_case:
case WireloadTree::unknown: case WireloadTree::unknown:
makeWireloadNetworkBest(parasitic, drvr_pin, wireload_cap, makeWireloadNetworkBest(parasitic, drvr_pin, wireload_cap,
wireload_res, fanout, ap); wireload_res, fanout);
break; break;
} }
return parasitic; return parasitic;
@ -117,22 +230,22 @@ Parasitics::makeWireloadNetworkWorst(Parasitic *parasitic,
const Pin *drvr_pin, const Pin *drvr_pin,
float wireload_cap, float wireload_cap,
float wireload_res, float wireload_res,
float /* fanout */, float /* fanout */)
const ParasiticAnalysisPt *ap)
{ {
ParasiticNode *drvr_node = ensureParasiticNode(parasitic, drvr_pin); ParasiticNode *drvr_node = ensureParasiticNode(parasitic, drvr_pin, network_);
Net *net = network_->net(drvr_pin); Net *net = network_->net(drvr_pin);
ParasiticNode *load_node = ensureParasiticNode(parasitic, net, 0); size_t resistor_index = 1;
makeResistor(nullptr, drvr_node, load_node, wireload_res, ap); ParasiticNode *load_node = ensureParasiticNode(parasitic, net, 0, network_);
parasitics_->incrCap(load_node, wireload_cap, ap); makeResistor(parasitic, resistor_index++, wireload_res, drvr_node, load_node);
parasitics_->incrCap(load_node, wireload_cap);
PinConnectedPinIterator *load_iter = PinConnectedPinIterator *load_iter =
network_->connectedPinIterator(drvr_pin); network_->connectedPinIterator(drvr_pin);
while (load_iter->hasNext()) { while (load_iter->hasNext()) {
const Pin *load_pin = load_iter->next(); const Pin *load_pin = load_iter->next();
if (load_pin != drvr_pin if (load_pin != drvr_pin
&& network_->isLoad(load_pin)) { && network_->isLoad(load_pin)) {
ParasiticNode *load_node1 = ensureParasiticNode(parasitic, load_pin); ParasiticNode *load_node1 = ensureParasiticNode(parasitic, load_pin, network_);
makeResistor(nullptr, load_node, load_node1, 0.0, ap); makeResistor(parasitic, resistor_index++, 0.0, load_node, load_node1);
} }
} }
} }
@ -143,19 +256,19 @@ Parasitics::makeWireloadNetworkBest(Parasitic *parasitic,
const Pin *drvr_pin, const Pin *drvr_pin,
float wireload_cap, float wireload_cap,
float /* wireload_res */, float /* wireload_res */,
float /* fanout */, float /* fanout */)
const ParasiticAnalysisPt *ap)
{ {
ParasiticNode *drvr_node = ensureParasiticNode(parasitic, drvr_pin); ParasiticNode *drvr_node = ensureParasiticNode(parasitic, drvr_pin, network_);
parasitics_->incrCap(drvr_node, wireload_cap, ap); parasitics_->incrCap(drvr_node, wireload_cap);
PinConnectedPinIterator *load_iter = PinConnectedPinIterator *load_iter =
network_->connectedPinIterator(drvr_pin); network_->connectedPinIterator(drvr_pin);
size_t resistor_index = 1;
while (load_iter->hasNext()) { while (load_iter->hasNext()) {
const Pin *load_pin = load_iter->next(); const Pin *load_pin = load_iter->next();
if (load_pin != drvr_pin if (load_pin != drvr_pin
&& network_->isLoad(load_pin)) { && network_->isLoad(load_pin)) {
ParasiticNode *load_node1 = ensureParasiticNode(parasitic, load_pin); ParasiticNode *load_node1 = ensureParasiticNode(parasitic, load_pin, network_);
makeResistor(nullptr, drvr_node, load_node1, 0.0, ap); makeResistor(parasitic, resistor_index++, 0.0, drvr_node, load_node1);
} }
} }
} }
@ -167,21 +280,21 @@ Parasitics::makeWireloadNetworkBalanced(Parasitic *parasitic,
const Pin *drvr_pin, const Pin *drvr_pin,
float wireload_cap, float wireload_cap,
float wireload_res, float wireload_res,
float fanout, float fanout)
const ParasiticAnalysisPt *ap)
{ {
float fanout_cap = wireload_cap / fanout; float fanout_cap = wireload_cap / fanout;
float fanout_res = wireload_res / 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 = PinConnectedPinIterator *load_iter =
network_->connectedPinIterator(drvr_pin); network_->connectedPinIterator(drvr_pin);
size_t resistor_index = 1;
while (load_iter->hasNext()) { while (load_iter->hasNext()) {
const Pin *load_pin = load_iter->next(); const Pin *load_pin = load_iter->next();
if (load_pin != drvr_pin if (load_pin != drvr_pin
&& network_->isLoad(load_pin)) { && network_->isLoad(load_pin)) {
ParasiticNode *load_node1 = ensureParasiticNode(parasitic, load_pin); ParasiticNode *load_node1 = ensureParasiticNode(parasitic, load_pin, network_);
makeResistor(nullptr, drvr_node, load_node1, fanout_res, ap); makeResistor(parasitic, resistor_index++, fanout_res, drvr_node, load_node1);
parasitics_->incrCap(load_node1, fanout_cap, ap); parasitics_->incrCap(load_node1, fanout_cap);
} }
} }
} }
@ -190,19 +303,14 @@ Parasitics::makeWireloadNetworkBalanced(Parasitic *parasitic,
ParasiticAnalysisPt::ParasiticAnalysisPt(const char *name, ParasiticAnalysisPt::ParasiticAnalysisPt(const char *name,
int index, int index,
const MinMax *min_max) : int index_max) :
name_(stringCopy(name)), name_(name),
index_(index), index_(index),
min_max_(min_max), index_max_(index_max),
coupling_cap_factor_(1.0) coupling_cap_factor_(1.0)
{ {
} }
ParasiticAnalysisPt::~ParasiticAnalysisPt()
{
stringDelete(name_);
}
void void
ParasiticAnalysisPt::setCouplingCapFactor(float factor) ParasiticAnalysisPt::setCouplingCapFactor(float factor)
{ {

View File

@ -24,7 +24,6 @@ using sta::Sta;
using sta::cmdLinkedNetwork; using sta::cmdLinkedNetwork;
using sta::Instance; using sta::Instance;
using sta::MinMaxAll; using sta::MinMaxAll;
using sta::ReducedParasiticType;
using sta::RiseFall; using sta::RiseFall;
using sta::Pin; using sta::Pin;
@ -40,15 +39,12 @@ read_spef_cmd(const char *filename,
bool pin_cap_included, bool pin_cap_included,
bool keep_coupling_caps, bool keep_coupling_caps,
float coupling_cap_factor, float coupling_cap_factor,
ReducedParasiticType reduce_to, bool reduce)
bool delete_after_reduce,
bool quiet)
{ {
cmdLinkedNetwork(); cmdLinkedNetwork();
return Sta::sta()->readSpef(filename, instance, corner, min_max, return Sta::sta()->readSpef(filename, instance, corner, min_max,
pin_cap_included, keep_coupling_caps, pin_cap_included, keep_coupling_caps,
coupling_cap_factor, reduce_to, coupling_cap_factor, reduce);
delete_after_reduce, quiet);
} }
void void

View File

@ -26,16 +26,29 @@ define_cmd_args "read_spef" \
[-coupling_reduction_factor factor]\ [-coupling_reduction_factor factor]\
[-reduce_to pi_elmore|pi_pole_residue2]\ [-reduce_to pi_elmore|pi_pole_residue2]\
[-delete_after_reduce]\ [-delete_after_reduce]\
[-quiet]\
[-save]\
filename} filename}
proc_redirect read_spef { proc_redirect read_spef {
parse_key_args "read_spef" args \ parse_key_args "read_spef" args \
keys {-path -coupling_reduction_factor -reduce_to -corner} \ keys {-path -coupling_reduction_factor -reduce_to -corner} \
flags {-min -max -increment -pin_cap_included -keep_capacitive_coupling \ flags {-min -max -increment -pin_cap_included -keep_capacitive_coupling \
-delete_after_reduce -quiet -save} -reduce -delete_after_reduce -quiet -save}
check_argc_eq1 "report_spef" $args 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] set instance [top_instance]
if [info exists keys(-path)] { if [info exists keys(-path)] {
@ -55,20 +68,10 @@ proc_redirect read_spef {
set keep_coupling_caps [info exists flags(-keep_capacitive_coupling)] set keep_coupling_caps [info exists flags(-keep_capacitive_coupling)]
set pin_cap_included [info exists flags(-pin_cap_included)] 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]] set filename [file nativename [lindex $args 0]]
return [read_spef_cmd $filename $instance $corner $min_max \ return [read_spef_cmd $filename $instance $corner $min_max \
$pin_cap_included $keep_coupling_caps $coupling_reduction_factor \ $pin_cap_included $keep_coupling_caps \
$reduce_to $delete_after_reduce $quiet] $coupling_reduction_factor $reduce]
} }
define_cmd_args "report_parasitic_annotation" {-report_unannotated} define_cmd_args "report_parasitic_annotation" {-report_unannotated}

View File

@ -30,22 +30,21 @@ namespace sta {
using std::max; using std::max;
typedef Map<ParasiticNode*, double> ParasiticNodeValueMap; typedef Map<ParasiticNode*, double> ParasiticNodeValueMap;
typedef Map<ParasiticDevice*, double> ParasiticDeviceValueMap; typedef Map<ParasiticResistor*, double> ResistorCurrentMap;
typedef Set<ParasiticDevice*> ParasiticDeviceSet; typedef Set<ParasiticResistor*> ParasiticResistorSet;
typedef Set<ParasiticNode*> ParasiticNodeSet; typedef Set<ParasiticNode*> ParasiticNodeSet;
class ReduceToPi : public StaState class ReduceToPi : public StaState
{ {
public: public:
ReduceToPi(StaState *sta); ReduceToPi(StaState *sta);
void reduceToPi(const Pin *drvr_pin, void reduceToPi(const Parasitic *parasitic_network,
const Pin *drvr_pin,
ParasiticNode *drvr_node, ParasiticNode *drvr_node,
bool includes_pin_caps,
float coupling_cap_factor, float coupling_cap_factor,
const RiseFall *rf, const RiseFall *rf,
const OperatingConditions *op_cond,
const Corner *corner, const Corner *corner,
const MinMax *cnst_min_max, const MinMax *min_max,
const ParasiticAnalysisPt *ap, const ParasiticAnalysisPt *ap,
float &c2, float &c2,
float &rpi, float &rpi,
@ -55,8 +54,7 @@ public:
protected: protected:
void reducePiDfs(const Pin *drvr_pin, void reducePiDfs(const Pin *drvr_pin,
ParasiticNode *node, ParasiticNode *node,
ParasiticDevice *from_res, ParasiticResistor *from_res,
const ParasiticAnalysisPt *ap,
double src_resistance, double src_resistance,
double &y1, double &y1,
double &y2, double &y2,
@ -70,18 +68,21 @@ protected:
float cap); float cap);
float downstreamCap(ParasiticNode *node); float downstreamCap(ParasiticNode *node);
float pinCapacitance(ParasiticNode *node); float pinCapacitance(ParasiticNode *node);
bool isLoopResistor(ParasiticDevice *device); bool isLoopResistor(ParasiticResistor *resistor);
void markLoopResistor(ParasiticDevice *device); void markLoopResistor(ParasiticResistor *resistor);
bool includes_pin_caps_; bool includes_pin_caps_;
float coupling_cap_multiplier_; float coupling_cap_multiplier_;
const RiseFall *rf_; const RiseFall *rf_;
const OperatingConditions *op_cond_;
const Corner *corner_; const Corner *corner_;
const MinMax *cnst_min_max_; const MinMax *min_max_;
const ParasiticAnalysisPt *ap_;
ParasiticNodeResistorMap resistor_map_;
ParasiticNodeCapacitorMap capacitor_map_;
ParasiticNodeSet visited_nodes_; ParasiticNodeSet visited_nodes_;
ParasiticNodeValueMap node_values_; ParasiticNodeValueMap node_values_;
ParasiticDeviceSet loop_resistors_; ParasiticResistorSet loop_resistors_;
bool pin_caps_one_value_; bool pin_caps_one_value_;
}; };
@ -89,9 +90,8 @@ ReduceToPi::ReduceToPi(StaState *sta) :
StaState(sta), StaState(sta),
coupling_cap_multiplier_(1.0), coupling_cap_multiplier_(1.0),
rf_(nullptr), rf_(nullptr),
op_cond_(nullptr),
corner_(nullptr), corner_(nullptr),
cnst_min_max_(nullptr), min_max_(nullptr),
pin_caps_one_value_(true) pin_caps_one_value_(true)
{ {
} }
@ -101,29 +101,30 @@ ReduceToPi::ReduceToPi(StaState *sta) :
// Thomas Savarino, Proceedings of the 1989 Design Automation // Thomas Savarino, Proceedings of the 1989 Design Automation
// Conference. // Conference.
void void
ReduceToPi::reduceToPi(const Pin *drvr_pin, ReduceToPi::reduceToPi(const Parasitic *parasitic_network,
const Pin *drvr_pin,
ParasiticNode *drvr_node, ParasiticNode *drvr_node,
bool includes_pin_caps,
float coupling_cap_factor, float coupling_cap_factor,
const RiseFall *rf, const RiseFall *rf,
const OperatingConditions *op_cond,
const Corner *corner, const Corner *corner,
const MinMax *cnst_min_max, const MinMax *min_max,
const ParasiticAnalysisPt *ap, const ParasiticAnalysisPt *ap,
float &c2, float &c2,
float &rpi, float &rpi,
float &c1) float &c1)
{ {
includes_pin_caps_ = includes_pin_caps; includes_pin_caps_ = parasitics_->includesPinCaps(parasitic_network),
coupling_cap_multiplier_ = coupling_cap_factor; coupling_cap_multiplier_ = coupling_cap_factor;
rf_ = rf; rf_ = rf;
op_cond_ = op_cond;
corner_ = corner; 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 y1, y2, y3, dcap;
double max_resistance = 0.0; 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); y1, y2, y3, dcap, max_resistance);
if (y2 == 0.0 && y3 == 0.0) { if (y2 == 0.0 && y3 == 0.0) {
@ -146,8 +147,7 @@ ReduceToPi::reduceToPi(const Pin *drvr_pin,
void void
ReduceToPi::reducePiDfs(const Pin *drvr_pin, ReduceToPi::reducePiDfs(const Pin *drvr_pin,
ParasiticNode *node, ParasiticNode *node,
ParasiticDevice *from_res, ParasiticResistor *from_res,
const ParasiticAnalysisPt *ap,
double src_resistance, double src_resistance,
double &y1, double &y1,
double &y2, double &y2,
@ -155,78 +155,78 @@ ReduceToPi::reducePiDfs(const Pin *drvr_pin,
double &dwn_cap, double &dwn_cap,
double &max_resistance) double &max_resistance)
{ {
double coupling_cap = 0.0; if (parasitics_->isExternal(node)) {
ParasiticDeviceIterator *device_iter1 = parasitics_->deviceIterator(node); y1 = y2 = y3 = 0.0;
while (device_iter1->hasNext()) { max_resistance = 0.0;
ParasiticDevice *device = device_iter1->next(); dwn_cap = 0.0;
if (parasitics_->isCouplingCap(device))
coupling_cap += parasitics_->value(device, ap);
} }
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) dwn_cap = parasitics_->nodeGndCap(node)
+ coupling_cap * coupling_cap_multiplier_ + coupling_cap * coupling_cap_multiplier_
+ pinCapacitance(node); + pinCapacitance(node);
y2 = y3 = 0.0; y1 = dwn_cap;
max_resistance = max(max_resistance, src_resistance); y2 = y3 = 0.0;
max_resistance = max(max_resistance, src_resistance);
visit(node); visit(node);
ParasiticDeviceIterator *device_iter2 = parasitics_->deviceIterator(node); ParasiticResistorSeq &resistors = resistor_map_[node];
while (device_iter2->hasNext()) { for (ParasiticResistor *resistor : resistors) {
ParasiticDevice *device = device_iter2->next(); if (!isLoopResistor(resistor)) {
if (parasitics_->isResistor(device) ParasiticNode *onode = parasitics_->otherNode(resistor, node);
&& !isLoopResistor(device)) { // One commercial extractor creates resistors with identical from/to nodes.
ParasiticNode *onode = parasitics_->otherNode(device, node); if (onode != node
// One commercial extractor creates resistors with identical from/to nodes. && resistor != from_res) {
if (onode != node if (isVisited(onode)) {
&& device != from_res) { // Resistor loop.
if (isVisited(onode)) { debugPrint(debug_, "parasitic_reduce", 2, " loop detected thru resistor %lu",
// Resistor loop. parasitics_->id(resistor));
debugPrint(debug_, "parasitic_reduce", 2, " loop detected thru resistor %s", markLoopResistor(resistor);
parasitics_->name(device)); }
markLoopResistor(device); else {
} double r = parasitics_->value(resistor);
else { double yd1, yd2, yd3, dcap;
double r = parasitics_->value(device, ap); reducePiDfs(drvr_pin, onode, resistor, src_resistance + r,
double yd1, yd2, yd3, dcap; yd1, yd2, yd3, dcap, max_resistance);
reducePiDfs(drvr_pin, onode, device, ap, src_resistance + r, // Rule 3. Upstream traversal of a series resistor.
yd1, yd2, yd3, dcap, max_resistance); // Rule 4. Parallel admittances add.
// Rule 3. Upstream traversal of a series resistor. y1 += yd1;
// Rule 4. Parallel admittances add. y2 += yd2 - r * yd1 * yd1;
y1 += yd1; y3 += yd3 - 2 * r * yd1 * yd2 + r * r * yd1 * yd1 * yd1;
y2 += yd2 - r * yd1 * yd1; dwn_cap += dcap;
y3 += yd3 - 2 * r * yd1 * yd2 + r * r * yd1 * yd1 * yd1; }
dwn_cap += dcap;
} }
} }
} }
}
delete device_iter2;
setDownstreamCap(node, dwn_cap); setDownstreamCap(node, dwn_cap);
leave(node); leave(node);
debugPrint(debug_, "parasitic_reduce", 3, debugPrint(debug_, "parasitic_reduce", 3,
" node %s y1=%.3g y2=%.3g y3=%.3g cap=%.3g", " node %s y1=%.3g y2=%.3g y3=%.3g cap=%.3g",
parasitics_->name(node), y1, y2, y3, dwn_cap); parasitics_->name(node), y1, y2, y3, dwn_cap);
}
} }
float float
ReduceToPi::pinCapacitance(ParasiticNode *node) ReduceToPi::pinCapacitance(ParasiticNode *node)
{ {
const Pin *pin = parasitics_->connectionPin(node); const Pin *pin = parasitics_->pin(node);
float pin_cap = 0.0; float pin_cap = 0.0;
if (pin) { if (pin) {
Port *port = network_->port(pin); Port *port = network_->port(pin);
LibertyPort *lib_port = network_->libertyPort(port); LibertyPort *lib_port = network_->libertyPort(port);
if (lib_port) { if (lib_port) {
if (!includes_pin_caps_) { if (!includes_pin_caps_) {
pin_cap = sdc_->pinCapacitance(pin, rf_, op_cond_, corner_, pin_cap = sdc_->pinCapacitance(pin, rf_, corner_, min_max_);
cnst_min_max_);
pin_caps_one_value_ &= lib_port->capacitanceIsOneValue(); pin_caps_one_value_ &= lib_port->capacitanceIsOneValue();
} }
} }
else if (network_->isTopLevelPort(pin)) 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; return pin_cap;
} }
@ -250,15 +250,15 @@ ReduceToPi::leave(ParasiticNode *node)
} }
bool bool
ReduceToPi::isLoopResistor(ParasiticDevice *device) ReduceToPi::isLoopResistor(ParasiticResistor *resistor)
{ {
return loop_resistors_.hasKey(device); return loop_resistors_.hasKey(resistor);
} }
void void
ReduceToPi::markLoopResistor(ParasiticDevice *device) ReduceToPi::markLoopResistor(ParasiticResistor *resistor)
{ {
loop_resistors_.insert(device); loop_resistors_.insert(resistor);
} }
void void
@ -280,50 +280,44 @@ class ReduceToPiElmore : public ReduceToPi
{ {
public: public:
ReduceToPiElmore(StaState *sta); ReduceToPiElmore(StaState *sta);
void makePiElmore(const Parasitic *parasitic_network, Parasitic *makePiElmore(const Parasitic *parasitic_network,
const Pin *drvr_pin, const Pin *drvr_pin,
ParasiticNode *drvr_node, ParasiticNode *drvr_node,
float coupling_cap_factor, float coupling_cap_factor,
const RiseFall *rf, const RiseFall *rf,
const OperatingConditions *op_cond, const Corner *corner,
const Corner *corner, const MinMax *min_max,
const MinMax *cnst_min_max, const ParasiticAnalysisPt *ap);
const ParasiticAnalysisPt *ap);
void reduceElmoreDfs(const Pin *drvr_pin, void reduceElmoreDfs(const Pin *drvr_pin,
ParasiticNode *node, ParasiticNode *node,
ParasiticDevice *from_res, ParasiticResistor *from_res,
double elmore, double elmore,
Parasitic *pi_elmore, Parasitic *pi_elmore);
const ParasiticAnalysisPt *ap);
}; };
void Parasitic *
reduceToPiElmore(const Parasitic *parasitic_network, reduceToPiElmore(const Parasitic *parasitic_network,
const Pin *drvr_pin, const Pin *drvr_pin,
float coupling_cap_factor, const RiseFall *rf,
const OperatingConditions *op_cond, float coupling_cap_factor,
const Corner *corner, const Corner *corner,
const MinMax *cnst_min_max, const MinMax *min_max,
const ParasiticAnalysisPt *ap, const ParasiticAnalysisPt *ap,
StaState *sta) StaState *sta)
{ {
Parasitics *parasitics = sta->parasitics(); Parasitics *parasitics = sta->parasitics();
ParasiticNode *drvr_node = parasitics->findNode(parasitic_network, ParasiticNode *drvr_node = parasitics->findNode(parasitic_network, drvr_pin);
drvr_pin);
if (drvr_node) { if (drvr_node) {
debugPrint(sta->debug(), "parasitic_reduce", 1, "Reduce driver %s", debugPrint(sta->debug(), "parasitic_reduce", 1, "Reduce driver %s %s %s",
sta->network()->pathName(drvr_pin)); sta->network()->pathName(drvr_pin),
rf->asString(),
min_max->asString());
ReduceToPiElmore reducer(sta); ReduceToPiElmore reducer(sta);
if (parasitics->checkAnnotation(drvr_pin, drvr_node)) { return reducer.makePiElmore(parasitic_network, drvr_pin, drvr_node,
reducer.makePiElmore(parasitic_network, drvr_pin, drvr_node, coupling_cap_factor, rf, corner,
coupling_cap_factor, RiseFall::rise(), min_max, ap);
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 nullptr;
} }
ReduceToPiElmore::ReduceToPiElmore(StaState *sta) : ReduceToPiElmore::ReduceToPiElmore(StaState *sta) :
@ -331,27 +325,24 @@ ReduceToPiElmore::ReduceToPiElmore(StaState *sta) :
{ {
} }
void Parasitic *
ReduceToPiElmore::makePiElmore(const Parasitic *parasitic_network, ReduceToPiElmore::makePiElmore(const Parasitic *parasitic_network,
const Pin *drvr_pin, const Pin *drvr_pin,
ParasiticNode *drvr_node, ParasiticNode *drvr_node,
float coupling_cap_factor, float coupling_cap_factor,
const RiseFall *rf, const RiseFall *rf,
const OperatingConditions *op_cond,
const Corner *corner, const Corner *corner,
const MinMax *cnst_min_max, const MinMax *min_max,
const ParasiticAnalysisPt *ap) const ParasiticAnalysisPt *ap)
{ {
float c2, rpi, c1; float c2, rpi, c1;
reduceToPi(drvr_pin, drvr_node, reduceToPi(parasitic_network, drvr_pin, drvr_node, coupling_cap_factor,
parasitics_->includesPinCaps(parasitic_network), rf, corner, min_max, ap, c2, rpi, c1);
coupling_cap_factor,
rf, op_cond, corner, cnst_min_max, ap,
c2, rpi, c1);
Parasitic *pi_elmore = parasitics_->makePiElmore(drvr_pin, rf, ap, Parasitic *pi_elmore = parasitics_->makePiElmore(drvr_pin, rf, ap,
c2, rpi, c1); c2, rpi, c1);
parasitics_->setIsReducedParasiticNetwork(pi_elmore, true); 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 // Find elmore delays on 2nd DFS search using downstream capacitances
@ -359,12 +350,11 @@ ReduceToPiElmore::makePiElmore(const Parasitic *parasitic_network,
void void
ReduceToPiElmore::reduceElmoreDfs(const Pin *drvr_pin, ReduceToPiElmore::reduceElmoreDfs(const Pin *drvr_pin,
ParasiticNode *node, ParasiticNode *node,
ParasiticDevice *from_res, ParasiticResistor *from_res,
double elmore, double elmore,
Parasitic *pi_elmore, Parasitic *pi_elmore)
const ParasiticAnalysisPt *ap)
{ {
const Pin *pin = parasitics_->connectionPin(node); const Pin *pin = parasitics_->pin(node);
if (from_res && pin) { if (from_res && pin) {
if (network_->isLoad(pin)) { if (network_->isLoad(pin)) {
debugPrint(debug_, "parasitic_reduce", 2, " Load %s elmore=%.3g", debugPrint(debug_, "parasitic_reduce", 2, " Load %s elmore=%.3g",
@ -374,22 +364,17 @@ ReduceToPiElmore::reduceElmoreDfs(const Pin *drvr_pin,
} }
} }
visit(node); visit(node);
ParasiticDeviceIterator *device_iter = parasitics_->deviceIterator(node); ParasiticResistorSeq &resistors = resistor_map_[node];
while (device_iter->hasNext()) { for (ParasiticResistor *resistor : resistors) {
ParasiticDevice *device = device_iter->next(); ParasiticNode *onode = parasitics_->otherNode(resistor, node);
if (parasitics_->isResistor(device)) { if (resistor != from_res
ParasiticNode *onode = parasitics_->otherNode(device, node); && !isVisited(onode)
if (device != from_res && !isLoopResistor(resistor)) {
&& !isVisited(onode) float r = parasitics_->value(resistor);
&& !isLoopResistor(device)) { double onode_elmore = elmore + r * downstreamCap(onode);
float r = parasitics_->value(device, ap); reduceElmoreDfs(drvr_pin, onode, resistor, onode_elmore, pi_elmore);
double onode_elmore = elmore + r * downstreamCap(onode);
reduceElmoreDfs(drvr_pin, onode, device, onode_elmore,
pi_elmore, ap);
}
} }
} }
delete device_iter;
leave(node); leave(node);
} }
@ -401,43 +386,38 @@ public:
ReduceToPiPoleResidue2(StaState *sta); ReduceToPiPoleResidue2(StaState *sta);
~ReduceToPiPoleResidue2(); ~ReduceToPiPoleResidue2();
void findPolesResidues(const Parasitic *parasitic_network, void findPolesResidues(const Parasitic *parasitic_network,
Parasitic *pi_pole_residue, Parasitic *pi_pole_residue,
const Pin *drvr_pin, const Pin *drvr_pin,
ParasiticNode *drvr_node, ParasiticNode *drvr_node);
const ParasiticAnalysisPt *ap); Parasitic *makePiPoleResidue2(const Parasitic *parasitic_network,
void makePiPoleResidue2(const Parasitic *parasitic_network, const Pin *drvr_pin,
const Pin *drvr_pin, ParasiticNode *drvr_node,
ParasiticNode *drvr_node, float coupling_cap_factor,
float coupling_cap_factor, const RiseFall *rf,
const RiseFall *rf, const Corner *corner,
const OperatingConditions *op_cond, const MinMax *min_max,
const Corner *corner, const ParasiticAnalysisPt *ap);
const MinMax *cnst_min_max,
const ParasiticAnalysisPt *ap);
private: private:
void findMoments(const Pin *drvr_pin, void findMoments(const Pin *drvr_pin,
ParasiticNode *drvr_node, ParasiticNode *drvr_node,
int moment_count, int moment_count);
const ParasiticAnalysisPt *ap);
void findMoments(const Pin *drvr_pin, void findMoments(const Pin *drvr_pin,
ParasiticNode *node, ParasiticNode *node,
double from_volt, double from_volt,
ParasiticDevice *from_res, ParasiticResistor *from_res,
int moment_index, int moment_index);
const ParasiticAnalysisPt *ap);
double findBranchCurrents(const Pin *drvr_pin, double findBranchCurrents(const Pin *drvr_pin,
ParasiticNode *node, ParasiticNode *node,
ParasiticDevice *from_res, ParasiticResistor *from_res,
int moment_index, int moment_index);
const ParasiticAnalysisPt *ap);
double moment(ParasiticNode *node, double moment(ParasiticNode *node,
int moment_index); int moment_index);
void setMoment(ParasiticNode *node, void setMoment(ParasiticNode *node,
double moment, double moment,
int moment_index); int moment_index);
double current(ParasiticDevice *res); double current(ParasiticResistor *res);
void setCurrent(ParasiticDevice *res, void setCurrent(ParasiticResistor *res,
double i); double i);
void findPolesResidues(Parasitic *pi_pole_residue, void findPolesResidues(Parasitic *pi_pole_residue,
const Pin *drvr_pin, const Pin *drvr_pin,
@ -445,7 +425,7 @@ private:
ParasiticNode *load_node); ParasiticNode *load_node);
// Resistor/capacitor currents. // Resistor/capacitor currents.
ParasiticDeviceValueMap currents_; ResistorCurrentMap currents_;
ParasiticNodeValueMap *moments_; ParasiticNodeValueMap *moments_;
}; };
@ -465,13 +445,13 @@ ReduceToPiPoleResidue2::ReduceToPiPoleResidue2(StaState *sta) :
// "An Explicit RC-Circuit Delay Approximation Based on the First // "An Explicit RC-Circuit Delay Approximation Based on the First
// Three Moments of the Impulse Response", Proceedings of the 33rd // Three Moments of the Impulse Response", Proceedings of the 33rd
// Design Automation Conference, 1996, pg 611-616. // Design Automation Conference, 1996, pg 611-616.
void Parasitic *
reduceToPiPoleResidue2(const Parasitic *parasitic_network, reduceToPiPoleResidue2(const Parasitic *parasitic_network,
const Pin *drvr_pin, const Pin *drvr_pin,
const RiseFall *rf,
float coupling_cap_factor, float coupling_cap_factor,
const OperatingConditions *op_cond,
const Corner *corner, const Corner *corner,
const MinMax *cnst_min_max, const MinMax *min_max,
const ParasiticAnalysisPt *ap, const ParasiticAnalysisPt *ap,
StaState *sta) StaState *sta)
{ {
@ -481,41 +461,33 @@ reduceToPiPoleResidue2(const Parasitic *parasitic_network,
debugPrint(sta->debug(), "parasitic_reduce", 1, "Reduce driver %s", debugPrint(sta->debug(), "parasitic_reduce", 1, "Reduce driver %s",
sta->network()->pathName(drvr_pin)); sta->network()->pathName(drvr_pin));
ReduceToPiPoleResidue2 reducer(sta); ReduceToPiPoleResidue2 reducer(sta);
if (parasitics->checkAnnotation(drvr_pin, drvr_node)) { return reducer.makePiPoleResidue2(parasitic_network, drvr_pin, drvr_node,
reducer.makePiPoleResidue2(parasitic_network, drvr_pin, drvr_node, coupling_cap_factor, rf,
coupling_cap_factor, RiseFall::rise(), corner, min_max, ap);
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 nullptr;
} }
void Parasitic *
ReduceToPiPoleResidue2::makePiPoleResidue2(const Parasitic *parasitic_network, ReduceToPiPoleResidue2::makePiPoleResidue2(const Parasitic *parasitic_network,
const Pin *drvr_pin, const Pin *drvr_pin,
ParasiticNode *drvr_node, ParasiticNode *drvr_node,
float coupling_cap_factor, float coupling_cap_factor,
const RiseFall *rf, const RiseFall *rf,
const OperatingConditions *op_cond,
const Corner *corner, const Corner *corner,
const MinMax *cnst_min_max, const MinMax *min_max,
const ParasiticAnalysisPt *ap) const ParasiticAnalysisPt *ap)
{ {
float c2, rpi, c1; float c2, rpi, c1;
reduceToPi(drvr_pin, drvr_node, reduceToPi(parasitic_network, drvr_pin, drvr_node,
parasitics_->includesPinCaps(parasitic_network), coupling_cap_factor, rf, corner, min_max, ap,
coupling_cap_factor,
rf, op_cond, corner, cnst_min_max, ap,
c2, rpi, c1); c2, rpi, c1);
Parasitic *pi_pole_residue = parasitics_->makePiPoleResidue(drvr_pin, Parasitic *pi_pole_residue = parasitics_->makePiPoleResidue(drvr_pin,
rf, ap, rf, ap,
c2, rpi, c1); c2, rpi, c1);
parasitics_->setIsReducedParasiticNetwork(pi_pole_residue, true); parasitics_->setIsReducedParasiticNetwork(pi_pole_residue, true);
findPolesResidues(parasitic_network, pi_pole_residue, findPolesResidues(parasitic_network, pi_pole_residue, drvr_pin, drvr_node);
drvr_pin, drvr_node, ap); return pi_pole_residue;
} }
ReduceToPiPoleResidue2::~ReduceToPiPoleResidue2() ReduceToPiPoleResidue2::~ReduceToPiPoleResidue2()
@ -525,13 +497,12 @@ ReduceToPiPoleResidue2::~ReduceToPiPoleResidue2()
void void
ReduceToPiPoleResidue2::findPolesResidues(const Parasitic *parasitic_network, ReduceToPiPoleResidue2::findPolesResidues(const Parasitic *parasitic_network,
Parasitic *pi_pole_residue, Parasitic *pi_pole_residue,
const Pin *drvr_pin, const Pin *drvr_pin,
ParasiticNode *drvr_node, ParasiticNode *drvr_node)
const ParasiticAnalysisPt *ap)
{ {
moments_ = new ParasiticNodeValueMap[4]; moments_ = new ParasiticNodeValueMap[4];
findMoments(drvr_pin, drvr_node, 4, ap); findMoments(drvr_pin, drvr_node, 4);
PinConnectedPinIterator *pin_iter = network_->connectedPinIterator(drvr_pin); PinConnectedPinIterator *pin_iter = network_->connectedPinIterator(drvr_pin);
while (pin_iter->hasNext()) { while (pin_iter->hasNext()) {
@ -549,8 +520,7 @@ ReduceToPiPoleResidue2::findPolesResidues(const Parasitic *parasitic_network,
void void
ReduceToPiPoleResidue2::findMoments(const Pin *drvr_pin, ReduceToPiPoleResidue2::findMoments(const Pin *drvr_pin,
ParasiticNode *drvr_node, ParasiticNode *drvr_node,
int moment_count, int moment_count)
const ParasiticAnalysisPt *ap)
{ {
// Driver model thevenin resistance. // Driver model thevenin resistance.
double rd = 0.0; 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 // current thru the resistors. Thus, there is no point in doing a
// pass to find the zero'th moments. // pass to find the zero'th moments.
for (int moment_index = 1; moment_index < moment_count; moment_index++) { for (int moment_index = 1; moment_index < moment_count; moment_index++) {
double rd_i = findBranchCurrents(drvr_pin, drvr_node, 0, double rd_i = findBranchCurrents(drvr_pin, drvr_node, 0, moment_index);
moment_index, ap);
double rd_volt = rd_i * rd; double rd_volt = rd_i * rd;
setMoment(drvr_node, 0.0, moment_index); 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 double
ReduceToPiPoleResidue2::findBranchCurrents(const Pin *drvr_pin, ReduceToPiPoleResidue2::findBranchCurrents(const Pin *drvr_pin,
ParasiticNode *node, ParasiticNode *node,
ParasiticDevice *from_res, ParasiticResistor *from_res,
int moment_index, int moment_index)
const ParasiticAnalysisPt *ap)
{ {
visit(node); visit(node);
double branch_i = 0.0; double branch_i = 0.0;
double coupling_cap = 0.0; double coupling_cap = 0.0;
ParasiticDeviceIterator *device_iter = parasitics_->deviceIterator(node); ParasiticResistorSeq &resistors = resistor_map_[node];
while (device_iter->hasNext()) { for (ParasiticResistor *resistor : resistors) {
ParasiticDevice *device = device_iter->next(); ParasiticNode *onode = parasitics_->otherNode(resistor, node);
if (parasitics_->isResistor(device)) { // One commercial extractor creates resistors with identical from/to nodes.
ParasiticNode *onode = parasitics_->otherNode(device, node); if (onode != node
// One commercial extractor creates resistors with identical from/to nodes. && resistor != from_res
if (onode != node && !isVisited(onode)
&& device != from_res && !isLoopResistor(resistor)) {
&& !isVisited(onode) branch_i += findBranchCurrents(drvr_pin, onode, resistor, moment_index);
&& !isLoopResistor(device)) {
branch_i += findBranchCurrents(drvr_pin, onode, device,
moment_index, ap);
}
} }
else if (parasitics_->isCouplingCap(device))
coupling_cap += parasitics_->value(device, ap);
} }
delete device_iter; ParasiticCapacitorSeq &capacitors = capacitor_map_[node];
double cap = parasitics_->nodeGndCap(node, ap) for (ParasiticCapacitor *capacitor : capacitors)
coupling_cap += parasitics_->value(capacitor);
double cap = parasitics_->nodeGndCap(node)
+ coupling_cap * coupling_cap_multiplier_ + coupling_cap * coupling_cap_multiplier_
+ pinCapacitance(node); + pinCapacitance(node);
branch_i += cap * moment(node, moment_index - 1); branch_i += cap * moment(node, moment_index - 1);
@ -610,34 +575,29 @@ void
ReduceToPiPoleResidue2::findMoments(const Pin *drvr_pin, ReduceToPiPoleResidue2::findMoments(const Pin *drvr_pin,
ParasiticNode *node, ParasiticNode *node,
double from_volt, double from_volt,
ParasiticDevice *from_res, ParasiticResistor *from_res,
int moment_index, int moment_index)
const ParasiticAnalysisPt *ap)
{ {
visit(node); visit(node);
ParasiticDeviceIterator *device_iter = parasitics_->deviceIterator(node); ParasiticResistorSeq &resistors = resistor_map_[node];
while (device_iter->hasNext()) { for (ParasiticResistor *resistor : resistors) {
ParasiticDevice *device = device_iter->next(); ParasiticNode *onode = parasitics_->otherNode(resistor, node);
if (parasitics_->isResistor(device)) { // One commercial extractor creates resistors with identical from/to nodes.
ParasiticNode *onode = parasitics_->otherNode(device, node); if (onode != node
// One commercial extractor creates resistors with identical from/to nodes. && resistor != from_res
if (onode != node && !isVisited(onode)
&& device != from_res && !isLoopResistor(resistor)) {
&& !isVisited(onode) double r = parasitics_->value(resistor);
&& !isLoopResistor(device)) { double r_volt = r * current(resistor);
double r = parasitics_->value(device, ap); double onode_volt = from_volt - r_volt;
double r_volt = r * current(device); setMoment(onode, onode_volt, moment_index);
double onode_volt = from_volt - r_volt; debugPrint(debug_, "parasitic_reduce", 3, " moment %s %d %.3g",
setMoment(onode, onode_volt, moment_index); parasitics_->name(onode),
debugPrint(debug_, "parasitic_reduce", 3, " moment %s %d %.3g", moment_index,
parasitics_->name(onode), onode_volt);
moment_index, findMoments(drvr_pin, onode, onode_volt, resistor, moment_index);
onode_volt);
findMoments(drvr_pin, onode, onode_volt, device, moment_index, ap);
}
} }
} }
delete device_iter;
leave(node); leave(node);
} }
@ -667,13 +627,13 @@ ReduceToPiPoleResidue2::setMoment(ParasiticNode *node,
} }
double double
ReduceToPiPoleResidue2::current(ParasiticDevice *res) ReduceToPiPoleResidue2::current(ParasiticResistor *res)
{ {
return currents_[res]; return currents_[res];
} }
void void
ReduceToPiPoleResidue2::setCurrent(ParasiticDevice *res, ReduceToPiPoleResidue2::setCurrent(ParasiticResistor *res,
double i) double i)
{ {
currents_[res] = i; currents_[res] = i;

View File

@ -27,25 +27,25 @@ class ParasiticAnalysisPt;
class StaState; class StaState;
// Reduce parasitic network to pi elmore model for drvr_pin. // Reduce parasitic network to pi elmore model for drvr_pin.
void Parasitic *
reduceToPiElmore(const Parasitic *parasitic_network, reduceToPiElmore(const Parasitic *parasitic_network,
const Pin *drvr_pin, const Pin *drvr_pin,
const RiseFall *rf,
float coupling_cap_factor, float coupling_cap_factor,
const OperatingConditions *op_cond,
const Corner *corner, const Corner *corner,
const MinMax *cnst_min_max, const MinMax *min_max,
const ParasiticAnalysisPt *ap, const ParasiticAnalysisPt *ap,
StaState *sta); StaState *sta);
// Reduce parasitic network to pi and 2nd order pole/residue models // Reduce parasitic network to pi and 2nd order pole/residue models
// for drvr_pin. // for drvr_pin.
void Parasitic *
reduceToPiPoleResidue2(const Parasitic *parasitic_network, reduceToPiPoleResidue2(const Parasitic *parasitic_network,
const Pin *drvr_pin, const Pin *drvr_pin,
const RiseFall *rf,
float coupling_cap_factor, float coupling_cap_factor,
const OperatingConditions *op_cond,
const Corner *corner, const Corner *corner,
const MinMax *cnst_min_max, const MinMax *min_max,
const ParasiticAnalysisPt *ap, const ParasiticAnalysisPt *ap,
StaState *sta); StaState *sta);

View File

@ -95,9 +95,11 @@ ReportParasiticAnnotation::reportAnnotationCounts()
report_->reportLine(" %s", network_->pathName(drvr_pin)); report_->reportLine(" %s", network_->pathName(drvr_pin));
Parasitic *parasitic = parasitics_->findParasiticNetwork(drvr_pin, parasitic_ap_); Parasitic *parasitic = parasitics_->findParasiticNetwork(drvr_pin, parasitic_ap_);
PinSet unannotated_loads = parasitics_->unannotatedLoads(parasitic, drvr_pin); if (parasitic) {
for (const Pin *load_pin : unannotated_loads) PinSet unannotated_loads = parasitics_->unannotatedLoads(parasitic, drvr_pin);
report_->reportLine(" %s", network_->pathName(load_pin)); for (const Pin *load_pin : unannotated_loads)
report_->reportLine(" %s", network_->pathName(load_pin));
}
} }
} }
} }
@ -105,6 +107,7 @@ ReportParasiticAnnotation::reportAnnotationCounts()
void void
ReportParasiticAnnotation::findCounts() ReportParasiticAnnotation::findCounts()
{ {
DcalcAnalysisPt *dcalc_ap = corner_->findDcalcAnalysisPt(min_max_);
VertexIterator vertex_iter(graph_); VertexIterator vertex_iter(graph_);
while (vertex_iter.hasNext()) { while (vertex_iter.hasNext()) {
Vertex *vertex = vertex_iter.next(); Vertex *vertex = vertex_iter.next();
@ -113,8 +116,11 @@ ReportParasiticAnnotation::findCounts()
if (vertex->isDriver(network_) if (vertex->isDriver(network_)
&& !dir->isInternal()) { && !dir->isInternal()) {
Parasitic *parasitic = parasitics_->findParasiticNetwork(pin, parasitic_ap_); Parasitic *parasitic = parasitics_->findParasiticNetwork(pin, parasitic_ap_);
if (parasitic == nullptr)
parasitic = arc_delay_calc_->findParasitic(pin, RiseFall::rise(), dcalc_ap);
if (parasitic) { if (parasitic) {
if (!parasitics_->checkAnnotation(parasitic, pin)) PinSet unannotated_loads = parasitics_->unannotatedLoads(parasitic, pin);
if (unannotated_loads.size() > 0)
partially_annotated_.push_back(pin); partially_annotated_.push_back(pin);
} }
else else

View File

@ -27,6 +27,8 @@
#include "PortDirection.hh" #include "PortDirection.hh"
#include "Sdc.hh" #include "Sdc.hh"
#include "Parasitics.hh" #include "Parasitics.hh"
#include "Corner.hh"
#include "ArcDelayCalc.hh"
#include "SpefReaderPvt.hh" #include "SpefReaderPvt.hh"
#include "SpefNamespace.hh" #include "SpefNamespace.hh"
@ -37,6 +39,7 @@ spefResetScanner();
namespace sta { namespace sta {
// Referenced by parser.
SpefReader *spef_reader; SpefReader *spef_reader;
bool bool
@ -46,15 +49,10 @@ readSpefFile(const char *filename,
bool pin_cap_included, bool pin_cap_included,
bool keep_coupling_caps, bool keep_coupling_caps,
float coupling_cap_factor, float coupling_cap_factor,
ReducedParasiticType reduce_to, bool reduce,
bool delete_after_reduce,
const OperatingConditions *op_cond,
const Corner *corner, const Corner *corner,
const MinMax *cnst_min_max, const MinMaxAll *min_max,
bool quiet, StaState *sta)
Report *report,
Network *network,
Parasitics *parasitics)
{ {
bool success = false; bool success = false;
// Use zlib to uncompress gzip'd files automagically. // Use zlib to uncompress gzip'd files automagically.
@ -62,8 +60,7 @@ readSpefFile(const char *filename,
if (stream) { if (stream) {
SpefReader reader(filename, stream, instance, ap, SpefReader reader(filename, stream, instance, ap,
pin_cap_included, keep_coupling_caps, coupling_cap_factor, pin_cap_included, keep_coupling_caps, coupling_cap_factor,
reduce_to, delete_after_reduce, op_cond, corner, reduce, corner, min_max, sta);
cnst_min_max, quiet, report, network, parasitics);
spef_reader = &reader; spef_reader = &reader;
::spefResetScanner(); ::spefResetScanner();
// yyparse returns 0 on success. // yyparse returns 0 on success.
@ -83,27 +80,19 @@ SpefReader::SpefReader(const char *filename,
bool pin_cap_included, bool pin_cap_included,
bool keep_coupling_caps, bool keep_coupling_caps,
float coupling_cap_factor, float coupling_cap_factor,
ReducedParasiticType reduce_to, bool reduce,
bool delete_after_reduce,
const OperatingConditions *op_cond,
const Corner *corner, const Corner *corner,
const MinMax *cnst_min_max, const MinMaxAll *min_max,
bool quiet, StaState *sta) :
Report *report, StaState(sta),
Network *network,
Parasitics *parasitics) :
filename_(filename), filename_(filename),
instance_(instance), instance_(instance),
ap_(ap), ap_(ap),
pin_cap_included_(pin_cap_included), pin_cap_included_(pin_cap_included),
keep_coupling_caps_(keep_coupling_caps), keep_coupling_caps_(keep_coupling_caps),
reduce_to_(reduce_to), reduce_(reduce),
delete_after_reduce_(delete_after_reduce),
op_cond_(op_cond),
corner_(corner), corner_(corner),
cnst_min_max_(cnst_min_max), min_max_(min_max),
keep_device_names_(false),
quiet_(quiet),
stream_(stream), stream_(stream),
line_(1), line_(1),
// defaults // defaults
@ -112,9 +101,6 @@ SpefReader::SpefReader(const char *filename,
bus_brkt_left_('\0'), bus_brkt_left_('\0'),
bus_brkt_right_('\0'), bus_brkt_right_('\0'),
net_(nullptr), net_(nullptr),
report_(report),
network_(network),
parasitics_(parasitics),
triple_index_(0), triple_index_(0),
time_scale_(1.0), time_scale_(1.0),
cap_scale_(1.0), cap_scale_(1.0),
@ -134,11 +120,8 @@ SpefReader::~SpefReader()
design_flow_ = nullptr; design_flow_ = nullptr;
} }
SpefNameMap::Iterator map_iter(name_map_); for (auto index_name : name_map_) {
while (map_iter.hasNext()) { char *name = index_name.second;
int index;
char *name;
map_iter.next(index, name);
stringDelete(name); stringDelete(name);
} }
} }
@ -164,7 +147,7 @@ SpefReader::setBusBrackets(char left, char right)
|| (left == '<' && right == '>') || (left == '<' && right == '>')
|| (left == ':' && right == '\0') || (left == ':' && right == '\0')
|| (left == '.' && right == '\0'))) || (left == '.' && right == '\0')))
warn(167, "illegal bus delimiters."); warn(1640, "illegal bus delimiters.");
bus_brkt_left_ = left; bus_brkt_left_ = left;
bus_brkt_right_ = right; bus_brkt_right_ = right;
} }
@ -248,7 +231,7 @@ SpefReader::setTimeScale(float scale,
else if (stringEq(units, "PS")) else if (stringEq(units, "PS"))
time_scale_ = scale * 1E-12F; time_scale_ = scale * 1E-12F;
else else
warn(168, "unknown units %s.", units); warn(1641, "unknown units %s.", units);
stringDelete(units); stringDelete(units);
} }
@ -261,7 +244,7 @@ SpefReader::setCapScale(float scale,
else if (stringEq(units, "FF")) else if (stringEq(units, "FF"))
cap_scale_ = scale * 1E-15F; cap_scale_ = scale * 1E-15F;
else else
warn(168, "unknown units %s.", units); warn(1642, "unknown units %s.", units);
stringDelete(units); stringDelete(units);
} }
@ -274,7 +257,7 @@ SpefReader::setResScale(float scale,
else if (stringEq(units, "KOHM")) else if (stringEq(units, "KOHM"))
res_scale_ = scale * 1E+3F; res_scale_ = scale * 1E+3F;
else else
warn(170, "unknown units %s.", units); warn(1643, "unknown units %s.", units);
stringDelete(units); stringDelete(units);
} }
@ -289,7 +272,7 @@ SpefReader::setInductScale(float scale,
else if (stringEq(units, "UH")) else if (stringEq(units, "UH"))
induct_scale_ = scale * 1E-6F; induct_scale_ = scale * 1E-6F;
else else
warn(168, "unknown units %s.", units); warn(1644, "unknown units %s.", units);
stringDelete(units); stringDelete(units);
} }
@ -305,14 +288,12 @@ char *
SpefReader::nameMapLookup(char *name) SpefReader::nameMapLookup(char *name)
{ {
if (name && name[0] == '*') { if (name && name[0] == '*') {
char *mapped_name;
bool exists;
int index = atoi(name + 1); int index = atoi(name + 1);
name_map_.findKey(index, mapped_name, exists); auto itr = name_map_.find(index);
if (exists) if (itr != name_map_.end())
return mapped_name; return itr->second;
else { else {
warn(169, "no name map entry for %d.", index); warn(1645, "no name map entry for %d.", index);
return nullptr; return nullptr;
} }
} }
@ -331,7 +312,7 @@ SpefReader::portDirection(char *spef_dir)
else if (stringEq(spef_dir, "B")) else if (stringEq(spef_dir, "B"))
direction = PortDirection::bidirect(); direction = PortDirection::bidirect();
else else
warn(170, "unknown port direction %s.", spef_dir); warn(1646, "unknown port direction %s.", spef_dir);
return direction; return direction;
} }
@ -358,16 +339,16 @@ SpefReader::findPin(char *name)
if (inst) { if (inst) {
pin = network_->findPin(inst, port_name); pin = network_->findPin(inst, port_name);
if (pin == nullptr) if (pin == nullptr)
warn(171, "pin %s not found.", name); warn(1647, "pin %s not found.", name);
} }
else else
warn(172, "instance %s not found.", name); warn(1648, "instance %s not found.", name);
} }
} }
else { else {
pin = findPortPinRelative(name); pin = findPortPinRelative(name);
if (pin == nullptr) if (pin == nullptr)
warn(173, "pin %s not found.", name); warn(1649, "pin %s not found.", name);
} }
} }
return pin; return pin;
@ -381,7 +362,7 @@ SpefReader::findNet(char *name)
if (name) { if (name) {
net = findNetRelative(name); net = findNetRelative(name);
if (net == nullptr) if (net == nullptr)
warn(174, "net %s not found.", name); warn(1650, "net %s not found.", name);
} }
return net; return net;
} }
@ -409,12 +390,9 @@ SpefReader::rspfDrvrBegin(Pin *drvr_pin,
float c2 = pi->c2()->value(triple_index_) * cap_scale_; float c2 = pi->c2()->value(triple_index_) * cap_scale_;
float rpi = pi->r1()->value(triple_index_) * res_scale_; float rpi = pi->r1()->value(triple_index_) * res_scale_;
float c1 = pi->c1()->value(triple_index_) * cap_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. // Only one parasitic, save it under rise transition.
parasitic_ = parasitics_->makePiElmore(drvr_pin, parasitic_ = parasitics_->makePiElmore(drvr_pin, RiseFall::rise(), ap_,
RiseFall::rise(), c2, rpi, c1);
ap_, c2, rpi, c1);
} }
delete pi; delete pi;
} }
@ -472,46 +450,18 @@ SpefReader::dspfBegin(Net *net,
void void
SpefReader::dspfFinish() SpefReader::dspfFinish()
{ {
if (parasitic_) { if (parasitic_ && reduce_) {
if (!quiet_) arc_delay_calc_->reduceParasitic(parasitic_, net_, corner_, min_max_);
parasitics_->check(parasitic_); parasitics_->deleteParasiticNetwork(net_, ap_);
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_);
}
} }
parasitic_ = nullptr; parasitic_ = nullptr;
net_ = nullptr; net_ = nullptr;
} }
// Caller is only interested in nodes on net_.
ParasiticNode * 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, SpefReader::findParasiticNode(char *name,
ParasiticNode *&node, bool local_only)
Net *&ext_net,
int &ext_node_id,
Pin *&ext_pin)
{ {
node = nullptr;
ext_net = nullptr;
ext_node_id = 0;
ext_pin = nullptr;
if (name && parasitic_) { if (name && parasitic_) {
char *delim = strrchr(name, delimiter_); char *delim = strrchr(name, delimiter_);
if (delim) { if (delim) {
@ -523,15 +473,15 @@ SpefReader::findParasiticNode(char *name,
// <instance>:<port> // <instance>:<port>
Pin *pin = network_->findPin(inst, name2); Pin *pin = network_->findPin(inst, name2);
if (pin) { if (pin) {
if (network_->isConnected(net_, pin)) if (local_only
node = parasitics_->ensureParasiticNode(parasitic_, pin); && !network_->isConnected(net_, pin))
else warn(1651, "%s not connected to net %s.", name, network_->pathName(net_));
ext_pin = pin; return parasitics_->ensureParasiticNode(parasitic_, pin, network_);
} }
else { else {
// Replace delimiter for error message. // Replace delimiter for error message.
*delim = delimiter_; *delim = delimiter_;
warn(176, "pin %s not found.", name); warn(1652, "pin %s not found.", name);
} }
} }
else { else {
@ -543,15 +493,13 @@ SpefReader::findParasiticNode(char *name,
const char *id_str = delim + 1; const char *id_str = delim + 1;
if (isDigits(id_str)) { if (isDigits(id_str)) {
int id = atoi(id_str); int id = atoi(id_str);
if (network_->isConnected(net, net_)) if (local_only
node = parasitics_->ensureParasiticNode(parasitic_, net, id); && !network_->isConnected(net, net_))
else { warn(1653, "%s not connected to net %s.", name, network_->pathName(net_));
ext_net = net; return parasitics_->ensureParasiticNode(parasitic_, net, id, network_);
ext_node_id = id;
}
} }
else 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); name = nameMapLookup(name);
Pin *pin = findPortPinRelative(name); Pin *pin = findPortPinRelative(name);
if (pin) { if (pin) {
if (network_->isConnected(net_, pin)) if (local_only
node = parasitics_->ensureParasiticNode(parasitic_, pin); && !network_->isConnected(net_, pin))
else warn(1655, "%s not connected to net %s.", name, network_->pathName(net_));
ext_pin = pin; return parasitics_->ensureParasiticNode(parasitic_, pin, network_);
} }
else else
warn(178, "pin %s not found.", name); warn(1656, "pin %s not found.", name);
} }
} }
return nullptr;
} }
void void
SpefReader::makeCapacitor(int, char *node_name, SpefReader::makeCapacitor(int, char *node_name,
SpefTriple *cap) SpefTriple *cap)
{ {
ParasiticNode *node = findParasiticNode(node_name); ParasiticNode *node = findParasiticNode(node_name, true);
if (node) { if (node) {
float cap1 = cap->value(triple_index_) * cap_scale_; float cap1 = cap->value(triple_index_) * cap_scale_;
parasitics_->incrCap(node, cap1, ap_); parasitics_->incrCap(node, cap1);
} }
delete cap; delete cap;
stringDelete(node_name); stringDelete(node_name);
@ -590,81 +539,36 @@ SpefReader::makeCapacitor(int id,
char *node_name2, char *node_name2,
SpefTriple *cap) SpefTriple *cap)
{ {
ParasiticNode *node1 = findParasiticNode(node_name1, false);
ParasiticNode *node2 = findParasiticNode(node_name2, false);
float cap1 = cap->value(triple_index_) * cap_scale_; float cap1 = cap->value(triple_index_) * cap_scale_;
if (keep_coupling_caps_) if (cap1 > 0.0) {
makeCouplingCap(id, node_name1, node_name2, cap1); if (keep_coupling_caps_)
else { parasitics_->makeCapacitor(parasitic_, id, cap1, node1, node2);
ParasiticNode *node1, *node2; else {
Net *ext_net1, *ext_net2; float scaled_cap = cap1 * ap_->couplingCapFactor();
int ext_node_id1, ext_node_id2; if (node1 && parasitics_->net(node1, network_) == net_)
Pin *ext_pin1, *ext_pin2; parasitics_->incrCap(node1, scaled_cap);
findParasiticNode(node_name1, node1, ext_net1, ext_node_id1, ext_pin1); if (node2 && parasitics_->net(node2, network_) == net_)
findParasiticNode(node_name2, node2, ext_net2, ext_node_id2, ext_pin2); parasitics_->incrCap(node2, scaled_cap);
float scaled_cap = cap1 * ap_->couplingCapFactor(); }
if (node1)
parasitics_->incrCap(node1, scaled_cap, ap_);
if (node2)
parasitics_->incrCap(node2, scaled_cap, ap_);
} }
delete cap; delete cap;
stringDelete(node_name1); stringDelete(node_name1);
stringDelete(node_name2); 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 void
SpefReader::makeResistor(int id, SpefReader::makeResistor(int id,
char *node_name1, char *node_name1,
char *node_name2, char *node_name2,
SpefTriple *res) SpefTriple *res)
{ {
ParasiticNode *node1 = findParasiticNode(node_name1); ParasiticNode *node1 = findParasiticNode(node_name1, true);
ParasiticNode *node2 = findParasiticNode(node_name2); ParasiticNode *node2 = findParasiticNode(node_name2, true);
if (node1 && node2) { if (node1 && node2) {
float res1 = res->value(triple_index_) * res_scale_; float res1 = res->value(triple_index_) * res_scale_;
const char *name = nullptr; parasitics_->makeResistor(parasitic_, id, res1, node1, node2);
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);
} }
delete res; delete res;
stringDelete(node_name1); stringDelete(node_name1);
@ -727,6 +631,6 @@ int
SpefParse_error(const char *msg) SpefParse_error(const char *msg)
{ {
spefFlushBuffer(); spefFlushBuffer();
sta::spef_reader->warn(1227, "%s.", msg); sta::spef_reader->warn(1657, "%s.", msg);
return 0; return 0;
} }

View File

@ -22,13 +22,11 @@
namespace sta { namespace sta {
class Report;
class Network;
class Parasitics;
class ParasiticAnalysisPt; class ParasiticAnalysisPt;
class Instance; class Instance;
class Corner; class Corner;
class OperatingConditions; class OperatingConditions;
class StaState;
// Read a file single value parasitics into analysis point ap. // Read a file single value parasitics into analysis point ap.
// In a Spef file with triplet values the first value is used. // 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 pin_cap_included,
bool keep_coupling_caps, bool keep_coupling_caps,
float coupling_cap_factor, float coupling_cap_factor,
ReducedParasiticType reduce_to, bool reduce,
bool delete_after_reduce,
const OperatingConditions *op_cond,
const Corner *corner, const Corner *corner,
const MinMax *cnst_min_max, const MinMaxAll *min_max,
bool quiet, StaState *sta);
Report *report,
Network *network,
Parasitics *parasitics);
} // namespace } // namespace

View File

@ -16,11 +16,13 @@
#pragma once #pragma once
#include <map>
#include "Zlib.hh" #include "Zlib.hh"
#include "Map.hh"
#include "StringSeq.hh" #include "StringSeq.hh"
#include "NetworkClass.hh" #include "NetworkClass.hh"
#include "ParasiticsClass.hh" #include "ParasiticsClass.hh"
#include "StaState.hh"
// Global namespace. // Global namespace.
#define YY_INPUT(buf,result,max_size) \ #define YY_INPUT(buf,result,max_size) \
@ -34,15 +36,14 @@ SpefParse_error(const char *msg);
namespace sta { namespace sta {
class Report; class Report;
class OperatingConditions; class MinMaxAll;
class MinMax;
class SpefRspfPi; class SpefRspfPi;
class SpefTriple; class SpefTriple;
class Corner; 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: public:
SpefReader(const char *filename, SpefReader(const char *filename,
@ -52,15 +53,10 @@ public:
bool pin_cap_included, bool pin_cap_included,
bool keep_coupling_caps, bool keep_coupling_caps,
float coupling_cap_factor, float coupling_cap_factor,
ReducedParasiticType reduce_to, bool reduce,
bool delete_after_reduce,
const OperatingConditions *op_cond,
const Corner *corner, const Corner *corner,
const MinMax *cnst_min_max, const MinMaxAll *min_max,
bool quiet, StaState *sta);
Report *report,
Network *network,
Parasitics *parasitics);
virtual ~SpefReader(); virtual ~SpefReader();
char divider() const { return divider_; } char divider() const { return divider_; }
void setDivider(char divider); void setDivider(char divider);
@ -128,30 +124,18 @@ private:
Pin *findPortPinRelative(const char *name); Pin *findPortPinRelative(const char *name);
Net *findNetRelative(const char *name); Net *findNetRelative(const char *name);
Instance *findInstanceRelative(const char *name); Instance *findInstanceRelative(const char *name);
void makeCouplingCap(int id, ParasiticNode *findParasiticNode(char *name,
char *node_name1, bool local_only);
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);
const char *filename_; const char *filename_;
Instance *instance_; Instance *instance_;
const ParasiticAnalysisPt *ap_; const ParasiticAnalysisPt *ap_;
bool pin_cap_included_; bool pin_cap_included_;
bool keep_coupling_caps_; bool keep_coupling_caps_;
ReducedParasiticType reduce_to_; bool reduce_;
bool delete_after_reduce_;
const OperatingConditions *op_cond_;
const Corner *corner_; const Corner *corner_;
const MinMax *cnst_min_max_; const MinMaxAll *min_max_;
// Normally no need to keep device names. // Normally no need to keep device names.
bool keep_device_names_;
bool quiet_;
gzFile stream_; gzFile stream_;
int line_; int line_;
char divider_; char divider_;
@ -159,9 +143,6 @@ private:
char bus_brkt_left_; char bus_brkt_left_;
char bus_brkt_right_; char bus_brkt_right_;
Net *net_; Net *net_;
Report *report_;
Network *network_;
Parasitics *parasitics_;
int triple_index_; int triple_index_;
float time_scale_; float time_scale_;

View File

@ -465,7 +465,7 @@ Sdc::setOperatingConditions(OperatingConditions *op_cond,
} }
OperatingConditions * OperatingConditions *
Sdc::operatingConditions(const MinMax *min_max) Sdc::operatingConditions(const MinMax *min_max) const
{ {
int mm_index = min_max->index(); int mm_index = min_max->index();
return operating_conditions_[mm_index]; return operating_conditions_[mm_index];
@ -2958,8 +2958,7 @@ Sdc::setPortExtWireCap(const Port *port,
PortExtCap *port_cap = ensurePortExtPinCap(port, corner); PortExtCap *port_cap = ensurePortExtPinCap(port, corner);
if (subtract_pin_cap) { if (subtract_pin_cap) {
Pin *pin = network_->findPin(network_->name(port)); Pin *pin = network_->findPin(network_->name(port));
const OperatingConditions *op_cond = operatingConditions(min_max); cap -= connectedPinCap(pin, rf, corner, min_max);
cap -= connectedPinCap(pin, rf, op_cond, corner, min_max);
if (cap < 0.0) if (cap < 0.0)
cap = 0.0; cap = 0.0;
} }
@ -3066,14 +3065,11 @@ Sdc::setNetWireCap(const Net *net,
{ {
float wire_cap = cap; float wire_cap = cap;
if (subtract_pin_cap) { if (subtract_pin_cap) {
OperatingConditions *op_cond = operatingConditions(min_max);
NetConnectedPinIterator *pin_iter = network_->connectedPinIterator(net); NetConnectedPinIterator *pin_iter = network_->connectedPinIterator(net);
if (pin_iter->hasNext()) { if (pin_iter->hasNext()) {
const Pin *pin = pin_iter->next(); const Pin *pin = pin_iter->next();
float pin_cap_rise = connectedPinCap(pin, RiseFall::rise(), float pin_cap_rise = connectedPinCap(pin, RiseFall::rise(), corner, min_max);
op_cond, corner, min_max); float pin_cap_fall = connectedPinCap(pin, RiseFall::fall(), corner, min_max);
float pin_cap_fall = connectedPinCap(pin, RiseFall::fall(),
op_cond, corner, min_max);
float pin_cap = (pin_cap_rise + pin_cap_fall) / 2.0F; float pin_cap = (pin_cap_rise + pin_cap_fall) / 2.0F;
wire_cap -= pin_cap; wire_cap -= pin_cap;
if ((wire_cap + pin_cap) < 0.0) if ((wire_cap + pin_cap) < 0.0)
@ -3108,7 +3104,6 @@ Sdc::hasNetWireCap(const Net *net) const
void void
Sdc::connectedCap(const Pin *pin, Sdc::connectedCap(const Pin *pin,
const RiseFall *rf, const RiseFall *rf,
const OperatingConditions *op_cond,
const Corner *corner, const Corner *corner,
const MinMax *min_max, const MinMax *min_max,
// Return values. // Return values.
@ -3117,8 +3112,7 @@ Sdc::connectedCap(const Pin *pin,
float &fanout, float &fanout,
bool &has_net_load) const bool &has_net_load) const
{ {
netCaps(pin, rf, op_cond, corner, min_max, netCaps(pin, rf, corner, min_max, pin_cap, wire_cap, fanout, has_net_load);
pin_cap, wire_cap, fanout, has_net_load);
float net_wire_cap; float net_wire_cap;
drvrPinWireCap(pin, corner, min_max, net_wire_cap, has_net_load); drvrPinWireCap(pin, corner, min_max, net_wire_cap, has_net_load);
if (has_net_load) if (has_net_load)
@ -3128,13 +3122,12 @@ Sdc::connectedCap(const Pin *pin,
float float
Sdc::connectedPinCap(const Pin *pin, Sdc::connectedPinCap(const Pin *pin,
const RiseFall *rf, const RiseFall *rf,
const OperatingConditions *op_cond,
const Corner *corner, const Corner *corner,
const MinMax *min_max) const MinMax *min_max)
{ {
float pin_cap, wire_cap, fanout; float pin_cap, wire_cap, fanout;
bool has_net_load; 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); pin_cap, wire_cap, fanout, has_net_load);
return pin_cap; return pin_cap;
} }
@ -3143,7 +3136,6 @@ class FindNetCaps : public PinVisitor
{ {
public: public:
FindNetCaps(const RiseFall *rf, FindNetCaps(const RiseFall *rf,
const OperatingConditions *op_cond,
const Corner *corner, const Corner *corner,
const MinMax *min_max, const MinMax *min_max,
float &pin_cap, float &pin_cap,
@ -3155,7 +3147,6 @@ public:
protected: protected:
const RiseFall *rf_; const RiseFall *rf_;
const OperatingConditions *op_cond_;
const Corner *corner_; const Corner *corner_;
const MinMax *min_max_; const MinMax *min_max_;
float &pin_cap_; float &pin_cap_;
@ -3166,7 +3157,6 @@ protected:
}; };
FindNetCaps::FindNetCaps(const RiseFall *rf, FindNetCaps::FindNetCaps(const RiseFall *rf,
const OperatingConditions *op_cond,
const Corner *corner, const Corner *corner,
const MinMax *min_max, const MinMax *min_max,
float &pin_cap, float &pin_cap,
@ -3176,7 +3166,6 @@ FindNetCaps::FindNetCaps(const RiseFall *rf,
const Sdc *sdc) : const Sdc *sdc) :
PinVisitor(), PinVisitor(),
rf_(rf), rf_(rf),
op_cond_(op_cond),
corner_(corner), corner_(corner),
min_max_(min_max), min_max_(min_max),
pin_cap_(pin_cap), pin_cap_(pin_cap),
@ -3190,7 +3179,7 @@ FindNetCaps::FindNetCaps(const RiseFall *rf,
void void
FindNetCaps::operator()(const Pin *pin) 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_); pin_cap_, wire_cap_, fanout_);
} }
@ -3198,7 +3187,6 @@ FindNetCaps::operator()(const Pin *pin)
void void
Sdc::netCaps(const Pin *drvr_pin, Sdc::netCaps(const Pin *drvr_pin,
const RiseFall *rf, const RiseFall *rf,
const OperatingConditions *op_cond,
const Corner *corner, const Corner *corner,
const MinMax *min_max, const MinMax *min_max,
// Return values. // Return values.
@ -3211,7 +3199,7 @@ Sdc::netCaps(const Pin *drvr_pin,
wire_cap = 0.0; wire_cap = 0.0;
fanout = 0.0; fanout = 0.0;
has_net_load = false; 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); wire_cap, fanout, has_net_load, this);
network_->visitConnectedPins(drvr_pin, visitor); network_->visitConnectedPins(drvr_pin, visitor);
} }
@ -3219,7 +3207,6 @@ Sdc::netCaps(const Pin *drvr_pin,
void void
Sdc::pinCaps(const Pin *pin, Sdc::pinCaps(const Pin *pin,
const RiseFall *rf, const RiseFall *rf,
const OperatingConditions *op_cond,
const Corner *corner, const Corner *corner,
const MinMax *min_max, const MinMax *min_max,
// Return values. // Return values.
@ -3252,7 +3239,7 @@ Sdc::pinCaps(const Pin *pin,
LibertyPort *port = network_->libertyPort(pin); LibertyPort *port = network_->libertyPort(pin);
if (port) { if (port) {
Instance *inst = network_->instance(pin); 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()) if (port->direction()->isAnyInput())
fanout++; fanout++;
} }
@ -3263,7 +3250,6 @@ float
Sdc::portCapacitance(Instance *inst, Sdc::portCapacitance(Instance *inst,
LibertyPort *port, LibertyPort *port,
const RiseFall *rf, const RiseFall *rf,
const OperatingConditions *op_cond,
const Corner *corner, const Corner *corner,
const MinMax *min_max) const const MinMax *min_max) const
{ {
@ -3271,20 +3257,20 @@ Sdc::portCapacitance(Instance *inst,
if (inst) if (inst)
inst_pvt = pvt(inst, min_max); inst_pvt = pvt(inst, min_max);
LibertyPort *corner_port = port->cornerPort(corner, 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); return corner_port->capacitance(rf, min_max, op_cond, inst_pvt);
} }
float float
Sdc::pinCapacitance(const Pin *pin, Sdc::pinCapacitance(const Pin *pin,
const RiseFall *rf, const RiseFall *rf,
const OperatingConditions *op_cond,
const Corner *corner, const Corner *corner,
const MinMax *min_max) const MinMax *min_max)
{ {
LibertyPort *port = network_->libertyPort(pin); LibertyPort *port = network_->libertyPort(pin);
if (port) { if (port) {
Instance *inst = network_->instance(pin); Instance *inst = network_->instance(pin);
return portCapacitance(inst, port, rf, op_cond, corner, min_max); return portCapacitance(inst, port, rf, corner, min_max);
} }
else else
return 0.0; return 0.0;

View File

@ -114,8 +114,9 @@ Corners::copy(Corners *corners)
makeAnalysisPts(); makeAnalysisPts();
for (ParasiticAnalysisPt *orig_ap : corners->parasitic_analysis_pts_) { for (ParasiticAnalysisPt *orig_ap : corners->parasitic_analysis_pts_) {
ParasiticAnalysisPt *ap = new ParasiticAnalysisPt(orig_ap->name(), orig_ap->index(), ParasiticAnalysisPt *ap = new ParasiticAnalysisPt(orig_ap->name(),
orig_ap->minMax()); orig_ap->index(),
orig_ap->indexMax());
parasitic_analysis_pts_.push_back(ap); parasitic_analysis_pts_.push_back(ap);
} }
@ -127,64 +128,46 @@ Corners::copy(Corners *corners)
} }
void void
Corners::makeParasiticAnalysisPts(bool per_corner, Corners::makeParasiticAnalysisPts(bool per_corner)
bool per_min_max)
{ {
parasitic_analysis_pts_.deleteContentsClear(); parasitic_analysis_pts_.deleteContentsClear();
if (per_corner && per_min_max) { if (per_corner) {
// each corner has min/max parasitics // per corner, per min/max
parasitic_analysis_pts_.resize(corners_.size() * MinMax::index_count);
for (Corner *corner : corners_) { for (Corner *corner : corners_) {
corner->setParasiticAnalysisPtcount(MinMax::index_count); corner->setParasiticAnalysisPtcount(MinMax::index_count);
for (MinMax *min_max : MinMax::range()) { for (MinMax *min_max : MinMax::range()) {
int mm_index = min_max->index(); int mm_index = min_max->index();
int ap_index = corner->index() * MinMax::index_count + mm_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(); string ap_name = corner->name();
ap_name += "_"; ap_name += "_";
ap_name += min_max->asString(); ap_name += min_max->asString();
ParasiticAnalysisPt *ap = new ParasiticAnalysisPt(ap_name.c_str(), ParasiticAnalysisPt *ap = new ParasiticAnalysisPt(ap_name.c_str(),
ap_index, ap_index, ap_index_max);
min_max); parasitic_analysis_pts_[ap_index] = ap;
parasitic_analysis_pts_.push_back(ap);
corner->setParasiticAP(ap, mm_index); corner->setParasiticAP(ap, mm_index);
} }
} }
} }
else if (per_corner && !per_min_max) { else {
// each corner has parasitics // shared corner, per min/max
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
parasitic_analysis_pts_.resize(MinMax::index_count); parasitic_analysis_pts_.resize(MinMax::index_count);
int ap_index_max = MinMax::max()->index();
for (MinMax *min_max : MinMax::range()) { for (MinMax *min_max : MinMax::range()) {
int mm_index = min_max->index(); int mm_index = min_max->index();
int ap_index = mm_index;
ParasiticAnalysisPt *ap = new ParasiticAnalysisPt(min_max->asString(), ParasiticAnalysisPt *ap = new ParasiticAnalysisPt(min_max->asString(),
mm_index, ap_index,
min_max); ap_index_max);
parasitic_analysis_pts_[mm_index] = ap; parasitic_analysis_pts_[ap_index] = ap;
for (Corner *corner : corners_) { for (Corner *corner : corners_) {
corner->setParasiticAnalysisPtcount(MinMax::index_count); corner->setParasiticAnalysisPtcount(MinMax::index_count);
corner->setParasiticAP(ap, mm_index); 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 void
@ -404,9 +387,9 @@ Corner::setParasiticAnalysisPtcount(int ap_count)
void void
Corner::setParasiticAP(ParasiticAnalysisPt *ap, Corner::setParasiticAP(ParasiticAnalysisPt *ap,
int index) int mm_index)
{ {
parasitic_analysis_pts_[index] = ap; parasitic_analysis_pts_[mm_index] = ap;
} }
void void

View File

@ -2261,7 +2261,7 @@ ReportPath::reportPathLine(const Path *path,
float cap = field_blank_; float cap = field_blank_;
// Don't show capacitance field for input pins. // Don't show capacitance field for input pins.
if (is_driver && field_capacitance_->enabled()) 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_, reportLine(what.c_str(), cap, slew, field_blank_,
incr, time, false, early_late, rf, line_case); incr, time, false, early_late, rf, line_case);
} }
@ -2653,7 +2653,7 @@ ReportPath::reportPath5(const Path *path,
float fanout = field_blank_; float fanout = field_blank_;
// Don't show capacitance field for input pins. // Don't show capacitance field for input pins.
if (is_driver && field_capacitance_->enabled()) 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. // Don't show fanout field for input pins.
if (is_driver && field_fanout_->enabled()) if (is_driver && field_fanout_->enabled())
fanout = drvrFanout(vertex, dcalc_ap->corner(), min_max); 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 void

View File

@ -384,9 +384,6 @@ protected:
bool hasExtInputDriver(const Pin *pin, bool hasExtInputDriver(const Pin *pin,
const RiseFall *rf, const RiseFall *rf,
const MinMax *min_max); const MinMax *min_max);
float loadCap(Pin *drvr_pin,
const RiseFall *rf,
DcalcAnalysisPt *dcalc_ap);
float drvrFanout(Vertex *drvr, float drvrFanout(Vertex *drvr,
const Corner *corner, const Corner *corner,
const MinMax *min_max); const MinMax *min_max);

View File

@ -271,9 +271,8 @@ Sta::Sta() :
update_genclks_(false), update_genclks_(false),
equiv_cells_(nullptr), equiv_cells_(nullptr),
graph_sdc_annotated_(false), graph_sdc_annotated_(false),
// Default to same parasitics for each corner min/max. // Default to same parasitics for all corners.
parasitics_per_corner_(false), parasitics_per_corner_(false)
parasitics_per_min_max_(false)
{ {
} }
@ -3796,10 +3795,7 @@ Sta::connectedCap(const Pin *drvr_pin,
float &wire_cap) const float &wire_cap) const
{ {
const DcalcAnalysisPt *dcalc_ap = corner->findDcalcAnalysisPt(min_max); 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, rf, dcalc_ap, pin_cap, wire_cap);
graph_delay_calc_->loadCap(drvr_pin, parasitic, rf, dcalc_ap,
pin_cap, wire_cap);
arc_delay_calc_->finishDrvrPin();
} }
void void
@ -3892,40 +3888,29 @@ Sta::readSpef(const char *filename,
bool pin_cap_included, bool pin_cap_included,
bool keep_coupling_caps, bool keep_coupling_caps,
float coupling_cap_factor, float coupling_cap_factor,
ReducedParasiticType reduce_to, bool reduce)
bool delete_after_reduce,
bool quiet)
{ {
setParasiticAnalysisPts(corner != nullptr, setParasiticAnalysisPts(corner != nullptr);
min_max != MinMaxAll::all()); const MinMax *ap_min_max = (min_max == MinMaxAll::all())
if (corner == nullptr)
corner = cmd_corner_;
const MinMax *cnst_min_max = (min_max == MinMaxAll::all())
? MinMax::max() ? MinMax::max()
: min_max->asMinMax(); : min_max->asMinMax();
ParasiticAnalysisPt *ap = corner->findParasiticAnalysisPt(cnst_min_max); const Corner *ap_corner = corner ? corner : corners_->corners()[0];
const OperatingConditions *op_cond = ParasiticAnalysisPt *ap = ap_corner->findParasiticAnalysisPt(ap_min_max);
sdc_->operatingConditions(cnst_min_max);
bool success = readSpefFile(filename, instance, ap, bool success = readSpefFile(filename, instance, ap,
pin_cap_included, keep_coupling_caps, pin_cap_included, keep_coupling_caps,
coupling_cap_factor, coupling_cap_factor, reduce,
reduce_to, delete_after_reduce, corner, min_max, this);
op_cond, corner, cnst_min_max, quiet,
report_, network_, parasitics_);
graph_delay_calc_->delaysInvalid(); graph_delay_calc_->delaysInvalid();
search_->arrivalsInvalid(); search_->arrivalsInvalid();
return success; return success;
} }
void void
Sta::setParasiticAnalysisPts(bool per_corner, Sta::setParasiticAnalysisPts(bool per_corner)
bool per_min_max)
{ {
if (per_corner != parasitics_per_corner_ if (per_corner != parasitics_per_corner_) {
|| per_min_max != parasitics_per_min_max_) {
deleteParasitics(); deleteParasitics();
parasitics_per_corner_ = per_corner; parasitics_per_corner_ = per_corner;
parasitics_per_min_max_ = per_min_max;
makeParasiticAnalysisPts(); makeParasiticAnalysisPts();
} }
} }
@ -3933,8 +3918,7 @@ Sta::setParasiticAnalysisPts(bool per_corner,
void void
Sta::makeParasiticAnalysisPts() Sta::makeParasiticAnalysisPts()
{ {
corners_->makeParasiticAnalysisPts(parasitics_per_corner_, corners_->makeParasiticAnalysisPts(parasitics_per_corner_);
parasitics_per_min_max_);
} }
void void
@ -4434,7 +4418,7 @@ Sta::connectLoadPinAfter(Vertex *vertex)
void void
Sta::disconnectPinBefore(const Pin *pin) Sta::disconnectPinBefore(const Pin *pin)
{ {
parasitics_->disconnectPinBefore(pin); parasitics_->disconnectPinBefore(pin, network_);
sdc_->disconnectPinBefore(pin); sdc_->disconnectPinBefore(pin);
sim_->disconnectPinBefore(pin); sim_->disconnectPinBefore(pin);
if (graph_) { if (graph_) {

View File

@ -100,8 +100,7 @@ private:
DcalcAPIndex dcalc_ap_index); DcalcAPIndex dcalc_ap_index);
void writeStageParasitics(Stage stage); void writeStageParasitics(Stage stage);
void writeStageParasiticNetwork(Pin *drvr_pin, void writeStageParasiticNetwork(Pin *drvr_pin,
Parasitic *parasitic, Parasitic *parasitic);
ParasiticAnalysisPt *parasitic_ap);
void writeStagePiElmore(Pin *drvr_pin, void writeStagePiElmore(Pin *drvr_pin,
Parasitic *parasitic); Parasitic *parasitic);
void writeNullParasitics(Pin *drvr_pin); 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 void
WritePathSpice::writeStageParasitics(Stage stage) WritePathSpice::writeStageParasitics(Stage stage)
{ {
@ -1361,7 +1312,7 @@ WritePathSpice::writeStageParasitics(Stage stage)
ParasiticAnalysisPt *parasitic_ap = dcalc_ap->parasiticAnalysisPt(); ParasiticAnalysisPt *parasitic_ap = dcalc_ap->parasiticAnalysisPt();
Parasitic *parasitic = parasitics_->findParasiticNetwork(drvr_pin, parasitic_ap); Parasitic *parasitic = parasitics_->findParasiticNetwork(drvr_pin, parasitic_ap);
if (parasitic) if (parasitic)
writeStageParasiticNetwork(drvr_pin, parasitic, parasitic_ap); writeStageParasiticNetwork(drvr_pin, parasitic);
else { else {
const RiseFall *drvr_rf = drvr_path->transition(this); const RiseFall *drvr_rf = drvr_path->transition(this);
parasitic = parasitics_->findPiElmore(drvr_pin, drvr_rf, parasitic_ap); parasitic = parasitics_->findPiElmore(drvr_pin, drvr_rf, parasitic_ap);
@ -1376,51 +1327,51 @@ WritePathSpice::writeStageParasitics(Stage stage)
void void
WritePathSpice::writeStageParasiticNetwork(Pin *drvr_pin, WritePathSpice::writeStageParasiticNetwork(Pin *drvr_pin,
Parasitic *parasitic, Parasitic *parasitic)
ParasiticAnalysisPt *parasitic_ap)
{ {
Set<const Pin*> reachable_pins; Set<const Pin*> reachable_pins;
int res_index = 1; int res_index = 1;
int cap_index = 1; int cap_index = 1;
// Sort devices for consistent regression results. // Sort resistors for consistent regression results.
Vector<ParasiticDevice*> devices; ParasiticResistorSeq resistors = parasitics_->resistors(parasitic);
ParasiticDeviceIterator *device_iter1 = parasitics_->deviceIterator(parasitic); sort(resistors.begin(), resistors.end(),
while (device_iter1->hasNext()) { [=] (const ParasiticResistor *r1,
ParasiticDevice *device = device_iter1->next(); const ParasiticResistor *r2) {
devices.push_back(device); 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_)); ParasiticCapacitorSeq capacitors = parasitics_->capacitors(parasitic);
sort(capacitors.begin(), capacitors.end(),
for (ParasiticDevice *device : devices) { [=] (const ParasiticCapacitor *c1,
float resistance = parasitics_->value(device, parasitic_ap); const ParasiticCapacitor *c2) {
if (parasitics_->isResistor(device)) { return parasitics_->id(c1) < parasitics_->id(c2);
ParasiticNode *node1 = parasitics_->node1(device); });
ParasiticNode *node2 = parasitics_->node2(device); for (ParasiticCapacitor *capacitor : capacitors) {
streamPrint(spice_stream_, "R%d %s %s %.3e\n", // Ground coupling caps for now.
res_index, ParasiticNode *node1 = parasitics_->node1(capacitor);
nodeName(node1), float cap = parasitics_->value(capacitor);
nodeName(node2), streamPrint(spice_stream_, "C%d %s 0 %.3e\n",
resistance); cap_index,
res_index++; nodeName(node1),
cap);
const Pin *pin1 = parasitics_->connectionPin(node1); cap_index++;
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++;
}
} }
// Add resistors from drvr to load for missing parasitic connections. // Add resistors from drvr to load for missing parasitic connections.
@ -1442,17 +1393,17 @@ WritePathSpice::writeStageParasiticNetwork(Pin *drvr_pin,
delete pin_iter; delete pin_iter;
// Sort node capacitors for consistent regression results. // Sort node capacitors for consistent regression results.
Vector<ParasiticNode*> nodes; ParasiticNodeSeq nodes = parasitics_->nodes(parasitic);
ParasiticNodeIterator *node_iter = parasitics_->nodeIterator(parasitic); sort(nodes.begin(), nodes.end(),
while (node_iter->hasNext()) { [=] (const ParasiticNode *node1,
ParasiticNode *node = node_iter->next(); const ParasiticNode *node2) {
nodes.push_back(node); const char *name1 = parasitics_->name(node1);
} const char *name2 = parasitics_->name(node2);
return stringLess(name1, name2);
sort(nodes, ParasiticNodeLess(parasitics_)); });
for (ParasiticNode *node : nodes) { for (ParasiticNode *node : nodes) {
float cap = parasitics_->nodeGndCap(node, parasitic_ap); float cap = parasitics_->nodeGndCap(node);
// Spice has a cow over zero value caps. // Spice has a cow over zero value caps.
if (cap > 0.0) { if (cap > 0.0) {
streamPrint(spice_stream_, "C%d %s 0 %.3e\n", streamPrint(spice_stream_, "C%d %s 0 %.3e\n",
@ -1462,7 +1413,6 @@ WritePathSpice::writeStageParasiticNetwork(Pin *drvr_pin,
cap_index++; cap_index++;
} }
} }
delete node_iter;
} }
void void
@ -1556,7 +1506,7 @@ WritePathSpice::initNodeMap(const char *net_name)
const char * const char *
WritePathSpice::nodeName(ParasiticNode *node) WritePathSpice::nodeName(ParasiticNode *node)
{ {
const Pin *pin = parasitics_->connectionPin(node); const Pin *pin = parasitics_->pin(node);
if (pin) if (pin)
return parasitics_->name(node); return parasitics_->name(node);
else { else {

View File

@ -392,6 +392,7 @@ proc get_ports_or_pins { pattern } {
################################################################ ################################################################
# -corner keyword is optional.
# If -corner keyword is missing: # If -corner keyword is missing:
# one corner: return default # one corner: return default
# multiple corners: error # multiple corners: error
@ -414,7 +415,6 @@ proc parse_corner { keys_var } {
} }
# -corner keyword is required. # -corner keyword is required.
# Assumes caller checks for existence of -corner keyword arg.
proc parse_corner_required { keys_var } { proc parse_corner_required { keys_var } {
upvar 1 $keys_var keys upvar 1 $keys_var keys

View File

@ -3064,6 +3064,12 @@ endpoints()
return Sta::sta()->endpointPins(); return Sta::sta()->endpointPins();
} }
size_t
endpoint_count()
{
return Sta::sta()->endpointPins().size();
}
PinSet PinSet
group_path_pins(const char *group_path_name) group_path_pins(const char *group_path_name)
{ {

View File

@ -1168,21 +1168,6 @@ using namespace sta;
Tcl_SetObjResult(interp, obj); 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 { %typemap(out) Arrival {
Tcl_SetObjResult(interp,Tcl_NewDoubleObj(delayAsFloat($1))); Tcl_SetObjResult(interp,Tcl_NewDoubleObj(delayAsFloat($1)));
} }

View File

@ -157,7 +157,9 @@ RiseFallMinMax::setValues(RiseFallMinMax *values)
void void
RiseFallMinMax::value(const RiseFall *rf, RiseFallMinMax::value(const RiseFall *rf,
const MinMax *min_max, const MinMax *min_max,
float &value, bool &exists) const // Return values.
float &value,
bool &exists) const
{ {
exists = exists_[rf->index()][min_max->index()]; exists = exists_[rf->index()][min_max->index()];
if (exists) if (exists)