Merge remote-tracking branch 'parallax/master'
Signed-off-by: Matt Liberty <mliberty@precisioninno.com>
This commit is contained in:
commit
431856884a
|
|
@ -73,4 +73,8 @@ bool
|
|||
equivCellSequentials(const LibertyCell *cell1,
|
||||
const LibertyCell *cell2);
|
||||
|
||||
bool
|
||||
equivCellFootprints(const LibertyCell *cell1,
|
||||
const LibertyCell *cell2);
|
||||
|
||||
} // namespace
|
||||
|
|
|
|||
|
|
@ -541,6 +541,8 @@ public:
|
|||
// for all the defined corners.
|
||||
static void checkLibertyCorners();
|
||||
void ensureVoltageWaveforms(const DcalcAnalysisPtSeq &dcalc_aps);
|
||||
const char *footprint() const;
|
||||
void setFootprint(const char *footprint);
|
||||
|
||||
protected:
|
||||
void addPort(ConcretePort *port);
|
||||
|
|
@ -631,6 +633,7 @@ protected:
|
|||
bool has_internal_ports_;
|
||||
bool have_voltage_waveforms_;
|
||||
std::mutex waveform_lock_;
|
||||
const char *footprint_;
|
||||
|
||||
private:
|
||||
friend class LibertyLibrary;
|
||||
|
|
|
|||
|
|
@ -154,6 +154,8 @@ public:
|
|||
bool includes_pin_caps,
|
||||
const ParasiticAnalysisPt *ap) = 0;
|
||||
virtual ParasiticNodeSeq nodes(const Parasitic *parasitic) const = 0;
|
||||
virtual void report(const Parasitic *parasitic) const;
|
||||
virtual const Net *net(const Parasitic *parasitic) const = 0;
|
||||
virtual ParasiticResistorSeq resistors(const Parasitic *parasitic) const = 0;
|
||||
virtual ParasiticCapacitorSeq capacitors(const Parasitic *parasitic) const = 0;
|
||||
// Delete parasitic network if it exists.
|
||||
|
|
|
|||
|
|
@ -325,7 +325,8 @@ equivCells(const LibertyCell *cell1,
|
|||
&& equivCellPgPorts(cell1, cell2)
|
||||
&& equivCellSequentials(cell1, cell2)
|
||||
&& equivCellStatetables(cell1, cell2)
|
||||
&& equivCellTimingArcSets(cell1, cell2);
|
||||
&& equivCellTimingArcSets(cell1, cell2)
|
||||
&& equivCellFootprints(cell1, cell2);
|
||||
}
|
||||
|
||||
bool
|
||||
|
|
@ -525,4 +526,11 @@ equivCellTimingArcSets(const LibertyCell *cell1,
|
|||
}
|
||||
}
|
||||
|
||||
bool
|
||||
equivCellFootprints(const LibertyCell *cell1,
|
||||
const LibertyCell *cell2)
|
||||
{
|
||||
return stringEqIf(cell1->footprint(), cell2->footprint());
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
|
|
|||
|
|
@ -940,7 +940,8 @@ LibertyCell::LibertyCell(LibertyLibrary *library,
|
|||
leakage_power_(0.0),
|
||||
leakage_power_exists_(false),
|
||||
has_internal_ports_(false),
|
||||
have_voltage_waveforms_(false)
|
||||
have_voltage_waveforms_(false),
|
||||
footprint_(nullptr)
|
||||
{
|
||||
liberty_cell_ = this;
|
||||
}
|
||||
|
|
@ -968,6 +969,8 @@ LibertyCell::~LibertyCell()
|
|||
ocv_derate_map_.deleteContents();
|
||||
|
||||
pg_port_map_.deleteContents();
|
||||
|
||||
stringDelete(footprint_);
|
||||
}
|
||||
|
||||
LibertyPort *
|
||||
|
|
@ -1989,6 +1992,18 @@ LibertyCell::ensureVoltageWaveforms(const DcalcAnalysisPtSeq &dcalc_aps)
|
|||
}
|
||||
}
|
||||
|
||||
void
|
||||
LibertyCell::setFootprint(const char *footprint)
|
||||
{
|
||||
footprint_ = stringCopy(footprint);
|
||||
}
|
||||
|
||||
const char*
|
||||
LibertyCell::footprint() const
|
||||
{
|
||||
return footprint_;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////
|
||||
|
||||
LibertyCellPortIterator::LibertyCellPortIterator(const LibertyCell *cell) :
|
||||
|
|
|
|||
|
|
@ -310,6 +310,7 @@ LibertyReader::defineVisitors()
|
|||
defineAttrVisitor("switch_cell_type", &LibertyReader::visitSwitchCellType);
|
||||
defineAttrVisitor("interface_timing", &LibertyReader::visitInterfaceTiming);
|
||||
defineAttrVisitor("scaling_factors", &LibertyReader::visitScalingFactors);
|
||||
defineAttrVisitor("cell_footprint", &LibertyReader::visitCellFootprint);
|
||||
|
||||
// Pins
|
||||
defineGroupVisitor("pin", &LibertyReader::beginPin,&LibertyReader::endPin);
|
||||
|
|
@ -3065,6 +3066,16 @@ LibertyReader::visitClockGatingIntegratedCell(LibertyAttr *attr)
|
|||
}
|
||||
}
|
||||
|
||||
void
|
||||
LibertyReader::visitCellFootprint(LibertyAttr *attr)
|
||||
{
|
||||
if (cell_) {
|
||||
const char *footprint = getAttrString(attr);
|
||||
if (footprint)
|
||||
cell_->setFootprint(stringCopy(footprint));
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////
|
||||
|
||||
void
|
||||
|
|
|
|||
|
|
@ -205,6 +205,7 @@ public:
|
|||
virtual void visitInterfaceTiming(LibertyAttr *attr);
|
||||
virtual void visitScalingFactors(LibertyAttr *attr);
|
||||
virtual void visitCellLeakagePower(LibertyAttr *attr);
|
||||
virtual void visitCellFootprint(LibertyAttr *attr);
|
||||
|
||||
virtual void beginPin(LibertyGroup *group);
|
||||
virtual void endPin(LibertyGroup *group);
|
||||
|
|
|
|||
|
|
@ -596,13 +596,14 @@ ConcreteParasiticNetwork::findParasiticNode(const Pin *pin) const
|
|||
ConcreteParasiticNode *
|
||||
ConcreteParasiticNetwork::ensureParasiticNode(const Net *net,
|
||||
int id,
|
||||
const Network *)
|
||||
const Network *network)
|
||||
{
|
||||
ConcreteParasiticNode *node;
|
||||
NetIdPair net_id(net, id);
|
||||
auto id_node = sub_nodes_.find(net_id);
|
||||
if (id_node == sub_nodes_.end()) {
|
||||
node = new ConcreteParasiticNode(net, id, net != net_);
|
||||
Net *net1 = network->highestNetAbove(const_cast<Net*>(net));
|
||||
node = new ConcreteParasiticNode(net, id, network->highestNetAbove(net1) != net_);
|
||||
sub_nodes_[net_id] = node;
|
||||
if (net == net_)
|
||||
max_node_id_ = max((int) max_node_id_, id);
|
||||
|
|
@ -1287,6 +1288,17 @@ ConcreteParasitics::deleteParasiticNetworks(const Net *net)
|
|||
}
|
||||
}
|
||||
|
||||
const Net *
|
||||
ConcreteParasitics::net(const Parasitic *parasitic) const
|
||||
{
|
||||
const ConcreteParasiticNetwork *cparasitic =
|
||||
static_cast<const ConcreteParasiticNetwork*>(parasitic);
|
||||
if (cparasitic->isParasiticNetwork())
|
||||
return cparasitic->net();
|
||||
else
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
bool
|
||||
ConcreteParasitics::includesPinCaps(const Parasitic *parasitic) const
|
||||
{
|
||||
|
|
|
|||
|
|
@ -112,6 +112,7 @@ public:
|
|||
void deleteParasiticNetwork(const Net *net,
|
||||
const ParasiticAnalysisPt *ap) override;
|
||||
void deleteParasiticNetworks(const Net *net) override;
|
||||
const Net *net(const Parasitic *parasitic) const override;
|
||||
bool includesPinCaps(const Parasitic *parasitic) const override;
|
||||
ParasiticNode *findParasiticNode(Parasitic *parasitic,
|
||||
const Net *net,
|
||||
|
|
|
|||
|
|
@ -207,7 +207,7 @@ public:
|
|||
const Network *network);
|
||||
virtual ~ConcreteParasiticNetwork();
|
||||
virtual bool isParasiticNetwork() const { return true; }
|
||||
const Net *net() { return net_; }
|
||||
const Net *net() const { return net_; }
|
||||
bool includesPinCaps() const { return includes_pin_caps_; }
|
||||
ConcreteParasiticNode *findParasiticNode(const Net *net,
|
||||
int id,
|
||||
|
|
|
|||
|
|
@ -18,6 +18,7 @@
|
|||
|
||||
#include "Error.hh"
|
||||
#include "Debug.hh"
|
||||
#include "Units.hh"
|
||||
#include "Liberty.hh"
|
||||
#include "Wireload.hh"
|
||||
#include "Network.hh"
|
||||
|
|
@ -34,6 +35,47 @@ Parasitics::Parasitics(StaState *sta) :
|
|||
{
|
||||
}
|
||||
|
||||
void
|
||||
Parasitics::report(const Parasitic *parasitic) const
|
||||
{
|
||||
if (isParasiticNetwork(parasitic)) {
|
||||
const Unit *cap_unit = units_->capacitanceUnit();
|
||||
report_->reportLine("Net %s %s",
|
||||
network_->pathName(net(parasitic)),
|
||||
cap_unit->asString(capacitance(parasitic)));
|
||||
report_->reportLine("Nodes:");
|
||||
for (ParasiticNode *node : nodes(parasitic))
|
||||
report_->reportLine("%s%s %s",
|
||||
name(node),
|
||||
isExternal(node) ? " (ext)" : "",
|
||||
cap_unit->asString(nodeGndCap(node)));
|
||||
report_->reportLine("Resistors:");
|
||||
for (ParasiticResistor *res : resistors(parasitic)) {
|
||||
ParasiticNode *node1 = this->node1(res);
|
||||
ParasiticNode *node2 = this->node2(res);
|
||||
report_->reportLine("%zu %s%s %s%s %s",
|
||||
id(res),
|
||||
name(node1),
|
||||
isExternal(node1) ? " (ext)" : "",
|
||||
name(node2),
|
||||
isExternal(node2) ? " (ext)" : "",
|
||||
units_->resistanceUnit()->asString(value(res)));
|
||||
}
|
||||
report_->reportLine("Coupling Capacitors:");
|
||||
for (ParasiticCapacitor *cap : capacitors(parasitic)) {
|
||||
ParasiticNode *node1 = this->node1(cap);
|
||||
ParasiticNode *node2 = this->node2(cap);
|
||||
report_->reportLine("%zu %s%s %s%s %s",
|
||||
id(cap),
|
||||
name(node1),
|
||||
isExternal(node1) ? " (ext)" : "",
|
||||
name(node2),
|
||||
isExternal(node2) ? " (ext)" : "",
|
||||
cap_unit->asString(value(cap)));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const Net *
|
||||
Parasitics::findParasiticNet(const Pin *pin) const
|
||||
{
|
||||
|
|
|
|||
|
|
@ -155,60 +155,53 @@ ReduceToPi::reducePiDfs(const Pin *drvr_pin,
|
|||
double &dwn_cap,
|
||||
double &max_resistance)
|
||||
{
|
||||
if (parasitics_->isExternal(node)) {
|
||||
y1 = y2 = y3 = 0.0;
|
||||
max_resistance = 0.0;
|
||||
dwn_cap = 0.0;
|
||||
}
|
||||
else {
|
||||
double coupling_cap = 0.0;
|
||||
ParasiticCapacitorSeq &capacitors = capacitor_map_[node];
|
||||
for (ParasiticCapacitor *capacitor : capacitors)
|
||||
coupling_cap += parasitics_->value(capacitor);
|
||||
double coupling_cap = 0.0;
|
||||
ParasiticCapacitorSeq &capacitors = capacitor_map_[node];
|
||||
for (ParasiticCapacitor *capacitor : capacitors)
|
||||
coupling_cap += parasitics_->value(capacitor);
|
||||
|
||||
dwn_cap = parasitics_->nodeGndCap(node)
|
||||
+ coupling_cap * coupling_cap_multiplier_
|
||||
+ pinCapacitance(node);
|
||||
y1 = dwn_cap;
|
||||
y2 = y3 = 0.0;
|
||||
max_resistance = max(max_resistance, src_resistance);
|
||||
dwn_cap = parasitics_->nodeGndCap(node)
|
||||
+ coupling_cap * coupling_cap_multiplier_
|
||||
+ pinCapacitance(node);
|
||||
y1 = dwn_cap;
|
||||
y2 = y3 = 0.0;
|
||||
max_resistance = max(max_resistance, src_resistance);
|
||||
|
||||
visit(node);
|
||||
ParasiticResistorSeq &resistors = resistor_map_[node];
|
||||
for (ParasiticResistor *resistor : resistors) {
|
||||
if (!isLoopResistor(resistor)) {
|
||||
ParasiticNode *onode = parasitics_->otherNode(resistor, node);
|
||||
// One commercial extractor creates resistors with identical from/to nodes.
|
||||
if (onode != node
|
||||
&& resistor != from_res) {
|
||||
if (isVisited(onode)) {
|
||||
// Resistor loop.
|
||||
debugPrint(debug_, "parasitic_reduce", 2, " loop detected thru resistor %zu",
|
||||
parasitics_->id(resistor));
|
||||
markLoopResistor(resistor);
|
||||
}
|
||||
else {
|
||||
double r = parasitics_->value(resistor);
|
||||
double yd1, yd2, yd3, dcap;
|
||||
reducePiDfs(drvr_pin, onode, resistor, src_resistance + r,
|
||||
yd1, yd2, yd3, dcap, max_resistance);
|
||||
// Rule 3. Upstream traversal of a series resistor.
|
||||
// Rule 4. Parallel admittances add.
|
||||
y1 += yd1;
|
||||
y2 += yd2 - r * yd1 * yd1;
|
||||
y3 += yd3 - 2 * r * yd1 * yd2 + r * r * yd1 * yd1 * yd1;
|
||||
dwn_cap += dcap;
|
||||
}
|
||||
visit(node);
|
||||
ParasiticResistorSeq &resistors = resistor_map_[node];
|
||||
for (ParasiticResistor *resistor : resistors) {
|
||||
if (!isLoopResistor(resistor)) {
|
||||
ParasiticNode *onode = parasitics_->otherNode(resistor, node);
|
||||
// One commercial extractor creates resistors with identical from/to nodes.
|
||||
if (onode != node
|
||||
&& resistor != from_res) {
|
||||
if (isVisited(onode)) {
|
||||
// Resistor loop.
|
||||
debugPrint(debug_, "parasitic_reduce", 2, " loop detected thru resistor %zu",
|
||||
parasitics_->id(resistor));
|
||||
markLoopResistor(resistor);
|
||||
}
|
||||
else {
|
||||
double r = parasitics_->value(resistor);
|
||||
double yd1, yd2, yd3, dcap;
|
||||
reducePiDfs(drvr_pin, onode, resistor, src_resistance + r,
|
||||
yd1, yd2, yd3, dcap, max_resistance);
|
||||
// Rule 3. Upstream traversal of a series resistor.
|
||||
// Rule 4. Parallel admittances add.
|
||||
y1 += yd1;
|
||||
y2 += yd2 - r * yd1 * yd1;
|
||||
y3 += yd3 - 2 * r * yd1 * yd2 + r * r * yd1 * yd1 * yd1;
|
||||
dwn_cap += dcap;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
setDownstreamCap(node, dwn_cap);
|
||||
leave(node);
|
||||
debugPrint(debug_, "parasitic_reduce", 3,
|
||||
" node %s y1=%.3g y2=%.3g y3=%.3g cap=%.3g",
|
||||
parasitics_->name(node), y1, y2, y3, dwn_cap);
|
||||
}
|
||||
|
||||
setDownstreamCap(node, dwn_cap);
|
||||
leave(node);
|
||||
debugPrint(debug_, "parasitic_reduce", 3,
|
||||
" node %s y1=%.3g y2=%.3g y3=%.3g cap=%.3g",
|
||||
parasitics_->name(node), y1, y2, y3, dwn_cap);
|
||||
}
|
||||
|
||||
float
|
||||
|
|
|
|||
|
|
@ -5240,6 +5240,8 @@ Sdc::exceptionFromClkStates(const Pin *pin,
|
|||
exceptionFromStates(first_from_inst_exceptions_.findKey(inst),
|
||||
pin, rf, min_max, true, states);
|
||||
}
|
||||
exceptionThruStates(first_thru_pin_exceptions_.findKey(pin),
|
||||
rf, min_max, states);
|
||||
}
|
||||
if (!first_from_clk_exceptions_.empty())
|
||||
exceptionFromStates(first_from_clk_exceptions_.findKey(clk),
|
||||
|
|
|
|||
Loading…
Reference in New Issue