Modified Files:

ChangeLog Makefile.am NOTES configure.in src/Makefile.am
 	src/spinit src/include/inpdefs.h src/include/mif.h
 	src/include/ngspice.h src/spicelib/devices/Makefile.am
 	src/spicelib/devices/cktcrte.c src/spicelib/devices/dev.c
 	src/spicelib/parser/inpdomod.c src/spicelib/parser/inptyplk.c
 	src/xspice/Makefile.am src/xspice/README
 	src/xspice/enh/enhtrans.c src/xspice/icm/Makefile.am
 	src/xspice/mif/mif.c src/xspice/mif/mif_inp2.c
 	src/xspice/mif/mifgetmod.c src/xspice/mif/mifutil.c
 	tests/Makefile.am
 Added Files:
 	src/xspice/icm/README src/xspice/icm/dlinfo.h
 	src/xspice/icm/dlmain.c src/xspice/icm/modpath.lst
 	src/xspice/icm/objects.inc src/xspice/icm/spice2poly.cm
 	src/xspice/icm/icm_spice2poly/Makefile.am
 	src/xspice/icm/icm_spice2poly/README
 	src/xspice/icm/icm_spice2poly/cfunc.c
 	src/xspice/icm/icm_spice2poly/cfunc.mod
 	src/xspice/icm/icm_spice2poly/ifspec.c
 	src/xspice/icm/icm_spice2poly/ifspec.ifs
 	src/xspice/icm/icm_spice2poly/make.bat
 	tests/TransImpedanceAmp/Makefile.am
 	tests/TransImpedanceAmp/README
 	tests/TransImpedanceAmp/output.net

Merged Changes from http://www.brorson.com/gEDA/ngspice/ngspice.html
Many thanks to Stuart Brorson.
This commit is contained in:
stefanjones 2003-06-25 10:37:48 +00:00
parent 84f79054a8
commit da89dcc6c5
39 changed files with 2681 additions and 158 deletions

View File

@ -1,3 +1,31 @@
2003-06-22 Stuart Brorson <sdb@cloud9.net>
* Finally got SPICE2 POLY stuff working. This involved lots of changes
in src/xspice/mif and src/xspice/enh. Particular changes were made in:
-- MIF_INP2A: re-arranged logic to fix parsing problems.
-- two2three_translate: fixed some stupid pointer problems.
-- etc.
* Revamped src/xspice/icm/ and src/xspice/icm/icm_spice2poly
directories to enable build of POLY codemodel. Makefiles were
fixed, and some stuff was added to enable cmpp (from SPICE Opus)
to build the codemodel precursors correctly. (Note that you need
to download and install SPICE Opus to rebuild the codemodel
stuff. See src/xspice/icm/README for more details.)
* Hacked Makefile.am's for much of the directory hierarchy, particularly
for src/xspice/icm and src/xspice/icm/icm_spice2poly to build the POLY
codemodel correctly. Note that top level make still doesn't detect
changes in the xspice hierarchy; read the NOTES file for a workaround.
* Added a SPICE netlist incorporating vendor models with SPICE2
POLYs in tests/TransImpedanceAmp/. Running this model
successfully demonstrates that you have built the XSpice POLY
codemodel correctly and that life is good . . . .
* Moved #define TRACE out of src/ngspice.h and made it a compiler
option (-DTRACE) invoked in src/Makefile when making spice.o.
2003-06-19 Adrian Dawe <a.dawe@multigig.com>
* Much improved spice wish interface; graph includes zooming,

View File

@ -18,3 +18,6 @@ tcl:
cd src && $(MAKE) tcl
install-tcl:
cd src && $(MAKE) install-tcl
codemodels:
cd src/xspice/icm && make

28
NOTES
View File

@ -1,3 +1,31 @@
SPICE 2 POLY CODEMODEL
SPICE2 POLY attributes are now available for controlled sources. To
use POLY attributes, configure tclspice/ngspice with the
--enable-xspice flag set as described above. After compilation of
ngspice, cd into $(top_srcdir)/src/xspice/icm and read the README file
there for instructions about how to get POLY support. (Hint: you have
to download some stuff from http://www.fe.uni-lj.si/ and edit the
Makefiles before you can do "make && make install" of the codemodel
stuff.)
-- SDB 6.22.2003.
--------------------------------------------------------------------
COMPILING XSPICE CHANGES
The dependencies in the Makefile don't seem to work when you are
compiling changes in the xspice stuff. Obviously, the best thing to
do is fix Makefile.am, but since I am not an expert at this, I have
been using the following workaround when making:
touch src/main.c && make && make install
I recommend you also do this if you hack anything under src/xspice.
-- SDB 6.19.2003.
---------------------------------------------------------------------
DEBUGGING SPICE
To avoid a segmentation fault in the initial run, use the following

View File

@ -207,6 +207,8 @@ dnl Checks for programs
AC_LIBTOOL_DLOPEN
AM_PROG_LIBTOOL
AC_PROG_LIBTOOL
dnl Checks for X11 header files and libraries - X11 support can be disabled
@ -363,6 +365,7 @@ fi
AC_SUBST(EKVDIR)
AC_SUBST(EKVLIB)
dnl Add new code models to the build by pointing to them here.
if test "$enable_xspice" = "yes"; then
AC_MSG_RESULT(X-Spice features included)
AC_DEFINE(XSPICE)
@ -412,7 +415,7 @@ src/spicelib/analysis/Makefile \
src/spicelib/devices/Makefile \
src/spicelib/devices/asrc/Makefile \
src/spicelib/devices/bjt/Makefile \
src/spicelib/devices/bjt2/Makefile \
dnl src/spicelib/devices/bjt2/Makefile \
src/spicelib/devices/bsim1/Makefile \
src/spicelib/devices/bsim2/Makefile \
src/spicelib/devices/bsim3v1/Makefile \
@ -428,7 +431,7 @@ src/spicelib/devices/ccvs/Makefile \
src/spicelib/devices/csw/Makefile \
src/spicelib/devices/cpl/Makefile \
src/spicelib/devices/dio/Makefile \
src/spicelib/devices/ekv/Makefile \
dnl src/spicelib/devices/ekv/Makefile \
src/spicelib/devices/ind/Makefile \
src/spicelib/devices/isrc/Makefile \
src/spicelib/devices/hfet1/Makefile \
@ -467,6 +470,8 @@ src/maths/sparse/Makefile \
src/misc/Makefile \
src/xspice/Makefile \
src/xspice/cm/Makefile \
src/xspice/icm/Makefile \
src/xspice/icm/icm_spice2poly/Makefile \
src/xspice/mif/Makefile \
src/xspice/evt/Makefile \
src/xspice/enh/Makefile \
@ -480,7 +485,8 @@ tests/bsim3soipd/Makefile \
tests/bsim3soifd/Makefile \
tests/bsim3soidd/Makefile \
tests/bsim4/Makefile \
tests/mesa/Makefile
tests/mesa/Makefile \
tests/TransImpedanceAmp/Makefile
)
dnl Printout Tcl option

View File

@ -18,7 +18,6 @@ initdata_DATA = spinit setplot spectrum
DYNAMIC_DEVICELIBS = \
spicelib/devices/asrc/libasrc.la \
spicelib/devices/bjt/libbjt.la \
## spicelib/devices/bjt2/libbjt2.la \
spicelib/devices/bsim1/libbsim1.la \
spicelib/devices/bsim2/libbsim2.la \
spicelib/devices/bsim3/libbsim3.la \
@ -60,6 +59,15 @@ DYNAMIC_DEVICELIBS = \
spicelib/devices/vcvs/libvcvs.la \
spicelib/devices/vsrc/libvsrc.la
## ----- Note that I moved this stuff to here because it was causing automake
## to choke when it was in the DYNAMIC_DEVICELIBS list above -----
## This lib deleted from DYNAMIC_DEVICELIBS by sdb 'cause there's no source for it.
## spicelib/devices/bjt2/libbjt2.la \
## poly added to dynamic libs by SDB on 6.1.2003
## xspice/icm/poly/libpoly.la
## Build ngspice first:
ngspice_SOURCES = \

View File

@ -74,6 +74,11 @@ typedef struct sINPmodel{
void *INPmodfast; /* high speed pointer to model for access */
} INPmodel;
/* global input model table. */
extern INPmodel *modtab;
/* listing types - used for debug listings */
#define LOGICAL 1
#define PHYSICAL 2

View File

@ -77,8 +77,11 @@ typedef struct {
} Mif_Info_t;
/* These are defined in mif.c */
extern int MIFiSize;
extern int MIFmSize;
extern Mif_Info_t g_mif_info;
#endif /* MIF */

View File

@ -3,15 +3,6 @@
* 1999 E. Rouat
************/
/* Uncomment this to get trace of program operation for
* debugging
*/
/* #define TRACE */
/* This was also added by SDB to aid in
* debugging. Remove when finished.
*/
/* #include "memwatch.h"
#define MEMWATCH */

View File

@ -3,7 +3,6 @@
SUBDIRS = \
asrc \
bjt \
## bjt2 \
bsim1 \
bsim2 \
bsim3 \
@ -44,6 +43,11 @@ SUBDIRS = \
vcvs \
vsrc
## This line move to here 'cause it was causing automake to choke
## when it was in the list of subdirs
## bjt2 \
noinst_LIBRARIES = libdev.a
libdev_a_SOURCES = \
@ -58,6 +62,6 @@ libdev_a_SOURCES = \
cktfinddev.c \
cktinit.c
INCLUDES = -I$(top_srcdir)/src/include
INCLUDES = -I$(top_srcdir)/src/include -I$(top_srcdir)/src/spicelib/devices
MAINTAINERCLEANFILES = Makefile.in

View File

@ -42,7 +42,7 @@ CKTcrtElt(void *ckt, void *inModPtr, void **inInstPtr, IFuid name)
#ifdef TRACE
/*------ SDB debug statement -------*/
printf("about to tmalloc, type = %d. . . \n", type);
printf("In CKTcrtElt, about to tmalloc new model, type = %d. . . \n", type);
#endif
instPtr = (GENinstance *) tmalloc(*DEVices[type]->DEVinstSize);

View File

@ -289,7 +289,7 @@ void load_alldevs(void){
}
#endif
/*-------------------- XSPICE additions below ----------------------*/
#ifdef XSPICE
#include <mif.h>
#include <cm.h>
@ -298,8 +298,18 @@ void load_alldevs(void){
#include <cktdefs.h> /*for DEVmaxnum*/
static void relink() {
ft_sim->numDevices = num_devices();
DEVmaxnum = num_devices();
/* added by SDB; DEVmaxnum is an external int defined in cktdefs.h */
extern int DEVmaxnum;
/*
* This replacement done by SDB on 6.11.2003
*
* ft_sim->numDevices = num_devices();
* DEVmaxnum = num_devices();
*/
ft_sim->numDevices = DEVNUM;
DEVmaxnum = DEVNUM;
ft_sim->devices = devices_ptr();
return;
}
@ -311,6 +321,10 @@ int add_device(int n, SPICEdev **devs, int flag){
for(i = 0; i < n;i++){
/*debug*/printf("Added device: %s\n",devs[i]->DEVpublic.name);
DEVices[DEVNUM+i] = devs[i];
/* added by SDB on 6.20.2003 */
DEVices[DEVNUM+i]->DEVinstSize = &MIFiSize;
DEVicesfl[DEVNUM+i] = flag;
}
DEVNUM += n;
@ -407,4 +421,6 @@ int load_opus(char *name){
return 0;
}
#endif
/*-------------------- end of XSPICE additions ----------------------*/

View File

@ -476,7 +476,8 @@ char *INPdomodel(void *ckt, card * image, INPtables * tab)
/* type poly added by SDB . . . */
#ifdef XSPICE
/* -------- Check if model is a poly (specific to xspice) --------- */
else if (strcmp(typename, "poly") == 0) {
else if ( (strcmp(typename, "poly") == 0) ||
(strcmp(typename, "POLY") == 0) ) {
type = INPtypelook("POLY");
if (type < 0) {
err =
@ -519,7 +520,7 @@ char *INPdomodel(void *ckt, card * image, INPtables * tab)
#ifdef TRACE
/* SDB debug statement */
printf("In INPdomodel, adding model typename = %s to model list. . .\n", typename);
printf("In INPdomodel, adding unknown model typename = %s to model list. . .\n", typename);
#endif
INPmakeMod(modname,type,image);

View File

@ -21,20 +21,32 @@ int INPtypelook(char *type)
#ifdef TRACE
/* SDB debug statement */
/* printf("In INPtypelook, examining model type = %s . . .\n", type); */
printf("In INPtypelook, examining model type = %s . . .\n", type);
#endif
for (i = 0; i < ft_sim->numDevices; i++) {
#ifdef TRACE
/* SDB debug statemnet */
/* printf("In INPtypelook, checking model against = %s . . .\n", (*(ft_sim->devices)[i]).name ); */
/* SDB debug statement */
printf("In INPtypelook, checking model type = %s against existing model = %s, . . .\n", type, (*(ft_sim->devices)[i]).name );
#endif
if (strcmp(type, (*(ft_sim->devices)[i]).name) == 0) {
/*found the device - return it */
#ifdef TRACE
/* SDB debug statement */
printf("In INPtypelook, found the device -- returning it!!!\n");
#endif
return i;
}
}
#ifdef TRACE
/* SDB debug statement */
printf("In INPtypelook, device not found!\n");
#endif
return -1;
}

View File

@ -2,3 +2,6 @@
alias exit quit
alias acct rusage all
set x11lineararcs
* For SPICE2 POLYs, edit the below line to point to the location
* of your codemode.
* codemodel /usr/local/src/tclspice-0.2.10/src/xspice/icm/spice2poly.cm

View File

@ -5,6 +5,10 @@ COMPILE = $(CC) $(DEFS) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CF
EXTRA_DIST = README
## This is removed because icm relies upon the existance of all other
## libs. It is currently compiled manually, last.
##SUBDIRS = mif cm enh evt ipc idn icm
SUBDIRS = mif cm enh evt ipc idn
INCLUDES = -I$(top_srcdir)/src/include -I$(top_srcdir)

View File

@ -22,3 +22,20 @@ TODO:
Stefan Jones
19/2/2002
-----------------------------------------
SPICE2 POLY codemodel support.
SPICE2 POLY attributes are now available for controlled sources. To
use POLY attributes, configure tclspice/ngspice with the
--enable-xspice flag set as described above. After compilation of
ngspice, cd into $(top_srcdir)/src/xspice/icm and read the README file
there for instructions about how to get POLY support. (Hint: you have
to download some stuff from http://www.fe.uni-lj.si/ and edit the
Makefiles before you can do "make && make install" of the codemodel
stuff.)
Please direct questions/comments/complaints to mailto:sdb@cloud9.net.
6.22.2003 -- SDB.

View File

@ -62,7 +62,6 @@ NON-STANDARD FEATURES
/*=== FUNCTION PROTOTYPES ===*/
static int needs_translating(char *card);
static int count_tokens(char *card);
static char *two2three_translate(char *orig_card, char **inst_card,
@ -92,8 +91,6 @@ struct line * ENHtranslate_poly(
struct line *l2;
char *card;
int poly_dimension;
char *buff;
/* Iterate through each card in the deck and translate as needed */
for(d = deck; d; d = d->li_next)
@ -174,15 +171,15 @@ static int needs_translating(
switch(*card) {
case 'e':
case 'g':
case 'e': case 'E':
case 'g': case 'G':
if(count_tokens(card) <=6)
return(0);
else
return(1);
case 'f':
case 'h':
case 'f': case 'F':
case 'h': case 'H':
if(count_tokens(card) <= 5)
return(0);
else
@ -217,17 +214,57 @@ static int count_tokens(
/********************************************************************/
/*====================================================================
/*--------------------------------------------------------------------*/
/*
two2three_translate()
Do the syntax translation of the 2G6 source to the new code model syntax.
Do the syntax translation of the 2G6 source to the new code model
syntax. The translation proceeds according to the template below.
Renamed by SDB to eliminate clash with translate fcn defined in subckt.c
4.17.2003 -- SDB
--------------------------------------------
VCVS:
ename N+ N- POLY(dim) NC+ NC- P0 P1 P2 . . .
N+ N- = outputs
NC+ NC- = inputs
*/
aname %vd[NC+ NC-] %vd[N+ N-] pname
.model pname spice2poly(coef=P0 P1 P2 . . . )
%vd[NC+ NC-] = inputs
%vd[N+ N-] = outputs
--------------------------------------------
CCCS
fname N+ N- POLY(dim) Vname P0 P1 P2 . . .
N+ N- = outputs
Vname = input voltage source (measures current)
aname %vnam[Vname] %id[N+ N-] pname
.model pname spice2poly(coef=P0 P1 P2 . . . )
%vnam[Vname] = input
%id[N+ N-] = output
--------------------------------------------
VCCS
gname N+ N- POLY(dim) NC+ NC- P0 P1 P2 , , ,
N+ N- = outputs
NC+ NC- = inputs
aname %vd[NC+ NC-] %id[N+ N-] pname
.model pname spice2poly(coef=P0 P1 P2 . . . )
%vd[NC+ NC-] = inputs
%id[N+ N-] = outputs
--------------------------------------------
CCVS
hname N+ N- POLY(dim) Vname P0 P1 P2 . . .
N+ N- = outputs
Vname = input voltage source (measures current)
aname %vnam[Vname] %vd[N+ N-] pname
.model pname spice2poly(coef=P0 P1 P2 . . . )
%vnam[Vname] = input
%vd[N+ N-] = output
====================================================================*/
/********************************************************************/
static char *two2three_translate(
char *orig_card, /* the original untranslated card */
@ -246,6 +283,7 @@ static char *two2three_translate(
char type;
char *tok;
char *name;
char **out_conn;
char **in_conn;
@ -259,20 +297,22 @@ static char *two2three_translate(
printf("In two2three_translate, card to translate = %s . . .\n", orig_card);
#endif
/* Get the first character into local storage for checking type */
/* Put the first character into local storage for checking type */
type = *orig_card;
/* Count the number of tokens for use in parsing */
num_tokens = count_tokens(orig_card);
/* Determine the dimension of the poly source */
/* Note that get_poly_dimension returns 0 for "no poly", -1 for
invalid dimensiion, otherwise returns numeric value of POLY */
dim = get_poly_dimension(orig_card);
if(dim <= 0) {
if(dim == -1) {
printf("ERROR in two2three_translate -- Argument to poly() is not an integer\n");
return("ERROR - Argument to poly() is not an integer\n");
}
/* Compute number of input connections based on type and dimension */
/* Compute number of output connections based on type and dimension */
switch(type) {
case 'E':
case 'e':
@ -286,10 +326,16 @@ static char *two2three_translate(
}
/* Compute number of coefficients. Return error if less than one. */
if(dim == 1)
num_coefs = num_tokens - num_conns - 3;
if(dim == 0)
num_coefs = num_tokens - num_conns - 3; /* no POLY token */
else
num_coefs = num_tokens - num_conns - 5;
num_coefs = num_tokens - num_conns - 5; /* POLY token present */
#ifdef TRACE
/* SDB debug statement */
printf("In two2three_translate, num_tokens=%d, num_conns=%d, num_coefs=%d . . .\n", num_tokens, num_conns, num_coefs);
#endif
if(num_coefs < 1)
return("ERROR - Number of connections differs from poly dimension\n");
@ -300,18 +346,30 @@ static char *two2three_translate(
card = orig_card;
name = MIFgettok(&card);
/* Get output connections (2 netnames) */
out_conn = (void *) MALLOC(2 * sizeof(char *));
for(i = 0; i < 2; i++)
out_conn[i] = MIFgettok(&card);
if(dim > 1)
for(i = 0; i < 2; i++)
txfree(MIFgettok(&card));
/* check for POLY, and ignore it if present */
if (dim > 0) {
#ifdef TRACE
/* SDB debug statement */
printf("In two2three_translate, found poly!!! dim = %d \n", dim);
#endif
tok = MIFgettok(&card); /* read and discard POLY */
tok = MIFgettok(&card); /* read and discard dimension */
}
/* Get input connections (2 netnames per dimension) */
in_conn = (void *) MALLOC(num_conns * sizeof(char *));
for(i = 0; i < num_conns; i++)
in_conn[i] = MIFgettok(&card);
/* The remainder of the line are the poly coeffs. */
coef = (void *) MALLOC(num_coefs * sizeof(char *));
for(i = 0; i < num_coefs; i++)
coef[i] = MIFgettok(&card);
@ -320,14 +378,14 @@ static char *two2three_translate(
/* Allow a fair amount of extra space for connection types, etc. */
/* to be safe... */
inst_card_len = 50;
inst_card_len = 70;
inst_card_len += 2 * (strlen(name) + 1);
for(i = 0; i < 2; i++)
inst_card_len += strlen(out_conn[i]) + 1;
for(i = 0; i < num_conns; i++)
inst_card_len += strlen(in_conn[i]) + 1;
mod_card_len = 50;
mod_card_len = 70;
mod_card_len += strlen(name) + 1;
for(i = 0; i < num_coefs; i++)
mod_card_len += strlen(coef[i]) + 1;
@ -340,6 +398,7 @@ static char *two2three_translate(
strcpy(*inst_card, "a$poly$");
sprintf(*inst_card + strlen(*inst_card), "%s ", name);
/* Write input nets/sources */
if((type == 'e') || (type == 'g') ||
(type == 'E') || (type == 'G'))
sprintf(*inst_card + strlen(*inst_card), "%%vd [ ");
@ -351,19 +410,26 @@ static char *two2three_translate(
sprintf(*inst_card + strlen(*inst_card), "] ");
/* Write output nets */
if((type == 'e') || (type == 'h') ||
(type == 'E') || (type == 'H'))
sprintf(*inst_card + strlen(*inst_card), "%%vd ");
sprintf(*inst_card + strlen(*inst_card), "%%vd [ ");
else
sprintf(*inst_card + strlen(*inst_card), "%%id ");
sprintf(*inst_card + strlen(*inst_card), "%%id [ ");
for(i = 0; i < 2; i++)
sprintf(*inst_card + strlen(*inst_card), "%s ", out_conn[i]);
sprintf(*inst_card + strlen(*inst_card), "] ");
/* Write model name */
sprintf(*inst_card + strlen(*inst_card), "a$poly$%s", name);
sprintf(*mod_card, ".model a$poly$%s poly coef = [ ", name);
/* Now create model card */
sprintf(*mod_card, ".model a$poly$%s spice2poly coef = [ ", name);
for(i = 0; i < num_coefs; i++)
sprintf(*mod_card + strlen(*mod_card), "%s ", coef[i]);
sprintf(*mod_card + strlen(*mod_card), "]");
@ -417,9 +483,11 @@ static char *two2three_translate(
get_poly_dimension()
Get the poly source dimension from the token immediately following
the 'poly' if any. If 'poly' is not present, return 1. If poly is
present and token following is a valid integer, return it. Else
return 0.
the 'poly' if any. Return values changed by SDB on 5.23.2003 to be:
If "poly" is not present, return 0.
If the dimension token following "poly" is invalid, return -1.
Otherwise, return the integer dimension.
Note that the dimension may only be 1 or 2. Is this correct SPICE?
*/
@ -429,7 +497,7 @@ static int get_poly_dimension(
int i;
int dim;
char *tok;
char *local_tok;
/* Skip over name and output connections */
@ -437,27 +505,32 @@ static int get_poly_dimension(
txfree(MIFgettok(&card));
/* Check the next token to see if it is "poly" */
/* If not, return a dimension of 1 */
tok = MIFgettok(&card);
if(strcmp(tok, "poly"))
/* If not, return 0 */
local_tok = MIFgettok(&card);
if( strcmp(local_tok, "poly") &&
strcmp(local_tok, "POLY") ) /* check that local_tok is *not* poly */
{
FREE(tok);
tok = NULL;
return(1);
FREE(local_tok);
local_tok = NULL;
return(0);
}
FREE(tok);
FREE(local_tok);
/* Must have been "poly", so next line must be a number */
/* Try to convert it. If successful, return the number */
/* else, return 0 to indicate an error... */
tok = MIFgettok(&card);
dim = atoi(tok);
FREE(tok);
/* else, return -1 to indicate an error... */
local_tok = MIFgettok(&card);
dim = atoi(local_tok);
FREE(local_tok);
/* This is stupid, but it works. . . . */
if ( (dim == 0) || (dim == 1) || (dim == 2) ) {
return(dim);
}
else {
return(-1);
}
} /* get_poly_dimension */

View File

@ -1,12 +1,194 @@
## Process this file with automake to produce Makefile.in
#
# JW 3/9/01 - had a go and makeing an autoconf script.
# Hacked on 5.23.2003 by SDB
noinst_LIBRARIES = libidnxsp.a
libidnxsp_a_SOURCES = \
idndig.c
SUBDIRS = icm_spice2poly
INCLUDES = -I$(top_srcdir)/src/include
MAINTAINERCLEANFILES = Makefile.in
EXTRA_DIST = README modpath.lst udnpath.lst spice2poly.cm dlmain.c
# Edit these to point to your Opus installation
CMPPDIR = /usr/local/opus/bin
OPUS_INCLUDE_DIR = /usr/local/opus/lib/spice/include
##------ 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/
clean: clean-recursive
rm -f cmextrn.h cminfo.h udnextrn.h udninfo.h *.o
cmextrn.h: modpath.lst $(SUBDIRS)/cfunc.c $(SUBDIRS)/ifspec.c
$(CMPPDIR)/cmpp -lst
cminfo.h: modpath.lst $(SUBDIRS)/cfunc.c $(SUBDIRS)/ifspec.c
$(CMPPDIR)/cmpp -lst
udnextrn.h: udnpath.lst $(SUBDIRS)/cfunc.c $(SUBDIRS)/ifspec.c
$(CMPPDIR)/cmpp -lst
udninfo.h: udnpath.lst $(SUBDIRS)/cfunc.c $(SUBDIRS)/ifspec.c
$(CMPPDIR)/cmpp -lst
all: spice2poly.cm
spice2poly.cm: $(SUBDIRS)/cfunc.o $(SUBDIRS)/ifspec.o dlmain.o
$(top_srcdir)/libtool --mode=link $(CC) -module -shared -fPIC -o spice2poly.cm \
$(SUBDIRS)/cfunc.o $(SUBDIRS)/ifspec.o dlmain.o \
$(SYSTEM_LIBS) $(LOCAL_LIB_DIRS) \
-Wl,--start-group -Wl,$(LOCAL_LIBS) -Wl,--end-group -ldl \
-Wl,--rpath,/usr/local/geda/lib/ng-spice-rework
dlmain.o: dlmain.c cmextrn.h udnextrn.h cminfo.h udninfo.h
$(CC) -fPIC -I$(OPUS_INCLUDE_DIR) $(INCLUDES) $(CFLAGS) -DCM_LINUX -c dlmain.c

52
src/xspice/icm/README Normal file
View File

@ -0,0 +1,52 @@
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. Make sure you do configure --enable-xspice when
configuring.
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. (Hint: I
place it in /usr/local/opus.)
4. Edit the Makefile in the directory below (icm_spice2poly/) and
make the variable CMPDIR point to the base location of your Opus
installation.
5. Do "make" in this directory. 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 this directory
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

9
src/xspice/icm/dlinfo.h Normal file
View File

@ -0,0 +1,9 @@
//////////////////////////////////////////////////////////////////////////////
// Modify these to include general information about the library
//////////////////////////////////////////////////////////////////////////////
char inf_Title[]="icm_poly.cm";
char inf_Version[]="0.1";
char inf_Description[]="Code model implementation of SPICE2 poly.";
char inf_Author[]="Hacked together by SDB, June 2003.";
char inf_Copyright[]="Released under GPL";

408
src/xspice/icm/dlmain.c Normal file
View File

@ -0,0 +1,408 @@
//////////////////////////////////////////////////////////////////////////////
// Build cmextrn.h, cminfo.h, udnextrn.h and udninfo.h from udnpath.lst and
// modpath.lst using 'cmpp -lst'. Then compile this file and link it with
// cm and udn object files to produce a dll that can be loaded by the
// spice opus simulator at run-time.
//
// Author: Arpad Buermen
//////////////////////////////////////////////////////////////////////////////
#include "dlinfo.h"
#include <devdefs.h>
#include <evtudn.h>
#include "port.h"
#include "misc.h"
#include "cmextrn.h"
#include "udnextrn.h"
#include "dllitf.h"
// This one is automatically set by the compiler
char inf_Date[]=__DATE__;
//////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////
// Do not modify anything below this line
//////////////////////////////////////////////////////////////////////////////
SPICEdev *cmDEVices[] = {
#include "cminfo.h"
NULL
};
int cmDEVicesCNT = sizeof(cmDEVices)/sizeof(SPICEdev *)-1;
Evt_Udn_Info_t *cmEVTudns[] = {
#include "udninfo.h"
NULL
};
int cmEVTudnCNT = sizeof(cmEVTudns)/sizeof(Evt_Udn_Info_t *)-1;
// Pointer to core info structure containing pointers to core functions.
struct coreInfo_t *coreitf;
//////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////
// Functions that return pointers to structures.
//////////////////////////////////////////////////////////////////////////////
#ifdef CM_WINDOWS
#undef CM_EXPORT
#define CM_EXPORT __declspec(dllexport)
#endif
#ifdef CM_LINUX
#undef CM_EXPORT
#define CM_EXPORT extern
#endif
int cmopusvers = 2;
// This one checks the opus dynamic link version.
CM_EXPORT void *CMsysvers() {
return (void *)&cmopusvers;
}
// This one returns the title
CM_EXPORT void *CMtitle() {
return (void *)inf_Title;
}
// This one returns the version
CM_EXPORT void *CMversion() {
return (void *)inf_Version;
}
// This one returns the date
CM_EXPORT void *CMdate() {
return (void *)inf_Date;
}
// This one returns the description
CM_EXPORT void *CMdescription() {
return (void *)inf_Description;
}
// This one returns the author
CM_EXPORT void *CMauthor() {
return (void *)inf_Author;
}
// This one returns the copyright
CM_EXPORT void *CMcopyright() {
return (void *)inf_Copyright;
}
// This one returns the device table
CM_EXPORT void *CMdevs() {
return (void *)cmDEVices;
}
// This one returns the device count
CM_EXPORT void *CMdevNum() {
return (void *)&cmDEVicesCNT;
}
// This one returns the UDN table
CM_EXPORT void *CMudns() {
return (void *)cmEVTudns;
}
// This one returns the UDN count
CM_EXPORT void *CMudnNum() {
return (void *)&cmEVTudnCNT;
}
// This one returns the pointer to the pointer to the core interface structure
CM_EXPORT void *CMgetCoreItfPtr() {
return (void *)(&coreitf);
}
//////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////
// These functions call the real core functions of SPICE OPUS using the
// pointers in coreitf structure.
//////////////////////////////////////////////////////////////////////////////
void MIF_INP2A(
GENERIC *ckt, /* circuit structure to put mod/inst structs in */
INPtables *tab, /* symbol table for node names, etc. */
card *current /* the card we are to parse */
) {
(coreitf->dllitf_MIF_INP2A)(ckt,tab,current);
}
char * MIFgetMod(
GENERIC *ckt,
char **name,
INPmodel **model,
INPtables *tab
) {
return (coreitf->dllitf_MIFgetMod)(ckt,name,model,tab);
}
IFvalue * MIFgetValue(
GENERIC *ckt,
char **line,
int type,
INPtables *tab,
char **err
) {
return (coreitf->dllitf_MIFgetValue)(ckt,line,type,tab,err);
}
int MIFsetup(
SMPmatrix *matrix,
GENmodel *inModel,
CKTcircuit *ckt,
int *state
) {
return (coreitf->dllitf_MIFsetup)(matrix,inModel,ckt,state);
}
int MIFunsetup(
GENmodel *inModel,
CKTcircuit *ckt
) {
return (coreitf->dllitf_MIFunsetup)(inModel,ckt);
}
int MIFload(
GENmodel *inModel,
CKTcircuit *ckt
) {
return (coreitf->dllitf_MIFload)(inModel,ckt);
}
int MIFmParam(
int param_index,
IFvalue *value,
GENmodel *inModel
) {
return (coreitf->dllitf_MIFmParam)(param_index,value,inModel);
}
int MIFask(
CKTcircuit *ckt,
GENinstance *inst,
int param_index,
IFvalue *value,
IFvalue *select
) {
return (coreitf->dllitf_MIFask)(ckt,inst,param_index,value,select);
}
int MIFmAsk(
CKTcircuit *ckt,
GENmodel *inModel,
int param_index,
IFvalue *value
) {
return (coreitf->dllitf_MIFmAsk)(ckt,inModel,param_index,value);
}
int MIFtrunc(
GENmodel *inModel,
CKTcircuit *ckt,
double *timeStep
) {
return (coreitf->dllitf_MIFtrunc)(inModel,ckt,timeStep);
}
int MIFconvTest(
GENmodel *inModel,
CKTcircuit *ckt
) {
return (coreitf->dllitf_MIFconvTest)(inModel,ckt);
}
int MIFdelete(
GENmodel *inModel,
IFuid name,
GENinstance **inst
) {
return (coreitf->dllitf_MIFdelete)(inModel,name,inst);
}
int MIFmDelete(
GENmodel **inModel,
IFuid modname,
GENmodel *model
) {
return (coreitf->dllitf_MIFmDelete)(inModel,modname,model);
}
void MIFdestroy(
GENmodel **inModel
) {
(coreitf->dllitf_MIFdestroy)(inModel);
}
char *MIFgettok(
char **s
) {
return (coreitf->dllitf_MIFgettok)(s);
}
char *MIFget_token(
char **s,
Mif_Token_Type_t *type
) {
return (coreitf->dllitf_MIFget_token)(s,type);
}
Mif_Cntl_Src_Type_t MIFget_cntl_src_type(
Mif_Port_Type_t in_port_type,
Mif_Port_Type_t out_port_type
) {
return (coreitf->dllitf_MIFget_cntl_src_type)(in_port_type,out_port_type);
}
char *MIFcopy(char *c) {
return (coreitf->dllitf_MIFcopy)(c);
}
void cm_climit_fcn(double in, double in_offset, double cntl_upper,
double cntl_lower, double lower_delta,
double upper_delta, double limit_range,
double gain, int percent, double *out_final,
double *pout_pin_final, double *pout_pcntl_lower_final,
double *pout_pcntl_upper_final) {
(coreitf->dllitf_cm_climit_fcn)(in,in_offset,cntl_upper,cntl_lower,lower_delta,
upper_delta,limit_range,gain,percent,out_final,
pout_pin_final,pout_pcntl_lower_final,
pout_pcntl_upper_final);
}
void cm_smooth_corner(double x_input, double x_center, double y_center,
double domain, double lower_slope, double upper_slope,
double *y_output, double *dy_dx) {
(coreitf->dllitf_cm_smooth_corner)(x_input,x_center,y_center,domain,lower_slope,
upper_slope,y_output,dy_dx);
}
void cm_smooth_discontinuity(double x_input, double x_lower, double y_lower,
double x_upper, double y_upper,
double *y_output, double *dy_dx) {
(coreitf->dllitf_cm_smooth_discontinuity)(x_input,x_lower,y_lower,x_upper,y_upper,
y_output,dy_dx);
}
double cm_smooth_pwl(double x_input, double *x, double *y, int size,
double input_domain, double *dout_din) {
return (coreitf->dllitf_cm_smooth_pwl)(x_input,x,y,size,input_domain,dout_din);
}
double cm_analog_ramp_factor(void) {
return (coreitf->dllitf_cm_analog_ramp_factor)();
}
void *cm_analog_alloc(int tag, int bytes) {
return (coreitf->dllitf_cm_analog_alloc)(tag,bytes);
}
void *cm_analog_get_ptr(int tag, int timepoint) {
return (coreitf->dllitf_cm_analog_get_ptr)(tag,timepoint);
}
int cm_analog_integrate(double integrand, double *integral, double *partial) {
return (coreitf->dllitf_cm_analog_integrate)(integrand,integral,partial);
}
int cm_analog_converge(double *state) {
return (coreitf->dllitf_cm_analog_converge)(state);
}
int cm_analog_set_temp_bkpt(double time) {
return (coreitf->dllitf_cm_analog_set_temp_bkpt)(time);
}
int cm_analog_set_perm_bkpt(double time) {
return (coreitf->dllitf_cm_analog_set_perm_bkpt)(time);
}
void cm_analog_not_converged(void) {
(coreitf->dllitf_cm_analog_not_converged)();
}
void cm_analog_auto_partial(void) {
(coreitf->dllitf_cm_analog_auto_partial)();
}
void *cm_event_alloc(int tag, int bytes){
return (coreitf->dllitf_cm_event_alloc)(tag,bytes);
}
void *cm_event_get_ptr(int tag, int timepoint) {
return (coreitf->dllitf_cm_event_get_ptr)(tag,timepoint);
}
int cm_event_queue(double time) {
return (coreitf->dllitf_cm_event_queue)(time);
}
char *cm_message_get_errmsg(void) {
return (coreitf->dllitf_cm_message_get_errmsg)();
}
int cm_message_send(char *msg) {
return (coreitf->dllitf_cm_message_send)(msg);
}
double cm_netlist_get_c(void) {
return (coreitf->dllitf_cm_netlist_get_c)();
}
double cm_netlist_get_l(void) {
return (coreitf->dllitf_cm_netlist_get_l)();
}
Complex_t cm_complex_set(double real, double imag) {
return (coreitf->dllitf_cm_complex_set)(real,imag);
}
Complex_t cm_complex_add(Complex_t x, Complex_t y) {
return (coreitf->dllitf_cm_complex_add)(x,y);
}
Complex_t cm_complex_subtract(Complex_t x, Complex_t y) {
return (coreitf->dllitf_cm_complex_subtract)(x,y);
}
Complex_t cm_complex_multiply(Complex_t x, Complex_t y) {
return (coreitf->dllitf_cm_complex_multiply)(x,y);
}
Complex_t cm_complex_divide(Complex_t x, Complex_t y) {
return (coreitf->dllitf_cm_complex_divide)(x,y);
}
FILE * cm_stream_out(void) {
return (coreitf->dllitf_cm_stream_out)();
}
FILE * cm_stream_in(void) {
return (coreitf->dllitf_cm_stream_in)();
}
FILE * cm_stream_err(void) {
return (coreitf->dllitf_cm_stream_err)();
}
char * tmalloc_internal(size_t s, int clean, const char *f, int l, int sw) {
return (coreitf->dllitf_tmalloc)(s,clean,f,l,sw);
}
char * trealloc_internal(char *ptr, size_t s, const char *f, int l, int sw) {
return (coreitf->dllitf_trealloc)(ptr,s,f,l,sw);
}
void tfree_internal(char *ptr, const char *f, int l, int sw) {
(coreitf->dllitf_tfree)(ptr,f,l,sw);
}

View File

@ -0,0 +1,193 @@
## 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 = /usr/local/opus/bin
##------ 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

View File

@ -0,0 +1,49 @@
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

View File

@ -0,0 +1,305 @@
#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;
}

View File

@ -0,0 +1,302 @@
/* ===========================================================================
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;
}

View File

@ -0,0 +1,187 @@
/*
* 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,
};

View File

@ -0,0 +1,75 @@
/* ===========================================================================
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"

View File

@ -0,0 +1,3 @@
#!/bin/sh
cmpp -mod cfunc.mod
cmpp -ifs

View File

@ -0,0 +1,2 @@
icm_spice2poly

View File

@ -0,0 +1 @@
icm_spice2poly/*.o

BIN
src/xspice/icm/spice2poly.cm Executable file

Binary file not shown.

View File

@ -39,10 +39,8 @@ NON-STANDARD FEATURES
#include "mif.h"
/* jgroves */
int MIFiSize = sizeof(MIFinstance); /* jgroves */
int MIFmSize = sizeof(MIFmodel); /* jgroves */
int MIFiSize = sizeof(MIFinstance);
int MIFmSize = sizeof(MIFmodel);
/* Allocate global used to pass info on analysis type, etc. from */

View File

@ -195,8 +195,8 @@ card *current; /* the card we are to parse */
#ifdef TRACE
/* SDB debug statement */
printf("In MIF_INP2A, after tokenizing, name = %s, model = %s\n",
name, model);
printf("In MIF_INP2A, about to get ports on line %s\n",
current->line);
#endif
@ -231,20 +231,21 @@ card *current; /* the card we are to parse */
/* and reading the first token following */
line = current->line;
MIFgettok(&line);
next_token = MIFget_token(&line,&next_token_type);
/* loop through the fixed number of connections expected */
MIFgettok(&line); /* read instance name again . . . .*/
/******* loop through the fixed number of connections expected *******/
for(i = 0; i < DEVices[type]->DEVpublic.num_conn; i++) {
/* there better be at least one more token besides the model name */
if(*line == '\0') {
LITERR("Missing connections on A device");
LITERR("Encountered end of line before all connections were found in model.");
return;
}
/* now get next token, should be a % after this statement */
next_token = MIFget_token(&line,&next_token_type);
/* prepare a pointer for fast access to info about this connection */
conn_info = &(DEVices[type]->DEVpublic.conn[i]);
@ -252,6 +253,34 @@ card *current; /* the card we are to parse */
def_port_type = conn_info->default_port_type;
def_port_type_str = conn_info->default_type;
/* Now get real info about connection type (instead of default info) */
if(next_token_type == MIF_PERCENT_TOK) { /* next_token_type should be a % */
/* get the port type identifier and check it for validity */
next_token = MIFget_token(&line,&next_token_type);
MIFget_port_type(ckt,
tab,
current,
&line,
&next_token,
&next_token_type,
&def_port_type,
&def_port_type_str,
conn_info,
&status);
if(status == MIF_ERROR)
return;
}
else {
LITERR("Non percent token encountered when expecting MIF_PERCENT_TOK");
return;
}
/* At this point, next_token should hold the token *after* the port type
identified (%v, %id, etc). */
/* set analog and event_driven flags on instance and model */
if((def_port_type == MIF_DIGITAL) || (def_port_type == MIF_USER_DEFINED)) {
fast->event_driven = MIF_TRUE;
@ -262,8 +291,8 @@ card *current; /* the card we are to parse */
mdfast->analog = MIF_TRUE;
}
/* check for a null connection and continue to next connection if found */
/* check for a null connection and continue to next connection if found */
if(next_token_type == MIF_NULL_TOK) {
/* make sure null is allowed */
@ -285,10 +314,13 @@ card *current; /* the card we are to parse */
fast->conn[i]->is_null = MIF_FALSE;
}
/* process connection as appropriate for scalar or array */
/* ===== process connection as appropriate for scalar or array ====== */
if(! conn_info->is_array) { /* a scalar connection - the simpler case */
/* At this point, next_token should hold the first netname in the port netlist. */
/* do a couple of error checks */
if(next_token_type == MIF_LARRAY_TOK) {
LITERR("ERROR - Scalar connection expected, [ found");
@ -315,44 +347,27 @@ card *current; /* the card we are to parse */
0, /* port index for scalar connection */
&status);
/* upon leaving MIFget_port, we should be *ready* to read a % with the next
get_token */
if(status == MIF_ERROR)
return;
fast->conn[i]->size = 1;
}
else { /* the connection is an array - much to be done ... */
else { /* ====== the connection is an array - much to be done ... ====== */
/* get the leading port type for the array if any */
/* it will distribute across all ports inside the braces */
/* overriding the default type in the interface spec */
if(next_token_type == MIF_PERCENT_TOK) {
/* get the port type identifier and check it for validity */
next_token = MIFget_token(&line,&next_token_type);
MIFget_port_type(ckt,
tab,
current,
&line,
&next_token,
&next_token_type,
&def_port_type,
&def_port_type_str,
conn_info,
&status);
if(status == MIF_ERROR)
return;
}
/* At this point, the next_token should be a [ */
/* check for required leading array delim character and eat it if found */
if(next_token_type != MIF_LARRAY_TOK) {
LITERR("Missing [, an array connection was expected");
return;
}
else
else /* eat the [ */
next_token = MIFget_token(&line,&next_token_type);
/* get and process ports until ] is encountered */
/*------ get and process ports until ] is encountered ------*/
for(j = 0;
(next_token_type != MIF_RARRAY_TOK) &&
@ -386,16 +401,24 @@ card *current; /* the card we are to parse */
if(status == MIF_ERROR)
return;
}
} /*------ end of for loop until ] is encountered ------*/
/* At this point, next_token should hold the next token after the
port netnames. This token should be a ]. */
/* make sure we exited because the end of the array connection */
/* was reached. If so, eat the closing array delimiter */
/* was reached. If so, eat the closing array delimiter ] */
if(*line == '\0') {
LITERR("Missing ] in array connection");
return;
}
else
next_token = MIFget_token(&line,&next_token_type);
/* else {
* next_token = MIFget_token(&line,&next_token_type);
* }
*/
/* At this point, the next time we get_token, we should get a % */
/* record the number of ports found for this connection */
if(j < 1) {
@ -404,12 +427,13 @@ card *current; /* the card we are to parse */
}
fast->conn[i]->size = j;
} /* array connection processing */
} /* ====== array connection processing ====== */
/* be careful about putting stuff here, there is a 'continue' used */
/* in the processing of NULL connections above */
} /* for number of connections */
} /******* for number of connections *******/
/* *********************** */
@ -418,8 +442,12 @@ card *current; /* the card we are to parse */
/* check for too many connections */
if(*line != '\0') {
LITERR("Too many connections");
/* At this point, we should have eaten all the net connections. At
this point, line should hold only the remainder of the model line (i.e.
the model name). */
if(strcmp(line,name) != 0) {
LITERR("Too many connections -- expecting model name but encountered other tokens.");
return;
}
@ -586,7 +614,17 @@ static void MIFinit_inst(
/*
MIFget_port_type
This function gets the port type identifier and checks it for validity.
This function gets the port type identifier and checks it for validity. It also
replaces false default information in conn_info with the real info based upon
the discovered port type string.
When we call it, we expect that the next token type (sent from above)
should be the port type (MIF_STRING_TOK type). That is, we should be sitting right
on the def of the port type (i.e. %vnam, %vd, %id, etc.) Note that the parser
should have stripped the % already.
Upon return, this fcn should leave next_token holding the token *after* the
port type (i.e. the thing after vnam, v, vd, id, etc).
*/
@ -643,8 +681,20 @@ MIFget_port_type(
LITERR("Port type is invalid");
*status = MIF_ERROR;
}
else
else {
/* Fix by SDB so that the netlist parser uses the actual nature
of the port instead of the default state to decide if it is an array. */
if ( (*port_type == MIF_DIFF_VOLTAGE) ||
(*port_type == MIF_DIFF_CURRENT) ||
(*port_type == MIF_DIFF_CONDUCTANCE) ||
(*port_type == MIF_DIFF_RESISTANCE) ) {
conn_info->is_array = 1;
}
*status = MIF_OK;
}
}
@ -658,6 +708,13 @@ MIFget_port
This function processes a port being parsed, either single ended,
or both connections of a differential.
When we call this fcn, next_token should be the *first* netname in the port
net list. Depending upon the type of port, this fcn should eat the appropriate
number of net tokens.
When we leave this fcn, next_token should hold the next token after the last
netname processed.
*/
@ -687,27 +744,6 @@ MIFget_port(
char *node;
/* get the leading port type if any */
if(*next_token_type == MIF_PERCENT_TOK) {
/* get the port type identifier and check it for validity */
*next_token = MIFget_token(line, next_token_type);
MIFget_port_type(ckt,
tab,
current,
line,
next_token,
next_token_type,
&def_port_type,
&def_port_type_str,
conn_info,
status);
if(*status == MIF_ERROR) {
return;
}
}
/* allocate space in the instance data struct for this port */
if(port_num == 0) {

View File

@ -64,7 +64,8 @@ NON-STANDARD FEATURES
#include "suffix.h"
/* This is the table of all models known to the program. */
/* It is now defined in inpdefs.h 6.19.2003 -- SDB. */
extern INPmodel *modtab;
extern SPICEdev **DEVices; /* info about all device types */
@ -111,20 +112,29 @@ char *MIFgetMod(
MIFmodel *mdfast;
/* Mif_Param_Info_t *param_info;*/
/* locate the named model in the modtab list */
/* =========== First locate the named model in the modtab list ================= */
#ifdef TRACE
/* SDB debug statement */
printf("In MIFgetMod, model name = %s . . .\n", name);
printf("In MIFgetMod, looking for model name = %s . . .\n", name);
#endif
/* maschmann : remove : from name */
/* maschmann : remove : from name
* char *pos;
* if((pos=strstr(name,":"))!=NULL) *pos=0;
*/
/* char *pos;
/*------------------------------------
for (i = &modtab; *i != (INPmodel *) NULL; i = &((*i)->INPnextModel)) {
if (strcmp((*i)->INPmodName, token) == 0) {
return (OK);
}
}
--------------------------*/
if((pos=strstr(name,":"))!=NULL) *pos=0; */
for (modtmp = modtab; modtmp != NULL; modtmp = ((modtmp)->INPnextModel)) {
/* loop through modtable looking for this model (*name) */
for (modtmp = modtab; modtmp != NULL; modtmp = ((modtmp)->INPnextModel) ) {
#ifdef TRACE
/* SDB debug statement */
@ -133,13 +143,16 @@ char *MIFgetMod(
if (strcmp((modtmp)->INPmodName,name) == 0) {
#ifdef TRACE
/* SDB debug statement */
printf("In MIFgetMod, found model!!!\n");
#endif
/* found the model in question - now instantiate if necessary */
/* and return an appropriate pointer to it */
/* ========= found the model in question - now instantiate if necessary ========== */
/* ============== and return an appropriate pointer to it ===================== */
/* make sure the type is valid before proceeding */
if(modtmp->INPmodType<0) {
if( (modtmp)->INPmodType < 0) {
/* illegal device type, so can't handle */
*model = NULL;
@ -213,7 +226,7 @@ char *MIFgetMod(
//err has not been allocated, but free() in INPerrCat()
// This did not allocate enough memory you wanker, K.A. replaced 5 March 2000
// temp = (char *)tmalloc((40+strlen(parm)) * sizeof(char));
// temp = (char *)tmalloc((40+strlen(parm)) * sizeof(char));
temp = (char *)tmalloc((42+strlen(parm)) * sizeof(char));// K.A. replaced 5 March 2000
sprintf(temp, "MIF: unrecognized parameter (%s) - ignored\n", parm);

View File

@ -62,6 +62,8 @@ is advanced to the following token and the token from the input
string is copied to malloced storage and a pointer to that storage
is returned. The original input string is undisturbed.
MIFgettok treats ( and ) like whitespace.
*/
char *MIFgettok(char **s)
@ -140,8 +142,8 @@ char *MIFgettok(char **s)
(*s)++;
/* make a copy using only the space needed by the string length */
ret_str = copy(buf);
/* Changed from copy to MIFcopy by SDB on 6.22.2003 */
ret_str = MIFcopy(buf);
FREE(buf);
return(ret_str);

View File

@ -1,6 +1,6 @@
## Process this file with automake to produce Makefile.in
SUBDIRS = resistance filters polezero bsim3soipd bsim3soifd bsim3soidd bsim4 mesa
SUBDIRS = resistance filters polezero bsim3soipd bsim3soifd bsim3soidd bsim4 mesa TransImpedanceAmp
TESTS = \
diffpair.cir \

View File

@ -0,0 +1,10 @@
## Process this file with automake to produce Makefile.in
TESTS = \
output.net
TESTS_ENVIRONMENT = $(SHELL) $(srcdir)/../check.sh $(top_builddir)/src/ngspice
EXTRA_DIST = output.net README
MAINTAINERCLEANFILES = Makefile.in

View File

@ -0,0 +1,41 @@
This directory holds a SPICE netlist with SPICE2 POLY constructs in
controlled sources as typically found in vendor models. The circuit
is just a two-stage transimpedance amp using an AD8009,
along with some slow components (AD780 and OP177A) to set bias
points. Vendor models are used for all active components.
Successfully running this test shows that you have successfully built
the XSpice stuff with the POLY codemodel, and that you should be able
to simulate SPICE netlists with embedded vendor models.
To run this netlist, just do the following:
[localhost]# ngspice
ngspice 1 -> source output.net
ngspice 2 -> run
ngspice 3 -> plot Vout2
(Note that when you read in the netlist, you will get a bunch of
warnings saying stuff like:
Warning -- Level not specified on line "()"
Using level 1.
Also, ngspice will complain about:
Error on line 50 : r:u101:1 u101:40 0 1e3 tc=7e-6
unknown parameter (tc)
Error on line 283 : .temp 0 25 50 75 100
Warning: .TEMP card obsolete - use .options TEMP and TNOM
You can ignore all this stuff . . . .)
You should get a pop-up window showing two square pulses (the second
smaller than the first) with a little bit of overshoot on the rising
and falling edges.
This stuff was done as an adjunct to work on the gEDA project.
Information about gEDA is available at http://geda.seul.org/ .
Please direct all questions/suggestions/bugs/complaints about XSpice
extensions to ngspice to Stuart Brorson -- mailto:sdb@cloud9.net.
6.23.2002 -- SDB.

View File

@ -0,0 +1,453 @@
*********************************************************
* Spice file generated by gnetlist *
* spice-SDB version 3.30.2003 by SDB -- *
* provides advanced spice netlisting capability. *
* Documentation at http://www.brorson.com/gEDA/SPICE/ *
*********************************************************
* Command stuff
.options gmin=1e-9
.options abstol=1e-11
* .ac dec 10 10MegHz 10 Ghz
* Remainder of file
R112 0 6 1Meg
R111 0 8 10Meg
R110 0 7 1Meg
Rref2in 11 VU780out 25000
Rref2fb VU2bias+ 11 33
C201 0 9 1uF
C202 10 0 1uF
XU200 0 11 10 9 VU2bias+ OP177A
R202 10 +5V 22
R201 -5V 9 22
Rref1in VU100in- VU780out 9130
Rref1fb VU1bias+ VU100in- 33
XU101 +5V 7 0 6 VU780out 8 AD780A
* AD780A SPICE Macromodel 5/93, Rev. A
* AAG / PMI
*
* This version of the AD780 voltage reference model simulates the worst case
* parameters of the 'A' grade. The worst case parameters used
* correspond to those in the data sheet.
*
* Copyright 1993 by Analog Devices, Inc.
*
* Refer to "README.DOC" file for License Statement. Use of this model
* indicates your acceptance with the terms and provisions in the License Statement.
*
* NODE NUMBERS
* VIN
* | TEMP
* | | GND
* | | | TRIM
* | | | | VOUT
* | | | | | RANGE
* | | | | | |
.SUBCKT AD780A 2 3 4 5 6 8
*
* BANDGAP REFERENCE
*
I1 4 40 DC 1.21174E-3
R1 40 4 1E3 TC=7E-6
EN 10 40 42 0 1
G1 4 10 2 4 4.85668E-9
F1 4 10 POLY(2) VS1 VS2 (0,2.42834E-5,3.8E-5)
Q1 2 10 11 QT
I2 11 4 DC 12.84E-6
R2 11 3 1E3
I3 3 4 DC 0
*
* NOISE VOLTAGE GENERATOR
*
VN1 41 0 DC 2
DN1 41 42 DEN
DN2 42 43 DEN
VN2 0 43 DC 2
*
* INTERNAL OP AMP
*
G2 4 12 10 20 1.93522E-4
R3 12 4 2.5837E9
C1 12 4 6.8444E-11
D1 12 13 DX
V1 2 13 DC 1.2
*
* SECONDARY POLE @ 508 kHz
*
G3 4 14 12 4 1E-6
R4 14 4 1E6
C2 14 4 3.1831E-13
*
* OUTPUT STAGE
*
ISY 2 4 6.8282E-4
FSY 2 4 V1 -1
RSY 2 4 500E3
*
G4 4 15 14 4 25E-6
R5 15 4 40E3
Q2 4 15 16 QP
I4 2 16 DC 100E-6
Q3 4 16 18 QP
R6 18 23 15
R7 16 21 150E3
R8 2 17 34.6
Q4 17 16 19 QN
R9 21 20 6.46E3
R10 20 4 6.1E3
R11 20 5 53E3
R12 20 8 15.6E3
I5 5 4 DC 0
I6 8 4 DC 0
VS1 21 19 DC 0
VS2 23 21 DC 0
L1 21 6 1E-7
*
* OUTPUT CURRENT LIMIT
*
FSC 15 4 VSC 1
VSC 2 22 DC 0
QSC 22 2 17 QN
*
.MODEL QT NPN(IS=1.68E-16 BF=1E4)
.MODEL QN NPN(IS=1E-15 BF=1E3)
.MODEL QP PNP(IS=1E-15 BF=1E3)
.MODEL DX D(IS=1E-15)
.MODEL DEN D(IS=1E-12 RS=2.425E+05 AF=1 KF=6.969E-16)
.ENDS AD780A
C101 0 U100V- 1uF
C102 U100V+ 0 1uF
XU100 0 VU100in- U100V+ U100V- VU1bias+ OP177A
* OP177A SPICE Macro-model 12/90, Rev. B
* JCB / PMI
*
* Revision History:
* REV. B
* Re-ordered subcircuit call out nodes to put the
* output node last.
* Changed Ios from 1E-9 to 0.5E-9
* Added F1 and F2 to fix short circuit current limit.
*
*
* This version of the OP-177 model simulates the worst case
* parameters of the 'A' grade. The worst case parameters
* used correspond to those in the data book.
*
*
* Copyright 1990 by Analog Devices, Inc.
*
* Refer to "README.DOC" file for License Statement. Use of this model
* indicates your acceptance with the terms and provisions in the License Statement.
*
* Node assignments
* non-inverting input
* | inverting input
* | | positive supply
* | | | negative supply
* | | | | output
* | | | | |
.SUBCKT OP177A 1 2 99 50 39
*
* INPUT STAGE & POLE AT 6 MHZ
*
R1 2 3 5E11
R2 1 3 5E11
R3 5 97 0.0606
R4 6 97 0.0606
CIN 1 2 4E-12
C2 5 6 218.9E-9
I1 4 51 1
IOS 1 2 0.5E-9
EOS 9 10 POLY(1) 30 33 10E-6 1
Q1 5 2 7 QX
Q2 6 9 8 QX
R5 7 4 0.009
R6 8 4 0.009
D1 2 1 DX
D2 1 2 DX
EN 10 1 12 0 1
GN1 0 2 15 0 1
GN2 0 1 18 0 1
*
EREF 98 0 33 0 1
EPLUS 97 0 99 0 1
ENEG 51 0 50 0 1
*
* VOLTAGE NOISE SOURCE WITH FLICKER NOISE
*
DN1 11 12 DEN
DN2 12 13 DEN
VN1 11 0 DC 2
VN2 0 13 DC 2
*
* CURRENT NOISE SOURCE WITH FLICKER NOISE
*
DN3 14 15 DIN
DN4 15 16 DIN
VN3 14 0 DC 2
VN4 0 16 DC 2
*
* SECOND CURRENT NOISE SOURCE
*
DN5 17 18 DIN
DN6 18 19 DIN
VN5 17 0 DC 2
VN6 0 19 DC 2
*
* FIRST GAIN STAGE
*
R7 20 98 1
G1 98 20 5 6 119.8
D3 20 21 DX
D4 22 20 DX
E1 97 21 POLY(1) 97 33 -2.4 1
E2 22 51 POLY(1) 33 51 -2.4 1
*
* GAIN STAGE & DOMINANT POLE AT 0.127 HZ
*
R8 23 98 1.253E9
C3 23 98 1E-9
G2 98 23 20 33 33.3E-6
V1 97 24 1.8
V2 25 51 1.8
D5 23 24 DX
D6 25 23 DX
*
* NEGATIVE ZERO AT -4MHZ
*
R9 26 27 1
C4 26 27 -39.75E-9
R10 27 98 1E-6
E3 26 98 23 33 1E6
*
* COMMON-MODE GAIN NETWORK WITH ZERO AT 63 HZ
*
R13 30 31 1
L2 31 98 2.52E-3
G4 98 30 3 33 0.316E-6
D7 30 97 DX
D8 51 30 DX
*
* POLE AT 2 MHZ
*
R14 32 98 1
C5 32 98 79.5E-9
G5 98 32 27 33 1
*
* OUTPUT STAGE
*
R15 33 97 1
R16 33 51 1
GSY 99 50 POLY(1) 99 50 0.725E-3 0.0425E-3
F1 34 0 V3 1
F2 0 34 V4 1
R17 34 99 400
R18 34 50 400
L3 34 39 2E-7
G6 37 50 32 34 2.5E-3
G7 38 50 34 32 2.5E-3
G8 34 99 99 32 2.5E-3
G9 50 34 32 50 2.5E-3
V3 35 34 6.8
V4 34 36 4.4
D9 32 35 DX
D10 36 32 DX
D11 99 37 DX
D12 99 38 DX
D13 50 37 DY
D14 50 38 DY
*
* MODELS USED
*
.MODEL QX NPN(BF=333.3E6)
.MODEL DX D(IS=1E-15)
.MODEL DY D(IS=1E-15 BV=50)
.MODEL DEN D(IS=1E-12, RS=14.61K, KF=2E-17, AF=1)
.MODEL DIN D(IS=1E-12, RS=7.55E-6, KF=3E-15, AF=1)
.ENDS
R102 U100V+ +5V 22
R101 -5V U100V- 22
R98 0 VU2bias+ 1K
R99 0 VU1bias+ 1K
C95 VU2bias+ 0 100pF
* C96 0 5 1uF
* C97 4 0 1uF
Cphotodiode 0 Vinput 0.9pF
C99 0 VU1bias+ 100pF
R25 Vout2 2 250
C24 Vout1 VU1in- 1pF
R24 VU1in- 1 150
* C21 0 3 1uF
Cc Vout2 VU2in- 1pF
Rc Vout1 VU2in- 10
RL 0 Vout2 50
.TEMP 0 25 50 75 100
C12 2 0 1.5pF
C11 0 V2- .01uF
C10 V2+ 0 .01uF
R13 +5V V2+ 5
R12 V2- -5V 5
R26 2 VU2in- 150
R11 Vout2 VU2in- 180
XU2 VU2bias+ VU2in- V2+ V2- Vout2 AD8009an
XU1 VU1bias+ VU1in- V1+ V1- Vout1 AD8009an
***** AD8009 SPICE model Rev B SMR/ADI 8-21-97
* Copyright 1997 by Analog Devices, Inc.
* Refer to "README.DOC" file for License Statement. Use of this model
* indicates your acceptance with the terms and provisions in the License Statement.
* rev B of this model corrects a problem in the output stage that would not
* correctly reflect the output current to the voltage supplies
* This model will give typical performance characteristics
* for the following parameters;
* closed loop gain and phase vs bandwidth
* output current and voltage limiting
* offset voltage (is static, will not vary with vcm)
* ibias (again, is static, will not vary with vcm)
* slew rate and step response performance
* (slew rate is based on 10-90% of step response)
* current on output will be reflected to the supplies
* vnoise, referred to the input
* inoise, referred to the input
* distortion is not characterized
* Node assignments
* non-inverting input
* | inverting input
* | | positive supply
* | | | negative supply
* | | | | output
* | | | | |
.SUBCKT AD8009an 1 2 99 50 28
* input stage *
q1 50 3 5 qp1
q2 99 5 4 qn1
q3 99 3 6 qn2
q4 50 6 4 qp2
i1 99 5 1.625e-3
i2 6 50 1.625e-3
cin1 1 98 2.6e-12
cin2 2 98 1e-12
v1 4 2 0
* input error sources *
eos 3 1 poly(1) 20 98 2e-3 1
fbn 2 98 poly(1) vnoise3 50e-6 1e-3
fbp 1 98 poly(1) vnoise3 50e-6 1e-3
* slew limiting stage *
fsl 98 16 v1 1
dsl1 98 16 d1
dsl2 16 98 d1
dsl3 16 17 d1
dsl4 17 16 d1
rsl 17 18 0.22
vsl 18 98 0
* gain stage *
f1 98 7 vsl 2
rgain 7 98 2.5e5
cgain 7 98 1.25e-12
dcl1 7 8 d1
dcl2 9 7 d1
vcl1 99 8 1.83
vcl2 9 50 1.83
gcm 98 7 poly(2) 98 0 30 0 0 1e-5 1e-5
* second pole *
epole 14 98 7 98 1
rpole 14 15 1
cpole 15 98 2e-10
* reference stage *
eref 98 0 poly(2) 99 0 50 0 0 0.5 0.5
ecmref 30 0 poly(2) 1 0 2 0 0 0.5 0.5
* vnoise stage *
rnoise1 19 98 4.6e-3
vnoise1 19 98 0
vnoise2 21 98 0.53
dnoise1 21 19 dn
fnoise1 20 98 vnoise1 1
rnoise2 20 98 1
* inoise stage *
rnoise3 22 98 8.18e-6
vnoise3 22 98 0
vnoise4 24 98 0.575
dnoise2 24 22 dn
fnoise2 23 98 vnoise3 1
rnoise4 23 98 1
* buffer stage *
gbuf 98 13 15 98 1e-2
rbuf 98 13 1e2
* output current reflected to supplies *
fcurr 98 40 voc 1
vcur1 26 98 0
vcur2 98 27 0
dcur1 40 26 d1
dcur2 27 40 d1
* output stage *
vo1 99 90 0
vo2 91 50 0
fout1 0 99 poly(2) vo1 vcur1 -9.27e-3 1 -1
fout2 50 0 poly(2) vo2 vcur2 -9.27e-3 1 -1
gout1 90 10 13 99 0.5
gout2 91 10 13 50 0.5
rout1 10 90 2
rout2 10 91 2
voc 10 28 0
rout3 28 98 1e6
dcl3 13 11 d1
dcl4 12 13 d1
vcl3 11 10 -0.445
vcl4 10 12 -0.445
.model qp1 pnp()
.model qp2 pnp()
.model qn1 npn()
.model qn2 npn()
.model d1 d()
.model dn d(af=1 kf=1e-8)
.ends
R6 1 Vout1 250
C3 1 0 1.5pF
V3 VU1in- Vinput DC 0V
* .INCLUDE /home/sdb/OpticalReceiver/Simulation.cmd
R5 -5V Vout1 1K
I1 0 Vinput AC 1 PWL (0ns 0mA 1nS 0mA 1.01nS 1mA 10nS 1mA 10.01nS 0mA 20nS 0mA 20.01nS .1mA 30nS .1mA 30.01nS 0mA)
R4 V1- -5V 5
C2 0 V1- .01uF
V2 -5V 0 DC -5V
R2 VU1in- Vout1 180
V1 +5V 0 DC 5V
C1 V1+ 0 .01uF
R1 +5V V1+ 5
* When run, this SPICE file should output a square waveform
* with a little overshoot
.tran 0.05ns 40ns
.plot Vout2
.END