Merge pull request #198 from openroadie/master

latest OpenSTA code.
This commit is contained in:
Harsh Vardhan 2023-10-05 07:32:53 +02:00 committed by GitHub
commit 9e792b0542
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
42 changed files with 469 additions and 278 deletions

View File

@ -266,8 +266,9 @@ ArnoldiDelayCalc::findParasitic(const Pin *drvr_pin,
const RiseFall *drvr_rf,
const DcalcAnalysisPt *dcalc_ap)
{
Parasitic *parasitic = nullptr;
const Corner *corner = dcalc_ap->corner();
// set_load has precidence over parasitics.
// set_load net has precidence over parasitics.
if (!sdc_->drvrPinHasWireCap(drvr_pin, corner)) {
const ParasiticAnalysisPt *parasitic_ap = dcalc_ap->parasiticAnalysisPt();
Parasitic *parasitic_network =
@ -291,22 +292,20 @@ ArnoldiDelayCalc::findParasitic(const Pin *drvr_pin,
}
if (parasitic_network) {
Parasitic *parasitic =
reduce_->reduceToArnoldi(parasitic_network,
drvr_pin,
parasitic_ap->couplingCapFactor(),
drvr_rf, op_cond, corner,
cnst_min_max, parasitic_ap);
parasitic = reduce_->reduceToArnoldi(parasitic_network,
drvr_pin,
parasitic_ap->couplingCapFactor(),
drvr_rf, op_cond, corner,
cnst_min_max, parasitic_ap);
if (delete_parasitic_network) {
Net *net = network_->net(drvr_pin);
parasitics_->deleteParasiticNetwork(net, parasitic_ap);
}
// Arnoldi parasitics their own class that are not saved in the parasitic db.
// Arnoldi parasitics are their own class that are not saved in the parasitic db.
unsaved_parasitics_.push_back(parasitic);
return parasitic;
}
}
return nullptr;
return parasitic;
}
ReducedParasiticType

View File

@ -99,17 +99,8 @@ DmpCeffElmoreDelayCalc::loadDelay(const Pin *load_pin,
if (drvr_parasitic_)
parasitics_->findElmore(drvr_parasitic_, load_pin, elmore, elmore_exists);
if (elmore_exists) {
if (input_port_) {
// Input port with no external driver.
if (parasitics_->isReducedParasiticNetwork(drvr_parasitic_))
dspfWireDelaySlew(load_pin, elmore, wire_delay1, load_slew1);
else {
// The elmore delay on an input port is used for the wire
// delay and the load slew is the same as the driver slew.
wire_delay1 = elmore;
load_slew1 = drvr_slew_;
}
}
if (input_port_)
dspfWireDelaySlew(load_pin, elmore, wire_delay1, load_slew1);
else
loadDelaySlew(load_pin, elmore, wire_delay1, load_slew1);
}
@ -202,57 +193,53 @@ DmpCeffTwoPoleDelayCalc::findParasitic(const Pin *drvr_pin,
const RiseFall *rf,
const DcalcAnalysisPt *dcalc_ap)
{
Parasitic *parasitic = nullptr;
const Corner *corner = dcalc_ap->corner();
// set_load has precidence over parasitics.
// set_load net has precidence over parasitics.
if (!sdc_->drvrPinHasWireCap(drvr_pin, corner)) {
Parasitic *parasitic = nullptr;
const ParasiticAnalysisPt *parasitic_ap = dcalc_ap->parasiticAnalysisPt();
if (parasitics_->haveParasitics()) {
// Prefer PiPoleResidue.
parasitic = parasitics_->findPiPoleResidue(drvr_pin, rf,
parasitic_ap);
if (parasitic)
return parasitic;
parasitic = parasitics_->findPiElmore(drvr_pin, rf, parasitic_ap);
if (parasitic)
return parasitic;
Parasitic *parasitic_network =
parasitics_->findParasiticNetwork(drvr_pin, parasitic_ap);
if (parasitic_network) {
parasitics_->reduceToPiPoleResidue2(parasitic_network, drvr_pin,
dcalc_ap->operatingConditions(),
corner,
dcalc_ap->constraintMinMax(),
parasitic_ap);
parasitic = parasitics_->findPiPoleResidue(drvr_pin, rf, parasitic_ap);
reduced_parasitic_drvrs_.push_back(drvr_pin);
return parasitic;
parasitic = parasitics_->findPiPoleResidue(drvr_pin, rf, parasitic_ap);
if (parasitic == nullptr) {
parasitic = parasitics_->findPiElmore(drvr_pin, rf, parasitic_ap);
if (parasitic == nullptr) {
Parasitic *parasitic_network =
parasitics_->findParasiticNetwork(drvr_pin, parasitic_ap);
if (parasitic_network) {
parasitics_->reduceToPiPoleResidue2(parasitic_network, drvr_pin,
dcalc_ap->operatingConditions(),
corner,
dcalc_ap->constraintMinMax(),
parasitic_ap);
parasitic = parasitics_->findPiPoleResidue(drvr_pin, rf, parasitic_ap);
reduced_parasitic_drvrs_.push_back(drvr_pin);
}
}
}
}
const MinMax *cnst_min_max = dcalc_ap->constraintMinMax();
Wireload *wireload = sdc_->wireload(cnst_min_max);
if (wireload) {
float pin_cap, wire_cap, fanout;
bool has_wire_cap;
graph_delay_calc_->netCaps(drvr_pin, rf, dcalc_ap,
pin_cap, wire_cap, fanout, has_wire_cap);
parasitic = parasitics_->estimatePiElmore(drvr_pin, rf, wireload,
fanout, pin_cap,
dcalc_ap->operatingConditions(),
corner,
cnst_min_max,
parasitic_ap);
// Estimated parasitics are not recorded in the "database", so
// it for deletion after the drvr pin delay calc is finished.
if (parasitic)
unsaved_parasitics_.push_back(parasitic);
return parasitic;
else {
const MinMax *cnst_min_max = dcalc_ap->constraintMinMax();
Wireload *wireload = sdc_->wireload(cnst_min_max);
if (wireload) {
float pin_cap, wire_cap, fanout;
bool has_wire_cap;
graph_delay_calc_->netCaps(drvr_pin, rf, dcalc_ap,
pin_cap, wire_cap, fanout, has_wire_cap);
parasitic = parasitics_->estimatePiElmore(drvr_pin, rf, wireload,
fanout, pin_cap,
dcalc_ap->operatingConditions(),
corner,
cnst_min_max,
parasitic_ap);
// Estimated parasitics are not recorded in the "database", so
// it for deletion after the drvr pin delay calc is finished.
if (parasitic)
unsaved_parasitics_.push_back(parasitic);
}
}
}
return nullptr;
return parasitic;
}
ReducedParasiticType
@ -322,14 +309,7 @@ DmpCeffTwoPoleDelayCalc::loadDelay(const Pin *load_pin,
if (input_port_) {
float elmore = 1.0F / p1;
// Input port with no external driver.
if (parasitics_->isReducedParasiticNetwork(drvr_parasitic_))
dspfWireDelaySlew(load_pin, elmore, wire_delay1, load_slew1);
else {
// For RSPF on an input port the elmore delay is used for the
// wire delay and the load slew is the same as the driver slew.
wire_delay1 = elmore;
load_slew1 = drvr_slew_;
}
dspfWireDelaySlew(load_pin, elmore, wire_delay1, load_slew1);
}
else {
if (pole_count >= 2)

View File

@ -54,7 +54,7 @@ GraphDelayCalc::incrementalDelayTolerance()
void
GraphDelayCalc::loadCap(const Pin *,
Parasitic *,
const Parasitic *,
const RiseFall *,
const DcalcAnalysisPt *,
// Return values.
@ -74,7 +74,7 @@ GraphDelayCalc::loadCap(const Pin *,
float
GraphDelayCalc::loadCap(const Pin *,
Parasitic *,
const Parasitic *,
const RiseFall *,
const DcalcAnalysisPt *) const
{

View File

@ -1062,7 +1062,7 @@ GraphDelayCalc1::loadCap(const Pin *drvr_pin,
float
GraphDelayCalc1::loadCap(const Pin *drvr_pin,
Parasitic *drvr_parasitic,
const Parasitic *drvr_parasitic,
const RiseFall *rf,
const DcalcAnalysisPt *dcalc_ap) const
{
@ -1072,7 +1072,7 @@ GraphDelayCalc1::loadCap(const Pin *drvr_pin,
float
GraphDelayCalc1::loadCap(const Pin *drvr_pin,
MultiDrvrNet *multi_drvr,
Parasitic *drvr_parasitic,
const Parasitic *drvr_parasitic,
const RiseFall *rf,
const DcalcAnalysisPt *dcalc_ap) const
{
@ -1091,7 +1091,7 @@ GraphDelayCalc1::loadCap(const Pin *drvr_pin,
void
GraphDelayCalc1::loadCap(const Pin *drvr_pin,
Parasitic *drvr_parasitic,
const Parasitic *drvr_parasitic,
const RiseFall *rf,
const DcalcAnalysisPt *dcalc_ap,
// Return values.
@ -1107,7 +1107,7 @@ GraphDelayCalc1::loadCap(const Pin *drvr_pin,
}
void
GraphDelayCalc1::loadCap(Parasitic *drvr_parasitic,
GraphDelayCalc1::loadCap(const Parasitic *drvr_parasitic,
bool has_net_load,
// Return values.
float &pin_cap,

View File

@ -59,14 +59,14 @@ public:
virtual float loadCap(const Pin *drvr_pin,
const DcalcAnalysisPt *dcalc_ap) const;
virtual void loadCap(const Pin *drvr_pin,
Parasitic *drvr_parasitic,
const Parasitic *drvr_parasitic,
const RiseFall *rf,
const DcalcAnalysisPt *dcalc_ap,
// Return values.
float &pin_cap,
float &wire_cap) const;
virtual float loadCap(const Pin *drvr_pin,
Parasitic *drvr_parasitic,
const Parasitic *drvr_parasitic,
const RiseFall *rf,
const DcalcAnalysisPt *dcalc_ap) const;
virtual void netCaps(const Pin *drvr_pin,
@ -195,14 +195,14 @@ protected:
const DcalcAnalysisPt *dcalc_ap);
bool bidirectDrvrSlewFromLoad(const Vertex *vertex) const;
MultiDrvrNet *multiDrvrNet(const Vertex *drvr_vertex) const;
void loadCap(Parasitic *drvr_parasitic,
void loadCap(const Parasitic *drvr_parasitic,
bool has_set_load,
// Return values.
float &pin_cap,
float &wire_cap) const;
float loadCap(const Pin *drvr_pin,
MultiDrvrNet *multi_drvr,
Parasitic *drvr_parasitic,
const Parasitic *drvr_parasitic,
const RiseFall *rf,
const DcalcAnalysisPt *dcalc_ap) const;

View File

@ -55,52 +55,50 @@ LumpedCapDelayCalc::findParasitic(const Pin *drvr_pin,
const RiseFall *rf,
const DcalcAnalysisPt *dcalc_ap)
{
Parasitic *parasitic = nullptr;
const Corner *corner = dcalc_ap->corner();
// set_load has precidence over parasitics.
// set_load net has precidence over parasitics.
if (!sdc_->drvrPinHasWireCap(drvr_pin, corner)) {
Parasitic *parasitic = nullptr;
const ParasiticAnalysisPt *parasitic_ap = dcalc_ap->parasiticAnalysisPt();
if (parasitics_->haveParasitics()) {
// Prefer PiElmore.
parasitic = parasitics_->findPiElmore(drvr_pin, rf, parasitic_ap);
if (parasitic)
return parasitic;
Parasitic *parasitic_network =
parasitics_->findParasiticNetwork(drvr_pin, parasitic_ap);
if (parasitic_network) {
parasitics_->reduceToPiElmore(parasitic_network, drvr_pin,
dcalc_ap->operatingConditions(),
corner,
dcalc_ap->constraintMinMax(),
parasitic_ap);
parasitic = parasitics_->findPiElmore(drvr_pin, rf, parasitic_ap);
reduced_parasitic_drvrs_.push_back(drvr_pin);
return parasitic;
if (parasitic == nullptr) {
Parasitic *parasitic_network =
parasitics_->findParasiticNetwork(drvr_pin, parasitic_ap);
if (parasitic_network) {
parasitics_->reduceToPiElmore(parasitic_network, drvr_pin,
dcalc_ap->operatingConditions(),
corner,
dcalc_ap->constraintMinMax(),
parasitic_ap);
parasitic = parasitics_->findPiElmore(drvr_pin, rf, parasitic_ap);
reduced_parasitic_drvrs_.push_back(drvr_pin);
}
}
}
const MinMax *cnst_min_max = dcalc_ap->constraintMinMax();
Wireload *wireload = sdc_->wireload(cnst_min_max);
if (wireload) {
float pin_cap, wire_cap, fanout;
bool has_wire_cap;
graph_delay_calc_->netCaps(drvr_pin, rf, dcalc_ap,
pin_cap, wire_cap, fanout, has_wire_cap);
parasitic = parasitics_->estimatePiElmore(drvr_pin, rf, wireload,
fanout, pin_cap,
dcalc_ap->operatingConditions(),
corner,
cnst_min_max,
parasitic_ap);
// Estimated parasitics are not recorded in the "database", so
// it for deletion after the drvr pin delay calc is finished.
if (parasitic)
unsaved_parasitics_.push_back(parasitic);
return parasitic;
else {
const MinMax *cnst_min_max = dcalc_ap->constraintMinMax();
Wireload *wireload = sdc_->wireload(cnst_min_max);
if (wireload) {
float pin_cap, wire_cap, fanout;
bool has_wire_cap;
graph_delay_calc_->netCaps(drvr_pin, rf, dcalc_ap,
pin_cap, wire_cap, fanout, has_wire_cap);
parasitic = parasitics_->estimatePiElmore(drvr_pin, rf, wireload,
fanout, pin_cap,
dcalc_ap->operatingConditions(),
corner,
cnst_min_max,
parasitic_ap);
// Estimated parasitics are not recorded in the "database", so save
// it for deletion after the drvr pin delay calc is finished.
if (parasitic)
unsaved_parasitics_.push_back(parasitic);
}
}
}
return nullptr;
return parasitic;
}
ReducedParasiticType

View File

@ -66,7 +66,7 @@ RCDelayCalc::dspfWireDelaySlew(const Pin *,
float vl = drvr_library_->slewLowerThreshold(drvr_rf_);
float vh = drvr_library_->slewUpperThreshold(drvr_rf_);
float slew_derate = drvr_library_->slewDerateFromLibrary();
wire_delay = static_cast<float>(-elmore * log(1.0 - vth));
wire_delay = -elmore * log(1.0 - vth);
load_slew = (drvr_slew_ + elmore * log((1.0 - vl) / (1.0 - vh))
/ slew_derate) * multi_drvr_slew_factor_;
}

View File

@ -134,14 +134,7 @@ SlewDegradeDelayCalc::loadDelay(const Pin *load_pin,
delayAsFloat(drvr_slew_),
delayAsFloat(wire_delay1));
}
else if (parasitics_->isReducedParasiticNetwork(drvr_parasitic_))
dspfWireDelaySlew(load_pin, elmore, wire_delay1, load_slew1);
else {
// For RSPF on an input port the elmore delay is used for the
// wire delay and the slew is copied from the driver.
wire_delay1 = elmore;
load_slew1 = drvr_slew_;
}
dspfWireDelaySlew(load_pin, elmore, wire_delay1, load_slew1);
}
thresholdAdjust(load_pin, wire_delay1, load_slew1);
wire_delay = wire_delay1;

View File

@ -191,7 +191,7 @@ Graph::makePortInstanceEdges(const Instance *inst,
if ((from_to_port == nullptr
|| from_port == from_to_port
|| to_port == from_to_port)
&& filterEdge(arc_set)) {
&& from_port) {
Pin *from_pin = network_->findPin(inst, from_port);
Pin *to_pin = network_->findPin(inst, to_port);
if (from_pin && to_pin) {

View File

@ -232,8 +232,6 @@ protected:
Edge *edge);
void removeDelays();
void removeDelayAnnotated(Edge *edge);
// User defined predicate to filter graph edges for liberty timing arcs.
virtual bool filterEdge(TimingArcSet *) const { return true; }
VertexTable *vertices_;
EdgeTable *edges_;

View File

@ -71,7 +71,7 @@ public:
// pin_cap = net pin capacitances + port external pin capacitance,
// wire_cap = annotated net capacitance + port external wire capacitance.
virtual void loadCap(const Pin *drvr_pin,
Parasitic *drvr_parasitic,
const Parasitic *drvr_parasitic,
const RiseFall *rf,
const DcalcAnalysisPt *dcalc_ap,
// Return values.
@ -86,7 +86,7 @@ public:
const DcalcAnalysisPt *dcalc_ap) const;
// Load pin_cap + wire_cap.
virtual float loadCap(const Pin *drvr_pin,
Parasitic *drvr_parasitic,
const Parasitic *drvr_parasitic,
const RiseFall *rf,
const DcalcAnalysisPt *dcalc_ap) const;
virtual void netCaps(const Pin *drvr_pin,

View File

@ -794,6 +794,7 @@ public:
DriverWaveform *driverWaveform(const RiseFall *rf) const;
void setDriverWaveform(DriverWaveform *driver_waveform,
const RiseFall *rf);
RiseFallMinMax clockTreePathDelays();
static bool equiv(const LibertyPort *port1,
const LibertyPort *port2);

View File

@ -110,8 +110,10 @@ public:
bool exists = exists_[mm_index];
if (exists)
return values_[mm_index];
else
else {
criticalError(226, "uninitialized value reference");
return 0.0;
}
}
void

View File

@ -38,7 +38,7 @@ public:
const ParasiticAnalysisPt *ap);
virtual void deleteDrvrReducedParasitics(const Pin *drvr_pin);
virtual float capacitance(Parasitic *parasitic) const;
virtual float capacitance(const Parasitic *parasitic) const;
virtual Parasitic *
findPiElmore(const Pin *drvr_pin,
@ -91,7 +91,7 @@ public:
virtual void poleResidue(const Parasitic *parasitic, int pole_index,
ComplexFloat &pole, ComplexFloat &residue) const;
virtual bool isParasiticNetwork(Parasitic *parasitic) const;
virtual bool isParasiticNetwork(const Parasitic *parasitic) const;
virtual Parasitic *findParasiticNetwork(const Net *net,
const ParasiticAnalysisPt *ap) const;
virtual Parasitic *
@ -101,9 +101,9 @@ public:
makeParasiticNetwork(const Net *net,
bool pin_cap_included,
const ParasiticAnalysisPt *ap);
virtual ParasiticDeviceIterator *deviceIterator(Parasitic *) { return nullptr; }
virtual ParasiticNodeIterator *nodeIterator(Parasitic *) { return nullptr; }
virtual bool includesPinCaps(Parasitic *parasitic) const;
virtual ParasiticDeviceIterator *deviceIterator(const Parasitic *) { return nullptr; }
virtual ParasiticNodeIterator *nodeIterator(const Parasitic *) { return nullptr; }
virtual bool includesPinCaps(const Parasitic *parasitic) const;
virtual void deleteParasiticNetwork(const Net *net,
const ParasiticAnalysisPt *ap);
virtual void deleteParasiticNetworks(const Net *net);
@ -132,7 +132,7 @@ public:
virtual const char *name(const ParasiticNode *node);
virtual const Pin *connectionPin(const ParasiticNode *node) const;
virtual ParasiticNode *findNode(Parasitic *parasitic,
virtual ParasiticNode *findNode(const Parasitic *parasitic,
const Pin *pin) const;
virtual float nodeGndCap(const ParasiticNode *node,
const ParasiticAnalysisPt *ap) const;
@ -148,33 +148,33 @@ public:
virtual ParasiticNode *otherNode(const ParasiticDevice *device,
ParasiticNode *node) const;
// Reduce parasitic network to reduce_to model.
virtual void reduceTo(Parasitic *parasitic,
virtual void reduceTo(const Parasitic *parasitic,
const Net *net,
ReducedParasiticType reduce_to,
const OperatingConditions *op_cond,
const Corner *corner,
const MinMax *cnst_min_max,
const ParasiticAnalysisPt *ap);
virtual void reduceToPiElmore(Parasitic *parasitic,
virtual void reduceToPiElmore(const Parasitic *parasitic,
const Net *net,
const OperatingConditions *op_cond,
const Corner *corner,
const MinMax *cnst_min_max,
const ParasiticAnalysisPt *ap);
// Reduce parasitic network to pi elmore model for drvr_pin.
virtual void reduceToPiElmore(Parasitic *parasitic,
virtual void reduceToPiElmore(const Parasitic *parasitic,
const Pin *drvr_pin,
const OperatingConditions *op_cond,
const Corner *corner,
const MinMax *cnst_min_max,
const ParasiticAnalysisPt *ap);
virtual void reduceToPiPoleResidue2(Parasitic *parasitic,
virtual void reduceToPiPoleResidue2(const Parasitic *parasitic,
const Net *net,
const OperatingConditions *op_cond,
const Corner *corner,
const MinMax *cnst_min_max,
const ParasiticAnalysisPt *ap);
virtual void reduceToPiPoleResidue2(Parasitic *parasitic,
virtual void reduceToPiPoleResidue2(const Parasitic *parasitic,
const Pin *drvr_pin,
const OperatingConditions *op_cond,
const Corner *corner,

View File

@ -71,7 +71,7 @@ public:
bool is_reduced) = 0;
// Capacitance value of parasitic object.
virtual float capacitance(Parasitic *parasitic) const = 0;
virtual float capacitance(const Parasitic *parasitic) const = 0;
////////////////////////////////////////////////////////////////
// Pi model driver load with elmore delays to load pins (RSPF).
@ -145,7 +145,7 @@ public:
// 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;
virtual bool isParasiticNetwork(const Parasitic *parasitic) const = 0;
virtual Parasitic *findParasiticNetwork(const Net *net,
const ParasiticAnalysisPt *ap) const = 0;
virtual Parasitic *findParasiticNetwork(const Pin *pin,
@ -153,14 +153,14 @@ public:
virtual Parasitic *makeParasiticNetwork(const Net *net,
bool includes_pin_caps,
const ParasiticAnalysisPt *ap) = 0;
virtual ParasiticDeviceIterator *deviceIterator(Parasitic *parasitic) = 0;
virtual ParasiticNodeIterator *nodeIterator(Parasitic *parasitic) = 0;
virtual ParasiticDeviceIterator *deviceIterator(const Parasitic *parasitic) = 0;
virtual ParasiticNodeIterator *nodeIterator(const Parasitic *parasitic) = 0;
// Delete parasitic network if it exists.
virtual void deleteParasiticNetwork(const Net *net,
const ParasiticAnalysisPt *ap) = 0;
virtual void deleteParasiticNetworks(const Net *net) = 0;
// True if the parasitic network caps include pin capacitances.
virtual bool includesPinCaps(Parasitic *parasitic) const = 0;
virtual bool includesPinCaps(const Parasitic *parasitic) const = 0;
// Parasitic network component builders.
// Make a subnode of the parasitic network net.
virtual ParasiticNode *ensureParasiticNode(Parasitic *parasitic,
@ -207,7 +207,7 @@ public:
virtual const char *name(const ParasiticNode *node) = 0;
virtual const Pin *connectionPin(const ParasiticNode *node) const = 0;
// Find the parasitic node connected to pin.
virtual ParasiticNode *findNode(Parasitic *parasitic,
virtual ParasiticNode *findNode(const Parasitic *parasitic,
const Pin *pin) const = 0;
// Node capacitance to ground.
virtual float nodeGndCap(const ParasiticNode *node,
@ -235,7 +235,7 @@ public:
const Pin *drvr_pin) = 0;
// Reduce parasitic network to reduce_to model.
virtual void reduceTo(Parasitic *parasitic,
virtual void reduceTo(const Parasitic *parasitic,
const Net *net,
ReducedParasiticType reduce_to,
const OperatingConditions *op_cond,
@ -243,21 +243,21 @@ public:
const MinMax *cnst_min_max,
const ParasiticAnalysisPt *ap) = 0;
// Reduce parasitic network to pi elmore models.
virtual void reduceToPiElmore(Parasitic *parasitic,
virtual void reduceToPiElmore(const Parasitic *parasitic,
const Net *net,
const OperatingConditions *op_cond,
const Corner *corner,
const MinMax *cnst_min_max,
const ParasiticAnalysisPt *ap) = 0;
// Reduce parasitic network to pi elmore model for drvr_pin.
virtual void reduceToPiElmore(Parasitic *parasitic,
virtual void reduceToPiElmore(const Parasitic *parasitic,
const Pin *drvr_pin,
const OperatingConditions *op_cond,
const Corner *corner,
const MinMax *cnst_min_max,
const ParasiticAnalysisPt *ap) = 0;
// Reduce parasitic network to pi and 2nd order pole/residue models.
virtual void reduceToPiPoleResidue2(Parasitic *parasitic,
virtual void reduceToPiPoleResidue2(const Parasitic *parasitic,
const Net *net,
const OperatingConditions *op_cond,
const Corner *corner,
@ -265,7 +265,7 @@ public:
const ParasiticAnalysisPt *ap) = 0;
// Reduce parasitic network to pi and 2nd order pole/residue models
// for drvr_pin.
virtual void reduceToPiPoleResidue2(Parasitic *parasitic,
virtual void reduceToPiPoleResidue2(const Parasitic *parasitic,
const Pin *drvr_pin,
const OperatingConditions *op_cond,
const Corner *corner,

View File

@ -23,6 +23,7 @@
#include "Map.hh"
#include "UnorderedMap.hh"
#include "StringSet.hh"
#include "MinMaxValues.hh"
#include "Delay.hh"
#include "NetworkClass.hh"
#include "GraphClass.hh"
@ -113,6 +114,7 @@ typedef Vector<PathVertex> PathVertexSeq;
typedef Vector<Slack> SlackSeq;
typedef Delay Crpr;
typedef Vector<PathRef> PathRefSeq;
typedef MinMaxValues<float> ClkDelays[RiseFall::index_count][RiseFall::index_count];
enum class ReportPathFormat { full,
full_clock,

View File

@ -900,12 +900,6 @@ public:
void setReportPathDigits(int digits);
void setReportPathNoSplit(bool no_split);
void setReportPathSigmas(bool report_sigmas);
// Report clk skews for clks.
void reportClkSkew(ClockSet *clks,
const Corner *corner,
const SetupHold *setup_hold,
int digits);
float findWorstClkSkew(const SetupHold *setup_hold);
// Header above reportPathEnd results.
void reportPathEndHeader();
// Footer below reportPathEnd results.
@ -919,6 +913,18 @@ public:
void reportPathEnds(PathEndSeq *ends);
ReportPath *reportPath() { return report_path_; }
void reportPath(Path *path);
// Report clk skews for clks.
void reportClkSkew(ClockSet *clks,
const Corner *corner,
const SetupHold *setup_hold,
int digits);
float findWorstClkSkew(const SetupHold *setup_hold);
// Find min/max/rise/fall delays for clk.
void findClkDelays(const Clock *clk,
// Return values.
ClkDelays &delays);
// Update arrival times for all pins.
// If necessary updateTiming propagates arrivals around latch
// loops until the arrivals converge.

View File

@ -201,7 +201,7 @@ public:
TableModel(TablePtr table,
TableTemplate *tbl_template,
ScaleFactorType scale_factor_type,
RiseFall *rf);
const RiseFall *rf);
void setScaleFactorType(ScaleFactorType type);
int order() const;
TableTemplate *tblTemplate() const { return tbl_template_; }

View File

@ -105,8 +105,8 @@ public:
void setModeName(const char *name);
const char *modeValue() const { return mode_value_; }
void setModeValue(const char *value);
TimingModel *model(RiseFall *rf) const;
void setModel(RiseFall *rf,
TimingModel *model(const RiseFall *rf) const;
void setModel(const RiseFall *rf,
TimingModel *model);
float ocvArcDepth() const { return ocv_arc_depth_; }
void setOcvArcDepth(float depth);

View File

@ -59,6 +59,8 @@ public:
static TimingRole *dataCheckHold() { return data_check_hold_; }
static TimingRole *nonSeqSetup() { return non_seq_setup_; }
static TimingRole *nonSeqHold() { return non_seq_hold_; }
static TimingRole *clockTreePathMin() { return clock_tree_path_min_; }
static TimingRole *clockTreePathMax() { return clock_tree_path_max_; }
const char *asString() const { return name_; }
int index() const { return index_; }
bool isWire() const;
@ -125,6 +127,8 @@ private:
static TimingRole *data_check_hold_;
static TimingRole *non_seq_setup_;
static TimingRole *non_seq_hold_;
static TimingRole *clock_tree_path_min_;
static TimingRole *clock_tree_path_max_;
static TimingRoleMap timing_roles_;
friend class TimingRoleLess;

View File

@ -55,9 +55,9 @@ public:
RiseFall *opposite() const;
// for range support.
// for (auto tr : RiseFall::range()) {}
// for (auto rf : RiseFall::range()) {}
static const std::array<RiseFall*, 2> &range() { return range_; }
// for (auto tr_index : RiseFall::rangeIndex()) {}
// for (auto rf_index : RiseFall::rangeIndex()) {}
static const std::array<int, 2> &rangeIndex() { return range_index_; }
static const int index_count = 2;
static const int index_max = (index_count - 1);

View File

@ -2352,15 +2352,16 @@ bool
LibertyPort::less(const LibertyPort *port1,
const LibertyPort *port2)
{
if (port1 == nullptr && port2 != nullptr)
return true;
if (port1 != nullptr && port2 == nullptr)
return false;
const char *name1 = port1->name();
const char *name2 = port2->name();
if (stringEq(name1, name2)) {
PortDirection *dir1 = port1->direction();
PortDirection *dir2 = port2->direction();
if (dir1 == dir2) {
}
else
return dir1->index() < dir2->index();
return dir1->index() < dir2->index();
}
return stringLess(name1, name2);
}
@ -2565,6 +2566,33 @@ LibertyPort::setDriverWaveform(DriverWaveform *driver_waveform,
driver_waveform_[rf->index()] = driver_waveform;
}
RiseFallMinMax
LibertyPort::clockTreePathDelays()
{
RiseFallMinMax delays;
const TimingArcSetSeq &arc_sets = liberty_cell_->timingArcSets(nullptr, this);
for (TimingArcSet *arc_set : arc_sets) {
TimingRole *role = arc_set->role();
if (role == TimingRole::clockTreePathMin()
|| role == TimingRole::clockTreePathMax()) {
for (TimingArc *arc : arc_set->arcs()) {
TimingModel *model = arc->model();
GateTimingModel *gate_model = dynamic_cast<GateTimingModel*>(model);
ArcDelay delay;
Slew slew;
gate_model->gateDelay(liberty_cell_, nullptr, 0.0, 0.0, 0.0, false,
delay, slew);
const RiseFall *rf = arc->toEdge()->asRiseFall();
const MinMax *min_max = (role == TimingRole::clockTreePathMin())
? MinMax::min()
: MinMax::max();
delays.setValue(rf, min_max, delay);
}
}
}
return delays;
}
////////////////////////////////////////////////////////////////
LibertyPortSeq
@ -2588,8 +2616,8 @@ bool
LibertyPortPairLess::operator()(const LibertyPortPair &pair1,
const LibertyPortPair &pair2) const
{
ObjectId id1 = pair1.first->id();
ObjectId id2 = pair2.first->id();
ObjectId id1 = pair1.first ? pair1.first->id() : 0;
ObjectId id2 = pair2.first ? pair2.first->id() : 0;
return id1 < id2
|| (id1 == id2
&& pair1.second->id() < pair2.second->id());

View File

@ -281,6 +281,14 @@ LibertyBuilder::makeTimingArcs(LibertyCell *cell,
RiseFall::fall(),
TimingRole::nonSeqHold(),
attrs);
case TimingType::min_clock_tree_path:
return makeClockTreePathArcs(cell, to_port, related_out,
TimingRole::clockTreePathMin(),
attrs);
case TimingType::max_clock_tree_path:
return makeClockTreePathArcs(cell, to_port, related_out,
TimingRole::clockTreePathMax(),
attrs);
case TimingType::min_pulse_width:
case TimingType::minimum_period:
case TimingType::nochange_high_high:
@ -289,8 +297,6 @@ LibertyBuilder::makeTimingArcs(LibertyCell *cell,
case TimingType::nochange_low_low:
case TimingType::retaining_time:
case TimingType::unknown:
case TimingType::min_clock_tree_path:
case TimingType::max_clock_tree_path:
return nullptr;
}
// Prevent warnings from lame compilers.
@ -647,6 +653,23 @@ LibertyBuilder::makeTristateDisableArcs(LibertyCell *cell,
return arc_set;
}
TimingArcSet *
LibertyBuilder::makeClockTreePathArcs(LibertyCell *cell,
LibertyPort *to_port,
LibertyPort *related_out,
TimingRole *role,
TimingArcAttrsPtr attrs)
{
TimingArcSet *arc_set = makeTimingArcSet(cell, nullptr, to_port,
related_out, role, attrs);
for (auto to_rf : RiseFall::range()) {
TimingModel *model = attrs->model(to_rf);
if (model)
makeTimingArc(arc_set, nullptr, to_rf, model);
}
return arc_set;
}
TimingArcSet *
LibertyBuilder::makeTimingArcSet(LibertyCell *cell,
LibertyPort *from,

View File

@ -79,6 +79,11 @@ public:
bool to_rise,
bool to_fall,
TimingArcAttrsPtr attrs);
TimingArcSet *makeClockTreePathArcs(LibertyCell *cell,
LibertyPort *to_port,
LibertyPort *related_out,
TimingRole *role,
TimingArcAttrsPtr attrs);
protected:
ConcretePort *makeBusPort(const char *name,

View File

@ -2195,6 +2195,8 @@ LibertyReader::makeTimingArcs(LibertyPort *to_port,
}
}
}
else
makeTimingArcs(to_port, related_out_port, timing);
}
void
@ -2363,6 +2365,26 @@ LibertyReader::makeTimingArcs(const char *from_port_name,
}
}
void
LibertyReader::makeTimingArcs(LibertyPort *to_port,
LibertyPort *related_out_port,
TimingGroup *timing)
{
if (to_port->hasMembers()) {
LibertyPortMemberIterator bit_iter(to_port);
while (bit_iter.hasNext()) {
LibertyPort *to_port_bit = bit_iter.next();
builder_.makeTimingArcs(cell_, nullptr, to_port_bit,
related_out_port, timing->attrs(),
timing->line());
}
}
else
builder_.makeTimingArcs(cell_, nullptr, to_port,
related_out_port, timing->attrs(),
timing->line());
}
////////////////////////////////////////////////////////////////
void

View File

@ -178,6 +178,9 @@ public:
LibertyPort *to_port,
LibertyPort *related_out_port,
TimingGroup *timing);
virtual void makeTimingArcs(LibertyPort *to_port,
LibertyPort *related_out_port,
TimingGroup *timing);
virtual void visitClockGatingIntegratedCell(LibertyAttr *attr);
virtual void visitArea(LibertyAttr *attr);

View File

@ -364,7 +364,8 @@ void
LibertyWriter::writeTimingArcSet(const TimingArcSet *arc_set)
{
fprintf(stream_, " timing() {\n");
fprintf(stream_, " related_pin : \"%s\";\n", arc_set->from()->name());
if (arc_set->from())
fprintf(stream_, " related_pin : \"%s\";\n", arc_set->from()->name());
TimingSense sense = arc_set->sense();
if (sense != TimingSense::unknown
&& sense != TimingSense::non_unate)
@ -398,11 +399,14 @@ LibertyWriter::writeTimingModels(const TimingArc *arc,
fprintf(stream_, " }\n");
const TableModel *slew_model = gate_model->slewModel();
template_name = slew_model->tblTemplate()->name();
fprintf(stream_, " %s_transition(%s) {\n", rf->name(), template_name);
writeTableModel(slew_model);
fprintf(stream_, " }\n");
} else if (check_model) {
if (slew_model) {
template_name = slew_model->tblTemplate()->name();
fprintf(stream_, " %s_transition(%s) {\n", rf->name(), template_name);
writeTableModel(slew_model);
fprintf(stream_, " }\n");
}
}
else if (check_model) {
const TableModel *model = check_model->model();
const char *template_name = model->tblTemplate()->name();
fprintf(stream_, " %s_constraint(%s) {\n", rf->name(), template_name);
@ -569,11 +573,15 @@ LibertyWriter::timingTypeString(const TimingArcSet *arc_set)
else
return "non_seq_hold_falling";
}
else if (role == TimingRole::clockTreePathMin())
return "min_clock_tree_path";
else if (role == TimingRole::clockTreePathMax())
return "max_clock_tree_path";
else {
report_->error(703, "%s/%s/%s timing arc type %s not supported.",
library_->name(),
arc_set->from()->libertyCell()->name(),
arc_set->from()->name(),
arc_set->to()->libertyCell()->name(),
arc_set->to()->name(),
role->asString());
return nullptr;
}

View File

@ -611,7 +611,7 @@ CheckTableModel::checkAxis(TableAxisPtr axis)
TableModel::TableModel(TablePtr table,
TableTemplate *tbl_template,
ScaleFactorType scale_factor_type,
RiseFall *rf) :
const RiseFall *rf) :
table_(table),
tbl_template_(tbl_template),
scale_factor_type_(int(scale_factor_type)),

View File

@ -127,13 +127,13 @@ TimingArcAttrs::setModeValue(const char *value)
}
TimingModel *
TimingArcAttrs::model(RiseFall *rf) const
TimingArcAttrs::model(const RiseFall *rf) const
{
return models_[rf->index()];
}
void
TimingArcAttrs::setModel(RiseFall *rf,
TimingArcAttrs::setModel(const RiseFall *rf,
TimingModel *model)
{
models_[rf->index()] = model;

View File

@ -45,6 +45,8 @@ TimingRole *TimingRole::data_check_setup_;
TimingRole *TimingRole::data_check_hold_;
TimingRole *TimingRole::non_seq_setup_;
TimingRole *TimingRole::non_seq_hold_;
TimingRole *TimingRole::clock_tree_path_min_;
TimingRole *TimingRole::clock_tree_path_max_;
TimingRoleMap TimingRole::timing_roles_;
@ -111,6 +113,10 @@ TimingRole::init()
MinMax::max(), TimingRole::setup(), 25);
non_seq_hold_ = new TimingRole("non-sequential hold", false, true, true,
MinMax::min(), TimingRole::hold(), 26);
clock_tree_path_min_ = new TimingRole("min clock tree path", false, false, false,
MinMax::min(), nullptr, 27);
clock_tree_path_max_ = new TimingRole("max clock tree path", false, false, false,
MinMax::max(), nullptr, 28);
}
void

View File

@ -131,13 +131,13 @@ ConcreteParasitic::setPoleResidue(const Pin *,
}
ParasiticDeviceIterator *
ConcreteParasitic::deviceIterator()
ConcreteParasitic::deviceIterator() const
{
return nullptr;
}
ParasiticNodeIterator *
ConcreteParasitic::nodeIterator()
ConcreteParasitic::nodeIterator() const
{
return nullptr;
}
@ -688,15 +688,15 @@ ConcreteParasiticNetwork::deleteDevices()
}
ParasiticNodeIterator *
ConcreteParasiticNetwork::nodeIterator()
ConcreteParasiticNetwork::nodeIterator() const
{
ConcreteParasiticNodeSeq *nodes = new ConcreteParasiticNodeSeq();
ConcreteParasiticPinNodeMap::Iterator node_iter2(pin_nodes_);
ConcreteParasiticPinNodeMap::ConstIterator node_iter2(pin_nodes_);
while (node_iter2.hasNext()) {
ConcreteParasiticPinNode *node = node_iter2.next();
nodes->push_back(node);
}
ConcreteParasiticSubNodeMap::Iterator node_iter1(sub_nodes_);
ConcreteParasiticSubNodeMap::ConstIterator node_iter1(sub_nodes_);
while (node_iter1.hasNext()) {
ConcreteParasiticSubNode *node = node_iter1.next();
nodes->push_back(node);
@ -705,7 +705,7 @@ ConcreteParasiticNetwork::nodeIterator()
}
ParasiticDeviceIterator *
ConcreteParasiticNetwork::deviceIterator()
ConcreteParasiticNetwork::deviceIterator() const
{
ConcreteParasiticDeviceSet *devices1 = new ConcreteParasiticDeviceSet();
devices(devices1);
@ -713,11 +713,11 @@ ConcreteParasiticNetwork::deviceIterator()
}
void
ConcreteParasiticNetwork::devices(ConcreteParasiticDeviceSet *devices)
ConcreteParasiticNetwork::devices(ConcreteParasiticDeviceSet *devices) const
{
// 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_);
ConcreteParasiticSubNodeMap::ConstIterator node_iter1(sub_nodes_);
while (node_iter1.hasNext()) {
ConcreteParasiticSubNode *node = node_iter1.next();
ConcreteParasiticDeviceSeq::Iterator device_iter(node->devices());
@ -727,10 +727,10 @@ ConcreteParasiticNetwork::devices(ConcreteParasiticDeviceSet *devices)
}
}
ConcreteParasiticPinNodeMap::Iterator node_iter2(pin_nodes_);
ConcreteParasiticPinNodeMap::ConstIterator node_iter2(pin_nodes_);
while (node_iter2.hasNext()) {
ConcreteParasiticPinNode *node = node_iter2.next();
ConcreteParasiticDeviceSeq::Iterator device_iter(node->devices());
ConcreteParasiticDeviceSeq::ConstIterator device_iter(node->devices());
while (device_iter.hasNext()) {
ConcreteParasiticDevice *device = device_iter.next();
devices->insert(device);
@ -771,7 +771,7 @@ ConcreteParasiticNetwork::ensureParasiticNode(const Net *net,
}
ConcreteParasiticNode *
ConcreteParasiticNetwork::findNode(const Pin *pin)
ConcreteParasiticNetwork::findNode(const Pin *pin) const
{
return pin_nodes_.findKey(pin);
}
@ -928,9 +928,9 @@ ConcreteParasitics::save()
}
float
ConcreteParasitics::capacitance(Parasitic *parasitic) const
ConcreteParasitics::capacitance(const Parasitic *parasitic) const
{
ConcreteParasitic *cparasitic = static_cast<ConcreteParasitic*>(parasitic);
const ConcreteParasitic *cparasitic = static_cast<const ConcreteParasitic*>(parasitic);
return cparasitic->capacitance();
}
@ -1273,9 +1273,9 @@ ConcreteParasitics::poleResidue(const Parasitic *parasitic,
////////////////////////////////////////////////////////////////
bool
ConcreteParasitics::isParasiticNetwork(Parasitic *parasitic) const
ConcreteParasitics::isParasiticNetwork(const Parasitic *parasitic) const
{
ConcreteParasitic *cparasitic = static_cast<ConcreteParasitic*>(parasitic);
const ConcreteParasitic *cparasitic = static_cast<const ConcreteParasitic*>(parasitic);
return cparasitic && cparasitic->isParasiticNetwork();
}
@ -1373,10 +1373,10 @@ ConcreteParasitics::deleteParasiticNetworks(const Net *net)
}
bool
ConcreteParasitics::includesPinCaps(Parasitic *parasitic) const
ConcreteParasitics::includesPinCaps(const Parasitic *parasitic) const
{
ConcreteParasiticNetwork *cparasitic =
static_cast<ConcreteParasiticNetwork*>(parasitic);
const ConcreteParasiticNetwork *cparasitic =
static_cast<const ConcreteParasiticNetwork*>(parasitic);
return cparasitic->includesPinCaps();
}
@ -1468,16 +1468,16 @@ ConcreteParasitics::makeResistor(const char *name,
}
ParasiticDeviceIterator *
ConcreteParasitics::deviceIterator(Parasitic *parasitic)
ConcreteParasitics::deviceIterator(const Parasitic *parasitic)
{
ConcreteParasitic *cparasitic = static_cast<ConcreteParasitic*>(parasitic);
const ConcreteParasitic *cparasitic = static_cast<const ConcreteParasitic*>(parasitic);
return cparasitic->deviceIterator();
}
ParasiticNodeIterator *
ConcreteParasitics::nodeIterator(Parasitic *parasitic)
ConcreteParasitics::nodeIterator(const Parasitic *parasitic)
{
ConcreteParasitic *cparasitic = static_cast<ConcreteParasitic*>(parasitic);
const ConcreteParasitic *cparasitic = static_cast<const ConcreteParasitic*>(parasitic);
return cparasitic->nodeIterator();
}
@ -1513,11 +1513,11 @@ ConcreteParasitics::connectionPin(const ParasiticNode *node) const
}
ParasiticNode *
ConcreteParasitics::findNode(Parasitic *parasitic,
ConcreteParasitics::findNode(const Parasitic *parasitic,
const Pin *pin) const
{
ConcreteParasiticNetwork *cparasitic =
static_cast<ConcreteParasiticNetwork*>(parasitic);
const ConcreteParasiticNetwork *cparasitic =
static_cast<const ConcreteParasiticNetwork*>(parasitic);
return cparasitic->findNode(pin);
}
@ -1674,7 +1674,7 @@ ConcreteParasitics::checkAnnotation2(const Pin *drvr_pin,
////////////////////////////////////////////////////////////////
void
ConcreteParasitics::reduceTo(Parasitic *parasitic,
ConcreteParasitics::reduceTo(const Parasitic *parasitic,
const Net *net,
ReducedParasiticType reduce_to,
const OperatingConditions *op_cond,
@ -1697,7 +1697,7 @@ ConcreteParasitics::reduceTo(Parasitic *parasitic,
}
void
ConcreteParasitics::reduceToPiElmore(Parasitic *parasitic,
ConcreteParasitics::reduceToPiElmore(const Parasitic *parasitic,
const Net *net,
const OperatingConditions *op_cond,
const Corner *corner,
@ -1718,7 +1718,7 @@ ConcreteParasitics::reduceToPiElmore(Parasitic *parasitic,
}
void
ConcreteParasitics::reduceToPiElmore(Parasitic *parasitic,
ConcreteParasitics::reduceToPiElmore(const Parasitic *parasitic,
const Pin *drvr_pin,
const OperatingConditions *op_cond,
const Corner *corner,
@ -1730,7 +1730,7 @@ ConcreteParasitics::reduceToPiElmore(Parasitic *parasitic,
}
void
ConcreteParasitics::reduceToPiPoleResidue2(Parasitic *parasitic,
ConcreteParasitics::reduceToPiPoleResidue2(const Parasitic *parasitic,
const Net *net,
const OperatingConditions *op_cond,
const Corner *corner,
@ -1750,7 +1750,7 @@ ConcreteParasitics::reduceToPiPoleResidue2(Parasitic *parasitic,
}
void
ConcreteParasitics::reduceToPiPoleResidue2(Parasitic *parasitic,
ConcreteParasitics::reduceToPiPoleResidue2(const Parasitic *parasitic,
const Pin *drvr_pin,
const OperatingConditions *op_cond,
const Corner *corner,

View File

@ -59,7 +59,7 @@ public:
virtual void setIsReducedParasiticNetwork(Parasitic *parasitic,
bool is_reduced);
virtual float capacitance(Parasitic *parasitic) const;
virtual float capacitance(const Parasitic *parasitic) const;
virtual bool isPiElmore(const Parasitic *parasitic) const;
virtual Parasitic *findPiElmore(const Pin *drvr_pin,
@ -108,7 +108,7 @@ public:
virtual void poleResidue(const Parasitic *parasitic, int pole_index,
ComplexFloat &pole, ComplexFloat &residue) const;
virtual bool isParasiticNetwork(Parasitic *parasitic) const;
virtual bool isParasiticNetwork(const Parasitic *parasitic) const;
virtual Parasitic *findParasiticNetwork(const Net *net,
const ParasiticAnalysisPt *ap) const;
virtual Parasitic *findParasiticNetwork(const Pin *pin,
@ -119,7 +119,7 @@ public:
virtual void deleteParasiticNetwork(const Net *net,
const ParasiticAnalysisPt *ap);
virtual void deleteParasiticNetworks(const Net *net);
virtual bool includesPinCaps(Parasitic *parasitic) const;
virtual bool includesPinCaps(const Parasitic *parasitic) const;
virtual ParasiticNode *ensureParasiticNode(Parasitic *parasitic,
const Net *net,
int id);
@ -142,12 +142,13 @@ 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 ParasiticDeviceIterator *deviceIterator(const Parasitic *parasitic);
virtual ParasiticNodeIterator *nodeIterator(const Parasitic *parasitic);
virtual const char *name(const ParasiticNode *node);
virtual const Pin *connectionPin(const ParasiticNode *node) const;
virtual ParasiticNode *findNode(Parasitic *parasitic, const Pin *pin) const;
virtual ParasiticNode *findNode(const Parasitic *parasitic,
const Pin *pin) const;
virtual float nodeGndCap(const ParasiticNode *node,
const ParasiticAnalysisPt *ap) const;
virtual ParasiticDeviceIterator *
@ -183,32 +184,32 @@ public:
virtual void disconnectPinBefore(const Pin *pin);
virtual void loadPinCapacitanceChanged(const Pin *pin);
virtual void reduceTo(Parasitic *parasitic,
virtual void reduceTo(const Parasitic *parasitic,
const Net *net,
ReducedParasiticType reduce_to,
const OperatingConditions *op_cond,
const Corner *corner,
const MinMax *cnst_min_max,
const ParasiticAnalysisPt *ap);
virtual void reduceToPiElmore(Parasitic *parasitic,
virtual void reduceToPiElmore(const Parasitic *parasitic,
const Net *net,
const OperatingConditions *op_cond,
const Corner *corner,
const MinMax *cnst_min_max,
const ParasiticAnalysisPt *ap);
virtual void reduceToPiElmore(Parasitic *parasitic,
virtual void reduceToPiElmore(const Parasitic *parasitic,
const Pin *drvr_pin,
const OperatingConditions *op_cond,
const Corner *corner,
const MinMax *cnst_min_max,
const ParasiticAnalysisPt *ap);
virtual void reduceToPiPoleResidue2(Parasitic *parasitic,
virtual void reduceToPiPoleResidue2(const Parasitic *parasitic,
const Net *net,
const OperatingConditions *op_cond,
const Corner *corner,
const MinMax *cnst_min_max,
const ParasiticAnalysisPt *ap);
virtual void reduceToPiPoleResidue2(Parasitic *parasitic,
virtual void reduceToPiPoleResidue2(const Parasitic *parasitic,
const Pin *drvr_pin,
const OperatingConditions *op_cond,
const Corner *corner,

View File

@ -78,8 +78,8 @@ public:
virtual void setPoleResidue(const Pin *load_pin,
ComplexFloatSeq *poles,
ComplexFloatSeq *residues);
virtual ParasiticDeviceIterator *deviceIterator();
virtual ParasiticNodeIterator *nodeIterator();
virtual ParasiticDeviceIterator *deviceIterator() const;
virtual ParasiticNodeIterator *nodeIterator() const;
};
// Pi model for a driver pin.
@ -407,17 +407,17 @@ public:
bool includesPinCaps() const { return includes_pin_caps_; }
ConcreteParasiticNode *ensureParasiticNode(const Net *net,
int id);
ConcreteParasiticNode *findNode(const Pin *pin);
ConcreteParasiticNode *findNode(const Pin *pin) const;
ConcreteParasiticNode *ensureParasiticNode(const Pin *pin);
virtual float capacitance() const;
ConcreteParasiticPinNodeMap *pinNodes() { return &pin_nodes_; }
ConcreteParasiticSubNodeMap *subNodes() { return &sub_nodes_; }
void disconnectPin(const Pin *pin,
const Net *net);
virtual ParasiticDeviceIterator *deviceIterator();
virtual ParasiticNodeIterator *nodeIterator();
virtual ParasiticDeviceIterator *deviceIterator() const;
virtual ParasiticNodeIterator *nodeIterator() const;
virtual void devices(// Return value.
ConcreteParasiticDeviceSet *devices);
ConcreteParasiticDeviceSet *devices) const;
private:
void deleteNodes();

View File

@ -72,7 +72,7 @@ NullParasitics::deleteDrvrReducedParasitics(const Pin *)
}
float
NullParasitics::capacitance(Parasitic *) const
NullParasitics::capacitance(const Parasitic *) const
{
return 0.0;
}
@ -212,7 +212,7 @@ NullParasitics::poleResidue(const Parasitic *,
}
bool
NullParasitics::isParasiticNetwork(Parasitic *) const
NullParasitics::isParasiticNetwork(const Parasitic *) const
{
return false;
}
@ -240,7 +240,7 @@ NullParasitics::makeParasiticNetwork(const Net *,
}
bool
NullParasitics::includesPinCaps(Parasitic *) const
NullParasitics::includesPinCaps(const Parasitic *) const
{
return false;
}
@ -327,7 +327,7 @@ NullParasitics::connectionPin(const ParasiticNode *) const
}
ParasiticNode *
NullParasitics::findNode(Parasitic *,
NullParasitics::findNode(const Parasitic *,
const Pin *) const
{
return nullptr;
@ -391,7 +391,7 @@ NullParasitics::otherNode(const ParasiticDevice *,
}
void
NullParasitics::reduceTo(Parasitic *,
NullParasitics::reduceTo(const Parasitic *,
const Net *,
ReducedParasiticType ,
const OperatingConditions *,
@ -402,7 +402,7 @@ NullParasitics::reduceTo(Parasitic *,
}
void
NullParasitics::reduceToPiElmore(Parasitic *,
NullParasitics::reduceToPiElmore(const Parasitic *,
const Net *,
const OperatingConditions *,
const Corner *,
@ -412,7 +412,7 @@ NullParasitics::reduceToPiElmore(Parasitic *,
}
void
NullParasitics::reduceToPiElmore(Parasitic *,
NullParasitics::reduceToPiElmore(const Parasitic *,
const Pin *,
const OperatingConditions *,
const Corner *,
@ -422,7 +422,7 @@ NullParasitics::reduceToPiElmore(Parasitic *,
}
void
NullParasitics::reduceToPiPoleResidue2(Parasitic *, const Net *,
NullParasitics::reduceToPiPoleResidue2(const Parasitic *, const Net *,
const OperatingConditions *,
const Corner *,
const MinMax *,
@ -431,7 +431,7 @@ NullParasitics::reduceToPiPoleResidue2(Parasitic *, const Net *,
}
void
NullParasitics::reduceToPiPoleResidue2(Parasitic *,
NullParasitics::reduceToPiPoleResidue2(const Parasitic *,
const Pin *,
const OperatingConditions *,
const Corner *,

View File

@ -280,7 +280,7 @@ class ReduceToPiElmore : public ReduceToPi
{
public:
ReduceToPiElmore(StaState *sta);
void makePiElmore(Parasitic *parasitic_network,
void makePiElmore(const Parasitic *parasitic_network,
const Pin *drvr_pin,
ParasiticNode *drvr_node,
float coupling_cap_factor,
@ -298,7 +298,7 @@ public:
};
void
reduceToPiElmore(Parasitic *parasitic_network,
reduceToPiElmore(const Parasitic *parasitic_network,
const Pin *drvr_pin,
float coupling_cap_factor,
const OperatingConditions *op_cond,
@ -332,7 +332,7 @@ ReduceToPiElmore::ReduceToPiElmore(StaState *sta) :
}
void
ReduceToPiElmore::makePiElmore(Parasitic *parasitic_network,
ReduceToPiElmore::makePiElmore(const Parasitic *parasitic_network,
const Pin *drvr_pin,
ParasiticNode *drvr_node,
float coupling_cap_factor,
@ -400,12 +400,12 @@ class ReduceToPiPoleResidue2 : public ReduceToPi
public:
ReduceToPiPoleResidue2(StaState *sta);
~ReduceToPiPoleResidue2();
void findPolesResidues(Parasitic *parasitic_network,
void findPolesResidues(const Parasitic *parasitic_network,
Parasitic *pi_pole_residue,
const Pin *drvr_pin,
ParasiticNode *drvr_node,
const ParasiticAnalysisPt *ap);
void makePiPoleResidue2(Parasitic *parasitic_network,
void makePiPoleResidue2(const Parasitic *parasitic_network,
const Pin *drvr_pin,
ParasiticNode *drvr_node,
float coupling_cap_factor,
@ -466,7 +466,7 @@ ReduceToPiPoleResidue2::ReduceToPiPoleResidue2(StaState *sta) :
// Three Moments of the Impulse Response", Proceedings of the 33rd
// Design Automation Conference, 1996, pg 611-616.
void
reduceToPiPoleResidue2(Parasitic *parasitic_network,
reduceToPiPoleResidue2(const Parasitic *parasitic_network,
const Pin *drvr_pin,
float coupling_cap_factor,
const OperatingConditions *op_cond,
@ -494,7 +494,7 @@ reduceToPiPoleResidue2(Parasitic *parasitic_network,
}
void
ReduceToPiPoleResidue2::makePiPoleResidue2(Parasitic *parasitic_network,
ReduceToPiPoleResidue2::makePiPoleResidue2(const Parasitic *parasitic_network,
const Pin *drvr_pin,
ParasiticNode *drvr_node,
float coupling_cap_factor,
@ -524,7 +524,7 @@ ReduceToPiPoleResidue2::~ReduceToPiPoleResidue2()
}
void
ReduceToPiPoleResidue2::findPolesResidues(Parasitic *parasitic_network,
ReduceToPiPoleResidue2::findPolesResidues(const Parasitic *parasitic_network,
Parasitic *pi_pole_residue,
const Pin *drvr_pin,
ParasiticNode *drvr_node,

View File

@ -28,7 +28,7 @@ class StaState;
// Reduce parasitic network to pi elmore model for drvr_pin.
void
reduceToPiElmore(Parasitic *parasitic_network,
reduceToPiElmore(const Parasitic *parasitic_network,
const Pin *drvr_pin,
float coupling_cap_factor,
const OperatingConditions *op_cond,
@ -40,7 +40,7 @@ reduceToPiElmore(Parasitic *parasitic_network,
// Reduce parasitic network to pi and 2nd order pole/residue models
// for drvr_pin.
void
reduceToPiPoleResidue2(Parasitic *parasitic_network,
reduceToPiPoleResidue2(const Parasitic *parasitic_network,
const Pin *drvr_pin,
float coupling_cap_factor,
const OperatingConditions *op_cond,

View File

@ -358,4 +358,29 @@ ClkSkews::findFanout(Vertex *from)
return endpoints;
}
////////////////////////////////////////////////////////////////
void
ClkSkews::findClkDelays(const Clock *clk,
// Return values.
ClkDelays &delays)
{
for (Vertex *clk_vertex : *graph_->regClkVertices()) {
VertexPathIterator path_iter(clk_vertex, this);
while (path_iter.hasNext()) {
PathVertex *path = path_iter.next();
const ClockEdge *path_clk_edge = path->clkEdge(this);
const RiseFall *clk_rf = path_clk_edge->transition();
const Clock *path_clk = path_clk_edge->clock();
if (path_clk == clk) {
Arrival arrival = path->arrival(this);
Delay clk_delay = delayAsFloat(arrival) - path_clk_edge->time();
const MinMax *min_max = path->minMax(this);
const RiseFall *rf = path->transition(this);
delays[clk_rf->index()][rf->index()].setValue(min_max, clk_delay);
}
}
}
}
} // namespace

View File

@ -19,6 +19,7 @@
#include "Map.hh"
#include "SdcClass.hh"
#include "StaState.hh"
#include "Transition.hh"
#include "SearchClass.hh"
namespace sta {
@ -27,7 +28,7 @@ class ClkSkew;
typedef Map<const Clock*, ClkSkew*> ClkSkewMap;
// Find and report min clock skews.
// Find and report clock skews between source/target registers.
class ClkSkews : public StaState
{
public:
@ -37,10 +38,13 @@ public:
const Corner *corner,
const SetupHold *setup_hold,
int digits);
// Find worst clock skew.
// Find worst clock skew between src/target registers.
float findWorstClkSkew(const Corner *corner,
const SetupHold *setup_hold);
void findClkDelays(const Clock *clk,
// Return values.
ClkDelays &delays);
protected:
void findClkSkew(ClockSet *clks,
const Corner *corner,

View File

@ -40,9 +40,11 @@
#include "Sta.hh"
#include "VisitPathEnds.hh"
#include "ArcDelayCalc.hh"
#include "ClkSkew.hh"
namespace sta {
using std::min;
using std::max;
using std::make_shared;
@ -96,6 +98,7 @@ MakeTimingModel::makeTimingModel()
findTimingFromInputs();
findClkedOutputPaths();
findClkInsertionDelays();
cell_->finish(false, report_, debug_);
restoreSdc();
@ -505,6 +508,63 @@ MakeTimingModel::findClkedOutputPaths()
delete output_iter;
}
////////////////////////////////////////////////////////////////
void
MakeTimingModel::findClkInsertionDelays()
{
Instance *top_inst = network_->topInstance();
Cell *top_cell = network_->cell(top_inst);
CellPortIterator *port_iter = network_->portIterator(top_cell);
while (port_iter->hasNext()) {
Port *port = port_iter->next();
if (network_->direction(port)->isInput()) {
const char *port_name = network_->name(port);
LibertyPort *lib_port = cell_->findLibertyPort(port_name);
Pin *pin = network_->findPin(top_inst, port);
if (sdc_->isClock(pin)) {
lib_port->setIsClock(true);
ClockSet *clks = sdc_->findClocks(pin);
size_t clk_count = clks->size();
if (clk_count == 1) {
for (const Clock *clk : *clks) {
TimingArcAttrsPtr attrs = nullptr;
ClkDelays delays;
sta_->findClkDelays(clk, delays);
for (const MinMax *min_max : MinMax::range()) {
for (const RiseFall *clk_rf : RiseFall::range()) {
int clk_rf_index = clk_rf->index();
float delay = min_max->initValue();
for (const int end_rf_index : RiseFall::rangeIndex()) {
float delay1;
bool exists;
delays[clk_rf_index][end_rf_index].value(min_max, delay1, exists);
if (exists)
delay = min_max->minMax(delay, delay1);
}
TimingModel *model = makeGateModelScalar(delay, clk_rf);
if (attrs == nullptr)
attrs = std::make_shared<TimingArcAttrs>();
attrs->setModel(clk_rf, model);
}
if (attrs)
attrs->setTimingSense(TimingSense::positive_unate);
TimingRole *role = (min_max == MinMax::min())
? TimingRole::clockTreePathMin()
: TimingRole::clockTreePathMax();
lib_builder_->makeClockTreePathArcs(cell_, lib_port, nullptr,
role, attrs);
}
}
}
}
}
}
delete port_iter;
}
////////////////////////////////////////////////////////////////
LibertyPort *
MakeTimingModel::modelPort(const Pin *pin)
{
@ -514,7 +574,7 @@ MakeTimingModel::modelPort(const Pin *pin)
TimingModel *
MakeTimingModel::makeScalarCheckModel(float value,
ScaleFactorType scale_factor_type,
RiseFall *rf)
const RiseFall *rf)
{
TablePtr table = make_shared<Table0>(value);
TableTemplate *tbl_template =
@ -528,7 +588,7 @@ MakeTimingModel::makeScalarCheckModel(float value,
TimingModel *
MakeTimingModel::makeGateModelScalar(Delay delay,
Slew slew,
RiseFall *rf)
const RiseFall *rf)
{
TablePtr delay_table = make_shared<Table0>(delayAsFloat(delay));
TablePtr slew_table = make_shared<Table0>(delayAsFloat(slew));
@ -544,12 +604,27 @@ MakeTimingModel::makeGateModelScalar(Delay delay,
return gate_model;
}
TimingModel *
MakeTimingModel::makeGateModelScalar(Delay delay,
const RiseFall *rf)
{
TablePtr delay_table = make_shared<Table0>(delayAsFloat(delay));
TableTemplate *tbl_template =
library_->findTableTemplate("scalar", TableTemplateType::delay);
TableModel *delay_model = new TableModel(delay_table, tbl_template,
ScaleFactorType::cell, rf);
GateTableModel *gate_model = new GateTableModel(delay_model, nullptr,
nullptr, nullptr,
nullptr, nullptr);
return gate_model;
}
// Eval the driver pin model along its load capacitance
// axis and add the input to output 'delay' to the table values.
TimingModel *
MakeTimingModel::makeGateModelTable(const Pin *output_pin,
Delay delay,
RiseFall *rf)
const RiseFall *rf)
{
const DcalcAnalysisPt *dcalc_ap = corner_->findDcalcAnalysisPt(min_max_);
const Pvt *pvt = dcalc_ap->operatingConditions();

View File

@ -62,6 +62,7 @@ private:
void findTimingFromInputs();
void findTimingFromInput(Port *input_port);
void findClkedOutputPaths();
void findClkInsertionDelays();
void findOutputDelays(const RiseFall *input_rf,
OutputPinDelays &output_pin_delays);
void makeSetupHoldTimingArcs(const Pin *input_pin,
@ -70,13 +71,15 @@ private:
OutputPinDelays &output_pin_delays);
TimingModel *makeScalarCheckModel(float value,
ScaleFactorType scale_factor_type,
RiseFall *rf);
const RiseFall *rf);
TimingModel *makeGateModelScalar(Delay delay,
Slew slew,
RiseFall *rf);
const RiseFall *rf);
TimingModel *makeGateModelScalar(Delay delay,
const RiseFall *rf);
TimingModel *makeGateModelTable(const Pin *output_pin,
Delay delay,
RiseFall *rf);
const RiseFall *rf);
TableTemplate *ensureTableTemplate(const TableTemplate *drvr_template,
TableAxisPtr load_axis);
TableAxisPtr loadCapacitanceAxis(const TableModel *table);

View File

@ -2617,6 +2617,15 @@ Sta::findWorstClkSkew(const SetupHold *setup_hold)
return clk_skews_->findWorstClkSkew(cmd_corner_, setup_hold);
}
void
Sta::findClkDelays(const Clock *clk,
// Return values.
ClkDelays &delays)
{
clkSkewPreamble();
clk_skews_->findClkDelays(clk, delays);
}
void
Sta::clkSkewPreamble()
{

View File

@ -454,7 +454,6 @@ proc get_cells { args } {
parse_key_args "get_cells" args keys {-hsc -filter -of_objects} \
flags {-hierarchical -regexp -nocase -quiet}
check_argc_eq0or1 "get_cells" $args
check_nocase_flag flags
set regexp [info exists flags(-regexp)]
@ -493,23 +492,20 @@ proc get_cells { args } {
$pin_iter finish
}
} else {
if { $args == {} } {
set insts [network_leaf_instances]
} else {
foreach pattern $patterns {
if { $divider != $hierarchy_separator } {
regsub $divider $pattern $hierarchy_separator pattern
}
if { $hierarchical } {
set matches [find_instances_hier_matching $pattern $regexp $nocase]
} else {
set matches [find_instances_matching $pattern $regexp $nocase]
}
if { $matches == {} && !$quiet} {
sta_warn 322 "instance '$pattern' not found."
}
set insts [concat $insts $matches]
check_argc_eq1 "get_cells" $args
foreach pattern $patterns {
if { $divider != $hierarchy_separator } {
regsub $divider $pattern $hierarchy_separator pattern
}
if { $hierarchical } {
set matches [find_instances_hier_matching $pattern $regexp $nocase]
} else {
set matches [find_instances_matching $pattern $regexp $nocase]
}
if { $matches == {} && !$quiet} {
sta_warn 322 "instance '$pattern' not found."
}
set insts [concat $insts $matches]
}
}
if [info exists keys(-filter)] {
@ -586,7 +582,6 @@ proc get_lib_cells { args } {
global hierarchy_separator
parse_key_args "get_lib_cells" args keys {-hsc -of_objects} \
flags {-regexp -nocase -quiet}
check_argc_eq0or1 "get_lib_cells" $args
check_nocase_flag flags
set regexp [info exists flags(-regexp)]
@ -601,6 +596,7 @@ proc get_lib_cells { args } {
lappend cells [$inst liberty_cell]
}
} else {
check_argc_eq1 "get_lib_cells" $args
# Copy backslashes that will be removed by foreach.
set patterns [string map {\\ \\\\} [lindex $args 0]]
# Parse library_name/pattern.
@ -838,7 +834,7 @@ proc get_nets { args } {
define_cmd_args "get_pins" \
{[-hierarchical] [-hsc separator] [-quiet] [-filter expr]\
[-regexp] [-nocase] [-of_objects objects] patterns}
[-regexp] [-nocase] [-of_objects objects] [patterns]}
define_cmd_alias "get_pin" "get_pins"