diff --git a/src/Makefile.am b/src/Makefile.am index 84c113ea7..5cbea62db 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -1,10 +1,11 @@ ## Process this file with automake to produce Makefile.in +## PN: remember to add CIDERSCRIPTS -SUBDIRS = misc maths frontend spicelib include @XSPICEDIR@ +SUBDIRS = misc maths frontend spicelib include @XSPICEDIR@ @CIDERDIR@ bin_PROGRAMS = ngspice ngnutmeg nghelp ngsconvert ngproc2mod ngmultidec makeidx -EXTRA_DIST = ngspice.txt ngspice.idx spinit setplot spectrum +EXTRA_DIST = ngspice.txt ngspice.idx spinit setplot spectrum @CIDERSCRIPTS@ helpdatadir = $(pkgdatadir)/helpdir @@ -12,19 +13,23 @@ helpdata_DATA = ngspice.idx ngspice.txt initdatadir = $(pkgdatadir)/scripts -initdata_DATA = spinit setplot spectrum +initdata_DATA = spinit setplot spectrum @CIDERSCRIPTS@ DYNAMIC_DEVICELIBS = \ spicelib/devices/asrc/libasrc.a \ spicelib/devices/bjt/libbjt.a \ + spicelib/devices/bjt2/libbjt2.a \ spicelib/devices/bsim1/libbsim1.a \ spicelib/devices/bsim2/libbsim2.a \ spicelib/devices/bsim3/libbsim3.a \ + spicelib/devices/bsim3v0/libbsim3v0.a \ spicelib/devices/bsim3v1/libbsim3v1.a \ - spicelib/devices/bsim3v2/libbsim3v2.a \ + spicelib/devices/bsim3v1s/libbsim3v1s.a \ + spicelib/devices/bsim3v1a/libbsim3v1a.a \ spicelib/devices/bsim4/libbsim4.a \ spicelib/devices/cap/libcap.a \ + spicelib/devices/libbsim3soi.a \ spicelib/devices/bsim3soi_pd/libbsim3soipd.a \ spicelib/devices/bsim3soi_fd/libbsim3soifd.a \ spicelib/devices/bsim3soi_dd/libbsim3soidd.a \ @@ -39,6 +44,7 @@ DYNAMIC_DEVICELIBS = \ spicelib/devices/isrc/libisrc.a \ spicelib/devices/hfet1/libhfet.a \ spicelib/devices/hfet2/libhfet2.a \ + spicelib/devices/hisim/libhisim.a \ spicelib/devices/jfet/libjfet.a \ spicelib/devices/jfet2/libjfet2.a \ spicelib/devices/ltra/libltra.a \ @@ -57,17 +63,10 @@ DYNAMIC_DEVICELIBS = \ spicelib/devices/urc/liburc.a \ spicelib/devices/vccs/libvccs.a \ spicelib/devices/vcvs/libvcvs.a \ - spicelib/devices/vsrc/libvsrc.a - - - -## ----- 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.a \ -## poly added to dynamic libs by SDB on 6.1.2003 -## xspice/icm/poly/libpoly.a - + spicelib/devices/vsrc/libvsrc.a \ + @NUMDEV@ + + ## Build ngspice first: ngspice_SOURCES = \ @@ -88,10 +87,12 @@ ngspice_LDADD = \ spicelib/devices/libdev.a \ @XSPICELIB2@ \ frontend/parser/libparser.a \ + @CIDERSIM@ frontend/help/libhlp.a \ spicelib/parser/libinp.a \ maths/deriv/libderiv.a \ maths/cmaths/libcmaths.a \ + maths/misc/libmathsmisc.a \ maths/poly/libpoly.a \ maths/ni/libni.a \ maths/sparse/libsparse.a \ diff --git a/src/frontend/resource.c b/src/frontend/resource.c index eee58cd0d..a18e75fe1 100644 --- a/src/frontend/resource.c +++ b/src/frontend/resource.c @@ -168,6 +168,9 @@ ft_ckspace(void) static void printres(char *name) { +#ifdef CIDER + char *paramname = NULL; +#endif bool yy = FALSE; static long lastsec = 0, lastusec = 0; struct variable *v; @@ -314,11 +317,24 @@ printres(char *name) /* Now get all the spice resource stuff. */ if (ft_curckt && ft_curckt->ci_ckt) { + +#ifdef CIDER +/* begin cider integration */ + if (!name || eq(name, "circuit") || eq(name, "task")) { + paramname = NULL; + } else { + paramname = name; + } + v = if_getstat(ft_curckt->ci_ckt, paramname); + if (paramname && v) { +/* end cider integration */ +#else /* ~CIDER */ if (name && eq(name, "task")) v = if_getstat(ft_curckt->ci_ckt, NULL); else v = if_getstat(ft_curckt->ci_ckt, name); if (name && v) { +#endif fprintf(cp_out, "%s = ", v->va_name); wl_print(cp_varwl(v), cp_out); (void) putc('\n', cp_out); @@ -333,6 +349,17 @@ printres(char *name) } yy = TRUE; } + +#ifdef CIDER + /* begin cider integration */ + /* Now print out interesting stuff about numerical devices. */ + if (!name || eq(name, "devices")) { + (void) NDEVacct(ft_curckt->ci_ckt, cp_out); + yy = TRUE; + } + /* end cider integration */ +#endif + } if (!yy) { diff --git a/src/include/Makefile.am b/src/include/Makefile.am index 846fddf20..3c6406586 100644 --- a/src/include/Makefile.am +++ b/src/include/Makefile.am @@ -1,60 +1,110 @@ ## Process this file with automake to produce Makefile.in -noinst_HEADERS = \ - acdefs.h \ - bool.h \ - cktdefs.h \ - complex.h \ - const.h \ - cpdefs.h \ - cpextern.h \ - cpstd.h \ - defines.h \ - devdefs.h \ - dgen.h \ - distodef.h \ - dvec.h \ - ftedbgra.h \ - ftedebug.h \ - ftedefs.h \ - ftedev.h \ - fteext.h \ - fteinp.h \ - fteinput.h \ - fteparse.h \ - gendefs.h \ - graph.h \ - grid.h \ - hlpdefs.h \ - iferrmsg.h \ - ifsim.h \ - inpdefs.h \ - inpmacs.h \ - inpptree.h \ - jobdefs.h \ - macros.h \ - memory.h \ - missing_math.h \ - ngspice.h \ - noisedef.h \ - opdefs.h \ - optdefs.h \ - plot.h \ - pnode.h \ - pzdefs.h \ - sen2defs.h \ - sensdefs.h \ - sensgen.h \ - sim.h \ - smpdefs.h \ - sperror.h \ - spmatrix.h \ - suffix.h \ - terminal.h \ - tfdefs.h \ - trandefs.h \ - trcvdefs.h \ - tskdefs.h \ - wordlist.h +noinst_HEADERS = \ + acdefs.h \ + bdrydefs.h \ + bool.h \ + carddefs.h \ + ciderinp.h \ + cidersupt.h \ + cktdefs.h \ + cluster.h \ + cmconstants.h \ + cm.h \ + cmproto.h \ + cmtypes.h \ + complex.h \ + const.h \ + contdefs.h \ + cpdefs.h \ + cpextern.h \ + cpstd.h \ + defines.h \ + devdefs.h \ + dgen.h \ + distodef.h \ + dllitf.h \ + domndefs.h \ + dvec.h \ + elctdefs.h \ + enh.h \ + evt.h \ + evtproto.h \ + evtudn.h \ + ftedbgra.h \ + ftedebug.h \ + ftedefs.h \ + ftedev.h \ + fteext.h \ + fteinp.h \ + fteinput.h \ + fteparse.h \ + gendefs.h \ + gendev.h \ + graph.h \ + grid.h \ + hlpdefs.h \ + iferrmsg.h \ + ifsim.h \ + inpdefs.h \ + inpmacs.h \ + inpptree.h \ + ipc.h \ + ipcproto.h \ + ipctiein.h \ + jobdefs.h \ + lsort.h \ + macros.h \ + material.h \ + matldefs.h \ + memory.h \ + meshdefs.h \ + meshext.h \ + methdefs.h \ + mifcmdat.h \ + mifdefs.h \ + mif.h \ + mifparse.h \ + mifproto.h \ + miftypes.h \ + missing_math.h \ + mobdefs.h \ + modldefs.h \ + multi_line.h \ + ngspice.h \ + noisedef.h \ + numcards.h \ + numconst.h \ + numenum.h \ + numgen.h \ + numglobs.h \ + onedev.h \ + onemesh.h \ + opdefs.h \ + optdefs.h \ + optndefs.h \ + outpdefs.h \ + plot.h \ + pnode.h \ + profile.h \ + pzdefs.h \ + sen2defs.h \ + sensdefs.h \ + sensgen.h \ + sim.h \ + smpdefs.h \ + sperror.h \ + spmatrix.h \ + suffix.h \ + swec.h \ + terminal.h \ + tfdefs.h \ + trandefs.h \ + trcvdefs.h \ + tskdefs.h \ + twodev.h \ + twomesh.h \ + wordlist.h \ + wstdio.h MAINTAINERCLEANFILES = Makefile.in diff --git a/src/include/bool.h b/src/include/bool.h index 868c6653a..804985f40 100644 --- a/src/include/bool.h +++ b/src/include/bool.h @@ -2,7 +2,12 @@ #define _BOOL_H typedef unsigned char bool; + +#define BOOLEAN int #define TRUE 1 #define FALSE 0 +#define NO 0 +#define YES 1 + #endif diff --git a/src/include/cktdefs.h b/src/include/cktdefs.h index 4439ccfe2..559fb4ef4 100644 --- a/src/include/cktdefs.h +++ b/src/include/cktdefs.h @@ -14,7 +14,7 @@ /* gtri - evt - wbk - 5/20/91 - add event-driven and enhancements data */ -#define MAXNUMDEVS 40 /* Max number of possible devices PN:XXX may cause toubles*/ +#define MAXNUMDEVS 64 /* Max number of possible devices PN:XXX may cause toubles*/ extern int DEVmaxnum; /* Not sure if still used */ #define MAXNUMDEVNODES 4 /* Max No. of nodes per device */ /* Need to change for SOI devs ? */ diff --git a/src/include/complex.h b/src/include/complex.h index bbcabc180..b923c487b 100644 --- a/src/include/complex.h +++ b/src/include/complex.h @@ -17,6 +17,22 @@ typedef struct _complex1 complex; #define realpart(cval) ((struct _complex1 *) (cval))->cx_real #define imagpart(cval) ((struct _complex1 *) (cval))->cx_imag +#ifdef CIDER +/* From Cider numcomplex.h + pn:leave it here until I decide what to do about +struct mosAdmittances { + complex yIdVdb; + complex yIdVsb; + complex yIdVgb; + complex yIsVdb; + complex yIsVsb; + complex yIsVgb; + complex yIgVdb; + complex yIgVsb; + complex yIgVgb; + }; + */ +#endif /* * Each expects two arguments for each complex number - a real and an @@ -270,6 +286,11 @@ typedef struct /* Macro function that returns the approx absolute value of a complex number. */ #define ELEMENT_MAG(ptr) (ABS((ptr)->Real) + ABS((ptr)->Imag)) + +#define CMPLX_ASSIGN_VALUE(cnum, vReal, vImag) \ +{ (cnum).Real = vReal; \ + (cnum).Imag = vImag; \ +} /* Complex assignment statements. */ #define CMPLX_ASSIGN(to,from) \ @@ -288,12 +309,21 @@ typedef struct { (to).Real = -(from).Real; \ (to).Imag = (from).Imag; \ } + #define CMPLX_CONJ(a) (a).Imag = -(a).Imag + +#define CONJUGATE(a) (a).Imag = -(a).Imag + #define CMPLX_NEGATE(a) \ { (a).Real = -(a).Real; \ (a).Imag = -(a).Imag; \ } +#define CMPLX_NEGATE_SELF(cnum) \ +{ (cnum).real = -(cnum).Real; \ + (cnum).imag = -(cnum).Imag; \ +} + /* Macro that returns the approx magnitude (L-1 norm) of a complex number. */ #define CMPLX_1_NORM(a) (ABS((a).Real) + ABS((a).Imag)) @@ -309,6 +339,11 @@ typedef struct (to).Imag = (from_a).Imag + (from_b).Imag; \ } +/* Macro function that performs addition of a complex and a scalar. */ +#define CMPLX_ADD_SELF_SCALAR(cnum, scalar) \ +{ (cnum).Real += scalar; \ +} + /* Macro function that performs complex subtraction. */ #define CMPLX_SUBT(to,from_a,from_b) \ { (to).Real = (from_a).Real - (from_b).Real; \ @@ -326,7 +361,7 @@ typedef struct { (to).Real -= (from).Real; \ (to).Imag -= (from).Imag; \ } - + /* Macro function that multiplies a complex number by a scalar. */ #define SCLR_MULT(to,sclr,cmplx) \ { (to).Real = (sclr) * (cmplx).Real; \ @@ -339,6 +374,33 @@ typedef struct (to).Imag *= (sclr); \ } +/* Macro function that multiplies two complex numbers. */ +#define CMPLX_MULT(to,from_a,from_b) \ +{ (to).real = (from_a).Real * (from_b).Real - \ + (from_a).Imag * (from_b).Imag; \ + (to).imag = (from_a).Real * (from_b).Imag + \ + (from_a).Imag * (from_b).Real; \ +} + +/* Macro function that multiplies a complex number and a scalar. */ +#define CMPLX_MULT_SCALAR(to,from, scalar) \ +{ (to).Real = (from).Real * scalar; \ + (to).Imag = (from).Imag * scalar; \ +} + +/* Macro function that implements *= for a complex and a scalar number. */ + +#define CMPLX_MULT_SELF_SCALAR(cnum, scalar) \ +{ (cnum).Real *= scalar; \ + (cnum).Imag *= scalar; \ +} + +/* Macro function that multiply-assigns a complex number by a scalar. */ +#define SCLR_MULT_ASSIGN(to,sclr) \ +{ (to).Real *= (sclr); \ + (to).Imag *= (sclr); \ +} + /* Macro function that multiplies two complex numbers. */ #define CMPLX_MULT(to,from_a,from_b) \ { (to).Real = (from_a).Real * (from_b).Real - \ diff --git a/src/include/defines.h b/src/include/defines.h index b28fe2aa6..117c162c4 100644 --- a/src/include/defines.h +++ b/src/include/defines.h @@ -97,7 +97,7 @@ #define HAS_ASCII #define HAS_TTY_ -#define HAS_TIME_ +#define HAS_TIME_H #define HAS_RLIMIT_ diff --git a/src/include/devdefs.h b/src/include/devdefs.h index d776fe14e..4422a66c3 100644 --- a/src/include/devdefs.h +++ b/src/include/devdefs.h @@ -22,6 +22,19 @@ void DEVqmeyer(double,double,double,double,double,double*,double*,double*, double,double); double DEVpred(CKTcircuit*,int); +#ifdef CIDER +/* Cider integration */ +double limitResistorVoltage( double, double, int * ); +double limitJunctionVoltage( double, double, int * ); +double limitVbe( double, double, int * ); +double limitVce( double, double, int * ); +double limitVgb( double, double, int * ); +#endif + + + + + typedef struct SPICEdev { IFdevice DEVpublic; @@ -80,6 +93,13 @@ typedef struct SPICEdev { /* procedure to do distortion operations */ int (*DEVnoise)(int, int, GENmodel*,CKTcircuit*, Ndata *, double *); /* noise routine */ +#ifdef CIDER + void (*DEVdump)(GENmodel *, CKTcircuit *); + void (*DEVacct)(GENmodel *, CKTcircuit *, FILE *); + /* routines to report device internals + * now used only by cider numerical devices + */ +#endif int *DEVinstSize; /* size of an instance */ int *DEVmodSize; /* size of a model */ diff --git a/src/include/macros.h b/src/include/macros.h index 7a203b986..dfaad4528 100644 --- a/src/include/macros.h +++ b/src/include/macros.h @@ -14,6 +14,8 @@ #define NUMELEMS(ARRAY) (sizeof(ARRAY)/sizeof(*ARRAY)) +/* String macros */ + #define eq(a,b) (!strcmp((a), (b))) #define eqc(a,b) (cieq((a), (b))) #define isalphanum(c) (isalpha(c) || isdigit(c)) @@ -22,10 +24,17 @@ ((c) <= 'F')) ? ((c) - 'A' + 10) : 0))) +/* Mathematical macros */ + #define MIN(a,b) ((a) < (b) ? (a) : (b)) #define MAX(a,b) ((a) > (b) ? (a) : (b)) +#define ABS(a) ((a) < 0.0 ? -(a) : (a)) +#define SGN(a) ((a) < 0.0 ? -(1.0) : (1.0)) #define SIGN(a,b) ( b >= 0 ? (a >= 0 ? a : - a) : (a >= 0 ? - a : a)) - +#define SWAP(type, a, b) {type swapx; swapx = a; a = b; b = swapx;} + + +#define NIL(type) ((type *)0) #define ABORT() fflush(stderr);fflush(stdout);abort(); #define ERROR(CODE,MESSAGE) { \ @@ -60,4 +69,15 @@ #define DEBUGMSG(testargs) #endif +/* Macro that queries the system to find the process time. */ + +#define ELAPSED_TIME( time ) \ +{ struct tms {int user, sys, cuser, csys;} buffer; \ + \ + times(&buffer); \ + time = buffer.user / 60.0; \ +} + + + #endif /* _MACROS_H_ */ diff --git a/src/include/ngspice.h b/src/include/ngspice.h index ddbddc8b0..e3149d8a7 100644 --- a/src/include/ngspice.h +++ b/src/include/ngspice.h @@ -25,6 +25,8 @@ #include "memory.h" #include "defines.h" #include "macros.h" +#include "bool.h" +#include "complex.h" #include #include @@ -110,7 +112,7 @@ struct timeb timebegin; #endif /* va: no index, but strchr */ #endif -#ifdef HAS_TIME_ +#ifdef HAS_TIME_H #include #endif @@ -167,4 +169,17 @@ extern char *Lib_Path; extern int ARCHme; /* My logical process number */ extern int ARCHsize; /* Total number of processes */ +#ifdef CIDER +/* Definitions of globals for Machine Accuracy Limits + * Imported from cider +*/ + +extern double BMin; /* lower limit for B(x) */ +extern double BMax; /* upper limit for B(x) */ +extern double ExpLim; /* limit for exponential */ +extern double Accuracy; /* accuracy of the machine */ +extern double Acc, MuLim, MutLim; +#endif /* CIDER */ + + #endif /* NGSPICE_H_INCLUDED */ diff --git a/src/main.c b/src/main.c index 112b14db3..62d1807cd 100644 --- a/src/main.c +++ b/src/main.c @@ -49,6 +49,10 @@ #endif #endif +#ifdef CIDER +#include "numenum.h" +#endif + extern void DevInit(void); /* Main options */ @@ -72,10 +76,57 @@ IFsimulator *ft_sim = NULL; int ARCHme; int ARCHsize; +#ifdef CIDER +/* Globals definitions for Machine Accuracy Limits + * (needed by CIDER) + */ +double BMin; /* lower limit for B(x) */ +double BMax; /* upper limit for B(x) */ +double ExpLim; /* limit for exponential */ +double Accuracy; /* accuracy of the machine */ +double Acc, MuLim, MutLim; +#endif + char *errRtn; char *errMsg; char *cp_program; +#ifdef CIDER +/* Global debug flags from CIDER, soon they will become + * spice variables :) + */ +BOOLEAN ONEacDebug = FALSE; +BOOLEAN ONEdcDebug = TRUE; +BOOLEAN ONEtranDebug = TRUE; +BOOLEAN ONEjacDebug = FALSE; + +BOOLEAN TWOacDebug = FALSE; +BOOLEAN TWOdcDebug = TRUE; +BOOLEAN TWOtranDebug = TRUE; +BOOLEAN TWOjacDebug = FALSE; + +/* CIDER Global Variable Declarations */ + +char *LogFileName = "cider.log"; /* This will go somewhere else */ + +int BandGapNarrowing; +int TempDepMobility, ConcDepMobility, FieldDepMobility, TransDepMobility; +int SurfaceMobility, MatchingMobility, MobDeriv; +int CCScattering; +int Srh, Auger, ConcDepLifetime, AvalancheGen; +int FreezeOut = FALSE; +int OneCarrier; + +int MaxIterations = 100; +int AcAnalysisMethod = DIRECT; + +double Temp, RelTemp, Vt; +double RefPsi;/* potential at Infinity */ +double EpsNorm, VNorm, NNorm, LNorm, TNorm, JNorm, GNorm, ENorm; + + /* end cider globals */ +#endif /* CIDER */ + struct variable *(*if_getparam)( ); @@ -225,6 +276,12 @@ int SIMinit(IFfrontEnd *frontEnd, IFsimulator **simulator) SIMinfo.analyses = (IFanalysis **)spice_analysis_ptr(); /* va: we recast, because we use * only the public part */ + +#ifdef CIDER +/* Evaluates limits of machine accuracy for CIDER */ + evalAccLimits(); +#endif /* CIDER */ + #endif /* SIMULATOR */ SPfrontEnd = frontEnd; diff --git a/src/maths/Makefile.am b/src/maths/Makefile.am index fbf0b1bd5..3b5c3aec2 100644 --- a/src/maths/Makefile.am +++ b/src/maths/Makefile.am @@ -1,4 +1,4 @@ # Process this file with automake -SUBDIRS = cmaths ni sparse poly deriv +SUBDIRS = cmaths ni sparse poly deriv misc MAINTAINERCLEANFILES = Makefile.in diff --git a/src/maths/cmaths/cmath1.c b/src/maths/cmaths/cmath1.c index a6bd1af86..b24738bcc 100644 --- a/src/maths/cmaths/cmath1.c +++ b/src/maths/cmaths/cmath1.c @@ -315,8 +315,8 @@ cx_exp(void *data, short int type, int length, int *newlength, short int *newtyp void * cx_sqrt(void *data, short int type, int length, int *newlength, short int *newtype) { - double *d; - complex *c; + double *d = NULL; + complex *c = NULL; double *dd = (double *) data; complex *cc = (complex *) data; int i, cres = (type == VF_REAL) ? 0 : 1; diff --git a/src/maths/cmaths/test_cx_ph.c b/src/maths/cmaths/test_cx_ph.c index 24c000e14..ce2f31d41 100644 --- a/src/maths/cmaths/test_cx_ph.c +++ b/src/maths/cmaths/test_cx_ph.c @@ -6,7 +6,6 @@ #include #include #include -#include #include "cmath.h" #include "cmath1.h" diff --git a/src/maths/ni/nidest.c b/src/maths/ni/nidest.c index 205e0a2ab..199ea24c4 100644 --- a/src/maths/ni/nidest.c +++ b/src/maths/ni/nidest.c @@ -10,7 +10,6 @@ Author: 1985 Thomas L. Quarles */ #include "ngspice.h" -#include #include "cktdefs.h" #include "nidest.h" @@ -20,7 +19,7 @@ NIdestroy(register CKTcircuit *ckt) { if (ckt->CKTmatrix) SMPdestroy(ckt->CKTmatrix); - ckt->CKTmatrix = 0; + ckt->CKTmatrix = NULL; if(ckt->CKTrhs) FREE(ckt->CKTrhs); if(ckt->CKTrhsOld) FREE(ckt->CKTrhsOld); if(ckt->CKTrhsSpare) FREE(ckt->CKTrhsSpare); diff --git a/src/maths/ni/nipred.h b/src/maths/ni/nipred.h index 96a23bf92..8c037d403 100644 --- a/src/maths/ni/nipred.h +++ b/src/maths/ni/nipred.h @@ -8,7 +8,7 @@ #ifdef PREDICTOR -intNIpred(register CKTcircuit * ckt); +int NIpred(register CKTcircuit * ckt); #endif /* PREDICTOR */ diff --git a/src/maths/ni/nireinit.c b/src/maths/ni/nireinit.c index f0a9e3f34..58d256144 100644 --- a/src/maths/ni/nireinit.c +++ b/src/maths/ni/nireinit.c @@ -11,7 +11,6 @@ Author: 1985 Thomas L. Quarles #include "ngspice.h" #include "cktdefs.h" -#include #include "smpdefs.h" #include "sperror.h" #include "nireinit.h" diff --git a/src/misc/misc_time.c b/src/misc/misc_time.c index 3913335dd..82df0fb80 100644 --- a/src/misc/misc_time.c +++ b/src/misc/misc_time.c @@ -8,7 +8,6 @@ Copyright 1990 Regents of the University of California. All rights reserved. #include #include "ngspice.h" -#include #include #include "misc_time.h" @@ -90,7 +89,10 @@ void timediff(struct timeb *now, struct timeb *begin, int *sec, int *msec) #endif #endif -/* How many seconds have elapsed in running time. */ +/* + * How many seconds have elapsed in running time. + * This is the routine called in IFseconds + */ double seconds(void) diff --git a/src/misc/string.c b/src/misc/string.c index 3c74d39b2..ebbbabd3e 100644 --- a/src/misc/string.c +++ b/src/misc/string.c @@ -131,6 +131,69 @@ strtolower(char *str) } } +#ifdef CIDER +/* + * Imported from cider file support/strmatch.c + * Original copyright notice: + * Author: 1991 David A. Gates, U. C. Berkeley CAD Group + * + */ + + +/* + * Case-insensitive test of whether p is a prefix of s and at least the + * first n characters are the same + */ + +int +cinprefix(p, s, n) +register char *p, *s; +register int n; +{ + if (!p || !s) return( 0 ); + + while (*p) { + if ((isupper(*p) ? tolower(*p) : *p) != (isupper(*s) ? tolower(*s) : *s)) + return( 0 ); + p++; + s++; + n--; + } + if (n > 0) + return( 0 ); + else + return( 1 ); + } + +/* + * Case-insensitive match of prefix string p against string s + * returns the number of matching characters + * + */ + + int +cimatch(p, s) +register char *p, *s; +{ + register int n = 0; + + if (!p || !s) return( 0 ); + + while (*p) { + if ((isupper(*p) ? tolower(*p) : *p) != (isupper(*s) ? tolower(*s) : *s)) + return( n ); + p++; + s++; + n++; + } + return( n ); + } + +#endif /* CIDER */ + + + + char * gettok(char **s) { diff --git a/src/misc/stringutil.h b/src/misc/stringutil.h index 759a1cd39..089979793 100644 --- a/src/misc/stringutil.h +++ b/src/misc/stringutil.h @@ -16,6 +16,13 @@ int ciprefix(register char *p, register char *s); void strtolower(char *str); char * gettok(char **s); +#ifdef CIDER +/* cider integration */ + +int cinprefix(register char *p, register char *s, register int n); +int cimatch(register char *p, register char *s); +#endif + #if !defined(HAVE_INDEX) && !defined(HAVE_STRCHR) char * index(register char *s, register char c); diff --git a/src/ngnutmeg.c b/src/ngnutmeg.c index 51b90b6df..9fc2ac152 100644 --- a/src/ngnutmeg.c +++ b/src/ngnutmeg.c @@ -23,7 +23,7 @@ Copyright 1990 Regents of the University of California. All rights reserved. #include "suffix.h" IFsimulator SIMinfo = { - "nutmeg", /* my name */ + "ngnutmeg", /* my name */ "data analysis and manipulation program", /* more about me */ Spice_Version, /* my version */ NULL, /* newCircuit function */ @@ -62,3 +62,12 @@ IFsimulator SIMinfo = { 0, NULL, }; + +#ifdef CIDER +/* An ugly hack */ +void +NDEVacct(void *ckt, FILE *file) +{ +fprintf(file, "Ouch, you have called NDEV from ngnutmeg\n"); +} +#endif diff --git a/src/ngspice.c b/src/ngspice.c index 628003d82..a80b5e803 100644 --- a/src/ngspice.c +++ b/src/ngspice.c @@ -13,8 +13,6 @@ Copyright 1990 Regents of the University of California. All rights reserved. #define CONFIG - -#include #include "devdefs.h" #include "noisedef.h" #include "suffix.h" diff --git a/src/spicelib/analysis/cktdltn.c b/src/spicelib/analysis/cktdltn.c index c76e2ff30..d1a7c2aef 100644 --- a/src/spicelib/analysis/cktdltn.c +++ b/src/spicelib/analysis/cktdltn.c @@ -6,7 +6,6 @@ Copyright 1992 Regents of the University of California. All rights reserved. */ #include "ngspice.h" -#include #include "cktdefs.h" #include "ifsim.h" #include "sperror.h" diff --git a/src/spicelib/analysis/cktdojob.c b/src/spicelib/analysis/cktdojob.c index 71e2857f4..29fb0f563 100644 --- a/src/spicelib/analysis/cktdojob.c +++ b/src/spicelib/analysis/cktdojob.c @@ -6,7 +6,6 @@ Modified: 2000 AlansFixes #include "ngspice.h" #include "cktdefs.h" -#include #include "sperror.h" #include "trandefs.h" diff --git a/src/spicelib/analysis/cktdump.c b/src/spicelib/analysis/cktdump.c index 3009428ac..c8c115c85 100644 --- a/src/spicelib/analysis/cktdump.c +++ b/src/spicelib/analysis/cktdump.c @@ -1,8 +1,16 @@ /********** Copyright 1990 Regents of the University of California. All rights reserved. -Author: 1985 Thomas L. Quarles +Author: 1985 Thomas L. Quarles, 1991 David A. Gates **********/ + /* +TODO: + Ngspice and cider integration note: + This file must be changed to be consistent with the ngspice interface. + The SPICEdev structure must be changed by adding a pointer to DEVdump + and DEVacct routines (as suggested below). + Paolo Nenzi Dec 2001 + No more sure about this notice (2003) */ /* CKTdump(ckt) @@ -10,20 +18,85 @@ Author: 1985 Thomas L. Quarles */ #include "ngspice.h" -#include #include "smpdefs.h" #include "cktdefs.h" +#ifdef CIDER +/* Begin cider integration */ +#include "gendefs.h" +#include "devdefs.h" + +extern SPICEdev **DEVices; +/* End cider integration */ +#endif void CKTdump(CKTcircuit *ckt, double ref, void *plot) { IFvalue refData; IFvalue valData; +#ifdef CIDER + int i; +#endif refData.rValue = ref; valData.v.numValue = ckt->CKTmaxEqNum-1; valData.v.vec.rVec = ckt->CKTrhsOld+1; (*(SPfrontEnd->OUTpData))(plot,&refData,&valData); + +#ifdef CIDER +/* + * Begin cider integration: + * This code has been hacked changing the SPICEdev structure. + * SPICEdev now has DEVdump and DEVacct as members. The + * following code works for any devices but as of this + * comment is written, only numerical devices have DEVdump + * and DEVacct routine (NUMD, NBJT, NUMD2, NBJT2, NUMOS). + */ + + for (i=0; iCKThead[i] != NULL) ){ + (*((*DEVices[i]).DEVdump))(ckt->CKThead[i],ckt); + } + } +/* End cider integration */ +#endif /* CIDER */ + +} + +#ifdef CIDER +/* + * Routine to dump statistics about numerical devices + * + * The following lines are historical: + * This is inefficient, because we have to look up the indices + * of the devices in the device table. Would be simpler if + * DEVices had an entry for an accounting function, so that indirection + * could be used. + * ------------------ + * The SPICEdev structure has been hacked and now has a DEVacct entry. + */ + +void +NDEVacct(CKTcircuit *ckt, FILE *file) +{ + int i; + + if ( !ckt->CKTisSetup ) { + return; + } + + for (i=0; iCKThead[i] != NULL) ){ + (*((*DEVices[i]).DEVacct))(ckt->CKThead[i],ckt, file); + } + } + return; } + +/* End cider integration */ +#endif /* CIDER */ + diff --git a/src/spicelib/analysis/cktload.c b/src/spicelib/analysis/cktload.c index e86bec724..62d34ca6d 100644 --- a/src/spicelib/analysis/cktload.c +++ b/src/spicelib/analysis/cktload.c @@ -13,7 +13,6 @@ Modified: 2000 AlansFixes */ #include "ngspice.h" -#include #include "smpdefs.h" #include "cktdefs.h" #include "devdefs.h" diff --git a/src/spicelib/analysis/cktmknod.c b/src/spicelib/analysis/cktmknod.c index ac916fab5..e763b968c 100644 --- a/src/spicelib/analysis/cktmknod.c +++ b/src/spicelib/analysis/cktmknod.c @@ -9,7 +9,6 @@ Author: 1985 Thomas L. Quarles */ #include "ngspice.h" -#include #include "ifsim.h" #include "iferrmsg.h" #include "smpdefs.h" diff --git a/src/spicelib/analysis/cktntask.c b/src/spicelib/analysis/cktntask.c index 8a06aed4a..5c5f077a1 100644 --- a/src/spicelib/analysis/cktntask.c +++ b/src/spicelib/analysis/cktntask.c @@ -7,7 +7,6 @@ Modified: 2000 AlansFixes */ #include "ngspice.h" -#include #include "tskdefs.h" #include "ifsim.h" #include "cktdefs.h" diff --git a/src/spicelib/analysis/cktpzstr.c b/src/spicelib/analysis/cktpzstr.c index e725b6a9b..a9e28094c 100644 --- a/src/spicelib/analysis/cktpzstr.c +++ b/src/spicelib/analysis/cktpzstr.c @@ -7,7 +7,6 @@ Copyright 1990 Regents of the University of California. All rights reserved. */ #include "ngspice.h" -#include #include "pzdefs.h" #include "complex.h" #include "cktdefs.h" diff --git a/src/spicelib/analysis/cktsens.c b/src/spicelib/analysis/cktsens.c index 2422231d7..d4c0b853c 100644 --- a/src/spicelib/analysis/cktsens.c +++ b/src/spicelib/analysis/cktsens.c @@ -221,8 +221,18 @@ int sens_sens(CKTcircuit *ckt, int restart) /* The unknown vector of node voltages overwrites rhs */ E = ckt->CKTrhs; iE = ckt->CKTirhs; - ckt->CKTrhsOld = E; - ckt->CKTirhsOld = iE; + + /* The following two lines assigned a pointer to another shadowing + * the previous definition and creating trouble when xfree() in + * NIdestroy tried to deallocate a non malloc'ed pointer + * + * Original code: + * ckt->CKTrhsOld = E; + * ckt->CKTirhsOld = iE; + */ + + *ckt->CKTrhsOld = *E; + *ckt->CKTirhsOld = *iE; Y = ckt->CKTmatrix; #ifdef ASDEBUG DEBUG(1) { diff --git a/src/spicelib/analysis/cktsetup.c b/src/spicelib/analysis/cktsetup.c index d5f05c021..0bb8478a8 100644 --- a/src/spicelib/analysis/cktsetup.c +++ b/src/spicelib/analysis/cktsetup.c @@ -10,7 +10,6 @@ Author: 1985 Thomas L. Quarles */ #include "ngspice.h" -#include #include "smpdefs.h" #include "cktdefs.h" #include "devdefs.h" diff --git a/src/spicelib/analysis/cktsgen.c b/src/spicelib/analysis/cktsgen.c index a208a559b..b8a228733 100644 --- a/src/spicelib/analysis/cktsgen.c +++ b/src/spicelib/analysis/cktsgen.c @@ -8,13 +8,18 @@ Copyright 1991 Regents of the University of California. All rights reserved. #include "cktdefs.h" #include "ifsim.h" #include "sensgen.h" -#include extern SPICEdev **DEVices; /* XXX */ extern char *Sfilter; +int set_model(sgen *); +int set_param(sgen *); +int set_inst(sgen *); +int set_dev(sgen *); +extern int sens_getp(sgen *, CKTcircuit *, IFvalue *); + sgen * sgen_init(CKTcircuit *ckt, int is_dc) { diff --git a/src/spicelib/analysis/cktsopt.c b/src/spicelib/analysis/cktsopt.c index 3a963bf53..64b6f5a4a 100644 --- a/src/spicelib/analysis/cktsopt.c +++ b/src/spicelib/analysis/cktsopt.c @@ -11,7 +11,6 @@ Modified: 2000 AlansFixes */ #include "ngspice.h" -#include #include "const.h" #include "optdefs.h" #include "tskdefs.h" diff --git a/src/spicelib/parser/inp2d.c b/src/spicelib/parser/inp2d.c index 393fc375e..41e02237f 100644 --- a/src/spicelib/parser/inp2d.c +++ b/src/spicelib/parser/inp2d.c @@ -1,6 +1,7 @@ /********** Copyright 1990 Regents of the University of California. All rights reserved. Author: 1988 Thomas L. Quarles +Modified: 2001 Paolo Nenzi (Cider Integration) **********/ #include "ngspice.h" @@ -50,7 +51,13 @@ void INP2D(void *ckt, INPtables * tab, card * current) INPinsert(&model, tab); current->error = INPgetMod(ckt, model, &thismodel, tab); if (thismodel != NULL) { - if (mytype != thismodel->INPmodType) { + if ((mytype != thismodel->INPmodType) + +#ifdef CIDER + && (thismodel->INPmodType != INPtypelook("NUMD")) + && (thismodel->INPmodType != INPtypelook("NUMD2")) +#endif + ){ LITERR("incorrect model type"); return; } @@ -71,7 +78,16 @@ void INP2D(void *ckt, INPtables * tab, card * current) IFC(bindNode, (ckt, fast, 2, node2)); PARSECALL((&line, ckt, type, fast, &leadval, &waslead, tab)); if (waslead) { + +#ifdef CIDER + if( type == INPtypelook("NUMD2") ) { + LITERR(" error: no unlabelled parameter permitted on NUMD2\n") + } else { +#endif ptemp.rValue = leadval; GCA(INPpName, ("area", &ptemp, ckt, type, fast)); } +#ifdef CIDER + } +#endif } diff --git a/src/spicelib/parser/inp2m.c b/src/spicelib/parser/inp2m.c index 64ae1fb9a..aab4aab96 100644 --- a/src/spicelib/parser/inp2m.c +++ b/src/spicelib/parser/inp2m.c @@ -1,6 +1,7 @@ /********** Copyright 1990 Regents of the University of California. All rights reserved. Author: 1988 Thomas L. Quarles +Modified: 2001 Paolo Nenzi (Cider Integration) **********/ #include "ngspice.h" @@ -89,13 +90,14 @@ INP2M (void *ckt, INPtables * tab, card * current) INPgetMod (ckt, model, &thismodel, tab); /* get pointer to the model */ if (thismodel != NULL) { - if ((thismodel->INPmodType != INPtypelook ("B3SOIPD")) && + if ((thismodel->INPmodType != INPtypelook ("B3SOI")) && + (thismodel->INPmodType != INPtypelook ("B3SOIPD")) && (thismodel->INPmodType != INPtypelook ("B3SOIFD")) && (thismodel->INPmodType != INPtypelook ("B3SOIDD")) ) { /* if model is not variable node B3SOIPD/FD/DD model, error! */ - LITERR ("only level 9-10 B3SOI(PD | FD | DD) can have 7 nodes") return; + LITERR ("only level 9, 29-31 B3SOI(PD | FD | DD) can have 7 nodes") return; } else { /* if looking at B3SOIPD/FD/DD model, allocate the 7th node */ @@ -113,14 +115,15 @@ INP2M (void *ckt, INPtables * tab, card * current) } else { /* 7th token is a model - only have 6 terminal device */ - if ((thismodel->INPmodType != INPtypelook ("B3SOIPD")) && + if ((thismodel->INPmodType != INPtypelook ("B3SOI")) && + (thismodel->INPmodType != INPtypelook ("B3SOIPD")) && (thismodel->INPmodType != INPtypelook ("B3SOIFD")) && (thismodel->INPmodType != INPtypelook ("B3SOIDD")) && (thismodel->INPmodType != INPtypelook ("SOI3")) ) { /* if model is not variable node B3SOIPD/FD/DD or STAG model, error! */ - LITERR ("only level 9-10 B3SOI(PD | FD | DD) and STAG (SOI3) can have 6 nodes") return; + LITERR ("only level 9, 29-31 B3SOI(PD | FD | DD) and STAG (SOI3) can have 6 nodes") return; } else { /* if looking at B3SOIPD/FD/DD or STAG (SOI3) model, allocate the 6th node */ @@ -132,14 +135,15 @@ INP2M (void *ckt, INPtables * tab, card * current) } else { /* 6th token is a model - only have 5 terminal device */ - if ((thismodel->INPmodType != INPtypelook ("B3SOIPD")) && + if ((thismodel->INPmodType != INPtypelook ("B3SOI")) && + (thismodel->INPmodType != INPtypelook ("B3SOIPD")) && (thismodel->INPmodType != INPtypelook ("B3SOIFD")) && (thismodel->INPmodType != INPtypelook ("B3SOIDD")) && (thismodel->INPmodType != INPtypelook ("SOI3")) ) { /* if model is not variable node B3SOIPD/FD/DD model, error! */ - LITERR ("only level 9-10 B3SOI(PD | FD | DD) and STAG (SOI3) can have 5 nodes") return; + LITERR ("only level 9, 29-31 B3SOI(PD | FD | DD) and STAG (SOI3) can have 5 nodes") return; } else { /* if looking at B3SOIPD/FD/DD or STAG (SOI3) model, allocate the 5th node */ @@ -171,16 +175,23 @@ INP2M (void *ckt, INPtables * tab, card * current) && thismodel->INPmodType != INPtypelook ("BSIM1") && thismodel->INPmodType != INPtypelook ("BSIM2") && thismodel->INPmodType != INPtypelook ("BSIM3") + && thismodel->INPmodType != INPtypelook ("B3SOI") && thismodel->INPmodType != INPtypelook ("B3SOIPD") && thismodel->INPmodType != INPtypelook ("B3SOIFD") && thismodel->INPmodType != INPtypelook ("B3SOIDD") && thismodel->INPmodType != INPtypelook ("BSIM4") - && thismodel->INPmodType != INPtypelook ("BSIM3V1") - && thismodel->INPmodType != INPtypelook ("BSIM3V2") + && thismodel->INPmodType != INPtypelook ("BSIM3v0") + && thismodel->INPmodType != INPtypelook ("BSIM3v1") + && thismodel->INPmodType != INPtypelook ("BSIM3v1S") + && thismodel->INPmodType != INPtypelook ("BSIM3v1A") && thismodel->INPmodType != INPtypelook ("SOI3") +#ifdef CIDER + && thismodel->INPmodType != INPtypelook ("NUMOS") +#endif #ifdef HAVE_EKV && thismodel->INPmodType != INPtypelook ("EKV") #endif + && thismodel->INPmodType != INPtypelook ("HiSIM1") ) { LITERR ("incorrect model type"); @@ -211,7 +222,8 @@ INP2M (void *ckt, INPtables * tab, card * current) IFC (bindNode, (ckt, fast, 3, node3)); IFC (bindNode, (ckt, fast, 4, node4)); /*use type not thismodel->INPmodType as it might not exist!*/ - if ((type == INPtypelook ("B3SOIPD")) || + if ((type == INPtypelook ("B3SOI")) || + (type == INPtypelook ("B3SOIPD")) || (type == INPtypelook ("B3SOIFD")) || (type == INPtypelook ("B3SOIDD")) || (type == INPtypelook ("SOI3"))) diff --git a/src/spicelib/parser/inp2q.c b/src/spicelib/parser/inp2q.c index ca72ad01c..28ad42e77 100644 --- a/src/spicelib/parser/inp2q.c +++ b/src/spicelib/parser/inp2q.c @@ -1,6 +1,7 @@ /********** Copyright 1990 Regents of the University of California. All rights reserved. Author: 1988 Thomas L. Quarles +Modified: 2001 Paolo Nenzi (Cider Integration) **********/ #include "ngspice.h" @@ -66,8 +67,13 @@ void INP2Q(void *ckt, INPtables * tab, card * current, void *gnode) INPinsert(&model, tab); current->error = INPgetMod(ckt, model, &thismodel, tab); if (thismodel != NULL) { - if(thismodel->INPmodType != INPtypelook("BJT") && - thismodel->INPmodType != INPtypelook("BJT2")) { + if((thismodel->INPmodType != INPtypelook("BJT")) + && (thismodel->INPmodType != INPtypelook("BJT2")) +#ifdef CIDER + && (thismodel->INPmodType != INPtypelook("NBJT")) + && (thismodel->INPmodType != INPtypelook("NBJT2")) +#endif + ) { LITERR("incorrect model type") return; } @@ -96,7 +102,15 @@ void INP2Q(void *ckt, INPtables * tab, card * current, void *gnode) IFC(bindNode, (ckt, fast, 4, node4)); PARSECALL((&line, ckt, type, fast, &leadval, &waslead, tab)); if (waslead) { +#ifdef CIDER + if( type == INPtypelook("NBJT2") ) { + LITERR(" error: no unlabelled parameter permitted on NBJT2\n") + } else { +#endif ptemp.rValue = leadval; GCA(INPpName, ("area", &ptemp, ckt, type, fast)); } +#ifdef CIDER + } +#endif } diff --git a/src/spicelib/parser/inpdomod.c b/src/spicelib/parser/inpdomod.c index 98d1694b9..c80812549 100644 --- a/src/spicelib/parser/inpdomod.c +++ b/src/spicelib/parser/inpdomod.c @@ -255,55 +255,71 @@ char *INPdomodel(void *ckt, card * image, INPtables * tab) case 9: type = INPtypelook("Mos9"); if(type < 0) { - err = INPmkTemp( - "Device type MOS9 not available in this binary\n"); + err = INPmkTemp + ("Device type MOS9 not available in this binary\n"); } break; case 10: - type = INPtypelook("B3SOIPD"); + type = INPtypelook("B3SOI"); if (type < 0) { err = INPmkTemp - ("Device type B3SOIPD not available in this binary\n"); + ("Device type B3SOI V3.0 not available in this binary\n"); } break; - case 11: - type = INPtypelook("B3SOIFD"); + case 14: + type = INPtypelook("BSIM4"); if (type < 0) { err = INPmkTemp - ("Device type B3SOIFD not available in this binary\n"); + ("Device type BSIM4 not available in this binary\n"); } break; - case 12: - type = INPtypelook("B3SOIDD"); + case 15: + type = INPtypelook("BSIM5"); if (type < 0) { err = INPmkTemp - ("Device type B3SOIDD not available in this binary\n"); + ("Device type BSIM5 not available in this binary\n"); } break; - case 14: - type = INPtypelook("BSIM4"); + case 16: + type = INPtypelook("BSIM6"); if (type < 0) { err = INPmkTemp - ("Device type BSIM4 not available in this binary\n");} + ("Device type BSIM6 not available in this binary\n");} break; - case 15: - type = INPtypelook("BSIM5"); + case 17: + type = INPtypelook("HiSIM1"); if (type < 0) { err = INPmkTemp - ("Placeholder: Device type BSIM5 not available in this binary\n"); + ("Placeholder: Device type HiSIM1 not available in this binary\n"); } break; - case 16: - type = INPtypelook("BSIM6"); + case 29: + type = INPtypelook("B3SOIPD"); + if (type < 0) { + err = + INPmkTemp + ("Placeholder: Device type B3SOIPD not available in this binary\n"); + } + break; + case 30: + type = INPtypelook("B3SOIFD"); + if (type < 0) { + err = + INPmkTemp + ("Placeholder: Device type B3SOIFD not available in this binary\n"); + } + break; + case 31: + type = INPtypelook("B3SOIDD"); if (type < 0) { err = INPmkTemp - ("Placeholder: Device type BSIM6 not available in this binary\n"); + ("Placeholder: Device type B3SOIDD not available in this binary\n"); } break; case 44: @@ -315,21 +331,37 @@ char *INPdomodel(void *ckt, card * image, INPtables * tab) } break; case 49: - type = INPtypelook("BSIM3V1"); + type = INPtypelook("BSIM3v1S"); if (type < 0) { err = INPmkTemp - ("Device type BSIM3V1 not available in this binary\n"); + ("Device type BSIM3v1S not available in this binary\n"); } break; case 50: - type = INPtypelook("BSIM3V2"); + type = INPtypelook("BSIM3v1"); + if (type < 0) { + err = + INPmkTemp + ("Device type BSIM3v1 not available in this binary\n"); + } + break; + case 51: + type = INPtypelook("BSIM3v1A"); if (type < 0) { err = INPmkTemp - ("Device type BSIM3V2 not available in this binary\n"); + ("Device type BSIM3v1A not available in this binary\n"); } break; + case 52: + type = INPtypelook("BSIM3v0"); + if (type < 0) { + err = + INPmkTemp + ("Device type BSIM3v0 not available in this binary\n"); + } + break; case 60: type = INPtypelook("SOI"); if (type < 0) { @@ -468,6 +500,62 @@ char *INPdomodel(void *ckt, card * image, INPtables * tab) INPmakeMod(modname, type, image); } +#ifdef CIDER + else if(strcmp(typename,"numd") == 0) { + err = INPfindLev(line,&lev); + switch( lev ) { + case 1: + default: + type = INPtypelook("NUMD"); + if(type < 0) { + err = + INPmkTemp + ("Device type NUMD not available in this binary\n"); + } + break; + case 2: + type = INPtypelook("NUMD2"); + if(type < 0) { + err = + INPmkTemp + ("Device type NUMD2 not available in this binary\n"); + } + break; + } + INPmakeMod(modname,type,image); + } else if(strcmp(typename,"nbjt") == 0) { + err = INPfindLev(line,&lev); + switch( lev ) { + case 1: + default: + type = INPtypelook("NBJT"); + if(type < 0) { + err = + INPmkTemp + ("Device type NBJT not available in this binary\n"); + } + break; + case 2: + type = INPtypelook("NBJT2"); + if(type < 0) { + err = + INPmkTemp + ("Device type NBJT2 not available in this binary\n"); + } + break; + } + INPmakeMod(modname,type,image); + } else if(strcmp(typename,"numos") == 0) { + type = INPtypelook("NUMOS"); + if(type < 0) { + err = + INPmkTemp + ("Device type NUMOS not available in this binary\n"); + } + INPmakeMod(modname,type,image); + } +#endif /* CIDER */ + /* type poly added by SDB . . . */ #ifdef XSPICE /* -------- Check if model is a poly (specific to xspice) --------- */ diff --git a/src/spicelib/parser/inpgmod.c b/src/spicelib/parser/inpgmod.c index 0a52a28c7..6bd3c3ab8 100644 --- a/src/spicelib/parser/inpgmod.c +++ b/src/spicelib/parser/inpgmod.c @@ -1,6 +1,7 @@ /********** Copyright 1990 Regents of the University of California. All rights reserved. -Author: 1985 Thomas L. Quarles +Author: 1985 Thomas L. Quarles, 1991 David A. Gates +Modified: 2001 Paolo Nenzi (Cider Integration) **********/ #include "ngspice.h" @@ -11,6 +12,21 @@ Author: 1985 Thomas L. Quarles #include "fteext.h" #include "inp.h" +#ifdef CIDER +/* begin Cider Integration */ +#include "numcards.h" +#include "carddefs.h" +#include "numgen.h" +#include "suffix.h" + +extern IFcardInfo *INPcardTab[]; +extern int INPnumCards; +#define E_MISSING -1 +#define E_AMBIGUOUS -2 + +/* end Cider Integration */ +#endif /* CIDER */ + extern INPmodel *modtab; char *INPgetMod(void *ckt, char *name, INPmodel ** model, INPtables * tab) @@ -65,6 +81,21 @@ char *INPgetMod(void *ckt, char *name, INPmodel ** model, INPtables * tab) if (error) return (INPerror(error)); /* parameter isolation, identification, binding */ + +#ifdef CIDER + /* begin cider integration */ + /* Handle Numerical Models Differently */ + if ( ((modtmp)->INPmodType == INPtypelook("NUMD")) || + ((modtmp)->INPmodType == INPtypelook("NBJT")) || + ((modtmp)->INPmodType == INPtypelook("NUMD2")) || + ((modtmp)->INPmodType == INPtypelook("NBJT2")) || + ((modtmp)->INPmodType == INPtypelook("NUMOS")) ) { + error = INPparseNumMod( ckt, modtmp, tab, &err ); + if (error) return(INPerror(error)); + } else { + /* It's an analytical model */ +#endif /* CIDER */ + line = ((modtmp)->INPmodLine)->line; #ifdef TRACE @@ -121,6 +152,9 @@ char *INPgetMod(void *ckt, char *name, INPmodel ** model, INPtables * tab) } FREE(parm); } +#ifdef CIDER + } /* analytical vs. numerical model parsing */ +#endif (modtmp)->INPmodUsed = 1; (modtmp)->INPmodLine->error = err; } @@ -142,3 +176,240 @@ char *INPgetMod(void *ckt, char *name, INPmodel ** model, INPtables * tab) return (err); } + +#ifdef CIDER +/* + * Parse a numerical model by running through the list of original + * input cards which make up the model + * Given: + * 1. First card looks like: .model modname modtype + * 2. Other cards look like: +? where ? tells us what + * to do with the next card: + * '#$*' = comment card + * '+' = continue previous card + * other = new card + */ +int +INPparseNumMod( ckt, model, tab, errMessage ) + void* ckt; + INPmodel *model; + INPtables *tab; + char **errMessage; +{ + card *txtCard; /* Text description of a card */ + GENcard *tmpCard; /* Processed description of a card */ + IFcardInfo *info; /* Info about the type of card located */ + char *line; + char *cardName = NULL; /* name of a card */ + char *parm; /* name of a parameter */ + int cardType; /* type/index for the current card */ + int cardNum = 0; /* number of this card in the overall line */ + int lastType = E_MISSING; /* type of previous card */ + char *err = NULL, *tmp; /* Strings for error messages */ + IFvalue *value; + int error, idx, invert; + + /* Chase down to the top of the list of actual cards */ + txtCard = model->INPmodLine->actualLine; + + /* Skip the first card if it exists since there's nothing interesting */ + /* txtCard will be empty if the numerical model is empty */ + if (txtCard) txtCard = txtCard->nextcard; + + /* Now parse each remaining card */ + while (txtCard) { + line = txtCard->line; + cardType = E_MISSING; + cardNum++; + + /* Skip the initial '+' and any whitespace. */ + line++; + while (*line == ' ' || *line == '\t') + line++; + + switch (*line) { + case '*': + case '$': + case '#': + case '\0': + case '\n': + /* comment or empty cards */ + lastType = E_MISSING; + break; + case '+': + /* continuation card */ + if (lastType >= 0) { + cardType = lastType; + while (*line == '+') line++; /* Skip leading '+'s */ + } else { + tmp = (char *)xmalloc((55)*sizeof(char)); + (void) sprintf(tmp, + "Error on card %d : illegal continuation \'+\' - ignored", + cardNum); + err = INPerrCat(err,tmp); + lastType = E_MISSING; + break; + } + /* FALL THRU when continuing a card */ + default: + if (cardType == E_MISSING) { + /* new command card */ + if (cardName) FREE(cardName); /* get rid of old card name */ + INPgetTok(&line,&cardName,1); /* get new card name */ + if (*cardName) { /* Found a name? */ + cardType = INPfindCard(cardName,INPcardTab,INPnumCards); + if (cardType >= 0) { + /* Add card structure to model */ + info = INPcardTab[cardType]; + error = (*(info->newCard))( (void *)&tmpCard, + model->INPmodfast ); + if (error) return(error); + /* Handle parameter-less cards */ + } else if (cinprefix( cardName, "title", 3 ) ) { + /* Do nothing */ + } else if (cinprefix( cardName, "comment", 3 ) ) { + /* Do nothing */ + } else if (cinprefix( cardName, "end", 3 ) ) { + /* Terminate parsing */ + txtCard = ((card *) 0); + cardType = E_MISSING; + } else { + /* Error */ + tmp =(char *)xmalloc((55+strlen(cardName))*sizeof(char)); + (void) sprintf(tmp, + "Error on card %d : unrecognized name (%s) - ignored", + cardNum, cardName ); + err = INPerrCat(err,tmp); + } + } + } + if (cardType >= 0) { /* parse the rest of this line */ + while (*line) { + /* Strip leading carat from booleans */ + if (*line == '^') { + invert = TRUE; + *line++; /* Skip the '^' */ + } else { + invert = FALSE; + } + INPgetTok(&line,&parm,1); + if (!*parm) + break; + idx = INPfindParm(parm, info->cardParms, info->numParms); + if (idx == E_MISSING) { + /* parm not found */ + tmp = (char *)xmalloc((60+strlen(parm)) * sizeof(char)); + (void)sprintf(tmp, + "Error on card %d : unrecognized parameter (%s) - ignored", + cardNum, parm); + err = INPerrCat(err, tmp); + } else if (idx == E_AMBIGUOUS) { + /* parm ambiguous */ + tmp = (char *)xmalloc((58+strlen(parm)) * sizeof(char)); + (void)sprintf(tmp, + "Error on card %d : ambiguous parameter (%s) - ignored", + cardNum, parm); + err = INPerrCat(err, tmp); + } else { + value = INPgetValue( ckt, &line, + ((info->cardParms)[idx]).dataType, tab ); + if (invert) { /* invert if it's a boolean entry */ + if (((((info->cardParms)[idx]).dataType)&IF_VARTYPES) + == IF_FLAG) { + value->iValue = 0; + } else { + tmp =(char *)xmalloc((63+strlen(parm))*sizeof(char)); + (void)sprintf(tmp, + "Error on card %d : non-boolean parameter (%s) - \'^\' ignored", + cardNum, parm); + err = INPerrCat(err, tmp); + } + } + error = (*(info->setCardParm))( + ((info->cardParms)[idx]).id, value, tmpCard ); + if (error) return(error); + } + FREE(parm); + } + } + lastType = cardType; + break; + } + if (txtCard) txtCard = txtCard->nextcard; + } + *errMessage = err; + return( 0 ); +} + +/* + * Locate the best match to a card name in an IFcardInfo table + */ +int +INPfindCard( name, table, numCards ) + char *name; + IFcardInfo *table[]; + int numCards; +{ + int test; + int match, bestMatch; + int best; + int length; + + length = strlen(name); + + /* compare all the names in the card table to this name */ + best = E_MISSING; + bestMatch = 0; + for ( test = 0; test < numCards; test++ ) { + match = cimatch( name, table[test]->name ); + if ((match == bestMatch ) && (match > 0)){ + best = E_AMBIGUOUS; + } else if ((match > bestMatch) && (match == length)) { + best = test; + bestMatch = match; + } + } + return(best); +} + +/* + * Locate the best match to a parameter name in an IFparm table + */ +int +INPfindParm( name, table, numParms ) + char *name; + IFparm *table; + int numParms; +{ + int test, best; + int match, bestMatch; + int id, bestId; + int length; + + length = strlen(name); + + /* compare all the names in the parameter table to this name */ + best = E_MISSING; + bestId = -1; + bestMatch = 0; + for ( test = 0; test < numParms; test++ ) { + match = cimatch( name, table[test].keyword ); + if ( (match == length) && (match == strlen(table[test].keyword)) ) { + /* exact match */ + best = test; + /* all done */ + break; + } + id = table[test].id; + if ((match == bestMatch) && (match > 0) && (id != bestId)) { + best = E_AMBIGUOUS; + } else if ((match > bestMatch) && (match == length)) { + bestMatch = match; + bestId = id; + best = test; + } + } + return(best); +} + +#endif /* CIDER */