1# OpenSTA, Static Timing Analyzer 2# Copyright (c) 2021, Parallax Software, Inc. 3# 4# This program is free software: you can redistribute it and/or modify 5# it under the terms of the GNU General Public License as published by 6# the Free Software Foundation, either version 3 of the License, or 7# (at your option) any later version. 8# 9# This program is distributed in the hope that it will be useful, 10# but WITHOUT ANY WARRANTY; without even the implied warranty of 11# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12# GNU General Public License for more details. 13# 14# You should have received a copy of the GNU General Public License 15# along with this program. If not, see <https://www.gnu.org/licenses/>. 16 17namespace eval sta { 18 19################################################################ 20# 21# Non-SDC commands 22# 23################################################################ 24 25define_cmd_args "delete_clock" {[-all] clocks} 26 27proc delete_clock { args } { 28 parse_key_args "delete_clock" args keys {} flags {-all} 29 if { [info exists flags(-all)] } { 30 check_argc_eq0 "delete_clock" $args 31 set clks [all_clocks] 32 } else { 33 check_argc_eq1 "delete_clock" $args 34 set clks [get_clocks_warn "clocks" [lindex $args 0]] 35 } 36 foreach clk $clks { 37 remove_clock_cmd $clk 38 } 39} 40 41################################################################ 42 43define_cmd_args "delete_generated_clock" {[-all] clocks} 44 45proc delete_generated_clock { args } { 46 remove_gclk_cmd "delete_generated_clock" $args 47} 48 49################################################################ 50 51define_cmd_args "set_disable_inferred_clock_gating" { objects } 52 53proc set_disable_inferred_clock_gating { objects } { 54 set_disable_inferred_clock_gating_cmd $objects 55} 56 57proc set_disable_inferred_clock_gating_cmd { objects } { 58 parse_inst_port_pin_arg $objects insts pins 59 foreach inst $insts { 60 disable_clock_gating_check_inst $inst 61 } 62 foreach pin $pins { 63 disable_clock_gating_check_pin $pin 64 } 65} 66 67################################################################ 68 69define_cmd_args "unset_case_analysis" {pins} 70 71proc unset_case_analysis { pins } { 72 set pins1 [get_port_pins_error "pins" $pins] 73 foreach pin $pins1 { 74 unset_case_analysis_cmd $pin 75 } 76} 77 78################################################################ 79 80define_cmd_args "unset_clock_groups" \ 81 {[-logically_exclusive] [-physically_exclusive]\ 82 [-asynchronous] [-name names] [-all]} 83 84proc unset_clock_groups { args } { 85 unset_clk_groups_cmd "unset_clock_groups" $args 86} 87 88proc unset_clk_groups_cmd { cmd cmd_args } { 89 parse_key_args $cmd cmd_args \ 90 keys {-name} \ 91 flags {-logically_exclusive -physically_exclusive -asynchronous -all} 92 93 set all [info exists flags(-all)] 94 set names {} 95 if {[info exists keys(-name)]} { 96 set names $keys(-name) 97 } 98 99 if { $all && $names != {} } { 100 sta_error 454 "the -all and -name options are mutually exclusive." 101 } 102 if { !$all && $names == {} } { 103 sta_error 455 "either -all or -name options must be specified." 104 } 105 106 set logically_exclusive [info exists flags(-logically_exclusive)] 107 set physically_exclusive [info exists flags(-physically_exclusive)] 108 set asynchronous [info exists flags(-asynchronous)] 109 110 if { ($logically_exclusive+$physically_exclusive+$asynchronous) == 0 } { 111 sta_error 456 "one of -logically_exclusive, -physically_exclusive or -asynchronous is required." 112 } 113 if { ($logically_exclusive+$physically_exclusive+$asynchronous) > 1 } { 114 sta_error 457 "the keywords -logically_exclusive, -physically_exclusive and -asynchronous are mutually exclusive." 115 } 116 117 if { $all } { 118 if { $logically_exclusive } { 119 unset_clock_groups_logically_exclusive "NULL" 120 } elseif { $physically_exclusive } { 121 unset_clock_groups_physically_exclusive "NULL" 122 } elseif { $asynchronous } { 123 unset_clock_groups_asynchronous "NULL" 124 } 125 } else { 126 foreach name $names { 127 if { $logically_exclusive } { 128 unset_clock_groups_logically_exclusive $name 129 } elseif { $physically_exclusive } { 130 unset_clock_groups_physically_exclusive $name 131 } elseif { $asynchronous } { 132 unset_clock_groups_asynchronous $name 133 } 134 } 135 } 136} 137 138################################################################ 139 140define_cmd_args "unset_clock_latency" {[-source] [-clock clock] objects} 141 142proc unset_clock_latency { args } { 143 unset_clk_latency_cmd "unset_clock_latency" $args 144} 145 146proc unset_clk_latency_cmd { cmd cmd_args } { 147 parse_key_args $cmd cmd_args keys {-clock} flags {-source} 148 check_argc_eq1 $cmd $cmd_args 149 set objects [lindex $cmd_args 0] 150 parse_clk_port_pin_arg $objects clks pins 151 set pin_clk "NULL" 152 if { [info exists keys(-clock)] } { 153 set pin_clk [get_clock_warn "clock" $keys(-clock)] 154 if { $clks != {} } { 155 sta_warn 303 "-clock ignored for clock objects." 156 } 157 } 158 159 if {[info exists flags(-source)]} { 160 # Source latency. 161 foreach clk $clks { 162 unset_clock_insertion_cmd $clk "NULL" 163 } 164 foreach pin $pins { 165 # Source only allowed on clocks and clock pins. 166 if { ![is_clock_pin $pin] } { 167 sta_error 458 "-source '[$pin path_name]' is not a clock pin." 168 } 169 unset_clock_insertion_cmd $pin_clk $pin 170 } 171 } else { 172 # Latency. 173 foreach clk $clks { 174 unset_clock_latency_cmd $clk "NULL" 175 } 176 foreach pin $pins { 177 unset_clock_latency_cmd $pin_clk $pin 178 } 179 } 180} 181 182################################################################ 183 184define_cmd_args "unset_clock_transition" {clocks} 185 186proc unset_clock_transition { args } { 187 check_argc_eq1 "unset_clock_transition" $args 188 set clks [get_clocks_warn "clocks" [lindex $args 0]] 189 foreach clk $clks { 190 unset_clock_slew_cmd $clk 191 } 192} 193 194################################################################ 195 196define_cmd_args "unset_clock_uncertainty" \ 197 {[-from|-rise_from|-fall_from from_clock]\ 198 [-to|-rise_to|-fall_to to_clock] [-rise] [-fall]\ 199 [-setup] [-hold] [objects]} 200 201proc unset_clock_uncertainty { args } { 202 unset_clk_uncertainty_cmd "unset_clock_uncertainty" $args 203} 204 205proc unset_clk_uncertainty_cmd { cmd cmd_args } { 206 parse_key_args $cmd cmd_args \ 207 keys {-from -rise_from -fall_from -to -rise_to -fall_to} \ 208 flags {-rise -fall -setup -hold} 209 210 set min_max "min_max" 211 if { [info exists flags(-setup)] && ![info exists flags(-hold)] } { 212 set min_max "max" 213 } 214 if { [info exists flags(-hold)] && ![info exists flags(-setup)] } { 215 set min_max "min" 216 } 217 218 if { [info exists keys(-from)] } { 219 set from_key "-from" 220 set from_rf "rise_fall" 221 } elseif { [info exists keys(-rise_from)] } { 222 set from_key "-rise_from" 223 set from_rf "rise" 224 } elseif { [info exists keys(-fall_from)] } { 225 set from_key "-fall_from" 226 set from_rf "fall" 227 } else { 228 set from_key "none" 229 } 230 231 if { [info exists keys(-to)] } { 232 set to_key "-to" 233 set to_rf "rise_fall" 234 } elseif { [info exists keys(-rise_to)] } { 235 set to_key "-rise_to" 236 set to_rf "rise" 237 } elseif { [info exists keys(-fall_to)] } { 238 set to_key "-fall_to" 239 set to_rf "fall" 240 } else { 241 set to_key "none" 242 } 243 244 if { $from_key != "none" && $to_key == "none" \ 245 || $from_key == "none" && $to_key != "none" } { 246 sta_error 459 "-from/-to must be used together." 247 } elseif { $from_key != "none" && $to_key != "none" } { 248 # Inter-clock uncertainty. 249 check_argc_eq0 "unset_clock_uncertainty" $cmd_args 250 251 # -from/-to can be lists. 252 set from_clks [get_clocks_warn "from_clocks" $keys($from_key)] 253 set to_clks [get_clocks_warn "to_clocks" $keys($to_key)] 254 255 foreach from_clk $from_clks { 256 foreach to_clk $to_clks { 257 unset_inter_clock_uncertainty $from_clk $from_rf \ 258 $to_clk $to_rf $min_max 259 } 260 } 261 } else { 262 # Single clock uncertainty. 263 check_argc_eq1 $cmd $cmd_args 264 if { [info exists keys(-rise)] \ 265 || [info exists keys(-fall)] } { 266 sta_error 460 "-rise, -fall options not allowed for single clock uncertainty." 267 } 268 set objects [lindex $cmd_args 0] 269 parse_clk_port_pin_arg $objects clks pins 270 271 foreach clk $clks { 272 unset_clock_uncertainty_clk $clk $min_max 273 } 274 foreach pin $pins { 275 unset_clock_uncertainty_pin $pin $min_max 276 } 277 } 278} 279 280################################################################ 281 282define_cmd_args "unset_data_check" \ 283 {[-from from_pin] [-rise_from from_pin] [-fall_from from_pin]\ 284 [-to to_pin] [-rise_to to_pin] [-fall_to to_pin]\ 285 [-setup | -hold] [-clock clock]} 286 287proc unset_data_check { args } { 288 unset_data_checks_cmd "unset_data_check" $args 289} 290 291proc unset_data_checks_cmd { cmd cmd_args } { 292 parse_key_args cmd cmd_args \ 293 keys {-from -rise_from -fall_from -to -rise_to -fall_to -clock} \ 294 flags {-setup -hold} 295 check_argc_eq0 $cmd $cmd_args 296 297 set from_rf "rise_fall" 298 set to_rf "rise_fall" 299 set clk "NULL" 300 set setup_hold "max" 301 if [info exists keys(-from)] { 302 set from [get_port_pin_error "from_pin" $keys(-from)] 303 } elseif [info exists keys(-rise_from)] { 304 set from [get_port_pin_error "from_pin" $keys(-rise_from)] 305 set from_rf "rise" 306 } elseif [info exists keys(-fall_from)] { 307 set from [get_port_pin_error "from_pin" $keys(-fall_from)] 308 set from_rf "fall" 309 } else { 310 sta_error 461 "missing -from, -rise_from or -fall_from argument." 311 } 312 313 if [info exists keys(-to)] { 314 set to [get_port_pin_error "to_pin" $keys(-to)] 315 } elseif [info exists keys(-rise_to)] { 316 set to [get_port_pin_error "to_pin" $keys(-rise_to)] 317 set to_rf "rise" 318 } elseif [info exists keys(-fall_to)] { 319 set to [get_port_pin_error "to_pin" $keys(-fall_to)] 320 set to_rf "fall" 321 } else { 322 sta_error 462 "missing -to, -rise_to or -fall_to argument." 323 } 324 325 if [info exists keys(-clock)] { 326 set clk [get_clock_warn "clock" $keys(-clock)] 327 } 328 329 if { [info exists flags(-setup)] && ![info exists flags(-hold)] } { 330 set setup_hold "setup" 331 } elseif { [info exists flags(-hold)] && ![info exists flags(-setup)] } { 332 set setup_hold "hold" 333 } else { 334 set setup_hold "setup_hold" 335 } 336 337 unset_data_check_cmd $from $from_rf $to $to_rf $clk $setup_hold 338} 339 340################################################################ 341 342define_cmd_args "unset_disable_inferred_clock_gating" { objects } 343 344proc unset_disable_inferred_clock_gating { objects } { 345 unset_disable_inferred_clock_gating_cmd $objects 346} 347 348proc unset_disable_inferred_clock_gating_cmd { objects } { 349 parse_inst_port_pin_arg $objects insts pins 350 foreach inst $insts { 351 unset_disable_clock_gating_check_inst $inst 352 } 353 foreach pin $pins { 354 unset_disable_clock_gating_check_pin $pin 355 } 356} 357 358################################################################ 359 360define_cmd_args "unset_disable_timing" \ 361 {[-from from_port] [-to to_port] objects} 362 363proc unset_disable_timing { args } { 364 unset_disable_cmd "unset_disable_timing" $args 365} 366 367proc unset_disable_cmd { cmd cmd_args } { 368 parse_key_args $cmd cmd_args keys {-from -to} flags {} 369 check_argc_eq1 $cmd $cmd_args 370 371 set from "" 372 if { [info exists keys(-from)] } { 373 set from $keys(-from) 374 } 375 set to "" 376 if { [info exists keys(-to)] } { 377 set to $keys(-to) 378 } 379 parse_libcell_libport_inst_port_pin_edge_timing_arc_set_arg $cmd_args \ 380 libcells libports insts ports pins edges timing_arc_sets 381 382 if { ([info exists keys(-from)] || [info exists keys(-to)]) \ 383 && ($libports != {} || $pins != {} || $ports != {}) } { 384 sta_warn 304 "-from/-to keywords ignored for lib_pin, port and pin arguments." 385 } 386 387 foreach libcell $libcells { 388 unset_disable_timing_cell $libcell $from $to 389 } 390 foreach libport $libports { 391 unset_disable_lib_port $libport 392 } 393 foreach inst $insts { 394 unset_disable_timing_instance $inst $from $to 395 } 396 foreach pin $pins { 397 unset_disable_pin $pin 398 } 399 foreach port $ports { 400 unset_disable_port $port 401 } 402 foreach edge $edges { 403 unset_disable_edge $edge 404 } 405 foreach timing_arc_set $timing_arc_sets { 406 unset_disable_timing_arc_set $timing_arc_set 407 } 408} 409 410proc unset_disable_timing_cell { cell from to } { 411 set from_ports [parse_disable_cell_ports $cell $from] 412 set to_ports [parse_disable_cell_ports $cell $to] 413 if { $from_ports == "NULL" && $to_ports == "NULL" } { 414 unset_disable_cell $cell "NULL" "NULL" 415 } elseif { $from_ports == "NULL" } { 416 foreach to_port $to_ports { 417 unset_disable_cell $cell "NULL" $to_port 418 } 419 } elseif { $to_ports == "NULL" } { 420 foreach from_port $from_ports { 421 unset_disable_cell $cell $from_port "NULL" 422 } 423 } else { 424 foreach from_port $from_ports { 425 foreach to_port $to_ports { 426 unset_disable_cell $cell $from_port $to_port 427 } 428 } 429 } 430} 431 432proc unset_disable_timing_instance { inst from to } { 433 set from_ports [parse_disable_inst_ports $inst $from] 434 set to_ports [parse_disable_inst_ports $inst $to] 435 if { ![$inst is_leaf] } { 436 sta_error 463 "-from/-to hierarchical instance not supported." 437 } 438 if { $from_ports == "NULL" && $to_ports == "NULL" } { 439 unset_disable_instance $inst "NULL" "NULL" 440 } elseif { $from_ports == "NULL" } { 441 foreach to_port $to_ports { 442 unset_disable_instance $inst "NULL" $to_port 443 } 444 } elseif { $to_ports == "NULL" } { 445 foreach from_port $from_ports { 446 unset_disable_instance $inst $from_port "NULL" 447 } 448 } else { 449 foreach from_port $from_ports { 450 foreach to_port $to_ports { 451 unset_disable_instance $inst $from_port $to_port 452 } 453 } 454 } 455} 456 457################################################################ 458 459define_cmd_args "unset_generated_clock" {[-all] clocks} 460 461proc unset_generated_clock { args } { 462 unset_gclk_cmd "unset_generated_clock" $args 463} 464 465proc remove_gclk_cmd { cmd cmd_args } { 466 parse_key_args $cmd cmd_args keys {} flags {-all} 467 if { [info exists flags(-all)] } { 468 check_argc_eq0 $cmd $cmd_args 469 set clks [all_clocks] 470 } else { 471 check_argc_eq1 $cmd $cmd_args 472 set clks [get_clocks_warn "clocks" [lindex $cmd_args 0]] 473 } 474 foreach clk $clks { 475 if { [$clk is_generated] } { 476 remove_clock_cmd $clk 477 } 478 } 479} 480 481################################################################ 482 483define_cmd_args "unset_input_delay" \ 484 {[-rise] [-fall] [-max] [-min]\ 485 [-clock clock] [-clock_fall]\ 486 port_pin_list} 487 488proc unset_input_delay { args } { 489 unset_port_delay "unset_input_delay" "unset_input_delay_cmd" $args 490} 491 492################################################################ 493 494define_cmd_args "unset_output_delay" \ 495 {[-rise] [-fall] [-max] [-min]\ 496 [-clock clock] [-clock_fall]\ 497 port_pin_list} 498 499proc unset_output_delay { args } { 500 unset_port_delay "unset_output_delay" "unset_output_delay_cmd" $args 501} 502 503proc unset_port_delay { cmd swig_cmd cmd_args } { 504 parse_key_args $cmd cmd_args \ 505 keys {-clock -reference_pin} \ 506 flags {-rise -fall -max -min -clock_fall } 507 check_argc_eq1 $cmd $cmd_args 508 509 set pins [get_port_pins_error "pins" [lindex $cmd_args 0]] 510 511 set clk "NULL" 512 if [info exists keys(-clock)] { 513 set clk [get_clock_warn "clock" $keys(-clock)] 514 } 515 516 if [info exists flags(-clock_fall)] { 517 set clk_rf "fall" 518 } else { 519 set clk_rf "rise" 520 } 521 522 set tr [parse_rise_fall_flags flags] 523 set min_max [parse_min_max_all_flags flags] 524 525 foreach pin $pins { 526 $swig_cmd $pin $tr $clk $clk_rf $min_max 527 } 528} 529 530################################################################ 531 532define_cmd_args "unset_path_exceptions" \ 533 {[-setup] [-hold] [-rise] [-fall] [-from from_list]\ 534 [-rise_from from_list] [-fall_from from_list]\ 535 [-through through_list] [-rise_through through_list]\ 536 [-fall_through through_list] [-to to_list] [-rise_to to_list]\ 537 [-fall_to to_list]} 538 539proc unset_path_exceptions { args } { 540 unset_path_exceptions_cmd "unset_path_exceptions" $args 541} 542 543proc unset_path_exceptions_cmd { cmd cmd_args } { 544 parse_key_args $cmd cmd_args \ 545 keys {-from -rise_from -fall_from -to -rise_to -fall_to} \ 546 flags {-setup -hold -rise -fall} 0 547 548 set min_max "min_max" 549 if { [info exists flags(-setup)] && ![info exists flags(-hold)] } { 550 set min_max "max" 551 } 552 if { [info exists flags(-hold)] && ![info exists flags(-setup)] } { 553 set min_max "min" 554 } 555 556 set arg_error 0 557 set from [parse_from_arg keys arg_error] 558 set thrus [parse_thrus_arg cmd_args arg_error] 559 set to [parse_to_arg keys flags arg_error] 560 if { $arg_error } { 561 delete_from_thrus_to $from $thrus $to 562 sta_error 464 "$cmd command failed." 563 return 0 564 } 565 566 check_for_key_args $cmd cmd_args 567 if { $cmd_args != {} } { 568 delete_from_thrus_to $from $thrus $to 569 sta_error 465 "positional arguments not supported." 570 } 571 if { ($from == "NULL" && $thrus == "" && $to == "NULL") } { 572 delete_from_thrus_to $from $thrus $to 573 sta_error 466 "-from, -through or -to required." 574 } 575 576 reset_path_cmd $from $thrus $to $min_max 577 delete_from_thrus_to $from $thrus $to 578} 579 580################################################################ 581 582define_cmd_args "unset_propagated_clock" {objects} 583 584proc unset_propagated_clock { objects } { 585 parse_clk_port_pin_arg $objects clks pins 586 foreach clk $clks { 587 unset_propagated_clock_cmd $clk 588 } 589 foreach pin $pins { 590 unset_propagated_clock_pin_cmd $pin 591 } 592} 593 594################################################################ 595 596define_cmd_args "unset_timing_derate" {} 597 598proc unset_timing_derate { args } { 599 check_argc_eq0 "unset_timing_derate" $args 600 reset_timing_derate_cmd 601} 602 603################################################################ 604# 605# Network editing commands 606# 607################################################################ 608 609define_cmd_args "connect_pin" {net pin} 610# deprecated 2.0.16 05/02/2019 611define_cmd_args "connect_pins" {net pins} 612 613define_cmd_args "delete_instance" {inst} 614 615define_cmd_args "delete_net" {net} 616 617define_cmd_args "disconnect_pin" {net -all|pin} 618# deprecated 2.0.16 05/02/2019 619define_cmd_args "disconnect_pins" {net -all|pins} 620 621define_cmd_args "make_instance" {inst_path lib_cell} 622 623define_cmd_args "make_net" {} 624 625define_cmd_args "replace_cell" {instance lib_cell} 626 627define_cmd_args "insert_buffer" {buffer_name buffer_cell net load_pins\ 628 buffer_out_net_name} 629 630################################################################ 631# 632# Delay calculation commands 633# 634################################################################ 635 636define_cmd_args "set_assigned_delay" \ 637 {-cell|-net [-rise] [-fall] [-corner corner_name] [-min] [-max]\ 638 [-from from_pins] [-to to_pins] delay} 639 640# Change the delay for timing arcs between from_pins and to_pins matching 641# on cell (instance) or net. 642proc set_assigned_delay { args } { 643 set_assigned_delay_cmd "set_assigned_delay" $args 644} 645 646proc set_assigned_delay_cmd { cmd cmd_args } { 647 parse_key_args $cmd cmd_args keys {-corner -from -to} \ 648 flags {-cell -net -rise -fall -max -min} 649 check_argc_eq1 $cmd $cmd_args 650 set corner [parse_corner keys] 651 set min_max [parse_min_max_all_check_flags flags] 652 set to_rf [parse_rise_fall_flags flags] 653 654 if [info exists keys(-from)] { 655 set from_pins [get_port_pins_error "from_pins" $keys(-from)] 656 } else { 657 sta_error 442 "$cmd missing -from argument." 658 } 659 if [info exists keys(-to)] { 660 set to_pins [get_port_pins_error "to_pins" $keys(-to)] 661 } else { 662 sta_error 443 "$cmd missing -to argument." 663 } 664 665 set delay [lindex $cmd_args 0] 666 if {![string is double $delay]} { 667 sta_error 444 "$cmd delay is not a float." 668 } 669 set delay [time_ui_sta $delay] 670 671 if {[info exists flags(-cell)] && [info exists flags(-net)]} { 672 sta_error 445 "set_annotated_delay -cell and -net options are mutually excluive." 673 } elseif {[info exists flags(-cell)]} { 674 if { $from_pins != {} } { 675 set inst [[lindex $from_pins 0] instance] 676 foreach pin $from_pins { 677 if {[$pin instance] != $inst} { 678 sta_error 446 "$cmd pin [get_full_name $pin] is not attached to instance [get_full_name $inst]." 679 } 680 } 681 foreach pin $to_pins { 682 if {[$pin instance] != $inst} { 683 sta_error 447 "$cmd pin [get_full_name $pin] is not attached to instance [get_full_name $inst]" 684 } 685 } 686 } 687 } elseif {![info exists flags(-net)]} { 688 sta_error 448 "$cmd -cell or -net required." 689 } 690 foreach from_pin $from_pins { 691 set from_vertices [$from_pin vertices] 692 set_assigned_delay1 [lindex $from_vertices 0] \ 693 $to_pins $to_rf $corner $min_max $delay 694 if { [llength $from_vertices] == 2 } { 695 set_assigned_delay1 [lindex $from_vertices 1] \ 696 $to_pins $to_rf $corner $min_max $delay 697 } 698 } 699} 700 701proc set_assigned_delay1 { from_vertex to_pins to_rf corner min_max delay } { 702 foreach to_pin $to_pins { 703 set to_vertices [$to_pin vertices] 704 set_assigned_delay2 $from_vertex [lindex $to_vertices 0] \ 705 $to_rf $corner $min_max $delay 706 if { [llength $to_vertices] == 2 } { 707 # Bidirect driver. 708 set_assigned_delay2 $from_vertex [lindex $to_vertices 1] \ 709 $to_rf $corner $min_max $delay 710 } 711 } 712} 713 714proc set_assigned_delay2 {from_vertex to_vertex to_rf corner min_max delay} { 715 set edge_iter [$from_vertex out_edge_iterator] 716 while {[$edge_iter has_next]} { 717 set edge [$edge_iter next] 718 if { [$edge to] == $to_vertex \ 719 && ![timing_role_is_check [$edge role]] } { 720 set arc_iter [$edge timing_arc_iterator] 721 while {[$arc_iter has_next]} { 722 set arc [$arc_iter next] 723 if { $to_rf == "rise_fall" \ 724 || $to_rf eq [$arc to_trans_name] } { 725 set_arc_delay $edge $arc $corner $min_max $delay 726 } 727 } 728 $arc_iter finish 729 } 730 } 731 $edge_iter finish 732} 733 734################################################################ 735 736define_cmd_args "set_assigned_check" \ 737 {-setup|-hold|-recovery|-removal [-rise] [-fall]\ 738 [-corner corner_name] [-min] [-max]\ 739 [-from from_pins] [-to to_pins] [-clock rise|fall]\ 740 [-cond sdf_cond] [-worst] check_value} 741 742# -worst is ignored. 743proc set_assigned_check { args } { 744 set_assigned_check_cmd "set_assigned_check" $args 745} 746 747# -worst is ignored. 748proc set_assigned_check_cmd { cmd cmd_args } { 749 parse_key_args $cmd cmd_args \ 750 keys {-from -to -corner -clock -cond} \ 751 flags {-setup -hold -recovery -removal -rise -fall -max -min -worst} 752 check_argc_eq1 $cmd $cmd_args 753 754 if { [info exists keys(-from)] } { 755 set from_pins [get_port_pins_error "from_pins" $keys(-from)] 756 } else { 757 sta_error 449 "$cmd missing -from argument." 758 } 759 set from_rf "rise_fall" 760 if { [info exists keys(-clock)] } { 761 set clk_arg $keys(-clock) 762 if { $clk_arg eq "rise" \ 763 || $clk_arg eq "fall" } { 764 set from_rf $clk_arg 765 } else { 766 sta_error 450 "$cmd -clock must be rise or fall." 767 } 768 } 769 770 if { [info exists keys(-to)] } { 771 set to_pins [get_port_pins_error "to_pins" $keys(-to)] 772 } else { 773 sta_error 451 "$cmd missing -to argument." 774 } 775 set to_rf [parse_rise_fall_flags flags] 776 set corner [parse_corner keys] 777 set min_max [parse_min_max_all_check_flags flags] 778 779 if { [info exists flags(-setup)] } { 780 set role "setup" 781 } elseif { [info exists flags(-hold)] } { 782 set role "hold" 783 } elseif { [info exists flags(-recovery)] } { 784 set role "recovery" 785 } elseif { [info exists flags(-removal)] } { 786 set role "removal" 787 } else { 788 sta_error 452 "$cmd missing -setup|-hold|-recovery|-removal check type.." 789 } 790 set cond "" 791 if { [info exists key(-cond)] } { 792 set cond $key(-cond) 793 } 794 set check_value [lindex $cmd_args 0] 795 if { ![string is double $check_value] } { 796 sta_error 453 "$cmd check_value is not a float." 797 } 798 set check_value [time_ui_sta $check_value] 799 800 foreach from_pin $from_pins { 801 set from_vertices [$from_pin vertices] 802 set_assigned_check1 [lindex $from_vertices 0] $from_rf \ 803 $to_pins $to_rf $role $corner $min_max $cond $check_value 804 if { [llength $from_vertices] == 2 } { 805 set_assigned_check1 [lindex $from_vertices 1] $from_rf \ 806 $to_pins $to_rf $role $corner $min_max $cond $check_value 807 } 808 } 809} 810 811proc set_assigned_check1 { from_vertex from_rf to_pins to_rf \ 812 role corner min_max cond check_value } { 813 foreach to_pin $to_pins { 814 set to_vertices [$to_pin vertices] 815 set_assigned_check2 $from_vertex $from_rf [lindex $to_vertices 0] \ 816 $to_rf $role $corner $min_max $cond $check_value 817 if { [llength $to_vertices] == 2 } { 818 # Bidirect driver. 819 set_assigned_check2 $from_vertex $from_rf \ 820 [lindex $to_vertices 1] $to_rf $role $corner $min_max \ 821 $cond $check_value 822 } 823 } 824} 825 826proc set_assigned_check2 { from_vertex from_rf to_vertex to_rf \ 827 role corner min_max cond check_value } { 828 set edge_iter [$from_vertex out_edge_iterator] 829 while {[$edge_iter has_next]} { 830 set edge [$edge_iter next] 831 if { [$edge to] == $to_vertex } { 832 set arc_iter [$edge timing_arc_iterator] 833 while {[$arc_iter has_next]} { 834 set arc [$arc_iter next] 835 if { ($from_rf eq "rise_fall" \ 836 || $from_rf eq [$arc from_trans_name]) \ 837 && ($to_rf eq "rise_fall" \ 838 || $to_rf eq [$arc to_trans_name]) \ 839 && [$arc role] eq $role \ 840 && ($cond eq "" || [$arc sdf_cond] eq $cond) } { 841 set_arc_delay $edge $arc $corner $min_max $check_value 842 } 843 } 844 $arc_iter finish 845 } 846 } 847 $edge_iter finish 848} 849 850################################################################a 851 852define_cmd_args "set_assigned_transition" \ 853 {[-rise] [-fall] [-corner corner_name] [-min] [-max] slew pins} 854 855# Change the slew on a list of ports. 856proc set_assigned_transition { args } { 857 parse_key_args "set_assigned_transition" args keys {-corner} \ 858 flags {-rise -fall -max -min} 859 860 set corner [parse_corner keys] 861 set min_max [parse_min_max_all_check_flags flags] 862 set tr [parse_rise_fall_flags flags] 863 check_argc_eq2 "set_assigned_transition" $args 864 865 set slew [lindex $args 0] 866 if {![string is double $slew]} { 867 sta_error 428 "set_assigned_transition transition is not a float." 868 } 869 set slew [time_ui_sta $slew] 870 set pins [get_port_pins_error "pins" [lindex $args 1]] 871 foreach pin $pins { 872 set vertices [$pin vertices] 873 set vertex [lindex $vertices 0] 874 set_annotated_slew $vertex $corner $min_max $tr $slew 875 if { [llength $vertices] == 2 } { 876 # Bidirect driver. 877 set vertex [lindex $vertices 1] 878 set_annotated_slew $vertex $min_max $tr $slew 879 } 880 } 881} 882 883################################################################a 884 885# compatibility 886define_cmd_args "read_parasitics" \ 887 {[-min]\ 888 [-max]\ 889 [-elmore]\ 890 [-path path]\ 891 [-increment]\ 892 [-pin_cap_included]\ 893 [-keep_capacitive_coupling]\ 894 [-coupling_reduction_factor factor]\ 895 [-reduce_to pi_elmore|pi_pole_residue2]\ 896 [-delete_after_reduce]\ 897 [-quiet]\ 898 [-save]\ 899 filename} 900 901################################################################ 902# 903# Utility commands 904# 905################################################################ 906 907define_cmd_args "delete_from_list" {list objs} 908 909proc delete_from_list { list objects } { 910 delete_objects_from_list_cmd $list $objects 911} 912 913proc delete_objects_from_list_cmd { list objects } { 914 set list0 [lindex $list 0] 915 set list_is_object [is_object $list0] 916 set list_type [object_type $list0] 917 foreach obj $objects { 918 # If the list is a collection of tcl objects (returned by get_*), 919 # convert the obj to be removed from a name to an object of the same 920 # type. 921 if {$list_is_object && ![is_object $obj]} { 922 if {$list_type == "Clock"} { 923 set obj [find_clock $obj] 924 } elseif {$list_type == "Port"} { 925 set top_instance [top_instance] 926 set top_cell [$top_instance cell] 927 set obj [$top_cell find_port $obj] 928 } elseif {$list_type == "Pin"} { 929 set obj [find_pin $obj] 930 } elseif {$list_type == "Instance"} { 931 set obj [find_instance $obj] 932 } elseif {$list_type == "Net"} { 933 set obj [find_net $obj] 934 } elseif {$list_type == "LibertyLibrary"} { 935 set obj [find_liberty $obj] 936 } elseif {$list_type == "LibertyCell"} { 937 set obj [find_liberty_cell $obj] 938 } elseif {$list_type == "LibertyPort"} { 939 set obj [get_lib_pins $obj] 940 } else { 941 sta_error 439 "unsupported object type $list_type." 942 } 943 } 944 set index [lsearch $list $obj] 945 if { $index != -1 } { 946 set list [lreplace $list $index $index] 947 } 948 } 949 return $list 950} 951 952################################################################ 953 954define_cmd_args "get_fanin" \ 955 {-to sink_list [-flat] [-only_cells] [-startpoints_only]\ 956 [-levels level_count] [-pin_levels pin_count]\ 957 [-trace_arcs timing|enabled|all]} 958 959proc get_fanin { args } { 960 parse_key_args "get_fanin" args \ 961 keys {-to -levels -pin_levels -trace_arcs} \ 962 flags {-flat -only_cells -startpoints_only} 963 if { [llength $args] != 0 } { 964 cmd_usage_error "get_fanin" 965 } 966 if { ![info exists keys(-to)] } { 967 cmd_usage_error "get_fanin" 968 } 969 parse_port_pin_net_arg $keys(-to) pins nets 970 foreach net $nets { 971 lappend pins [net_driver_pins $net] 972 } 973 set flat [info exists flags(-flat)] 974 set only_insts [info exists flags(-only_cells)] 975 set startpoints_only [info exists flags(-startpoints_only)] 976 set inst_levels 0 977 if { [info exists keys(-levels)] } { 978 set inst_levels $keys(-levels) 979 } 980 set pin_levels 0 981 if { [info exists keys(-pin_levels)] } { 982 set pin_levels $keys(-pin_levels) 983 } 984 985 set thru_disabled 0 986 set thru_constants 0 987 if { [info exists keys(-trace_arcs)] } { 988 set trace_arcs $keys(-trace_arcs) 989 if { $trace_arcs == "timing" } { 990 set thru_disabled 0 991 set thru_constants 0 992 } elseif { $trace_arcs == "enabled" } { 993 set thru_disabled 0 994 set thru_constants 0 995 } elseif { $trace_arcs == "all" } { 996 set thru_disabled 1 997 set thru_constants 1 998 } else { 999 cmd_usage_error "get_fanin" 1000 } 1001 } 1002 if { $only_insts } { 1003 return [find_fanin_insts $pins $flat $startpoints_only \ 1004 $inst_levels $pin_levels $thru_disabled $thru_constants] 1005 } else { 1006 return [find_fanin_pins $pins $flat $startpoints_only \ 1007 $inst_levels $pin_levels $thru_disabled $thru_constants] 1008 } 1009} 1010 1011################################################################ 1012 1013define_cmd_args "get_fanout" \ 1014 {-from source_list [-flat] [-only_cells] [-endpoints_only]\ 1015 [-levels level_count] [-pin_levels pin_count]\ 1016 [-trace_arcs timing|enabled|all]} 1017 1018proc get_fanout { args } { 1019 parse_key_args "get_fanout" args \ 1020 keys {-from -levels -pin_levels -trace_arcs} \ 1021 flags {-flat -only_cells -endpoints_only} 1022 if { [llength $args] != 0 } { 1023 cmd_usage_error "get_fanout" 1024 } 1025 parse_port_pin_net_arg $keys(-from) pins nets 1026 foreach net $nets { 1027 lappend pins [net_load_pins $net] 1028 } 1029 set flat [info exists flags(-flat)] 1030 set only_insts [info exists flags(-only_cells)] 1031 set endpoints_only [info exists flags(-endpoints_only)] 1032 1033 set inst_levels 0 1034 if { [info exists keys(-levels)] } { 1035 set inst_levels $keys(-levels) 1036 } 1037 1038 set pin_levels 0 1039 if { [info exists keys(-pin_levels)] } { 1040 set pin_levels $keys(-pin_levels) 1041 } 1042 1043 set thru_disabled 0 1044 set thru_constants 0 1045 if { [info exists keys(-trace_arcs)] } { 1046 set trace_arcs $keys(-trace_arcs) 1047 if { $trace_arcs == "timing" } { 1048 set thru_disabled 0 1049 set thru_constants 0 1050 } elseif { $trace_arcs == "enabled" } { 1051 set thru_disabled 0 1052 set thru_constants 0 1053 } elseif { $trace_arcs == "all" } { 1054 set thru_disabled 1 1055 set thru_constants 1 1056 } else { 1057 cmd_usage_error "get_fanout" 1058 } 1059 } 1060 if { $only_insts } { 1061 return [find_fanout_insts $pins $flat $endpoints_only \ 1062 $inst_levels $pin_levels $thru_disabled $thru_constants] 1063 } else { 1064 return [find_fanout_pins $pins $flat $endpoints_only \ 1065 $inst_levels $pin_levels $thru_disabled $thru_constants] 1066 } 1067} 1068 1069################################################################ 1070 1071define_cmd_args "get_name" {objects} 1072define_cmd_args "get_full_name" {objects} 1073 1074################################################################ 1075 1076define_cmd_args "get_property" \ 1077 {[-object_type cell|pin|net|port|clock|timing_arc] object property} 1078 1079proc get_property { args } { 1080 return [get_property_cmd "get_property" "-object_type" $args] 1081} 1082 1083################################################################ 1084 1085proc get_property_cmd { cmd type_key cmd_args } { 1086 parse_key_args $cmd cmd_args keys $type_key flags {-quiet} 1087 set quiet [info exists flags(-quiet)] 1088 check_argc_eq2 $cmd $cmd_args 1089 set object [lindex $cmd_args 0] 1090 if { $object == "" } { 1091 sta_error 491 "$cmd object is null." 1092 } elseif { ![is_object $object] } { 1093 if [info exists keys($type_key)] { 1094 set object_type $keys($type_key) 1095 } else { 1096 sta_error 492 "$cmd $type_key must be specified with object name argument." 1097 } 1098 set object [get_property_object_type $object_type $object $quiet] 1099 } 1100 set prop [lindex $cmd_args 1] 1101 return [get_object_property $object $prop] 1102} 1103 1104proc get_object_property { object prop } { 1105 if { [is_object $object] } { 1106 set object_type [object_type $object] 1107 if { $object_type == "Instance" } { 1108 return [instance_property $object $prop] 1109 } elseif { $object_type == "Pin" } { 1110 return [pin_property $object $prop] 1111 } elseif { $object_type == "Net" } { 1112 return [net_property $object $prop] 1113 } elseif { $object_type == "Clock" } { 1114 return [clock_property $object $prop] 1115 } elseif { $object_type == "Port" } { 1116 return [port_property $object $prop] 1117 } elseif { $object_type == "LibertyPort" } { 1118 return [liberty_port_property $object $prop] 1119 } elseif { $object_type == "LibertyCell" } { 1120 return [liberty_cell_property $object $prop] 1121 } elseif { $object_type == "Cell" } { 1122 return [cell_property $object $prop] 1123 } elseif { $object_type == "Library" } { 1124 return [library_property $object $prop] 1125 } elseif { $object_type == "LibertyLibrary" } { 1126 return [liberty_library_property $object $prop] 1127 } elseif { $object_type == "Edge" } { 1128 return [edge_property $object $prop] 1129 } elseif { $object_type == "PathEnd" } { 1130 return [path_end_property $object $prop] 1131 } elseif { $object_type == "PathRef" } { 1132 return [path_ref_property $object $prop] 1133 } elseif { $object_type == "TimingArcSet" } { 1134 return [timing_arc_set_property $object $prop] 1135 } else { 1136 sta_error 606 "get_property unsupported object type $object_type." 1137 } 1138 } else { 1139 sta_error 493 "get_property $object is not an object." 1140 } 1141} 1142 1143proc get_property_object_type { object_type object_name quiet } { 1144 set object "NULL" 1145 if { $object_type == "cell" } { 1146 set object [get_cells -quiet $object_name] 1147 } elseif { $object_type == "pin" } { 1148 set object [get_pins -quiet $object_name] 1149 } elseif { $object_type == "net" } { 1150 set object [get_nets -quiet $object_name] 1151 } elseif { $object_type == "port" } { 1152 set object [get_ports -quiet $object_name] 1153 } elseif { $object_type == "clock" } { 1154 set object [get_clocks -quiet $object_name] 1155 } elseif { $object_type == "lib_cell" } { 1156 set object [get_lib_cells -quiet $object_name] 1157 } elseif { $object_type == "lib_pin" } { 1158 set object [get_lib_pins -quiet $object_name] 1159 } elseif { $object_type == "lib" } { 1160 set object [get_libs -quiet $object_name] 1161 } else { 1162 sta_error 494 "$object_type not supported." 1163 } 1164 if { $object == "NULL" && !$quiet } { 1165 sta_error 495 "$object_type '$object_name' not found." 1166 } 1167 return [lindex $object 0] 1168} 1169 1170proc get_object_type { obj } { 1171 set object_type [object_type $obj] 1172 if { $object_type == "Clock" } { 1173 return "clock" 1174 } elseif { $object_type == "LibertyCell" } { 1175 return "libcell" 1176 } elseif { $object_type == "LibertyPort" } { 1177 return "libpin" 1178 } elseif { $object_type == "Cell" } { 1179 return "design" 1180 } elseif { $object_type == "Instance" } { 1181 return "cell" 1182 } elseif { $object_type == "Port" } { 1183 return "port" 1184 } elseif { $object_type == "Pin" } { 1185 return "pin" 1186 } elseif { $object_type == "Net" } { 1187 return "net" 1188 } elseif { $object_type == "Edge" } { 1189 return "timing_arc" 1190 } elseif { $object_type == "TimingArcSet" } { 1191 return "timing_arc" 1192 } else { 1193 return "?" 1194 } 1195} 1196 1197proc get_name { object } { 1198 return [get_object_property $object "name"] 1199} 1200 1201proc get_full_name { object } { 1202 return [get_object_property $object "full_name"] 1203} 1204 1205proc sort_by_name { objects } { 1206 return [lsort -command name_cmp $objects] 1207} 1208 1209proc name_cmp { obj1 obj2 } { 1210 return [string compare [get_name $obj1] [get_name $obj2]] 1211} 1212 1213proc sort_by_full_name { objects } { 1214 return [lsort -command full_name_cmp $objects] 1215} 1216 1217proc full_name_cmp { obj1 obj2 } { 1218 return [string compare [get_full_name $obj1] [get_full_name $obj2]] 1219} 1220 1221################################################################ 1222 1223define_cmd_args "get_timing_edges" \ 1224 {[-from from_pin] [-to to_pin] [-of_objects objects] [-filter expr]} 1225 1226proc get_timing_edges { args } { 1227 return [get_timing_edges_cmd "get_timing_edges" $args] 1228} 1229 1230proc get_timing_edges_cmd { cmd cmd_args } { 1231 parse_key_args $cmd cmd_args \ 1232 keys {-from -to -of_objects -filter} flags {} 1233 check_argc_eq0 $cmd $cmd_args 1234 1235 set arcs {} 1236 if { [info exists keys(-of_objects)] } { 1237 if { [info exists keys(-from)] \ 1238 || [info exists keys(-from)] } { 1239 sta_error 440 "-from/-to arguments not supported with -of_objects." 1240 } 1241 set arcs [get_timing_arcs_objects $keys(-of_objects)] 1242 } elseif { [info exists keys(-from)] \ 1243 && [info exists keys(-to)] } { 1244 set arcs [get_timing_arcs_from_to \ 1245 [get_port_pin_error "from" $keys(-from)] \ 1246 [get_port_pin_error "to" $keys(-to)]] 1247 } elseif { [info exists keys(-from)] } { 1248 set arcs [get_timing_arcs_from $keys(-from)] 1249 } elseif { [info exists keys(-to)] } { 1250 set arcs [get_timing_arcs_to $keys(-to)] 1251 } else { 1252 cmd_usage_error $cmd 1253 } 1254 if [info exists keys(-filter)] { 1255 set arcs [filter_timing_arcs1 $keys(-filter) $arcs] 1256 } 1257 return $arcs 1258} 1259 1260proc get_timing_arcs_objects { object_arg } { 1261 parse_libcell_inst_arg $object_arg libcells insts 1262 if { $insts != {} } { 1263 set edges {} 1264 foreach inst $insts { 1265 lappend edges [instance_edges $inst] 1266 } 1267 return $edges 1268 } elseif { $libcells != {} } { 1269 set arc_sets {} 1270 foreach libcell $libcells { 1271 lappend arc_sets [libcell_timing_arc_sets $libcell] 1272 } 1273 return $arc_sets 1274 } 1275} 1276 1277proc instance_edges { inst } { 1278 set edges {} 1279 set pin_iter [$inst pin_iterator] 1280 while {[$pin_iter has_next]} { 1281 set pin [$pin_iter next] 1282 foreach vertex [$pin vertices] { 1283 set edge_iter [$vertex out_edge_iterator] 1284 while {[$edge_iter has_next]} { 1285 set edge [$edge_iter next] 1286 if { [$edge role] != "wire" } { 1287 lappend edges $edge 1288 } 1289 } 1290 $edge_iter finish 1291 } 1292 } 1293 $pin_iter finish 1294 return $edges 1295} 1296 1297proc libcell_timing_arc_sets { libcell } { 1298 set arc_sets {} 1299 set arc_iter [$libcell timing_arc_set_iterator] 1300 while { [$arc_iter has_next] } { 1301 lappend arc_sets [$arc_iter next] 1302 } 1303 $arc_iter finish 1304 return $arc_sets 1305} 1306 1307proc get_timing_arcs_from_to { from_pin_arg to_pin_arg } { 1308 set edges {} 1309 set from_pin [get_port_pin_error "from" $from_pin_arg] 1310 set to_pin [get_port_pin_error "to" $to_pin_arg] 1311 foreach from_vertex [$from_pin vertices] { 1312 foreach to_vertex [$to_pin vertices] { 1313 set edge_iter [$from_vertex out_edge_iterator] 1314 while {[$edge_iter has_next]} { 1315 set edge [$edge_iter next] 1316 if { [$edge to] == $to_vertex } { 1317 lappend edges $edge 1318 } 1319 } 1320 $edge_iter finish 1321 } 1322 } 1323 return $edges 1324} 1325 1326proc get_timing_arcs_from { from_pin_arg } { 1327 set from_pin [get_port_pin_error "from" $from_pin_arg] 1328 set edges {} 1329 foreach from_vertex [$from_pin vertices] { 1330 set edge_iter [$from_vertex out_edge_iterator] 1331 while {[$edge_iter has_next]} { 1332 set edge [$edge_iter next] 1333 lappend edges $edge 1334 } 1335 $edge_iter finish 1336 } 1337 return $edges 1338} 1339 1340proc get_timing_arcs_to { to_pin_arg } { 1341 set to_pin [get_port_pin_error "to" $to_pin_arg] 1342 set edges {} 1343 foreach to_vertex [$to_pin vertices] { 1344 set edge_iter [$to_vertex in_edge_iterator] 1345 while {[$edge_iter has_next]} { 1346 set edge [$edge_iter next] 1347 lappend edges $edge 1348 } 1349 $edge_iter finish 1350 } 1351 return $edges 1352} 1353 1354proc filter_timing_arcs1 { filter objects } { 1355 variable filter_regexp1 1356 variable filter_or_regexp 1357 variable filter_and_regexp 1358 set filtered_objects {} 1359 # Ignore sub-exprs in filter_regexp1 for expr2 match var. 1360 if { [regexp $filter_or_regexp $filter ignore expr1 \ 1361 ignore ignore ignore expr2] } { 1362 regexp $filter_regexp1 $expr1 ignore attr_name op arg 1363 set filtered_objects1 [filter_timing_arcs $attr_name $op $arg $objects] 1364 regexp $filter_regexp1 $expr2 ignore attr_name op arg 1365 set filtered_objects2 [filter_timing_arcs $attr_name $op $arg $objects] 1366 set filtered_objects [concat $filtered_objects1 $filtered_objects2] 1367 } elseif { [regexp $filter_and_regexp $filter ignore expr1 \ 1368 ignore ignore ignore expr2] } { 1369 regexp $filter_regexp1 $expr1 ignore attr_name op arg 1370 set filtered_objects [filter_timing_arcs $attr_name $op $arg $objects] 1371 regexp $filter_regexp1 $expr2 ignore attr_name op arg 1372 set filtered_objects [filter_timing_arcs $attr_name $op \ 1373 $arg $filtered_objects] 1374 } elseif { [regexp $filter_regexp1 $filter ignore attr_name op arg] } { 1375 set filtered_objects [filter_timing_arcs $attr_name $op $arg $objects] 1376 } else { 1377 sta_error 441 "unsupported -filter expression." 1378 } 1379 return $filtered_objects 1380} 1381 1382################################################################ 1383 1384define_cmd_args "report_clock_properties" {[clocks]} 1385 1386proc_redirect report_clock_properties { 1387 check_argc_eq0or1 "report_clock_properties" $args 1388 update_generated_clks 1389 report_line "Clock Period Waveform" 1390 report_line "----------------------------------------------------" 1391 if { [llength $args] == 0 } { 1392 set clk_iter [clock_iterator] 1393 while {[$clk_iter has_next]} { 1394 set clk [$clk_iter next] 1395 report_clock1 $clk 1396 } 1397 $clk_iter finish 1398 } else { 1399 foreach clk [get_clocks_warn "clock_name" [lindex $args 0]] { 1400 report_clock1 $clk 1401 } 1402 } 1403} 1404 1405proc report_clock1 { clk } { 1406 global sta_report_default_digits 1407 1408 if { [$clk waveform_valid] } { 1409 set digits $sta_report_default_digits 1410 set waveform [$clk waveform] 1411 if { $waveform == {} } { 1412 set wave " " 1413 } else { 1414 set wave "" 1415 foreach edge $waveform { 1416 set wave "$wave[format "%10s" [format_time $edge $digits]]" 1417 } 1418 } 1419 if {[$clk is_generated]} { 1420 set generated " (generated)" 1421 } else { 1422 set generated "" 1423 } 1424 report_line "[format %-20s [get_name $clk]][format %10s [format_time [$clk period] $digits]] $wave$generated" 1425 } 1426} 1427 1428################################################################ 1429 1430define_cmd_args "report_object_full_names" {objects} 1431 1432proc report_object_full_names { objects } { 1433 foreach obj [sort_by_full_name $objects] { 1434 report_line [get_full_name $obj] 1435 } 1436} 1437 1438define_cmd_args "report_object_names" {objects} 1439 1440proc report_object_names { objects } { 1441 foreach obj [sort_by_name $objects] { 1442 report_line [get_name $obj] 1443 } 1444} 1445 1446################################################################ 1447 1448define_cmd_args "report_units" {} 1449 1450proc report_units { args } { 1451 check_argc_eq0 "report_units" $args 1452 foreach unit {"time" "capacitance" "resistance" "voltage" "current" "power" "distance"} { 1453 report_line " $unit 1[unit_scale_abreviation $unit][unit_suffix $unit]" 1454 } 1455} 1456 1457################################################################ 1458 1459define_cmd_args "with_output_to_variable" { var { cmds }} 1460 1461# with_output_to_variable variable { command args... } 1462proc with_output_to_variable { var_name args } { 1463 upvar 1 $var_name var 1464 1465 set body [lindex $args 0] 1466 sta::redirect_string_begin; 1467 catch $body ret 1468 set var [sta::redirect_string_end] 1469 return $ret 1470} 1471 1472define_cmd_args "set_pocv_sigma_factor" { factor } 1473 1474################################################################ 1475 1476define_cmd_args "write_path_spice" { -path_args path_args\ 1477 -spice_directory spice_directory\ 1478 -lib_subckt_file lib_subckts_file\ 1479 -model_file model_file\ 1480 -power power\ 1481 -ground ground} 1482 1483proc write_path_spice { args } { 1484 parse_key_args "write_path_spice" args \ 1485 keys {-spice_directory -lib_subckt_file -model_file \ 1486 -power -ground -path_args} \ 1487 flags {} 1488 1489 if { [info exists keys(-spice_directory)] } { 1490 set spice_dir [file nativename $keys(-spice_directory)] 1491 if { ![file exists $spice_dir] } { 1492 sta_error 496 "Directory $spice_dir not found." 1493 } 1494 if { ![file isdirectory $spice_dir] } { 1495 sta_error 497 "$spice_dir is not a directory." 1496 } 1497 if { ![file writable $spice_dir] } { 1498 sta_error 498 "Cannot write in $spice_dir." 1499 } 1500 } else { 1501 sta_error 499 "No -spice_directory specified." 1502 } 1503 1504 if { [info exists keys(-lib_subckt_file)] } { 1505 set lib_subckt_file [file nativename $keys(-lib_subckt_file)] 1506 if { ![file readable $lib_subckt_file] } { 1507 sta_error 500 "-lib_subckt_file $lib_subckt_file is not readable." 1508 } 1509 } else { 1510 sta_error 501 "No -lib_subckt_file specified." 1511 } 1512 1513 if { [info exists keys(-model_file)] } { 1514 set model_file [file nativename $keys(-model_file)] 1515 if { ![file readable $model_file] } { 1516 sta_error 502 "-model_file $model_file is not readable." 1517 } 1518 } else { 1519 sta_error 503 "No -model_file specified." 1520 } 1521 1522 if { [info exists keys(-power)] } { 1523 set power $keys(-power) 1524 } else { 1525 sta_error 504 "No -power specified." 1526 } 1527 1528 if { [info exists keys(-ground)] } { 1529 set ground $keys(-ground) 1530 } else { 1531 sta_error 505 "No -ground specified." 1532 } 1533 1534 if { ![info exists keys(-path_args)] } { 1535 sta_error 506 "No -path_args specified." 1536 } 1537 set path_args $keys(-path_args) 1538 set path_ends [eval [concat find_timing_paths $path_args]] 1539 if { $path_ends == {} } { 1540 sta_error 507 "No paths found for -path_args $path_args." 1541 } else { 1542 set path_index 1 1543 foreach path_end $path_ends { 1544 set path [$path_end path] 1545 set path_name "path_$path_index" 1546 set spice_file [file join $spice_dir "$path_name.sp"] 1547 set subckt_file [file join $spice_dir "$path_name.subckt"] 1548 write_path_spice_cmd $path $spice_file $subckt_file \ 1549 $lib_subckt_file $model_file $power $ground 1550 incr path_index 1551 } 1552 } 1553} 1554 1555# sta namespace end. 1556} 1557