This commit is contained in:
James Cherry 2019-01-25 18:06:24 -08:00
parent f2a28bdcaf
commit ca231b29cc
10 changed files with 156 additions and 93 deletions

View File

@ -164,7 +164,7 @@ ArnoldiReduce::loadWork()
int resistor_count = 0; int resistor_count = 0;
ConcreteParasiticDeviceSet devices; ConcreteParasiticDeviceSet devices;
parasitic_network_->devices(devices); parasitic_network_->devices(&devices);
ConcreteParasiticDeviceSet::Iterator device_iter(devices); ConcreteParasiticDeviceSet::Iterator device_iter(devices);
while (device_iter.hasNext()) { while (device_iter.hasNext()) {
ParasiticDevice *device = device_iter.next(); ParasiticDevice *device = device_iter.next();

View File

@ -134,6 +134,18 @@ ConcreteParasitic::setPoleResidue(const Pin *,
{ {
} }
ParasiticDeviceIterator *
ConcreteParasitic::deviceIterator()
{
return NULL;
}
ParasiticNodeIterator *
ConcreteParasitic::nodeIterator()
{
return NULL;
}
//////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////
ConcreteElmore::ConcreteElmore() : ConcreteElmore::ConcreteElmore() :
@ -726,12 +738,37 @@ void
ConcreteParasiticNetwork::deleteDevices() ConcreteParasiticNetwork::deleteDevices()
{ {
ConcreteParasiticDeviceSet devices1; ConcreteParasiticDeviceSet devices1;
devices(devices1); devices(&devices1);
devices1.deleteContents(); devices1.deleteContents();
} }
ParasiticNodeIterator *
ConcreteParasiticNetwork::nodeIterator()
{
ConcreteParasiticNodeSeq *nodes = new ConcreteParasiticNodeSeq();
ConcreteParasiticPinNodeMap::Iterator node_iter2(pin_nodes_);
while (node_iter2.hasNext()) {
ConcreteParasiticPinNode *node = node_iter2.next();
nodes->push_back(node);
}
ConcreteParasiticSubNodeMap::Iterator node_iter1(sub_nodes_);
while (node_iter1.hasNext()) {
ConcreteParasiticSubNode *node = node_iter1.next();
nodes->push_back(node);
}
return new ConcreteParasiticNodeSeqIterator(nodes);
}
ParasiticDeviceIterator *
ConcreteParasiticNetwork::deviceIterator()
{
ConcreteParasiticDeviceSet *devices1 = new ConcreteParasiticDeviceSet();
devices(devices1);
return new ConcreteParasiticDeviceSetIterator(devices1);
}
void void
ConcreteParasiticNetwork::devices(ConcreteParasiticDeviceSet &devices) ConcreteParasiticNetwork::devices(ConcreteParasiticDeviceSet *devices)
{ {
// Collect devices into a set so they are only deleted once // Collect devices into a set so they are only deleted once
// because multiple sub-nodes or pin nodes can refer to them. // because multiple sub-nodes or pin nodes can refer to them.
@ -741,7 +778,7 @@ ConcreteParasiticNetwork::devices(ConcreteParasiticDeviceSet &devices)
ConcreteParasiticDeviceSeq::Iterator device_iter(node->devices()); ConcreteParasiticDeviceSeq::Iterator device_iter(node->devices());
while (device_iter.hasNext()) { while (device_iter.hasNext()) {
ConcreteParasiticDevice *device = device_iter.next(); ConcreteParasiticDevice *device = device_iter.next();
devices.insert(device); devices->insert(device);
} }
} }
@ -751,7 +788,7 @@ ConcreteParasiticNetwork::devices(ConcreteParasiticDeviceSet &devices)
ConcreteParasiticDeviceSeq::Iterator device_iter(node->devices()); ConcreteParasiticDeviceSeq::Iterator device_iter(node->devices());
while (device_iter.hasNext()) { while (device_iter.hasNext()) {
ConcreteParasiticDevice *device = device_iter.next(); ConcreteParasiticDevice *device = device_iter.next();
devices.insert(device); devices->insert(device);
} }
} }
} }
@ -1798,6 +1835,20 @@ ConcreteParasitics::makeResistor(const char *name,
cnode2->addDevice(resistor); cnode2->addDevice(resistor);
} }
ParasiticDeviceIterator *
ConcreteParasitics::deviceIterator(Parasitic *parasitic)
{
ConcreteParasitic *cparasitic = static_cast<ConcreteParasitic*>(parasitic);
return cparasitic->deviceIterator();
}
ParasiticNodeIterator *
ConcreteParasitics::nodeIterator(Parasitic *parasitic)
{
ConcreteParasitic *cparasitic = static_cast<ConcreteParasitic*>(parasitic);
return cparasitic->nodeIterator();
}
float float
ConcreteParasitics::nodeGndCap(const ParasiticNode *node, ConcreteParasitics::nodeGndCap(const ParasiticNode *node,
const ParasiticAnalysisPt *) const const ParasiticAnalysisPt *) const
@ -1838,17 +1889,11 @@ ConcreteParasitics::findNode(Parasitic *parasitic,
return cparasitic->findNode(pin); return cparasitic->findNode(pin);
} }
ConcreteParasiticDeviceIterator::
ConcreteParasiticDeviceIterator(ConcreteParasiticNode *node) :
iter_(node->devices())
{
}
ParasiticDeviceIterator * ParasiticDeviceIterator *
ConcreteParasitics::deviceIterator(ParasiticNode *node) const ConcreteParasitics::deviceIterator(ParasiticNode *node) const
{ {
ConcreteParasiticNode *cnode = static_cast<ConcreteParasiticNode*>(node); ConcreteParasiticNode *cnode = static_cast<ConcreteParasiticNode*>(node);
return new ConcreteParasiticDeviceIterator(cnode); return new ConcreteParasiticDeviceSeqIterator(cnode->devices());
} }
const char * const char *
@ -2031,4 +2076,34 @@ ConcreteParasitics::estimatePiElmore(const Pin *drvr_pin,
sdc_); sdc_);
} }
////////////////////////////////////////////////////////////////
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();
}
} // namespace } // namespace

View File

@ -162,6 +162,8 @@ public:
virtual void makeResistor(const char *name, ParasiticNode *node1, virtual void makeResistor(const char *name, ParasiticNode *node1,
ParasiticNode *node2, ParasiticNode *node2,
float res, const ParasiticAnalysisPt *ap); float res, const ParasiticAnalysisPt *ap);
virtual ParasiticDeviceIterator *deviceIterator(Parasitic *parasitic);
virtual ParasiticNodeIterator *nodeIterator(Parasitic *parasitic);
virtual const char *name(const ParasiticNode *node); virtual const char *name(const ParasiticNode *node);
virtual const Pin *connectionPin(const ParasiticNode *node) const; virtual const Pin *connectionPin(const ParasiticNode *node) const;

View File

@ -25,6 +25,7 @@ class ConcretePoleResidue;
class ConcreteParasiticDevice; class ConcreteParasiticDevice;
class ConcreteParasiticPinNode; class ConcreteParasiticPinNode;
class ConcreteParasiticSubNode; class ConcreteParasiticSubNode;
class ConcreteParasiticNode;
typedef Map<const Pin*, float> ConcreteElmoreLoadMap; typedef Map<const Pin*, float> ConcreteElmoreLoadMap;
typedef ConcreteElmoreLoadMap::Iterator ConcretePiElmoreLoadIterator; typedef ConcreteElmoreLoadMap::Iterator ConcretePiElmoreLoadIterator;
@ -41,6 +42,7 @@ typedef Map<const Pin*,
ConcreteParasiticPinNode*> ConcreteParasiticPinNodeMap; ConcreteParasiticPinNode*> ConcreteParasiticPinNodeMap;
typedef Vector<ConcreteParasiticDevice*> ConcreteParasiticDeviceSeq; typedef Vector<ConcreteParasiticDevice*> ConcreteParasiticDeviceSeq;
typedef Set<ConcreteParasiticDevice*> ConcreteParasiticDeviceSet; typedef Set<ConcreteParasiticDevice*> ConcreteParasiticDeviceSet;
typedef Vector<ConcreteParasiticNode*> ConcreteParasiticNodeSeq;
// Empty base class definitions so casts are not required on returned // Empty base class definitions so casts are not required on returned
// objects. // objects.
@ -78,6 +80,8 @@ public:
virtual void setPoleResidue(const Pin *load_pin, virtual void setPoleResidue(const Pin *load_pin,
ComplexFloatSeq *poles, ComplexFloatSeq *poles,
ComplexFloatSeq *residues); ComplexFloatSeq *residues);
virtual ParasiticDeviceIterator *deviceIterator();
virtual ParasiticNodeIterator *nodeIterator();
}; };
class ConcreteElmore class ConcreteElmore
@ -268,7 +272,8 @@ protected:
class ConcreteParasiticSubNode : public ConcreteParasiticNode class ConcreteParasiticSubNode : public ConcreteParasiticNode
{ {
public: public:
ConcreteParasiticSubNode(Net *net, int id); ConcreteParasiticSubNode(Net *net,
int id);
virtual const char *name(const Network *network) const; virtual const char *name(const Network *network) const;
private: private:
@ -391,10 +396,22 @@ public:
private: private:
}; };
class ConcreteParasiticDeviceIterator : public ParasiticDeviceIterator class ConcreteParasiticDeviceSetIterator : public ParasiticDeviceIterator
{ {
public: public:
ConcreteParasiticDeviceIterator(ConcreteParasiticNode *node); 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(); } bool hasNext() { return iter_.hasNext(); }
ParasiticDevice *next() { return iter_.next(); } ParasiticDevice *next() { return iter_.next(); }
@ -402,6 +419,18 @@ private:
ConcreteParasiticDeviceSeq::ConstIterator iter_; ConcreteParasiticDeviceSeq::ConstIterator iter_;
}; };
class ConcreteParasiticNodeSeqIterator : public ParasiticNodeIterator
{
public:
ConcreteParasiticNodeSeqIterator(ConcreteParasiticNodeSeq *devices);
virtual ~ConcreteParasiticNodeSeqIterator();
bool hasNext() { return iter_.hasNext(); }
ParasiticNode *next() { return iter_.next(); }
private:
ConcreteParasiticNodeSeq::ConstIterator iter_;
};
class ConcreteParasiticNetwork : public ParasiticNetwork, class ConcreteParasiticNetwork : public ParasiticNetwork,
public ConcreteParasitic public ConcreteParasitic
{ {
@ -418,7 +447,10 @@ public:
ConcreteParasiticPinNodeMap *pinNodes() { return &pin_nodes_; } ConcreteParasiticPinNodeMap *pinNodes() { return &pin_nodes_; }
ConcreteParasiticSubNodeMap *subNodes() { return &sub_nodes_; } ConcreteParasiticSubNodeMap *subNodes() { return &sub_nodes_; }
void disconnectPin(const Pin *pin, Net *net); void disconnectPin(const Pin *pin, Net *net);
void devices(ConcreteParasiticDeviceSet &devices); virtual ParasiticDeviceIterator *deviceIterator();
virtual ParasiticNodeIterator *nodeIterator();
virtual void devices(// Return value.
ConcreteParasiticDeviceSet *devices);
private: private:
void deleteNodes(); void deleteNodes();

View File

@ -126,6 +126,8 @@ public:
makeParasiticNetwork(Net *net, makeParasiticNetwork(Net *net,
bool pin_cap_included, bool pin_cap_included,
const ParasiticAnalysisPt *ap); const ParasiticAnalysisPt *ap);
virtual ParasiticDeviceIterator *deviceIterator(Parasitic *) { return NULL; }
virtual ParasiticNodeIterator *nodeIterator(Parasitic *) { return NULL; }
virtual bool includesPinCaps(Parasitic *parasitic) const; virtual bool includesPinCaps(Parasitic *parasitic) const;
virtual void deleteParasiticNetwork(const Net *net, virtual void deleteParasiticNetwork(const Net *net,
const ParasiticAnalysisPt *ap); const ParasiticAnalysisPt *ap);

View File

@ -33,6 +33,7 @@ class Corner;
typedef std::complex<float> ComplexFloat; typedef std::complex<float> ComplexFloat;
typedef Vector<ComplexFloat> ComplexFloatSeq; typedef Vector<ComplexFloat> ComplexFloatSeq;
typedef Iterator<ParasiticDevice*> ParasiticDeviceIterator; typedef Iterator<ParasiticDevice*> ParasiticDeviceIterator;
typedef Iterator<ParasiticNode*> ParasiticNodeIterator;
// Parasitics API. // Parasitics API.
// All parasitic parameters can have multiple values, each corresponding // All parasitic parameters can have multiple values, each corresponding
@ -171,7 +172,7 @@ public:
ComplexFloat &residue) const=0; ComplexFloat &residue) const=0;
//////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////
// Parasitic Network (detailed parasitics, or DSPF). // Parasitic Network (detailed parasitics).
// This api assumes that parasitic networks are not rise/fall // This api assumes that parasitic networks are not rise/fall
// dependent because they do not include pin capacitances. // dependent because they do not include pin capacitances.
virtual bool isParasiticNetwork(Parasitic *parasitic) const = 0; virtual bool isParasiticNetwork(Parasitic *parasitic) const = 0;
@ -184,6 +185,8 @@ public:
virtual Parasitic *makeParasiticNetwork(Net *net, virtual Parasitic *makeParasiticNetwork(Net *net,
bool pin_cap_included, bool pin_cap_included,
const ParasiticAnalysisPt *ap) = 0; const ParasiticAnalysisPt *ap) = 0;
virtual ParasiticDeviceIterator *deviceIterator(Parasitic *parasitic) = 0;
virtual ParasiticNodeIterator *nodeIterator(Parasitic *parasitic) = 0;
// Delete parasitic network if it exists. // Delete parasitic network if it exists.
virtual void deleteParasiticNetwork(const Net *net, virtual void deleteParasiticNetwork(const Net *net,
const ParasiticAnalysisPt *ap) = 0; const ParasiticAnalysisPt *ap) = 0;

View File

@ -75,9 +75,9 @@ PathEnd::pathEarlyLate(const StaState *sta) const
} }
const EarlyLate * const EarlyLate *
PathEnd::clkEarlyLate(const StaState *) const PathEnd::clkEarlyLate(const StaState *sta) const
{ {
return NULL; return checkRole(sta)->tgtClkEarlyLate();
} }
const TransRiseFall * const TransRiseFall *
@ -552,15 +552,6 @@ PathEndClkConstrained::setPath(PathEnumed *path,
crpr_valid_ = false; crpr_valid_ = false;
} }
const EarlyLate *
PathEndClkConstrained::clkEarlyLate(const StaState *sta) const
{
if (clk_path_.isNull())
return NULL;
else
return clk_path_.pathAnalysisPt(sta)->pathMinMax();
}
float float
PathEndClkConstrained::sourceClkOffset(const StaState *sta) const PathEndClkConstrained::sourceClkOffset(const StaState *sta) const
{ {

View File

@ -239,7 +239,6 @@ private:
class PathEndClkConstrained : public PathEnd class PathEndClkConstrained : public PathEnd
{ {
public: public:
virtual const EarlyLate *clkEarlyLate(const StaState *sta) const;
virtual float sourceClkOffset(const StaState *sta) const; virtual float sourceClkOffset(const StaState *sta) const;
virtual Delay sourceClkLatency(const StaState *sta) const; virtual Delay sourceClkLatency(const StaState *sta) const;
virtual Delay sourceClkInsertionDelay(const StaState *sta) const; virtual Delay sourceClkInsertionDelay(const StaState *sta) const;

View File

@ -747,7 +747,7 @@ WritePathSpice::writeStageVoltageSources(Stage stage,
} }
} }
} }
else else if (drvr_port->function())
sensitizationValues(inst, drvr_port->function(), input_port, port_values); sensitizationValues(inst, drvr_port->function(), input_port, port_values);
int volt_index = 1; int volt_index = 1;
debugPrint1(debug_, "write_spice", 2, "subckt %s\n", cell->name()); debugPrint1(debug_, "write_spice", 2, "subckt %s\n", cell->name());
@ -986,55 +986,6 @@ WritePathSpice::onePort(FuncExpr *expr)
} }
} }
class ParasiticNodeNameLess
{
public:
ParasiticNodeNameLess(Parasitics *parasitics);
bool operator()(const ParasiticNode *node1,
const ParasiticNode *node2) const;
private:
Parasitics *parasitics_;
};
ParasiticNodeNameLess::ParasiticNodeNameLess(Parasitics *parasitics) :
parasitics_(parasitics)
{
}
bool
ParasiticNodeNameLess::operator()(const ParasiticNode *node1,
const ParasiticNode *node2) const
{
return stringLess(parasitics_->name(node1),
parasitics_->name(node2));
}
typedef Set<ParasiticDevice*> ParasiticDeviceSet;
// Less uses names rather than pointers for stable results.
typedef Set<ParasiticNode*, ParasiticNodeNameLess> ParasiticNodeSet;
void
findParasiticDevicesNodes(ParasiticNode *node,
Parasitics *parasitics,
// Return values.
ParasiticNodeSet &nodes,
ParasiticDeviceSet &devices)
{
nodes.insert(node);
auto device_iter = parasitics->deviceIterator(node);
while (device_iter->hasNext()) {
auto device = device_iter->next();
if (!devices.hasKey(device)) {
devices.insert(device);
auto other_node = parasitics->otherNode(device, node);
if (other_node)
findParasiticDevicesNodes(other_node, parasitics, nodes, devices);
}
}
delete device_iter;
}
void void
WritePathSpice::writeStageParasitics(Stage stage) WritePathSpice::writeStageParasitics(Stage stage)
{ {
@ -1052,14 +1003,9 @@ WritePathSpice::writeStageParasitics(Stage stage)
net ? network_->pathName(net) : network_->pathName(drvr_pin); net ? network_->pathName(net) : network_->pathName(drvr_pin);
initNodeMap(net_name); initNodeMap(net_name);
streamPrint(spice_stream_, "* Net %s\n", net_name); streamPrint(spice_stream_, "* Net %s\n", net_name);
auto node = parasitics_->findNode(parasitic, drvr_pin); ParasiticDeviceIterator *device_iter = parasitics_->deviceIterator(parasitic);
ParasiticNodeNameLess node_name_less(parasitics_); while (device_iter->hasNext()) {
ParasiticNodeSet nodes(node_name_less); auto device = device_iter->next();
ParasiticDeviceSet devices;
findParasiticDevicesNodes(node, parasitics_, nodes, devices);
ParasiticDeviceSet::Iterator device_iter(devices);
while (device_iter.hasNext()) {
auto device = device_iter.next();
auto resistance = parasitics_->value(device, parasitic_ap); auto resistance = parasitics_->value(device, parasitic_ap);
if (parasitics_->isResistor(device)) { if (parasitics_->isResistor(device)) {
ParasiticNode *node1 = parasitics_->node1(device); ParasiticNode *node1 = parasitics_->node1(device);
@ -1082,10 +1028,12 @@ WritePathSpice::writeStageParasitics(Stage stage)
cap_index++; cap_index++;
} }
} }
ParasiticNodeSet::Iterator node_iter(nodes); delete device_iter;
while (node_iter.hasNext()) { ParasiticNodeIterator *node_iter = parasitics_->nodeIterator(parasitic);
auto node = node_iter.next(); while (node_iter->hasNext()) {
auto node = node_iter->next();
auto cap = parasitics_->nodeGndCap(node, parasitic_ap); auto cap = parasitics_->nodeGndCap(node, parasitic_ap);
// Spice has a cow over zero value caps.
if (cap > 0.0) { if (cap > 0.0) {
streamPrint(spice_stream_, "C%d %s 0 %.3e\n", streamPrint(spice_stream_, "C%d %s 0 %.3e\n",
cap_index, cap_index,
@ -1094,6 +1042,7 @@ WritePathSpice::writeStageParasitics(Stage stage)
cap_index++; cap_index++;
} }
} }
delete node_iter;
} }
else { else {
streamPrint(spice_stream_, "* No parasitics found for this net.\n"); streamPrint(spice_stream_, "* No parasitics found for this net.\n");

View File

@ -1932,7 +1932,7 @@ proc write_path_spice { args } {
flags {} flags {}
if { [info exists keys(-spice_directory)] } { if { [info exists keys(-spice_directory)] } {
set spice_dir $keys(-spice_directory) set spice_dir [file_expand_tilde $keys(-spice_directory)]
if { ![file exists $spice_dir] } { if { ![file exists $spice_dir] } {
sta_error "Directory $spice_dir not found.\n" sta_error "Directory $spice_dir not found.\n"
} }
@ -1947,7 +1947,7 @@ proc write_path_spice { args } {
} }
if { [info exists keys(-lib_subckt_file)] } { if { [info exists keys(-lib_subckt_file)] } {
set lib_subckt_file $keys(-lib_subckt_file) set lib_subckt_file [file_expand_tilde $keys(-lib_subckt_file)]
if { ![file readable $lib_subckt_file] } { if { ![file readable $lib_subckt_file] } {
sta_error "-lib_subckt_file $lib_subckt_file is not readable.\n" sta_error "-lib_subckt_file $lib_subckt_file is not readable.\n"
} }
@ -1956,7 +1956,7 @@ proc write_path_spice { args } {
} }
if { [info exists keys(-lib_subckt_file)] } { if { [info exists keys(-lib_subckt_file)] } {
set model_file $keys(-model_file) set model_file [file_expand_tilde $keys(-model_file)]
if { ![file readable $model_file] } { if { ![file readable $model_file] } {
sta_error "-model_file $model_file is not readable.\n" sta_error "-model_file $model_file is not readable.\n"
} }
@ -2003,5 +2003,15 @@ proc write_path_spice { args } {
} }
} }
proc file_expand_tilde { filename } {
global env
if { [string range $filename 0 1] == "~/" } {
return [file join $env(HOME) [string range $filename 2 end]]
} else {
return $filename
}
}
# sta namespace end. # sta namespace end.
} }