From 55ec1973d0aeb126d9e2af01538d748b2706687b Mon Sep 17 00:00:00 2001 From: James Cherry Date: Wed, 8 Jun 2022 10:03:41 -0700 Subject: [PATCH] make timing model setup/hold Signed-off-by: James Cherry --- liberty/LibertyBuilder.hh | 15 +++--- liberty/TableModel.cc | 2 +- search/MakeTimingModel.cc | 109 +++++++++++++++++++++++++++----------- search/MakeTimingModel.hh | 5 ++ 4 files changed, 92 insertions(+), 39 deletions(-) diff --git a/liberty/LibertyBuilder.hh b/liberty/LibertyBuilder.hh index 7e68fcff..477f4be4 100644 --- a/liberty/LibertyBuilder.hh +++ b/liberty/LibertyBuilder.hh @@ -59,6 +59,14 @@ public: LeakagePower *makeLeakagePower(LibertyCell *cell, LeakagePowerAttrs *attrs); + TimingArcSet *makeFromTransitionArcs(LibertyCell *cell, + LibertyPort *from_port, + LibertyPort *to_port, + LibertyPort *related_out, + RiseFall *from_rf, + TimingRole *role, + TimingArcAttrs *attrs); + protected: ConcretePort *makeBusPort(const char *name, int from_index, @@ -111,13 +119,6 @@ protected: LibertyPort *related_out, RiseFall *from_rf, TimingArcAttrs *attrs); - TimingArcSet *makeFromTransitionArcs(LibertyCell *cell, - LibertyPort *from_port, - LibertyPort *to_port, - LibertyPort *related_out, - RiseFall *from_rf, - TimingRole *role, - TimingArcAttrs *attrs); TimingArcSet *makePresetClrArcs(LibertyCell *cell, LibertyPort *from_port, LibertyPort *to_port, diff --git a/liberty/TableModel.cc b/liberty/TableModel.cc index c039b76b..6ae924d8 100644 --- a/liberty/TableModel.cc +++ b/liberty/TableModel.cc @@ -352,7 +352,7 @@ CheckTableModel::CheckTableModel(TableModel *model, model_(model) { for (auto el_index : EarlyLate::rangeIndex()) - sigma_models_[el_index] = sigma_models[el_index]; + sigma_models_[el_index] = sigma_models ? sigma_models[el_index] : nullptr; } CheckTableModel::~CheckTableModel() diff --git a/search/MakeTimingModel.cc b/search/MakeTimingModel.cc index b9c1563e..9b3aea30 100644 --- a/search/MakeTimingModel.cc +++ b/search/MakeTimingModel.cc @@ -20,6 +20,8 @@ #include "Units.hh" #include "Transition.hh" #include "Liberty.hh" +#include "TimingArc.hh" +#include "TableModel.hh" #include "liberty/LibertyBuilder.hh" #include "LibertyWriter.hh" #include "Network.hh" @@ -29,6 +31,7 @@ #include "dcalc/GraphDelayCalc1.hh" #include "Sdc.hh" #include "StaState.hh" +#include "PathEnd.hh" #include "Sta.hh" namespace sta { @@ -89,6 +92,7 @@ MakeTimingModel::makeTimingModel(const char *cell_name, findClkedOutputPaths(); #endif findInputSetupHolds(); + cell_->finish(false, report_, debug_); } void @@ -190,41 +194,64 @@ MakeTimingModel::findInputSetupHolds() Pin *input_pin = input_iter->next(); if (network_->direction(input_pin)->isInput() && !sta_->isClockSrc(input_pin)) { + LibertyPort *input_port = modelPort(input_pin); for (Clock *clk : *sdc_->clocks()) { - for (RiseFall *clk_rf : RiseFall::range()) { - for (MinMax *min_max : MinMax::range()) { - MinMaxAll *min_max2 = min_max->asMinMaxAll(); - bool setup = min_max == MinMax::max(); - bool hold = !setup; - for (RiseFall *input_rf : RiseFall::range()) { - sdc_->setInputDelay(input_pin, RiseFallBoth::riseFall(), clk, clk_rf, - nullptr, false, false, min_max2, false, 0.0); + for (const Pin *clk_pin : clk->pins()) { + LibertyPort *clk_port = modelPort(clk_pin); + for (RiseFall *clk_rf : RiseFall::range()) { + for (MinMax *min_max : MinMax::range()) { + MinMaxAll *min_max2 = min_max->asMinMaxAll(); + bool setup = min_max == MinMax::max(); + bool hold = !setup; + TimingRole *role = setup ? TimingRole::setup() : TimingRole::hold(); + TimingArcAttrs *attrs = nullptr; + for (RiseFall *input_rf : RiseFall::range()) { + sdc_->setInputDelay(input_pin, RiseFallBoth::riseFall(), clk, clk_rf, + nullptr, false, false, min_max2, false, 0.0); - PinSet *from_pins = new PinSet; - from_pins->insert(input_pin); - ExceptionFrom *from = sta_->makeExceptionFrom(from_pins, nullptr, nullptr, - input_rf->asRiseFallBoth()); + PinSet *from_pins = new PinSet; + from_pins->insert(input_pin); + ExceptionFrom *from = sta_->makeExceptionFrom(from_pins, nullptr, nullptr, + input_rf->asRiseFallBoth()); - ClockSet *to_clks = new ClockSet; - to_clks->insert(clk); - ExceptionTo *to = sta_->makeExceptionTo(nullptr, to_clks, nullptr, - clk_rf->asRiseFallBoth(), - RiseFallBoth::riseFall()); - PathEndSeq *ends = sta_->findPathEnds(from, nullptr, to, false, corner_, - min_max2, - 1, 1, false, - -INF, INF, false, nullptr, - setup, hold, setup, hold, setup, hold); - if (!ends->empty()) { - debugPrint(debug_, "timing_model", 1, "%s %s %s -> clock %s %s", - setup ? "setup" : "hold", - network_->pathName(input_pin), - input_rf->asString(), - clk->name(), - clk_rf->asString()); - PathEnd *end = (*ends)[0]; - sta_->reportPathEnd(end); + ClockSet *to_clks = new ClockSet; + to_clks->insert(clk); + ExceptionTo *to = sta_->makeExceptionTo(nullptr, to_clks, nullptr, + clk_rf->asRiseFallBoth(), + RiseFallBoth::riseFall()); + PathEndSeq *ends = sta_->findPathEnds(from, nullptr, to, false, corner_, + min_max2, + 1, 1, false, + -INF, INF, false, nullptr, + setup, hold, setup, hold, setup, hold); + if (!ends->empty()) { + PathEnd *end = (*ends)[0]; + debugPrint(debug_, "timing_model", 1, "%s %s %s -> clock %s %s", + setup ? "setup" : "hold", + network_->pathName(input_pin), + input_rf->asString(), + clk->name(), + clk_rf->asString()); + if (debug_->check("timing_model", 2)) + sta_->reportPathEnd(end); + Arrival data_arrival = end->path()->arrival(sta_); + Delay clk_latency = end->targetClkDelay(sta_); + ArcDelay check_setup = end->margin(sta_); + float margin = data_arrival - clk_latency + check_setup; + + ScaleFactorType scale_type = setup + ? ScaleFactorType::setup + : ScaleFactorType::hold; + TimingModel *check_model = makeScalarCheckModel(margin, scale_type, input_rf); + if (attrs == nullptr) + attrs = new TimingArcAttrs(); + attrs->setModel(input_rf, check_model); + } } + if (attrs) + lib_builder_->makeFromTransitionArcs(cell_, clk_port, + input_port, nullptr, + clk_rf, role, attrs); } } } @@ -273,4 +300,24 @@ MakeTimingModel::findClkedOutputPaths() } } +LibertyPort * +MakeTimingModel::modelPort(const Pin *pin) +{ + return cell_->findLibertyPort(network_->name(network_->port(pin))); +} + +TimingModel * +MakeTimingModel::makeScalarCheckModel(float value, + ScaleFactorType scale_factor_type, + RiseFall *rf) +{ + Table *table = new Table0(value); + TableTemplate *tbl_template = + library_->findTableTemplate("scalar", TableTemplateType::delay); + TableModel *table_model = new TableModel(table, tbl_template, + scale_factor_type, rf); + CheckTableModel *check_model = new CheckTableModel(table_model, nullptr); + return check_model; +} + } // namespace diff --git a/search/MakeTimingModel.hh b/search/MakeTimingModel.hh index 3d8f7ded..ac284a2b 100644 --- a/search/MakeTimingModel.hh +++ b/search/MakeTimingModel.hh @@ -47,6 +47,11 @@ private: void findInputSetupHolds(); void findClkedOutputPaths(); + LibertyPort *modelPort(const Pin *pin); + TimingModel *makeScalarCheckModel(float value, + ScaleFactorType scale_factor_type, + RiseFall *rf); + Sta *sta_; LibertyLibrary *library_; LibertyCell *cell_;