diff --git a/CMakeLists.txt b/CMakeLists.txt index bb1d30b0..2436b263 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -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 diff --git a/dcalc/Arnoldi.hh b/dcalc/Arnoldi.hh index 545bec72..3dc238b1 100644 --- a/dcalc/Arnoldi.hh +++ b/dcalc/Arnoldi.hh @@ -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] }; diff --git a/dcalc/ArnoldiDelayCalc.cc b/dcalc/ArnoldiDelayCalc.cc index 88d0c880..5cb2cf86 100644 --- a/dcalc/ArnoldiDelayCalc.cc +++ b/dcalc/ArnoldiDelayCalc.cc @@ -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 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; } diff --git a/dcalc/ArnoldiReduce.cc b/dcalc/ArnoldiReduce.cc index 1a0779d7..5c80c382 100644 --- a/dcalc/ArnoldiReduce.cc +++ b/dcalc/ArnoldiReduce.cc @@ -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(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(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; } diff --git a/dcalc/ArnoldiReduce.hh b/dcalc/ArnoldiReduce.hh index c5e1a004..ad49da34 100644 --- a/dcalc/ArnoldiReduce.hh +++ b/dcalc/ArnoldiReduce.hh @@ -37,21 +37,20 @@ class rcmodel; struct ts_edge; struct ts_point; -typedef Map ArnolidPtMap; +typedef Map 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_; diff --git a/dcalc/DelayCalcBase.cc b/dcalc/DelayCalcBase.cc index ea748e8d..7db5663f 100644 --- a/dcalc/DelayCalcBase.cc +++ b/dcalc/DelayCalcBase.cc @@ -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 diff --git a/dcalc/DelayCalcBase.hh b/dcalc/DelayCalcBase.hh index 1c7e8173..76137d0b 100644 --- a/dcalc/DelayCalcBase.hh +++ b/dcalc/DelayCalcBase.hh @@ -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 unsaved_parasitics_; - Vector reduced_parasitic_drvrs_; + using ArcDelayCalc::reduceParasitic; }; } // namespace diff --git a/dcalc/DmpDelayCalc.cc b/dcalc/DmpDelayCalc.cc index 15145abd..8006a0f8 100644 --- a/dcalc/DmpDelayCalc.cc +++ b/dcalc/DmpDelayCalc.cc @@ -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, diff --git a/dcalc/GraphDelayCalc.cc b/dcalc/GraphDelayCalc.cc index ba9f1463..da3b40d0 100644 --- a/dcalc/GraphDelayCalc.cc +++ b/dcalc/GraphDelayCalc.cc @@ -365,9 +365,11 @@ GraphDelayCalc::seedNoDrvrCellSlew(Vertex *drvr_vertex, Delay drive_delay = delay_zero; float drive_res; drive->driveResistance(rf, cnst_min_max, drive_res, exists); - Parasitic *parasitic = arc_delay_calc->findParasitic(drvr_pin, rf, dcalc_ap); + const Parasitic *parasitic; + float cap; + parasiticLoad(drvr_pin, rf, dcalc_ap, nullptr, arc_delay_calc, + cap, parasitic); if (exists) { - float cap = loadCap(drvr_pin, parasitic, rf, dcalc_ap); drive_delay = cap * drive_res; slew = cap * drive_res; } @@ -408,7 +410,7 @@ GraphDelayCalc::seedNoDrvrSlew(Vertex *drvr_vertex, load_pin_index_map, dcalc_ap); annotateLoadDelays(drvr_vertex, rf, dcalc_result, load_pin_index_map, delay_zero, false, dcalc_ap); - arc_delay_calc->finishDrvrPin(); + arc_delay_calc_->finishDrvrPin(); } void @@ -500,6 +502,7 @@ GraphDelayCalc::findInputDriverDelay(const LibertyCell *drvr_cell, } } } + arc_delay_calc_->finishDrvrPin(); } // Driving cell delay is the load dependent delay, which is the gate @@ -521,8 +524,10 @@ GraphDelayCalc::findInputArcDelay(const Pin *drvr_pin, const RiseFall *drvr_rf = arc->toEdge()->asRiseFall(); if (drvr_rf) { DcalcAPIndex ap_index = dcalc_ap->index(); - Parasitic *parasitic = arc_delay_calc_->findParasitic(drvr_pin, drvr_rf, dcalc_ap); - float load_cap = loadCap(drvr_pin, parasitic, drvr_rf, dcalc_ap); + const Parasitic *parasitic; + float load_cap; + parasiticLoad(drvr_pin, drvr_rf, dcalc_ap, nullptr, arc_delay_calc_, + load_cap, parasitic); LoadPinIndexMap load_pin_index_map = makeLoadPinIndexMap(drvr_vertex); ArcDcalcResult intrinsic_result = @@ -547,6 +552,7 @@ GraphDelayCalc::findInputArcDelay(const Pin *drvr_pin, graph_->setSlew(drvr_vertex, drvr_rf, ap_index, gate_slew); annotateLoadDelays(drvr_vertex, drvr_rf, gate_result, load_pin_index_map, load_delay, false, dcalc_ap); + arc_delay_calc_->finishDrvrPin(); } } @@ -646,7 +652,7 @@ GraphDelayCalc::findDriverDelays(Vertex *drvr_vertex, initLoadSlews(drvr_vertex); delay_changed |= findDriverDelays1(drvr_vertex, multi_drvr, arc_delay_calc); } - arc_delay_calc->finishDrvrPin(); + arc_delay_calc_->finishDrvrPin(); return delay_changed; } @@ -849,7 +855,6 @@ GraphDelayCalc::findDriverEdgeDelays(Vertex *drvr_vertex, Vertex *from_vertex = edge->from(graph_); const TimingArcSet *arc_set = edge->timingArcSet(); bool delay_changed = false; - PinSeq load_pins = loadPins(drvr_vertex); LoadPinIndexMap load_pin_index_map = makeLoadPinIndexMap(drvr_vertex); for (auto dcalc_ap : corners_->dcalcAnalysisPts()) { for (const TimingArc *arc : arc_set->arcs()) @@ -892,9 +897,11 @@ GraphDelayCalc::findDriverArcDelays(Vertex *drvr_vertex, const RiseFall *drvr_rf = arc->toEdge()->asRiseFall(); if (from_rf && drvr_rf) { const Pin *drvr_pin = drvr_vertex->pin(); - Parasitic *parasitic = arc_delay_calc->findParasitic(drvr_pin, drvr_rf, - dcalc_ap); - float load_cap = loadCap(drvr_pin, parasitic, drvr_rf, dcalc_ap, multi_drvr); + const Parasitic *parasitic; + float load_cap; + parasiticLoad(drvr_pin, drvr_rf, dcalc_ap, multi_drvr, arc_delay_calc, + load_cap, parasitic); + if (multi_drvr && multi_drvr->parallelGates(network_)) { ArcDcalcArgSeq dcalc_args = makeArcDcalcArgs(drvr_vertex, multi_drvr, @@ -921,6 +928,7 @@ GraphDelayCalc::findDriverArcDelays(Vertex *drvr_vertex, delay_changed |= annotateDelaysSlews(edge, arc, dcalc_result, load_pin_index_map, dcalc_ap); } + arc_delay_calc->finishDrvrPin(); } return delay_changed; } @@ -1126,21 +1134,6 @@ GraphDelayCalc::annotateLoadDelays(Vertex *drvr_vertex, } } -PinSeq -GraphDelayCalc::loadPins(Vertex *drvr_vertex) -{ - PinSeq load_pins; - VertexOutEdgeIterator edge_iter(drvr_vertex, graph_); - while (edge_iter.hasNext()) { - Edge *wire_edge = edge_iter.next(); - if (wire_edge->isWire()) { - Vertex *load_vertex = wire_edge->to(graph_); - load_pins.push_back(load_vertex->pin()); - } - } - return load_pins; -} - LoadPinIndexMap GraphDelayCalc::makeLoadPinIndexMap(Vertex *drvr_vertex) { @@ -1159,6 +1152,7 @@ GraphDelayCalc::makeLoadPinIndexMap(Vertex *drvr_vertex) return load_pin_index_map; } +// External float GraphDelayCalc::loadCap(const Pin *drvr_pin, const DcalcAnalysisPt *dcalc_ap) const @@ -1166,92 +1160,104 @@ GraphDelayCalc::loadCap(const Pin *drvr_pin, const MinMax *min_max = dcalc_ap->constraintMinMax(); float load_cap = 0.0; for (auto drvr_rf : RiseFall::range()) { - Parasitic *parasitic = arc_delay_calc_->findParasitic(drvr_pin, drvr_rf, dcalc_ap); - float cap = loadCap(drvr_pin, parasitic, drvr_rf, dcalc_ap, nullptr); - arc_delay_calc_->finishDrvrPin(); + float cap = loadCap(drvr_pin, drvr_rf, dcalc_ap); if (min_max->compare(cap, load_cap)) load_cap = cap; } + arc_delay_calc_->finishDrvrPin(); return load_cap; } +// External float GraphDelayCalc::loadCap(const Pin *drvr_pin, - const RiseFall *drvr_rf, - const DcalcAnalysisPt *dcalc_ap) const -{ - Parasitic *parasitic = arc_delay_calc_->findParasitic(drvr_pin, drvr_rf, - dcalc_ap); - float cap = loadCap(drvr_pin, parasitic, drvr_rf, dcalc_ap, nullptr); - return cap; -} - -float -GraphDelayCalc::loadCap(const Pin *drvr_pin, - const Parasitic *parasitic, const RiseFall *rf, const DcalcAnalysisPt *dcalc_ap) const -{ - return loadCap(drvr_pin, parasitic, rf, dcalc_ap, nullptr); -} - -float -GraphDelayCalc::loadCap(const Pin *drvr_pin, - const Parasitic *parasitic, - const RiseFall *rf, - const DcalcAnalysisPt *dcalc_ap, - const MultiDrvrNet *multi_drvr) const { float pin_cap, wire_cap; - bool has_net_load; - float fanout; - if (multi_drvr) - multi_drvr->netCaps(rf, dcalc_ap, - pin_cap, wire_cap, fanout, has_net_load); - else - netCaps(drvr_pin, rf, dcalc_ap, - pin_cap, wire_cap, fanout, has_net_load); - loadCap(parasitic, has_net_load, pin_cap, wire_cap); - return wire_cap + pin_cap; + loadCap(drvr_pin, rf, dcalc_ap, pin_cap, wire_cap); + return pin_cap + wire_cap; } +// External void GraphDelayCalc::loadCap(const Pin *drvr_pin, - const Parasitic *parasitic, const RiseFall *rf, const DcalcAnalysisPt *dcalc_ap, - // Return values. float &pin_cap, float &wire_cap) const { - bool has_net_load; - float fanout; - // Find pin and external pin/wire capacitance. - netCaps(drvr_pin, rf, dcalc_ap, - pin_cap, wire_cap, fanout, has_net_load); - loadCap(parasitic, has_net_load, pin_cap, wire_cap); + MultiDrvrNet *multi_drvr = nullptr; + if (graph_) { + Vertex *drvr_vertex = graph_->pinDrvrVertex(drvr_pin); + multi_drvr = multiDrvrNet(drvr_vertex); + } + const Parasitic *parasitic; + parasiticLoad(drvr_pin, rf, dcalc_ap, multi_drvr, arc_delay_calc_, + pin_cap, wire_cap, parasitic); + arc_delay_calc_->finishDrvrPin(); +} + +float +GraphDelayCalc::loadCap(const Pin *drvr_pin, + const RiseFall *rf, + const DcalcAnalysisPt *dcalc_ap, + ArcDelayCalc *arc_delay_calc) const +{ + const Parasitic *parasitic; + float pin_cap, wire_cap; + parasiticLoad(drvr_pin, rf, dcalc_ap, nullptr, arc_delay_calc, + pin_cap, wire_cap, parasitic); + return pin_cap + wire_cap; } void -GraphDelayCalc::loadCap(const Parasitic *parasitic, - bool has_net_load, - // Return values. - float &pin_cap, - float &wire_cap) const +GraphDelayCalc::parasiticLoad(const Pin *drvr_pin, + const RiseFall *rf, + const DcalcAnalysisPt *dcalc_ap, + const MultiDrvrNet *multi_drvr, + ArcDelayCalc *arc_delay_calc, + // Return values. + float &load_cap, + const Parasitic *¶sitic) const { + float pin_cap, wire_cap; + parasiticLoad(drvr_pin, rf, dcalc_ap, multi_drvr, arc_delay_calc, + pin_cap, wire_cap, parasitic); + load_cap = pin_cap + wire_cap; +} + +void +GraphDelayCalc::parasiticLoad(const Pin *drvr_pin, + const RiseFall *rf, + const DcalcAnalysisPt *dcalc_ap, + const MultiDrvrNet *multi_drvr, + ArcDelayCalc *arc_delay_calc, + // Return values. + float &pin_cap, + float &wire_cap, + const Parasitic *¶sitic) const +{ + bool has_net_load; + float fanout; + netCaps(drvr_pin, rf, dcalc_ap, multi_drvr, + pin_cap, wire_cap, fanout, has_net_load); + + parasitic = arc_delay_calc->findParasitic(drvr_pin, rf, dcalc_ap); // set_load net has precedence over parasitics. if (!has_net_load && parasitic) { if (parasitics_->isParasiticNetwork(parasitic)) wire_cap += parasitics_->capacitance(parasitic); else { // PiModel includes both pin and external caps. - float cap = parasitics_->capacitance(parasitic); - if (pin_cap > cap) { - pin_cap = 0.0; - wire_cap = cap; + float parasitic_cap = parasitics_->capacitance(parasitic); + if (parasitic_cap >= pin_cap) + wire_cap = parasitic_cap - pin_cap; + else { + wire_cap = 0.0; + // Ignore parasitic if pin cap is greater. + parasitic = nullptr; } - else - wire_cap = cap - pin_cap; } } } @@ -1271,15 +1277,29 @@ GraphDelayCalc::netCaps(const Pin *drvr_pin, Vertex *drvr_vertex = graph_->pinDrvrVertex(drvr_pin); multi_drvr = multiDrvrNet(drvr_vertex); } + netCaps(drvr_pin, rf, dcalc_ap, multi_drvr, + pin_cap, wire_cap, fanout, has_net_load); +} + +void +GraphDelayCalc::netCaps(const Pin *drvr_pin, + const RiseFall *rf, + const DcalcAnalysisPt *dcalc_ap, + const MultiDrvrNet *multi_drvr, + // Return values. + float &pin_cap, + float &wire_cap, + float &fanout, + bool &has_net_load) const +{ if (multi_drvr) multi_drvr->netCaps(rf, dcalc_ap, pin_cap, wire_cap, fanout, has_net_load); else { - const OperatingConditions *op_cond = dcalc_ap->operatingConditions(); const Corner *corner = dcalc_ap->corner(); const MinMax *min_max = dcalc_ap->constraintMinMax(); // Find pin and external pin/wire capacitance. - sdc_->connectedCap(drvr_pin, rf, op_cond, corner, min_max, + sdc_->connectedCap(drvr_pin, rf, corner, min_max, pin_cap, wire_cap, fanout, has_net_load); } } @@ -1405,13 +1425,8 @@ GraphDelayCalc::findCheckEdgeDelays(Edge *edge, delayAsString(from_slew, this), delayAsString(to_slew, this)); float related_out_cap = 0.0; - if (related_out_pin) { - Parasitic *related_out_parasitic = - arc_delay_calc->findParasitic(related_out_pin, to_rf, dcalc_ap); - related_out_cap = loadCap(related_out_pin, - related_out_parasitic, - to_rf, dcalc_ap); - } + if (related_out_pin) + related_out_cap = loadCap(related_out_pin, to_rf,dcalc_ap,arc_delay_calc); ArcDelay check_delay = arc_delay_calc->checkDelay(to_pin, arc, from_slew, to_slew, related_out_cap, dcalc_ap); @@ -1420,6 +1435,7 @@ GraphDelayCalc::findCheckEdgeDelays(Edge *edge, delayAsString(check_delay, this)); graph_->setArcDelay(edge, arc, ap_index, check_delay); delay_changed = true; + arc_delay_calc_->finishDrvrPin(); } } } @@ -1467,12 +1483,8 @@ GraphDelayCalc::reportDelayCalc(const Edge *edge, if (related_out_port) related_out_pin = network_->findPin(inst, related_out_port); float related_out_cap = 0.0; - if (related_out_pin) { - Parasitic *related_out_parasitic = - arc_delay_calc_->findParasitic(related_out_pin, to_rf, dcalc_ap); - related_out_cap = loadCap(related_out_pin, related_out_parasitic, - to_rf, dcalc_ap); - } + if (related_out_pin) + related_out_cap = loadCap(related_out_pin, to_rf, dcalc_ap, arc_delay_calc_); if (role->isTimingCheck()) { const Slew &from_slew = checkEdgeClkSlew(from_vertex, from_rf, dcalc_ap); int slew_index = dcalc_ap->checkDataSlewIndex(); @@ -1484,10 +1496,11 @@ GraphDelayCalc::reportDelayCalc(const Edge *edge, related_out_cap, dcalc_ap, digits); } else { - Parasitic *to_parasitic = - arc_delay_calc_->findParasitic(to_pin, to_rf, dcalc_ap); const Slew &from_slew = edgeFromSlew(from_vertex, from_rf, edge, dcalc_ap); - float load_cap = loadCap(to_pin, to_parasitic, to_rf, dcalc_ap); + const Parasitic *to_parasitic; + float load_cap; + parasiticLoad(to_pin, to_rf, dcalc_ap, nullptr, arc_delay_calc_, + load_cap, to_parasitic); LoadPinIndexMap load_pin_index_map = makeLoadPinIndexMap(to_vertex); result = arc_delay_calc_->reportGateDelay(to_pin, arc, from_slew, load_cap, to_parasitic, load_pin_index_map, @@ -1591,7 +1604,6 @@ MultiDrvrNet::findCaps(const Sdc *sdc) for (auto dcalc_ap : corners->dcalcAnalysisPts()) { DcalcAPIndex ap_index = dcalc_ap->index(); const Corner *corner = dcalc_ap->corner(); - const OperatingConditions *op_cond = dcalc_ap->operatingConditions(); const MinMax *min_max = dcalc_ap->constraintMinMax(); for (auto drvr_rf : RiseFall::range()) { int drvr_rf_index = drvr_rf->index(); @@ -1600,7 +1612,7 @@ MultiDrvrNet::findCaps(const Sdc *sdc) float pin_cap, wire_cap, fanout; bool has_net_load; // Find pin and external pin/wire capacitance. - sdc->connectedCap(drvr_pin, drvr_rf, op_cond, corner, min_max, + sdc->connectedCap(drvr_pin, drvr_rf, corner, min_max, pin_cap, wire_cap, fanout, has_net_load); net_caps.init(pin_cap, wire_cap, fanout, has_net_load); } diff --git a/dcalc/LumpedCapDelayCalc.cc b/dcalc/LumpedCapDelayCalc.cc index 975ca045..67cecec0 100644 --- a/dcalc/LumpedCapDelayCalc.cc +++ b/dcalc/LumpedCapDelayCalc.cc @@ -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 diff --git a/dcalc/LumpedCapDelayCalc.hh b/dcalc/LumpedCapDelayCalc.hh index 0968c494..b62a2faf 100644 --- a/dcalc/LumpedCapDelayCalc.hh +++ b/dcalc/LumpedCapDelayCalc.hh @@ -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 * diff --git a/dcalc/UnitDelayCalc.cc b/dcalc/UnitDelayCalc.cc index d9ce6c7a..39c02fb5 100644 --- a/dcalc/UnitDelayCalc.cc +++ b/dcalc/UnitDelayCalc.cc @@ -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 diff --git a/dcalc/UnitDelayCalc.hh b/dcalc/UnitDelayCalc.hh index 788a3742..8d247f5d 100644 --- a/dcalc/UnitDelayCalc.hh +++ b/dcalc/UnitDelayCalc.hh @@ -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, diff --git a/doc/ChangeLog.txt b/doc/ChangeLog.txt index d6a2e522..f665546c 100644 --- a/doc/ChangeLog.txt +++ b/doc/ChangeLog.txt @@ -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 ------------------------- diff --git a/doc/OpenSTA.odt b/doc/OpenSTA.odt index 38c37ccb..30afc942 100644 Binary files a/doc/OpenSTA.odt and b/doc/OpenSTA.odt differ diff --git a/doc/OpenSTA.pdf b/doc/OpenSTA.pdf index 5fb586c1..b04d5b6e 100644 Binary files a/doc/OpenSTA.pdf and b/doc/OpenSTA.pdf differ diff --git a/include/sta/ArcDelayCalc.hh b/include/sta/ArcDelayCalc.hh index db3a4f0c..2bcc11a8 100644 --- a/include/sta/ArcDelayCalc.hh +++ b/include/sta/ArcDelayCalc.hh @@ -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, diff --git a/include/sta/Corner.hh b/include/sta/Corner.hh index 8af89e49..9ef972ab 100644 --- a/include/sta/Corner.hh +++ b/include/sta/Corner.hh @@ -55,8 +55,7 @@ public: void operatingConditionsChanged(); // Make one parasitic analysis points. - void makeParasiticAnalysisPts(bool per_corner, - bool per_min_max); + void makeParasiticAnalysisPts(bool per_corner); int parasiticAnalysisPtCount() const; ParasiticAnalysisPtSeq ¶siticAnalysisPts(); @@ -114,7 +113,7 @@ public: protected: void setParasiticAnalysisPtcount(int ap_count); void setParasiticAP(ParasiticAnalysisPt *path_ap, - int ap_index); + int mm_index); void setDcalcAnalysisPtcount(DcalcAPIndex ap_count); void addDcalcAP(DcalcAnalysisPt *dcalc_ap); void addPathAP(PathAnalysisPt *path_ap); diff --git a/include/sta/GraphDelayCalc.hh b/include/sta/GraphDelayCalc.hh index ef467261..a93dd890 100644 --- a/include/sta/GraphDelayCalc.hh +++ b/include/sta/GraphDelayCalc.hh @@ -72,41 +72,26 @@ public: // delays to be recomputed during incremental delay calculation. virtual float incrementalDelayTolerance(); virtual void setIncrementalDelayTolerance(float tol); - // Load pin_cap + wire_cap. - virtual float loadCap(const Pin *drvr_pin, - const RiseFall *drvr_rf, - const DcalcAnalysisPt *dcalc_ap) const; - // Load pin_cap + wire_cap including parasitic min/max for rise/fall. - virtual float loadCap(const Pin *drvr_pin, - const DcalcAnalysisPt *dcalc_ap) const; - // pin_cap = net pin capacitances + port external pin capacitance, - // wire_cap = annotated net capacitance + port external wire capacitance. - virtual void loadCap(const Pin *drvr_pin, - const Parasitic *parasitic, - const RiseFall *rf, - const DcalcAnalysisPt *dcalc_ap, - // Return values. - float &pin_cap, - float &wire_cap) const; - // Load pin_cap + wire_cap including parasitic. - virtual float loadCap(const Pin *drvr_pin, - const Parasitic *parasitic, - const RiseFall *rf, - const DcalcAnalysisPt *dcalc_ap) const; + float loadCap(const Pin *drvr_pin, - const Parasitic *parasitic, - const RiseFall *rf, - const DcalcAnalysisPt *dcalc_ap, - const MultiDrvrNet *multi_drvr) const; - virtual void netCaps(const Pin *drvr_pin, - const RiseFall *rf, - const DcalcAnalysisPt *dcalc_ap, - // Return values. - float &pin_cap, - float &wire_cap, - float &fanout, - bool &has_set_load) const; - PinSeq loadPins(Vertex *drvr_vertex); + const DcalcAnalysisPt *dcalc_ap) const; + float loadCap(const Pin *drvr_pin, + const RiseFall *rf, + const DcalcAnalysisPt *dcalc_ap) const; + void loadCap(const Pin *drvr_pin, + const RiseFall *rf, + const DcalcAnalysisPt *dcalc_ap, + // Return values. + float &pin_cap, + float &wire_cap) const; + void netCaps(const Pin *drvr_pin, + const RiseFall *rf, + const DcalcAnalysisPt *dcalc_ap, + // Return values. + float &pin_cap, + float &wire_cap, + float &fanout, + bool &has_set_load) const; LoadPinIndexMap makeLoadPinIndexMap(Vertex *drvr_vertex); void findDriverArcDelays(Vertex *drvr_vertex, Edge *edge, @@ -242,11 +227,36 @@ protected: const RiseFall *from_rf, const DcalcAnalysisPt *dcalc_ap); bool bidirectDrvrSlewFromLoad(const Vertex *vertex) const; - void loadCap(const Parasitic *parasitic, - bool has_set_load, - // Return values. - float &pin_cap, - float &wire_cap) const; + float loadCap(const Pin *drvr_pin, + const RiseFall *rf, + const DcalcAnalysisPt *dcalc_ap, + ArcDelayCalc *arc_delay_calc) const; + void parasiticLoad(const Pin *drvr_pin, + const RiseFall *rf, + const DcalcAnalysisPt *dcalc_ap, + const MultiDrvrNet *multi_drvr, + ArcDelayCalc *arc_delay_calc, + // Return values. + float &cap, + const Parasitic *¶sitic) const; + void parasiticLoad(const Pin *drvr_pin, + const RiseFall *rf, + const DcalcAnalysisPt *dcalc_ap, + const MultiDrvrNet *multi_drvr, + ArcDelayCalc *arc_delay_calc, + // Return values. + float &pin_cap, + float &wire_cap, + const Parasitic *¶sitic) const; + void netCaps(const Pin *drvr_pin, + const RiseFall *rf, + const DcalcAnalysisPt *dcalc_ap, + const MultiDrvrNet *multi_drvr, + // Return values. + float &pin_cap, + float &wire_cap, + float &fanout, + bool &has_net_load) const; // Observer for edge delay changes. DelayCalcObserver *observer_; diff --git a/include/sta/NullParasitics.hh b/include/sta/NullParasitics.hh deleted file mode 100644 index cbf4529e..00000000 --- a/include/sta/NullParasitics.hh +++ /dev/null @@ -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 . - -#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 diff --git a/include/sta/Parasitics.hh b/include/sta/Parasitics.hh index 5ac6b93f..a55143c9 100644 --- a/include/sta/Parasitics.hh +++ b/include/sta/Parasitics.hh @@ -17,6 +17,8 @@ #pragma once #include +#include +#include #include "StaState.hh" #include "LibertyClass.hh" @@ -31,16 +33,17 @@ class Corner; typedef std::complex ComplexFloat; typedef Vector ComplexFloatSeq; -typedef Iterator ParasiticDeviceIterator; -typedef Iterator ParasiticNodeIterator; +typedef std::vector ParasiticNodeSeq; +typedef std::vector ParasiticResistorSeq; +typedef std::vector ParasiticCapacitorSeq; +typedef std::map ParasiticNodeResistorMap; +typedef std::map 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_; }; diff --git a/include/sta/ParasiticsClass.hh b/include/sta/ParasiticsClass.hh index 43abc027..b898effe 100644 --- a/include/sta/ParasiticsClass.hh +++ b/include/sta/ParasiticsClass.hh @@ -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 diff --git a/include/sta/Sdc.hh b/include/sta/Sdc.hh index c92a1c75..a8cb921e 100644 --- a/include/sta/Sdc.hh +++ b/include/sta/Sdc.hh @@ -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); diff --git a/include/sta/Sta.hh b/include/sta/Sta.hh index 5425aa99..34fd2375 100644 --- a/include/sta/Sta.hh +++ b/include/sta/Sta.hh @@ -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. diff --git a/parasitics/ConcreteParasitics.cc b/parasitics/ConcreteParasitics.cc index eb2afef0..cd4cc8a6 100644 --- a/parasitics/ConcreteParasitics.cc +++ b/parasitics/ConcreteParasitics.cc @@ -29,9 +29,7 @@ #include "Liberty.hh" #include "Sdc.hh" #include "Parasitics.hh" -#include "ReduceParasitics.hh" #include "MakeConcreteParasitics.hh" -#include "Parasitics.hh" #include "ConcreteParasiticsPvt.hh" #include "Corner.hh" @@ -129,18 +127,6 @@ ConcreteParasitic::setPoleResidue(const Pin *, { } -ParasiticDeviceIterator * -ConcreteParasitic::deviceIterator() const -{ - return nullptr; -} - -ParasiticNodeIterator * -ConcreteParasitic::nodeIterator() const -{ - return nullptr; -} - //////////////////////////////////////////////////////////////// ConcretePi::ConcretePi(float c2, @@ -190,16 +176,10 @@ ConcretePi::setIsReduced(bool reduced) ConcretePiElmore::ConcretePiElmore(float c2, float rpi, float c1) : - ConcretePi(c2, rpi, c1), - loads_(nullptr) + ConcretePi(c2, rpi, c1) { } -ConcretePiElmore::~ConcretePiElmore() -{ - delete loads_; -} - float ConcretePiElmore::capacitance() const { @@ -239,93 +219,46 @@ ConcretePiElmore::findElmore(const Pin *load_pin, float &elmore, bool &exists) const { - if (loads_) - loads_->findKey(load_pin, elmore, exists); - else + auto itr = loads_.find(load_pin); + if (itr == loads_.end()) exists = false; + else { + elmore = itr->second; + exists = true; + } } void ConcretePiElmore::setElmore(const Pin *load_pin, float elmore) { - if (loads_ == nullptr) - loads_ = new ConcreteElmoreLoadMap; - (*loads_)[load_pin] = elmore; + loads_[load_pin] = elmore; } void ConcretePiElmore::deleteLoad(const Pin *load_pin) { - loads_->erase(load_pin); + loads_.erase(load_pin); } -//////////////////////////////////////////////////////////////// - -ConcretePiElmoreEstimated::ConcretePiElmoreEstimated(float c2, - float rpi, - float c1, - float elmore_res, - float elmore_cap, - bool elmore_use_load_cap, - const RiseFall *rf, - const OperatingConditions *op, - const Corner *corner, - const MinMax *min_max, - Sdc *sdc): - ConcretePi(c2, rpi, c1), - elmore_res_(elmore_res), - elmore_cap_(elmore_cap), - elmore_use_load_cap_(elmore_use_load_cap), - rf_(rf), - op_cond_(op), - corner_(corner), - min_max_(min_max), - sdc_(sdc) +PinSet +ConcretePiElmore::unannotatedLoads(const Pin *drvr_pin, + const Parasitics *parasitics) const { -} - -float -ConcretePiElmoreEstimated::capacitance() const -{ - return ConcretePi::capacitance(); -} - -void -ConcretePiElmoreEstimated::piModel(float &c2, - float &rpi, - float &c1) const -{ - ConcretePi::piModel(c2, rpi, c1); -} - -void -ConcretePiElmoreEstimated::findElmore(const Pin *load_pin, - float &elmore, - bool &exists) const -{ - float load_cap = 0.0; - if (elmore_use_load_cap_) - load_cap = sdc_->pinCapacitance(load_pin, rf_, op_cond_, - corner_, min_max_); - elmore = elmore_res_ * (elmore_cap_ + load_cap); - exists = true; -} - -void -ConcretePiElmoreEstimated::setElmore(const Pin *, - float) -{ - // Cannot set elmore on estimated parasitic. + PinSet loads = parasitics->loads(drvr_pin); + for (auto pin_elmore : loads_) { + const Pin *load = pin_elmore.first; + loads.erase(load); + } + return loads; } //////////////////////////////////////////////////////////////// ConcretePoleResidue:: -ConcretePoleResidue(ComplexFloatSeq *poles, - ComplexFloatSeq *residues) : - poles_(poles), - residues_(residues) +ConcretePoleResidue() : + poles_(nullptr), + residues_(nullptr) { } @@ -358,24 +291,22 @@ ConcretePoleResidue::setPoleResidue(ComplexFloatSeq *poles, residues_ = residues; } +PinSet +ConcretePoleResidue::unannotatedLoads(const Pin *, + const Parasitics *) const +{ + return PinSet(); +} + //////////////////////////////////////////////////////////////// ConcretePiPoleResidue::ConcretePiPoleResidue(float c2, float rpi, float c1) : - ConcretePi(c2, rpi, c1), - load_pole_residue_(nullptr) + ConcretePi(c2, rpi, c1) { } -ConcretePiPoleResidue::~ConcretePiPoleResidue() -{ - if (load_pole_residue_) { - load_pole_residue_->deleteContents(); - delete load_pole_residue_; - } -} - float ConcretePiPoleResidue::capacitance() const { @@ -413,10 +344,11 @@ ConcretePiPoleResidue::setIsReduced(bool reduced) Parasitic * ConcretePiPoleResidue::findPoleResidue(const Pin *load_pin) const { - if (load_pole_residue_) - return load_pole_residue_->findKey(load_pin); - else + auto itr = load_pole_residue_.find(load_pin); + if (itr == load_pole_residue_.end()) return nullptr; + else + return &const_cast(itr->second); } void @@ -424,32 +356,48 @@ ConcretePiPoleResidue::setPoleResidue(const Pin *load_pin, ComplexFloatSeq *poles, ComplexFloatSeq *residues) { - if (load_pole_residue_ == nullptr) - load_pole_residue_ = new ConcretePoleResidueMap; - ConcretePoleResidue *pole_residue = load_pole_residue_->findKey(load_pin); - if (pole_residue == nullptr) { - pole_residue = new ConcretePoleResidue(poles, residues); - (*load_pole_residue_)[load_pin] = pole_residue; - } - else - pole_residue->setPoleResidue(poles, residues); + ConcretePoleResidue &pole_residue = load_pole_residue_[load_pin]; + pole_residue.setPoleResidue(poles, residues); } void ConcretePiPoleResidue::deleteLoad(const Pin *load_pin) { - ConcretePoleResidue *pole_residue = load_pole_residue_->findKey(load_pin); - if (pole_residue) { - load_pole_residue_->erase(load_pin); - delete pole_residue; + load_pole_residue_.erase(load_pin); +} + +PinSet +ConcretePiPoleResidue::unannotatedLoads(const Pin *drvr_pin, + const Parasitics *parasitics) const +{ + PinSet loads = parasitics->loads(drvr_pin); + for (auto pin_pole_residue : load_pole_residue_) { + const Pin *load = pin_pole_residue.first; + loads.erase(load); } + return loads; } //////////////////////////////////////////////////////////////// -ConcreteParasiticNode::ConcreteParasiticNode() : +ConcreteParasiticNode::ConcreteParasiticNode(const Net *net, + int id, + bool is_external) : + is_net_(true), + is_external_(is_external), + id_(id), cap_(0.0) { + net_pin_.net_ = net; +} + +ConcreteParasiticNode::ConcreteParasiticNode(const Pin *pin, + bool is_external) : + is_net_(false), + is_external_(is_external), + cap_(0.0) +{ + net_pin_.pin_ = pin; } void @@ -458,201 +406,89 @@ ConcreteParasiticNode::incrCapacitance(float cap) cap_ += cap; } -float -ConcreteParasiticNode::capacitance() const +const char * +ConcreteParasiticNode::name(const Network *network) const { - return cap_; + if (is_net_) { + const char *net_name = network->pathName(net_pin_.net_); + return stringPrintTmp("%s:%d", net_name, id_); + } + else + return network->pathName(net_pin_.pin_); } -void -ConcreteParasiticNode::addDevice(ConcreteParasiticDevice *device) +const Pin * +ConcreteParasiticNode::pin() const { - devices_.push_back(device); + if (is_net_) + return nullptr; + else + return net_pin_.pin_; +} + +const Net * +ConcreteParasiticNode::net(const Network *network) const +{ + if (is_net_) + return net_pin_.net_; + else { + Net *net = network->net(net_pin_.pin_); + // Pins on the top level instance may not have nets. + // Use the net connected to the pin's terminal. + if (net == nullptr && network->isTopLevelPort(net_pin_.pin_)) { + Term *term = network->term(net_pin_.pin_); + if (term) + return network->net(term); + } + return net; + } } //////////////////////////////////////////////////////////////// -ConcreteParasiticSubNode::ConcreteParasiticSubNode(const Net *net, - int id) : - ConcreteParasiticNode(), + +ConcreteParasiticDevice::ConcreteParasiticDevice(size_t id, + float value, + ConcreteParasiticNode *node1, + ConcreteParasiticNode *node2) : + id_(id), + value_(value), + node1_(node1), + node2_(node2) +{ +} + +void +ConcreteParasiticDevice::replaceNode(ConcreteParasiticNode *from_node, + ConcreteParasiticNode *to_node) +{ + if (from_node == node1_) + node1_ = to_node; + else if (from_node == node2_) + node2_ = to_node; +} + +ConcreteParasiticResistor::ConcreteParasiticResistor(size_t id, + float value, + ConcreteParasiticNode *node1, + ConcreteParasiticNode *node2) : + ConcreteParasiticDevice(id, value, node1, node2) +{ +} + +ConcreteParasiticCapacitor::ConcreteParasiticCapacitor(size_t id, + float value, + ConcreteParasiticNode *node1, + ConcreteParasiticNode *node2) : + ConcreteParasiticDevice(id, value, node1, node2) +{ +} + +//////////////////////////////////////////////////////////////// + +ConcreteParasiticNetwork::ConcreteParasiticNetwork(const Net *net, + bool includes_pin_caps) : net_(net), - id_(id) -{ -} - -const char * -ConcreteParasiticSubNode::name(const Network *network) const -{ - const char *net_name = network->pathName(net_); - return stringPrintTmp("%s:%d", net_name, id_); -} - -//////////////////////////////////////////////////////////////// - -ConcreteParasiticPinNode::ConcreteParasiticPinNode(const Pin *pin) : - ConcreteParasiticNode(), - pin_(pin) -{ -} - -const char * -ConcreteParasiticPinNode::name(const Network *network) const -{ - return network->pathName(pin_); -} - -//////////////////////////////////////////////////////////////// - -ConcreteParasiticDevice::ConcreteParasiticDevice(const char *name, - ConcreteParasiticNode *node, - float value) : - name_(name), - node_(node), - value_(value) -{ -} - -ConcreteParasiticDevice::~ConcreteParasiticDevice() -{ - if (name_) - stringDelete(name_); -} - -ConcreteParasiticResistor:: -ConcreteParasiticResistor(const char *name, - ConcreteParasiticNode *node, - ConcreteParasiticNode *other_node, - float res) : - ConcreteParasiticDevice(name, node, res), - other_node_(other_node) -{ -} - -ParasiticNode * -ConcreteParasiticResistor::otherNode(ParasiticNode *node) const -{ - if (node == node_) - return other_node_; - else if (node == other_node_) - return node_; - else - return nullptr; -} - -void -ConcreteParasiticResistor::replaceNode(ConcreteParasiticNode *from_node, - ConcreteParasiticNode *to_node) -{ - if (from_node == node_) - node_ = to_node; - else - other_node_ = to_node; -} - -//////////////////////////////////////////////////////////////// - -ConcreteCouplingCap::ConcreteCouplingCap(const char *name, - ConcreteParasiticNode *node, - float cap) : - ConcreteParasiticDevice(name, node, cap) -{ -} - -void -ConcreteCouplingCap::replaceNode(ConcreteParasiticNode *from_node, - ConcreteParasiticNode *to_node) -{ - if (from_node == node_) - node_ = to_node; -} - -//////////////////////////////////////////////////////////////// - -ConcreteCouplingCapInt:: -ConcreteCouplingCapInt(const char *name, - ConcreteParasiticNode *node, - ConcreteParasiticNode *other_node, - float cap) : - ConcreteCouplingCap(name, node, cap), - other_node_(other_node) -{ -} - -ParasiticNode * -ConcreteCouplingCapInt::otherNode(ParasiticNode *node) const -{ - if (node == node_) - return other_node_; - else if (node == other_node_) - return node_; - else - return nullptr; -} - -void -ConcreteCouplingCapInt::replaceNode(ConcreteParasiticNode *from_node, - ConcreteParasiticNode *to_node) -{ - if (from_node == node_) - node_ = to_node; - else - other_node_ = to_node; -} - -//////////////////////////////////////////////////////////////// - -ConcreteCouplingCapExtNode:: -ConcreteCouplingCapExtNode(const char *name, - ConcreteParasiticNode *node, - Net *, - int, - float cap) : - ConcreteCouplingCap(name, node, cap) -{ -} - -ParasiticNode * -ConcreteCouplingCapExtNode::otherNode(ParasiticNode *) const -{ - return nullptr; -} - -void -ConcreteCouplingCapExtNode::replaceNode(ConcreteParasiticNode *from_node, - ConcreteParasiticNode *to_node) -{ - if (from_node == node_) - node_ = to_node; -} - -//////////////////////////////////////////////////////////////// - -ConcreteCouplingCapExtPin:: -ConcreteCouplingCapExtPin(const char *name, - ConcreteParasiticNode *node, - Pin *, - float cap) : - ConcreteCouplingCap(name, node, cap) -{ -} - -ParasiticNode * -ConcreteCouplingCapExtPin::otherNode(ParasiticNode *) const -{ - return nullptr; -} - -void -ConcreteCouplingCapExtPin::replaceNode(ConcreteParasiticNode *from_node, - ConcreteParasiticNode *to_node) -{ - if (from_node == node_) - node_ = to_node; -} - -//////////////////////////////////////////////////////////////// - -ConcreteParasiticNetwork::ConcreteParasiticNetwork(bool includes_pin_caps) : max_node_id_(0), includes_pin_caps_(includes_pin_caps) { @@ -667,128 +503,209 @@ ConcreteParasiticNetwork::~ConcreteParasiticNetwork() void ConcreteParasiticNetwork::deleteNodes() { - ConcreteParasiticSubNodeMap::Iterator node_iter1(sub_nodes_); - while (node_iter1.hasNext()) { - NetIdPair *net_id; - ConcreteParasiticSubNode *node; - node_iter1.next(net_id, node); - delete net_id; + for (auto id_node : sub_nodes_) { + ConcreteParasiticNode *node = id_node.second; + delete node; + } + for (auto pin_node : pin_nodes_) { + ParasiticNode *node = pin_node.second; delete node; } - pin_nodes_.deleteContents(); } void ConcreteParasiticNetwork::deleteDevices() { - ConcreteParasiticDeviceSet devices1; - devices(&devices1); - devices1.deleteContents(); -} - -ParasiticNodeIterator * -ConcreteParasiticNetwork::nodeIterator() const -{ - ConcreteParasiticNodeSeq *nodes = new ConcreteParasiticNodeSeq(); - ConcreteParasiticPinNodeMap::ConstIterator node_iter2(pin_nodes_); - while (node_iter2.hasNext()) { - ConcreteParasiticPinNode *node = node_iter2.next(); - nodes->push_back(node); + for (ParasiticResistor *resistor : resistors_) { + ConcreteParasiticResistor *cresistor = + reinterpret_cast(resistor); + delete cresistor; } - ConcreteParasiticSubNodeMap::ConstIterator node_iter1(sub_nodes_); - while (node_iter1.hasNext()) { - ConcreteParasiticSubNode *node = node_iter1.next(); - nodes->push_back(node); + for (ParasiticCapacitor *capacitor : capacitors_) { + ConcreteParasiticCapacitor *ccapacitor = + reinterpret_cast(capacitor); + delete ccapacitor; } - return new ConcreteParasiticNodeSeqIterator(nodes); -} - -ParasiticDeviceIterator * -ConcreteParasiticNetwork::deviceIterator() const -{ - ConcreteParasiticDeviceSet *devices1 = new ConcreteParasiticDeviceSet(); - devices(devices1); - return new ConcreteParasiticDeviceSetIterator(devices1); } void -ConcreteParasiticNetwork::devices(ConcreteParasiticDeviceSet *devices) const +ConcreteParasiticNetwork::addResistor(ParasiticResistor *resistor) { - // Collect devices into a set so they are only deleted once - // because multiple sub-nodes or pin nodes can refer to them. - ConcreteParasiticSubNodeMap::ConstIterator node_iter1(sub_nodes_); - while (node_iter1.hasNext()) { - ConcreteParasiticSubNode *node = node_iter1.next(); - ConcreteParasiticDeviceSeq::Iterator device_iter(node->devices()); - while (device_iter.hasNext()) { - ConcreteParasiticDevice *device = device_iter.next(); - devices->insert(device); - } - } + resistors_.push_back(resistor); +} - ConcreteParasiticPinNodeMap::ConstIterator node_iter2(pin_nodes_); - while (node_iter2.hasNext()) { - ConcreteParasiticPinNode *node = node_iter2.next(); - ConcreteParasiticDeviceSeq::ConstIterator device_iter(node->devices()); - while (device_iter.hasNext()) { - ConcreteParasiticDevice *device = device_iter.next(); - devices->insert(device); - } +void +ConcreteParasiticNetwork::addCapacitor(ParasiticCapacitor *capacitor) +{ + capacitors_.push_back(capacitor); +} + +ParasiticNodeSeq +ConcreteParasiticNetwork::nodes() const +{ + ParasiticNodeSeq nodes; + for (auto pin_node : pin_nodes_) { + ParasiticNode *node = pin_node.second; + nodes.push_back(node); } + for (auto id_node : sub_nodes_) { + ParasiticNode *node = id_node.second; + nodes.push_back(node); + } + return nodes; } float ConcreteParasiticNetwork::capacitance() const { float cap = 0.0; - ConcreteParasiticSubNodeMap::ConstIterator sub_node_iter(sub_nodes_); - while (sub_node_iter.hasNext()) { - ConcreteParasiticSubNode *node = sub_node_iter.next(); - cap += node->capacitance(); + for (auto id_node : sub_nodes_) { + ConcreteParasiticNode *node = id_node.second; + if (!node->isExternal()) + cap += node->capacitance(); } - ConcreteParasiticPinNodeMap::ConstIterator pin_node_iter(pin_nodes_); - while (pin_node_iter.hasNext()) { - ConcreteParasiticPinNode *node = pin_node_iter.next(); - cap += node->capacitance(); + for (auto pin_node : pin_nodes_) { + ConcreteParasiticNode *node = pin_node.second; + if (!node->isExternal()) + cap += node->capacitance(); } + + for (ParasiticCapacitor *capacitor : capacitors_) { + ConcreteParasiticCapacitor *ccap = + static_cast(capacitor); + cap += ccap->value(); + } + return cap; } ConcreteParasiticNode * ConcreteParasiticNetwork::ensureParasiticNode(const Net *net, - int id) + int id, + const Network *) { + ConcreteParasiticNode *node; NetIdPair net_id(net, id); - ConcreteParasiticSubNode *node = sub_nodes_.findKey(&net_id); - if (node == nullptr) { - node = new ConcreteParasiticSubNode(net, id); - sub_nodes_[new NetIdPair(net, id)] = node; + auto id_node = sub_nodes_.find(net_id); + if (id_node == sub_nodes_.end()) { + node = new ConcreteParasiticNode(net, id, net != net_); + sub_nodes_[net_id] = node; max_node_id_ = max((int) max_node_id_, id); } + else + node = id_node->second; + return node; +} + +ConcreteParasiticNode * +ConcreteParasiticNetwork::ensureParasiticNode(const Pin *pin, + const Network *network) +{ + ConcreteParasiticNode *node; + auto pin_node = pin_nodes_.find(pin); + if (pin_node == pin_nodes_.end()) { + Net *net = network->net(pin); + // Pins on the top level instance may not have nets. + // Use the net connected to the pin's terminal. + if (net == nullptr && network->isTopLevelPort(pin)) { + Term *term = network->term(pin); + if (term) + net = network->net(term); + } + else + net = network->highestNetAbove(net); + node = new ConcreteParasiticNode(pin, net != net_); + pin_nodes_[pin] = node; + } + else + node = pin_node->second; return node; } ConcreteParasiticNode * ConcreteParasiticNetwork::findNode(const Pin *pin) const { - return pin_nodes_.findKey(pin); + auto pin_node = pin_nodes_.find(pin); + if (pin_node == pin_nodes_.end()) + return nullptr; + else + return pin_node->second; +} + +PinSet +ConcreteParasiticNetwork::unannotatedLoads(const Pin *drvr_pin, + const Parasitics *parasitics) const +{ + PinSet loads = parasitics->loads(drvr_pin); + ParasiticNode *drvr_node = findNode(drvr_pin); + if (drvr_node) { + ParasiticNodeResistorMap resistor_map = + parasitics->parasiticNodeResistorMap(this); + ParasiticNodeSet visited_nodes; + ParasiticResistorSet loop_resistors; + unannotatedLoads(drvr_node, nullptr, loads, visited_nodes, + loop_resistors, resistor_map, parasitics); + } + return loads; } void -ConcreteParasiticNetwork::disconnectPin(const Pin *pin, - const Net *net) +ConcreteParasiticNetwork::unannotatedLoads(ParasiticNode *node, + ParasiticResistor *from_res, + PinSet &loads, + ParasiticNodeSet &visited_nodes, + ParasiticResistorSet &loop_resistors, + ParasiticNodeResistorMap &resistor_map, + const Parasitics *parasitics) const { - ConcreteParasiticNode *node = pin_nodes_.findKey(pin); - if (node) { + const Pin *pin = parasitics->pin(node); + if (pin) + loads.erase(const_cast(pin)); + + visited_nodes.insert(node); + ParasiticResistorSeq &resistors = resistor_map[node]; + for (ParasiticResistor *resistor : resistors) { + if (loop_resistors.find(resistor) == loop_resistors.end()) { + ParasiticNode *onode = parasitics->otherNode(resistor, node); + // One commercial extractor creates resistors with identical from/to nodes. + if (onode != node + && resistor != from_res) { + if (visited_nodes.find(onode) == visited_nodes.end()) + unannotatedLoads(onode, resistor, loads, visited_nodes, + loop_resistors, resistor_map, parasitics); + else + // resistor loop + loop_resistors.insert(resistor); + } + } + } + visited_nodes.erase(node); +} + +//////////////////////////////////////////////////////////////// + +void +ConcreteParasiticNetwork::disconnectPin(const Pin *pin, + const Net *net, + const Network *network) +{ + auto pin_node = pin_nodes_.find(pin); + if (pin_node != pin_nodes_.end()) { + ConcreteParasiticNode *node = pin_node->second; // Make a subnode to replace the pin node. - ConcreteParasiticNode *subnode = ensureParasiticNode(net,max_node_id_+1); + ConcreteParasiticNode *subnode = ensureParasiticNode(net,max_node_id_+1, + network); // Hand over the devices. - ConcreteParasiticDeviceSeq::Iterator device_iter(node->devices()); - while (device_iter.hasNext()) { - ConcreteParasiticDevice *device = device_iter.next(); - subnode->addDevice(device); - device->replaceNode(node, subnode); + for (ParasiticResistor *resistor : resistors_) { + ConcreteParasiticResistor *cresistor = + reinterpret_cast(resistor); + cresistor->replaceNode(node, subnode); + } + for (ParasiticCapacitor *capacitor : capacitors_) { + ConcreteParasiticCapacitor *ccapacitor = + reinterpret_cast(capacitor); + ccapacitor->replaceNode(node, subnode); } pin_nodes_.erase(pin); @@ -796,25 +713,14 @@ ConcreteParasiticNetwork::disconnectPin(const Pin *pin, } } -ConcreteParasiticNode * -ConcreteParasiticNetwork::ensureParasiticNode(const Pin *pin) -{ - ConcreteParasiticPinNode *node = pin_nodes_.findKey(pin); - if (node == nullptr) { - node = new ConcreteParasiticPinNode(pin); - pin_nodes_[pin] = node; - } - return node; -} - bool -NetIdPairLess::operator()(const NetIdPair *net_id1, - const NetIdPair *net_id2) const +NetIdPairLess::operator()(const NetIdPair &net_id1, + const NetIdPair &net_id2) const { - const Net *net1 = net_id1->first; - const Net *net2 = net_id2->first; - int id1 = net_id1->second; - int id2 = net_id2->second; + const Net *net1 = net_id1.first; + const Net *net2 = net_id2.first; + int id1 = net_id1.second; + int id2 = net_id2.second; return net1 < net2 || (net1 == net2 && id1 < id2); @@ -913,19 +819,6 @@ ConcreteParasitics::deleteParasitics(const Net *net, } } -void -ConcreteParasitics::deleteUnsavedParasitic(Parasitic *parasitic) -{ - ConcreteParasitic *cparasitic = static_cast(parasitic); - delete cparasitic; -} - -void -ConcreteParasitics::save() -{ - // No database to save to. -} - float ConcreteParasitics::capacitance(const Parasitic *parasitic) const { @@ -949,7 +842,8 @@ ConcreteParasitics::setIsReducedParasiticNetwork(Parasitic *parasitic, } void -ConcreteParasitics::disconnectPinBefore(const Pin *pin) +ConcreteParasitics::disconnectPinBefore(const Pin *pin, + const Network *network) { if (haveParasitics()) { deleteReducedParasitics(pin); @@ -962,7 +856,7 @@ ConcreteParasitics::disconnectPinBefore(const Pin *pin) for (int i = 0; i < ap_count; i++) { ConcreteParasiticNetwork *parasitic = parasitics[i]; if (parasitic) - parasitic->disconnectPin(pin, net); + parasitic->disconnectPin(pin, net, network); } } } @@ -1050,10 +944,6 @@ ConcreteParasitics::findPiElmore(const Pin *drvr_pin, ConcreteParasitic **parasitics = drvr_parasitic_map_.findKey(drvr_pin); if (parasitics) { ConcreteParasitic *parasitic = parasitics[ap_rf_index]; - if (parasitic == nullptr && rf == RiseFall::fall()) { - ap_rf_index = parasiticAnalysisPtIndex(ap, RiseFall::rise()); - parasitic = parasitics[ap_rf_index]; - } if (parasitic && parasitic->isPiElmore()) return parasitic; } @@ -1286,8 +1176,12 @@ ConcreteParasitics::findParasiticNetwork(const Net *net, UniqueLock lock(lock_); if (!parasitic_network_map_.empty()) { ConcreteParasiticNetwork **parasitics=parasitic_network_map_.findKey(net); - if (parasitics) - return parasitics[ap->index()]; + if (parasitics) { + ConcreteParasiticNetwork *parasitic = parasitics[ap->index()]; + if (parasitic == nullptr) + parasitic = parasitics[ap->indexMax()]; + return parasitic; + } } } return nullptr; @@ -1303,8 +1197,12 @@ ConcreteParasitics::findParasiticNetwork(const Pin *pin, // Only call findParasiticNet if parasitics exist. const Net *net = findParasiticNet(pin); ConcreteParasiticNetwork **parasitics=parasitic_network_map_.findKey(net); - if (parasitics) - return parasitics[ap->index()]; + if (parasitics) { + ConcreteParasiticNetwork *parasitic = parasitics[ap->index()]; + if (parasitic == nullptr) + parasitic = parasitics[ap->indexMax()]; + return parasitic; + } } } return nullptr; @@ -1326,9 +1224,12 @@ ConcreteParasitics::makeParasiticNetwork(const Net *net, } int ap_index = ap->index(); ConcreteParasiticNetwork *parasitic = parasitics[ap_index]; - if (parasitic) + if (parasitic) { delete parasitic; - parasitic = new ConcreteParasiticNetwork(includes_pin_caps); + for (const Pin *drvr_pin : *network_->drivers(net)) + deleteParasitics(drvr_pin, ap); + } + parasitic = new ConcreteParasiticNetwork(net, includes_pin_caps); parasitics[ap_index] = parasitic; return parasitic; } @@ -1343,14 +1244,20 @@ ConcreteParasitics::deleteParasiticNetwork(const Net *net, if (parasitics) { int ap_index = ap->index(); delete parasitics[ap_index]; + parasitics[ap_index] = nullptr; + int ap_count = corners_->parasiticAnalysisPtCount(); - if (ap_count == 1) { - // If there is only one parasitic we can remove the array and map entry. + bool have_parasitics = false; + for (int i = 0; i < ap_count; i++) { + if (parasitics[i]) { + have_parasitics = true; + break; + } + } + if (!have_parasitics) { delete [] parasitics; parasitic_network_map_.erase(net); } - else - parasitics[ap_index] = nullptr; } } } @@ -1382,113 +1289,89 @@ ConcreteParasitics::includesPinCaps(const Parasitic *parasitic) const ParasiticNode * ConcreteParasitics::ensureParasiticNode(Parasitic *parasitic, const Net *net, - int id) + int id, + const Network *network) { ConcreteParasiticNetwork *cparasitic = static_cast(parasitic); - return cparasitic->ensureParasiticNode(net, id); + return cparasitic->ensureParasiticNode(net, id, network); } ParasiticNode * ConcreteParasitics::ensureParasiticNode(Parasitic *parasitic, - const Pin *pin) + const Pin *pin, + const Network *network) { ConcreteParasiticNetwork *cparasitic = static_cast(parasitic); - return cparasitic->ensureParasiticNode(pin); + return cparasitic->ensureParasiticNode(pin, network); } void ConcreteParasitics::incrCap(ParasiticNode *node, - float cap, - const ParasiticAnalysisPt *) + float cap) { ConcreteParasiticNode *cnode = static_cast(node); cnode->incrCapacitance(cap); } void -ConcreteParasitics::makeCouplingCap(const char *name, - ParasiticNode *node, - ParasiticNode *other_node, - float cap, - const ParasiticAnalysisPt *) -{ - ConcreteParasiticNode *cnode = static_cast(node); - ConcreteParasiticNode *other_cnode = - static_cast(other_node); - ConcreteCouplingCap *coupling_cap = - new ConcreteCouplingCapInt(name, cnode, other_cnode, cap); - cnode->addDevice(coupling_cap); - other_cnode->addDevice(coupling_cap); -} - -void -ConcreteParasitics::makeCouplingCap(const char *name, - ParasiticNode *node, - Net *other_node_net, - int other_node_id, - float cap, - const ParasiticAnalysisPt *) -{ - ConcreteParasiticNode *cnode = static_cast(node); - ConcreteCouplingCap *coupling_cap = - new ConcreteCouplingCapExtNode(name, cnode, other_node_net, - other_node_id, cap); - cnode->addDevice(coupling_cap); -} - -void -ConcreteParasitics::makeCouplingCap(const char *name, - ParasiticNode *node, - Pin *other_node_pin, - float cap, - const ParasiticAnalysisPt *) -{ - ConcreteParasiticNode *cnode = static_cast(node); - ConcreteCouplingCap *coupling_cap = - new ConcreteCouplingCapExtPin(name, cnode, other_node_pin, cap); - cnode->addDevice(coupling_cap); -} - -void -ConcreteParasitics::makeResistor(const char *name, - ParasiticNode *node1, - ParasiticNode *node2, - float res, - const ParasiticAnalysisPt *) +ConcreteParasitics::makeCapacitor(Parasitic *parasitic, + size_t index, + float cap, + ParasiticNode *node1, + ParasiticNode *node2) { ConcreteParasiticNode *cnode1 = static_cast(node1); ConcreteParasiticNode *cnode2 = static_cast(node2); - ConcreteParasiticDevice *resistor = - new ConcreteParasiticResistor(name, cnode1, cnode2, res); - cnode1->addDevice(resistor); - cnode2->addDevice(resistor); + ConcreteParasiticCapacitor *capacitor = + new ConcreteParasiticCapacitor(index, cap, cnode1, cnode2); + ConcreteParasiticNetwork *cparasitic = + static_cast(parasitic); + cparasitic->addCapacitor(capacitor); } -ParasiticDeviceIterator * -ConcreteParasitics::deviceIterator(const Parasitic *parasitic) +void +ConcreteParasitics::makeResistor(Parasitic *parasitic, + size_t index, + float res, + ParasiticNode *node1, + ParasiticNode *node2) { - const ConcreteParasitic *cparasitic = static_cast(parasitic); - return cparasitic->deviceIterator(); + ConcreteParasiticNode *cnode1 = static_cast(node1); + ConcreteParasiticNode *cnode2 = static_cast(node2); + ParasiticResistor *resistor = new ConcreteParasiticResistor(index, res, + cnode1, cnode2); + ConcreteParasiticNetwork *cparasitic = + static_cast(parasitic); + cparasitic->addResistor(resistor); } -ParasiticNodeIterator * -ConcreteParasitics::nodeIterator(const Parasitic *parasitic) +ParasiticNodeSeq +ConcreteParasitics::nodes(const Parasitic *parasitic) const { - const ConcreteParasitic *cparasitic = static_cast(parasitic); - return cparasitic->nodeIterator(); + const ConcreteParasiticNetwork *cparasitic = + static_cast(parasitic); + return cparasitic->nodes(); } -float -ConcreteParasitics::nodeGndCap(const ParasiticNode *node, - const ParasiticAnalysisPt *) const +ParasiticResistorSeq +ConcreteParasitics::resistors(const Parasitic *parasitic) const { - const ConcreteParasiticNode *cnode = - static_cast(node); - return cnode->capacitance(); + const ConcreteParasiticNetwork *cparasitic = + static_cast(parasitic); + return cparasitic->resistors(); } +ParasiticCapacitorSeq +ConcreteParasitics::capacitors(const Parasitic *parasitic) const +{ + const ConcreteParasiticNetwork *cparasitic = + static_cast(parasitic); + return cparasitic->capacitors(); +} + + const char * ConcreteParasitics::name(const ParasiticNode *node) { @@ -1497,18 +1380,37 @@ ConcreteParasitics::name(const ParasiticNode *node) return cnode->name(network_); } -const Pin * -ConcreteParasitics::connectionPin(const ParasiticNode *node) const +float +ConcreteParasitics::nodeGndCap(const ParasiticNode *node) const { const ConcreteParasiticNode *cnode = static_cast(node); - if (cnode->isPinNode()) { - const ConcreteParasiticPinNode *pin_node = - dynamic_cast(cnode); - return pin_node->pin(); - } - else - return nullptr; + return cnode->capacitance(); +} + +const Pin * +ConcreteParasitics::pin(const ParasiticNode *node) const +{ + const ConcreteParasiticNode *cnode = + static_cast(node); + return cnode->pin(); +} + +const Net * +ConcreteParasitics::net(const ParasiticNode *node, + const Network *network) const +{ + const ConcreteParasiticNode *cnode = + static_cast(node); + return cnode->net(network); +} + +bool +ConcreteParasitics::isExternal(const ParasiticNode *node) const +{ + const ConcreteParasiticNode *cnode = + static_cast(node); + return cnode->isExternal(); } ParasiticNode * @@ -1520,305 +1422,82 @@ ConcreteParasitics::findNode(const Parasitic *parasitic, return cparasitic->findNode(pin); } -ParasiticDeviceIterator * -ConcreteParasitics::deviceIterator(ParasiticNode *node) const -{ - ConcreteParasiticNode *cnode = static_cast(node); - return new ConcreteParasiticDeviceSeqIterator(cnode->devices()); -} +//////////////////////////////////////////////////////////////// -const char * -ConcreteParasitics::name(const ParasiticDevice *device) const +size_t +ConcreteParasitics::id(const ParasiticResistor *resistor) const { - const ConcreteParasiticDevice *cdevice = - static_cast(device); - return cdevice->name(); -} - -bool -ConcreteParasitics::isResistor(const ParasiticDevice *device) const -{ - const ConcreteParasiticDevice *cdevice = - static_cast(device); - return cdevice->isResistor(); -} - -bool -ConcreteParasitics::isCouplingCap(const ParasiticDevice *device) const -{ - const ConcreteParasiticDevice *cdevice = - static_cast(device); - return cdevice->isCouplingCap(); + const ConcreteParasiticResistor *cresistor = + static_cast(resistor); + return cresistor->id(); } float -ConcreteParasitics::value(const ParasiticDevice *device, - const ParasiticAnalysisPt *) const +ConcreteParasitics::value(const ParasiticResistor *resistor) const { - const ConcreteParasiticDevice *cdevice = - static_cast(device); - return cdevice->value(); + const ConcreteParasiticResistor *cresistor = + static_cast(resistor); + return cresistor->value(); } ParasiticNode * -ConcreteParasitics::node1(const ParasiticDevice *device) const +ConcreteParasitics::node1(const ParasiticResistor *resistor) const { - const ConcreteParasiticDevice *cdevice = - static_cast(device); - return cdevice->node1(); + const ConcreteParasiticResistor *cresistor = + static_cast(resistor); + return cresistor->node1(); } ParasiticNode * -ConcreteParasitics::node2(const ParasiticDevice *device) const +ConcreteParasitics::node2(const ParasiticResistor *resistor) const { - const ConcreteParasiticDevice *cdevice = - static_cast(device); - return cdevice->node2(); -} - -ParasiticNode * -ConcreteParasitics::otherNode(const ParasiticDevice *device, - ParasiticNode *node) const -{ - const ConcreteParasiticDevice *cdevice = - static_cast(device); - return cdevice->otherNode(node); + const ConcreteParasiticResistor *cresistor = + static_cast(resistor); + return cresistor->node2(); } //////////////////////////////////////////////////////////////// -bool -ConcreteParasitics::checkAnnotation(Parasitic *parasitic_network, - const Pin *drvr_pin) +size_t +ConcreteParasitics::id(const ParasiticCapacitor *capacitor) const { - ParasiticNode *drvr_node = findNode(parasitic_network, drvr_pin); - if (drvr_node) - return checkAnnotation(drvr_pin, drvr_node); - return false; + const ConcreteParasiticCapacitor *ccapacitor = + static_cast(capacitor); + return ccapacitor->id(); } -bool -ConcreteParasitics::checkAnnotation(const Pin *drvr_pin, - ParasiticNode *drvr_node) +float +ConcreteParasitics::value(const ParasiticCapacitor *capacitor) const { - PinSet unannotated_loads = checkAnnotation1(drvr_pin, drvr_node); - return unannotated_loads.empty(); + const ConcreteParasiticCapacitor *ccapacitor = + static_cast(capacitor); + return ccapacitor->value(); } +ParasiticNode * +ConcreteParasitics::node1(const ParasiticCapacitor *capacitor) const +{ + const ConcreteParasiticCapacitor *ccapacitor = + static_cast(capacitor); + return ccapacitor->node1(); +} + +ParasiticNode * +ConcreteParasitics::node2(const ParasiticCapacitor *capacitor) const +{ + const ConcreteParasiticCapacitor *ccapacitor = + static_cast(capacitor); + return ccapacitor->node2(); +} + +//////////////////////////////////////////////////////////////// + PinSet -ConcreteParasitics::unannotatedLoads(Parasitic *parasitic_network, - const Pin *drvr_pin) +ConcreteParasitics::unannotatedLoads(const Parasitic *parasitic, + const Pin *drvr_pin) const { - ParasiticNode *drvr_node = findNode(parasitic_network, drvr_pin); - if (drvr_node) - return checkAnnotation1(drvr_pin, drvr_node); - return PinSet(network_); -} - -PinSet -ConcreteParasitics::checkAnnotation1(const Pin *drvr_pin, - ParasiticNode *drvr_node) -{ - 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); - } - delete pin_iter; - - ParasiticNodeSet visited_nodes; - ParasiticDeviceSet loop_resistors; - checkAnnotation2(drvr_pin, drvr_node, nullptr, loads, - visited_nodes, loop_resistors); - return loads; -} - -void -ConcreteParasitics::checkAnnotation2(const Pin *drvr_pin, - ParasiticNode *node, - ParasiticDevice *from_res, - PinSet &loads, - ParasiticNodeSet &visited_nodes, - ParasiticDeviceSet &loop_resistors) -{ - const Pin *pin = parasitics_->connectionPin(node); - if (pin) - loads.erase(const_cast(pin)); - - visited_nodes.insert(node); - ParasiticDeviceIterator *device_iter = parasitics_->deviceIterator(node); - while (device_iter->hasNext()) { - ParasiticDevice *device = device_iter->next(); - if (parasitics_->isResistor(device) - && loop_resistors.find(device) == loop_resistors.end()) { - ParasiticNode *onode = parasitics_->otherNode(device, node); - // One commercial extractor creates resistors with identical from/to nodes. - if (onode != node - && device != from_res) { - if (visited_nodes.find(onode) == visited_nodes.end()) - checkAnnotation2(drvr_pin, onode, device, loads, - visited_nodes, loop_resistors); - else - // resistor loop - loop_resistors.insert(device); - } - } - } - delete device_iter; - visited_nodes.erase(node); -} - -//////////////////////////////////////////////////////////////// - -void -ConcreteParasitics::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) -{ - switch (reduce_to) { - case ReducedParasiticType::pi_elmore: - reduceToPiElmore(parasitic, net, op_cond, corner, cnst_min_max, ap); - break; - case ReducedParasiticType::pi_pole_residue2: - reduceToPiPoleResidue2(parasitic, net, op_cond, corner, - cnst_min_max, ap); - break; - case ReducedParasiticType::arnoldi: - case ReducedParasiticType::none: - break; - } -} - -void -ConcreteParasitics::reduceToPiElmore(const Parasitic *parasitic, - const Net *net, - const OperatingConditions *op_cond, - const Corner *corner, - const MinMax *cnst_min_max, - const ParasiticAnalysisPt *ap) -{ - debugPrint(debug_, "parasitic_reduce", 1, "Reduce net %s", - network_->pathName(net)); - NetConnectedPinIterator *pin_iter = network_->connectedPinIterator(net); - while (pin_iter->hasNext()) { - const Pin *pin = pin_iter->next(); - if (network_->isDriver(pin)) { - sta::reduceToPiElmore(parasitic, pin, ap->couplingCapFactor(), - op_cond, corner, cnst_min_max, ap, this); - } - } - delete pin_iter; -} - -void -ConcreteParasitics::reduceToPiElmore(const Parasitic *parasitic, - const Pin *drvr_pin, - const OperatingConditions *op_cond, - const Corner *corner, - const MinMax *cnst_min_max, - const ParasiticAnalysisPt *ap) -{ - sta::reduceToPiElmore(parasitic, drvr_pin, ap->couplingCapFactor(), - op_cond, corner, cnst_min_max, ap, this); -} - -void -ConcreteParasitics::reduceToPiPoleResidue2(const Parasitic *parasitic, - const Net *net, - const OperatingConditions *op_cond, - const Corner *corner, - const MinMax *cnst_min_max, - const ParasiticAnalysisPt *ap) -{ - debugPrint(debug_, "parasitic_reduce", 1, "Reduce net %s", - network_->pathName(net)); - NetConnectedPinIterator *pin_iter = network_->connectedPinIterator(net); - while (pin_iter->hasNext()) { - const Pin *pin = pin_iter->next(); - if (network_->isDriver(pin)) - sta::reduceToPiPoleResidue2(parasitic, pin, ap->couplingCapFactor(), - op_cond, corner, cnst_min_max, ap, this); - } - delete pin_iter; -} - -void -ConcreteParasitics::reduceToPiPoleResidue2(const Parasitic *parasitic, - const Pin *drvr_pin, - const OperatingConditions *op_cond, - const Corner *corner, - const MinMax *cnst_min_max, - const ParasiticAnalysisPt *ap) -{ - sta::reduceToPiPoleResidue2(parasitic, drvr_pin, - ap->couplingCapFactor(), - op_cond, corner, cnst_min_max, - ap, this); -} - -//////////////////////////////////////////////////////////////// - -Parasitic * -ConcreteParasitics::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 *) -{ - float c2, rpi, c1, elmore_res, elmore_cap; - bool elmore_use_load_cap; - estimatePiElmore(drvr_pin, rf, wireload, fanout, net_pin_cap, - op_cond, corner, min_max, this, - c2, rpi, c1, - elmore_res, elmore_cap, elmore_use_load_cap); - - if (c1 > 0.0 || c2 > 0.0) - return new ConcretePiElmoreEstimated(c2, rpi, c1, elmore_res, elmore_cap, - elmore_use_load_cap, - rf, op_cond, corner, min_max, - sdc_); - else - return nullptr; -} - -//////////////////////////////////////////////////////////////// - -ConcreteParasiticDeviceSeqIterator:: -ConcreteParasiticDeviceSeqIterator(ConcreteParasiticDeviceSeq *devices) : - iter_(devices) -{ -} - -ConcreteParasiticDeviceSetIterator:: -ConcreteParasiticDeviceSetIterator(ConcreteParasiticDeviceSet *devices) : - iter_(devices) -{ -} - -ConcreteParasiticDeviceSetIterator::~ConcreteParasiticDeviceSetIterator() -{ - delete iter_.container(); -} - -ConcreteParasiticNodeSeqIterator:: -ConcreteParasiticNodeSeqIterator(ConcreteParasiticNodeSeq *nodes) : - iter_(nodes) -{ -} - -ConcreteParasiticNodeSeqIterator::~ConcreteParasiticNodeSeqIterator() -{ - delete iter_.container(); + const ConcreteParasitic *cparasitic = static_cast(parasitic); + return cparasitic->unannotatedLoads(drvr_pin, this); } } // namespace diff --git a/parasitics/ConcreteParasitics.hh b/parasitics/ConcreteParasitics.hh index a09dc3ff..842b3046 100644 --- a/parasitics/ConcreteParasitics.hh +++ b/parasitics/ConcreteParasitics.hh @@ -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 ConcreteParasiticMap; typedef Map ConcreteParasiticNetworkMap; -typedef Set ParasiticNodeSet; -typedef Set 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; }; diff --git a/parasitics/ConcreteParasiticsPvt.hh b/parasitics/ConcreteParasiticsPvt.hh index 8df141d4..c4bcc346 100644 --- a/parasitics/ConcreteParasiticsPvt.hh +++ b/parasitics/ConcreteParasiticsPvt.hh @@ -16,38 +16,38 @@ #pragma once +#include +#include + #include "Parasitics.hh" namespace sta { class ConcretePoleResidue; class ConcreteParasiticDevice; -class ConcreteParasiticPinNode; -class ConcreteParasiticSubNode; class ConcreteParasiticNode; -typedef Map ConcreteElmoreLoadMap; -typedef ConcreteElmoreLoadMap::Iterator ConcretePiElmoreLoadIterator; -typedef Map ConcretePoleResidueMap; +typedef std::map ConcreteElmoreLoadMap; +typedef std::map ConcretePoleResidueMap; typedef std::pair 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 ConcreteParasiticSubNodeMap; -typedef Map ConcreteParasiticPinNodeMap; -typedef Vector ConcreteParasiticDeviceSeq; -typedef Set ConcreteParasiticDeviceSet; -typedef Vector ConcreteParasiticNodeSeq; +typedef std::map ConcreteParasiticSubNodeMap; +typedef std::map ConcreteParasiticPinNodeMap; +typedef std::set ParasiticNodeSet; +typedef std::set ParasiticResistorSet; +typedef std::vector 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 diff --git a/parasitics/EstimateParasitics.cc b/parasitics/EstimateParasitics.cc index f4a1f670..fa6d0cbc 100644 --- a/parasitics/EstimateParasitics.cc +++ b/parasitics/EstimateParasitics.cc @@ -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; diff --git a/parasitics/EstimateParasitics.hh b/parasitics/EstimateParasitics.hh index e767c499..48cc6aee 100644 --- a/parasitics/EstimateParasitics.hh +++ b/parasitics/EstimateParasitics.hh @@ -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, diff --git a/parasitics/NullParasitics.cc b/parasitics/NullParasitics.cc deleted file mode 100644 index 19fc9e90..00000000 --- a/parasitics/NullParasitics.cc +++ /dev/null @@ -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 . - -#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 diff --git a/parasitics/Parasitics.cc b/parasitics/Parasitics.cc index 0ab4a40e..605ab87e 100644 --- a/parasitics/Parasitics.cc +++ b/parasitics/Parasitics.cc @@ -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) { diff --git a/parasitics/Parasitics.i b/parasitics/Parasitics.i index 25455c15..64d33e51 100644 --- a/parasitics/Parasitics.i +++ b/parasitics/Parasitics.i @@ -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 diff --git a/parasitics/Parasitics.tcl b/parasitics/Parasitics.tcl index c027efa7..c6b9823a 100644 --- a/parasitics/Parasitics.tcl +++ b/parasitics/Parasitics.tcl @@ -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} diff --git a/parasitics/ReduceParasitics.cc b/parasitics/ReduceParasitics.cc index a0389fe3..f6a692d1 100644 --- a/parasitics/ReduceParasitics.cc +++ b/parasitics/ReduceParasitics.cc @@ -30,22 +30,21 @@ namespace sta { using std::max; typedef Map ParasiticNodeValueMap; -typedef Map ParasiticDeviceValueMap; -typedef Set ParasiticDeviceSet; +typedef Map ResistorCurrentMap; +typedef Set ParasiticResistorSet; typedef Set 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; diff --git a/parasitics/ReduceParasitics.hh b/parasitics/ReduceParasitics.hh index 8b84947e..ec7f8d3d 100644 --- a/parasitics/ReduceParasitics.hh +++ b/parasitics/ReduceParasitics.hh @@ -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); diff --git a/parasitics/ReportParasiticAnnotation.cc b/parasitics/ReportParasiticAnnotation.cc index f1ad6f8e..bc6c9b6e 100644 --- a/parasitics/ReportParasiticAnnotation.cc +++ b/parasitics/ReportParasiticAnnotation.cc @@ -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 diff --git a/parasitics/SpefReader.cc b/parasitics/SpefReader.cc index e823bd2e..d0efbd27 100644 --- a/parasitics/SpefReader.cc +++ b/parasitics/SpefReader.cc @@ -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, // : 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; } diff --git a/parasitics/SpefReader.hh b/parasitics/SpefReader.hh index e29c5d63..105f5dd1 100644 --- a/parasitics/SpefReader.hh +++ b/parasitics/SpefReader.hh @@ -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 diff --git a/parasitics/SpefReaderPvt.hh b/parasitics/SpefReaderPvt.hh index f7f1d7c5..44fc7af2 100644 --- a/parasitics/SpefReaderPvt.hh +++ b/parasitics/SpefReaderPvt.hh @@ -16,11 +16,13 @@ #pragma once +#include + #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 > SpefNameMap; +typedef std::map> 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_; diff --git a/sdc/Sdc.cc b/sdc/Sdc.cc index 055a2050..2f345a13 100644 --- a/sdc/Sdc.cc +++ b/sdc/Sdc.cc @@ -465,7 +465,7 @@ Sdc::setOperatingConditions(OperatingConditions *op_cond, } OperatingConditions * -Sdc::operatingConditions(const MinMax *min_max) +Sdc::operatingConditions(const MinMax *min_max) const { int mm_index = min_max->index(); return operating_conditions_[mm_index]; @@ -2958,8 +2958,7 @@ Sdc::setPortExtWireCap(const Port *port, PortExtCap *port_cap = ensurePortExtPinCap(port, corner); if (subtract_pin_cap) { Pin *pin = network_->findPin(network_->name(port)); - const OperatingConditions *op_cond = operatingConditions(min_max); - cap -= connectedPinCap(pin, rf, op_cond, corner, min_max); + cap -= connectedPinCap(pin, rf, corner, min_max); if (cap < 0.0) cap = 0.0; } @@ -3066,14 +3065,11 @@ Sdc::setNetWireCap(const Net *net, { float wire_cap = cap; if (subtract_pin_cap) { - OperatingConditions *op_cond = operatingConditions(min_max); NetConnectedPinIterator *pin_iter = network_->connectedPinIterator(net); if (pin_iter->hasNext()) { const Pin *pin = pin_iter->next(); - float pin_cap_rise = connectedPinCap(pin, RiseFall::rise(), - op_cond, corner, min_max); - float pin_cap_fall = connectedPinCap(pin, RiseFall::fall(), - op_cond, corner, min_max); + float pin_cap_rise = connectedPinCap(pin, RiseFall::rise(), corner, min_max); + float pin_cap_fall = connectedPinCap(pin, RiseFall::fall(), corner, min_max); float pin_cap = (pin_cap_rise + pin_cap_fall) / 2.0F; wire_cap -= pin_cap; if ((wire_cap + pin_cap) < 0.0) @@ -3108,7 +3104,6 @@ Sdc::hasNetWireCap(const Net *net) const void Sdc::connectedCap(const Pin *pin, const RiseFall *rf, - const OperatingConditions *op_cond, const Corner *corner, const MinMax *min_max, // Return values. @@ -3117,8 +3112,7 @@ Sdc::connectedCap(const Pin *pin, float &fanout, bool &has_net_load) const { - netCaps(pin, rf, op_cond, corner, min_max, - pin_cap, wire_cap, fanout, has_net_load); + netCaps(pin, rf, corner, min_max, pin_cap, wire_cap, fanout, has_net_load); float net_wire_cap; drvrPinWireCap(pin, corner, min_max, net_wire_cap, has_net_load); if (has_net_load) @@ -3128,13 +3122,12 @@ Sdc::connectedCap(const Pin *pin, float Sdc::connectedPinCap(const Pin *pin, const RiseFall *rf, - const OperatingConditions *op_cond, const Corner *corner, const MinMax *min_max) { float pin_cap, wire_cap, fanout; bool has_net_load; - connectedCap(pin, rf, op_cond, corner, min_max, + connectedCap(pin, rf, corner, min_max, pin_cap, wire_cap, fanout, has_net_load); return pin_cap; } @@ -3143,7 +3136,6 @@ class FindNetCaps : public PinVisitor { public: FindNetCaps(const RiseFall *rf, - const OperatingConditions *op_cond, const Corner *corner, const MinMax *min_max, float &pin_cap, @@ -3155,7 +3147,6 @@ public: protected: const RiseFall *rf_; - const OperatingConditions *op_cond_; const Corner *corner_; const MinMax *min_max_; float &pin_cap_; @@ -3166,7 +3157,6 @@ protected: }; FindNetCaps::FindNetCaps(const RiseFall *rf, - const OperatingConditions *op_cond, const Corner *corner, const MinMax *min_max, float &pin_cap, @@ -3176,7 +3166,6 @@ FindNetCaps::FindNetCaps(const RiseFall *rf, const Sdc *sdc) : PinVisitor(), rf_(rf), - op_cond_(op_cond), corner_(corner), min_max_(min_max), pin_cap_(pin_cap), @@ -3190,7 +3179,7 @@ FindNetCaps::FindNetCaps(const RiseFall *rf, void FindNetCaps::operator()(const Pin *pin) { - sdc_->pinCaps(pin, rf_, op_cond_, corner_, min_max_, + sdc_->pinCaps(pin, rf_, corner_, min_max_, pin_cap_, wire_cap_, fanout_); } @@ -3198,7 +3187,6 @@ FindNetCaps::operator()(const Pin *pin) void Sdc::netCaps(const Pin *drvr_pin, const RiseFall *rf, - const OperatingConditions *op_cond, const Corner *corner, const MinMax *min_max, // Return values. @@ -3211,7 +3199,7 @@ Sdc::netCaps(const Pin *drvr_pin, wire_cap = 0.0; fanout = 0.0; has_net_load = false; - FindNetCaps visitor(rf, op_cond, corner, min_max, pin_cap, + FindNetCaps visitor(rf, corner, min_max, pin_cap, wire_cap, fanout, has_net_load, this); network_->visitConnectedPins(drvr_pin, visitor); } @@ -3219,7 +3207,6 @@ Sdc::netCaps(const Pin *drvr_pin, void Sdc::pinCaps(const Pin *pin, const RiseFall *rf, - const OperatingConditions *op_cond, const Corner *corner, const MinMax *min_max, // Return values. @@ -3252,7 +3239,7 @@ Sdc::pinCaps(const Pin *pin, LibertyPort *port = network_->libertyPort(pin); if (port) { Instance *inst = network_->instance(pin); - pin_cap += portCapacitance(inst, port, rf, op_cond, corner, min_max); + pin_cap += portCapacitance(inst, port, rf, corner, min_max); if (port->direction()->isAnyInput()) fanout++; } @@ -3263,7 +3250,6 @@ float Sdc::portCapacitance(Instance *inst, LibertyPort *port, const RiseFall *rf, - const OperatingConditions *op_cond, const Corner *corner, const MinMax *min_max) const { @@ -3271,20 +3257,20 @@ Sdc::portCapacitance(Instance *inst, if (inst) inst_pvt = pvt(inst, min_max); LibertyPort *corner_port = port->cornerPort(corner, min_max); + OperatingConditions *op_cond = operatingConditions(min_max); return corner_port->capacitance(rf, min_max, op_cond, inst_pvt); } float Sdc::pinCapacitance(const Pin *pin, const RiseFall *rf, - const OperatingConditions *op_cond, const Corner *corner, const MinMax *min_max) { LibertyPort *port = network_->libertyPort(pin); if (port) { Instance *inst = network_->instance(pin); - return portCapacitance(inst, port, rf, op_cond, corner, min_max); + return portCapacitance(inst, port, rf, corner, min_max); } else return 0.0; diff --git a/search/Corner.cc b/search/Corner.cc index f6dc49ad..47902c7c 100644 --- a/search/Corner.cc +++ b/search/Corner.cc @@ -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 diff --git a/search/ReportPath.cc b/search/ReportPath.cc index aef52398..89b31d28 100644 --- a/search/ReportPath.cc +++ b/search/ReportPath.cc @@ -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 diff --git a/search/ReportPath.hh b/search/ReportPath.hh index 57fb3041..75778cc0 100644 --- a/search/ReportPath.hh +++ b/search/ReportPath.hh @@ -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); diff --git a/search/Sta.cc b/search/Sta.cc index 6b77b365..60627cf5 100644 --- a/search/Sta.cc +++ b/search/Sta.cc @@ -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_) { diff --git a/search/WritePathSpice.cc b/search/WritePathSpice.cc index 6b605ca0..608c32d9 100644 --- a/search/WritePathSpice.cc +++ b/search/WritePathSpice.cc @@ -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 reachable_pins; int res_index = 1; int cap_index = 1; - // Sort devices for consistent regression results. - Vector 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 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 { diff --git a/tcl/CmdArgs.tcl b/tcl/CmdArgs.tcl index 74027c9f..a53562d5 100644 --- a/tcl/CmdArgs.tcl +++ b/tcl/CmdArgs.tcl @@ -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 diff --git a/tcl/StaTcl.i b/tcl/StaTcl.i index 12fb18e6..628c4fd9 100644 --- a/tcl/StaTcl.i +++ b/tcl/StaTcl.i @@ -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) { diff --git a/tcl/StaTclTypes.i b/tcl/StaTclTypes.i index d2f77d5e..a2af7ecb 100644 --- a/tcl/StaTclTypes.i +++ b/tcl/StaTclTypes.i @@ -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))); } diff --git a/util/RiseFallMinMax.cc b/util/RiseFallMinMax.cc index 6c534b30..22081616 100644 --- a/util/RiseFallMinMax.cc +++ b/util/RiseFallMinMax.cc @@ -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)