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