forked from The-OpenROAD-Project/OpenSTA
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathDelayCalc.tcl
367 lines (332 loc) · 11.4 KB
/
DelayCalc.tcl
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
# OpenSTA, Static Timing Analyzer
# Copyright (c) 2023, Parallax Software, Inc.
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <https://www.gnu.org/licenses/>.
namespace eval sta {
# Allow any combination of -from/-to pins.
proc report_dcalc_cmd { cmd cmd_args digits_key } {
global sta_report_default_digits
parse_key_args $cmd cmd_args \
keys "$digits_key -from -to -corner" \
flags {-min -max}
set corner [parse_corner keys]
set min_max [parse_min_max_flags flags]
check_argc_eq0 $cmd $cmd_args
set digits $sta_report_default_digits
if [info exists keys($digits_key)] {
set digits $keys($digits_key)
check_positive_integer $digits_key $digits
}
if {[info exists keys(-from)] && [info exists keys(-to)]} {
set from_pin [get_port_pin_error "from_pin" $keys(-from)]
set to_pin [get_port_pin_error "to_pin" $keys(-to)]
foreach from_vertex [$from_pin vertices] {
foreach to_vertex [$to_pin vertices] {
set iter [$from_vertex out_edge_iterator]
while {[$iter has_next]} {
set edge [$iter next]
if { [$edge to] == $to_vertex } {
report_edge_dcalc $edge $corner $min_max $digits
}
}
$iter finish
}
}
} elseif [info exists keys(-from)] {
set from_pin [get_port_pin_error "from_pin" $keys(-from)]
foreach from_vertex [$from_pin vertices] {
set iter [$from_vertex out_edge_iterator]
while {[$iter has_next]} {
set edge [$iter next]
report_edge_dcalc $edge $corner $min_max $digits
}
$iter finish
}
} elseif [info exists keys(-to)] {
set to_pin [get_port_pin_error "to_pin" $keys(-to)]
foreach to_vertex [$to_pin vertices] {
set iter [$to_vertex in_edge_iterator]
while {[$iter has_next]} {
set edge [$iter next]
report_edge_dcalc $edge $corner $min_max $digits
}
$iter finish
}
}
}
proc report_edge_dcalc { edge corner min_max digits } {
set role [$edge role]
if { $role != "wire" } {
set from_vertex [$edge from]
set from_pin [$from_vertex pin]
set to_vertex [$edge to]
set to_pin [$to_vertex pin]
set cell [[$to_pin instance] cell]
set library [$cell library]
# Filter timing checks based on min_max.
if {!(($min_max == "max" && $role == "hold") \
|| ($min_max=="min" && $role=="setup"))} {
report_line "Library: [get_name $library]"
report_line "Cell: [get_name $cell]"
set sense [$edge sense]
if { $sense != "unknown" } {
report_line "Arc sense: $sense"
}
report_line "Arc type: $role"
foreach arc [$edge timing_arcs] {
set from [get_name [$from_pin port]]
set from_rf [$arc from_edge]
set to [get_name [$to_pin port]]
set to_rf [$arc to_edge]
report_line "$from $from_rf -> $to $to_rf"
report_line [report_delay_calc_cmd $edge $arc $corner $min_max $digits]
if { [$edge delay_annotated $arc $corner $min_max] } {
set delay [$edge arc_delay $arc $corner $min_max]
report_line "Annotated value = [format_time $delay $digits]"
}
report_line "............................................."
report_line ""
}
}
}
}
################################################################
define_hidden_cmd_args "set_delay_calculator" [delay_calc_names]
proc set_delay_calculator { alg } {
if { [is_delay_calc_name $alg] } {
set_delay_calculator_cmd $alg
} else {
sta_error 435 "delay calculator $alg not found."
}
}
define_cmd_args "set_pocv_sigma_factor" { factor }
################################################################
define_cmd_args "set_assigned_delay" \
{-cell|-net [-rise] [-fall] [-corner corner] [-min] [-max]\
[-from from_pins] [-to to_pins] 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} \
flags {-cell -net -rise -fall -max -min}
check_argc_eq1 $cmd $cmd_args
set corner [parse_corner keys]
set min_max [parse_min_max_all_check_flags flags]
set to_rf [parse_rise_fall_flags flags]
if [info exists keys(-from)] {
set from_pins [get_port_pins_error "from_pins" $keys(-from)]
} else {
sta_error 442 "$cmd missing -from argument."
}
if [info exists keys(-to)] {
set to_pins [get_port_pins_error "to_pins" $keys(-to)]
} else {
sta_error 443 "$cmd missing -to argument."
}
set delay [lindex $cmd_args 0]
if {![string is double $delay]} {
sta_error 444 "$cmd delay is not a float."
}
set delay [time_ui_sta $delay]
if {[info exists flags(-cell)] && [info exists flags(-net)]} {
sta_error 445 "set_annotated_delay -cell and -net options are mutually excluive."
} elseif {[info exists flags(-cell)]} {
if { $from_pins != {} } {
set inst [[lindex $from_pins 0] instance]
foreach pin $from_pins {
if {[$pin instance] != $inst} {
sta_error 446 "$cmd pin [get_full_name $pin] is not attached to instance [get_full_name $inst]."
}
}
foreach pin $to_pins {
if {[$pin instance] != $inst} {
sta_error 447 "$cmd pin [get_full_name $pin] is not attached to instance [get_full_name $inst]"
}
}
}
} elseif {![info exists flags(-net)]} {
sta_error 448 "$cmd -cell or -net required."
}
foreach from_pin $from_pins {
set from_vertices [$from_pin vertices]
set_assigned_delay1 [lindex $from_vertices 0] \
$to_pins $to_rf $corner $min_max $delay
if { [llength $from_vertices] == 2 } {
set_assigned_delay1 [lindex $from_vertices 1] \
$to_pins $to_rf $corner $min_max $delay
}
}
}
proc set_assigned_delay1 { from_vertex to_pins to_rf corner min_max delay } {
foreach to_pin $to_pins {
set to_vertices [$to_pin vertices]
set_assigned_delay2 $from_vertex [lindex $to_vertices 0] \
$to_rf $corner $min_max $delay
if { [llength $to_vertices] == 2 } {
# Bidirect driver.
set_assigned_delay2 $from_vertex [lindex $to_vertices 1] \
$to_rf $corner $min_max $delay
}
}
}
proc set_assigned_delay2 {from_vertex to_vertex to_rf corner min_max delay} {
set edge_iter [$from_vertex out_edge_iterator]
while {[$edge_iter has_next]} {
set edge [$edge_iter next]
if { [$edge to] == $to_vertex \
&& ![timing_role_is_check [$edge role]] } {
foreach arc [$edge timing_arcs] {
if { $to_rf == "rise_fall" \
|| $to_rf eq [$arc to_edge_name] } {
set_arc_delay $edge $arc $corner $min_max $delay
}
}
}
}
$edge_iter finish
}
################################################################
define_cmd_args "set_assigned_check" \
{-setup|-hold|-recovery|-removal [-rise] [-fall]\
[-corner corner] [-min] [-max]\
[-from from_pins] [-to to_pins] [-clock rise|fall]\
[-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 \
keys {-from -to -corner -clock -cond} \
flags {-setup -hold -recovery -removal -rise -fall -max -min}
check_argc_eq1 $cmd $cmd_args
if { [info exists keys(-from)] } {
set from_pins [get_port_pins_error "from_pins" $keys(-from)]
} else {
sta_error 449 "$cmd missing -from argument."
}
set from_rf "rise_fall"
if { [info exists keys(-clock)] } {
set clk_arg $keys(-clock)
if { $clk_arg eq "rise" \
|| $clk_arg eq "fall" } {
set from_rf $clk_arg
} else {
sta_error 450 "$cmd -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 451 "$cmd missing -to argument."
}
set to_rf [parse_rise_fall_flags flags]
set corner [parse_corner keys]
set min_max [parse_min_max_all_check_flags flags]
if { [info exists flags(-setup)] } {
set role "setup"
} elseif { [info exists flags(-hold)] } {
set role "hold"
} elseif { [info exists flags(-recovery)] } {
set role "recovery"
} elseif { [info exists flags(-removal)] } {
set role "removal"
} else {
sta_error 452 "$cmd 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]
if { ![string is double $check_value] } {
sta_error 453 "$cmd check_value is not a float."
}
set check_value [time_ui_sta $check_value]
foreach from_pin $from_pins {
set from_vertices [$from_pin vertices]
set_assigned_check1 [lindex $from_vertices 0] $from_rf \
$to_pins $to_rf $role $corner $min_max $cond $check_value
if { [llength $from_vertices] == 2 } {
set_assigned_check1 [lindex $from_vertices 1] $from_rf \
$to_pins $to_rf $role $corner $min_max $cond $check_value
}
}
}
proc set_assigned_check1 { from_vertex from_rf to_pins to_rf \
role corner min_max cond check_value } {
foreach to_pin $to_pins {
set to_vertices [$to_pin vertices]
set_assigned_check2 $from_vertex $from_rf [lindex $to_vertices 0] \
$to_rf $role $corner $min_max $cond $check_value
if { [llength $to_vertices] == 2 } {
# Bidirect driver.
set_assigned_check2 $from_vertex $from_rf \
[lindex $to_vertices 1] $to_rf $role $corner $min_max \
$cond $check_value
}
}
}
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]
while {[$edge_iter has_next]} {
set edge [$edge_iter next]
if { [$edge to] == $to_vertex } {
foreach arc [$edge timing_arcs] {
if { ($from_rf eq "rise_fall" \
|| $from_rf eq [$arc from_edge_name]) \
&& ($to_rf eq "rise_fall" \
|| $to_rf eq [$arc to_edge_name]) \
&& [$arc role] eq $role \
&& ($cond eq "" || [$arc sdf_cond] eq $cond) } {
set_arc_delay $edge $arc $corner $min_max $check_value
}
}
}
}
$edge_iter finish
}
################################################################a
define_cmd_args "set_assigned_transition" \
{[-rise] [-fall] [-corner corner] [-min] [-max] slew pins}
# Change the slew on a list of ports.
proc set_assigned_transition { args } {
parse_key_args "set_assigned_transition" args keys {-corner} \
flags {-rise -fall -max -min}
set corner [parse_corner keys]
set min_max [parse_min_max_all_check_flags flags]
set tr [parse_rise_fall_flags flags]
check_argc_eq2 "set_assigned_transition" $args
set slew [lindex $args 0]
if {![string is double $slew]} {
sta_error 428 "set_assigned_transition transition is not a float."
}
set slew [time_ui_sta $slew]
set pins [get_port_pins_error "pins" [lindex $args 1]]
foreach pin $pins {
set vertices [$pin vertices]
set vertex [lindex $vertices 0]
set_annotated_slew $vertex $corner $min_max $tr $slew
if { [llength $vertices] == 2 } {
# Bidirect driver.
set vertex [lindex $vertices 1]
set_annotated_slew $vertex $min_max $tr $slew
}
}
}
# sta namespace end
}