2004-06-22 Stefan Jones <stefan.jones@multigig.com>
* configure.in: Change to version 17 2004-06-22 Adrian Dawe <adrian.dawe@multigig.com> * src/pkgIndex.tcl.in src/spicepp.pl src/spicepp.tcl src/spicewish src/Makefile.am: Added spicepp integration and spicewish command line options.
This commit is contained in:
parent
f798049285
commit
dd677f2a10
11
ChangeLog
11
ChangeLog
|
|
@ -1,3 +1,14 @@
|
|||
2004-06-22 Stefan Jones <stefan.jones@multigig.com>
|
||||
|
||||
* configure.in:
|
||||
Change to version 17
|
||||
|
||||
2004-06-22 Adrian Dawe <adrian.dawe@multigig.com>
|
||||
|
||||
* src/pkgIndex.tcl.in src/spicepp.pl src/spicepp.tcl src/spicewish
|
||||
src/Makefile.am:
|
||||
Added spicepp integration and spicewish command line options.
|
||||
|
||||
2004-06-10 Stefan Jones <stefan.jones@multigig.com>
|
||||
|
||||
* include/ngspice.h:
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@ dnl Create a configuration header
|
|||
AM_CONFIG_HEADER(config.h)
|
||||
|
||||
dnl Initialize automake stuff
|
||||
AM_INIT_AUTOMAKE(tclspice,0.2.16)
|
||||
AM_INIT_AUTOMAKE(tclspice,0.2.17)
|
||||
|
||||
dnl --enable-ftedebug : enable frontend debug macros
|
||||
AC_ARG_ENABLE(ftedebug,
|
||||
|
|
|
|||
|
|
@ -195,6 +195,8 @@ install-tclspice: ${TCL_FILES}
|
|||
$(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
|
||||
$(mkinstalldirs) $(DESTDIR)$(bindir)
|
||||
$(INSTALL_PROGRAM) spicewish $(DESTDIR)$(bindir)
|
||||
|
||||
|
|
|
|||
|
|
@ -79,7 +79,8 @@ proc Loadspice { version dir } {
|
|||
spicewish::init_gui $spicefile
|
||||
}
|
||||
|
||||
set ::spice_version $version
|
||||
set ::spice_version $version
|
||||
set ::spice_library $dir
|
||||
}
|
||||
|
||||
proc q { } { exit }
|
||||
|
|
@ -88,8 +89,5 @@ proc q { } { exit }
|
|||
set version "%VERSION%"
|
||||
set libdir "%LIB_DIR%"
|
||||
|
||||
#set version "0.2.7"
|
||||
#set libdir "/usr/local/lib"
|
||||
|
||||
package ifneeded spice $version [list Loadspice $version $libdir]
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,855 @@
|
|||
eval '(exit $?0)' &&
|
||||
eval 'exec perl -S $0 ${1+"$@"}' &&
|
||||
eval 'exec perl -S $0 $argv:q'
|
||||
if 0;
|
||||
# Copyright 2000 by John Sheahan <john@reptechnic.com.au>
|
||||
#
|
||||
# This program is free software; you may redistribute and/or modify it under
|
||||
# the terms of the GNU General Public License Version 2 as published by the
|
||||
# Free Software Foundation.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful, but
|
||||
# WITHOUT ANY WARRANTY, without even the implied warranty of MERCHANTABILITY
|
||||
# or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
# for complete details.
|
||||
#
|
||||
|
||||
$ver= '$Id$ ';
|
||||
|
||||
require "getopts.pl";
|
||||
&Getopts("hi");
|
||||
(defined($opt_i)) ? ($interactive=1) : ($interactive=0) ;
|
||||
if (defined($opt_h)) {
|
||||
print "$0 $ver\n";
|
||||
print " -i interactive\n";
|
||||
|
||||
print " hspice-like spice preprocessor for berkeley spice\n";
|
||||
die;
|
||||
}
|
||||
# preprocess a hspice-like deck for berkeley spice 3f5
|
||||
# expand .lib .param .temp .global
|
||||
# expoand .meas
|
||||
# support $ for comment to lineend
|
||||
|
||||
# $debug=1;
|
||||
|
||||
# first pass read in deck,
|
||||
# inline continuation lines, remove comment lines
|
||||
|
||||
$_=<>;chop;@deck=" " . $_; # heading/comment line passthrough
|
||||
|
||||
while (<>) {
|
||||
chop;
|
||||
# dont lowercase stuff in quotes
|
||||
if (/^(.*)([\'\"])(.*)([\"\'])(.*)/) {
|
||||
$_=lc($1) . $2 . $3 . $4 . lc($5);
|
||||
}
|
||||
else { $_ = lc($_); }
|
||||
s/\$.*//; # no trailing comments;
|
||||
s/^\*.*//; # no comments;
|
||||
s/^\s*$//; # no bl lines
|
||||
s/^\s+(.*)/$1/g; #get rid of blankspace
|
||||
if (/^\s*\+(.*)/) { # continuation
|
||||
$_ = pop (@deck) . " " . $1;
|
||||
}
|
||||
push @deck,$_ if (length($_) >0);
|
||||
}
|
||||
|
||||
while(&read_libs){}
|
||||
|
||||
&read_parameters;
|
||||
&eval_parameters;
|
||||
&expand_parameters;
|
||||
|
||||
&expand_eqns;
|
||||
|
||||
#&remove_vbracket;
|
||||
|
||||
&read_globals;
|
||||
&expand_global_subs;
|
||||
&expand_global_calls;
|
||||
|
||||
&fix_temp;
|
||||
|
||||
&expand_linearize;
|
||||
&expand_meas;
|
||||
&expand_control;
|
||||
|
||||
&process_models;
|
||||
|
||||
&printdeck;
|
||||
|
||||
|
||||
if ($debug) {
|
||||
foreach $param (sort keys %param) {
|
||||
print STDERR "param $param = $param{$param}\n";
|
||||
}
|
||||
foreach $global (sort keys %global) {
|
||||
print STDERR " global $global\n";
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
################# subroutines #############
|
||||
|
||||
# include the specified model from the library. complain if not found.
|
||||
sub libinclude {
|
||||
local ($file,$model,$found,@lib );
|
||||
$file=$_[0];
|
||||
$model=$_[1];
|
||||
@lib=();
|
||||
open (INCLUDE, "$file") || die "include file $file cannot be opened";
|
||||
$found=0;
|
||||
while (<INCLUDE>) {
|
||||
#get rid of blankspace, also allows you to optimise matches below
|
||||
s/^\s+(.*)/$1/g;
|
||||
last if ($found && /^\.endl/i);
|
||||
if ($found) {
|
||||
chop;
|
||||
# dont lowercase stuff in quotes
|
||||
if (/^(.*)([\'\"])(.*)([\"\'])(.*)/) {
|
||||
$_=lc($1) . $2 . $3 . $4 . lc($5);
|
||||
}
|
||||
else { $_ = lc($_); }
|
||||
s/\$.*//; # no trailing comments;
|
||||
s/^\*.*//; # no comments;
|
||||
s/\s\s+/ /g; # shrink multiple whitespaces
|
||||
s/\s*=\s*/=/g; # compress around =
|
||||
if (/^\+(.*)/) { # continuation
|
||||
$_ = pop (@lib) . " " . $1;
|
||||
}
|
||||
push @lib,$_ if (length($_)>0);
|
||||
}
|
||||
if (/^\.lib\s+$model\b/i) { $found=1}
|
||||
}
|
||||
print STDERR "did not find model $model in library $file\n" unless ($found);
|
||||
return @lib;
|
||||
}
|
||||
################## &read_libs ############
|
||||
sub read_libs {
|
||||
local ($i,$file,$model,$flag);
|
||||
$flag=0;
|
||||
for ($i=0;$i<@deck;$i++) {
|
||||
$_=$deck[$i];
|
||||
if (/^\.lib\s+[\'\"](.*)[\'\"]\s+(\S+)/i) {
|
||||
$flag=1;
|
||||
$file=$1;
|
||||
$model=$2;
|
||||
@lib=&libinclude($file,$model);
|
||||
$_=@lib;
|
||||
splice(@deck,$i,1,@lib);
|
||||
} }
|
||||
return $flag;
|
||||
}
|
||||
|
||||
|
||||
############## read globals ############
|
||||
# record a hash of all global signals. kill the line.
|
||||
sub read_globals {
|
||||
local ($i,$file,$model,@kill);
|
||||
for ($i=0;$i<@deck;$i++) {
|
||||
if ($deck[$i] =~ /^\.globals?\s+(.*)/) {
|
||||
for (split(" ",$1)) { $global{$_}=1 }
|
||||
push @kill,$i;
|
||||
}
|
||||
}
|
||||
&zapdeck(@kill);
|
||||
}
|
||||
|
||||
############## kill line(s) in deck ################
|
||||
sub zapdeck {
|
||||
# give it a list of lines to remove in increasing order!!!
|
||||
while ($_=pop(@_)) {
|
||||
splice @deck,$_,1;
|
||||
}
|
||||
}
|
||||
######### parameters #################
|
||||
# find parameter define lines, remeber and delete them
|
||||
sub read_parameters {
|
||||
local ($i,$j,@kill);
|
||||
for ($i=0;$i<@deck;$i++) {
|
||||
if ($deck[$i] =~/^\.param\s+(.*)/) { # record param/value pairs
|
||||
# print STDERR "found param line $1\n";
|
||||
push @kill,$i;
|
||||
$_=$1;
|
||||
$done=0;
|
||||
until ($done) {
|
||||
if (/^\s*(\S+)\s*\=\s*\'([^\']*)\'(.*)/) {
|
||||
# print STDERR "PARAM $1 = $2\n";
|
||||
$param{$1}=&unit($2);
|
||||
$_=$3;
|
||||
}
|
||||
elsif (/^\s*(\S+)\s*\=\s*(\S+)(.*)/) {
|
||||
# print STDERR "PARAM(2) $1 = $2\n";
|
||||
$param{$1}=&unit($2);
|
||||
# print STDERR "PARAM(2) $1 = $param{$1}\n";
|
||||
$_=$3;
|
||||
}
|
||||
else { $done=1; }
|
||||
}
|
||||
# @param=split(" ",$1);
|
||||
# for ($j=0;$j<@param;$j++) {
|
||||
# if ($param[$j] =~ /(\S*)\s*=\s*(\S+)/) {
|
||||
# $param{$1}=$2;
|
||||
# }
|
||||
# else {
|
||||
# print STDERR "parameter parse error in line $_\n";
|
||||
} } # } }
|
||||
&zapdeck(@kill);
|
||||
}
|
||||
# replace parameters with defined string
|
||||
# if the line starts with . - sub most places
|
||||
# if not ., sub only last item
|
||||
sub expand_parameters {
|
||||
local ($i,$j,$nline,$skip,$tmptoken);
|
||||
for ($i=0;$i<@deck;$i++) {
|
||||
$skip=&skipnumber($deck[$i]);
|
||||
if ($i==0) {$skip=0} # replace the first line
|
||||
# print STDERR "skipping $skip fields $i $deck[$i]\n";
|
||||
$nline='';
|
||||
$_=$deck[$i];
|
||||
s/\(/ \( /g; # delimit openbracket
|
||||
s/\)/ \) /g; # delimit closebracket
|
||||
s/=/ = /g;
|
||||
@_=split;
|
||||
for ($j=0;$j<$skip;$j++) {
|
||||
$nline .= $_[$j] . " ";
|
||||
}
|
||||
for ($j=$skip;$j<@_;$j++) {
|
||||
$tmptoken = $_[$j];
|
||||
while (defined($param{$tmptoken})) {
|
||||
$tmptoken = $param{$tmptoken};
|
||||
}
|
||||
$nline .= $tmptoken . " ";
|
||||
# print STDERR "first $_[$j]\n" if ($j == $skip);
|
||||
|
||||
}
|
||||
# print STDERR "$nline \n" if ($nline =~ /pwl/);
|
||||
$_=$nline;
|
||||
# undelimit openbracket for v(??) only
|
||||
s/([vi]) \(\s*([^\)\s]*)\s*\)/$1\($2\)/g;
|
||||
s/ = /=/g; #
|
||||
s/ $//; # trailing space
|
||||
$deck[$i]=$_;
|
||||
} }
|
||||
|
||||
################## add globals to subckt IO line ######################
|
||||
|
||||
# accept subroutine data
|
||||
# add used global signals to the io defn line
|
||||
# remember them in $globalsub{sub} to fix other instantiate lines
|
||||
sub expand_global_subs {
|
||||
local ($i,$subroutine,$extras,%nodes,$subckt);
|
||||
for ($i=0;$i<@deck;$i++) {
|
||||
$_=$deck[$i];
|
||||
if (defined($subckt)) { # remember nodes if in a subckt
|
||||
@_=split;
|
||||
for ($j=1;$j<@_-1;$j++) { # not first or last
|
||||
$nodes{$_[$j]}++ if (defined($global{$_[$j]}));
|
||||
}
|
||||
}
|
||||
if (/^\.subckt\s+(\S+)/) {
|
||||
$subckt=$1;
|
||||
$line=$i;
|
||||
}
|
||||
elsif (/^\.ends/) {
|
||||
$extras=join(" ", keys %nodes);
|
||||
$deck[$line] =~ s/^(.subckt.*)$/$1 $extras/;
|
||||
$globalsub{$subckt}=$extras;
|
||||
undef $subckt;
|
||||
} } }
|
||||
|
||||
sub expand_global_calls {
|
||||
local ($i);
|
||||
for ($i=0;$i<@deck;$i++) {
|
||||
$_=$deck[$i];
|
||||
if (/^(x.*)\s+(\S+)\s*$/ && defined($globalsub{$2})) {
|
||||
$deck[$i]="$1 $globalsub{$2} $2\n";
|
||||
} } }
|
||||
############ measure ####################
|
||||
# appears you have to linearize it all the first time
|
||||
sub expand_linearize {
|
||||
local ($i,@xtra,$first);
|
||||
for ($i=0;$i<@deck;$i++) {
|
||||
$_=$deck[$i];
|
||||
if (/^\.(tran|ac|dc)/) {
|
||||
$analysis=$1;
|
||||
}
|
||||
elsif (/^\.measu?r?e?\s+(\S+)\s+trig(.*)/) {
|
||||
$_=".meas $analysis $1 trig$2";
|
||||
$deck[$i]=$_;
|
||||
# fill in the missing type so I don't have to think later
|
||||
}
|
||||
if (/^\.measu?r?e? (tran|dc|ac)\s+(\S+)\s+trig\s+(\S+) .* targ\s+(\S+) .*/) {
|
||||
$first=$i unless (defined($first));
|
||||
$linearize{$3}=1;
|
||||
$linearize{$4}=1;
|
||||
}
|
||||
}
|
||||
if (defined($first)) {
|
||||
push(@xtra, ".control");
|
||||
$list=join(" ", keys %linearize);
|
||||
push(@xtra, "linearize time $list");
|
||||
push(@xtra, ".endc");
|
||||
splice(@deck,$first,0,@xtra);
|
||||
@xtra=();
|
||||
}
|
||||
}
|
||||
sub expand_meas {
|
||||
local ($i,@xtra);
|
||||
for ($i=0;$i<@deck;$i++) {
|
||||
$_=$deck[$i];
|
||||
if (/^\.measu?r?e? (tran|dc|ac)\s+(\S+)\s+trig\s+(\S+) .* targ\s+(\S+) .*/) {
|
||||
$name=$2;
|
||||
$trig=$3;
|
||||
$targ=$4;
|
||||
push(@xtra, ".control");
|
||||
push(@xtra, "print time $trig $targ > meas.data");
|
||||
push(@xtra, "echo $_ > meas.ctl");
|
||||
push(@xtra, "shell measure_spice $name");
|
||||
push(@xtra, ".endc");
|
||||
splice(@deck,$i,1,@xtra);
|
||||
@xtra=();
|
||||
}
|
||||
}
|
||||
}
|
||||
####################### control codes #############
|
||||
sub expand_control {
|
||||
local ($i,@xtra);
|
||||
for ($i=0;$i<@deck;$i++) {
|
||||
$_=$deck[$i];
|
||||
if (/^\.(plot|print|tran|end)\b/) {
|
||||
$cmd=$1;
|
||||
s/^\.//; # drop initial dot
|
||||
s/\stran\s/ /;
|
||||
s/start=\S+//; # starts annow it
|
||||
push(@xtra, ".control");
|
||||
if ($cmd eq "end") {
|
||||
push(@xtra, "destroy all" ) unless ($interactive);
|
||||
push(@xtra, "quit") unless ($interactive);
|
||||
}
|
||||
else {
|
||||
push(@xtra, $_);
|
||||
}
|
||||
push(@xtra, ".endc");
|
||||
splice(@deck,$i,1,@xtra);
|
||||
@xtra=();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
################# translate model level #######
|
||||
# bsim3 (v3)
|
||||
sub fix_temp {
|
||||
for ($i=0;$i<@deck;$i++) {
|
||||
if ($deck[$i] =~ /^\.tempe?r?a?t?u?r?e?\s*\=\s*(\S+)/) {
|
||||
$deck[$i] = ".options temp=$1";
|
||||
} } }
|
||||
|
||||
sub printdeck {
|
||||
for (@deck) {
|
||||
print &wrapline(70,"","+","\n"," ",split(" ",$_));
|
||||
}
|
||||
}
|
||||
|
||||
######################### wrapline ###############
|
||||
|
||||
# wrapline( linelen, header, header2, trailer,
|
||||
# separator, list )
|
||||
# where
|
||||
# linelen max number of chars per line eg 70
|
||||
# header is a string stuck on to the beginning
|
||||
# header2 is a string to add to the second and all subsequent lines,
|
||||
# {if they exist]
|
||||
# trailer is a string to tack on to the end of the structure
|
||||
# separator is put between multiple elements in the list (NOT last)
|
||||
# list
|
||||
# returns string
|
||||
|
||||
sub wrapline {
|
||||
local($maxlen, $header, $header2, $trailer,
|
||||
$separator, $linelen, @list, $output, $term, $last_term);
|
||||
|
||||
($maxlen, $header, $header2, $trailer, $separator, @list)=@_;
|
||||
$output=$header;
|
||||
$linelen=length($output);
|
||||
$last_term=pop(@list);
|
||||
foreach $term (@list) {
|
||||
if ((length($term)+$linelen+length($separator))>$maxlen) {
|
||||
$output .= "\n$header2" ;
|
||||
$linelen = length($header2);
|
||||
}
|
||||
$output .= "$term$separator";
|
||||
$linelen += length($term)+ length($separator);
|
||||
}
|
||||
if ((length($last_term)+$linelen+length($trailer))>$maxlen) {
|
||||
$output .= "\n$header2" ;
|
||||
}
|
||||
$output .= "$last_term$trailer";
|
||||
return $output;
|
||||
}
|
||||
|
||||
######################### equation support ########
|
||||
sub isnumber {
|
||||
if (($_[0] =~ /\s*[\+\-]?[0-9\.]+\s*/) ||
|
||||
($_[0] =~ /\s*[\+\-]?[0-9\.]+e[\+\-]?\d+/)) {
|
||||
return 1;
|
||||
}
|
||||
else {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
sub process {
|
||||
# print STDERR "mapped $_[0] ";
|
||||
local ($nline,$r,$i,$tmptoken);
|
||||
$_=$_[0];
|
||||
s/([\(\)\*\/])/ $1 /g; # space delimit operators
|
||||
s/([^eE])([\+\-])/$1 $2 /g; # special case for 1e-10 etc.
|
||||
s/\^\^/ ^^ /g; # space delimit exponent
|
||||
# print STDERR " delim $_ ";
|
||||
@_=split;
|
||||
for ($i=0;$i<@_;$i++) {
|
||||
$tmptoken = $_[$i];
|
||||
while (defined($param{$tmptoken})) {
|
||||
$tmptoken = $param{$tmptoken};
|
||||
}
|
||||
$nline .= $tmptoken . " ";
|
||||
}
|
||||
# print STDERR " $nline " ;
|
||||
$r=eval($nline);
|
||||
print STDERR $@ if ($@ ne '');
|
||||
# print STDERR "to $r\n";
|
||||
return $r;
|
||||
}
|
||||
|
||||
# probably only one level deep..
|
||||
sub eval_parameters {
|
||||
local ($val, $nval, $param);
|
||||
for $param (keys %param) {
|
||||
# print STDERR "checking param $param \n";
|
||||
$val=$param{$param};
|
||||
if ($val =~ /[\'\"](.*)[\'\"]/) {
|
||||
$nval=&process($1);
|
||||
# print STDERR "eval: processed $val to $nval\n";
|
||||
$param{$param}=$nval;
|
||||
}
|
||||
else {
|
||||
$nval = &unit($val);
|
||||
# print STDERR "eval: united $val to $nval\n";
|
||||
$param{$param}=$nval;
|
||||
}
|
||||
}
|
||||
}
|
||||
sub expand_eqns {
|
||||
local ($i,$head,$tail,$p);
|
||||
for ($i=0;$i<@deck;$i++) {
|
||||
$_=$deck[$i];
|
||||
while (/(.*)\'([^\']*)\'(.*)/) {
|
||||
$head=$1; $tail=$3;
|
||||
$p=&process($2);
|
||||
$_=$head . " $p " . $tail;
|
||||
s/= /=/g;
|
||||
# print STDERR "translated $deck[$i]\n to $_\n";
|
||||
}
|
||||
$deck[$i]=$_;
|
||||
}
|
||||
}
|
||||
# if it looks like v(pin) replace with pin
|
||||
sub remove_vbracket {
|
||||
local ($i,$nline);
|
||||
for ($i=0;$i<@deck;$i++) {
|
||||
$_=$deck[$i];
|
||||
$nline='';
|
||||
for (split) {
|
||||
if (/^v\((.*)\)$/) {
|
||||
# print STDERR "found vbracket $_ to $1 line $i\n";
|
||||
$_=$1;
|
||||
}
|
||||
$nline .= $_ . " ";
|
||||
}
|
||||
$deck[$i]=$nline;
|
||||
} }
|
||||
|
||||
|
||||
|
||||
|
||||
sub unit {
|
||||
if ($_[0] =~ /^([0-9e\+\-\.]+)(t|g|meg|k|mil|m|u|n|p|f)?(v|a|s)?$/) {
|
||||
if ($2 eq 't') { $mult = 1e12 }
|
||||
elsif ($2 eq 'g') { $mult = 1e9 }
|
||||
elsif ($2 eq 'meg') { $mult = 1e6 }
|
||||
elsif ($2 eq 'k') { $mult = 1e3 }
|
||||
elsif ($2 eq 'm') { $mult = 1e-3 }
|
||||
elsif ($2 eq 'u') { $mult = 1e-6 }
|
||||
elsif ($2 eq 'n') { $mult = 1e-9 }
|
||||
elsif ($2 eq 'p') { $mult = 1e-12 }
|
||||
elsif ($2 eq 'f') { $mult = 1e-15 }
|
||||
elsif ($2 eq 'mil') { $mult = 25.4e-6}
|
||||
else { $mult = 1 }
|
||||
# print STDERR "unit $_[0] mult $mult val $1 letter $2 unit $3\n";
|
||||
return $1 * $mult;
|
||||
}
|
||||
return $_[0]; # maybe perl does it better??
|
||||
}
|
||||
|
||||
|
||||
# when substituting parameters , skip this number from the start
|
||||
sub skipnumber {
|
||||
local ($in,$f);
|
||||
$in=$_[0];
|
||||
$_=substr($in,0,1); # get the first char in the line
|
||||
$f=$_;
|
||||
# apart from the bjt - which I treat as a 3node device - all these
|
||||
# have a fixed number of nodes
|
||||
$n=tr/cdefghijklmoqrstuvw/2244442322443244424/; # element nodes
|
||||
# print STDERR "first char $f matched $_ skip $_ \n";
|
||||
if ($n == 1) {
|
||||
return $_+1; # add the name of the instance to the number of nodes
|
||||
}
|
||||
@_=split(" ",$in);
|
||||
$_=@_;
|
||||
if ($f eq 'x') { # only the last on ein a subckt call
|
||||
return $_-1;
|
||||
}
|
||||
$first=shift(@_);
|
||||
if ($first =~ /^\.meas/) { return 1 } # process this line
|
||||
elsif ($first =~ /^\.tran/) { return 1 } # process this line
|
||||
elsif ($first =~ /^\.lib/) { return 2 } # process last one
|
||||
elsif ($first =~ /^\.model/) { return 3 }
|
||||
else { return $_ } # skip the line
|
||||
}
|
||||
|
||||
################Fix all model incompatabilites #####################
|
||||
|
||||
sub process_models {
|
||||
$spice_scale = 1;
|
||||
|
||||
&change_models;
|
||||
&change_instances;
|
||||
}
|
||||
|
||||
################# reads all avalible models ####################
|
||||
######### Translate the hspice levels to ones for ng-spice ##########
|
||||
# The wise men at multigig have decided the following:
|
||||
#if level= 28 then use level=4
|
||||
# if level=49 or 53
|
||||
# Check BSIM version,
|
||||
# if version = 3.2 use level 50 (3v3.2)
|
||||
# if version = 3.1 use level 49 (3v3.1)
|
||||
# if version = 4.2 use level 14 (4v2.1)
|
||||
# else use level 8
|
||||
# (most up to date model, 3v3.2.2 at the moment)
|
||||
# The parameters are also modified as follows:
|
||||
#always remove the following:
|
||||
#hspver, acm, calcasm, ldif, hdif, rd, rs, rsc, rdc (not used)
|
||||
# Remove: NQSMOD if version >= 3v3.2
|
||||
|
||||
sub change_models {
|
||||
local ($i,$model,@params,%default,$bin,$p);
|
||||
%default = (acm => 0, calcacm => 0, lmlt => 1, wmlt => 1, xl => 0,
|
||||
xw => 0, php => 1, ldif => 0, hdif => 0, lmin => 0,
|
||||
lmax => 0, wmin => 0, wmax => 0, hspver => 0,
|
||||
rd => 0, rs => 0, rsc => 0, rdc => 0, geo => 0,
|
||||
tlev => 0, nlev => 0, n => 0, tt => 0, binflag => 1,
|
||||
# There are from Bsim4.3 which ngspice does not have
|
||||
stimod => -1, sa0 => 0, sb0 => 0, kvsat => 0, wlod => 0,
|
||||
tku0 => 0, ku0 => 0, llodku0 => 0, wlodku0 => 0, lku0 => 0, wku0 => 0,
|
||||
pku0 => 0, kvth0 => 0, stk2 => 0, steta0 => 0, lkvth0 => 0, wkvth0 => 0,
|
||||
pkvth0 => 0, llodvth => 0, wlodvth => 0, lodk2 => 1, lodeta0 => 1);
|
||||
for ($i=0;$i<@deck;$i++) {
|
||||
$_ = $deck[$i];
|
||||
if(/^\.model\s+(\S+)\s+[np]mos/) {
|
||||
# print STDERR "got ".$_."\n";
|
||||
|
||||
split /\./, $1 ;
|
||||
$model = $_[0];
|
||||
$bin = $1;
|
||||
push @$model, $bin;
|
||||
|
||||
#First read level and version info and set the level
|
||||
#and put acm to default value
|
||||
|
||||
$_ = $deck[$i];
|
||||
/\blevel\s*=\s*([0-9]+)\b/;
|
||||
|
||||
if($1 == 49){
|
||||
$$bin{"acm"} = 0;}
|
||||
elsif($1 == 53){
|
||||
$$bin{"acm"} = 10;}
|
||||
else{
|
||||
$$bin{"acm"} = 0; }
|
||||
|
||||
if(/\bversion\s*=\s*([0-9\.]+)\b/){
|
||||
|
||||
if($1 eq "3.2"){
|
||||
$deck[$i] =~ s/\blevel\s*=\s*[0-9]+\b/level=50/;
|
||||
$deck[$i] =~ s/(.*)\bnqsmod\s*=\s*\S*\b(.*)/$1$2/;}
|
||||
|
||||
elsif($1 eq "3.1"){
|
||||
$deck[$i] =~ s/\blevel\s*=\s*[0-9]+\b/level=49/;}
|
||||
|
||||
elsif($1 eq "4.2"){
|
||||
$deck[$i] =~ s/\blevel\s*=\s*[0-9]+\b/level=14/;
|
||||
$deck[$i] =~ s/\bversion\s*=\s*[0-9\.]+\b/version=4.2.1/;
|
||||
} else {
|
||||
$deck[$i] =~ s/\blevel\s*=\s*[0-9]+\b/level=8/;
|
||||
$deck[$i] =~ s/(.*)\bnqsmod\s*=\s*\S*\b(.*)/$1$2/;}
|
||||
}
|
||||
|
||||
|
||||
# get rid of hspice only variables, and store them
|
||||
foreach $p (keys %default){
|
||||
if ($p ne "acm"){
|
||||
$$bin{$p} = $default{$p};}
|
||||
}
|
||||
$newline = "";
|
||||
@list = split /[\s\(\)]/,$deck[$i];
|
||||
# zap ".model name type"
|
||||
$newline = shift @list;
|
||||
$newline .= " " . shift @list;
|
||||
$newline .= " " . shift @list;
|
||||
foreach $item (@list) {
|
||||
($name,$value) = split /=/,$item;
|
||||
if(exists($default{$name})){
|
||||
$$bin{$name} = $value;
|
||||
} else {
|
||||
$newline .= " " . $item;
|
||||
}
|
||||
}
|
||||
$deck[$i] = $newline;
|
||||
|
||||
#translate some vars
|
||||
$deck[$i] =~ s/(\b)tref(\s*=)/${1}tnom$2/;
|
||||
|
||||
#HDIFeff needed not HDIF
|
||||
$$bin{"hdif"} *= $$bin{"wmlt"};
|
||||
}
|
||||
#end if mosfet model
|
||||
if (/\.opt\S*\s+scale=(\S+)/) {
|
||||
$spice_scale = &unit($1);
|
||||
}
|
||||
}
|
||||
#end for
|
||||
}
|
||||
#end sub
|
||||
|
||||
#### selects the correct model and does l, w scaling and acm#####
|
||||
|
||||
|
||||
sub change_instances {
|
||||
local($i,$model,$l,$w,$p,$m,$ad,$as,$pd,$ps);
|
||||
for ($i=0;$i<@deck;$i++) {
|
||||
$_ = $deck[$i];
|
||||
if(/^m\S+\s+\S+\s+\S+\s+\S+\s+\S+\s+(\S+)/) {
|
||||
|
||||
#print STDERR "processing ".$_."\n";
|
||||
$model = $1;
|
||||
|
||||
|
||||
#Model binning
|
||||
if(/.*\bl\s*=\s*(\S+)\b.*/){
|
||||
$l = &unit($1);
|
||||
$l *= $spice_scale;
|
||||
}else {print STDERR "no l found\n";die;}
|
||||
|
||||
if(/.*\bw\s*=\s*(\S+)\b.*/){
|
||||
$w = &unit($1);
|
||||
$w *= $spice_scale;
|
||||
}else {print STDERR "no w found\n";die;}
|
||||
|
||||
#Loops though all bins and selects one
|
||||
foreach $p (@$model){
|
||||
if(
|
||||
$l <= $$p{'lmax'} &&
|
||||
$l >= $$p{'lmin'} &&
|
||||
$w <= $$p{'wmax'} &&
|
||||
$w >= $$p{'wmin'}
|
||||
){
|
||||
$deck[$i] =~
|
||||
s/(^\S+\s+\S+\s+\S+\s+\S+\s+\S+\s+)(\S+)/$1$p/;
|
||||
$model = $p;
|
||||
goto model_found;
|
||||
}
|
||||
}
|
||||
print STDERR "Model or bin not found for model=$model, w=$w, l=$l\n";
|
||||
next;
|
||||
model_found:
|
||||
#W & L mangling and acm stuff
|
||||
#Get m
|
||||
if($deck[$i] =~ s/(.*)\bm\s*=\s*([0-9]+)\b(.*)/$1$3/){
|
||||
$m = $2;}else {$m = 1;}
|
||||
|
||||
#get and remove pd, ps, ad, as
|
||||
if($deck[$i] =~ s/(.*)\bpd\s*=\s*(\S+)\b(.*)/$1$3/){
|
||||
$pd = &unit($2);
|
||||
$pd *= $spice_scale;
|
||||
}else{ $pd = 0;}
|
||||
|
||||
if($deck[$i] =~ s/(.*)\bps\s*=\s*(\S+)\b(.*)/$1$3/){
|
||||
$ps = &unit($2);
|
||||
$ps *= $spice_scale;
|
||||
}else{ $ps = 0;}
|
||||
|
||||
if($deck[$i] =~ s/(.*)\bas\s*=\s*(\S+)\b(.*)/$1$3/){
|
||||
$as = &unit($2);
|
||||
$as *= $spice_scale * $spice_scale;
|
||||
}else{ $as = 0;}
|
||||
|
||||
if($deck[$i] =~ s/(.*)\bad\s*=\s*(\S+)\b(.*)/$1$3/){
|
||||
$ad = &unit($2);
|
||||
$ad *= $spice_scale * $spice_scale;
|
||||
}else{ $ad = 0;}
|
||||
|
||||
#Calculate Leff and Weff
|
||||
$w = $m * ($w * $$model{"wmlt"} + $$model{"xw"});
|
||||
$l = $l * $$model{"lmlt"} + $$model{"xl"};
|
||||
|
||||
#Now do the ACM stuff......
|
||||
#gathered from Hspice manual release 1999.4 December 1999
|
||||
|
||||
#Now the perimeters and areas
|
||||
#calculated using hspice methods..
|
||||
if( $$model{"acm"} == 0){
|
||||
#pg 869, 19-33
|
||||
$ad = $m * $ad * $$model{"wmlt"} * $$model{"wmlt"};
|
||||
$as = $m * $as * $$model{"wmlt"} * $$model{"wmlt"};
|
||||
$pd = $m * $pd * $$model{"wmlt"};
|
||||
$ps = $m * $ps * $$model{"wmlt"};
|
||||
|
||||
}
|
||||
|
||||
elsif( $$model{"acm"} == 1){
|
||||
#pg 871, 19-35
|
||||
$as = $ad = $$model{"wmlt"} * $w;
|
||||
$ps = $pd = $w;
|
||||
}
|
||||
|
||||
elsif( $$model{"acm"} == 2){
|
||||
#pg 874, 19-39
|
||||
if($ad){
|
||||
$ad = $ad * $m * $$model{"wmlt"} * $$model{"wmlt"};
|
||||
}else {
|
||||
$ad = 2 * $$model{"hdif"} * $w;}
|
||||
|
||||
if($as){
|
||||
$as = $m * $as * $$model{"wmlt"} * $$model{"wmlt"};
|
||||
}else{
|
||||
$as = 2 * $$model{"hdif"} * $w;}
|
||||
|
||||
if($pd){
|
||||
$pd = $m * $pd * $$model{"wmlt"};
|
||||
}else {
|
||||
$pd = 4 * $$model{"hdif"} + 2 * $w;
|
||||
}
|
||||
|
||||
if($ps){
|
||||
$ps = $m * $ps * $$model{"wmlt"};
|
||||
}else{
|
||||
$ps = 4 * $$model{"hdif"} + 2 * $w;
|
||||
}
|
||||
}
|
||||
|
||||
elsif( $$model{"acm"} == 3){
|
||||
#pg 879, 19-43
|
||||
if($ad){
|
||||
$ad = $m * $ad * $$model{"wmlt"} * $$model{"wmlt"};}
|
||||
elsif($$model{"geo"} == 0 || $$model{"geo"} == 2){
|
||||
$ad = 2 * $$model{"hdif"} * $w;
|
||||
}else{
|
||||
$ad = $$model{"hdif"} * $w;
|
||||
}
|
||||
|
||||
if($as){
|
||||
$as = $m * $as * $$model{"wmlt"} * $$model{"wmlt"};}
|
||||
elsif($$model{"geo"} == 0 || $$model{"geo"} == 1){
|
||||
$as = 2 * $$model{"hdif"} * $w;
|
||||
}else{
|
||||
$as = $$model{"hdif"} * $w;
|
||||
}
|
||||
|
||||
if($pd){
|
||||
$pd = $m * $pd * $$model{"wmlt"};}
|
||||
elsif($$model{"geo"} == 0 || $$model{"geo"} == 2){
|
||||
$pd = 4 * $$model{"hdif"} + $w;
|
||||
}else{
|
||||
$pd = 2 * $$model{"hdif"};
|
||||
}
|
||||
|
||||
if($ps){
|
||||
$ps = $m * $ps * $$model{"wmlt"};}
|
||||
elsif($$model{"geo"} == 0 || $$model{"geo"} == 1){
|
||||
$ps = 4 * $$model{"hdif"} + $w;
|
||||
}else{
|
||||
$ps = 2 * $$model{"hdif"};
|
||||
}
|
||||
}
|
||||
|
||||
#following acm's from pg 1198, 26-246
|
||||
|
||||
elsif( $$model{"acm"} == 10){
|
||||
|
||||
}
|
||||
|
||||
elsif( $$model{"acm"} == 11){
|
||||
|
||||
}
|
||||
|
||||
elsif( $$model{"acm"} == 12 ){
|
||||
if( $$model{"calcacm"} == 1 ) {
|
||||
if($ad){
|
||||
$ad = $ad * $$model{"wmlt"} * $$model{"wmlt"};
|
||||
}else{
|
||||
$ad = 2 * $$model{"hdif"} * $w;
|
||||
}
|
||||
|
||||
if($as){
|
||||
$as = $as * $$model{"wmlt"} * $$model{"wmlt"};
|
||||
}else{
|
||||
$as = 2 * $$model{"hdif"} * $w;
|
||||
}
|
||||
|
||||
if($ps){
|
||||
$ps = $ps * $$model{"wmlt"};
|
||||
}else{
|
||||
$ps = 4 * $$model{"hdif"} + 2 * $w;
|
||||
}
|
||||
|
||||
if($pd){
|
||||
$pd = $pd * $$model{"wmlt"};
|
||||
}else{
|
||||
$pd = 4 * $$model{"hdif"} + 2 * $w;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
elsif( $$model{"acm"} == 13){
|
||||
|
||||
}
|
||||
else {
|
||||
print STDERR "Bad acm number in ".$model." ".$acm."\n";
|
||||
die;
|
||||
}
|
||||
|
||||
#Now write the values into the file......
|
||||
$l /= $spice_scale;
|
||||
$w /= $spice_scale;
|
||||
|
||||
$pd /= $spice_scale;
|
||||
$ps /= $spice_scale;
|
||||
|
||||
$as /= $spice_scale * $spice_scale;
|
||||
$ad /= $spice_scale * $spice_scale;
|
||||
|
||||
$deck[$i] =~ s/\b(l\s*=\s*)(\S+)\b/$1$l/;
|
||||
|
||||
$deck[$i] =~ s/\b(w\s*=\s*)(\S+)\b/$1$w/;
|
||||
|
||||
$deck[$i] .= " pd=".$pd." ps=".$ps." as=".$as." ad=".$ad;
|
||||
}
|
||||
#end if mosfet
|
||||
}
|
||||
#end for
|
||||
}
|
||||
#end of sub
|
||||
|
|
@ -0,0 +1,170 @@
|
|||
# Script to run Spicepp from Tcl
|
||||
# 07/06/04 - ad
|
||||
#
|
||||
# version 0.1.2
|
||||
#
|
||||
# note:
|
||||
# edit variable spicepp_dir to for dir contaning spicepp code
|
||||
# spicepp avaliable at http://sourceforge.net/projects/tclspice
|
||||
#
|
||||
|
||||
namespace eval spicepp {
|
||||
|
||||
variable version 0.1.3
|
||||
variable spicepp_dir $::spice_library/spice
|
||||
variable outFile_extension ".pp-cir"
|
||||
variable timeStamp_prefix "* spicepp:"
|
||||
variable Hspice_structures ".meas .param .lib .globals"
|
||||
|
||||
#------------------------------------------------------
|
||||
#
|
||||
# returns
|
||||
# - empty string if an error
|
||||
# - name of passed file if in spice3f5 syntax
|
||||
# - or name of translated file
|
||||
#
|
||||
proc convert { fileName } {
|
||||
|
||||
variable outFile_extension
|
||||
variable spicepp_dir
|
||||
|
||||
if {![file exists $fileName]} {
|
||||
puts "spicepp: '${fileName}' dosen't exist"
|
||||
return ""
|
||||
}
|
||||
|
||||
# output fileName
|
||||
set strLen [expr [string length $fileName] - [string length [file extension $fileName]] -1]
|
||||
set outFile [string range $fileName 0 $strLen]
|
||||
set outFile "${outFile}${outFile_extension}"
|
||||
|
||||
# check that input file contains Hspice statements
|
||||
if {![checkHSpiceFormat $fileName]} {
|
||||
puts "spicepp: '$fileName' doesn't contain any Hspice statements."
|
||||
return $fileName
|
||||
}
|
||||
|
||||
# check modified time stamp in previous generated output files
|
||||
# against modified time of input file
|
||||
if {![checkTimeStamp $fileName $outFile]} {
|
||||
puts "spicepp: '$fileName' hasn't been modified since last translation"
|
||||
return $outFile
|
||||
}
|
||||
|
||||
# conversion Start Time
|
||||
set sTime [clock seconds]
|
||||
|
||||
# execute Spicepp on given file
|
||||
puts "spicepp: converting '$fileName' > '$outFile'"
|
||||
|
||||
if {[catch {exec ${spicepp_dir}/spicepp.pl $fileName > $outFile} errResult]} {
|
||||
puts "spicepp couldn't convert '$fileName'"
|
||||
puts $errResult
|
||||
return ""
|
||||
}
|
||||
|
||||
# add time stamp to output file
|
||||
addTimeStamp $fileName $outFile
|
||||
|
||||
# Conversion Time
|
||||
#puts "Spicepp : [expr [clock seconds] - $sTime]s"
|
||||
|
||||
return $outFile
|
||||
}
|
||||
|
||||
#-----------------------------------------
|
||||
# adds the modified time of orginal spice deck to second line
|
||||
# of output file
|
||||
#
|
||||
proc addTimeStamp { inpFile outFile } {
|
||||
|
||||
variable timeStamp_prefix
|
||||
|
||||
set mTime [file mtime $inpFile]
|
||||
|
||||
set fileId [open $outFile "r"]
|
||||
set fileData [read $fileId]
|
||||
set fileData [split $fileData "\n"]
|
||||
close $fileId
|
||||
|
||||
set fileId [open $outFile "w"]
|
||||
set lineCnt 0
|
||||
|
||||
foreach lineData $fileData {
|
||||
|
||||
if {$lineCnt ==1} {
|
||||
puts $fileId "$timeStamp_prefix $mTime"
|
||||
}
|
||||
puts $fileId $lineData
|
||||
incr lineCnt
|
||||
}
|
||||
close $fileId
|
||||
}
|
||||
|
||||
#-------------------------------------------
|
||||
# Checks modified time stamp in output file against
|
||||
# modified time of input file
|
||||
proc checkTimeStamp { inpFile outFile } {
|
||||
|
||||
variable timeStamp_prefix
|
||||
|
||||
# check output file exists
|
||||
if {![file exists $outFile]} {
|
||||
return 1
|
||||
}
|
||||
|
||||
set fileId [open $outFile "r"]
|
||||
set fileData [read $fileId]
|
||||
set fileData [split $fileData "\n"]
|
||||
close $fileId
|
||||
|
||||
set timeStampData [lindex $fileData 1]
|
||||
set timeStampData [string range $timeStampData [string length $timeStamp_prefix] end]
|
||||
# remove spaces
|
||||
eval set timeStampData \"$timeStampData\"
|
||||
|
||||
if {![string is integer $timeStampData]} {
|
||||
return 1
|
||||
}
|
||||
|
||||
# compare modified times
|
||||
if { $timeStampData == [file mtime $inpFile] } {
|
||||
return 0
|
||||
}
|
||||
return 1
|
||||
}
|
||||
|
||||
#---------------------------------------------
|
||||
# parses the spice file for any Hspice stuctures
|
||||
# .meas .lib etc
|
||||
proc checkHSpiceFormat { fileName } {
|
||||
|
||||
variable Hspice_structures
|
||||
|
||||
set fileId [open $fileName "r"]
|
||||
set fileData [read $fileId]
|
||||
set fileData [split $fileData "\n"]
|
||||
close $fileId
|
||||
|
||||
for {set lineCnt 0} {$lineCnt < [llength $fileData]} {incr lineCnt} {
|
||||
set line [lindex $fileData $lineCnt]
|
||||
|
||||
# get line structre
|
||||
set line [string range $line 0 [expr [string first " " $line] -1]]
|
||||
|
||||
# lowercase
|
||||
set line [string tolower $line]
|
||||
|
||||
# skip line if '*' as lsearch returns a 0
|
||||
if {$line == "*"} { continue }
|
||||
|
||||
# check line structure against Hspice list
|
||||
if {[lsearch $Hspice_structures $line] != -1} {
|
||||
# puts "match found line $lineCnt : '$line'"
|
||||
return 1
|
||||
}
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
}
|
||||
150
src/spicewish
150
src/spicewish
|
|
@ -1,52 +1,114 @@
|
|||
#!/bin/sh
|
||||
#
|
||||
# 22/6/04 -ad
|
||||
|
||||
# the next line starts SpiceWish interactively with the given file name \
|
||||
exec wish "$0" "$@"
|
||||
|
||||
|
||||
namespace eval spicewish {
|
||||
|
||||
# load tclspice
|
||||
package require spice
|
||||
|
||||
proc 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 } {
|
||||
|
||||
# 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]} {
|
||||
|
||||
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
|
||||
|
||||
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 }
|
||||
default { usage }
|
||||
}
|
||||
} elseif {[file isfile $arg]} {
|
||||
set fileName $arg
|
||||
}
|
||||
}
|
||||
|
||||
if {$fileName == "" } { usage }
|
||||
|
||||
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 .
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
proc tclreadline { } {
|
||||
# readline with prompt set to "tclspice > "
|
||||
if {$::tcl_interactive} {
|
||||
package require tclreadline
|
||||
proc ::tclreadline::prompt1 { } { return "tclspice > " }
|
||||
::tclreadline::Loop
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
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
|
||||
}
|
||||
|
||||
spicewish::load $argv $argc
|
||||
|
||||
namespace import -force spice::*
|
||||
namespace import -force spicewish::*
|
||||
|
||||
spicewish::tclreadline
|
||||
|
|
|
|||
Loading…
Reference in New Issue