Skip to content

Commit ce2d2f6

Browse files
committed
rsz: Optimize latch time-borrow setup paths
Treat positive latch time borrowing as hidden setup debt when collecting and repairing setup endpoints. This lets repair_timing optimize paths that report zero slack only because latch transparency is fully consumed.\n\nUse effective endpoint slack during legacy setup repair and accept endpoint improvement when global WNS is unchanged. Add an inferred clock gator regression that verifies repair_timing reduces latch borrow on the enable path.\n\nTesting:\n- cmake --build tools/OpenROAD/build --target openroad -j64\n- ctest --test-dir tools/OpenROAD/build -R '^rsz\.inferred_clock_gator_time_borrow\.tcl$' --output-on-failure Signed-off-by: Jaehyun Kim <jhkim@precisioninno.com>
1 parent ad9e724 commit ce2d2f6

10 files changed

Lines changed: 365 additions & 12 deletions

src/rsz/src/RepairTargetCollector.cc

Lines changed: 52 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -812,9 +812,9 @@ void RepairTargetCollector::collectViolatingEndpoints()
812812

813813
const sta::VertexSet& endpoints = sta_->endpoints();
814814
for (sta::Vertex* endpoint : endpoints) {
815-
const sta::Slack endpoint_slack = sta_->slack(endpoint, max_);
816-
if (sta::fuzzyLess(endpoint_slack, slack_margin_)) {
817-
violating_endpoints_.emplace_back(endpoint->pin(), endpoint_slack);
815+
const sta::Slack effective_slack = getEndpointEffectiveSlack(endpoint);
816+
if (sta::fuzzyLess(effective_slack, slack_margin_)) {
817+
violating_endpoints_.emplace_back(endpoint->pin(), effective_slack);
818818
}
819819
}
820820

@@ -832,6 +832,55 @@ void RepairTargetCollector::collectViolatingEndpoints()
832832
* 100));
833833
}
834834

835+
sta::Slack RepairTargetCollector::getEndpointEffectiveSlack(
836+
sta::Vertex* endpoint) const
837+
{
838+
const sta::Slack reported_slack = sta_->slack(endpoint, max_);
839+
if (sta::fuzzyGreater(reported_slack, slack_margin_)) {
840+
return reported_slack;
841+
}
842+
843+
sta::PinSet* to_pins = new sta::PinSet(network_);
844+
to_pins->insert(endpoint->pin());
845+
sta::ExceptionTo* to = sdc_->makeExceptionTo(to_pins,
846+
nullptr,
847+
nullptr,
848+
sta::RiseFallBoth::riseFall(),
849+
sta::RiseFallBoth::riseFall());
850+
851+
sta::StringSeq group_names;
852+
sta::PathEndSeq path_ends
853+
= search_->findPathEnds(nullptr, // from
854+
nullptr, // thrus
855+
to, // to
856+
false, // unconstrained
857+
sta_->scenes(), // scene
858+
sta::MinMaxAll::max(), // min_max
859+
1, // group_path_count
860+
1, // endpoint_path_count
861+
false, // unique_pins
862+
false, // unique_edges
863+
-sta::INF, // slack_min
864+
sta::INF, // slack_max
865+
true, // sort_by_slack
866+
group_names, // group_names
867+
true,
868+
false,
869+
true,
870+
true,
871+
true,
872+
true); // checks
873+
874+
if (path_ends.empty()) {
875+
return reported_slack;
876+
}
877+
878+
// Treat consumed latch transparency as hidden setup debt for repair_timing.
879+
// Only positive borrow adds debt; flop endpoints report zero borrow.
880+
const sta::Arrival borrow = path_ends[0]->borrow(search_);
881+
return reported_slack - std::max<float>(borrow, 0.0f);
882+
}
883+
835884
void RepairTargetCollector::collectViolatingStartpoints()
836885
{
837886
violating_startpoints_.clear();

src/rsz/src/RepairTargetCollector.hh

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -169,6 +169,10 @@ class RepairTargetCollector
169169

170170
// Public endpoint collection for TNS Phase
171171
void collectViolatingEndpoints();
172+
// Effective slack includes hidden setup debt from latch time borrowing.
173+
// A latch endpoint with reported slack of zero but positive borrow is treated
174+
// as a setup violation by subtracting the borrow from the reported slack.
175+
sta::Slack getEndpointEffectiveSlack(sta::Vertex* endpoint) const;
172176
sta::Slack getPathSlackByIndex(const sta::Pin* endpoint_pin, int path_index);
173177
const vector<std::pair<const sta::Pin*, sta::Slack>>& getViolatingEndpoints()
174178
const

src/rsz/src/policy/SetupLegacyBase.cc

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -95,7 +95,8 @@ bool SetupLegacyBase::repairSetupPin(const sta::Pin* end_pin)
9595
return false;
9696
}
9797

98-
const sta::Slack end_slack = sta_->slack(end_vertex, max_);
98+
const sta::Slack end_slack
99+
= target_collector_->getEndpointEffectiveSlack(end_vertex);
99100
sta::Path* end_path = sta_->vertexWorstSlackPath(end_vertex, max_);
100101
if (end_path == nullptr) {
101102
return false;
@@ -299,7 +300,8 @@ void SetupLegacyBase::saveImprovedCheckpoint(
299300
void SetupLegacyBase::refreshEndpointSlacks(
300301
SetupLegacyBase::EndpointRepairState& endpoint_state)
301302
{
302-
endpoint_state.end_slack = sta_->slack(endpoint_state.end, max_);
303+
endpoint_state.end_slack
304+
= target_collector_->getEndpointEffectiveSlack(endpoint_state.end);
303305
sta_->worstSlack(
304306
max_, endpoint_state.worst_slack, endpoint_state.worst_vertex);
305307
}

src/rsz/src/policy/SetupLegacyPolicy.cc

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -238,8 +238,7 @@ void SetupLegacyPolicy::repairEndpoint(EndpointRepairState& endpoint_state,
238238
refreshEndpointSlacks(endpoint_state);
239239

240240
// Promote only the passes that improve the tracked objective.
241-
const bool better = pathImproved(main_state.end_index,
242-
endpoint_state.end_slack,
241+
const bool better = pathImproved(endpoint_state.end_slack,
243242
endpoint_state.worst_slack,
244243
endpoint_state.prev_end_slack,
245244
endpoint_state.prev_worst_slack);
@@ -394,14 +393,13 @@ void SetupLegacyPolicy::runMainRepairLoop(const ViolatingEnds& violating_ends,
394393
}
395394
}
396395

397-
bool SetupLegacyPolicy::pathImproved(const int end_index,
398-
const sta::Slack end_slack,
396+
bool SetupLegacyPolicy::pathImproved(const sta::Slack end_slack,
399397
const sta::Slack worst_slack,
400398
const sta::Slack prev_end_slack,
401399
const sta::Slack prev_worst_slack) const
402400
{
403401
return sta::fuzzyGreater(worst_slack, prev_worst_slack)
404-
|| (end_index != 1 && sta::fuzzyEqual(worst_slack, prev_worst_slack)
402+
|| (sta::fuzzyEqual(worst_slack, prev_worst_slack)
405403
&& sta::fuzzyGreater(end_slack, prev_end_slack));
406404
}
407405

src/rsz/src/policy/SetupLegacyPolicy.hh

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -56,8 +56,7 @@ class SetupLegacyPolicy : public SetupLegacyBase
5656
{
5757
return "LEGACY Phase Endpoint Profiler";
5858
}
59-
bool pathImproved(int end_index,
60-
sta::Slack end_slack,
59+
bool pathImproved(sta::Slack end_slack,
6160
sta::Slack worst_slack,
6261
sta::Slack prev_end_slack,
6362
sta::Slack prev_worst_slack) const;

src/rsz/test/BUILD

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -257,6 +257,7 @@ PASSFAIL_TESTS = [
257257
# NOTE: cpp_tests excluded - it's a CMake-specific wrapper script that expects
258258
# build directory structure not compatible with Bazel
259259
# "cpp_tests",
260+
"inferred_clock_gator_time_borrow",
260261
"repair_setup_legacy_mt",
261262
"repair_setup_mt1",
262263
]

src/rsz/test/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -239,6 +239,7 @@ or_integration_tests(
239239
global_sizing_threads
240240
global_sizing_presize
241241
PASSFAIL_TESTS
242+
inferred_clock_gator_time_borrow
242243
repair_setup_legacy_mt
243244
repair_setup_mt1
244245
cpp_tests
Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
VERSION 5.8 ;
2+
DIVIDERCHAR "/" ;
3+
BUSBITCHARS "[]" ;
4+
DESIGN inferred_clock_gator_time_borrow ;
5+
UNITS DISTANCE MICRONS 2000 ;
6+
7+
DIEAREA ( 0 0 ) ( 240000 240000 ) ;
8+
9+
COMPONENTS 10 ;
10+
- enable_buf0 BUF_X1 + PLACED ( 40000 120000 ) N ;
11+
- enable_buf1 BUF_X1 + PLACED ( 80000 120000 ) N ;
12+
- enable_latch DLL_X1 + PLACED ( 89540 158990 ) N ;
13+
- inferred_gate AND2_X1 + PLACED ( 88400 89470 ) N ;
14+
- sibling_branch CLKBUF_X3 + PLACED ( 91580 89470 ) N ;
15+
- sibling_ff0 DFF_X1 + PLACED ( 139840 89510 ) N ;
16+
- gated_ff0 DFF_X1 + PLACED ( 159600 158985 ) N ;
17+
- gated_ff1 DFF_X1 + PLACED ( 167580 158985 ) N ;
18+
- gated_ff2 DFF_X1 + PLACED ( 159600 167045 ) N ;
19+
- gated_ff3 DFF_X1 + PLACED ( 167580 167045 ) N ;
20+
END COMPONENTS
21+
22+
PINS 2 ;
23+
- clk + NET clk + DIRECTION INPUT + USE SIGNAL
24+
+ LAYER metal6 ( -140 0 ) ( 140 280 ) + FIXED ( 120000 240000 ) S ;
25+
- en_in + NET en_in + DIRECTION INPUT + USE SIGNAL
26+
+ LAYER metal6 ( -140 0 ) ( 140 280 ) + FIXED ( 0 120000 ) W ;
27+
END PINS
28+
29+
NETS 7 ;
30+
- clk
31+
( PIN clk )
32+
( enable_latch GN )
33+
( inferred_gate A1 )
34+
( sibling_branch A )
35+
+ USE SIGNAL ;
36+
- en_in
37+
( PIN en_in )
38+
( enable_buf0 A )
39+
+ USE SIGNAL ;
40+
- en_mid0
41+
( enable_buf0 Z )
42+
( enable_buf1 A )
43+
+ USE SIGNAL ;
44+
- en_mid1
45+
( enable_buf1 Z )
46+
( enable_latch D )
47+
+ USE SIGNAL ;
48+
- en_lat
49+
( enable_latch Q )
50+
( inferred_gate A2 )
51+
( sibling_ff0 D )
52+
( gated_ff0 D )
53+
( gated_ff1 D )
54+
( gated_ff2 D )
55+
( gated_ff3 D )
56+
+ USE SIGNAL ;
57+
- sibling_clk
58+
( sibling_branch Z )
59+
( sibling_ff0 CK )
60+
+ USE SIGNAL ;
61+
- gated_clk
62+
( inferred_gate ZN )
63+
( gated_ff0 CK )
64+
( gated_ff1 CK )
65+
( gated_ff2 CK )
66+
( gated_ff3 CK )
67+
+ USE SIGNAL ;
68+
END NETS
69+
70+
END DESIGN
Lines changed: 162 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,162 @@
1+
[INFO ODB-0227] LEF file: Nangate45/Nangate45.lef, created 22 layers, 27 vias, 135 library cells
2+
[INFO ODB-0128] Design: inferred_clock_gator_time_borrow
3+
[INFO ODB-0130] Created 2 pins.
4+
[INFO ODB-0131] Created 10 components and 52 component-terminals.
5+
[INFO ODB-0133] Created 7 nets and 22 connections.
6+
[INFO CTS-0050] Root buffer is CLKBUF_X3.
7+
[INFO CTS-0051] Sink buffer is CLKBUF_X3.
8+
[INFO CTS-0052] The following clock buffers will be used for CTS:
9+
CLKBUF_X3
10+
[INFO CTS-0049] Characterization buffer is CLKBUF_X3.
11+
[INFO CTS-0007] Net "clk" found for clock "clk".
12+
[INFO CTS-0011] Clock net "clk" for macros has 2 sinks.
13+
[INFO CTS-0011] Clock net "clk_regs" for registers has 1 sinks.
14+
[INFO CTS-0010] Clock net "gated_clk" has 4 sinks.
15+
[WARNING CTS-0041] Net "sibling_clk" has 1 sinks. Skipping...
16+
[INFO CTS-0008] TritonCTS found 3 clock nets.
17+
[INFO CTS-0097] Characterization used 1 buffer(s) types.
18+
[INFO CTS-0201] 0 blockages from hard placement blockages and placed macros will be used.
19+
[INFO CTS-0027] Generating H-Tree topology for net clk.
20+
[INFO CTS-0028] Total number of sinks: 2.
21+
[INFO CTS-0060] Macro sinks will be clustered in groups of up to 4 and based on buffer max cap.
22+
[INFO CTS-0030] Number of static layers: 1.
23+
[INFO CTS-0020] Wire segment unit: 14000 dbu (7 um).
24+
[INFO CTS-0021] Distance between buffers: 5 units (80 um).
25+
[INFO CTS-0023] Original sink region: [(91830, 90695), (167065, 165470)].
26+
[INFO CTS-0024] Normalized sink region: [(6.55929, 6.47821), (11.9332, 11.8193)].
27+
[INFO CTS-0025] Width: 5.3739.
28+
[INFO CTS-0026] Height: 5.3411.
29+
Level 1
30+
Direction: Horizontal
31+
Sinks per sub-region: 1
32+
Sub-region size: 2.6870 X 5.3411
33+
[INFO CTS-0034] Segment length (rounded): 1.
34+
[INFO CTS-0032] Stop criterion found. Max number of sinks is 15.
35+
[INFO CTS-0035] Number of sinks covered: 2.
36+
[INFO CTS-0201] 0 blockages from hard placement blockages and placed macros will be used.
37+
[INFO CTS-0027] Generating H-Tree topology for net clk_regs.
38+
[INFO CTS-0028] Total number of sinks: 1.
39+
[INFO CTS-0090] Sinks will be clustered based on buffer max cap.
40+
[INFO CTS-0030] Number of static layers: 1.
41+
[INFO CTS-0020] Wire segment unit: 14000 dbu (7 um).
42+
[INFO CTS-0021] Distance between buffers: 5 units (80 um).
43+
[INFO CTS-0023] Original sink region: [(92825, 160215), (92825, 160215)].
44+
[INFO CTS-0024] Normalized sink region: [(6.63036, 11.4439), (6.63036, 11.4439)].
45+
[INFO CTS-0025] Width: 0.0000.
46+
[INFO CTS-0026] Height: 0.0000.
47+
Level 1
48+
Direction: Vertical
49+
Sinks per sub-region: 1
50+
Sub-region size: 0.0000 X 0.0000
51+
[INFO CTS-0034] Segment length (rounded): 1.
52+
[INFO CTS-0032] Stop criterion found. Max number of sinks is 15.
53+
[INFO CTS-0035] Number of sinks covered: 1.
54+
[INFO CTS-0201] 0 blockages from hard placement blockages and placed macros will be used.
55+
[INFO CTS-0027] Generating H-Tree topology for net gated_clk.
56+
[INFO CTS-0028] Total number of sinks: 4.
57+
[INFO CTS-0090] Sinks will be clustered based on buffer max cap.
58+
[INFO CTS-0030] Number of static layers: 1.
59+
[INFO CTS-0020] Wire segment unit: 14000 dbu (7 um).
60+
[INFO CTS-0021] Distance between buffers: 5 units (80 um).
61+
[INFO CTS-0023] Original sink region: [(162830, 160215), (170810, 168275)].
62+
[INFO CTS-0024] Normalized sink region: [(11.6307, 11.4439), (12.2007, 12.0196)].
63+
[INFO CTS-0025] Width: 0.5700.
64+
[INFO CTS-0026] Height: 0.5757.
65+
Level 1
66+
Direction: Vertical
67+
Sinks per sub-region: 2
68+
Sub-region size: 0.5700 X 0.2879
69+
[INFO CTS-0034] Segment length (rounded): 1.
70+
[INFO CTS-0032] Stop criterion found. Max number of sinks is 15.
71+
[INFO CTS-0035] Number of sinks covered: 4.
72+
[INFO CTS-0018] Created 3 clock buffers.
73+
[INFO CTS-0012] Minimum number of buffers in the clock path: 2.
74+
[INFO CTS-0013] Maximum number of buffers in the clock path: 2.
75+
[INFO CTS-0015] Created 3 clock nets.
76+
[INFO CTS-0016] Fanout distribution for the current clock = 1:2..
77+
[INFO CTS-0017] Max level of the clock tree: 1.
78+
[INFO CTS-0018] Created 2 clock buffers.
79+
[INFO CTS-0012] Minimum number of buffers in the clock path: 2.
80+
[INFO CTS-0013] Maximum number of buffers in the clock path: 2.
81+
[INFO CTS-0015] Created 2 clock nets.
82+
[INFO CTS-0016] Fanout distribution for the current clock = 1:1..
83+
[INFO CTS-0017] Max level of the clock tree: 1.
84+
[INFO CTS-0018] Created 3 clock buffers.
85+
[INFO CTS-0012] Minimum number of buffers in the clock path: 2.
86+
[INFO CTS-0013] Maximum number of buffers in the clock path: 2.
87+
[INFO CTS-0015] Created 3 clock nets.
88+
[INFO CTS-0016] Fanout distribution for the current clock = 2:2..
89+
[INFO CTS-0017] Max level of the clock tree: 1.
90+
[INFO CTS-0098] Clock net "clk"
91+
[INFO CTS-0099] Sinks 2
92+
[INFO CTS-0100] Leaf buffers 0
93+
[INFO CTS-0101] Average sink wire length 97.63 um
94+
[INFO CTS-0102] Path depth 2 - 2
95+
[INFO CTS-0207] Dummy loads inserted 1
96+
[INFO CTS-0124] Clock net "clk_regs"
97+
[INFO CTS-0125] Sinks 1
98+
[INFO CTS-0098] Clock net "gated_clk"
99+
[INFO CTS-0099] Sinks 4
100+
[INFO CTS-0100] Leaf buffers 0
101+
[INFO CTS-0101] Average sink wire length 15.14 um
102+
[INFO CTS-0102] Path depth 2 - 2
103+
[INFO CTS-0207] Dummy loads inserted 0
104+
[INFO CTS-0033] Balancing latency for clock clk
105+
[INFO CTS-0036] inserted 4 delay buffers
106+
[INFO CTS-0037] Total number of delay buffers: 4
107+
[WARNING STA-0450] virtual clock vclk can not be propagated.
108+
BEFORE_BORROW 0.4005
109+
[INFO RSZ-0100] Repair move sequence: UnbufferMove SizeUpMove BufferMove SplitLoadMove
110+
[INFO RSZ-0094] Found 7 endpoints with setup violations.
111+
[INFO RSZ-0099] Repairing 7 out of 7 (100.00%) violating endpoints...
112+
Iter | Removed | Resized | Inserted | Cloned | Pin | Area | WNS | StTNS | EnTNS | Viol | Worst
113+
| Buffers | Gates | Buffers | Gates | Swaps | | | | | Endpts | St/EnPt
114+
------------------------------------------------------------------------------------------------------------------------------
115+
0* | 0 | 0 | 0 | 0 | 0 | +0.0% | -0.055 | -0.1 | -0.1 | 7 | inferred_gate/A2
116+
21* | 1 | 1 | 3 | 0 | 0 | +3.9% | -0.027 | -0.0 | -0.1 | 7 | inferred_gate/A2
117+
final | 1 | 1 | 3 | 0 | 0 | +3.9% | -0.027 | -0.0 | -0.1 | 7 | inferred_gate/A2
118+
------------------------------------------------------------------------------------------------------------------------------
119+
[INFO RSZ-0059] Removed 1 buffers.
120+
[INFO RSZ-0040] Inserted 3 buffers.
121+
[INFO RSZ-0051] Resized 1 instances: 1 up, 0 up match, 0 down, 0 VT
122+
[WARNING RSZ-0062] Unable to repair all setup violations.
123+
AFTER_BORROW 0.3769
124+
Startpoint: enable_latch (negative level-sensitive latch clocked by clk)
125+
Endpoint: inferred_gate (rising clock gating-check end-point clocked by clk)
126+
Path Group: gated clock
127+
Path Type: max
128+
129+
Delay Time Description
130+
-------------------------------------------------------------
131+
0.5000 0.5000 clock clk (fall edge)
132+
0.0000 0.5000 clock source latency
133+
0.0000 0.5000 v clk (in)
134+
0.0248 0.5248 v delaybuf_2_clk/Z (CLKBUF_X3)
135+
0.0278 0.5525 v delaybuf_3_clk/Z (CLKBUF_X3)
136+
0.0261 0.5787 v clkbuf_regs_0_clk/Z (CLKBUF_X3)
137+
0.0263 0.6049 v clkbuf_0_clk_regs/Z (CLKBUF_X3)
138+
0.0259 0.6309 v clkbuf_1_0__f_clk_regs/Z (CLKBUF_X3)
139+
0.0000 0.6309 v enable_latch/GN (DLL_X2)
140+
0.3769 1.0078 time given to startpoint
141+
0.0000 1.0078 v enable_latch/D (DLL_X2)
142+
0.0731 1.0809 v enable_latch/Q (DLL_X2)
143+
0.0007 1.0815 v inferred_gate/A2 (AND2_X1)
144+
1.0815 data arrival time
145+
146+
1.0000 1.0000 clock clk (rise edge)
147+
0.0000 1.0000 clock source latency
148+
0.0000 1.0000 ^ clk (in)
149+
0.0255 1.0255 ^ clkbuf_0_clk/Z (CLKBUF_X3)
150+
0.0292 1.0547 ^ clkbuf_1_1__f_clk/Z (CLKBUF_X3)
151+
0.0001 1.0548 ^ inferred_gate/A1 (AND2_X1)
152+
0.0000 1.0548 clock reconvergence pessimism
153+
0.0000 1.0548 clock gating setup time
154+
1.0548 data required time
155+
-------------------------------------------------------------
156+
1.0548 data required time
157+
-1.0815 data arrival time
158+
-------------------------------------------------------------
159+
-0.0268 slack (VIOLATED)
160+
161+
162+
pass inferred_clock_gator_time_borrow

0 commit comments

Comments
 (0)