blob: e2e776999fbd500b59855eec430b5edd5a5938d1 [file] [log] [blame]
#
# $Id: CALtvfExt.tcl 1 2018/03/19 18:29:31 GMT bmadden Exp $
#
# CALtvfExt.tcl
#
# Copyright (c) 2007 by Cypress Semiconductor
# Cypress Kentucky CAD Center (KYCC)
#
# Date : Jun 09, 2007
# Author: Cory Davis (cry) @ KYCC
#
# Description:
# This file will define all TVF procs to be used in DEVICE statements.
# All of these will be accessed under the CALtvfExt TVF FUNCTION
#
# Revision History:
# cry 06/09/07 initial version
#
#
# Perform arithmetic that may hit a number too large or too small for TCL to handle.
# If the number is too small, return zero. If the number is too large, return a very
# large number. For any other errors, report the error.
#
# In this way, parameters are still calculated sucessfully.
#
proc catch_expr { arg } {
set rtval 0.0
if { [ catch { set rtval [ expr $arg ] } result ] } {
global errorCode
global errorInfo
set tmpCode $errorCode
set tmpError $errorInfo
if { [ string match "ARITH UNDERFLOW *" $errorCode ] } {
set rtval 0.0
} elseif { [ string match "ARITH OVERFLOW *" $errorCode ] } {
set rtval 1e200
} else {
error $result $tmpError $tmpCode
}
}
return $rtval
}
#
# Calculate the SCA instance parameter. This parameter is units. All values passed in by Calibre are done in meters,
# so be well aware of the 1e-6 multiplier when working with values.
#
# SC_W will be edges projected from the width portion of the gate.
# SC_L will be edges projected from the length portion of the gate.
# W is the drawn width of the gate
# L is the drawn length of the gate
# SCref is a modeling parameter (found in the device models) that is required to calculate WPE.
#
# Note: each slice count will have half the total number of segments, as the fragementation returns both the "a" and "b"
# portion for each slice - i.e. for each step through the iteration, we hit the segment on both sides of the gate.
#
proc cal_tvf_ext_sca { SC_W SC_L W L SCref } {
set W [$W]
set L [$L]
if { 0 == $W || 0 == $L } {
return 0.0
}
set slice_count_W [ $SC_W slice_count ]
set SCref [$SCref]
set sca_sum_W 0.0
for { set i 0 } { $i < $slice_count_W} { incr i } {
set SC_Wa_i [$SC_W a $i]
set SC_Wb_i [$SC_W b $i]
set SC_Ww_i [$SC_W w $i]
set sca_sum_W [expr {$sca_sum_W + ($SC_Ww_i * ((1.0/$SC_Wa_i) - (1.0/($SC_Wa_i+$L)) + (1.0/$SC_Wb_i) - (1.0/($SC_Wb_i+$L)) ))}]
}
set slice_count_L [ $SC_L slice_count ]
set sca_sum_L 0.0
for { set i 0 } { $i < $slice_count_L} { incr i } {
set SC_La_i [$SC_L a $i]
set SC_Lb_i [$SC_L b $i]
set SC_Lw_i [$SC_L w $i]
set sca_sum_L [expr {$sca_sum_L + ($SC_Lw_i * ((1.0/$SC_La_i) - (1.0/($SC_La_i+$W)) + (1.0/$SC_Lb_i) - (1.0/($SC_Lb_i+$W)) )) }]
}
return [ expr { ($sca_sum_W + $sca_sum_L)* (($SCref * $SCref) / ($W * $L )) }]
}
#
# Calculate the SCB instance parameter. This parameter is units. All values passed in by Calibre are done in meters,
# so be well aware of the 1e-6 multiplier when working with values.
#
# SC_W will be edges projected from the width portion of the gate.
# SC_L will be edges projected from the length portion of the gate.
# W is the drawn width of the gate
# L is the drawn length of the gate
# SCref is a modeling parameter (found in the device models) that is required to calculate WPE.
#
# Note: each slice count will have half the total number of segments, as the fragementation returns both the "a" and "b"
# portion for each slice - i.e. for each step through the iteration, we hit the segment on both sides of the gate.
#
# Note: the -10, 10, 100 values are part of the physical equation, and are not hard-coded technology-specific parameters.
#
proc cal_tvf_ext_scb { SC_W SC_L W L SCref} {
set W [$W]
set L [$L]
if { 0 == $W || 0 == $L } {
return 0.0
}
set SCref [$SCref]
set SCrefU10 [expr { 10.0 / $SCref }]
set SCrefUN10 [expr { -1.0 * $SCrefU10 }]
set slice_count_W [ $SC_W slice_count ]
set scb_sum_W 0.0
for { set i 0 } { $i < $slice_count_W} { incr i } {
set SC_Wa_i [$SC_W a $i]
set SC_Wb_i [$SC_W b $i]
set SC_Ww_i [$SC_W w $i]
set Wexp1a [catch_expr "exp($SCrefUN10 * $SC_Wa_i )"]
set Wexp2a [catch_expr "exp($SCrefUN10 * ($SC_Wa_i+$L))"]
set Wexp1b [catch_expr "exp($SCrefUN10 * $SC_Wb_i )"]
set Wexp2b [catch_expr "exp($SCrefUN10 * ($SC_Wb_i+$L))"]
set scb_sum_W [expr {$scb_sum_W + ($SC_Ww_i * ((($SCrefU10*$SC_Wa_i*$Wexp1a + $Wexp1a) - ($SCrefU10*($SC_Wa_i+$L)*$Wexp2a + $Wexp2a )) + (($SCrefU10*$SC_Wb_i*$Wexp1b + $Wexp1b) - ($SCrefU10*($SC_Wb_i+$L)*$Wexp2b + $Wexp2b))))}]
}
set slice_count_L [ $SC_L slice_count ]
set scb_sum_L 0.0
for { set i 0 } { $i < $slice_count_L} { incr i } {
set SC_La_i [$SC_L a $i]
set SC_Lb_i [$SC_L b $i]
set SC_Lw_i [$SC_L w $i]
set Lexp1a [catch_expr "exp($SCrefUN10 * $SC_La_i )"]
set Lexp2a [catch_expr "exp($SCrefUN10 * ($SC_La_i+$W))"]
set Lexp1b [catch_expr "exp($SCrefUN10 * $SC_Lb_i )"]
set Lexp2b [catch_expr "exp($SCrefUN10 * ($SC_Lb_i+$W))"]
set scb_sum_L [expr {$scb_sum_L + ($SC_Lw_i * ((($SCrefU10*$SC_La_i*$Lexp1a + $Lexp1a) - ($SCrefU10*($SC_La_i+$W)*$Lexp2a + $Lexp2a )) + (($SCrefU10*$SC_Lb_i*$Lexp1b + $Lexp1b) - ($SCrefU10*($SC_Lb_i+$W)*$Lexp2b + $Lexp2b))))}]
}
return [ expr { ($scb_sum_W + $scb_sum_L) / ($W * $L * 100) * $SCref }]
}
#
# Calculate the SCC instance parameter. This parameter is units. All values passed in by Calibre are done in meters,
# so be well aware of the 1e-6 multiplier when working with values.
#
# SC_W will be edges projected from the width portion of the gate.
# SC_L will be edges projected from the length portion of the gate.
# W is the drawn width of the gate
# L is the drawn length of the gate
# SCref is a modeling parameter (found in the device models) that is required to calculate WPE.
#
# Note: each slice count will have half the total number of segments, as the fragementation returns both the "a" and "b"
# portion for each slice - i.e. for each step through the iteration, we hit the segment on both sides of the gate.
#
# Note: the -20, 20, 400 values are part of the physical equation, and are not hard-coded technology-specific parameters.
#
proc cal_tvf_ext_scc { SC_W SC_L W L SCref} {
set W [$W]
set L [$L]
if { 0 == $W || 0 == $L } {
return 0.0
}
set SCref [$SCref]
set SCrefU20 [expr { 20.0 / $SCref }]
set SCrefUN20 [expr { -1.0 * $SCrefU20 }]
set scc_sum_W 0.0
set slice_count_W [ $SC_W slice_count ]
for { set i 0 } { $i < $slice_count_W} { incr i } {
set SC_Wa_i [$SC_W a $i]
set SC_Wb_i [$SC_W b $i]
set SC_Ww_i [$SC_W w $i]
set Wexp1a [catch_expr "exp($SCrefUN20 * $SC_Wa_i )"]
set Wexp2a [catch_expr "exp($SCrefUN20 * ($SC_Wa_i+$L))"]
set Wexp1b [catch_expr "exp($SCrefUN20 * $SC_Wb_i )"]
set Wexp2b [catch_expr "exp($SCrefUN20 * ($SC_Wb_i+$L))"]
set scc_sum_W [expr {$scc_sum_W + ( $SC_Ww_i * ((($SCrefU20*$SC_Wa_i*$Wexp1a + $Wexp1a) - ($SCrefU20*($SC_Wa_i+$L)*$Wexp2a + $Wexp2a )) + (($SCrefU20*$SC_Wb_i*$Wexp1b + $Wexp1b) - ($SCrefU20*($SC_Wb_i+$L)*$Wexp2b + $Wexp2b ) ) )) } ]
}
set slice_count_L [ $SC_L slice_count ]
set scc_sum_L 0.0
for { set i 0 } { $i < $slice_count_L} { incr i } {
set SC_La_i [$SC_L a $i]
set SC_Lb_i [$SC_L b $i]
set SC_Lw_i [$SC_L w $i]
set Lexp1a [catch_expr "exp($SCrefUN20 * $SC_La_i )"]
set Lexp2a [catch_expr "exp($SCrefUN20 * ($SC_La_i+$W))"]
set Lexp1b [catch_expr "exp($SCrefUN20 * $SC_Lb_i )"]
set Lexp2b [catch_expr "exp($SCrefUN20 * ($SC_Lb_i+$W))"]
set scc_sum_L [expr { $scc_sum_L + ( $SC_Lw_i * ((($SCrefU20*$SC_La_i*$Lexp1a + $Lexp1a) - ($SCrefU20*($SC_La_i+$W)*$Lexp2a + $Lexp2a )) + (($SCrefU20*$SC_Lb_i*$Lexp1b + $Lexp1b) - ($SCrefU20*($SC_Lb_i+$W)*$Lexp2b + $Lexp2b ) ) )) } ]
}
return [ expr { ($scc_sum_W + $scc_sum_L) / ($W * $L * 400) * $SCref }]
}