commit
9e792b0542
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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
|
||||
{
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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_;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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) {
|
||||
|
|
|
|||
|
|
@ -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_;
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
|
|
|
|||
|
|
@ -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_; }
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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());
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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)),
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
|
|
|
|||
|
|
@ -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 *,
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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()
|
||||
{
|
||||
|
|
|
|||
34
tcl/Sdc.tcl
34
tcl/Sdc.tcl
|
|
@ -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"
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue