sync
This commit is contained in:
parent
f2a28bdcaf
commit
ca231b29cc
|
|
@ -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();
|
||||
|
|
|
|||
|
|
@ -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<ConcreteParasitic*>(parasitic);
|
||||
return cparasitic->deviceIterator();
|
||||
}
|
||||
|
||||
ParasiticNodeIterator *
|
||||
ConcreteParasitics::nodeIterator(Parasitic *parasitic)
|
||||
{
|
||||
ConcreteParasitic *cparasitic = static_cast<ConcreteParasitic*>(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<ConcreteParasiticNode*>(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
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -25,6 +25,7 @@ class ConcretePoleResidue;
|
|||
class ConcreteParasiticDevice;
|
||||
class ConcreteParasiticPinNode;
|
||||
class ConcreteParasiticSubNode;
|
||||
class ConcreteParasiticNode;
|
||||
|
||||
typedef Map<const Pin*, float> ConcreteElmoreLoadMap;
|
||||
typedef ConcreteElmoreLoadMap::Iterator ConcretePiElmoreLoadIterator;
|
||||
|
|
@ -41,6 +42,7 @@ typedef Map<const Pin*,
|
|||
ConcreteParasiticPinNode*> ConcreteParasiticPinNodeMap;
|
||||
typedef Vector<ConcreteParasiticDevice*> ConcreteParasiticDeviceSeq;
|
||||
typedef Set<ConcreteParasiticDevice*> ConcreteParasiticDeviceSet;
|
||||
typedef Vector<ConcreteParasiticNode*> 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();
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -33,6 +33,7 @@ class Corner;
|
|||
typedef std::complex<float> ComplexFloat;
|
||||
typedef Vector<ComplexFloat> ComplexFloatSeq;
|
||||
typedef Iterator<ParasiticDevice*> ParasiticDeviceIterator;
|
||||
typedef Iterator<ParasiticNode*> 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;
|
||||
|
|
|
|||
|
|
@ -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
|
||||
{
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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<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
|
||||
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");
|
||||
|
|
|
|||
16
tcl/Cmds.tcl
16
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.
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue