diff --git a/dcalc/ArnoldiReduce.cc b/dcalc/ArnoldiReduce.cc index 9e72fb3a..90f4f8e5 100644 --- a/dcalc/ArnoldiReduce.cc +++ b/dcalc/ArnoldiReduce.cc @@ -164,7 +164,7 @@ ArnoldiReduce::loadWork() int resistor_count = 0; ConcreteParasiticDeviceSet devices; - parasitic_network_->devices(devices); + parasitic_network_->devices(&devices); ConcreteParasiticDeviceSet::Iterator device_iter(devices); while (device_iter.hasNext()) { ParasiticDevice *device = device_iter.next(); diff --git a/parasitics/ConcreteParasitics.cc b/parasitics/ConcreteParasitics.cc index 8c800a43..46dc70d1 100644 --- a/parasitics/ConcreteParasitics.cc +++ b/parasitics/ConcreteParasitics.cc @@ -134,6 +134,18 @@ ConcreteParasitic::setPoleResidue(const Pin *, { } +ParasiticDeviceIterator * +ConcreteParasitic::deviceIterator() +{ + return NULL; +} + +ParasiticNodeIterator * +ConcreteParasitic::nodeIterator() +{ + return NULL; +} + //////////////////////////////////////////////////////////////// ConcreteElmore::ConcreteElmore() : @@ -726,12 +738,37 @@ void ConcreteParasiticNetwork::deleteDevices() { ConcreteParasiticDeviceSet devices1; - devices(devices1); + devices(&devices1); 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 -ConcreteParasiticNetwork::devices(ConcreteParasiticDeviceSet &devices) +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. @@ -741,7 +778,7 @@ ConcreteParasiticNetwork::devices(ConcreteParasiticDeviceSet &devices) ConcreteParasiticDeviceSeq::Iterator device_iter(node->devices()); while (device_iter.hasNext()) { 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()); while (device_iter.hasNext()) { ConcreteParasiticDevice *device = device_iter.next(); - devices.insert(device); + devices->insert(device); } } } @@ -1798,6 +1835,20 @@ ConcreteParasitics::makeResistor(const char *name, cnode2->addDevice(resistor); } +ParasiticDeviceIterator * +ConcreteParasitics::deviceIterator(Parasitic *parasitic) +{ + ConcreteParasitic *cparasitic = static_cast(parasitic); + return cparasitic->deviceIterator(); +} + +ParasiticNodeIterator * +ConcreteParasitics::nodeIterator(Parasitic *parasitic) +{ + ConcreteParasitic *cparasitic = static_cast(parasitic); + return cparasitic->nodeIterator(); +} + float ConcreteParasitics::nodeGndCap(const ParasiticNode *node, const ParasiticAnalysisPt *) const @@ -1838,17 +1889,11 @@ ConcreteParasitics::findNode(Parasitic *parasitic, return cparasitic->findNode(pin); } -ConcreteParasiticDeviceIterator:: -ConcreteParasiticDeviceIterator(ConcreteParasiticNode *node) : - iter_(node->devices()) -{ -} - ParasiticDeviceIterator * ConcreteParasitics::deviceIterator(ParasiticNode *node) const { ConcreteParasiticNode *cnode = static_cast(node); - return new ConcreteParasiticDeviceIterator(cnode); + return new ConcreteParasiticDeviceSeqIterator(cnode->devices()); } const char * @@ -2031,4 +2076,34 @@ ConcreteParasitics::estimatePiElmore(const Pin *drvr_pin, 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 diff --git a/parasitics/ConcreteParasitics.hh b/parasitics/ConcreteParasitics.hh index 1171d00a..106f9547 100644 --- a/parasitics/ConcreteParasitics.hh +++ b/parasitics/ConcreteParasitics.hh @@ -162,6 +162,8 @@ public: virtual void makeResistor(const char *name, ParasiticNode *node1, ParasiticNode *node2, float res, const ParasiticAnalysisPt *ap); + virtual ParasiticDeviceIterator *deviceIterator(Parasitic *parasitic); + virtual ParasiticNodeIterator *nodeIterator(Parasitic *parasitic); virtual const char *name(const ParasiticNode *node); virtual const Pin *connectionPin(const ParasiticNode *node) const; diff --git a/parasitics/ConcreteParasiticsPvt.hh b/parasitics/ConcreteParasiticsPvt.hh index 7bc2fca7..c6497866 100644 --- a/parasitics/ConcreteParasiticsPvt.hh +++ b/parasitics/ConcreteParasiticsPvt.hh @@ -25,6 +25,7 @@ class ConcretePoleResidue; class ConcreteParasiticDevice; class ConcreteParasiticPinNode; class ConcreteParasiticSubNode; +class ConcreteParasiticNode; typedef Map ConcreteElmoreLoadMap; typedef ConcreteElmoreLoadMap::Iterator ConcretePiElmoreLoadIterator; @@ -41,6 +42,7 @@ typedef Map ConcreteParasiticPinNodeMap; typedef Vector ConcreteParasiticDeviceSeq; typedef Set ConcreteParasiticDeviceSet; +typedef Vector ConcreteParasiticNodeSeq; // Empty base class definitions so casts are not required on returned // objects. @@ -78,6 +80,8 @@ public: virtual void setPoleResidue(const Pin *load_pin, ComplexFloatSeq *poles, ComplexFloatSeq *residues); + virtual ParasiticDeviceIterator *deviceIterator(); + virtual ParasiticNodeIterator *nodeIterator(); }; class ConcreteElmore @@ -268,7 +272,8 @@ protected: class ConcreteParasiticSubNode : public ConcreteParasiticNode { public: - ConcreteParasiticSubNode(Net *net, int id); + ConcreteParasiticSubNode(Net *net, + int id); virtual const char *name(const Network *network) const; private: @@ -391,10 +396,22 @@ public: private: }; -class ConcreteParasiticDeviceIterator : public ParasiticDeviceIterator +class ConcreteParasiticDeviceSetIterator : public ParasiticDeviceIterator { 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(); } ParasiticDevice *next() { return iter_.next(); } @@ -402,6 +419,18 @@ 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_; +}; + class ConcreteParasiticNetwork : public ParasiticNetwork, public ConcreteParasitic { @@ -418,7 +447,10 @@ public: ConcreteParasiticPinNodeMap *pinNodes() { return &pin_nodes_; } ConcreteParasiticSubNodeMap *subNodes() { return &sub_nodes_; } 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: void deleteNodes(); diff --git a/parasitics/NullParasitics.hh b/parasitics/NullParasitics.hh index 3c4b14ed..1b95795e 100644 --- a/parasitics/NullParasitics.hh +++ b/parasitics/NullParasitics.hh @@ -126,6 +126,8 @@ public: makeParasiticNetwork(Net *net, bool pin_cap_included, const ParasiticAnalysisPt *ap); + virtual ParasiticDeviceIterator *deviceIterator(Parasitic *) { return NULL; } + virtual ParasiticNodeIterator *nodeIterator(Parasitic *) { return NULL; } virtual bool includesPinCaps(Parasitic *parasitic) const; virtual void deleteParasiticNetwork(const Net *net, const ParasiticAnalysisPt *ap); diff --git a/parasitics/Parasitics.hh b/parasitics/Parasitics.hh index c9592487..87f6a791 100644 --- a/parasitics/Parasitics.hh +++ b/parasitics/Parasitics.hh @@ -33,6 +33,7 @@ class Corner; typedef std::complex ComplexFloat; typedef Vector ComplexFloatSeq; typedef Iterator ParasiticDeviceIterator; +typedef Iterator ParasiticNodeIterator; // Parasitics API. // All parasitic parameters can have multiple values, each corresponding @@ -171,7 +172,7 @@ public: ComplexFloat &residue) const=0; //////////////////////////////////////////////////////////////// - // Parasitic Network (detailed parasitics, or DSPF). + // Parasitic Network (detailed parasitics). // This api assumes that parasitic networks are not rise/fall // dependent because they do not include pin capacitances. virtual bool isParasiticNetwork(Parasitic *parasitic) const = 0; @@ -184,6 +185,8 @@ public: virtual Parasitic *makeParasiticNetwork(Net *net, bool pin_cap_included, const ParasiticAnalysisPt *ap) = 0; + virtual ParasiticDeviceIterator *deviceIterator(Parasitic *parasitic) = 0; + virtual ParasiticNodeIterator *nodeIterator(Parasitic *parasitic) = 0; // Delete parasitic network if it exists. virtual void deleteParasiticNetwork(const Net *net, const ParasiticAnalysisPt *ap) = 0; diff --git a/search/PathEnd.cc b/search/PathEnd.cc index 02842c23..b65a7799 100644 --- a/search/PathEnd.cc +++ b/search/PathEnd.cc @@ -75,9 +75,9 @@ PathEnd::pathEarlyLate(const StaState *sta) const } const EarlyLate * -PathEnd::clkEarlyLate(const StaState *) const +PathEnd::clkEarlyLate(const StaState *sta) const { - return NULL; + return checkRole(sta)->tgtClkEarlyLate(); } const TransRiseFall * @@ -552,15 +552,6 @@ PathEndClkConstrained::setPath(PathEnumed *path, 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 PathEndClkConstrained::sourceClkOffset(const StaState *sta) const { diff --git a/search/PathEnd.hh b/search/PathEnd.hh index 7e34dc3d..306078cd 100644 --- a/search/PathEnd.hh +++ b/search/PathEnd.hh @@ -239,7 +239,6 @@ private: class PathEndClkConstrained : public PathEnd { public: - virtual const EarlyLate *clkEarlyLate(const StaState *sta) const; virtual float sourceClkOffset(const StaState *sta) const; virtual Delay sourceClkLatency(const StaState *sta) const; virtual Delay sourceClkInsertionDelay(const StaState *sta) const; diff --git a/search/WritePathSpice.cc b/search/WritePathSpice.cc index 7548e68c..511f6387 100644 --- a/search/WritePathSpice.cc +++ b/search/WritePathSpice.cc @@ -747,7 +747,7 @@ WritePathSpice::writeStageVoltageSources(Stage stage, } } } - else + else if (drvr_port->function()) sensitizationValues(inst, drvr_port->function(), input_port, port_values); int volt_index = 1; 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 ParasiticDeviceSet; -// Less uses names rather than pointers for stable results. -typedef Set 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 WritePathSpice::writeStageParasitics(Stage stage) { @@ -1052,14 +1003,9 @@ WritePathSpice::writeStageParasitics(Stage stage) net ? network_->pathName(net) : network_->pathName(drvr_pin); initNodeMap(net_name); streamPrint(spice_stream_, "* Net %s\n", net_name); - auto node = parasitics_->findNode(parasitic, drvr_pin); - ParasiticNodeNameLess node_name_less(parasitics_); - ParasiticNodeSet nodes(node_name_less); - ParasiticDeviceSet devices; - findParasiticDevicesNodes(node, parasitics_, nodes, devices); - ParasiticDeviceSet::Iterator device_iter(devices); - while (device_iter.hasNext()) { - auto device = device_iter.next(); + ParasiticDeviceIterator *device_iter = parasitics_->deviceIterator(parasitic); + while (device_iter->hasNext()) { + auto device = device_iter->next(); auto resistance = parasitics_->value(device, parasitic_ap); if (parasitics_->isResistor(device)) { ParasiticNode *node1 = parasitics_->node1(device); @@ -1082,10 +1028,12 @@ WritePathSpice::writeStageParasitics(Stage stage) cap_index++; } } - ParasiticNodeSet::Iterator node_iter(nodes); - while (node_iter.hasNext()) { - auto node = node_iter.next(); + delete device_iter; + ParasiticNodeIterator *node_iter = parasitics_->nodeIterator(parasitic); + while (node_iter->hasNext()) { + auto node = node_iter->next(); auto cap = parasitics_->nodeGndCap(node, parasitic_ap); + // Spice has a cow over zero value caps. if (cap > 0.0) { streamPrint(spice_stream_, "C%d %s 0 %.3e\n", cap_index, @@ -1094,6 +1042,7 @@ WritePathSpice::writeStageParasitics(Stage stage) cap_index++; } } + delete node_iter; } else { streamPrint(spice_stream_, "* No parasitics found for this net.\n"); diff --git a/tcl/Cmds.tcl b/tcl/Cmds.tcl index 4864b185..91591b62 100644 --- a/tcl/Cmds.tcl +++ b/tcl/Cmds.tcl @@ -1932,7 +1932,7 @@ proc write_path_spice { args } { flags {} 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] } { sta_error "Directory $spice_dir not found.\n" } @@ -1947,7 +1947,7 @@ proc write_path_spice { args } { } 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] } { 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)] } { - set model_file $keys(-model_file) + set model_file [file_expand_tilde $keys(-model_file)] if { ![file readable $model_file] } { 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. }