diff --git a/include/sta/Parasitics.hh b/include/sta/Parasitics.hh index 7cf45d33..a5a34c11 100644 --- a/include/sta/Parasitics.hh +++ b/include/sta/Parasitics.hh @@ -154,6 +154,8 @@ public: bool includes_pin_caps, const ParasiticAnalysisPt *ap) = 0; virtual ParasiticNodeSeq nodes(const Parasitic *parasitic) const = 0; + virtual void report(const Parasitic *parasitic) const; + virtual const Net *net(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. diff --git a/parasitics/ConcreteParasitics.cc b/parasitics/ConcreteParasitics.cc index ec76fdcb..d636ea05 100644 --- a/parasitics/ConcreteParasitics.cc +++ b/parasitics/ConcreteParasitics.cc @@ -596,13 +596,14 @@ ConcreteParasiticNetwork::findParasiticNode(const Pin *pin) const ConcreteParasiticNode * ConcreteParasiticNetwork::ensureParasiticNode(const Net *net, int id, - const Network *) + const Network *network) { ConcreteParasiticNode *node; NetIdPair net_id(net, id); auto id_node = sub_nodes_.find(net_id); if (id_node == sub_nodes_.end()) { - node = new ConcreteParasiticNode(net, id, net != net_); + Net *net1 = network->highestNetAbove(const_cast(net)); + node = new ConcreteParasiticNode(net, id, network->highestNetAbove(net1) != net_); sub_nodes_[net_id] = node; if (net == net_) max_node_id_ = max((int) max_node_id_, id); @@ -1287,6 +1288,17 @@ ConcreteParasitics::deleteParasiticNetworks(const Net *net) } } +const Net * +ConcreteParasitics::net(const Parasitic *parasitic) const +{ + const ConcreteParasiticNetwork *cparasitic = + static_cast(parasitic); + if (cparasitic->isParasiticNetwork()) + return cparasitic->net(); + else + return nullptr; +} + bool ConcreteParasitics::includesPinCaps(const Parasitic *parasitic) const { diff --git a/parasitics/ConcreteParasitics.hh b/parasitics/ConcreteParasitics.hh index fbb1b3d4..f9259fd2 100644 --- a/parasitics/ConcreteParasitics.hh +++ b/parasitics/ConcreteParasitics.hh @@ -112,6 +112,7 @@ public: void deleteParasiticNetwork(const Net *net, const ParasiticAnalysisPt *ap) override; void deleteParasiticNetworks(const Net *net) override; + const Net *net(const Parasitic *parasitic) const override; bool includesPinCaps(const Parasitic *parasitic) const override; ParasiticNode *findParasiticNode(Parasitic *parasitic, const Net *net, diff --git a/parasitics/ConcreteParasiticsPvt.hh b/parasitics/ConcreteParasiticsPvt.hh index b4503b70..e098b2bb 100644 --- a/parasitics/ConcreteParasiticsPvt.hh +++ b/parasitics/ConcreteParasiticsPvt.hh @@ -207,7 +207,7 @@ public: const Network *network); virtual ~ConcreteParasiticNetwork(); virtual bool isParasiticNetwork() const { return true; } - const Net *net() { return net_; } + const Net *net() const { return net_; } bool includesPinCaps() const { return includes_pin_caps_; } ConcreteParasiticNode *findParasiticNode(const Net *net, int id, diff --git a/parasitics/Parasitics.cc b/parasitics/Parasitics.cc index 65b62a1d..a82a96e7 100644 --- a/parasitics/Parasitics.cc +++ b/parasitics/Parasitics.cc @@ -18,6 +18,7 @@ #include "Error.hh" #include "Debug.hh" +#include "Units.hh" #include "Liberty.hh" #include "Wireload.hh" #include "Network.hh" @@ -34,6 +35,47 @@ Parasitics::Parasitics(StaState *sta) : { } +void +Parasitics::report(const Parasitic *parasitic) const +{ + if (isParasiticNetwork(parasitic)) { + const Unit *cap_unit = units_->capacitanceUnit(); + report_->reportLine("Net %s %s", + network_->pathName(net(parasitic)), + cap_unit->asString(capacitance(parasitic))); + report_->reportLine("Nodes:"); + for (ParasiticNode *node : nodes(parasitic)) + report_->reportLine("%s%s %s", + name(node), + isExternal(node) ? " (ext)" : "", + cap_unit->asString(nodeGndCap(node))); + report_->reportLine("Resistors:"); + for (ParasiticResistor *res : resistors(parasitic)) { + ParasiticNode *node1 = this->node1(res); + ParasiticNode *node2 = this->node2(res); + report_->reportLine("%zu %s%s %s%s %s", + id(res), + name(node1), + isExternal(node1) ? " (ext)" : "", + name(node2), + isExternal(node2) ? " (ext)" : "", + units_->resistanceUnit()->asString(value(res))); + } + report_->reportLine("Coupling Capacitors:"); + for (ParasiticCapacitor *cap : capacitors(parasitic)) { + ParasiticNode *node1 = this->node1(cap); + ParasiticNode *node2 = this->node2(cap); + report_->reportLine("%zu %s%s %s%s %s", + id(cap), + name(node1), + isExternal(node1) ? " (ext)" : "", + name(node2), + isExternal(node2) ? " (ext)" : "", + cap_unit->asString(value(cap))); + } + } +} + const Net * Parasitics::findParasiticNet(const Pin *pin) const { diff --git a/parasitics/ReduceParasitics.cc b/parasitics/ReduceParasitics.cc index 07c5b733..a4190b3f 100644 --- a/parasitics/ReduceParasitics.cc +++ b/parasitics/ReduceParasitics.cc @@ -155,60 +155,53 @@ ReduceToPi::reducePiDfs(const Pin *drvr_pin, double &dwn_cap, double &max_resistance) { - if (parasitics_->isExternal(node)) { - y1 = y2 = y3 = 0.0; - max_resistance = 0.0; - dwn_cap = 0.0; - } - else { - double coupling_cap = 0.0; - ParasiticCapacitorSeq &capacitors = capacitor_map_[node]; - for (ParasiticCapacitor *capacitor : capacitors) - coupling_cap += parasitics_->value(capacitor); + double coupling_cap = 0.0; + ParasiticCapacitorSeq &capacitors = capacitor_map_[node]; + for (ParasiticCapacitor *capacitor : capacitors) + coupling_cap += parasitics_->value(capacitor); - 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); + 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); - 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 %zu", - 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; - } + 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 %zu", + 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; } } } - - 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