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/EstimateParasitics.cc
parasitics/NullParasitics.cc
parasitics/Parasitics.cc
parasitics/ReduceParasitics.cc
parasitics/ReportParasiticAnnotation.cc

View File

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

View File

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

View File

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

View File

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

View File

@ -23,6 +23,7 @@
#include "Network.hh"
#include "Parasitics.hh"
#include "Sdc.hh"
#include "Corner.hh"
#include "DcalcAnalysisPt.hh"
namespace sta {
@ -34,6 +35,35 @@ DelayCalcBase::DelayCalcBase(StaState *sta) :
{
}
void
DelayCalcBase::reduceParasitic(const Parasitic *parasitic_network,
const Net *net,
const Corner *corner,
const MinMaxAll *min_max)
{
NetConnectedPinIterator *pin_iter = network_->connectedPinIterator(net);
while (pin_iter->hasNext()) {
const Pin *pin = pin_iter->next();
if (network_->isDriver(pin)) {
for (RiseFall *rf : RiseFall::range()) {
for (const MinMax *min_max : min_max->range()) {
if (corner == nullptr) {
for (const Corner *corner1 : *corners_) {
DcalcAnalysisPt *dcalc_ap = corner1->findDcalcAnalysisPt(min_max);
reduceParasitic(parasitic_network, pin, rf, dcalc_ap);
}
}
else {
DcalcAnalysisPt *dcalc_ap = corner->findDcalcAnalysisPt(min_max);
reduceParasitic(parasitic_network, pin, rf, dcalc_ap);
}
}
}
}
}
delete pin_iter;
}
TimingModel *
DelayCalcBase::model(const TimingArc *arc,
const DcalcAnalysisPt *dcalc_ap) const
@ -67,12 +97,6 @@ DelayCalcBase::checkModel(const TimingArc *arc,
void
DelayCalcBase::finishDrvrPin()
{
for (auto parasitic : unsaved_parasitics_)
parasitics_->deleteUnsavedParasitic(parasitic);
unsaved_parasitics_.clear();
for (auto drvr_pin : reduced_parasitic_drvrs_)
parasitics_->deleteDrvrReducedParasitics(drvr_pin);
reduced_parasitic_drvrs_.clear();
}
// For DSPF on an input port the elmore delay is used as the time

View File

@ -28,13 +28,18 @@ public:
explicit DelayCalcBase(StaState *sta);
void finishDrvrPin() override;
void reduceParasitic(const Parasitic *parasitic_network,
const Net *net,
const Corner *corner,
const MinMaxAll *min_max) override;
ArcDelay checkDelay(const Pin *check_pin,
const TimingArc *arc,
const Slew &from_slew,
const Slew &to_slew,
float related_out_cap,
const DcalcAnalysisPt *dcalc_ap) override;
string reportCheckDelay(const Pin *check_pin,
const TimingArc *arc,
const Slew &from_slew,
@ -72,11 +77,7 @@ protected:
const Pvt *pinPvt(const Pin *pin,
const DcalcAnalysisPt *dcalc_ap);
// Parasitics returned by findParasitic that are reduced or estimated
// that can be deleted after delay calculation for the driver pin
// is finished.
Vector<Parasitic*> unsaved_parasitics_;
Vector<const Pin *> reduced_parasitic_drvrs_;
using ArcDelayCalc::reduceParasitic;
};
} // namespace

View File

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

View File

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

View File

@ -23,6 +23,7 @@
#include "TimingArc.hh"
#include "TimingModel.hh"
#include "Liberty.hh"
#include "PortDirection.hh"
#include "Network.hh"
#include "Sdc.hh"
#include "Parasitics.hh"
@ -58,53 +59,46 @@ LumpedCapDelayCalc::findParasitic(const Pin *drvr_pin,
Parasitic *parasitic = nullptr;
const Corner *corner = dcalc_ap->corner();
// set_load net has precedence over parasitics.
if (!sdc_->drvrPinHasWireCap(drvr_pin, corner)) {
const ParasiticAnalysisPt *parasitic_ap = dcalc_ap->parasiticAnalysisPt();
if (parasitics_->haveParasitics()) {
// Prefer PiElmore.
parasitic = parasitics_->findPiElmore(drvr_pin, rf, parasitic_ap);
if (parasitic == nullptr) {
Parasitic *parasitic_network =
parasitics_->findParasiticNetwork(drvr_pin, parasitic_ap);
if (parasitic_network) {
parasitics_->reduceToPiElmore(parasitic_network, drvr_pin,
dcalc_ap->operatingConditions(),
corner,
dcalc_ap->constraintMinMax(),
parasitic_ap);
parasitic = parasitics_->findPiElmore(drvr_pin, rf, parasitic_ap);
reduced_parasitic_drvrs_.push_back(drvr_pin);
}
}
}
else {
const MinMax *cnst_min_max = dcalc_ap->constraintMinMax();
Wireload *wireload = sdc_->wireload(cnst_min_max);
if (wireload) {
float pin_cap, wire_cap, fanout;
bool has_net_load;
graph_delay_calc_->netCaps(drvr_pin, rf, dcalc_ap,
pin_cap, wire_cap, fanout, has_net_load);
parasitic = parasitics_->estimatePiElmore(drvr_pin, rf, wireload,
fanout, pin_cap,
dcalc_ap->operatingConditions(),
corner,
cnst_min_max,
parasitic_ap);
// Estimated parasitics are not recorded in the "database", so save
// it for deletion after the drvr pin delay calc is finished.
if (parasitic)
unsaved_parasitics_.push_back(parasitic);
}
}
if (sdc_->drvrPinHasWireCap(drvr_pin, corner)
|| network_->direction(drvr_pin)->isInternal())
return nullptr;
const ParasiticAnalysisPt *parasitic_ap = dcalc_ap->parasiticAnalysisPt();
// Prefer PiElmore.
parasitic = parasitics_->findPiElmore(drvr_pin, rf, parasitic_ap);
if (parasitic)
return parasitic;
Parasitic *parasitic_network = parasitics_->findParasiticNetwork(drvr_pin,
parasitic_ap);
if (parasitic_network) {
parasitic = reduceParasitic(parasitic_network, drvr_pin, rf, dcalc_ap);
if (parasitic)
return parasitic;
}
const MinMax *min_max = dcalc_ap->constraintMinMax();
Wireload *wireload = sdc_->wireload(min_max);
if (wireload) {
float pin_cap, wire_cap, fanout;
bool has_net_load;
graph_delay_calc_->netCaps(drvr_pin, rf, dcalc_ap,
pin_cap, wire_cap, fanout, has_net_load);
parasitic = parasitics_->estimatePiElmore(drvr_pin, rf, wireload, fanout,
pin_cap, corner, min_max);
}
return parasitic;
}
ReducedParasiticType
LumpedCapDelayCalc::reducedParasiticType() const
Parasitic *
LumpedCapDelayCalc::reduceParasitic(const Parasitic *parasitic_network,
const Pin *drvr_pin,
const RiseFall *rf,
const DcalcAnalysisPt *dcalc_ap)
{
return ReducedParasiticType::pi_elmore;
const Corner *corner = dcalc_ap->corner();
const ParasiticAnalysisPt *parasitic_ap = dcalc_ap->parasiticAnalysisPt();
return parasitics_->reduceToPiElmore(parasitic_network, drvr_pin, rf,
corner, dcalc_ap->constraintMinMax(),
parasitic_ap);
}
ArcDcalcResult

View File

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

View File

@ -45,10 +45,21 @@ UnitDelayCalc::findParasitic(const Pin *,
return nullptr;
}
ReducedParasiticType
UnitDelayCalc::reducedParasiticType() const
Parasitic *
UnitDelayCalc::reduceParasitic(const Parasitic *,
const Pin *,
const RiseFall *,
const DcalcAnalysisPt *)
{
return nullptr;
}
void
UnitDelayCalc::reduceParasitic(const Parasitic *,
const Net *,
const Corner *,
const MinMaxAll *)
{
return ReducedParasiticType::none;
}
ArcDcalcResult

View File

@ -29,7 +29,14 @@ public:
Parasitic *findParasitic(const Pin *drvr_pin,
const RiseFall *rf,
const DcalcAnalysisPt *dcalc_ap) override;
ReducedParasiticType reducedParasiticType() const override;
Parasitic *reduceParasitic(const Parasitic *parasitic_network,
const Pin *drvr_pin,
const RiseFall *rf,
const DcalcAnalysisPt *dcalc_ap) override;
void reduceParasitic(const Parasitic *parasitic_network,
const Net *net,
const Corner *corner,
const MinMaxAll *min_max) override;
ArcDcalcResult inputPortDelay(const Pin *port_pin,
float in_slew,
const RiseFall *rf,

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

Binary file not shown.

Binary file not shown.

View File

@ -124,7 +124,18 @@ public:
virtual Parasitic *findParasitic(const Pin *drvr_pin,
const RiseFall *rf,
const DcalcAnalysisPt *dcalc_ap) = 0;
virtual ReducedParasiticType reducedParasiticType() const = 0;
// Reduce parasitic_network to a representation acceptable to the delay calculator.
virtual Parasitic *reduceParasitic(const Parasitic *parasitic_network,
const Pin *drvr_pin,
const RiseFall *rf,
const DcalcAnalysisPt *dcalc_ap) = 0;
// Reduce parasitic_network to a representation acceptable to the delay calculator
// for one or more corners and min/max rise/fall.
// Null corner means reduce all corners.
virtual void reduceParasitic(const Parasitic *parasitic_network,
const Net *net,
const Corner *corner,
const MinMaxAll *min_max) = 0;
// Find the wire delays and slews for an input port without a driving cell.
// This call primarily initializes the load delay/slew iterator.
virtual ArcDcalcResult inputPortDelay(const Pin *port_pin,

View File

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

View File

@ -72,41 +72,26 @@ public:
// delays to be recomputed during incremental delay calculation.
virtual float incrementalDelayTolerance();
virtual void setIncrementalDelayTolerance(float tol);
// Load pin_cap + wire_cap.
virtual float loadCap(const Pin *drvr_pin,
const RiseFall *drvr_rf,
const DcalcAnalysisPt *dcalc_ap) const;
// Load pin_cap + wire_cap including parasitic min/max for rise/fall.
virtual float loadCap(const Pin *drvr_pin,
const DcalcAnalysisPt *dcalc_ap) const;
// pin_cap = net pin capacitances + port external pin capacitance,
// wire_cap = annotated net capacitance + port external wire capacitance.
virtual void loadCap(const Pin *drvr_pin,
const Parasitic *parasitic,
const RiseFall *rf,
const DcalcAnalysisPt *dcalc_ap,
// Return values.
float &pin_cap,
float &wire_cap) const;
// Load pin_cap + wire_cap including parasitic.
virtual float loadCap(const Pin *drvr_pin,
const Parasitic *parasitic,
const RiseFall *rf,
const DcalcAnalysisPt *dcalc_ap) const;
float loadCap(const Pin *drvr_pin,
const Parasitic *parasitic,
const RiseFall *rf,
const DcalcAnalysisPt *dcalc_ap,
const MultiDrvrNet *multi_drvr) const;
virtual void netCaps(const Pin *drvr_pin,
const RiseFall *rf,
const DcalcAnalysisPt *dcalc_ap,
// Return values.
float &pin_cap,
float &wire_cap,
float &fanout,
bool &has_set_load) const;
PinSeq loadPins(Vertex *drvr_vertex);
const DcalcAnalysisPt *dcalc_ap) const;
float loadCap(const Pin *drvr_pin,
const RiseFall *rf,
const DcalcAnalysisPt *dcalc_ap) const;
void loadCap(const Pin *drvr_pin,
const RiseFall *rf,
const DcalcAnalysisPt *dcalc_ap,
// Return values.
float &pin_cap,
float &wire_cap) const;
void netCaps(const Pin *drvr_pin,
const RiseFall *rf,
const DcalcAnalysisPt *dcalc_ap,
// Return values.
float &pin_cap,
float &wire_cap,
float &fanout,
bool &has_set_load) const;
LoadPinIndexMap makeLoadPinIndexMap(Vertex *drvr_vertex);
void findDriverArcDelays(Vertex *drvr_vertex,
Edge *edge,
@ -242,11 +227,36 @@ protected:
const RiseFall *from_rf,
const DcalcAnalysisPt *dcalc_ap);
bool bidirectDrvrSlewFromLoad(const Vertex *vertex) const;
void loadCap(const Parasitic *parasitic,
bool has_set_load,
// Return values.
float &pin_cap,
float &wire_cap) const;
float loadCap(const Pin *drvr_pin,
const RiseFall *rf,
const DcalcAnalysisPt *dcalc_ap,
ArcDelayCalc *arc_delay_calc) const;
void parasiticLoad(const Pin *drvr_pin,
const RiseFall *rf,
const DcalcAnalysisPt *dcalc_ap,
const MultiDrvrNet *multi_drvr,
ArcDelayCalc *arc_delay_calc,
// Return values.
float &cap,
const Parasitic *&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.
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
#include <complex>
#include <map>
#include <vector>
#include "StaState.hh"
#include "LibertyClass.hh"
@ -31,16 +33,17 @@ class Corner;
typedef std::complex<float> ComplexFloat;
typedef Vector<ComplexFloat> ComplexFloatSeq;
typedef Iterator<ParasiticDevice*> ParasiticDeviceIterator;
typedef Iterator<ParasiticNode*> ParasiticNodeIterator;
typedef std::vector<ParasiticNode*> ParasiticNodeSeq;
typedef std::vector<ParasiticResistor*> ParasiticResistorSeq;
typedef std::vector<ParasiticCapacitor*> ParasiticCapacitorSeq;
typedef std::map<ParasiticNode *, ParasiticResistorSeq> ParasiticNodeResistorMap;
typedef std::map<ParasiticNode *, ParasiticCapacitorSeq> ParasiticNodeCapacitorMap;
// Parasitics API.
// All parasitic parameters can have multiple values, each corresponding
// to an analysis point.
// Parasitic annotation for a pin or net may exist for one analysis point
// and not another.
// If there is only one parasitic for both rise and fall transitions
// the parasitic readers will save it under the rise transition.
class Parasitics : public StaState
{
public:
@ -50,8 +53,6 @@ public:
// Clear all state.
virtual void clear() = 0;
// Save parasitics to database file.
virtual void save() = 0;
// Delete all parasitics.
virtual void deleteParasitics() = 0;
// Delete all parasitics on net at analysis point.
@ -60,7 +61,6 @@ public:
// Delete all parasitics on pin at analysis point.
virtual void deleteParasitics(const Pin *pin,
const ParasiticAnalysisPt *ap) = 0;
virtual void deleteUnsavedParasitic(Parasitic *parasitic) = 0;
virtual void deleteReducedParasitics(const Net *net,
const ParasiticAnalysisPt *ap) = 0;
virtual void deleteDrvrReducedParasitics(const Pin *drvr_pin) = 0;
@ -153,8 +153,9 @@ public:
virtual Parasitic *makeParasiticNetwork(const Net *net,
bool includes_pin_caps,
const ParasiticAnalysisPt *ap) = 0;
virtual ParasiticDeviceIterator *deviceIterator(const Parasitic *parasitic) = 0;
virtual ParasiticNodeIterator *nodeIterator(const Parasitic *parasitic) = 0;
virtual ParasiticNodeSeq nodes(const Parasitic *parasitic) const = 0;
virtual ParasiticResistorSeq resistors(const Parasitic *parasitic) const = 0;
virtual ParasiticCapacitorSeq capacitors(const Parasitic *parasitic) const = 0;
// Delete parasitic network if it exists.
virtual void deleteParasiticNetwork(const Net *net,
const ParasiticAnalysisPt *ap) = 0;
@ -165,130 +166,98 @@ public:
// Make a subnode of the parasitic network net.
virtual ParasiticNode *ensureParasiticNode(Parasitic *parasitic,
const Net *net,
int id) = 0;
int id,
const Network *network) = 0;
// Make a subnode of the parasitic network net connected to pin.
virtual ParasiticNode *ensureParasiticNode(Parasitic *parasitic,
const Pin *pin) = 0;
const Pin *pin,
const Network *network) = 0;
// Increment the grounded capacitance on node.
virtual void incrCap(ParasiticNode *node,
float cap,
const ParasiticAnalysisPt *ap) = 0;
// Coupling capacitor between parasitic nodes on a net.
// name is optional. The device takes ownership of the name string.
virtual void makeCouplingCap(const char *name,
ParasiticNode *node,
ParasiticNode *other_node,
float cap,
const ParasiticAnalysisPt *ap) = 0;
// Coupling capacitor to parasitic node on a different net.
// name is optional. The device takes ownership of the name string.
virtual void makeCouplingCap(const char *name,
ParasiticNode *node,
Net *other_node_net,
int other_node_id,
float cap,
const ParasiticAnalysisPt *ap) = 0;
// Coupling capacitor to pin on a different net.
// name is optional. The device takes ownership of the name string.
virtual void makeCouplingCap(const char *name,
ParasiticNode *node,
Pin *other_node_pin,
float cap,
const ParasiticAnalysisPt *ap) = 0;
// name is optional. The device takes ownership of the name string.
virtual void makeResistor(const char *name,
ParasiticNode *node1,
ParasiticNode *node2,
float res,
const ParasiticAnalysisPt *ap) = 0;
// Check integrity of parasitic network.
void check(Parasitic *parasitic) const;
float cap) = 0;
virtual const char *name(const ParasiticNode *node) = 0;
virtual const Pin *connectionPin(const ParasiticNode *node) const = 0;
virtual const Pin *pin(const ParasiticNode *node) const = 0;
virtual const Net *net(const ParasiticNode *node,
const Network *network) const = 0;
virtual bool isExternal(const ParasiticNode *node) const = 0;
// Find the parasitic node connected to pin.
virtual ParasiticNode *findNode(const Parasitic *parasitic,
const Pin *pin) const = 0;
// Node capacitance to ground.
virtual float nodeGndCap(const ParasiticNode *node,
const ParasiticAnalysisPt *ap) const = 0;
virtual ParasiticDeviceIterator *
deviceIterator(ParasiticNode *node) const = 0;
virtual bool isResistor(const ParasiticDevice *device) const = 0;
virtual bool isCouplingCap(const ParasiticDevice *device) const = 0;
virtual const char *name(const ParasiticDevice *device) const = 0;
// Device "value" (resistance, capacitance).
virtual float value(const ParasiticDevice *device,
const ParasiticAnalysisPt *ap) const = 0;
virtual ParasiticNode *node1(const ParasiticDevice *device) const = 0;
virtual ParasiticNode *node2(const ParasiticDevice *device) const = 0;
virtual ParasiticNode *otherNode(const ParasiticDevice *device,
ParasiticNode *node) const = 0;
virtual float nodeGndCap(const ParasiticNode *node) const = 0;
// Return true if all loads are annoatated.
virtual bool checkAnnotation(Parasitic *parasitic_network,
const Pin *drvr_pin) = 0;
virtual bool checkAnnotation(const Pin *drvr_pin,
ParasiticNode *drvr_node) = 0;
// Return loads missing path from driver.
virtual PinSet unannotatedLoads(Parasitic *parasitic_network,
const Pin *drvr_pin) = 0;
// Coupling capacitor between parasitic nodes on a net.
virtual void makeCapacitor(Parasitic *parasitic,
size_t id,
float cap,
ParasiticNode *node1,
ParasiticNode *node2) = 0;
virtual size_t id(const ParasiticCapacitor *capacitor) const = 0;
virtual float value(const ParasiticCapacitor *capacitor) const = 0;
virtual ParasiticNode *node1(const ParasiticCapacitor *capacitor) const = 0;
virtual ParasiticNode *node2(const ParasiticCapacitor *capacitor) const = 0;
virtual ParasiticNode *otherNode(const ParasiticCapacitor *capacitor,
ParasiticNode *node) const;
virtual void makeResistor(Parasitic *parasitic,
size_t id,
float res,
ParasiticNode *node1,
ParasiticNode *node2) = 0;
virtual size_t id(const ParasiticResistor *resistor) const = 0;
virtual float value(const ParasiticResistor *resistor) const = 0;
virtual ParasiticNode *node1(const ParasiticResistor *resistor) const = 0;
virtual ParasiticNode *node2(const ParasiticResistor *resistor) const = 0;
virtual ParasiticNode *otherNode(const ParasiticResistor *capacitor,
ParasiticNode *node) const;
// Iteration over resistors connected to a nodes.
// ParasiticNodeResistorMap resistor_map =
// parasitics_->parasiticNodeResistorMap(parasitic_network);
// ParasiticResistorSeq &resistors = resistor_map_[node];
// for (ParasiticResistor *resistor : resistors) {
// }
ParasiticNodeResistorMap parasiticNodeResistorMap(const Parasitic *parasitic) const;
ParasiticNodeCapacitorMap parasiticNodeCapacitorMap(const Parasitic *parasitic) const;
// Filters loads that are missing path from driver.
virtual PinSet unannotatedLoads(const Parasitic *parasitic,
const Pin *drvr_pin) const = 0;
// unannotatedLoads helper.
PinSet loads(const Pin *drvr_pin) const;
// Reduce parasitic network to reduce_to model.
virtual void reduceTo(const Parasitic *parasitic,
const Net *net,
ReducedParasiticType reduce_to,
const OperatingConditions *op_cond,
const Corner *corner,
const MinMax *cnst_min_max,
const ParasiticAnalysisPt *ap) = 0;
// Reduce parasitic network to pi elmore models.
virtual void reduceToPiElmore(const Parasitic *parasitic,
const Net *net,
const OperatingConditions *op_cond,
const Corner *corner,
const MinMax *cnst_min_max,
const ParasiticAnalysisPt *ap) = 0;
// Reduce parasitic network to pi elmore model for drvr_pin.
virtual void reduceToPiElmore(const Parasitic *parasitic,
const Pin *drvr_pin,
const OperatingConditions *op_cond,
const Corner *corner,
const MinMax *cnst_min_max,
const ParasiticAnalysisPt *ap) = 0;
// Reduce parasitic network to pi and 2nd order pole/residue models.
virtual void reduceToPiPoleResidue2(const Parasitic *parasitic,
const Net *net,
const OperatingConditions *op_cond,
const Corner *corner,
const MinMax *cnst_min_max,
const ParasiticAnalysisPt *ap) = 0;
Parasitic *reduceToPiElmore(const Parasitic *parasitic,
const Pin *drvr_pin,
const RiseFall *rf,
const Corner *corner,
const MinMax *cnst_min_max,
const ParasiticAnalysisPt *ap);
// Reduce parasitic network to pi and 2nd order pole/residue models
// for drvr_pin.
virtual void reduceToPiPoleResidue2(const Parasitic *parasitic,
const Pin *drvr_pin,
const OperatingConditions *op_cond,
const Corner *corner,
const MinMax *cnst_min_max,
const ParasiticAnalysisPt *ap) = 0;
Parasitic *reduceToPiPoleResidue2(const Parasitic *parasitic,
const Pin *drvr_pin,
const RiseFall *rf,
const Corner *corner,
const MinMax *cnst_min_max,
const ParasiticAnalysisPt *ap);
// Estimate parasitic as pi elmore using wireload model.
virtual Parasitic *estimatePiElmore(const Pin *drvr_pin,
const RiseFall *rf,
const Wireload *wireload,
float fanout,
float net_pin_cap,
const OperatingConditions *op_cond,
const Corner *corner,
const MinMax *min_max,
const ParasiticAnalysisPt *ap) = 0;
Parasitic *estimatePiElmore(const Pin *drvr_pin,
const RiseFall *rf,
const Wireload *wireload,
float fanout,
float net_pin_cap,
const Corner *corner,
const MinMax *min_max);
Parasitic *makeWireloadNetwork(const Pin *drvr_pin,
const Wireload *wireload,
float fanout,
const OperatingConditions *op_cond,
const MinMax *min_max,
const ParasiticAnalysisPt *ap);
// Network edit before/after methods.
virtual void disconnectPinBefore(const Pin *pin) = 0;
virtual void disconnectPinBefore(const Pin *pin,
const Network *network) = 0;
virtual void loadPinCapacitanceChanged(const Pin *pin) = 0;
protected:
@ -296,20 +265,17 @@ protected:
const Pin *drvr_pin,
float wireload_cap,
float wireload_res,
float fanout,
const ParasiticAnalysisPt *ap);
float fanout);
void makeWireloadNetworkBest(Parasitic *parasitic,
const Pin *drvr_pin,
float wireload_cap,
float wireload_res,
float fanout,
const ParasiticAnalysisPt *ap);
float fanout);
void makeWireloadNetworkBalanced(Parasitic *parasitic,
const Pin *drvr_pin,
float wireload_cap,
float wireload_res,
float fanout,
const ParasiticAnalysisPt *ap);
float fanout);
const Net *findParasiticNet(const Pin *pin) const;
};
@ -320,19 +286,18 @@ class ParasiticAnalysisPt
public:
ParasiticAnalysisPt(const char *name,
int index,
const MinMax *min_max);
~ParasiticAnalysisPt();
const char *name() const { return name_; }
int index_max);
const char *name() const { return name_.c_str(); }
int index() const { return index_; }
const MinMax *minMax() const { return min_max_; }
int indexMax() const { return index_max_; }
// Coupling capacitor factor used by all reduction functions.
float couplingCapFactor() const { return coupling_cap_factor_; }
void setCouplingCapFactor(float factor);
private:
const char *name_;
string name_;
int index_;
const MinMax *min_max_;
int index_max_;
float coupling_cap_factor_;
};

View File

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

View File

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

View File

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

File diff suppressed because it is too large Load Diff

View File

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

View File

@ -16,38 +16,38 @@
#pragma once
#include <map>
#include <set>
#include "Parasitics.hh"
namespace sta {
class ConcretePoleResidue;
class ConcreteParasiticDevice;
class ConcreteParasiticPinNode;
class ConcreteParasiticSubNode;
class ConcreteParasiticNode;
typedef Map<const Pin*, float> ConcreteElmoreLoadMap;
typedef ConcreteElmoreLoadMap::Iterator ConcretePiElmoreLoadIterator;
typedef Map<const Pin*, ConcretePoleResidue*> ConcretePoleResidueMap;
typedef std::map<const Pin*, float> ConcreteElmoreLoadMap;
typedef std::map<const Pin*, ConcretePoleResidue> ConcretePoleResidueMap;
typedef std::pair<const Net*, int> NetIdPair;
struct NetIdPairLess
{
bool operator()(const NetIdPair *net_id1,
const NetIdPair *net_id2) const;
bool operator()(const NetIdPair &net_id1,
const NetIdPair &net_id2) const;
};
typedef Map<NetIdPair*, ConcreteParasiticSubNode*,
NetIdPairLess > ConcreteParasiticSubNodeMap;
typedef Map<const Pin*,
ConcreteParasiticPinNode*> ConcreteParasiticPinNodeMap;
typedef Vector<ConcreteParasiticDevice*> ConcreteParasiticDeviceSeq;
typedef Set<ConcreteParasiticDevice*> ConcreteParasiticDeviceSet;
typedef Vector<ConcreteParasiticNode*> ConcreteParasiticNodeSeq;
typedef std::map<NetIdPair,ConcreteParasiticNode*,
NetIdPairLess> ConcreteParasiticSubNodeMap;
typedef std::map<const Pin*, ConcreteParasiticNode*> ConcreteParasiticPinNodeMap;
typedef std::set<ParasiticNode*> ParasiticNodeSet;
typedef std::set<ParasiticResistor*> ParasiticResistorSet;
typedef std::vector<ParasiticResistor*> ParasiticResistorSeq;
// Empty base class definitions so casts are not required on returned
// objects.
class Parasitic {};
class ParasiticNode {};
class ParasiticDevice {};
class ParasiticResistor {};
class ParasiticCapacitor {};
class ParasiticNetwork {};
// Base class for parasitics.
@ -78,8 +78,8 @@ public:
virtual void setPoleResidue(const Pin *load_pin,
ComplexFloatSeq *poles,
ComplexFloatSeq *residues);
virtual ParasiticDeviceIterator *deviceIterator() const;
virtual ParasiticNodeIterator *nodeIterator() const;
virtual PinSet unannotatedLoads(const Pin *drvr_pin,
const Parasitics *parasitics) const = 0;
};
// Pi model for a driver pin.
@ -114,70 +114,46 @@ public:
ConcretePiElmore(float c2,
float rpi,
float c1);
virtual ~ConcretePiElmore();
virtual bool isPiElmore() const { return true; }
virtual bool isPiModel() const { return true; }
virtual float capacitance() const;
virtual void piModel(float &c2, float &rpi, float &c1) const;
virtual void setPiModel(float c2, float rpi, float c1);
virtual bool isReducedParasiticNetwork() const;
virtual void setIsReduced(bool reduced);
virtual void findElmore(const Pin *load_pin, float &elmore,
bool &exists) const;
virtual void setElmore(const Pin *load_pin, float elmore);
bool isPiElmore() const override { return true; }
bool isPiModel() const override { return true; }
float capacitance() const override;
void piModel(float &c2,
float &rpi,
float &c1) const override;
void setPiModel(float c2,
float rpi,
float c1) override;
bool isReducedParasiticNetwork() const override;
void setIsReduced(bool reduced) override;
void findElmore(const Pin *load_pin,
float &elmore,
bool &exists) const override;
void setElmore(const Pin *load_pin,
float elmore) override;
PinSet unannotatedLoads(const Pin *drvr_pin,
const Parasitics *parasitics) const override;
void deleteLoad(const Pin *load_pin);
private:
ConcreteElmoreLoadMap *loads_;
};
// PiElmore from wireload model estimate.
class ConcretePiElmoreEstimated : public ConcretePi,
public ConcreteParasitic
{
public:
ConcretePiElmoreEstimated(float c2,
float rpi,
float c1,
float elmore_res,
float elmore_cap,
bool elmore_use_load_cap,
const RiseFall *rf,
const OperatingConditions *op_cond,
const Corner *corner,
const MinMax *min_max,
Sdc *sdc);
virtual float capacitance() const;
virtual bool isPiElmore() const { return true; }
virtual bool isPiModel() const { return true; }
virtual void piModel(float &c2, float &rpi, float &c1) const;
virtual void findElmore(const Pin *load_pin, float &elmore,
bool &exists) const;
virtual void setElmore(const Pin *load_pin, float elmore);
private:
float elmore_res_;
float elmore_cap_;
bool elmore_use_load_cap_;
const RiseFall *rf_;
const OperatingConditions *op_cond_;
const Corner *corner_;
const MinMax *min_max_;
Sdc *sdc_;
ConcreteElmoreLoadMap loads_;
};
class ConcretePoleResidue : public ConcreteParasitic
{
public:
ConcretePoleResidue(ComplexFloatSeq *poles,
ComplexFloatSeq *residues);
ConcretePoleResidue();
virtual ~ConcretePoleResidue();
virtual bool isPoleResidue() const { return true; }
size_t poleResidueCount() const;
void poleResidue(int index, ComplexFloat &pole, ComplexFloat &residue) const;
void setPoleResidue(ComplexFloatSeq *poles, ComplexFloatSeq *residues);
float capacitance() const { return 0.0; }
virtual bool isPoleResidue() const override { return true; }
float capacitance() const override { return 0.0; }
PinSet unannotatedLoads(const Pin *drvr_pin,
const Parasitics *parasitics) const override;
void setPoleResidue(ComplexFloatSeq *poles,
ComplexFloatSeq *residues);
void poleResidue(int index,
ComplexFloat &pole,
ComplexFloat &residue) const;
size_t poleResidueCount() const;
using ConcreteParasitic::setPoleResidue;
private:
@ -193,240 +169,147 @@ public:
ConcretePiPoleResidue(float c2,
float rpi,
float c1);
virtual ~ConcretePiPoleResidue();
virtual bool isPiPoleResidue() const { return true; }
virtual bool isPiModel() const { return true; }
virtual float capacitance() const;
virtual bool isPiPoleResidue() const override { return true; }
virtual bool isPiModel() const override { return true; }
virtual float capacitance() const override;
virtual void piModel(float &c2,
float &rpi,
float &c1) const;
float &c1) const override;
virtual void setPiModel(float c2,
float rpi,
float c1);
virtual bool isReducedParasiticNetwork() const;
virtual void setIsReduced(bool reduced);
virtual Parasitic *findPoleResidue(const Pin *load_pin) const;
float c1) override;
virtual bool isReducedParasiticNetwork() const override;
virtual void setIsReduced(bool reduced) override;
virtual Parasitic *findPoleResidue(const Pin *load_pin) const override;
virtual void setPoleResidue(const Pin *load_pin,
ComplexFloatSeq *poles,
ComplexFloatSeq *residues);
ComplexFloatSeq *residues) override;
virtual PinSet unannotatedLoads(const Pin *drvr_pin,
const Parasitics *parasitics) const override;
void deleteLoad(const Pin *load_pin);
private:
ConcretePoleResidueMap *load_pole_residue_;
};
class ConcreteParasiticNode : public ParasiticNode
{
public:
virtual ~ConcreteParasiticNode() {}
float capacitance() const;
virtual const char *name(const Network *network) const = 0;
virtual bool isPinNode() const { return false; }
ConcreteParasiticDeviceSeq *devices() { return &devices_; }
void incrCapacitance(float cap);
void addDevice(ConcreteParasiticDevice *device);
protected:
ConcreteParasiticNode();
float cap_;
ConcreteParasiticDeviceSeq devices_;
friend class ConcreteParasiticNetwork;
};
class ConcreteParasiticSubNode : public ConcreteParasiticNode
{
public:
ConcreteParasiticSubNode(const Net *net,
int id);
virtual const char *name(const Network *network) const;
private:
const Net *net_;
int id_;
};
class ConcreteParasiticPinNode : public ConcreteParasiticNode
{
public:
ConcreteParasiticPinNode(const Pin *pin);
const Pin *pin() const { return pin_; }
virtual bool isPinNode() const { return true; }
virtual const char *name(const Network *network) const;
private:
const Pin *pin_;
};
class ConcreteParasiticDevice : public ParasiticDevice
{
public:
ConcreteParasiticDevice(const char *name,
ConcreteParasiticNode *node,
float value);
virtual ~ConcreteParasiticDevice();
virtual bool isResistor() const { return false; }
virtual bool isCouplingCap() const { return false; }
const char *name() const { return name_; }
float value() const { return value_; }
ConcreteParasiticNode *node1() const { return node_; }
virtual ConcreteParasiticNode *node2() const = 0;
virtual ParasiticNode *otherNode(ParasiticNode *node) const = 0;
virtual void replaceNode(ConcreteParasiticNode *from_node,
ConcreteParasiticNode *to_node) = 0;
protected:
const char *name_;
ConcreteParasiticNode *node_;
float value_;
friend class ConcreteParasiticNetwork;
};
class ConcreteParasiticResistor : public ConcreteParasiticDevice
{
public:
ConcreteParasiticResistor(const char *name,
ConcreteParasiticNode *node,
ConcreteParasiticNode *other_node,
float res);
virtual bool isResistor() const { return true; }
virtual ConcreteParasiticNode *node2() const { return other_node_; }
virtual ParasiticNode *otherNode(ParasiticNode *node) const;
virtual void replaceNode(ConcreteParasiticNode *from_node,
ConcreteParasiticNode *to_node);
private:
ConcreteParasiticNode *other_node_;
};
// Base class for coupling capacitors.
class ConcreteCouplingCap : public ConcreteParasiticDevice
{
public:
ConcreteCouplingCap(const char *name,
ConcreteParasiticNode *node,
float cap);
virtual bool isCouplingCap() const { return true; }
virtual ConcreteParasiticNode *node2() const { return nullptr; }
virtual void replaceNode(ConcreteParasiticNode *from_node,
ConcreteParasiticNode *to_node);
};
class ConcreteCouplingCapInt : public ConcreteCouplingCap
{
public:
ConcreteCouplingCapInt(const char *name,
ConcreteParasiticNode *node,
ConcreteParasiticNode *other_node,
float cap);
virtual bool isCouplingCap() const { return true; }
virtual ConcreteParasiticNode *node2() const { return other_node_; }
virtual ParasiticNode *otherNode(ParasiticNode *node) const;
virtual void replaceNode(ConcreteParasiticNode *from_node,
ConcreteParasiticNode *to_node);
private:
ConcreteParasiticNode *other_node_;
};
class ConcreteCouplingCapExtNode : public ConcreteCouplingCap
{
public:
ConcreteCouplingCapExtNode(const char *name,
ConcreteParasiticNode *node,
Net *other_node_net,
int other_node_id,
float cap);
virtual bool isCouplingCap() const { return true; }
virtual ParasiticNode *otherNode(ParasiticNode *node) const;
virtual void replaceNode(ConcreteParasiticNode *from_node,
ConcreteParasiticNode *to_node);
private:
};
class ConcreteCouplingCapExtPin : public ConcreteCouplingCap
{
public:
ConcreteCouplingCapExtPin(const char *name,
ConcreteParasiticNode *node,
Pin *other_node_pin,
float cap);
virtual bool isCouplingCap() const { return true; }
virtual ParasiticNode *otherNode(ParasiticNode *node) const;
virtual void replaceNode(ConcreteParasiticNode *from_node,
ConcreteParasiticNode *to_node);
private:
};
class ConcreteParasiticDeviceSetIterator : public ParasiticDeviceIterator
{
public:
ConcreteParasiticDeviceSetIterator(ConcreteParasiticDeviceSet *devices);
virtual ~ConcreteParasiticDeviceSetIterator();
bool hasNext() { return iter_.hasNext(); }
ParasiticDevice *next() { return iter_.next(); }
private:
ConcreteParasiticDeviceSet::ConstIterator iter_;
};
class ConcreteParasiticDeviceSeqIterator : public ParasiticDeviceIterator
{
public:
ConcreteParasiticDeviceSeqIterator(ConcreteParasiticDeviceSeq *devices);
bool hasNext() { return iter_.hasNext(); }
ParasiticDevice *next() { return iter_.next(); }
private:
ConcreteParasiticDeviceSeq::ConstIterator iter_;
};
class ConcreteParasiticNodeSeqIterator : public ParasiticNodeIterator
{
public:
ConcreteParasiticNodeSeqIterator(ConcreteParasiticNodeSeq *devices);
virtual ~ConcreteParasiticNodeSeqIterator();
bool hasNext() { return iter_.hasNext(); }
ParasiticNode *next() { return iter_.next(); }
private:
ConcreteParasiticNodeSeq::ConstIterator iter_;
ConcretePoleResidueMap load_pole_residue_;
};
class ConcreteParasiticNetwork : public ParasiticNetwork,
public ConcreteParasitic
{
public:
ConcreteParasiticNetwork(bool includes_pin_caps);
ConcreteParasiticNetwork(const Net *net,
bool includes_pin_caps);
virtual ~ConcreteParasiticNetwork();
virtual bool isParasiticNetwork() const { return true; }
const Net *net() { return net_; }
bool includesPinCaps() const { return includes_pin_caps_; }
ConcreteParasiticNode *ensureParasiticNode(const Net *net,
int id);
int id,
const Network *network);
ConcreteParasiticNode *ensureParasiticNode(const Pin *pin,
const Network *network);
ConcreteParasiticNode *findNode(const Pin *pin) const;
ConcreteParasiticNode *ensureParasiticNode(const Pin *pin);
virtual float capacitance() const;
ConcreteParasiticPinNodeMap *pinNodes() { return &pin_nodes_; }
ConcreteParasiticSubNodeMap *subNodes() { return &sub_nodes_; }
ParasiticNodeSeq nodes() const;
void disconnectPin(const Pin *pin,
const Net *net);
virtual ParasiticDeviceIterator *deviceIterator() const;
virtual ParasiticNodeIterator *nodeIterator() const;
virtual void devices(// Return value.
ConcreteParasiticDeviceSet *devices) const;
const Net *net,
const Network *network);
ParasiticResistorSeq resistors() const { return resistors_; }
void addResistor(ParasiticResistor *resistor);
ParasiticCapacitorSeq capacitors() const { return capacitors_; }
void addCapacitor(ParasiticCapacitor *capacitor);
virtual PinSet unannotatedLoads(const Pin *drvr_pin,
const Parasitics *parasitics) const;
private:
void unannotatedLoads(ParasiticNode *node,
ParasiticResistor *from_res,
PinSet &loads,
ParasiticNodeSet &visited_nodes,
ParasiticResistorSet &loop_resistors,
ParasiticNodeResistorMap &resistor_map,
const Parasitics *parasitics) const;
void deleteNodes();
void deleteDevices();
const Net *net_;
ConcreteParasiticSubNodeMap sub_nodes_;
ConcreteParasiticPinNodeMap pin_nodes_;
ParasiticResistorSeq resistors_;
ParasiticCapacitorSeq capacitors_;
unsigned max_node_id_:31;
bool includes_pin_caps_:1;
};
class ConcreteParasiticNode : public ParasiticNode
{
public:
ConcreteParasiticNode(const Net *net,
int id,
bool is_external);
ConcreteParasiticNode(const Pin *pin,
bool is_external);
float capacitance() const { return cap_; }
const char *name(const Network *network) const;
const Net *net(const Network *network) const;
bool isExternal() const { return is_external_; }
const Pin *pin() const;
void incrCapacitance(float cap);
protected:
ConcreteParasiticNode();
union {
const Net *net_;
const Pin *pin_;
} net_pin_;
bool is_net_:1;
bool is_external_:1;
unsigned id_:30;
float cap_;
friend class ConcreteParasiticNetwork;
};
class ConcreteParasiticDevice
{
public:
ConcreteParasiticDevice(size_t id,
float value,
ConcreteParasiticNode *node1,
ConcreteParasiticNode *node2);
int id() const { return id_; }
float value() const { return value_; }
ConcreteParasiticNode *node1() const { return node1_; }
ConcreteParasiticNode *node2() const { return node2_; }
void replaceNode(ConcreteParasiticNode *from_node,
ConcreteParasiticNode *to_node);
protected:
size_t id_;
float value_;
ConcreteParasiticNode *node1_;
ConcreteParasiticNode *node2_;
};
class ConcreteParasiticResistor : public ParasiticResistor,
public ConcreteParasiticDevice
{
public:
ConcreteParasiticResistor(size_t id,
float value,
ConcreteParasiticNode *node1,
ConcreteParasiticNode *node2);
};
class ConcreteParasiticCapacitor : public ParasiticCapacitor,
public ConcreteParasiticDevice
{
public:
ConcreteParasiticCapacitor(size_t id,
float value,
ConcreteParasiticNode *node1,
ConcreteParasiticNode *node2);
};
} // namespace

View File

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

View File

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

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 "PortDirection.hh"
#include "Sdc.hh"
#include "Corner.hh"
#include "ReduceParasitics.hh"
#include "EstimateParasitics.hh"
namespace sta {
@ -51,28 +53,138 @@ Parasitics::findParasiticNet(const Pin *pin) const
return nullptr;
}
void
Parasitics::check(Parasitic *) const
PinSet
Parasitics::loads(const Pin *drvr_pin) const
{
#if 0
ConcreteParasiticSubNodeMap::Iterator sub_node_iter(sub_nodes_);
while (sub_node_iter.hasNext()) {
ConcreteParasiticSubNode *node = sub_node_iter.next();
ConcreteParasiticDeviceSeq::Iterator device_iter(node->devices());
int res_count = 0;
while (device_iter.hasNext()) {
ConcreteParasiticDevice *device = device_iter.next();
if (device->isResistor())
res_count++;
}
if (res_count == 0)
report->warn("sub node %s has no resistor connections",
node->name(network));
else if (res_count == 1)
report->warn("sub node %s has one resistor connection",
node->name(network));
PinSet loads(network_);
NetConnectedPinIterator *pin_iter = network_->connectedPinIterator(drvr_pin);
while (pin_iter->hasNext()) {
const Pin *pin = pin_iter->next();
if (network_->isLoad(pin) && !network_->isHierarchical(pin))
loads.insert(pin);
}
#endif
delete pin_iter;
return loads;
}
ParasiticNodeResistorMap
Parasitics::parasiticNodeResistorMap(const Parasitic *parasitic) const
{
ParasiticNodeResistorMap resistor_map;
for (ParasiticResistor *resistor : resistors(parasitic)) {
ParasiticNode *n1 = node1(resistor);
ParasiticNode *n2 = node2(resistor);
resistor_map[n1].push_back(resistor);
resistor_map[n2].push_back(resistor);
}
return resistor_map;
}
ParasiticNodeCapacitorMap
Parasitics::parasiticNodeCapacitorMap(const Parasitic *parasitic) const
{
ParasiticNodeCapacitorMap capacitor_map;
for (ParasiticCapacitor *capacitor : capacitors(parasitic)) {
ParasiticNode *n1 = node1(capacitor);
ParasiticNode *n2 = node2(capacitor);
capacitor_map[n1].push_back(capacitor);
capacitor_map[n2].push_back(capacitor);
}
return capacitor_map;
}
ParasiticNode *
Parasitics::otherNode(const ParasiticResistor *resistor,
ParasiticNode *node) const
{
ParasiticNode *n1 = node1(resistor);
if (node == n1)
return node2(resistor);
else if (node == node2(resistor))
return n1;
else
return nullptr;
}
ParasiticNode *
Parasitics::otherNode(const ParasiticCapacitor *capacitor,
ParasiticNode *node) const
{
ParasiticNode *n1 = node1(capacitor);
if (node == n1)
return node2(capacitor);
else if (node == node2(capacitor))
return n1;
else
return nullptr;
}
////////////////////////////////////////////////////////////////
Parasitic *
Parasitics::reduceToPiElmore(const Parasitic *parasitic,
const Pin *drvr_pin,
const RiseFall *rf,
const Corner *corner,
const MinMax *cnst_min_max,
const ParasiticAnalysisPt *ap)
{
return sta::reduceToPiElmore(parasitic, drvr_pin, rf, ap->couplingCapFactor(),
corner, cnst_min_max, ap, this);
}
Parasitic *
Parasitics::reduceToPiPoleResidue2(const Parasitic *parasitic,
const Pin *drvr_pin,
const RiseFall *rf,
const Corner *corner,
const MinMax *cnst_min_max,
const ParasiticAnalysisPt *ap)
{
return sta::reduceToPiPoleResidue2(parasitic, drvr_pin, rf,
ap->couplingCapFactor(),
corner, cnst_min_max,
ap, this);
}
////////////////////////////////////////////////////////////////
Parasitic *
Parasitics::estimatePiElmore(const Pin *drvr_pin,
const RiseFall *rf,
const Wireload *wireload,
float fanout,
float net_pin_cap,
const Corner *corner,
const MinMax *min_max)
{
EstimateParasitics estimate(this);
float c2, rpi, c1, elmore_res, elmore_cap;
bool elmore_use_load_cap;
estimate.estimatePiElmore(drvr_pin, rf, wireload, fanout, net_pin_cap,
corner, min_max,
c2, rpi, c1,
elmore_res, elmore_cap, elmore_use_load_cap);
if (c1 > 0.0 || c2 > 0.0) {
ParasiticAnalysisPt *ap = corner->findParasiticAnalysisPt(min_max);
Parasitic *parasitic = makePiElmore(drvr_pin, rf, ap, c2, rpi, c1);
NetConnectedPinIterator *pin_iter = network_->connectedPinIterator(drvr_pin);
while (pin_iter->hasNext()) {
const Pin *pin = pin_iter->next();
if (network_->isLoad(pin)) {
float load_cap = 0.0;
if (elmore_use_load_cap)
load_cap = sdc_->pinCapacitance(pin, rf, corner, min_max);
float elmore = elmore_res * (elmore_cap + load_cap);
setElmore(parasitic, pin, elmore);
}
}
delete pin_iter;
return parasitic;
}
else
return nullptr;
}
////////////////////////////////////////////////////////////////
@ -81,11 +193,12 @@ Parasitic *
Parasitics::makeWireloadNetwork(const Pin *drvr_pin,
const Wireload *wireload,
float fanout,
const OperatingConditions *op_cond,
const MinMax *min_max,
const ParasiticAnalysisPt *ap)
{
Net *net = network_->net(drvr_pin);
Parasitic *parasitic = makeParasiticNetwork(net, false, ap);
const OperatingConditions *op_cond = sdc_->operatingConditions(min_max);
float wireload_cap, wireload_res;
wireload->findWireload(fanout, op_cond, wireload_cap, wireload_res);
@ -95,16 +208,16 @@ Parasitics::makeWireloadNetwork(const Pin *drvr_pin,
switch (tree) {
case WireloadTree::worst_case:
makeWireloadNetworkWorst(parasitic, drvr_pin, wireload_cap,
wireload_res, fanout, ap);
wireload_res, fanout);
break;
case WireloadTree::balanced:
makeWireloadNetworkBalanced(parasitic, drvr_pin, wireload_cap,
wireload_res, fanout, ap);
wireload_res, fanout);
break;
case WireloadTree::best_case:
case WireloadTree::unknown:
makeWireloadNetworkBest(parasitic, drvr_pin, wireload_cap,
wireload_res, fanout, ap);
wireload_res, fanout);
break;
}
return parasitic;
@ -117,22 +230,22 @@ Parasitics::makeWireloadNetworkWorst(Parasitic *parasitic,
const Pin *drvr_pin,
float wireload_cap,
float wireload_res,
float /* fanout */,
const ParasiticAnalysisPt *ap)
float /* fanout */)
{
ParasiticNode *drvr_node = ensureParasiticNode(parasitic, drvr_pin);
ParasiticNode *drvr_node = ensureParasiticNode(parasitic, drvr_pin, network_);
Net *net = network_->net(drvr_pin);
ParasiticNode *load_node = ensureParasiticNode(parasitic, net, 0);
makeResistor(nullptr, drvr_node, load_node, wireload_res, ap);
parasitics_->incrCap(load_node, wireload_cap, ap);
size_t resistor_index = 1;
ParasiticNode *load_node = ensureParasiticNode(parasitic, net, 0, network_);
makeResistor(parasitic, resistor_index++, wireload_res, drvr_node, load_node);
parasitics_->incrCap(load_node, wireload_cap);
PinConnectedPinIterator *load_iter =
network_->connectedPinIterator(drvr_pin);
while (load_iter->hasNext()) {
const Pin *load_pin = load_iter->next();
if (load_pin != drvr_pin
&& network_->isLoad(load_pin)) {
ParasiticNode *load_node1 = ensureParasiticNode(parasitic, load_pin);
makeResistor(nullptr, load_node, load_node1, 0.0, ap);
ParasiticNode *load_node1 = ensureParasiticNode(parasitic, load_pin, network_);
makeResistor(parasitic, resistor_index++, 0.0, load_node, load_node1);
}
}
}
@ -143,19 +256,19 @@ Parasitics::makeWireloadNetworkBest(Parasitic *parasitic,
const Pin *drvr_pin,
float wireload_cap,
float /* wireload_res */,
float /* fanout */,
const ParasiticAnalysisPt *ap)
float /* fanout */)
{
ParasiticNode *drvr_node = ensureParasiticNode(parasitic, drvr_pin);
parasitics_->incrCap(drvr_node, wireload_cap, ap);
ParasiticNode *drvr_node = ensureParasiticNode(parasitic, drvr_pin, network_);
parasitics_->incrCap(drvr_node, wireload_cap);
PinConnectedPinIterator *load_iter =
network_->connectedPinIterator(drvr_pin);
size_t resistor_index = 1;
while (load_iter->hasNext()) {
const Pin *load_pin = load_iter->next();
if (load_pin != drvr_pin
&& network_->isLoad(load_pin)) {
ParasiticNode *load_node1 = ensureParasiticNode(parasitic, load_pin);
makeResistor(nullptr, drvr_node, load_node1, 0.0, ap);
ParasiticNode *load_node1 = ensureParasiticNode(parasitic, load_pin, network_);
makeResistor(parasitic, resistor_index++, 0.0, drvr_node, load_node1);
}
}
}
@ -167,21 +280,21 @@ Parasitics::makeWireloadNetworkBalanced(Parasitic *parasitic,
const Pin *drvr_pin,
float wireload_cap,
float wireload_res,
float fanout,
const ParasiticAnalysisPt *ap)
float fanout)
{
float fanout_cap = wireload_cap / fanout;
float fanout_res = wireload_res / fanout;
ParasiticNode *drvr_node = ensureParasiticNode(parasitic, drvr_pin);
ParasiticNode *drvr_node = ensureParasiticNode(parasitic, drvr_pin, network_);
PinConnectedPinIterator *load_iter =
network_->connectedPinIterator(drvr_pin);
size_t resistor_index = 1;
while (load_iter->hasNext()) {
const Pin *load_pin = load_iter->next();
if (load_pin != drvr_pin
&& network_->isLoad(load_pin)) {
ParasiticNode *load_node1 = ensureParasiticNode(parasitic, load_pin);
makeResistor(nullptr, drvr_node, load_node1, fanout_res, ap);
parasitics_->incrCap(load_node1, fanout_cap, ap);
ParasiticNode *load_node1 = ensureParasiticNode(parasitic, load_pin, network_);
makeResistor(parasitic, resistor_index++, fanout_res, drvr_node, load_node1);
parasitics_->incrCap(load_node1, fanout_cap);
}
}
}
@ -190,19 +303,14 @@ Parasitics::makeWireloadNetworkBalanced(Parasitic *parasitic,
ParasiticAnalysisPt::ParasiticAnalysisPt(const char *name,
int index,
const MinMax *min_max) :
name_(stringCopy(name)),
int index_max) :
name_(name),
index_(index),
min_max_(min_max),
index_max_(index_max),
coupling_cap_factor_(1.0)
{
}
ParasiticAnalysisPt::~ParasiticAnalysisPt()
{
stringDelete(name_);
}
void
ParasiticAnalysisPt::setCouplingCapFactor(float factor)
{

View File

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

View File

@ -26,16 +26,29 @@ define_cmd_args "read_spef" \
[-coupling_reduction_factor factor]\
[-reduce_to pi_elmore|pi_pole_residue2]\
[-delete_after_reduce]\
[-quiet]\
[-save]\
filename}
proc_redirect read_spef {
parse_key_args "read_spef" args \
keys {-path -coupling_reduction_factor -reduce_to -corner} \
flags {-min -max -increment -pin_cap_included -keep_capacitive_coupling \
-delete_after_reduce -quiet -save}
check_argc_eq1 "report_spef" $args
-reduce -delete_after_reduce -quiet -save}
check_argc_eq1 "read_spef" $args
set reduce [info exists flags(-reduce)]
if { [info exists flags(-quiet)] } {
sta_warn 272 "read_spef -quiet is deprecated."
}
if { [info exists keys(-reduce_to)] } {
sta_warn 273 "read_spef -reduce_to is deprecated. Use -reduce instead."
set reduce 1
}
if { [info exists flags(-delete_after_reduce)] } {
sta_warn 274 "read_spef -delete_after_reduce is deprecated."
}
if { [info exists flags(-save)] } {
sta_warn 275 "read_spef -save is deprecated."
}
set instance [top_instance]
if [info exists keys(-path)] {
@ -55,20 +68,10 @@ proc_redirect read_spef {
set keep_coupling_caps [info exists flags(-keep_capacitive_coupling)]
set pin_cap_included [info exists flags(-pin_cap_included)]
set reduce_to "none"
if [info exists keys(-reduce_to)] {
set reduce_to $keys(-reduce_to)
if { !($reduce_to == "pi_elmore" || $reduce_to == "pi_pole_residue2") } {
sta_error 271 "-reduce_to must be pi_elmore or pi_pole_residue2."
}
}
set delete_after_reduce [info exists flags(-delete_after_reduce)]
set quiet [info exists flags(-quiet)]
set save [info exists flags(-save)]
set filename [file nativename [lindex $args 0]]
return [read_spef_cmd $filename $instance $corner $min_max \
$pin_cap_included $keep_coupling_caps $coupling_reduction_factor \
$reduce_to $delete_after_reduce $quiet]
$pin_cap_included $keep_coupling_caps \
$coupling_reduction_factor $reduce]
}
define_cmd_args "report_parasitic_annotation" {-report_unannotated}

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -2261,7 +2261,7 @@ ReportPath::reportPathLine(const Path *path,
float cap = field_blank_;
// Don't show capacitance field for input pins.
if (is_driver && field_capacitance_->enabled())
cap = loadCap(pin, rf, dcalc_ap);
cap = graph_delay_calc_->loadCap(pin, rf, dcalc_ap);
reportLine(what.c_str(), cap, slew, field_blank_,
incr, time, false, early_late, rf, line_case);
}
@ -2653,7 +2653,7 @@ ReportPath::reportPath5(const Path *path,
float fanout = field_blank_;
// Don't show capacitance field for input pins.
if (is_driver && field_capacitance_->enabled())
cap = loadCap(pin, rf, dcalc_ap);
cap = graph_delay_calc_->loadCap(pin, rf, dcalc_ap);
// Don't show fanout field for input pins.
if (is_driver && field_fanout_->enabled())
fanout = drvrFanout(vertex, dcalc_ap->corner(), min_max);
@ -2837,18 +2837,6 @@ ReportPath::pathInputDelayRefPath(const Path *path,
}
}
float
ReportPath::loadCap(Pin *drvr_pin,
const RiseFall *rf,
DcalcAnalysisPt *dcalc_ap)
{
Parasitic *parasitic = nullptr;
parasitic = arc_delay_calc_->findParasitic(drvr_pin, rf, dcalc_ap);
float load_cap = graph_delay_calc_->loadCap(drvr_pin, parasitic, rf, dcalc_ap);
arc_delay_calc_->finishDrvrPin();
return load_cap;
}
////////////////////////////////////////////////////////////////
void

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -1168,21 +1168,6 @@ using namespace sta;
Tcl_SetObjResult(interp, obj);
}
%typemap(in) ReducedParasiticType {
int length;
char *arg = Tcl_GetStringFromObj($input, &length);
if (stringEq(arg, "pi_elmore"))
$1 = ReducedParasiticType::pi_elmore;
else if (stringEq(arg, "pi_pole_residue2"))
$1 = ReducedParasiticType::pi_pole_residue2;
else if (stringEq(arg, "none"))
$1 = ReducedParasiticType::none;
else {
tclArgError(interp, "%s pi_elmore, pi_pole_residue2, or none.", arg);
return TCL_ERROR;
}
}
%typemap(out) Arrival {
Tcl_SetObjResult(interp,Tcl_NewDoubleObj(delayAsFloat($1)));
}

View File

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