8 changed files with 28 additions and 1168 deletions
-
82src/xspice/icm/dlmain.c
-
193src/xspice/icm/icm_spice2poly/Makefile.am
-
49src/xspice/icm/icm_spice2poly/README
-
305src/xspice/icm/icm_spice2poly/cfunc.c
-
302src/xspice/icm/icm_spice2poly/cfunc.mod
-
187src/xspice/icm/icm_spice2poly/ifspec.c
-
75src/xspice/icm/icm_spice2poly/ifspec.ifs
-
3src/xspice/icm/icm_spice2poly/make.bat
@ -1,193 +0,0 @@ |
|||
## Process this file with automake to produce Makefile.in
|
|||
#
|
|||
# Makefile.am hand-crafted by SDB on 5.25.2003 to create POLY
|
|||
# codemodel shared object. To enable simulation of POLY controlled sources,
|
|||
# do the following:
|
|||
#
|
|||
|
|||
# Edit this to point to cmpp in your installation.
|
|||
CMPPDIR = $(top_srcdir)/src/xspice/cmpp |
|||
|
|||
##------ automake definitions below. ------
|
|||
##
|
|||
|
|||
## Yes, listing all this stuff is ugly, but I wasn't clever enough to
|
|||
## find a better way to make it work.
|
|||
|
|||
SYSTEM_LIBS = -lm -lncurses -L/usr/X11R6/lib -lX11 -lXt -lXext -lXmu -lXaw -lSM -lICE |
|||
|
|||
LOCAL_LIBS = -lcmxsp,-levtxsp,-lidnxsp,-lipcxsp,-lenhxsp,-lmifxsp,-ldev,-lckt,-linp,-lparser,-lhlp,-linp,-lderiv,-lcmaths,-lpoly,-lni,-lsparse,-lmisc,-lfte,-lplotting |
|||
|
|||
DEVICE_LIBS = -lasrc,-lbjt,-lbsim1,-lbsim2,-lbsim3,-lbsim3v1,-lbsim3v2,-lbsim4,-lcap,-lbsim3soipd,-lbsim3soifd,-lbsim3soidd,-lcccs,-lccvs,-lccvs,-lcpl,-lcsw,-ldio,-lind,-lisrc,-lhfet,-lhfet2,-ljfet,-ljfet2,-lltra,-lmes,-lmesa,-lmos1,-lmos2,-lmos3,-lmos6,-lmos9,-lres,-lsoi3,-lsw,-ltxl,-ltra,-lurc,-lvccs,-lvcvs,-lvsrc |
|||
|
|||
|
|||
LOCAL_LIB_DIRS = \
|
|||
-L$(top_srcdir)/src/xspice/cm/ \
|
|||
-L$(top_srcdir)/src/xspice/enh/ \
|
|||
-L$(top_srcdir)/src/xspice/evt/ \
|
|||
-L$(top_srcdir)/src/xspice/idn/ \
|
|||
-L$(top_srcdir)/src/xspice/ipc/ \
|
|||
-L$(top_srcdir)/src/xspice/mif/ \
|
|||
-L$(top_srcdir)/src/spicelib/devices/ \
|
|||
-L$(top_srcdir)/src/spicelib/analysis/ \
|
|||
-L$(top_srcdir)/src/spicelib/parser/ \
|
|||
\
|
|||
-L$(top_srcdir)/src/frontend/parser/ \
|
|||
-L$(top_srcdir)/src/frontend/help/ \
|
|||
-L$(top_srcdir)/src/maths/deriv/ \
|
|||
-L$(top_srcdir)/src/maths/cmaths/ \
|
|||
-L$(top_srcdir)/src/maths/poly/ \
|
|||
-L$(top_srcdir)/src/maths/ni/ \
|
|||
-L$(top_srcdir)/src/maths/sparse/ \
|
|||
-L$(top_srcdir)/src/misc/ \
|
|||
\
|
|||
-L$(top_srcdir)/src/frontend/ \
|
|||
-L$(top_srcdir)/src/frontend/plotting/ \
|
|||
\
|
|||
-L$(top_srcdir)/src/spicelib/devices/asrc/ \
|
|||
-L$(top_srcdir)/src/spicelib/devices/bjt/ \
|
|||
-L$(top_srcdir)/src/spicelib/devices/bsim1/ \
|
|||
-L$(top_srcdir)/src/spicelib/devices/bsim2/ \
|
|||
-L$(top_srcdir)/src/spicelib/devices/bsim3/ \
|
|||
-L$(top_srcdir)/src/spicelib/devices/bsim3v1/ \
|
|||
-L$(top_srcdir)/src/spicelib/devices/bsim3v2/ \
|
|||
-L$(top_srcdir)/src/spicelib/devices/bsim4/ \
|
|||
-L$(top_srcdir)/src/spicelib/devices/cap/ \
|
|||
-L$(top_srcdir)/src/spicelib/devices/bsim3soi_pd/ \
|
|||
-L$(top_srcdir)/src/spicelib/devices/bsim3soi_fd/ \
|
|||
-L$(top_srcdir)/src/spicelib/devices/bsim3soi_dd/ \
|
|||
-L$(top_srcdir)/src/spicelib/devices/cccs/ \
|
|||
-L$(top_srcdir)/src/spicelib/devices/ccvs/ \
|
|||
-L$(top_srcdir)/src/spicelib/devices/ccvs/ \
|
|||
-L$(top_srcdir)/src/spicelib/devices/cpl/ \
|
|||
-L$(top_srcdir)/src/spicelib/devices/csw/ \
|
|||
-L$(top_srcdir)/src/spicelib/devices/dio/ \
|
|||
\
|
|||
-L$(top_srcdir)/src/spicelib/devices/ind/ \
|
|||
-L$(top_srcdir)/src/spicelib/devices/isrc/ \
|
|||
-L$(top_srcdir)/src/spicelib/devices/hfet1/ \
|
|||
-L$(top_srcdir)/src/spicelib/devices/hfet2/ \
|
|||
-L$(top_srcdir)/src/spicelib/devices/jfet/ \
|
|||
-L$(top_srcdir)/src/spicelib/devices/jfet2/ \
|
|||
-L$(top_srcdir)/src/spicelib/devices/ltra/ \
|
|||
-L$(top_srcdir)/src/spicelib/devices/mes/ \
|
|||
-L$(top_srcdir)/src/spicelib/devices/mesa/ \
|
|||
-L$(top_srcdir)/src/spicelib/devices/mos1/ \
|
|||
-L$(top_srcdir)/src/spicelib/devices/mos2/ \
|
|||
-L$(top_srcdir)/src/spicelib/devices/mos3/ \
|
|||
-L$(top_srcdir)/src/spicelib/devices/mos6/ \
|
|||
-L$(top_srcdir)/src/spicelib/devices/mos9/ \
|
|||
-L$(top_srcdir)/src/spicelib/devices/res/ \
|
|||
-L$(top_srcdir)/src/spicelib/devices/soi3/ \
|
|||
-L$(top_srcdir)/src/spicelib/devices/sw/ \
|
|||
-L$(top_srcdir)/src/spicelib/devices/txl/ \
|
|||
-L$(top_srcdir)/src/spicelib/devices/tra/ \
|
|||
-L$(top_srcdir)/src/spicelib/devices/urc/ \
|
|||
-L$(top_srcdir)/src/spicelib/devices/vccs/ \
|
|||
-L$(top_srcdir)/src/spicelib/devices/vcvs/ \
|
|||
-L$(top_srcdir)/src/spicelib/devices/vsrc/ |
|||
|
|||
|
|||
EXTRA_LIB_DIRS = \
|
|||
-L$(top_srcdir)/src/xspice/cm/.libs/ \
|
|||
-L$(top_srcdir)/src/xspice/enh/.libs/ \
|
|||
-L$(top_srcdir)/src/xspice/evt/.libs/ \
|
|||
-L$(top_srcdir)/src/xspice/idn/.libs/ \
|
|||
-L$(top_srcdir)/src/xspice/ipc/.libs/ \
|
|||
-L$(top_srcdir)/src/xspice/mif/.libs/ \
|
|||
-L$(top_srcdir)/src/spicelib/devices/.libs/ \
|
|||
-L$(top_srcdir)/src/spicelib/analysis/.libs/ \
|
|||
-L$(top_srcdir)/src/spicelib/parser/.libs/ \
|
|||
\
|
|||
-L$(top_srcdir)/src/frontend/parser/.libs/ \
|
|||
-L$(top_srcdir)/src/frontend/help/.libs/ \
|
|||
-L$(top_srcdir)/src/maths/deriv/.libs/ \
|
|||
-L$(top_srcdir)/src/maths/cmaths/.libs/ \
|
|||
-L$(top_srcdir)/src/maths/poly/.libs/ \
|
|||
-L$(top_srcdir)/src/maths/ni/.libs/ \
|
|||
-L$(top_srcdir)/src/maths/sparse/.libs \
|
|||
-L$(top_srcdir)/src/misc/.libs/ \
|
|||
\
|
|||
-L$(top_srcdir)/src/frontend/.libs/ \
|
|||
-L$(top_srcdir)/src/frontend/plotting/.libs/ \
|
|||
\
|
|||
-L$(top_srcdir)/src/spicelib/devices/asrc/.libs/ \
|
|||
-L$(top_srcdir)/src/spicelib/devices/bjt/.libs/ \
|
|||
-L$(top_srcdir)/src/spicelib/devices/bsim1/.libs/ \
|
|||
-L$(top_srcdir)/src/spicelib/devices/bsim2/.libs/ \
|
|||
-L$(top_srcdir)/src/spicelib/devices/bsim3/.libs/ \
|
|||
-L$(top_srcdir)/src/spicelib/devices/bsim3v1/.libs/ \
|
|||
-L$(top_srcdir)/src/spicelib/devices/bsim3v2/.libs/ \
|
|||
-L$(top_srcdir)/src/spicelib/devices/bsim4/.libs/ \
|
|||
-L$(top_srcdir)/src/spicelib/devices/cap/.libs/ \
|
|||
-L$(top_srcdir)/src/spicelib/devices/bsim3soi_pd/.libs/ \
|
|||
-L$(top_srcdir)/src/spicelib/devices/bsim3soi_fd/.libs/ \
|
|||
-L$(top_srcdir)/src/spicelib/devices/bsim3soi_dd/.libs/ \
|
|||
-L$(top_srcdir)/src/spicelib/devices/cccs/.libs/ \
|
|||
-L$(top_srcdir)/src/spicelib/devices/ccvs/.libs/ \
|
|||
-L$(top_srcdir)/src/spicelib/devices/ccvs/.libs/ \
|
|||
-L$(top_srcdir)/src/spicelib/devices/cpl/.libs/ \
|
|||
-L$(top_srcdir)/src/spicelib/devices/csw/.libs/ \
|
|||
-L$(top_srcdir)/src/spicelib/devices/dio/.libs/ \
|
|||
\
|
|||
-L$(top_srcdir)/src/spicelib/devices/ind/.libs/ \
|
|||
-L$(top_srcdir)/src/spicelib/devices/isrc/.libs/ \
|
|||
-L$(top_srcdir)/src/spicelib/devices/hfet1/.libs/ \
|
|||
-L$(top_srcdir)/src/spicelib/devices/hfet2/.libs/ \
|
|||
-L$(top_srcdir)/src/spicelib/devices/jfet/.libs/ \
|
|||
-L$(top_srcdir)/src/spicelib/devices/jfet2/.libs/ \
|
|||
-L$(top_srcdir)/src/spicelib/devices/ltra/.libs/ \
|
|||
-L$(top_srcdir)/src/spicelib/devices/mes/.libs/ \
|
|||
-L$(top_srcdir)/src/spicelib/devices/mesa/.libs/ \
|
|||
-L$(top_srcdir)/src/spicelib/devices/mos1/.libs/ \
|
|||
-L$(top_srcdir)/src/spicelib/devices/mos2/.libs/ \
|
|||
-L$(top_srcdir)/src/spicelib/devices/mos3/.libs/ \
|
|||
-L$(top_srcdir)/src/spicelib/devices/mos6/.libs/ \
|
|||
-L$(top_srcdir)/src/spicelib/devices/mos9/.libs/ \
|
|||
-L$(top_srcdir)/src/spicelib/devices/res/.libs/ \
|
|||
-L$(top_srcdir)/src/spicelib/devices/soi3/.libs/ \
|
|||
-L$(top_srcdir)/src/spicelib/devices/sw/.libs/ \
|
|||
-L$(top_srcdir)/src/spicelib/devices/txl/.libs/ \
|
|||
-L$(top_srcdir)/src/spicelib/devices/tra/.libs/ \
|
|||
-L$(top_srcdir)/src/spicelib/devices/urc/.libs/ \
|
|||
-L$(top_srcdir)/src/spicelib/devices/vccs/.libs/ \
|
|||
-L$(top_srcdir)/src/spicelib/devices/vcvs/.libs/ \
|
|||
-L$(top_srcdir)/src/spicelib/devices/vsrc/.libs/ |
|||
|
|||
|
|||
INCLUDES = -I$(top_srcdir)/src/include -I$(top_srcdir) |
|||
|
|||
EXTRA_DIST = cfunc.mod ifspec.ifs README cfunc.c ifspec.c README |
|||
|
|||
MAINTAINERCLEANFILES = Makefile.in |
|||
|
|||
##------ Make targets listed below. ------
|
|||
|
|||
all: cfunc.o ifspec.o |
|||
|
|||
clean: |
|||
rm -f *.o *.cm *.la |
|||
rm -fR .libs |
|||
|
|||
cfunc.o: cfunc.c |
|||
$(CC) -fPIC $(INCLUDES) $(CFLAGS) -c cfunc.c |
|||
|
|||
ifspec.o: ifspec.c |
|||
$(CC) -fPIC $(INCLUDES) $(CFLAGS) -c ifspec.c |
|||
|
|||
# Don't use the below targets unless you know what you are doing!
|
|||
#
|
|||
# Hint: if you create ifspec.c using cmpp, you need to replace MIFunsetup
|
|||
# with NULL in ifspec.c before making ifspec.o (compiling with gcc) because
|
|||
# MIFunsetup is apparently unimplemented.
|
|||
#
|
|||
#cclean: clean
|
|||
# rm -f cfunc.c ifspec.c
|
|||
#
|
|||
#cfunc.c: cfunc.mod
|
|||
# $(CMPPDIR)/cmpp -mod cfunc.mod
|
|||
#
|
|||
#ifspec.c: ifspec.ifs
|
|||
# $(CMPPDIR)/cmpp -ifs
|
|||
|
|||
|
|||
@ -1,49 +0,0 @@ |
|||
This directory holds a codemodel which enables ngspice to handle SPICE |
|||
2 POLY attributes on controlled sources. In short, when a SPICE 2 |
|||
netlist is read in, any controlled sources with POLY attributes are |
|||
translated into codemodel devices with an associated .model which |
|||
invokes spice2poly to evaluate the polynomial. |
|||
|
|||
To use this model, you need to do the following: |
|||
|
|||
1. Compile the rest of ngspice/tclspice in the usual way from the |
|||
base directory. |
|||
|
|||
2. Download and install SPICE Opus (available from |
|||
http://www.fe.uni-lj.si/ ). From this you need the program cmpp, as |
|||
well as some of the include files. |
|||
|
|||
3. Edit the Makefile in this directory and make the variable CMPPDIR |
|||
point to the base location of your Opus installation. |
|||
|
|||
4. Edit the Makefile in the directory above (..) and make the |
|||
variable CMPDIR point to the base location of your Opus installation. |
|||
|
|||
5. Do "make" in the directory above (..). The makefiles are set up |
|||
to do all the necessary stuff to turn the spice2poly sources into a |
|||
shared object named spice2poly.cm which you can load into ngspice. |
|||
(Alternatively, you can do "make codemodels" from $(top_srcdir); I |
|||
have included codemodels as a target which cd's into the directory |
|||
below and does "make".) |
|||
|
|||
6. Read the codemodel into ngspice in the following way: |
|||
|
|||
ngspice 1 -> codemodel /usr/local/src/tclspice-0.2.10/src/xspice/icm/spice2poly.cm |
|||
|
|||
(Of course, you should point to the location where *you* built |
|||
spice2poly.cm!) You might want to put this invocation into your |
|||
spinit file (which usually lives in $(top_srcdir)/src/). |
|||
|
|||
7. Then read in your SPICE netlist. SPICE 2 POLY attributes in |
|||
controlled sources will be translated into .models invoking the |
|||
spice2poly codemodel. You should be able to run ngspice and simulate |
|||
in the usual way! |
|||
|
|||
---------------------------------------------------------------------- |
|||
Please send any comments/questions/bug reports to: |
|||
|
|||
Stuart Brorson |
|||
sdb@cloud9.net |
|||
|
|||
-- SDB 6.19.2003 |
|||
|
|||
@ -1,305 +0,0 @@ |
|||
#line 1 "cfunc.mod" |
|||
#include "cm.h" |
|||
#line 1 "cfunc.mod" |
|||
/* =========================================================================== |
|||
FILE cfunc.mod |
|||
|
|||
MEMBER OF process XSPICE |
|||
|
|||
Copyright 1991 |
|||
Georgia Tech Research Corporation |
|||
Atlanta, Georgia 30332 |
|||
All Rights Reserved |
|||
|
|||
PROJECT A-8503 |
|||
|
|||
AUTHORS |
|||
|
|||
9/12/91 Bill Kuhn |
|||
|
|||
MODIFICATIONS |
|||
|
|||
<date> <person name> <nature of modifications> |
|||
|
|||
SUMMARY |
|||
|
|||
This file contains the definition of a code model polynomial controlled |
|||
source compatible with SPICE 2G6 poly sources. |
|||
|
|||
INTERFACES |
|||
|
|||
spice2poly() |
|||
|
|||
REFERENCED FILES |
|||
|
|||
None. |
|||
|
|||
NON-STANDARD FEATURES |
|||
|
|||
None. |
|||
|
|||
=========================================================================== */ |
|||
|
|||
/* |
|||
|
|||
This code model implements the non-linear polynomial controlled sources |
|||
available in SPICE 2G6. An automatic translator added into the simulator |
|||
front end is used to map 2G6 syntax into a call to this model in the |
|||
required syntax. |
|||
|
|||
This model may also be called directly as follows: |
|||
|
|||
a1 [ <input(s)> ] <output> xxx |
|||
.model xxx spice2poly ( coef = [ <list of 2G6 compatible coefficients> ] ) |
|||
|
|||
Refer to the 2G6 User Guide for an explanation of the coefficients. |
|||
|
|||
|
|||
This model is patterned after the FORTRAN code used in the 2G6 simulator. |
|||
Function cm_poly() below performs the functions of subroutines NLCSRC and |
|||
EVPOLY. Function evterm() performs the function of subroutine EVTERM, |
|||
and function nxtpwr() performs the function of subroutine NXTPWR. |
|||
|
|||
*/ |
|||
|
|||
|
|||
|
|||
|
|||
void *malloc(int); |
|||
void free(void *); |
|||
|
|||
/* SPICE 2G6 type utility functions */ |
|||
static double evterm(double x, int n); |
|||
static void nxtpwr(int *pwrseq, int pdim); |
|||
|
|||
|
|||
|
|||
|
|||
void spice2poly (Mif_Private_t *private) |
|||
{ |
|||
int num_inputs; /* Number of inputs to model */ |
|||
int num_coefs; /* Number of coefficients */ |
|||
int *exp; /* List of exponents in products */ |
|||
/* One for each input */ |
|||
|
|||
int i; /* Counter */ |
|||
int j; /* Counter */ |
|||
int k; /* Counter */ |
|||
|
|||
double *in; /* Values of inputs to model */ |
|||
double *coef; /* Values of coefficients */ |
|||
|
|||
double sum; /* Temporary for accumulating sum of terms */ |
|||
double product; /* Temporary for accumulating product */ |
|||
|
|||
double *acgains; /* Static variable holding AC gains for AC analysis */ |
|||
|
|||
|
|||
/* Get number of input values */ |
|||
|
|||
num_inputs = private->conn[0]->size; |
|||
|
|||
/* If this is the first call to the model, allocate the static variable */ |
|||
/* array */ |
|||
|
|||
if(private->circuit.init) { |
|||
acgains = malloc(num_inputs * sizeof(double)); |
|||
for(i = 0; i < num_inputs; i++) |
|||
acgains[i] = 0.0; |
|||
private->inst_var[0]->element[0].pvalue = acgains; |
|||
} |
|||
else |
|||
acgains = private->inst_var[0]->element[0].pvalue; |
|||
|
|||
/* If analysis type is AC, use the previously computed DC partials */ |
|||
/* for the AC gains */ |
|||
|
|||
if(private->circuit.anal_type == MIF_AC) { |
|||
for(i = 0; i < num_inputs; i++) { |
|||
acgains = private->inst_var[0]->element[0].pvalue; |
|||
private->conn[1]->port[0]->ac_gain[0].port[i].real = acgains[i]; |
|||
private->conn[1]->port[0]->ac_gain[0].port[i].imag = 0.0; |
|||
} |
|||
return; |
|||
} |
|||
|
|||
/* Get input values and coefficients to local storage for faster access */ |
|||
|
|||
in = malloc(num_inputs * sizeof(double)); |
|||
for(i = 0; i < num_inputs; i++) |
|||
in[i] = private->conn[0]->port[i]->input.rvalue; |
|||
|
|||
num_coefs = private->param[0]->size; |
|||
|
|||
coef = malloc(num_coefs * sizeof(double)); |
|||
for(i = 0; i < num_coefs; i++) |
|||
coef[i] = private->param[0]->element[i].rvalue; |
|||
|
|||
|
|||
/* Allocate the array of exponents used in computing the poly terms */ |
|||
exp = malloc(num_inputs * sizeof(int)); |
|||
|
|||
/* Initialize the exponents to zeros */ |
|||
for(i = 0; i < num_inputs; i++) |
|||
exp[i] = 0; |
|||
|
|||
|
|||
/* Compute the output of the source by summing the required products */ |
|||
for(i = 1, sum = coef[0]; i < num_coefs; i++) { |
|||
|
|||
/* Get the list of powers for the product terms in this term of the sum */ |
|||
nxtpwr(exp, num_inputs); |
|||
|
|||
/* Form the product of the inputs taken to the required powers */ |
|||
for(j = 0, product = 1.0; j < num_inputs; j++) |
|||
product *= evterm(in[j], exp[j]); |
|||
|
|||
/* Add the product times the appropriate coefficient into the sum */ |
|||
sum += coef[i] * product; |
|||
} |
|||
private->conn[1]->port[0]->output.rvalue = sum; |
|||
|
|||
|
|||
/* Compute and output the partials for each input */ |
|||
for(i = 0; i < num_inputs; i++) { |
|||
|
|||
/* Reinitialize the exponent list to zeros */ |
|||
for(j = 0; j < num_inputs; j++) |
|||
exp[j] = 0; |
|||
|
|||
/* Compute the partials by summing the required products */ |
|||
for(j = 1, sum = 0.0; j < num_coefs; j++) { |
|||
|
|||
/* Get the list of powers for the product terms in this term of the sum */ |
|||
nxtpwr(exp, num_inputs); |
|||
|
|||
/* If power for input for which partial is being evaluated */ |
|||
/* is zero, the term is a constant, so the partial is zero */ |
|||
if(exp[i] == 0) |
|||
continue; |
|||
|
|||
/* Form the product of the inputs taken to the required powers */ |
|||
for(k = 0, product = 1.0; k < num_inputs; k++) { |
|||
/* If input is not the one for which the partial is being taken */ |
|||
/* take the term to the specified exponent */ |
|||
if(k != i) |
|||
product *= evterm(in[k], exp[k]); |
|||
/* else, take the derivative of this term as n*x**(n-1) */ |
|||
else |
|||
product *= exp[k] * evterm(in[k], exp[k] - 1); |
|||
} |
|||
|
|||
/* Add the product times the appropriate coefficient into the sum */ |
|||
sum += coef[j] * product; |
|||
} |
|||
|
|||
private->conn[1]->port[0]->partial[0].port[i] = sum; |
|||
|
|||
/* If this is DC analysis, save the partial for use as AC gain */ |
|||
/* value in an AC analysis */ |
|||
|
|||
if(private->circuit.anal_type == MIF_DC) |
|||
acgains[i] = sum; |
|||
} |
|||
|
|||
/* Free the allocated items and return */ |
|||
free(in); |
|||
free(coef); |
|||
free(exp); |
|||
|
|||
return; |
|||
} |
|||
|
|||
|
|||
/* Function evterm computes the value of x**n */ |
|||
|
|||
static double evterm( |
|||
double x, |
|||
int n) |
|||
{ |
|||
double product; /* Temporary accumlator for forming the product */ |
|||
|
|||
product = 1.0; |
|||
while(n > 0) { |
|||
product *= x; |
|||
n--; |
|||
} |
|||
|
|||
return(product); |
|||
} |
|||
|
|||
|
|||
|
|||
/* |
|||
|
|||
This function is a literal translation of subroutine NXTPWR in SPICE 2G6. |
|||
This was done to guarantee compatibility with the ordering of |
|||
coefficients used by 2G6. The 2G6 User Guide does not completely define |
|||
the algorithm used and the GOTO loaded FORTRAN code is difficult to unravel. |
|||
Therefore, a one-to-one translation was deemed the safest approach. |
|||
|
|||
No attempt is made to document the function statements since no documentaton |
|||
is available in the 2G6 code. However, it can be noted that the code |
|||
appears to generate the exponents of the product terms in the sum-of-products |
|||
produced by the following expansion for two and three dimensional polynomials: |
|||
|
|||
2D (a + b) ** n |
|||
3D (a + (b + c)) ** n |
|||
|
|||
where n begins at 1 and increments as needed for as many terms as there are |
|||
coefficients on the polynomial source SPICE deck card, and where terms that |
|||
are identical under the laws of associativity are dropped. Thus, for example, |
|||
the exponents for the following sums are produced: |
|||
|
|||
2D a + b + a**2 + ab + b**2 + c**3 + ... |
|||
3D a + b + c + a**2 + a*b + a*c + b**2 + bc + c**2 + a**3 + ... |
|||
|
|||
*/ |
|||
|
|||
/* Define a macro to tranlate between FORTRAN-style array references */ |
|||
/* and C-style array references */ |
|||
|
|||
#define PWRSEQ(x) pwrseq[x - 1] |
|||
|
|||
|
|||
static void nxtpwr( |
|||
int *pwrseq, /* Array of exponents */ |
|||
int pdim) |
|||
{ |
|||
int i; |
|||
int k; |
|||
int km1; |
|||
int psum; |
|||
|
|||
if(pdim == 1) goto stmt80; |
|||
k = pdim; |
|||
stmt10: if(PWRSEQ(k) != 0) goto stmt20; |
|||
k = k - 1; |
|||
if(k != 0) goto stmt10; |
|||
goto stmt80; |
|||
stmt20: if(k == pdim) goto stmt30; |
|||
PWRSEQ(k) = PWRSEQ(k) - 1; |
|||
PWRSEQ(k+1) = PWRSEQ(k+1) + 1; |
|||
goto stmt100; |
|||
stmt30: km1 = k - 1; |
|||
for(i = 1; i <= km1; i++) |
|||
if(PWRSEQ(i) != 0) goto stmt50; |
|||
stmt40: PWRSEQ(1) = PWRSEQ(pdim) + 1; |
|||
PWRSEQ(pdim) = 0; |
|||
goto stmt100; |
|||
stmt50: psum = 1; |
|||
k = pdim; |
|||
stmt60: if(PWRSEQ(k-1) >= 1) goto stmt70; |
|||
psum = psum + PWRSEQ(k); |
|||
PWRSEQ(k) = 0; |
|||
k = k - 1; |
|||
goto stmt60; |
|||
stmt70: PWRSEQ(k) = PWRSEQ(k) + psum; |
|||
PWRSEQ(k-1) = PWRSEQ(k-1) - 1; |
|||
goto stmt100; |
|||
stmt80: PWRSEQ(1) = PWRSEQ(1) + 1; |
|||
|
|||
stmt100: return; |
|||
|
|||
} |
|||
|
|||
@ -1,302 +0,0 @@ |
|||
/* =========================================================================== |
|||
FILE cfunc.mod |
|||
|
|||
MEMBER OF process XSPICE |
|||
|
|||
Copyright 1991 |
|||
Georgia Tech Research Corporation |
|||
Atlanta, Georgia 30332 |
|||
All Rights Reserved |
|||
|
|||
PROJECT A-8503 |
|||
|
|||
AUTHORS |
|||
|
|||
9/12/91 Bill Kuhn |
|||
|
|||
MODIFICATIONS |
|||
|
|||
<date> <person name> <nature of modifications> |
|||
|
|||
SUMMARY |
|||
|
|||
This file contains the definition of a code model polynomial controlled |
|||
source compatible with SPICE 2G6 poly sources. |
|||
|
|||
INTERFACES |
|||
|
|||
spice2poly() |
|||
|
|||
REFERENCED FILES |
|||
|
|||
None. |
|||
|
|||
NON-STANDARD FEATURES |
|||
|
|||
None. |
|||
|
|||
=========================================================================== */ |
|||
|
|||
/* |
|||
|
|||
This code model implements the non-linear polynomial controlled sources |
|||
available in SPICE 2G6. An automatic translator added into the simulator |
|||
front end is used to map 2G6 syntax into a call to this model in the |
|||
required syntax. |
|||
|
|||
This model may also be called directly as follows: |
|||
|
|||
a1 [ <input(s)> ] <output> xxx |
|||
.model xxx spice2poly ( coef = [ <list of 2G6 compatible coefficients> ] ) |
|||
|
|||
Refer to the 2G6 User Guide for an explanation of the coefficients. |
|||
|
|||
|
|||
This model is patterned after the FORTRAN code used in the 2G6 simulator. |
|||
Function cm_poly() below performs the functions of subroutines NLCSRC and |
|||
EVPOLY. Function evterm() performs the function of subroutine EVTERM, |
|||
and function nxtpwr() performs the function of subroutine NXTPWR. |
|||
|
|||
*/ |
|||
|
|||
|
|||
|
|||
|
|||
void *malloc(int); |
|||
void free(void *); |
|||
|
|||
/* SPICE 2G6 type utility functions */ |
|||
static double evterm(double x, int n); |
|||
static void nxtpwr(int *pwrseq, int pdim); |
|||
|
|||
|
|||
|
|||
|
|||
void spice2poly (ARGS) |
|||
{ |
|||
int num_inputs; /* Number of inputs to model */ |
|||
int num_coefs; /* Number of coefficients */ |
|||
int *exp; /* List of exponents in products */ |
|||
/* One for each input */ |
|||
|
|||
int i; /* Counter */ |
|||
int j; /* Counter */ |
|||
int k; /* Counter */ |
|||
|
|||
double *in; /* Values of inputs to model */ |
|||
double *coef; /* Values of coefficients */ |
|||
|
|||
double sum; /* Temporary for accumulating sum of terms */ |
|||
double product; /* Temporary for accumulating product */ |
|||
|
|||
double *acgains; /* Static variable holding AC gains for AC analysis */ |
|||
|
|||
|
|||
/* Get number of input values */ |
|||
|
|||
num_inputs = PORT_SIZE(in); |
|||
|
|||
/* If this is the first call to the model, allocate the static variable */ |
|||
/* array */ |
|||
|
|||
if(INIT) { |
|||
acgains = malloc(num_inputs * sizeof(double)); |
|||
for(i = 0; i < num_inputs; i++) |
|||
acgains[i] = 0.0; |
|||
STATIC_VAR(acgains) = acgains; |
|||
} |
|||
else |
|||
acgains = STATIC_VAR(acgains); |
|||
|
|||
/* If analysis type is AC, use the previously computed DC partials */ |
|||
/* for the AC gains */ |
|||
|
|||
if(ANALYSIS == MIF_AC) { |
|||
for(i = 0; i < num_inputs; i++) { |
|||
acgains = STATIC_VAR(acgains); |
|||
AC_GAIN(out,in[i]).real = acgains[i]; |
|||
AC_GAIN(out,in[i]).imag = 0.0; |
|||
} |
|||
return; |
|||
} |
|||
|
|||
/* Get input values and coefficients to local storage for faster access */ |
|||
|
|||
in = malloc(num_inputs * sizeof(double)); |
|||
for(i = 0; i < num_inputs; i++) |
|||
in[i] = INPUT(in[i]); |
|||
|
|||
num_coefs = PARAM_SIZE(coef); |
|||
|
|||
coef = malloc(num_coefs * sizeof(double)); |
|||
for(i = 0; i < num_coefs; i++) |
|||
coef[i] = PARAM(coef[i]); |
|||
|
|||
|
|||
/* Allocate the array of exponents used in computing the poly terms */ |
|||
exp = malloc(num_inputs * sizeof(int)); |
|||
|
|||
/* Initialize the exponents to zeros */ |
|||
for(i = 0; i < num_inputs; i++) |
|||
exp[i] = 0; |
|||
|
|||
|
|||
/* Compute the output of the source by summing the required products */ |
|||
for(i = 1, sum = coef[0]; i < num_coefs; i++) { |
|||
|
|||
/* Get the list of powers for the product terms in this term of the sum */ |
|||
nxtpwr(exp, num_inputs); |
|||
|
|||
/* Form the product of the inputs taken to the required powers */ |
|||
for(j = 0, product = 1.0; j < num_inputs; j++) |
|||
product *= evterm(in[j], exp[j]); |
|||
|
|||
/* Add the product times the appropriate coefficient into the sum */ |
|||
sum += coef[i] * product; |
|||
} |
|||
OUTPUT(out) = sum; |
|||
|
|||
|
|||
/* Compute and output the partials for each input */ |
|||
for(i = 0; i < num_inputs; i++) { |
|||
|
|||
/* Reinitialize the exponent list to zeros */ |
|||
for(j = 0; j < num_inputs; j++) |
|||
exp[j] = 0; |
|||
|
|||
/* Compute the partials by summing the required products */ |
|||
for(j = 1, sum = 0.0; j < num_coefs; j++) { |
|||
|
|||
/* Get the list of powers for the product terms in this term of the sum */ |
|||
nxtpwr(exp, num_inputs); |
|||
|
|||
/* If power for input for which partial is being evaluated */ |
|||
/* is zero, the term is a constant, so the partial is zero */ |
|||
if(exp[i] == 0) |
|||
continue; |
|||
|
|||
/* Form the product of the inputs taken to the required powers */ |
|||
for(k = 0, product = 1.0; k < num_inputs; k++) { |
|||
/* If input is not the one for which the partial is being taken */ |
|||
/* take the term to the specified exponent */ |
|||
if(k != i) |
|||
product *= evterm(in[k], exp[k]); |
|||
/* else, take the derivative of this term as n*x**(n-1) */ |
|||
else |
|||
product *= exp[k] * evterm(in[k], exp[k] - 1); |
|||
} |
|||
|
|||
/* Add the product times the appropriate coefficient into the sum */ |
|||
sum += coef[j] * product; |
|||
} |
|||
|
|||
PARTIAL(out,in[i]) = sum; |
|||
|
|||
/* If this is DC analysis, save the partial for use as AC gain */ |
|||
/* value in an AC analysis */ |
|||
|
|||
if(ANALYSIS == MIF_DC) |
|||
acgains[i] = sum; |
|||
} |
|||
|
|||
/* Free the allocated items and return */ |
|||
free(in); |
|||
free(coef); |
|||
free(exp); |
|||
|
|||
return; |
|||
} |
|||
|
|||
|
|||
/* Function evterm computes the value of x**n */ |
|||
|
|||
static double evterm( |
|||
double x, |
|||
int n) |
|||
{ |
|||
double product; /* Temporary accumlator for forming the product */ |
|||
|
|||
product = 1.0; |
|||
while(n > 0) { |
|||
product *= x; |
|||
n--; |
|||
} |
|||
|
|||
return(product); |
|||
} |
|||
|
|||
|
|||
|
|||
/* |
|||
|
|||
This function is a literal translation of subroutine NXTPWR in SPICE 2G6. |
|||
This was done to guarantee compatibility with the ordering of |
|||
coefficients used by 2G6. The 2G6 User Guide does not completely define |
|||
the algorithm used and the GOTO loaded FORTRAN code is difficult to unravel. |
|||
Therefore, a one-to-one translation was deemed the safest approach. |
|||
|
|||
No attempt is made to document the function statements since no documentaton |
|||
is available in the 2G6 code. However, it can be noted that the code |
|||
appears to generate the exponents of the product terms in the sum-of-products |
|||
produced by the following expansion for two and three dimensional polynomials: |
|||
|
|||
2D (a + b) ** n |
|||
3D (a + (b + c)) ** n |
|||
|
|||
where n begins at 1 and increments as needed for as many terms as there are |
|||
coefficients on the polynomial source SPICE deck card, and where terms that |
|||
are identical under the laws of associativity are dropped. Thus, for example, |
|||
the exponents for the following sums are produced: |
|||
|
|||
2D a + b + a**2 + ab + b**2 + c**3 + ... |
|||
3D a + b + c + a**2 + a*b + a*c + b**2 + bc + c**2 + a**3 + ... |
|||
|
|||
*/ |
|||
|
|||
/* Define a macro to tranlate between FORTRAN-style array references */ |
|||
/* and C-style array references */ |
|||
|
|||
#define PWRSEQ(x) pwrseq[x - 1] |
|||
|
|||
|
|||
static void nxtpwr( |
|||
int *pwrseq, /* Array of exponents */ |
|||
int pdim) |
|||
{ |
|||
int i; |
|||
int k; |
|||
int km1; |
|||
int psum; |
|||
|
|||
if(pdim == 1) goto stmt80; |
|||
k = pdim; |
|||
stmt10: if(PWRSEQ(k) != 0) goto stmt20; |
|||
k = k - 1; |
|||
if(k != 0) goto stmt10; |
|||
goto stmt80; |
|||
stmt20: if(k == pdim) goto stmt30; |
|||
PWRSEQ(k) = PWRSEQ(k) - 1; |
|||
PWRSEQ(k+1) = PWRSEQ(k+1) + 1; |
|||
goto stmt100; |
|||
stmt30: km1 = k - 1; |
|||
for(i = 1; i <= km1; i++) |
|||
if(PWRSEQ(i) != 0) goto stmt50; |
|||
stmt40: PWRSEQ(1) = PWRSEQ(pdim) + 1; |
|||
PWRSEQ(pdim) = 0; |
|||
goto stmt100; |
|||
stmt50: psum = 1; |
|||
k = pdim; |
|||
stmt60: if(PWRSEQ(k-1) >= 1) goto stmt70; |
|||
psum = psum + PWRSEQ(k); |
|||
PWRSEQ(k) = 0; |
|||
k = k - 1; |
|||
goto stmt60; |
|||
stmt70: PWRSEQ(k) = PWRSEQ(k) + psum; |
|||
PWRSEQ(k-1) = PWRSEQ(k-1) - 1; |
|||
goto stmt100; |
|||
stmt80: PWRSEQ(1) = PWRSEQ(1) + 1; |
|||
|
|||
stmt100: return; |
|||
|
|||
} |
|||
|
|||
@ -1,187 +0,0 @@ |
|||
|
|||
/* |
|||
* Structures for model: spice2poly |
|||
* |
|||
* Automatically generated by cmpp preprocessor |
|||
* |
|||
* !!! DO NOT EDIT !!! |
|||
* |
|||
*/ |
|||
|
|||
|
|||
// #include "prefix.h" |
|||
#include <stdio.h> |
|||
#include "ngspice.h" |
|||
#include "devdefs.h" |
|||
#include "ifsim.h" |
|||
#include "mifdefs.h" |
|||
#include "mifproto.h" |
|||
#include "mifparse.h" |
|||
// #include "suffix.h" |
|||
|
|||
|
|||
static IFparm MIFmPTable[] = { |
|||
IOP("coef", 0, (IF_REAL|IF_VECTOR), "2g6 compatible spice card coefficient list"), |
|||
}; |
|||
|
|||
|
|||
static IFparm MIFpTable[] = { |
|||
OP("acgains", 1, IF_STRING, "partial derivatives from dc analysis used for ac gains"), |
|||
}; |
|||
|
|||
|
|||
static Mif_Port_Type_t MIFportEnum0[] = { |
|||
MIF_DIFF_VOLTAGE, |
|||
MIF_DIFF_CURRENT, |
|||
MIF_VSOURCE_CURRENT, |
|||
}; |
|||
|
|||
|
|||
static char *MIFportStr0[] = { |
|||
"vd", |
|||
"id", |
|||
"vnam", |
|||
}; |
|||
|
|||
|
|||
static Mif_Port_Type_t MIFportEnum1[] = { |
|||
MIF_DIFF_VOLTAGE, |
|||
MIF_DIFF_CURRENT, |
|||
}; |
|||
|
|||
|
|||
static char *MIFportStr1[] = { |
|||
"vd", |
|||
"id", |
|||
}; |
|||
|
|||
|
|||
static Mif_Conn_Info_t MIFconnTable[] = { |
|||
{ |
|||
"in", |
|||
"input", |
|||
MIF_IN, |
|||
MIF_DIFF_VOLTAGE, |
|||
"vd", |
|||
3, |
|||
MIFportEnum0, |
|||
MIFportStr0, |
|||
MIF_TRUE, |
|||
MIF_TRUE, |
|||
1, |
|||
MIF_FALSE, |
|||
0, |
|||
MIF_FALSE, |
|||
}, |
|||
{ |
|||
"out", |
|||
"output", |
|||
MIF_OUT, |
|||
MIF_DIFF_VOLTAGE, |
|||
"vd", |
|||
2, |
|||
MIFportEnum1, |
|||
MIFportStr1, |
|||
MIF_FALSE, |
|||
MIF_FALSE, |
|||
0, |
|||
MIF_FALSE, |
|||
0, |
|||
MIF_FALSE, |
|||
}, |
|||
}; |
|||
|
|||
|
|||
static Mif_Param_Info_t MIFparamTable[] = { |
|||
{ |
|||
"coef", |
|||
"2g6 compatible spice card coefficient list", |
|||
MIF_REAL, |
|||
MIF_FALSE, |
|||
{MIF_FALSE, 0, 0.0, {0.0, 0.0}, NULL}, |
|||
MIF_FALSE, |
|||
{MIF_FALSE, 0, 0.0, {0.0, 0.0}, NULL}, |
|||
MIF_FALSE, |
|||
{MIF_FALSE, 0, 0.0, {0.0, 0.0}, NULL}, |
|||
MIF_TRUE, |
|||
MIF_FALSE, |
|||
0, |
|||
MIF_TRUE, |
|||
2, |
|||
MIF_FALSE, |
|||
0, |
|||
MIF_FALSE, |
|||
}, |
|||
}; |
|||
|
|||
|
|||
static Mif_Inst_Var_Info_t MIFinst_varTable[] = { |
|||
{ |
|||
"acgains", |
|||
"partial derivatives from dc analysis used for ac gains", |
|||
MIF_STRING, |
|||
MIF_FALSE, |
|||
}, |
|||
}; |
|||
|
|||
|
|||
extern void spice2poly(Mif_Private_t *); |
|||
|
|||
static int val_terms = 0; |
|||
static int val_numNames = 0; |
|||
static int val_numInstanceParms = 1; |
|||
static int val_numModelParms = 1; |
|||
static int val_sizeofMIFinstance = sizeof(MIFinstance); |
|||
static int val_sizeofMIFmodel = sizeof(MIFmodel); |
|||
|
|||
SPICEdev spice2poly_info = { |
|||
{ "spice2poly", |
|||
"2g6 compatible polynomial controlled source", |
|||
&val_terms, |
|||
&val_numNames, |
|||
NULL, |
|||
&val_numInstanceParms, |
|||
MIFpTable, |
|||
&val_numModelParms, |
|||
MIFmPTable, |
|||
spice2poly, |
|||
2, |
|||
MIFconnTable, |
|||
1, |
|||
MIFparamTable, |
|||
1, |
|||
MIFinst_varTable, |
|||
}, |
|||
NULL, |
|||
MIFmParam, |
|||
MIFload, |
|||
MIFsetup, |
|||
NULL, /* removed by sdb MIFunsetup, */ |
|||
NULL, |
|||
NULL, |
|||
MIFtrunc, |
|||
NULL, |
|||
MIFload, |
|||
NULL, |
|||
MIFdestroy, |
|||
MIFmDelete, |
|||
MIFdelete, |
|||
NULL, |
|||
MIFask, |
|||
MIFmAsk, |
|||
NULL, |
|||
MIFconvTest, |
|||
NULL, |
|||
NULL, |
|||
NULL, |
|||
NULL, |
|||
NULL, |
|||
NULL, |
|||
NULL, |
|||
NULL, |
|||
NULL, |
|||
&val_sizeofMIFinstance, |
|||
&val_sizeofMIFmodel, |
|||
|
|||
}; |
|||
|
|||
@ -1,75 +0,0 @@ |
|||
/* =========================================================================== |
|||
FILE ifspec.ifs |
|||
|
|||
MEMBER OF process XSPICE |
|||
|
|||
Copyright 1991 |
|||
Georgia Tech Research Corporation |
|||
Atlanta, Georgia 30332 |
|||
All Rights Reserved |
|||
|
|||
PROJECT A-8503 |
|||
|
|||
AUTHORS |
|||
|
|||
9/12/91 Bill Kuhn |
|||
|
|||
MODIFICATIONS |
|||
|
|||
<date> <person name> <nature of modifications> |
|||
|
|||
SUMMARY |
|||
|
|||
This file contains the definition of a code model polynomial controlled |
|||
source compatible with SPICE 2G6 poly sources. |
|||
|
|||
INTERFACES |
|||
|
|||
None. |
|||
|
|||
REFERENCED FILES |
|||
|
|||
None. |
|||
|
|||
NON-STANDARD FEATURES |
|||
|
|||
None. |
|||
|
|||
=========================================================================== */ |
|||
|
|||
NAME_TABLE: |
|||
|
|||
Spice_Model_Name: spice2poly |
|||
C_Function_Name: spice2poly |
|||
Description: "2G6 compatible polynomial controlled source" |
|||
|
|||
|
|||
PORT_TABLE: |
|||
|
|||
Port_Name: in out |
|||
Description: "input" "output" |
|||
Direction: in out |
|||
Default_Type: vd vd |
|||
Allowed_Types: [vd,id,vnam] [vd,id] |
|||
Vector: yes no |
|||
Vector_Bounds: [1 -] - |
|||
Null_Allowed: no no |
|||
|
|||
|
|||
PARAMETER_TABLE: |
|||
|
|||
Parameter_Name: coef |
|||
Description: "2G6 compatible spice card coefficient list" |
|||
Data_Type: real |
|||
Default_Value: - |
|||
Limits: - |
|||
Vector: yes |
|||
Vector_Bounds: [2 -] |
|||
Null_Allowed: no |
|||
|
|||
|
|||
STATIC_VAR_TABLE: |
|||
|
|||
Static_Var_Name: acgains |
|||
Data_Type: pointer |
|||
Description: "Partial derivatives from DC analysis used for AC gains" |
|||
@ -1,3 +0,0 @@ |
|||
#!/bin/sh |
|||
cmpp -mod cfunc.mod |
|||
cmpp -ifs |
|||
Write
Preview
Loading…
Cancel
Save
Reference in new issue