diff --git a/include/sta/Sta.hh b/include/sta/Sta.hh index 3520a9db..2ba6d43b 100644 --- a/include/sta/Sta.hh +++ b/include/sta/Sta.hh @@ -1314,7 +1314,8 @@ public: void writeTimingModel(const char *lib_name, const char *cell_name, const char *filename, - const Corner *corner); + const Corner *corner, + const bool scalar); // Find equivalent cells in equiv_libs. // Optionally add mappings for cells in map_libs. diff --git a/search/MakeTimingModel.cc b/search/MakeTimingModel.cc index 3b8c5a0b..1a10acbb 100644 --- a/search/MakeTimingModel.cc +++ b/search/MakeTimingModel.cc @@ -53,9 +53,10 @@ makeTimingModel(const char *lib_name, const char *cell_name, const char *filename, const Corner *corner, + const bool scalar, Sta *sta) { - MakeTimingModel maker(lib_name, cell_name, filename, corner, sta); + MakeTimingModel maker(lib_name, cell_name, filename, corner, scalar, sta); return maker.makeTimingModel(); } @@ -63,12 +64,14 @@ MakeTimingModel::MakeTimingModel(const char *lib_name, const char *cell_name, const char *filename, const Corner *corner, + const bool scalar, Sta *sta) : StaState(sta), lib_name_(lib_name), cell_name_(cell_name), filename_(filename), corner_(corner), + scalar_(scalar), cell_(nullptr), min_max_(MinMax::max()), lib_builder_(new LibertyBuilder), @@ -86,7 +89,8 @@ MakeTimingModel::~MakeTimingModel() LibertyLibrary * MakeTimingModel::makeTimingModel() { - saveSdc(); + if (!scalar_) + saveSdc(); tbl_template_index_ = 1; makeLibrary(); @@ -101,7 +105,9 @@ MakeTimingModel::makeTimingModel() findClkInsertionDelays(); cell_->finish(false, report_, debug_); - restoreSdc(); + + if (!scalar_) + restoreSdc(); return library_; } @@ -503,7 +509,14 @@ MakeTimingModel::findClkedOutputPaths() TimingArcAttrsPtr attrs = nullptr; for (RiseFall *output_rf : RiseFall::range()) { float delay = delays.value(output_rf, min_max_) - clk_edge->time(); - TimingModel *gate_model = makeGateModelTable(output_pin, delay, output_rf); + TimingModel *gate_model; + if (scalar_) { + const DcalcAnalysisPt *dcalc_ap = corner_->findDcalcAnalysisPt(min_max_); + Slew slew = graph_->slew(output_vertex, output_rf, dcalc_ap->index()); + gate_model = makeGateModelScalar(delay, slew, output_rf); + } + else + gate_model = makeGateModelTable(output_pin, delay, output_rf); if (attrs == nullptr) attrs = std::make_shared(); attrs->setModel(output_rf, gate_model); @@ -656,7 +669,7 @@ MakeTimingModel::makeGateModelTable(const Pin *output_pin, PinSet *drvrs = network_->drivers(network_->net(network_->term(output_pin))); const Pin *drvr_pin = *drvrs->begin(); const LibertyPort *drvr_port = network_->libertyPort(drvr_pin); - if (drvr_port && false) { + if (drvr_port) { const LibertyCell *drvr_cell = drvr_port->libertyCell(); for (TimingArcSet *arc_set : drvr_cell->timingArcSets(nullptr, drvr_port)) { for (TimingArc *drvr_arc : arc_set->arcs()) { diff --git a/search/MakeTimingModel.hh b/search/MakeTimingModel.hh index 60b6662e..68a501a0 100644 --- a/search/MakeTimingModel.hh +++ b/search/MakeTimingModel.hh @@ -27,6 +27,7 @@ makeTimingModel(const char *lib_name, const char *cell_name, const char *filename, const Corner *corner, + const bool scalar, Sta *sta); } // namespace diff --git a/search/MakeTimingModelPvt.hh b/search/MakeTimingModelPvt.hh index 7e3b83e4..832aa822 100644 --- a/search/MakeTimingModelPvt.hh +++ b/search/MakeTimingModelPvt.hh @@ -50,6 +50,7 @@ public: const char *cell_name, const char *filename, const Corner *corner, + const bool scalar, Sta *sta); ~MakeTimingModel(); LibertyLibrary *makeTimingModel(); @@ -98,6 +99,7 @@ private: const char *cell_name_; const char *filename_; const Corner *corner_; + const bool scalar_; LibertyLibrary *library_; LibertyCell *cell_; MinMax *min_max_; diff --git a/search/Search.i b/search/Search.i index cafe0907..7a759be9 100644 --- a/search/Search.i +++ b/search/Search.i @@ -927,9 +927,10 @@ void write_timing_model_cmd(const char *lib_name, const char *cell_name, const char *filename, - const Corner *corner) + const Corner *corner, + const bool scalar) { - Sta::sta()->writeTimingModel(lib_name, cell_name, filename, corner); + Sta::sta()->writeTimingModel(lib_name, cell_name, filename, corner, scalar); } //////////////////////////////////////////////////////////////// diff --git a/search/Search.tcl b/search/Search.tcl index 381da541..e80fb811 100644 --- a/search/Search.tcl +++ b/search/Search.tcl @@ -1024,17 +1024,19 @@ proc worst_clock_skew { args } { ################################################################ -define_cmd_args "write_timing_model" {[-corner corner] \ +define_cmd_args "write_timing_model" {[-scalar] \ + [-corner corner] \ [-library_name lib_name]\ [-cell_name cell_name]\ filename} proc write_timing_model { args } { parse_key_args "write_timing_model" args \ - keys {-library_name -cell_name -corner} flags {} + keys {-library_name -cell_name -corner} flags {-scalar} check_argc_eq1 "write_timing_model" $args set filename [file nativename [lindex $args 0]] + set scalar [info exists flags(-scalar)] if { [info exists keys(-cell_name)] } { set cell_name $keys(-cell_name) } else { @@ -1046,8 +1048,7 @@ proc write_timing_model { args } { set lib_name $cell_name } set corner [parse_corner keys] - write_timing_model_cmd $lib_name $cell_name $filename $corner - + write_timing_model_cmd $lib_name $cell_name $filename $corner $scalar } ################################################################ diff --git a/search/Sta.cc b/search/Sta.cc index 0ffa6403..f214c400 100644 --- a/search/Sta.cc +++ b/search/Sta.cc @@ -5622,10 +5622,11 @@ void Sta::writeTimingModel(const char *lib_name, const char *cell_name, const char *filename, - const Corner *corner) + const Corner *corner, + const bool scalar) { LibertyLibrary *library = makeTimingModel(lib_name, cell_name, filename, - corner, this); + corner, scalar, this); writeLiberty(library, filename, this); } diff --git a/test/regression_vars.tcl b/test/regression_vars.tcl index bef50a3b..ef0d4c84 100644 --- a/test/regression_vars.tcl +++ b/test/regression_vars.tcl @@ -135,6 +135,7 @@ record_sta_tests { get_objrefs get_lib_pins_of_objects report_checks_src_attr + write_timing_model_scalar } define_test_group fast [group_tests all] diff --git a/test/write_timing_model_scalar.ok b/test/write_timing_model_scalar.ok new file mode 100644 index 00000000..9be2cbbe --- /dev/null +++ b/test/write_timing_model_scalar.ok @@ -0,0 +1,121 @@ +library (counter) { + comment : ""; + delay_model : table_lookup; + simulation : false; + capacitive_load_unit (1,pF); + leakage_power_unit : 1pW; + current_unit : "1A"; + pulling_resistance_unit : "1kohm"; + time_unit : "1ns"; + voltage_unit : "1v"; + library_features(report_delay_calculation); + + input_threshold_pct_rise : 50; + input_threshold_pct_fall : 50; + output_threshold_pct_rise : 50; + output_threshold_pct_fall : 50; + slew_lower_threshold_pct_rise : 20; + slew_lower_threshold_pct_fall : 20; + slew_upper_threshold_pct_rise : 80; + slew_upper_threshold_pct_fall : 80; + slew_derate_from_library : 1.0; + + + nom_process : 1.0; + nom_temperature : 25.0; + nom_voltage : 1.80; + + + cell ("counter") { + area : 25.024 + is_macro_cell : true; + pin("clk") { + direction : input; + clock : true; + capacitance : 0.0019; + timing() { + timing_sense : positive_unate; + timing_type : min_clock_tree_path; + cell_rise(scalar) { + values("0.00000"); + } + cell_fall(scalar) { + values("0.00000"); + } + } + timing() { + timing_sense : positive_unate; + timing_type : max_clock_tree_path; + cell_rise(scalar) { + values("0.00000"); + } + cell_fall(scalar) { + values("0.00000"); + } + } + } + pin("reset") { + direction : input; + capacitance : 0.0036; + timing() { + related_pin : "clk"; + timing_type : hold_rising; + rise_constraint(scalar) { + values("0.29559"); + } + } + timing() { + related_pin : "clk"; + timing_type : setup_rising; + rise_constraint(scalar) { + values("-0.22827"); + } + } + } + pin("in") { + direction : input; + capacitance : 0.0020; + timing() { + related_pin : "clk"; + timing_type : hold_rising; + rise_constraint(scalar) { + values("-0.03143"); + } + fall_constraint(scalar) { + values("-0.03771"); + } + } + timing() { + related_pin : "clk"; + timing_type : setup_rising; + rise_constraint(scalar) { + values("0.05608"); + } + fall_constraint(scalar) { + values("0.10489"); + } + } + } + pin("out") { + direction : output; + capacitance : 1.0000; + timing() { + related_pin : "clk"; + timing_type : rising_edge; + cell_rise(scalar) { + values("6.24237"); + } + rise_transition(scalar) { + values("8.46194"); + } + cell_fall(scalar) { + values("3.79896"); + } + fall_transition(scalar) { + values("4.53677"); + } + } + } + } + +} diff --git a/test/write_timing_model_scalar.tcl b/test/write_timing_model_scalar.tcl new file mode 100644 index 00000000..38f3a43a --- /dev/null +++ b/test/write_timing_model_scalar.tcl @@ -0,0 +1,9 @@ +# write_timing_model with -scalar option +read_liberty ../examples/sky130hd_tt.lib.gz +read_verilog verilog_attribute.v +link_design counter +create_clock -name clk -period 0 clk +set_input_delay -clock clk 0 [all_inputs -no_clocks] +set_output_delay -clock clk 0 [all_outputs] +set_load 1 [all_outputs] +write_timing_model -scalar results/write_timing_model_scalar.log