Updated 2014-04-02 05:18:15 by charleshsiao

This code was contributed by [charleshsiao] on 2014-04-01 .. formatting is tidied up, now we just need some explanatory context :-).

HJG So... executing sed and awk means this needs to be run on a unix-system. Using sed plus awk separately is... well, strange. (awk could do both steps of the processing) Doing that inside tcl, which has perfectly good string-operations, is... well, stranger. (tcl could do it alone)
Reading a bunch of files means we need to know the contents of theses files to get this program running. FS_NVM_V2.lib - no idea...

This code is for semiconductor device model tunning. We can do its tunning if no money to buying modeling tool. We maybe can get model card from tsmc/UMC... like this form.
+ u0 = 0.012
+ ua = ...
+ ub = ...
+ dsub = ...
+ drout = ...
+ pvag = ...
+ cdsc = ...
+ cdscb = ...
+ cdscd = ...

When doing curve fitting, we need do sp runset writing in advance. Maybe named vd-id.sp and need hspice tool. so, judge.tcl would looks like:
exec hspice vd-id.sp > OUT
foreach ip {46 47 48 49 50 51 52} {
set line [exec sed -n "${ip}p" OUT]
if [regexp {^\s*[0-9]} $line x] break
}; #dynamic check which lines are our needing data
exec cat OUT | sed -n "${ip},[expr $ip+55]p" | awk \{print $2} > gc
...
set run 1
proc base {file array} {
    global $array
    array set $array {}; set ww 1
    set hand [open $file r]
    set yy [read $hand]
    foreach j $yy {
        array set $array "$ww $j"
        incr ww
    }
    incr ww -1
    close $hand
    set sum 0
    for {set w 1} {$w<=$ww} {incr w} {set sum [expr $sum+[set ${array}($w)]*[set ${array}($w)]]}
    set ${array}(sum) $sum
}

foreach {rr} {ga gb da db dat dbt dyt dzt} {
    base $rr $rr
}

proc comp {a b} {
    global $a $b
    if {[llength [array get $a]]!=[llength [array get $b]]} return
    set num [llength [array names $a]]
    incr num -1
    set dsum 0
    for {set i 1} {$i<=$num} {incr i} {
        set dsum [expr $dsum+([set ${a}($i)]-[set ${b}($i)])*([set ${a}($i)]-[set ${b}($i)])]
    }
    return "[expr sqrt($dsum/$num)/sqrt([set ${a}(sum)]/$num)]"
}
#puts [comp ga gc]

proc rms {} {
    foreach rr {gc gd dd de dd2 de2 dw2 dx2} {global $rr; base $rr $rr}
    return [expr 1.0*[comp ga gc]]
    return [expr ([comp ga gc]+[comp gb gd])*0.5]
   #return [expr ([comp ga gc]+[comp gb gd]+[comp da dd]+[comp db de])*0.25]
   #return [expr ([comp ga gc]+[comp gb gd]+[comp da dd]+[comp db de]+[comp dat dd2]+[comp dbt de2]+[comp dyt dw2]+[comp dzt dx2])*0.125]
}

proc altr {l c inter} {
    global run
    set vsat [exec sed -n ${l}p l55sp_v151_FS_NVM_V2.lib | awk "{print \$[set c]}"]
   #set vsat [exec sed -n  763p l55sp_v151.lib | awk "{print \$4}"]
    set line [exec sed -n ${l}p l55sp_v151_FS_NVM_V2.lib]
   #set line [exec sed -n  763p l55sp_v151.lib]
    exec tclsh judge.tcl &
    exec tclsh judge2.tcl &
    after 4000
    #puts [rms]
    #puts "[comp ga gc]+[comp gb gd]+[comp da dd]+[comp db de]+[comp dat dd2]+[comp dbt de2]+[comp dyt dw2]+[comp dzt dx2]"
    set now [rms]
    set last 1000
    set plus [expr $vsat+$inter]
    set minus [expr $vsat-$inter]
    set line [lreplace $line [expr $c-1] [expr $c-1] $plus]
    exec sed -i "${l}c $line" l55sp_v151_FS_NVM_V2.lib
    exec tclsh judge.tcl &
    exec tclsh judge2.tcl &
    after 4000
    set plus [rms]
    set line [lreplace $line [expr $c-1] [expr $c-1] $minus]
    exec sed -i "${l}c $line" l55sp_v151_FS_NVM_V2.lib
    exec tclsh judge.tcl &
    exec tclsh judge2.tcl &
    after 4000
    set minus [rms]
    if {$minus<$now} {set dir -1} elseif {$plus<$now} {set dir 1} else {
        global var brms; set var "temp best!!"; set brms "$now"
        set line [lreplace $line [expr $c-1] [expr $c-1] $vsat]
        exec sed -i "${l}c $line" l55sp_v151_FS_NVM_V2.lib
        return
    }
    #puts $dir
    while {$last>=$now && $run==1} {
        set last $now
        set vsat [expr $vsat+$inter*$dir]
        set line [lreplace $line [expr $c-1] [expr $c-1] $vsat]
        exec sed -i "${l}c $line" l55sp_v151_FS_NVM_V2.lib
        exec tclsh judge.tcl &
        exec tclsh judge2.tcl &
        after 4000
        set now [rms]
        puts $vsat
        puts $now
    }
    set vsat [expr $vsat-$inter*$dir]
    set line [lreplace $line [expr $c-1] [expr $c-1] $vsat]
    exec sed -i "${l}c $line" l55sp_v151_FS_NVM_V2.lib
    exec tclsh judge.tcl &
    exec tclsh judge2.tcl &
    after 4000
    set now [rms]
    global var brms
    set var $vsat
    set brms $now
}

bind . <Control-Key-c> {set run 0}

#altr 214 4 0.0001
label .a  -text "item default value:" -width 50
label .b  -textvariable va -fg blue
label .aa -text "now value:"
label .bb -textvariable varl -fg red
label .c  -textvariable item -fg red
#button .a -text [exec sed -n 214p default.lib | awk "{print \$4}"] -command {}
#button .b -text U0 -command {altr 214 4 0.0001}
#button .c -text UA -command {altr 215 4 0.1e-9}
#button .d -text UB -command {altr 216 4 0.1e-18}
menu .m
. configure -menu .m
.m add command -label U0   -command {set l 214; set c 4; set varl [exec sed -n ${l}p l55sp_v151_FS_NVM_V2.lib | awk "{print \$[set c]}"]; set item U0; set va [exec sed -n ${l}p default.lib | awk "{print \$[set c]}"]; set brms ""; set var ""; set int [exp $va]}
.m add command -label UA   -command {set l 215; set c 4; set varl [exec sed -n ${l}p l55sp_v151_FS_NVM_V2.lib | awk "{print \$[set c]}"]; set item UA; set va [exec sed -n ${l}p default.lib | awk "{print \$[set c]}"]; set brms ""; set var ""; set int [exp $va]}
.m add command -label UB   -command {set l 216; set c 4; set varl [exec sed -n ${l}p l55sp_v151_FS_NVM_V2.lib | awk "{print \$[set c]}"]; set item UB; set va [exec sed -n ${l}p default.lib | awk "{print \$[set c]}"]; set brms ""; set var ""; set int [exp $va]}
.m add command -label DSUB  -command {set l 217; set c 4; set item DSUB; foreach {varl va int} [settle $l $c] break; set brms ""; set var ""}
.m add command -label DROUT -command {set l 218; set c 4; set item DROUT; foreach {varl va int} [settle $l $c] break; set brms ""; set var ""}
.m add command -label PVAG  -command {set l 219; set c 4; set item PVAG; foreach {varl va int} [settle $l $c] break; set brms ""; set var ""}
.m add command -label CDSC  -command {set l 220; set c 4; set item CDSC; foreach {varl va int} [settle $l $c] break; set brms ""; set var ""}
.m add command -label CDSCB -command {set l 221; set c 4; set item CDSCB; foreach {varl va int} [settle $l $c] break; set brms ""; set var ""}
.m add command -label CDSCD -command {set l 222; set c 4; set item CDSCD; foreach {varl va int} [settle $l $c] break; set brms ""; set var ""}

entry  .cc -textvariable int
button .d -text RUN -command {if {$int!=""} {altr $l $c $int}}
label  .e -text "temp the best arg-rms"
entry  .f -textvariable brms
label  .g -text "temp the fittest value"
entry  .i -textvariable var
#button .e -text minv -command {altr 752 7 1}
pack .a .b .aa .bb .c .cc .d .e .f .g .i



proc exp val {
#if {$val>0} {set op 1} else {set op 0}
    if {[expr log10(abs($val))]>=0} {set pw 1} else {set pw 0}
    if $pw {set new "1e[expr int(log10(abs($val)))-2]"} else {set new "1e[expr int(log10(abs($val)))-3]"}
    #if $op {return $new} else {return [expr -$new]}
    return $new
}

proc settle {l c} {
    set varl [exec sed -n ${l}p l55sp_v151_FS_NVM_V2.lib | awk "{print \$[set c]}"]
    set va   [exec sed -n ${l}p default.lib | awk "{print \$[set c]}"]
    set int [exp $va]
    return "$varl $va $int"
}