====== PT report_qor Script ====== # # Procedure to emulate DC's report_qor in PT # # Version 1.10 6/1/09 pjarvis # # Revision history # 1.0 (pfj) 9/3/03 - Initial release # 1.1 (pfj) 9/4/03 - Added hold-time reporting # 1.2 (pfj) 9/4/03 - Rewrote report_constraint parser and added all other DRCs # 1.3 (pfj) 9/4/03 - Added missing DRCs and fixed a bunch of related problems # 1.4 (pfj) 9/5/03 - Rewrote DRC parser to eliminate dependency on list of DRCs # 1.5 (pfj) 9/30/03 - Fixed bug with unconstrained path slacks # 1.6 (pfj) 5/14/04 - Changed report_constraint to use 5 digits for consistency with its DRC summary values # 1.7 (pfj) 4/27/07 - Added DMSA support; switched to redirect -variable instead of using temp file; # fixed bug with recovery/removal sum/count not being reported in async_default group; # added -significant_digits switch and dummy -physical switch (compatibility with DC/ICC) # 1.8 (pfj) 11/5/07 - Added code to stop script from running in 2007.06-* PrimeTime DMSA mode prior to 2007.06-SP3 # to avoid merged-reporting bug from STAR 9000188708 # 1.9 (pfj) 11/13/07 - Changed get_pins -of [get_cells $nonhier_cells] to the more-memory-efficient # get_pins -hier * -filter "is_hierarchical==false" approach; reduces overall memory usage # 1.10 (pfj) 6/1/09 - Fixed bug in DMSA mode where zero TNS and path count is reported with nonzero WNS; # alphabetized display of path groups to avoid nondeterministic get_timing_paths group ordering proc report_qor {args} { global sh_product_version global sh_dev_null global report_default_significant_digits global synopsys_program_name global pt_shell_mode set results(-help) "no help" set results(-significant_digits) "none" parse_proc_arguments -args $args results if {$results(-help)==""} { help -verbose report_qor return 1 } if {$results(-significant_digits)=="none"} { set significant_digits $report_default_significant_digits } else { if {$results(-significant_digits) < 0 || $results(-significant_digits) > 13} { echo "Error: value '$results(-signiificant_digits)' not in range (0 to 13). (CMD-019)" return 0 } else { set significant_digits $results(-significant_digits) } } proc count_levels {path} { set levels 0 set endpoint [get_object_name [get_attribute -quiet $path endpoint]] foreach_in_collection point [get_attribute -quiet $path points] { set object [get_attribute -quiet $point object] if {[get_attribute -quiet $object object_class] == "pin"} { if {[get_attribute -quiet $object pin_direction] == "in"} { if {[get_attribute -quiet $object is_port] == "false"} { if {[get_attribute -quiet $object full_name] != $endpoint} { incr levels } } } } } return $levels } proc display_path_group {levels arrival slack cost count significant_digits scenario} { echo " ---------------------------------------------" echo [format " Levels of Logic:%29d$scenario" $levels] echo [format " Critical Path Length:%24.${significant_digits}f$scenario" $arrival] if {[regexp {[^a-zA-Z]} $slack full]} { echo [format " Critical Path Slack:%25.${significant_digits}f$scenario" $slack] } else { echo [format " Critical Path Slack: unconstrained$scenario"] } echo [format " Total Negative Slack:%24.${significant_digits}f" $cost] echo [format " No. of Violating Paths:%22d" $count] echo " ---------------------------------------------" } proc display_cell_count_and_drcs {hier_cells_count nonhier_cells_count area hier_pins_count nonhier_pins_count cost count drc_list significant_digits scenario} { upvar $cost cost_local upvar $count count_local echo "\n\n Cell Count" echo " ---------------------------------------------" echo [format " Hierarchical Cell Count:%21d$scenario" $hier_cells_count] echo [format " Hierarchical Port Count:%21d$scenario" $hier_pins_count] echo [format " Leaf Cell Count:%29d$scenario" $nonhier_cells_count] echo " ---------------------------------------------" echo "\n\n Area" echo " ---------------------------------------------" echo [format " Design Area:%33.6f$scenario" $area] if {[info exists cost_local(max_area)]} { echo [format " Area Cost:%35.6f" $cost_local(max_area)] } echo " ---------------------------------------------" echo "\n\n Design Rule Violations" echo " ---------------------------------------------" echo [format " Total No. of Pins in Design:%17d$scenario" $nonhier_pins_count] foreach i $drc_list { if {$count_local($i) != 0} { set len [expr 38 - [string length $i]] echo [format " $i Count:%${len}d" $count_local($i)] } } set total_cost 0 foreach i $drc_list { if {$cost_local($i) != 0} { set len [expr 39 - [string length $i]] set total_cost [expr $total_cost + $cost_local($i)] echo [format " $i Cost:%${len}.${significant_digits}f" $cost_local($i)] } } echo [format " Total DRC Cost:%30.${significant_digits}f" $total_cost] echo " ---------------------------------------------\n" } if {$synopsys_program_name != "pt_shell"} { echo "Error: This script only functions properly in PrimeTime." return 0 } set constraint_text "" set drc_list "" set group_list "" if {$pt_shell_mode == "primetime" || $pt_shell_mode == "primetime_slave"} { set cost(unconstrained) 0 set count(unconstrained) 0 redirect $sh_dev_null {catch {set design [current_design]}} if { $design == "" } { echo "Error: Current design is not defined. (DES-001)" return 0 } echo "\n****************************************" echo "Report : qor" echo "Design : [get_object_name $design]" echo "Version: $sh_product_version" echo "Date : [date]" echo "****************************************\n" redirect -variable constraint_text {report_constraint -all_violators -nosplit -significant_digits 5} foreach line [split $constraint_text "\n"] { switch -regexp $line { {^.* +([-\.0-9]+) +\(VIOLATED} { regexp {^.* +([-\.0-9]+) +\(VIOLATED} $line full slack set cost($group) [expr $cost($group) + $slack] incr count($group) continue } { *max_delay/setup.*'(.*)'} { regexp { *max_delay/setup.*'(.*)'} $line full group set cost($group) 0 set count($group) 0 continue } { *min_delay/hold.*'(.*)'} { regexp { *min_delay/hold.*'(.*)'} $line full group set group ${group}_min set cost($group) 0 set count($group) 0 continue } {^ *([a-zA-Z_]+) *$} { regexp {^ *([a-zA-Z_]+) *$} $line full group if {$group == "recovery" } { set group async_default } if {$group == "removal"} { set group async_default_min } if ![info exists cost($group)] { set cost($group) 0 set count($group) 0 if {$group != "max_area" && $group != "async_default" && $group != "async_default_min"} { lappend drc_list $group } } continue } } } foreach_in_collection path [sort_collection [get_timing_paths] path_group] { set path_group [get_attribute -quiet [get_attribute -quiet $path path_group] full_name] if {$path_group == ""} { set path_group unconstrained } if {[regexp {\*\*[a-z_]*\*\*} $path_group full]} { set path_group [string map {\* ""} $path_group] } if {![info exists cost($path_group)]} { set cost($path_group) 0 set count($path_group) 0 } set levels [count_levels $path] set slack [get_attribute -quiet $path slack] echo "\n Timing Path Group '$path_group' (max_delay/setup)" display_path_group $levels [get_attribute -quiet $path arrival] $slack $cost($path_group) $count($path_group) $significant_digits "" } echo "" foreach_in_collection path [sort_collection [get_timing_paths -delay min] path_group] { redirect $sh_dev_null {set path_group [get_attribute -quiet [get_attribute -quiet $path path_group] full_name]} if {$path_group == ""} { set path_group unconstrained } if {[regexp {\*\*[a-z_]*\*\*} $path_group full]} { set path_group [string map {\* ""} $path_group] } if {![info exists cost(${path_group}_min)]} { set cost(${path_group}_min) 0 set count(${path_group}_min) 0 } set levels [count_levels $path] set slack [get_attribute -quiet $path slack] echo "\n Timing Path Group '$path_group' (min_delay/hold)" display_path_group $levels [get_attribute -quiet $path arrival] $slack $cost(${path_group}_min) $count(${path_group}_min) $significant_digits "" } set hier_cells [get_cells -quiet -hier * -filter "is_hierarchical == true"] set nonhier_cells [get_cells -quiet -hier * -filter "is_hierarchical == false"] display_cell_count_and_drcs [sizeof_collection $hier_cells] \ [sizeof_collection $nonhier_cells] \ [get_attribute -quiet $design area] \ [sizeof_collection [get_pins -quiet -of $hier_cells]] \ [sizeof_collection [get_pins -quiet -hier * -filter "is_hierarchical==false"]] \ cost \ count \ $drc_list \ $significant_digits \ "" } elseif {$pt_shell_mode == "primetime_master"} { global multi_scenario_message_verbosity_level set old_verbosity_level $multi_scenario_message_verbosity_level set multi_scenario_message_verbosity_level low if [info exists constraint_text] { unset constraint_text } if {$sh_product_version=="Z-2007.06"||$sh_product_version=="Z-2007.06-SP1"||$sh_product_version=="Z-2007.06-SP2"||$sh_product_version=="Z-2007.06-SP2-1"} { echo "Error: Aborting script execution! Due to a DMSA bug in Z-2007.06 versions prior to Z-2007.06-SP3 (STAR 9000188708)," echo " this script will produce inconsistent and incorrect results. The bug is fixed in Z-2007.06-SP3 PrimeTime." echo " To use this script in DMSA mode, please use Z-2007.06-SP3 or later PrimeTime instead." return 0 } echo "\n****************************************" echo "Report : qor" echo "Design : multi-scenario design" echo "Version: $sh_product_version" echo "Date : [date]" echo "****************************************\n" get_distributed_variables -pre_commands \ {redirect -variable constraint_text {report_constraint -all_violators -nosplit -significant_digits 5}} \ constraint_text set max_paths [get_timing_paths -attributes "full_name slack path_group points arrival object object_class pin_direction is_port endpoint"] set min_paths [get_timing_paths -delay min -attributes "full_name slack path_group points arrival object object_class pin_direction is_port endpoint"] set old_scenario_list [current_scenario] foreach_in scenario $old_scenario_list { set first_scenario_name [get_object_name $scenario] break } current_scenario $first_scenario_name get_distributed_variables -pre_commands \ {set hier_cells [get_cells -quiet -hier * -filter "is_hierarchical == true"]; \ set nonhier_cells [get_cells -quiet -hier * -filter "is_hierarchical == false"]; \ set hier_cells_count [sizeof_collection $hier_cells]; \ set hier_pins_count [sizeof_collection [get_pins -quiet -of $hier_cells]]; \ set nonhier_cells_count [sizeof_collection $nonhier_cells]; \ set nonhier_pins_count [sizeof_collection [get_pins -quiet -hier * -filter "is_hierarchical==false"]]; \ set area [get_attribute -quiet [current_design] area]; \ } "hier_cells_count nonhier_cells_count hier_pins_count nonhier_pins_count area" current_scenario $old_scenario_list set multi_scenario_message_verbosity_level $old_verbosity_level set group "" foreach scenario [array names constraint_text] { foreach line [split $constraint_text($scenario) "\n"] { switch -regexp $line { {^ +(\S+ ?[\(\)a-zA-Z]*).* ([-\.0-9]+) +\(VIOLATED} { regexp {^ +(\S+ ?[\(\)a-zA-Z]*).* ([-\.0-9]+) +\(VIOLATED} $line full object slack set object [string trimright $object] if ![info exists slack_${group}($object)] { set slack_${group}($object) $slack } else { if [expr $slack < [set slack_${group}($object)]] { set slack_${group}($object) $slack } continue } } { *max_delay/setup.*'(.*)'} { regexp { *max_delay/setup.*'(.*)'} $line full group if ![info exists slack_$group] { array set slack_$group "" array set slack_$group "" set cost($group) 0 set count($group) 0 lappend group_list $group } continue } { *min_delay/hold.*'(.*)'} { regexp { *min_delay/hold.*'(.*)'} $line full group set group ${group}_min if ![info exists slack_$group] { array set slack_$group "" array set slack_$group "" set cost($group) 0 set count($group) 0 lappend group_list $group } continue } {^ *([a-zA-Z_]+) *$} { regexp {^ *([a-zA-Z_]+) *$} $line full group if {$group == "recovery"} { set group async_default if ![info exists slack_async_default] { lappend group_list async_default } } if {$group == "removal"} { set group async_default_min if ![info exists slack_async_default_min] { lappend group_list async_default_min } } if ![info exists slack_$group] { if {$group != "max_area" && $group != "async_default" && $group != "async_default_min"} { lappend drc_list $group } array set slack_$group "" array set slack_$group "" set cost($group) 0 set count($group) 0 } continue } } } } foreach group "$group_list $drc_list" { foreach object [array names slack_$group] { set cost($group) [expr $cost($group) + [set slack_${group}($object)]] incr count($group) } } foreach_in_collection path [sort_collection $max_paths path_group] { set path_group [get_attribute -quiet [get_attribute -quiet $path path_group] full_name] if {$path_group == ""} { set path_group unconstrained } if {[regexp {\*\*[a-z_]*\*\*} $path_group full]} { set path_group [string map {\* ""} $path_group] } if {![info exists cost($path_group)]} { set cost($path_group) 0 set count($path_group) 0 } set levels [count_levels $path] set slack [get_attribute -quiet $path slack] set scenario_name [get_attribute $path scenario_name] echo "\n Timing Path Group '$path_group' (max_delay/setup)" display_path_group $levels [get_attribute -quiet $path arrival] $slack $cost($path_group) $count($path_group) $significant_digits " ($scenario_name)" } echo "" foreach_in_collection path [sort_collection $min_paths path_group] { redirect $sh_dev_null {set path_group [get_attribute -quiet [get_attribute -quiet $path path_group] full_name]} if {$path_group == ""} { set path_group unconstrained } if {[regexp {\*\*[a-z_]*\*\*} $path_group full]} { set path_group [string map {\* ""} $path_group] } if {![info exists cost(${path_group}_min)]} { set cost(${path_group}_min) 0 set count(${path_group}_min) 0 } set levels [count_levels $path] set slack [get_attribute -quiet $path slack] set scenario_name [get_attribute $path scenario_name] echo "\n Timing Path Group '$path_group' (min_delay/hold)" display_path_group $levels [get_attribute -quiet $path arrival] $slack $cost(${path_group}_min) $count(${path_group}_min) $significant_digits " ($scenario_name)" } display_cell_count_and_drcs $hier_cells_count($first_scenario_name) \ $nonhier_cells_count($first_scenario_name) \ $area($first_scenario_name) \ $hier_pins_count($first_scenario_name) \ $nonhier_pins_count($first_scenario_name) \ cost \ count \ $drc_list \ $significant_digits \ " ($first_scenario_name)" } } define_proc_attributes report_qor \ -info "Report QoR" \ -define_args {\ {-physical "For compatibility with DC/ICC report_qor; ignored in PrimeTime" "" boolean optional} {-significant_digits "Precision level of report (range from 0 to 13)" "" int optional} }