2004-07-19 Adrian Dawe <adrian.dawe@multigig.com>
* src/{Makefile.am,controls.tcl,engUnits.tcl,gnuplot.tcl,
measure.tcl,nodeDialog.tcl,pkgIndex.tcl.in,readline.tcl,
spicewish,spicewish.tcl,tclspice_source.tcl,viewer.tcl}:
New and much improved tclspice CLI
This commit is contained in:
parent
c89ae6e9f5
commit
d913383038
|
|
@ -1,3 +1,10 @@
|
|||
2004-07-19 Adrian Dawe <adrian.dawe@multigig.com>
|
||||
|
||||
* src/{Makefile.am,controls.tcl,engUnits.tcl,gnuplot.tcl,
|
||||
measure.tcl,nodeDialog.tcl,pkgIndex.tcl.in,readline.tcl,
|
||||
spicewish,spicewish.tcl,tclspice_source.tcl,viewer.tcl}:
|
||||
New and much improved tclspice CLI
|
||||
|
||||
2004-07-12 Stefan Jones <stefan.jones@multigig.com>
|
||||
|
||||
* src/tclspice.c:
|
||||
|
|
|
|||
|
|
@ -171,8 +171,11 @@ TCL_PKG_PATH = @TCL_PACKAGE_PATH@
|
|||
|
||||
TCLSPICE_VERSION = @VERSION@
|
||||
|
||||
TCL_FILES = libspice.so pkgIndex.tcl measure_spice.pl spicepp.pl \
|
||||
tclspice_source.tcl spicepp.tcl
|
||||
TCL_SOURCE = controls.tcl measure.tcl spicepp.tcl \
|
||||
engUnits.tcl nodeDialog.tcl spicewish.tcl viewer.tcl \
|
||||
gnuplot.tcl readline.tcl pkgIndex.tcl
|
||||
|
||||
TCL_FILES = libspice.so measure_spice.pl spicepp.pl $(TCL_SOURCE)
|
||||
|
||||
LIBSPICE_OBJS = tclspice.o
|
||||
|
||||
|
|
@ -195,15 +198,16 @@ install-tcl-recursive:
|
|||
|| case "$$amf" in *=*) exit 1;; *k*) fail=yes;; *) exit 1;; esac; \
|
||||
done;
|
||||
|
||||
install-tclspice: ${TCL_FILES}
|
||||
install-tclspice: $(TCL_FILES)
|
||||
$(mkinstalldirs) $(DESTDIR)$(TCL_PKG_PATH)
|
||||
$(INSTALL_DATA) libspice.so $(DESTDIR)$(TCL_PKG_PATH)
|
||||
$(mkinstalldirs) $(DESTDIR)$(TCL_PKG_PATH)/spice
|
||||
$(INSTALL_DATA) pkgIndex.tcl $(DESTDIR)$(TCL_PKG_PATH)/spice
|
||||
$(INSTALL_DATA) tclspice_source.tcl $(DESTDIR)$(TCL_PKG_PATH)/spice
|
||||
$(INSTALL_DATA) spicepp.tcl $(DESTDIR)$(TCL_PKG_PATH)/spice
|
||||
$(INSTALL_PROGRAM) spicepp.pl $(DESTDIR)$(TCL_PKG_PATH)/spice
|
||||
$(INSTALL_PROGRAM) measure_spice.pl $(DESTDIR)$(TCL_PKG_PATH)/spice
|
||||
@for f in $(TCL_SOURCE) ; do \
|
||||
echo $(INSTALL_DATA) $$f $(DESTDIR)$(TCL_PKG_PATH)/spice; \
|
||||
$(INSTALL_DATA) $$f $(DESTDIR)$(TCL_PKG_PATH)/spice; \
|
||||
done
|
||||
$(mkinstalldirs) $(DESTDIR)$(bindir)
|
||||
$(INSTALL_PROGRAM) spicewish $(DESTDIR)$(bindir)
|
||||
|
||||
|
|
@ -225,4 +229,4 @@ tcl-recursive:
|
|||
(cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) all) \
|
||||
|| case "$$amf" in *=*) exit 1;; *k*) fail=yes;; *) exit 1;; esac; \
|
||||
done;
|
||||
make ${TCL_FILES}
|
||||
make $(TCL_FILES)
|
||||
|
|
|
|||
|
|
@ -0,0 +1,43 @@
|
|||
|
||||
namespace eval controls {
|
||||
|
||||
variable wName ".controls"
|
||||
|
||||
proc create { } {
|
||||
variable wName
|
||||
|
||||
if {[winfo exists $wName]} {
|
||||
wm deiconify $wName
|
||||
raise $wName
|
||||
return
|
||||
}
|
||||
|
||||
set w [toplevel $wName]
|
||||
|
||||
pack [button $w.bRun -text "Run" -command "spicewish::run" -width 8] -fill x
|
||||
pack [button $w.bHalt -text "Halt" -command "spicewish::halt"] -fill x
|
||||
pack [button $w.bPlot -text "Plot" -command "spicewish::plot"] -fill x
|
||||
pack [button $w.bExit -text "Exit" -command "[namespace current]::Exit"] -fill x
|
||||
pack [label $w.lFake -height 1] -fill x
|
||||
}
|
||||
|
||||
proc Exit { } {
|
||||
set widget_list [winfo children .]
|
||||
|
||||
# test if tk console ( .tkcon ) is being used
|
||||
if [info exists ::CAD_HOME] {
|
||||
|
||||
# kill only the spicewish based windows
|
||||
foreach winname $widget_list {
|
||||
# viewer windows
|
||||
if {[regexp {.tclspice[0-9]+} $winname]} {
|
||||
wm withdraw $winname
|
||||
}
|
||||
if { $winname == ".controls" } {
|
||||
wm withdraw ".controls"
|
||||
}
|
||||
|
||||
}
|
||||
} else { exit }
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,86 @@
|
|||
|
||||
namespace eval eng {
|
||||
|
||||
proc float_eng { num {forceunit ""} } {
|
||||
|
||||
set significant_digits 4 ;#- mininum signficant digits to show - might show more e.g. 125 will be shown no matter what
|
||||
|
||||
#lookup hashes
|
||||
set table_eng_float_MSC(T) 1e+12
|
||||
set table_eng_float_MSC(G) 1e+9
|
||||
set table_eng_float_MSC(M) 1e+6
|
||||
set table_eng_float_MSC(K) 1e+3
|
||||
set table_eng_float_MSC(\n) 1; # Will need to change?
|
||||
set table_eng_float_MSC(m) 1e-3
|
||||
set table_eng_float_MSC(u) 1e-6
|
||||
set table_eng_float_MSC(\u03BC) 1e-6
|
||||
set table_eng_float_MSC(n) 1e-9
|
||||
set table_eng_float_MSC(p) 1e-12
|
||||
set table_eng_float_MSC(f) 1e-15
|
||||
set table_eng_float_MSC(a) 1e-18
|
||||
|
||||
#inverse hash
|
||||
set table_float_eng_MSC(1e+12)" T"
|
||||
set table_float_eng_MSC(1e+9) " G"
|
||||
set table_float_eng_MSC(1e+6) " M"
|
||||
set table_float_eng_MSC(1e+3) " K"
|
||||
set table_float_eng_MSC(1) " "
|
||||
set table_float_eng_MSC(1e-3) " m"
|
||||
set table_float_eng_MSC(1e-6) " \u03BC"
|
||||
set table_float_eng_MSC(1e-9) " n"
|
||||
set table_float_eng_MSC(1e-12) " p"
|
||||
set table_float_eng_MSC(1e-15) " f"
|
||||
set table_float_eng_MSC(1e-18) " a"
|
||||
|
||||
|
||||
set indexes [lsort -real -decreasing "[array names table_float_eng_MSC]"]
|
||||
|
||||
set out {}; # If no suffix found, return number as is
|
||||
|
||||
if "$num != 0" {
|
||||
foreach index $indexes {
|
||||
|
||||
set newnum "[expr {$num / $index}]"
|
||||
set whole 0
|
||||
set fraction 0; # In case of integer input
|
||||
|
||||
# regexp {^(\d+)} $newnum whole; # Messy!
|
||||
# Uses stupid variable to save having to do two regexp's
|
||||
regexp {^(\d+)\.*(\d*)} $newnum stupid whole fraction
|
||||
|
||||
if {[expr {[string match {*e*} $newnum] == 0}] && \
|
||||
[expr {$whole >0 }] } {
|
||||
|
||||
set suf "$table_float_eng_MSC($index)"
|
||||
|
||||
#work out how many decimal places to show - fixed to 4 significant digits
|
||||
set decimal_length_to_show [expr (($significant_digits - 1) - [string length $whole])]
|
||||
|
||||
if {$decimal_length_to_show >= 0} {
|
||||
|
||||
if { $fraction == "" } {
|
||||
set newnm $whole
|
||||
} else {
|
||||
#need some decimal places to give the resolution required
|
||||
set newnum "$whole.[string range $fraction 0 [expr ($decimal_length_to_show)]]"
|
||||
}
|
||||
|
||||
} else {
|
||||
#no decimal places
|
||||
set newnum $whole ;#- just use the whole, no decimals
|
||||
}
|
||||
|
||||
set out "$newnum$suf"
|
||||
return "$out"
|
||||
break
|
||||
} else {
|
||||
#puts "[expr {fmod($newnum,1)}] is not big enough"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if {[string equal $out {}]} {
|
||||
return $num
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,63 @@
|
|||
|
||||
namespace eval gnuplot {
|
||||
|
||||
proc writeDataFile { plotNum args } {
|
||||
|
||||
set fileName "gnuplot.dat"
|
||||
set fileId [open $fileName "w"]
|
||||
|
||||
set plot_list "[spicewish::vectors::defaultScale $plotNum] $args"
|
||||
|
||||
puts $fileId "// $plot_list"
|
||||
|
||||
for {set dPoint 0} {$dPoint < [spice::plot_datapoints $plotNum]} {incr dPoint} {
|
||||
|
||||
for {set i 0} {$i < [llength $plot_list]} {incr i} {
|
||||
set vecName [lindex $plot_list $i]
|
||||
puts -nonewline $fileId "[spice::plot_get_value $vecName $plotNum $dPoint]\t"
|
||||
}
|
||||
puts $fileId ""
|
||||
}
|
||||
|
||||
|
||||
close $fileId
|
||||
}
|
||||
|
||||
proc writeCommandFile { plotNum args } {
|
||||
set fileName "gnuplot.cmd"
|
||||
set fileId [open $fileName "w"]
|
||||
|
||||
puts $fileId "set title \"[spice::plot_title $plotNum]\""
|
||||
|
||||
puts $fileId "set xlabel \"[spicewish::vectors::defaultScale $plotNum]\""
|
||||
puts $fileId "set ylabel \" \""
|
||||
puts $fileId "plot \\"
|
||||
|
||||
for {set pCnt 0} {$pCnt < [llength $args]} {incr pCnt} {
|
||||
set plotName [lindex $args $pCnt]
|
||||
|
||||
if {$pCnt ==[expr [llength $args] -1]} {
|
||||
puts $fileId "\"gnuplot.dat\" using 1:[expr $pCnt +2] with lines title \"$plotName\""
|
||||
} else {
|
||||
puts $fileId "\"gnuplot.dat\" using 1:[expr $pCnt +2] with lines title \"$plotName\", \\"
|
||||
}
|
||||
}
|
||||
|
||||
puts $fileId "pause -1 \"Hit return to exit\""
|
||||
|
||||
close $fileId
|
||||
}
|
||||
|
||||
proc plot { args } {
|
||||
set plotNum 0
|
||||
|
||||
eval "set validVecs \[spicewish::vectors::validVectorList $plotNum $args \]"
|
||||
|
||||
if {$validVecs == ""} {
|
||||
puts "Error: no valid vectors"
|
||||
return
|
||||
}
|
||||
eval writeCommandFile $plotNum $validVecs
|
||||
eval writeDataFile $plotNum $validVecs
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,315 @@
|
|||
|
||||
namespace eval meas_dialog {
|
||||
|
||||
variable measCnt 1
|
||||
variable nName{} ""
|
||||
variable cycleCnt{} ""
|
||||
variable freq_d{} ""
|
||||
variable riseTime_d{} ""
|
||||
variable _propDelay{} ""
|
||||
variable _riseTime_20{} ""
|
||||
variable VDD 2.5
|
||||
|
||||
|
||||
proc create_widget { } {
|
||||
variable measCnt
|
||||
variable nName
|
||||
|
||||
set w ".meas${measCnt}"
|
||||
toplevel $w
|
||||
|
||||
pack [label $w.lNode -textvariable [namespace current]::nName($measCnt) -background "grey" -width 20]
|
||||
pack [frame $w.fFreq] -fill x
|
||||
pack [label $w.fFreq.l -text "Freq :"] -side left
|
||||
pack [label $w.fFreq.v -textvariable spicewish::meas_dialog::freq_d($measCnt)] -side right
|
||||
pack [frame $w.fRiseTime] -fill x
|
||||
pack [label $w.fRiseTime.l -text "RiseTime :"] -side left
|
||||
pack [label $w.fRiseTime.v -textvariable [namespace current]::riseTime_d($measCnt)] -side right
|
||||
pack [frame $w.fCycleCnt] -fill x
|
||||
pack [label $w.fCycleCnt.l -text "CycleCnt :"] -side left
|
||||
pack [label $w.fCycleCnt.v -textvariable [namespace current]::cycleCnt($measCnt)] -side right
|
||||
pack [button $w.bExit -text "Close"]
|
||||
bind $w.bExit <ButtonPress-1> { spicewish::meas_dialog::destroy_widget [winfo parent %W] }
|
||||
|
||||
}
|
||||
|
||||
proc destroy_widget { w } {
|
||||
|
||||
if {![scan $w ".meas%i" index]} {return}
|
||||
|
||||
# Remove all associated triggers
|
||||
catch { spice::unregisterTrigger ${index}_propDelay }
|
||||
catch { spice::unregisterTrigger ${index}_riseTime_20 }
|
||||
catch { spice::unregisterTrigger ${index}_riseTime_80 }
|
||||
|
||||
after 10 destroy $w ;# can't destroy widget beacuse of bind to button
|
||||
}
|
||||
|
||||
proc TriggerCallBack { args } {
|
||||
variable nName
|
||||
variable freq_d
|
||||
variable cycleCnt
|
||||
variable riseTime_d
|
||||
variable _propDelay
|
||||
variable _riseTime_20
|
||||
|
||||
# set nName [lindex $args 0] ;# - NodeName
|
||||
set tTime [lindex $args 1] ;# - Trigger Time
|
||||
set sStep [expr [lindex $args 2] -1] ;# - pop trigger returns steps completed not spice step
|
||||
set mName [lindex $args 5] ;# - MarkerName
|
||||
|
||||
if {![scan $mName "%i_" index]} { return }
|
||||
|
||||
if {$mName == "${index}_propDelay"} {
|
||||
set freq_d($index) "[spicewish::eng::float_eng [expr 1/($tTime - $_propDelay($index))]]Hz"
|
||||
set _propDelay($index) $tTime
|
||||
incr cycleCnt($index)
|
||||
}
|
||||
if {$mName == "${index}_riseTime_20"} {
|
||||
set _riseTime_20($index) $tTime
|
||||
}
|
||||
|
||||
if {$mName == "${index}_riseTime_80"} {
|
||||
set riseTime_d($index) "[spicewish::eng::float_eng [expr $tTime - $_riseTime_20($index)]]s"
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
proc stepCallBack { } {
|
||||
|
||||
}
|
||||
|
||||
proc registerTrigger { } {
|
||||
|
||||
variable measCnt
|
||||
variable nName
|
||||
variable VDD
|
||||
|
||||
spice::registerTrigger $nName($measCnt) [expr $VDD *0.5] [expr $VDD *0.5] 1 ${measCnt}_propDelay
|
||||
spice::registerTrigger $nName($measCnt) [expr $VDD *0.2] [expr $VDD *0.2] 1 ${measCnt}_riseTime_20
|
||||
spice::registerTrigger $nName($measCnt) [expr $VDD *0.8] [expr $VDD *0.8] 1 ${measCnt}_riseTime_80
|
||||
}
|
||||
|
||||
proc add { nodeName } {
|
||||
variable measCnt
|
||||
variable nName
|
||||
variable cycleCnt
|
||||
variable freq_d
|
||||
variable riseTime_d
|
||||
variable _propDelay
|
||||
variable _riseTime_20
|
||||
|
||||
if {$spice::steps_completed == 0 } {
|
||||
return
|
||||
}
|
||||
|
||||
set nName(${measCnt}) $nodeName
|
||||
set freq_d(${measCnt}) 0
|
||||
set cycleCnt(${measCnt}) 0
|
||||
set riseTime_d(${measCnt}) 0
|
||||
set _propDelay(${measCnt}) 0
|
||||
set _riseTime_20(${measCnt}) 0
|
||||
|
||||
create_widget
|
||||
|
||||
registerTrigger
|
||||
|
||||
incr measCnt
|
||||
}
|
||||
|
||||
spice::registerTriggerCallback [namespace current]::TriggerCallBack
|
||||
}
|
||||
|
||||
|
||||
namespace eval meas_markers {
|
||||
|
||||
variable VDD 2.5
|
||||
|
||||
proc preciseTrigPoint { trig_stepV trig_stepT prev_stepV prev_stepT Vtrigger} {
|
||||
|
||||
set spiceTimeStep [expr $trig_stepT - $prev_stepT]
|
||||
set Vrate_through_trig [expr ($trig_stepV - $prev_stepV) / $spiceTimeStep]
|
||||
set trigger_delta_time [expr (0 - (($trig_stepV - $Vtrigger) / $Vrate_through_trig))]
|
||||
set tTrigger [expr $trig_stepT + $trigger_delta_time ]
|
||||
|
||||
return $tTrigger
|
||||
}
|
||||
|
||||
proc riseTime { w x y } {
|
||||
|
||||
variable VDD
|
||||
|
||||
set index [marker_position $w $x $y]
|
||||
|
||||
if {$index == -1} { return }
|
||||
|
||||
# find the time when crosses 20% of VDD
|
||||
for {set i $index} {$i < [nodeData length]} {incr i} {
|
||||
set cur_V [nodeData index $i]
|
||||
set cur_T [timeData index $i]
|
||||
set prev_V [nodeData index [expr $i -1]]
|
||||
set prev_T [timeData index [expr $i -1]]
|
||||
|
||||
if {$cur_V > [expr $VDD *0.2]} {
|
||||
set x1 [preciseTrigPoint $cur_V $cur_T $prev_V $prev_T [expr $VDD *0.2]]
|
||||
set y1 [expr $VDD *0.2]
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
# find the time when crosses 80% of VDD
|
||||
for {set i $index} {$i < [nodeData length]} {incr i} {
|
||||
set cur_V [nodeData index $i]
|
||||
set cur_T [timeData index $i]
|
||||
set prev_V [nodeData index [expr $i -1]]
|
||||
set prev_T [timeData index [expr $i -1]]
|
||||
|
||||
if {$cur_V > [expr $VDD * 0.8]} {
|
||||
set x2 [ preciseTrigPoint $cur_V $cur_T $prev_V $prev_T [expr $VDD *0.8]]
|
||||
set y2 [expr $VDD *0.8]
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
$w line create "m_riseTime" -xdata {$x1 $x2} \
|
||||
-ydata {$y1 $y2} \
|
||||
-color "black" \
|
||||
-label "" \
|
||||
-symbol "cross"
|
||||
|
||||
set RiseTime [expr $x2 - $x1]
|
||||
set xd [expr $x1 + (($x2 - $x1) /2)]
|
||||
set yd [expr $y1 + (($y2 - $y1) /2)]
|
||||
|
||||
$w marker create text -text "[spicewish::eng::float_eng $RiseTime]s" \
|
||||
-coords {$xd $yd} \
|
||||
-name "m_riseTime_t" \
|
||||
-anchor "nw"
|
||||
|
||||
blt::vector destroy nodeData
|
||||
blt::vector destroy timeData
|
||||
}
|
||||
|
||||
proc propDelay { w x y } {
|
||||
|
||||
variable VDD
|
||||
|
||||
set index [marker_position $w $x $y]
|
||||
|
||||
if {$index == -1} { return}
|
||||
|
||||
# find the time when crosses 50% of VDD
|
||||
for {set i $index} {$i < [nodeData length]} {incr i} {
|
||||
set cur_V [nodeData index $i]
|
||||
set cur_T [timeData index $i]
|
||||
set prev_V [nodeData index [expr $i -1]]
|
||||
set prev_T [timeData index [expr $i -1]]
|
||||
|
||||
if {$cur_V > [expr $VDD * 0.5]} {
|
||||
set x1 [preciseTrigPoint $cur_V $cur_T $prev_V $prev_T [expr $VDD *0.5]]
|
||||
set y1 [expr $VDD * 0.5]
|
||||
set index $i
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
# second crossing of 50% VDD
|
||||
set state 0
|
||||
for {set i $index} {$i < [nodeData length]} {incr i} {
|
||||
set cur_V [nodeData index $i]
|
||||
set cur_T [timeData index $i]
|
||||
set prev_V [nodeData index [expr $i -1]]
|
||||
set prev_T [timeData index [expr $i -1]]
|
||||
|
||||
if {$state && ($cur_V > [expr $VDD * 0.5])} {
|
||||
set x2 [preciseTrigPoint $cur_V $cur_T $prev_V $prev_T [expr $VDD * 0.5]]
|
||||
set y2 [expr $VDD * 0.5]
|
||||
set state 0
|
||||
break
|
||||
} elseif {(!$state) && ($cur_V < [expr $VDD * 0.5])} {
|
||||
set state 1
|
||||
}
|
||||
}
|
||||
|
||||
$w line create "m_riseTime" -xdata {$x1 $x2} \
|
||||
-ydata {$y1 $y2} \
|
||||
-color "black" \
|
||||
-label "" \
|
||||
-symbol "cross"
|
||||
|
||||
set Freq [expr 1/($x2 - $x1)]
|
||||
set xd [expr $x1 + (($x2 - $x1) /2)]
|
||||
set yd [expr $y1 + (($y2 - $y1) /2)]
|
||||
|
||||
$w marker create text -text "[spicewish::eng::float_eng $Freq]Hz" \
|
||||
-coords {$xd $yd} \
|
||||
-name "m_riseTime_t" \
|
||||
-anchor "nw" \
|
||||
-xoffset 10 -yoffset 10
|
||||
|
||||
blt::vector destroy nodeData
|
||||
blt::vector destroy timeData
|
||||
}
|
||||
|
||||
proc marker_position { w x y } {
|
||||
|
||||
variable VDD
|
||||
set VDD [spice::get_value vdd [ expr $::spice::steps_completed -1]]
|
||||
|
||||
catch { $w element delete "m_riseTime" }
|
||||
catch { $w marker delete "m_riseTime_t" }
|
||||
|
||||
set x [expr $x - 10]
|
||||
set y [expr $y - 28]
|
||||
|
||||
set currentNode [$w element get current]
|
||||
|
||||
if {$currentNode == "" } { return -1 }
|
||||
|
||||
set xaxis [$w xaxis invtransform $x]
|
||||
set yaxis [$w yaxis invtransform $y]
|
||||
|
||||
# get blt vectors
|
||||
blt::vector create nodeData
|
||||
blt::vector create timeData
|
||||
|
||||
spice::spicetoblt time timeData
|
||||
spice::spicetoblt $currentNode nodeData
|
||||
|
||||
if {![$w element closest $x $y closestData -halo 5.0i]} {return -1}
|
||||
|
||||
set prev_V [nodeData index $closestData(index)]
|
||||
|
||||
# test if rising edge 20-80%
|
||||
if {($prev_V < [expr $VDD *0.2]) || ($prev_V >[expr $VDD * 0.8])} {
|
||||
return -1
|
||||
}
|
||||
|
||||
# test next voltage is greater (rising edge)
|
||||
if {$prev_V > [nodeData index [expr $closestData(index) +1]]} {
|
||||
return -1
|
||||
}
|
||||
|
||||
# back track index until rise of waveform
|
||||
for {set index $closestData(index)} { $index > 0} {incr index -1} {
|
||||
set cur_V [nodeData index $index]
|
||||
if {$cur_V > $prev_V} { break }
|
||||
set prev_V [nodeData index $index]
|
||||
}
|
||||
return $index
|
||||
}
|
||||
|
||||
proc release { w x y } {
|
||||
|
||||
catch { $w element delete "m_riseTime" }
|
||||
$w marker delete "m_riseTime_t"
|
||||
}
|
||||
|
||||
proc bindings { w } {
|
||||
|
||||
bind $w <Key-F1> { spicewish::meas_markers::release %W.g %x %y }
|
||||
bind $w <Key-F2> { spicewish::meas_markers::riseTime %W.g %x %y }
|
||||
bind $w <Key-F3> { spicewish::meas_markers::propDelay %W.g %x %y}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,172 @@
|
|||
|
||||
|
||||
namespace eval nodeDialog {
|
||||
|
||||
variable w ".nodeSelect"
|
||||
variable plot_title
|
||||
variable selection
|
||||
variable selectionCnt
|
||||
|
||||
proc create { } {
|
||||
variable w
|
||||
|
||||
if {[winfo exists $w]} {
|
||||
raise $w
|
||||
return
|
||||
}
|
||||
|
||||
toplevel $w
|
||||
|
||||
pack [frame $w.plots] -fill x
|
||||
pack [listbox $w.plots.lst -height 3 \
|
||||
-width 50 \
|
||||
-yscrollcommand {.nodeSelect.plots.sx set} \
|
||||
] -fill x -expand 1 -side left
|
||||
|
||||
pack [scrollbar $w.plots.sx -orient vertical \
|
||||
-width 9 \
|
||||
-command {.nodeSelect.plots.lst yview}\
|
||||
] -fill y -side right
|
||||
|
||||
|
||||
pack [frame $w.nodes] -fill both -expand 1
|
||||
pack [blt::hierbox $w.nodes.hb -hideroot 1 \
|
||||
-yscrollcommand {.nodeSelect.nodes.sx set} \
|
||||
-selectbackground "#e6e6e6" \
|
||||
] -fill both -expand 1 -side left
|
||||
|
||||
pack [scrollbar $w.nodes.sx -orient vertical \
|
||||
-width 9 \
|
||||
-command {.nodeSelect.nodes.hb yview} \
|
||||
] -fill y -side right
|
||||
|
||||
$w.nodes.hb bind all <Button-1> {
|
||||
set hierbox_path %W
|
||||
set index [$hierbox_path index current]
|
||||
set nodeName [$hierbox_path entry cget $index -label]
|
||||
set plotTypeName [spice::plot_typename [.nodeSelect.plots.lst curselection]]
|
||||
set listPos [lsearch $::spicewish::nodeDialog::selection($plotTypeName) $nodeName]
|
||||
|
||||
if { [ $hierbox_path entry cget $index -labelcolor] == "black"} {
|
||||
$hierbox_path entry configure $index -labelcolor "blue"
|
||||
$hierbox_path configure -selectforeground blue
|
||||
|
||||
if {$listPos == -1 } {
|
||||
lappend spicewish::nodeDialog::selection($plotTypeName) $nodeName
|
||||
}
|
||||
} else {
|
||||
$hierbox_path entry configure $index -labelcolor "black"
|
||||
$hierbox_path configure -selectforeground black
|
||||
|
||||
set spicewish::nodeDialog::selection($plotTypeName) [lreplace $::spicewish::nodeDialog::selection($plotTypeName) $listPos $listPos]
|
||||
|
||||
|
||||
}
|
||||
set spicewish::nodeDialog::selectionCnt [llength $::spicewish::nodeDialog::selection($plotTypeName)]
|
||||
}
|
||||
pack [frame $w.fcont] -fill x
|
||||
pack [button $w.fcont.bNodeCnt -textvariable spicewish::nodeDialog::selectionCnt \
|
||||
-padx 1m \
|
||||
-command spicewish::nodeDialog::clearSelection \
|
||||
] -side left
|
||||
pack [button $w.fcont.bPlot -text "Plot" \
|
||||
-command spicewish::nodeDialog::plotSelection ]
|
||||
|
||||
bind $w.plots.lst <ButtonRelease-1> { spicewish::nodeDialog::selectPlot %W }
|
||||
|
||||
wm protocol $w WM_TAKE_FOCUS { spicewish::nodeDialog::currentPlots }
|
||||
|
||||
currentPlots
|
||||
}
|
||||
|
||||
proc plotSelection { } {
|
||||
variable selection
|
||||
|
||||
set plotNum [.nodeSelect.plots.lst curselection]
|
||||
set plotTypeName [spice::plot_typename $plotNum]
|
||||
eval "spicewish::viewer::oplot $plotNum $selection($plotTypeName)"
|
||||
}
|
||||
|
||||
proc loadSelection { } {
|
||||
variable selection
|
||||
variable selectionCnt
|
||||
|
||||
set plotTypeName [spice::plot_typename [.nodeSelect.plots.lst curselection]]
|
||||
|
||||
set w_hb ".nodeSelect.nodes.hb"
|
||||
|
||||
for {set index 1} { $index <= [$w_hb index end] } {incr index} {
|
||||
if {[$w_hb index $index] == "" } {continue}
|
||||
|
||||
set name [$w_hb entry cget $index -label]
|
||||
set listPos [lsearch $selection($plotTypeName) $name]
|
||||
|
||||
if {$listPos != -1} {
|
||||
$w_hb entry configure $index -labelcolor "blue"
|
||||
}
|
||||
}
|
||||
set selectionCnt [llength $selection($plotTypeName)]
|
||||
}
|
||||
|
||||
proc clearSelection { } {
|
||||
variable selection
|
||||
|
||||
set plotTypeName [spice::plot_typename [.nodeSelect.plots.lst curselection]]
|
||||
set selection($plotTypeName) ""
|
||||
|
||||
populateTree [.nodeSelect.plots.lst curselection]
|
||||
}
|
||||
|
||||
proc currentPlots { } {
|
||||
variable plot_title
|
||||
variable selection
|
||||
|
||||
set index 0
|
||||
while { ![catch {set t [spice::plot_name $index]} ] } {
|
||||
|
||||
set p_title [spice::plot_title $index]
|
||||
set p_typeName [spice::plot_typename $index]
|
||||
|
||||
set plot_title($index) "$p_typeName :$p_title"
|
||||
|
||||
if {![info exists selection($p_typeName)]} {
|
||||
set selection($p_typeName) ""
|
||||
}
|
||||
|
||||
incr index
|
||||
}
|
||||
|
||||
.nodeSelect.plots.lst delete 0 end
|
||||
|
||||
for {set i 0} {$i < [array size plot_title]} {incr i} {
|
||||
.nodeSelect.plots.lst insert end $plot_title($i)
|
||||
}
|
||||
|
||||
.nodeSelect.plots.lst selection set 0
|
||||
populateTree 0
|
||||
|
||||
}
|
||||
|
||||
proc populateTree { index } {
|
||||
|
||||
set w ".nodeSelect.nodes.hb"
|
||||
$w delete 0
|
||||
|
||||
set defaultScale [spice::plot_defaultscale $index]
|
||||
|
||||
foreach node [spice::plot_variables $index] {
|
||||
set text ": [spicewish::vectors::type $index $node], real, [spice::plot_datapoints $index]"
|
||||
if {$node == $defaultScale} {
|
||||
set text "$text \[default scale\]"
|
||||
}
|
||||
|
||||
$w insert -at 0 end $node -labelfont {times 9} -text $text -labelcolor "black"
|
||||
}
|
||||
loadSelection
|
||||
}
|
||||
|
||||
proc selectPlot { w } {
|
||||
set index [$w curselection]
|
||||
populateTree $index
|
||||
}
|
||||
}
|
||||
|
|
@ -72,13 +72,47 @@ proc Loadspice { version dir } {
|
|||
puts "DefineLinestyle $linestyleid $mask"
|
||||
}
|
||||
|
||||
proc spice_init_gui { spicefile } {
|
||||
if { ! [ winfo exists .controls ] } {
|
||||
source "%LIB_DIR%/spice/tclspice_source.tcl" ;#- only load procs when gui needed
|
||||
}
|
||||
spicewish::init_gui $spicefile
|
||||
# proc spice_init_gui { spicefile } {
|
||||
# if { ! [ winfo exists .controls ] } {
|
||||
# source "/usr/lib/spice/tclspice_source.tcl" ;#- only load procs when gui needed
|
||||
# }
|
||||
# spicewish::init_gui $spicefile
|
||||
# }
|
||||
|
||||
proc spice_init_gui { fileName {gui 0} {batchMode 0}} {
|
||||
|
||||
# source tclcode
|
||||
if {[info procs spicewish::plot] == ""} {
|
||||
source [file join "spice/spicewish.tcl"]
|
||||
}
|
||||
|
||||
if {!$batchMode} { spice::version }
|
||||
|
||||
if {$fileName != ""} {
|
||||
|
||||
switch [file extension $fileName] {
|
||||
".tcl" {
|
||||
source $fileName
|
||||
}
|
||||
".raw" {
|
||||
spice::load $fileName
|
||||
}
|
||||
default {
|
||||
spice::source $fileName
|
||||
|
||||
if {$batchMode} {
|
||||
spice::run
|
||||
spice::write out.raw
|
||||
exit
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if {$gui == 0} {
|
||||
wm withdraw .
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
set ::spice_version $version
|
||||
set ::spice_library $dir
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,45 @@
|
|||
|
||||
namespace eval readline {
|
||||
|
||||
proc completer { word start end line } {
|
||||
|
||||
if {[info procs ::tclreadline::TryFromList] == ""} {
|
||||
::tclreadline::ScriptCompleter $word $start $end $line
|
||||
}
|
||||
|
||||
set command [lindex $line 0]
|
||||
|
||||
switch $command {
|
||||
"spicewish\:\:source" - "spice\:\:source" - "source" {
|
||||
return [::tclreadline::TryFromList $word [glob *]]
|
||||
}
|
||||
"spicewish\:\:load" - "spice\:\:load" - "load" {
|
||||
return [::tclreadline::TryFromList $word [glob *]]
|
||||
}
|
||||
"spicewish\:\:plot" - "plot" {
|
||||
return [::tclreadline::TryFromList $word [spice::plot_variables 0]]
|
||||
}
|
||||
"spicewish\:\:iplot" - "iplot" {
|
||||
return [::tclreadline::TryFromList $word [spice::plot_variables 0]]
|
||||
}
|
||||
"spicewish\:\:measDialog" - "measDialog" {
|
||||
return [::tclreadline::TryFromList $word [spice::plot_variables 0]]
|
||||
}
|
||||
"spicewish\:\:write2gnuplot" - "write2gnuplot" {
|
||||
return [::tclreadline::TryFromList $word [spice::plot_variables 0]]
|
||||
}
|
||||
|
||||
"spicewish\:\:run" - "run" {
|
||||
return ""
|
||||
}
|
||||
"spicewish\:\:halt" - "halt" {
|
||||
return ""
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
::tclreadline::ScriptCompleter $word $start $end $line
|
||||
}
|
||||
|
||||
::tclreadline::readline customcompleter "spicewish::readline::completer"
|
||||
}
|
||||
220
src/spicewish
220
src/spicewish
|
|
@ -4,124 +4,126 @@
|
|||
# the next line starts SpiceWish interactively with the given file name \
|
||||
exec wish "$0" "$@"
|
||||
|
||||
|
||||
namespace eval spicewish {
|
||||
|
||||
# load tclspice
|
||||
package require spice
|
||||
package require spice
|
||||
package require tclreadline
|
||||
|
||||
proc usage { } {
|
||||
puts "usage: spicewish \[options ...\] \[inputfile ...\]"
|
||||
puts " -b Run in batch mode."
|
||||
puts " -pp Execute spicePP on given file."
|
||||
puts " -cm load Xspice codemodel."
|
||||
puts " -version Display version number."
|
||||
puts ""
|
||||
exit
|
||||
}
|
||||
proc spicewish_usage { } {
|
||||
puts "usage: spicewish \[options ...\] \[inputfile ...\]"
|
||||
puts " -b Run in batch mode."
|
||||
puts " -pp Execute spicePP on given file."
|
||||
puts " -version Display version number."
|
||||
puts ""
|
||||
exit
|
||||
}
|
||||
|
||||
proc version { } {
|
||||
puts " $::spice_version\n"
|
||||
exit
|
||||
}
|
||||
proc run_spicepp { fileName } {
|
||||
|
||||
proc run_spicepp { fileName } {
|
||||
# load tcl code to run spicePP (perl)
|
||||
source [file join $::spice_library "spice/spicepp.tcl"]
|
||||
|
||||
# load tcl code to run spicePP (perl)
|
||||
source [file join $::spice_library "spice/spicepp.tcl"]
|
||||
puts ""
|
||||
# check if file contains Hspice statemenst
|
||||
if {[spicepp::checkHSpiceFormat $fileName]} {
|
||||
|
||||
puts ""
|
||||
# check if file contains Hspice statemenst
|
||||
if {[spicepp::checkHSpiceFormat $fileName]} {
|
||||
|
||||
set ppFileName [spicepp::convert $fileName]
|
||||
if {$ppFileName == ""} {
|
||||
|
||||
puts "spicepp: Error translating file '$fileName'."
|
||||
exit
|
||||
}
|
||||
puts "spicewish: sourcing '$ppFileName'."
|
||||
return $ppFileName
|
||||
} else {
|
||||
puts "spicepp: '$fileName' contains no Hspice statements."
|
||||
puts "spicewish: sourcing '$fileName'."
|
||||
return $fileName
|
||||
}
|
||||
}
|
||||
|
||||
proc load { argv argc } {
|
||||
set fileName ""
|
||||
set mode_batch 0
|
||||
set mode_spicePP 0
|
||||
set codeModels {}
|
||||
|
||||
for {set i 0} {$i < $argc} {incr i} {
|
||||
set arg [lindex $argv $i]
|
||||
|
||||
if {[string match {-*} $arg]} {
|
||||
set val [lindex $argv [expr $i + 1]]
|
||||
|
||||
switch -glob -- $arg {
|
||||
-- - -argv {
|
||||
set argv [concat -- [lrange $argv $i end]]
|
||||
set argc [llength $argv]
|
||||
break
|
||||
}
|
||||
-h - -help { usage }
|
||||
-b { set mode_batch 1 }
|
||||
-version { version }
|
||||
-pp { set mode_spicePP 1 }
|
||||
-cm {
|
||||
set val [lindex $argv [incr i]]
|
||||
lappend codeModels $val
|
||||
}
|
||||
default { usage }
|
||||
}
|
||||
} elseif {[file isfile $arg]} {
|
||||
set fileName $arg
|
||||
}
|
||||
}
|
||||
|
||||
if {$fileName == "" } { usage }
|
||||
|
||||
if {[llength $codeModels] != 0} {
|
||||
foreach codeModel $codeModels {
|
||||
spice::codemodel $codeModel
|
||||
}
|
||||
}
|
||||
|
||||
if {$mode_spicePP} {
|
||||
set fileName [ run_spicepp $fileName ]
|
||||
}
|
||||
|
||||
if { [ file extension $fileName ] == ".tcl" } {
|
||||
source $fileName
|
||||
} else {
|
||||
spice_init_gui $fileName
|
||||
|
||||
if {$mode_batch} {
|
||||
# remove control widget
|
||||
wm withdraw .
|
||||
}
|
||||
}
|
||||
set ::spicewish_mode "standalone"
|
||||
}
|
||||
|
||||
proc tclreadline { } {
|
||||
# readline with prompt set to "tclspice > "
|
||||
if {$::tcl_interactive} {
|
||||
package require tclreadline
|
||||
proc ::tclreadline::prompt1 { } { return "tclspice > " }
|
||||
::tclreadline::Loop
|
||||
set ppFileName [spicepp::convert $fileName]
|
||||
if {$ppFileName == ""} {
|
||||
puts "spicepp: Error translating file '$fileName'."
|
||||
exit
|
||||
}
|
||||
puts "spicewish: sourcing '$ppFileName'."
|
||||
return $ppFileName
|
||||
} else {
|
||||
puts "spicepp: '$fileName' contains no Hspice statements."
|
||||
puts "spicewish: sourcing '$fileName'."
|
||||
return $fileName
|
||||
}
|
||||
}
|
||||
|
||||
proc spicewish_load { argv argc } {
|
||||
set fileName ""
|
||||
set mode_batch 0
|
||||
set mode_spicePP 0
|
||||
|
||||
for {set i 0} {$i < $argc} {incr i} {
|
||||
set arg [lindex $argv $i]
|
||||
|
||||
if {[string match {-*} $arg]} {
|
||||
set val [lindex $argv [expr $i + 1]]
|
||||
|
||||
switch -glob -- $arg {
|
||||
-- - -argv {
|
||||
set argv [concat -- [lrange $argv $i end]]
|
||||
set argc [llength $argv]
|
||||
break
|
||||
}
|
||||
-h - -help { spicewish_usage }
|
||||
-b { set ::mode_batch 1 }
|
||||
-version { spice::version }
|
||||
-pp { set mode_spicePP 1 }
|
||||
default { spicewish_usage }
|
||||
}
|
||||
} else {
|
||||
set fileName $arg
|
||||
}
|
||||
}
|
||||
|
||||
if {$fileName == "" } {
|
||||
spice_init_gui "" 0 $mode_batch
|
||||
return
|
||||
}
|
||||
|
||||
if {![file isfile $fileName]} { spicewish_usage }
|
||||
|
||||
if {$mode_spicePP} {
|
||||
set fileName [ run_spicepp $fileName ]
|
||||
}
|
||||
|
||||
spice_init_gui $fileName 0 $mode_batch
|
||||
}
|
||||
|
||||
proc Tclreadline { } {
|
||||
# readline with prompt set to "tclspice > "
|
||||
if {$::tcl_interactive} {
|
||||
proc ::tclreadline::prompt1 { } { return "tclspice -> " }
|
||||
|
||||
puts "tclspice ->"
|
||||
puts "tclspice ->"
|
||||
::tclreadline::Loop .tclspice-history
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
proc spicewish_import_namespaces { } {
|
||||
|
||||
# spice::
|
||||
namespace eval spice {
|
||||
namespace export ac help save alias sens alter altermod setcirc asciiplot jobs setplot aspice setscale bg let settype linearize shell bug listing shift show cdump maxstep showmod compose newhelp noise spec cross oldhelp spice dc op spice_data define spice_header deftype state delete plot_datapoints status delta plot_date step plot_get_value stop diff plot_name strcmp display plot_nvars tf disto plot_title dowhile plot_variables tran dump print transpose echo pz tutorial edit quit unalias else rehash undefine end repeat unlet reset fourier reshape version spicetoblt resume where get_output rspice get_param write goto running xgraph hardcopy rusage steps_completed blt_vnum codemodel loadsnap savesnap
|
||||
}
|
||||
|
||||
namespace import -force spice::*
|
||||
|
||||
# spicewish::
|
||||
rename ::source ::tclSource
|
||||
rename ::load ::tclLoad
|
||||
|
||||
namespace eval spicewish {
|
||||
set ::nameSpaceList [namespace export]
|
||||
}
|
||||
|
||||
namespace import -force spicewish::*
|
||||
|
||||
foreach procName $::nameSpaceList {
|
||||
tclreadline::readline add ${procName}
|
||||
}
|
||||
|
||||
rename spicewish_import_namespaces ""
|
||||
}
|
||||
|
||||
|
||||
set ::tcl_interactive 1
|
||||
source [file join $::spice_library spice/spicewish.tcl]
|
||||
|
||||
spicewish::load $argv $argc
|
||||
spicewish_import_namespaces
|
||||
spicewish_load $::argv $::argc
|
||||
|
||||
namespace import -force spice::*
|
||||
namespace import -force spicewish::*
|
||||
|
||||
spicewish::tclreadline
|
||||
Tclreadline
|
||||
|
|
|
|||
|
|
@ -0,0 +1,89 @@
|
|||
#package require spice
|
||||
|
||||
namespace eval spicewish {
|
||||
|
||||
set dir [file join $::spice_library spice]
|
||||
variable stepCallBack_list ""
|
||||
|
||||
source [file join $dir viewer.tcl ]
|
||||
source [file join $dir controls.tcl ]
|
||||
source [file join $dir engUnits.tcl ]
|
||||
source [file join $dir nodeDialog.tcl ]
|
||||
source [file join $dir readline.tcl ]
|
||||
source [file join $dir measure.tcl ]
|
||||
source [file join $dir gnuplot.tcl]
|
||||
|
||||
proc plot {args} {
|
||||
|
||||
# no plots passed load selection dialog
|
||||
if {$args == ""} {
|
||||
spicewish::nodeDialog::create
|
||||
return
|
||||
}
|
||||
eval spicewish::viewer::plot $args
|
||||
}
|
||||
|
||||
proc gui { } {
|
||||
spicewish::controls::create
|
||||
}
|
||||
|
||||
proc iplot {args} {
|
||||
eval spicewish::viewer::iplot $args
|
||||
}
|
||||
|
||||
proc source { fileName } {
|
||||
if {![file exists $fileName]} {
|
||||
puts "$fileName: No such file"
|
||||
return
|
||||
}
|
||||
|
||||
if {[string tolower [file extension $fileName]] == ".tcl" } {
|
||||
uplevel 1 ::tclSource $fileName
|
||||
return
|
||||
}
|
||||
|
||||
spice::source $fileName
|
||||
}
|
||||
|
||||
proc load { fileName } {
|
||||
if {[string tolower [file extension $fileName]] == ".raw" } {
|
||||
spice::load $fileName
|
||||
return
|
||||
}
|
||||
|
||||
uplevel 1 ::tclLoad $fileName
|
||||
}
|
||||
|
||||
proc run { } {
|
||||
if {$::spice::steps_completed == 0} {
|
||||
spice::bg run
|
||||
} else {
|
||||
spice::bg resume
|
||||
}
|
||||
}
|
||||
|
||||
proc halt { } {
|
||||
spice::halt
|
||||
spicewish::viewer::Update
|
||||
}
|
||||
|
||||
proc measDialog { node } {
|
||||
spicewish::meas_dialog::add $node
|
||||
}
|
||||
|
||||
proc write2gnuplot { args } {
|
||||
eval spicewish::gnuplot::plot $args
|
||||
}
|
||||
|
||||
proc stepCallBack { } {
|
||||
variable stepCallBack_list
|
||||
|
||||
foreach callBack $stepCallBack_list {
|
||||
eval $callBack
|
||||
}
|
||||
}
|
||||
|
||||
spice::registerStepCallback spicewish::stepCallBack 1 1
|
||||
|
||||
namespace export plot gui iplot source run halt load measDialog write2gnuplot
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
|
|
@ -0,0 +1,379 @@
|
|||
|
||||
namespace eval viewer {
|
||||
|
||||
variable wNames ".tclspice"
|
||||
variable viewCnt 1
|
||||
|
||||
variable viewTraces
|
||||
variable viewTraceScale
|
||||
variable view_w
|
||||
variable view_traces
|
||||
variable view_type
|
||||
variable view_plotName
|
||||
|
||||
variable meas_dx
|
||||
variable meas_dy
|
||||
variable meas_x1
|
||||
variable meas_y1
|
||||
variable meas_x2
|
||||
variable meas_y2
|
||||
|
||||
proc create { plotNum } {
|
||||
variable wNames
|
||||
variable viewCnt
|
||||
variable view_w
|
||||
|
||||
set w [toplevel "${wNames}${viewCnt}"]
|
||||
set plotName [spicewish::vectors::plotTypeName $plotNum]
|
||||
|
||||
wm title $w "\[$w\] - $plotName - [spice::plot_title $plotNum]"
|
||||
|
||||
# measurments
|
||||
frame $w.meas
|
||||
|
||||
blt::graph $w.g -width 1000 -height 250
|
||||
eval "$w.g axis configure x -scrollcommand {$w.x set}"
|
||||
eval "$w.g axis configure y -scrollcommand {$w.y set}"
|
||||
eval "scrollbar $w.x -orient horizontal -command {$w.g axis view x} -width 9"
|
||||
eval "scrollbar $w.y -command {$w.g axis view y} -width 9"
|
||||
|
||||
# x-axis title
|
||||
$w.g axis configure x -title [spicewish::vectors::defaultScale $plotNum]
|
||||
|
||||
create_measurments $w
|
||||
|
||||
# table
|
||||
blt::table $w \
|
||||
0,0 $w.meas -fill x -cspan 3 \
|
||||
1,1 $w.g -fill both -rspan 2 \
|
||||
1,2 $w.y -fill y -rspan 2 \
|
||||
3,1 $w.x -fill x
|
||||
|
||||
blt::table configure $w r0 r2 c0 c2 r3 -resize none
|
||||
|
||||
# graph settings
|
||||
Blt_ZoomStack $w.g
|
||||
Blt_Crosshairs $w.g
|
||||
$w.g grid on
|
||||
$w.g axis configure x -command { spicewish::viewer::axis_callback } -subdivisions 2
|
||||
|
||||
set view_w($viewCnt) "$w"
|
||||
|
||||
# freq/risetime measurments
|
||||
spicewish::meas_markers::bindings $w
|
||||
|
||||
eval "wm protocol $w WM_DELETE_WINDOW {spicewish::viewer::Destroy $w}"
|
||||
|
||||
incr viewCnt
|
||||
return [expr $viewCnt -1]
|
||||
}
|
||||
|
||||
proc create_measurments { w } {
|
||||
variable meas_dx
|
||||
variable meas_dy
|
||||
variable meas_x1
|
||||
variable meas_y1
|
||||
variable meas_x2
|
||||
variable meas_y2
|
||||
|
||||
set meas_dx($w.g) 0.00000000000000
|
||||
set meas_dy($w.g) 0.00000000000000
|
||||
set meas_x1($w.g) 0.00000000000000
|
||||
set meas_y1($w.g) 0.00000000000000
|
||||
set meas_x2($w.g) 0.00000000000000
|
||||
set meas_y2($w.g) 0.00000000000000
|
||||
|
||||
set w_meas "$w.meas"
|
||||
|
||||
# measurements
|
||||
pack [label $w_meas.dyv -textvariable spicewish::viewer::meas_dy($w.g) -background "lightgrey" -width 16] -side right
|
||||
pack [label $w_meas.dy -text "dy :" -background "lightgrey" ] -side right
|
||||
bind $w_meas.dyv <ButtonPress-1> { regexp {(.[0-9A-z]+)} %W w; puts "dy : $::spicewish::viewer::meas_dy($w.g)"}
|
||||
|
||||
pack [label $w_meas.dxv -textvariable spicewish::viewer::meas_dx($w.g) -background "grey" -width 16] -side right
|
||||
pack [label $w_meas.dx -text "dx : " -background "grey"] -side right
|
||||
bind $w_meas.dxv <ButtonPress-1> { regexp {(.[0-9A-z]+)} %W w; puts "dx : $::spicewish::viewer::meas_dx($w.g)"}
|
||||
bind $w_meas.dxv <ButtonPress-2> {
|
||||
regexp {(.[0-9A-z]+)} %W w
|
||||
if { $::spicewish::viewer::meas_dx($w.g) != 0 } {
|
||||
puts "freq : [spicewish::eng::float_eng [expr 1 / $::spicewish::viewer::meas_dx($w.g)]] Hz"
|
||||
}
|
||||
}
|
||||
|
||||
pack [ label $w_meas.y2v -textvariable spicewish::viewer::meas_y2($w.g) -background "lightgrey" -width 16 ] -side right
|
||||
pack [ label $w_meas.y2 -text "y2 :" -background "lightgrey"] -side right
|
||||
bind $w_meas.y2v <ButtonPress-1> { regexp {(.[0-9A-z]+)} %W w; puts "y2 : $::spicewish::viewer::meas_y2($w.g)"}
|
||||
|
||||
pack [ label $w_meas.y1v -textvariable spicewish::viewer::meas_y1($w.g) -background "grey" -width 16] -side right
|
||||
pack [ label $w_meas.y1 -text "y1 :" -background "grey" ] -side right
|
||||
bind $w_meas.y1v <ButtonPress-1> { regexp {(.[0-9A-z]+)} %W w; puts "y1 : $::spicewish::viewer::meas_y1($w.g)"}
|
||||
|
||||
pack [ label $w_meas.x2v -textvariable spicewish::viewer::meas_x2($w.g) -background "lightgrey" -width 16 ] -side right
|
||||
pack [ label $w_meas.x2 -text "x2 :" -background "lightgrey" ] -side right
|
||||
bind $w_meas.x2v <ButtonPress-1> { regexp {(.[0-9A-z]+)} %W w; puts "x2 : $::spicewish::viewer::meas_x2($w.g)"}
|
||||
|
||||
pack [ label $w_meas.x1v -textvariable spicewish::viewer::meas_x1($w.g) -background "grey" -width 16 ] -side right
|
||||
pack [ label $w_meas.x1 -text "x1 :" -background "grey" ] -side right
|
||||
bind $w_meas.x1v <ButtonPress-1> { regexp {(.[0-9A-z]+)} %W w; puts "x1 : $::spicewish::viewer::meas_x1($w.g)"}
|
||||
|
||||
# cursor motion bindings
|
||||
bind $w.g <Motion> {
|
||||
if { $::zoomInfo(%W,B,x) != "" } {
|
||||
set ::spicewish::viewer::meas_x2(%W) [%W xaxis invtransform $::zoomInfo(%W,B,x)]
|
||||
set ::spicewish::viewer::meas_y2(%W) [%W yaxis invtransform $::zoomInfo(%W,B,y)]
|
||||
set ::spicewish::viewer::meas_x1(%W) [%W xaxis invtransform $::zoomInfo(%W,A,x)]
|
||||
set ::spicewish::viewer::meas_y1(%W) [%W yaxis invtransform $::zoomInfo(%W,A,y)]
|
||||
set ::spicewish::viewer::meas_dx(%W) [expr ($::spicewish::viewer::meas_x2(%W) - $::spicewish::viewer::meas_x1(%W))]
|
||||
set ::spicewish::viewer::meas_dy(%W) [expr ($::spicewish::viewer::meas_y2(%W) - $::spicewish::viewer::meas_y1(%W))]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
proc names { } {
|
||||
variable view_w
|
||||
|
||||
return [array names view_w]
|
||||
}
|
||||
|
||||
proc plot { args } {
|
||||
eval "oplot 0 $args"
|
||||
}
|
||||
|
||||
proc oplot { plotNum args } {
|
||||
|
||||
variable view_w
|
||||
variable view_traces
|
||||
variable view_type
|
||||
variable view_plotName
|
||||
|
||||
eval "set args \[spicewish::vectors::validVectorList $plotNum $args\]"
|
||||
|
||||
if {$args == ""} {return}
|
||||
|
||||
# create a new viewer
|
||||
set viewNum [create $plotNum]
|
||||
set w $view_w($viewNum)
|
||||
set view_traces($viewNum) ""
|
||||
set view_type($viewNum) "plot"
|
||||
set view_plotName($viewNum) [spicewish::vectors::plotTypeName $plotNum]
|
||||
|
||||
# add/update default scale
|
||||
set defBLTvec [spicewish::vectors::create $plotNum [spicewish::vectors::defaultScale $plotNum]]
|
||||
|
||||
if {$defBLTvec == ""} {
|
||||
puts "Error: plotting '[spicewish::vectors::defaultScale $plotNum]'"
|
||||
return
|
||||
}
|
||||
|
||||
set traceCnt 0
|
||||
#loop for all vectors
|
||||
foreach vectorName $args {
|
||||
|
||||
# don't allow duplicate traces
|
||||
|
||||
set BLTvec [spicewish::vectors::create $plotNum "$vectorName"]
|
||||
|
||||
if {$BLTvec == ""} {
|
||||
puts "Error: plotting '$vectorName'"
|
||||
continue
|
||||
}
|
||||
|
||||
lappend view_traces($viewNum) $vectorName
|
||||
|
||||
$w.g element create "$vectorName" \
|
||||
-xdata $defBLTvec \
|
||||
-ydata $BLTvec \
|
||||
-symbol "circle" \
|
||||
-linewidth 2 \
|
||||
-pixels 3 \
|
||||
-color [trace_colour $traceCnt]
|
||||
|
||||
incr traceCnt
|
||||
}
|
||||
return $w
|
||||
}
|
||||
|
||||
proc iplot { args } {
|
||||
variable view_type
|
||||
|
||||
eval "set view_w [plot $args]"
|
||||
|
||||
# register callBack
|
||||
if {[lsearch $spicewish::stepCallBack_list "spicewish::viewer::stepCallBack"] == -1} {
|
||||
lappend spicewish::stepCallBack_list "spicewish::viewer::stepCallBack"
|
||||
}
|
||||
|
||||
set viewNum [get_index $view_w]
|
||||
set view_type($viewNum) "iplot"
|
||||
}
|
||||
|
||||
proc get_index { name } {
|
||||
variable view_w
|
||||
|
||||
foreach viewNum [array names view_w] {
|
||||
if { $name == $view_w($viewNum) } {
|
||||
return $viewNum
|
||||
}
|
||||
}
|
||||
return -1
|
||||
}
|
||||
|
||||
proc get_plotNum { plotTypeName } {
|
||||
|
||||
for {set i 0} {$i < [spicewish::vectors::avaliable_plots]} {incr i} {
|
||||
if {[spicewish::vectors::plotTypeName $i] == $plotTypeName} {
|
||||
return $i
|
||||
}
|
||||
}
|
||||
return -1
|
||||
}
|
||||
|
||||
proc axis_callback { widget value } {
|
||||
|
||||
return [ spicewish::eng::float_eng $value]
|
||||
}
|
||||
|
||||
proc trace_colour { index } {
|
||||
|
||||
set def_colours "red blue orange green magenta brown"
|
||||
|
||||
if {$index < [llength $def_colours]} {
|
||||
return [lindex $def_colours $index]
|
||||
} else {
|
||||
# creates a random colour
|
||||
set randred [format "%03x" [expr {int (rand() * 4095)}]]
|
||||
set randgreen [format "%03x" [expr {int (rand() * 4095)}]]
|
||||
set randblue [format "%03x" [expr {int (rand() * 4095)}]]
|
||||
return "#$randred$randgreen$randblue"
|
||||
}
|
||||
}
|
||||
|
||||
proc stepCallBack { } {
|
||||
|
||||
set currentPlotName [spicewish::vectors::plotTypeName 0]
|
||||
|
||||
#puts $::spice::steps_completed
|
||||
# hack !!!
|
||||
spicewish::vectors::create 0 "time"
|
||||
spicewish::vectors::create 0 "a0_x1_y0"
|
||||
|
||||
}
|
||||
|
||||
proc Update { } {
|
||||
variable view_traces
|
||||
variable view_plotName
|
||||
|
||||
foreach index [names] {
|
||||
|
||||
set plotTypeName $view_plotName($index)
|
||||
set plotNum [get_plotNum $plotTypeName]
|
||||
|
||||
# default scale
|
||||
spicewish::vectors::create $plotNum [spicewish::vectors::defaultScale $plotNum]
|
||||
|
||||
foreach trace $view_traces($index) {
|
||||
spicewish::vectors::create $plotNum $trace
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
proc Destroy { w } {
|
||||
variable view_traces
|
||||
variable view_w
|
||||
|
||||
foreach index [names ] {
|
||||
if {[string match $view_w($index) $w]} {
|
||||
unset view_w($index)
|
||||
catch {unset view_traces($index)}
|
||||
}
|
||||
}
|
||||
|
||||
destroy $w
|
||||
}
|
||||
}
|
||||
|
||||
namespace eval vectors {
|
||||
|
||||
proc names { {plot 0} } {
|
||||
# traces for current plot
|
||||
return [spice::plot_variables $plot]
|
||||
|
||||
}
|
||||
|
||||
proc exists { plot name } {
|
||||
|
||||
set list [names $plot]
|
||||
|
||||
if {[lsearch -exact $list $name] != -1} {
|
||||
return $name
|
||||
} else {
|
||||
return ""
|
||||
}
|
||||
}
|
||||
|
||||
proc validVectorList { plotNum args } {
|
||||
set validList ""
|
||||
|
||||
foreach vector $args {
|
||||
set vector [string tolower $vector]
|
||||
|
||||
if {[exists $plotNum $vector] != ""} {
|
||||
lappend validList $vector
|
||||
}
|
||||
}
|
||||
|
||||
return $validList
|
||||
}
|
||||
|
||||
proc plotTypeName { plot } {
|
||||
# plot type eg tran1, dc1
|
||||
return [spice::plot_typename $plot]
|
||||
}
|
||||
|
||||
proc type { plot name } {
|
||||
set spice_data [spice::spice_data $plot] ;# "{a0 voltage}{time time}"
|
||||
|
||||
set name [string tolower $name]
|
||||
set spice_data [string tolower $spice_data]
|
||||
|
||||
foreach plot $spice_data {
|
||||
set p_name [lindex $plot 0] ;# node name
|
||||
set p_type [lindex $plot 1] ;# voltage/current/time
|
||||
|
||||
if {$p_name == $name} {
|
||||
return $p_type
|
||||
}
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
proc avaliable_plots { } {
|
||||
set cnt 0
|
||||
while {![catch { spice::plot_name $cnt }]} {
|
||||
incr cnt
|
||||
}
|
||||
return $cnt
|
||||
}
|
||||
|
||||
proc defaultScale { plot } {
|
||||
|
||||
return [spice::plot_defaultscale $plot]
|
||||
}
|
||||
|
||||
proc create { plot name } {
|
||||
|
||||
# valid vector
|
||||
if {[exists $plot $name] == ""} {return ""}
|
||||
|
||||
if { ![info exists "::[plotTypeName $plot]:v:${name}"]} {
|
||||
set ::[plotTypeName $plot]:v:${name} "[blt::vector #auto]"
|
||||
}
|
||||
|
||||
eval "set tmp \${::[plotTypeName $plot]:v:${name}}"
|
||||
|
||||
eval spice::plot_getvector $plot $name $tmp
|
||||
|
||||
return $tmp
|
||||
}
|
||||
|
||||
}
|
||||
Loading…
Reference in New Issue