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 17################################################################ 18# 19# SDC commands. 20# Alphabetical within groups as in the SDC spec. 21# 22# Argument parsing and checking is done in TCL before calling a 23# SWIG interface function. 24# 25################################################################ 26 27namespace eval sta { 28 29define_cmd_args "read_sdc" {[-echo] filename} 30 31proc_redirect read_sdc { 32 parse_key_args "read_sdc" args keys {} flags {-echo} 33 34 check_argc_eq1 "read_sdc" $args 35 set echo [info exists flags(-echo)] 36 set filename [file nativename [lindex $args 0]] 37 source_ $filename $echo 0 38} 39 40################################################################ 41 42set ::sta_continue_on_error 0 43 44define_cmd_args "source" \ 45 {[-echo] [-verbose] filename [> filename] [>> filename]} 46 47# Override source to support -echo and return codes. 48proc_redirect source { 49 parse_key_args "source" args keys {-encoding} flags {-echo -verbose} 50 if { [llength $args] != 1 } { 51 cmd_usage_error "source" 52 } 53 set echo [info exists flags(-echo)] 54 set verbose [info exists flags(-verbose)] 55 set filename [file nativename [lindex $args 0]] 56 source_ $filename $echo $verbose 57} 58 59proc source_ { filename echo verbose } { 60 global sta_continue_on_error 61 variable sdc_file 62 variable sdc_line 63 if [catch {open $filename r} stream] { 64 sta_error 511 "cannot open '$filename'." 65 } else { 66 # Save file and line in recursive call to source. 67 if { [info exists sdc_file] } { 68 set sdc_file_save $sdc_file 69 set sdc_line_save $sdc_line 70 } 71 set sdc_file $filename 72 set sdc_line 1 73 set cmd "" 74 set error {} 75 while {![eof $stream]} { 76 gets $stream line 77 if { $line != "" } { 78 if {$echo} { 79 report_line $line 80 } 81 } 82 append cmd $line "\n" 83 if { [string index $line end] != "\\" \ 84 && [info complete $cmd] } { 85 set error {} 86 set error_code [catch {uplevel \#0 $cmd} result] 87 # cmd consumed 88 set cmd "" 89 # Flush results printed outside tcl to stdout/stderr. 90 fflush 91 switch $error_code { 92 0 { if { $verbose && $result != "" } { report_line $result } } 93 1 { set error $result } 94 2 { set error {invoked "return" outside of a proc.} } 95 3 { set error {invoked "break" outside of a loop.} } 96 4 { set error {invoked "continue" outside of a loop.} } 97 } 98 if { $error != {} } { 99 if { $sta_continue_on_error } { 100 # Only prepend error message with file/line once. 101 if { [string first "Error" $error] == 0 } { 102 report_line $error 103 } else { 104 report_line "Error: [file tail $sdc_file], $sdc_line $error" 105 } 106 set error {} 107 } else { 108 break 109 } 110 } 111 } 112 incr sdc_line 113 } 114 close $stream 115 if { $cmd != {} } { 116 sta_error 512 "incomplete command at end of file." 117 } 118 set error_sdc_file $sdc_file 119 set error_sdc_line $sdc_line 120 if { [info exists sdc_file_save] } { 121 set sdc_file $sdc_file_save 122 set sdc_line $sdc_line_save 123 } else { 124 unset sdc_file 125 unset sdc_line 126 } 127 if { $error != {} } { 128 # Only prepend error message with file/line once. 129 if { [string first "Error" $error] == 0 } { 130 error $error 131 } else { 132 error "Error: [file tail $error_sdc_file], $error_sdc_line $error" 133 } 134 } 135 } 136} 137 138################################################################ 139 140define_cmd_args "write_sdc" \ 141 {[-map_hpins] [-no_timestamp] [-digits digits] filename} 142 143proc write_sdc { args } { 144 parse_key_args "write_sdc" args keys {-digits -significant_digits} \ 145 flags {-map_hpins -compatible -no_timestamp} 146 check_argc_eq1 "write_sdc" $args 147 148 set digits 4 149 if { [info exists keys(-digits)] } { 150 set digits $keys(-digits) 151 } 152 if { [info exists keys(-significant_digits)] } { 153 set digits $keys(-significant_digits) 154 } 155 check_positive_integer "-digits" $digits 156 157 set filename [file nativename [lindex $args 0]] 158 set no_timestamp [info exists flags(-no_timestamp)] 159 set map_hpins [info exists flags(-map_hpins)] 160 set native [expr ![info exists flags(-compatible)]] 161 write_sdc_cmd $filename $map_hpins $native $no_timestamp $digits 162} 163 164################################################################ 165# 166# General Purpose Commands 167# 168################################################################ 169 170define_cmd_args "current_instance" {[instance]} 171 172proc current_instance { {inst ""} } { 173 if { $inst == "" } { 174 set current_instance [top_instance] 175 } else { 176 set current_instance [get_instance_error "instance" $inst] 177 } 178 set cell [get_name [$current_instance cell]] 179 report_line "Current instance is $cell." 180 # Current instance state variable must be part of the sta state so 181 # the tcl interpreter can be shared by multiple sdc files. 182 set_current_instance $current_instance 183} 184 185################################################################ 186 187define_cmd_args "set_hierarchy_separator" { seperator } 188 189set ::hierarchy_separator "/" 190 191proc set_hierarchy_separator { separator } { 192 global hierarchy_separator 193 check_path_divider $separator 194 set_path_divider $separator 195 set hierarchy_separator $separator 196} 197 198proc check_path_divider { divider } { 199 set sdc_dividers "/@^#.|" 200 if { !([string length $divider] == 1 201 && [string first $divider $sdc_dividers] != -1)} { 202 sta_error 513 "hierarchy separator must be one of '$sdc_dividers'." 203 } 204} 205 206################################################################ 207 208define_cmd_args "set_units" \ 209 {[-time time_unit] [-capacitance cap_unit] [-resistance res_unit]\ 210 [-voltage voltage_unit] [-current current_unit] [-power power_unit]\ 211 [-distance distance_unit]} 212 213# Note that the set_units command does NOT actually set the units. 214# It merely checks that the current units are the same as the 215# units in the set_units command. 216proc set_units { args } { 217 parse_key_args "set_units" args \ 218 keys {-capacitance -resistance -time -voltage -current -power -distance} \ 219 flags {} 220 check_argc_eq0 "set_units" $args 221 check_unit "time" -time "s" keys 222 check_unit "capacitance" -capacitance "f" keys 223 check_unit "resistance" -resistance "ohm" keys 224 check_unit "voltage" -voltage "v" keys 225 check_unit "current" -current "A" keys 226 check_unit "power" -power "W" keys 227 check_unit "distance" -distance "m" keys 228} 229 230proc check_unit { unit key unit_name key_var } { 231 upvar 1 $key_var keys 232 if { [info exists keys($key)] } { 233 set value $keys($key) 234 if { [string equal -nocase $value $unit_name] } { 235 check_unit_scale $unit 1.0 236 } else { 237 set prefix [string index $value 0] 238 set suffix [string range $value 1 end] 239 # unit includes "1" prefix 240 if { [string is digit $prefix] } { 241 set prefix [string index $value 1] 242 set suffix [string range $value 2 end] 243 } 244 if { [string equal -nocase $suffix $unit_name] } { 245 set scale [unit_prefix_scale $unit $prefix] 246 check_unit_scale $unit $scale 247 } else { 248 sta_error 514 "unknown unit $unit '$suffix'." 249 } 250 } 251 } 252} 253 254proc unit_prefix_scale { unit prefix } { 255 if { [string equal $prefix "M"] } { 256 return 1E+6 257 } elseif { [string equal $prefix "k"] } { 258 return 1E+3 259 } elseif { [string equal $prefix "m"] } { 260 return 1E-3 261 } elseif { [string equal $prefix "u"] } { 262 return 1E-6 263 } elseif { [string equal $prefix "n"] } { 264 return 1E-9 265 } elseif { [string equal $prefix "p"] } { 266 return 1E-12 267 } elseif { [string equal $prefix "f"] } { 268 return 1E-15 269 } else { 270 sta_error 604 "unknown $unit prefix '$prefix'." 271 } 272} 273 274proc check_unit_scale { unit scale } { 275 set unit_scale [unit_scale $unit] 276 if { ![fuzzy_equal $scale $unit_scale] } { 277 sta_warn 319 "$unit scale [format %.0e $scale] does not match library scale [format %.0e $unit_scale]." 278 } 279} 280 281################################################################ 282 283define_cmd_args "set_cmd_units" \ 284 {[-capacitance cap_unit] [-resistance res_unit] [-time time_unit]\ 285 [-voltage voltage_unit] [-current current_unit] [-power power_unit]\ 286 [-distance distance_unit]} 287 288proc set_cmd_units { args } { 289 parse_key_args "set_cmd_units" args \ 290 keys {-capacitance -resistance -time -voltage -current -power \ 291 -distance -digits -suffix} \ 292 flags {} 293 294 check_argc_eq0 "set_cmd_units" $args 295 set_unit_values "capacitance" -capacitance "f" keys 296 set_unit_values "time" -time "s" keys 297 set_unit_values "voltage" -voltage "v" keys 298 set_unit_values "current" -current "A" keys 299 set_unit_values "resistance" -resistance "ohm" keys 300 set_unit_values "distance" -distance "m" keys 301} 302 303proc set_unit_values { unit key unit_name key_var } { 304 upvar 1 $key_var keys 305 if { [info exists keys($key)] } { 306 set value $keys($key) 307 if { [string equal -nocase $value $unit_name] } { 308 set_cmd_unit_scale $unit 1.0 309 } else { 310 set prefix [string index $value 0] 311 set suffix [string range $value 1 end] 312 # unit includes "1" prefix 313 if { [string is digit $prefix] } { 314 set prefix [string index $value 1] 315 set suffix [string range $value 2 end] 316 } 317 if { [string equal -nocase $suffix $unit_name] } { 318 set scale [unit_prefix_scale $unit $prefix] 319 set_cmd_unit_scale $unit $scale 320 } else { 321 sta_error 515 "unknown $unit unit '$suffix'." 322 } 323 } 324 if [info exists keys(-digits)] { 325 set_cmd_unit_digits $unit $keys(-digits) 326 } 327 if [info exists keys(-suffix)] { 328 set_cmd_unit_suffix $unit $keys(-suffix) 329 } 330 } 331} 332 333################################################################ 334# 335# Object Access Commands 336# 337################################################################ 338 339define_cmd_args "all_clocks" {} 340 341proc all_clocks { } { 342 set clks {} 343 set clk_iter [clock_iterator] 344 while {[$clk_iter has_next]} { 345 set clk [$clk_iter next] 346 lappend clks $clk 347 } 348 $clk_iter finish 349 return $clks 350} 351 352################################################################ 353 354define_cmd_args "all_inputs" {} 355 356proc all_inputs { } { 357 return [all_ports_for_direction "input"] 358} 359 360################################################################ 361 362define_cmd_args "all_outputs" {} 363 364proc all_outputs { } { 365 return [all_ports_for_direction "output"] 366} 367 368proc all_ports_for_direction { direction } { 369 set top_instance [top_instance] 370 set top_cell [$top_instance cell] 371 set ports {} 372 set iter [$top_cell port_iterator] 373 while {[$iter has_next]} { 374 set port [$iter next] 375 set port_dir [port_direction $port] 376 if { $port_dir == $direction || $port_dir == "bidirect" } { 377 set ports [concat $ports [port_members $port]] 378 } 379 } 380 $iter finish 381 return $ports 382} 383 384proc port_members { port } { 385 if [$port is_bus] { 386 # Expand bus ports. 387 set ports {} 388 set member_iter [$port member_iterator] 389 while {[$member_iter has_next]} { 390 set bit_port [$member_iter next] 391 lappend ports $bit_port 392 } 393 $member_iter finish 394 return $ports 395 } else { 396 return $port 397 } 398} 399 400################################################################ 401 402define_cmd_args all_registers \ 403 {[-clock clocks] [-rise_clock clocks] [-fall_clock clocks] [-cells] [-data_pins] [-clock_pins]\ 404 [-async_pins] [-output_pins] [-level_sensitive] [-edge_triggered]} 405 406proc all_registers { args } { 407 parse_key_args "all_registers" args keys {-clock -rise_clock -fall_clock} \ 408 flags {-cells -data_pins -clock_pins -async_pins -output_pins -level_sensitive -edge_triggered} 409 check_argc_eq0 "all_registers" $args 410 411 set clks {} 412 set clk_rf "rise_fall" 413 if [info exists keys(-clock)] { 414 set clks [get_clocks_warn "clocks" $keys(-clock)] 415 } 416 if [info exists keys(-rise_clock)] { 417 set clks [get_clocks_warn "clocks" $keys(-rise_clock)] 418 set clk_rf "rise" 419 } 420 if [info exists keys(-fall_clock)] { 421 set clks [get_clocks_warn "clocks" $keys(-fall_clock)] 422 set clk_rf "fall" 423 } 424 425 if {[info exists flags(-edge_triggered)] \ 426 && ![info exists flags(-level_sensitive)]} { 427 set edge_triggered 1 428 set level_sensitive 0 429 } elseif {[info exists flags(-level_sensitive)] \ 430 && ![info exists flags(-edge_triggered)]} { 431 set level_sensitive 1 432 set edge_triggered 0 433 } else { 434 set edge_triggered 1 435 set level_sensitive 1 436 } 437 if [info exists flags(-cells)] { 438 return [find_register_instances $clks $clk_rf \ 439 $edge_triggered $level_sensitive] 440 } elseif [info exists flags(-data_pins)] { 441 return [find_register_data_pins $clks $clk_rf \ 442 $edge_triggered $level_sensitive] 443 } elseif [info exists flags(-clock_pins)] { 444 return [find_register_clk_pins $clks $clk_rf \ 445 $edge_triggered $level_sensitive] 446 } elseif [info exists flags(-async_pins)] { 447 return [find_register_async_pins $clks $clk_rf \ 448 $edge_triggered $level_sensitive] 449 } elseif [info exists flags(-output_pins)] { 450 return [find_register_output_pins $clks $clk_rf \ 451 $edge_triggered $level_sensitive] 452 } else { 453 # -cells is the default. 454 return [find_register_instances $clks $clk_rf \ 455 $edge_triggered $level_sensitive] 456 } 457} 458 459################################################################ 460 461define_cmd_args "current_design" {[design]} 462 463variable current_design_name "" 464 465proc current_design { {design ""} } { 466 variable current_design_name 467 468 if { $design == "" } { 469 # top_instance errors if the network has not been linked. 470 set current_design_name [get_name [get_object_property [top_instance] cell]] 471 } elseif { ![network_is_linked] } { 472 set current_design_name $design 473 return $design 474 } elseif { [network_is_linked] && $design == [get_name [get_object_property [top_instance] cell]] } { 475 set current_design_name $design 476 return $design 477 } else { 478 sta_warn 320 "current_design for other than top cell not supported." 479 set current_design_name $design 480 return $design 481 } 482} 483 484################################################################ 485 486define_cmd_args "get_cells" \ 487 {[-hierarchical] [-hsc separator] [-filter expr]\ 488 [-regexp] [-nocase] [-quiet] [-of_objects objects] [patterns]} 489 490define_cmd_alias "get_cell" "get_cells" 491 492# Really get_instances, but SDC calls instances "cells". 493proc get_cells { args } { 494 global hierarchy_separator 495 496 parse_key_args "get_cells" args keys {-hsc -filter -of_objects} \ 497 flags {-hierarchical -regexp -nocase -quiet} 498 check_argc_eq0or1 "get_cells" $args 499 check_nocase_flag flags 500 501 set regexp [info exists flags(-regexp)] 502 set nocase [info exists flags(-nocase)] 503 set hierarchical [info exists flags(-hierarchical)] 504 set quiet [info exists flags(-quiet)] 505 # Copy backslashes that will be removed by foreach. 506 set patterns [string map {\\ \\\\} [lindex $args 0]] 507 set divider $hierarchy_separator 508 if [info exists keys(-hsc)] { 509 set divider $keys(-hsc) 510 check_path_divider $divider 511 } 512 set insts {} 513 if [info exists keys(-of_objects)] { 514 if { $args != {} } { 515 sta_warn 321 "patterns argument not supported with -of_objects." 516 } 517 parse_port_pin_net_arg $keys(-of_objects) pins nets 518 foreach pin $pins { 519 if { [$pin is_top_level_port] } { 520 set net [get_nets [get_name $pin]] 521 if { $net != "NULL" } { 522 lappend nets $net 523 } 524 } else { 525 lappend insts [$pin instance] 526 } 527 } 528 foreach net $nets { 529 set pin_iter [$net pin_iterator] 530 while { [$pin_iter has_next] } { 531 set pin [$pin_iter next] 532 lappend insts [$pin instance] 533 } 534 $pin_iter finish 535 } 536 } else { 537 if { $args == {} } { 538 set insts [network_leaf_instances] 539 } else { 540 foreach pattern $patterns { 541 if { $divider != $hierarchy_separator } { 542 regsub $divider $pattern $hierarchy_separator pattern 543 } 544 if { $hierarchical } { 545 set matches [find_instances_hier_matching $pattern $regexp $nocase] 546 } else { 547 set matches [find_instances_matching $pattern $regexp $nocase] 548 } 549 if { $matches == {} && !$quiet} { 550 sta_warn 322 "instance '$pattern' not found." 551 } 552 set insts [concat $insts $matches] 553 } 554 } 555 if [info exists keys(-filter)] { 556 set insts [filter_insts1 $keys(-filter) $insts] 557 } 558 } 559 return $insts 560} 561 562proc filter_insts1 { filter objects } { 563 variable filter_regexp1 564 variable filter_or_regexp 565 variable filter_and_regexp 566 set filtered_objects {} 567 # Ignore sub-exprs in filter_regexp1 for expr2 match var. 568 if { [regexp $filter_or_regexp $filter ignore expr1 \ 569 ignore ignore ignore expr2] } { 570 regexp $filter_regexp1 $expr1 ignore attr_name op arg 571 set filtered_objects1 [filter_insts $attr_name $op $arg $objects] 572 regexp $filter_regexp1 $expr2 ignore attr_name op arg 573 set filtered_objects2 [filter_insts $attr_name $op $arg $objects] 574 set filtered_objects [concat $filtered_objects1 $filtered_objects2] 575 } elseif { [regexp $filter_and_regexp $filter ignore expr1 \ 576 ignore ignore ignore expr2] } { 577 regexp $filter_regexp1 $expr1 ignore attr_name op arg 578 set filtered_objects [filter_insts $attr_name $op $arg $objects] 579 regexp $filter_regexp1 $expr2 ignore attr_name op arg 580 set filtered_objects [filter_insts $attr_name $op $arg $filtered_objects] 581 } elseif { [regexp $filter_regexp1 $filter ignore attr_name op arg] } { 582 set filtered_objects [filter_insts $attr_name $op $arg $objects] 583 } else { 584 sta_error 516 "unsupported -filter expression." 585 } 586 return $filtered_objects 587} 588 589################################################################ 590 591define_cmd_args "get_clocks" {[-regexp] [-nocase] [-quiet] patterns} 592 593define_cmd_alias "get_clock" "get_clocks" 594 595proc get_clocks { args } { 596 parse_key_args "get_clocks" args keys {} flags {-regexp -nocase -quiet} 597 check_argc_eq1 "get_clocks" $args 598 check_nocase_flag flags 599 600 # Copy backslashes that will be removed by foreach. 601 set patterns [string map {\\ \\\\} [lindex $args 0]] 602 set regexp [info exists flags(-regexp)] 603 set nocase [info exists flags(-nocase)] 604 set clocks {} 605 foreach pattern $patterns { 606 set matches [find_clocks_matching $pattern $regexp $nocase] 607 if { $matches != {} } { 608 set clocks [concat $clocks $matches] 609 } else { 610 if {![info exists flags(-quiet)]} { 611 sta_warn 323 "clock '$pattern' not found." 612 } 613 } 614 } 615 return $clocks 616} 617 618################################################################ 619 620define_cmd_args "get_lib_cells" \ 621 {[-hsc separator] [-regexp] [-nocase] [-quiet]\ 622 [-of_objects objects] [patterns]} 623 624define_cmd_alias "get_lib_cell" "get_lib_cells" 625 626proc get_lib_cells { args } { 627 global hierarchy_separator 628 parse_key_args "get_lib_cells" args keys {-hsc -of_objects} \ 629 flags {-regexp -nocase -quiet} 630 check_argc_eq0or1 "get_lib_cells" $args 631 check_nocase_flag flags 632 633 set regexp [info exists flags(-regexp)] 634 set nocase [info exists flags(-nocase)] 635 set cells {} 636 if [info exists keys(-of_objects)] { 637 if { $args != {} } { 638 sta_warn 324 "positional arguments not supported with -of_objects." 639 } 640 set insts [get_instances_error "objects" $keys(-of_objects)] 641 foreach inst $insts { 642 lappend cells [$inst liberty_cell] 643 } 644 } else { 645 # Copy backslashes that will be removed by foreach. 646 set patterns [string map {\\ \\\\} [lindex $args 0]] 647 # Parse library_name/pattern. 648 set divider $hierarchy_separator 649 if [info exists keys(-hsc)] { 650 set divider $keys(-hsc) 651 check_path_divider $divider 652 } 653 set cell_regexp [cell_regexp_hsc $divider] 654 set quiet [info exists flags(-quiet)] 655 foreach pattern $patterns { 656 if { ![regexp $cell_regexp $pattern ignore lib_name cell_pattern]} { 657 set lib_name "*" 658 set cell_pattern $pattern 659 } 660 # Allow wildcards in the library name (incompatible). 661 set libs [get_libs -quiet $lib_name] 662 if { $libs == {} } { 663 if {!$quiet} { 664 sta_warn 325 "library '$lib_name' not found." 665 } 666 } else { 667 foreach lib $libs { 668 set matches [$lib find_liberty_cells_matching $cell_pattern \ 669 $regexp $nocase] 670 if {$matches != {}} { 671 set cells [concat $cells $matches] 672 } 673 } 674 if { $cells == {} } { 675 if {!$quiet} { 676 sta_warn 326 "cell '$cell_pattern' not found." 677 } 678 } 679 } 680 } 681 } 682 return $cells 683} 684 685################################################################ 686 687define_cmd_args "get_lib_pins" \ 688 {[-hsc separator] [-regexp] [-nocase] [-quiet] patterns} 689 690define_cmd_alias "get_lib_pin" "get_lib_pins" 691 692# "get_lib_ports" in sta terminology. 693proc get_lib_pins { args } { 694 global hierarchy_separator 695 parse_key_args "get_lib_pins" args keys {-hsc} flags {-regexp -nocase -quiet} 696 check_argc_eq1 "get_lib_pins" $args 697 check_nocase_flag flags 698 699 set regexp [info exists flags(-regexp)] 700 set nocase [info exists flags(-nocase)] 701 set quiet [info exists flags(-quiet)] 702 # Copy backslashes that will be removed by foreach. 703 set patterns [string map {\\ \\\\} [lindex $args 0]] 704 # Parse library_name/cell_name/pattern. 705 set divider $hierarchy_separator 706 if [info exists keys(-hsc)] { 707 set divider $keys(-hsc) 708 check_path_divider $divider 709 } 710 set port_regexp1 [port_regexp_hsc $divider] 711 set port_regexp2 [cell_regexp_hsc $divider] 712 set ports {} 713 foreach pattern $patterns { 714 # match library/cell/port 715 set libs {} 716 if { [regexp $port_regexp1 $pattern ignore lib_name cell_name port_pattern] } { 717 set libs [get_libs -quiet $lib_name] 718 # match cell/port 719 } elseif { [regexp $port_regexp2 $pattern ignore cell_name port_pattern] } { 720 set libs [get_libs *] 721 } else { 722 if { !$quiet } { 723 sta_warn 327 "library/cell/port '$pattern' not found." 724 } 725 return {} 726 } 727 if { $libs != {} } { 728 set found_match 0 729 set cells {} 730 foreach lib $libs { 731 set cells [$lib find_liberty_cells_matching $cell_name $regexp $nocase] 732 foreach cell $cells { 733 set matches [$cell find_liberty_ports_matching $port_pattern \ 734 $regexp $nocase] 735 foreach match $matches { 736 lappend ports $match 737 set found_match 1 738 } 739 } 740 } 741 if { !$found_match } { 742 if { !$quiet } { 743 sta_warn 328 "port '$port_pattern' not found." 744 } 745 } 746 } else { 747 if { !$quiet } { 748 sta_warn 329 "library '$lib_name' not found." 749 } 750 } 751 } 752 return $ports 753} 754 755proc check_nocase_flag { flags_var } { 756 upvar 1 $flags_var flags 757 if { [info exists flags(-nocase)] && ![info exists flags(-regexp)] } { 758 sta_warn 330 "-nocase ignored without -regexp." 759 } 760} 761 762################################################################ 763 764define_cmd_args "get_libs" {[-regexp] [-nocase] [-quiet] patterns} 765 766define_cmd_alias "get_lib" "get_libs" 767 768proc get_libs { args } { 769 parse_key_args "get_libs" args keys {} flags {-regexp -nocase -quiet} 770 check_argc_eq1 "get_libs" $args 771 check_nocase_flag flags 772 773 # Copy backslashes that will be removed by foreach. 774 set patterns [string map {\\ \\\\} [lindex $args 0]] 775 set regexp [info exists flags(-regexp)] 776 set nocase [info exists flags(-nocase)] 777 set libs {} 778 foreach pattern $patterns { 779 set matches [find_liberty_libraries_matching $pattern $regexp $nocase] 780 if {$matches != {}} { 781 set libs [concat $libs $matches] 782 } else { 783 if {![info exists flags(-quiet)]} { 784 sta_warn 331 "library '$pattern' not found." 785 } 786 } 787 } 788 return $libs 789} 790 791proc find_liberty_libraries_matching { pattern regexp nocase } { 792 # Remove "lib.db:" reference from the library name. 793 set ix [string last ".db:" $pattern] 794 if { $ix != -1 } { 795 set pattern2 [string range $pattern [expr $ix + 4] end] 796 } else { 797 set pattern2 $pattern 798 } 799 if { $regexp } { 800 # Anchor the regexp pattern. 801 set pattern2 "^${pattern}$" 802 } 803 set lib_iter [liberty_library_iterator] 804 set matches {} 805 while { [$lib_iter has_next] } { 806 set lib [$lib_iter next] 807 set lib_name [get_name $lib] 808 if { (!$regexp && [string match $pattern2 $lib_name]) \ 809 || ($regexp && $nocase && [regexp -nocase $pattern2 $lib_name]) \ 810 || ($regexp && !$nocase && [regexp $pattern2 $lib_name]) } { 811 lappend matches $lib 812 } 813 } 814 $lib_iter finish 815 return $matches 816} 817 818################################################################ 819 820define_cmd_args "get_nets" \ 821 {[-hierarchical] [-hsc separator] [-regexp] [-nocase] [-quiet]\ 822 [-of_objects objects] [patterns]} 823 824define_cmd_alias "get_net" "get_nets" 825 826proc get_nets { args } { 827 global hierarchy_separator 828 829 parse_key_args get_nets args keys {-hsc -of_objects} \ 830 flags {-hierarchical -regexp -nocase -quiet} 831 check_nocase_flag flags 832 833 set regexp [info exists flags(-regexp)] 834 set nocase [info exists flags(-nocase)] 835 set hierarchical [info exists flags(-hierarchical)] 836 set quiet [info exists flags(-quiet)] 837 # Copy backslashes that will be removed by foreach. 838 set patterns [string map {\\ \\\\} [lindex $args 0]] 839 if [info exists keys(-hsc)] { 840 set divider $keys(-hsc) 841 check_path_divider $divider 842 set patterns [string map "$divider $hierarchy_separator" $patterns] 843 } 844 set nets {} 845 if [info exists keys(-of_objects)] { 846 if { $args != {} } { 847 sta_warn 332 "patterns argument not supported with -of_objects." 848 } 849 parse_inst_pin_arg $keys(-of_objects) insts pins 850 foreach inst $insts { 851 set pin_iter [$inst pin_iterator] 852 while { [$pin_iter has_next] } { 853 set pin [$pin_iter next] 854 lappend nets [$pin net] 855 } 856 $pin_iter finish 857 } 858 foreach pin $pins { 859 lappend nets [$pin net] 860 } 861 } else { 862 check_argc_eq1 "get_nets" $args 863 foreach pattern $patterns { 864 if { $hierarchical } { 865 set matches [find_nets_hier_matching $pattern $regexp $nocase] 866 } else { 867 set matches [find_nets_matching $pattern $regexp $nocase] 868 } 869 set nets [concat $nets $matches] 870 if { $matches == {} && !$quiet } { 871 sta_warn 333 "net '$pattern' not found." 872 } 873 } 874 } 875 return $nets 876} 877 878################################################################ 879 880define_cmd_args "get_pins" \ 881 {[-hierarchical] [-hsc separator] [-quiet] [-filter expr]\ 882 [-regexp] [-nocase] [-of_objects objects] patterns} 883 884define_cmd_alias "get_pin" "get_pins" 885 886proc get_pins { args } { 887 global hierarchy_separator 888 889 parse_key_args "get_pins" args keys {-hsc -of_objects -filter} \ 890 flags {-hierarchical -regexp -nocase -quiet} 891 check_nocase_flag flags 892 893 set regexp [info exists flags(-regexp)] 894 set nocase [info exists flags(-nocase)] 895 set hierarchical [info exists flags(-hierarchical)] 896 set quiet [info exists flags(-quiet)] 897 set pins {} 898 if [info exists keys(-of_objects)] { 899 if { $args != {} } { 900 sta_warn 334 "patterns argument not supported with -of_objects." 901 } 902 parse_inst_net_arg $keys(-of_objects) insts nets 903 foreach inst $insts { 904 set pin_iter [$inst pin_iterator] 905 while { [$pin_iter has_next] } { 906 set pin [$pin_iter next] 907 lappend pins $pin 908 } 909 $pin_iter finish 910 } 911 foreach net $nets { 912 set pin_iter [$net pin_iterator] 913 while { [$pin_iter has_next] } { 914 set pin [$pin_iter next] 915 lappend pins $pin 916 } 917 $pin_iter finish 918 } 919 } else { 920 check_argc_eq1 "get_pins" $args 921 set patterns [lindex $args 0] 922 if [info exists keys(-hsc)] { 923 set divider $keys(-hsc) 924 check_path_divider $divider 925 set patterns [string map "$divider $hierarchy_separator" $patterns] 926 } 927 # Copy backslashes that will be removed by foreach. 928 set patterns [string map {\\ \\\\} $patterns] 929 foreach pattern $patterns { 930 if { $hierarchical } { 931 set matches [find_pins_hier_matching $pattern $regexp $nocase] 932 } else { 933 set matches [find_pins_matching $pattern $regexp $nocase] 934 } 935 set pins [concat $pins $matches] 936 if { $matches == {} && !$quiet } { 937 sta_warn 335 "pin '$pattern' not found." 938 } 939 } 940 } 941 if [info exists keys(-filter)] { 942 set pins [filter_pins1 $keys(-filter) $pins] 943 } 944 return $pins 945} 946 947proc filter_pins1 { filter objects } { 948 variable filter_regexp1 949 variable filter_or_regexp 950 variable filter_and_regexp 951 set filtered_objects {} 952 # Ignore sub-exprs in filter_regexp1 for expr2 match var. 953 if { [regexp $filter_or_regexp $filter ignore expr1 \ 954 ignore ignore ignore expr2] } { 955 regexp $filter_regexp1 $expr1 ignore attr_name op arg 956 set filtered_objects1 [filter_pins $attr_name $op $arg $objects] 957 regexp $filter_regexp1 $expr2 ignore attr_name op arg 958 set filtered_objects2 [filter_pins $attr_name $op $arg $objects] 959 set filtered_objects [concat $filtered_objects1 $filtered_objects2] 960 } elseif { [regexp $filter_and_regexp $filter ignore expr1 \ 961 ignore ignore ignore expr2] } { 962 regexp $filter_regexp1 $expr1 ignore attr_name op arg 963 set filtered_objects [filter_pins $attr_name $op $arg $objects] 964 regexp $filter_regexp1 $expr2 ignore attr_name op arg 965 set filtered_objects [filter_pins $attr_name $op $arg $filtered_objects] 966 } elseif { [regexp $filter_regexp1 $filter ignore attr_name op arg] } { 967 set filtered_objects [filter_pins $attr_name $op $arg $objects] 968 } else { 969 sta_error 517 "unsupported -filter expression." 970 } 971 return $filtered_objects 972} 973 974################################################################ 975 976define_cmd_args "get_ports" \ 977 {[-quiet] [-filter expr] [-regexp] [-nocase] [-of_objects objects] [patterns]} 978 979define_cmd_alias "get_port" "get_ports" 980 981# Find top level design ports matching pattern. 982proc get_ports { args } { 983 parse_key_args "get_ports" args keys {-of_objects -filter} \ 984 flags {-regexp -nocase -quiet} 985 check_nocase_flag flags 986 987 set regexp [info exists flags(-regexp)] 988 set nocase [info exists flags(-nocase)] 989 # Copy backslashes that will be removed by foreach. 990 set patterns [string map {\\ \\\\} [lindex $args 0]] 991 set ports {} 992 if [info exists keys(-of_objects)] { 993 if { $args != {} } { 994 sta_warn 336 "patterns argument not supported with -of_objects." 995 } 996 set nets [get_nets_warn "objects" $keys(-of_objects)] 997 foreach net $nets { 998 set ports [concat $ports [$net ports]] 999 } 1000 } else { 1001 check_argc_eq1 "get_ports" $args 1002 foreach pattern $patterns { 1003 set matches [find_ports_matching $pattern $regexp $nocase] 1004 if { $matches != {} } { 1005 set ports [concat $ports $matches] 1006 } else { 1007 if {![info exists flags(-quiet)]} { 1008 sta_warn 337 "port '$pattern' not found." 1009 } 1010 } 1011 } 1012 } 1013 if [info exists keys(-filter)] { 1014 set ports [filter_ports1 $keys(-filter) $ports] 1015 } 1016 return $ports 1017} 1018 1019variable filter_regexp1 {@?([a-zA-Z_]+) *(==|=~) *([0-9a-zA-Z_\*]+)} 1020variable filter_or_regexp "($filter_regexp1) +\\|\\| +($filter_regexp1)" 1021variable filter_and_regexp "($filter_regexp1) +&& +($filter_regexp1)" 1022 1023proc filter_ports1 { filter objects } { 1024 variable filter_regexp1 1025 variable filter_or_regexp 1026 variable filter_and_regexp 1027 set filtered_objects {} 1028 # Ignore sub-exprs in filter_regexp1 for expr2 match var. 1029 if { [regexp $filter_or_regexp $filter ignore expr1 \ 1030 ignore ignore ignore expr2] } { 1031 regexp $filter_regexp1 $expr1 ignore attr_name op arg 1032 set filtered_objects1 [filter_ports $attr_name $op $arg $objects] 1033 regexp $filter_regexp1 $expr2 ignore attr_name op arg 1034 set filtered_objects2 [filter_ports $attr_name $op $arg $objects] 1035 set filtered_objects [concat $filtered_objects1 $filtered_objects2] 1036 } elseif { [regexp $filter_and_regexp $filter ignore expr1 \ 1037 ignore ignore ignore expr2] } { 1038 regexp $filter_regexp1 $expr1 ignore attr_name op arg 1039 set filtered_objects [filter_ports $attr_name $op $arg $objects] 1040 regexp $filter_regexp1 $expr2 ignore attr_name op arg 1041 set filtered_objects [filter_ports $attr_name $op $arg $filtered_objects] 1042 } elseif { [regexp $filter_regexp1 $filter ignore attr_name op arg] } { 1043 set filtered_objects [filter_ports $attr_name $op $arg $objects] 1044 } else { 1045 sta_error 518 "unsupported -filter expression." 1046 } 1047 return $filtered_objects 1048} 1049 1050################################################################ 1051# 1052# Timing Constraints 1053# 1054################################################################ 1055 1056define_cmd_args "create_clock" \ 1057 {[-name name] [-period period] [-waveform waveform] [-add]\ 1058 [-comment comment] [pins]} 1059 1060proc create_clock { args } { 1061 parse_key_args "create_clock" args \ 1062 keys {-name -period -waveform -comment} \ 1063 flags {-add} 1064 1065 check_argc_eq0or1 "create_clock" $args 1066 set argc [llength $args] 1067 if { $argc == 0 } { 1068 set pins {} 1069 } elseif { $argc == 1 } { 1070 set pins [get_port_pins_error "pins" [lindex $args 0]] 1071 } 1072 1073 set add [info exists flags(-add)] 1074 if [info exists keys(-name)] { 1075 set name $keys(-name) 1076 } elseif { $pins != {} } { 1077 if { $add } { 1078 sta_error 519 "-add requires -name." 1079 } 1080 # Default clock name is the first pin name. 1081 set name [get_full_name [lindex $pins 0]] 1082 } else { 1083 sta_error 520 "-name or port_pin_list must be specified." 1084 } 1085 1086 if [info exists keys(-period)] { 1087 set period $keys(-period) 1088 check_positive_float "period" $period 1089 set period [time_ui_sta $period] 1090 } else { 1091 sta_error 521 "missing -period argument." 1092 } 1093 1094 if [info exists keys(-waveform)] { 1095 set wave_arg $keys(-waveform) 1096 if { [expr [llength $wave_arg] % 2] != 0 } { 1097 sta_error 522 "-waveform edge_list must have an even number of edge times." 1098 } 1099 set first_edge 1 1100 set prev_edge 0 1101 set waveform {} 1102 foreach edge $wave_arg { 1103 check_float "-waveform edge" $edge 1104 set edge [time_ui_sta $edge] 1105 if { $first_edge && $edge > $period } { 1106 set edge [expr $edge - $period] 1107 } 1108 if { !$first_edge && $edge < $prev_edge } { 1109 sta_warn 338 "adjusting non-increasing clock -waveform edge times." 1110 set edge [expr $edge + $period] 1111 } 1112 if { $edge > [expr $period * 2] } { 1113 sta_warn 339 "-waveform time greater than two periods." 1114 } 1115 lappend waveform $edge 1116 set prev_edge $edge 1117 set first_edge 0 1118 } 1119 } else { 1120 set waveform [list 0 [expr $period / 2.0]] 1121 } 1122 1123 set comment [parse_comment_key keys] 1124 1125 make_clock $name $pins $add $period $waveform $comment 1126} 1127 1128################################################################ 1129 1130define_cmd_args "create_generated_clock" \ 1131 {[-name clock_name] -source master_pin [-master_clock clock]\ 1132 [-divide_by divisor | -multiply_by multiplier]\ 1133 [-duty_cycle duty_cycle] [-invert] [-edges edge_list]\ 1134 [-edge_shift edge_shift_list] [-combinational] [-add]\ 1135 [-pll_output pll_out_pin] [-pll_feedback pll_fdbk_pin]\ 1136 [-comment comment] port_pin_list} 1137 1138proc create_generated_clock { args } { 1139 parse_key_args "create_generated_clock" args keys \ 1140 {-name -source -master_clock -divide_by -multiply_by \ 1141 -duty_cycle -edges -edge_shift -pll_output -pll_feedback -comment} \ 1142 flags {-invert -combinational -add} 1143 1144 check_argc_eq1 "create_generated_clock" $args 1145 parse_port_pin_net_arg [lindex $args 0] pins nets 1146 # Convert net args to net driver pin. 1147 foreach net $nets { 1148 set drivers [net_driver_pins $net] 1149 if { $drivers != {} } { 1150 lappend pins [lindex $drivers 0] 1151 } 1152 } 1153 if { $pins == {} } { 1154 sta_error 523 "empty ports/pins/nets argument." 1155 } 1156 set add [info exists flags(-add)] 1157 1158 if [info exists keys(-name)] { 1159 set name $keys(-name) 1160 } elseif { $pins != {} } { 1161 if { $add } { 1162 sta_error 524 "-add requires -name." 1163 } 1164 # Default clock name is the first pin name. 1165 set name [get_full_name [lindex $pins 0]] 1166 } else { 1167 sta_error 525 "name or port_pin_list must be specified." 1168 } 1169 1170 if [info exists keys(-source)] { 1171 set source $keys(-source) 1172 set source_pin [get_port_pin_error "master_pin" $source] 1173 } else { 1174 sta_error 526 "missing -source argument." 1175 } 1176 1177 set master_clk "NULL" 1178 set divide_by 0 1179 set multiply_by 0 1180 set duty_cycle 0 1181 set edges {} 1182 set edge_shifts {} 1183 set pll_out "NULL" 1184 set pll_feedback "NULL" 1185 1186 set combinational [info exists flags(-combinational)] 1187 1188 if {[info exists keys(-master_clock)]} { 1189 set master_clk [get_clock_error "-master_clk" $keys(-master_clock)] 1190 if { $master_clk == "NULL" } { 1191 sta_error 527 "-master_clock argument empty." 1192 } 1193 } elseif { $add } { 1194 sta_error 528 "-add requireds -master_clock." 1195 } 1196 1197 if {[info exists keys(-divide_by)] && [info exists keys(-multiply_by)]} { 1198 sta_error 529 "-multiply_by and -divide_by options are exclusive." 1199 } elseif {[info exists keys(-divide_by)]} { 1200 set divide_by $keys(-divide_by) 1201 if {![string is integer $divide_by] || $divide_by < 1} { 1202 sta_error 530 "-divide_by is not an integer greater than one." 1203 } 1204 if {$combinational && $divide_by != 1} { 1205 sta_error 531 "-combinational implies -divide_by 1." 1206 } 1207 } elseif {[info exists keys(-multiply_by)]} { 1208 set multiply_by $keys(-multiply_by) 1209 if {![string is integer $multiply_by] || $multiply_by < 1} { 1210 sta_error 532 "-multiply_by is not an integer greater than one." 1211 } 1212 if {[info exists keys(-duty_cycle)]} { 1213 set duty_cycle $keys(-duty_cycle) 1214 if {![string is double $duty_cycle] \ 1215 || $duty_cycle < 0.0 || $duty_cycle > 100.0} { 1216 sta_error 533 "-duty_cycle is not a float between 0 and 100." 1217 } 1218 } 1219 } elseif {[info exists keys(-edges)]} { 1220 set edges $keys(-edges) 1221 if { [llength $edges] != 3 } { 1222 sta_error 534 "-edges only supported for three edges." 1223 } 1224 set prev_edge [expr [lindex $edges 0] - 1] 1225 foreach edge $edges { 1226 check_cardinal "-edges" $edge 1227 if { $edge <= $prev_edge } { 1228 sta_error 535 "edges times are not monotonically increasing." 1229 } 1230 } 1231 if [info exists keys(-edge_shift)] { 1232 foreach shift $keys(-edge_shift) { 1233 check_float "-edge_shift" $shift 1234 lappend edge_shifts [time_ui_sta $shift] 1235 } 1236 if { [llength $edge_shifts] != [llength $edges] } { 1237 sta_error 536 "-edge_shift length does not match -edges length." 1238 } 1239 } 1240 } elseif { $combinational } { 1241 set divide_by 1 1242 } else { 1243 sta_error 537 "missing -multiply_by, -divide_by, -combinational or -edges argument." 1244 } 1245 1246 set invert 0 1247 if {[info exists flags(-invert)]} { 1248 if {!([info exists keys(-divide_by)] \ 1249 || [info exists keys(-multiply_by)] \ 1250 || [info exists flags(-combinational)])} { 1251 sta_error 538 "cannot specify -invert without -multiply_by, -divide_by or -combinational." 1252 } 1253 set invert 1 1254 } 1255 1256 if {[info exists keys(-duty_cycle)] && ![info exists keys(-multiply_by)]} { 1257 sta_error 539 "-duty_cycle requires -multiply_by value." 1258 } 1259 1260 if { [info exists keys(-pll_feedback)] || [info exists keys(-pll_output)] } { 1261 if {![info exists keys(-pll_output)] } { 1262 sta_error 540 "missing -pll_output argument." 1263 } 1264 if { ![info exists keys(-pll_feedback)] } { 1265 sta_error 541 "missing -pll_feedback argument." 1266 } 1267 set pll_feedback [get_pin_error "-pll_feedback" $keys(-pll_feedback)] 1268 set pll_out [get_pin_error "-pll_output" $keys(-pll_output)] 1269 set pll_inst [$pll_out instance] 1270 if { [$pll_feedback instance] != $pll_inst } { 1271 sta_error 542 "PLL output and feedback pins must be on the same instance." 1272 } 1273 if { [$source_pin instance] != $pll_inst } { 1274 sta_error 543 "source pin must be on the same instance as the PLL output pin." 1275 } 1276 if { [lsearch $pins $pll_out] == -1 } { 1277 sta_error 544 "PLL output must be one of the clock pins." 1278 } 1279 } 1280 1281 set comment [parse_comment_key keys] 1282 1283 make_generated_clock $name $pins $add $source_pin $master_clk \ 1284 $pll_out $pll_feedback \ 1285 $divide_by $multiply_by $duty_cycle $invert $combinational \ 1286 $edges $edge_shifts $comment 1287} 1288 1289################################################################ 1290 1291define_cmd_args "group_path" \ 1292 {-name group_name [-weight weight] [-critical_range range]\ 1293 [-default] [-comment comment]\ 1294 [-from from_list] [-rise_from from_list] [-fall_from from_list]\ 1295 [-through through_list] [-rise_through through_list]\ 1296 [-fall_through through_list] [-to to_list] [-rise_to to_list]\ 1297 [-fall_to to_list]} 1298 1299# The -weight and -critical_range arguments are ignored. 1300proc group_path { args } { 1301 parse_key_args "group_path" args \ 1302 keys {-name -weight -critical_range \ 1303 -from -rise_from -fall_from \ 1304 -to -rise_to -fall_to -comment} \ 1305 flags {-default} 0 1306 1307 set cmd "group_path" 1308 set arg_error 0 1309 set from [parse_from_arg keys arg_error] 1310 set thrus [parse_thrus_arg args arg_error] 1311 set to [parse_to_arg1 keys "rise_fall" arg_error] 1312 check_exception_pins $from $to 1313 if { $arg_error } { 1314 delete_from_thrus_to $from $thrus $to 1315 sta_error 545 "group_path command failed." 1316 return 0 1317 } 1318 1319 check_for_key_args $cmd args 1320 if { $args != {} } { 1321 delete_from_thrus_to $from $thrus $to 1322 sta_error 546 "positional arguments not supported." 1323 } 1324 if { ($from == "NULL" && $thrus == "" && $to == "NULL") } { 1325 delete_from_thrus_to $from $thrus $to 1326 sta_error 547 "-from, -through or -to required." 1327 } 1328 1329 set default [info exists flags(-default)] 1330 set name_exists [info exists keys(-name)] 1331 if { $default && $name_exists } { 1332 sta_error 548 "-name and -default are mutually exclusive." 1333 } elseif { !$name_exists && !$default } { 1334 sta_error 549 "-name or -default option is required." 1335 } elseif { $default } { 1336 set name "" 1337 } else { 1338 set name $keys(-name) 1339 } 1340 1341 set comment [parse_comment_key keys] 1342 1343 make_group_path $name $default $from $thrus $to $comment 1344} 1345 1346proc check_exception_pins { from to } { 1347 variable sdc_file 1348 variable sdc_line 1349 if { [info exists sdc_file] } { 1350 set file $sdc_file 1351 set line $sdc_line 1352 } else { 1353 set file "" 1354 set line 0 1355 } 1356 check_exception_from_pins $from $file $line 1357 check_exception_to_pins $to $file $line 1358} 1359 1360################################################################ 1361 1362define_cmd_args "set_clock_gating_check" \ 1363 {[-setup setup_time] [-hold hold_time] [-rise] [-fall]\ 1364 [-low] [-high] [objects]} 1365 1366proc set_clock_gating_check { args } { 1367 parse_key_args "set_clock_gating_check" args keys {-setup -hold } \ 1368 flags {-rise -fall -high -low} 1369 1370 check_argc_eq0or1 "set_clock_gating_check" $args 1371 set tr [parse_rise_fall_flags flags] 1372 1373 set active_value "" 1374 if {[info exists flags(-high)] && [info exists flags(-low)]} { 1375 sta_error 550 "cannot specify both -high and -low." 1376 } elseif [info exists flags(-low)] { 1377 set active_value "0" 1378 } elseif [info exists flags(-high)] { 1379 set active_value "1" 1380 } 1381 1382 if { !([info exists keys(-hold)] || [info exists keys(-setup)]) } { 1383 sta_error 551 "missing -setup or -hold argument." 1384 } 1385 if [info exists keys(-hold)] { 1386 set_clock_gating_check1 $args $tr "min" $keys(-hold) $active_value 1387 } 1388 if [info exists keys(-setup)] { 1389 set_clock_gating_check1 $args $tr "max" $keys(-setup) $active_value 1390 } 1391} 1392 1393proc set_clock_gating_check1 { args tr setup_hold margin active_value } { 1394 set margin [time_ui_sta $margin] 1395 if { [llength $args] == 0 } { 1396 if { $active_value != "" } { 1397 sta_error 552 "-high and -low only permitted for pins and instances." 1398 } 1399 set_clock_gating_check_cmd $tr $setup_hold $margin 1400 } elseif { [llength $args] == 1 } { 1401 parse_clk_inst_port_pin_arg [lindex $args 0] clks insts pins 1402 1403 if { $clks != {} && $active_value != "" } { 1404 sta_error 553 "-high and -low only permitted for pins and instances." 1405 } 1406 foreach clk $clks { 1407 set_clock_gating_check_clk_cmd $clk $tr $setup_hold $margin 1408 } 1409 1410 if { $active_value == "" } { 1411 set active_value "X" 1412 } 1413 foreach pin $pins { 1414 set_clock_gating_check_pin_cmd $pin $tr $setup_hold \ 1415 $margin $active_value 1416 } 1417 foreach inst $insts { 1418 set_clock_gating_check_instance_cmd $inst $tr $setup_hold \ 1419 $margin $active_value 1420 } 1421 } 1422} 1423 1424################################################################ 1425 1426define_cmd_args "set_clock_groups" \ 1427 {[-name name] [-logically_exclusive] [-physically_exclusive]\ 1428 [-asynchronous] [-allow_paths] [-comment comment] -group clocks} 1429 1430proc set_clock_groups { args } { 1431 parse_key_args "set_clock_groups" args \ 1432 keys {-name -comment} \ 1433 flags {-logically_exclusive -physically_exclusive \ 1434 -asynchronous -allow_paths} 0 1435 1436 if {[info exists keys(-name)]} { 1437 set name $keys(-name) 1438 } else { 1439 set name "" 1440 } 1441 set logically_exclusive [info exists flags(-logically_exclusive)] 1442 set physically_exclusive [info exists flags(-physically_exclusive)] 1443 set asynchronous [info exists flags(-asynchronous)] 1444 set allow_paths [info exists flags(-allow_paths)] 1445 1446 if { ($logically_exclusive+$physically_exclusive+$asynchronous) == 0 } { 1447 sta_error 554 "one of -logically_exclusive, -physically_exclusive or -asynchronous is required." 1448 } 1449 if { ($logically_exclusive+$physically_exclusive+$asynchronous) > 1 } { 1450 sta_error 555 "the keywords -logically_exclusive, -physically_exclusive and -asynchronous are mutually exclusive." 1451 } 1452 1453 set comment [parse_comment_key keys] 1454 1455 set clk_groups [make_clock_groups $name $logically_exclusive \ 1456 $physically_exclusive $asynchronous $allow_paths \ 1457 $comment] 1458 1459 while { $args != "" } { 1460 set arg [lindex $args 0] 1461 if {[string match $arg "-group"]} { 1462 set group_clks [get_clocks_warn "clocks" [lindex $args 1]] 1463 if { $group_clks != {} } { 1464 clock_groups_make_group $clk_groups $group_clks 1465 } 1466 set args [lrange $args 2 end] 1467 } else { 1468 if {[is_keyword_arg $arg]} { 1469 sta_warn 349 "unknown keyword argument $arg." 1470 } else { 1471 sta_warn 341 "extra positional argument $arg." 1472 } 1473 set args [lrange $args 1 end] 1474 } 1475 } 1476} 1477 1478################################################################ 1479 1480define_cmd_args "set_clock_latency" \ 1481 {[-source] [-clock clock] [-rise] [-fall] [-min] [-max]\ 1482 [-early] [-late] delay objects} 1483 1484proc set_clock_latency { args } { 1485 parse_key_args "set_clock_latency" args keys {-clock} \ 1486 flags {-rise -fall -min -max -source -late -early} 1487 1488 check_argc_eq2 "set_clock_latency" $args 1489 1490 set delay [lindex $args 0] 1491 check_float "delay" $delay 1492 set delay [time_ui_sta $delay] 1493 set objects [lindex $args 1] 1494 1495 parse_clk_port_pin_arg $objects clks pins 1496 1497 set tr [parse_rise_fall_flags flags] 1498 set min_max [parse_min_max_all_flags flags] 1499 1500 set pin_clk "NULL" 1501 if { [info exists keys(-clock)] } { 1502 set pin_clk [get_clock_warn "clock" $keys(-clock)] 1503 if { $clks != {} } { 1504 sta_warn 342 "-clock ignored for clock objects." 1505 } 1506 } 1507 1508 if {[info exists flags(-source)]} { 1509 # Insertion delay (source latency). 1510 set early_late [parse_early_late_all_flags flags] 1511 1512 foreach clk $clks { 1513 set_clock_insertion_cmd $clk "NULL" $tr $min_max $early_late $delay 1514 } 1515 foreach pin $pins { 1516 # Source only allowed on clocks and clock pins. 1517 if { ![is_clock_src $pin] } { 1518 sta_error 556 "-source '[get_full_name $pin]' is not a clock pin." 1519 } 1520 set_clock_insertion_cmd $pin_clk $pin $tr $min_max $early_late $delay 1521 } 1522 } else { 1523 # Latency. 1524 if {[info exists flags(-early)] || [info exists flags(-late)]} { 1525 sta_error 557 "-early/-late is only allowed with -source." 1526 } 1527 1528 foreach clk $clks { 1529 set_clock_latency_cmd $clk "NULL" $tr $min_max $delay 1530 } 1531 foreach pin $pins { 1532 set_clock_latency_cmd $pin_clk $pin $tr $min_max $delay 1533 } 1534 } 1535} 1536 1537################################################################ 1538 1539define_cmd_args "set_sense" \ 1540 {[-type clock|data] [-positive] [-negative] [-pulse pulse_type]\ 1541 [-stop_propagation] [-clocks clocks] pins} 1542 1543proc set_sense { args } { 1544 parse_key_args "set_sense" args keys {-type} flags {} 0 1545 1546 set type "clock" 1547 if { [info exists keys(-type)] } { 1548 set type $keys(-type) 1549 if { $type == "data" } { 1550 sta_warn 343 "set_sense -type data not supported." 1551 } elseif { $type == "clock" } { 1552 set_clock_sense_cmd1 "set_sense" $args 1553 } else { 1554 sta_error 558 "set_sense -type clock|data" 1555 } 1556 } 1557} 1558 1559# deprecated in SDC 2.1 1560define_cmd_args "set_clock_sense" \ 1561 {[-positive] [-negative] [-pulse pulse_type] [-stop_propagation] \ 1562 [-clock clocks] pins} 1563 1564proc set_clock_sense { args } { 1565 sta_warn 344 "set_clock_sense is deprecated as of SDC 2.1. Use set_sense -type clock." 1566 set_clock_sense_cmd1 "set_clock_sense" $args 1567} 1568 1569proc set_clock_sense_cmd1 { cmd cmd_args } { 1570 # SDC uses -clock, OT, OC use -clocks 1571 parse_key_args $cmd cmd_args keys {-clock -clocks -pulse} \ 1572 flags {-positive -negative -stop_propagation} 0 1573 check_argc_eq1 $cmd $cmd_args 1574 1575 set pulse [info exists keys(-pulse)] 1576 if { $pulse } { 1577 sta_warn 345 "-pulse argument not supported." 1578 } 1579 set positive [info exists flags(-positive)] 1580 set negative [info exists flags(-negative)] 1581 set stop_propagation [info exists flags(-stop_propagation)] 1582 if { ($positive && ($negative || $stop_propagation || $pulse)) \ 1583 || ($negative && ($positive || $stop_propagation || $pulse)) \ 1584 || ($stop_propagation && ($positive || $negative || $pulse)) 1585 || ($pulse && ($positive || $negative || $stop_propagation)) } { 1586 sta_warn 346 "-positive, -negative, -stop_propagation and -pulse are mutually exclusive." 1587 } 1588 1589 set pins [get_port_pins_error "pins" [lindex $cmd_args 0]] 1590 set clks {} 1591 if {[info exists keys(-clock)]} { 1592 set clks [get_clocks_warn "clock" $keys(-clock)] 1593 } 1594 if {[info exists keys(-clocks)]} { 1595 set clks [get_clocks_warn "clocks" $keys(-clocks)] 1596 } 1597 foreach pin $pins { 1598 if {[$pin is_hierarchical]} { 1599 sta_warn 347 "hierarchical pin '[get_full_name $pin]' not supported." 1600 } 1601 } 1602 set_clock_sense_cmd $pins $clks $positive $negative $stop_propagation 1603} 1604 1605################################################################ 1606 1607define_cmd_args "set_clock_transition" \ 1608 {[-rise] [-fall] [-min] [-max] transition clocks} 1609 1610proc set_clock_transition { args } { 1611 parse_key_args "set_clock_transition" args keys {} \ 1612 flags {-rise -fall -max -min} 1613 1614 set tr [parse_rise_fall_flags flags] 1615 set min_max [parse_min_max_all_flags flags] 1616 check_argc_eq2 "set_clock_transition" $args 1617 1618 set slew [lindex $args 0] 1619 set clks [get_clocks_warn "clocks" [lindex $args 1]] 1620 1621 foreach clk $clks { 1622 if { [$clk is_virtual] } { 1623 sta_warn 559 "transition time can not be specified for virtual clocks." 1624 } else { 1625 set_clock_slew_cmd $clk $tr $min_max [time_ui_sta $slew] 1626 } 1627 } 1628} 1629 1630################################################################ 1631 1632# -rise/-fall are obsolete. 1633define_cmd_args "set_clock_uncertainty" \ 1634 {[-from|-rise_from|-fall_from from_clock]\ 1635 [-to|-rise_to|-fall_to to_clock] [-rise] [-fall]\ 1636 [-setup] [-hold] uncertainty [objects]} 1637 1638proc set_clock_uncertainty { args } { 1639 parse_key_args "set_clock_uncertainty" args \ 1640 keys {-from -rise_from -fall_from -to -rise_to -fall_to} \ 1641 flags {-rise -fall -setup -hold} 1642 1643 if { [llength $args] == 0 } { 1644 sta_error 560 "missing uncertainty value." 1645 } 1646 set uncertainty [lindex $args 0] 1647 check_float "uncertainty" $uncertainty 1648 set uncertainty [time_ui_sta $uncertainty] 1649 1650 set min_max "min_max" 1651 if { [info exists flags(-setup)] && ![info exists flags(-hold)] } { 1652 set min_max "max" 1653 } 1654 if { [info exists flags(-hold)] && ![info exists flags(-setup)] } { 1655 set min_max "min" 1656 } 1657 1658 if { [info exists keys(-from)] } { 1659 set from_key "-from" 1660 set from_rf "rise_fall" 1661 } elseif { [info exists keys(-rise_from)] } { 1662 set from_key "-rise_from" 1663 set from_rf "rise" 1664 } elseif { [info exists keys(-fall_from)] } { 1665 set from_key "-fall_from" 1666 set from_rf "fall" 1667 } else { 1668 set from_key "none" 1669 } 1670 1671 if { [info exists keys(-to)] } { 1672 set to_key "-to" 1673 set to_rf "rise_fall" 1674 } elseif { [info exists keys(-rise_to)] } { 1675 set to_key "-rise_to" 1676 set to_rf "rise" 1677 } elseif { [info exists keys(-fall_to)] } { 1678 set to_key "-fall_to" 1679 set to_rf "fall" 1680 } else { 1681 set to_key "none" 1682 } 1683 1684 if { $from_key != "none" && $to_key == "none" \ 1685 || $from_key == "none" && $to_key != "none" } { 1686 sta_error 561 "-from/-to must be used together." 1687 } elseif { $from_key != "none" && $to_key != "none" } { 1688 # Inter-clock uncertainty. 1689 check_argc_eq1 "-from/-to" $args 1690 1691 # -from/-to can be lists. 1692 set from_clks [get_clocks_warn "from_clocks" $keys($from_key)] 1693 set to_clks [get_clocks_warn "to_clocks" $keys($to_key)] 1694 1695 foreach from_clk $from_clks { 1696 foreach to_clk $to_clks { 1697 set_inter_clock_uncertainty $from_clk $from_rf \ 1698 $to_clk $to_rf $min_max $uncertainty 1699 } 1700 } 1701 } else { 1702 # Single clock uncertainty. 1703 check_argc_eq2 "set_clock_uncertainty" $args 1704 if { [info exists flags(-rise)] \ 1705 || [info exists flags(-fall)] } { 1706 sta_error 562 "-rise, -fall options not allowed for single clock uncertainty." 1707 } 1708 set objects [lindex $args 1] 1709 parse_clk_port_pin_arg $objects clks pins 1710 1711 foreach clk $clks { 1712 set_clock_uncertainty_clk $clk $min_max $uncertainty 1713 } 1714 foreach pin $pins { 1715 set_clock_uncertainty_pin $pin $min_max $uncertainty 1716 } 1717 } 1718} 1719 1720################################################################ 1721 1722define_cmd_args "set_data_check" \ 1723 {[-from from_pin] [-rise_from from_pin] [-fall_from from_pin]\ 1724 [-to to_pin] [-rise_to to_pin] [-fall_to to_pin]\ 1725 [-setup | -hold] [-clock clock] margin} 1726 1727proc set_data_check { args } { 1728 parse_key_args "set_data_check" args \ 1729 keys {-from -rise_from -fall_from -to -rise_to -fall_to -clock} \ 1730 flags {-setup -hold} 1731 check_argc_eq1 "set_data_check" $args 1732 1733 set margin [time_ui_sta $args] 1734 set from_rf "rise_fall" 1735 set to_rf "rise_fall" 1736 set clk "NULL" 1737 1738 if [info exists keys(-from)] { 1739 set from [get_port_pin_error "from_pin" $keys(-from)] 1740 } elseif [info exists keys(-rise_from)] { 1741 set from [get_port_pin_error "from_pin" $keys(-rise_from)] 1742 set from_rf "rise" 1743 } elseif [info exists keys(-fall_from)] { 1744 set from [get_port_pin_error "from_pin" $keys(-fall_from)] 1745 set from_rf "fall" 1746 } else { 1747 sta_error 563 "missing -from, -rise_from or -fall_from argument." 1748 } 1749 1750 if [info exists keys(-to)] { 1751 set to [get_port_pin_error "to_pin" $keys(-to)] 1752 } elseif [info exists keys(-rise_to)] { 1753 set to [get_port_pin_error "to_pin" $keys(-rise_to)] 1754 set to_rf "rise" 1755 } elseif [info exists keys(-fall_to)] { 1756 set to [get_port_pin_error "to_pin" $keys(-fall_to)] 1757 set to_rf "fall" 1758 } else { 1759 sta_error 564 "missing -to, -rise_to or -fall_to argument." 1760 } 1761 1762 if [info exists keys(-clock)] { 1763 set clk [get_clock_warn "clock" $keys(-clock)] 1764 } 1765 1766 if { [info exists flags(-setup)] && ![info exists flags(-hold)] } { 1767 set setup_hold "setup" 1768 } elseif { [info exists flags(-hold)] && ![info exists flags(-setup)] } { 1769 set setup_hold "hold" 1770 } else { 1771 set setup_hold "setup_hold" 1772 } 1773 1774 set_data_check_cmd $from $from_rf $to $to_rf $clk $setup_hold $margin 1775} 1776 1777################################################################ 1778 1779define_cmd_args "set_disable_timing" \ 1780 {[-from from_port] [-to to_port] objects} 1781 1782# Parallax supports -from or -to alone. 1783# OT requires both -from and -to args. 1784proc set_disable_timing { args } { 1785 parse_key_args "set_disable_timing" args keys {-from -to} flags {} 1786 check_argc_eq1 "set_disable_timing" $args 1787 1788 set from {} 1789 if { [info exists keys(-from)] } { 1790 set from $keys(-from) 1791 } 1792 set to {} 1793 if { [info exists keys(-to)] } { 1794 set to $keys(-to) 1795 } 1796 parse_libcell_libport_inst_port_pin_edge_timing_arc_set_arg $args \ 1797 libcells libports insts ports pins edges timing_arc_sets 1798 1799 if { ([info exists keys(-from)] || [info exists keys(-to)]) \ 1800 && ($libports != {} || $pins != {} || $ports != {}) } { 1801 sta_warn 348 "-from/-to keywords ignored for lib_pin, port and pin arguments." 1802 } 1803 1804 foreach libcell $libcells { 1805 set_disable_timing_cell $libcell $from $to 1806 } 1807 foreach libport $libports { 1808 disable_lib_port $libport 1809 } 1810 foreach inst $insts { 1811 set_disable_timing_instance $inst $from $to 1812 } 1813 foreach pin $pins { 1814 disable_pin $pin 1815 } 1816 foreach port $ports { 1817 disable_port $port 1818 } 1819 foreach edge $edges { 1820 disable_edge $edge 1821 } 1822 foreach timing_arc_set $timing_arc_sets { 1823 disable_timing_arc_set $timing_arc_set 1824 } 1825} 1826 1827proc set_disable_timing_instance { inst from to } { 1828 set from_ports [parse_disable_inst_ports $inst $from] 1829 set to_ports [parse_disable_inst_ports $inst $to] 1830 if { ![$inst is_leaf] } { 1831 sta_error 565 "-from/-to hierarchical instance not supported." 1832 } 1833 if { $from_ports == "NULL" && $to_ports == "NULL" } { 1834 disable_instance $inst "NULL" "NULL" 1835 } elseif { $from_ports == "NULL" } { 1836 foreach to_port $to_ports { 1837 disable_instance $inst "NULL" $to_port 1838 } 1839 } elseif { $to_ports == "NULL" } { 1840 foreach from_port $from_ports { 1841 disable_instance $inst $from_port "NULL" 1842 } 1843 } else { 1844 foreach from_port $from_ports { 1845 foreach to_port $to_ports { 1846 disable_instance $inst $from_port $to_port 1847 } 1848 } 1849 } 1850} 1851 1852# Find ports in inst's cell that have pins. 1853# Bus ports are expanded into a list. 1854proc parse_disable_inst_ports { inst port_name } { 1855 global hierarchy_separator 1856 1857 if { $port_name == "" } { 1858 set ports "NULL" 1859 } else { 1860 set cell [instance_property $inst cell] 1861 set port [$cell find_port $port_name] 1862 if { $port == "NULL" } { 1863 sta_error 566 "pin '[get_full_name $inst]${hierarchy_separator}${port_name}' not found." 1864 } else { 1865 set lib_port [get_property $port liberty_port] 1866 set ports [port_members $lib_port] 1867 } 1868 } 1869 return $ports 1870} 1871 1872proc set_disable_timing_cell { cell from to } { 1873 set from_ports [parse_disable_cell_ports $cell $from] 1874 set to_ports [parse_disable_cell_ports $cell $to] 1875 if { $from_ports == "NULL" && $to_ports == "NULL" } { 1876 disable_cell $cell "NULL" "NULL" 1877 } elseif { $from_ports == "NULL" } { 1878 foreach to_port $to_ports { 1879 disable_cell $cell "NULL" $to_port 1880 } 1881 } elseif { $to_ports == "NULL" } { 1882 foreach from_port $from_ports { 1883 disable_cell $cell $from_port "NULL" 1884 } 1885 } else { 1886 foreach from_port $from_ports { 1887 foreach to_port $to_ports { 1888 disable_cell $cell $from_port $to_port 1889 } 1890 } 1891 } 1892} 1893 1894# Find cell ports. 1895# Bus ports are expanded into a list. 1896proc parse_disable_cell_ports { cell port_name } { 1897 global hierarchy_separator 1898 1899 if { $port_name == "" } { 1900 set ports "NULL" 1901 } else { 1902 set port [$cell find_liberty_port $port_name] 1903 if { $port == "NULL" } { 1904 sta_error 567 "pin '[get_name $cell]${hierarchy_separator}${port_name}' not found." 1905 } else { 1906 set ports [port_members $port] 1907 } 1908 } 1909 return $ports 1910} 1911 1912################################################################ 1913 1914define_cmd_args "set_false_path" \ 1915 {[-setup] [-hold] [-rise] [-fall] [-reset_path] [-comment comment]\ 1916 [-from from_list] [-rise_from from_list] [-fall_from from_list]\ 1917 [-through through_list] [-rise_through through_list]\ 1918 [-fall_through through_list] [-to to_list] [-rise_to to_list]\ 1919 [-fall_to to_list]} 1920 1921proc set_false_path { args } { 1922 parse_key_args "set_false_path" args \ 1923 keys {-from -rise_from -fall_from -to -rise_to -fall_to -comment} \ 1924 flags {-setup -hold -rise -fall -reset_path} 0 1925 1926 set min_max "min_max" 1927 if { [info exists flags(-setup)] && ![info exists flags(-hold)] } { 1928 set min_max "max" 1929 } 1930 if { [info exists flags(-hold)] && ![info exists flags(-setup)] } { 1931 set min_max "min" 1932 } 1933 1934 set cmd "set_false_path" 1935 set arg_error 0 1936 set from [parse_from_arg keys arg_error] 1937 set thrus [parse_thrus_arg args arg_error] 1938 set to [parse_to_arg keys flags arg_error] 1939 check_exception_pins $from $to 1940 if { $arg_error } { 1941 delete_from_thrus_to $from $thrus $to 1942 } else { 1943 check_for_key_args $cmd args 1944 if { $args != {} } { 1945 sta_warn 600 "'$args' ignored." 1946 } 1947 if { ($from == "NULL" && $thrus == "" && $to == "NULL") } { 1948 delete_from_thrus_to $from $thrus $to 1949 sta_warn 350 "-from, -through or -to required." 1950 } else { 1951 if [info exists flags(-reset_path)] { 1952 reset_path_cmd $from $thrus $to $min_max 1953 } 1954 1955 set comment [parse_comment_key keys] 1956 1957 make_false_path $from $thrus $to $min_max $comment 1958 } 1959 } 1960} 1961 1962################################################################ 1963 1964define_cmd_args "set_ideal_latency" \ 1965 {[-rise] [-fall] [-min] [-max] delay objects} 1966 1967proc set_ideal_latency { args } { 1968 # ignored 1969} 1970 1971################################################################ 1972 1973# Specifies net has zero weight for placement. 1974define_cmd_args "set_ideal_net" { nets } 1975 1976################################################################ 1977 1978define_cmd_args "set_ideal_network" {[-no_propagation] objects} 1979 1980proc set_ideal_network { args } { 1981 # ignored 1982} 1983 1984################################################################ 1985 1986define_cmd_args "set_ideal_transition" \ 1987 {[-rise] [-fall] [-min] [-max] transition_time objects} 1988 1989proc set_ideal_transition { args } { 1990 # ignored 1991} 1992 1993################################################################ 1994 1995define_cmd_args "set_input_delay" \ 1996 {[-rise] [-fall] [-max] [-min]\ 1997 [-clock clock] [-clock_fall]\ 1998 [-reference_pin ref_pin]\ 1999 [-source_latency_included] [-network_latency_included]\ 2000 [-add_delay] delay port_pin_list} 2001 2002proc set_input_delay { args } { 2003 set_port_delay "set_input_delay" "set_input_delay_cmd" $args \ 2004 {"input" "bidirect"} 2005} 2006 2007proc set_port_delay { cmd sta_cmd cmd_args port_dirs } { 2008 parse_key_args $cmd cmd_args \ 2009 keys {-clock -reference_pin} \ 2010 flags {-rise -fall -max -min -clock_fall -add_delay \ 2011 -source_latency_included -network_latency_included} 2012 check_argc_eq2 $cmd $cmd_args 2013 2014 set delay_arg [lindex $cmd_args 0] 2015 check_float "delay" $delay_arg 2016 set delay [time_ui_sta $delay_arg] 2017 set pins [get_port_pins_error "pins" [lindex $cmd_args 1]] 2018 2019 set clk "NULL" 2020 if [info exists keys(-clock)] { 2021 set clk [get_clock_warn "clock" $keys(-clock)] 2022 } 2023 2024 set ref_pin "NULL" 2025 if [info exists keys(-reference_pin)] { 2026 set ref_pin [get_port_pin_error "ref_pin" $keys(-reference_pin)] 2027 if { [info exists flags(-source_latency_included)] } { 2028 sta_warn 351 "-source_latency_included ignored with -reference_pin." 2029 } 2030 if { [info exists flags(-network_latency_included)] } { 2031 sta_warn 352 "-network_latency_included ignored with -reference_pin." 2032 } 2033 } 2034 2035 if [info exists flags(-clock_fall)] { 2036 set clk_rf "fall" 2037 } else { 2038 set clk_rf "rise" 2039 } 2040 2041 set tr [parse_rise_fall_flags flags] 2042 set min_max [parse_min_max_all_flags flags] 2043 set add [info exists flags(-add_delay)] 2044 set source_latency_included [info exists flags(-source_latency_included)] 2045 set network_latency_included [info exists flags(-network_latency_included)] 2046 2047 foreach pin $pins { 2048 if { [$pin is_top_level_port] \ 2049 && [lsearch $port_dirs [pin_direction $pin]] == -1 } { 2050 sta_warn 353 "$cmd not allowed on [pin_direction $pin] port '[get_full_name $pin]'." 2051 } elseif { $clk != "NULL" && [lsearch [$clk sources] $pin] != -1 } { 2052 sta_warn 354 "$cmd relative to a clock defined on the same port/pin not allowed." 2053 } else { 2054 $sta_cmd $pin $tr $clk $clk_rf $ref_pin\ 2055 $source_latency_included $network_latency_included \ 2056 $min_max $add $delay 2057 } 2058 } 2059} 2060 2061################################################################ 2062 2063define_cmd_args "set_max_delay" \ 2064 {[-rise] [-fall] [-ignore_clock_latency] [-reset_path] [-comment comment]\ 2065 [-from from_list] [-rise_from from_list] [-fall_from from_list]\ 2066 [-through through_list] [-rise_through through_list]\ 2067 [-fall_through through_list]\ 2068 [-to to_list] [-rise_to to_list] [-fall_to to_list] delay} 2069 2070proc set_max_delay { args } { 2071 set_path_delay "set_max_delay" $args max 2072} 2073 2074proc set_path_delay { cmd args min_max } { 2075 parse_key_args $cmd args \ 2076 keys {-from -rise_from -fall_from -to -rise_to -fall_to -comment} \ 2077 flags {-rise -fall -ignore_clock_latency -reset_path} 0 2078 2079 set arg_error 0 2080 set from [parse_from_arg keys arg_error] 2081 set thrus [parse_thrus_arg args arg_error] 2082 set to [parse_to_arg keys flags arg_error] 2083 if { $arg_error } { 2084 delete_from_thrus_to $from $thrus $to 2085 } else { 2086 check_for_key_args $cmd args 2087 if { [llength $args] == 0 } { 2088 delete_from_thrus_to $from $thrus $to 2089 sta_error 568 "missing delay argument." 2090 } elseif { [llength $args] == 1 } { 2091 set delay $args 2092 check_float "$cmd delay" $delay 2093 set delay [time_ui_sta $delay] 2094 } else { 2095 sta_warn 355 "'$args' ignored." 2096 } 2097 2098 set ignore_clk_latency [info exists flags(-ignore_clock_latency)] 2099 2100 if [info exists flags(-reset_path)] { 2101 reset_path_cmd $from $thrus $to "all" 2102 } 2103 2104 set comment [parse_comment_key keys] 2105 2106 make_path_delay $from $thrus $to $min_max $ignore_clk_latency \ 2107 $delay $comment 2108 } 2109} 2110 2111################################################################ 2112 2113define_cmd_args "set_max_time_borrow" {limit objects} 2114 2115proc set_max_time_borrow { limit objects } { 2116 check_positive_float "borrow_limit" $limit 2117 set limit [time_ui_sta $limit] 2118 parse_clk_inst_pin_arg $objects clks insts pins 2119 foreach pin $pins { 2120 set_latch_borrow_limit_pin $pin $limit 2121 } 2122 foreach inst $insts { 2123 set_latch_borrow_limit_inst $inst $limit 2124 } 2125 foreach clk $clks { 2126 set_latch_borrow_limit_clk $clk $limit 2127 } 2128} 2129 2130################################################################ 2131 2132define_cmd_args "set_min_delay" \ 2133 {[-rise] [-fall] [-ignore_clock_latency] [-reset_path] [-comment comment]\ 2134 [-from from_list] [-rise_from from_list] [-fall_from from_list]\ 2135 [-through through_list] [-rise_through through_list]\ 2136 [-fall_through through_list]\ 2137 [-to to_list] [-rise_to to_list] [-fall_to to_list] delay} 2138 2139proc set_min_delay { args } { 2140 set_path_delay "set_min_delay" $args min 2141} 2142 2143################################################################ 2144 2145define_cmd_args "set_min_pulse_width" {[-low] [-high] value [objects]} 2146 2147proc set_min_pulse_width { args } { 2148 parse_key_args "set_min_pulse_width" args keys {} flags {-low -high} 2149 check_argc_eq1or2 "set_min_pulse_width" $args 2150 2151 if { [info exists flags(-low)] } { 2152 set hi_low "fall" 2153 } elseif { [info exists flags(-high)] } { 2154 set hi_low "rise" 2155 } else { 2156 set hi_low "rise_fall" 2157 } 2158 2159 set min_width [lindex $args 0] 2160 check_positive_float "min pulse width" $min_width 2161 set min_width [time_ui_sta $min_width] 2162 2163 if { [llength $args] == 2 } { 2164 set objects [lindex $args 1] 2165 parse_clk_inst_pin_arg $objects clks insts pins 2166 foreach pin $pins { 2167 set_min_pulse_width_pin $pin $hi_low $min_width 2168 } 2169 foreach inst $insts { 2170 set_min_pulse_width_inst $inst $hi_low $min_width 2171 } 2172 foreach clk $clks { 2173 set_min_pulse_width_clk $clk $hi_low $min_width 2174 } 2175 } else { 2176 set_min_pulse_width_global $hi_low $min_width 2177 } 2178} 2179 2180################################################################ 2181 2182define_cmd_args "set_multicycle_path" \ 2183 {[-setup] [-hold] [-rise] [-fall] [-start] [-end]\ 2184 [-reset_path] [-comment comment]\ 2185 [-from from_list] [-rise_from from_list]\ 2186 [-fall_from from_list] [-through through_list]\ 2187 [-rise_through through_list] [-fall_through through_list]\ 2188 [-to to_list] [-rise_to to_list] [-fall_to to_list] path_multiplier} 2189 2190proc set_multicycle_path { args } { 2191 parse_key_args "set_multicycle_path" args \ 2192 keys {-from -rise_from -fall_from -to -rise_to -fall_to -comment} \ 2193 flags {-setup -hold -rise -fall -start -end -reset_path} 0 2194 2195 set min_max "min_max" 2196 set use_end_clk 1 2197 if { [info exists flags(-setup)] && ![info exists flags(-hold)] } { 2198 # -setup 2199 set min_max "max" 2200 set use_end_clk 1 2201 } 2202 if { [info exists flags(-hold)] && ![info exists flags(-setup)] } { 2203 # -hold 2204 set min_max "min" 2205 set use_end_clk 0 2206 } 2207 2208 set cmd "set_multicycle_path" 2209 set arg_error 0 2210 set from [parse_from_arg keys arg_error] 2211 set thrus [parse_thrus_arg args arg_error] 2212 set to [parse_to_arg keys flags arg_error] 2213 check_exception_pins $from $to 2214 if { $arg_error } { 2215 delete_from_thrus_to $from $thrus $to 2216 } else { 2217 check_for_key_args $cmd args 2218 if { [llength $args] == 0 } { 2219 delete_from_thrus_to $from $thrus $to 2220 sta_error 569 "missing path multiplier argument." 2221 } elseif { [llength $args] == 1 } { 2222 set path_multiplier $args 2223 check_integer "path multiplier" $path_multiplier 2224 } else { 2225 sta_warn 356 "'$args' ignored." 2226 } 2227 2228 set start [info exists flags(-start)] 2229 set end [info exists flags(-end)] 2230 if { $start && $end } { 2231 delete_from_thrus_to $from $thrus $to 2232 sta_error 570 "cannot use -start with -end." 2233 } elseif { $start } { 2234 set use_end_clk 0 2235 } elseif { $end } { 2236 set use_end_clk 1 2237 } 2238 2239 if [info exists flags(-reset_path)] { 2240 reset_path_cmd $from $thrus $to $min_max 2241 } 2242 2243 set comment [parse_comment_key keys] 2244 2245 make_multicycle_path $from $thrus $to $min_max $use_end_clk \ 2246 $path_multiplier $comment 2247 } 2248} 2249 2250################################################################ 2251 2252define_cmd_args "set_output_delay" \ 2253 {[-rise] [-fall] [-max] [-min]\ 2254 [-clock clock] [-clock_fall]\ 2255 [-reference_pin ref_pin]\ 2256 [-source_latency_included] [-network_latency_included]\ 2257 [-add_delay] delay port_pin_list} 2258 2259proc set_output_delay { args } { 2260 set_port_delay "set_output_delay" "set_output_delay_cmd" $args \ 2261 {"output" "tristate" "bidirect"} 2262} 2263 2264################################################################ 2265 2266define_cmd_args "set_propagated_clock" {objects} 2267 2268proc set_propagated_clock { objects } { 2269 parse_clk_port_pin_arg $objects clks pins 2270 foreach clk $clks { 2271 if { [$clk is_virtual] } { 2272 sta_warn 357 "virtual clock [get_name $clk] can not be propagated." 2273 } else { 2274 set_propagated_clock_cmd $clk 2275 } 2276 } 2277 foreach pin $pins { 2278 set_propagated_clock_pin_cmd $pin 2279 } 2280} 2281 2282################################################################ 2283# 2284# Environment Commands 2285# 2286################################################################ 2287 2288define_cmd_args "set_case_analysis" \ 2289 {0|1|zero|one|rise|rising|fall|falling pins} 2290 2291proc set_case_analysis { value pins } { 2292 if { !($value == "0" \ 2293 || $value == "1" \ 2294 || $value == "zero" \ 2295 || $value == "one" \ 2296 || $value == "rise" \ 2297 || $value == "rising" \ 2298 || $value == "fall" \ 2299 || $value == "falling") } { 2300 sta_error 571 "value must be 0, zero, 1, one, rise, rising, fall, or falling." 2301 } 2302 set pins1 [get_port_pins_error "pins" $pins] 2303 foreach pin $pins1 { 2304 set_case_analysis_cmd $pin $value 2305 } 2306} 2307 2308################################################################ 2309 2310define_cmd_args "set_drive" {[-rise] [-fall] [-min] [-max] \ 2311 resistance ports} 2312 2313proc set_drive { args } { 2314 parse_key_args "set_drive" args keys {} flags {-rise -fall -min -max} 2315 set tr [parse_rise_fall_flags flags] 2316 set min_max [parse_min_max_all_check_flags flags] 2317 2318 check_argc_eq2 "set_drive" $args 2319 2320 set res [lindex $args 0] 2321 check_positive_float "resistance" $res 2322 set res [resistance_ui_sta $res] 2323 set ports [get_ports_error "ports" [lindex $args 1]] 2324 foreach port $ports { 2325 set_drive_resistance_cmd $port $tr $min_max $res 2326 } 2327} 2328 2329################################################################ 2330 2331define_cmd_args "set_driving_cell" \ 2332 {[-lib_cell cell] [-library library]\ 2333 [-rise] [-fall] [-min] [-max]\ 2334 [-pin pin] [-from_pin from_pin]\ 2335 [-input_transition_rise trans_rise] [-input_transition_fall trans_fall]\ 2336 [-multiply_by factor] [-dont_scale] [-no_design_rule] ports} 2337 2338proc set_driving_cell { args } { 2339 parse_key_args "set_driving_cell" args \ 2340 keys {-lib_cell -cell -library -pin -from_pin -multiply_by \ 2341 -input_transition_rise -input_transition_fall} \ 2342 flags {-rise -fall -min -max -dont_scale -no_design_rule} 2343 2344 set tr [parse_rise_fall_flags flags] 2345 set min_max [parse_min_max_all_flags flags] 2346 2347 # -cell is an undocumented non-sdc alias for -lib_cell. 2348 if { [info exists keys(-cell)] } { 2349 set keys(-lib_cell) $keys(-cell) 2350 } 2351 2352 if { [info exists keys(-lib_cell)] } { 2353 set cell_name $keys(-lib_cell) 2354 if { [info exists keys(-library)] } { 2355 set library [get_liberty_error "library" $keys(-library)] 2356 set cell [$library find_liberty_cell $cell_name] 2357 if { $cell == "NULL" } { 2358 sta_error 572 "cell '$lib_name:$cell_name' not found." 2359 } 2360 } else { 2361 set library "NULL" 2362 set cell [find_liberty_cell $cell_name] 2363 if { $cell == "NULL" } { 2364 sta_error 573 "'$cell_name' not found." 2365 } 2366 } 2367 } else { 2368 sta_error 574 "missing -lib_cell argument." 2369 } 2370 2371 set to_port "NULL" 2372 if [info exists keys(-pin)] { 2373 set to_port_name $keys(-pin) 2374 set to_port [$cell find_liberty_port $to_port_name] 2375 if { $to_port == "NULL" } { 2376 sta_error 575 "port '$to_port_name' not found." 2377 } 2378 } else { 2379 set port_iter [$cell liberty_port_iterator] 2380 set output_count 0 2381 while {[$port_iter has_next]} { 2382 set port [$port_iter next] 2383 set dir [liberty_port_direction $port] 2384 if { [port_direction_any_output $dir] } { 2385 incr output_count 2386 if { $output_count > 1 } { 2387 $port_iter finish 2388 sta_error 576 "-pin argument required for cells with multiple outputs." 2389 } 2390 set to_port $port 2391 # No break. Keep looking for output ports to make sure there 2392 # is only one. 2393 } 2394 } 2395 $port_iter finish 2396 } 2397 2398 set from_port "NULL" 2399 if [info exists keys(-from_pin)] { 2400 set from_port_name $keys(-from_pin) 2401 set from_port [$cell find_liberty_port $from_port_name] 2402 if { $from_port == "NULL" } { 2403 sta_error 577 "port '$from_port_name' not found." 2404 } 2405 } 2406 2407 set from_slew_rise 0 2408 if [info exists keys(-input_transition_rise)] { 2409 set from_slew_rise $keys(-input_transition_rise) 2410 check_positive_float "-input_transition_rise" $from_slew_rise 2411 set from_slew_rise [time_ui_sta $from_slew_rise] 2412 } 2413 set from_slew_fall 0 2414 if [info exists keys(-input_transition_fall)] { 2415 set from_slew_fall $keys(-input_transition_fall) 2416 check_positive_float "-input_transition_fall" $from_slew_fall 2417 set from_slew_fall [time_ui_sta $from_slew_fall] 2418 } 2419 2420 if [info exists keys(-multiply_by)] { 2421 sta_warn 358 "-multiply_by ignored." 2422 } 2423 if [info exists flags(-dont_scale)] { 2424 sta_warn 359 "-dont_scale ignored." 2425 } 2426 if [info exists flags(-no_design_rule)] { 2427 sta_warn 360 "-no_design_rule ignored." 2428 } 2429 2430 check_argc_eq1 "set_driving_cell" $args 2431 2432 set ports [get_ports_error "ports" [lindex $args 0]] 2433 foreach port $ports { 2434 set_drive_cell_cmd $library $cell $port $from_port \ 2435 $from_slew_rise $from_slew_fall $to_port $tr $min_max 2436 } 2437} 2438 2439################################################################ 2440 2441define_cmd_args "set_fanout_load" {fanout ports} 2442 2443proc set_fanout_load { fanout port_list } { 2444 sta_warn 601 "set_fanout_load not supported." 2445} 2446 2447################################################################ 2448 2449define_cmd_args "set_input_transition" \ 2450 {[-rise] [-fall] [-min] [-max] transition ports} 2451 2452proc set_input_transition { args } { 2453 parse_key_args "set_input_transition" args keys {-clock -clock_fall} \ 2454 flags {-rise -fall -max -min} 2455 2456 set tr [parse_rise_fall_flags flags] 2457 set min_max [parse_min_max_all_flags flags] 2458 2459 2460 check_argc_eq2 "set_input_transition" $args 2461 2462 set slew [lindex $args 0] 2463 check_positive_float "transition" $slew 2464 set slew [time_ui_sta $slew] 2465 set ports [get_ports_error "ports" [lindex $args 1]] 2466 2467 if [info exists keys(-clock)] { 2468 sta_warn 361 "-clock not supported." 2469 } 2470 if [info exists keys(-clock_fall)] { 2471 sta_warn 362 "-clock_fall not supported." 2472 } 2473 2474 foreach port $ports { 2475 set_input_slew_cmd $port $tr $min_max $slew 2476 } 2477} 2478 2479################################################################ 2480 2481define_cmd_args "set_load" \ 2482 {[-rise] [-fall] [-max] [-min] [-subtract_pin_load]\ 2483 [-pin_load] [-wire_load] capacitance objects} 2484 2485proc set_load { args } { 2486 parse_key_args "set_load" args keys {-corner} \ 2487 flags {-rise -fall -min -max -subtract_pin_load -pin_load -wire_load}\ 2488 2489 check_argc_eq2 "set_load" $args 2490 2491 set pin_load [info exists flags(-pin_load)] 2492 set wire_load [info exists flags(-wire_load)] 2493 set subtract_pin_load [info exists flags(-subtract_pin_load)] 2494 set corner [parse_corner_or_all keys] 2495 set min_max [parse_min_max_all_check_flags flags] 2496 set tr [parse_rise_fall_flags flags] 2497 2498 set cap [lindex $args 0] 2499 check_positive_float "capacitance" $cap 2500 set cap [capacitance_ui_sta $cap] 2501 parse_port_net_args [lindex $args 1] ports nets 2502 2503 if { $ports != {} } { 2504 # -pin_load is the default. 2505 if { $pin_load || (!$pin_load && !$wire_load) } { 2506 foreach port $ports { 2507 set_port_pin_cap $port $tr $min_max $cap 2508 } 2509 } elseif { $wire_load } { 2510 foreach port $ports { 2511 set_port_wire_cap $port $subtract_pin_load $tr $min_max $cap 2512 } 2513 } 2514 } 2515 if { $nets != {} } { 2516 if { $pin_load } { 2517 sta_warn 363 "-pin_load not allowed for net objects." 2518 } 2519 if { $wire_load } { 2520 sta_warn 364 "-wire_load not allowed for net objects." 2521 } 2522 if { $tr != "rise_fall" } { 2523 sta_warn 365 "-rise/-fall not allowed for net objects." 2524 } 2525 foreach net $nets { 2526 set_net_wire_cap $net $subtract_pin_load $corner $min_max $cap 2527 } 2528 } 2529} 2530 2531################################################################ 2532 2533define_cmd_args "set_logic_dc" {port_list} 2534 2535proc set_logic_dc { port_list } { 2536 set_logic_value $port_list "X" 2537} 2538 2539# OT supports set_logic cmds on pins. 2540# OC only supports them on ports. 2541proc set_logic_value { port_list value } { 2542 set pins [get_port_pins_error "pins" $port_list] 2543 foreach pin $pins { 2544 set_logic_value_cmd $pin $value 2545 } 2546} 2547 2548################################################################ 2549 2550define_cmd_args "set_logic_one" {port_list} 2551 2552proc set_logic_one { port_list } { 2553 set_logic_value $port_list "1" 2554} 2555 2556################################################################ 2557 2558define_cmd_args "set_logic_zero" {port_list} 2559 2560proc set_logic_zero { port_list } { 2561 set_logic_value $port_list "0" 2562} 2563 2564################################################################ 2565 2566define_cmd_args "set_max_area" {area} 2567 2568proc set_max_area { area } { 2569 check_positive_float "area" $area 2570 set_max_area_cmd $area 2571} 2572 2573################################################################ 2574 2575define_cmd_args "set_max_capacitance" {cap objects} 2576 2577proc set_max_capacitance { cap objects } { 2578 set_capacitance_limit $cap "max" $objects 2579} 2580 2581proc set_capacitance_limit { cap min_max objects } { 2582 parse_cell_port_pin_args $objects cells ports pins 2583 check_positive_float "limit" $cap 2584 set cap [capacitance_ui_sta $cap] 2585 foreach cell $cells { 2586 set_cell_capacitance_limit $cell $min_max $cap 2587 } 2588 foreach port $ports { 2589 set_port_capacitance_limit $port $min_max $cap 2590 } 2591 foreach pin $pins { 2592 set_pin_capacitance_limit $pin $min_max $cap 2593 } 2594} 2595 2596################################################################ 2597 2598define_cmd_args "set_max_fanout" {fanout objects} 2599 2600proc set_max_fanout { fanout objects } { 2601 set_fanout_limit $fanout "max" $objects 2602} 2603 2604proc set_fanout_limit { fanout min_max objects } { 2605 check_positive_float "limit" $fanout 2606 parse_cell_port_args $objects cells ports 2607 foreach port $ports { 2608 set dir [port_direction $port] 2609 if { !($dir == "input" || $dir == "bidirect") } { 2610 sta_error 578 "port '[get_name $port]' is not an input." 2611 } 2612 set_port_fanout_limit $port $min_max $fanout 2613 } 2614 foreach cell $cells { 2615 set_cell_fanout_limit $cell $min_max $fanout 2616 } 2617} 2618 2619################################################################ 2620 2621define_cmd_args "set_max_transition" \ 2622 {[-clock_path] [-data_path] [-rise] [-fall] slew objects} 2623 2624proc set_max_transition { args } { 2625 parse_key_args "set_max_transition" args keys {} \ 2626 flags {-clock_path -data_path -rise -fall} 2627 check_argc_eq2 "set_max_transition" $args 2628 2629 set slew [lindex $args 0] 2630 check_positive_float "transition" $slew 2631 set slew [time_ui_sta $slew] 2632 2633 set objects [lindex $args 1] 2634 parse_clk_cell_port_args $objects clks cells ports 2635 2636 set tr [parse_rise_fall_flags flags] 2637 2638 set path_types {} 2639 if { ![info exists flags(-clock_path)] \ 2640 && ![info exists flags(-data_path)] } { 2641 # Derate clk and data if neither -clock_path or -data_path. 2642 set path_types {"clk" "data"} 2643 } 2644 if { [info exists flags(-clock_path)] } { 2645 lappend path_types "clk" 2646 } 2647 if { [info exists flags(-data_path)] } { 2648 lappend path_types "data" 2649 } 2650 2651 if { ($ports != {} || $cells != {}) \ 2652 && ([info exists flags(-clock_path)] \ 2653 || [info exists flags(-data_path)] 2654 || [info exists flags(-rise)] 2655 || [info exists flags(-fall)]) } { 2656 sta_warn 366 "-data_path, -clock_path, -rise, -fall ignored for ports and designs." 2657 } 2658 2659 # -clock_path/-data_path and transition only apply to clock objects. 2660 foreach path_type $path_types { 2661 foreach clk $clks { 2662 set_slew_limit_clk $clk $tr $path_type "max" $slew 2663 } 2664 } 2665 foreach cell $cells { 2666 set_slew_limit_cell $cell "max" $slew 2667 } 2668 foreach port $ports { 2669 set_slew_limit_port $port "max" $slew 2670 } 2671} 2672 2673################################################################ 2674 2675define_cmd_args "set_port_fanout_number" \ 2676 {[-max] [-min] fanout ports} 2677 2678proc set_port_fanout_number { args } { 2679 parse_key_args "set_port_fanout_number" args keys {} flags {-max -min} 2680 set min_max [parse_min_max_all_check_flags flags] 2681 2682 check_argc_eq2 "set_port_fanout_number" $args 2683 2684 set fanout [lindex $args 0] 2685 check_positive_integer "fanout" $fanout 2686 set ports [get_ports_error "ports" [lindex $args 1]] 2687 foreach port $ports { 2688 set_port_ext_fanout_cmd $port $fanout $min_max 2689 } 2690} 2691 2692################################################################ 2693 2694define_cmd_args "set_resistance" {[-min] [-max] resistance nets} 2695 2696proc set_resistance { args } { 2697 parse_key_args "set_resistance" args keys {} flags {-max -min} 2698 set min_max [parse_min_max_all_check_flags flags] 2699 2700 check_argc_eq2 "set_resistance" $args 2701 2702 set res [lindex $args 0] 2703 check_positive_float "resistance" $res 2704 set res [resistance_ui_sta $res] 2705 set nets [get_nets_error "nets" [lindex $args 1]] 2706 foreach net $nets { 2707 set_net_resistance $net $min_max $res 2708 } 2709} 2710 2711################################################################ 2712 2713define_cmd_args "set_timing_derate" \ 2714 {-early|-late [-rise] [-fall] [-clock] [-data] \ 2715 [-net_delay] [-cell_delay] [-cell_check] derate [objects]} 2716 2717proc set_timing_derate { args } { 2718 parse_key_args "set_timing_derate" args keys {} \ 2719 flags {-rise -fall -early -late -clock -data \ 2720 -net_delay -cell_delay -cell_check} 2721 check_argc_eq1or2 "set_timing_derate" $args 2722 2723 set derate [lindex $args 0] 2724 check_float "derate" $derate 2725 if { $derate > 2.0 } { 2726 sta_warn 367 "derating factor greater than 2.0." 2727 } 2728 2729 set tr [parse_rise_fall_flags flags] 2730 set early_late [parse_early_late_flags flags] 2731 2732 set path_types {} 2733 if { ![info exists flags(-clock)] \ 2734 && ![info exists flags(-data)] } { 2735 # Derate clk and data if neither -clock or -data. 2736 lappend path_types "clk" 2737 lappend path_types "data" 2738 } 2739 if { [info exists flags(-clock)] } { 2740 lappend path_types "clk" 2741 } 2742 if { [info exists flags(-data)] } { 2743 lappend path_types "data" 2744 } 2745 2746 set derate_types {} 2747 if { [info exists flags(-net_delay)] } { 2748 lappend derate_types "net_delay" 2749 } 2750 if { [info exists flags(-cell_delay)] } { 2751 lappend derate_types "cell_delay" 2752 } 2753 if { [info exists flags(-cell_check)] } { 2754 lappend derate_types "cell_check" 2755 } 2756 2757 if { [llength $args] == 2 } { 2758 set objects [lindex $args 1] 2759 parse_libcell_inst_net_arg $objects libcells insts nets 2760 if { $nets != {} } { 2761 if { [info exists flags(-cell_delay)] \ 2762 || [info exists flags(-cell_check)] } { 2763 sta_warn 368 "-cell_delay and -cell_check flags ignored for net objects." 2764 } 2765 foreach net $nets { 2766 foreach path_type $path_types { 2767 set_timing_derate_net_cmd $net $path_type $tr $early_late $derate 2768 } 2769 } 2770 } 2771 if { ![info exists flags(-cell_delay)] \ 2772 && ![info exists flags(-cell_check)] } { 2773 # Cell checks are not derated if no flags are specified. 2774 set derate_types {cell_delay} 2775 } 2776 foreach derate_type $derate_types { 2777 foreach path_type $path_types { 2778 foreach inst $insts { 2779 set_timing_derate_inst_cmd $inst $derate_type $path_type \ 2780 $tr $early_late $derate 2781 } 2782 foreach libcell $libcells { 2783 set_timing_derate_cell_cmd $libcell $derate_type $path_type \ 2784 $tr $early_late $derate 2785 } 2786 } 2787 } 2788 } else { 2789 if { ![info exists flags(-net_delay)] \ 2790 && ![info exists flags(-cell_delay)] \ 2791 && ![info exists flags(-cell_check)] } { 2792 # Cell checks are not derated if no flags are specified. 2793 set derate_types {net_delay cell_delay} 2794 } 2795 foreach derate_type $derate_types { 2796 foreach path_type $path_types { 2797 set_timing_derate_cmd $derate_type $path_type $tr $early_late $derate 2798 } 2799 } 2800 } 2801} 2802 2803proc parse_from_arg { keys_var arg_error_var } { 2804 upvar 1 $keys_var keys 2805 2806 if [info exists keys(-from)] { 2807 set key "-from" 2808 set tr "rise_fall" 2809 } elseif [info exists keys(-rise_from)] { 2810 set key "-rise_from" 2811 set tr "rise" 2812 } elseif [info exists keys(-fall_from)] { 2813 set key "-fall_from" 2814 set tr "fall" 2815 } else { 2816 return "NULL" 2817 } 2818 parse_clk_inst_port_pin_arg $keys($key) from_clks from_insts from_pins 2819 if {$from_pins == {} && $from_insts == {} && $from_clks == {}} { 2820 upvar 1 $arg_error_var arg_error 2821 set arg_error 1 2822 sta_warn 369 "no valid objects specified for $key." 2823 return "NULL" 2824 } 2825 return [make_exception_from $from_pins $from_clks $from_insts $tr] 2826} 2827 2828# "arg_error" is set to notify the caller to cleanup and post error. 2829proc parse_thrus_arg { args_var arg_error_var } { 2830 upvar 1 $args_var args 2831 2832 set thrus {} 2833 set args_rtn {} 2834 while { $args != {} } { 2835 set arg [lindex $args 0] 2836 set tr "" 2837 if { $arg == "-through" } { 2838 set tr "rise_fall" 2839 set key "-through" 2840 } elseif { $arg == "-rise_through" } { 2841 set tr "rise" 2842 set key "-rise_through" 2843 } elseif { $arg == "-fall_through" } { 2844 set tr "fall" 2845 set key "-fall_through" 2846 } 2847 if { $tr != "" } { 2848 if { [llength $args] > 1 } { 2849 set args [lrange $args 1 end] 2850 set arg [lindex $args 0] 2851 parse_inst_port_pin_net_arg $arg insts pins nets 2852 if {$pins == {} && $insts == {} && $nets == {}} { 2853 upvar 1 $arg_error_var arg_error 2854 set arg_error 1 2855 sta_warn 370 "no valid objects specified for $key" 2856 } else { 2857 lappend thrus [make_exception_thru $pins $nets $insts $tr] 2858 } 2859 } 2860 } else { 2861 lappend args_rtn $arg 2862 } 2863 set args [lrange $args 1 end] 2864 } 2865 set args $args_rtn 2866 return $thrus 2867} 2868 2869# Parse -to|-rise_to|-fall_to keywords. 2870proc parse_to_arg { keys_var flags_var arg_error_var } { 2871 upvar 1 $keys_var keys 2872 upvar 1 $flags_var flags 2873 upvar 1 $arg_error_var arg_error 2874 2875 set end_rf [parse_rise_fall_flags flags] 2876 return [parse_to_arg1 keys $end_rf arg_error] 2877} 2878 2879proc parse_to_arg1 { keys_var end_rf arg_error_var } { 2880 upvar 1 $keys_var keys 2881 upvar 1 $arg_error_var arg_error 2882 2883 if [info exists keys(-to)] { 2884 set key "-to" 2885 set to_rf "rise_fall" 2886 } elseif [info exists keys(-rise_to)] { 2887 set key "-rise_to" 2888 set to_rf "rise" 2889 } elseif [info exists keys(-fall_to)] { 2890 set key "-fall_to" 2891 set to_rf "fall" 2892 } else { 2893 # -rise/-fall without -to/-rise_to/-fall_to (no objects). 2894 if { $end_rf != "rise_fall" } { 2895 return [make_exception_to {} {} {} "rise_fall" $end_rf] 2896 } else { 2897 return "NULL" 2898 } 2899 } 2900 parse_clk_inst_port_pin_arg $keys($key) to_clks to_insts to_pins 2901 if {$to_pins == {} && $to_insts == {} && $to_clks == {}} { 2902 upvar 1 $arg_error_var arg_error 2903 set arg_error 1 2904 sta_warn 602 "no valid objects specified for $key." 2905 return "NULL" 2906 } 2907 return [make_exception_to $to_pins $to_clks $to_insts $to_rf $end_rf] 2908} 2909 2910proc delete_from_thrus_to { from thrus to } { 2911 if { $from != "NULL" } { 2912 delete_exception_from $from 2913 } 2914 if { $thrus != {} } { 2915 foreach thru $thrus { 2916 delete_exception_thru $thru 2917 } 2918 } 2919 if { $to != "NULL" } { 2920 delete_exception_to $to 2921 } 2922} 2923 2924proc parse_comment_key { keys_var } { 2925 upvar 1 $keys_var keys 2926 2927 set comment "" 2928 if { [info exists keys(-comment)] } { 2929 set comment $keys(-comment) 2930 } 2931 return $comment 2932} 2933 2934################################################################ 2935 2936define_cmd_args "set_min_capacitance" {cap objects} 2937 2938proc set_min_capacitance { cap objects } { 2939 set_capacitance_limit $cap "min" $objects 2940} 2941 2942################################################################ 2943 2944define_cmd_args "set_operating_conditions" \ 2945 {[-analysis_type single|bc_wc|on_chip_variation] [-library lib]\ 2946 [condition] [-min min_condition] [-max max_condition]\ 2947 [-min_library min_lib] [-max_library max_lib]} 2948 2949proc set_operating_conditions { args } { 2950 parse_key_args "set_operating_conditions" args \ 2951 keys {-analysis_type -library -min -max -min_library -max_library} flags {} 2952 parse_op_cond_analysis_type keys 2953 check_argc_eq0or1 set_operating_conditions $args 2954 if { [llength $args] == 1 } { 2955 set op_cond_name $args 2956 parse_op_cond $op_cond_name "-library" "all" keys 2957 } 2958 if [info exists keys(-min)] { 2959 parse_op_cond $keys(-min) "-min_library" "min" keys 2960 } 2961 if [info exists keys(-max)] { 2962 parse_op_cond $keys(-max) "-max_library" "max" keys 2963 } 2964} 2965 2966proc parse_op_cond { op_cond_name lib_key min_max key_var } { 2967 upvar 1 $key_var keys 2968 if [info exists keys($lib_key)] { 2969 set liberty [get_liberty_error $lib_key $keys($lib_key)] 2970 set op_cond [$liberty find_operating_conditions $op_cond_name] 2971 if { $op_cond == "NULL" } { 2972 sta_error 579 "operating condition '$op_cond_name' not found." 2973 } else { 2974 set_operating_conditions_cmd $op_cond $min_max 2975 } 2976 } else { 2977 set found 0 2978 set lib_iter [liberty_library_iterator] 2979 while {[$lib_iter has_next]} { 2980 set lib [$lib_iter next] 2981 set op_cond [$lib find_operating_conditions $op_cond_name] 2982 if { $op_cond != "NULL" } { 2983 set_operating_conditions_cmd $op_cond $min_max 2984 set found 1 2985 break 2986 } 2987 } 2988 $lib_iter finish 2989 if { !$found } { 2990 sta_error 580 "operating condition '$op_cond_name' not found." 2991 } 2992 } 2993} 2994 2995proc parse_op_cond_analysis_type { key_var } { 2996 upvar 1 $key_var keys 2997 if [info exists keys(-analysis_type)] { 2998 set analysis_type $keys(-analysis_type) 2999 if { $analysis_type == "single" \ 3000 || $analysis_type == "bc_wc" \ 3001 || $analysis_type == "on_chip_variation" } { 3002 set_analysis_type_cmd $analysis_type 3003 } else { 3004 sta_error 581 "-analysis_type must be single, bc_wc or on_chip_variation." 3005 } 3006 } elseif { [info exists keys(-min)] && [info exists keys(-max)] } { 3007 set_analysis_type_cmd "bc_wc" 3008 } 3009} 3010 3011################################################################ 3012 3013define_cmd_args "set_wire_load_min_block_size" {block_size} 3014 3015proc set_wire_load_min_block_size { block_size } { 3016 sta_warn 371 "set_wire_load_min_block_size not supported." 3017} 3018 3019################################################################ 3020 3021define_cmd_args "set_wire_load_mode" "top|enclosed|segmented" 3022 3023proc set_wire_load_mode { mode } { 3024 if { $mode == "top" \ 3025 || $mode == "enclosed" \ 3026 || $mode == "segmented" } { 3027 set_wire_load_mode_cmd $mode 3028 } else { 3029 sta_error 582 "mode must be top, enclosed or segmented." 3030 } 3031} 3032 3033################################################################ 3034 3035define_cmd_args "set_wire_load_model" \ 3036 {-name model_name [-library lib_name] [-min] [-max] [objects]} 3037 3038proc set_wire_load_model { args } { 3039 parse_key_args "set_wire_load_model" args keys {-name -library} \ 3040 flags {-min -max} 3041 3042 check_argc_eq0or1 "set_wire_load_model" $args 3043 if { ![info exists keys(-name)] } { 3044 sta_error 583 "no wire load model specified." 3045 } 3046 3047 set model_name $keys(-name) 3048 set min_max [parse_min_max_all_check_flags flags] 3049 3050 set wireload "NULL" 3051 if [info exists keys(-library)] { 3052 set library [get_liberty_error "library" $keys(-library)] 3053 set wireload [$library find_wireload $model_name] 3054 } else { 3055 set lib_iter [liberty_library_iterator] 3056 while {[$lib_iter has_next]} { 3057 set lib [$lib_iter next] 3058 set wireload [$lib find_wireload $model_name] 3059 if {$wireload != "NULL"} { 3060 break; 3061 } 3062 } 3063 $lib_iter finish 3064 } 3065 if {$wireload == "NULL"} { 3066 sta_error 605 "wire load model '$model_name' not found." 3067 } 3068 set objects $args 3069 set_wire_load_cmd $wireload $min_max 3070} 3071 3072################################################################ 3073 3074define_cmd_args "set_wire_load_selection_group" \ 3075 {[-library lib] [-min] [-max] group_name [objects]} 3076 3077proc set_wire_load_selection_group { args } { 3078 parse_key_args "set_wire_load_selection_group" args keys {-library} \ 3079 flags {-min -max} 3080 3081 set argc [llength $args] 3082 check_argc_eq1or2 "wire_load_selection_group" $args 3083 3084 set selection_name [lindex $args 0] 3085 set objects [lindex $args 1] 3086 3087 set min_max [parse_min_max_all_check_flags flags] 3088 3089 set selection "NULL" 3090 if [info exists keys(-library)] { 3091 set library [get_liberty_error "library" $keys(-library)] 3092 set selection [$library find_wireload_selection $selection_name] 3093 } else { 3094 set lib_iter [liberty_library_iterator] 3095 while {[$lib_iter has_next]} { 3096 set lib [$lib_iter next] 3097 set selection [$lib find_wireload_selection $selection_name] 3098 if {$selection != "NULL"} { 3099 break; 3100 } 3101 } 3102 $lib_iter finish 3103 } 3104 if {$selection == "NULL"} { 3105 sta_error 584 "wire load selection group '$selection_name' not found." 3106 } 3107 set_wire_load_selection_group_cmd $selection $min_max 3108} 3109 3110################################################################ 3111# 3112# Multivoltage and Power Optimization Commands 3113# 3114################################################################ 3115 3116define_cmd_args "create_voltage_area" \ 3117 {[-name name] [-coordinate coordinates] [-guard_band_x guard_x]\ 3118 [-guard_band_y guard_y] cells } 3119 3120proc create_voltage_area { args } { 3121 # ignored 3122} 3123 3124################################################################ 3125 3126define_cmd_args "set_level_shifter_strategy" {[-rule rule_type]} 3127 3128proc set_level_shifter_strategy { args } { 3129 # ignored 3130} 3131 3132################################################################ 3133 3134define_cmd_args "set_level_shifter_threshold" {[-voltage volt]} 3135 3136proc set_level_shifter_threshold { args } { 3137 # ignored 3138} 3139 3140################################################################ 3141 3142define_cmd_args "set_max_dynamic_power" {power [unit]} 3143 3144proc set_max_dynamic_power { power {unit {}} } { 3145 # ignored 3146} 3147 3148################################################################ 3149 3150define_cmd_args "set_max_leakage_power" {power [unit]} 3151 3152proc set_max_leakage_power { power {unit {}} } { 3153 # ignored 3154} 3155 3156################################################################ 3157# 3158# Non-SDC commands 3159# 3160################################################################ 3161 3162define_cmd_args "define_corners" { corner1 [corner2]... } 3163 3164proc define_corners { args } { 3165 define_corners_cmd $args 3166} 3167 3168################################################################ 3169 3170define_cmd_args "set_pvt"\ 3171 {insts [-min] [-max] [-process process] [-voltage voltage]\ 3172 [-temperature temperature]} 3173 3174proc set_pvt { args } { 3175 parse_key_args "set_pvt" args \ 3176 keys {-process -voltage -temperature} flags {-min -max} 3177 3178 set min_max [parse_min_max_all_flags flags] 3179 check_argc_eq1 "set_pvt" $args 3180 set insts [get_instances_error "instances" [lindex $args 0]] 3181 3182 if { $min_max == "all" } { 3183 set_pvt_min_max $insts "min" keys 3184 set_pvt_min_max $insts "max" keys 3185 } else { 3186 set_pvt_min_max $insts $min_max keys 3187 } 3188} 3189 3190proc set_pvt_min_max { insts min_max keys_var } { 3191 upvar 1 $keys_var keys 3192 set op_cond [operating_conditions $min_max] 3193 if { $op_cond == "NULL" } { 3194 set op_cond [default_operating_conditions] 3195 } 3196 if [info exists keys(-process)] { 3197 set process $keys(-process) 3198 check_float "-process" $process 3199 } else { 3200 set process [$op_cond process] 3201 } 3202 if [info exists keys(-voltage)] { 3203 set voltage $keys(-voltage) 3204 check_float "-voltage" $voltage 3205 } else { 3206 set voltage [$op_cond voltage] 3207 } 3208 if [info exists keys(-temperature)] { 3209 set temperature $keys(-temperature) 3210 check_float "-temperature" $temperature 3211 } else { 3212 set temperature [$op_cond temperature] 3213 } 3214 3215 foreach inst $insts { 3216 set_instance_pvt $inst $min_max $process $voltage $temperature 3217 } 3218} 3219 3220proc default_operating_conditions {} { 3221 set found 0 3222 set lib_iter [liberty_library_iterator] 3223 while {[$lib_iter has_next]} { 3224 set lib [$lib_iter next] 3225 set op_cond [$lib default_operating_conditions] 3226 if { $op_cond != "NULL" } { 3227 set found 1 3228 break 3229 } 3230 } 3231 $lib_iter finish 3232 if { !$found } { 3233 sta_error 585 "no default operating conditions found." 3234 } 3235 return $op_cond 3236} 3237 3238################################################################ 3239 3240proc cell_regexp {} { 3241 global hierarchy_separator 3242 return [cell_regexp_hsc $hierarchy_separator] 3243} 3244 3245proc cell_regexp_hsc { hsc } { 3246 return "^(\[^${hsc}\]+)${hsc}(\[^${hsc}\]+)$" 3247} 3248 3249proc port_regexp {} { 3250 global hierarchy_separator 3251 return [port_regexp_hsc $hierarchy_separator] 3252} 3253 3254proc port_regexp_hsc { hsc } { 3255 return "^(\[^${hsc}\]+)${hsc}(\[^${hsc}\]+)${hsc}(\[^${hsc}\]+)$" 3256} 3257 3258# sta namespace end. 3259} 3260