| # |
| # $Id: CALtvfPERC.tcl 1 2018/03/19 18:29:31 GMT bmadden Exp $ |
| # |
| # CALtvfPERC.tcl |
| # |
| # Copyright (c) 2010 by Cypress Semiconductor |
| # Cypress Kentucky CAD Center (KYCC) |
| # |
| # Date : Dec 23, 2010 |
| # Author: Kungyen Chang (kuc) @ KYCC |
| # |
| # Description: |
| # Contains the PERC functions used for PERC P2P resistance checks |
| # |
| # Revision History: |
| # kuc 12/23/10 initial version |
| # kuc 01/26/11 added res_dev_nearest |
| # vun 05/11/12 updated res_dev for min/max res calculation |
| # kuc 07/29/14 added code to make X and Y coordinate lookup function with |
| # different versions of Calibre |
| # |
| |
| # globals used for the next 2 functions |
| # we use globals because the PERC command that calls these functions doesn't allow for passing of variables |
| set dev_net_type_pinAtNet {} |
| array set dev_array {} |
| |
| # rule value is a global variable that gets set for every rule |
| set rule_value 0 |
| |
| # current_error stores the name of the check |
| set current_error "" |
| |
| # Versions of Calibre 2013.2 or higher do not have X and Y coordinates |
| # retrievable using the perc::property function. |
| # |
| # Instead, the functions perc::x_coord and perc::y_coord, perc::xy_coord are used. |
| # The get_X and get_Y functions return the X and Y coordinates using the correct function for |
| # the Calibre version provided. |
| |
| # store whether or not the perc::x_coord and perc::y_coord functions are defined |
| set coordinate_functions_defined 0 |
| if {([info commands perc::x_coord] != "") && ([info commands perc::y_coord] != "")} { |
| set coordinate_functions_defined 1 |
| } |
| |
| proc get_X { dev } { |
| global coordinate_functions_defined |
| if {$coordinate_functions_defined == 1} { |
| return [perc::x_coord $dev] |
| } else { |
| return [perc::property $dev X] |
| } |
| } |
| proc get_Y { dev } { |
| global coordinate_functions_defined |
| if {$coordinate_functions_defined == 1} { |
| return [perc::y_coord $dev] |
| } else { |
| return [perc::property $dev Y] |
| } |
| } |
| |
| # |
| # used to store devices in the global array, this is used to store |
| # potential pin pairs for the diff->tap resistance check |
| # |
| proc add_devices_to_array { net dev pin } { |
| global dev_net_type_pinAtNet |
| global dev_array |
| |
| lappend dev_net_type_pinAtNet {$net $dev $pin} |
| set result [perc::count -net $net -type $dev -pinAtNet $pin -list] |
| set dev_count [lindex $result 0] |
| set dev_list [lindex $result 1] |
| if { $dev_count == 0 } { return 0 } |
| |
| # add all the devices to the array/hash |
| for {set i 0} {$i < $dev_count} {incr i} { |
| set d [lindex $dev_list $i] |
| set tapnet [perc::property $d tapnet] |
| set dev_array($net,$dev,$pin,$tapnet) $d |
| } |
| } |
| |
| # |
| # adds pin pairs for the diff->tap resistance check |
| # |
| proc res_dev_difftap {net dev1 pin1 dev2 pin2} { |
| global dev_net_type_pinAtNet |
| global dev_array |
| global rule_value |
| global current_error |
| |
| set result [perc::count -net $net -type $dev1 -pinAtNet $pin1 -list] |
| set dev1_count [lindex $result 0] |
| set dev1_list [lindex $result 1] |
| if { $dev1_count == 0 } { return 0 } |
| |
| set result [perc::count -net $net -type $dev2 -pinAtNet $pin2 -list] |
| set dev2_count [lindex $result 0] |
| set dev2_list [lindex $result 1] |
| if { $dev2_count == 0 } { |
| foreach d1 $dev1_list { |
| puts "WARNING: Corresponding tap not found for [perc::name $d1] with tapnet [perc::property $d1 tapnet]" |
| perc::export_device $d1 -check_type $current_error -annotate [list [list error_type 1 ]] |
| } |
| return 0 |
| } |
| |
| if { [lsearch $dev_net_type_pinAtNet {$net $dev2 $pin2}] < 0} { |
| add_devices_to_array $net $dev2 $pin2 |
| } |
| |
| set d1 "" |
| set d2 "" |
| set pair_count 0 |
| |
| puts "Exporting pin pairs for [perc::name $net] at [clock format [clock seconds]]" |
| puts "Checking $dev1_count sources vs $dev2_count taps" |
| |
| for {set i 0} {$i < $dev1_count} {incr i} { |
| set d1 [lindex $dev1_list $i] |
| set d1_net [perc::property $d1 tapnet] |
| if { [info exists dev_array($net,$dev2,$pin2,$d1_net)] } { |
| set d2 $dev_array($net,$dev2,$pin2,$d1_net) |
| perc::export_pin_pair [list $d1 $pin1 $d2 $pin2] -p2p "> $rule_value" |
| } else { |
| puts "WARNING: Corresponding tap not found for [perc::name $d1] with tapnet $d1_net" |
| perc::export_device $d1 -check_type $current_error -annotate [list [list error_type 1 ]] |
| } |
| set pair_count [expr {$pair_count + 1}] |
| if { ([expr {$pair_count % 1000}] == 0) && ($pair_count > 0) } { |
| puts "Done with $pair_count at [clock format [clock seconds]]" |
| } |
| } |
| puts "Completed exporting $pair_count pin pairs for [perc::name $net] at [clock format [clock seconds]]" |
| } |
| |
| # |
| # adds pin pairs for a generic P2P resistance check |
| # |
| proc res_dev {net dev1 pin1 dev2 pin2 gt_lt} { |
| global rule_value |
| global current_error |
| |
| set result [perc::count -net $net -type $dev1 -pinAtNet $pin1 -list] |
| set dev1_count [lindex $result 0] |
| set dev1_list [lindex $result 1] |
| if { $dev1_count == 0 } { return 0 } |
| |
| set result [perc::count -net $net -type $dev2 -pinAtNet $pin2 -list] |
| set dev2_count [lindex $result 0] |
| set dev2_list [lindex $result 1] |
| |
| set pair_count 0 |
| |
| if { $dev2_count == 0 } { |
| foreach d1 $dev1_list { |
| perc::export_device $d1 -check_type $current_error -annotate [list [list error_type 1]] |
| } |
| return 0 |
| } |
| |
| for {set i 0} {$i < $dev1_count} {incr i} { |
| set d1 [lindex $dev1_list $i] |
| for {set j 0} {$j < $dev2_count} {incr j} { |
| |
| set d2 [lindex $dev2_list $j] |
| |
| if {"lt" == $gt_lt } { |
| perc::export_pin_pair [list $d1 $pin1 $d2 $pin2] -p2p "< $rule_value" |
| } else { |
| perc::export_pin_pair [list $d1 $pin1 $d2 $pin2] -p2p "> $rule_value" |
| } |
| set pair_count [expr $pair_count + 1] |
| if { ([expr {$pair_count % 1000}] == 0) && ($pair_count > 0) } { |
| puts "Done with $pair_count at [clock format [clock seconds]]" |
| } |
| } |
| } |
| puts "Completed exporting $pair_count pin pairs for [perc::name $net] at [clock format [clock seconds]]" |
| } |
| |
| |
| # |
| # adds pin pairs for a generic P2P resistance check |
| # adds the nearest dev2 to dev1 as a pin pair, discards all other dev2/dev1 combos |
| # |
| proc res_dev_nearest {net dev1 pin1 dev2 pin2 gt_lt} { |
| global rule_value |
| global current_error |
| |
| set result [perc::count -net $net -type $dev1 -pinAtNet $pin1 -list] |
| set dev1_count [lindex $result 0] |
| set dev1_list [lindex $result 1] |
| if { $dev1_count == 0 } { return 0 } |
| |
| set result [perc::count -net $net -type $dev2 -pinAtNet $pin2 -list] |
| set dev2_count [lindex $result 0] |
| set dev2_list [lindex $result 1] |
| |
| set pair_count 0 |
| |
| if { $dev2_count == 0 } { |
| foreach d1 $dev1_list { |
| perc::export_device $d1 -check_type $current_error -annotate [list [list error_type 1]] |
| } |
| return 0 |
| } |
| |
| # stores the nearest device |
| set lowest_dist "" |
| set lowest_dist_dev "" |
| |
| for {set i 0} {$i < $dev1_count} {incr i} { |
| set d1 [lindex $dev1_list $i] |
| set d1_x [get_X $d1] |
| set d1_y [get_Y $d1] |
| for {set j 0} {$j < $dev2_count} {incr j} { |
| set d2 [lindex $dev2_list $j] |
| set d2_x [get_X $d2] |
| set d2_y [get_Y $d2] |
| set sep_dist [expr {sqrt( pow( abs( $d2_x - $d1_x ), 2.0 ) + pow( abs( $d2_y - $d1_y ), 2.0 ) )}] |
| |
| # if this is the first calculation then we automatically store the shape and distance |
| # otherwise we only store it if this beats the current lowest distance |
| if { $j == 0 } { |
| set lowest_dist $sep_dist |
| set lowest_dist_dev $d2 |
| } else { |
| if { $sep_dist < $lowest_dist } { |
| set lowest_dist $sep_dist |
| set lowest_dist_dev $d2 |
| } |
| } |
| } |
| if {"lt" == $gt_lt } { |
| perc::export_pin_pair [list $d1 $pin1 $lowest_dist_dev $pin2] -p2p "< $rule_value" |
| } else { |
| perc::export_pin_pair [list $d1 $pin1 $lowest_dist_dev $pin2] -p2p "> $rule_value" |
| } |
| set pair_count [expr $pair_count + 1] |
| if { ([expr {$pair_count % 1000}] == 0) && ($pair_count > 0) } { |
| puts "Done with $pair_count at [clock format [clock seconds]]" |
| } |
| } |
| puts "Completed exporting $pair_count pin pairs for [perc::name $net] at [clock format [clock seconds]]" |
| } |
| |
| |