From 76d6dd1dae89eaf3e0b9039593d54dbf531113cc Mon Sep 17 00:00:00 2001 From: James Cherry Date: Wed, 4 Oct 2023 14:33:09 -0700 Subject: [PATCH] write_timing_model min/max_clock_tree_path commit 327766984f2beedc5c83b0acdab0df48fb61d2ba Author: James Cherry Date: Wed Oct 4 11:09:38 2023 -0700 write_timing_model min/max_clock_tree_path Signed-off-by: James Cherry commit 675c1ff6d8cfa90a0d1bd5c8960a8b23e75056a3 Author: James Cherry Date: Wed Oct 4 09:02:39 2023 -0700 min/max_clock_tree_path Signed-off-by: James Cherry Signed-off-by: James Cherry --- graph/Graph.cc | 2 +- include/sta/Graph.hh | 2 - include/sta/MinMaxValues.hh | 4 +- include/sta/SearchClass.hh | 2 + include/sta/Sta.hh | 18 +++++--- include/sta/TableModel.hh | 2 +- include/sta/TimingArc.hh | 4 +- include/sta/TimingRole.hh | 4 ++ include/sta/Transition.hh | 4 +- liberty/Liberty.cc | 13 +++--- liberty/LibertyBuilder.cc | 27 +++++++++++- liberty/LibertyBuilder.hh | 5 +++ liberty/LibertyReader.cc | 22 ++++++++++ liberty/LibertyReaderPvt.hh | 3 ++ liberty/LibertyWriter.cc | 24 +++++++---- liberty/TableModel.cc | 2 +- liberty/TimingArc.cc | 4 +- liberty/TimingRole.cc | 6 +++ search/ClkSkew.cc | 25 +++++++++++ search/ClkSkew.hh | 10 +++-- search/MakeTimingModel.cc | 81 ++++++++++++++++++++++++++++++++++-- search/MakeTimingModelPvt.hh | 9 ++-- search/Sta.cc | 9 ++++ 23 files changed, 239 insertions(+), 43 deletions(-) diff --git a/graph/Graph.cc b/graph/Graph.cc index 6875636a..8d5bc4ee 100644 --- a/graph/Graph.cc +++ b/graph/Graph.cc @@ -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) { diff --git a/include/sta/Graph.hh b/include/sta/Graph.hh index 8fc8813f..247b5bcf 100644 --- a/include/sta/Graph.hh +++ b/include/sta/Graph.hh @@ -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_; diff --git a/include/sta/MinMaxValues.hh b/include/sta/MinMaxValues.hh index 790f386d..50d0b9eb 100644 --- a/include/sta/MinMaxValues.hh +++ b/include/sta/MinMaxValues.hh @@ -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 diff --git a/include/sta/SearchClass.hh b/include/sta/SearchClass.hh index b582341d..6aea164f 100644 --- a/include/sta/SearchClass.hh +++ b/include/sta/SearchClass.hh @@ -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 PathVertexSeq; typedef Vector SlackSeq; typedef Delay Crpr; typedef Vector PathRefSeq; +typedef MinMaxValues ClkDelays[RiseFall::index_count][RiseFall::index_count]; enum class ReportPathFormat { full, full_clock, diff --git a/include/sta/Sta.hh b/include/sta/Sta.hh index f14d0f60..718aa880 100644 --- a/include/sta/Sta.hh +++ b/include/sta/Sta.hh @@ -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. diff --git a/include/sta/TableModel.hh b/include/sta/TableModel.hh index 1184a3b8..0ec14588 100644 --- a/include/sta/TableModel.hh +++ b/include/sta/TableModel.hh @@ -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_; } diff --git a/include/sta/TimingArc.hh b/include/sta/TimingArc.hh index 3d46a815..1c30b77c 100644 --- a/include/sta/TimingArc.hh +++ b/include/sta/TimingArc.hh @@ -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); diff --git a/include/sta/TimingRole.hh b/include/sta/TimingRole.hh index 3aadc4fc..be20a04a 100644 --- a/include/sta/TimingRole.hh +++ b/include/sta/TimingRole.hh @@ -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; diff --git a/include/sta/Transition.hh b/include/sta/Transition.hh index ceb474d5..f4035d20 100644 --- a/include/sta/Transition.hh +++ b/include/sta/Transition.hh @@ -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 &range() { return range_; } - // for (auto tr_index : RiseFall::rangeIndex()) {} + // for (auto rf_index : RiseFall::rangeIndex()) {} static const std::array &rangeIndex() { return range_index_; } static const int index_count = 2; static const int index_max = (index_count - 1); diff --git a/liberty/Liberty.cc b/liberty/Liberty.cc index dea3e49b..bf90baa1 100644 --- a/liberty/Liberty.cc +++ b/liberty/Liberty.cc @@ -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); } @@ -2588,8 +2589,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()); diff --git a/liberty/LibertyBuilder.cc b/liberty/LibertyBuilder.cc index 779d5d68..c80a1de7 100644 --- a/liberty/LibertyBuilder.cc +++ b/liberty/LibertyBuilder.cc @@ -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, diff --git a/liberty/LibertyBuilder.hh b/liberty/LibertyBuilder.hh index 62286512..f6b64b86 100644 --- a/liberty/LibertyBuilder.hh +++ b/liberty/LibertyBuilder.hh @@ -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, diff --git a/liberty/LibertyReader.cc b/liberty/LibertyReader.cc index 9946e201..8ec9ff1d 100644 --- a/liberty/LibertyReader.cc +++ b/liberty/LibertyReader.cc @@ -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 diff --git a/liberty/LibertyReaderPvt.hh b/liberty/LibertyReaderPvt.hh index 5b799a50..4a32067d 100644 --- a/liberty/LibertyReaderPvt.hh +++ b/liberty/LibertyReaderPvt.hh @@ -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); diff --git a/liberty/LibertyWriter.cc b/liberty/LibertyWriter.cc index 6d6a7b80..48bdce86 100644 --- a/liberty/LibertyWriter.cc +++ b/liberty/LibertyWriter.cc @@ -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; } diff --git a/liberty/TableModel.cc b/liberty/TableModel.cc index 45e7cfe4..57e9865a 100644 --- a/liberty/TableModel.cc +++ b/liberty/TableModel.cc @@ -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)), diff --git a/liberty/TimingArc.cc b/liberty/TimingArc.cc index 4176985e..ba7301c7 100644 --- a/liberty/TimingArc.cc +++ b/liberty/TimingArc.cc @@ -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; diff --git a/liberty/TimingRole.cc b/liberty/TimingRole.cc index 1676a14a..4747a2e6 100644 --- a/liberty/TimingRole.cc +++ b/liberty/TimingRole.cc @@ -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 diff --git a/search/ClkSkew.cc b/search/ClkSkew.cc index 8d001d9d..03c1019f 100644 --- a/search/ClkSkew.cc +++ b/search/ClkSkew.cc @@ -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 diff --git a/search/ClkSkew.hh b/search/ClkSkew.hh index 6e9c332f..b7c7a290 100644 --- a/search/ClkSkew.hh +++ b/search/ClkSkew.hh @@ -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 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, diff --git a/search/MakeTimingModel.cc b/search/MakeTimingModel.cc index 6cbae47e..734c80f7 100644 --- a/search/MakeTimingModel.cc +++ b/search/MakeTimingModel.cc @@ -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(); + 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(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(delayAsFloat(delay)); TablePtr slew_table = make_shared(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(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(); diff --git a/search/MakeTimingModelPvt.hh b/search/MakeTimingModelPvt.hh index 2895acee..d2ae18f2 100644 --- a/search/MakeTimingModelPvt.hh +++ b/search/MakeTimingModelPvt.hh @@ -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); diff --git a/search/Sta.cc b/search/Sta.cc index a67dfae7..58dae681 100644 --- a/search/Sta.cc +++ b/search/Sta.cc @@ -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() {