diff --git a/README.Tcl b/README.Tcl new file mode 100644 index 000000000..84dc08cec --- /dev/null +++ b/README.Tcl @@ -0,0 +1,62 @@ +README for TclSpice +------------------- + +** What is it? + +TclSpice is an improved version of Berkeley Spice designed to be used with +the Tcl/Tk scripting language. The project is open-source (BSD license) +and based upon the NG-Spice source code base with many improvements + +** Features and Improvements + + * Fully Tcl scriptable - installs with 'package require spice' statement + * Hspice syntax (SpicePP). + * GUI interfaces, various (Tk). + - SpiceWish (BLT graph widget) + * BLT (tcl compatible) vectors for storage, manipulation and arithmetic + upon Spice waveforms. + * Xspice additions (Georgia Tech). + * Trigger upon waveform events. + * Spice 'simulator state' save and restore for rapid 'what-if' simulations + (no longer need to re-simulate from the beginning each time a + device value is changed). + +** INSTALL + + * Requirements: (over normal ngspice) + + Tcl/Tk 8.3 or higher compiled with thread support + BLT-2.4u for Tcl or newer ( http://www.sourceforge.net/projects/blt/ ) + tclreadline ( http://tclreadline.sourceforge.net/ ) + + IMPORTANT: + If Tcl/Tk is not compiled with thread support ( --enable-threads + configure argument ) then tclspice will be quite unstable. + + * Building and installing + + $ tar -zxf tclspice0.2.??.tar.gz + $ cd tclspice + $ ./configure --enable-tcl --enable-experimental --enable-xspice + $ make tcl + $ make install-tcl + + IMPORTANT: + Use make tcl and make install-tcl otherwise tclspice will fail + to compile. + +** USAGE + + $ spicewish + + +** More information: + + tclspice/src/tcl/README : more in depth information on how to create your + own Tcl scripts. + Example also supplied in the same directory (vector_test.tcl). + + http://tclspice.sourceforge.net/ : Homepage of Tclspice + + Stefan Jones + ngspice-devel@lists.sourceforge.net : Email support! diff --git a/src/ChangeLog b/src/ChangeLog index 98a7da4d6..ba203353d 100644 --- a/src/ChangeLog +++ b/src/ChangeLog @@ -1,3 +1,7 @@ +2003-07-08 Stefan Jones + * tclspice.c: handle SIGINT while running a command + * Makefile.am spicewish tclspice_source.tcl: new frontend + * pkgIndex.tcl: don't export spice::history 2003-06-25 Stefan Jones * tclspice.c : diff --git a/src/Makefile.am b/src/Makefile.am index 0ccd601ed..7a2bf72fd 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -181,7 +181,7 @@ CLEANFILES = pkgIndex.tcl libspice.so TCL_PKG_PATH = @TCL_PACKAGE_PATH@ -TCLSPICE_VERSION = 0.2.11 +TCLSPICE_VERSION = 0.2.12 TCL_FILES = libspice.so pkgIndex.tcl @@ -202,10 +202,13 @@ install-tcl-recursive: done; install-tclspice: ${TCL_FILES} - install -c -m 644 libspice.so $(TCL_PKG_PATH) - mkdir -p $(TCL_PKG_PATH)/spice - install -c -m 644 pkgIndex.tcl $(TCL_PKG_PATH)/spice - install -c -m 644 tclspice_source.tcl $(TCL_PKG_PATH)/spice + $(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 + $(mkinstalldirs) $(DESTDIR)$(bindir) + $(INSTALL_PROGRAM) spicewish $(DESTDIR)$(bindir) tclspice.o: tclspice.c $(COMPILE) -c -fpic tclspice.c -DTCLSPICE_version="\"$(TCLSPICE_VERSION)\"" diff --git a/src/pkgIndex.tcl.in b/src/pkgIndex.tcl.in index 6e4f18639..eb59cc94e 100755 --- a/src/pkgIndex.tcl.in +++ b/src/pkgIndex.tcl.in @@ -17,7 +17,7 @@ proc Loadspice { version dir } { blt::vector create ::spice::Y_Data namespace eval spice { - namespace export ac help save alias history sens alter altermod iplot 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 plot 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 run write goto running xgraph hardcopy rusage steps_completed blt_vnum codemodel halt loadsnap savesnap + namespace export ac help save alias sens alter altermod iplot 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 plot 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 run write goto running xgraph hardcopy rusage steps_completed blt_vnum codemodel halt loadsnap savesnap } diff --git a/src/spicewish b/src/spicewish new file mode 100755 index 000000000..c9a3fedfc --- /dev/null +++ b/src/spicewish @@ -0,0 +1,52 @@ +#!/bin/sh + +# the next line starts SpiceWish interactively with the given file name \ +exec wish "$0" "$@" + +set ::tcl_interactive 1 + +if { [ llength $argv ] != 1 } { + puts " usage: spicewish filename.cir \n" + wm withdraw . + exit +} else { + set fileName $argv +} + + +# check file exists +if {![ file exists $fileName ]} { + puts " file '${fileName}' doesn't exists \n" + exit +} + +if { [ file extension $fileName ] == ".tcl" } { + source $fileName + +} else { + package require spice + spice_init_gui $fileName + + # import the spice namespace + namespace import spice::* + + # import the spicewish namespace + namespace import -force spicewish::* + + set ::spicewish_mode "standalone" +} + + + + +# readline with prompt set to "tclspice > " +if {$tcl_interactive} { + package require tclreadline + proc ::tclreadline::prompt1 { } { return "tclspice > " } + + + ::tclreadline::Loop +} + + + diff --git a/src/tclspice.c b/src/tclspice.c index 08d1415a2..c1bc1e4c1 100755 --- a/src/tclspice.c +++ b/src/tclspice.c @@ -43,6 +43,11 @@ #endif #endif +/* To interupt a spice run */ +#include +#include +extern jmp_buf jbuf; + /*Included for the module to access data*/ #include #include @@ -367,6 +372,7 @@ static int _thread_stop(){ static int _run(int args,char **argv){ char buf[1024] = "", *string; int i; + sighandler_t oldHandler; bool fl_bg = FALSE; /* run task in background if preceeded by "bg"*/ if(!strcmp(argv[0],"bg")) { @@ -375,6 +381,13 @@ static int _run(int args,char **argv){ fl_bg = TRUE; } + /* Catch Ctrl-C to break simulations */ + oldHandler = signal(SIGINT,ft_sigintr); + if(setjmp(jbuf)!=0) { + signal(SIGINT,oldHandler); + return TCL_OK; + } + /*build a char * to pass to cp_evloop */ for(i=0;i { regexp {(.[0-9A-z]+)} %W w; puts "dx : $::spicewish_meas_dx($w.g)"} bind $w_meas.dxv { - regexp {(.[0-9A-z]+)} %W w; puts "freq : [ sw_float_eng [ expr 1 / $::spicewish_meas_dx($w.g) ] ] Hz"} + regexp {(.[0-9A-z]+)} %W w; if { $::spicewish_meas_dx($w.g) != 0 } { puts "freq : [ sw_float_eng [ expr 1 / $::spicewish_meas_dx($w.g) ] ] Hz" } } pack [ label $w_meas.y2v -textvariable spicewish_meas_y2($w.g) -background "lightgrey" -width 16 ] -side right pack [ label $w_meas.y2 -text "y2 :" -background "lightgrey"] -side right @@ -1360,16 +1378,26 @@ proc sw_nodeselection_loadSelection { w { viewer "" } } { #---------------------------------------------------------------------------------- # tests if trace is a valid spice node # -proc sw_spice_validNode { trace } { +proc sw_spice_validNode { trace {spicedeck 0} } { if { $::spice::steps_completed <1 } { spice::step 1 } + # check against the spice deck set trace [ string tolower $trace ] set spiceNodeList [ spice::spice_data ] ;#- all lowercase for { set i 0 } { $i< [ llength $spiceNodeList] } { incr i } { if { [ lcontain [ lindex [ lindex $spiceNodeList $i ] 0 ] $trace] } { return 1 } } + + # if flaged jsu check against the spice deck + if { $spicedeck } { return 0 } + + # bltplot straing eg "a1_x1_y0+4" + spice::X_Data set "" + spice::bltplot $trace + if { [ spice::X_Data length ] != 0 } { return 1 } + return 0 } @@ -1501,10 +1529,26 @@ proc sw_trace_vectorUpdate { viewer traceName } { if { $holder_traceName == $traceName } { if { [ sw_spice_validNode $traceName ] } { + + # spice node - spice::spicetoblt $holder_traceName $holder_traceVector - spice::spicetoblt time $holder_traceTimeVector + # check if in spice deck + if { [ sw_spice_validNode $traceName 1 ] } { + spice::spicetoblt $holder_traceName $holder_traceVector + spice::spicetoblt time $holder_traceTimeVector + } else { + spice::X_Data set "" + spice::Y_Data set "" + spice::bltplot $holder_traceName + + # no vectors returned + if { ( [ spice::X_Data length ] != 0 ) && ( [ spice::Y_Data length ] != 0 ) } { + eval "$holder_traceVector set spice::Y_Data" + eval "$holder_traceTimeVector set spice::X_Data " + } + + } } else { # external node @@ -1515,6 +1559,7 @@ proc sw_trace_vectorUpdate { viewer traceName } { } + #---------------------------------------------------------------------------------------------------- # return the traces type # either @@ -1579,11 +1624,14 @@ proc sw_plot { args } { set traceName [ string tolower $trace ] ;#- lowercase to match spice + + switch [ sw_trace_type $traceName ] { "" { # not valid trace #puts "$trace not valid " + } "spice" { @@ -1599,12 +1647,19 @@ proc sw_plot { args } { # generate trace colour set traceColour [ sw_trace_colour $viewer $traceName ] + + # get unique vector name set traceVectorName [ sw_trace_createUniqueVector $viewer ] set traceTimeVectorName "$viewer.time" - + #puts "$viewer $traceVectorName $traceTimeVectorName " + blt::vector create $traceVectorName blt::vector create $traceTimeVectorName ;# make sure that time vector exists + + # add trace to the data holder + lappend ::spicewish_plots($viewer) "$traceName $traceVectorName $traceColour $traceTimeVectorName" + } "external" { @@ -1620,11 +1675,12 @@ proc sw_plot { args } { set traceTimeVectorName [ lindex $traceInfo 3 ] } } + # add trace to the data holder + lappend ::spicewish_plots($viewer) "$traceName $traceVectorName $traceColour $traceTimeVectorName" } } - # add trace to the data holder - lappend ::spicewish_plots($viewer) "$traceName $traceVectorName $traceColour $traceTimeVectorName" + } # update the viewer @@ -1707,6 +1763,8 @@ proc sw_update { args } { set traceColour [ lindex $traceInfo 2 ] set timeVector [ lindex $traceInfo 3 ] + + if { $traceName == "" } { continue } @@ -1796,6 +1854,7 @@ proc sw_halt { } { # sw_controls_editor_saveFile # sw_controls_editor_includeFiles # sw_controls_editor_syntaxHighlighting_toggle +# sw_controls_editor_syntaxHighlighting_update # sw_controls_editor_syntaxHighlighting # #======================================================== @@ -1816,6 +1875,7 @@ proc sw_controls_create { fileName } { spice::reset spice::source $fileName .controls.brun configure -text "Run" + return } @@ -1833,9 +1893,6 @@ proc sw_controls_create { fileName } { # create spice file editor widget + load file + highlight paremeters set editor_w [ sw_controls_editor_create $fileName ] - # sw_controls_editor_loadFile $editor_w $fileName - # sw_controls_editor_syntaxHighlighting - # $editor_w.text configure -state disabled ;#- disabled no editting for now # table blt::table . \ @@ -1856,14 +1913,15 @@ proc sw_controls_create { fileName } { wm deiconify . ;#- required for magic use + wm protocol . WM_DELETE_WINDOW { sw_controls_exit } ;#- safe exit for magic use # keyboard shortcuts if {1} { - bind . { sw_run } - bind . { sw_halt } - bind . { sw_nodeselection_create } - bind . { sw_update } - bind . { sw_controls_editor_toggle } + bind . { sw_run } + bind . { sw_halt } + bind . { sw_nodeselection_create } + bind . { sw_update } + bind . { sw_controls_editor_toggle } } } @@ -1895,7 +1953,7 @@ proc sw_controls_exit { } { #--------------------------------------------------------------------------------------------- # sets the line number at the bottom of the status bar # -proc sw_controls_editor_lineNumber { w } { +proc sw_controls_editor_lineNumber { w key } { set lineIndex [ $w index insert ] set lineIndex [ split $lineIndex . ] @@ -1911,6 +1969,14 @@ proc sw_controls_editor_lineNumber { w } { "100" { set ::sw_editor_lineInfo($w) "L${lineNum}--C${colNum}--Bot" } default { set ::sw_editor_lineInfo($w) "L${lineNum}--C${colNum}--${percentage}%" } } + + # only update syntax colouring when a new character is added + if { $::spicewish_globals(editor_syntaxHighlight_auto) } { + set list_key { Up Down Right Left Alt_L End Home Mode_switch Control_L Control_R Shift_R Shift_L Insert Prior Next ?? } + if { [lsearch -exact $list_key $key] == -1} { + sw_controls_editor_syntaxHighlighting_update $w $lineNum + } + } } @@ -1929,7 +1995,7 @@ proc sw_controls_editor_popupMenu { w x y { _x ""} { _y ""} } { set node [ $w get [lindex $sel_coords 0] [lindex $sel_coords 1] ] # test if valid node - if { [ sw_spice_validNode $node ] } { + if { [ sw_spice_validNode $node 1 ] } { set coords_first [ $w bbox [lindex [ $w tag ranges sel ] 0 ] ] set coords_sec [ $w bbox [lindex [ $w tag ranges sel ] 1 ] ] @@ -1942,16 +2008,31 @@ proc sw_controls_editor_popupMenu { w x y { _x ""} { _y ""} } { } } - + catch {destroy .m} ;# destroy old pop up menu .m -tearoff 0 .m add command -label "Drag and drop" -state disabled .m add command -label "New viewer" -command "sw_viewer_create" - .m add checkbutton -label "Syntax highlighting" \ + + + .m add cascade -label "Syntax Highlighting" -menu .m.syntax + menu .m.syntax -tearoff 0 + .m.syntax add checkbutton -label "In buffers" \ -variable spicewish_globals(editor_syntaxHighlight) \ -command "sw_controls_editor_syntaxHighlighting_toggle" + + if { $::spicewish_globals(editor_syntaxHighlight) } { + .m.syntax add checkbutton -label "Automatic" \ + -variable spicewish_globals(editor_syntaxHighlight_auto) + } else { + + .m.syntax add checkbutton -label "Automatic" \ + -variable spicewish_globals(editor_syntaxHighlight_auto) \ + -state disabled + + } .m add checkbutton -label "Status bar" \ -variable spicewish_globals(editor_statusbar) \ @@ -2003,9 +2084,9 @@ proc sw_controls_editor_create_statusbar { { w "" } } { pack [ label $w.status.line.lv -textvariable sw_editor_lineInfo($w.text) ] -side left # - line number - bindings - bind $w.text