1
2sta::define_cmd_args "create_physical_cluster" {cluster_name}
3
4proc create_physical_cluster { args } {
5  sta::check_argc_eq1 "create_physical_cluster" $args
6  set cluster_name $args
7  set db [ord::get_db]
8  set chip [$db getChip]
9  if { $chip == "NULL" } {
10    utl::error "please load the design before trying to use this command"
11  }
12  set block [$chip getBlock]
13  set group [odb::dbGroup_create $block $cluster_name]
14  if { $group == "NULL" } {
15    utl::error "duplicate group name"
16  }
17}
18
19sta::define_cmd_args "create_child_physical_clusters" {[-top_module | -modinst path]}
20
21proc create_child_physical_clusters { args } {
22  sta::parse_key_args "create_child_physical_clusters" args keys {-modinst} flags {-top_module}
23  set cluster_name $args
24  set db [ord::get_db]
25  set chip [$db getChip]
26  if { $chip == "NULL" } {
27    utl::error "please load the design before trying to use this command"
28  }
29  set block [$chip getBlock]
30  if { [info exists flags(-top_module)] } {
31    set module [$block getTopModule]
32  } elseif { [info exists keys(-modinst)] } {
33    set module [[$block findModInst $keys(-modinst)] getMaster]
34  } else {
35    utl::error "please define either top module or the modinst path"
36  }
37  if { $module == "NULL" } {
38    utl::error "module does not exist"
39  }
40  set module_instance [$module getModInst]
41  set modinsts [$module getChildren]
42  set insts [$module getInsts]
43  foreach modinst $modinsts {
44    set cluster_name "[$module getName]_[$modinst getName]"
45    set group [odb::dbGroup_create $block $cluster_name]
46    if { $group == "NULL" } {
47      utl::error "duplicate group name"
48    }
49    $group addModInst $modinst
50  }
51  if { [llength $insts] > 0 } {
52    if { $module_instance == "NULL" } {
53      set group [odb::dbGroup_create $block "[$module getName]_glue"]
54    } else {
55      set parent [$module_instance getParent]
56      set group [odb::dbGroup_create $block "[$parent getName]_[$module_instance getName]_glue"]
57    }
58    if { $group == "NULL" } {
59      utl::error "duplicate group name"
60    }
61    foreach inst $insts {
62      $group addInst $inst
63    }
64  }
65}
66proc set_ndr_layer_rule { tech ndr layerName input isSpacing} {
67  set layer [$tech findLayer $layerName]
68  if { $layer == "NULL" } {
69    utl::warn ODB 1000 "Layer ${layerName} not found, skipping NDR for this layer"
70    return
71  }
72  if { [$layer getType] != "ROUTING" } {
73    return
74  }
75  set rule [$ndr getLayerRule $layer]
76  if { $rule == "NULL" } {
77    set rule [odb::dbTechLayerRule_create $ndr $layer]
78  }
79  set input [string trim $input]
80  if { [string is double $input] } {
81    set value [ord::microns_to_dbu $input]
82  } elseif { [string first "*" $input] == 0 } {
83    if { $isSpacing } {
84      set value [expr [string trim $input "*"] * [$layer getSpacing]]
85    } else {
86      set value [expr [string trim $input "*"] * [$layer getWidth]]
87    }
88  } else {
89    utl::warn ODB 1009 "Invalid input in create_ndr cmd"
90    return
91  }
92  if { $isSpacing } {
93    $rule setSpacing $value
94  } else {
95    $rule setWidth $value
96  }
97}
98proc set_ndr_rules { tech ndr values isSpacing } {
99  if { [llength $values] == 1 } {
100    # Omitting layers
101    set value [lindex $values 0]
102    foreach layer [$tech getLayers] {
103      if { [$layer getType] != "ROUTING" } {
104        continue
105      }
106      set_ndr_layer_rule $tech $ndr [$layer getName] $value $isSpacing
107    }
108    return
109  }
110  for {set i 0} {$i < [llength $values]} {incr i 2} {
111    set layers [lindex $values $i]
112    set value [lindex $values [expr $i + 1]]
113    if { [string first ":" $layers] == -1 } {
114      set_ndr_layer_rule $tech $ndr $layers $value $isSpacing
115    } else {
116      lassign [split $layers ":" ] firstLayer lastLayer
117      set foundFirst 0
118      set foundLast 0
119      foreach layer [$tech getLayers] {
120        if { [$layer getType] != "ROUTING" } {
121          continue
122        }
123        if { $foundFirst == 0 } {
124          if { [$layer getName] == $firstLayer } {
125            set foundFirst 1
126          } else {
127            continue
128          }
129        }
130        set_ndr_layer_rule $tech $ndr [$layer getName] $value $isSpacing
131        if { [$layer getName] == $lastLayer } {
132          set foundLast 1
133          break
134        }
135      }
136      if { $foundFirst == 0 } {
137        utl::warn ODB 1001 "Layer ${firstLayer} not found"
138      }
139      if { $foundLast == 0 } {
140        utl::warn ODB 1002 "Layer ${lastLayer} not found"
141      }
142    }
143
144  }
145}
146
147sta::define_cmd_args "create_ndr" { -name name [-spacing val] [-width val] [-via val]}
148
149proc create_ndr { args } {
150  sta::parse_key_args "create_ndr" args keys {-name -spacing -width -via} flags {}
151  if { ![info exists keys(-name)] } {
152    utl::error ODB 1004 "-name is missing"
153  }
154  set name $keys(-name)
155  set block [[[ord::get_db] getChip] getBlock]
156  set tech [[ord::get_db] getTech]
157  set ndr [odb::dbTechNonDefaultRule_create $block $name]
158  if { $ndr == "NULL" } {
159    utl::error ODB 1005 "NonDefaultRule ${name} already exists"
160  }
161  if { [info exists keys(-spacing)] } {
162    set spacings $keys(-spacing)
163    if { [llength $spacings] != 1 && [expr [llength $spacings] % 2] == 1 } {
164      utl::error ODB 1006 "Spacing values \[$spacings\] are malformed"
165    }
166    set_ndr_rules $tech $ndr $spacings 1
167  }
168  if { [info exists keys(-width)] } {
169    set widths $keys(-width)
170    if { [llength $widths] != 1 &&  [expr [llength $widths] % 2] == 1 } {
171      utl::error ODB 1007 "Width values \[$widths\] are malformed"
172    }
173    set_ndr_rules $tech $ndr $widths 0
174  }
175  if { [info exists keys(-via)] } {
176    foreach viaName $keys(-via) {
177      set via [$tech findVia $viaName]
178      if { $via == "NULL" } {
179        utl::error ODB 1008 "Via ${viaName} not found, skipping NDR for this via"
180        continue
181      }
182      $ndr addUseVia $via
183    }
184  }
185
186}
187
188sta::define_cmd_args "create_voltage_domain" {domain_name -area {llx lly urx ury}}
189
190proc create_voltage_domain { args } {
191  sta::parse_key_args "create_voltage_domain" args keys {-area} flags {}
192  set domain_name [lindex $args 0]
193  if { [info exists keys(-area)] } {
194    set area $keys(-area)
195    if { [llength $area] != 4 } {
196      utl::error "-area is a list of 4 coordinates"
197    }
198    lassign $area llx lly urx ury
199    sta::check_positive_float "-area" $llx
200    sta::check_positive_float "-area" $lly
201    sta::check_positive_float "-area" $urx
202    sta::check_positive_float "-area" $ury
203  } else {
204    utl::error "please define area"
205  }
206  sta::check_argc_eq1 "create_voltage_domain" $args
207  set domain_name $args
208  set db [ord::get_db]
209  set chip [$db getChip]
210  if { $chip == "NULL" } {
211    utl::error "please load the design before trying to use this command"
212  }
213  set block [$chip getBlock]
214  set group [odb::dbGroup_create $block $domain_name \
215		[ord::microns_to_dbu $llx] [ord::microns_to_dbu $lly] \
216		[ord::microns_to_dbu $urx] [ord::microns_to_dbu $ury]]
217  if { $group == "NULL" } {
218    utl::error "duplicate group name"
219  }
220}
221
222sta::define_cmd_args "delete_physical_cluster" {cluster_name}
223
224proc delete_physical_cluster { args } {
225  sta::check_argc_eq1 "delete_physical_cluster" $args
226  set cluster_name $args
227  set db [ord::get_db]
228  set chip [$db getChip]
229  if { $chip == "NULL" } {
230    utl::error "please load the design before trying to use this command"
231  }
232  set block [$chip getBlock]
233  set group [$block findGroup $cluster_name]
234  if { $group == "NULL" } {
235    utl::error "group does not exist"
236  }
237  if { [$group getType] == "VOLTAGE_DOMAIN" } {
238    utl::error "group is not of physical cluster type"
239  }
240  odb::dbGroup_destroy $group
241}
242
243sta::define_cmd_args "delete_voltage_domain" {domain_name}
244
245proc delete_voltage_domain { args } {
246  sta::check_argc_eq1 "delete_voltage_domain" $args
247  set domain_name $args
248  set db [ord::get_db]
249  set chip [$db getChip]
250  if { $chip == "NULL" } {
251    utl::error "please load the design before trying to use this command"
252  }
253  set block [$chip getBlock]
254  set group [$block findGroup $domain_name]
255  if { $group == "NULL" } {
256    utl::error "group does not exist"
257  }
258  if { [$group getType] == "PHYSICAL_CLUSTER" } {
259    utl::error "group is not of voltage domain type"
260  }
261  odb::dbGroup_destroy $group
262}
263
264sta::define_cmd_args "assign_power_net" {-domain domain_name -net snet_name}
265
266proc assign_power_net { args } {
267  sta::parse_key_args "assign_power_net" args keys {-domain -net} flags {}
268  if { [info exists keys(-domain)] } {
269    set domain_name $keys(-domain)
270  } else {
271    utl::error "define domain name"
272  }
273  if { [info exists keys(-net)] } {
274    set net_name $keys(-net)
275  } else {
276    utl::error "define net name"
277  }
278  set db [ord::get_db]
279  set chip [$db getChip]
280  if { $chip == "NULL" } {
281    utl::error "please load the design before trying to use this command"
282  }
283  set block [$chip getBlock]
284  set group [$block findGroup $domain_name]
285  set net [$block findNet $net_name]
286  if { $group == "NULL" } {
287    utl::error "group does not exist"
288  }
289  if { [$group getType] == "PHYSICAL_CLUSTER" } {
290    utl::error "group is not of voltage domain type"
291  }
292  if { $net == "NULL" } {
293    utl::error "net does not exist"
294  }
295  $group addPowerNet $net
296}
297
298sta::define_cmd_args "assign_ground_net" {-domain domain_name -net snet_name}
299
300proc assign_ground_net { args } {
301  sta::parse_key_args "assign_ground_net" args keys {-domain -net} flags {}
302  if { [info exists keys(-domain)] } {
303    set domain_name $keys(-domain)
304  } else {
305    utl::error "define domain name"
306  }
307  if { [info exists keys(-net)] } {
308    set net_name $keys(-net)
309  } else {
310    utl::error "define net name"
311  }
312  set db [ord::get_db]
313  set chip [$db getChip]
314  if { $chip == "NULL" } {
315    utl::error "please load the design before trying to use this command"
316  }
317  set block [$chip getBlock]
318  set group [$block findGroup $domain_name]
319  set net [$block findNet $net_name]
320  if { $group == "NULL" } {
321    utl::error "group does not exist"
322  }
323  if { [$group getType] == "PHYSICAL_CLUSTER" } {
324    utl::error "group is not of voltage domain type"
325  }
326  if { $net == "NULL" } {
327    utl::error "net does not exist"
328  }
329  $group addGroundNet $net
330}
331
332sta::define_cmd_args "add_to_physical_cluster" { [-modinst path | -inst inst_name | -physical_cluster cluster_name]  cluster_name }
333
334proc add_to_physical_cluster { args } {
335  sta::parse_key_args "add_to_physical_cluster" args keys {-modinst -inst -physical_cluster} flags {}
336  sta::check_argc_eq1 "add_to_physical_cluster" $args
337  set cluster_name $args
338  set db [ord::get_db]
339  set chip [$db getChip]
340  if { $chip == "NULL" } {
341    utl::error "please load the design before trying to use this command"
342  }
343  set block [$chip getBlock]
344  set group [$block findGroup $cluster_name]
345  if { $group == "NULL" } {
346    utl::error "cluster does not exist"
347  }
348  if { [$group getType] == "VOLTAGE_DOMAIN" } {
349    utl::error "group is not of physical cluster type"
350  }
351  if { [info exists keys(-modinst)] } {
352    set modinst [$block findModInst $keys(-modinst)]
353    if { $modinst == "NULL" } {
354      utl::error "modinst does not exist"
355    }
356    $group addModInst $modinst
357  }
358  if { [info exists keys(-inst)] } {
359    set inst [$block findInst $keys(-inst)]
360    if { $inst == "NULL" } {
361      utl::error "inst does not exist"
362    }
363    $group addInst $inst
364  }
365  if { [info exists keys(-physical_cluster)] } {
366    set child [$block findGroup $keys(-physical_cluster)]
367    if { $child == "NULL" } {
368      utl::error "child physical cluster does not exist"
369    }
370    if { [$child getType] == "VOLTAGE DOMAIN" } {
371      utl::error "child group is not of physical cluster type"
372    }
373    $group addGroup $child
374  }
375}
376
377sta::define_cmd_args "remove_from_physical_cluster" { [-parent_module module_name -modinst modinst_name | -inst inst_name | -physical_cluster cluster_name]  cluster_name }
378
379proc remove_from_physical_cluster { args } {
380  sta::parse_key_args "remove_from_physical_cluster" args keys {-parent_module -modinst -inst -physical_cluster} flags {}
381  sta::check_argc_eq1 "remove_from_physical_cluster" $args
382  set cluster_name $args
383  set db [ord::get_db]
384  set chip [$db getChip]
385  if { $chip == "NULL" } {
386    utl::error "please load the design before trying to use this command"
387  }
388  set block [$chip getBlock]
389  set group [$block findGroup $cluster_name]
390  if { $group == "NULL" } {
391    utl::error "cluster does not exist"
392  }
393  if { [$group getType] == "VOLTAGE_DOMAIN" } {
394    utl::error "group is not of physical cluster type"
395  }
396  if { [info exists keys(-parent_module)] } {
397    set module [$block findModule $keys(-parent_module)]
398    if { $module == "NULL" } {
399      utl::error "parent module does not exist"
400    }
401    set modinst [$module findModInst $keys(-modinst)]
402    if { $modinst == "NULL" } {
403      utl::error "modinst does not exist"
404    }
405    $group removeModInst $modinst
406  }
407  if { [info exists keys(-inst)] } {
408    set inst [$block findInst $keys(-inst)]
409    if { $inst == "NULL" } {
410      utl::error "inst does not exist"
411    }
412    $group removeInst $inst
413  }
414  if { [info exists keys(-physical_cluster)] } {
415    set child [$block findGroup $keys(-physical_cluster)]
416    if { $child == "NULL" } {
417      utl::error "child physical cluster does not exist"
418    }
419    if { [$child getType] == "VOLTAGE_DOMAIN" } {
420      utl::error "child group is not of physical cluster type"
421    }
422    $group removeGroup $child
423  }
424}
425
426sta::define_cmd_args "report_physical_clusters" {}
427
428proc report_physical_clusters {} {
429  set db [ord::get_db]
430  set chip [$db getChip]
431  if { $chip == "NULL" } {
432    utl::error "please load the design before trying to use this command"
433  }
434  set block [$chip getBlock]
435  set groups [$block getGroups]
436  utl::report "\nReporting Physical Clusters"
437  foreach group $groups {
438    if { [$group getType] == "PHYSICAL_CLUSTER" } {
439      report_group $group
440    }
441  }
442}
443
444sta::define_cmd_args "report_voltage_domains" {}
445
446proc report_voltage_domains {} {
447  set db [ord::get_db]
448  set chip [$db getChip]
449  if { $chip == "NULL" } {
450    utl::error "please load the design before trying to use this command"
451  }
452  set block [$chip getBlock]
453  set groups [$block getGroups]
454  utl::report "\nReporting Voltage Domains"
455  foreach group $groups {
456    if { [$group getType] == "VOLTAGE_DOMAIN" } {
457      report_group $group
458    }
459  }
460}
461
462proc report_group { group } {
463  utl::report "[expr \"[$group getType]\" == \"PHYSICAL_CLUSTER\" ? \"Physical Cluster\": \"Voltage Domain\"]: [$group getName]"
464  if { [$group hasBox] } {
465    set rect [$group getBox]
466    utl::report "  * Box : ([$rect xMin],[$rect yMin]) ([$rect xMax],[$rect yMax])"
467  }
468  set modinsts [$group getModInsts]
469  set insts [$group getInsts]
470  set children [$group getGroups]
471  set powerNets [$group getPowerNets]
472  set groundNets [$group getGroundNets]
473  if { [llength $modinsts] > 0 } {
474    utl::report "  * ModInsts: "
475    foreach modinst $modinsts {
476      utl::report "    * [$modinst getHierarchalName]"
477    }
478  }
479  if { [llength $insts] > 0 } {
480    utl::report "  * Insts: "
481    foreach inst $insts {
482      utl::report "    * [$inst getName]"
483    }
484  }
485  if { [llength $children] > 0 } {
486    utl::report "  * Children: "
487    foreach child $children {
488      utl::report "    * [$child getName]"
489    }
490  }
491  if { [llength $powerNets] > 0 } {
492    utl::report "  * Power Nets: "
493    foreach net $powerNets {
494      utl::report "    * [$net getName]"
495    }
496  }
497  if { [llength $groundNets] > 0 } {
498    utl::report "  * Ground Nets: "
499    foreach net $groundNets {
500      utl::report "    * [$net getName]"
501    }
502  }
503}
504
505# pre-logger compatibility for this file only
506namespace eval ord {
507
508proc error { args } {
509 utl::error ODB 0 [lindex $args 0]
510}
511
512}
513