2004-06-22 Stefan Jones <stefan.jones@multigig.com>
* src/measure_spice.pl src/spicepp.pl.in Makefile.am: Add .measure statement support 2004-06-22 Adrian Dawe <adrian.dawe@multigig.com> * src/spicewish: Added -cm switch to load a codemodel
This commit is contained in:
parent
34d93b64c9
commit
a066cb7006
|
|
@ -7,7 +7,11 @@
|
|||
include <errno.h> for Tcl version of perror
|
||||
|
||||
* src/main.c:
|
||||
Add dummy INPretrieve() symbol so ngnutmeg and co link with xspice enabled
|
||||
Add dummy INPretrieve() symbol so ngnutmeg and co link with
|
||||
xspice enabled.
|
||||
|
||||
* src/measure_spice.pl src/spicepp.pl.in Makefile.am:
|
||||
Add .measure statement support
|
||||
|
||||
2004-06-22 Adrian Dawe <adrian.dawe@multigig.com>
|
||||
|
||||
|
|
@ -15,6 +19,9 @@
|
|||
src/Makefile.am:
|
||||
Added spicepp integration and spicewish command line options.
|
||||
|
||||
* src/spicewish:
|
||||
Added -cm switch to load a codemodel
|
||||
|
||||
2004-06-10 Stefan Jones <stefan.jones@multigig.com>
|
||||
|
||||
* include/ngspice.h:
|
||||
|
|
|
|||
|
|
@ -171,14 +171,20 @@ TCL_PKG_PATH = @TCL_PACKAGE_PATH@
|
|||
|
||||
TCLSPICE_VERSION = @VERSION@
|
||||
|
||||
TCL_FILES = libspice.so pkgIndex.tcl
|
||||
TCL_FILES = libspice.so pkgIndex.tcl measure_spice.pl spicepp.pl \
|
||||
tclspice_source.tcl spicepp.tcl
|
||||
|
||||
LIBSPICE_OBJS = tclspice.o
|
||||
|
||||
pkgIndex.tcl: pkgIndex.tcl.in
|
||||
rm -f pkgIndex.tcl
|
||||
sed -e 's;%LIB_DIR%;$(TCL_PKG_PATH);g' pkgIndex.tcl.in | \
|
||||
sed -e 's;%VERSION%;$(TCLSPICE_VERSION);g' > pkgIndex.tcl
|
||||
rm -f $@
|
||||
sed -e 's;%LIB_DIR%;$(TCL_PKG_PATH);g' $< | \
|
||||
sed -e 's;%VERSION%;$(TCLSPICE_VERSION);g' > $@
|
||||
|
||||
spicepp.pl: spicepp.pl.in
|
||||
rm -f $@
|
||||
sed -e 's;%LIB_DIR%;$(TCL_PKG_PATH);g' $< | \
|
||||
sed -e 's;%VERSION%;$(TCLSPICE_VERSION);g' > $@
|
||||
|
||||
install-tcl: install-tcl-recursive install-tclspice install-data-am
|
||||
|
||||
|
|
@ -197,6 +203,7 @@ install-tclspice: ${TCL_FILES}
|
|||
$(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
|
||||
$(mkinstalldirs) $(DESTDIR)$(bindir)
|
||||
$(INSTALL_PROGRAM) spicewish $(DESTDIR)$(bindir)
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,184 @@
|
|||
eval '(exit $?0)' &&
|
||||
eval 'exec perl -S $0 ${1+"$@"}' &&
|
||||
eval 'exec perl -S $0 $argv:q'
|
||||
if 0;
|
||||
# $Id$
|
||||
# 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.
|
||||
#
|
||||
# measure utility for spice
|
||||
# call to 'meas' inserted into spicedeck by spicepp
|
||||
# preceeded by write of a data and control file
|
||||
# copyright John Sheahan taudelta@integritynet.com.au
|
||||
$ver='$id$ ';
|
||||
|
||||
# data is in meas.data in pwd
|
||||
############# control information if=nfo is in meas.ctl
|
||||
# output is appended to spice.log
|
||||
$data="meas.data";
|
||||
$ctl="meas.ctl";
|
||||
$log="spice.log";
|
||||
|
||||
$date = `date`; chop($date);
|
||||
$user=$ENV{"USER"};
|
||||
|
||||
open CTL, $ctl || die "cannot open control file $ctl";
|
||||
$_=<CTL>;
|
||||
if (/^\.measu?r?e? (tran|dc|ac) (\S+) trig\s+(\S+) (.*)targ\s+(\S+)(.*)/) {
|
||||
$name=$2;
|
||||
$trig=$3;
|
||||
$trigstr=$4;
|
||||
$targ=$5;
|
||||
$targstr=$6;
|
||||
if ($trigstr =~ /\bval=(\S+)/) { $trigval=&unit($1)}
|
||||
else { print "ERROR: no trigger value\n"; }
|
||||
if ($trigstr =~ /\b(fall|rise|count)=(\S+)/) {$trigdrn=$1 ; $trigcount=&unit($2); }
|
||||
else { print "ERROR: no trigger rise/ fall / cross\n"; }
|
||||
if ($trigstr =~ /\btd=(\S+)/) {$trigdelay=&unit($1)}
|
||||
else {$trigdelay=0}
|
||||
if ($targstr =~ /\bval=(\S+)/) { $targval=&unit($1)}
|
||||
else { print "ERROR: no target value\n"; }
|
||||
if ($targstr =~ /\b(fall|rise|count)=(\S+)/) {$targdrn=$1 ; $targcount=&unit($2); }
|
||||
else { print "ERROR: no target rise/ fall / cross\n"; }
|
||||
if ($targstr =~ /\btd=(\S+)/) {$targdelay=&unit($1)}
|
||||
else {$targdelay=0}
|
||||
/^\.measu?r?e? (tran|dc|ac) \S+ (.*)/; $remainder=$2;
|
||||
}
|
||||
else {
|
||||
print "ERROR cannot parse command line\n";
|
||||
}
|
||||
close CTL;
|
||||
#($name, $a_level,$a_drn,$b_level,$b_drn)=split;
|
||||
|
||||
open DATA, $data || die "cannot open data file $data";
|
||||
$title=<DATA>;
|
||||
while (<DATA>) {
|
||||
if (/^(\d+)\s+([0-9\.e\+\-]+)\s+([0-9\.e\+\-]+)\s+([0-9\.e\+\-]+)/) {
|
||||
$time[$1]=$2;
|
||||
$a[$1]=$3;
|
||||
$b[$1]=$4;
|
||||
}
|
||||
}
|
||||
close DATA;
|
||||
|
||||
$first=&get_index($trigdelay,@time);
|
||||
if ($trigdrn eq 'rise') {
|
||||
$aindex = &get_rise($trigval,$trigcount,$first,@a);
|
||||
}
|
||||
elsif ($trigdrn eq 'fall') {
|
||||
$aindex = &get_fall($trigval,$trigcount,$first,@a);
|
||||
}
|
||||
else {
|
||||
$aindex = &get_cross($trigval,$trigcount,$first,@a);
|
||||
}
|
||||
$atime = &get_time($aindex,@time);
|
||||
#print "atime=$atime aindex=$aindex first=$first tdelay=$trigdelay count=$trigcount drn=$trigdrn\n";
|
||||
|
||||
$first=&get_index($targdelay,@time);
|
||||
if ($targdrn eq 'rise') {
|
||||
$bindex = &get_rise($targval,$targcount,$first,@b);
|
||||
}
|
||||
elsif ($targdrn eq 'fall') {
|
||||
$bindex = &get_fall($targval,$targcount,$first,@b);
|
||||
}
|
||||
else {
|
||||
$bindex = &get_cross($targval,$targcount,$first,@b);
|
||||
}
|
||||
$btime = &get_time($bindex,@time);
|
||||
#print "btime=$btime bindex=$bindex\n";
|
||||
#print "btime=$btime bindex=$bindex first=$first tdelay=$targdelay count=$targcount drn=$targdrn\n";
|
||||
$ans=$btime-$atime;
|
||||
|
||||
open LOG, ">>$log" || die "cannot open logfile $log";
|
||||
print LOG "$title";
|
||||
print LOG "$user $date\n";
|
||||
print LOG "$name=$ans trig=$atime targ=$btime $remainder\n\n";
|
||||
print "$user $date\n";
|
||||
print "$name=$ans trig=$atime targ=$btime $remainder\n";
|
||||
close LOG;
|
||||
|
||||
|
||||
################### get_fall ################
|
||||
sub get_fall {
|
||||
$level=shift(@_);
|
||||
$count=shift(@_);
|
||||
$first=shift(@_);
|
||||
for ($i=$first;$i<@_-1;$i++) {
|
||||
if (($_[$i] >= $level) && ($_[$i+1] < $level)) {
|
||||
$count--;
|
||||
return $i + (($_[$i]-$level)/($_[$i]-$_[$i+1])) if ($count==0);
|
||||
}
|
||||
}
|
||||
return undef;
|
||||
}
|
||||
sub get_rise {
|
||||
$level=shift(@_);
|
||||
$count=shift(@_);
|
||||
$first=shift(@_);
|
||||
for ($i=$first;$i<@_-1;$i++) {
|
||||
if (($_[$i] <= $level) && ($_[$i+1] > $level)) {
|
||||
$count--;
|
||||
return $i + (($level-$_[$i])/($_[$i+1]-$_[$i])) if ($count==0);
|
||||
}
|
||||
}
|
||||
return undef;
|
||||
}
|
||||
sub get_cross {
|
||||
$level=shift(@_);
|
||||
$count=shift(@_);
|
||||
$first=shift(@_);
|
||||
for ($i=$first;$i<@_-1;$i++) {
|
||||
if ((($_[$i] <= $level) && ($_[$i+1] > $level)) ||
|
||||
(($_[$i] >= $level) && ($_[$i+1] < $level))) {
|
||||
$count--;
|
||||
return $i + (($level-$_[$i])/($_[$i+1]-$_[$i])) if ($count==0);
|
||||
}
|
||||
}
|
||||
return undef;
|
||||
}
|
||||
# return the interpolated time corresponding to the (fractional) index
|
||||
sub get_time {
|
||||
$level=shift(@_);
|
||||
$index=int($level);
|
||||
$time = $_[$index] + (($_[$index+1] - $_[$index]) * ($level-$index));
|
||||
return $time;
|
||||
}
|
||||
|
||||
# return the first index at or after the given time
|
||||
sub get_index {
|
||||
$time=shift(@_);
|
||||
for ($i=0;$i<@_-1;$i++) {
|
||||
return $i if ($_[$i] >= $time)
|
||||
}
|
||||
return undef;
|
||||
}
|
||||
|
||||
|
||||
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 }
|
||||
return $1 * $mult;
|
||||
}
|
||||
else {
|
||||
print "ERROR: cannot result value $_[0]\n";
|
||||
}
|
||||
return $_; # maybe perl does it better??
|
||||
}
|
||||
|
|
@ -307,7 +307,7 @@ sub expand_meas {
|
|||
push(@xtra, ".control");
|
||||
push(@xtra, "print time $trig $targ > meas.data");
|
||||
push(@xtra, "echo $_ > meas.ctl");
|
||||
push(@xtra, "shell measure_spice $name");
|
||||
push(@xtra, "shell /usr/lib/spice/measure_spice.pl $name");
|
||||
push(@xtra, ".endc");
|
||||
splice(@deck,$i,1,@xtra);
|
||||
@xtra=();
|
||||
|
|
|
|||
|
|
@ -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 %LIB_DIR%/spice/measure_spice.pl $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
|
||||
|
|
@ -14,6 +14,7 @@ namespace eval spicewish {
|
|||
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
|
||||
|
|
@ -52,6 +53,7 @@ namespace eval spicewish {
|
|||
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]
|
||||
|
|
@ -69,6 +71,10 @@ namespace eval spicewish {
|
|||
-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]} {
|
||||
|
|
@ -78,6 +84,12 @@ namespace eval spicewish {
|
|||
|
||||
if {$fileName == "" } { usage }
|
||||
|
||||
if {[llength $codeModels] != 0} {
|
||||
foreach codeModel $codeModels {
|
||||
spice::codemodel $codeModel
|
||||
}
|
||||
}
|
||||
|
||||
if {$mode_spicePP} {
|
||||
set fileName [ run_spicepp $fileName ]
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue