Merge remote-tracking branch 'upstream/master'
Signed-off-by: Matt Liberty <mliberty@precisioninno.com>
This commit is contained in:
commit
b71b48ad16
|
|
@ -77,20 +77,9 @@ CcsCeffDelayCalc::gateDelay(const Pin *drvr_pin,
|
|||
const LoadPinIndexMap &load_pin_index_map,
|
||||
const DcalcAnalysisPt *dcalc_ap)
|
||||
{
|
||||
bool vdd_exists;
|
||||
LibertyCell *drvr_cell = arc->to()->libertyCell();
|
||||
const LibertyLibrary *drvr_library = drvr_cell->libertyLibrary();
|
||||
const RiseFall *rf = arc->toEdge()->asRiseFall();
|
||||
drvr_library->supplyVoltage("VDD", vdd_, vdd_exists);
|
||||
if (!vdd_exists)
|
||||
report_->error(1700, "VDD not defined in library %s", drvr_library->name());
|
||||
vth_ = drvr_library->outputThreshold(rf) * vdd_;
|
||||
vl_ = drvr_library->slewLowerThreshold(rf) * vdd_;
|
||||
vh_ = drvr_library->slewUpperThreshold(rf) * vdd_;
|
||||
in_slew_ = delayAsFloat(in_slew);
|
||||
load_cap_ = load_cap;
|
||||
parasitic_ = parasitic;
|
||||
drvr_cell->ensureVoltageWaveforms();
|
||||
output_waveforms_ = nullptr;
|
||||
|
||||
GateTableModel *table_model = gateTableModel(arc, dcalc_ap);
|
||||
|
|
@ -103,6 +92,18 @@ CcsCeffDelayCalc::gateDelay(const Pin *drvr_pin,
|
|||
&& output_waveforms->slewAxis()->inBounds(in_slew_)
|
||||
&& output_waveforms->capAxis()->inBounds(c2_)
|
||||
&& output_waveforms->capAxis()->inBounds(load_cap_)) {
|
||||
bool vdd_exists;
|
||||
LibertyCell *drvr_cell = arc->to()->libertyCell();
|
||||
const LibertyLibrary *drvr_library = drvr_cell->libertyLibrary();
|
||||
const RiseFall *rf = arc->toEdge()->asRiseFall();
|
||||
drvr_library->supplyVoltage("VDD", vdd_, vdd_exists);
|
||||
if (!vdd_exists)
|
||||
report_->error(1700, "VDD not defined in library %s", drvr_library->name());
|
||||
vth_ = drvr_library->outputThreshold(rf) * vdd_;
|
||||
vl_ = drvr_library->slewLowerThreshold(rf) * vdd_;
|
||||
vh_ = drvr_library->slewUpperThreshold(rf) * vdd_;
|
||||
|
||||
drvr_cell->ensureVoltageWaveforms();
|
||||
in_slew_ = delayAsFloat(in_slew);
|
||||
output_waveforms_ = output_waveforms;
|
||||
ref_time_ = output_waveforms_->referenceTime(in_slew_);
|
||||
|
|
|
|||
|
|
@ -142,8 +142,6 @@ CcsSimDelayCalc::gateDelay(const Pin *drvr_pin,
|
|||
const LoadPinIndexMap &load_pin_index_map,
|
||||
const DcalcAnalysisPt *dcalc_ap)
|
||||
{
|
||||
Vertex *drvr_vertex = graph_->pinDrvrVertex(drvr_pin);
|
||||
load_pin_index_map_ = graph_delay_calc_->makeLoadPinIndexMap(drvr_vertex);
|
||||
ArcDcalcArgSeq dcalc_args;
|
||||
dcalc_args.emplace_back(nullptr, drvr_pin, nullptr, arc, in_slew, parasitic);
|
||||
ArcDcalcResultSeq dcalc_results = gateDelays(dcalc_args, load_cap,
|
||||
|
|
@ -167,18 +165,6 @@ CcsSimDelayCalc::gateDelays(ArcDcalcArgSeq &dcalc_args,
|
|||
parasitic_network_ = dcalc_args[0].parasitic();
|
||||
ArcDcalcResultSeq dcalc_results(drvr_count_);
|
||||
|
||||
// Assume drivers are in the same library.
|
||||
LibertyCell *drvr_cell = dcalc_args[0].arc()->to()->libertyCell();
|
||||
const LibertyLibrary *drvr_library = drvr_cell->libertyLibrary();
|
||||
bool vdd_exists;
|
||||
drvr_library->supplyVoltage("VDD", vdd_, vdd_exists);
|
||||
if (!vdd_exists)
|
||||
report_->error(1720, "VDD not defined in library %s", drvr_library->name());
|
||||
vth_ = drvr_library->outputThreshold(drvr_rf_) * vdd_;
|
||||
vl_ = drvr_library->slewLowerThreshold(drvr_rf_) * vdd_;
|
||||
vh_ = drvr_library->slewUpperThreshold(drvr_rf_) * vdd_;
|
||||
drvr_cell->ensureVoltageWaveforms();
|
||||
|
||||
size_t drvr_count = dcalc_args.size();
|
||||
output_waveforms_.resize(drvr_count);
|
||||
ref_time_.resize(drvr_count);
|
||||
|
|
@ -198,6 +184,19 @@ CcsSimDelayCalc::gateDelays(ArcDcalcArgSeq &dcalc_args,
|
|||
debugPrint(debug_, "ccs_dcalc", 1, "%s %s",
|
||||
network_->libertyPort(dcalc_arg.drvrPin())->libertyCell()->name(),
|
||||
drvr_rf_->asString());
|
||||
|
||||
LibertyCell *drvr_cell = dcalc_arg.arc()->to()->libertyCell();
|
||||
const LibertyLibrary *drvr_library = drvr_cell->libertyLibrary();
|
||||
bool vdd_exists;
|
||||
drvr_library->supplyVoltage("VDD", vdd_, vdd_exists);
|
||||
if (!vdd_exists)
|
||||
report_->error(1720, "VDD not defined in library %s", drvr_library->name());
|
||||
drvr_cell->ensureVoltageWaveforms();
|
||||
if (drvr_idx == 0) {
|
||||
vth_ = drvr_library->outputThreshold(drvr_rf_) * vdd_;
|
||||
vl_ = drvr_library->slewLowerThreshold(drvr_rf_) * vdd_;
|
||||
vh_ = drvr_library->slewUpperThreshold(drvr_rf_) * vdd_;
|
||||
}
|
||||
}
|
||||
else
|
||||
dcalc_failed_ = true;
|
||||
|
|
@ -259,6 +258,8 @@ CcsSimDelayCalc::gateDelays(ArcDcalcArgSeq &dcalc_args,
|
|||
delayAsString(wire_delay, this),
|
||||
delayAsString(load_slew, this));
|
||||
|
||||
LibertyLibrary *drvr_library =
|
||||
network_->libertyPort(load_pin)->libertyCell()->libertyLibrary();
|
||||
thresholdAdjust(load_pin, drvr_library, drvr_rf_, wire_delay, load_slew);
|
||||
dcalc_result.setWireDelay(load_idx, wire_delay);
|
||||
dcalc_result.setLoadSlew(load_idx, load_slew);
|
||||
|
|
|
|||
|
|
@ -138,13 +138,9 @@ define_cmd_args "set_assigned_delay" \
|
|||
# Change the delay for timing arcs between from_pins and to_pins matching
|
||||
# on cell (instance) or net.
|
||||
proc set_assigned_delay { args } {
|
||||
set_assigned_delay_cmd "set_assigned_delay" $args
|
||||
}
|
||||
|
||||
proc set_assigned_delay_cmd { cmd cmd_args } {
|
||||
parse_key_args $cmd cmd_args keys {-corner -from -to} \
|
||||
parse_key_args "set_assigned_delay" args keys {-corner -from -to} \
|
||||
flags {-cell -net -rise -fall -max -min}
|
||||
check_argc_eq1 $cmd $cmd_args
|
||||
check_argc_eq1 "set_assigned_delay" $args
|
||||
set corner [parse_corner keys]
|
||||
set min_max [parse_min_max_all_check_flags flags]
|
||||
set to_rf [parse_rise_fall_flags flags]
|
||||
|
|
@ -152,17 +148,17 @@ proc set_assigned_delay_cmd { cmd cmd_args } {
|
|||
if [info exists keys(-from)] {
|
||||
set from_pins [get_port_pins_error "from_pins" $keys(-from)]
|
||||
} else {
|
||||
sta_error 181 "$cmd missing -from argument."
|
||||
sta_error 181 ""set_assigned_delay" missing -from argument."
|
||||
}
|
||||
if [info exists keys(-to)] {
|
||||
set to_pins [get_port_pins_error "to_pins" $keys(-to)]
|
||||
} else {
|
||||
sta_error 182 "$cmd missing -to argument."
|
||||
sta_error 182 ""set_assigned_delay" missing -to argument."
|
||||
}
|
||||
|
||||
set delay [lindex $cmd_args 0]
|
||||
set delay [lindex $args 0]
|
||||
if {![string is double $delay]} {
|
||||
sta_error 183 "$cmd delay is not a float."
|
||||
sta_error 183 ""set_assigned_delay" delay is not a float."
|
||||
}
|
||||
set delay [time_ui_sta $delay]
|
||||
|
||||
|
|
@ -173,17 +169,17 @@ proc set_assigned_delay_cmd { cmd cmd_args } {
|
|||
set inst [[lindex $from_pins 0] instance]
|
||||
foreach pin $from_pins {
|
||||
if {[$pin instance] != $inst} {
|
||||
sta_error 185 "$cmd pin [get_full_name $pin] is not attached to instance [get_full_name $inst]."
|
||||
sta_error 185 "set_assigned_delay pin [get_full_name $pin] is not attached to instance [get_full_name $inst]."
|
||||
}
|
||||
}
|
||||
foreach pin $to_pins {
|
||||
if {[$pin instance] != $inst} {
|
||||
sta_error 186 "$cmd pin [get_full_name $pin] is not attached to instance [get_full_name $inst]"
|
||||
sta_error 186 "set_assigned_delay pin [get_full_name $pin] is not attached to instance [get_full_name $inst]"
|
||||
}
|
||||
}
|
||||
}
|
||||
} elseif {![info exists flags(-net)]} {
|
||||
sta_error 187 "$cmd -cell or -net required."
|
||||
sta_error 187 "set_assigned_delay -cell or -net required."
|
||||
}
|
||||
foreach from_pin $from_pins {
|
||||
set from_vertices [$from_pin vertices]
|
||||
|
|
@ -210,6 +206,7 @@ proc set_assigned_delay1 { from_vertex to_pins to_rf corner min_max delay } {
|
|||
}
|
||||
|
||||
proc set_assigned_delay2 {from_vertex to_vertex to_rf corner min_max delay} {
|
||||
set matched 0
|
||||
set edge_iter [$from_vertex out_edge_iterator]
|
||||
while {[$edge_iter has_next]} {
|
||||
set edge [$edge_iter next]
|
||||
|
|
@ -219,11 +216,15 @@ proc set_assigned_delay2 {from_vertex to_vertex to_rf corner min_max delay} {
|
|||
if { $to_rf == "rise_fall" \
|
||||
|| $to_rf eq [$arc to_edge_name] } {
|
||||
set_arc_delay $edge $arc $corner $min_max $delay
|
||||
set matched 1
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
$edge_iter finish
|
||||
if { !$matched } {
|
||||
sta_error 193 "set_assigned_delay no timing arcs found between from/to pins."
|
||||
}
|
||||
}
|
||||
|
||||
################################################################
|
||||
|
|
@ -235,19 +236,15 @@ define_cmd_args "set_assigned_check" \
|
|||
[-cond sdf_cond] check_value}
|
||||
|
||||
proc set_assigned_check { args } {
|
||||
set_assigned_check_cmd "set_assigned_check" $args
|
||||
}
|
||||
|
||||
proc set_assigned_check_cmd { cmd cmd_args } {
|
||||
parse_key_args $cmd cmd_args \
|
||||
parse_key_args "set_assigned_check" args \
|
||||
keys {-from -to -corner -clock -cond} \
|
||||
flags {-setup -hold -recovery -removal -rise -fall -max -min}
|
||||
check_argc_eq1 $cmd $cmd_args
|
||||
check_argc_eq1 "set_assigned_check" $args
|
||||
|
||||
if { [info exists keys(-from)] } {
|
||||
set from_pins [get_port_pins_error "from_pins" $keys(-from)]
|
||||
} else {
|
||||
sta_error 188 "$cmd missing -from argument."
|
||||
sta_error 188 "set_assigned_check missing -from argument."
|
||||
}
|
||||
set from_rf "rise_fall"
|
||||
if { [info exists keys(-clock)] } {
|
||||
|
|
@ -256,14 +253,14 @@ proc set_assigned_check_cmd { cmd cmd_args } {
|
|||
|| $clk_arg eq "fall" } {
|
||||
set from_rf $clk_arg
|
||||
} else {
|
||||
sta_error 189 "$cmd -clock must be rise or fall."
|
||||
sta_error 189 "set_assigned_check -clock must be rise or fall."
|
||||
}
|
||||
}
|
||||
|
||||
if { [info exists keys(-to)] } {
|
||||
set to_pins [get_port_pins_error "to_pins" $keys(-to)]
|
||||
} else {
|
||||
sta_error 190 "$cmd missing -to argument."
|
||||
sta_error 190 "set_assigned_check missing -to argument."
|
||||
}
|
||||
set to_rf [parse_rise_fall_flags flags]
|
||||
set corner [parse_corner keys]
|
||||
|
|
@ -278,15 +275,15 @@ proc set_assigned_check_cmd { cmd cmd_args } {
|
|||
} elseif { [info exists flags(-removal)] } {
|
||||
set role "removal"
|
||||
} else {
|
||||
sta_error 191 "$cmd missing -setup|-hold|-recovery|-removal check type.."
|
||||
sta_error 191 "set_assigned_check missing -setup|-hold|-recovery|-removal check type.."
|
||||
}
|
||||
set cond ""
|
||||
if { [info exists key(-cond)] } {
|
||||
set cond $key(-cond)
|
||||
}
|
||||
set check_value [lindex $cmd_args 0]
|
||||
set check_value [lindex $args 0]
|
||||
if { ![string is double $check_value] } {
|
||||
sta_error 192 "$cmd check_value is not a float."
|
||||
sta_error 192 ""set_assigned_check" check_value is not a float."
|
||||
}
|
||||
set check_value [time_ui_sta $check_value]
|
||||
|
||||
|
|
@ -319,6 +316,7 @@ proc set_assigned_check1 { from_vertex from_rf to_pins to_rf \
|
|||
proc set_assigned_check2 { from_vertex from_rf to_vertex to_rf \
|
||||
role corner min_max cond check_value } {
|
||||
set edge_iter [$from_vertex out_edge_iterator]
|
||||
set matched 0
|
||||
while {[$edge_iter has_next]} {
|
||||
set edge [$edge_iter next]
|
||||
if { [$edge to] == $to_vertex } {
|
||||
|
|
@ -330,11 +328,15 @@ proc set_assigned_check2 { from_vertex from_rf to_vertex to_rf \
|
|||
&& [$arc role] eq $role \
|
||||
&& ($cond eq "" || [$arc sdf_cond] eq $cond) } {
|
||||
set_arc_delay $edge $arc $corner $min_max $check_value
|
||||
set matched 1
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
$edge_iter finish
|
||||
if { !$matched } {
|
||||
sta_error 194 "set_assigned_check no check arcs found between from/to pins."
|
||||
}
|
||||
}
|
||||
|
||||
################################################################a
|
||||
|
|
|
|||
|
|
@ -16,6 +16,14 @@ replaced with the -reduce flag. With the -reduce flag, the current
|
|||
delay calculator reduces the parastic network to the appropriate type
|
||||
and deletes the parasitic network.
|
||||
|
||||
The report_clock_skew and report_clock_latency commands now supports
|
||||
the -include_internal_latency flag to control inclusion of macro
|
||||
internal clock delays from the cell liberty min/max_clock_tree_path
|
||||
timing groups.
|
||||
|
||||
report_clock_skew -include_internal_latency
|
||||
report_clock_latency -include_internal_latency
|
||||
|
||||
Release 2.4.0 2023/01/19
|
||||
-------------------------
|
||||
|
||||
|
|
|
|||
BIN
doc/OpenSTA.odt
BIN
doc/OpenSTA.odt
Binary file not shown.
BIN
doc/OpenSTA.pdf
BIN
doc/OpenSTA.pdf
Binary file not shown.
|
|
@ -179,6 +179,11 @@ public:
|
|||
const PathVertex *tgt_clk_path,
|
||||
const TimingRole *check_role,
|
||||
const StaState *sta);
|
||||
// Non inter-clock uncertainty.
|
||||
static float checkTgtClkUncertainty(const PathVertex *tgt_clk_path,
|
||||
const ClockEdge *tgt_clk_edge,
|
||||
const TimingRole *check_role,
|
||||
const StaState *sta);
|
||||
static float checkSetupMcpAdjustment(const ClockEdge *src_clk_edge,
|
||||
const ClockEdge *tgt_clk_edge,
|
||||
const MultiCyclePath *mcp,
|
||||
|
|
@ -187,10 +192,6 @@ public:
|
|||
|
||||
protected:
|
||||
PathEnd(Path *path);
|
||||
static float checkNonInterClkUncertainty(const PathVertex *tgt_clk_path,
|
||||
const ClockEdge *tgt_clk_edge,
|
||||
const TimingRole *check_role,
|
||||
const StaState *sta);
|
||||
static void checkInterClkUncertainty(const ClockEdge *src_clk_edge,
|
||||
const ClockEdge *tgt_clk_edge,
|
||||
const TimingRole *check_role,
|
||||
|
|
|
|||
|
|
@ -914,14 +914,18 @@ public:
|
|||
void reportClkSkew(ConstClockSeq clks,
|
||||
const Corner *corner,
|
||||
const SetupHold *setup_hold,
|
||||
bool include_internal_latency,
|
||||
int digits);
|
||||
float findWorstClkSkew(const SetupHold *setup_hold);
|
||||
float findWorstClkSkew(const SetupHold *setup_hold,
|
||||
bool include_internal_latency);
|
||||
|
||||
void reportClkLatency(ConstClockSeq clks,
|
||||
const Corner *corner,
|
||||
bool include_internal_latency,
|
||||
int digits);
|
||||
// Find min/max/rise/fall delays for clk.
|
||||
ClkDelays findClkDelays(const Clock *clk);
|
||||
ClkDelays findClkDelays(const Clock *clk,
|
||||
bool include_internal_latency);
|
||||
|
||||
// Update arrival times for all pins.
|
||||
// If necessary updateTiming propagates arrivals around latch
|
||||
|
|
|
|||
|
|
@ -33,7 +33,7 @@ public:
|
|||
// Return values.
|
||||
Delay &insertion,
|
||||
Delay &delay,
|
||||
float &lib_clk_delay,
|
||||
float &internal_latency,
|
||||
Delay &latency,
|
||||
PathVertex &path,
|
||||
bool &exists) const;
|
||||
|
|
@ -49,6 +49,7 @@ public:
|
|||
const RiseFall *end_rf,
|
||||
const MinMax *min_max,
|
||||
PathVertex *path,
|
||||
bool include_internal_latency,
|
||||
StaState *sta);
|
||||
|
||||
private:
|
||||
|
|
@ -61,7 +62,7 @@ private:
|
|||
|
||||
Delay insertion_[RiseFall::index_count][RiseFall::index_count][MinMax::index_count];
|
||||
Delay delay_[RiseFall::index_count][RiseFall::index_count][MinMax::index_count];
|
||||
float lib_clk_delay_[RiseFall::index_count][RiseFall::index_count][MinMax::index_count];
|
||||
float internal_latency_[RiseFall::index_count][RiseFall::index_count][MinMax::index_count];
|
||||
Delay latency_[RiseFall::index_count][RiseFall::index_count][MinMax::index_count];
|
||||
PathVertex path_[RiseFall::index_count][RiseFall::index_count][MinMax::index_count];
|
||||
bool exists_[RiseFall::index_count][RiseFall::index_count][MinMax::index_count];
|
||||
|
|
|
|||
|
|
@ -40,20 +40,23 @@ ClkLatency::ClkLatency(StaState *sta) :
|
|||
|
||||
ClkDelays
|
||||
ClkLatency::findClkDelays(const Clock *clk,
|
||||
const Corner *corner)
|
||||
const Corner *corner,
|
||||
bool include_internal_latency)
|
||||
{
|
||||
ConstClockSeq clks;
|
||||
clks.push_back(clk);
|
||||
ClkDelayMap clk_delay_map = findClkDelays(clks, corner);
|
||||
ClkDelayMap clk_delay_map = findClkDelays(clks, corner,
|
||||
include_internal_latency);
|
||||
return clk_delay_map[clk];
|
||||
}
|
||||
|
||||
void
|
||||
ClkLatency::reportClkLatency(ConstClockSeq clks,
|
||||
const Corner *corner,
|
||||
bool include_internal_latency,
|
||||
int digits)
|
||||
{
|
||||
ClkDelayMap clk_delay_map = findClkDelays(clks, corner);
|
||||
ClkDelayMap clk_delay_map = findClkDelays(clks, corner, include_internal_latency);
|
||||
|
||||
// Sort the clocks to report in a stable order.
|
||||
ConstClockSeq sorted_clks;
|
||||
|
|
@ -80,20 +83,20 @@ ClkLatency::reportClkLatency(const Clock *clk,
|
|||
PathVertex path_min;
|
||||
Delay insertion_min;
|
||||
Delay delay_min;
|
||||
float lib_clk_delay_min;
|
||||
float internal_latency_min;
|
||||
Delay latency_min;
|
||||
bool exists_min;
|
||||
clk_delays.delay(src_rf, end_rf, MinMax::min(), insertion_min,
|
||||
delay_min, lib_clk_delay_min, latency_min,
|
||||
delay_min, internal_latency_min, latency_min,
|
||||
path_min, exists_min);
|
||||
PathVertex path_max;
|
||||
Delay insertion_max;
|
||||
Delay delay_max;
|
||||
float lib_clk_delay_max;
|
||||
float internal_latency_max;
|
||||
Delay latency_max;
|
||||
bool exists_max;
|
||||
clk_delays.delay(src_rf, end_rf, MinMax::max(), insertion_max,
|
||||
delay_max, lib_clk_delay_max, latency_max,
|
||||
delay_max, internal_latency_max, latency_max,
|
||||
path_max, exists_max);
|
||||
if (exists_min & exists_max) {
|
||||
report_->reportLine("%s -> %s",
|
||||
|
|
@ -112,11 +115,11 @@ ClkLatency::reportClkLatency(const Clock *clk,
|
|||
"",
|
||||
delayAsString(delay_max, this, digits),
|
||||
sdc_network_->pathName(path_max.pin(this)));
|
||||
if (lib_clk_delay_min != 0.0
|
||||
|| lib_clk_delay_max != 0.0)
|
||||
report_->reportLine("%7s %7s liberty clock tree delay",
|
||||
time_unit->asString(lib_clk_delay_min, digits),
|
||||
time_unit->asString(lib_clk_delay_max, digits));
|
||||
if (internal_latency_min != 0.0
|
||||
|| internal_latency_max != 0.0)
|
||||
report_->reportLine("%7s %7s internal clock latency",
|
||||
time_unit->asString(internal_latency_min, digits),
|
||||
time_unit->asString(internal_latency_max, digits));
|
||||
report_->reportLine("---------------");
|
||||
report_->reportLine("%7s %7s latency",
|
||||
delayAsString(latency_min, this, digits),
|
||||
|
|
@ -132,7 +135,8 @@ ClkLatency::reportClkLatency(const Clock *clk,
|
|||
|
||||
ClkDelayMap
|
||||
ClkLatency::findClkDelays(ConstClockSeq clks,
|
||||
const Corner *corner)
|
||||
const Corner *corner,
|
||||
bool include_internal_latency)
|
||||
{
|
||||
ClkDelayMap clk_delay_map;
|
||||
// Make entries for the relevant clocks to filter path clocks.
|
||||
|
|
@ -159,7 +163,8 @@ ClkLatency::findClkDelays(ConstClockSeq clks,
|
|||
bool exists;
|
||||
clk_delays.latency(clk_rf, end_rf, min_max, clk_latency, exists);
|
||||
if (!exists || delayGreater(latency, clk_latency, min_max, this))
|
||||
clk_delays.setLatency(clk_rf, end_rf, min_max, path, this);
|
||||
clk_delays.setLatency(clk_rf, end_rf, min_max, path,
|
||||
include_internal_latency, this);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -176,7 +181,7 @@ ClkDelays::ClkDelays()
|
|||
for (auto mm_index : MinMax::rangeIndex()) {
|
||||
insertion_[src_rf_index][end_rf_index][mm_index] = 0.0;
|
||||
delay_[src_rf_index][end_rf_index][mm_index] = 0.0;
|
||||
lib_clk_delay_[src_rf_index][end_rf_index][mm_index] = 0.0;
|
||||
internal_latency_[src_rf_index][end_rf_index][mm_index] = 0.0;
|
||||
latency_[src_rf_index][end_rf_index][mm_index] = 0.0;
|
||||
exists_[src_rf_index][end_rf_index][mm_index] = false;
|
||||
}
|
||||
|
|
@ -202,7 +207,7 @@ ClkDelays::delay(const RiseFall *src_rf,
|
|||
path = path_[src_rf_index][end_rf_index][mm_index];
|
||||
insertion = insertion_[src_rf_index][end_rf_index][mm_index];
|
||||
delay = delay_[src_rf_index][end_rf_index][mm_index];
|
||||
lib_clk_delay = lib_clk_delay_[src_rf_index][end_rf_index][mm_index];
|
||||
lib_clk_delay = internal_latency_[src_rf_index][end_rf_index][mm_index];
|
||||
latency = latency_[src_rf_index][end_rf_index][mm_index];
|
||||
exists = exists_[src_rf_index][end_rf_index][mm_index];
|
||||
}
|
||||
|
|
@ -227,6 +232,7 @@ ClkDelays::setLatency(const RiseFall *src_rf,
|
|||
const RiseFall *end_rf,
|
||||
const MinMax *min_max,
|
||||
PathVertex *path,
|
||||
bool include_internal_latency,
|
||||
StaState *sta)
|
||||
{
|
||||
int src_rf_index = src_rf->index();
|
||||
|
|
@ -239,10 +245,13 @@ ClkDelays::setLatency(const RiseFall *src_rf,
|
|||
float delay1 = delay(path, sta);
|
||||
delay_[src_rf_index][end_rf_index][mm_index] = delay1;
|
||||
|
||||
float lib_clk_delay = clkTreeDelay(path, sta);
|
||||
lib_clk_delay_[src_rf_index][end_rf_index][mm_index] = lib_clk_delay;
|
||||
float internal_latency = 0.0;
|
||||
if (include_internal_latency) {
|
||||
internal_latency = clkTreeDelay(path, sta);
|
||||
internal_latency_[src_rf_index][end_rf_index][mm_index] = internal_latency;
|
||||
}
|
||||
|
||||
float latency = insertion + delay1 + lib_clk_delay;
|
||||
float latency = insertion + delay1 + internal_latency;
|
||||
latency_[src_rf_index][end_rf_index][mm_index] = latency;
|
||||
|
||||
path_[src_rf_index][end_rf_index][mm_index] = *path;
|
||||
|
|
|
|||
|
|
@ -37,13 +37,16 @@ public:
|
|||
// Report clk latency for clks.
|
||||
void reportClkLatency(ConstClockSeq clks,
|
||||
const Corner *corner,
|
||||
bool include_internal_latency,
|
||||
int digits);
|
||||
ClkDelays findClkDelays(const Clock *clk,
|
||||
const Corner *corner);
|
||||
const Corner *corner,
|
||||
bool include_internal_latency);
|
||||
|
||||
protected:
|
||||
ClkDelayMap findClkDelays(ConstClockSeq clks,
|
||||
const Corner *corner);
|
||||
const Corner *corner,
|
||||
bool include_internal_latency);
|
||||
void reportClkLatency(const Clock *clk,
|
||||
ClkDelays &clk_delays,
|
||||
int digits);
|
||||
|
|
|
|||
|
|
@ -34,6 +34,7 @@
|
|||
#include "SearchPred.hh"
|
||||
#include "Search.hh"
|
||||
#include "Crpr.hh"
|
||||
#include "PathEnd.hh"
|
||||
|
||||
namespace sta {
|
||||
|
||||
|
|
@ -46,6 +47,7 @@ public:
|
|||
ClkSkew();
|
||||
ClkSkew(PathVertex *src_path,
|
||||
PathVertex *tgt_path,
|
||||
bool include_internal_latency,
|
||||
StaState *sta);
|
||||
ClkSkew(const ClkSkew &clk_skew);
|
||||
void operator=(const ClkSkew &clk_skew);
|
||||
|
|
@ -53,9 +55,10 @@ public:
|
|||
PathVertex *tgtPath() { return &tgt_path_; }
|
||||
float srcLatency(StaState *sta);
|
||||
float tgtLatency(StaState *sta);
|
||||
float srcClkTreeDelay(StaState *sta);
|
||||
float tgtClkTreeDelay(StaState *sta);
|
||||
float srcInternalClkLatency(StaState *sta);
|
||||
float tgtInternalClkLatency(StaState *sta);
|
||||
Crpr crpr(StaState *sta);
|
||||
float uncertainty(StaState *sta);
|
||||
float skew() const { return skew_; }
|
||||
|
||||
private:
|
||||
|
|
@ -64,6 +67,7 @@ private:
|
|||
|
||||
PathVertex src_path_;
|
||||
PathVertex tgt_path_;
|
||||
bool include_internal_latency_;
|
||||
float skew_;
|
||||
};
|
||||
|
||||
|
|
@ -74,17 +78,23 @@ ClkSkew::ClkSkew() :
|
|||
|
||||
ClkSkew::ClkSkew(PathVertex *src_path,
|
||||
PathVertex *tgt_path,
|
||||
StaState *sta)
|
||||
bool include_internal_latency,
|
||||
StaState *sta) :
|
||||
src_path_(src_path),
|
||||
tgt_path_(tgt_path),
|
||||
include_internal_latency_(include_internal_latency)
|
||||
{
|
||||
src_path_ = src_path;
|
||||
tgt_path_ = tgt_path;
|
||||
skew_ = srcLatency(sta) - tgtLatency(sta) - delayAsFloat(crpr(sta));
|
||||
skew_ = srcLatency(sta)
|
||||
- tgtLatency(sta)
|
||||
- delayAsFloat(crpr(sta))
|
||||
+ uncertainty(sta);
|
||||
}
|
||||
|
||||
ClkSkew::ClkSkew(const ClkSkew &clk_skew)
|
||||
{
|
||||
src_path_ = clk_skew.src_path_;
|
||||
tgt_path_ = clk_skew.tgt_path_;
|
||||
include_internal_latency_ = clk_skew.include_internal_latency_;
|
||||
skew_ = clk_skew.skew_;
|
||||
}
|
||||
|
||||
|
|
@ -93,6 +103,7 @@ ClkSkew::operator=(const ClkSkew &clk_skew)
|
|||
{
|
||||
src_path_ = clk_skew.src_path_;
|
||||
tgt_path_ = clk_skew.tgt_path_;
|
||||
include_internal_latency_ = clk_skew.include_internal_latency_;
|
||||
skew_ = clk_skew.skew_;
|
||||
}
|
||||
|
||||
|
|
@ -105,7 +116,7 @@ ClkSkew::srcLatency(StaState *sta)
|
|||
}
|
||||
|
||||
float
|
||||
ClkSkew::srcClkTreeDelay(StaState *sta)
|
||||
ClkSkew::srcInternalClkLatency(StaState *sta)
|
||||
{
|
||||
return clkTreeDelay(src_path_, sta);
|
||||
}
|
||||
|
|
@ -119,7 +130,7 @@ ClkSkew::tgtLatency(StaState *sta)
|
|||
}
|
||||
|
||||
float
|
||||
ClkSkew::tgtClkTreeDelay(StaState *sta)
|
||||
ClkSkew::tgtInternalClkLatency(StaState *sta)
|
||||
{
|
||||
return clkTreeDelay(tgt_path_, sta);
|
||||
}
|
||||
|
|
@ -128,13 +139,17 @@ float
|
|||
ClkSkew::clkTreeDelay(PathVertex &clk_path,
|
||||
StaState *sta)
|
||||
{
|
||||
const Vertex *vertex = clk_path.vertex(sta);
|
||||
const Pin *pin = vertex->pin();
|
||||
const LibertyPort *port = sta->network()->libertyPort(pin);
|
||||
const MinMax *min_max = clk_path.minMax(sta);
|
||||
const RiseFall *rf = clk_path.transition(sta);
|
||||
float slew = delayAsFloat(clk_path.slew(sta));
|
||||
return port->clkTreeDelay(slew, rf, min_max);
|
||||
if (include_internal_latency_) {
|
||||
const Vertex *vertex = clk_path.vertex(sta);
|
||||
const Pin *pin = vertex->pin();
|
||||
const LibertyPort *port = sta->network()->libertyPort(pin);
|
||||
const MinMax *min_max = clk_path.minMax(sta);
|
||||
const RiseFall *rf = clk_path.transition(sta);
|
||||
float slew = delayAsFloat(clk_path.slew(sta));
|
||||
return port->clkTreeDelay(slew, rf, min_max);
|
||||
}
|
||||
else
|
||||
return 0.0;
|
||||
}
|
||||
|
||||
Crpr
|
||||
|
|
@ -144,6 +159,17 @@ ClkSkew::crpr(StaState *sta)
|
|||
return check_crpr->checkCrpr(&src_path_, &tgt_path_);
|
||||
}
|
||||
|
||||
float
|
||||
ClkSkew::uncertainty(StaState *sta)
|
||||
{
|
||||
TimingRole *check_role = (src_path_.minMax(sta) == SetupHold::max())
|
||||
? TimingRole::setup()
|
||||
: TimingRole::hold();
|
||||
// Uncertainty decreases slack, but increases skew.
|
||||
return -PathEnd::checkTgtClkUncertainty(&tgt_path_, tgt_path_.clkEdge(sta),
|
||||
check_role, sta);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////
|
||||
|
||||
ClkSkews::ClkSkews(StaState *sta) :
|
||||
|
|
@ -155,9 +181,11 @@ void
|
|||
ClkSkews::reportClkSkew(ConstClockSeq clks,
|
||||
const Corner *corner,
|
||||
const SetupHold *setup_hold,
|
||||
bool include_internal_latency,
|
||||
int digits)
|
||||
{
|
||||
ClkSkewMap skews = findClkSkew(clks, corner, setup_hold);
|
||||
ClkSkewMap skews = findClkSkew(clks, corner, setup_hold,
|
||||
include_internal_latency);
|
||||
|
||||
// Sort the clocks to report in a stable order.
|
||||
ConstClockSeq sorted_clks;
|
||||
|
|
@ -185,29 +213,32 @@ ClkSkews::reportClkSkew(ClkSkew &clk_skew,
|
|||
PathVertex *tgt_path = clk_skew.tgtPath();
|
||||
float src_latency = clk_skew.srcLatency(this);
|
||||
float tgt_latency = clk_skew.tgtLatency(this);
|
||||
float src_clk_tree_delay = clk_skew.srcClkTreeDelay(this);
|
||||
float tgt_clk_tree_delay = clk_skew.tgtClkTreeDelay(this);
|
||||
float src_internal_clk_latency = clk_skew.srcInternalClkLatency(this);
|
||||
float tgt_internal_clk_latency = clk_skew.tgtInternalClkLatency(this);
|
||||
float uncertainty = clk_skew.uncertainty(this);
|
||||
|
||||
if (src_clk_tree_delay != 0.0)
|
||||
src_latency -= src_clk_tree_delay;
|
||||
if (src_internal_clk_latency != 0.0)
|
||||
src_latency -= src_internal_clk_latency;
|
||||
report_->reportLine("%7s source latency %s %s",
|
||||
time_unit->asString(src_latency, digits),
|
||||
sdc_network_->pathName(src_path->pin(this)),
|
||||
src_path->transition(this)->asString());
|
||||
if (src_clk_tree_delay != 0.0)
|
||||
report_->reportLine("%7s source clock tree delay",
|
||||
time_unit->asString(src_clk_tree_delay, digits));
|
||||
if (src_internal_clk_latency != 0.0)
|
||||
report_->reportLine("%7s source internal clock delay",
|
||||
time_unit->asString(src_internal_clk_latency, digits));
|
||||
|
||||
if (tgt_clk_tree_delay != 0.0)
|
||||
tgt_latency -= tgt_clk_tree_delay;
|
||||
if (tgt_internal_clk_latency != 0.0)
|
||||
tgt_latency -= tgt_internal_clk_latency;
|
||||
report_->reportLine("%7s target latency %s %s",
|
||||
time_unit->asString(-tgt_latency, digits),
|
||||
sdc_network_->pathName(tgt_path->pin(this)),
|
||||
tgt_path->transition(this)->asString());
|
||||
if (tgt_clk_tree_delay != 0.0)
|
||||
report_->reportLine("%7s target clock tree delay",
|
||||
time_unit->asString(-tgt_clk_tree_delay, digits));
|
||||
|
||||
if (tgt_internal_clk_latency != 0.0)
|
||||
report_->reportLine("%7s target internal clock delay",
|
||||
time_unit->asString(-tgt_internal_clk_latency, digits));
|
||||
if (uncertainty != 0.0)
|
||||
report_->reportLine("%7s clock uncertainty",
|
||||
time_unit->asString(uncertainty, digits));
|
||||
report_->reportLine("%7s CRPR",
|
||||
time_unit->asString(delayAsFloat(-clk_skew.crpr(this)),
|
||||
digits));
|
||||
|
|
@ -219,12 +250,13 @@ ClkSkews::reportClkSkew(ClkSkew &clk_skew,
|
|||
|
||||
float
|
||||
ClkSkews::findWorstClkSkew(const Corner *corner,
|
||||
const SetupHold *setup_hold)
|
||||
const SetupHold *setup_hold,
|
||||
bool include_internal_latency)
|
||||
{
|
||||
ConstClockSeq clks;
|
||||
for (const Clock *clk : *sdc_->clocks())
|
||||
clks.push_back(clk);
|
||||
ClkSkewMap skews = findClkSkew(clks, corner, setup_hold);
|
||||
ClkSkewMap skews = findClkSkew(clks, corner, setup_hold, include_internal_latency);
|
||||
float worst_skew = 0.0;
|
||||
for (auto clk_skew_itr : skews) {
|
||||
ClkSkew &clk_skew = clk_skew_itr.second;
|
||||
|
|
@ -238,7 +270,8 @@ ClkSkews::findWorstClkSkew(const Corner *corner,
|
|||
ClkSkewMap
|
||||
ClkSkews::findClkSkew(ConstClockSeq &clks,
|
||||
const Corner *corner,
|
||||
const SetupHold *setup_hold)
|
||||
const SetupHold *setup_hold,
|
||||
bool include_internal_latency)
|
||||
{
|
||||
ClkSkewMap skews;
|
||||
|
||||
|
|
@ -258,7 +291,8 @@ ClkSkews::findClkSkew(ConstClockSeq &clks,
|
|||
? rf->asRiseFallBoth()
|
||||
: RiseFallBoth::riseFall();
|
||||
findClkSkewFrom(src_vertex, q_vertex, src_rf, clk_set,
|
||||
corner, setup_hold, skews);
|
||||
corner, setup_hold, include_internal_latency,
|
||||
skews);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -287,6 +321,7 @@ ClkSkews::findClkSkewFrom(Vertex *src_vertex,
|
|||
ConstClockSet &clk_set,
|
||||
const Corner *corner,
|
||||
const SetupHold *setup_hold,
|
||||
bool include_internal_latency,
|
||||
ClkSkewMap &skews)
|
||||
{
|
||||
VertexSet endpoints = findFanout(q_vertex);
|
||||
|
|
@ -306,7 +341,8 @@ ClkSkews::findClkSkewFrom(Vertex *src_vertex,
|
|||
? tgt_rf1->asRiseFallBoth()
|
||||
: RiseFallBoth::riseFall();
|
||||
findClkSkew(src_vertex, src_rf, tgt_vertex, tgt_rf,
|
||||
clk_set, corner, setup_hold, skews);
|
||||
clk_set, corner, setup_hold,
|
||||
include_internal_latency, skews);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -320,6 +356,7 @@ ClkSkews::findClkSkew(Vertex *src_vertex,
|
|||
ConstClockSet &clk_set,
|
||||
const Corner *corner,
|
||||
const SetupHold *setup_hold,
|
||||
bool include_internal_latency,
|
||||
ClkSkewMap &skews)
|
||||
{
|
||||
Unit *time_unit = units_->timeUnit();
|
||||
|
|
@ -343,7 +380,7 @@ ClkSkews::findClkSkew(Vertex *src_vertex,
|
|||
&& tgt_rf->matches(tgt_path->transition(this))
|
||||
&& tgt_path->minMax(this) == tgt_min_max
|
||||
&& tgt_path->pathAnalysisPt(this)->corner() == src_corner) {
|
||||
ClkSkew probe(src_path, tgt_path, this);
|
||||
ClkSkew probe(src_path, tgt_path, include_internal_latency, this);
|
||||
ClkSkew &clk_skew = skews[src_clk];
|
||||
debugPrint(debug_, "clk_skew", 2,
|
||||
"%s %s %s -> %s %s %s crpr = %s skew = %s",
|
||||
|
|
|
|||
|
|
@ -39,15 +39,18 @@ public:
|
|||
void reportClkSkew(ConstClockSeq clks,
|
||||
const Corner *corner,
|
||||
const SetupHold *setup_hold,
|
||||
bool include_internal_latency,
|
||||
int digits);
|
||||
// Find worst clock skew between src/target registers.
|
||||
float findWorstClkSkew(const Corner *corner,
|
||||
const SetupHold *setup_hold);
|
||||
const SetupHold *setup_hold,
|
||||
bool include_internal_latency);
|
||||
|
||||
protected:
|
||||
ClkSkewMap findClkSkew(ConstClockSeq &clks,
|
||||
const Corner *corner,
|
||||
const SetupHold *setup_hold);
|
||||
const SetupHold *setup_hold,
|
||||
bool include_internal_latency);
|
||||
bool hasClkPaths(Vertex *vertex,
|
||||
ConstClockSet &clks);
|
||||
void findClkSkewFrom(Vertex *src_vertex,
|
||||
|
|
@ -56,6 +59,7 @@ protected:
|
|||
ConstClockSet &clk_set,
|
||||
const Corner *corner,
|
||||
const SetupHold *setup_hold,
|
||||
bool include_internal_latency,
|
||||
ClkSkewMap &skews);
|
||||
void findClkSkew(Vertex *src_vertex,
|
||||
const RiseFallBoth *src_rf,
|
||||
|
|
@ -64,6 +68,7 @@ protected:
|
|||
ConstClockSet &clk_set,
|
||||
const Corner *corner,
|
||||
const SetupHold *setup_hold,
|
||||
bool include_internal_latency,
|
||||
ClkSkewMap &skews);
|
||||
VertexSet findFanout(Vertex *from);
|
||||
void reportClkSkew(ClkSkew &clk_skew,
|
||||
|
|
|
|||
|
|
@ -548,7 +548,7 @@ MakeTimingModel::findClkInsertionDelays()
|
|||
size_t clk_count = clks->size();
|
||||
if (clk_count == 1) {
|
||||
for (const Clock *clk : *clks) {
|
||||
ClkDelays delays = sta_->findClkDelays(clk);
|
||||
ClkDelays delays = sta_->findClkDelays(clk, true);
|
||||
for (const MinMax *min_max : MinMax::range()) {
|
||||
makeClkTreePaths(lib_port, min_max, TimingSense::positive_unate, delays);
|
||||
makeClkTreePaths(lib_port, min_max, TimingSense::negative_unate, delays);
|
||||
|
|
|
|||
|
|
@ -355,15 +355,14 @@ PathEnd::checkClkUncertainty(const ClockEdge *src_clk_edge,
|
|||
if (inter_exists)
|
||||
return inter_clk;
|
||||
else
|
||||
return checkNonInterClkUncertainty(tgt_clk_path, tgt_clk_edge,
|
||||
check_role, sta);
|
||||
return checkTgtClkUncertainty(tgt_clk_path, tgt_clk_edge, check_role, sta);
|
||||
}
|
||||
|
||||
float
|
||||
PathEnd::checkNonInterClkUncertainty(const PathVertex *tgt_clk_path,
|
||||
const ClockEdge *tgt_clk_edge,
|
||||
const TimingRole *check_role,
|
||||
const StaState *sta)
|
||||
PathEnd::checkTgtClkUncertainty(const PathVertex *tgt_clk_path,
|
||||
const ClockEdge *tgt_clk_edge,
|
||||
const TimingRole *check_role,
|
||||
const StaState *sta)
|
||||
{
|
||||
MinMax *min_max = check_role->pathMinMax();
|
||||
ClockUncertainties *uncertainties = nullptr;
|
||||
|
|
@ -637,8 +636,7 @@ PathEndClkConstrained::targetClkArrivalNoCrpr(const StaState *sta) const
|
|||
Delay
|
||||
PathEndClkConstrained::targetClkDelay(const StaState *sta) const
|
||||
{
|
||||
return checkTgtClkDelay(targetClkPath(), targetClkEdge(sta),
|
||||
checkRole(sta), sta);
|
||||
return checkTgtClkDelay(targetClkPath(), targetClkEdge(sta), checkRole(sta), sta);
|
||||
}
|
||||
|
||||
Delay
|
||||
|
|
@ -666,8 +664,7 @@ PathEndClkConstrained::targetNonInterClkUncertainty(const StaState *sta) const
|
|||
// This returns non inter-clock uncertainty.
|
||||
return 0.0;
|
||||
else
|
||||
return checkNonInterClkUncertainty(targetClkPath(), tgt_clk_edge,
|
||||
check_role, sta);
|
||||
return checkTgtClkUncertainty(targetClkPath(), tgt_clk_edge, check_role, sta);
|
||||
}
|
||||
|
||||
float
|
||||
|
|
@ -1018,7 +1015,9 @@ Delay
|
|||
PathEndCheck::clkSkew(const StaState *sta)
|
||||
{
|
||||
commonClkPessimism(sta);
|
||||
return sourceClkDelay(sta) - targetClkDelay(sta) - crpr_;
|
||||
return sourceClkDelay(sta) - targetClkDelay(sta) - crpr_
|
||||
// Uncertainty decreases slack, but increases skew.
|
||||
- checkTgtClkUncertainty(&clk_path_, clk_path_.clkEdge(sta), checkRole(sta), sta);
|
||||
}
|
||||
|
||||
Delay
|
||||
|
|
|
|||
|
|
@ -2604,17 +2604,21 @@ void
|
|||
Sta::reportClkSkew(ConstClockSeq clks,
|
||||
const Corner *corner,
|
||||
const SetupHold *setup_hold,
|
||||
bool include_internal_latency,
|
||||
int digits)
|
||||
{
|
||||
clkSkewPreamble();
|
||||
clk_skews_->reportClkSkew(clks, corner, setup_hold, digits);
|
||||
clk_skews_->reportClkSkew(clks, corner, setup_hold,
|
||||
include_internal_latency, digits);
|
||||
}
|
||||
|
||||
float
|
||||
Sta::findWorstClkSkew(const SetupHold *setup_hold)
|
||||
Sta::findWorstClkSkew(const SetupHold *setup_hold,
|
||||
bool include_internal_latency)
|
||||
{
|
||||
clkSkewPreamble();
|
||||
return clk_skews_->findWorstClkSkew(cmd_corner_, setup_hold);
|
||||
return clk_skews_->findWorstClkSkew(cmd_corner_, setup_hold,
|
||||
include_internal_latency);
|
||||
}
|
||||
|
||||
void
|
||||
|
|
@ -2630,19 +2634,21 @@ Sta::clkSkewPreamble()
|
|||
void
|
||||
Sta::reportClkLatency(ConstClockSeq clks,
|
||||
const Corner *corner,
|
||||
bool include_internal_latency,
|
||||
int digits)
|
||||
{
|
||||
ensureClkArrivals();
|
||||
ClkLatency clk_latency(this);
|
||||
clk_latency.reportClkLatency(clks, corner, digits);
|
||||
clk_latency.reportClkLatency(clks, corner, include_internal_latency, digits);
|
||||
}
|
||||
|
||||
ClkDelays
|
||||
Sta::findClkDelays(const Clock *clk)
|
||||
Sta::findClkDelays(const Clock *clk,
|
||||
bool include_internal_latency)
|
||||
{
|
||||
ensureClkArrivals();
|
||||
ClkLatency clk_latency(this);
|
||||
return clk_latency.findClkDelays(clk, nullptr);
|
||||
return clk_latency.findClkDelays(clk, nullptr, include_internal_latency);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////
|
||||
|
|
|
|||
|
|
@ -3666,6 +3666,9 @@ proc define_corners { args } {
|
|||
if { [get_libs -quiet *] != {} } {
|
||||
sta_error 482 "define_corners must be called before read_liberty."
|
||||
}
|
||||
if { [llength $args] == 0 } {
|
||||
sta_error 577 "define_corners must define at least one corner."
|
||||
}
|
||||
define_corners_cmd $args
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -311,15 +311,17 @@ proc delays_are_inf { delays } {
|
|||
################################################################
|
||||
|
||||
define_cmd_args "report_clock_skew" {[-setup|-hold]\
|
||||
[-clock clocks]\
|
||||
[-corner corner]\
|
||||
[-digits digits]}
|
||||
[-clock clocks]\
|
||||
[-corner corner]\
|
||||
[-include_internal_latency]
|
||||
[-digits digits]}
|
||||
|
||||
proc_redirect report_clock_skew {
|
||||
global sta_report_default_digits
|
||||
|
||||
parse_key_args "report_clock_skew" args \
|
||||
keys {-clock -corner -digits} flags {-setup -hold}
|
||||
keys {-clock -corner -digits} \
|
||||
flags {-setup -hold -include_internal_latency}
|
||||
check_argc_eq0 "report_clock_skew" $args
|
||||
|
||||
if { [info exists flags(-setup)] && [info exists flags(-hold)] } {
|
||||
|
|
@ -338,6 +340,7 @@ proc_redirect report_clock_skew {
|
|||
set clks [all_clocks]
|
||||
}
|
||||
set corner [parse_corner_or_all keys]
|
||||
set include_internal_latency [info exists flags(-include_internal_latency)]
|
||||
if [info exists keys(-digits)] {
|
||||
set digits $keys(-digits)
|
||||
check_positive_integer "-digits" $digits
|
||||
|
|
@ -345,7 +348,7 @@ proc_redirect report_clock_skew {
|
|||
set digits $sta_report_default_digits
|
||||
}
|
||||
if { $clks != {} } {
|
||||
report_clk_skew $clks $corner $setup_hold $digits
|
||||
report_clk_skew $clks $corner $setup_hold $include_internal_latency $digits
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -353,13 +356,15 @@ proc_redirect report_clock_skew {
|
|||
|
||||
define_cmd_args "report_clock_latency" {[-clock clocks]\
|
||||
[-corner corner]\
|
||||
[-include_internal_latency]
|
||||
[-digits digits]}
|
||||
|
||||
proc_redirect report_clock_latency {
|
||||
global sta_report_default_digits
|
||||
|
||||
parse_key_args "report_clock_" args \
|
||||
keys {-clock -corner -digits} flags {}
|
||||
keys {-clock -corner -digits} \
|
||||
flags {-include_internal_latency}
|
||||
check_argc_eq0 "report_clock_latency" $args
|
||||
|
||||
if [info exists keys(-clock)] {
|
||||
|
|
@ -368,6 +373,7 @@ proc_redirect report_clock_latency {
|
|||
set clks [all_clocks]
|
||||
}
|
||||
set corner [parse_corner_or_all keys]
|
||||
set include_internal_latency [info exists flags(-include_internal_latency)]
|
||||
if [info exists keys(-digits)] {
|
||||
set digits $keys(-digits)
|
||||
check_positive_integer "-digits" $digits
|
||||
|
|
@ -375,7 +381,7 @@ proc_redirect report_clock_latency {
|
|||
set digits $sta_report_default_digits
|
||||
}
|
||||
if { $clks != {} } {
|
||||
report_clk_latency $clks $corner $digits
|
||||
report_clk_latency $clks $corner $include_internal_latency $digits
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -995,10 +1001,12 @@ proc worst_slack1 { cmd args1 } {
|
|||
|
||||
################################################################
|
||||
|
||||
define_hidden_cmd_args "worst_clock_skew" {[-setup]|[-hold]}
|
||||
define_hidden_cmd_args "worst_clock_skew" \
|
||||
{[-setup]|[-hold][-include_internal_latency]}
|
||||
|
||||
proc worst_clock_skew { args } {
|
||||
parse_key_args "worst_clock_skew" args keys {} flags {-setup -hold}
|
||||
parse_key_args "worst_clock_skew" args keys {} \
|
||||
flags {-setup -hold -include_internal_latency}
|
||||
check_argc_eq0 "worst_clock_skew" $args
|
||||
if { ([info exists flags(-setup)] && [info exists flags(-hold)]) \
|
||||
|| (![info exists flags(-setup)] && ![info exists flags(-hold)]) } {
|
||||
|
|
@ -1008,7 +1016,8 @@ proc worst_clock_skew { args } {
|
|||
} elseif { [info exists flags(-hold)] } {
|
||||
set setup_hold "hold"
|
||||
}
|
||||
return [time_sta_ui [worst_clk_skew_cmd $setup_hold]]
|
||||
set include_internal_latency [info exists flags(-include_internal_latency)]
|
||||
return [time_sta_ui [worst_clk_skew_cmd $setup_hold $include_internal_latency]]
|
||||
}
|
||||
|
||||
################################################################
|
||||
|
|
|
|||
16
tcl/StaTcl.i
16
tcl/StaTcl.i
|
|
@ -3034,32 +3034,40 @@ report_path_cmd(PathRef *path)
|
|||
Sta::sta()->reportPath(path);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////
|
||||
|
||||
void
|
||||
report_clk_skew(ConstClockSeq clks,
|
||||
const Corner *corner,
|
||||
const SetupHold *setup_hold,
|
||||
bool include_internal_latency,
|
||||
int digits)
|
||||
{
|
||||
cmdLinkedNetwork();
|
||||
Sta::sta()->reportClkSkew(clks, corner, setup_hold, digits);
|
||||
Sta::sta()->reportClkSkew(clks, corner, setup_hold,
|
||||
include_internal_latency, digits);
|
||||
}
|
||||
|
||||
void
|
||||
report_clk_latency(ConstClockSeq clks,
|
||||
const Corner *corner,
|
||||
bool include_internal_latency,
|
||||
int digits)
|
||||
{
|
||||
cmdLinkedNetwork();
|
||||
Sta::sta()->reportClkLatency(clks, corner, digits);
|
||||
Sta::sta()->reportClkLatency(clks, corner, include_internal_latency, digits);
|
||||
}
|
||||
|
||||
float
|
||||
worst_clk_skew_cmd(const SetupHold *setup_hold)
|
||||
worst_clk_skew_cmd(const SetupHold *setup_hold,
|
||||
bool include_internal_latency)
|
||||
{
|
||||
cmdLinkedNetwork();
|
||||
return Sta::sta()->findWorstClkSkew(setup_hold);
|
||||
return Sta::sta()->findWorstClkSkew(setup_hold, include_internal_latency);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////
|
||||
|
||||
PinSet
|
||||
startpoints()
|
||||
{
|
||||
|
|
|
|||
Loading…
Reference in New Issue