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
6 changes: 4 additions & 2 deletions src/interface/python/py_ista/py_ista_utils.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,8 @@ 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)));
}
for (const std::string key : {"-min_slew_degradation", "-adjust_driver_resistance"}) {
for (const std::string key :
{"-min_slew_degradation", "-adjust_driver_resistance", "-small_rc_fanout_reduction", "-check_constant_capacitance"}) {
value = ecc::getJsonData(json, {"STA", key});
if (!value.empty()) {
if (value != "0" && value != "1")
Expand Down Expand Up @@ -115,7 +116,8 @@ 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"]);
}
for (const std::string key : {"-min_slew_degradation", "-adjust_driver_resistance"}) {
for (const std::string key :
{"-min_slew_degradation", "-adjust_driver_resistance", "-small_rc_fanout_reduction", "-check_constant_capacitance"}) {
const auto found = config_dict.find(key);
if (found != config_dict.end() && !found->second.empty()) {
const std::string& value = found->second;
Expand Down
5 changes: 4 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 @@ -38,6 +38,8 @@ TclInitSTA::TclInitSTA(const char* cmd_name) : TclCmd(cmd_name)
// int32_t min_slew_degradation; // optional
_config_list.push_back(std::make_pair("-min_slew_degradation", ValueType::kString));
_config_list.push_back(std::make_pair("-adjust_driver_resistance", ValueType::kString));
_config_list.push_back(std::make_pair("-small_rc_fanout_reduction", ValueType::kString));
_config_list.push_back(std::make_pair("-check_constant_capacitance", 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 @@ -60,7 +62,8 @@ unsigned TclInitSTA::exec()
return 0;
}
std::map<std::string, std::any> config_map = TclUtil::getConfigMap(this, _config_list);
for (const std::string key : {"-min_slew_degradation", "-adjust_driver_resistance"}) {
for (const std::string key :
{"-min_slew_degradation", "-adjust_driver_resistance", "-small_rc_fanout_reduction", "-check_constant_capacitance"}) {
if (!config_map.contains(key))
continue;
std::string value = std::any_cast<std::string>(config_map.at(key));
Expand Down
56 changes: 28 additions & 28 deletions src/operation/iSTA/interface/MinTimingDataExporter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -17,11 +17,11 @@
#include "PinCapacitanceCalculator.hpp"
#include "TimingData.hpp"
#include "graph/TimingStateQuery.hpp"
#include "timing_checker/PathChecker.hpp"
#include "liberty/TimingArc.hpp"
#include "liberty/TimingCheckArc.hpp"
#include "network/Instance.hpp"
#include "network/Pin.hpp"
#include "timing_checker/PathChecker.hpp"

namespace ista {
namespace {
Expand All @@ -46,8 +46,7 @@ bool hasMinCaptureState(Database& database, const std::string& pin_name, TransTy
for (const auto& [clock_name, state] : point->second.get_clock_state_map()) {
if (state.is_source_path_only || !database.sdc().get_clock_map().contains(clock_name))
continue;
if (state.is_structural
&& !clockPinValues(database, pin_name, clock_name, AnalysisType::kMin, transition).propagated)
if (state.is_structural && !clockPinValues(database, pin_name, clock_name, AnalysisType::kMin, transition).propagated)
return true;
const auto value = state.arrival(AnalysisType::kMin, transition);
if (value.has_value() && std::isfinite(*value))
Expand Down Expand Up @@ -93,20 +92,17 @@ bool hasCheckTable(const LibertyArcData& arc, std::size_t edge)
return edge == 0 ? !arc.rise_check.values.empty() : !arc.fall_check.values.empty();
}

TimingMinQualification qualifyMinCheck(Database& database, const TimingEndpointArcData& endpoint,
const TimingData& snapshot, const std::set<MinCheckKey>& active_checks)
TimingMinQualification qualifyMinCheck(Database& database, const TimingEndpointArcData& endpoint, const TimingData& snapshot,
const std::set<MinCheckKey>& active_checks)
{
const auto check_type = static_cast<TimingCheckType>(endpoint.check_type);
if (check_type != TimingCheckType::kHold && check_type != TimingCheckType::kRemoval)
return excluded(TimingMinQualificationReason::kNotMinCheck);
if (!hasMinCaptureState(database, endpoint.source_pin, endpoint.timing_type == 1 ? TransType::kRise : TransType::kFall))
return excluded(TimingMinQualificationReason::kNoCaptureClockState);
auto result = excluded(TimingMinQualificationReason::kInactiveCheck);
const auto cell = std::find_if(snapshot.lib_cells.begin(), snapshot.lib_cells.end(), [&](const auto& value) {
return value.name == endpoint.library_cell;
});
if (cell == snapshot.lib_cells.end() || endpoint.library_arc_id < 0
|| static_cast<std::size_t>(endpoint.library_arc_id) >= cell->arcs.size())
const auto cell = std::find_if(snapshot.lib_cells.begin(), snapshot.lib_cells.end(), [&](const auto& value) { return value.name == endpoint.library_cell; });
if (cell == snapshot.lib_cells.end() || endpoint.library_arc_id < 0 || static_cast<std::size_t>(endpoint.library_arc_id) >= cell->arcs.size())
return excluded(TimingMinQualificationReason::kInactiveCheck);
const auto& arc = cell->arcs[endpoint.library_arc_id];
for (std::size_t edge = 0; edge < 2; ++edge) {
Expand All @@ -115,8 +111,7 @@ TimingMinQualification qualifyMinCheck(Database& database, const TimingEndpointA
continue;
}
auto active = [&](int32_t capture_transition) {
return active_checks.contains({endpoint.source_pin, endpoint.sink_pin, endpoint.check_type,
edge == 0 ? 1 : -1, capture_transition});
return active_checks.contains({endpoint.source_pin, endpoint.sink_pin, endpoint.check_type, edge == 0 ? 1 : -1, capture_transition});
};
const bool legal_context = endpoint.timing_type == 0 ? active(1) || active(-1) : active(endpoint.timing_type);
result.valid[edge] = hasCheckTable(arc, edge) && legal_context;
Expand All @@ -139,8 +134,7 @@ void exportMinTiming(TimingData& snapshot, Database& database, const Config& con
pin.min_rise_aat_ps = pin.min_fall_aat_ps = 9.0e7;
pin.min_rise_rat_ps = pin.min_fall_rat_ps = -9.0e7;
pins.emplace(pin.name, &pin);
if (pin.is_port && (pin.direction == static_cast<int32_t>(PinDirection::kOutput)
|| pin.direction == static_cast<int32_t>(PinDirection::kInout))) {
if (pin.is_port && (pin.direction == static_cast<int32_t>(PinDirection::kOutput) || pin.direction == static_cast<int32_t>(PinDirection::kInout))) {
// HoldRC adds these to endpoint pin caps before summing the net load.
// Export only this output port's external load, never the other sinks.
pin.min_output_rise_load_pf = pin_capacitance.pinCapacitance(pin.name, AnalysisType::kMin, TransType::kRise) * snapshot.capacitance_unit_pf;
Expand Down Expand Up @@ -177,7 +171,7 @@ void exportMinTiming(TimingData& snapshot, Database& database, const Config& con
}
if (start_points.contains(name)) {
const auto key = std::make_tuple(name, path.get_clock_name(), path.get_path_state_tag(), static_cast<int32_t>(source_type),
transitionCode(transition), transitionCode(path.get_launch_clock_trans_type()));
transitionCode(transition), transitionCode(path.get_launch_clock_trans_type()));
if (launch_keys.insert(key).second) {
TimingMinLaunchData launch;
launch.start_point = name;
Expand All @@ -191,18 +185,18 @@ void exportMinTiming(TimingData& snapshot, Database& database, const Config& con
launch.slew_ps = path.get_slew() * snapshot.time_unit_ps;
launch.launch_time_ps = path.get_launch_time() * snapshot.time_unit_ps;
if (!launch.launch_pin.empty())
launch.launch_slew_ps = query.getClockSlew(launch.launch_pin, launch.launch_clock, AnalysisType::kMin,
path.get_launch_clock_trans_type(), path.get_launch_clock_trans_type())
* snapshot.time_unit_ps;
launch.launch_slew_ps = query.getClockSlew(launch.launch_pin, launch.launch_clock, AnalysisType::kMin, path.get_launch_clock_trans_type(),
path.get_launch_clock_trans_type())
* snapshot.time_unit_ps;
snapshot.min_launches.push_back(std::move(launch));
}
}
if (!endpoints.contains(name))
continue;
const auto endpoint_pin = database.network().pins().find(name);
const bool is_output_port = endpoint_pin != database.network().pins().end() && endpoint_pin->second.get_is_port()
&& (endpoint_pin->second.get_direction() == PinDirection::kOutput
|| endpoint_pin->second.get_direction() == PinDirection::kInout);
const bool is_output_port
= endpoint_pin != database.network().pins().end() && endpoint_pin->second.get_is_port()
&& (endpoint_pin->second.get_direction() == PinDirection::kOutput || endpoint_pin->second.get_direction() == PinDirection::kInout);
if (is_output_port && !hasLaunchClockState(database, path))
continue;
const auto checked = checker.checkPathCandidates(path, name, AnalysisType::kMin);
Expand All @@ -213,6 +207,8 @@ void exportMinTiming(TimingData& snapshot, Database& database, const Config& con
// consumers must retain the context before endpoint reduction.
for (const auto& candidate : checked) {
const auto& check = candidate.check();
if (check.type == TimingCheckType::kClockGatingHold)
continue; // schema 2 consumers require a Liberty hold LUT.
TimingMinContextData context;
context.start_point = path.get_start_point();
context.end_point = name;
Expand All @@ -238,9 +234,9 @@ void exportMinTiming(TimingData& snapshot, Database& database, const Config& con
context.uncertainty_ps = check.uncertainty * snapshot.time_unit_ps;
context.cppr_ps = check.reconvergence * snapshot.time_unit_ps;
if (!check.capture_pin.empty())
context.capture_slew_ps = query.getClockSlew(check.capture_pin, check.capture_clock, AnalysisType::kMin,
check.capture_pin_transition, check.capture_transition)
* snapshot.time_unit_ps;
context.capture_slew_ps
= query.getClockSlew(check.capture_pin, check.capture_clock, AnalysisType::kMin, check.capture_pin_transition, check.capture_transition)
* snapshot.time_unit_ps;
if (!context.launch_pin.empty())
context.launch_clock_slew_ps = query.getClockSlew(context.launch_pin, context.launch_clock, AnalysisType::kMin,
path.get_launch_clock_trans_type(), path.get_launch_clock_trans_type())
Expand Down Expand Up @@ -291,13 +287,17 @@ void exportMinTiming(TimingData& snapshot, Database& database, const Config& con
std::set<MinCheckKey> active_checks;
for (const auto& context : snapshot.min_contexts)
if (context.check_type != 0)
active_checks.emplace(context.capture_pin, context.end_point, context.check_type,
context.data_transition, context.capture_pin_transition);
active_checks.emplace(context.capture_pin, context.end_point, context.check_type, context.data_transition, context.capture_pin_transition);
for (auto& arc : snapshot.timing_check_arcs)
arc.min_qualification = qualifyMinCheck(database, arc, snapshot, active_checks);
for (auto& arc : snapshot.constraint_arcs)
arc.min_qualification = qualifyMinCheck(database, arc, snapshot, active_checks);
for (auto& pin : snapshot.pins) {
if (database.graph().clockGatingChecks().contains(pin.name)) {
pin.min_qualification.valid = {false, false};
pin.min_qualification.reason = {TimingMinQualificationReason::kUnsupportedConstraint, TimingMinQualificationReason::kUnsupportedConstraint};
continue;
}
if (pin.is_port) {
auto output = qualifyMinOutput(database, pin.name);
const bool has_output_context = pin.min_qualification.valid[0] || pin.min_qualification.valid[1];
Expand All @@ -317,8 +317,8 @@ void exportMinTiming(TimingData& snapshot, Database& database, const Config& con
pin.min_qualification.valid[edge] = false;
pin.min_qualification.reason[edge] = TimingMinQualificationReason::kDisabledTransition;
} else if (pin.min_qualification.valid[edge] && !pin.min_path_valid[edge]
&& !(pin.is_port && (pin.direction == static_cast<int32_t>(PinDirection::kOutput)
|| pin.direction == static_cast<int32_t>(PinDirection::kInout)))) {
&& !(pin.is_port
&& (pin.direction == static_cast<int32_t>(PinDirection::kOutput) || pin.direction == static_cast<int32_t>(PinDirection::kInout)))) {
pin.min_qualification.valid[edge] = false;
pin.min_qualification.reason[edge] = TimingMinQualificationReason::kNoMinPathState;
}
Expand Down
16 changes: 8 additions & 8 deletions src/operation/iSTA/interface/STAInterface.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -146,7 +146,7 @@ bool STAInterface::initSTA(std::map<std::string, std::any> config_map)

bool STAInterface::initialize(std::map<std::string, std::any> config_map, InputScope scope)
{
for (const std::string key : {"-min_slew_degradation", "-adjust_driver_resistance"}) {
for (const std::string key : {"-min_slew_degradation", "-adjust_driver_resistance", "-small_rc_fanout_reduction", "-check_constant_capacitance"}) {
if (config_map.contains(key)) {
int32_t value = std::any_cast<int32_t>(config_map.at(key));
if (value != 0 && value != 1)
Expand Down Expand Up @@ -175,7 +175,7 @@ bool STAInterface::initialize(std::map<std::string, std::any> config_map, InputS
STALOG.info(Loc::current(), "Starting...");

DataManager::initInst();
readDesign(config_map, scope);
readDesign(config_map);
DelayCalculator::initInst();
SdcCommand::initInst();
sdc::registerSdcCommands(SdcCommand::getInst());
Expand All @@ -184,6 +184,8 @@ bool STAInterface::initialize(std::map<std::string, std::any> config_map, InputS
if (!file.empty())
readHierarchy(STADM.getDatabase().network(), *dmInst->get_idb_layout(), file);
}
if (scope == InputScope::kTiming)
ReadParasitics(STADM.getDatabase().parasitics(), STADM.getDatabase().network()).read();
// Simulation values are derived from constraints and are rebuilt by analysis.
STADM.getDatabase().graph().simValues().clear();
if (!readSdc(STADM.getDatabase().sdc())) {
Expand Down Expand Up @@ -220,7 +222,7 @@ void STAInterface::prepareTimingModel()
if (!_initialized) {
throw std::runtime_error("STA must be initialized before prepareTimingModel");
}
TimingAnalyzer analyzer(STADM.getDatabase(), STADC);
TimingAnalyzer analyzer(STADM.getDatabase(), STADC, STADM.getConfig().check_constant_capacitance != 0);
if (_model_ready && analyzer.isStructureCurrent()) {
return;
}
Expand All @@ -245,7 +247,7 @@ void STAInterface::runSTA()
STALOG.info(Loc::current(), "Starting...");

try {
TimingAnalyzer(STADM.getDatabase(), STADC).analyze(_model_ready);
TimingAnalyzer(STADM.getDatabase(), STADC, STADM.getConfig().check_constant_capacitance != 0).analyze(_model_ready);

TimingReporter(STADM.getDatabase(), STADM.getConfig()).report();

Expand Down Expand Up @@ -284,7 +286,7 @@ void STAInterface::extractLib()
STALOG.info(Loc::current(), "Starting...");

try {
TimingAnalyzer(STADM.getDatabase(), STADC).analyze();
TimingAnalyzer(STADM.getDatabase(), STADC, STADM.getConfig().check_constant_capacitance != 0).analyze();

auto timing_model = ModelExtractor(STADM.getDatabase()).extract();
std::string output_path = STADM.getConfig().tc_temp_directory_path;
Expand Down Expand Up @@ -392,16 +394,14 @@ ClockTreeGraphData STAInterface::exportClockTreeGraph()
return ista::exportClockTreeGraph(STADM.getDatabase());
}

void STAInterface::readDesign(std::map<std::string, std::any>& config_map, InputScope scope)
void STAInterface::readDesign(std::map<std::string, std::any>& config_map)
{
Monitor monitor;
STALOG.info(Loc::current(), "Starting...");
STADM.readConfig(config_map);
STADM.getDatabase().sdc().set_sdc_file_path(dmInst->get_config().get_sdc_path());
readNetwork(STADM.getDatabase().network());
ReadLiberty(STADM.getDatabase().liberty(), STADM.getDatabase().network()).read();
if (scope == InputScope::kTiming)
ReadParasitics(STADM.getDatabase().parasitics()).read();
STADM.buildDesign();
STALOG.info(Loc::current(), "Completed", monitor.getStatsInfo());
}
Expand Down
2 changes: 1 addition & 1 deletion src/operation/iSTA/interface/STAInterface.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ class STAInterface
kConstraints
};
bool initialize(std::map<std::string, std::any> config_map, InputScope scope);
void readDesign(std::map<std::string, std::any>& config_map, InputScope scope);
void readDesign(std::map<std::string, std::any>& config_map);

bool _initialized = false;
bool _model_ready = false;
Expand Down
Loading
Loading