diff --git a/include/sta/Liberty.hh b/include/sta/Liberty.hh index 15a37283..27f0fd1e 100644 --- a/include/sta/Liberty.hh +++ b/include/sta/Liberty.hh @@ -796,10 +796,16 @@ public: void setDriverWaveform(DriverWaveform *driver_waveform, const RiseFall *rf); void setClkTreeDelay(const TableModel *model, - const RiseFall *rf, + const RiseFall *from_rf, + const RiseFall *to_rf, const MinMax *min_max); + // Should be deprecated. float clkTreeDelay(float in_slew, - const RiseFall *rf, + const RiseFall *from_rf, + const MinMax *min_max) const; + float clkTreeDelay(float in_slew, + const RiseFall *from_rf, + const RiseFall *to_rf, const MinMax *min_max) const; // Assumes input slew of 0.0. RiseFallMinMax clkTreeDelays() const; @@ -846,7 +852,7 @@ protected: ReceiverModelPtr receiver_model_; DriverWaveform *driver_waveform_[RiseFall::index_count]; // Redundant with clock_tree_path_delay timing arcs but faster to access. - const TableModel *clk_tree_delay_[RiseFall::index_count][MinMax::index_count]; + const TableModel *clk_tree_delay_[RiseFall::index_count][RiseFall::index_count][MinMax::index_count]; unsigned int min_pulse_width_exists_:RiseFall::index_count; bool min_period_exists_:1; diff --git a/liberty/Liberty.cc b/liberty/Liberty.cc index e6c34f4f..05fae172 100644 --- a/liberty/Liberty.cc +++ b/liberty/Liberty.cc @@ -2001,9 +2001,11 @@ LibertyPort::LibertyPort(LibertyCell *cell, liberty_port_ = this; min_pulse_width_[RiseFall::riseIndex()] = 0.0; min_pulse_width_[RiseFall::fallIndex()] = 0.0; - for (auto rf_index : RiseFall::rangeIndex()) { - for (auto mm_index : MinMax::rangeIndex()) - clk_tree_delay_[rf_index][mm_index] = nullptr; + for (auto from_rf_index : RiseFall::rangeIndex()) { + for (auto to_rf_index : RiseFall::rangeIndex()) { + for (auto mm_index : MinMax::rangeIndex()) + clk_tree_delay_[from_rf_index][to_rf_index][mm_index] = nullptr; + } } } @@ -2607,12 +2609,15 @@ RiseFallMinMax LibertyPort::clkTreeDelays() const { RiseFallMinMax delays; - for (const RiseFall *rf : RiseFall::range()) { - for (const MinMax *min_max : MinMax::range()) { - const TableModel *model = clk_tree_delay_[rf->index()][min_max->index()]; - if (model) { - float delay = model->findValue(0.0, 0.0, 0.0); - delays.setValue(rf, min_max, delay); + for (const RiseFall *from_rf : RiseFall::range()) { + for (const RiseFall *to_rf : RiseFall::range()) { + for (const MinMax *min_max : MinMax::range()) { + const TableModel *model = + clk_tree_delay_[from_rf->index()][to_rf->index()][min_max->index()]; + if (model) { + float delay = model->findValue(0.0, 0.0, 0.0); + delays.setValue(from_rf, min_max, delay); + } } } } @@ -2624,7 +2629,21 @@ LibertyPort::clkTreeDelay(float in_slew, const RiseFall *rf, const MinMax *min_max) const { - const TableModel *model = clk_tree_delay_[rf->index()][min_max->index()]; + const TableModel *model = clk_tree_delay_[rf->index()][rf->index()][min_max->index()]; + if (model) + return model->findValue(in_slew, 0.0, 0.0); + else + return 0.0; +} + +float +LibertyPort::clkTreeDelay(float in_slew, + const RiseFall *from_rf, + const RiseFall *to_rf, + const MinMax *min_max) const +{ + const TableModel *model = + clk_tree_delay_[from_rf->index()][to_rf->index()][min_max->index()]; if (model) return model->findValue(in_slew, 0.0, 0.0); else @@ -2633,10 +2652,11 @@ LibertyPort::clkTreeDelay(float in_slew, void LibertyPort::setClkTreeDelay(const TableModel *model, - const RiseFall *rf, + const RiseFall *from_rf, + const RiseFall *to_rf, const MinMax *min_max) { - clk_tree_delay_[rf->index()][min_max->index()] = model; + clk_tree_delay_[from_rf->index()][to_rf->index()][min_max->index()] = model; } //////////////////////////////////////////////////////////////// diff --git a/liberty/LibertyBuilder.cc b/liberty/LibertyBuilder.cc index dac8d59b..39a1f1b8 100644 --- a/liberty/LibertyBuilder.cc +++ b/liberty/LibertyBuilder.cc @@ -642,9 +642,27 @@ LibertyBuilder::makeClockTreePathArcs(LibertyCell *cell, for (auto to_rf : RiseFall::range()) { TimingModel *model = attrs->model(to_rf); if (model) { - makeTimingArc(arc_set, nullptr, to_rf->asTransition(), model); const GateTableModel *gate_model = dynamic_cast(model); - to_port->setClkTreeDelay(gate_model->delayModel(), to_rf, min_max); + RiseFall *opp_rf = to_rf->opposite(); + switch (attrs->timingSense()) { + case TimingSense::positive_unate: + makeTimingArc(arc_set, to_rf, to_rf, model); + to_port->setClkTreeDelay(gate_model->delayModel(), to_rf, to_rf, min_max); + break; + case TimingSense::negative_unate: + makeTimingArc(arc_set, opp_rf, to_rf, model); + to_port->setClkTreeDelay(gate_model->delayModel(), opp_rf, to_rf, min_max); + break; + case TimingSense::non_unate: + case TimingSense::unknown: + makeTimingArc(arc_set, to_rf, to_rf, model); + makeTimingArc(arc_set, opp_rf, to_rf, model); + to_port->setClkTreeDelay(gate_model->delayModel(), to_rf, to_rf, min_max); + to_port->setClkTreeDelay(gate_model->delayModel(), opp_rf, to_rf, min_max); + break; + case TimingSense::none: + break; + } } } return arc_set; diff --git a/search/ClkDelays.hh b/search/ClkDelays.hh index 3aadfa88..003b705c 100644 --- a/search/ClkDelays.hh +++ b/search/ClkDelays.hh @@ -36,13 +36,13 @@ public: float &lib_clk_delay, float &latency, PathVertex &path, - bool &exists); + bool &exists) const; void latency(const RiseFall *src_rf, const RiseFall *end_rf, const MinMax *min_max, // Return values. float &delay, - bool &exists); + bool &exists) const; static float latency(PathVertex *clk_path, StaState *sta); void setLatency(const RiseFall *src_rf, diff --git a/search/ClkLatency.cc b/search/ClkLatency.cc index 9e2e91a4..8c9c90ce 100644 --- a/search/ClkLatency.cc +++ b/search/ClkLatency.cc @@ -194,7 +194,7 @@ ClkDelays::delay(const RiseFall *src_rf, float &lib_clk_delay, float &latency, PathVertex &path, - bool &exists) + bool &exists) const { int src_rf_index = src_rf->index(); int end_rf_index = end_rf->index(); @@ -213,7 +213,7 @@ ClkDelays::latency(const RiseFall *src_rf, const MinMax *min_max, // Return values. float &latency, - bool &exists) + bool &exists) const { int src_rf_index = src_rf->index(); int end_rf_index = end_rf->index(); diff --git a/search/MakeTimingModel.cc b/search/MakeTimingModel.cc index ff9a861f..c35dfa23 100644 --- a/search/MakeTimingModel.cc +++ b/search/MakeTimingModel.cc @@ -544,30 +544,8 @@ MakeTimingModel::findClkInsertionDelays() for (const Clock *clk : *clks) { ClkDelays delays = sta_->findClkDelays(clk); for (const MinMax *min_max : MinMax::range()) { - TimingArcAttrsPtr attrs = nullptr; - for (const RiseFall *clk_rf : RiseFall::range()) { - float delay = min_max->initValue(); - for (const RiseFall *end_rf : RiseFall::range()) { - PathVertex clk_path; - float insertion, delay1, lib_clk_delay, latency; - bool exists; - delays.delay(clk_rf, end_rf, min_max, insertion, delay1, - lib_clk_delay, latency, clk_path, exists); - if (exists) - delay = min_max->minMax(delay, delayAsFloat(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, role, - min_max, attrs); + makeClkTreePaths(lib_port, min_max, TimingSense::positive_unate, delays); + makeClkTreePaths(lib_port, min_max, TimingSense::negative_unate, delays); } } } @@ -577,6 +555,38 @@ MakeTimingModel::findClkInsertionDelays() delete port_iter; } +void +MakeTimingModel::makeClkTreePaths(LibertyPort *lib_port, + const MinMax *min_max, + TimingSense sense, + const ClkDelays &delays) +{ + TimingArcAttrsPtr attrs = nullptr; + for (const RiseFall *clk_rf : RiseFall::range()) { + const RiseFall *end_rf = (sense == TimingSense::positive_unate) + ? clk_rf + : clk_rf->opposite(); + PathVertex clk_path; + float insertion, delay, lib_clk_delay, latency; + bool exists; + delays.delay(clk_rf, end_rf, min_max, insertion, delay, + lib_clk_delay, latency, clk_path, exists); + if (exists) { + TimingModel *model = makeGateModelScalar(delay, end_rf); + if (attrs == nullptr) + attrs = std::make_shared(); + attrs->setModel(end_rf, model); + } + } + if (attrs) { + attrs->setTimingSense(sense); + TimingRole *role = (min_max == MinMax::min()) + ? TimingRole::clockTreePathMin() + : TimingRole::clockTreePathMax(); + lib_builder_->makeClockTreePathArcs(cell_, lib_port, role, min_max, attrs); + } +} + //////////////////////////////////////////////////////////////// LibertyPort * diff --git a/search/MakeTimingModelPvt.hh b/search/MakeTimingModelPvt.hh index da5f15b8..e7587f6f 100644 --- a/search/MakeTimingModelPvt.hh +++ b/search/MakeTimingModelPvt.hh @@ -64,6 +64,10 @@ private: void findTimingFromInput(Port *input_port); void findClkedOutputPaths(); void findClkInsertionDelays(); + void makeClkTreePaths(LibertyPort *lib_port, + const MinMax *min_max, + TimingSense sense, + const ClkDelays &delays); void findOutputDelays(const RiseFall *input_rf, OutputPinDelays &output_pin_delays); void makeSetupHoldTimingArcs(const Pin *input_pin,