From a46a66c2c468b93e6314e60540e8041d7df16689 Mon Sep 17 00:00:00 2001 From: Stan Lee <135666755+stanminlee@users.noreply.github.com> Date: Thu, 21 May 2026 16:28:51 -0700 Subject: [PATCH 01/23] everything minus tcl wrapper --- include/sta/ExceptionPath.hh | 31 +++++++++++++++++++ include/sta/PathEnd.hh | 3 ++ include/sta/Sdc.hh | 6 ++++ include/sta/SdcClass.hh | 1 + include/sta/Sta.hh | 6 ++++ sdc/ExceptionPath.cc | 59 ++++++++++++++++++++++++++++++++++++ sdc/Sdc.cc | 19 ++++++++++-- sdc/Sdc.i | 11 +++++++ sdc/WriteSdc.cc | 8 +++++ search/PathEnd.cc | 39 ++++++++++++++++++++++-- search/ReportPath.cc | 4 +++ search/Sta.cc | 14 ++++++++- search/VisitPathEnds.cc | 21 +++++++------ 13 files changed, 207 insertions(+), 15 deletions(-) diff --git a/include/sta/ExceptionPath.hh b/include/sta/ExceptionPath.hh index c1c099781..327ea046c 100644 --- a/include/sta/ExceptionPath.hh +++ b/include/sta/ExceptionPath.hh @@ -63,6 +63,7 @@ public: virtual bool isLoop() const { return false; } virtual bool isMultiCycle() const { return false; } virtual bool isPathDelay() const { return false; } + virtual bool isPathMargin() const { return false; } virtual bool isGroupPath() const { return false; } virtual bool isFilter() const { return false; } virtual ExceptionPathType type() const = 0; @@ -97,6 +98,7 @@ public: static int pathDelayPriority() { return 3000; } static int multiCyclePathPriority() { return 2000; } static int filterPathPriority() { return 1000; } + static int pathMarginPriority() { return 500; } static int groupPathPriority() { return 0; } // Compare the value (path delay or cycle count) to another exception // of the same priority. Because the exception "values" are floats, @@ -126,6 +128,7 @@ public: virtual bool useEndClk() const { return false; } virtual int pathMultiplier() const { return 0; } virtual float delay() const { return 0.0; } + virtual float margin() const { return 0.0; } virtual const char *name() const { return nullptr; } virtual bool isDefault() const { return false; } virtual bool ignoreClkLatency() const { return false; } @@ -224,6 +227,34 @@ protected: float delay_; }; +// set_path_margin +class PathMargin : public ExceptionPath +{ +public: + PathMargin(ExceptionFrom *from, + ExceptionThruSeq *thrus, + ExceptionTo *to, + const MinMaxAll *min_max, + float margin, + bool own_pts, + const char *comment); + virtual ExceptionPath *clone(ExceptionFrom *from, + ExceptionThruSeq *thrus, + ExceptionTo *to, + bool own_pts); + virtual bool isPathMargin() const { return true; } + virtual ExceptionPathType type() const { return ExceptionPathType::path_margin; } + virtual const char *typeString() const; + virtual bool mergeable(ExceptionPath *exception) const; + virtual bool overrides(ExceptionPath *exception) const; + virtual float margin() const { return margin_; } + virtual int typePriority() const; + virtual bool tighterThan(ExceptionPath *exception) const; + +protected: + float margin_; +}; + // set_multicycle_path class MultiCyclePath : public ExceptionPath { diff --git a/include/sta/PathEnd.hh b/include/sta/PathEnd.hh index c61eb16ae..bc57985e4 100644 --- a/include/sta/PathEnd.hh +++ b/include/sta/PathEnd.hh @@ -137,6 +137,8 @@ public: // Target clock uncertainty + inter-clk uncertainty. virtual float targetClkUncertainty(const StaState *sta) const; virtual float targetClkMcpAdjustment(const StaState *sta) const; + // Target clock path margin. + virtual float targetClkPathMargin(const StaState *sta) const; virtual const TimingRole *checkRole(const StaState *sta) const; const TimingRole *checkGenericRole(const StaState *sta) const; virtual bool pathDelayMarginIsExternal() const; @@ -257,6 +259,7 @@ public: virtual float targetNonInterClkUncertainty(const StaState *sta) const; virtual float interClkUncertainty(const StaState *sta) const; virtual float targetClkUncertainty(const StaState *sta) const; + virtual float targetClkPathMargin(const StaState *sta) const; virtual Crpr crpr(const StaState *sta) const; virtual Required requiredTime(const StaState *sta) const; virtual Slack slack(const StaState *sta) const; diff --git a/include/sta/Sdc.hh b/include/sta/Sdc.hh index e4f32afec..215117e4f 100644 --- a/include/sta/Sdc.hh +++ b/include/sta/Sdc.hh @@ -762,6 +762,12 @@ public: bool break_path, float delay, const char *comment); + void makePathMargin(ExceptionFrom *from, + ExceptionThruSeq *thrus, + ExceptionTo *to, + const MinMaxAll *min_max, + float margin, + const char *comment); bool pathDelaysWithoutTo() const { return path_delays_without_to_; } // Delete matching false/multicycle/path_delay exceptions. // Caller owns from, thrus, to exception points (and must delete them). diff --git a/include/sta/SdcClass.hh b/include/sta/SdcClass.hh index 2fece7b36..8e05222c2 100644 --- a/include/sta/SdcClass.hh +++ b/include/sta/SdcClass.hh @@ -67,6 +67,7 @@ class PortDelay; enum class AnalysisType { single, bc_wc, ocv }; enum class ExceptionPathType { false_path, loop, multi_cycle, path_delay, + path_margin, group_path, filter, any}; enum class ClockSense { positive, negative, stop }; diff --git a/include/sta/Sta.hh b/include/sta/Sta.hh index eff131a4b..063a178dd 100644 --- a/include/sta/Sta.hh +++ b/include/sta/Sta.hh @@ -517,6 +517,12 @@ public: bool break_path, float delay, const char *comment); + void makePathMargin(ExceptionFrom *from, + ExceptionThruSeq *thrus, + ExceptionTo *to, + const MinMaxAll *min_max, + float margin, + const char *comment); void makeGroupPath(const char *name, bool is_default, ExceptionFrom *from, diff --git a/sdc/ExceptionPath.cc b/sdc/ExceptionPath.cc index 163dcf653..011253ec3 100644 --- a/sdc/ExceptionPath.cc +++ b/sdc/ExceptionPath.cc @@ -564,6 +564,64 @@ PathDelay::overrides(ExceptionPath *exception) const //////////////////////////////////////////////////////////////// +PathMargin::PathMargin(ExceptionFrom *from, + ExceptionThruSeq *thrus, + ExceptionTo *to, + const MinMaxAll *min_max, + float margin, + bool own_pts, + const char *comment) : + ExceptionPath(from, thrus, to, min_max, own_pts, + pathMarginPriority() + fromThruToPriority(from, thrus, to), + comment), + margin_(margin) +{ +} + +ExceptionPath * +PathMargin::clone(ExceptionFrom *from, + ExceptionThruSeq *thrus, + ExceptionTo *to, + bool own_pts) +{ + return new PathMargin(from, thrus, to, min_max_, margin_, own_pts, comment_); +} + +int +PathMargin::typePriority() const +{ + return pathMarginPriority(); +} + +bool +PathMargin::tighterThan(ExceptionPath *) const +{ + return false; +} + +const char * +PathMargin::typeString() const +{ + return "Margin"; +} + +bool +PathMargin::mergeable(ExceptionPath *) const +{ + return false; +} + +bool +PathMargin::overrides(ExceptionPath *exception) const +{ + // A later set_path_margin with the same scope replaces the earlier one. + return exception->isPathMargin() + && exception->priority() == priority_ + && exception->minMax() == min_max_; +} + +//////////////////////////////////////////////////////////////// + FalsePath::FalsePath(ExceptionFrom *from, ExceptionThruSeq *thrus, ExceptionTo *to, @@ -624,6 +682,7 @@ FalsePath::mergeable(ExceptionPath *exception) const bool FalsePath::overrides(ExceptionPath *exception) const { + // Most recent definition overrides earlier ones. return exception->priority() == priority() && exception->minMax() == min_max_; } diff --git a/sdc/Sdc.cc b/sdc/Sdc.cc index e105e3c9c..595ab61e6 100644 --- a/sdc/Sdc.cc +++ b/sdc/Sdc.cc @@ -4086,12 +4086,26 @@ Sdc::makePathDelay(ExceptionFrom *from, const char *comment) { checkFromThrusTo(from, thrus, to); - PathDelay *exception = new PathDelay(from, thrus, to, min_max, + PathDelay *exception = new PathDelay(from, thrus, to, min_max, ignore_clk_latency, break_path, delay, true, comment); addException(exception); } +void +Sdc::makePathMargin(ExceptionFrom *from, + ExceptionThruSeq *thrus, + ExceptionTo *to, + const MinMaxAll *min_max, + float margin, + const char *comment) +{ + checkFromThrusTo(from, thrus, to); + PathMargin *exception = new PathMargin(from, thrus, to, min_max, + margin, true, comment); + addException(exception); +} + void Sdc::recordPathDelayInternalFrom(ExceptionPath *exception) { @@ -4499,7 +4513,8 @@ Sdc::addException1(ExceptionPath *exception) void Sdc::addException2(ExceptionPath *exception) { - if (exception->isMultiCycle() || exception->isPathDelay()) + if (exception->isMultiCycle() || exception->isPathDelay() + || exception->isPathMargin()) deleteMatchingExceptions(exception); recordException(exception); mergeException(exception); diff --git a/sdc/Sdc.i b/sdc/Sdc.i index a1ee1e5a4..23519a314 100644 --- a/sdc/Sdc.i +++ b/sdc/Sdc.i @@ -720,6 +720,17 @@ make_path_delay(ExceptionFrom *from, delay, comment); } +void +make_path_margin(ExceptionFrom *from, + ExceptionThruSeq *thrus, + ExceptionTo *to, + const MinMaxAll *min_max, + float margin, + const char *comment) +{ + Sta::sta()->makePathMargin(from, thrus, to, min_max, margin, comment); +} + void reset_path_cmd(ExceptionFrom * from, ExceptionThruSeq *thrus, diff --git a/sdc/WriteSdc.cc b/sdc/WriteSdc.cc index b3095d915..b44d00790 100644 --- a/sdc/WriteSdc.cc +++ b/sdc/WriteSdc.cc @@ -1295,6 +1295,10 @@ WriteSdc::writeExceptionCmd(ExceptionPath *exception) const if (exception->ignoreClkLatency()) gzprintf(stream_, " -ignore_clock_latency"); } + else if (exception->isPathMargin()) { + gzprintf(stream_, "set_path_margin"); + writeSetupHoldFlag(exception->minMax()); + } else if (exception->isGroupPath()) { if (exception->isDefault()) gzprintf(stream_, "group_path -default"); @@ -1315,6 +1319,10 @@ WriteSdc::writeExceptionValue(ExceptionPath *exception) const gzprintf(stream_, " "); writeTime(exception->delay()); } + else if (exception->isPathMargin()) { + gzprintf(stream_, " "); + writeTime(exception->margin()); + } } void diff --git a/search/PathEnd.cc b/search/PathEnd.cc index 12b539d4a..d13b1d4de 100644 --- a/search/PathEnd.cc +++ b/search/PathEnd.cc @@ -231,6 +231,12 @@ PathEnd::targetClkMcpAdjustment(const StaState *) const return 0.0; } +float +PathEnd::targetClkPathMargin(const StaState *) const +{ + return 0.0; +} + const TimingRole * PathEnd::checkRole(const StaState *) const { @@ -641,7 +647,8 @@ PathEndClkConstrained::targetClkArrivalNoCrpr(const StaState *sta) const targetClkEdge(sta), targetClkPath(), checkRole(sta), sta) - + targetClkMcpAdjustment(sta); + + targetClkMcpAdjustment(sta) + + targetClkPathMargin(sta); } Delay @@ -699,6 +706,30 @@ PathEndClkConstrained::targetClkUncertainty(const StaState *sta) const targetClkPath(), checkRole(sta), sta); } +float +PathEndClkConstrained::targetClkPathMargin(const StaState *sta) const +{ + const Sdc *sdc = sta->sdc(); + const TimingRole *role = checkRole(sta); + ExceptionPath *exception = nullptr; + int hi_priority_exception = -1; + // Look up a path margin for the target + sdc->exceptionTo(ExceptionPathType::path_margin, + path_->pin(sta), + path_->transition(sta), + targetClkEdge(sta), + role->pathMinMax(), + false, + exception, hi_priority_exception); + if (!exception) // no path margin found + return 0.0; + float margin = exception->margin(); + // Setup time margin is sign-flipped + if (role->genericRole() == TimingRole::setup()) + margin = -margin; + return margin; +} + Crpr PathEndClkConstrained::crpr(const StaState *sta) const { @@ -1426,7 +1457,8 @@ PathEndOutputDelay::targetClkArrivalNoCrpr(const StaState *sta) const return targetClkTime(sta) + tgtClkDelay(tgt_clk_edge, check_role, sta) + targetClkUncertainty(sta) - + checkMcpAdjustment(path_, tgt_clk_edge, sta); + + checkMcpAdjustment(path_, tgt_clk_edge, sta) + + targetClkPathMargin(sta); } } @@ -1967,7 +1999,8 @@ PathEndPathDelay::targetClkArrivalNoCrpr(const StaState *sta) const const ClockEdge *tgt_clk_edge = targetClkEdge(sta); if (tgt_clk_edge) return targetClkDelay(sta) - + targetClkUncertainty(sta); + + targetClkUncertainty(sta) + + targetClkPathMargin(sta); else if (clk_path_) return clk_path_->arrival(); else diff --git a/search/ReportPath.cc b/search/ReportPath.cc index eb775c841..487f6bae1 100644 --- a/search/ReportPath.cc +++ b/search/ReportPath.cc @@ -2653,6 +2653,10 @@ ReportPath::reportClkUncertainty(const PathEnd *end, if (inter_uncertainty != 0.0) reportLine("inter-clock uncertainty", inter_uncertainty, clk_arrival, early_late); + float margin = end->targetClkPathMargin(this); + clk_arrival += margin; + if (margin != 0.0) + reportLine("path margin", margin, clk_arrival, early_late); } //////////////////////////////////////////////////////////////// diff --git a/search/Sta.cc b/search/Sta.cc index d34ffecbd..345e46cbc 100644 --- a/search/Sta.cc +++ b/search/Sta.cc @@ -2000,13 +2000,25 @@ Sta::makePathDelay(ExceptionFrom *from, float delay, const char *comment) { - sdc_->makePathDelay(from, thrus, to, min_max, + sdc_->makePathDelay(from, thrus, to, min_max, ignore_clk_latency, break_path, delay, comment); search_->endpointsInvalid(); search_->arrivalsInvalid(); } +void +Sta::makePathMargin(ExceptionFrom *from, + ExceptionThruSeq *thrus, + ExceptionTo *to, + const MinMaxAll *min_max, + float margin, + const char *comment) +{ + sdc_->makePathMargin(from, thrus, to, min_max, margin, comment); + search_->arrivalsInvalid(); +} + void Sta::resetPath(ExceptionFrom *from, ExceptionThruSeq *thrus, diff --git a/search/VisitPathEnds.cc b/search/VisitPathEnds.cc index b5a762d54..ec914ce87 100644 --- a/search/VisitPathEnds.cc +++ b/search/VisitPathEnds.cc @@ -178,12 +178,12 @@ VisitPathEnds::visitCheckEnd(const Pin *pin, && tgt_clk != sdc_->defaultArrivalClock() && sdc_->sameClockGroup(src_clk, tgt_clk) && !sdc_->clkStopPropagation(tgt_pin, tgt_clk) - // False paths and path delays override - // paths. + // False paths, path delays, and path margins override && (exception == nullptr || exception->isFilter() || exception->isGroupPath() - || exception->isMultiCycle())) { + || exception->isMultiCycle() + || exception->isPathMargin())) { MultiCyclePath *mcp=dynamic_cast(exception); if (network_->isLatchData(pin) && check_role == TimingRole::setup()) { @@ -359,11 +359,12 @@ VisitPathEnds::visitOutputDelayEnd1(OutputDelay *output_delay, else if (src_clk_edge && tgt_clk_edge && sdc_->sameClockGroup(path->clock(this), tgt_clk_edge->clock()) - // False paths and path delays override. + // False paths, path delays, and path margins override. && (exception == nullptr || exception->isFilter() || exception->isGroupPath() - || exception->isMultiCycle())) { + || exception->isMultiCycle() + || exception->isPathMargin())) { MultiCyclePath *mcp = dynamic_cast(exception); PathEndOutputDelay path_end(output_delay, path, ref_path, mcp, this); visitor->visit(&path_end); @@ -426,11 +427,12 @@ VisitPathEnds::visitGatedClkEnd(const Pin *pin, ExceptionPath *exception = exceptionTo(path, pin, end_rf, clk_edge, min_max); if (sdc_->sameClockGroup(src_clk, clk) - // False paths and path delays override. + // False paths, path delays, and path margins override. && (exception == nullptr || exception->isFilter() || exception->isGroupPath() - || exception->isMultiCycle()) + || exception->isMultiCycle() + || exception->isPathMargin()) && (!filtered || search_->matchesFilter(path, clk_edge))) { MultiCyclePath *mcp = @@ -548,11 +550,12 @@ VisitPathEnds::visitDataCheckEnd1(DataCheck *check, tgt_clk_edge, min_max); if (sdc_->sameClockGroup(src_clk, tgt_clk) && !sdc_->clkStopPropagation(from_pin, tgt_clk) - // False paths and path delays override. + // False paths, path delays, and path margins override. && (exception == 0 || exception->isFilter() || exception->isGroupPath() - || exception->isMultiCycle()) + || exception->isMultiCycle() + || exception->isPathMargin()) && (!filtered || search_->matchesFilter(path, tgt_clk_edge))) { MultiCyclePath *mcp=dynamic_cast(exception); From 7c4c7d7b0abb2d06307309f79551346bebb22b02 Mon Sep 17 00:00:00 2001 From: Stan Lee <135666755+stanminlee@users.noreply.github.com> Date: Thu, 21 May 2026 16:44:33 -0700 Subject: [PATCH 02/23] tcl wrapper --- sdc/Sdc.tcl | 55 +++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 55 insertions(+) diff --git a/sdc/Sdc.tcl b/sdc/Sdc.tcl index d23f8af89..67d96219b 100644 --- a/sdc/Sdc.tcl +++ b/sdc/Sdc.tcl @@ -2457,6 +2457,61 @@ proc set_min_delay { args } { ################################################################ +define_cmd_args "set_path_margin" \ + {[-setup] [-hold] [-rise] [-fall] [-comment comment]\ + [-from from_list] [-rise_from from_list] [-fall_from from_list]\ + [-through|-thr|-th through_list] [-rise_through|-rise_thr|-rise_th through_list]\ + [-fall_through|-fall_thr|-fall_th through_list]\ + [-to to_list] [-rise_to to_list] [-fall_to to_list] margin} + +proc set_path_margin { args } { + parse_key_args "set_path_margin" args \ + keys {-from -rise_from -fall_from -to -rise_to -fall_to -comment} \ + flags {-rise -fall -setup -hold} 0 + + # Applies to setup, hold, or both. + set min_max "min_max" + if { [info exists flags(-setup)] && ![info exists flags(-hold)] } { + set min_max "max" + } elseif { [info exists flags(-hold)] && ![info exists flags(-setup)] } { + set min_max "min" + } + + # Validate arguments. + set cmd "set_path_margin" + set arg_error 0 + set from [parse_from_arg keys arg_error] + set thrus [parse_thrus_arg args arg_error] + set to [parse_to_arg keys flags arg_error] + check_exception_pins $from $to + if { $arg_error } { + delete_from_thrus_to $from $thrus $to + return + } + + # Validate margin value count and argument type. + check_for_key_args $cmd args + if { [llength $args] == 0 } { + delete_from_thrus_to $from $thrus $to + sta_error 1800 "missing margin argument." + } elseif { [llength $args] > 1 } { + sta_warn 1801 "'$args' ignored." + } + if { $from == "NULL" && $thrus == "" && $to == "NULL" } { + delete_from_thrus_to $from $thrus $to + sta_error 1802 "-from, -through or -to required." + } + + # Parse margin value. + set margin [lindex $args 0] + check_float "set_path_margin margin" $margin + set margin [time_ui_sta $margin] + set comment [parse_comment_key keys] + make_path_margin $from $thrus $to $min_max $margin $comment +} + +################################################################ + define_cmd_args "set_min_pulse_width" {[-low] [-high] value [objects]} proc set_min_pulse_width { args } { From cf17c558691efe4146d4e5ab54c64c478b96aef2 Mon Sep 17 00:00:00 2001 From: Stan Lee <135666755+stanminlee@users.noreply.github.com> Date: Thu, 21 May 2026 17:03:10 -0700 Subject: [PATCH 03/23] test --- test/regression_vars.tcl | 1 + test/set_path_margin.ok | 118 +++++++++++++++++++++++++++++++++++++++ test/set_path_margin.tcl | 26 +++++++++ 3 files changed, 145 insertions(+) create mode 100644 test/set_path_margin.ok create mode 100644 test/set_path_margin.tcl diff --git a/test/regression_vars.tcl b/test/regression_vars.tcl index 405ac17e2..ef66af6cb 100644 --- a/test/regression_vars.tcl +++ b/test/regression_vars.tcl @@ -183,6 +183,7 @@ record_public_tests { power_json prima3 report_checks_sorted + set_path_margin report_checks_src_attr report_json1 report_json2 diff --git a/test/set_path_margin.ok b/test/set_path_margin.ok new file mode 100644 index 000000000..a8ae88a7a --- /dev/null +++ b/test/set_path_margin.ok @@ -0,0 +1,118 @@ +Startpoint: r2 (rising edge-triggered flip-flop clocked by clk) +Endpoint: r3 (rising edge-triggered flip-flop clocked by clk) +Path Group: clk +Path Type: max + + Delay Time Description +------------------------------------------------------------- + 0.0000 0.0000 clock clk (rise edge) + 0.0000 0.0000 clock network delay (ideal) + 0.0000 0.0000 ^ r2/CK (DFF_X1) + 0.0772 0.0772 v r2/Q (DFF_X1) + 0.0233 0.1006 v u1/Z (BUF_X1) + 0.0273 0.1278 v u2/ZN (AND2_X1) + 0.0000 0.1278 v r3/D (DFF_X1) + 0.1278 data arrival time + + 10.0000 10.0000 clock clk (rise edge) + 0.0000 10.0000 clock network delay (ideal) + -0.5000 9.5000 path margin + 0.0000 9.5000 clock reconvergence pessimism + 9.5000 ^ r3/CK (DFF_X1) + -0.0390 9.4610 library setup time + 9.4610 data required time +------------------------------------------------------------- + 9.4610 data required time + -0.1278 data arrival time +------------------------------------------------------------- + 9.3332 slack (MET) + + +Startpoint: r1 (rising edge-triggered flip-flop clocked by clk) +Endpoint: r3 (rising edge-triggered flip-flop clocked by clk) +Path Group: clk +Path Type: min + + Delay Time Description +------------------------------------------------------------- + 0.0000 0.0000 clock clk (rise edge) + 0.0000 0.0000 clock network delay (ideal) + 0.0000 0.0000 ^ r1/CK (DFF_X1) + 0.0772 0.0772 v r1/Q (DFF_X1) + 0.0254 0.1026 v u2/ZN (AND2_X1) + 0.0000 0.1026 v r3/D (DFF_X1) + 0.1026 data arrival time + + 0.0000 0.0000 clock clk (rise edge) + 0.0000 0.0000 clock network delay (ideal) + 0.5000 0.5000 path margin + 0.0000 0.5000 clock reconvergence pessimism + 0.5000 ^ r3/CK (DFF_X1) + 0.0016 0.5016 library hold time + 0.5016 data required time +------------------------------------------------------------- + 0.5016 data required time + -0.1026 data arrival time +------------------------------------------------------------- + -0.3990 slack (VIOLATED) + + +Startpoint: r2 (rising edge-triggered flip-flop clocked by clk) +Endpoint: r3 (rising edge-triggered flip-flop clocked by clk) +Path Group: clk +Path Type: max + + Delay Time Description +------------------------------------------------------------- + 0.0000 0.0000 clock clk (rise edge) + 0.0000 0.0000 clock network delay (ideal) + 0.0000 0.0000 ^ r2/CK (DFF_X1) + 0.0772 0.0772 v r2/Q (DFF_X1) + 0.0233 0.1006 v u1/Z (BUF_X1) + 0.0273 0.1278 v u2/ZN (AND2_X1) + 0.0000 0.1278 v r3/D (DFF_X1) + 0.1278 data arrival time + + 10.0000 10.0000 clock clk (rise edge) + 0.0000 10.0000 clock network delay (ideal) + 67.0000 77.0000 path margin + 0.0000 77.0000 clock reconvergence pessimism + 77.0000 ^ r3/CK (DFF_X1) + -0.0390 76.9610 library setup time + 76.9610 data required time +------------------------------------------------------------- + 76.9610 data required time + -0.1278 data arrival time +------------------------------------------------------------- + 76.8332 slack (MET) + + +Startpoint: r1 (rising edge-triggered flip-flop clocked by clk) +Endpoint: r3 (rising edge-triggered flip-flop clocked by clk) +Path Group: clk +Path Type: min + + Delay Time Description +------------------------------------------------------------- + 0.0000 0.0000 clock clk (rise edge) + 0.0000 0.0000 clock network delay (ideal) + 0.0000 0.0000 ^ r1/CK (DFF_X1) + 0.0772 0.0772 v r1/Q (DFF_X1) + 0.0254 0.1026 v u2/ZN (AND2_X1) + 0.0000 0.1026 v r3/D (DFF_X1) + 0.1026 data arrival time + + 0.0000 0.0000 clock clk (rise edge) + 0.0000 0.0000 clock network delay (ideal) + -0.5000 -0.5000 path margin + 0.0000 -0.5000 clock reconvergence pessimism + -0.5000 ^ r3/CK (DFF_X1) + 0.0016 -0.4984 library hold time + -0.4984 data required time +------------------------------------------------------------- + -0.4984 data required time + -0.1026 data arrival time +------------------------------------------------------------- + 0.6010 slack (MET) + + diff --git a/test/set_path_margin.tcl b/test/set_path_margin.tcl new file mode 100644 index 000000000..fd0a548a2 --- /dev/null +++ b/test/set_path_margin.tcl @@ -0,0 +1,26 @@ +# set_path_margin: per-path slack adjustment on the capture clock. + +read_liberty ../examples/nangate45_typ.lib.gz +read_verilog ../examples/example1.v +link_design top +create_clock -name clk -period 10 {clk1 clk2 clk3} +set_input_delay -clock clk 0 {in1 in2} + +proc setup_at { pin } { + report_checks -to $pin -path_delay max -digits 4 -fields {} -group_path_count 1 +} +proc hold_at { pin } { + report_checks -to $pin -path_delay min -digits 4 -fields {} -group_path_count 1 +} + +set_path_margin -setup 0.50 -comment {tighten setup time} -to [get_pins r3/D] +setup_at [get_pins r3/D] + +set_path_margin -hold 0.50 -comment {tighten hold time} -to [get_pins r3/D] +hold_at [get_pins r3/D] + +set_path_margin -setup -67 -comment {loosen setup time} -to [get_pins r3/D] +setup_at [get_pins r3/D] + +set_path_margin -hold -0.50 -comment {loosen hold time} -to [get_pins r3/D] +hold_at [get_pins r3/D] From f36f4f5e8fcbc4af0e23123651bd6da1ed8d1aee Mon Sep 17 00:00:00 2001 From: Stan Lee <135666755+stanminlee@users.noreply.github.com> Date: Thu, 21 May 2026 22:34:49 -0700 Subject: [PATCH 04/23] smallfixes --- search/PathEnd.cc | 24 +++++++++--------------- 1 file changed, 9 insertions(+), 15 deletions(-) diff --git a/search/PathEnd.cc b/search/PathEnd.cc index d13b1d4de..09856a8ef 100644 --- a/search/PathEnd.cc +++ b/search/PathEnd.cc @@ -709,23 +709,17 @@ PathEndClkConstrained::targetClkUncertainty(const StaState *sta) const float PathEndClkConstrained::targetClkPathMargin(const StaState *sta) const { - const Sdc *sdc = sta->sdc(); - const TimingRole *role = checkRole(sta); - ExceptionPath *exception = nullptr; - int hi_priority_exception = -1; - // Look up a path margin for the target - sdc->exceptionTo(ExceptionPathType::path_margin, - path_->pin(sta), - path_->transition(sta), - targetClkEdge(sta), - role->pathMinMax(), - false, - exception, hi_priority_exception); - if (!exception) // no path margin found + ExceptionPath *exception = + sta->search()->exceptionTo(ExceptionPathType::path_margin, + path_, path_->pin(sta), + path_->transition(sta), + targetClkEdge(sta), + checkRole(sta)->pathMinMax(), + false, false); + if (!exception) return 0.0; float margin = exception->margin(); - // Setup time margin is sign-flipped - if (role->genericRole() == TimingRole::setup()) + if (checkRole(sta)->genericRole() == TimingRole::setup()) margin = -margin; return margin; } From 16be080324794e811bb8dfe7c33e0b53ecb551b1 Mon Sep 17 00:00:00 2001 From: Stan Lee <135666755+stanminlee@users.noreply.github.com> Date: Thu, 21 May 2026 22:41:58 -0700 Subject: [PATCH 05/23] update test --- test/set_path_margin.ok | 176 +++++++++++++++++++++++++++++++++++++++ test/set_path_margin.tcl | 44 +++++++--- 2 files changed, 209 insertions(+), 11 deletions(-) diff --git a/test/set_path_margin.ok b/test/set_path_margin.ok index a8ae88a7a..d03b4bfe1 100644 --- a/test/set_path_margin.ok +++ b/test/set_path_margin.ok @@ -116,3 +116,179 @@ Path Type: min 0.6010 slack (MET) +Startpoint: r1 (rising edge-triggered flip-flop clocked by clk) +Endpoint: r3 (rising edge-triggered flip-flop clocked by clk) +Path Group: clk +Path Type: max + + Delay Time Description +------------------------------------------------------------- + 0.0000 0.0000 clock clk (rise edge) + 0.0000 0.0000 clock network delay (ideal) + 0.0000 0.0000 ^ r1/CK (DFF_X1) + 0.0836 0.0836 ^ r1/Q (DFF_X1) + 0.0277 0.1113 ^ u2/ZN (AND2_X1) + 0.0000 0.1113 ^ r3/D (DFF_X1) + 0.1113 data arrival time + + 10.0000 10.0000 clock clk (rise edge) + 0.0000 10.0000 clock network delay (ideal) + -2.0000 8.0000 path margin + 0.0000 8.0000 clock reconvergence pessimism + 8.0000 ^ r3/CK (DFF_X1) + -0.0311 7.9689 library setup time + 7.9689 data required time +------------------------------------------------------------- + 7.9689 data required time + -0.1113 data arrival time +------------------------------------------------------------- + 7.8576 slack (MET) + + +Startpoint: r2 (rising edge-triggered flip-flop clocked by clk) +Endpoint: r3 (rising edge-triggered flip-flop clocked by clk) +Path Group: clk +Path Type: max + + Delay Time Description +------------------------------------------------------------- + 0.0000 0.0000 clock clk (rise edge) + 0.0000 0.0000 clock network delay (ideal) + 0.0000 0.0000 ^ r2/CK (DFF_X1) + 0.0772 0.0772 v r2/Q (DFF_X1) + 0.0233 0.1006 v u1/Z (BUF_X1) + 0.0273 0.1278 v u2/ZN (AND2_X1) + 0.0000 0.1278 v r3/D (DFF_X1) + 0.1278 data arrival time + + 10.0000 10.0000 clock clk (rise edge) + 0.0000 10.0000 clock network delay (ideal) + 67.0000 77.0000 path margin + 0.0000 77.0000 clock reconvergence pessimism + 77.0000 ^ r3/CK (DFF_X1) + -0.0390 76.9610 library setup time + 76.9610 data required time +------------------------------------------------------------- + 76.9610 data required time + -0.1278 data arrival time +------------------------------------------------------------- + 76.8332 slack (MET) + + +Startpoint: r1 (rising edge-triggered flip-flop clocked by clk) +Endpoint: r3 (rising edge-triggered flip-flop clocked by clk) +Path Group: clk +Path Type: max + + Delay Time Description +------------------------------------------------------------- + 0.0000 0.0000 clock clk (rise edge) + 0.0000 0.0000 clock network delay (ideal) + 0.0000 0.0000 ^ r1/CK (DFF_X1) + 0.0836 0.0836 ^ r1/Q (DFF_X1) + 0.0277 0.1113 ^ u2/ZN (AND2_X1) + 0.0000 0.1113 ^ r3/D (DFF_X1) + 0.1113 data arrival time + + 10.0000 10.0000 clock clk (rise edge) + 0.0000 10.0000 clock network delay (ideal) + -5.0000 5.0000 path margin + 0.0000 5.0000 clock reconvergence pessimism + 5.0000 ^ r3/CK (DFF_X1) + -0.0311 4.9689 library setup time + 4.9689 data required time +------------------------------------------------------------- + 4.9689 data required time + -0.1113 data arrival time +------------------------------------------------------------- + 4.8576 slack (MET) + + +Startpoint: r2 (rising edge-triggered flip-flop clocked by clk) +Endpoint: r3 (rising edge-triggered flip-flop clocked by clk) +Path Group: clk +Path Type: max + + Delay Time Description +------------------------------------------------------------- + 0.0000 0.0000 clock clk (rise edge) + 0.0000 0.0000 clock network delay (ideal) + 0.0000 0.0000 ^ r2/CK (DFF_X1) + 0.0772 0.0772 v r2/Q (DFF_X1) + 0.0233 0.1006 v u1/Z (BUF_X1) + 0.0273 0.1278 v u2/ZN (AND2_X1) + 0.0000 0.1278 v r3/D (DFF_X1) + 0.1278 data arrival time + + 10.0000 10.0000 clock clk (rise edge) + 0.0000 10.0000 clock network delay (ideal) + 0.0000 10.0000 clock reconvergence pessimism + 10.0000 ^ r3/CK (DFF_X1) + -0.0390 9.9610 library setup time + 9.9610 data required time +------------------------------------------------------------- + 9.9610 data required time + -0.1278 data arrival time +------------------------------------------------------------- + 9.8332 slack (MET) + + +Startpoint: r1 (rising edge-triggered flip-flop clocked by clk) +Endpoint: r3 (rising edge-triggered flip-flop clocked by clk) +Path Group: clk +Path Type: max + + Delay Time Description +------------------------------------------------------------- + 0.0000 0.0000 clock clk (rise edge) + 0.0000 0.0000 clock network delay (ideal) + 0.0000 0.0000 ^ r1/CK (DFF_X1) + 0.0836 0.0836 ^ r1/Q (DFF_X1) + 0.0277 0.1113 ^ u2/ZN (AND2_X1) + 0.0000 0.1113 ^ r3/D (DFF_X1) + 0.1113 data arrival time + + 10.0000 10.0000 clock clk (rise edge) + 0.0000 10.0000 clock network delay (ideal) + -2.0000 8.0000 path margin + 0.0000 8.0000 clock reconvergence pessimism + 8.0000 ^ r3/CK (DFF_X1) + -0.0311 7.9689 library setup time + 7.9689 data required time +------------------------------------------------------------- + 7.9689 data required time + -0.1113 data arrival time +------------------------------------------------------------- + 7.8576 slack (MET) + + +Startpoint: r2 (rising edge-triggered flip-flop clocked by clk) +Endpoint: r3 (rising edge-triggered flip-flop clocked by clk) +Path Group: clk +Path Type: max + + Delay Time Description +------------------------------------------------------------- + 0.0000 0.0000 clock clk (rise edge) + 0.0000 0.0000 clock network delay (ideal) + 0.0000 0.0000 ^ r2/CK (DFF_X1) + 0.0772 0.0772 v r2/Q (DFF_X1) + 0.0233 0.1006 v u1/Z (BUF_X1) + 0.0273 0.1278 v u2/ZN (AND2_X1) + 0.0000 0.1278 v r3/D (DFF_X1) + 0.1278 data arrival time + + 10.0000 10.0000 clock clk (rise edge) + 0.0000 10.0000 clock network delay (ideal) + -3.0000 7.0000 path margin + 0.0000 7.0000 clock reconvergence pessimism + 7.0000 ^ r3/CK (DFF_X1) + -0.0390 6.9610 library setup time + 6.9610 data required time +------------------------------------------------------------- + 6.9610 data required time + -0.1278 data arrival time +------------------------------------------------------------- + 6.8332 slack (MET) + + diff --git a/test/set_path_margin.tcl b/test/set_path_margin.tcl index fd0a548a2..a17d605ef 100644 --- a/test/set_path_margin.tcl +++ b/test/set_path_margin.tcl @@ -6,21 +6,43 @@ link_design top create_clock -name clk -period 10 {clk1 clk2 clk3} set_input_delay -clock clk 0 {in1 in2} -proc setup_at { pin } { - report_checks -to $pin -path_delay max -digits 4 -fields {} -group_path_count 1 +proc setup_at { args } { + report_checks {*}$args -path_delay max -digits 4 -fields {} -group_path_count 1 } -proc hold_at { pin } { - report_checks -to $pin -path_delay min -digits 4 -fields {} -group_path_count 1 +proc hold_at { args } { + report_checks {*}$args -path_delay min -digits 4 -fields {} -group_path_count 1 } +# Test -to and that -setup and -hold are properly applied. set_path_margin -setup 0.50 -comment {tighten setup time} -to [get_pins r3/D] -setup_at [get_pins r3/D] - +setup_at -to [get_pins r3/D] set_path_margin -hold 0.50 -comment {tighten hold time} -to [get_pins r3/D] -hold_at [get_pins r3/D] - +hold_at -to [get_pins r3/D] set_path_margin -setup -67 -comment {loosen setup time} -to [get_pins r3/D] -setup_at [get_pins r3/D] - +setup_at -to [get_pins r3/D] set_path_margin -hold -0.50 -comment {loosen hold time} -to [get_pins r3/D] -hold_at [get_pins r3/D] +hold_at -to [get_pins r3/D] + +# Test -from +reset_path -through [get_pins u1/Z] +set_path_margin -setup 2.0 -from [get_pins r1/CK] +# Should see path margin. +setup_at -from [get_pins r1/CK] -to [get_pins r3/D] +# Should not see path margin. +setup_at -from [get_pins r2/CK] -to [get_pins r3/D] + +# Test -from and -to. +reset_path -to [get_pins r3/D] +set_path_margin -setup 5.0 -from [get_pins r1/CK] -to [get_pins r3/D] +# Should see path margin. +setup_at -from [get_pins r1/CK] -to [get_pins r3/D] +# Should not see path margin. +setup_at -from [get_pins r2/CK] -to [get_pins r3/D] + +# Test -through. +reset_path -to [get_pins r3/D] +set_path_margin -setup 3.0 -through [get_pins u1/Z] +# Should not see path margin. +setup_at -from [get_pins r1/CK] -to [get_pins r3/D] +# Should see path margin. +setup_at -from [get_pins r2/CK] -to [get_pins r3/D] From dc507813ce89bec08b59154855e7fe6f78ad0abe Mon Sep 17 00:00:00 2001 From: Stan Lee <135666755+stanminlee@users.noreply.github.com> Date: Thu, 21 May 2026 22:50:42 -0700 Subject: [PATCH 06/23] better testing --- test/set_path_margin.ok | 117 +++++++++++++++++++++++++++++++++++++++ test/set_path_margin.tcl | 18 ++++++ 2 files changed, 135 insertions(+) diff --git a/test/set_path_margin.ok b/test/set_path_margin.ok index d03b4bfe1..a674dd0de 100644 --- a/test/set_path_margin.ok +++ b/test/set_path_margin.ok @@ -292,3 +292,120 @@ Path Type: max 6.8332 slack (MET) +Startpoint: r1 (rising edge-triggered flip-flop clocked by clk) +Endpoint: r3 (rising edge-triggered flip-flop clocked by clk) +Path Group: clk +Path Type: max + + Delay Time Description +------------------------------------------------------------- + 0.0000 0.0000 clock clk (rise edge) + 0.0000 0.0000 clock network delay (ideal) + 0.0000 0.0000 ^ r1/CK (DFF_X1) + 0.0836 0.0836 ^ r1/Q (DFF_X1) + 0.0277 0.1113 ^ u2/ZN (AND2_X1) + 0.0000 0.1113 ^ r3/D (DFF_X1) + 0.1113 data arrival time + + 10.0000 10.0000 clock clk (rise edge) + 0.0000 10.0000 clock network delay (ideal) + -4.0000 6.0000 path margin + 0.0000 6.0000 clock reconvergence pessimism + 6.0000 ^ r3/CK (DFF_X1) + -0.0311 5.9689 library setup time + 5.9689 data required time +------------------------------------------------------------- + 5.9689 data required time + -0.1113 data arrival time +------------------------------------------------------------- + 5.8576 slack (MET) + + +Startpoint: r2 (rising edge-triggered flip-flop clocked by clk) +Endpoint: r3 (rising edge-triggered flip-flop clocked by clk) +Path Group: clk +Path Type: max + + Delay Time Description +------------------------------------------------------------- + 0.0000 0.0000 clock clk (rise edge) + 0.0000 0.0000 clock network delay (ideal) + 0.0000 0.0000 ^ r2/CK (DFF_X1) + 0.0772 0.0772 v r2/Q (DFF_X1) + 0.0233 0.1006 v u1/Z (BUF_X1) + 0.0273 0.1278 v u2/ZN (AND2_X1) + 0.0000 0.1278 v r3/D (DFF_X1) + 0.1278 data arrival time + + 10.0000 10.0000 clock clk (rise edge) + 0.0000 10.0000 clock network delay (ideal) + -4.0000 6.0000 path margin + 0.0000 6.0000 clock reconvergence pessimism + 6.0000 ^ r3/CK (DFF_X1) + -0.0390 5.9610 library setup time + 5.9610 data required time +------------------------------------------------------------- + 5.9610 data required time + -0.1278 data arrival time +------------------------------------------------------------- + 5.8332 slack (MET) + + +Startpoint: r1 (rising edge-triggered flip-flop clocked by clk) +Endpoint: r3 (rising edge-triggered flip-flop clocked by clk) +Path Group: clk +Path Type: max + + Delay Time Description +------------------------------------------------------------- + 0.0000 0.0000 clock clk (rise edge) + 0.0000 0.0000 clock network delay (ideal) + 0.0000 0.0000 ^ r1/CK (DFF_X1) + 0.0836 0.0836 ^ r1/Q (DFF_X1) + 0.0277 0.1113 ^ u2/ZN (AND2_X1) + 0.0000 0.1113 ^ r3/D (DFF_X1) + 0.1113 data arrival time + + 10.0000 10.0000 clock clk (rise edge) + 0.0000 10.0000 clock network delay (ideal) + -6.0000 4.0000 path margin + 0.0000 4.0000 clock reconvergence pessimism + 4.0000 ^ r3/CK (DFF_X1) + -0.0311 3.9689 library setup time + 3.9689 data required time +------------------------------------------------------------- + 3.9689 data required time + -0.1113 data arrival time +------------------------------------------------------------- + 3.8576 slack (MET) + + +Startpoint: r2 (rising edge-triggered flip-flop clocked by clk) +Endpoint: r3 (rising edge-triggered flip-flop clocked by clk) +Path Group: clk +Path Type: max + + Delay Time Description +------------------------------------------------------------- + 0.0000 0.0000 clock clk (rise edge) + 0.0000 0.0000 clock network delay (ideal) + 0.0000 0.0000 ^ r2/CK (DFF_X1) + 0.0772 0.0772 v r2/Q (DFF_X1) + 0.0233 0.1006 v u1/Z (BUF_X1) + 0.0273 0.1278 v u2/ZN (AND2_X1) + 0.0000 0.1278 v r3/D (DFF_X1) + 0.1278 data arrival time + + 10.0000 10.0000 clock clk (rise edge) + 0.0000 10.0000 clock network delay (ideal) + 0.0000 10.0000 clock reconvergence pessimism + 10.0000 ^ r3/CK (DFF_X1) + -0.0390 9.9610 library setup time + 9.9610 data required time +------------------------------------------------------------- + 9.9610 data required time + -0.1278 data arrival time +------------------------------------------------------------- + 9.8332 slack (MET) + + diff --git a/test/set_path_margin.tcl b/test/set_path_margin.tcl index a17d605ef..293e5cb2d 100644 --- a/test/set_path_margin.tcl +++ b/test/set_path_margin.tcl @@ -46,3 +46,21 @@ set_path_margin -setup 3.0 -through [get_pins u1/Z] setup_at -from [get_pins r1/CK] -to [get_pins r3/D] # Should see path margin. setup_at -from [get_pins r2/CK] -to [get_pins r3/D] + +# Test a clock-scoped startpoint. +reset_path -from [get_pins r1/CK] +reset_path -through [get_pins u1/Z] +set_path_margin -setup 4.0 -from [get_clocks clk] +# Should see path margin on the clock. +setup_at -from [get_pins r1/CK] -to [get_pins r3/D] +setup_at -from [get_pins r2/CK] -to [get_pins r3/D] + +# Test -from, -through, and -to. +reset_path -from [get_clocks clk] +set_path_margin -setup 6.0 -from [get_pins r1/CK] \ + -through [get_pins u2/A1] \ + -to [get_pins r3/D] +# Should see path margin. +setup_at -from [get_pins r1/CK] -to [get_pins r3/D] +# Should not see path margin. +setup_at -from [get_pins r2/CK] -to [get_pins r3/D] From 00bd442e6d80d09a70db454a123f4bbb8d98305c Mon Sep 17 00:00:00 2001 From: Akash Levy Date: Tue, 26 May 2026 01:42:01 -0700 Subject: [PATCH 07/23] Reformat makePathMargin function parameters --- include/sta/Sdc.hh | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/include/sta/Sdc.hh b/include/sta/Sdc.hh index bcf79ba51..c49e7a64c 100644 --- a/include/sta/Sdc.hh +++ b/include/sta/Sdc.hh @@ -767,10 +767,10 @@ public: std::string_view comment); void makePathMargin(ExceptionFrom *from, ExceptionThruSeq *thrus, - ExceptionTo *to, - const MinMaxAll *min_max, - float margin, - const char *comment); + ExceptionTo *to, + const MinMaxAll *min_max, + float margin, + const char *comment); bool pathDelaysWithoutTo() const { return path_delays_without_to_; } // Delete matching false/multicycle/path_delay exceptions. // Caller owns from, thrus, to exception points (and must delete them). From 45fe5b265a1f69e19d3fd6a487f916ba6bac9854 Mon Sep 17 00:00:00 2001 From: Akash Levy Date: Tue, 26 May 2026 01:42:41 -0700 Subject: [PATCH 08/23] Update Sta.hh --- include/sta/Sta.hh | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/include/sta/Sta.hh b/include/sta/Sta.hh index aabb7bba2..44474a448 100644 --- a/include/sta/Sta.hh +++ b/include/sta/Sta.hh @@ -660,11 +660,11 @@ public: std::string_view comment, Sdc *sdc); void makePathMargin(ExceptionFrom *from, - ExceptionThruSeq *thrus, - ExceptionTo *to, - const MinMaxAll *min_max, - float margin, - const char *comment); + ExceptionThruSeq *thrus, + ExceptionTo *to, + const MinMaxAll *min_max, + float margin, + const char *comment); void makeGroupPath(std::string_view name, bool is_default, ExceptionFrom *from, From db0e0033ac8754e64fd11f978a4622e73f66b956 Mon Sep 17 00:00:00 2001 From: Akash Levy Date: Tue, 26 May 2026 01:46:30 -0700 Subject: [PATCH 09/23] Update Sdc.cc --- sdc/Sdc.cc | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/sdc/Sdc.cc b/sdc/Sdc.cc index f717617da..68ee832ad 100644 --- a/sdc/Sdc.cc +++ b/sdc/Sdc.cc @@ -4105,15 +4105,15 @@ Sdc::makePathDelay(ExceptionFrom *from, void Sdc::makePathMargin(ExceptionFrom *from, - ExceptionThruSeq *thrus, - ExceptionTo *to, - const MinMaxAll *min_max, - float margin, - const char *comment) + ExceptionThruSeq *thrus, + ExceptionTo *to, + const MinMaxAll *min_max, + float margin, + const char *comment) { checkFromThrusTo(from, thrus, to); PathMargin *exception = new PathMargin(from, thrus, to, min_max, - margin, true, comment); + margin, true, comment); addException(exception); } From de241e5e11bc4120960826ffb5226bb16e722a1d Mon Sep 17 00:00:00 2001 From: Akash Levy Date: Tue, 26 May 2026 01:51:16 -0700 Subject: [PATCH 10/23] Format constructor and clone method parameters --- include/sta/ExceptionPath.hh | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/include/sta/ExceptionPath.hh b/include/sta/ExceptionPath.hh index 8273750db..eb5c04c22 100644 --- a/include/sta/ExceptionPath.hh +++ b/include/sta/ExceptionPath.hh @@ -235,16 +235,16 @@ class PathMargin : public ExceptionPath { public: PathMargin(ExceptionFrom *from, - ExceptionThruSeq *thrus, - ExceptionTo *to, - const MinMaxAll *min_max, - float margin, - bool own_pts, - const char *comment); + ExceptionThruSeq *thrus, + ExceptionTo *to, + const MinMaxAll *min_max, + float margin, + bool own_pts, + const char *comment); virtual ExceptionPath *clone(ExceptionFrom *from, - ExceptionThruSeq *thrus, - ExceptionTo *to, - bool own_pts); + ExceptionThruSeq *thrus, + ExceptionTo *to, + bool own_pts); virtual bool isPathMargin() const { return true; } virtual ExceptionPathType type() const { return ExceptionPathType::path_margin; } virtual const char *typeString() const; From 68f25783c0a96a5ea99dac99b0c74836a12a4c85 Mon Sep 17 00:00:00 2001 From: Akash Levy Date: Tue, 26 May 2026 01:55:06 -0700 Subject: [PATCH 11/23] Update ExceptionPath.cc --- sdc/ExceptionPath.cc | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/sdc/ExceptionPath.cc b/sdc/ExceptionPath.cc index 303a1faee..12f09c782 100644 --- a/sdc/ExceptionPath.cc +++ b/sdc/ExceptionPath.cc @@ -560,24 +560,24 @@ PathDelay::overrides(ExceptionPath *exception) const //////////////////////////////////////////////////////////////// PathMargin::PathMargin(ExceptionFrom *from, - ExceptionThruSeq *thrus, - ExceptionTo *to, - const MinMaxAll *min_max, - float margin, - bool own_pts, - const char *comment) : + ExceptionThruSeq *thrus, + ExceptionTo *to, + const MinMaxAll *min_max, + float margin, + bool own_pts, + const char *comment) : ExceptionPath(from, thrus, to, min_max, own_pts, - pathMarginPriority() + fromThruToPriority(from, thrus, to), - comment), + pathMarginPriority() + fromThruToPriority(from, thrus, to), + comment), margin_(margin) { } ExceptionPath * PathMargin::clone(ExceptionFrom *from, - ExceptionThruSeq *thrus, - ExceptionTo *to, - bool own_pts) + ExceptionThruSeq *thrus, + ExceptionTo *to, + bool own_pts) { return new PathMargin(from, thrus, to, min_max_, margin_, own_pts, comment_); } From 5bfd662f53551c726a41ff3d406fcb8b3703ff85 Mon Sep 17 00:00:00 2001 From: Akash Levy Date: Tue, 26 May 2026 01:56:17 -0700 Subject: [PATCH 12/23] Refactor make_path_margin function parameters --- sdc/Sdc.i | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/sdc/Sdc.i b/sdc/Sdc.i index 18fd3d7d0..238879654 100644 --- a/sdc/Sdc.i +++ b/sdc/Sdc.i @@ -857,11 +857,11 @@ make_path_delay(ExceptionFrom *from, void make_path_margin(ExceptionFrom *from, - ExceptionThruSeq *thrus, - ExceptionTo *to, - const MinMaxAll *min_max, - float margin, - const char *comment) + ExceptionThruSeq *thrus, + ExceptionTo *to, + const MinMaxAll *min_max, + float margin, + const char *comment) { Sta::sta()->makePathMargin(from, thrus, to, min_max, margin, comment); } From 88123f88f8ce41dde59f7668c875eab46f3ca0e4 Mon Sep 17 00:00:00 2001 From: Akash Levy Date: Tue, 26 May 2026 02:00:55 -0700 Subject: [PATCH 13/23] Move set_path_margin to a different position --- test/regression_vars.tcl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/regression_vars.tcl b/test/regression_vars.tcl index 0b1372cc3..79371c168 100644 --- a/test/regression_vars.tcl +++ b/test/regression_vars.tcl @@ -182,11 +182,11 @@ record_public_tests { prima3 read_saif_null_instance report_checks_sorted - set_path_margin report_checks_src_attr report_json1 report_json2 sdc_strip_escaped_bus + set_path_margin slash_port_test suppress_msg vcd_timestamp From 2dfbfd3392b5fb792d84672d19eca46afd815b20 Mon Sep 17 00:00:00 2001 From: Akash Levy Date: Tue, 26 May 2026 02:02:03 -0700 Subject: [PATCH 14/23] Fix formatting of makePathMargin function parameters --- search/Sta.cc | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/search/Sta.cc b/search/Sta.cc index 157d7d85e..72a7eb3be 100644 --- a/search/Sta.cc +++ b/search/Sta.cc @@ -2071,11 +2071,11 @@ Sta::makePathDelay(ExceptionFrom *from, void Sta::makePathMargin(ExceptionFrom *from, - ExceptionThruSeq *thrus, - ExceptionTo *to, - const MinMaxAll *min_max, - float margin, - const char *comment) + ExceptionThruSeq *thrus, + ExceptionTo *to, + const MinMaxAll *min_max, + float margin, + const char *comment) { sdc_->makePathMargin(from, thrus, to, min_max, margin, comment); search_->arrivalsInvalid(); From f4e57aca5bb5510b60382531b4c4f59a1f26877a Mon Sep 17 00:00:00 2001 From: Akash Levy Date: Tue, 26 May 2026 02:06:59 -0700 Subject: [PATCH 15/23] Smallfixes for typeString --- include/sta/ExceptionPath.hh | 2 +- sdc/ExceptionPath.cc | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/include/sta/ExceptionPath.hh b/include/sta/ExceptionPath.hh index eb5c04c22..4d748374d 100644 --- a/include/sta/ExceptionPath.hh +++ b/include/sta/ExceptionPath.hh @@ -247,7 +247,7 @@ public: bool own_pts); virtual bool isPathMargin() const { return true; } virtual ExceptionPathType type() const { return ExceptionPathType::path_margin; } - virtual const char *typeString() const; + virtual std::string_view *typeString() const; virtual bool mergeable(ExceptionPath *exception) const; virtual bool overrides(ExceptionPath *exception) const; virtual float margin() const { return margin_; } diff --git a/sdc/ExceptionPath.cc b/sdc/ExceptionPath.cc index 12f09c782..cb0c8c0c4 100644 --- a/sdc/ExceptionPath.cc +++ b/sdc/ExceptionPath.cc @@ -594,7 +594,7 @@ PathMargin::tighterThan(ExceptionPath *) const return false; } -const char * +std::string_view PathMargin::typeString() const { return "Margin"; From b6b04e029a66936f97206747d31a7e51200f4250 Mon Sep 17 00:00:00 2001 From: Akash Levy Date: Tue, 26 May 2026 02:07:26 -0700 Subject: [PATCH 16/23] Oops --- include/sta/ExceptionPath.hh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/sta/ExceptionPath.hh b/include/sta/ExceptionPath.hh index 4d748374d..78a48895d 100644 --- a/include/sta/ExceptionPath.hh +++ b/include/sta/ExceptionPath.hh @@ -247,7 +247,7 @@ public: bool own_pts); virtual bool isPathMargin() const { return true; } virtual ExceptionPathType type() const { return ExceptionPathType::path_margin; } - virtual std::string_view *typeString() const; + virtual std::string_view typeString() const; virtual bool mergeable(ExceptionPath *exception) const; virtual bool overrides(ExceptionPath *exception) const; virtual float margin() const { return margin_; } From 9231a44c76c7ca001f44a7cc7ad73fc96c5f7950 Mon Sep 17 00:00:00 2001 From: Akash Levy Date: Tue, 26 May 2026 02:09:18 -0700 Subject: [PATCH 17/23] Last string_view fix --- include/sta/ExceptionPath.hh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/sta/ExceptionPath.hh b/include/sta/ExceptionPath.hh index 78a48895d..0b5e824e1 100644 --- a/include/sta/ExceptionPath.hh +++ b/include/sta/ExceptionPath.hh @@ -240,7 +240,7 @@ public: const MinMaxAll *min_max, float margin, bool own_pts, - const char *comment); + std::string_view comment); virtual ExceptionPath *clone(ExceptionFrom *from, ExceptionThruSeq *thrus, ExceptionTo *to, From eede2fa28b7bc7dceff0c1cd9aed63f1f90172e5 Mon Sep 17 00:00:00 2001 From: Akash Levy Date: Tue, 26 May 2026 02:09:39 -0700 Subject: [PATCH 18/23] Actually one more --- sdc/ExceptionPath.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sdc/ExceptionPath.cc b/sdc/ExceptionPath.cc index cb0c8c0c4..65f9f348a 100644 --- a/sdc/ExceptionPath.cc +++ b/sdc/ExceptionPath.cc @@ -565,7 +565,7 @@ PathMargin::PathMargin(ExceptionFrom *from, const MinMaxAll *min_max, float margin, bool own_pts, - const char *comment) : + std::string_view comment) : ExceptionPath(from, thrus, to, min_max, own_pts, pathMarginPriority() + fromThruToPriority(from, thrus, to), comment), From 527cd5ddca935776fce3847098675c6efde60f91 Mon Sep 17 00:00:00 2001 From: Akash Levy Date: Tue, 26 May 2026 02:11:04 -0700 Subject: [PATCH 19/23] Fix for reporting --- search/ReportPath.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/search/ReportPath.cc b/search/ReportPath.cc index 6ac459041..44094ce2b 100644 --- a/search/ReportPath.cc +++ b/search/ReportPath.cc @@ -2682,7 +2682,7 @@ ReportPath::reportClkUncertainty(const PathEnd *end, reportLine("inter-clock uncertainty", inter_uncertainty, clk_arrival, early_late); float margin = end->targetClkPathMargin(this); - clk_arrival += margin; + clk_arrival = delaySum(clk_arrival, margin, this); if (margin != 0.0) reportLine("path margin", margin, clk_arrival, early_late); } From 137aca28f62e0d235496ca9b0c67780c93e053de Mon Sep 17 00:00:00 2001 From: Akash Levy Date: Tue, 26 May 2026 02:19:42 -0700 Subject: [PATCH 20/23] More fixups --- include/sta/PathEnd.hh | 1 + include/sta/Sdc.hh | 2 +- include/sta/Sta.hh | 3 ++- sdc/Sdc.cc | 4 ++-- sdc/Sdc.i | 6 ++++-- search/Sta.cc | 5 +++-- 6 files changed, 13 insertions(+), 8 deletions(-) diff --git a/include/sta/PathEnd.hh b/include/sta/PathEnd.hh index fb126f5d8..253277391 100644 --- a/include/sta/PathEnd.hh +++ b/include/sta/PathEnd.hh @@ -262,6 +262,7 @@ public: float targetNonInterClkUncertainty(const StaState *sta) const override; float interClkUncertainty(const StaState *sta) const override; float targetClkUncertainty(const StaState *sta) const override; + float targetClkPathMargin(const StaState *sta) const override; Crpr crpr(const StaState *sta) const override; Required requiredTime(const StaState *sta) const override; Slack slack(const StaState *sta) const override; diff --git a/include/sta/Sdc.hh b/include/sta/Sdc.hh index c49e7a64c..cf064c19d 100644 --- a/include/sta/Sdc.hh +++ b/include/sta/Sdc.hh @@ -770,7 +770,7 @@ public: ExceptionTo *to, const MinMaxAll *min_max, float margin, - const char *comment); + std::string_view comment); bool pathDelaysWithoutTo() const { return path_delays_without_to_; } // Delete matching false/multicycle/path_delay exceptions. // Caller owns from, thrus, to exception points (and must delete them). diff --git a/include/sta/Sta.hh b/include/sta/Sta.hh index 44474a448..8e4a94dbb 100644 --- a/include/sta/Sta.hh +++ b/include/sta/Sta.hh @@ -664,7 +664,8 @@ public: ExceptionTo *to, const MinMaxAll *min_max, float margin, - const char *comment); + std::string_view comment, + Sdc *sdc); void makeGroupPath(std::string_view name, bool is_default, ExceptionFrom *from, diff --git a/sdc/Sdc.cc b/sdc/Sdc.cc index 68ee832ad..fc82ef54d 100644 --- a/sdc/Sdc.cc +++ b/sdc/Sdc.cc @@ -4109,11 +4109,11 @@ Sdc::makePathMargin(ExceptionFrom *from, ExceptionTo *to, const MinMaxAll *min_max, float margin, - const char *comment) + std::string_view comment) { checkFromThrusTo(from, thrus, to); PathMargin *exception = new PathMargin(from, thrus, to, min_max, - margin, true, comment); + margin, true, comment); addException(exception); } diff --git a/sdc/Sdc.i b/sdc/Sdc.i index 238879654..16e5bc409 100644 --- a/sdc/Sdc.i +++ b/sdc/Sdc.i @@ -861,9 +861,11 @@ make_path_margin(ExceptionFrom *from, ExceptionTo *to, const MinMaxAll *min_max, float margin, - const char *comment) + std::string_view comment) { - Sta::sta()->makePathMargin(from, thrus, to, min_max, margin, comment); + Sta *sta = Sta::sta(); + Sdc *sdc = sta->cmdSdc(); + sta->makePathMargin(from, thrus, to, min_max, margin, comment, sdc); } void diff --git a/search/Sta.cc b/search/Sta.cc index 72a7eb3be..8b5f03738 100644 --- a/search/Sta.cc +++ b/search/Sta.cc @@ -2075,9 +2075,10 @@ Sta::makePathMargin(ExceptionFrom *from, ExceptionTo *to, const MinMaxAll *min_max, float margin, - const char *comment) + std::string_view comment, + Sdc *sdc) { - sdc_->makePathMargin(from, thrus, to, min_max, margin, comment); + sdc->makePathMargin(from, thrus, to, min_max, margin, comment); search_->arrivalsInvalid(); } From 5c16348fad72ef6a8e659a13280e85f940aa00f2 Mon Sep 17 00:00:00 2001 From: Akash Levy Date: Tue, 26 May 2026 02:19:49 -0700 Subject: [PATCH 21/23] Final fixup --- search/PathEnd.cc | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/search/PathEnd.cc b/search/PathEnd.cc index d9431df92..8dd8d8450 100644 --- a/search/PathEnd.cc +++ b/search/PathEnd.cc @@ -701,13 +701,14 @@ PathEndClkConstrained::targetClkUncertainty(const StaState *sta) const float PathEndClkConstrained::targetClkPathMargin(const StaState *sta) const { + Sdc *sdc = path_->sdc(sta); ExceptionPath *exception = sta->search()->exceptionTo(ExceptionPathType::path_margin, path_, path_->pin(sta), path_->transition(sta), targetClkEdge(sta), checkRole(sta)->pathMinMax(), - false, false); + false, false, sdc); if (!exception) return 0.0; float margin = exception->margin(); From 9d2426b033bbb4f9202096ace8ea6541e56a3056 Mon Sep 17 00:00:00 2001 From: Akash Levy Date: Tue, 26 May 2026 02:23:49 -0700 Subject: [PATCH 22/23] Remove comment --- sdc/ExceptionPath.cc | 1 - 1 file changed, 1 deletion(-) diff --git a/sdc/ExceptionPath.cc b/sdc/ExceptionPath.cc index 65f9f348a..34aab4bc5 100644 --- a/sdc/ExceptionPath.cc +++ b/sdc/ExceptionPath.cc @@ -677,7 +677,6 @@ FalsePath::mergeable(ExceptionPath *exception) const bool FalsePath::overrides(ExceptionPath *exception) const { - // Most recent definition overrides earlier ones. return exception->priority() == priority() && exception->minMax() == min_max_; } From 9fee88793d2ea5eff77b3b3cb92c199f8196d6fc Mon Sep 17 00:00:00 2001 From: Akash Levy Date: Tue, 26 May 2026 02:33:10 -0700 Subject: [PATCH 23/23] Add JSON support and test for it --- search/ReportPath.cc | 4 ++++ test/set_path_margin.ok | 14 ++++++++++++++ test/set_path_margin.tcl | 24 ++++++++++++++++++++++++ 3 files changed, 42 insertions(+) diff --git a/search/ReportPath.cc b/search/ReportPath.cc index 44094ce2b..6ea84b93e 100644 --- a/search/ReportPath.cc +++ b/search/ReportPath.cc @@ -1246,6 +1246,10 @@ ReportPath::reportJson(const PathEnd *end, delayAsFloat(end->checkCrpr(this))); result += sta::format(" \"margin\": {:.3e},\n", delayAsFloat(end->margin(this))); + float path_margin = end->targetClkPathMargin(this); + if (path_margin != 0.0) + result += sta::format(" \"path_margin\": {:.3e},\n", + path_margin); result += sta::format(" \"required_time\": {:.3e},\n", delayAsFloat(end->requiredTimeOffset(this))); result += sta::format(" \"slack\": {:.3e}\n", diff --git a/test/set_path_margin.ok b/test/set_path_margin.ok index a674dd0de..14e88b1dd 100644 --- a/test/set_path_margin.ok +++ b/test/set_path_margin.ok @@ -28,6 +28,7 @@ Path Type: max 9.3332 slack (MET) +setup_to_tighten -5.000e-10 Startpoint: r1 (rising edge-triggered flip-flop clocked by clk) Endpoint: r3 (rising edge-triggered flip-flop clocked by clk) Path Group: clk @@ -57,6 +58,7 @@ Path Type: min -0.3990 slack (VIOLATED) +hold_to_tighten 5.000e-10 Startpoint: r2 (rising edge-triggered flip-flop clocked by clk) Endpoint: r3 (rising edge-triggered flip-flop clocked by clk) Path Group: clk @@ -87,6 +89,7 @@ Path Type: max 76.8332 slack (MET) +setup_to_loosen 6.700e-08 Startpoint: r1 (rising edge-triggered flip-flop clocked by clk) Endpoint: r3 (rising edge-triggered flip-flop clocked by clk) Path Group: clk @@ -116,6 +119,7 @@ Path Type: min 0.6010 slack (MET) +hold_to_loosen -5.000e-10 Startpoint: r1 (rising edge-triggered flip-flop clocked by clk) Endpoint: r3 (rising edge-triggered flip-flop clocked by clk) Path Group: clk @@ -145,6 +149,7 @@ Path Type: max 7.8576 slack (MET) +setup_from_r1 -2.000e-09 Startpoint: r2 (rising edge-triggered flip-flop clocked by clk) Endpoint: r3 (rising edge-triggered flip-flop clocked by clk) Path Group: clk @@ -175,6 +180,7 @@ Path Type: max 76.8332 slack (MET) +setup_from_r2 6.700e-08 Startpoint: r1 (rising edge-triggered flip-flop clocked by clk) Endpoint: r3 (rising edge-triggered flip-flop clocked by clk) Path Group: clk @@ -204,6 +210,7 @@ Path Type: max 4.8576 slack (MET) +setup_from_to_r1 -5.000e-09 Startpoint: r2 (rising edge-triggered flip-flop clocked by clk) Endpoint: r3 (rising edge-triggered flip-flop clocked by clk) Path Group: clk @@ -233,6 +240,7 @@ Path Type: max 9.8332 slack (MET) +setup_from_to_r2 none Startpoint: r1 (rising edge-triggered flip-flop clocked by clk) Endpoint: r3 (rising edge-triggered flip-flop clocked by clk) Path Group: clk @@ -262,6 +270,7 @@ Path Type: max 7.8576 slack (MET) +setup_through_r1 -2.000e-09 Startpoint: r2 (rising edge-triggered flip-flop clocked by clk) Endpoint: r3 (rising edge-triggered flip-flop clocked by clk) Path Group: clk @@ -292,6 +301,7 @@ Path Type: max 6.8332 slack (MET) +setup_through_r2 -3.000e-09 Startpoint: r1 (rising edge-triggered flip-flop clocked by clk) Endpoint: r3 (rising edge-triggered flip-flop clocked by clk) Path Group: clk @@ -321,6 +331,7 @@ Path Type: max 5.8576 slack (MET) +setup_from_clk_r1 -4.000e-09 Startpoint: r2 (rising edge-triggered flip-flop clocked by clk) Endpoint: r3 (rising edge-triggered flip-flop clocked by clk) Path Group: clk @@ -351,6 +362,7 @@ Path Type: max 5.8332 slack (MET) +setup_from_clk_r2 -4.000e-09 Startpoint: r1 (rising edge-triggered flip-flop clocked by clk) Endpoint: r3 (rising edge-triggered flip-flop clocked by clk) Path Group: clk @@ -380,6 +392,7 @@ Path Type: max 3.8576 slack (MET) +setup_combo_r1 -6.000e-09 Startpoint: r2 (rising edge-triggered flip-flop clocked by clk) Endpoint: r3 (rising edge-triggered flip-flop clocked by clk) Path Group: clk @@ -409,3 +422,4 @@ Path Type: max 9.8332 slack (MET) +setup_combo_r2 none diff --git a/test/set_path_margin.tcl b/test/set_path_margin.tcl index 293e5cb2d..e84378cfe 100644 --- a/test/set_path_margin.tcl +++ b/test/set_path_margin.tcl @@ -12,40 +12,60 @@ proc setup_at { args } { proc hold_at { args } { report_checks {*}$args -path_delay min -digits 4 -fields {} -group_path_count 1 } +proc report_json_path_margin { label path_delay args } { + set cmd [concat [list report_checks] $args \ + [list -path_delay $path_delay -format json -group_path_count 1]] + with_output_to_variable json $cmd + if { [regexp {"path_margin": ([^,\n]+)} $json match margin] } { + puts "$label $margin" + } else { + puts "$label none" + } +} # Test -to and that -setup and -hold are properly applied. set_path_margin -setup 0.50 -comment {tighten setup time} -to [get_pins r3/D] setup_at -to [get_pins r3/D] +report_json_path_margin setup_to_tighten max -to [get_pins r3/D] set_path_margin -hold 0.50 -comment {tighten hold time} -to [get_pins r3/D] hold_at -to [get_pins r3/D] +report_json_path_margin hold_to_tighten min -to [get_pins r3/D] set_path_margin -setup -67 -comment {loosen setup time} -to [get_pins r3/D] setup_at -to [get_pins r3/D] +report_json_path_margin setup_to_loosen max -to [get_pins r3/D] set_path_margin -hold -0.50 -comment {loosen hold time} -to [get_pins r3/D] hold_at -to [get_pins r3/D] +report_json_path_margin hold_to_loosen min -to [get_pins r3/D] # Test -from reset_path -through [get_pins u1/Z] set_path_margin -setup 2.0 -from [get_pins r1/CK] # Should see path margin. setup_at -from [get_pins r1/CK] -to [get_pins r3/D] +report_json_path_margin setup_from_r1 max -from [get_pins r1/CK] -to [get_pins r3/D] # Should not see path margin. setup_at -from [get_pins r2/CK] -to [get_pins r3/D] +report_json_path_margin setup_from_r2 max -from [get_pins r2/CK] -to [get_pins r3/D] # Test -from and -to. reset_path -to [get_pins r3/D] set_path_margin -setup 5.0 -from [get_pins r1/CK] -to [get_pins r3/D] # Should see path margin. setup_at -from [get_pins r1/CK] -to [get_pins r3/D] +report_json_path_margin setup_from_to_r1 max -from [get_pins r1/CK] -to [get_pins r3/D] # Should not see path margin. setup_at -from [get_pins r2/CK] -to [get_pins r3/D] +report_json_path_margin setup_from_to_r2 max -from [get_pins r2/CK] -to [get_pins r3/D] # Test -through. reset_path -to [get_pins r3/D] set_path_margin -setup 3.0 -through [get_pins u1/Z] # Should not see path margin. setup_at -from [get_pins r1/CK] -to [get_pins r3/D] +report_json_path_margin setup_through_r1 max -from [get_pins r1/CK] -to [get_pins r3/D] # Should see path margin. setup_at -from [get_pins r2/CK] -to [get_pins r3/D] +report_json_path_margin setup_through_r2 max -from [get_pins r2/CK] -to [get_pins r3/D] # Test a clock-scoped startpoint. reset_path -from [get_pins r1/CK] @@ -53,7 +73,9 @@ reset_path -through [get_pins u1/Z] set_path_margin -setup 4.0 -from [get_clocks clk] # Should see path margin on the clock. setup_at -from [get_pins r1/CK] -to [get_pins r3/D] +report_json_path_margin setup_from_clk_r1 max -from [get_pins r1/CK] -to [get_pins r3/D] setup_at -from [get_pins r2/CK] -to [get_pins r3/D] +report_json_path_margin setup_from_clk_r2 max -from [get_pins r2/CK] -to [get_pins r3/D] # Test -from, -through, and -to. reset_path -from [get_clocks clk] @@ -62,5 +84,7 @@ set_path_margin -setup 6.0 -from [get_pins r1/CK] \ -to [get_pins r3/D] # Should see path margin. setup_at -from [get_pins r1/CK] -to [get_pins r3/D] +report_json_path_margin setup_combo_r1 max -from [get_pins r1/CK] -to [get_pins r3/D] # Should not see path margin. setup_at -from [get_pins r2/CK] -to [get_pins r3/D] +report_json_path_margin setup_combo_r2 max -from [get_pins r2/CK] -to [get_pins r3/D]