Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 15 additions & 0 deletions src/interface/python/py_ista/py_ista_utils.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
// ***************************************************************************************
#include <tcl_util.h>

#include <stdexcept>
#include <string>

#include "json_parser.h"
Expand Down Expand Up @@ -53,6 +54,13 @@ bool initStaConfigMapByJSON(const std::string& config, std::map<std::string, std
if (!value.empty()) {
config_map.insert(std::make_pair("-timing_path_limit", std::stoi(value)));
}
value = ecc::getJsonData(json, {"STA", "-min_slew_degradation"});
if (!value.empty()) {
if (value != "0" && value != "1") {
throw std::invalid_argument("-min_slew_degradation must be 0 or 1");
}
config_map.insert(std::make_pair("-min_slew_degradation", int32_t(value == "1")));
}
value = ecc::getJsonData(json, {"STA", "-timing_corner"});
if (!value.empty()) {
config_map.insert(std::make_pair("-timing_corner", value));
Expand Down Expand Up @@ -101,6 +109,13 @@ void initStaConfigMapByDict(std::map<std::string, std::string>& config_dict, std
if (config_dict.count("-timing_path_limit") > 0 && !config_dict["-timing_path_limit"].empty()) {
config_map["-timing_path_limit"] = std::stoi(config_dict["-timing_path_limit"]);
}
if (config_dict.count("-min_slew_degradation") > 0 && !config_dict["-min_slew_degradation"].empty()) {
const std::string& value = config_dict.at("-min_slew_degradation");
if (value != "0" && value != "1") {
throw std::invalid_argument("-min_slew_degradation must be 0 or 1");
}
config_map["-min_slew_degradation"] = int32_t(value == "1");
}
if (config_dict.count("-timing_corner") > 0 && !config_dict["-timing_corner"].empty()) {
config_map["-timing_corner"] = config_dict["-timing_corner"];
}
Expand Down
18 changes: 17 additions & 1 deletion src/interface/tcl/tcl_ista/src/tcl_init_sta.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,8 @@ TclInitSTA::TclInitSTA(const char* cmd_name) : TclCmd(cmd_name)
_config_list.push_back(std::make_pair("-output_timing_features", ValueType::kInt));
// int32_t timing_path_limit; // optional
_config_list.push_back(std::make_pair("-timing_path_limit", ValueType::kInt));
// int32_t min_slew_degradation; // optional
_config_list.push_back(std::make_pair("-min_slew_degradation", ValueType::kString));
// std::string timing_corner; // optional
_config_list.push_back(std::make_pair("-timing_corner", ValueType::kString));
// int32_t max_paths; // optional
Expand All @@ -56,7 +58,21 @@ unsigned TclInitSTA::exec()
return 0;
}
std::map<std::string, std::any> config_map = TclUtil::getConfigMap(this, _config_list);
STAI.initSTA(config_map);
if (config_map.contains("-min_slew_degradation")) {
std::string value = std::any_cast<std::string>(config_map.at("-min_slew_degradation"));
if (value != "0" && value != "1") {
Tcl_SetObjResult(ecc::ScriptEngine::getOrCreateInstance()->get_interp(),
Tcl_NewStringObj("-min_slew_degradation must be 0 or 1", -1));
return 0;
}
config_map["-min_slew_degradation"] = int32_t(value == "1");
}
try {
STAI.initSTA(config_map);
} catch (const std::exception& error) {
Tcl_SetObjResult(ecc::ScriptEngine::getOrCreateInstance()->get_interp(), Tcl_NewStringObj(error.what(), -1));
return 0;
}
return 1;
}

Expand Down
33 changes: 33 additions & 0 deletions src/operation/iSTA/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,3 +20,36 @@ src/operation/iSTA/
Keep command and external API boundaries in `interface/`. Keep shared iSTA
state in `source/data_manager/`. Add concrete algorithm stages under
`source/module/<stage>/` only when the stage design is known.

## Minimum slew during RC propagation

`init_sta -min_slew_degradation 1` (the default) propagates the calculated
receiver waveform slew. The same integer option is accepted by the C++ config
map and the Python dictionary/JSON bindings. Values other than `0` or `1` are
rejected. As with other Python configuration fields, an empty dictionary/JSON
string leaves the option unspecified. Configure it before starting a run;
changing the internal config after calculation requires reinitializing the
delay calculator and its caches.

`-min_slew_degradation 0` enables an experimental early-mode approximation for
cell-driven RC trees: when the moment-reduced pi resistance exceeds `0.45` times
the Arnoldi driver resistance, a receiver with matching slew thresholds and
slew derate uses the driver slew. Receivers with different slew conventions
retain their calculated waveform, including the existing library conversion.
The compatibility check applies to each load and transition; equivalent
fractional and percentage thresholds are accepted across library names.
The resistance decision uses the analysis corner and output transition.
RC wire delay and its threshold correction still use the calculated waveform.
Maximum analysis, input-port waveforms, resistance loops, and the DMP fallback
retain their previous behavior.

This approximation was evaluated against controlled PrimeTime minimum-slew
runs. Restricting it to compatible slew conventions avoids applying the
approximation to unvalidated library conversions, which previously worsened
some SRAM receiver delays. This is a conservative scope limit, not a
requirement of RC physics. The fitted Arnoldi resistance is a heuristic,
not an exact physical resistance derived from the delay/load slope.
Neither the ratio nor this scope limit should be treated as PrimeTime's
complete algorithm. Some paths improve and others regress, so the option
remains experimental. It does not resolve all driver-model or SDF coverage
differences.
9 changes: 9 additions & 0 deletions src/operation/iSTA/interface/STAInterface.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@
// ***************************************************************************************
#include "STAInterface.hpp"

#include <stdexcept>

#ifdef __GLIBC__
#include <malloc.h>
#endif
Expand Down Expand Up @@ -70,6 +72,12 @@ void STAInterface::destroyInst()

void STAInterface::initSTA(std::map<std::string, std::any> config_map)
{
if (config_map.contains("-min_slew_degradation")) {
int32_t value = std::any_cast<int32_t>(config_map.at("-min_slew_degradation"));
if (value != 0 && value != 1) {
throw std::invalid_argument("-min_slew_degradation must be 0 or 1");
}
}
Logger::initInst();
// clang-format off
STALOG.info(Loc::current(), ">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>");
Expand Down Expand Up @@ -257,6 +265,7 @@ void STAInterface::wrapConfig(std::map<std::string, std::any>& config_map)
STADM.getConfig().output_timing_reports = STAUTIL.getConfigValue<int32_t>(config_map, "-output_timing_reports", 1);
STADM.getConfig().output_timing_features = STAUTIL.getConfigValue<int32_t>(config_map, "-output_timing_features", 1);
STADM.getConfig().timing_path_limit = STAUTIL.getConfigValue<int32_t>(config_map, "-timing_path_limit", 20);
STADM.getConfig().min_slew_degradation = STAUTIL.getConfigValue<int32_t>(config_map, "-min_slew_degradation", 1);
STADM.getConfig().timing_corner = STAUTIL.getConfigValue<std::string>(config_map, "-timing_corner", "");
STADM.getConfig().is_path_report_number_specified = STAUTIL.exist(config_map, std::string("-max_paths"))
|| STAUTIL.exist(config_map, std::string("-max_path"))
Expand Down
2 changes: 2 additions & 0 deletions src/operation/iSTA/source/data_manager/DataManager.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -351,6 +351,8 @@ void DataManager::printConfig()
STALOG.info(Loc::current(), STAUTIL.getSpaceByTabNum(2), _config.output_timing_reports);
STALOG.info(Loc::current(), STAUTIL.getSpaceByTabNum(1), "output_timing_features");
STALOG.info(Loc::current(), STAUTIL.getSpaceByTabNum(2), _config.output_timing_features);
STALOG.info(Loc::current(), STAUTIL.getSpaceByTabNum(1), "min_slew_degradation");
STALOG.info(Loc::current(), STAUTIL.getSpaceByTabNum(2), _config.min_slew_degradation);
STALOG.info(Loc::current(), STAUTIL.getSpaceByTabNum(1), "timing_path_limit");
STALOG.info(Loc::current(), STAUTIL.getSpaceByTabNum(2), _config.timing_path_limit);
// ********** STA ********** //
Expand Down
1 change: 1 addition & 0 deletions src/operation/iSTA/source/data_manager/advance/Config.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ class Config
int32_t output_timing_reports = 1;
int32_t output_timing_features = 1;
int32_t timing_path_limit = 20;
int32_t min_slew_degradation = 1;
std::string timing_corner;
bool is_path_report_number_specified = false;
bool has_timing_report_slack_lesser_than = false;
Expand Down
Loading
Loading