OpenSTA/parasitics/ConcreteParasitics.cc

2020 lines
50 KiB
C++

// OpenSTA, Static Timing Analyzer
// Copyright (c) 2018, Parallax Software, Inc.
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <https://www.gnu.org/licenses/>.
#include <limits>
#include <algorithm> // max
#include "Machine.hh"
#include "Report.hh"
#include "Debug.hh"
#include "Error.hh"
#include "Set.hh"
#include "MinMax.hh"
#include "Network.hh"
#include "Wireload.hh"
#include "Liberty.hh"
#include "Sdc.hh"
#include "Parasitics.hh"
#include "ReduceParasitics.hh"
#include "MakeConcreteParasitics.hh"
#include "ConcreteParasitics.hh"
#include "Parasitics.hh"
#include "Corner.hh"
#include "ConcreteParasiticsPvt.hh"
// Multiple inheritance is used to share elmore and pi model base
// classes, but care is taken to make sure there are no loops in the
// inheritance graph (ConcreteParasitic only included once).
namespace sta {
using std::max;
ConcreteParasitic::~ConcreteParasitic()
{
}
bool
ConcreteParasitic::isLumpedElmore() const
{
return false;
}
bool
ConcreteParasitic::isPiElmore() const
{
return false;
}
bool
ConcreteParasitic::isPiModel() const
{
return false;
}
bool
ConcreteParasitic::isPiPoleResidue() const
{
return false;
}
bool
ConcreteParasitic::isPoleResidue() const
{
return false;
}
bool
ConcreteParasitic::isParasiticNetwork() const
{
return false;
}
void
ConcreteParasitic::piModel(float &,
float &,
float &) const
{
}
void
ConcreteParasitic::setPiModel(float,
float,
float)
{
}
bool
ConcreteParasitic::isReducedParasiticNetwork() const
{
return false;
}
void
ConcreteParasitic::setIsReduced(bool)
{
}
void
ConcreteParasitic::findElmore(const Pin *,
float &,
bool &exists) const
{
exists = false;
}
void
ConcreteParasitic::setElmore(const Pin *,
float)
{
}
Parasitic *
ConcreteParasitic::findPoleResidue(const Pin *) const
{
return NULL;
}
void
ConcreteParasitic::setPoleResidue(const Pin *,
ComplexFloatSeq *,
ComplexFloatSeq *)
{
}
////////////////////////////////////////////////////////////////
ConcreteElmore::ConcreteElmore() :
loads_(NULL)
{
}
ConcreteElmore::~ConcreteElmore()
{
delete loads_;
}
void
ConcreteElmore::findElmore(const Pin *load_pin,
float &elmore,
bool &exists) const
{
if (loads_)
loads_->findKey(load_pin, elmore, exists);
else
exists = false;
}
void
ConcreteElmore::deleteLoad(const Pin *load_pin)
{
loads_->eraseKey(load_pin);
}
void
ConcreteElmore::setElmore(const Pin *load_pin,
float elmore)
{
if (loads_ == NULL)
loads_ = new ConcreteElmoreLoadMap;
(*loads_)[load_pin] = elmore;
}
////////////////////////////////////////////////////////////////
ConcreteLumpedElmore::ConcreteLumpedElmore(float cap) :
ConcreteElmore(),
cap_(cap)
{
}
void
ConcreteLumpedElmore::setCapacitance(float cap)
{
cap_ = cap;
}
void
ConcreteLumpedElmore::findElmore(const Pin *load_pin,
float &elmore,
bool &exists) const
{
ConcreteElmore::findElmore(load_pin, elmore, exists);
}
void
ConcreteLumpedElmore::setElmore(const Pin *load_pin,
float elmore)
{
ConcreteElmore::setElmore(load_pin, elmore);
}
////////////////////////////////////////////////////////////////
ConcretePi::ConcretePi(float c2,
float rpi,
float c1) :
c2_(c2),
rpi_(rpi),
c1_(c1),
is_reduced_(false)
{
}
float
ConcretePi::capacitance() const
{
return c1_ + c2_;
}
void
ConcretePi::setPiModel(float c2,
float rpi,
float c1)
{
c2_ = c2;
rpi_ = rpi;
c1_ = c1;
}
void
ConcretePi::piModel(float &c2,
float &rpi,
float &c1) const
{
c2 = c2_;
rpi = rpi_;
c1 = c1_;
}
void
ConcretePi::setIsReduced(bool reduced)
{
is_reduced_ = reduced;
}
////////////////////////////////////////////////////////////////
ConcretePiElmore::ConcretePiElmore(float c2,
float rpi,
float c1) :
ConcretePi(c2, rpi, c1),
ConcreteElmore()
{
}
float
ConcretePiElmore::capacitance() const
{
return ConcretePi::capacitance();
}
void
ConcretePiElmore::piModel(float &c2,
float &rpi,
float &c1) const
{
ConcretePi::piModel(c2, rpi, c1);
}
void
ConcretePiElmore::setPiModel(float c2,
float rpi,
float c1)
{
ConcretePi::setPiModel(c2, rpi, c1);
}
bool
ConcretePiElmore::isReducedParasiticNetwork() const
{
return ConcretePi::isReducedParasiticNetwork();
}
void
ConcretePiElmore::setIsReduced(bool reduced)
{
ConcretePi::setIsReduced(reduced);
}
void
ConcretePiElmore::findElmore(const Pin *load_pin,
float &elmore,
bool &exists) const
{
ConcreteElmore::findElmore(load_pin, elmore, exists);
}
void
ConcretePiElmore::setElmore(const Pin *load_pin,
float elmore)
{
ConcreteElmore::setElmore(load_pin, elmore);
}
////////////////////////////////////////////////////////////////
ConcretePiElmoreEstimated::ConcretePiElmoreEstimated(float c2,
float rpi,
float c1,
float elmore_res,
float elmore_cap,
bool elmore_use_load_cap,
const TransRiseFall *tr,
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),
tr_(tr),
op_cond_(op),
corner_(corner),
min_max_(min_max),
sdc_(sdc)
{
}
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, tr_, 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.
}
////////////////////////////////////////////////////////////////
ConcretePoleResidue::
ConcretePoleResidue(ComplexFloatSeq *poles,
ComplexFloatSeq *residues) :
poles_(poles),
residues_(residues)
{
}
ConcretePoleResidue::~ConcretePoleResidue()
{
delete poles_;
delete residues_;
}
size_t
ConcretePoleResidue::poleResidueCount() const
{
return poles_->size();
}
void
ConcretePoleResidue::poleResidue(int index,
ComplexFloat &pole,
ComplexFloat &residue) const
{
pole = (*poles_)[index];
residue = (*residues_)[index];
}
void
ConcretePoleResidue::setPoleResidue(ComplexFloatSeq *poles,
ComplexFloatSeq *residues)
{
poles_ = poles;
residues_ = residues;
}
////////////////////////////////////////////////////////////////
ConcretePiPoleResidue::ConcretePiPoleResidue(float c2,
float rpi,
float c1) :
ConcretePi(c2, rpi, c1),
load_pole_residue_(NULL)
{
}
ConcretePiPoleResidue::~ConcretePiPoleResidue()
{
if (load_pole_residue_) {
load_pole_residue_->deleteContents();
delete load_pole_residue_;
}
}
float
ConcretePiPoleResidue::capacitance() const
{
return ConcretePi::capacitance();
}
void
ConcretePiPoleResidue::piModel(float &c2,
float &rpi,
float &c1) const
{
ConcretePi::piModel(c2, rpi, c1);
}
void
ConcretePiPoleResidue::setPiModel(float c2,
float rpi,
float c1)
{
ConcretePi::setPiModel(c2, rpi, c1);
}
bool
ConcretePiPoleResidue::isReducedParasiticNetwork() const
{
return ConcretePi::isReducedParasiticNetwork();
}
void
ConcretePiPoleResidue::setIsReduced(bool reduced)
{
ConcretePi::setIsReduced(reduced);
}
Parasitic *
ConcretePiPoleResidue::findPoleResidue(const Pin *load_pin) const
{
if (load_pole_residue_)
return load_pole_residue_->findKey(load_pin);
else
return NULL;
}
void
ConcretePiPoleResidue::setPoleResidue(const Pin *load_pin,
ComplexFloatSeq *poles,
ComplexFloatSeq *residues)
{
if (load_pole_residue_ == NULL)
load_pole_residue_ = new ConcretePoleResidueMap;
ConcretePoleResidue *pole_residue = load_pole_residue_->findKey(load_pin);
if (pole_residue == NULL) {
pole_residue = new ConcretePoleResidue(poles, residues);
(*load_pole_residue_)[load_pin] = pole_residue;
}
else
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_->eraseKey(load_pin);
delete pole_residue;
}
}
////////////////////////////////////////////////////////////////
ConcreteParasiticNode::ConcreteParasiticNode() :
cap_(0.0)
{
}
void
ConcreteParasiticNode::incrCapacitance(float cap)
{
cap_ += cap;
}
float
ConcreteParasiticNode::capacitance() const
{
return cap_;
}
void
ConcreteParasiticNode::addDevice(ConcreteParasiticDevice *device)
{
devices_.push_back(device);
}
////////////////////////////////////////////////////////////////
ConcreteParasiticSubNode::ConcreteParasiticSubNode(Net *net,
int id) :
ConcreteParasiticNode(),
net_(net),
id_(id)
{
}
const char *
ConcreteParasiticSubNode::name(const Network *network) const
{
const char *net_name = network->pathName(net_);
return stringPrintTmp(strlen(net_name) + INT_DIGITS + 2,
"%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 NULL;
}
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 NULL;
}
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 NULL;
}
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 NULL;
}
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)
{
}
ConcreteParasiticNetwork::~ConcreteParasiticNetwork()
{
deleteDevices();
deleteNodes();
}
void
ConcreteParasiticNetwork::deleteNodes()
{
ConcreteParasiticSubNodeMap::Iterator node_iter1(sub_nodes_);
while (node_iter1.hasNext()) {
NetId *net_id;
ConcreteParasiticSubNode *node;
node_iter1.next(net_id, node);
delete net_id;
delete node;
}
pin_nodes_.deleteContents();
}
void
ConcreteParasiticNetwork::deleteDevices()
{
ConcreteParasiticDeviceSet devices1;
devices(devices1);
devices1.deleteContents();
}
void
ConcreteParasiticNetwork::devices(ConcreteParasiticDeviceSet &devices)
{
// Collect devices into a set so they are only deleted once
// because multiple sub-nodes or pin nodes can refer to them.
ConcreteParasiticSubNodeMap::Iterator 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);
}
}
ConcreteParasiticPinNodeMap::Iterator node_iter2(pin_nodes_);
while (node_iter2.hasNext()) {
ConcreteParasiticPinNode *node = node_iter2.next();
ConcreteParasiticDeviceSeq::Iterator device_iter(node->devices());
while (device_iter.hasNext()) {
ConcreteParasiticDevice *device = device_iter.next();
devices.insert(device);
}
}
}
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();
}
ConcreteParasiticPinNodeMap::ConstIterator pin_node_iter(pin_nodes_);
while (pin_node_iter.hasNext()) {
ConcreteParasiticPinNode *node = pin_node_iter.next();
cap += node->capacitance();
}
return cap;
}
ConcreteParasiticNode *
ConcreteParasiticNetwork::ensureParasiticNode(Net *net,
int id)
{
NetId net_id(net, id);
ConcreteParasiticSubNode *node = sub_nodes_.findKey(&net_id);
if (node == NULL) {
node = new ConcreteParasiticSubNode(net, id);
sub_nodes_[new NetId(net, id)] = node;
max_node_id_ = max((int) max_node_id_, id);
}
return node;
}
ConcreteParasiticNode *
ConcreteParasiticNetwork::findNode(const Pin *pin)
{
return pin_nodes_.findKey(pin);
}
void
ConcreteParasiticNetwork::disconnectPin(const Pin *pin,
Net *net)
{
ConcreteParasiticNode *node = pin_nodes_.findKey(pin);
if (node) {
// Make a subnode to replace the pin node.
ConcreteParasiticNode *subnode = ensureParasiticNode(net,max_node_id_+1);
// 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);
}
pin_nodes_.eraseKey(pin);
delete node;
}
}
ConcreteParasiticNode *
ConcreteParasiticNetwork::ensureParasiticNode(const Pin *pin)
{
ConcreteParasiticPinNode *node = pin_nodes_.findKey(pin);
if (node == NULL) {
node = new ConcreteParasiticPinNode(pin);
pin_nodes_[pin] = node;
}
return node;
}
bool
NetIdLess::operator()(const NetId *net_id1,
const NetId *net_id2) const
{
Net *net1 = net_id1->first;
Net *net2 = net_id2->first;
int id1 = net_id1->second;
int id2 = net_id2->second;
return net1 < net2
|| (net1 == net2
&& id1 < id2);
}
////////////////////////////////////////////////////////////////
Parasitics *
makeConcreteParasitics(StaState *sta)
{
return new ConcreteParasitics(sta);
}
ConcreteParasitics::ConcreteParasitics(StaState *sta) :
Parasitics(sta),
lumped_elmore_maps_(NULL),
pi_elmore_maps_(NULL),
pi_pole_residue_maps_(NULL),
parasitic_network_maps_(NULL)
{
}
ConcreteParasitics::~ConcreteParasitics()
{
clear();
}
bool
ConcreteParasitics::haveParasitics()
{
return lumped_elmore_maps_ != NULL
|| pi_elmore_maps_ != NULL
|| pi_pole_residue_maps_ != NULL
|| parasitic_network_maps_ != NULL;
}
void
ConcreteParasitics::clear()
{
deleteParasitics();
if (lumped_elmore_maps_) {
ParasiticAnalysisPtIterator ap_iter(corners_);
while (ap_iter.hasNext()) {
ParasiticAnalysisPt *ap = ap_iter.next();
TransRiseFallIterator tr_iter;
while (tr_iter.hasNext()) {
TransRiseFall *tr = tr_iter.next();
int ap_index = parasiticAnalysisPtIndex(ap, tr);
delete (*lumped_elmore_maps_)[ap_index];
}
}
delete lumped_elmore_maps_;
lumped_elmore_maps_ = NULL;
}
if (pi_elmore_maps_) {
ParasiticAnalysisPtIterator ap_iter(corners_);
while (ap_iter.hasNext()) {
ParasiticAnalysisPt *ap = ap_iter.next();
TransRiseFallIterator tr_iter;
while (tr_iter.hasNext()) {
TransRiseFall *tr = tr_iter.next();
int ap_index = parasiticAnalysisPtIndex(ap, tr);
delete (*pi_elmore_maps_)[ap_index];
}
}
delete pi_elmore_maps_;
pi_elmore_maps_ = NULL;
}
if (pi_pole_residue_maps_) {
ParasiticAnalysisPtIterator ap_iter(corners_);
while (ap_iter.hasNext()) {
ParasiticAnalysisPt *ap = ap_iter.next();
TransRiseFallIterator tr_iter;
while (tr_iter.hasNext()) {
TransRiseFall *tr = tr_iter.next();
int ap_index = parasiticAnalysisPtIndex(ap, tr);
delete (*pi_pole_residue_maps_)[ap_index];
}
}
delete pi_pole_residue_maps_;
pi_pole_residue_maps_ = NULL;
}
if (parasitic_network_maps_) {
ParasiticAnalysisPtIterator ap_iter(corners_);
while (ap_iter.hasNext()) {
ParasiticAnalysisPt *ap = ap_iter.next();
TransRiseFallIterator tr_iter;
while (tr_iter.hasNext()) {
TransRiseFall *tr = tr_iter.next();
int ap_index = parasiticAnalysisPtIndex(ap, tr);
delete (*parasitic_network_maps_)[ap_index];
}
}
delete parasitic_network_maps_;
parasitic_network_maps_ = NULL;
}
}
int
ConcreteParasitics::parasiticAnalysisPtIndex(const ParasiticAnalysisPt *ap,
const TransRiseFall *tr) const
{
return ap->index() * TransRiseFall::index_count + tr->index();
}
void
ConcreteParasitics::deleteParasitics()
{
ParasiticAnalysisPtIterator ap_iter(corners_);
while (ap_iter.hasNext()) {
ParasiticAnalysisPt *ap = ap_iter.next();
TransRiseFallIterator tr_iter;
while (tr_iter.hasNext()) {
TransRiseFall *tr = tr_iter.next();
int ap_index = parasiticAnalysisPtIndex(ap, tr);
deleteParasitics(ap_index);
}
}
}
void
ConcreteParasitics::deleteParasitics(int ap_index)
{
if (lumped_elmore_maps_)
(*lumped_elmore_maps_)[ap_index]->deleteContentsClear();
if (pi_elmore_maps_)
(*pi_elmore_maps_)[ap_index]->deleteContentsClear();
if (pi_pole_residue_maps_)
(*pi_pole_residue_maps_)[ap_index]->deleteContentsClear();
if (parasitic_network_maps_)
(*parasitic_network_maps_)[ap_index]->deleteContentsClear();
}
void
ConcreteParasitics::deleteParasitics(const Pin *drvr_pin,
const ParasiticAnalysisPt *ap)
{
TransRiseFallIterator tr_iter;
while (tr_iter.hasNext()) {
TransRiseFall *tr = tr_iter.next();
int ap_index = parasiticAnalysisPtIndex(ap, tr);
if (lumped_elmore_maps_) {
ConcreteLumpedElmore *lumped_elmore =
(*lumped_elmore_maps_)[ap_index]->findKey(drvr_pin);
if (lumped_elmore) {
delete lumped_elmore;
(*lumped_elmore_maps_)[ap_index]->eraseKey(drvr_pin);
}
}
if (pi_elmore_maps_) {
ConcretePiElmore *pi_elmore =
(*pi_elmore_maps_)[ap_index]->findKey(drvr_pin);
if (pi_elmore) {
delete pi_elmore;
(*pi_elmore_maps_)[ap_index]->eraseKey(drvr_pin);
}
}
if (pi_pole_residue_maps_) {
ConcretePiPoleResidue *pi_pole_residue =
(*pi_pole_residue_maps_)[ap_index]->findKey(drvr_pin);
if (pi_pole_residue) {
(*pi_pole_residue_maps_)[ap_index]->eraseKey(drvr_pin);
delete pi_pole_residue;
}
}
}
}
void
ConcreteParasitics::deleteParasitics(const Net *net,
const ParasiticAnalysisPt *ap)
{
NetConnectedPinIterator *pin_iter = network_->connectedPinIterator(net);
while (pin_iter->hasNext()) {
Pin *pin = pin_iter->next();
if (network_->isDriver(pin))
deleteParasitics(pin, ap);
}
delete pin_iter;
if (parasitic_network_maps_) {
TransRiseFallIterator tr_iter;
while (tr_iter.hasNext()) {
TransRiseFall *tr = tr_iter.next();
int ap_index = parasiticAnalysisPtIndex(ap, tr);
ConcreteParasiticNetwork *parasitic_network =
(*parasitic_network_maps_)[ap_index]->findKey(net);
if (parasitic_network) {
(*parasitic_network_maps_)[ap_index]->eraseKey(net);
delete parasitic_network;
}
}
}
}
void
ConcreteParasitics::deleteParasitic(const Pin *drvr_pin,
const TransRiseFall *tr,
const ParasiticAnalysisPt *ap,
Parasitic *parasitic)
{
ConcreteParasitic *cparasitic = static_cast<ConcreteParasitic*>(parasitic);
// Estimated parasitics are not recorded in a parasitic map and do
// not require an analysis pt.
if (ap) {
int ap_index = parasiticAnalysisPtIndex(ap, tr);
lock_.writeLock();
if (cparasitic->isLumpedElmore())
(*lumped_elmore_maps_)[ap_index]->eraseKey(drvr_pin);
else if (cparasitic->isPiElmore() && pi_elmore_maps_)
(*pi_elmore_maps_)[ap_index]->eraseKey(drvr_pin);
else if (cparasitic->isPiPoleResidue())
(*pi_pole_residue_maps_)[ap_index]->eraseKey(drvr_pin);
else if (cparasitic->isParasiticNetwork()) {
const Net *net = network_->net(drvr_pin);
(*parasitic_network_maps_)[ap_index]->eraseKey(net);
}
lock_.unlock();
}
delete cparasitic;
}
void
ConcreteParasitics::makeParasiticAnalysisPtAfter()
{
// Make room in the parasitic maps.
size_t map_size = mapSize();
if (lumped_elmore_maps_)
lumped_elmore_maps_->resize(map_size);
if (pi_elmore_maps_)
pi_elmore_maps_->resize(map_size);
if (pi_pole_residue_maps_)
pi_pole_residue_maps_->resize(map_size);
if (parasitic_network_maps_)
parasitic_network_maps_->resize(map_size);
ParasiticAnalysisPtIterator ap_iter(corners_);
while (ap_iter.hasNext()) {
ParasiticAnalysisPt *ap = ap_iter.next();
TransRiseFallIterator tr_iter;
while (tr_iter.hasNext()) {
TransRiseFall *tr = tr_iter.next();
size_t ap_index = parasiticAnalysisPtIndex(ap, tr);
if (lumped_elmore_maps_)
(*lumped_elmore_maps_)[ap_index] = new ConcreteLumpedElmoreMap;
if (pi_elmore_maps_)
(*pi_elmore_maps_)[ap_index] = new ConcretePiElmoreMap;
if (pi_pole_residue_maps_)
(*pi_pole_residue_maps_)[ap_index] = new ConcretePiPoleResidueMap;
if (parasitic_network_maps_)
(*parasitic_network_maps_)[ap_index] = new ConcreteParasiticNetworkMap;
}
}
}
int
ConcreteParasitics::mapSize()
{
return corners_->parasiticAnalysisPtCount() * TransRiseFall::index_count;
}
void
ConcreteParasitics::finish(Parasitic *)
{
}
void
ConcreteParasitics::save()
{
// No database to save to.
}
float
ConcreteParasitics::capacitance(Parasitic *parasitic) const
{
ConcreteParasitic *cparasitic = static_cast<ConcreteParasitic*>(parasitic);
return cparasitic->capacitance();
}
bool
ConcreteParasitics::isReducedParasiticNetwork(Parasitic *parasitic) const
{
ConcreteParasitic *cparasitic = static_cast<ConcreteParasitic*>(parasitic);
return cparasitic->isReducedParasiticNetwork();
}
void
ConcreteParasitics::setIsReducedParasiticNetwork(Parasitic *parasitic,
bool is_reduced)
{
ConcreteParasitic *cparasitic = static_cast<ConcreteParasitic*>(parasitic);
cparasitic->setIsReduced(is_reduced);
}
void
ConcreteParasitics::disconnectPinBefore(const Pin *pin)
{
if (haveParasitics()) {
Net *net = findParasiticNet(pin);
if (net) {
if (lumped_elmore_maps_ || pi_elmore_maps_ || pi_pole_residue_maps_) {
NetConnectedPinIterator *pin_iter=network_->connectedPinIterator(net);
while (pin_iter->hasNext()) {
Pin *net_pin = pin_iter->next();
if (network_->isDriver(net_pin)) {
ParasiticAnalysisPtIterator ap_iter(corners_);
while (ap_iter.hasNext()) {
ParasiticAnalysisPt *ap = ap_iter.next();
TransRiseFallIterator tr_iter;
while (tr_iter.hasNext()) {
TransRiseFall *tr = tr_iter.next();
int ap_index = parasiticAnalysisPtIndex(ap, tr);
disconnectPinBefore(net_pin, pin, ap_index);
}
}
}
}
delete pin_iter;
}
if (parasitic_network_maps_) {
ParasiticAnalysisPtIterator ap_iter(corners_);
while (ap_iter.hasNext()) {
ParasiticAnalysisPt *ap = ap_iter.next();
TransRiseFallIterator tr_iter;
while (tr_iter.hasNext()) {
TransRiseFall *tr = tr_iter.next();
int ap_index = parasiticAnalysisPtIndex(ap, tr);
ConcreteParasiticNetwork *parasitic_network =
(*parasitic_network_maps_)[ap_index]->findKey(net);
if (parasitic_network)
parasitic_network->disconnectPin(pin, net);
}
}
}
}
}
}
void
ConcreteParasitics::disconnectPinBefore(const Pin *drvr_pin,
const Pin *pin,
int ap_index)
{
if (lumped_elmore_maps_) {
ConcreteLumpedElmore *lumped_elmore =
(*lumped_elmore_maps_)[ap_index]->findKey(drvr_pin);
if (lumped_elmore) {
if (pin == drvr_pin) {
delete lumped_elmore;
(*lumped_elmore_maps_)[ap_index]->eraseKey(drvr_pin);
}
else
lumped_elmore->deleteLoad(pin);
}
}
if (pi_elmore_maps_) {
ConcretePiElmore *pi_elmore =
(*pi_elmore_maps_)[ap_index]->findKey(drvr_pin);
if (pi_elmore) {
if (pin == drvr_pin) {
delete pi_elmore;
(*pi_elmore_maps_)[ap_index]->eraseKey(drvr_pin);
}
else
pi_elmore->deleteLoad(pin);
}
}
if (pi_pole_residue_maps_) {
ConcretePiPoleResidue *pi_pole_residue =
(*pi_pole_residue_maps_)[ap_index]->findKey(drvr_pin);
if (pi_pole_residue) {
if (pin == drvr_pin) {
delete pi_pole_residue;
(*pi_pole_residue_maps_)[ap_index]->eraseKey(drvr_pin);
}
else
pi_pole_residue->deleteLoad(pin);
}
}
}
////////////////////////////////////////////////////////////////
bool
ConcreteParasitics::isLumpedElmore(Parasitic *parasitic) const
{
ConcreteParasitic *cparasitic = static_cast<ConcreteParasitic*>(parasitic);
return cparasitic && cparasitic->isLumpedElmore();
}
bool
ConcreteParasitics::hasLumpedElmore(const Pin *drvr_pin,
const TransRiseFall *tr,
const ParasiticAnalysisPt *ap) const
{
if (lumped_elmore_maps_ && ap) {
int ap_index = parasiticAnalysisPtIndex(ap, tr);
lock_.readLock();
bool exists = (*lumped_elmore_maps_)[ap_index]->hasKey(drvr_pin);
lock_.unlock();
return exists;
}
else
return false;
}
Parasitic *
ConcreteParasitics::findLumpedElmore(const Pin *drvr_pin,
const TransRiseFall *tr,
const ParasiticAnalysisPt *ap) const
{
if (ap && lumped_elmore_maps_) {
int ap_index = parasiticAnalysisPtIndex(ap, tr);
lock_.readLock();
Parasitic *parasitic = (*lumped_elmore_maps_)[ap_index]->findKey(drvr_pin);
lock_.unlock();
return parasitic;
}
else
return NULL;
}
Parasitic *
ConcreteParasitics::makeLumpedElmore(const Pin *drvr_pin,
float cap,
const TransRiseFall *tr,
const ParasiticAnalysisPt *ap)
{
int ap_index = parasiticAnalysisPtIndex(ap, tr);
lock_.writeLock();
if (lumped_elmore_maps_ == NULL) {
lumped_elmore_maps_ = new ConcreteLumpedElmoreMapSeq(mapSize());
ParasiticAnalysisPtIterator ap_iter(corners_);
while (ap_iter.hasNext()) {
ParasiticAnalysisPt *ap = ap_iter.next();
TransRiseFallIterator tr_iter;
while (tr_iter.hasNext()) {
TransRiseFall *tr = tr_iter.next();
size_t ap_index = parasiticAnalysisPtIndex(ap, tr);
(*lumped_elmore_maps_)[ap_index] = new ConcreteLumpedElmoreMap;
}
}
}
ConcreteLumpedElmore *lumped_elmore =
(*lumped_elmore_maps_)[ap_index]->findKey(drvr_pin);
if (lumped_elmore)
lumped_elmore->setCapacitance(cap);
else {
lumped_elmore = new ConcreteLumpedElmore(cap);
(*(*lumped_elmore_maps_)[ap_index])[drvr_pin] = lumped_elmore;
}
lock_.unlock();
return lumped_elmore;
}
void
ConcreteParasitics::deleteLumpedElmore(const Pin *drvr_pin,
const TransRiseFall *tr,
const ParasiticAnalysisPt *ap)
{
if (ap && lumped_elmore_maps_) {
int ap_index = parasiticAnalysisPtIndex(ap, tr);
lock_.writeLock();
ConcreteLumpedElmore *lumped_elmore =
(*lumped_elmore_maps_)[ap_index]->findKey(drvr_pin);
if (lumped_elmore) {
(*lumped_elmore_maps_)[ap_index]->eraseKey(drvr_pin);
delete lumped_elmore;
}
lock_.unlock();
}
}
////////////////////////////////////////////////////////////////
bool
ConcreteParasitics::isPiElmore(Parasitic *parasitic) const
{
ConcreteParasitic *cparasitic = static_cast<ConcreteParasitic*>(parasitic);
return cparasitic && cparasitic->isPiElmore();
}
bool
ConcreteParasitics::hasPiElmore(const Pin *drvr_pin,
const TransRiseFall *tr,
const ParasiticAnalysisPt *ap) const
{
if (ap && pi_elmore_maps_) {
int ap_index = parasiticAnalysisPtIndex(ap, tr);
lock_.readLock();
bool exists = (*pi_elmore_maps_)[ap_index]->hasKey(drvr_pin);
if (!exists && tr == TransRiseFall::fall()) {
ap_index = parasiticAnalysisPtIndex(ap, TransRiseFall::rise());
exists = (*pi_elmore_maps_)[ap_index]->hasKey(drvr_pin);
}
lock_.unlock();
return exists;
}
else
return false;
}
Parasitic *
ConcreteParasitics::findPiElmore(const Pin *drvr_pin,
const TransRiseFall *tr,
const ParasiticAnalysisPt *ap) const
{
if (ap && pi_elmore_maps_) {
int ap_index = parasiticAnalysisPtIndex(ap, tr);
lock_.readLock();
Parasitic *parasitic = (*pi_elmore_maps_)[ap_index]->findKey(drvr_pin);
if (parasitic == NULL && tr == TransRiseFall::fall()) {
ap_index = parasiticAnalysisPtIndex(ap, TransRiseFall::rise());
parasitic = (*pi_elmore_maps_)[ap_index]->findKey(drvr_pin);
}
lock_.unlock();
return parasitic;
}
else
return NULL;
}
Parasitic *
ConcreteParasitics::makePiElmore(const Pin *drvr_pin,
const TransRiseFall *tr,
const ParasiticAnalysisPt *ap,
float c2,
float rpi,
float c1)
{
int ap_index = parasiticAnalysisPtIndex(ap, tr);
lock_.writeLock();
if (pi_elmore_maps_ == NULL) {
pi_elmore_maps_ = new ConcretePiElmoreMapSeq(mapSize());
ParasiticAnalysisPtIterator ap_iter(corners_);
while (ap_iter.hasNext()) {
ParasiticAnalysisPt *ap = ap_iter.next();
TransRiseFallIterator tr_iter;
while (tr_iter.hasNext()) {
TransRiseFall *tr = tr_iter.next();
size_t ap_index = parasiticAnalysisPtIndex(ap, tr);
(*pi_elmore_maps_)[ap_index] = new ConcretePiElmoreMap;
}
}
}
ConcretePiElmore *pi_elmore = (*pi_elmore_maps_)[ap_index]->findKey(drvr_pin);
if (pi_elmore)
pi_elmore->setPiModel(c2, rpi, c1);
else {
pi_elmore = new ConcretePiElmore(c2, rpi, c1);
(*(*pi_elmore_maps_)[ap_index])[drvr_pin] = pi_elmore;
}
lock_.unlock();
return pi_elmore;
}
void
ConcreteParasitics::deletePiElmore(const Pin *drvr_pin,
const TransRiseFall *tr,
const ParasiticAnalysisPt *ap)
{
if (ap && pi_elmore_maps_) {
int ap_index = parasiticAnalysisPtIndex(ap, tr);
lock_.writeLock();
ConcretePiElmore *pi_elmore =
(*pi_elmore_maps_)[ap_index]->findKey(drvr_pin);
if (pi_elmore) {
(*pi_elmore_maps_)[ap_index]->eraseKey(drvr_pin);
delete pi_elmore;
}
lock_.unlock();
}
}
////////////////////////////////////////////////////////////////
bool
ConcreteParasitics::isPiModel(Parasitic *parasitic) const
{
ConcreteParasitic *cparasitic = static_cast<ConcreteParasitic*>(parasitic);
return cparasitic && cparasitic->isPiModel();
}
void
ConcreteParasitics::piModel(Parasitic *parasitic,
float &c2,
float &rpi,
float &c1) const
{
ConcreteParasitic *cparasitic = static_cast<ConcreteParasitic*>(parasitic);
cparasitic->piModel(c2, rpi, c1);
}
void
ConcreteParasitics::setPiModel(Parasitic *parasitic,
float c2,
float rpi,
float c1)
{
ConcreteParasitic *cparasitic = static_cast<ConcreteParasitic*>(parasitic);
cparasitic->setPiModel(c2, rpi, c1);
}
////////////////////////////////////////////////////////////////
void
ConcreteParasitics::findElmore(Parasitic *parasitic,
const Pin *load_pin,
float &elmore,
bool &exists) const
{
ConcreteParasitic *cparasitic = static_cast<ConcreteParasitic*>(parasitic);
cparasitic->findElmore(load_pin, elmore, exists);
}
void
ConcreteParasitics::setElmore(Parasitic *parasitic,
const Pin *load_pin,
float elmore)
{
ConcreteParasitic *cparasitic = static_cast<ConcreteParasitic*>(parasitic);
cparasitic->setElmore(load_pin, elmore);
}
////////////////////////////////////////////////////////////////
bool
ConcreteParasitics::isPiPoleResidue(Parasitic* parasitic) const
{
ConcreteParasitic *cparasitic = static_cast<ConcreteParasitic*>(parasitic);
return cparasitic && cparasitic->isPiPoleResidue();
}
bool
ConcreteParasitics::hasPiPoleResidue(const Pin *drvr_pin,
const TransRiseFall *tr,
const ParasiticAnalysisPt *ap) const
{
if (ap && pi_pole_residue_maps_) {
int ap_index = parasiticAnalysisPtIndex(ap, tr);
lock_.readLock();
bool exists = (*pi_pole_residue_maps_)[ap_index]->hasKey(drvr_pin);
if (!exists && tr == TransRiseFall::fall()) {
ap_index = parasiticAnalysisPtIndex(ap, TransRiseFall::rise());
exists = (*pi_pole_residue_maps_)[ap_index]->hasKey(drvr_pin);
}
lock_.unlock();
return exists;
}
else
return false;
}
Parasitic *
ConcreteParasitics::findPiPoleResidue(const Pin *drvr_pin,
const TransRiseFall *tr,
const ParasiticAnalysisPt *ap) const
{
if (ap && pi_pole_residue_maps_) {
int ap_index = parasiticAnalysisPtIndex(ap, tr);
lock_.readLock();
Parasitic *parasitic = (*pi_pole_residue_maps_)[ap_index]->findKey(drvr_pin);
if (parasitic == NULL && tr == TransRiseFall::fall()) {
ap_index = parasiticAnalysisPtIndex(ap, TransRiseFall::rise());
parasitic = (*pi_pole_residue_maps_)[ap_index]->findKey(drvr_pin);
}
lock_.unlock();
return parasitic;
}
else
return NULL;
}
Parasitic *
ConcreteParasitics::makePiPoleResidue(const Pin *drvr_pin,
const TransRiseFall *tr,
const ParasiticAnalysisPt *ap,
float c2,
float rpi,
float c1)
{
int ap_index = parasiticAnalysisPtIndex(ap, tr);
lock_.writeLock();
if (pi_pole_residue_maps_ == NULL) {
pi_pole_residue_maps_ = new ConcretePiPoleResidueMapSeq(mapSize());
ParasiticAnalysisPtIterator ap_iter(corners_);
while (ap_iter.hasNext()) {
ParasiticAnalysisPt *ap = ap_iter.next();
TransRiseFallIterator tr_iter;
while (tr_iter.hasNext()) {
TransRiseFall *tr = tr_iter.next();
size_t ap_index = parasiticAnalysisPtIndex(ap, tr);
(*pi_pole_residue_maps_)[ap_index] = new ConcretePiPoleResidueMap;
}
}
}
ConcretePiPoleResidue *pi_pole_residue =
(*pi_pole_residue_maps_)[ap_index]->findKey(drvr_pin);
if (pi_pole_residue)
pi_pole_residue->setPiModel(c2, rpi, c1);
else {
pi_pole_residue = new ConcretePiPoleResidue(c2, rpi, c1);
(*(*pi_pole_residue_maps_)[ap_index])[drvr_pin] = pi_pole_residue;
}
lock_.unlock();
return pi_pole_residue;
}
Parasitic *
ConcreteParasitics::findPoleResidue(const Parasitic *parasitic,
const Pin *load_pin) const
{
const ConcreteParasitic *cparasitic =
static_cast<const ConcreteParasitic*>(parasitic);
return cparasitic->findPoleResidue(load_pin);
}
void
ConcreteParasitics::setPoleResidue(Parasitic *parasitic,
const Pin *load_pin,
ComplexFloatSeq *poles,
ComplexFloatSeq *residues)
{
ConcreteParasitic *cparasitic =
static_cast<ConcreteParasitic*>(parasitic);
cparasitic->setPoleResidue(load_pin, poles, residues);
}
////////////////////////////////////////////////////////////////
bool
ConcreteParasitics::isPoleResidue(const Parasitic *parasitic) const
{
const ConcreteParasitic *cparasitic =
static_cast<const ConcreteParasitic*>(parasitic);
return cparasitic->isPoleResidue();
}
size_t
ConcreteParasitics::poleResidueCount(const Parasitic *parasitic) const
{
const ConcretePoleResidue *pr_parasitic =
static_cast<const ConcretePoleResidue*>(parasitic);
return pr_parasitic->poleResidueCount();
}
void
ConcreteParasitics::poleResidue(const Parasitic *parasitic,
int pole_index,
ComplexFloat &pole,
ComplexFloat &residue) const
{
const ConcretePoleResidue *pr_parasitic =
static_cast<const ConcretePoleResidue*>(parasitic);
pr_parasitic->poleResidue(pole_index, pole, residue);
}
////////////////////////////////////////////////////////////////
// Parasitic networks do not have separate rise/fall values.
int
ConcreteParasitics::parasiticNetworkAnalysisPtIndex(const ParasiticAnalysisPt *ap) const
{
return parasiticAnalysisPtIndex(ap, TransRiseFall::rise());
}
bool
ConcreteParasitics::isParasiticNetwork(Parasitic *parasitic) const
{
ConcreteParasitic *cparasitic = static_cast<ConcreteParasitic*>(parasitic);
return cparasitic && cparasitic->isParasiticNetwork();
}
bool
ConcreteParasitics::hasParasiticNetwork(const Net *net,
const ParasiticAnalysisPt *ap) const
{
if (ap && parasitic_network_maps_) {
int ap_index = parasiticNetworkAnalysisPtIndex(ap);
lock_.readLock();
bool exists = (*parasitic_network_maps_)[ap_index]->hasKey(net);
lock_.unlock();
return exists;
}
else
return false;
}
Parasitic *
ConcreteParasitics::findParasiticNetwork(const Pin *pin,
const ParasiticAnalysisPt *ap) const
{
if (ap && parasitic_network_maps_) {
int ap_index = parasiticNetworkAnalysisPtIndex(ap);
ConcreteParasiticNetworkMap *parasitics = (*parasitic_network_maps_)[ap_index];
lock_.readLock();
Parasitic *parasitic = NULL;
if (parasitics->size()) {
// Only call findParasiticNet if parasitics exist.
Net *net = findParasiticNet(pin);
parasitic = parasitics->findKey(net);
}
lock_.unlock();
return parasitic;
}
else
return NULL;
}
Parasitic *
ConcreteParasitics::makeParasiticNetwork(Net *net,
bool includes_pin_caps,
const ParasiticAnalysisPt *ap)
{
int ap_index = parasiticNetworkAnalysisPtIndex(ap);
lock_.writeLock();
if (parasitic_network_maps_ == NULL) {
parasitic_network_maps_ = new ConcreteParasiticNetworkMapSeq(mapSize());
ParasiticAnalysisPtIterator ap_iter(corners_);
while (ap_iter.hasNext()) {
ParasiticAnalysisPt *ap = ap_iter.next();
TransRiseFallIterator tr_iter;
while (tr_iter.hasNext()) {
TransRiseFall *tr = tr_iter.next();
size_t ap_index = parasiticAnalysisPtIndex(ap, tr);
(*parasitic_network_maps_)[ap_index] = new ConcreteParasiticNetworkMap;
}
}
}
ConcreteParasiticNetwork *parasitic =
(*parasitic_network_maps_)[ap_index]->findKey(net);
if (parasitic == NULL) {
parasitic = new ConcreteParasiticNetwork(includes_pin_caps);
(*(*parasitic_network_maps_)[ap_index])[net] = parasitic;
}
lock_.unlock();
return parasitic;
}
void
ConcreteParasitics::deleteParasiticNetwork(const Net *net,
const ParasiticAnalysisPt *ap)
{
if (ap && parasitic_network_maps_) {
int ap_index = parasiticNetworkAnalysisPtIndex(ap);
lock_.writeLock();
ConcreteParasiticNetwork *parasitic =
(*parasitic_network_maps_)[ap_index]->findKey(net);
if (parasitic) {
(*parasitic_network_maps_)[ap_index]->eraseKey(net);
delete parasitic;
}
lock_.unlock();
}
}
bool
ConcreteParasitics::includesPinCaps(Parasitic *parasitic) const
{
ConcreteParasiticNetwork *cparasitic =
static_cast<ConcreteParasiticNetwork*>(parasitic);
return cparasitic->includesPinCaps();
}
ParasiticNode *
ConcreteParasitics::ensureParasiticNode(Parasitic *parasitic,
Net *net,
int id)
{
ConcreteParasiticNetwork *cparasitic =
static_cast<ConcreteParasiticNetwork*>(parasitic);
return cparasitic->ensureParasiticNode(net, id);
}
ParasiticNode *
ConcreteParasitics::ensureParasiticNode(Parasitic *parasitic,
const Pin *pin)
{
ConcreteParasiticNetwork *cparasitic =
static_cast<ConcreteParasiticNetwork*>(parasitic);
return cparasitic->ensureParasiticNode(pin);
}
void
ConcreteParasitics::incrCap(ParasiticNode *node,
float cap,
const ParasiticAnalysisPt *)
{
ConcreteParasiticNode *cnode = static_cast<ConcreteParasiticNode*>(node);
cnode->incrCapacitance(cap);
}
void
ConcreteParasitics::makeCouplingCap(const char *name,
ParasiticNode *node,
ParasiticNode *other_node,
float cap,
const ParasiticAnalysisPt *)
{
ConcreteParasiticNode *cnode = static_cast<ConcreteParasiticNode*>(node);
ConcreteParasiticNode *other_cnode =
static_cast<ConcreteParasiticNode*>(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<ConcreteParasiticNode*>(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<ConcreteParasiticNode*>(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 *)
{
ConcreteParasiticNode *cnode1 = static_cast<ConcreteParasiticNode*>(node1);
ConcreteParasiticNode *cnode2 = static_cast<ConcreteParasiticNode*>(node2);
ConcreteParasiticDevice *resistor =
new ConcreteParasiticResistor(name, cnode1, cnode2, res);
cnode1->addDevice(resistor);
cnode2->addDevice(resistor);
}
float
ConcreteParasitics::nodeGndCap(const ParasiticNode *node,
const ParasiticAnalysisPt *) const
{
const ConcreteParasiticNode *cnode =
static_cast<const ConcreteParasiticNode*>(node);
return cnode->capacitance();
}
const char *
ConcreteParasitics::name(const ParasiticNode *node)
{
const ConcreteParasiticNode *cnode =
static_cast<const ConcreteParasiticNode*>(node);
return cnode->name(network_);
}
const Pin *
ConcreteParasitics::connectionPin(const ParasiticNode *node) const
{
const ConcreteParasiticNode *cnode =
static_cast<const ConcreteParasiticNode*>(node);
if (cnode->isPinNode()) {
const ConcreteParasiticPinNode *pin_node =
dynamic_cast<const ConcreteParasiticPinNode*>(cnode);
return pin_node->pin();
}
else
return NULL;
}
ParasiticNode *
ConcreteParasitics::findNode(Parasitic *parasitic,
const Pin *pin) const
{
ConcreteParasiticNetwork *cparasitic =
static_cast<ConcreteParasiticNetwork*>(parasitic);
return cparasitic->findNode(pin);
}
ConcreteParasiticDeviceIterator::
ConcreteParasiticDeviceIterator(ConcreteParasiticNode *node) :
iter_(node->devices())
{
}
ParasiticDeviceIterator *
ConcreteParasitics::deviceIterator(ParasiticNode *node) const
{
ConcreteParasiticNode *cnode = static_cast<ConcreteParasiticNode*>(node);
return new ConcreteParasiticDeviceIterator(cnode);
}
const char *
ConcreteParasitics::name(const ParasiticDevice *device) const
{
const ConcreteParasiticDevice *cdevice =
static_cast<const ConcreteParasiticDevice*>(device);
return cdevice->name();
}
bool
ConcreteParasitics::isResistor(const ParasiticDevice *device) const
{
const ConcreteParasiticDevice *cdevice =
static_cast<const ConcreteParasiticDevice*>(device);
return cdevice->isResistor();
}
bool
ConcreteParasitics::isCouplingCap(const ParasiticDevice *device) const
{
const ConcreteParasiticDevice *cdevice =
static_cast<const ConcreteParasiticDevice*>(device);
return cdevice->isCouplingCap();
}
float
ConcreteParasitics::value(const ParasiticDevice *device,
const ParasiticAnalysisPt *) const
{
const ConcreteParasiticDevice *cdevice =
static_cast<const ConcreteParasiticDevice*>(device);
return cdevice->value();
}
ParasiticNode *
ConcreteParasitics::otherNode(const ParasiticDevice *device,
ParasiticNode *node) const
{
const ConcreteParasiticDevice *cdevice =
static_cast<const ConcreteParasiticDevice*>(device);
return cdevice->otherNode(node);
}
////////////////////////////////////////////////////////////////
void
ConcreteParasitics::reduceTo(Parasitic *parasitic,
const Net *net,
ReduceParasiticsTo reduce_to,
const TransRiseFall *tr,
const OperatingConditions *op_cond,
const Corner *corner,
const MinMax *cnst_min_max,
const ParasiticAnalysisPt *ap)
{
switch (reduce_to) {
case reduce_parasitics_to_pi_elmore:
reduceToPiElmore(parasitic, net, tr, op_cond, corner, cnst_min_max, ap);
break;
case reduce_parasitics_to_pi_pole_residue2:
reduceToPiPoleResidue2(parasitic, net, tr, op_cond, corner,
cnst_min_max, ap);
break;
case reduce_parasitics_to_none:
break;
}
}
void
ConcreteParasitics::reduceToPiElmore(Parasitic *parasitic,
const Net *net,
const TransRiseFall *tr,
const OperatingConditions *op_cond,
const Corner *corner,
const MinMax *cnst_min_max,
const ParasiticAnalysisPt *ap)
{
debugPrint1(debug_, "parasitic_reduce", 1, "Reduce net %s\n",
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(),
tr, op_cond, corner, cnst_min_max, ap, this);
}
}
delete pin_iter;
}
Parasitic *
ConcreteParasitics::reduceToPiElmore(Parasitic *parasitic,
const Pin *drvr_pin,
const TransRiseFall *tr,
const OperatingConditions *op_cond,
const Corner *corner,
const MinMax *cnst_min_max,
const ParasiticAnalysisPt *ap)
{
return sta::reduceToPiElmore(parasitic, drvr_pin, ap->couplingCapFactor(),
tr, op_cond, corner, cnst_min_max, ap, this);
}
void
ConcreteParasitics::reduceToPiPoleResidue2(Parasitic *parasitic,
const Net *net,
const TransRiseFall *tr,
const OperatingConditions *op_cond,
const Corner *corner,
const MinMax *cnst_min_max,
const ParasiticAnalysisPt *ap)
{
debugPrint1(debug_, "parasitic_reduce", 1, "Reduce net %s\n",
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(),
tr, op_cond, corner, cnst_min_max, ap, this);
}
delete pin_iter;
}
Parasitic *
ConcreteParasitics::reduceToPiPoleResidue2(Parasitic *parasitic,
const Pin *drvr_pin,
const TransRiseFall *tr,
const OperatingConditions *op_cond,
const Corner *corner,
const MinMax *cnst_min_max,
const ParasiticAnalysisPt *ap)
{
return sta::reduceToPiPoleResidue2(parasitic, drvr_pin,
ap->couplingCapFactor(),
tr, op_cond, corner, cnst_min_max,
ap, this);
}
////////////////////////////////////////////////////////////////
Parasitic *
ConcreteParasitics::estimatePiElmore(const Pin *drvr_pin,
const TransRiseFall *tr,
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, tr, wireload, fanout, net_pin_cap,
op_cond, corner, min_max, this,
c2, rpi, c1,
elmore_res, elmore_cap, elmore_use_load_cap);
return new ConcretePiElmoreEstimated(c2, rpi, c1, elmore_res, elmore_cap,
elmore_use_load_cap,
tr, op_cond, corner, min_max,
sdc_);
}
} // namespace