Advertisement
ramswa02

Rubix Custom Commands for PrimeTime

Jun 9th, 2015
989
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
TCL 104.26 KB | None | 0 0
  1. # Copyright 2015, ARM Limited
  2. # All rights reserved.
  3.  
  4. #----------------------------------------------------------------------------------------
  5. #   Rubix SignOff Infrastructure
  6. #
  7. #   File Content        :   Rubix Custom Commands (tcl scripts)
  8. #   EDA Tool        :   Synopsys, PrimeTime
  9. #   Date            :   22-June-2015
  10. #   Author          :   Ramnath Swamy
  11. #   Company         :   ARM Ltd
  12. #
  13. #----------------------------------------------------------------------------------------
  14.  
  15. ###########################################################################################
  16. #                          Main Procedures
  17. ###########################################################################################
  18.  
  19. echo "RM-Info: Starting - Procs Script"
  20. echo "         [info script]\n"
  21.  
  22. #========================================================================================
  23. # Proc Type 1:             Procs for STA Review
  24. #========================================================================================
  25.  
  26. #----------------------------------------------------------------------------------------
  27. # Check For Un-Constrained Endpoints
  28. #----------------------------------------------------------------------------------------
  29.  
  30. proc rbx_report_unconstrained_endpoints { args } {
  31.  
  32.   #.......................................................
  33.   # Print help and quit
  34.   #.......................................................
  35.   if {[lsearch $args "-help"] > -1} {
  36.     puts "rbx_report_unconstrained_endpoints -output <output_file> -remove_clocks <list_of_clocks> -omit_insts_strings <list_of_instance_name_strings>"
  37.     return
  38.   }
  39.  
  40.   #.......................................................
  41.   # Arguments Handling
  42.   #.......................................................
  43.  
  44.   # Default Argument Values
  45.   set output            ""
  46.   set remove_clocks     ""
  47.   set omit_insts_strings    ""
  48.  
  49.   # Check and get the values of the arguments
  50.   if {[llength $args] != 2 && [llength $args] != 4 && [llength $args] != 6} {
  51.     puts "\nRubix-Error: Missing or too many options given for rbx_report_unconstrained_endpoints command.\n"; return
  52.   }
  53.  
  54.   foreach a $args {
  55.     # Check if Wrong option is used
  56.     if {[string match "-*" $a] && $a != "-output" && $a != "-remove_clocks" && $a != "-omit_insts_strings" } {
  57.       puts "\nRubix-Error: Option $a is not valid for rbx_report_unconstrained_endpoints command.\n"; return
  58.     }
  59.  
  60.     # Get the values of the options
  61.     if {$a == "-output"}        { set output            [rbx_value -output $args] }
  62.     if {$a == "-remove_clocks"}     { set remove_clocks     [rbx_value -remove_clocks $args] }
  63.     if {$a == "-omit_insts_strings"}    { set omit_insts_strings    [rbx_value -omit_insts_strings $args] }
  64.   }
  65.  
  66.   #.......................................................
  67.   # Execute the main procedure
  68.   #.......................................................
  69.  
  70.   # Suppress messages
  71.   suppress_message "ATTR-1"
  72.  
  73.   global            sh_product_version
  74.  
  75.   # remove_clocks - These could be for e.g. dft clocks when the check is done
  76.   #                         to see all endpoints are constrained wrt functional clocks
  77.  
  78.   # Create Report file
  79.   redirect     $output {puts [format "%-10s" "***********************************************************************"]}
  80.   redirect -append $output {puts [format "%-10s %-15s" " Rubix Custom Report" "\n"]}
  81.   redirect -append $output {puts [format "%-10s %-15s" " Report" ": rbx_report_unconstrained_endpoints"]}
  82.   if { $remove_clocks != ""} {
  83.   redirect -append $output {puts [format "%-10s %-15s" " "       " -remove_clocks \$removed_clocks"]}}
  84.   if { $omit_insts_strings != ""} {
  85.   redirect -append $output {puts [format "%-10s %-15s" " "       " -omit_insts_strings \$omit_instance_strings"]}}
  86.   redirect -append $output {puts [format "%-10s %-15s" " Design" ": [get_attribute [get_design] full_name]"]}
  87.   redirect -append $output {puts [format "%-10s %-15s" " Version" ": $sh_product_version"]}
  88.   redirect -append $output {puts [format "%-10s %-15s" " Date" ": [date]"]}
  89.   redirect -append $output {puts [format "%-10s" "***********************************************************************"]}
  90.  
  91.   set all_omited_dpins_cnt  0
  92.   set all_omited_cgpins_cnt 0
  93.  
  94.   # Remove clocks if asked to
  95.   if {[llength $remove_clocks] > 0} {
  96.     # Print clocks that were removed before producing this report
  97.     redirect -append $output {puts      " Unconstrained pins are generated after removing the following clocks"}
  98.     redirect -append $output {puts      "\n \$removed_clocks ="}
  99.     foreach rclk $remove_clocks {
  100.       remove_clock      $rclk
  101.       set remove_clocks     [concat $remove_clocks $rclk]
  102.       redirect -append $output {puts        "                   $rclk"}
  103.     }
  104.     redirect -append $output {puts      "***********************************************************************"}
  105.   }
  106.   set remove_clocks [lsort -unique $remove_clocks]
  107.  
  108.   # Omit Instances if asked to
  109.   if {[llength $omit_insts_strings] > 0} {
  110.     # Print instance strings that are omitted
  111.     redirect -append $output {puts      " All the instances with the following string(s) are omitted from the analysis"}
  112.     redirect -append $output {puts      "\n \$omit_instance_strings ="}
  113.     foreach oinst $omit_insts_strings {
  114.       redirect -append $output {puts        "                   $oinst"}
  115.     }
  116.     redirect -append $output {puts      "***********************************************************************"}
  117.   }
  118.  
  119.   # Print clocks in the design
  120.   redirect -append $output {puts        "\n Unconstrained pins are generated with the following clocks in the session"}
  121.   foreach clk [get_object_name [all_clocks]] {
  122.     redirect -append $output {puts      "                   $clk"}
  123.   }
  124.   redirect -append $output {puts        "***********************************************************************"}
  125.  
  126.   # Get all the timing endpoints
  127.   set data_inputs_all       [get_pins -hier * -filter "is_data_pin==true"]
  128.   set clk_gate_enables_all  [get_pins -hier * -filter "is_clock_gating_pin==true && is_clock_pin==false"]
  129.  
  130.   # For Hierarchical Analysis
  131.   foreach omit_inst $omit_insts_strings {
  132.     set omit_insts_dinputs  [get_pins -hier * -filter "is_data_pin==true && full_name =~ *$omit_inst*"]
  133.     set data_inputs_all     [remove_from_collection $data_inputs_all $omit_insts_dinputs]
  134.  
  135.     set omit_insts_cginputs [get_pins -hier * -filter "is_clock_gating_pin==true && full_name =~ *$omit_inst*"]
  136.     set clk_gate_enables_all    [remove_from_collection $clk_gate_enables_all $omit_insts_cginputs]
  137.  
  138.     set all_omited_dpins_cnt    [expr $all_omited_dpins_cnt + [sizeof_collection $omit_insts_dinputs]]
  139.     set all_omited_cgpins_cnt   [expr $all_omited_cgpins_cnt + [sizeof_collection $omit_insts_cginputs]]
  140.   }
  141.  
  142.   set data_inputs       [get_object_name   $data_inputs_all]
  143.   set clk_gate_enables      [get_object_name   $clk_gate_enables_all]
  144.  
  145.   # Print un-constrained pins
  146.   redirect -append $output {puts [format "%-25s %-50s" "\nUnconstrained Reason" "Unconstrained Pin"]}
  147.   redirect -append $output {puts [format "%-25s"       "-----------------------------------------------------------------------"]}
  148.   foreach pin "$data_inputs $clk_gate_enables" {
  149.     if {[sizeof_collection  [get_timing_paths -to [get_pins $pin]]] < 1} {
  150.       set unconstr_reason   [get_attribute  [get_pins $pin] dominant_exception]
  151.       if {$unconstr_reason==""} {set unconstr_reason "Not Known"}
  152.       redirect -append $output {puts [format "%-25s %-50s" "$unconstr_reason" "$pin"]}
  153.     }
  154.   }
  155.  
  156.  
  157.   redirect -append $output {puts "\n\n***********************************************************************"}
  158.   redirect -append $output {puts " Summary:"}
  159.   redirect -append $output {puts "      No of Data Endpoints unverified / verified     = $all_omited_dpins_cnt/[llength $data_inputs]"}
  160.   redirect -append $output {puts "      No of ClkGate Endpoints unverified / verified  = $all_omited_cgpins_cnt/[llength $clk_gate_enables]"}
  161.   redirect -append $output {puts "***********************************************************************"}
  162.  
  163.  
  164.   redirect -append $output {puts              "\n1\n"}
  165.  
  166.   # Enable the suppressed messages
  167.   unsuppress_message "ATTR-1"
  168.  
  169. }
  170.  
  171.  
  172. #----------------------------------------------------------------------------------------
  173. # Proc Check if Shift Enable pins are controlled only by DFT Controller
  174. # If a SE pin of a FF is not controlled by DFT controller then the FF might be used
  175. # for Functional purpose.
  176. #----------------------------------------------------------------------------------------
  177. proc rbx_report_functional_si_endpoints { \
  178.                                         scan_enable_control_pin
  179.                                         { fmt  csv } \
  180.                                        } {
  181.  
  182.   set t1                [clock seconds]
  183.  
  184.   set all_se_pins       [get_pins -hier */SE]
  185.  
  186.   # Print header
  187.   puts [format "%-20s" "#*********************************************************************************************"]
  188.   puts [format "%-30s %-15s" "#Report" ": rbx_report_functional_si_endpoints"]
  189.   puts [format "%-30s %-15s" "#DFT Scan enable control pin" ": $scan_enable_control_pin"]
  190.   puts [format "%-20s" "#*********************************************************************************************"]
  191.   if { $fmt == "csv" } {
  192.     puts        [format "\nShift Enable Pin,Driver Pin"]
  193.   } else {
  194.     puts        [format "%-200s %-50s" "Shift Enable Pin" " Driving Pin"]
  195.   }
  196.  
  197.   # Check each SE pin of sequential cell
  198.   suppress_message UITE-416
  199.  
  200.   foreach_in_collection pin $all_se_pins {
  201.     set pin    [get_attr [get_pins $pin] full_name]
  202.     set driver [get_attr [get_attribute [get_timing_path -to  $pin] startpoint] full_name]
  203.  
  204.     if { $driver != "$scan_enable_control_pin" } {
  205.       puts [format "%-200s %-50s" "$pin" " $driver"]
  206.     }
  207.   }
  208.  
  209.   unsuppress_message UITE-416
  210.  
  211.   puts "\n1\n"
  212.  
  213.   set t2                [clock seconds]
  214.   echo                  "\n# rbx_report_functional_si_endpoints RUNTIME: [rbx_get_runtime $t1 $t2] "
  215. }
  216.  
  217.  
  218. #----------------------------------------------------------------------------------------
  219. # Report a pba version of the 'report_constraint -all_violators' report for both setup and hold
  220. #----------------------------------------------------------------------------------------
  221.  
  222. proc rbx_report_pba_timing_all_endpoints { args } {
  223.  
  224.   #.......................................................
  225.   # Print help and quit
  226.   #.......................................................
  227.   if {[lsearch $args "-help"] > -1} {
  228.     puts "rbx_report_pba_timing_all_endpoints -check_type \[setup | hold\] -output \[path/to/filename\] -overwrite"
  229.     return
  230.   }
  231.  
  232.  
  233.   #.......................................................
  234.   # Arguments Handling
  235.   #.......................................................
  236.  
  237.   upvar pt_shell_mode pt_shell_mode
  238.   upvar pba_recalculate_full_path pba_recalculate_full_path
  239.   upvar pba_enable_path_based_physical_exclusivity pba_enable_path_based_physical_exclusivity
  240.  
  241.   # Default Argument Values
  242.   set check_type "setup"
  243.   set report_file ""
  244.   set overwrite 0
  245.  
  246.   # Check and get the values of the arguments
  247.   if {[llength $args] != 2 && [llength $args] != 4 && [llength $args] != 5 } {
  248.     puts "\nRubix-Error: Missing or too many options given for rbx_report_pba_timing_all_endpoints command.\n"; return
  249.   }
  250.  
  251.   foreach a $args {
  252.     # Check if wrong option is used
  253.     if {[string match "-*" $a] && $a != "-check_type" && $a != "-output"  && $a != "-overwrite"} {
  254.       puts "\nRubix-Error: Option $a is not valid for rbx_report_pba_timing_all_endpoints command.\n"; return
  255.     }
  256.  
  257.     # Get the values of the options
  258.     if {$a == "-check_type"}    { set check_type  [rbx_value -check_type $args] }
  259.     if {$a == "-output"}        { set report_file [rbx_value -output     $args] }
  260.     if {$a == "-overwrite"}     { set overwrite  1 }
  261.   }
  262.  
  263.   #.......................................................
  264.   # Checks before starting execution
  265.   #.......................................................
  266.  
  267.   if {[file exists $report_file] && $overwrite == 0} {
  268.     puts "\nRubix-Error: Output file already exists."
  269.     puts "             Move or delete the exisitng file, use a different output file, or use -overwrite.\n"
  270.     return
  271.   }
  272.  
  273.   if {$pt_shell_mode != "primetime_master"} {
  274.     puts "\nRubix-Error: This is a DMSA command.\n"
  275.     return
  276.   }
  277.  
  278.   #.......................................................
  279.   # Execute the main procedure
  280.   #.......................................................
  281.  
  282.   set t1      [clock seconds]
  283.   set rpt     [open "$report_file"        w+]
  284.  
  285.   # Make sure all loaded scenarios are active
  286.   current_scenario -all
  287.  
  288.   # create a variable in each of the scenarios containing the check type, then pull it in
  289.   remote_execute { set scenario_check_type $check_type($standalone_scenario) }
  290.   get_distributed_variables scenario_check_type
  291.  
  292.   # initialize list
  293.   set scenario_list ""
  294.  
  295.   # populate list
  296.   foreach scenario [get_attribute [current_scenario] full_name] {
  297.     if {$scenario_check_type($scenario) == $check_type} {
  298.         lappend scenario_list $scenario
  299.     }
  300.   }
  301.  
  302.   # set active scenarios
  303.   current_scenario $scenario_list
  304.  
  305.   if {[llength $scenario_list] == 0} {
  306.     puts "\nRubix-Error: No scenarios loaded which match the required check_type.\n"
  307.     return
  308.   }
  309.  
  310.   # Print header
  311.   puts $rpt [format "%-20s" "#*********************************************************************************************"]
  312.   puts $rpt [format "%-30s %-15s" "# Report" ": rbx_report_pba_timing_all_endpoints"]
  313.   puts $rpt [format "%-30s %-15s" "# Check_type" ": $check_type"]
  314.   puts $rpt [format "%-30s %-15s" "# Scenarios" ": [llength $scenario_list]"]
  315.   foreach scenario $scenario_list { puts $rpt [format "%-15s %-15s" "#" "$scenario"] }
  316.   puts $rpt [format "%-45s %-15s" "# pba_recalculate_full_path" ": $pba_recalculate_full_path"]
  317.   if {!$pba_recalculate_full_path} { puts $rpt [format "%-15s %-15s" "#" "Consider setting true for reducing pessimism at the expense of runtime"] }
  318.   puts $rpt [format "%-45s %-15s" "# pba_enable_path_based_physical_exclusivity" ": $pba_enable_path_based_physical_exclusivity"]
  319.   if {!$pba_enable_path_based_physical_exclusivity} { puts $rpt [format "%-15s %-15s" "#" "Consider setting true for reducing pessimism at the expense of runtime"] }
  320.   puts $rpt [format "%-20s" "#*********************************************************************************************\n"]
  321.  
  322.   remote_execute { set path_groups [get_object_name [get_path_groups *]] }
  323.   get_distributed_variables path_groups -merge_type list
  324.  
  325.   switch $check_type {
  326.      setup {
  327.         set delay_type max
  328.      }
  329.      hold {
  330.         set delay_type min
  331.      }
  332.   }
  333.  
  334.   echo "Rubix-Info: [llength $path_groups] path groups to report"
  335.   echo "            If this report takes too long, consider fixing timing first"
  336.  
  337.   # Report for all path groups
  338.   set i 1
  339.   foreach pg $path_groups {
  340.     echo "            Reporting path_group $i of [llength $path_groups]"
  341.     incr i
  342.     puts $rpt "+-------------------------------------------------+"
  343.     puts $rpt "|   Group $pg                                      "                                    
  344.     puts $rpt "+-------------------------------------------------+"
  345.  
  346.     set timing_path_collection \
  347.             [get_timing_paths   -slack_lesser_than 0 \
  348.                                 -delay_type $delay_type \
  349.                                 -pba_mode ex \
  350.                                 -max_paths 1000 \
  351.                                 -group $pg \
  352.                                 -attributes {slack endpoint} \
  353.             ]
  354.  
  355.     if {[sizeof_collection $timing_path_collection] > 0} {
  356.         puts $rpt [format "\t%-8s %-10s %-10s" "Slack" "Scenario" "Endpoint"]
  357.         foreach_in_collection timing_path $timing_path_collection {
  358.             puts $rpt [format "\t%-8.3f %-40s %-10s" \
  359.                         [get_attribute $timing_path slack] \
  360.                         [get_attribute $timing_path scenario_name] \
  361.                         [get_attribute [get_attribute $timing_path endpoint] full_name] \
  362.                  ]
  363.         }
  364.     } else {
  365.         puts $rpt "\tNo failing paths"
  366.     }
  367.    
  368.   }
  369.  
  370.   close $rpt
  371.  
  372.   #.......................................................
  373.   # End of proc
  374.   #.......................................................
  375.  
  376.   set t2                [clock seconds]
  377.   echo                  "\n# rbx_report_functional_si_endpoints RUNTIME: [rbx_get_runtime $t1 $t2] "
  378. }
  379.  
  380.  
  381.  
  382. #========================================================================================
  383. # Proc Type 2:             Procs to check timing quality of the design
  384. #========================================================================================
  385.  
  386.  
  387. #----------------------------------------------------------------------------------------
  388. # Proc to check if clock network has multi-vt
  389. #----------------------------------------------------------------------------------------
  390.  
  391. proc rbx_check_clock_cell_type { args } {
  392.  
  393.   #.......................................................
  394.   # Print help and quit
  395.   #.......................................................
  396.   if {[lsearch $args "-help"] > -1} {
  397.     puts "rbx_check_clock_cell_type -cts_lib_list cts_lib_list [-output_style csv | table]"
  398.     return
  399.   }
  400.  
  401.   #.......................................................
  402.   # Arguments Handling
  403.   #.......................................................
  404.  
  405.   # Default Argument Values
  406.   set cts_lib_list ""
  407.   set output_style table
  408.  
  409.   # Check and get the values of the arguments
  410.   if {[llength $args] != 2 && [llength $args] != 4} {
  411.     puts "\nRubix-Error: Missing or too many options given for rbx_check_clock_cell_type command.\n"; return
  412.   }
  413.  
  414.   foreach a $args {
  415.     # Check if Wrong option is used
  416.     if {[string match "-*" $a] && $a != "-cts_lib_list" && $a != "-output_style"} {
  417.       puts "\nRubix-Error: Option $a is not valid for rbx_check_clock_cell_type command.\n"; return
  418.     }
  419.  
  420.     # Get the values of the options
  421.     if {$a == "-cts_lib_list"}  { set cts_lib_list [rbx_value -cts_lib_list $args] }
  422.     if {$a == "-output_style"}  { set output_style [rbx_value -output_style $args] }
  423.   }
  424.  
  425.   #.......................................................
  426.   # Execute the main procedure
  427.   #.......................................................
  428.  
  429.   global    sh_product_version
  430.  
  431.   set t1          [clock seconds]
  432.   set all_nets    [get_nets -hier *]
  433.  
  434.   # For printing one lib per line
  435.   foreach clib $cts_lib_list {
  436.     lappend cts_lib_list_stacked "\n\t$clib"
  437.   }
  438.   set cts_lib_list_stacked [string map {\{ "" \} ""} $cts_lib_list_stacked]
  439.  
  440.   puts [format "%-20s" "*********************************************************************************************"]
  441.   puts [format "%-10s %-15s" " Rubix Custom Report" "\n"]
  442.   puts [format "%-10s %-15s" " Report" ": rbx_check_clock_cell_type"]
  443.   puts [format "%-10s %-15s" " "       " -cts_lib_list $cts_lib_list_stacked"]
  444.   puts [format "%-10s %-15s" " "       " -output_style $output_style"]
  445.   puts [format "%-10s %-15s" " Design" ": [get_attribute [get_design] full_name]"]
  446.   puts [format "%-10s %-15s" " Version" ": $sh_product_version"]
  447.   puts [format "%-10s %-15s" " Date" ": [date]"]
  448.   puts [format "%-10s" "*********************************************************************************************"]
  449.   switch $output_style {
  450.      table {
  451.         puts [format "%-150s %-20s %-30s" "Cell" " Reference" " Library used Currently"]
  452.         puts [format "%-150s %-20s %-30s" "----" " ---------" " ----------------------"]
  453.   }
  454.      csv {
  455.         puts "Cell,Reference,Library used Currently"
  456.         puts "----,---------,----------------------"
  457.      }
  458.   }
  459.  
  460.  
  461.   # Process all nets in the design
  462.   foreach_in_collection net $all_nets {
  463.  
  464.     set net     [get_attribute [get_nets $net] full_name]
  465.     set driver  [get_attribute [get_pins -quiet -leaf -of_objects [get_net $net] -filter "direction==out"] full_name ]
  466.  
  467.     # Extract only the clock nets and get the cells connected to it
  468.     if { [sizeof_collection [get_attribute -quiet [get_pins -quiet $driver] clocks ]] > 0 } {
  469.       set pins    [filter_collection [get_pins -leaf -of_objects [get_nets $net]] "is_clock_pin==false"] ; # Ignore if the pin is clock pin (of FF)
  470.  
  471.       # Get the library name of each cell
  472.       foreach_in_collection pin $pins {
  473.         set cell    [get_attribute [get_cells -of_objects [get_pins $pin]] full_name]
  474.         set ref     [get_attribute [get_cells -of_objects [get_pins $pin]] ref_name]
  475.         set lib     [string map [list "/$ref" ""] [get_attribute [get_lib_cells */$ref] full_name]]
  476.  
  477.         # Print if lib none of cts_lib_list list
  478.         if { [lsearch $cts_lib_list $lib] < 0 } {
  479.           switch $output_style {
  480.             table { puts  [format "%-150s %-20s %-30s" "$cell" " $ref" " $lib"]}
  481.             csv   { puts                                $cell,$ref,$lib"}
  482.          }
  483.        }
  484.      }
  485.    }
  486.  }
  487.  
  488.  puts "\n1\n"
  489.  set t2        [clock seconds]
  490.   echo          "\n# rbx_check_clock_cell_type RUNTIME: [rbx_get_runtime $t1 $t2] "
  491. }
  492.  
  493.  
  494. #----------------------------------------------------------------------------------------
  495. # Proc to get average clock latency
  496. #----------------------------------------------------------------------------------------
  497.  
  498. proc rbx_report_average_clock_latency { \
  499.                   clocks_list \
  500.                   {clock_type launch} \
  501.                   {report_file rbx_report_average_clock_latency.rpt} \
  502.                                     } {
  503.  
  504.     set t1      [clock seconds]
  505.  
  506.     set rpt     [open "$report_file"        w+]
  507.     set rpt_csv [open "${report_file}_csv"  w+]
  508.  
  509.     echo "RM-Info: Caculating average insertion delays of clocks. Results are written into following files."
  510.     echo "         [file normalize $report_file] and"
  511.     echo "         [file normalize ${report_file}_csv] \n"
  512.  
  513.     if { $clock_type == "launch" } {
  514.         set lat_type "startpoint_clock_latency"
  515.     } else {
  516.         set lat_type "endpoint_clock_latency"
  517.     }
  518.  
  519.     suppress_message UITE-416
  520.  
  521.     foreach f "$rpt $rpt_csv" {
  522.         puts $f [format "%-20s" "#*********************************************************************************************"]
  523.         puts $f [format "%-30s %-15s" "# Report" ": rbx_report_average_clock_latency"]
  524.         puts $f [format "%-30s %-15s" "# Clock type" ": $clock_type"]
  525.         puts $f [format "%-30s" "#---------------------------------------------------------------------------------------------"]
  526.         puts $f [format "%-30s %-15s" "# Note" ": Depending on which clock path (launch/capture) is derated"]
  527.         puts $f [format "%-30s %-15s" "#     " "  users can choose to measure insertion delay from either "]
  528.         puts $f [format "%-30s %-15s" "#     " "  paths by setting \"clock_type\" to lauch or capture. "]
  529.         puts $f [format "%-30s" "#*********************************************************************************************"]
  530.     }
  531.  
  532.     puts $rpt     [format "%-15s %-20s %-20s" "Clock" "Average Insertion Delay" "           Sinks(ICG not included)"]
  533.     puts $rpt     [format "%-15s %-20s %-20s" "-----" "-----------------------" "           -----------------------"]
  534.     puts $rpt_csv [format "Clock,Average Insertion Delay,Sinks(ICG not included)"]
  535.     puts $rpt_csv [format "-----,-----------------------,-----------------------"]
  536.  
  537.     foreach clk $clocks_list {
  538.         set cp_pins [get_attribute -quiet [get_clocks -quiet $clk] clock_network_pins]
  539.  
  540.         set total_lat 0
  541.         set num       0
  542.  
  543.         foreach_in_collection p $cp_pins {
  544.             set lat [get_attribute [get_timing_path -from [get_pins $p]] $lat_type]
  545.  
  546.             if { $lat > 0 } {
  547.                 set total_lat [expr $total_lat + $lat]
  548.                 incr num
  549.             }
  550.         }
  551.  
  552.         puts $rpt     [format "%-15s %-.2f %-20s" "$clk" "[expr $total_lat / $num]" "                              $num"]
  553.         puts $rpt_csv [format "$clk,[expr $total_lat / $num],$num"]
  554.         echo "         - Finished caculating insertion delay of $clk."
  555.     }
  556.  
  557.     echo ""
  558.     puts  $rpt     "\n1\n"
  559.     puts  $rpt_csv "\n1\n"
  560.  
  561.     unsuppress_message UITE-416
  562.  
  563.     set t2          [clock seconds]
  564.     puts $rpt       "\n# rbx_report_average_clock_latency RUNTIME: [rbx_get_runtime $t1 $t2] "
  565.     puts $rpt_csv   "\n# rbx_report_average_clock_latency RUNTIME: [rbx_get_runtime $t1 $t2] "
  566.  
  567.     close $rpt
  568.     close $rpt_csv
  569. }
  570.  
  571. #----------------------------------------------------------------------------------------
  572. # Proc to get clock nets with Effective coupling capacitance
  573. #----------------------------------------------------------------------------------------
  574.  
  575. proc rbx_report_xtalk_clock_nets { args } {
  576.  
  577.   #.......................................................
  578.   # Print help and quit
  579.   #.......................................................
  580.   if {[lsearch $args "-help"] > -1} {
  581.     puts "rbx_report_xtalk_clock_nets -ccap_threshold cap_value -omit_clocks clocks_list [-include_position] [-output_style csv | table]"
  582.     return
  583.   }
  584.  
  585.   #.......................................................
  586.   # Arguments Handling
  587.   #.......................................................
  588.  
  589.   # Default Argument Values
  590.   set ccap_threshold    0
  591.   set omit_clocks   ""
  592.   set include_position  0
  593.   set output_style  table
  594.  
  595.   # Check and get the values of the arguments
  596.   if {[llength $args] < 0 || [llength $args] > 7 } {
  597.     puts "\nRubix-Error: Missing or too many options given for rbx_report_xtalk_clock_nets command.\n"; return
  598.   }
  599.  
  600.   foreach a $args {
  601.     # Check if Wrong option is used
  602.     if {[string match {-[A-Z|a-y]*} $a] && $a != "-ccap_threshold" && $a != "-include_position" && $a != "-omit_clocks" && $a != "-output_style"} {
  603.       puts "\nRubix-Error: Option $a is not valid for rbx_report_xtalk_clock_nets command.\n"; return
  604.     }
  605.  
  606.     # Get the values of the options
  607.     if {$a == "-ccap_threshold"}    { set ccap_threshold [rbx_value -ccap_threshold $args] }
  608.     if {$a == "-omit_clocks"}       { set omit_clocks [rbx_value -omit_clocks $args] }
  609.     if {$a == "-include_position"}  { set include_position 1 }
  610.     if {$a == "-output_style"}      { set output_style [rbx_value -output_style $args] }
  611.   }
  612.  
  613.   #.......................................................
  614.   # Execute the main procedure
  615.   #.......................................................
  616.  
  617.     set t1          [clock seconds]
  618.  
  619.     global          sh_product_version
  620.     global          si_enable_analysis
  621.     global          xtalk_clk_nets
  622.     global          xtalk_clk_nets_values
  623.  
  624.     set omit_clocks_stacked ""
  625.     set xtalk_clk_nets      0
  626.     set xtalk_clk_nets_values   0
  627.     set ccap_list       ""
  628.  
  629.     if { $si_enable_analysis == "true" } {
  630.         # Get all nets in the design
  631.         set all_nets        [get_nets -hier *]
  632.  
  633.     # For printing one lib per line
  634.     foreach oc $omit_clocks {
  635.           lappend omit_clocks_stacked "\n\t          $oc"
  636.         }
  637.         set omit_clocks_stacked [string map {\{ "" \} ""} $omit_clocks_stacked]
  638.  
  639.  
  640.         # Print header
  641.     puts [format "%-20s" "*********************************************************************************************"]
  642.     puts [format "%-10s %-15s" " Rubix Custom Report" "\n"]
  643.     puts [format "%-10s %-15s" " Report" ": rbx_report_xtalk_clock_nets"]
  644.     puts [format "%-10s %-15s" " "       " -ccap_threshold $ccap_threshold"]
  645.         if { $include_position == 1} {
  646.     puts [format "%-10s %-15s" " "       " -include_position"]}
  647.         if { $omit_clocks_stacked != ""} {
  648.     puts [format "%-10s %-15s" " "       " -omit_clocks \$omitted_clocks"]}
  649.     puts [format "%-10s %-15s" " "       " -output_style $output_style"]
  650.     puts [format "%-10s %-15s" " Design" ": [get_attribute [get_design] full_name]"]
  651.     puts [format "%-10s %-15s" " Version" ": $sh_product_version"]
  652.     puts [format "%-10s %-15s" " Date" ": [date]"]
  653.         puts [format "%-30s" "*********************************************************************************************"]
  654.         if {[llength $omit_clocks] > 0} {
  655.           puts      "\n \$omitted_clocks ="
  656.           foreach oclk $omit_clocks {
  657.             puts        "                   $oclk"
  658.           }
  659.           puts [format "%-30s" "*********************************************************************************************"]
  660.         }
  661.         puts [format "%-10s" "# Note: -Violating nets and their ccaps are stored in \"xtalk_clk_nets\" and \"xtalk_clk_nets_values\" tcl lists"]
  662.         if { $include_position == 1 } {
  663.             puts [format "%-30s" "#       -Position ranges from 0 to 10. 0 -> leaf ; 10 -> trunk"]
  664.         }
  665.         puts [format "%-30s" "*********************************************************************************************"]
  666.  
  667.         if { $output_style == "csv" } {
  668.             switch $include_position {
  669.                 0 {puts "\n#Coupling-Cap,CCap %,Agrsr-Count,Driver-Ref-Name,Net,Driver-Name,Clocks"}
  670.                 1  {puts "\n#Coupling-Cap,CCap %,Agrsr-Count,Position,Driver-Ref-Name,Net,Driver-Name,Clocks"}
  671.             }
  672.         } else {
  673.             switch $include_position {
  674.                 0    {   puts [format "%-15s %-10s %-20s %-20s %-50s %-50s %-30s" "#Coupling-Cap" " CCap %" " Agrsr-Count" " Driver-Ref-Name" " Net" " Driver-Name" " Clocks"]
  675.                          puts [format "%-15s %-10s %-20s %-20s %-50s %-50s %-30s" "#------------" " ------" " -----------" " ---------------" " ---" " -----------" " ------"]}
  676.                 1    {   puts [format "%-15s %-10s %-20s %-20s %-20s %-50s %-50s %-30s" "#Coupling-Cap" " CCap %" " Agrsr-Count" "Position" " Driver-Ref-Name" " Net" " Driver-Name" " Clocks"]
  677.                          puts [format "%-15s %-10s %-20s %-20s %-20s %-50s %-50s %-30s" "#------------" " ------" " -----------" "--------" " ---------------" " ---" " -----------" " ------"]}
  678.             }
  679.         }
  680.  
  681.         # Process and print report
  682.         foreach_in_collection net $all_nets {
  683.             set net       [get_attribute [get_nets -quiet $net] full_name]
  684.             set driver    [get_attribute [get_pins -quiet -leaf -of_objects [get_net $net] -filter "direction==out"] full_name ]
  685.  
  686.             # Initialise
  687.             set ccap            "x"
  688.             set clocks          "x"
  689.             set ref_driver      "x"
  690.             set aggressor_count "x"
  691.  
  692.             # Filter out the clock nets and get its ccap, driver
  693.             if { [sizeof_collection [get_attribute -quiet [get_pins -quiet $driver] clocks ]] > 0 } {
  694.                 if {$omit_clocks != ""} {
  695.                     set   clocks          [get_attribute [remove_from_collection [get_attribute -quiet [get_pins $driver] clocks] [get_clocks "${omit_clocks}"]] full_name]
  696.                 } else {
  697.                     set   clocks          [get_attribute                         [get_attribute -quiet [get_pins $driver] clocks]                                full_name]
  698.                 }
  699.                 set ccap            [get_attribute -quiet [get_nets $net] total_effective_coupling_capacitance]
  700.                 set ba_ccap         [get_attribute -quiet [get_nets $net] ba_capacitance_max]
  701.                 set ref_driver      [get_attribute -quiet [get_cells -of_objects [get_pins $driver]] ref_name]
  702.                 set agrsr_count     [get_attribute -quiet [get_nets $net] number_of_effective_aggressors]
  703.  
  704.                 if { $include_position == 1 } {
  705.                     set all_leaves      [sizeof_collection [get_attribute -quiet [get_clocks -quiet $clocks] clock_network_pins]]
  706.                     set current_leaves  [sizeof_collection [all_fanout -from $driver -endpoints_only -flat -trace_arcs all]]
  707.                 }
  708.  
  709.                 if { $ccap > $ccap_threshold } {
  710.                     lappend ccap_list        [get_attribute -quiet [get_nets $net] total_effective_coupling_capacitance]
  711.                     lappend a_net($ccap)        $net
  712.                     set a_ba_ccap_pct($net) [expr round(100*$ccap/$ba_ccap)]
  713.                     set a_driver($net)      $driver
  714.                     set a_clocks($net)      $clocks
  715.                     set a_ref_driver($net)  $ref_driver
  716.                     set a_agrsr_count($net) $agrsr_count
  717.  
  718.                     if { $include_position == 1 } {
  719.                         if {$all_leaves > 0 && $current_leaves > 0} {
  720.                             set   a_position($net)    [expr round(10*$current_leaves/$all_leaves)]
  721.                             if { $a_position($net) > 10 } { ; # Due to complex clocking sometimes this number exeeds 10, which is in-correct.
  722.                                 set a_position($net)    not_known_CODE1
  723.                             }
  724.                         } else {
  725.                             set   a_position($net)    not_known_CODE2 ; # Avoid erroring out when no leaves are found.
  726.                         }
  727.                     }
  728.                 }
  729.             }
  730.         }
  731.  
  732.         # Sort the ccap values in decending order
  733.         set ccap_list [lsort -unique -decreasing $ccap_list]
  734.  
  735.         # For each ccap print ccap, net, driver, clocks
  736.         foreach c $ccap_list {
  737.             foreach n $a_net($c) {  ; # There can be multiple nets with same ccap
  738.                 if { $output_style == "csv" } {
  739.                     switch $include_position {
  740.                         0  {puts [format "$c,$a_ba_ccap_pct($n),$a_agrsr_count($n),$a_ref_driver($n),$n,$a_driver($n),$a_clocks($n)"]}
  741.                         1  {puts [format "$c,$a_ba_ccap_pct($n),$a_agrsr_count($n),$a_position($n),$a_ref_driver($n),$n,$a_driver($n),$a_clocks($n)"]}
  742.                     }
  743.                 } else {
  744.                     switch $include_position {
  745.                         0  {puts [format "%-15s %-10s %-20s %-20s %-50s %-50s %-30s" "$c" " $a_ba_ccap_pct($n)" " $a_agrsr_count($n)" " $a_ref_driver($n)" " $n" " $a_driver($n)" " $a_clocks($n)"]}
  746.                         1  {puts [format "%-15s %-10s %-20s %-20s %-20s %-50s %-50s %-30s" "$c" " $a_ba_ccap_pct($n)" " $a_agrsr_count($n)" " $a_position($n)" " $a_ref_driver($n)" " $n" " $a_driver($n)" " $a_clocks($n)"]}
  747.                     }
  748.                 }
  749.             }
  750.         }
  751.     } else {
  752.         puts "\nRubix-Error: CrossTalk analysis is not enabled. \"set si_enable_analysis true\" before reporting the coupling on clock nets\n"
  753.     }
  754.  
  755.     puts "\n1\n"
  756.  
  757.     set t2        [clock seconds]
  758.     echo          "\n# rbx_report_xtalk_clock_nets RUNTIME: [rbx_get_runtime $t1 $t2] "
  759.  
  760. }
  761.  
  762. #----------------------------------------------------------------------------------------
  763. # Proc to get details of nets reproted in report_si_bottleneck
  764. #----------------------------------------------------------------------------------------
  765.  
  766. proc rbx_report_xtalk_bottlenecks { args } {
  767.  
  768.   # Processes reports of command report_si_bottleneck
  769.  
  770.   global sta_path
  771.  
  772.   #.......................................................
  773.   # Print help and quit
  774.   #.......................................................
  775.   if {[lsearch $args "-help"] > -1} {
  776.     puts "\nrbx_report_xtalk_bottlenecks -si_bottle_neck_rpt_lst <si_bottelnect_report_list> \[-signal_type clock|data|both\]\n"
  777.     return
  778.   }
  779.  
  780.   #.......................................................
  781.   # Arguments Handling
  782.   #.......................................................
  783.  
  784.   # Default Argument Values
  785.   set si_bottle_neck_rpt_lst            ""
  786.   set signal_type               "both"
  787.  
  788.   # Check and get the values of the arguments
  789.   if {[llength $args] != 2 && [llength $args] != 4} {
  790.     puts "\nRubix-Error: Missing or too many options given for rbx_report_xtalk_bottlenecks command.\n"; return
  791.   }
  792.  
  793.   foreach a $args {
  794.     # Check if Wrong option is used
  795.     if {[string match {-*} $a] && $a != "-si_bottle_neck_rpt_lst" && $a != "-signal_type"} {
  796.       puts "\nRubix-Error: Option $a is not valid for rbx_report_xtalk_bottlenecks command.\n"; return
  797.     }
  798.  
  799.     # Get the values of the options
  800.     if {$a == "-si_bottle_neck_rpt_lst"}    { set si_bottle_neck_rpt_lst [rbx_value -si_bottle_neck_rpt_lst $args] }
  801.     if {$a == "-signal_type"}           { set signal_type [rbx_value -signal_type $args] }
  802.   }
  803.  
  804.   # Update Needed: Check for -nosplit
  805.  
  806.   #.......................................................
  807.   # Execute the main procedure
  808.   #.......................................................
  809.  
  810.   global    sh_product_version
  811.  
  812.     set t1            [clock seconds]
  813.  
  814.     set net_lst           ""
  815.     set file_lst          ""
  816.  
  817.     foreach current_rpt $si_bottle_neck_rpt_lst {
  818.  
  819.         set rpt [open "$current_rpt" r]
  820.         set start_reading 0
  821.  
  822.         # Read Each Line for PT Transition Report File
  823.         foreach {line} [split [read $rpt] \n] {
  824.  
  825.             if {$line != 1} {
  826.                 # Remove leading blanks
  827.                 set line [string trim $line]
  828.                 regsub -all { +} $line {;} l
  829.  
  830.                 # Get each word
  831.                 set words [split $l ";"]
  832.  
  833.                 if {[llength $words] != 0} {
  834.                     # Start reading after header
  835.                     if {$start_reading == 1} {
  836.                         set     net              [lindex $words 0]
  837.                         set     cost($net)       [lindex $words 1]
  838.                         lappend cost_lst($net)   [lindex $words 1]
  839.  
  840.                         if {[info exists worst_cost($net)] && $cost($net) != ""} {
  841.                             set     worst_cost($net) [expr $worst_cost($net) + $cost($net)]
  842.                         } else {
  843.                             set     worst_cost($net) $cost($net)
  844.                         }
  845.  
  846.                         if {[lsearch $net_lst $net] < 0} {
  847.                             lappend net_lst    [lindex $words 0]
  848.                         }
  849.  
  850.                         if {[info exists scen_count($net)]} {
  851.                             incr scen_count($net)
  852.                         } else {
  853.                             set  scen_count($net) 1
  854.                         }
  855.  
  856.                     }
  857.                 }
  858.  
  859.                 if {[string match "------------------------*" [lindex $words 0]]} {
  860.                     set start_reading 1
  861.                 }
  862.  
  863.             }
  864.         }
  865.     }
  866.  
  867.     foreach n $net_lst {
  868.         lappend     worst_cost_lst  $worst_cost($n)
  869.         set         wc        $worst_cost($n)
  870.  
  871.         if {[sizeof_collection [get_attribute -quiet [get_nets $n] clocks]] > 0} {
  872.             set is_clk_net($n)    "true"
  873.         } else {
  874.             set is_clk_net($n)    "false"
  875.         }
  876.  
  877.         if {[info exists nets_of_wc($worst_cost($n))]} {
  878.             lappend nets_of_wc($wc)                     $n
  879.             lappend costs_of_wc($worst_cost($n))        $cost_lst($n)
  880.             lappend scens_count_of_wc($worst_cost($n))  $scen_count($n)
  881.         } else {
  882.             set nets_of_wc($wc)                     $n
  883.             set costs_of_wc($worst_cost($n))        $cost_lst($n)
  884.             set scens_count_of_wc($worst_cost($n))  $scen_count($n)
  885.         }
  886.  
  887.     }
  888.  
  889.     foreach f $si_bottle_neck_rpt_lst {
  890.         set file_lst    "$file_lst\n#                                $f"
  891.     }
  892.  
  893.     # For printing one file per line
  894.     foreach clib $si_bottle_neck_rpt_lst {
  895.       lappend si_bottle_neck_rpt_lst_stacked "\n\t\t$clib"
  896.     }
  897.     set si_bottle_neck_rpt_lst_stacked [string map {\{ "" \} ""} $si_bottle_neck_rpt_lst_stacked]
  898.  
  899.     puts [format "%-20s" "*********************************************************************************************"]
  900.     puts [format "%-10s %-15s" " Rubix Custom Report" "\n"]
  901.     puts [format "%-10s %-15s" " Report" ": rbx_report_xtalk_bottlenecks"]
  902.     puts [format "%-10s %-15s" " "       " -si_bottle_neck_rpt_lst $si_bottle_neck_rpt_lst_stacked"]
  903.     puts [format "%-10s %-15s" " "       " -signal_type $signal_type"]
  904.     puts [format "%-10s %-15s" " Design" ": [get_attribute [get_design] full_name]"]
  905.     puts [format "%-10s %-15s" " Version" ": $sh_product_version"]
  906.     puts [format "%-10s %-15s" " Date" ": [date]"]
  907.     puts [format "%-10s" "*********************************************************************************************"]
  908.     puts "\n"
  909.  
  910.     puts [format "%-11s %-18s %-12s %-15s %-20s" "# Is-Clock" "No of occurance" "Worst Cost" "Total Costs" "Net"]
  911.     puts [format "%-11s %-18s %-12s %-15s %-20s" "# --------" "---------------" "----------" "-----------" "---"]
  912.  
  913.     foreach wc [lsort -decreasing $worst_cost_lst] {
  914.         foreach n $nets_of_wc($wc) {
  915.             if {$signal_type == "clock" && $is_clk_net($n) == "true"} {
  916.                 puts [format "%-11s %-18s %-12s %-15s %-20s" "  $is_clk_net($n)" "$scen_count($n)" "[rbx_get_biggest $cost_lst($n)]" "[rbx_ladd $cost_lst($n)]" "$n"]
  917.             } elseif {$signal_type == "data" && $is_clk_net($n) == "false"} {
  918.                 puts [format "%-11s %-18s %-12s %-15s %-20s" "  $is_clk_net($n)" "$scen_count($n)" "[rbx_get_biggest $cost_lst($n)]" "[rbx_ladd $cost_lst($n)]" "$n"]
  919.             } elseif {$signal_type == "both"} {
  920.                 puts [format "%-11s %-18s %-12s %-15s %-20s" "  $is_clk_net($n)" "$scen_count($n)" "[rbx_get_biggest $cost_lst($n)]" "[rbx_ladd $cost_lst($n)]" "$n"]
  921.             }
  922.         }
  923.     }
  924.  
  925.     puts "\n1"
  926.     set t2  [clock seconds]
  927.     puts    "\n# rbx_report_xtalk_bottlenecks RUNTIME: [rbx_get_runtime $t1 $t2] \n"
  928. }
  929.  
  930. #----------------------------------------------------------------------------------------
  931. # Proc to get the details of pins reported by report_noise command
  932. #----------------------------------------------------------------------------------------
  933.  
  934. proc rbx_get_noise_pin_details { args } {
  935.  
  936.   #.......................................................
  937.   # Print help and quit
  938.   #.......................................................
  939.   if {[lsearch $args "-help"] > -1} {
  940.     puts "rbx_get_noise_pin_details -noise_report <noise_report> -noise_region <all | above_low | below_high | below_low | above_high>"
  941.     return
  942.   }
  943.  
  944.   #.......................................................
  945.   # Arguments Handling
  946.   #.......................................................
  947.  
  948.   # Default Argument Values
  949.   set noise_report          ""
  950.   set noise_region          "all"
  951.  
  952.   # Check and get the values of the arguments
  953.   if {[llength $args] < 2 || [llength $args] > 4} {
  954.     puts "\nRubix-Error: Missing or too many options for rbx_get_noise_pin_details command.\n"; return
  955.   }
  956.  
  957.   foreach a $args {
  958.     # Check if Wrong option is used
  959.     if {[string match "-*" $a] && $a != "-noise_report" && [string match "-*" $a] && $a != "-noise_region"} {
  960.       puts "\nRubix-Error: Option $a is not valid for rbx_get_noise_pin_details command.\n"; return
  961.     }
  962.  
  963.     # Get the values of the options
  964.     if {$a == "-noise_report"}      { set noise_report          [rbx_value -noise_report $args] }
  965.     if {$a == "-noise_region"}      { set noise_region          [rbx_value -noise_region $args] }
  966.   }
  967.  
  968.   #.......................................................
  969.   # Execute the main procedure
  970.   #.......................................................
  971.  
  972.   global  sh_product_version
  973.  
  974.   global  glitch_pin_list
  975.   global  glitch_net_list
  976.   global  aggressors
  977.   set     glitch_pin_list     ""
  978.   set     glitch_net_list     ""
  979.  
  980.   puts [format "%-20s" "*********************************************************************************************"]
  981.   puts [format "%-10s %-15s" " Rubix Custom Report" "\n"]
  982.   puts [format "%-10s %-15s" " Report" ": rbx_get_noise_pin_details"]
  983.   puts [format "%-10s %-15s" " "       " -noise_report $noise_report"]
  984.   puts [format "%-10s %-15s" " "       " -noise_region $noise_region"]
  985.   puts [format "%-10s %-15s" " Design" ": [get_attribute [get_design] full_name]"]
  986.   puts [format "%-10s %-15s" " Version" ": $sh_product_version"]
  987.   puts [format "%-10s %-15s" " Date" ": [date]"]
  988.   puts [format "%-10s" "*********************************************************************************************"]
  989.  
  990.   puts [format "%-10s %-10s %-75s %-75s %-75s %-75s %-75s %-75s" "# Slack_S" "Slack_H" "Is Clock" "Pin" "Net" "Driver" "Aggressors Count" "{ Aggressors }"]
  991.   puts "#-----------------------------------------------------------------------------------------------------------------------------------------------------------"
  992.  
  993.   set rpt             [open "$noise_report" r]
  994.   set start_reading   0
  995.  
  996.   foreach {line} [split [read $rpt] \n] {
  997.  
  998.       if {$line != 1} {
  999.           # Remove leading blanks
  1000.           set line [string trim $line]
  1001.           regsub -all { +} $line {;} l
  1002.  
  1003.           # Get each word
  1004.           set words [split $l ";"]
  1005.  
  1006.           # Get Noise type to analyze
  1007.       if {$noise_region == "all"} {
  1008.             if {[lindex $words 1] == "above_low" || [lindex $words 1] == "below_low" || [lindex $words 1] == "above_high" || [lindex $words 1] == "below_high"} {
  1009.                 set start_reading 1
  1010.             } elseif {[llength $words] == 0} {
  1011.                 set start_reading 0
  1012.             }
  1013.       } else {
  1014.             if {[lindex $words 1] == "$noise_region"} {
  1015.                 set start_reading 1
  1016.             } elseif {[llength $words] == 0} {
  1017.                 set start_reading 0
  1018.             }
  1019.       }
  1020.  
  1021.           # Start Reading
  1022.           if {$start_reading == 1} {
  1023.               if {[llength $words] == 5} {
  1024.                   if {[lsearch $glitch_pin_list [lindex $words 0]] < 0} {
  1025.                       set pin                 [lindex $words 0]
  1026.                       set net($pin)           [get_object_name [get_nets -of_objects $pin]]
  1027.                       set driver($pin)        [rbx_get_driver $pin]
  1028.                       set aggressors($pin)    [get_attr [get_nets [get_object_name [get_nets -of_objects $pin]]] aggressors]
  1029.                       set slk_s($pin)         [get_attr [get_timing_path -through $pin -delay max] slack]
  1030.                       set slk_h($pin)         [get_attr [get_timing_path -through $pin -delay min] slack]
  1031.  
  1032.                       lappend glitch_pin_list $pin
  1033.                       lappend glitch_net_list [get_object_name [get_nets -of_objects $pin]]
  1034.  
  1035.               # Determine if pin is clock or data
  1036.                       if {[sizeof_collection [get_attribute -quiet [get_pins $pin] clocks]] < 1} {
  1037.                         set sig_type($pin)   "No"
  1038.                       } else {
  1039.                         set sig_type($pin)   "Yes"
  1040.                       }
  1041.  
  1042.  
  1043.                   } else {
  1044.                       set pin                 [lindex $words 0]
  1045.                       set aggressors($pin)    [lsort -unique "$aggressors($pin) [get_attr [get_nets [get_nets -of_objects $pin]] aggressors]"]
  1046.                       if {$slk_s($pin) > [get_attr [get_timing_path -through $pin -delay max] slack]} {
  1047.                           set slk_s($pin)     [get_attr [get_timing_path -through $pin -delay max] slack]
  1048.                       }
  1049.                       if {$slk_h($pin) > [get_attr [get_timing_path -through $pin -delay min] slack]} {
  1050.                           set slk_h($pin)     [get_attr [get_timing_path -through $pin -delay min] slack]
  1051.                       }
  1052.                   }
  1053.               }
  1054.           }
  1055.       }
  1056.   }
  1057.  
  1058.   foreach p $glitch_pin_list {
  1059.       if {$slk_s($p) == ""} { set slk_s($p) "-"}
  1060.       if {$slk_h($p) == ""} { set slk_h($p) "-"}
  1061.       puts [format "%-10s %-10s %-75s %-75s %-75s %-75s %-75s %-75s" "$slk_s($p)" "$slk_h($p)" "$sig_type($p)" "$p" "$net($p)" "$driver($p)" "[llength $aggressors($p)]" "{ $aggressors($p) }"]
  1062.   }
  1063.  
  1064.   puts "\n1\n"
  1065.   close $rpt
  1066. }
  1067.  
  1068. #----------------------------------------------------------------------------------------
  1069. # Get nets with SI delay from the PT reports
  1070. #----------------------------------------------------------------------------------------
  1071. proc rbx_get_si_violators_from_pt_reports { args } {
  1072.  
  1073.   #.......................................................
  1074.   # Print help and quit
  1075.   #.......................................................
  1076.   if {[lsearch $args "-help"] > -1} {
  1077.     puts "\n    rbx_get_si_violators_from_pt_reports
  1078.         -pt_report_list <timing_report_list>
  1079.         \[-xtalk_delay_greater_than greater_delta_limit\]
  1080.         \[-pins | -nets\]
  1081.         \[-all | -violating\] \n"
  1082.     return
  1083.   }
  1084.  
  1085.   #.......................................................
  1086.   # Arguments Handling
  1087.   #.......................................................
  1088.  
  1089.   # Default Argument Values
  1090.   set pt_report_list                ""
  1091.   set xtalk_delay_greater_than          0
  1092.   set pins_or_nets              pins
  1093.   set all_or_violating              all
  1094.  
  1095.   # Check and get the values of the arguments
  1096.   if {[llength $args] < 2 || [llength $args] > 6} {
  1097.     puts "\nRubix-Error: Missing or too many options given for rbx_get_si_violators_from_pt_reports command.\n"; return
  1098.   }
  1099.  
  1100.   # Check if two or more mutually exclusive options are used
  1101.   if {[lsearch $args -nets] > -1 && [lsearch $args -pins] > -1} {
  1102.       puts "\nRubix-Error: Options -nets and -pins are mutually exclusive.\n"; return
  1103.   }
  1104.  
  1105.   if {[lsearch $args -all] > -1 && [lsearch $args -violating] > -1} {
  1106.       puts "\nRubix-Error: Options -all and -violating are mutually exclusive.\n"; return
  1107.   }
  1108.  
  1109.   foreach a $args {
  1110.     # Check if Wrong option is used
  1111.     if {[string match {-[A-Z|a-y]*} $a] && $a != "-pt_report_list" && $a != "-xtalk_delay_greater_than" \
  1112.                                     && $a != "-pins" && $a != "-nets" && $a != "-all" && $a != "-violating"} {
  1113.       puts "\nRubix-Error: Option $a is not valid for rbx_get_si_violators_from_pt_reports command.\n"; return
  1114.     }
  1115.  
  1116.     # Get the values of the options
  1117.     if {$a == "-pt_report_list"}        { set pt_report_list [rbx_value -pt_report_list $args] }
  1118.     if {$a == "-xtalk_delay_greater_than"}  { set xtalk_delay_greater_than [rbx_value -xtalk_delay_greater_than $args] }
  1119.     if {$a == "-pins"}              { set pins_or_nets pins }
  1120.     if {$a == "-nets"}              { set pins_or_nets nets }
  1121.     if {$a == "-all"}               { set all_or_violating all }
  1122.     if {$a == "-violating"}         { set all_or_violating violating }
  1123.   }
  1124.  
  1125.   # Update Needed: Check for -nosplit
  1126.  
  1127.   #.......................................................
  1128.   # Execute the main procedure
  1129.   #.......................................................
  1130.  
  1131.   # Suppress messages
  1132.   suppress_message "ATTR-3"
  1133.  
  1134.   global            sh_product_version
  1135.   global all_xtalk_nets_to_print
  1136.  
  1137.   # Initialize
  1138.   set all_xtalk_nets_to_print ""
  1139.   set all_xtalk_pins_to_print ""
  1140.  
  1141.   set violating_xtalk_nets_to_print ""
  1142.   set violating_xtalk_pins_to_print ""
  1143.   set violating_xtalk_nets          ""
  1144.   set violating_xtalk_pins          ""
  1145.  
  1146.   # For printing one lib per line
  1147.   foreach ptrep $pt_report_list {
  1148.     lappend pt_report_list_stacked "\n\t\t$ptrep"
  1149.   }
  1150.   set pt_report_list_stacked [string map {\{ "" \} ""} $pt_report_list_stacked]
  1151.  
  1152.   puts [format "%-20s" "*********************************************************************************************"]
  1153.   puts [format "%-10s %-15s" " Rubix Custom Report" "\n"]
  1154.   puts [format "%-10s %-15s" " Report" ": rbx_get_si_violators_from_pt_reports"]
  1155.   puts [format "%-10s %-15s" " "       " -pt_report_list $pt_report_list_stacked"]
  1156.   puts [format "%-10s %-15s" " "       " -xtalk_delay_greater_than $xtalk_delay_greater_than"]
  1157.   puts [format "%-10s %-15s" " "       " -$pins_or_nets"]
  1158.   puts [format "%-10s %-15s" " "       " -$all_or_violating"]
  1159.   puts [format "%-10s %-15s" " Design" ": [get_attribute [get_design] full_name]"]
  1160.   puts [format "%-10s %-15s" " Version" ": $sh_product_version"]
  1161.   puts [format "%-10s %-15s" " Date" ": [date]"]
  1162.   puts [format "%-10s" "*********************************************************************************************"]
  1163.   puts "\n"
  1164.  
  1165.     # Open Files for Reading/Writing
  1166.     foreach current_rpt $pt_report_list {
  1167.  
  1168.         set rpt         [open "$current_rpt"    r]
  1169.  
  1170.         # Read Each Line from PT report
  1171.         foreach {line} [split [read $rpt] \n] {
  1172.  
  1173.             # Remove leading blanks
  1174.             set line [string trim $line]
  1175.  
  1176.             if {[string match "*NAME OVERFLOW*" $line]} { ;   # Lines with this string will be evaluated leading to unrealistic number of nets
  1177.                 set line "dont_evaluate_line"
  1178.             } elseif {[string match "*:*" $line]} {
  1179.         set line "dont_evaluate_line"
  1180.             } else {
  1181.                 regsub -all { +} $line {;} l
  1182.             }
  1183.  
  1184.             # Get each word
  1185.             set words [split $l ";"]
  1186.  
  1187.             # Detect the net
  1188.             if {[lindex $words 1] == "(net)"} {
  1189.                 set net [lindex $words 0]
  1190.             } else {
  1191.                 set net ""
  1192.             }
  1193.  
  1194.             # Stop processing if the reports does not contain delta-delay
  1195.             if {([lindex $words 0] == "Point" && [lsearch $words Delta] < 0) } {
  1196.           puts "\nRubix-Error: Following timing reports does not contain delta delay. Report timing with -delta option."
  1197.           puts "               $current_rpt\n"
  1198.           return
  1199.         }
  1200.  
  1201.             # Stop processing if the reports contains more than required details
  1202.             if {([lindex $words 0] == "Point" && [llength $words] > 5) } {
  1203.           puts "\n"
  1204.           puts "Rubix-Error: Following timing reports contains more details than expected."
  1205.           puts "               Report timing with only -delta/-nets/-nosplit options and without any option like -cap, -tran that add more columns to the report."
  1206.           puts "               $current_rpt\n"
  1207.           return
  1208.         }
  1209.  
  1210.             # Detect the line with Detla delay greater than the given threshold
  1211.             if {([llength $words] == 7) && ([lindex $words 2] > $xtalk_delay_greater_than || [lindex $words 2] < -$xtalk_delay_greater_than)} {
  1212.                 lappend all_xtalk_nets_to_print     $net_on_previous_line
  1213.                 lappend all_xtalk_pins_to_print     [lindex $words 0]
  1214.         set delta_del($net_on_previous_line)    [lindex $words 2]
  1215.         set delta_del([lindex $words 0])    [lindex $words 2]
  1216.  
  1217.         # Check if clock or data
  1218.         if {[sizeof_collection [get_attribute -quiet [get_nets $net_on_previous_line] clocks]] < 1} {
  1219.           set sig_type($net_on_previous_line)   "data"             
  1220.         } else {
  1221.           set sig_type($net_on_previous_line)   "clock"            
  1222.         }
  1223.  
  1224.         # Check if clock or data
  1225.         if {[sizeof_collection [get_attribute -quiet [get_pins [lindex $words 0]] clocks]] < 1} {
  1226.           set sig_type([lindex $words 0])   "data"             
  1227.         } else {
  1228.           set sig_type([lindex $words 0])   "clock"            
  1229.         }
  1230.  
  1231.                 lappend violating_xtalk_nets        $net_on_previous_line
  1232.                 lappend violating_xtalk_pins        [lindex $words 0]
  1233.             }
  1234.  
  1235.             # Detect the line with slack and check if it is met or violating and decide wheather to print the nets/pins or not
  1236.             if {[lindex $words 0] == "slack" && [lindex $words 1] == "(VIOLATED)"} {
  1237.                 set violating_xtalk_nets_to_print [concat $violating_xtalk_nets_to_print $violating_xtalk_nets]
  1238.                 set violating_xtalk_pins_to_print [concat $violating_xtalk_pins_to_print $violating_xtalk_pins]
  1239.  
  1240.                 set violating_xtalk_nets ""
  1241.                 set violating_xtalk_pins ""
  1242.             } elseif {[lindex $words 0] == "slack" && [lindex $words 1] == "(MET)"} {
  1243.                 set violating_xtalk_nets ""
  1244.                 set violating_xtalk_pins ""
  1245.             }
  1246.  
  1247.             set net_on_previous_line $net
  1248.         }
  1249.         close $rpt
  1250.     }
  1251.  
  1252.     # Decide to print nets from all paths or just violating paths
  1253.     switch $all_or_violating {
  1254.         all     {set nets_to_print $all_xtalk_nets_to_print;       set pins_to_print $all_xtalk_pins_to_print}
  1255.         violating   {set nets_to_print $violating_xtalk_nets_to_print; set pins_to_print $violating_xtalk_pins_to_print}
  1256.     }
  1257.  
  1258.     # Print the nets with xtalk
  1259.     if {$pins_or_nets == "nets"} {
  1260.         puts ""
  1261.         puts "Total number of nets with crosstalk more than +-${xtalk_delay_greater_than}ns = [llength [lsort -unique $nets_to_print]]"
  1262.         puts ""
  1263.         puts [format  "%-12s %-15s %-12s" "Delta Delay" "Signal Type" "Net"]
  1264.         puts [format  "%-12s %-15s %-12s" "-----------" "-----------" "---"]
  1265.         foreach n [lsort -unique $nets_to_print] {
  1266.           puts [format  "%-12s %-15s %-12s" "$delta_del($n)" "$sig_type($n)" "$n"]
  1267.         }
  1268.     } elseif {$pins_or_nets == "pins"} {
  1269.         puts ""
  1270.         puts "Total number of pins with crosstalk more than +-${xtalk_delay_greater_than}ns = [llength [lsort -unique $pins_to_print]]"
  1271.         puts ""
  1272.         puts [format  "%-12s %-15s %-12s" "Delta Delay" "Signal Type" "Pin"]
  1273.         puts [format  "%-12s %-15s %-12s" "-----------" "-----------" "---"]
  1274.         foreach p [lsort -unique $pins_to_print] {
  1275.           puts [format  "%-12s %-15s %-12s" "$delta_del($p)" "$sig_type($p)" "$p"]
  1276.         }
  1277.     }
  1278.  
  1279.   puts "\n1\n"
  1280.  
  1281.   # Un-Suppress messages
  1282.   unsuppress_message "ATTR-3"
  1283.  
  1284. }
  1285.  
  1286. #----------------------------------------------------------------------------------------
  1287. # Get Common Glitch Nets
  1288. #----------------------------------------------------------------------------------------
  1289.  
  1290. proc rbx_get_glitch_nets { log_file_list } {
  1291.  
  1292.     global  glitch_pin_list
  1293.     global  glitch_net_list
  1294.     global  aggressors
  1295.     set     glitch_pin_list ""
  1296.     set     glitch_net_list ""
  1297.     set     max_occurance   [expr 2*[llength $log_file_list]]
  1298.  
  1299.     puts [format "%-12s %-18s %-10s %-10s %-75s %-75s %-75s %-75s" "# Occurance"  "Aggressors_count" "WNS_S" "WNS_H" "Pin" "Net" "Driver" "Aggressors"]
  1300.     puts "#-----------------------------------------------------------------------------------------------------------------------------------------------------------"
  1301.  
  1302.     foreach log_file $log_file_list {
  1303.  
  1304.         set log             [open "$log_file" r]
  1305.         set start_reading   0
  1306.  
  1307.         foreach {line} [split [read $log] \n] {
  1308.  
  1309.             # Remove leading blanks
  1310.             set line [string trim $line]
  1311.             regsub -all { +} $line {;} l
  1312.  
  1313.             # Get each word
  1314.             set words [split $l ";"]
  1315.  
  1316.             # Get each word
  1317.             if {[lindex $words 1] != "Slack_S" && [llength $words] >= 6} {
  1318.                 if {[lsearch $glitch_pin_list [lindex $words 2]] < 0} {
  1319.                     set pin                     [lindex $words 2]
  1320.                     set net($pin)               [lindex $words 3]
  1321.                     set driver($pin)            [lindex $words 4]
  1322.                     set occurance($pin)         1
  1323.                     set aggressors($pin)        [lreplace $words 0 4]
  1324.                     set aggressors_count($pin)  [llength $aggressors($pin)]
  1325.                     set wns_s($pin)             [lindex $words 0]
  1326.                     set wns_h($pin)             [lindex $words 1]
  1327.  
  1328.                     lappend glitch_pin_list     $pin
  1329.                     lappend glitch_net_list     [get_object_name [get_nets -of_objects $pin]]
  1330.                 } else {
  1331.                     set pin [lindex $words 2]
  1332.                     incr occurance($pin)
  1333.                     set aggressors($pin)    [lsort -unique "$aggressors($pin) [lreplace $words 0 4]"]
  1334.                     if {$aggressors_count($pin) < [llength $aggressors($pin)]} {
  1335.                         set aggressors_count($pin) [llength $aggressors($pin)]
  1336.                     }
  1337.                     if {$wns_s($pin) > [lindex $words 0]} { set wns_s($pin) [lindex $words 0]}
  1338.                     if {$wns_h($pin) > [lindex $words 1]} { set wns_h($pin) [lindex $words 1]}
  1339.                 }
  1340.             }
  1341.         }
  1342.         close $log
  1343.     }
  1344.  
  1345.     for {set i $max_occurance} {$i >= 1} {incr i -1} {
  1346.         foreach p $glitch_pin_list {
  1347.             if {$i == $occurance($p)} {
  1348.                 if {$wns_s($p) != "-" } { set wns_s($p) [format  "%.3f" "$wns_s($p)"] }
  1349.                 if {$wns_h($p) != "-" } { set wns_h($p) [format  "%.3f" "$wns_h($p)"] }
  1350.                 puts [format "%-12s %-18s %-10s %-10s %-75s %-75s %-75s %-75s" "$occurance($p)"  "$aggressors_count($p)" "$wns_s($p)" "$wns_h($p)" "$p" "$net($p)" "$driver($p)" "$aggressors($p)"]
  1351.             }
  1352.         }
  1353.     }
  1354.     puts "\n---EOF---\n"
  1355. }
  1356.  
  1357.  
  1358. #----------------------------------------------------------------------------------------
  1359. # Triage RC-011
  1360. #----------------------------------------------------------------------------------------
  1361. proc rbx_analyze_rc011 { args } {
  1362.  
  1363.   #.......................................................
  1364.   # Print help and quit
  1365.   #.......................................................
  1366.   if {[lsearch $args "-help"] > -1} {
  1367.     puts "\nrbx_analyze_rc011 -pt_log <primetime_log_file_with_rc011> -check_type \[setup | hold\] -rc011_slack_lesser_than \n"
  1368.     return
  1369.   }
  1370.  
  1371.   #.......................................................
  1372.   # Arguments Handling
  1373.   #.......................................................
  1374.  
  1375.   # Default Argument Values
  1376.   set pt_log                    ""
  1377.   set check_type                setup
  1378.   set rc011_slack_lesser_than           0
  1379.   #set output_style             table
  1380.  
  1381.   # Check and get the values of the arguments
  1382.   if {[llength $args] != 2 && [llength $args] != 4 && [llength $args] != 6} {
  1383.     puts "\nRubix-Error: Missing or too many options given for rbx_analyze_rc011 command.\n"; return
  1384.   }
  1385.  
  1386.   foreach a $args {
  1387.     # Check if Wrong option is used
  1388.     if {[string match {-[A-Z|a-y]*} $a] && $a != "-pt_log" && $a != "-check_type" && $a != "-rc011_slack_lesser_than"} {
  1389.       puts "\nRubix-Error: Option $a is not valid for rbx_analyze_rc011 command.\n"; return
  1390.     }
  1391.  
  1392.     # Get the values of the options
  1393.     if {$a == "-pt_log"}            { set pt_log [rbx_value -pt_log $args] }
  1394.     if {$a == "-check_type"}            { set check_type [rbx_value -check_type $args] }
  1395.     if {$a == "-rc011_slack_lesser_than"}   { set rc011_slack_lesser_than [rbx_value -rc011_slack_lesser_than $args] }
  1396.   }
  1397.  
  1398.   #.......................................................
  1399.   # Execute the main procedure
  1400.   #.......................................................
  1401.  
  1402.   global    sh_product_version
  1403.   global    sh_continue_on_error
  1404.  
  1405.   set t1    [clock seconds]
  1406.  
  1407.   puts [format "%-20s" "*********************************************************************************************"]
  1408.   puts [format "%-10s %-15s" " Rubix Custom Report" "\n"]
  1409.   puts [format "%-10s %-15s" " Report" ": rbx_analyze_rc011"]
  1410.   puts [format "%-10s %-15s" " "       " -pt_log $pt_log"]
  1411.   puts [format "%-10s %-15s" " "       " -check_type $check_type"]
  1412.   puts [format "%-10s %-15s" " "       " -rc011_slack_lesser_than $rc011_slack_lesser_than"]
  1413.   puts [format "%-10s %-15s" " Design" ": [get_attribute [get_design] full_name]"]
  1414.   puts [format "%-10s %-15s" " Version" ": $sh_product_version"]
  1415.   puts [format "%-10s %-15s" " Date" ": [date]"]
  1416.   puts [format "%-10s" "*********************************************************************************************"]
  1417.   puts [format "%-15s" "Type:"]
  1418.   puts [format "%-15s" "    OL - Over Table Limit"]
  1419.   puts [format "%-15s" "    UL - Under Table Limit"]
  1420.   puts "\n"
  1421.  
  1422.   suppress_message              UITE-416
  1423.   set top_sh_continue_on_error          $sh_continue_on_error
  1424.   set sh_continue_on_error          true
  1425.  
  1426.   set log                   [open "$pt_log" r]
  1427.  
  1428.   set already_tested_arcs_max           ""
  1429.   set already_tested_arcs_min           ""
  1430.   set rc011_max_tran_cap_starts         0
  1431.   set rc011_min_tran_cap_starts         0
  1432.   set endpoints_max_all             ""
  1433.   set endpoints_min_all             ""
  1434.   set rc011_clock_pins              ""
  1435.  
  1436.   puts [format  "%-6s %-12s %-20s %-15s" "Type" "RC011-Slack" "Path-${check_type}-Slack" "Endpoint"]
  1437.   puts [format  "%-6s %-12s %-20s %-15s" "----" "-----------" "----------------" "--------"]
  1438.   puts [format  "%-6s %-12s %-16s %-15s %-15s %-6s" "" "" "" "" "Stage Delay" "RC011-Data-Pins"]
  1439.   puts [format  "%-6s %-12s %-16s %-15s %-15s %-6s" "" "" "" "" "-----------" "---------------"]
  1440.  
  1441.  
  1442.   foreach {line} [split [read $log] \n] {
  1443.  
  1444.     if {$line != 1} {
  1445.       # Remove leading blanks
  1446.       set line [string trim $line]
  1447.       regsub -all { +} $line {;} l
  1448.  
  1449.       # Get each word
  1450.       set words [split $l ";"]
  1451.  
  1452.       #.......................................................
  1453.       # Detect the start of RC-011 max transition/Capacitance messages and Process
  1454.       #.......................................................
  1455.       if {[string match "Warning: An extrapolation *uses the last library index*" $line]} {
  1456.         set rc011_max_tran_cap_starts  1
  1457.         set rc011_max_tran_cap_line_no 0
  1458.       }
  1459.  
  1460.       if {$rc011_max_tran_cap_starts == 1} {
  1461.  
  1462.         incr rc011_max_tran_cap_line_no
  1463.  
  1464.         # Get extrapolation %
  1465.         if {$rc011_max_tran_cap_line_no == 1} {
  1466.           set extrapolation_pct [lindex $words 23]
  1467.           regsub -all {%} $extrapolation_pct {} extrapolation_pct
  1468.         }
  1469.  
  1470.         # Get Instance, from Pin and to Pin
  1471.         if {$rc011_max_tran_cap_line_no == 2} {
  1472.           regsub -all {.*-->}     [lindex $words 6] {} to_pin
  1473.  
  1474.           regsub -all {/.-->.*}   [lindex $words 6] {} instance
  1475.           regsub -all {/..-->.*}  $instance     {} instance
  1476.           regsub -all {/...-->.*} $instance     {} instance
  1477.  
  1478.           regsub -all {\-\->.*}   [lindex $words 6] {} from_pin_fullname
  1479.  
  1480.         }
  1481.  
  1482.         # Detect the end of RC-011 message
  1483.         if {$rc011_max_tran_cap_line_no == 3} {
  1484.  
  1485.           # Mark the end of RC-011 message
  1486.           set rc011_max_tran_cap_starts     0
  1487.  
  1488.           # Get the slew on pin
  1489.           regsub -all {.*/}  [lindex $words 3] {} actual_slew
  1490.           regsub -all {,}    $actual_slew      {} actual_slew
  1491.  
  1492.           # Get the lib slew
  1493.           regsub -all {\]}   [lindex $words 8] {} lib_slew
  1494.  
  1495.           # Process the first appearing RC-011 and skip the rest
  1496.           if {[lsearch $already_tested_arcs_max "${from_pin_fullname}$to_pin"] < 0} {
  1497.         set fp          $from_pin_fullname
  1498.         set tp          $to_pin
  1499.             lappend already_tested_arcs_max "${fp}$tp"
  1500.  
  1501.  
  1502.         if {[sizeof_collection [get_attribute -quiet [get_pins $from_pin_fullname] clocks]] < 1} {
  1503.               # Process setup and hold timing differently
  1504.               if {$check_type == "setup"} {
  1505.                 set delay_type      max
  1506.                 set delay_index     0
  1507.               } elseif {$check_type == "hold"} {
  1508.                 set delay_type      min
  1509.                 set delay_index     end
  1510.               }
  1511.  
  1512.           # Delay of the affected ARC
  1513.           set stage_del($fp)        [lindex [lsort -decreasing [get_attribute [get_timing_arcs -from $fp -to $instance/$tp] delay_${delay_type}_rise]] $delay_index]
  1514.               set stage_del($fp)        [format "%.3f" "$stage_del($fp)"]
  1515.               set lib_tbl_max_del       [expr $stage_del($fp)*((100-$extrapolation_pct)/100.0)] ; # Delay corresponding to maximum slew and load in the .lib
  1516.               if {$lib_slew != "" && $actual_slew != ""} {
  1517.                 set slew_excess_ratio   [expr $actual_slew/$lib_slew]
  1518.               }
  1519.               set delay_excess      [expr $lib_tbl_max_del*$slew_excess_ratio]      ; # Delay corresponding to current slew
  1520.  
  1521.  
  1522.               # Get Slack of the timing path through the RC-011 timing arc and stage-delay (= delay of the timing arc affected)
  1523.           set endpoints_max     [get_object_name [all_fanout -endpoints_only -from $instance/$tp]]
  1524.           set endpoints_max_all "$endpoints_max_all $endpoints_max"
  1525.           foreach ep $endpoints_max {
  1526.             set slack($ep)      [get_attribute [get_timing_path -delay $delay_type -through $fp -through $instance/$tp -to $ep] slack]
  1527.                 if {$slack($ep) != ""} {
  1528.                   # Convert the slack to 3 decimal places
  1529.                   set slack($ep)        [format "%.3f" "$slack($ep)"]
  1530.                 }
  1531.                 set slack_reduction [format "%.3f" [expr ($delay_excess - $stage_del($fp))]]
  1532.  
  1533.             # Setup slack reduces if delay of the affected arc is more than 10% of maximum table delay
  1534.                 if {$check_type == "setup"} {
  1535.           if {[info exist rc011_slack_max($ep)]} {
  1536.                 set rc011_slack_max($ep)    [format "%.3f" [expr $rc011_slack_max($ep) - $slack_reduction]]
  1537.               } else {
  1538.                 set rc011_slack_max($ep)    [format "%.3f" [expr $slack($ep) - $slack_reduction]]
  1539.               }
  1540.             }
  1541.  
  1542.             # Hold slack increases if delay of the affected arc is more than 10% of maximum table delay
  1543.                 if {$check_type == "hold"}  {
  1544.           if {[info exist rc011_slack_max($ep)]} {
  1545.                 set rc011_slack_max($ep) [format  "%.3f" [expr $rc011_slack_max($ep) + $slack_reduction]]
  1546.               } else {
  1547.                 set rc011_slack_max($ep) [format  "%.3f" [expr $slack($ep) + $slack_reduction]]
  1548.               }
  1549.             }
  1550.  
  1551.             # Cells Causing RC-011 for a given FF
  1552.             if {[info exist rc011_pins_max($ep)]} {
  1553.                   set rc011_pins_max($ep) "$rc011_pins_max($ep) $fp"
  1554.                 } else {
  1555.                   set rc011_pins_max($ep) "$fp"
  1556.                 }
  1557.           }
  1558.  
  1559.             } else {
  1560.           set rccp          $fp
  1561.           set rc011_clock_pins  "$rc011_clock_pins $fp"
  1562.           if {[info exist rccp_type($rccp)] && $rccp_type($rccp)=="UL"} {
  1563.             set rccp_type($rccp)    "OL, UL"
  1564.           } else {
  1565.             set rccp_type($rccp)    "OL"
  1566.           }
  1567.             }
  1568.           }
  1569.         }
  1570.       }
  1571.  
  1572.  
  1573.       #.......................................................
  1574.       # Detect the start of RC-011 min transition/Capacitance messages
  1575.       #.......................................................
  1576.       if {[string match "Warning: An extrapolation *limited the extrapolation to*" $line]} {
  1577.         set rc011_min_tran_cap_starts   1
  1578.         set rc011_min_tran_cap_line_no  0
  1579.       }
  1580.  
  1581.       if {$rc011_min_tran_cap_starts == 1} {
  1582.  
  1583.         incr rc011_min_tran_cap_line_no
  1584.  
  1585.         # Get extrapolation %
  1586.         if {$rc011_min_tran_cap_line_no == 1} {
  1587.           set extrapolation_pct [lindex $words 19]
  1588.           regsub -all {%} $extrapolation_pct {} extrapolation_pct
  1589.         }
  1590.  
  1591.         # Get Instance, from Pin and to Pin
  1592.         if {$rc011_min_tran_cap_line_no == 2} {
  1593.           regsub -all {.*-->}     [lindex $words 6] {} to_pin
  1594.  
  1595.           regsub -all {/.-->.*}   [lindex $words 6] {} instance
  1596.           regsub -all {/..-->.*}  $instance     {} instance
  1597.           regsub -all {/...-->.*} $instance     {} instance
  1598.  
  1599.           regsub -all {\-\->.*}   [lindex $words 6] {} from_pin_fullname
  1600.  
  1601.         }
  1602.  
  1603.         # Detect the end of RC-011 message
  1604.         if {$rc011_min_tran_cap_line_no == 3} {
  1605.  
  1606.           # Mark the end of RC-011 message
  1607.           set rc011_min_tran_cap_starts     0
  1608.  
  1609.           # Get the slew on pin
  1610.           regsub -all {.*/}  [lindex $words 3] {} actual_slew
  1611.           regsub -all {,}    $actual_slew      {} actual_slew
  1612.  
  1613.           # Get the lib slew
  1614.           regsub -all {.*\[}   [lindex $words 7] {} lib_slew
  1615.           #puts "lib_slew $lib_slew"
  1616.  
  1617.           # Process the first appearing RC-011 and skip the rest
  1618.           if {[lsearch $already_tested_arcs_min "${from_pin_fullname}$to_pin"] < 0} {
  1619.         set fp          $from_pin_fullname
  1620.         set tp          $to_pin
  1621.             lappend already_tested_arcs_min "${fp}$tp"
  1622.  
  1623.         if {[sizeof_collection [get_attribute -quiet [get_pins $from_pin_fullname] clocks]] < 1} {
  1624.               # Process setup and hold timing differently
  1625.               if {$check_type == "setup"} {
  1626.                 set delay_type  max
  1627.                 set delay_index 0
  1628.               } elseif {$check_type == "hold"} {
  1629.                 set delay_type  min
  1630.                 set delay_index end
  1631.               }
  1632.  
  1633.           # Delay of the affected ARC
  1634.               set stage_del($fp)    [lindex [lsort -decreasing [get_attribute [get_timing_arcs -from $fp -to $instance/$tp] delay_${delay_type}_rise]] $delay_index]
  1635.               set stage_del($fp)    [format "%.3f" "$stage_del($fp)"]
  1636.               set lib_tbl_min_del   [expr ($stage_del($fp)*100)/(100-$extrapolation_pct)]   ; # Delay corresponding to minimum slew and load in the .lib
  1637.  
  1638.               if {$lib_slew != "" && $actual_slew != ""} {
  1639.                 set slew_excess_ratio   [expr $actual_slew/$lib_slew]
  1640.               }
  1641.               set delay_excess      [expr $lib_tbl_min_del*$slew_excess_ratio]      ; # Delay corresponding to current slew
  1642.  
  1643.               # Get Slack of the timing path through the RC-011 timing arc and stage-delay (= delay of the timing arc affected)
  1644.           set endpoints_min     [get_object_name [all_fanout -endpoints_only -from $instance/$tp]]
  1645.           set endpoints_min_all "$endpoints_min_all $endpoints_min"
  1646.           foreach ep $endpoints_min {
  1647.             set slack($ep)      [get_attribute [get_timing_path -delay $delay_type -through $fp -through $instance/$tp -to $ep] slack]
  1648.                 if {$slack($ep) != ""} {
  1649.                   # Convert the slack to 3 decimal places
  1650.                   set slack($ep)        [format "%.3f" "$slack($ep)"]
  1651.                 }
  1652.                 set slack_reduction [format "%.3f" [expr ($stage_del($fp) - $delay_excess)]]
  1653.  
  1654.             # Setup slack increases if delay of the affected arc is less than 80% of minimum table delay
  1655.                 if {$check_type == "setup"} {
  1656.           if {[info exist rc011_slack_min($ep)]} {
  1657.                 set rc011_slack_min($ep)    [format "%.3f" [expr $rc011_slack_min($ep) + $slack_reduction]]
  1658.               } else {
  1659.               set rc011_slack_min($ep)  [format "%.3f" [expr $slack($ep) + $slack_reduction]]
  1660.               }
  1661.             }
  1662.  
  1663.             # Hold slack reduces if delay of the affected arc is less than 80% of minimum table delay
  1664.                 if {$check_type == "hold"}  {
  1665.           if {[info exist rc011_slack_min($ep)]} {
  1666.                 set rc011_slack_min($ep) [format  "%.3f" [expr $rc011_slack_min($ep) - $slack_reduction]]
  1667.               } else {
  1668.                 set rc011_slack_min($ep) [format  "%.3f" [expr $slack($ep) - $slack_reduction]]
  1669.               }
  1670.             }
  1671.  
  1672.             # Cells Causing RC-011 for a given FF
  1673.             if {[info exist rc011_pins_min($ep)]} {
  1674.                   set rc011_pins_min($ep)   "$rc011_pins_min($ep) $fp"
  1675.                 } else {
  1676.                   set rc011_pins_min($ep)   "$fp"
  1677.             }
  1678.           }
  1679.  
  1680.             } else {
  1681.           set rccp          $fp
  1682.           set rc011_clock_pins  "$rc011_clock_pins $fp"
  1683.           if {[info exist rccp_type($rccp)] && $rccp_type($rccp)=="OL"} {
  1684.             set rccp_type($rccp)    "OL, UL"
  1685.           } else {
  1686.             set rccp_type($rccp)    "UL"
  1687.           }
  1688.         }
  1689.           }
  1690.         }
  1691.       }
  1692.  
  1693.  
  1694.     }
  1695.   }
  1696.  
  1697.   close $log
  1698.  
  1699.   foreach ep [lsort -u $endpoints_max_all] {
  1700.     if {$rc011_slack_max($ep) < $rc011_slack_lesser_than} {
  1701.       puts [format  "%-6s %-12s %-20s %-15s" "\nOL" "$rc011_slack_max($ep)" "$slack($ep)" "$ep"]
  1702.       foreach i $rc011_pins_max($ep) {
  1703.         puts [format  "%-6s %-12s %-16s %-15s %-15s %-6s" "" "" "" "" "$stage_del($i)" "$i"]
  1704.       }
  1705.     }
  1706.   }
  1707.  
  1708.   foreach ep [lsort -u $endpoints_min_all] {
  1709.     if {$rc011_slack_min($ep) < $rc011_slack_lesser_than} {
  1710.       puts [format  "%-6s %-12s %-20s %-15s" "\nUL" "$rc011_slack_min($ep)" "$slack($ep)" "$ep"]
  1711.       foreach i $rc011_pins_min($ep) {
  1712.         puts [format  "%-6s %-12s %-16s %-15s %-15s %-6s" "" "" "" "" "$stage_del($i)" "$i"]
  1713.       }
  1714.     }
  1715.   }
  1716.  
  1717.   puts "\n\n"
  1718.   puts [format  "%-10s %-12s" "Type" "RC011-Clock-Pin"]
  1719.   puts [format  "%-10s %-12s" "----" "---------------"]
  1720.   foreach j [lsort -u $rc011_clock_pins] {
  1721.     puts [format  "%-10s %-12s" "$rccp_type($j)" "$j"]
  1722.   }
  1723.  
  1724.   puts "\n1\n"
  1725.  
  1726.   unsuppress_message UITE-416
  1727.   set sh_continue_on_error $top_sh_continue_on_error
  1728. }
  1729.  
  1730. #----------------------------------------------------------------------------------------
  1731. # Find clock pins in report_constraints file
  1732. #----------------------------------------------------------------------------------------
  1733.  
  1734. proc rbx_get_clock_pins_from_pt_rpt_constraints { args } {
  1735.  
  1736.   #.......................................................
  1737.   # Print help and quit
  1738.   #.......................................................
  1739.   if {[lsearch $args "-help"] > -1} {
  1740.     puts "\n    rbx_get_clock_pins_from_pt_rpt_constraints -pt_report_list <report_constraints_file_list> -constraint_type <constraint_type>\n"
  1741.     return
  1742.   }
  1743.  
  1744.   #.......................................................
  1745.   # Arguments Handling
  1746.   #.......................................................
  1747.  
  1748.   # Default Argument Values
  1749.   set pt_report_list                ""
  1750.  
  1751.   # Check and get the values of the arguments
  1752.   if {[llength $args] < 4} {
  1753.     puts "\nRubix-Error: Missing options for rbx_get_clock_pins_from_pt_rpt_constraints command.\n"; return
  1754.   }
  1755.  
  1756.   foreach a $args {
  1757.     # Check if Wrong option is used
  1758.     if {[string match {-[A-Z|a-y]*} $a] && $a != "-pt_report_list" && $a != "-constraint_type"} {
  1759.       puts "\nRubix-Error: Option $a is not valid for rbx_get_clock_pins_from_pt_rpt_constraints command.\n"; return
  1760.     }
  1761.  
  1762.     # Get the values of the options
  1763.     if {$a == "-pt_report_list"}        { set pt_report_list [rbx_value -pt_report_list $args] }
  1764.     if {$a == "-constraint_type"}       { set constraint_type [rbx_value -constraint_type $args] }
  1765.   }
  1766.  
  1767.  
  1768.   #.......................................................
  1769.   # Execute the main procedure
  1770.   #.......................................................
  1771.  
  1772.   set    t1 [clock seconds]
  1773.  
  1774.   global    sh_product_version
  1775.  
  1776.   # Suppress messages
  1777.   suppress_message "ATTR-3"
  1778.  
  1779.  
  1780.   # For printing one lib per line
  1781.   foreach ptrep $pt_report_list {
  1782.     lappend pt_report_list_stacked "\n\t\t$ptrep"
  1783.   }
  1784.   set pt_report_list_stacked [string map {\{ "" \} ""} $pt_report_list_stacked]
  1785.  
  1786.   puts [format "%-20s" "*********************************************************************************************"]
  1787.   puts [format "%-10s %-15s" " Rubix Custom Report" "\n"]
  1788.   puts [format "%-10s %-15s" " Report" ": rbx_get_clock_pins_from_pt_rpt_constraints"]
  1789.   puts [format "%-10s %-15s" " "       " -pt_report_list $pt_report_list_stacked"]
  1790.   puts [format "%-10s %-15s" " "       " -constraint_type $constraint_type"]
  1791.   puts [format "%-10s %-15s" " Design" ": [get_attribute [get_design] full_name]"]
  1792.   puts [format "%-10s %-15s" " Version" ": $sh_product_version"]
  1793.   puts [format "%-10s %-15s" " Date" ": [date]"]
  1794.   puts [format "%-10s" "*********************************************************************************************"]
  1795.   puts "\n"
  1796.   puts [format "%-6s %-6s %-6s %-6s" "Pin" "Required" "Actual" "Slack" ]
  1797.   puts "----------------------------------------------------------------------------------------------------------------------"
  1798.  
  1799.   foreach current_rpt $pt_report_list {
  1800.  
  1801.     # Initialisation
  1802.     set constr_position  0
  1803.     set heading_seperator 0
  1804.  
  1805.     # Open Files for Reading/Writing
  1806.     set pt_rpt_con [open "$current_rpt" r]
  1807.  
  1808.  
  1809.     # Read Each Line for PT Transition Report File
  1810.     foreach {line} [split [read $pt_rpt_con] \n] {
  1811.  
  1812.       # Remove leading blanks
  1813.       set line [string trim $line]
  1814.       regsub -all { +} $line {;} l
  1815.  
  1816.       # Get each word
  1817.       set words [split $l ";"]
  1818.  
  1819.       # Detect the portion under "max_transition"
  1820.       if {[lindex $words 0] == "$constraint_type"} {
  1821.         set constr_position 1
  1822.       }
  1823.  
  1824.       # Process only the max_transition portion
  1825.       if {($constr_position == 1) && ($heading_seperator < 2)} {
  1826.  
  1827.         ## Write pins if they clock pins and if they are violating transition
  1828.         if {[string match "*VIOLATED*" [lindex $words 4]] && [llength [get_attribute [get_pins [lindex $words 0]] clocks]] > 0} {
  1829.           puts [format "%-6s %-6s %-6s %-6s %-6s" "[lindex $words 0]" "[lindex $words 1]" "[lindex $words 2]" "[lindex $words 3]" "[lindex $words 4]"]
  1830.         }
  1831.  
  1832.         ## Stop Writing
  1833.         if {[string match "*--------------------------------------------*" [lindex $words 0]]} {
  1834.           incr heading_seperator
  1835.         }
  1836.       }
  1837.  
  1838.     }
  1839.   }
  1840.  
  1841.   puts          "\n1"
  1842.  
  1843.   set t2        [clock seconds]
  1844.   puts          "\n# rbx_get_clock_pins_from_pt_rpt_constraints RUNTIME: [rbx_get_runtime $t1 $t2] \n"
  1845.  
  1846.   close $pt_rpt_con
  1847.  
  1848.   # Enable the suppressed messages
  1849.   unsuppress_message "ATTR-3"
  1850.  
  1851. }
  1852.  
  1853.  
  1854. #----------------------------------------------------------------------------------------
  1855. # Check if the transition limit is within lib limit
  1856. #----------------------------------------------------------------------------------------
  1857.  
  1858. proc rbx_get_lib_transition { pin_list } {
  1859.  
  1860.   puts "Slack\t - Actual Tran\t - Lib Limit\t - Pin"
  1861.   foreach p $pin_list {
  1862.     set lib_tran  [get_attribute [get_pins $p] max_transition]
  1863.     set rise_tran [get_attribute [get_pins $p] actual_rise_transition_max]
  1864.     set fall_tran [get_attribute [get_pins $p] actual_fall_transition_max]
  1865.  
  1866.     if {$rise_tran > $fall_tran} {
  1867.       set tran $rise_tran
  1868.     } else {
  1869.       set tran $fall_tran
  1870.     }
  1871.  
  1872.     puts "[expr $lib_tran - $tran]\t - $tran\t - $lib_tran\t - $p"
  1873.   }
  1874.  
  1875. }
  1876.  
  1877. #----------------------------------------------------------------------------------------
  1878. # Write a "TransitionFile" for EDI
  1879. #----------------------------------------------------------------------------------------
  1880.  
  1881. proc rbx_write_transition_file  { \
  1882.                   pt_rpt_constraints_file \
  1883.                   edi_trans_file \
  1884.                   { comment "" } \
  1885.                 } {
  1886.  
  1887.   set    t1 [clock seconds]
  1888.  
  1889.   global version_name
  1890.   global standalone_scenario
  1891.   global library_corner($standalone_scenario)
  1892.  
  1893.   # Initialisation
  1894.   set constr_position  0
  1895.   set heading_seperator 0
  1896.  
  1897.   # Open Files for Reading/Writing
  1898.   set pt_rpt_con [open "$pt_rpt_constraints_file" r]
  1899.   set edi_tr_fl  [open "$edi_trans_file" w]
  1900.  
  1901.   puts $edi_tr_fl "#*******************************************************************************************************"
  1902.   puts $edi_tr_fl "# Transition File for EDI"
  1903.   puts $edi_tr_fl "#-------------------------------------------------------------------------------------------------------"
  1904.   puts $edi_tr_fl "# Written by \"rbx_write_transition_file\" on [date]"
  1905.   puts $edi_tr_fl "#-------------------------------------------------------------------------------------------------------"
  1906.   puts $edi_tr_fl "# Comment:"
  1907.   puts $edi_tr_fl "# $comment"
  1908.   puts $edi_tr_fl "#*******************************************************************************************************"
  1909.   puts $edi_tr_fl ""
  1910.  
  1911.   puts "\nRM-Info: Reading file $pt_rpt_constraints_file..."
  1912.  
  1913.   # Read Each Line for PT Transition Report File
  1914.   foreach {line} [split [read $pt_rpt_con] \n] {
  1915.  
  1916.     # Remove leading blanks
  1917.     set line [string trim $line]
  1918.     regsub -all { +} $line {;} l
  1919.  
  1920.     # Get each word
  1921.     set words [split $l ";"]
  1922.  
  1923.     # Detect the portion under "max_transition"
  1924.     if {[lindex $words 0] == "max_transition"} {
  1925.       set constr_position 1
  1926.     }
  1927.  
  1928.     # Process only the max_transition portion
  1929.     if {($constr_position == 1) && ($heading_seperator < 2)} {
  1930.  
  1931.       ## Write Transition File for EDI
  1932.       if {[lindex $words 4] == "(VIOLATED)"} {
  1933.         puts $edi_tr_fl "setTranTime -maxR [lindex $words 2] [lindex $words 0]"
  1934.       }
  1935.  
  1936.       ## Stop Writing Transition file if max_transition portion is over
  1937.       if {[string match "*--------------------------------------------*" [lindex $words 0]]} {
  1938.         incr heading_seperator
  1939.       }
  1940.     }
  1941.  
  1942.   }
  1943.  
  1944.   puts "\nRM-Info: Writing transition file $edi_trans_file..."
  1945.  
  1946.   puts $edi_tr_fl "\n#--- EOF ---"
  1947.  
  1948.   set t2        [clock seconds]
  1949.   puts $edi_tr_fl   "\n# rbx_write_transition_file RUNTIME: [rbx_get_runtime $t1 $t2] "
  1950.  
  1951.   close $pt_rpt_con
  1952.   close $edi_tr_fl
  1953. }
  1954.  
  1955. #----------------------------------------------------------------------------------------
  1956. # Trace buffer/inverter chain
  1957. #----------------------------------------------------------------------------------------
  1958.  
  1959. proc rbx_trace_buf_inv_chain { pin_list } {
  1960.  
  1961.     foreach p $pin_list {
  1962.         set trace_pin       $p
  1963.         set stop_tracing    0
  1964.  
  1965.         while {$stop_tracing==0} {
  1966.             set driver_inpin_count      [sizeof_collection [get_pins -of_objects [get_cells -of_objects [rbx_get_driver $trace_pin]] -filter "direction==in"]]
  1967.             set driver_inpin            [get_pins -of_objects [get_cells -of_objects [rbx_get_driver $trace_pin]] -filter "direction==in"]
  1968.  
  1969.             if {$driver_inpin_count == 1} {
  1970.                 lappend nets    [get_object_name [get_nets -of_objects $driver_inpin]]
  1971.                 set trace_pin   $driver_inpin
  1972.             } else {    
  1973.                 set stop_tracing 1
  1974.             }
  1975.         }
  1976.     }
  1977.     return $nets
  1978. }
  1979.  
  1980. #----------------------------------------------------------------------------------------
  1981. # Get Cell worst from/to setup/hold slacks
  1982. #----------------------------------------------------------------------------------------
  1983.  
  1984. proc rbx_report_cell_interface_timing {\
  1985.                                    pin_clock_pairs \
  1986.                                    report_file \
  1987.                                      } {
  1988.  
  1989.     set rpt_csv [open "${report_file}"  w+]
  1990.  
  1991.     puts $rpt_csv "check,reg_to_mem,mem_to_reg"
  1992.     foreach pcp $pin_clock_pairs {
  1993.  
  1994.         set pin   [lindex $pcp 0]
  1995.         set clock [lindex $pcp 1]
  1996.  
  1997.         set cell        [get_object_name [get_cells -of_objects [get_pins $pin]]]
  1998.  
  1999.         set to_setup    [get_attribute [get_timing_path -to [get_pins $cell/*] -from [get_clocks $clock] -max_path 1]           slack]
  2000.         set to_hold     [get_attribute [get_timing_path -to [get_pins $cell/*] -from [get_clocks $clock] -max_path 1 -delay min]    slack]
  2001.  
  2002.         set from_setup  [get_attribute [get_timing_path -from [get_pins $cell/*] -to [get_clocks $clock] -max_path 1]           slack]
  2003.         set from_hold   [get_attribute [get_timing_path -from [get_pins $cell/*] -to [get_clocks $clock] -max_path 1 -delay min]    slack]
  2004.  
  2005.         set to_setup    [lindex $to_setup 0]
  2006.         set to_hold     [lindex $to_hold 0]
  2007.  
  2008.         set from_setup  [lindex $from_setup 0]
  2009.         set from_hold   [lindex $from_hold 0]
  2010.  
  2011.         puts $rpt_csv "$clock,$cell"
  2012.         puts $rpt_csv "setup,${to_setup},${from_setup}"
  2013.         puts $rpt_csv "hold,${to_hold},${from_hold}"
  2014.         puts $rpt_csv ""
  2015.     }
  2016.  
  2017.     close $rpt_csv
  2018.  
  2019. }
  2020.  
  2021. #--------------------------------------------------------------------------------
  2022. # Proc to get clock latency statistics
  2023. #--------------------------------------------------------------------------------
  2024.  
  2025. proc rbx_report_clock_latency { check clk_name} {
  2026.  
  2027.     echo "clock,latency,pin,type"
  2028.     foreach_in_collection reg [get_cells -hierarchical * -filter "is_hierarchical == false && ref_name =~ *DFF*"] {
  2029.         ## Get clk pin **
  2030.  
  2031.         set clk_pin [get_pins -of_objects $reg -filter "direction == in && is_clock_pin == true"]
  2032.         set pin_name [get_attribute $clk_pin full_name]
  2033.      
  2034.         ## Get path types **
  2035.      
  2036.         set is_ip false
  2037.         set is_op false
  2038.         set is_from_reg false
  2039.         set is_to_reg false
  2040.  
  2041.         set d_pins [get_pins -quiet -of_objects $reg -filter "direction == in && is_data_pin == true && lib_pin_name =~ D*"]
  2042.         foreach_in_collection pin $d_pins {
  2043.             if { [regexp {^v} [lindex [lindex [lindex [get_attribute $pin arrival_window] 0] 0] 0]] } {
  2044.                 set is_ip true
  2045.             }
  2046.             if { [regexp $clk_name [lindex [lindex [lindex [get_attribute $pin arrival_window] 0] 0] 0]] } {
  2047.                 set is_from_reg true
  2048.             }
  2049.         }
  2050.      
  2051.         set q_pins [get_pins -quiet -of_objects $reg -filter "direction == out && lib_pin_name =~ Q*"]
  2052.         foreach_in_collection pin $q_pins {
  2053.             if { [sizeof_collection [filter_collection [all_fanout -flat -endpoints_only -from $pin] "object_class =~ port"]] > 0 } {
  2054.                 set is_op true
  2055.             }
  2056.             set ep_pin_collection [filter_collection [filter_collection [all_fanout -flat -endpoints_only -from $pin] "object_class =~ pin"] "lib_pin_name =~ D*"]
  2057.             if { [sizeof_collection $ep_pin_collection] > 0 } {
  2058.                 set is_to_reg true
  2059.             }      
  2060.         }
  2061.      
  2062.         set R2R [expr $is_from_reg && $is_to_reg]
  2063.         set I2O [expr $is_ip && $is_op]
  2064.         set I2R [expr $is_ip && $is_to_reg]
  2065.         set R2O [expr $is_from_reg && $is_op]
  2066.      
  2067.         foreach thing [lindex [get_attribute $clk_pin arrival_window] 0] {
  2068.         # check for pos_edge
  2069.             if { [lindex $thing 1] == "pos_edge" } {
  2070.                 # get clock name
  2071.                 set pin_clock_name [lindex $thing 0]
  2072.                 if {$pin_clock_name == $clk_name} {
  2073.                     if {$check == "setup" } {
  2074.                         # get max_r_f
  2075.                         set clock_lat [lindex [lindex $thing 3] 1]
  2076.                     } else {
  2077.                         # get min_r_f
  2078.                         set clock_lat [lindex [lindex $thing 2] 1]
  2079.                     }
  2080.                     if {$R2R} {
  2081.                         echo $pin_clock_name,$clock_lat,$pin_name,R2R
  2082.                     }
  2083.                     if {$I2O} {
  2084.                         echo $pin_clock_name,$clock_lat,$pin_name,I2O
  2085.                     }
  2086.                     if {$I2R} {
  2087.                         echo $pin_clock_name,$clock_lat,$pin_name,I2R
  2088.                     }
  2089.                     if {$R2O} {
  2090.                         echo $pin_clock_name,$clock_lat,$pin_name,R2O
  2091.                     }      
  2092.                 }
  2093.             }
  2094.         }
  2095.     }
  2096. }
  2097.  
  2098.  
  2099.  
  2100. # --- EOF ---
  2101. #----------------------------------------------------------------------------------------
  2102. # Print Setup/Hold violations to endpoints
  2103. #----------------------------------------------------------------------------------------
  2104. proc rbx_report_pin_setup_hold { to_from_through endpoint_pin_list } {
  2105.     puts "Setup\tHold\tPin"
  2106.     foreach i [get_object_name [get_pins $endpoint_pin_list]] {
  2107.         set s_slk [get_attribute [get_timing_path $to_from_through [get_pins $i]           ] slack]
  2108.         set h_slk [get_attribute [get_timing_path $to_from_through [get_pins $i] -delay min] slack]
  2109.         puts "$s_slk\t$h_slk\t$i"
  2110.     }
  2111. }
  2112.  
  2113. #----------------------------------------------------------------------------------------
  2114. # Get Slacks from PBA report
  2115. #----------------------------------------------------------------------------------------
  2116. proc rbx_get_slacks {
  2117.                      report_file \
  2118.                    } {
  2119.  
  2120.   set rpt     [open "$report_file"              r]
  2121.  
  2122.   foreach {line} [split [read $rpt] \n] {
  2123.  
  2124.     if {$line != 1} {
  2125.       # Remove leading blanks
  2126.       set line [string trim $line]
  2127.       regsub -all { +} $line {;} l
  2128.  
  2129.       # Get each word
  2130.       set words [split $l ";"]
  2131.  
  2132.       if {"[lindex $words 1][lindex $words 2][lindex $words 3]" == "(withderatingapplied)"} {
  2133.         set derated_slack [lindex $words 5]
  2134.       } elseif {"[lindex $words 1][lindex $words 2][lindex $words 3]" == "(withnoderating)"} {
  2135.         set non_derated_slack [lindex $words 5]
  2136.       }
  2137.     }
  2138.  
  2139.   }
  2140.  
  2141.   close $rpt
  2142.   return [list $derated_slack $non_derated_slack]
  2143.  
  2144. }
  2145.  
  2146. #========================================================================================
  2147. # Proc Type 3:             Procs for Design Exploration and Debug
  2148. #========================================================================================
  2149.  
  2150. #----------------------------------------------------------------------------------------
  2151. # Get Fanout FF
  2152. #----------------------------------------------------------------------------------------
  2153.  
  2154. proc rbx_get_fo_ff { pin {ret list}} {
  2155.     set ff_list  [all_fanout -from $pin -endpoints_only -flat]
  2156.     set ff_count [sizeof_collection $ff_list]
  2157.  
  2158.     if {$ret == "list"} {
  2159.         return $ff_list
  2160.     } else {
  2161.         return $ff_count
  2162.     }
  2163. }
  2164.  
  2165. #----------------------------------------------------------------------------------------
  2166. # Get Pin Driver
  2167. #----------------------------------------------------------------------------------------
  2168.  
  2169. proc rbx_get_driver {pin} {
  2170.     suppress_message    "SEL-003"
  2171.     set driver      [get_object_name [get_pins -quiet -leaf -of_objects [get_net -of_object [get_pins $pin]] -filter "direction==out"]]
  2172.     if {$driver == ""}  {set driver "UNKNOWN"}
  2173.     unsuppress_message  "SEL-003"
  2174.     return      $driver
  2175. }
  2176.  
  2177. #----------------------------------------------------------------------------------------
  2178. # Get Cell Driver
  2179. #----------------------------------------------------------------------------------------
  2180.  
  2181. proc rbx_get_driver_cell {pin } {
  2182.     set driver          [get_pins -leaf -of_objects [get_net -of_object [get_pins $pin]] -filter "direction==out"]
  2183.     set driver_name     [get_attribute [get_pins $driver] full_name]
  2184.     set driver_cell     [get_attribute [get_cell -of_object [get_pins $driver]] ref_name]
  2185.     puts                "$driver_name,$driver_cell"
  2186. }
  2187.  
  2188. #----------------------------------------------------------------------------------------
  2189. # Get pin Receiver
  2190. #----------------------------------------------------------------------------------------
  2191.  
  2192. proc rbx_get_receivers {pin} {
  2193.     set receivers [get_pins -of_objects [get_net -of_object [get_pins $pin]] -filter "direction==in"]
  2194.     return $receivers
  2195. }
  2196.  
  2197. #----------------------------------------------------------------------------------------
  2198. # Get Coreceivers
  2199. #----------------------------------------------------------------------------------------
  2200.  
  2201. proc rbx_get_coreceivers {pin} {
  2202.     get_receivers [get_driver $pin]
  2203. }
  2204.  
  2205. #----------------------------------------------------------------------------------------
  2206. # Print Reference Name
  2207. #----------------------------------------------------------------------------------------
  2208.  
  2209. proc rbx_print_ref_name { instance_list } {
  2210.   foreach i $instance_list {
  2211.     set r [get_attribute [get_cells $i] ref_name]
  2212.     puts [format "%-40s %-15s" "$r" "$i"]
  2213.   }
  2214. }
  2215.  
  2216. #----------------------------------------------------------------------------------------
  2217. # Get instance names of complex cells
  2218. #----------------------------------------------------------------------------------------
  2219.  
  2220. proc rbx_get_complex_cells { } {
  2221.     foreach_in_collection c [remove_from_collection [get_cells -hier * -filter "is_hierarchical!=true"] [get_cells -hier * -filter "is_combinational==true"]] {
  2222.         if {[get_attribute [get_cells $c] number_of_pins]>15} {
  2223.             echo "[get_object_name [get_cells $c]]"
  2224.         }
  2225.     }
  2226. }
  2227.  
  2228. #----------------------------------------------------------------------------------------
  2229. # Check if start point is a latch
  2230. #----------------------------------------------------------------------------------------
  2231.  
  2232. proc rbx_is_startpoint_latch {\
  2233.                  pin_list \
  2234.                 } {
  2235.  
  2236.   global timing_report_unconstrained_paths
  2237.  
  2238.   suppress_message "SEL-003 UITE-416 ATTR-3"
  2239.  
  2240.   set init_rep_uncon_path $timing_report_unconstrained_paths
  2241.   set timing_report_unconstrained_paths true
  2242.  
  2243.   foreach p $pin_list {
  2244.     set sp_clk              [get_object_name [get_attribute [get_timing_path -to $p] startpoint_clock]]
  2245.     set ep_clk              [get_object_name [get_attribute [get_timing_path -to $p] endpoint_clock]]
  2246.     set arr                 [get_attribute [get_timing_path -to $p] arrival]
  2247.     set sp_clk_lat          [lindex [get_attribute [get_timing_path -from [get_cells -of_objects $p]] startpoint_clock_latency] 0]
  2248.     set current_startpoint  [get_object_name [get_attribute [get_timing_path -to $p] startpoint]]
  2249.     set startpoint_is_latch [get_attribute [get_timing_path -to $p] startpoint_is_level_sensitive]
  2250.  
  2251.     if {$startpoint_is_latch=="false"} {
  2252.       #puts "$current_startpoint\t\t$p"
  2253.       puts "[expr $arr - $sp_clk_lat] - $p"
  2254.     }
  2255.  
  2256.   }
  2257.  
  2258.   unsuppress_message "SEL-003 UITE-416 ATTR-3"
  2259.   set timing_report_unconstrained_paths $init_rep_uncon_path
  2260. }
  2261.  
  2262. #----------------------------------------------------------------------------------------
  2263. # Show Arcs
  2264. #----------------------------------------------------------------------------------------
  2265.  
  2266. proc rbx_show_arcs {args} {
  2267.     set arcs [eval [concat get_timing_arcs $args]]
  2268.     echo [format "%15s    %-15s  %8s %8s  %s" "from_pin" "to_pin" "rise" "fall" "is_cellarc"]
  2269.     echo [format "%15s    %-15s  %8s %8s  %s" "--------" "------" "----" "----" "----------"]
  2270.  
  2271.     foreach_in_collection arc $arcs {
  2272.         set is_cellarc [get_attribute $arc is_cellarc]
  2273.         set fpin [get_attribute $arc from_pin]
  2274.         set tpin [get_attribute $arc to_pin]
  2275.         set rise [get_attribute $arc delay_max_rise]
  2276.         set fall [get_attribute $arc delay_max_fall]
  2277.  
  2278.         set from_pin_name [get_attribute $fpin full_name]
  2279.  
  2280.         set to_pin_name [get_attribute $tpin full_name]
  2281.         #echo [format "%15s -> %-15s  %8s %8s  %s" $from_pin_name $to_pin_name \
  2282.              [format_float $rise] [format_float $fall] \
  2283.              $is_cellarc]
  2284.     puts [format "%15s -> %-15s  %8s %8s  %s" $from_pin_name $to_pin_name $rise $fall $is_cellarc]
  2285.     }
  2286. }
  2287.  
  2288. #----------------------------------------------------------------------------------------
  2289. # Get the difference between rise and fall timing through the set of pins
  2290. #----------------------------------------------------------------------------------------
  2291.  
  2292. proc rbx_get_rise_fall_diff { pin_list } {
  2293.  
  2294.     set max_rise 0
  2295.     set max_fall 0
  2296.     set min_rise 0
  2297.     set min_fall 0
  2298.    
  2299.     for {set i 0} {$i < [llength $pin_list]} {incr i 2} {
  2300.         set max_rise [expr $max_rise + [lindex [get_attr [get_timing_arc -from [lindex $pin_list $i ] -to [lindex $pin_list [expr $i+1] ]] delay_max_rise] 0]]
  2301.         set max_fall [expr $max_fall + [lindex [get_attr [get_timing_arc -from [lindex $pin_list $i ] -to [lindex $pin_list [expr $i+1] ]] delay_max_fall] 0]]
  2302.         set min_rise [expr $min_rise + [lindex [get_attr [get_timing_arc -from [lindex $pin_list $i ] -to [lindex $pin_list [expr $i+1] ]] delay_min_rise] 0]]
  2303.         set min_fall [expr $min_fall + [lindex [get_attr [get_timing_arc -from [lindex $pin_list $i ] -to [lindex $pin_list [expr $i+1] ]] delay_min_fall] 0]]
  2304.     }
  2305.  
  2306.     set high_pulse_change [expr $min_fall - $max_rise]
  2307.     set low_pulse_change  [expr $min_rise - $max_fall]
  2308.  
  2309.     puts "high_pulse_change = $high_pulse_change"
  2310.     puts "low_pulse_change  = $low_pulse_change"
  2311.  
  2312. }
  2313.  
  2314. #----------------------------------------------------------------------------------------
  2315. # Find the clocks propagating to a pin
  2316. #----------------------------------------------------------------------------------------
  2317. proc rbx_find_clocks {pin} {
  2318.   get_attribute [get_pins $pin] clocks
  2319. }
  2320.  
  2321. #----------------------------------------------------------------------------------------
  2322. # Estimate ECO
  2323. #----------------------------------------------------------------------------------------
  2324. proc rbx_estimate_eco {inst cell} {
  2325.   estimate_eco -nosplit -sort_by area -lib_cells [get_lib_cells */$cell*] $inst
  2326. }
  2327.  
  2328. #----------------------------------------------------------------------------------------
  2329. # Estimate size_cell
  2330. #----------------------------------------------------------------------------------------
  2331. proc rbx_estimate_size_cell {inst cell {check max}} {
  2332.     estimate_eco -nosplit -sort_by slack -$check -lib_cells [get_lib_cells */$cell*] $inst
  2333. }
  2334.  
  2335. #----------------------------------------------------------------------------------------
  2336. # Print one element of PT list in one line
  2337. #----------------------------------------------------------------------------------------
  2338. proc rbx_print_list { pt_lst } {
  2339.     foreach i [get_object_name $pt_lst] {
  2340.         echo $i
  2341.     }
  2342. }
  2343.  
  2344. #----------------------------------------------------------------------------------------
  2345. # Print Clock Freq
  2346. #----------------------------------------------------------------------------------------
  2347. proc rbx_print_clk_freq { clk_list } {
  2348.     puts [format "%-20s %-15s" "Clock" "Frequency in MHz"]
  2349.     foreach c $clk_list {
  2350.         puts [format "%-20s %-15s" "$c" "[expr round(1000/[get_attr [get_clocks $c] period])]"]
  2351.     }
  2352. }
  2353.  
  2354.  
  2355.  
  2356. #########################################################################################
  2357. #                          Child Procedures
  2358. #                 Procs Used within the above procs
  2359. #########################################################################################
  2360. #----------------------------------------------------------------------------------------
  2361. # Proc to get runtime
  2362. #----------------------------------------------------------------------------------------
  2363.  
  2364. proc rbx_get_runtime     {\
  2365.                          start_clock_seconds \
  2366.                          end_clock_seconds \
  2367.                         } {
  2368.  
  2369.     set time                        [expr $end_clock_seconds - $start_clock_seconds]
  2370.  
  2371.     if {$time < 60}                 { return "$time seconds" }
  2372.     if {$time > 60 && $time < 3599} { return "[expr $time/60] minutes" }
  2373.     if {$time > 3599}               { return "[expr $time/3600]:[expr ($time%3600)/60] hours" }
  2374. }
  2375.  
  2376. #----------------------------------------------------------------------------------------
  2377. # Format Float
  2378. #----------------------------------------------------------------------------------------
  2379.  
  2380. proc rbx_format_float {number {format_str "/f %.2f"}} {
  2381.     switch -exact -- $number {
  2382.         UNINIT { }
  2383.         INFINITY { }
  2384.         default {set number [format $format_str $number]}
  2385.     }
  2386.     return $number;
  2387. }
  2388.  
  2389. #----------------------------------------------------------------------------------------
  2390. # Get Value of an option
  2391. #----------------------------------------------------------------------------------------
  2392. proc rbx_value { argument arg} {
  2393.   set [set argument] "[lindex $arg [expr [lsearch $arg $argument] + 1]]"
  2394.   return "[set $argument]"
  2395. }
  2396.  
  2397. #----------------------------------------------------------------------------------------
  2398. # Add a list of integers
  2399. #----------------------------------------------------------------------------------------
  2400. proc rbx_ladd { integer_list } {
  2401.   set sum 0
  2402.   foreach i $integer_list {set sum [expr $sum + $i]}
  2403.   return $sum
  2404. }
  2405.  
  2406. #----------------------------------------------------------------------------------------
  2407. # Get the biggest integer from the list
  2408. #----------------------------------------------------------------------------------------
  2409. proc rbx_get_biggest { integer_list } {
  2410.   set biggest ""
  2411.   foreach i $integer_list {
  2412.     if {$biggest == "" || $i > $biggest} {
  2413.       set biggest $i
  2414.     }
  2415.   }
  2416.  
  2417.   return $biggest
  2418. }
  2419.  
  2420.  
  2421.  
  2422. #########################################################################################
  2423. #       +Pointer to Man Pages
  2424. #       +set for help command to display the custom commands
  2425. #########################################################################################
  2426. #########################################################################################
  2427.  
  2428. # Pointer to man pages
  2429. # set sh_user_man_path <path_to_man_pages/cat1/rbx_*.cat1>
  2430.  
  2431. # Following makes PrimeTime help command to display these commands
  2432. # Man pages exist for the custom commands that are un-commented
  2433. define_proc_attributes rbx_report_unconstrained_endpoints       -info "Rubix Custom Command:  "
  2434. #define_proc_attributes rbx_report_functional_si_endpoints      -info "Rubix Custom Command:  "
  2435. define_proc_attributes rbx_report_pba_timing_all_endpoints      -info "Rubix Custom Command:  "
  2436. define_proc_attributes rbx_check_clock_cell_type            -info "Rubix Custom Command:  "
  2437. #define_proc_attributes rbx_report_average_clock_latency        -info "Rubix Custom Command:  "
  2438. define_proc_attributes rbx_report_xtalk_clock_nets          -info "Rubix Custom Command:  "
  2439. define_proc_attributes rbx_report_xtalk_bottlenecks         -info "Rubix Custom Command:  "
  2440. define_proc_attributes rbx_get_noise_pin_details            -info "Rubix Custom Command:  "
  2441. define_proc_attributes rbx_get_si_violators_from_pt_reports     -info "Rubix Custom Command:  "
  2442. #define_proc_attributes rbx_get_glitch_nets             -info "Rubix Custom Command:  "
  2443. define_proc_attributes rbx_analyze_rc011                -info "Rubix Custom Command:  "
  2444. define_proc_attributes rbx_get_clock_pins_from_pt_rpt_constraints   -info "Rubix Custom Command:  "
  2445. #define_proc_attributes rbx_get_lib_transition              -info "Rubix Custom Command:  "
  2446. #define_proc_attributes rbx_write_transition_file           -info "Rubix Custom Command:  "
  2447. #define_proc_attributes rbx_trace_buf_inv_chain             -info "Rubix Custom Command:  "
  2448. #define_proc_attributes rbx_report_cell_interface_timing        -info "Rubix Custom Command:  "
  2449. #define_proc_attributes rbx_report_clock_latency            -info "Rubix Custom Command:  "
  2450. #define_proc_attributes rbx_report_pin_setup_hold           -info "Rubix Custom Command:  "
  2451. #define_proc_attributes rbx_get_slacks                  -info "Rubix Custom Command:  "
  2452. #define_proc_attributes rbx_get_fo_ff                   -info "Rubix Custom Command:  "
  2453. #define_proc_attributes rbx_get_driver                  -info "Rubix Custom Command:  "
  2454. #define_proc_attributes rbx_get_driver_cell             -info "Rubix Custom Command:  "
  2455. #define_proc_attributes rbx_get_receivers               -info "Rubix Custom Command:  "
  2456. #define_proc_attributes rbx_get_coreceivers             -info "Rubix Custom Command:  "
  2457. #define_proc_attributes rbx_print_ref_name              -info "Rubix Custom Command:  "
  2458. #define_proc_attributes rbx_get_complex_cells               -info "Rubix Custom Command:  "
  2459. #define_proc_attributes rbx_is_startpoint_latch             -info "Rubix Custom Command:  "
  2460. #define_proc_attributes rbx_show_arcs                   -info "Rubix Custom Command:  "
  2461. #define_proc_attributes rbx_get_rise_fall_diff              -info "Rubix Custom Command:  "
  2462. #define_proc_attributes rbx_find_clocks                 -info "Rubix Custom Command:  "
  2463. #define_proc_attributes rbx_estimate_eco                -info "Rubix Custom Command:  "
  2464. #define_proc_attributes rbx_estimate_size_cell              -info "Rubix Custom Command:  "
  2465. #define_proc_attributes rbx_print_list                  -info "Rubix Custom Command:  "
  2466. #define_proc_attributes rbx_print_clk_freq              -info "Rubix Custom Command:  "
  2467. #define_proc_attributes rbx_get_runtime                 -info "Rubix Custom Command:  "
  2468. #define_proc_attributes rbx_format_float                -info "Rubix Custom Command:  "
  2469. #define_proc_attributes rbx_value                   -info "Rubix Custom Command:  "
  2470. #define_proc_attributes rbx_ladd                    -info "Rubix Custom Command:  "
  2471. #define_proc_attributes rbx_get_biggest                 -info "Rubix Custom Command:  "
  2472.  
  2473. # --- EOF ---
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement