diff --git a/ChangeLog b/ChangeLog index 6a4ad9a00..9baca46b5 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,28 @@ +2006-08-31 Stefan Jones + + * configure.in: + Version 0.2.19 + + * configure.in + src/Makefile.am + src/frontend/Makefile.am + src/frontend/numparam/{.cvsignore,Makefile.am,downgrad.txt,general.h, + mystring.c,ngconfig.sh,numpaif.h,numparam.h,nupatest.c,readme.txt, + spicenum.c,washprog.c,xpressn.c} : + numparam port from ngspice + + * src/frontend/subckt.h src/include/fteext.h: + gcc-4 compile fixes + + * src/spicelib/analysis/dctran.c: + Stop printing initial DC solution if over 30 nodes + + * src/spicelib/devices/bsim4/{.cvsignore,B4TERMS_OF_USE,Makefile.am, + b4.c,b4acld.c,b4ask.c,b4check.c,b4cvtest.c,b4del.c,b4dest.c,b4geo.c, + b4getic.c,b4ld.c,b4mask.c,b4mdel.c,b4mpar.c,b4noi.c,b4par.c,b4pzld.c, + b4set.c,b4temp.c,b4trunc.c,bsim4def.h,bsim4ext.h,bsim4init.c,bsim4itf.h}: + Bsim4 update from ngspice + 2005-07-22 Stefan Jones * Changelog: diff --git a/configure.in b/configure.in index 6c003e04b..25534ed0d 100644 --- a/configure.in +++ b/configure.in @@ -5,7 +5,7 @@ dnl Create a configuration header AM_CONFIG_HEADER(config.h) dnl Initialize automake stuff -AM_INIT_AUTOMAKE(tclspice,0.2.18) +AM_INIT_AUTOMAKE(tclspice,0.2.19) dnl --enable-ftedebug : enable frontend debug macros AC_ARG_ENABLE(ftedebug, @@ -68,6 +68,10 @@ dnl exclude readline libs by saying --with-readline=no at configure time. AC_ARG_WITH(readline, [ --with-readline[=yes/no] Enable GNU readline support for CLI. Default=yes.]) +dnl --enable-numparams: define NUMPARAMS in the code. This is for .param support +AC_ARG_ENABLE(numparam, + [ --enable-numparam Enable numparams library support, experimental *not in standard distribution*]) + dnl Enable maintainer commands only if requested AM_MAINTAINER_MODE @@ -435,6 +439,18 @@ if test "$enable_cluster" = "yes"; then LIBS="$LIBS -lpthread" fi +if test "$enable_numparam" = "yes"; then + AC_MSG_RESULT(Numparam library is enabled) + AC_DEFINE(NUMPARAMS) + NUMPARAMDIR="numparam" + NUMPARAMLIB="frontend/numparam/libnumparam.a" +else + NUMPARAMDIR="" + NUMPARAMLIB="" +fi +AC_SUBST(NUMPARAMDIR) +AC_SUBST(NUMPARAMLIB) + dnl ---- Option to include GNU readline support in ngspice CLI ---- if test "$with_readline" != "no" -a \ \( "x$with_tcl" == "x" -o "$with_tcl" == "no" \) ; then @@ -503,6 +519,7 @@ src/spicelib/devices/vcvs/Makefile \ src/spicelib/devices/vsrc/Makefile \ src/spicelib/parser/Makefile \ src/frontend/Makefile \ +src/frontend/numparam/Makefile \ src/frontend/help/Makefile \ src/frontend/parser/Makefile \ src/frontend/plotting/Makefile \ diff --git a/src/Makefile.am b/src/Makefile.am index 7bbd1866b..751eb80a6 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -77,6 +77,7 @@ ngspice_LDADD = \ spicelib/devices/libdev.a \ @XSPICELIB2@ \ frontend/parser/libparser.a \ + @NUMPARAMLIB@ \ frontend/help/libhlp.a \ spicelib/parser/libinp.a \ maths/deriv/libderiv.a \ @@ -101,6 +102,7 @@ ngnutmeg_LDADD = \ frontend/libfte.a \ frontend/plotting/libplotting.a \ frontend/parser/libparser.a \ + @NUMPARAMLIB@ \ frontend/help/libhlp.a \ maths/cmaths/libcmaths.a \ maths/poly/libpoly.a \ diff --git a/src/frontend/Makefile.am b/src/frontend/Makefile.am index 62e4ef85b..f6bf66bab 100644 --- a/src/frontend/Makefile.am +++ b/src/frontend/Makefile.am @@ -1,6 +1,6 @@ ## Process this file with automake to produce Makefile.in -SUBDIRS = plotting help parser +SUBDIRS = plotting help parser @NUMPARAMDIR@ noinst_LIBRARIES = libfte.a diff --git a/src/frontend/numparam/.cvsignore b/src/frontend/numparam/.cvsignore new file mode 100644 index 000000000..e440fafda --- /dev/null +++ b/src/frontend/numparam/.cvsignore @@ -0,0 +1,3 @@ +Makefile.in +Makefile +.deps diff --git a/src/frontend/numparam/Makefile.am b/src/frontend/numparam/Makefile.am new file mode 100644 index 000000000..f20a62bb0 --- /dev/null +++ b/src/frontend/numparam/Makefile.am @@ -0,0 +1,16 @@ +## Process this file with automake to produce Makefile.in + +EXTRA_DIST = downgrad.txt ngconfig.sh readme.txt nupatest.c washprog.c + +noinst_LIBRARIES = libnumparam.a + +libnumparam_a_SOURCES = \ + spicenum.c \ + xpressn.c \ + mystring.c \ + general.h \ + numpaif.h \ + numparam.h + +INCLUDES = -I$(top_srcdir)/src/include +MAINTAINERCLEANFILES = Makefile.in diff --git a/src/frontend/numparam/downgrad.txt b/src/frontend/numparam/downgrad.txt new file mode 100644 index 000000000..24b13b8bb --- /dev/null +++ b/src/frontend/numparam/downgrad.txt @@ -0,0 +1,89 @@ +! downgrad.txt, Use with 'washprog.c' +! opcodes: x=exclusion, m=macro, w=wordsubst s= general subst +! Macros to keep: Cconst Hi Lo Str Strbig Use ...? + +w Proc void +w Begin { +w EndProc ;} +w Func "" +w EndFunc ;} +w If "if (" +w Then ") {" +w Else ";} else {" +w ElsIf ";} else if (" +w EndIf ;} +w While "while (" +w Do ") {" +w Done ;} +w Repeat "do {" +w Until ";} while ( !(" +w EndRep )); +w For "for (" +w Switch "switch (" +w CaseOne ") { case" +w Case "; break; } case" +w AndCase ":; case" +w Is :{ +w Default "; break;} default: {" +w EndSw ";break;} }" + +m Const(1,2) "const short 1 = 2;" + +m Record(1) "typedef struct _t1 {" +m RecPtr(1) "typedef struct _t1 *" +m EndRec(1) "} 1;" +m Addr(1) &1 + +w False 0 +w True 1 +w Not ! +w And && +w Or || +w Div / +w Mod % + +w Shl << +w Shr >> +w AND & +w OR | +w XOR \^ +w NOT ~ +w AT * + +m Inc(1) 1++ +m Dec(1) 1-- +w Null NULL +w Void void +m Table(1) "[1]= {" +w EndTab }; + +m chr(1) (char)(1) +m Zero(1) (!(1)) +m NotZ(1) (1) + +w Pointer "void *" +w Pfile "FILE *" + +w Char "unsigned char" +w Byte "unsigned char" +w Bool "unsigned char" +w Word "unsigned short" +w Pchar "char *" + +w Intern static +w Extern extern +m Tarray(1,2,3) "typedef 2 1[3];" +m Tarray\2(1,2,3,4) "typedef 2 1[3][4];" +m Darray(1,2,3) "2 1[3];" + +!m Cconst(1,2) "typedef enum {1 = 2} _n1;" +!m Str(1,2) "char 2[1+03]={00,00,(char)1}" +!m Strbig(1,2) "char 2[1+04]={00, (char)Hi(1), (char)Lo(1)}" + +w Aconst(1,2,3) "2 1[3] ={" +w EndAco "};" +m Sini(1) "sini(1,sizeof(1)-04)" +m New(1) "(1 *)new(sizeof(1))" +m Dispose(1) "dispose((void *)1)" +m NewArr(1,2) "(1 *)new(sizeof(1)*2)" + diff --git a/src/frontend/numparam/general.h b/src/frontend/numparam/general.h new file mode 100644 index 000000000..fcf033dc1 --- /dev/null +++ b/src/frontend/numparam/general.h @@ -0,0 +1,211 @@ +/* general.h */ + +/*** Part 1: the C language redefined for quiche eaters **** + * + * Real Hackers: undo all these macros with the 'washprog.c' utility ! + */ + + /* Proc ...... Begin .... EndProc */ +#define Proc void +#define Begin { +#define EndProc ;} + /* Func short ...(...) Begin...EndFunc */ +#define Func +#define EndFunc ;} + /* If ... Then...ElsIf..Then...Else...EndIf */ +#define If if( +#define Then ){ +#define Else ;}else{ +#define ElsIf ;}else if( +#define EndIf ;} + /* While...Do...Done */ +#define While while( +#define Do ){ +#define Done ;} + /* Repeat...Until...EndRep */ +#define Repeat do{ +#define Until ;}while(!( +#define EndRep )); + /* For i=1;i<=10; Inc(i) Do...Done */ +#define For for( + /* Switch...CaseOne...Is...Case..Is...Default...EndSw */ +#define Switch switch( +#define CaseOne ){ case +#define Case ;break;}case +#define AndCase :; case +#define Is :{ +#define Default ;break;}default:{ +#define EndSw ;break;}} + +#define Record(x) typedef struct _t ## x { +#define RecPtr(x) typedef struct _t ## x * +#define EndRec(x) } x; +#define Addr(x) &x + +#define False 0 +#define True 1 +#define Not ! +#define And && +#define Or || +#define Div / +#define Mod % + +#define Shl << +#define Shr >> +#define AND & +#define OR | +#define XOR ^ +#define NOT ~ +#define AT * + +#define Inc(p) (p)++ +#define Dec(p) (p)-- + +/* see screened versions below: +#define New(t) (t*)malloc(sizeof(t)) +#define Dispose(p) free((void*)p) +*/ + +#ifdef NULL +#define Null NULL +#else +#define Null (void *)0L +#endif + +#define chr(x) (char)(x) +#define Zero(x) (!(x)) +#define NotZ(x) (x) + +typedef void* Pointer; +#define Type(a,b) typedef b a; + +#ifdef _STDIO_H /* somebody pulled stdio */ +Type(Pfile, FILE AT) +#else +#ifdef __STDIO_H /* Turbo C */ + Type(Pfile, FILE AT) +#else + Type(Pfile, FILE*) /* sjb - was Pointer, now FILE* */ +#endif +#endif + +Type(Char, unsigned char) +Type(Byte, unsigned char) +#ifndef Bool +Type(Bool, unsigned char) +#endif +Type(Word, unsigned short) +Type(Pchar, char AT) + +#define Intern static +#define Extern extern +#define Tarray(a,d,n) typedef d a[n]; +#define Tarray2(a,d,n,m) typedef d a[n][m]; +#define Darray(a,d,n) d a[n]; + +#define Const(x,y) const short x=y; +#define Cconst(x,y) typedef enum {x=y} _n ## x; + +#define Aconst(a,tp,sze) tp a[sze] ={ +#define EndAco }; + +/* the following require the 'mystring' mini-library */ + +#define Mcopy(a,b) rawcopy((Pchar)a, (Pchar)b, sizeof(a),sizeof(b)) +#define Rcopy(a,b) rawcopy((Pchar)(&a), (Pchar)(&b), sizeof(&a),sizeof(&b)) +#define New(tp) (tp *)new(sizeof(tp)) +#define Dispose(p) dispose((void *)p) +#define NewArr(t,n) (t *)new(sizeof(t)*n) + + +/*** Part 2: common 'foolproof' string library ******/ +/* + include beforehand the following: +#include // NULL FILE fopen feof fgets fclose fputs fputc gets +#include + the function code is in 'mystring.c' . +*/ + +#define Use(x) x=0;x=x +#define Uses(s) s=s +#define Usep(x) x=x +#define Hi(x) (((x) Shr 8) AND 0xff) +#define Lo(x) ((x) AND 0xff) + +#define Strbig(n,a) char a[n+4]={0, (char)Hi(n), (char)Lo(n)} +#define Str(n,a) char a[n+3]={0,0,(char)n} /* n<255 ! */ +#define Sini(s) sini(s,sizeof(s)-4) + +Cconst(Maxstr,2004) /* was 255, string maxlen, may be up to 32000 or so */ + +typedef char string[258]; + +Cconst(Esc, 27) +Cconst(Tab, 9) +Cconst(Bs, 8) +Cconst(Lf, 10) +Cconst(Cr, 13) + +Proc sini( Pchar s, short i); +Proc sfix(Pchar s, short i, short max); +Func short maxlen(Pchar s); +Func Pchar pscopy( Pchar s, Pchar a, short i,short j); +Func Bool scopy( Pchar a, Pchar b); +Func Bool ccopy( Pchar a, char c); +Func Bool sadd( Pchar s, Pchar t); +Func Bool nadd( Pchar s, long n); +Func Bool cadd( Pchar s, char c); +Func Bool sins( Pchar s, Pchar t); +Func Bool cins( Pchar s, char c); +Func short cpos( char c, Pchar s); +Func short spos( Pchar sub, Pchar s); + +Func short length(Pchar s); +Func Bool steq(Pchar s, Pchar t); +Func Bool stne(Pchar s, Pchar t); +Func short scompare(Pchar a, Pchar b); +Func short ord(char c); +Func short pred(short i); +Func short succ(short i); +Proc stri(long n, Pchar s); +Proc strif(long n, short f, Pchar s); +Proc strf(double x, short a, short b, Pchar s); /* float -> string */ +Func long ival(Pchar s, short *err); +Func double rval(Pchar s, short *err); + +Func char upcase(char c); +Func char lowcase(char c); +Func short hi(long w); +Func short lo(long w); +Func Bool odd(long x); +Func Bool alfa(char c); +Func Bool num(char c); +Func Bool alfanum(char c); +Func Pchar stupcase( Pchar s); + +/***** primitive input-output ***/ +Proc wc(char c); +Proc wln(void); +Proc ws( Pchar s); +Proc wi(long i); +Proc rs( Pchar s); +Func char rc(void); + +Func short freadstr(Pfile f, Pchar s, short max); +Func char freadc(Pfile f); +Func long freadi(Pfile f); + +Func long np_round(double d); /* sjb to avoid clash with round() in math.h */ +Func long np_trunc(double x); /* sjb to avoid clash with trunc() in math.h */ +Func double sqr(double x); +Func double absf(double x); /* abs */ +Func long absi( long i); +Func double frac(double x); + +Func Bool reset(Pfile f); +Func Bool rewrite(Pfile f); +Proc rawcopy(Pointer a, Pointer b, short la, short lb); +Func Pointer new(long sz); +Proc dispose(Pointer p); +Func Pchar newstring(short n); + diff --git a/src/frontend/numparam/mystring.c b/src/frontend/numparam/mystring.c new file mode 100644 index 000000000..cde0eaf67 --- /dev/null +++ b/src/frontend/numparam/mystring.c @@ -0,0 +1,886 @@ +/* mystring.c Copyright (C) 2002 Georg Post + * + * This file is part of Numparam, see: readme.txt + * Free software under the terms of the GNU Lesser General Public License + * $Id$ + */ + +#ifdef __TURBOC__ +extern unsigned _stklen= 32000; /* Turbo C default was only 4 K */ +#endif + +#include +#include +/* #include -- ceil floor */ +#include "config.h" +#ifdef HAS_WINDOWS +#include "wstdio.h" +#endif + +#include "general.h" + +#define Getmax(s,ls) (((Byte)(s[ls+1])) Shl 8) + (Byte)(s[ls+2]) + +/***** primitive input-output ***/ + +Proc wc(char c) +Begin + fputc(c, stdout) +EndProc + +Proc wln(void) +Begin wc('\n') EndProc + +Proc ws( Pchar s) +Begin + short k=0; + While s[k] !=0 Do + wc(s[k]); Inc(k) + Done +EndProc + +Proc wi(long i) +Begin + Str(16,s); + nadd(s,i); + ws(s) +EndProc + +Proc rs( Pchar s) +Begin /*basic line input, limit= 80 chars */ + short max,i; + char c; + max=maxlen(s); + i=0; sini(s,max); + If max>80 Then max=80 EndIf + Repeat + c=fgetc(stdin); + If (i=' ') Then + cadd(s,c); Inc(i) + EndIf + Until (c==Cr) Or (c=='\n') EndRep + /* return i */ +EndFunc + +Func char rc(void) +Begin + short ls; + Str(80,s); + rs(s); ls=length(s); + If ls>0 Then + return s[ls-1] + Else + return 0 + EndIf +EndProc + +/******* Strings ************ + * are 0-terminated char arrays with a 2-byte trailer: max length. + * the string mini-library is "overflow-safe" under these conditions: + * use Str(n,s) macro: define and initialize a string s of maxlen n<255 + * use sini() to initialize empty strings; sfix() for non-empty ones. + * the Sini() macro does automatic sizing, for automatic char arrays + * to allocate a string on the heap, use newstring(n). + * use maxlen() and length() to retrieve string max and actual length + * use: cadd, cins, sadd, sins, scopy, pscopy to manipulate them + * never put '\x0' characters inside strings ! + * + * the 'killer idea' is the following: + * on string overflow and/or on heap allocation failure, a program + * MUST die. + */ + +Intern +Proc stringbug(Pchar op, Pchar s, Pchar t, char c) +/* we brutally stop the program on string overflow */ +Begin + char rep=' '; + ws(" STRING overflow "); + ws(op); wln(); + ws(" Operand1: "); + ws(s); wln(); + If t != Null Then + ws(" Operand2: "); + ws(t); wln(); + EndIf + If c != 0 Then + wc('{'); wc(c); wc('}') + EndIf + ws(" [A]bort [I]gnore ? "); + rep=rc(); + If upcase(rep)=='A' Then exit(1) EndIf +EndProc + +Proc sini(Pchar s, short max) /* suppose s is allocated */ +Begin + If max<1 Then + max=1 + ElsIf max>Maxstr Then + max=Maxstr + EndIf + s[0]=0; + s[1]= Hi(max); s[2]= Lo(max); +EndProc + +Proc sfix(Pchar s, short i, short max) +/* suppose s is allocated and filled with non-zero stuff */ +Begin + short j; + If max<1 Then + max=1 + ElsIf max>Maxstr Then + max=Maxstr + EndIf + If i>max Then + i=max + ElsIf i<0 Then + i=0 + EndIf + s[i]=0; + s[i+1]= Hi(max); s[i+2]= Lo(max); + For j=0;jMaxstr Then + max=Maxstr + EndIf + s[i+1]= Hi(max); s[i+2]= Lo(max); +EndProc + +Func short length(Pchar s) +Begin + short lg=0; + While NotZ(s[lg]) Do Inc(lg) Done + return lg +EndFunc + +Func short maxlen(Pchar s) +Begin + short ls= length(s); + return Getmax(s,ls) +EndFunc + +Func Bool sadd( Pchar s, Pchar t) +Begin + Bool ok; + short i=0, max, ls= length(s); + max= Getmax(s,ls); + While (t[i] !=0) And (ls=0; Dec(i) Do s[i+1]=s[i] Done; + s[0]=c; + EndIf + If Not ok Then + stringbug("cins",s, Null,c) + EndIf + return ok +EndProc + +Func Bool sins( Pchar s, Pchar t) +Begin + short i, max, ls= length(s), lt=length(t); + Bool ok; + max= Getmax(s,ls); + ok= ((ls+lt) < max); + If ok Then + For i=ls+2; i>=0; Dec(i) Do s[i+lt]=s[i] Done; + For i=0; i='a')And(c<='z') Then + return c+'A'-'a' + Else + return c + EndIf +EndFunc + +Func Bool scopy(Pchar s, Pchar t) /* returns success flag */ +Begin + Bool ok; + short i,max, ls= length(s); + max= Getmax(s,ls); + i=0; + While (t[i] !=0) And (i0 Then + s[0]=c; sfix(s,1,max); + ok=True + EndIf + If Not ok Then + stringbug("ccopy",s, Null,c) + EndIf + return ok +EndProc + +Func Pchar pscopy(Pchar s, Pchar t, short start, short leng) +/* partial string copy, with Turbo Pascal convention for "start" */ +/* BUG: position count starts at 1, not 0 ! */ +Begin + short max= maxlen(s); /* keep it for later */ + short stop= length(t); + short i; + Bool ok= (max>=0) And (max<=Maxstr); + If Not ok Then + stringbug("copy target non-init", s, t, 0) + EndIf + If leng>max Then + leng=max; ok=False + EndIf + If start>stop Then /* nothing! */ + ok=False; + inistring(s,0,max) + Else + If (start+leng-1)>stop Then + leng = stop-start+1; + ok=False + EndIf + For i=0; i0 Do + d[k]=n Mod 10; Inc(k); + n= n Div 10 + Done + If k==0 Then + ok=cadd(s,'0') + Else + ls=length(s); + ok= (len-ls)>k; + If ok Then + If sg=='-' Then + s[ls]=sg; Inc(ls) + EndIf + For j=k-1; j>=0; Dec(j) Do + s[ls]=d[j]+'0'; Inc(ls) + Done + sfix(s,ls,len); + EndIf + EndIf + If Not ok Then + stringbug("nadd",s, Null,sg) + EndIf + return ok +EndProc + +Proc stri( long n, Pchar s) +/* convert integer to string */ +Begin + sini(s, maxlen(s)); + nadd(s,n) +EndProc + +Proc rawcopy(Pointer a, Pointer b, short la, short lb) +/* dirty binary copy */ +Begin + short j,n; + If lbb[j] Then + k=1 + EndIf + return k +EndFunc + +Func Bool steq(Pchar a, Pchar b) /* string a==b test */ +Begin + Word j=0; + While (a[j]==b[j]) And (a[j]!=0) And (b[j]!=0) Do Inc(j) Done; + return ((a[j]==0) And (b[j]==0)) /* string equality test */ +EndFunc + +Func Bool stne(Pchar s, Pchar t) +Begin + return scompare(s,t) !=0 +EndFunc + +Func short hi(long w) +Begin + return (w AND 0xff00) Shr 8 +EndFunc + +Func short lo(long w) +Begin + return (w AND 0xff) +EndFunc + +Func char lowcase(char c) +Begin + If (c>='A')And(c<='Z') Then + return (char)(c-'A' +'a') + Else + return c + EndIf +EndFunc + +Func Bool alfa( char c) +Begin + return ((c>='a') And (c<='z')) Or ((c>='A') And (c<='Z')); +EndFunc + +Func Bool num( char c) +Begin + return (c>='0') And (c<='9'); +EndFunc + +Func Bool alfanum(char c) +Begin + return + ((c>='a') And (c<='z')) Or ((c>='A')And(c<='Z')) + Or ((c>='0')And(c<='9')) + Or (c=='_') +EndFunc + +Func short freadstr(Pfile f, Pchar s, short max) +/* read a line from a file. + BUG: long lines truncated without warning, ctrl chars are dumped. +*/ +Begin + char c; + short i=0, mxlen=maxlen(s); + If mxlen=' ') Or (c<0) Or (c==Tab)) And (i0) And (c<=' ')) EndRep /* skip space */ + If c=='-' Then + minus=True; c=fgetc(f) + EndIf + While num(c) Do + z= 10*z + c-'0'; c=fgetc(f) + Done + ungetc(c,f) ; /* re-push character lookahead */ + If minus Then z= -z EndIf; + return z +EndFunc + +Func Pchar stupcase( Pchar s) +Begin + short i=0; + While s[i] !=0 Do + s[i]= upcase(s[i]); Inc(i) + Done + return s +EndFunc + +/***** pointer tricks: app won't use naked malloc(), free() ****/ + +Proc dispose(Pointer p) +Begin + If p != Null Then free(p) EndIf +EndProc + +Func Pointer new(long sz) +Begin + Pointer p; + If sz<=0 Then + return Null + Else +#ifdef __TURBOC__ + /* truncate to 64 K ! */ + If sz> 0xffff Then sz= 0xffff EndIf + p= malloc((Word)sz); +#else + p= malloc(sz); +#endif + If p==Null Then /* fatal error */ + ws(" new() failure. Program halted.\n"); + exit(1); + EndIf + return p + EndIf +EndFunc + +Func Pchar newstring(short n) +Begin + Pchar s= (Pchar)new(n+4); + sini(s, n); + return s +EndFunc + +/***** elementary math *******/ + +Func double sqr(double x) +Begin + return x*x +EndFunc + +Func double absf(double x) +Begin + If x<0.0 Then + return -x + Else + return x + EndIf +EndFunc + +Func long absi(long i) +Begin + If i>=0 Then + return(i) + Else + return(-i) + EndIf +EndFunc + +Proc strif(long i, short f, Pchar s) +/* formatting like str(i:f,s) in Turbo Pascal */ +Begin + short j,k,n,max; + char cs; + char t[32]; + k=0; + max=maxlen(s); + If i<0 Then + i= -i; cs='-' + Else + cs=' ' + EndIf; + While i>0 Do + j=(short)(i Mod 10); + i=(long)(i Div 10); + t[k]=chr('0'+j); Inc(k) + Done + If k==0 Then + t[k]='0'; Inc(k) + EndIf + If cs=='-' Then + t[k]=cs + Else + Dec(k) + EndIf; + /* now the string is in 0...k in reverse order */ + For j=1; j<=k; Inc(j) Do t[k+j]=t[k-j] Done /* mirror image */ + t[2*k+1]=0; /* null termination */ + n=0; + If (f>k) And (f<40) Then /* reasonable format */ + For j=k+2; j<=f; Inc(j) Do + s[n]=' '; Inc(n) + Done + EndIf + For j=0; j<=k+1; Inc(j) Do s[n+j]=t[k+j] Done; /* shift t down */ + k=length(s); + sfix(s,k,max); +EndProc + +Func Bool odd(long x) +Begin + return NotZ(x AND 1) +EndFunc + +Func short vali(Pchar s, long * i) +/* convert s to integer i. returns error code 0 if Ok */ +/* BUG: almost identical to ival() with arg/return value swapped ... */ +Begin + short k=0, digit=0, ls; + long z=0; + Bool minus=False, ok=True; + char c; + ls=length(s); + Repeat + c=s[k]; Inc(k) + Until (k>=ls) Or Not ((c>0) And (c<=' ')) EndRep /* skip space */ + If c=='-' Then + minus=True; + c=s[k]; Inc(k) + EndIf + While num(c) Do + z= 10*z + c-'0'; + c=s[k]; Inc(k); + Inc(digit) + Done + If minus Then z= -z EndIf; + *i= z; + ok= (digit>0) And (c==0); /* successful end of string */ + If ok Then + return 0 + Else + return k /* one beyond error position */ + EndIf +EndFunc + +Intern +Func Bool match + (Pchar s, Pchar t, short n, short tstart, Bool testcase) +Begin +/* returns 0 If tstart is out of range. But n may be 0 ? */ +/* True if s matches t[tstart...tstart+n] */ + short i,j,lt; + Bool ok; + char a,b; + i=0; j=tstart; + lt= length(t); + ok=(tstart0 Then /*Else return 0*/ + While (k<=b) And (Not ok) Do + ok=match(t,s, a,k, tstcase); /* we must start at k=0 ! */ + Inc(k); + If s[k]==' ' Then Inc(j) EndIf /* word counter */ + Done + EndIf + If opt==2 Then k=j EndIf + If ok Then + return k + Else + return 0 + EndIf +EndFunc + +Func short spos(Pchar sub, Pchar s) +/* equivalent to Turbo Pascal pos(). + BUG: counts 1 ... length(s), not from 0 like C +*/ +Begin + return posi( sub, s, 0) +EndFunc + +/**** float formatting with printf/scanf ******/ + +Func short valr(Pchar s, double *r) +/* returns 0 if ok, else length of partial string ? */ +Begin + short n=sscanf(s, "%lG", r); + If n==1 Then + return(0) + Else + return(1) + EndIf +EndFunc + +Proc strf( double x, short f1, short f2, Pchar t) +/* e-format if f2<0, else f2 digits after the point, total width=f1 */ +/* if f1=0, also e-format with f2 digits */ +Begin /*default f1=17, f2=-1*/ + Str(30,fmt); + short n,mlt; + mlt=maxlen(t); + cadd(fmt,'%'); + If f1>0 Then + nadd(fmt , f1); /* f1 is the total width */ + If f2<0 Then + sadd(fmt,"lE") /* exponent format */ + Else + cadd(fmt,'.'); + nadd(fmt,f2); + sadd(fmt,"lf") + EndIf + Else + cadd(fmt,'.'); + nadd(fmt, absi(f2-6)); /* note the 6 surplus positions */ + cadd(fmt,'e'); + EndIf + n=sprintf(t, fmt, x); + sfix(t,n, mlt); +EndProc + +Func double rval(Pchar s, short *err) +/* returns err=0 if ok, else length of partial string ? */ +Begin + double r= 0.0; + short n=sscanf(s, "%lG", &r); + If n==1 Then + (*err)=0 + Else + (*err)=1 + EndIf + return r; +EndFunc + +Func long ival(Pchar s, short *err) +/* value of s as integer string. error code err= 0 if Ok */ +Begin + short k=0, digit=0, ls; + long z=0; + Bool minus=False, ok=True; + char c; + ls=length(s); + Repeat + c=s[k]; Inc(k) + Until (k>=ls) Or Not ((c>0) And (c<=' ')) EndRep /* skip space */ + If c=='-' Then + minus=True; + c=s[k]; Inc(k) + EndIf + While num(c) Do + z= 10*z + c-'0'; + c=s[k]; Inc(k); + Inc(digit) + Done + If minus Then z= -z EndIf; + ok= (digit>0) And (c==0); /* successful end of string */ + If ok Then + (*err)= 0 + Else + (*err)= k /* one beyond error position */ + EndIf + return z +EndFunc + +#ifndef _MATH_H + +Func long np_round(double x) +/* using , it would be simpler: floor(x+0.5) */ +Begin + double u; + long z; + short n; + Str(40,s); + u=2e9; + If x>u Then + x=u + ElsIf x< -u Then + x= -u + EndIf + n=sprintf(s,"%-12.0f", x); + s[n]=0; + sscanf(s,"%ld", Addr(z)); + return z +EndFunc + +Func long np_trunc(double x) +Begin + long n=np_round(x); + If (n>x) And (x>=0.0) Then + Dec(n) + ElsIf (nu) Or (x< -u) Then + return x + Else + return np_trunc(x) + EndIf +EndFunc + +#else /* use floor() and ceil() */ + +Func long np_round(double r) +Begin + return (long)floor(r+0.5) +EndFunc + +Func long np_trunc(double r) +Begin + If r>=0.0 Then + return (long)floor(r) + Else + return (long)ceil(r) + EndIf +EndFunc + +Func double frac(double x) +Begin + If x>=0.0 Then + return(x - floor(x)) + Else + return(x - ceil(x)) + EndIf +EndFunc + +Func double intp(double x) /* integral part */ +Begin + If x>=0.0 Then + return floor(x) + Else + return ceil(x) + EndIf +EndFunc + +#endif /* _MATH_H */ + + diff --git a/src/frontend/numparam/ngconfig.sh b/src/frontend/numparam/ngconfig.sh new file mode 100644 index 000000000..c51b18d0b --- /dev/null +++ b/src/frontend/numparam/ngconfig.sh @@ -0,0 +1,20 @@ +#!/bin/sh + +# ngconfig.sh +# configure options for ngspice with numparam add-on +# run this in ngspice's top-level directory + +# specify your Numparam directory +HACK=/home/post/spice3f5/hack + +# over-write the original subckt.c +cp -biv $HACK/ngsubckt.c src/frontend/subckt.c + +# my box needs CFLAGS on 1st run, else 'terminal.c' wont find 'termcap.h' ? + +CFLAGS=-I/usr/include/ncurses \ +LIBS=$HACK/libnupa.a \ +./configure --without-x --prefix=/usr/local/ngsp + +#### end of sample script #### + diff --git a/src/frontend/numparam/numpaif.h b/src/frontend/numparam/numpaif.h new file mode 100644 index 000000000..bb795c65d --- /dev/null +++ b/src/frontend/numparam/numpaif.h @@ -0,0 +1,20 @@ +/* + * numpaif.h + * external interface to spice frontend subckt.c + * $Id$ + */ + +#ifndef NUMPAIF_H +#define NUMPAIF_H + +#define NUPADECKCOPY 0 +#define NUPASUBSTART 1 +#define NUPASUBDONE 2 +#define NUPAEVALDONE 3 + +extern char * nupa_copy(char *s, int linenum); +extern int nupa_eval(char *s, int linenum); +extern int nupa_signal(int sig, char *info); +extern void nupa_scan(char * s, int linenum); + +#endif /* NUMPAIF_H */ diff --git a/src/frontend/numparam/numparam.h b/src/frontend/numparam/numparam.h new file mode 100644 index 000000000..04adc3175 --- /dev/null +++ b/src/frontend/numparam/numparam.h @@ -0,0 +1,77 @@ +/* + * numparam.h + * $Id$ + */ + +/*** interface to spice frontend subckt.c ***/ + +#include "numpaif.h" + +/***** numparam internals ********/ + +#define ln(x) log(x) +#define trunc(x) floor(x) + +Cconst(Nul, 0) +Cconst(Nodekey,'#') /*introduces node symbol*/ +Cconst(Intro ,'&') /*introduces preprocessor tokens*/ +Cconst(Comment,'*') /*Spice Comment lines*/ +Cconst(Pspice,'{') /*Pspice expression */ +Cconst(Maxdico,200) /*size of symbol table*/ + +/* Composite line length + This used to be 250 characters, but this is too easy to exceed with a + .model line, especially when spread over several continuation + lines with much white space. I hope 1000 will be enough. */ +Cconst(Llen,1000) + +typedef char str20 [24]; +typedef char str80 [84]; + +Cconst(Maxline, 1000) /* size of initial unexpanded circuit code */ +Cconst(Maxckt, 5000) /* size of expanded circuit code */ + + +typedef Pchar auxtable; /* dummy */ + +Record(entry) + char tp; /* type: I)nt R)eal S)tring F)unction M)acro P)ointer */ + str20 nom; + short level; /* subckt nesting level */ + double vl; /* float value if defined */ + Word ivl; /*int value or string buffer index*/ + Pchar sbbase; /* string buffer base address if any */ +EndRec(entry) + +Record(fumas) /*function,macro,string*/ + Word start /*,stop*/ ; /*buffer index or location */ +EndRec(fumas) + +Record(tdico) +/* the input scanner data structure */ + str80 srcfile; /* last piece of source file name */ + short srcline; + short errcount; + entry dat[Maxdico+1]; + short nbd; /* number of data entries */ + fumas fms[101]; + short nfms; /* number of functions & macros */ + short stack[20]; + short tos; /* top of stack index for symbol mark/release mechanics */ + str20 option; /* one-character translator options */ + auxtable nodetab; + Darray(refptr, Pchar, Maxline) /* pointers to source code lines */ + Darray(category, char, Maxline) /* category of each line */ +EndRec(tdico) + +Proc initdico(tdico * dico); +Func short donedico(tdico * dico); +Func Bool defsubckt( tdico *dico, Pchar s, Word w, char categ); +Func short findsubckt( tdico *dico, Pchar s, Pchar subname); +Func Bool nupa_substitute( tdico *dico, Pchar s, Pchar r, Bool err); +Func Bool nupa_assignment( tdico *dico, Pchar s, char mode); +Func Bool nupa_subcktcall( tdico *dico, Pchar s, Pchar x, Bool err); +Proc nupa_subcktexit( tdico *dico); +Func tdico * nupa_fetchinstance(void); +Func char getidtype( tdico *d, Pchar s); + diff --git a/src/frontend/numparam/nupatest.c b/src/frontend/numparam/nupatest.c new file mode 100644 index 000000000..830a15e0e --- /dev/null +++ b/src/frontend/numparam/nupatest.c @@ -0,0 +1,454 @@ +/* nupatest.c Copyright (C) 2002 Georg Post + * + * This file is part of Numparam, see: readme.txt + * Free software under the terms of the GNU Lesser General Public License + * $Id$ + */ + +/**** test executable for the numparam library ****/ +/**** usage: nupatest ****/ + +#include + +#include "general.h" +#include "numparam.h" + +Cconst(pfxsep,'_') /* official prefix separator is ':' not '_' ! */ + +Darray(buff, Pchar, Maxline) /* input lines */ +Darray(buf2, Pchar, Maxline) /* stripped lines */ +Darray(pxbuf, Pchar, Maxline) /* prefix for subnodes */ +Darray(runbuf, short, Maxckt) /* index list of expanded circuit */ +Darray(pindex, short, Maxckt) /* prefix index list */ +short irunbuf= 0; /* count lines of runbuf */ +short ipx=0; /* count prefixes in pxbuf */ + +/* + this toy imitates the Spice subcircuit expansion. + To ckeck against Genuine Spice, use the 'listing expand' JDML command + Bug1: model or device call with parameters: incorrectly parsed + needs a database about _optional_ model/device pars... + better: Enter all .model identifiers in the symbol table ! + Bug2: nested subckt declarations, local .models: might be dangerous. + expanded circuit lines, device/node names: + any line that starts with a letter (device): splice the prefix in + any node that isnt a formal param: add the prefix + any formal param node: substitute actual params and their prefixes + +Node and subdevice references for prefixing: + +deviceletter[n] is a device type prefix +nbofnodes [n] is the number of "node-type" arguments that follow. +nbsubdevice [n] is the number of "subdevices" for splice-in prefix. + +To solve the Q ambiguity, forbid any model identifiers as node names. + +Bug3: +In arbitrary dependent sources, we must parse v(,) and i(,) expressions +and substitute node/device name arguments. + +*/ + +Func short runscript( tdico *dico, Pchar prefix, + short istart, short istop, short maxnest) +/* recursive top-down expansion: circuit --> list of line numbers */ +/* keep it simple,stupid compared to Spice's code */ +/* prefix: inherited string for node & device prefixing */ +/* istart, istop: allowed interval in table buf[], buf2[]. */ +/* return value: number of lines included */ +Begin + short i,j, idef, nnest, nline, dn, myipx; + Strbig(Llen, subpfx); /* subckt prefix */ + Str(80, subname); + char c; + Bool done= False; + i=istart; + nline=0; + Inc(ipx); myipx= ipx; /* local copy */ + pxbuf[ipx]= newstring( length(prefix)); + scopy( pxbuf[ipx], prefix); + While (maxnest>0) And (icategory[i]; + If c=='U' Then + done=True; /* subcircuit end. Keep as a comment? */ + buf2[i][0]='#'; + EndIf + If c=='S' Then /* skip nested subcircuits */ + nnest=1; + Repeat + Inc(i); c= dico->category[i]; + If c=='S' Then + Inc(nnest) + ElsIf c=='U' Then + Dec(nnest) + EndIf + Until (nnest<=0) Or (i>=istop) EndRep + ElsIf c=='X' Then /* recursion here ! */ + runbuf[irunbuf]= i; + pindex[irunbuf]= myipx; + Inc(irunbuf); Inc(nline); + /* keep out-commented X line for parameter passing */ + idef = findsubckt( dico, buf2[i], subname); + buf2[i][0]= '*'; + If idef>0 Then + scopy(subpfx, prefix); + cadd(subpfx, pfxsep); + j=1; /* add the instance name from buf2[i] */ + While buf2[i][j] > ' ' Do + cadd( subpfx, buf2[i][j]); Inc(j) + Done + dn= runscript(dico, subpfx, idef+1, istop, maxnest-1); + nline= nline+dn; + Else /* FIXME: error message here! */ + ws("cannot find subckt "); ws(buf2[i]); wln(); + EndIf + ElsIf (c != '?') And NotZ(buf2[i][0]) Then + /* keep any other valid non-empty line, and its prefix pointer */ + runbuf[irunbuf]= i; + pindex[irunbuf]= myipx; + Inc(irunbuf); Inc(nline); + EndIf + Inc(i); + Done + return nline +EndProc + +Proc gluepluslines( short imax) +/* general sweep to eliminate continuation lines */ +Begin + short i,j,k, ls, p; + Strbig(Llen,s); + i=1; + While i<= imax Do + If (buff[i][0]=='+') And (i>1) Then + j= i-1; + While (i < imax) And (buff[i+1][0]=='+') Do Inc(i) Done + /* the lines j+1 ... i are continuation lines to j */ + For k=j; k<=i; Inc(k) Do + ls=length(s); + sadd(s, buff[k]); + p= spos("//",s); + If p>0 Then pscopy(s,s, 1,p-1) EndIf + If ls>0 Then s[ls]=' ' EndIf /* erase the + */ + Done + ls= length(s); + If ls> 80 Then + Dispose(buff[j]); + buff[j]=newstring(ls) + EndIf + scopy(buff[j], s) + EndIf + Inc(i) + Done +EndProc + +#if 0 /* sjb - this is in mystring.c */ +Proc rs(Pchar s) /* 78 coumn limit */ +Begin + short i; + Bool done; + char c; + short max=maxlen(s); + If max>78 Then max=78 EndIf + i=0; done=False; + scopy(s,""); + While Not done Do + c=fgetc(stdin); + If (c>=' ')And(c<='~') And (i0) Then + pscopy(s,s,1,ls-1) + EndIf /* kill EOF character */ +EndProc + +Proc wordinsert(Pchar s, Pchar w, short i) +/* insert w before s[i] */ +Begin + Strbig(Llen,t); + short ls=length(s); + pscopy(t,s,i+1,ls); pscopy(s,s,1,i); + sadd(s,w); sadd(s,t); +EndProc + +Func short worddelete(Pchar s, short i) +/* delete word starting at s[i] */ +Begin + Strbig(Llen,t); + short ls= length(s); + short j=i; + While (j' ') Do Inc(j) Done + pscopy(t,s,j+1,ls); + pscopy(s,s,1,i); + sadd(s,t); + return j-i /* nb of chars deleted */ +EndProc + +Func short getnextword(Pchar s, Pchar u, short j) +Begin + short ls,k; + ls= length(s); + k=j; + While (j ' ') Do Inc(j) Done /* skip current word */ + pscopy(u, s, k+1, j-k); + While (j0 Then + For k=0; k' ' Do + cadd(u,wl[i]); Inc(i) + Done + EndIf +EndProc + +Pchar deviceletter= "RLCVIBSGETOUWFHDQKJZM"; +Pchar nbofnodes = "222222444443222240334"; +Pchar nbsubdevice = "000000000000111002000"; + +Proc prefixing(Pchar s, Pchar p, Pchar formals, Pchar actuals, + char categ, tdico *dic) +/* s is a line in expanded subcircuit. + p is the prefix to be glued anywhere . + assume that everything except first and last word in s may be a node. + formals: node parameter list of a subckt definition line + actuals: substitutes from the last X... call line (commented-out) + subdevices (L belonging to a K line, for example) must be within the + same subckt, they get the same prefix splice-in. + There is a kludge for Q lines (may have 3 or 4 nodes, you never know). +Reminder on Numparam symbols: + naming convention: subckt,model,numparam and node names must be unique. + cannot re-use a model name as a param name elsewhere, for example. +*/ +Begin + short i,j,k,ls, jnext, dsize; + short dtype, nodes, subdv; + Bool done; + char leadchar; + Str(80,u); Str(80,v); Str(80,pfx); + i=0; ls=length(s); + While (i= 0 Then + nodes= nbofnodes[dtype] - '0'; + subdv= nbsubdevice[dtype] - '0'; + Else + nodes=999; subdv=0; + EndIf + While Not done Do + jnext= getnextword(s,u,j); + done=(jnext >= length(s)); /* was the last one, do not transform */ + /* bug: are there semilocal nodes ? in nested subckt declarations ? */ + If (leadchar=='Q') And (Not done) Then /* BJT: watch non-node name */ + scopy(v,u); stupcase(v); + done= getidtype(dic, v) == 'O'; /* a model name stops the node list */ + EndIf + If (Not done) And (nodes>0) Then /* transform a node name */ + k= inwordlist(u, formals); + If (k>0) Then /* parameter node */ + dsize= - worddelete(s,j); + takewordlist(u,k, actuals); + wordinsert(s,u,j); + dsize= dsize + length(u); + ElsIf stne(u,"0") Then /* local node */ + wordinsert(s,pfx,j); + dsize= length(pfx); + Else dsize=0 EndIf + ElsIf (Not done) And (subdv >0) Then /* splice a subdevice name */ + wordinsert(s,p,j+1); + dsize= length(p); + EndIf + j= jnext + dsize; /* jnext did shift ...*/ + If nodes >0 Then Dec(nodes) + ElsIf subdv >0 Then Dec(subdv) + EndIf + done= done Or (Zero(nodes) And Zero(subdv)); + Done + EndIf +EndProc + +Proc getnodelist(Pchar form, Pchar act, Pchar s, tdico *dic, short k) +/* the line s contains the actual node parameters, between 1st & last word */ +Begin + short j,ls, idef; + Str(80,u); Strbig(Llen,t); + ccopy(act,' '); ccopy(form,' '); + j=0; ls= length(s); + j= getnextword(s,u,j); + While j */ + If idef>0 Then + scopy(t, buf2[idef]) + Else + ws("Subckt call error: "); ws(s); wln(); + EndIf + j=0; ls= length(t); + j= getnextword(t,u,j); + j= getnextword(t,u,j); + While jcategory[k], dic); + If dic->category[k] == 'X' Then + If parstack< (10-1) Then Inc(parstack) EndIf + getnodelist(formals[parstack], actuals[parstack], s, dic,k); + /*dbg: ws("Form: "); ws(formals[parstack] ); wln(); */ + /*dbg: ws("Actu: "); ws(actuals[parstack]); wln(); */ + ElsIf dic->category[k]=='U' Then /* return from subckt */ + If parstack>0 Then Dec(parstack) EndIf + EndIf + If fout != Null Then + fwrites(fout, s); fwriteln(fout) + EndIf + EndIf + Done + If fout != Null Then fclose(fout) EndIf + nupa_signal(NUPAEVALDONE, Null); /* frees the buff[i] */ + For i= 10-1; i>=0; Dec(i) Do + Dispose(actuals[i]); + Dispose(formals[i]); + Done + For i= Maxline -1; i>=0; Dec(i) Do + Dispose(pxbuf[i]); + Dispose(buf2[i]); + /* Dispose(buff[i]) done elsewhere */ + Done +EndProc + +Func int main(int argc, Pchar argv[]) +Begin + Str(80,fname); + If argc>1 Then + scopy(fname, argv[1]) + Else + scopy(fname,"testfile.nup") + EndIf + nupa_test(fname, 'w'); + return 0 +EndFunc + diff --git a/src/frontend/numparam/readme.txt b/src/frontend/numparam/readme.txt new file mode 100644 index 000000000..24ce2be43 --- /dev/null +++ b/src/frontend/numparam/readme.txt @@ -0,0 +1,674 @@ +******************************************************** +README.TXT the minimal Numparam documentation +******************************************************** + +Numparam: an add-on library for electronic circuit analysis front-ends +Copyright (C) 2002 Georg Post + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + +CONTENTS + +A. The Numparam library +B. Circuit description with Numparam (in lieu of a tutorial) +C. Reference section +D. Installation +E. Theory of operation +F. Files in this package +G. Known bugs + + +A. The Numparam library: + +The spice-3f(x) front end lacks some features of commercial derivatives, +such as the ability to define numerical attributes of devices by symbols +or by constant (at circuit-expansion time) numerical expressions. +Numerical parameters - other than node names - for subcircuits are also +commonly available in these non-free Spices. + +This library provides a retrofit to the Spice circuit description language +to add these features. By design, the new code is organized as an independent +library which does not import any Spice header files and whose only interface +to Spice is a set of three function headers. The only place where these +functions are called - if a new compile-time option for Spice is set - is +the code file src/lib/fte/subckt.c. There are no patches anywhere else. + +The purpose of this minimal coupling was to freely license the additional code. +It is distributed under the GNU-LGPL and thus can be linked to the original +Spice which is open-source software but maintains a special license. +(As I read somewhere, Berkeley Spice is reserved to people friendly to the USA). +Due to GPL-type requirements, I cannot merge any lines from Spice with +the new code, and I cannot avoid redundancies, such as one more symbol table +manager and the umpteenth arithmetic expression parser. + +Coding style of my add-on is a bit personal. Using a set of keyword-hiding +macros, it is closer to Pascal and/or Basic than to authentic C programs. +Most of it originated from my initial Turbo Pascal preprocessors that have been +translated to C. After all, I'm definitely not "friendly to the C language". +Even in disguise, the code is pure Ansi-C and compiles without a warning +under the severest settings of gcc (under GNU/Linux) or Turbo C++ (under +MS-DOS). For C hardliners, I include the 'washprog' utility which downgrades +the source code to the common C look-&-feel. Extreme purists might apply +some appropriate "indent" utility, in addition. + + +B. Circuit description with Numparam (in lieu of a tutorial). + +As we now know, all the text entry to Spice comes in two separate languages: +- a circuit description language (CDL) which defines the electronic hardware. +- an analysis job and data management language (JDML) which may be used + as an interactive shell or in batch files. + +In the circuit description "CDL" file, the design is typically organized +as a hierarchical set of subcircuits which are connected together in +the 'main' circuit (they are "called", like procedures in a general-purpose +programming language). CDL is line-oriented, with a recognizer role assigned +to the first non-space character of a line. +(In the ancient times of data processing, a line was called a "card".) +For example, '*' introduces comment lines. 'C' places a capacitor +device in the circuit, 'R' a resistor, 'L' an inductor, and so on. +'X' signals the "call" of a subcircuit. Character '+' introduces a continuation +line (the way to split exceedingly long lines into pieces). + +A special class of lines that start with a dot '.' have control functions +inside CDL: they do not add physical circuit elements. +For instance, the control pair '.subckt' and '.ends' brackets a subcircuit +definition section in CDL. +In the old days of Spice-2, some of the functions now assigned to JDML were +also inserted as dot cards. You can still insert pieces of JDML inside +a CDL file, as a section enclosed within lines '.control' and '.endc' . + +Example CDL file, a netlist of some double T RC-filter: + +* First-example +.subckt myfilter in out +Ra in p1 2k +Rb p1 out 2k +C1 p1 0 2nF +Ca in p2 1nF +Cb p2 out 1nF +R1 p2 0 1k +.ends myfilter + +X1 input output myfilter +V1 input 0 AC 1V +.end + +Let us recall what the Spice "front-end" essentially does to your +circuit-description (CDL) file whenever it is submitted, either at program +start-up or after some interactive JDML commands like 'edit' or 'source'. +First, all the JDML sections in the file are sorted out and kept for +later use (unless the file is pure JDML and thus immediately executed). +Next, the hierarchy of subcircuits is expanded and an internal representation +of the flattened circuit is stored, i.e. a set of CDL lines without any more +'X' and '.subckt' lines. This flat circuit is also known as the "netlist". +Then, the netlist is translated into the internal data structures of Spice, +essentially a sparse matrix of elements indexed by pairs of circuit nodes. + +Finally, the mathematical analysis is carried out under the control of JDML, +and output data may be stored, printed, plotted, compared, and so on. +Analyses may be repeated under varying bias/frequency/time... conditions. +But to change the circuit topology, the CDL must be edited and re-compiled. + +Numparam-specific features of CDL : + +The Numparam library is an enhancement of the Spice front-end which adds +clarity and arithmetic functionality to the circuit description language. + +The most wanted feature of a language is to have word-like symbols that +take the place of specific values or objects. The dot-line + +.param = + +defines such symbols. For example, to describe a triple RC filter +with identical values of components, we do not need to explicitly +repeat constant numbers. The CDL code may go like this: + + .param res= 1kohm // numparam allows comment tails like in C++ + .param tau= 10ns // we want a time constant + .param cap= tau/res // tau= RC, of course + + .subckt triplerc in out + R1 in p1 {res} + C1 p1 0 {cap} + R2 p1 p2 {res} + C2 p2 0 {cap} + R3 p2 out {res} + C3 out 0 {cap} + .ends + +As you can see, the use of symbols anywhere in the circuit description +requires the curly braces : + { } +This coding style is even more interesting if circuit elements have known +fixed ratios (Butterworth filters and the like) and we only need to +touch one value (a time constant) to tune the circuit. + +Only numerical constants such as '30pF' may be used without enclosing +braces. It is the braces that tell our CDL front-end to look up +symbols and to crunch arithmetic expressions inside. + +Obviously, it was restrictive that subcircuit definitions could only +accept interface node names as symbolic parameters. With the following +syntax of the .subckt line, we add numerical parameters: + + .subckt ... params: = = ... + +Example, a parameterized filter: + + .subckt triplerc2 in out params: res=1kohm cap=50pF + * all the following lines as above. + * the specified default values are always overridden with X lines. + +To call variants of such a subcircuit later on, we may write: + + X1 in out1 triplerc2 {r1} {c1} + X2 in out2 triplerc2 {2*r1} {c1/2} + X3 in out3 triplerc2 {3*r1} {c1/3} + +where the r1 and c1 symbols are defined in .param lines. +So, we can use subcircuits with one or more parameters, the same way +as Spice2 already allowed an area parameter for diodes and transistors. + + +Here is the first example, rewritten with parameters: + +* Param-example +.param amplitude= 1V + +.subckt myfilter in out ++ params: rval=100k cval= 100nF +Ra in p1 {2*rval} +Rb p1 out {2*rval} +C1 p1 0 {2*cval} +Ca in p2 {cval} +Cb p2 out {cval} +R1 p2 0 {rval} +.ends myfilter + +X1 input output myfilter 1k 1nF +V1 input 0 AC {amplitude} +.end + +Note: +Now, there is some possible confusion in Spice because of multiple numerical +expression features. The .param lines and the braces expressions are +evaluated in the front-end, that is, just after the subcircuit expansion. +(Technically, the X lines are kept as comments in the expanded circuit +so that the actual parameters can correctly be substituted ). +So, after the netlist expansion and before the internal data setup, all +number attributes in the circuit are known constants. + However, there are some circuit elements in Spice which accept arithmetic +expressions that are NOT evaluated at this point, but only later during +circuit analysis. These are the arbitrary current and voltage sources. +The syntactic difference is that "compile-time" expressions are +within braces, but "run-time" expressions have no braces. + To make things more complicated, the backend language JDML also accepts +arithmetic/logic expressions that operate on its own scalar or vector data sets. + +It would be desirable to have the same expression syntax, operator and function +set, and precedence rules, for the three contexts mentioned above. +In the current Numparam implementation, that goal is not yet achieved... + + +C. Reference section: + +The Numparam add-on supports the following elements in the circuit description +language. + +1. '.param' control lines to define symbolic numbers +2. arithmetic expressions in place of any numeric constant +3. formal and actual numeric parameters for subcircuit definition and 'call'. + +NOT YET IMPLEMENTED: + To activate the additional functions, put a line near the top of the CDL file: + .option numparam + +In the syntax description, + means an alphanumeric identifier (<20 chars, starting with a letter) + means an expression, composed of s, Spice numbers, and operators. + +1. The .param line: + Syntax: .param = ; = .... + + This line assigns numerical values to identifiers. More than one assignment + per line is possible using the ';' separator. + The .param lines inside subcircuits are copied per call, like any other line. + All assignments are executed sequentially through the expanded circuit. + Before its first use, a name must have been assigned a value. + +2. Brace expressions in cicuit elements: + Syntax: { } + + These are allowed in .model lines and in device lines, wherever only constant + Spice numbers could be used in spice2/3. A Spice number is a floating + point number with an optional scaling suffix, immediately glued to the + numeric tokens (see below). + Warning: {..} cannot be used to 'parameterize' node names or parts of names. + ( We are not into obfuscated shell scripting ...) + All identifiers used within an must have known values at the time + when the line is evaluated, else an error is flagged. + +3. Subcircuit parameters: + The syntax of a subcircuit definition header is: + .subckt node node ... params: = =... + + node is an integer number or an identifier, for one of the external nodes. + The 'params:' keyword introduces an optional section of the line. + Each is a formal parameter, and each is either a Spice + number or a brace expression. + Inside the '.subckt' ... '.ends' context, each formal parameter may be + used like any identifier that was defined on a .param control line. + The parts are supposed to be default values of the parameters. + However, in the current version of Numparam, they are not used and each + invocation of the subcircuit must supply the _exact_ number of actual + parameters. + + The syntax of a subcircuit call (invocation) is: + X node node ... .... + + Here is the symbolic name given to that instance of the subcircuit, + is the name of a subcircuit defined beforehand. node node ... is + the list of actual nodes where the subcircuit is connected. + is either a Spice number or a brace expression { } . + The sequence of items on the X line must exactly match the number + and the order of formal parameters of the subcircuit. + +4. Symbol scope + + All Subcircuit and Model names are considered global and must be unique. + The .param symbols that are defined outside of any '.subckt' ... '.ends' + section are global. Inside such a section, the pertaining 'params:' + symbols and any .param assignments are considered local: they mask any + global identical names, until the .ends line is encountered. + You cannot reassign to a global number inside a .subckt, a local copy is + created instead. Scope nesting works up to a level of 10. For example, + if the main circuit calls A which has a formal parameter xx, A calls B + which has a param. xx, and B calls C which also has a formal param. xx, + there will be three versions of 'xx' in the symbol table but only the most + local one - belonging to C - is visible. + +5. Syntax of expressions ( optional parts within [ ...] ): + + An expression may be one of: + where is either a Spice number or an identifier + + ( [ , ...] ) + + ( ) + + As expected, atoms, builtin function calls and stuff within parentheses + are evaluated before the other operators. The operators are evaluated + following a list of precedence close to the one of the C language. + For equal precedence binary ops, evaluation goes left to right. + + Operators: Alias Internal symb. Precedence + + - - 1 (unary -) + not ! ! 1 (unary not) + ** ^ ^ 2 (power) + * * 3 (multiply) + / / 3 (divide) + mod % % 3 (modulo) + div \ \ 3 (integer divide) + + + 4 (add) + - - 4 (subtract) + == = 5 (equality) + <> != # 5 (un-equal) + <= L 5 (less or equal) + >= G 5 (greater or equal) + < < 5 (less than) + > > 5 (greater than) + and && & 6 (and) + or || | 7 (or) + + The result of logical operators is 1 or 0 , for True or False. + + + Builtin functions: Internal ref. + + defined 0 (returns 1 if symbol is defined, else 0) + sqr 1 + sqrt 2 + sin 3 + cos 4 + exp 5 + ln 6 + arctan 7 + abs 8 + pwr 9 + + Scaling suffixes (any decorative alphanum. string may follow ...) + + g 1e9 + meg 1e6 + k 1e3 + m 1e-3 + u 1e-6 + n 1e-9 + p 1e-12 + f 1e-15 + + Note: there are intentional redundancies in expression syntax, e.g. + x^y , x**y and pwr(x,y) all have nearly the same result. + +6. Reserved words + In addition to the above function names and to the verbose operators + ( not and or div mod ), other words are reserved and cannot be used + as parameter names. Historically, they come from a version of Numparam + that was a full-blown macro language. I won't link that one to Spice, + not before somebody proves to me that such a thing could be useful... + + and or not div mod if else end while macro funct defined + include for to downto is var + sqr sqrt sin cos exp ln arctan abs pwr + + +7. Alternative syntax + the & sign is tolerated to provide some 'historical' parameter notation: + & as the first character of a line is equivalent to: .param + Inside a line, the notation &(....) is equivalent to {....}, and + &identifier means the same thing as {identifier} . + + This notation exists a bit for the same reason as my macros which wipe + the curly braces out of the C language: entering those signs is a pain in + the neck on IBM French-type keyboards. You hit, among others, a vanishingly + small AltGr key which is squeezed by superfluous buttons that show ugly + office-software logos... + + Comments in the style of C++ line trailers (//) are detected and erased. + Warning: this is NOT possible in embedded .control parts of a source + file, these JDML lines are outside of Numparam's scope. DOS-style + carriage returns at line ends are difficult for JDML, too. + + +D. Installation + +There are two versions of Spice on which this library has been tried: +a. a 1997 version spice3f5 that was arranged for Red Hat Linux +b. the version 14 of ngspice (will now be privileged for development) + +On my system, the size of libnupa.a is about 47k, so this is the additional +bloat that the spice3 and nutmeg binary programs will accumulate. +( The numparam source tarball weighs in for some 70k ) + +The common part to build the Numparam library is this: + +0. choose any directory you like for Numparam, let's call it $HACK. +1. un-tar the .c and .h files and the rest, in Numparam's directory : + tar xzvf numparam.tgz + +2. compile the lib sources with gcc -c -Wall: + + gcc -c -ansi -pedantic -Wall spicenum.c nupatest.c xpressn.c mystring.c + +3. pre-link together the library part to numparam.o and libnupa.a: + + ld -r -o numparam.o spicenum.o xpressn.o mystring.o + ar -rcs libnupa.a spicenum.o xpressn.o mystring.o + +4. make the test executable nupatest: + + gcc -o nupatest nupatest.o spicenum.o xpressn.o mystring.o -lm + +The script file 'mknumpar.sh' does all this (2-4). + + +5a. Link with the "third version of Spice3f5 for RedHat Linux 2.6" (1997) + + do the following in the spice3f5 top-level directory: + + 1. patch the file src/lib/fte/subckt.c : + cp -biv $HACK/rhsubckt.c src/lib/fte/subckt.c + 2. edit src/bin/makeops , to add $HACK/libnupa.a to LIBS and LIBN. + 3. ./util/build linux + 4. ./util/build linux install + + +5b. Link procedure for ngspice version 14 + +I haven't yet a working knowledge of the 'automake/autoconf' system, so I'll +describe the pedestrian hacks to get Numparam in. That's evil; the right way +would need a configuration flag that chooses to make and to link the library. +Only the top level files 'configure.in' and 'Makefile.am' should be revised +to process the numparam option. (?) +Help! + +1. replace the file src/frontend/subckt.c with Numparam's patched version : + cp -biv $HACK/ngsubckt.c src/frontend/subckt.c +2. run ./configure with a "LIBS prefix" to include numparam (see below) +3. make +4. make install + +Here is one "prefixed" ngspice configure script that works on my system: + +#!/bin/sh + +# ngconfig.sh +# configure options for ngspice with numparam add-on +# run this in ngspice's top-level directory + +# specify your Numparam directory +HACK=/home/post/spice3f5/hack + +# over-write the original subckt.c +cp -biv $HACK/ngsubckt.c src/frontend/subckt.c + +# my box needs CFLAGS on 1st run, else 'terminal.c' wont find 'termcap.h' ? + +CFLAGS=-I/usr/include/ncurses \ +LIBS=$HACK/libnupa.a \ +./configure --without-x --prefix=/usr/local/ngsp + +#### end of sample script #### + + +E. Theory of operation + +Spice's front end does a lot of malloc/free type memory gymnastics and does not +seem to care much about small leaks here and there. Numparam will do some +malloc'ing in place of Spice (essentially the translated strings of the input +deck) and rely on Spice to clean it up - or not - later on. My library will +clean up its private space only (the symbol tables) and will make some +assumptions about the interface function calls coming from Spice. +Here is the scenario supposed to be followed by Spice and Numparam: + +0. the patched codefile subckt.c imports the following header lines: + +#define NUPADECKCOPY 0 +#define NUPASUBSTART 1 +#define NUPASUBDONE 2 +#define NUPAEVALDONE 3 + +extern char * nupa_copy(char *s, int linenum); +extern int nupa_eval(char *s, int linenum); +extern int nupa_signal(int sig); + +These are the three library functions called, i.e. + +- nupa_copy by inp_subcktexpand to preprocess all extended-syntax lines. +- nupa_eval by inp_subcktexpand to do the parameter substitutions +- nupa_signal with one of the 4 signals, from various places to + send state information to the Numparam library. + +The only places with numparam patches are the functions +inp_subcktexpand() and its recursive subroutine doit(), in the +file subckt.c . At this stage, we suppose that: +- any .control sections are filtered out +- any .include are expanded +- any + continuation line chunks are glued together + +1. In the first phase, Numparam runs through the deck (whose .control sections + have already been removed by Spice) to create copies of the lines + without the extended syntax. Pointers to the original deck lines are kept + and the copies are traditional Spice, with placeholders for + symbols and expressions. Spice loses the originals and gets the bleached-out + copies. + +2. The "doit()" circuit expansions are modified to keep more information. + Contrary to the initial Spice code, now the subcircuit invocation + lines are preserved as comments, which allows Numparam to update + symbolic subcircuit parameters a bit later. Subcircuit exit lines are also + copied and out-commented, to keep track of identifier scopes during + the final pass. + +If this seems waste of storage, just consider all those sloppy memory +leaks in the circuit expansion code... + +3. The final wash-up is a sequential call to the library (nupa_eval()) + line-by-line through the expanded circuit. By using its pointers + to the original lines, Numparam recovers the added syntax features. + It triggers all the symbol value computations and inserts constant + numbers into the circuit definition lines, whose length must not change! + This option is a kludge to avoid memory reallocation [ my intuitive + fear is that these free() malloc() realloc() and friends swallow a lot of + CPU time ? ]. + +4. The termination signal at the end of inp_subcktexpand() tells the Numparam + library to clean up its mess, release its pointers to the original + Spice circuit description text, and to get prepared for another run. + Note: Numparam frees the storage related to the original lines + whose pointers have been stolen in phase 1. + + +In a future release, Numparam will be re-entrant, all its 'global' data being +referenced via a handle which the client program should keep around. + + +F. Files in this package + +The following Ansi C code files belong to Numparam: + +general.h header file with macros to disguise the C language. + stuff for an 'overflow-safe' string library ( whose biggest bug + is that it indexes strings from 1 like Pascal). + +numparam.h header file for numparam-specific symbols and functions + +mystring.c collection of 'safer' character string (and misc.) functions. + beware of the nasty Turbo Pascal conventions. + +xpressn.c the interpreter of arithmetic/logical expressions + +spicenum.c the interface part, functions that are called by Spice. + +nupatest.c a stand-alone subcircuit expander, for test purpose. + +washprog.c a program that washes all the above C files, including itself, + to recover the crude syntax of the True Language (see below). + +Patched versions of spice's subckt.c file incorporate the library calls +and maybe try to repair some memory leaks (in rhsubckt.c, not yet tested). + +rhsubckt.c for spice3f5 1997 Red Hat (src/lib/fte/subckt.c) +ngsubckt.c for ngspice version 14 (src/frontend/subckt.c) +subckt.dif 'diff' between ngsubckt.c and ngspice frontend/subckt.c + +The following text, data and script files are also included: + +readme.txt this documentation file +downgrad.txt the substitution rules required for washprog.c +mknumpar.sh script to make the library binaries +ngconfig.sh sample script to run ./configure for ngspice + +configure.in crappy ? +Makefile.am crappy ? + +testfile.nup a test text (nonsense circuit) for Numparam ? + + +So, if you are a Real Programmer, think that the Pascal amateurs confound +programming with writing novels, and find those Basic greenhorns' style +too childish, then execute the following two-liner first of all +(should work on GNU/Linux, but it's not a speed monster) : + +gcc -o washprog washprog.c mystring.c +./washprog *.c + +You get all the *.c files in a version where the first character becomes an +underbar, and the interior resembles to _code_. (although it lacks such +powerful features as continue, break, goto, ?:-expressions, gets(), ... ) + + +G. Known Bugs + +First of all, lots of size limits - incompatible with the Spirit of the +Gnu, who wants that everything may grow as much as malloc() can grab ... + +- circuit source code line length: 80 chars +- circuit '+' extended code lines: 250 chars +- number of source lines: 1000 +- number of lines in expanded circuit: 5000 +- length of numparam identifiers: 20 chars +- number of numparam identifiers: 200 +- length of file names: 80 chars +- significant digits in param results: 5 +- nesting depth of parentheses 9 +- nesting of subckt calls 10 + +All these constants should be in the header file but aren't. + +After each circuit expansion, numparam asks a silly question +of the "Abort/Continue" type. A debugging feature, to be killed soon. + +The Numparam symbol table accumulates the following sets of names: +subcircuits, models, global parameters, subcircuit arguments. +Node names, however, are completely ignored. + +Call the following "bugs" or "features": +- A model/subckt name cannot be defined twice, even if local to a subcircuit. +- The same name cannot design a model here, and a parameter elsewhere. +- A subcircuit argument masks any global parameter of same name, + anytime the subckt is invoked. Inside a .subckt context, .param assignments + also have local scope and override global identical names. + +It is wise to always use unique names for everything. + + +While Numparam is in 'early beta stage', I strongly suggest to use +'nupatest' first, on any 'parameterized' Spice circuit file, +before starting the enhanced circuit analyser. + +The command + nupatest foobar.cir +produces an output file 'foobar.out' which is the expanded and +parameter-reduced flat netlist. +By the way, it produces error messages whenever it chokes on the source file. +If nupatest succeeds, the spice+numparam combo should swallow it, too. +Big bug: Nupatest does not yet prefix and infix things inside v() and i(). + + +Numparam comes with two very experimental files 'configure.in' and +'Makefile.am' as an exercise of the automake/autoconf mechanisms. +I certainly got a lot of things wrong and had to do _eight_ steps to +have it kind of work: + +1. edit/create configure.in +2. edit/create Makefile.am +3. run autoheader --> config.h.in +4. run automake --foreign --add-missing --verbose --> Makefile.in +5. run aclocal --> aclocal.m4 +6. run autoconf --> configure +7. run ./configure --> Makefile config.h +8. run make + +Do we need all this, and -worse- do we need to repeat it whenever we touch +'configure.in' and/or 'Makefile.am' ? Help! + + +Please send your bug reports, improvements, flames etc. to the author: +georg.post @ wanadoo.fr + diff --git a/src/frontend/numparam/spicenum.c b/src/frontend/numparam/spicenum.c new file mode 100644 index 000000000..03b468134 --- /dev/null +++ b/src/frontend/numparam/spicenum.c @@ -0,0 +1,581 @@ +/* spicenum.c Copyright (C) 2002 Georg Post + * + * This file is part of Numparam, see: readme.txt + * Free software under the terms of the GNU Lesser General Public License + */ + +/* number parameter add-on for Spice. + to link with mystring.o, xpressn.o (math formula interpreter), + and with Spice frontend src/lib/fte.a . + Interface function nupa_signal to tell us about automaton states. +Buglist (some are 'features'): + blank lines get category '*' + inserts conditional blanks before or after braces + between .control and .endc, flags all lines as 'category C', dont touch. + there are reserved magic numbers (1e9 + n) as placeholders + control lines must not contain {} . + ignores the '.option numparam' line planned to trigger the actions + operation of .include certainly doesnt work + there are frozen maxima for source and expanded circuit size. +Todo: + add support for nested .if .elsif .else .endif controls. +*/ + +#include +#include +#ifdef __TURBOC__ +#include /* exit() */ +#endif + +#include "general.h" +#include "numparam.h" + +/* Uncomment this line to allow debug tracing */ +/* #define TRACE_NUMPARAMS */ + +/* the nupa_signal arguments sent from Spice: + + sig=1: Start of the subckt expansion. + sig=2: Stop of the subckt expansion. + sig=3: Stop of the evaluation phase. + sig=0: Start of a deck copy operation + + After sig=1 until sig=2, nupa_copy does no transformations. + At sig=2, we prepare for nupa_eval loop. + After sig=3, we assume the initial state (clean). + + In Clean state, a lot of deckcopy operations come in and we + overwrite any line pointers, or we start a new set after each sig=0 ? + Anyway, we neutralize all & and .param lines (category[] array!) + and we substitute all {} &() and &id placeholders by dummy numbers. + The placeholders are long integers 1000000000+n (10 digits, n small). + +*/ +/********** string handling ***********/ + +#define PlaceHold 1000000000L +Intern long placeholder= 0; + +#ifdef NOT_REQUIRED /* SJB - not required as front-end now does stripping */ +Intern +Func short stripcomment( Pchar s) +/* allow end-of-line comments in Spice, like C++ */ +Begin + short i,ls; + char c,d; + Bool stop; + ls=length(s); + c=' '; i=0; stop=False; + While (i0)And (s[i-1]<=' ') Do Dec(i) Done; /*strip blank space*/ + If i<=0 Then + scopy(s,"") + Else + pscopy(s,s,1,i) + EndIf + Else + i= -1 + EndIf + return i /* i>=0 if comment stripped at that position */ +EndFunc +#endif /* NOT_REQUIRED */ + +Intern +Proc stripsomespace(Pchar s, Bool incontrol) +Begin +/* iff s starts with one of some markers, strip leading space */ + Str(12,markers); + short i,ls; + scopy(markers,"*.&+#$"); + If Not incontrol Then + sadd(markers,"xX") + EndIf + ls=length(s); i=0; + While (i0) And (i0) Then + pscopy(s,s,i+1,ls) + EndIf +EndProc + +#if 0 /* unused? */ +Proc partition(Pchar t) +/* t is a list val=expr val=expr .... Insert Lf-& before any val= */ +/* the Basic preprocessor doesnt understand multiple cmd/line */ +/* bug: strip trailing spaces */ +Begin + Strbig(Llen,u); + short i,lt,state; + char c; + cadd(u,Intro); + state=0; /* a trivial 3-state machine */ + lt=length(t); + While t[lt-1] <= ' ' Do Dec(lt) Done + For i=0; i0) And (j' ' Then cadd(t,' ') EndIf + nadd(t, PlaceHold + placeholder); + If s[j]>=' ' Then cadd(t,' ') EndIf + i=length(t); + pscopy(s,s, j+1, ls); + sadd(t,s); + scopy(s,t); + Else + Inc(i) + EndIf + ls=length(s) + Done + return n +EndFunc + +Intern +Func short findsubname(tdico * dico, Pchar s) +/* truncate the parameterized subckt call to regular old Spice */ +/* scan a string from the end, skipping non-idents and {expressions} */ +/* then truncate s after the last subckt(?) identifier */ +Begin + Str(80, name); + short h,j,k,nest,ls; + Bool found; + h=0; + ls=length(s); + k=ls; found=False; + While (k>=0) And (Not found) Do /* skip space, then non-space */ + While (k>=0) And (s[k]<=' ') Do Dec(k) Done; + h=k+1; /* at h: space */ + While (k>=0) And (s[k]>' ') Do + If s[k]=='}' Then + nest=1; + Dec(k); + While (nest>0) And (k>=0) Do + If s[k]=='{' Then + Dec(nest) + ElsIf s[k]=='}' Then + Inc(nest) + EndIf + Dec(k) + Done + h=k+1; /* h points to '{' */ + Else + Dec(k) + EndIf; + Done + found = (k>=0) And alfa(s[k+1]); /* suppose an identifier */ + If found Then /* check for known subckt name */ + scopy(name,""); j= k+1; + While alfanum(s[j]) Do + cadd(name, upcase(s[j])); Inc(j) + Done + found= (getidtype(dico, name) == 'U'); + EndIf + Done + If found And (h new style with braces. */ +Begin + Strbig(Llen,t); + short i,state, ls; + char c,d; + i=0; state=0; + ls= length(s); + While i0) Then + If d=='(' Then + state=1; Inc(i); c='{' + ElsIf alfa(d) Then + cadd(t,'{'); Inc(i); + While alfanum(s[i]) Do + cadd(t,s[i]); Inc(i) + Done + c='}'; Dec(i); + EndIf + ElsIf NotZ(state) Then + If c=='(' Then + Inc(state) + ElsIf c==')' Then + Dec(state) + EndIf + If Zero(state) Then /* replace ) by terminator */ + c='}'; + EndIf + EndIf + cadd(t,c); + Inc(i) + Done + scopy(s,t); +EndProc + +Intern +Func char transform(tdico * dico, Pchar s, Bool nostripping, Pchar u) +/* line s is categorized and crippled down to basic Spice + * returns in u control word following dot, if any + * + * any + line is copied as-is. + * any & or .param line is commented-out. + * any .subckt line has params section stripped off + * any X line loses its arguments after sub-circuit name + * any &id or &() or {} inside line gets a 10-digit substitute. + * + * strip the new syntax off the codeline s, and + * return the line category as follows: + * '*' comment line + * '+' continuation line + * ' ' other untouched netlist or command line + * 'P' parameter line, commented-out; (name,linenr)-> symbol table. + * 'S' subckt entry line, stripped; (name,linenr)-> symbol table. + * 'U' subckt exit line + * 'X' subckt call line, stripped + * 'C' control entry line + * 'E' control exit line + * '.' any other dot line + * 'B' netlist (or .model ?) line that had Braces killed + */ +Begin + Strbig(Llen,t); + char category; + short i,k, a,n; +/* i=stripcomment(s); sjb - not required now that front-end does stripping */ + stripsomespace(s, nostripping); + modernizeex(s); /* required for stripbraces count */ + scopy(u,""); + If s[0]=='.' Then /* check Pspice parameter format */ + scopy(t,s); + stupcase(t); + k=1; + While t[k]>' ' Do + cadd(u, t[k]); Inc(k) + Done + If spos(".PARAM",t) ==1 Then /* comment it out */ + s[0]='*'; + category='P'; + ElsIf spos(".SUBCKT",t) ==1 Then /* split off any "params" tail */ + a= spos("PARAMS:",t); + If a>0 Then + pscopy(s,s,1,a-1); + EndIf + category='S'; + ElsIf spos(".CONTROL",t) ==1 Then + category='C' + ElsIf spos(".ENDC",t) ==1 Then + category='E' + ElsIf spos(".ENDS",t) ==1 Then + category='U' + Else + category='.'; + n= stripbraces(s); + If n>0 Then category='B' EndIf /* priority category ! */ + EndIf + ElsIf s[0]==Intro Then /* private style preprocessor line */ + s[0]='*'; + category='P'; + ElsIf upcase(s[0])=='X' Then /* strip actual parameters */ + i=findsubname(dico, s); /* i= index following last identifier in s */ +/* pscopy(s,s,1,i); sjb - this is already done by findsubname() */ + category='X' + ElsIf s[0]=='+' Then /* continuation line */ + category='+' + ElsIf cpos(s[0],"*$#")<=0 Then /* not a comment line! */ + n= stripbraces(s); + If n>0 Then + category='B' /* line that uses braces */ + Else + category=' ' + EndIf; /* ordinary code line*/ + Else + category='*' + EndIf + return category +EndFunc + +/************ core of numparam **************/ + +/* some day, all these nasty globals will go into the tdico structure + and everything will get hidden behind some "handle" ... +*/ + +Intern int linecount= 0; /* global: number of lines received via nupa_copy */ +Intern int evalcount= 0; /* number of lines through nupa_eval() */ +Intern int nblog=0; /* serial number of (debug) logfile */ +Intern Bool inexpansion= False; /* flag subckt expansion phase */ +Intern Bool incontrol= False; /* flag control code sections */ +Intern Bool dologfile= True; /* for debugging */ +Intern Bool firstsignal=True; +Intern Pfile logfile= Null; +Intern tdico * dico=Null; + +/* already part of dico : */ +/* Str(80, srcfile); source file */ +/* Darray(refptr, Pchar, Maxline) pointers to source code lines */ +/* Darray(category, char, Maxline) category of each line */ + +/* + Open ouput to a log file. + takes no action if logging is disabled. + Open the log if not already open. +*/ +Intern +Proc putlogfile(char c, int num, Pchar t) +Begin + Strbig(Llen, u); + Str(20,fname); + If dologfile Then + If(logfile == Null) Then + scopy(fname,"logfile."); + Inc(nblog); nadd(fname,nblog); + logfile=fopen(fname, "w"); + EndIf + If(logfile != Null) Then + cadd(u,c); nadd(u,num); + cadd(u,':'); cadd(u,' '); + sadd(u,t); cadd(u,'\n'); + fputs(u,logfile); + EndIf + EndIf +EndProc + +Intern +Proc nupa_init( Pchar srcfile) +Begin + short i; + /* init the symbol table and so on, before the first nupa_copy. */ + evalcount=0; + linecount= 0; + incontrol=False; + placeholder= 0; + dico= New(tdico); + initdico(dico); + For i=0; irefptr[i]= Null; + dico->category[i]='?'; + Done + Sini(dico->srcfile); + If srcfile != Null Then scopy(dico->srcfile, srcfile) EndIf +EndProc + +Intern +Proc nupa_done(void) +Begin + short i; + Str(80,rep); + short dictsize, nerrors; + If logfile != Null Then + fclose(logfile); + logfile=Null; + EndIf + nerrors= dico->errcount; + dictsize= donedico(dico); + For i=Maxline-1; i>=0; Dec(i) Do + Dispose( dico->refptr[i]) + Done + Dispose(dico); + dico= Null; + If NotZ(nerrors) Then + /* debug: ask if spice run really wanted */ + scopy(rep," Copies="); nadd(rep,linecount); + sadd(rep," Evals="); nadd(rep,evalcount); + sadd(rep," Placeholders="); nadd(rep,placeholder); + sadd(rep," Symbols="); nadd(rep,dictsize); + sadd(rep," Errors="); nadd(rep,nerrors); + cadd(rep,'\n'); ws(rep); + ws("Numparam expansion errors: Run Spice anyway? y/n ? \n"); + rs(rep); + If upcase(rep[0]) != 'Y' Then exit(-1) EndIf + EndIf + linecount= 0; + evalcount= 0; + placeholder= 0; + /* release symbol table data */ +EndProc + +/* SJB - Scan the line for subcircuits */ +Proc nupa_scan(Pchar s, int linenum) +Begin + If spos(".SUBCKT",s) ==1 Then + defsubckt( dico, s, linenum, 'U' ); + EndIf +EndProc + +Func Pchar nupa_copy(Pchar s, int linenum) +/* returns a copy (not quite) of s in freshly allocated memory. + linenum, for info only, is the source line number. + origin pointer s is kept, memory is freed later in nupa_done. + must abort all Spice if malloc() fails. + Is called for the first time sequentially for all spice deck lines. + Is then called again for all X invocation lines, top-down for + subckts defined at the outer level, but bottom-up for local + subcircuit expansion, but has no effect in that phase. + we steal a copy of the source line pointer. + - comment-out a .param or & line + - substitute placeholders for all {..} --> 10-digit numeric values. +*/ +Begin + Strbig(Llen,u); + Strbig(Llen,keywd); + Pchar t; + short i,ls; + char c,d; + ls= length(s); + While (ls>0) And (s[ls-1]<=' ') Do Dec(ls) Done + pscopy(u,s, 1,ls); /* strip trailing space, CrLf and so on */ + dico->srcline= linenum; + If (Not inexpansion) And (linenum >=0) And (linenumrefptr[linenum]= s; + c= transform(dico, u, incontrol, keywd); + If c=='C' Then + incontrol=True + ElsIf c=='E' Then + incontrol=False + EndIf + If incontrol Then c='C' EndIf /* force it */ + d= dico->category[linenum]; /* warning if already some strategic line! */ + If (d=='P') Or (d=='S') Or (d=='X') Then + fputs(" Numparam warning: overwriting P,S or X line.\n",stderr); + EndIf + If c=='S' Then + defsubckt( dico, s, linenum, 'U' ) + ElsIf steq(keywd,"MODEL") Then + defsubckt( dico, s, linenum, 'O' ) + EndIf; /* feed symbol table */ + dico->category[linenum]= c; + EndIf /* keep a local copy and mangle the string */ + ls=length(u); + t= NewArr( char, ls+1); /* == (Pchar)malloc(ls+1); */ + If t==NULL Then + fputs("Fatal: String malloc crash in nupa_copy()\n", stderr); + exit(-1) + Else + For i=0;i<=ls; Inc(i) Do + t[i]=u[i] + Done + If Not inexpansion Then + putlogfile(dico->category[linenum],linenum,t) + EndIf; + EndIf + return t +EndFunc + +Func int nupa_eval(Pchar s, int linenum) +/* s points to a partially transformed line. + compute variables if linenum points to a & or .param line. + If the original is an X line, compute actual params. + Else substitute any &(expr) with the current values. + All the X lines are preserved (commented out) in the expanded circuit. +*/ +Begin + short idef; /* subckt definition line */ + char c; + Str(80,subname); + dico->srcline= linenum; + c= dico->category[linenum]; +#ifdef TRACE_NUMPARAMS + printf("** SJB - in nupa_eval()\n"); + printf("** SJB - processing line %3d: %s\n",linenum,s); + printf("** SJB - category '%c'\n",c); +#endif /* TRACE_NUMPARAMS */ + If c=='P' Then /* evaluate parameters */ + nupa_assignment( dico, dico->refptr[linenum] , 'N'); + ElsIf c=='B' Then /* substitute braces line */ + nupa_substitute( dico, dico->refptr[linenum], s, False); + ElsIf c=='X' Then /* compute args of subcircuit, if required */ + idef = findsubckt( dico, s, subname); + If idef>0 Then + nupa_subcktcall( dico, + dico->refptr[idef], dico->refptr[linenum], False); + Else + putlogfile('?',linenum, " illegal subckt call."); + EndIf + ElsIf c=='U' Then /* release local symbols = parameters */ + nupa_subcktexit( dico); + EndIf + putlogfile('e',linenum,s); + Inc(evalcount); +#ifdef TRACE_NUMPARAMS + ws("** SJB - --> "); ws(s); wln(); + ws("** SJB - leaving nupa_eval()"); wln(); wln(); +#endif /* TRACE_NUMPARAMS */ + return 1 +EndFunc + +Func int nupa_signal(int sig, Pchar info) +/* warning: deckcopy may come inside a recursion ! substart no! */ +/* info is context-dependent string data */ +Begin + putlogfile('!',sig, " Nupa Signal"); + If sig == NUPADECKCOPY Then + If firstsignal Then + nupa_init(info); + firstsignal=False; + EndIf + ElsIf sig == NUPASUBSTART Then + inexpansion=True + ElsIf sig == NUPASUBDONE Then + inexpansion=False + ElsIf sig == NUPAEVALDONE Then + nupa_done(); + firstsignal=True + EndIf + return 1 +EndFunc + +#ifdef USING_NUPATEST +/* This is use only by the nupatest program */ +Func tdico * nupa_fetchinstance(void) +Begin + return dico +EndFunc +#endif /* USING_NUPATEST */ diff --git a/src/frontend/numparam/washprog.c b/src/frontend/numparam/washprog.c new file mode 100644 index 000000000..a53f14d8d --- /dev/null +++ b/src/frontend/numparam/washprog.c @@ -0,0 +1,996 @@ +/* washprog.c Copyright (C) 2002 Georg Post + * + * This file is part of Numparam, see: readme.txt + * Free software under the terms of the GNU Lesser General Public License + */ + +/**** washprog: trivial text substitution utility. ****/ + +/* history: this was an exercise to make an 'intersection' language + of C and Java, that would look like Basic. A complete failure, of course. + + Now only used to clean my Basic/Pascal-contaminated C code. + With the rules file below, it destroys all those macros of mine for + quiche eaters, which seem offensive to C aficionados. + + Standard rules file needed : downgrad.txt + + Typical command line: ./washprog -r downgrad washprog.c + + There is no printf. Console Output/Input primitives are as follows: + wc ws wr wn wi wln rln + The bare-bones string(=Pchar) manipulation library is this: + pscopy streq str length upcase scopy sadd saddn cadd pos + +Format of substitution rules: + + s substitute. use "" around string if spaces inside. + w first string must be a whole word only + m macro substitution with args 1 2 3 ... + u macro with atomic args, no punctuation "(;,:)" inside. + x exclude text section from strng1 to strng2. + a dynamically add a new macro rule, if table space left. + + string: may contain special chars: ^A ... ^Z \n \" + macro1: string with "placeholders" 1 2 ... 9, in this order + macro2: may contain the "arguments" anywhere + non-arg digits in macro2 are prefixed 0 + + Heavy use of 3 string operations: + - pscopy() substring extraction. + - comparison: match(). + - spos() substring search + + added : special postprocessing for C to place the ; and } : +1. any ';' following a ';' or '}' is wiped out. +2. any ';' preceding a '}' is wiped out. +3. any remaining ';' on start of line is shifted to end of preceding one. +*/ + +#include /* NULL FILE fopen feof fgets fclose fputs fputc gets */ +#include "general.h" + +Cconst(nsub, 100+1) /*max nbr of substitution rules */ +Cconst(nargs, 11) /*max number of macro args + 1*/ +Cconst(wild,'æ') /* wildcard character in patterns */ +Cconst(joker,1) /* one-character placeholder */ +Cconst( Recursion, True) /* 20 % slower, re-substitute inside macro args */ + +Tarray(macargs, string, nargs) /* 0..9 macro copy args, 10: a wildcard */ + + /* global vars */ +short isr; /* nb of substitution rules */ +Bool cMode; /* a scanning options: c language mode */ +short lookmax; /* input lookahead max size */ +Pfile fout; /* file filled by: echoOut macroOut translate traduire */ + +Tarray(str40, char, 44) +Tarray(str80, char, 84) +Darray(search, str40, nsub) +Darray(replace, str80, nsub) +Str(nsub, srule); +Str(nsub, wildcard); + +/********* trivial io ***/ + +Proc wsf( Pchar s, short fmt) +Begin + short k; + For k=1; k<=fmt-length(s); Inc(k) Do + wc(' ') + Done + ws(s) +EndProc + +Proc wcf(char c, short fmt) +Begin + short k; + For k=1; k<=fmt-1; Inc(k) Do + wc(' ') + Done + wc(c) +EndProc + +Proc wif(long i, short fmt) +Begin /*default fmt=1*/ + Str(30, s); + nadd(s,i); + wsf(s,fmt) +EndProc + +Proc rln(Pchar s) /* 78 column limit */ +Begin + short i; Bool done; char c; + short max=maxlen(s); + If max>78 Then max=78 EndIf + i=0; done=False; + scopy(s,""); + While Not done Do + c=fgetc(stdin); + If (c>=' ') And (c<='~') And (i='0') And (c<='9'); + If num Then z= (short)( 10*z+ c - '0') EndIf + Until Not num EndRep + If (z>lookmax) And (z<255) Then + lookmax= z + EndIf + ws("Lookahead="); wi(lookmax); + EndIf + Done + wln(); +EndProc + +/******** matching routines *******/ + +Proc copySpace(Pchar s, Pchar t, short a, short b) /* a,b>0 ! Pascal indexing */ +Begin +/*echo any "nontrivial" whitespace t-->s */ + short lt,i,k, comment; + Bool leader; + char c; +/*-StartProc-*/ + scopy(s,""); + leader=False; /*leader space on new line...*/ + k=0; + comment=0; /* for C type whitespaces 1 And 2*/ + lt= length(t); + If b>lt Then b=lt EndIf + For i=(short)(a-1); i0) And (c<' ') Then leader=True EndIf + If cMode And (c=='/') And (t[i+1]=='*') Then comment=1 EndIf + If ((c>0) And (c<' ')) Or (leader And (c==' ')) Or (comment>0) Then + cadd(s,c); Inc(k); + EndIf + If (comment==1) And (c=='/') And (t[i-1]=='*') Then comment=0 EndIf + Done +EndProc + +Func short skipCwhite(Pchar t, short j, short lt) /* assume C indexing */ +Begin +/* skip any C And C++ type whitespace in t, from j to lt */ +/* returns j-1 If current char is no white at all! */ + char c; + short comment; /*types 1 And 2! */ + /*t[j] may already be '/' ? */ comment=0; + c=t[j]; /*If c>' ', we are done! */ + If (c>0) And (c<=' ') Then + Repeat + If (comment==0) And (c=='/') Then + If t[j+1]=='*' Then + comment=1 + ElsIf t[j+1]=='/' Then + comment=2 + EndIf + ElsIf (comment==1) And (c=='/') And (t[j-1]=='*') Then + comment=0 + ElsIf (comment==2) And (c==Lf) Then + comment=0 + EndIf + Inc(j); c=t[j]; + Until (j>lt) Or ((comment==0) And (c>' ')) EndRep + EndIf + return (short)(j-1); /* return last white-matching char position */ +EndProc + +Func Bool simple(Pchar s) +Begin /* check if no strange punctuations inside s */ + char c; + short i,ls; + Bool found; +/*-StartProc-*/ + ls=length(s); + i=0; + Repeat c=s[i]; + found=(c=='(') Or (c==')') Or (c==',') Or (c==';') Or (c==':'); + Inc(i); + Until found Or (i>=ls) EndRep + return Not found; +EndFunc + +Func Bool match(Pchar s, Pchar t, short n, short tstart) +Begin +/* test if t starts with substring s. + returns 0 If tstart is out of range. But n may be 0 ? + options: Singlechar wildcards "?" +*/ + short i,j,lt; + Bool ok; +/*-StartProc-*/ + i=0; j=tstart; + lt= length(t); + ok=(tstart0 Then /*Else return 0*/ + While (k<=b) And (Not ok) Do + ok=match(sub,s, a,k); /*remark we must start at k=0 ! */ + Inc(k); + Done + EndIf + If ok Then + return k + Else + return 0 + EndIf +EndFunc + +Func short matchwhite(Pchar s, Pchar t, short n, short tstart) +Begin +/* like match, but any whitespace in t matches space in s*/ + short i,j,lt; Bool ok; +/*-StartProc-*/ + i=0; j=tstart; + lt= length(t); + ok=(tstart0) Do Inc(j) Done + Dec(j); + EndIf + Repeat + Inc(j) + Until (j>=lt) Or (t[j]>' ') EndRep /*skip space in t*/ + Dec(j); + Else + ok= (j<=lt) And ((s[i]==t[j]) Or (s[i]==joker)); + EndIf + Inc(i); Inc(j); + Done + If ok Then + return (short)(j-tstart) + Else + return (short)0 + EndIf +EndFunc + +Func short posizero(Pchar sub, Pchar s) +Begin /*another Pos */ +/* substring search. like posi, but reject quotes & bracketed stuff */ + short a,b,k; + Bool ok; + short blevel; + char c; +/*-StartProc-*/ + ok=False; + a=length(sub); + b=(short)(length(s)-a); + k=0; blevel=0; + If a>0 Then /*Else return 0*/ + While (k<=b) And (Not ok) Do + ok= (matchwhite(sub,s, a,k)>0); + If (k<=b) And (Not ok) Then + c=s[k]; + If (c==')') Or (c==']') Or (c=='}') Then + If c!=sub[0] Then Dec(blevel) EndIf /*negative level: fail!*/ + If blevel<0 Then k=b EndIf + ElsIf (c=='\'') Or (c=='\"') Then /*skip quote */ + Repeat Inc(k) + Until (k>=b) Or (s[k]==c) EndRep + ElsIf (c=='(') Or (c=='[') Or (c=='{') Then /*skip block*/ + Inc(blevel); /*counts the bracketing level */ + Repeat + Inc(k); c=s[k]; + If (c=='(') Or (c=='[') Or (c=='{') Then + Inc(blevel) + ElsIf (c==')') Or (c==']') Or (c=='}') Then + Dec(blevel) + EndIf + Until (k>=b) Or (blevel==0) EndRep + EndIf + EndIf + Inc(k); + Done + EndIf + If ok Then + return k + Else + return 0 + EndIf +EndFunc + +Func short isMacro(Pchar s, char option, Pchar t, short tstart, + string maccopy[] ) +/* s= macro template, t=buffer, maccopy = arg Array + return value: number of characters matched, + restrictive option: 'u' + macro substitution args 1 2 3 ...9. + sample: bla1tra2gla3vla matches "bla ME tra YOU gla HIM vla" + substitute 1 by maccopy[1] etc +*/ +Begin + Darray(ps, short, nargs+1) + Word j,k,dk,ls, lst, lmt, jmax, pj; + Bool ok; + char arg; + Strbig(Llen,u); + Str(40,st); +/* returns >0 If comparison Ok == length of compared Pchar */ +/*-StartProc-*/ k=0; + ok= (s[0]==t[tstart]); /* shortcut: how much does it accelerate ? some % */ + If ok Then + ps[0]=0; + ps[nargs]=0; /*only 1..9 are valid data, 10 filler templates*/ + j=0; + Repeat + Inc(j); arg= (char)(j+'0'); + ps[j]= cpos(arg,s); + Until (j>=nargs) Or (ps[j]==0) EndRep + ls= length(s); + ps[j]=(short)(ls+1); /*For last template chunk*/ + jmax=j; j=1; + k=0; lmt=0; + Repeat + pscopy(st,s, (Word)(ps[j-1]+1), (Word)(ps[j]-ps[j-1]-1) ); + /*j-th template Pchar*/ lst=length(st); + If j==1 Then + If option=='u' Then + lmt= matchwhite(st,t,lst,tstart); + ok=(lmt>0) /*length of match in t*/ + Else + ok= match(st,t,lst,tstart) + EndIf + If ok Then + pscopy(u,t, (Word)(tstart+1), (Word)255); + pj=1 + Else + pj=0 + EndIf + Else + If option=='u' Then + pj= posizero(st,u); + If pj>0 Then lmt= matchwhite(st,u, lst, (short)(pj-1)) EndIf + Else + pj= posi(st,u) + EndIf /* qs[j]= k+pj; is position in t*/ + ok=(pj>0); + EndIf + If ok Then + If option=='u' Then + If j==1 Then scopy(maccopy[0],"") EndIf + saddn(maccopy[j-1],u, (Word)(pj-1)); + dk= (Word)(pj+lmt); + copySpace(maccopy[j], t, + (Word)(tstart+k+pj), (Word)(tstart+k+dk)); + /* space in t[k+pj...k+dk] goes into maccopy[j] as a prefix. */ + Else + pscopy(maccopy[j-1],u, (Word)1, (Word)(pj-1)); + /*the stuff preceding the marker*/ + dk= (Word)(pj+lst); /* start of unexplored part */ + EndIf + pscopy(u,u, (Word)dk, (Word)length(u)); /*shift in the rest*/ + k= (Word)(k+dk-1); + EndIf + Inc(j) + Until (j>jmax) Or (Not ok) EndRep + EndIf + If Not ok Then k=0 EndIf + return k +EndFunc + +Func short similar(Pchar s, char wilds, Pchar t, + short tstart, string maccopy[] ) +/* try to match s with t, then save the wildcard parts ins maccopy[] */ +/* s=template, t=buffer, wilds= number of wildcards, maccopy=substitute */ +/* return value: number of characters matched */ +Begin + Word j,k,ps,ls; + Bool ok; + char endc; + Strbig(Llen,u); +/* returns >0 if comparison Ok = length of compared string */ +/* char comparison, s may have wildcard regions with "æ" BUT 1 valid End */ +/*-StartProc-*/ + ls=length(s); + k=0; + If wilds==wild Then + ps= cpos(wild,s) + Else + ps=0 + EndIf + If ps==0 Then + If match(s,t,ls,tstart) Then + k=ls; + ps= cpos(joker,s); /*save joker's substitute*/ + If ps>0 Then + maccopy[nargs][0]=t[ps-1+tstart] + EndIf + Else + k=0 + EndIf + Else + k= (Word)(ps-1); + While s[k]==wild Do Inc(k) Done + endc=s[k]; /*End char to detect, at length */ + ok= match(s,t, (short)(ps-1), tstart); + If ok Then + pscopy(u,t, (Word)(ps+tstart), (Word)255); + j= cpos(endc, u); + ok=(j>0); + If ok Then + k= (Word)(ps+j-1); + pscopy(maccopy[nargs],t, (Word)(ps+tstart), (Word)(j-1)); + EndIf + EndIf + If Not ok Then k=0 EndIf + EndIf + return k +EndProc + +Func short addSubList(Pchar s, short isr) +/* add the rule s to the Rule list at isr */ +Begin + short j,ls; + char c,d,endc; + Bool start,stop; +/*-StartProc-*/ + ls=length(s); /* must kill the Newline */ + endc=' '; + While (ls>0) And (s[ls]<' ') Do Dec(ls) Done; + s[ls+1]=' '; + s[ls+2]=0; /* add a space */ + If s[0]=='o' Then + setOptions(s) + ElsIf (isr0) Then + j=1; + Inc(isr); + scopy(search[isr],""); scopy(replace[isr],""); + srule[isr]=(s[0]); + wildcard[isr]=0; + /*init search*/ + start=True; stop=False; + d=0; + While Not stop Do + Inc(j); c=s[j]; + If start Then + If c !=' ' Then + start=False; + If c=='\"' Then endc=c Else endc=' ' EndIf + EndIf + Else + stop=(c==endc) + EndIf + If Not (start Or (c==endc)) Then + If c=='?' Then + c=joker + ElsIf (c=='^') And (s[j+1]>= ' ') Then + Inc(j); c=s[j]; + If (c>='@') And (c<='_') Then + c= (char)(c-'@') + EndIf + ElsIf (c=='\\') And (s[j+1]>= ' ') Then + Inc(j); c=s[j]; + If c=='n' Then c= Cr; d=Lf EndIf + EndIf + cadd(search[isr],c); + If (c==wild) Or (c==joker) Then + wildcard[isr]=c + EndIf + If d!=0 Then + cadd(search[isr],d); + d=0 + EndIf + EndIf + Done + If endc!=' ' Then Inc(j) EndIf + /*init replace*/ + start=True; stop=False; + d=0; + While Not stop Do + Inc(j); c=s[j]; + If start Then + If c!=' ' Then + start=False; + If c=='\"' Then endc=c Else endc=' ' EndIf + EndIf + Else + stop=(c==endc) + EndIf + If Not (start Or (c==endc)) Then + If c=='?' Then + c=joker + ElsIf (c=='^') And (s[j+1]>= ' ') Then + Inc(j); c=s[j]; + If (c>='@') And (c<='Z') Then c= (char)(c-'@') EndIf + ElsIf (c=='\\') And (s[j+1]>= ' ') Then + Inc(j); c=s[j]; /*echo next char */ + If c=='n' Then c=Cr; d=Lf EndIf + EndIf + cadd(replace[isr],c); + If d!=0 Then + cadd(replace[isr],d); + d=0 + EndIf + EndIf + Done + If endc !=' ' Then Inc(j) EndIf + EndIf + If isr>=nsub Then + ws("No more room for rules."); wln() + EndIf + return isr +EndFunc + +Func Bool getSubList(Pchar slist) +/* read the search and substitution rule list */ +Begin + Strbig(Llen,s); + Pfile f; + Bool done, ok; +/*-StartProc-*/ + cMode=False; + lookmax= 80; /* or 250: handle 4 full lines maximum ? */ + If Zero(slist[0]) Then + scopy(slist, "slist.txt") + EndIf + f=fopen(slist,"rb"); + isr=0; + done= (f == Null); + ok= Not done; + While Not done Do + fgets(s,(short)80,f); + isr=addSubList(s,isr); + done= feof(f) + Done + If f != Null Then fclose(f) EndIf + ws("Number of rules: "); + wi(isr); wln(); + return ok +EndFunc + +Func Bool nonAlfa(char c) +Begin + return ((c<'a') Or (c>'z')) And ((c<'A') Or (c>'Z')) +EndFunc + +/********** optional output postprocessor **************/ + +/* the main translator calls these: + washinit to reset the postprocessor + washchar to output a char + washstring to output a string + washflush to terminate +*/ + +/* C reformatter, keeping an eye on the following (modulo whitespace): + ; } Lf. + + This is just a state machine, handling 3 rules using an output buffer obf. + means space excluding \n, and , space including newlines. + Wanted: regular-expression scripts or tricks to do the same or better... + + Rule1: Lf; --> ;Lf states 2 3 + Rule2: ;; --> ; state 1 + Rule3: }; --> } state 1 +*/ + +Bool washmore= True; /* flag that activates the postprocessor */ +Strbig(Llen,obf); /* output buffer */ +short iobf=0; /* its index */ +short wstate=0; /* output state machine */ + +Proc washinit(void) +Begin + iobf=0; + wstate=0 +EndProc + +Proc washchar(char c) +Begin /* state machine receives one character */ + short i; + If Not washmore Then /* never leave state 0 */ + fputc(c, fout) + ElsIf wstate==0 Then /* buffer empty */ + If (c==';') Or (c=='}') Then + iobf=0; obf[iobf]=c; + Inc(iobf); wstate=1 + ElsIf c<=' ' Then + iobf=0; obf[iobf]=c; + Inc(iobf); + If c==Lf Then wstate=3 Else wstate=2 EndIf + Else + fputc(c, fout) + EndIf + ElsIf wstate==1 Then + If c <= ' ' Then + obf[iobf]=c; Inc(iobf) + Else + If c != ';' Then + obf[iobf]=c; Inc(iobf) + EndIf + For i=0; i0) And (j0) And (j0; + If ok And (srule[i]=='w') Then + ok=nonAlfa(lastBf1) And nonAlfa(bf[sm]) + EndIf + If Not ok Then Inc(i) EndIf + Done + If ok Then + If (srule[i]=='m') Or (srule[i]=='u') Then + macroOut(replace[i], mac) + Else + echoOut(replace[i],wildcard[i], mac) + EndIf + lastBf1=bf[sm-1]; pscopy(bf,bf, (Word)(sm+1), (Word)255); + Inc(nbrep); + Else + lastBf1=bf[0]; + washchar(lastBf1); + pscopy(bf,bf, (Word)2, (Word)255); + EndIf + done= Zero(bf[0]) + Done +EndProc + +Proc translator( Pchar fname) +/* checks list of possible substitution rules sequentially. + Does the first that matches. Option: recursion. + BUG: is very slow. +*/ +Begin + Strbig(Llen, outname); Strbig(Llen,bf); + Bool done; + Darray( mac, string, nargs) + Pfile fin; + Bool ok; + short i,sm, exclusion, idot; + char c,lastBf1; + Word nbrep,nline; +/*-StartProc-*/ + For i=0; i0 if an exclusion rule is active */ + fin=fopen( fname, "rb"); + scopy(outname, fname); + idot= cpos('.',outname); + If idot <= 8 Then /* room for underbar prefix, even in Ms-dos */ + cins(outname,'_') + ElsIf NotZ(outname[0]) Then /* just erase first char */ + outname[0] = '_' + Else + scopy(outname,"washprog.out") + EndIf + fout=fopen( outname,"wb"); + washinit(); + done= (fin == Null) Or (fout == Null); + scopy(bf,""); + lastBf1=' '; + /* lookmax=80; handle a line maximum ! */ + While Not done Do + c=' '; + While (c !=0) And (length(bf)0 Then + i=exclusion; + sm=similar(replace[i], (char)0, bf, (short)0, mac); + ok= sm>0 + EndIf + If Zero(exclusion) Then + i=1; + While (i<=isr) And (Not ok) Do /*search for 1st match*/ + If (srule[i]=='m') Or (srule[i]=='u') Or (srule[i]=='a') Then + If alfa(lastBf1) And (alfa(search[i][0])) Then + sm=0 /*inside word*/ + Else + sm= isMacro(search[i], srule[i], bf, (short)0,mac) + EndIf + Else + sm=similar(search[i],wildcard[i],bf, (short)0, mac) + EndIf + ok=sm>0; + If ok And (srule[i]=='w') Then + ok=nonAlfa(lastBf1) And nonAlfa(bf[sm]) + EndIf + If Not ok Then Inc(i) EndIf + Done + EndIf + If ok Then + If (srule[i]=='m') Or (srule[i]=='u') Then + macroOut(replace[i], mac) + ElsIf srule[i]=='x' Then + If Zero(exclusion) Then + exclusion=i + Else + exclusion=0 + EndIf + ElsIf srule[i]=='a' Then + makeNewRule(replace[i],mac) + Else + echoOut(replace[i],wildcard[i],mac) + EndIf + lastBf1=bf[sm-1]; pscopy(bf,bf, (Word)(sm+1), (Word)lookmax); + Inc(nbrep); + Else + lastBf1=bf[0]; + If Zero(exclusion) Then washchar(lastBf1) EndIf; + pscopy(bf,bf, (Word)2, (Word)lookmax); + /*avoid this time-consuming buffer shuffling ?*/ + EndIf + done= Zero(bf[0]); + Done + If fout !=Null Then + washflush(); + fputc('\n', fout); + fclose(fout) + EndIf + If fin !=Null Then fclose(fin) EndIf + ws("Lines: "); wi(nline); + ws(" Replacements: "); + wi(nbrep); wln(); +EndProc + +Func int main( int argc, Pchar argv[]) +Begin + Str(80,dico); + short istart= 1; + Bool ok= True; +/*-StartProc-*/ + allocdata(); + scopy(dico,"downgrad"); /* default rules file */ + ws(" washprog: A text substitution utility"); wln(); + If (argc>2) And steq(argv[1],"-r") Then + scopy(dico,argv[2]); + istart= 3; +/* + Else + ws("Dictionary file (.TXT automatic): "); + rln(dico); +*/ + EndIf + If spos(".txt",dico) <=0 Then + sadd(dico,".txt") + EndIf + ok= getSubList(dico); /*list of substitution rules */ + While ok And (istart< argc) Do + If argv[istart][0] != '_' Then /* leading underbar not accepted */ + translator( argv[istart]) + EndIf + Inc(istart) + Done + return 0 +EndFunc + diff --git a/src/frontend/numparam/xpressn.c b/src/frontend/numparam/xpressn.c new file mode 100644 index 000000000..626863ead --- /dev/null +++ b/src/frontend/numparam/xpressn.c @@ -0,0 +1,1551 @@ +/* xpressn.c Copyright (C) 2002 Georg Post + * + * This file is part of Numparam, see: readme.txt + * Free software under the terms of the GNU Lesser General Public License + */ + +#include /* for function message() only. */ +#include + +#include "general.h" +#include "numparam.h" + +/************ keywords ************/ + +/* SJB - 150 chars is ample for this - see initkeys() */ +Intern Str(150, keys); /*all my keywords*/ +Intern Str(150, fmath); /* all math functions */ + +Intern +Proc initkeys(void) +/* the list of reserved words */ +Begin + scopy(keys, + "and or not div mod if else end while macro funct defined" + " include for to downto is var"); + stupcase(keys); + scopy(fmath, "sqr sqrt sin cos exp ln arctan abs pwr"); + stupcase(fmath); +EndProc + +Intern +Func double mathfunction(short f, double z, double x) +/* the list of built-in functions. Patch 'fmath' and here to get more ...*/ +Begin + double y; + Switch f + CaseOne 1 Is y= x*x + Case 2 Is y= sqrt(x) + Case 3 Is y= sin(x) + Case 4 Is y= cos(x) + Case 5 Is y= exp(x) + Case 6 Is y= ln(x) + Case 7 Is y= atan(x) + Case 8 Is y= fabs(x) + Case 9 Is y= exp( x* ln(fabs(z))) + /* pwr(,): the only one with 2 args */ + Default y=x EndSw + return y +EndFunc + +Cconst(Defd,12) +/* serial numb. of 'defined' keyword. The others are not used (yet) */ + +Intern +Func Bool message( tdico * dic, Pchar s) +/* record 'dic' should know about source file and line */ +Begin + Strbig(Llen,t); + Inc( dic->errcount); + If (dic->srcfile != Null) And NotZ(dic->srcfile[0]) Then + scopy(t, dic->srcfile); cadd(t,':') + EndIf + If dic->srcline >=0 Then + nadd(t,dic->srcline); sadd(t,": "); + EndIf + sadd(t,s); cadd(t,'\n'); + fputs(t,stderr); + return True /*error!*/ +EndFunc + +Proc debugwarn( tdico *d, Pchar s) +Begin + message(d,s); + Dec( d->errcount) +EndProc + +/************* historical: stubs for nodetable manager ************/ +/* in the full preprocessor version there was a node translator for spice2 */ + +Intern +Proc initsymbols(auxtable * n) +Begin +EndProc + +Intern +Proc donesymbols(auxtable * n) +Begin +EndProc + +/* Intern +Func short parsenode(auxtable *n, Pchar s) +Begin + return 0 +EndFunc +*/ + +/************ the input text symbol table (dictionary) *************/ + +Proc initdico(tdico * dico) +Begin + short i; + dico->nbd=0; + Sini(dico->option); + Sini(dico->srcfile); + dico->srcline= -1; + dico->errcount= 0; + For i=0; i<=Maxdico; Inc(i) Do + sini(dico->dat[i].nom,20) + Done + dico->tos= 0; + dico->stack[dico->tos]= 0; /* global data beneath */ + initsymbols(Addr(dico->nodetab)); + initkeys(); +EndProc + +/* local semantics for parameters inside a subckt */ +/* arguments as wll as .param expressions */ +/* to do: scope semantics ? + "params:" and all new symbols should have local scope inside subcircuits. + redefinition of old symbols gives a warning message. +*/ + +Cconst(Push,'u') +Cconst(Pop, 'o') + +Intern +Proc dicostack(tdico *dico, char op) +/* push or pop operation for nested subcircuit locals */ +Begin + + If op==Push Then + If dico->tos < (20-1) Then Inc(dico->tos) + Else message(dico, " Subckt Stack overflow") + EndIf + dico->stack [dico->tos]= dico->nbd; + ElsIf op==Pop Then + /* obsolete: undefine all data items of level dico->tos + For i=dico->nbd; i>0; Dec(i) Do + c= dico->dat[i].tp; + If ((c=='R') Or (c=='S')) And (dico->dat[i].level == dico->tos) Then + dico->dat[i].tp= '?' + EndIf + Done + */ + If dico->tos >0 Then + dico->nbd= dico->stack[dico->tos]; /* simply kill all local items */ + Dec(dico->tos) + Else message(dico," Subckt Stack underflow.") + EndIf + EndIf +EndProc + +Func short donedico(tdico * dico) +Begin + short sze= dico->nbd; + donesymbols(Addr(dico->nodetab)); + return sze; +EndProc + +Intern +Func short entrynb( tdico * d, Pchar s) +/* symbol lookup from end to start, for stacked local symbols .*/ +/* bug: sometimes we need access to same-name symbol, at lower level? */ +Begin + short i; + Bool ok; + ok=False; + i=d->nbd+1; + While (Not ok) And (i>1) Do + Dec(i); + ok= steq(d->dat[i].nom, s); + Done + If Not ok Then + return 0 + Else + return i + EndIf +EndFunc + +Func char getidtype( tdico *d, Pchar s) +/* test if identifier s is known. Answer its type, or '?' if not in list */ +Begin + char itp='?'; /* assume unknown */ + short i= entrynb(d, s); + If i >0 Then itp= d->dat[i].tp EndIf + return itp +EndFunc + +Intern +Func double fetchnumentry( + tdico * dico, + Pchar t, + Bool * perr) +Begin + Bool err= *perr; + Word k; + double u; + Strbig(Llen, s); + k=entrynb(dico,t); /*no keyword*/ + /*dbg -- If k<=0 Then ws("Dico num lookup fails. ") EndIf */ + While (k>0) And (dico->dat[k].tp=='P') Do + k= dico->dat[k].ivl + Done /*pointer chain*/ + If k>0 Then + If dico->dat[k].tp!='R' Then k=0 EndIf + EndIf + If k>0 Then + u=dico->dat[k].vl + Else + u=0.0; + scopy(s,"Undefined number ["); sadd(s,t); cadd(s,']'); + err=message( dico, s) + EndIf + *perr= err; + return u +EndFunc + +/******* writing dictionary entries *********/ + +Intern +Func short attrib( tdico * dico, Pchar t, char op) +Begin +/* seek or attribute dico entry number for string t. + Option op='N' : force a new entry, if tos>level and old is valid. +*/ + short i; + Bool ok; + i=dico->nbd+1; + ok=False; + While (Not ok) And (i>1) Do /*search old*/ + Dec(i); + ok= steq(dico->dat[i].nom,t); + Done + If ok And (op=='N') + And ( dico->dat[i].level < dico->tos) + And ( dico->dat[i].tp != '?') + Then ok=False EndIf + If Not ok Then + Inc(dico->nbd); + i= dico->nbd; + If dico->nbd > Maxdico Then + i=0 + Else + scopy(dico->dat[i].nom,t); + dico->dat[i].tp='?'; /*signal Unknown*/ + dico->dat[i].level= dico->tos; + EndIf + EndIf + return i +EndFunc + +Intern +Func Bool define( + tdico * dico, + Pchar t, /* identifier to define */ + char op, /* option */ + char tpe, /* type marker */ + double z, /* float value if any */ + Word w, /* integer value if any */ + Pchar base) /* string pointer if any */ +Begin +/*define t as real or integer, + opcode= 'N' impose a new item under local conditions. + check for pointers, too, in full macrolanguage version: + Call with 'N','P',0.0, ksymbol ... for VAR parameter passing. + Overwrite warning, beware: During 1st pass (macro definition), + we already make symbol entries which are dummy globals ! + we mark each id with its subckt level, and warn if write at higher one. +*/ + short i; + char c; + Bool err, warn; + Strbig(Llen,v); + i=attrib(dico,t,op); + err=False; + If i<=0 Then + err=message( dico," Symbol table overflow") + Else + If dico->dat[i].tp=='P' Then + i= dico->dat[i].ivl + EndIf; /*pointer indirection*/ + If i>0 Then + c=dico->dat[i].tp + Else + c=' ' + EndIf + If (c=='R') Or (c=='S') Or (c=='?') Then + dico->dat[i].vl=z; + dico->dat[i].tp=tpe; + dico->dat[i].ivl=w; + dico->dat[i].sbbase= base; + /* If (c !='?') And (i<= dico->stack[dico->tos]) Then */ + If c=='?' Then + dico->dat[i].level= dico->tos + EndIf /* promote! */ + If dico->dat[i].level < dico->tos Then + /* warn about re-write to a global scope! */ + scopy(v,t); cadd(v,':'); + nadd(v,dico->dat[i].level); + sadd(v," overwritten."); + warn=message( dico,v); + EndIf + Else + scopy(v,t); + sadd(v,": cannot redefine"); + err=message( dico,v); + EndIf + EndIf + return err; +EndFunc + +Func Bool defsubckt(tdico *dico, Pchar s, Word w, char categ) +/* called on 1st pass of spice source code, + to enter subcircuit (categ=U) and model (categ=O) names +*/ +Begin + Str(80,u); + Bool err; + short i,j,ls; + ls=length(s); + i=0; + While (i' ') Do Inc(i) Done + While (i' ') Do Inc(j) Done + If (j>i) And alfa(s[i]) Then + pscopy(u,s, i+1, j-i); + stupcase(u); + err= define( dico, u, ' ',categ, 0.0, w, Null); + Else + err= message( dico,"Subcircuit or Model without name."); + EndIf + return err +EndFunc + +Func short findsubckt( tdico *dico, Pchar s, Pchar subname) +/* input: s is a subcircuit invocation line. + returns 0 if not found, else the stored definition line number value + and the name in string subname */ +Begin + Str(80,u); /* u= subckt name is last token in string s */ + short i,j,k; + k=length(s); + While (k>=0) And (s[k]<=' ') Do Dec(k) Done + j=k; + While (k>=0) And (s[k]>' ') Do Dec(k) Done + pscopy(u,s, k+2, j-k); + stupcase(u); + i= entrynb(dico,u); + If (i>0) And (dico->dat[i].tp == 'U') Then + i= dico->dat[i].ivl; + scopy(subname,u) + Else + i= 0; + scopy(subname,""); + message(dico, "Cannot find subcircuit."); + EndIf + return i +EndFunc + +#if 0 /* unused, from the full macro language... */ +Intern +Func short deffuma( /* define function or macro entry. */ + tdico * dico, Pchar t, char tpe, Word bufstart, + Bool * pjumped, Bool * perr) +Begin + Bool jumped= *pjumped; Bool err= *perr; +/* if not jumped, define new function or macro, returns index to buffferstart + if jumped, return index to existing function +*/ + short i,j; + Strbig(Llen, v); + i=attrib(dico,t,' '); j=0; + If i<=0 Then + err=message( dico," Symbol table overflow") + Else + If dico->dat[i].tp != '?' Then /*old item!*/ + If jumped Then + j=dico->dat[i].ivl + Else + scopy(v,t); sadd(v," already defined"); + err=message( dico,v) + EndIf + Else + dico->dat[i].tp=tpe; + Inc(dico->nfms); j=dico->nfms; + dico->dat[i].ivl=j; + dico->fms[j].start= bufstart; /* =ibf->bufaddr = start addr in buffer */ + EndIf + EndIf + *pjumped= jumped; + *perr= err; + return j; +EndFunc +#endif + +/************ input scanner stuff **************/ + +Intern +Func Byte keyword( Pchar keys, Pchar t) +Begin +/* return 0 if t not found in list keys, else the ordinal number */ + Byte i,j,k; + short lt,lk; + Bool ok; + lt=length(t); + lk=length(keys); + k=0; j=0; + Repeat + Inc(j); + i=0; ok=True; + Repeat + Inc(i); Inc(k); + ok= (k<=lk) And (t[i-1]==keys[k-1]); + Until (Not ok) Or (i>=lt) EndRep + If ok Then + ok=(k==lk) Or (keys[k]<=' ') + EndIf + If Not ok And (k' ') Do Inc(k) Done + EndIf + Until ok Or (k>=lk) EndRep + If ok Then + return j + Else + return 0 + EndIf +EndFunc + +Intern +Func double parseunit( double x, Pchar s) +/* the Spice suffixes */ +Begin + double u; + Str(20, t); + Bool isunit; + isunit=True; + pscopy(t,s,1,3); + If steq(t,"MEG") Then + u=1e6 + ElsIf s[0]=='G' Then + u=1e9 + ElsIf s[0]=='K' Then + u=1e3 + ElsIf s[0]=='M' Then + u=0.001 + ElsIf s[0]=='U' Then + u=1e-6 + ElsIf s[0]=='N' Then + u=1e-9 + ElsIf s[0]=='P' Then + u=1e-12 + ElsIf s[0]=='F' Then + u=1e-15 + Else + isunit=False + EndIf + If isunit Then x=x*u EndIf + return x +EndFunc + +Intern +Func short fetchid( + Pchar s, Pchar t, + short ls, short i) +/* copy next identifier from s into t, advance and return scan index i */ +Begin + char c; + Bool ok; + c=s[i-1]; + While (Not alfa(c)) And (i='0') And (c<='9')) Or ((c>='A') And (c<='Z')); + If ok Then cadd(t,c) EndIf + Until Not ok EndRep + return i /*return updated i */ +EndFunc + +Intern +Func double exists( + tdico * d, + Pchar s, + short * pi, + Bool * perror) +/* check if s in smboltable 'defined': expect (ident) and return 0 or 1 */ +Begin + Bool error= *perror; + short i= *pi; + double x; + short ls; + char c; + Bool ok; + Strbig(Llen, t); + ls=length(s); + x=0.0; + Repeat + Inc(i); + If i>ls Then + c=Nul + Else + c=s[i-1] + EndIf; + ok= (c=='(') + Until ok Or (c==Nul) EndRep + If ok Then + i=fetchid(s,t, ls,i); Dec(i); + If entrynb(d,t)>0 Then x=1.0 EndIf + Repeat + Inc(i); + If i>ls Then + c=Nul + Else + c=s[i-1] + EndIf + ok= (c==')') + Until ok Or (c==Nul) EndRep + EndIf + If Not ok Then + error=message( d," Defined() syntax"); + EndIf /*keep pointer on last closing ")" */ + *perror= error; + *pi=i; + return x; +EndFunc + +Intern +Func double fetchnumber( tdico *dico, + Pchar s, short ls, + short * pi, + Bool * perror) +/* parse a Spice number in string s */ +Begin + Bool error= *perror; + short i= *pi; + short k,err; + char d; + Str(20, t); + Strbig(Llen, v); + double u; + k=i; + Repeat + Inc(k); + If k>ls Then + d=chr(0) + Else + d=s[k-1] + EndIf + Until Not ((d=='.') Or ((d>='0') And (d<='9'))) EndRep + If (d=='e') Or (d=='E') Then /*exponent follows*/ + Inc(k); d=s[k-1]; + If (d=='+') Or (d=='-') Then Inc(k) EndIf + Repeat + Inc(k); + If k>ls Then + d=chr(0) + Else + d=s[k-1] + EndIf + Until Not ((d>='0') And (d<='9')) EndRep + EndIf + pscopy(t,s,i, k-i); + If t[0]=='.' Then + cins(t,'0') + ElsIf t[length(t)-1]=='.' Then + cadd(t,'0') + EndIf + u= rval(t, Addr(err)); + If err!=0 Then + scopy(v,"Number format error: "); + sadd(v,t); + error=message( dico,v) + Else + scopy(t,""); + While alfa(d) Do + cadd(t,upcase(d)); + Inc(k); + If k>ls Then + d=Nul + Else + d=s[k-1] + EndIf + Done + u=parseunit(u,t); + EndIf + i=k-1; + *perror= error; + *pi=i; + return u; +EndFunc + +Intern +Func char fetchoperator( tdico *dico, + Pchar s, short ls, + short * pi, + Byte * pstate, Byte * plevel, + Bool * perror) +/* grab an operator from string s and advance scan index pi. + each operator has: one-char alias, precedence level, new interpreter state. +*/ +Begin + short i= *pi; + Byte state= *pstate; + Byte level= *plevel; + Bool error= *perror; + char c,d; + Strbig(Llen, v); + c=s[i-1]; + If i') Then + c='#'; Inc(i) + ElsIf (c=='<') And (d=='=') Then + c='L'; Inc(i) + ElsIf (c=='>') And (d=='=') Then + c='G'; Inc(i) + ElsIf (c=='*') And (d=='*') Then + c='^'; Inc(i) + ElsIf (c=='=') And (d=='=') Then + Inc(i) + ElsIf (c=='&') And (d=='&') Then + Inc(i) + ElsIf (c=='|') And (d=='|') Then + Inc(i) + EndIf; + If (c=='+') Or (c=='-') Then + state=2; /*pending operator*/ + level=4; + ElsIf (c=='*')Or (c=='/') Or (c=='%')Or(c=='\\') Then + state=2; level=3; + ElsIf c=='^' Then + state=2; level=2; + ElsIf cpos(c,"=<>#GL") >0 Then + state=2; level= 5; + ElsIf c=='&' Then + state=2; level=6; + ElsIf c=='|' Then + state=2; level=7; + ElsIf c=='!' Then + state=3; + Else state=0; + If c>' ' Then + scopy(v,"Syntax error: letter ["); + cadd(v,c); cadd(v,']'); + error=message( dico,v); + EndIf + EndIf + *pi=i; + *pstate=state; + *plevel=level; + *perror=error; + return c; +EndFunc + +Intern +Func char opfunctkey( tdico *dico, + Byte kw, char c, + Byte * pstate, Byte * plevel, Bool * perror) +/* handle operator and built-in keywords */ +Begin + Byte state= *pstate; + Byte level= *plevel; + Bool error= *perror; +/*if kw operator keyword, c=token*/ + Switch kw /*AND OR NOT DIV MOD Defined*/ + CaseOne 1 Is + c='&'; state=2; level=6 + Case 2 Is + c='|'; state=2; level=7 + Case 3 Is + c='!'; state=3; level=1 + Case 4 Is + c='\\'; state=2; level=3 + Case 5 Is + c='%'; state=2; level=3 + Case Defd Is + c='?'; state=1; level=0 + Default + state=0; + error=message( dico," Unexpected Keyword"); + EndSw /*case*/ + *pstate=state; + *plevel=level; + *perror=error; + return c +EndFunc + +Intern +Func double operate( + char op, + double x, + double y) +Begin +/* execute operator op on a pair of reals */ +/* bug: x:=x op y or simply x:=y for empty op? No error signalling! */ + double u=1.0; + double z=0.0; + double epsi=1e-30; + double t; + Switch op + CaseOne ' ' Is + x=y; /*problem here: do type conversions ?! */ + Case '+' Is + x=x+y; + Case '-' Is + x=x-y; + Case '*' Is + x=x*y; + Case '/' Is + If absf(y)>epsi Then x=x/y EndIf + Case '^' Is /*power*/ + t=absf(x); + If tx Then x=y EndIf; /*=Max*/ + Case '=' Is + If x == y Then x=u Else x=z EndIf; + Case '#' Is /*<>*/ + If x != y Then x=u Else x=z EndIf; + Case '>' Is + If x>y Then x=u Else x=z EndIf; + Case '<' Is + If x=*/ + If x>=y Then x=u Else x=z EndIf; + Case 'L' Is /*<=*/ + If x<=y Then x=u Else x=z EndIf; + Case '!' Is /*Not*/ + If y==z Then x=u Else x=z EndIf; + Case '%' Is /*Mod*/ + t= np_trunc(x/y); + x= x-y*t + Case '\\' Is /*Div*/ + x= np_trunc(absf(x/y)); + EndSw /*case*/ + return x; +EndFunc + +Intern +Func double formula( + tdico * dico, + Pchar s, + Bool * perror) +Begin +/* Expression parser. + s is a formula with parentheses and math ops +-* / ... + State machine and an array of accumulators handle operator precedence. + Parentheses handled by recursion. + Empty expression is forbidden: must find at least 1 atom. + Syntax error if no toggle between binoperator And (unop/state1) ! + States : 1=atom, 2=binOp, 3=unOp, 4= stop-codon. + Allowed transitions: 1->2->(3,1) and 3->(3,1). +*/ + Cconst(nprece,9) /*maximal nb of precedence levels*/ + Bool error= *perror; + Byte state,oldstate, topop,ustack, level, kw, fu; + double u=0.0,v; + double accu[nprece+1]; + char oper[nprece+1]; + char uop[nprece+1]; + short i,k,ls,natom, arg2; + char c,d; + Strbig(Llen, t); + Bool ok; + For i=0; i<=nprece; Inc(i) Do + accu[i]=0.0; oper[i]=' ' + Done + i=0; + ls=length(s); + While(ls>0) And (s[ls-1]<=' ') Do Dec(ls) Done /*clean s*/ + state=0; natom=0; ustack=0; + topop=0; oldstate=0; fu=0; + error=False; + While (ils Then + d=chr(0) + Else + d=s[k-1] + EndIf + If d=='(' Then + Inc(level) + ElsIf d==')' Then + Dec(level) + EndIf + If (d==',') And (level==1) Then arg2=k EndIf /* comma list? */ + Until (k>ls) Or ((d==')') And (level<=0)) EndRep + If k>ls Then + error=message( dico,"Closing \")\" not found."); + Inc(natom); /*shut up other error message*/ + Else + If arg2 > i Then + pscopy(t,s,i+1, arg2-i-1); + v=formula( dico, t, Addr(error)); + i=arg2; + EndIf + pscopy(t,s,i+1, k-i-1); + u=formula( dico, t, Addr(error)); + state=1; /*atom*/ + If fu>0 Then + u= mathfunction(fu,v,u) + EndIf + EndIf + i=k; fu=0; + ElsIf alfa(c) Then + i=fetchid(s,t, ls,i); /*user id, but sort out keywords*/ + state=1; + Dec(i); + kw=keyword(keys,t); /*debug ws('[',kw,']'); */ + If kw==0 Then + fu= keyword(fmath,t); /* numeric function? */ + If fu==0 Then + u=fetchnumentry( dico, t, Addr(error)) + Else + state=0 + EndIf /* state==0 means: ignore for the moment */ + Else + c=opfunctkey( dico, kw,c, Addr(state), Addr(level) ,Addr(error)) + EndIf + If kw==Defd Then + u=exists( dico, s, Addr(i), Addr(error)) + EndIf + ElsIf ((c=='.') Or ((c>='0') And (c<='9'))) Then + u=fetchnumber( dico, s,ls, Addr(i), Addr(error)); + state=1; + Else + c=fetchoperator(dico, s,ls, + Addr(i), Addr(state),Addr(level),Addr(error)); + /*may change c to some other operator char!*/ + EndIf /* control chars <' ' ignored*/ + ok= (oldstate==0) Or (state==0) Or + ((oldstate==1) And (state==2)) Or ((oldstate!=1)And(state!=2)); + If Not ok Then + error=message( dico," Misplaced operator") + EndIf + If state==3 Then /*push unary operator*/ + Inc(ustack); + uop[ustack]=c; + ElsIf state==1 Then /*atom pending*/ Inc(natom); + If i>=ls Then + state=4; level=topop + EndIf /*close all ops below*/ + For k=ustack; k>=1; Dec(k) Do + u=operate(uop[k],u,u) + Done + ustack=0; + accu[0]=u; /* done: all pending unary operators */ + EndIf + If (state==2) Or (state==4) Then + /* do pending binaries of priority Upto "level" */ + For k=1; k<=level; Inc(k) Do /* not yet speed optimized! */ + accu[k]=operate(oper[k],accu[k],accu[k-1]); + accu[k-1]=0.0; + oper[k]=' '; /*reset intermediates*/ + Done + oper[level]=c; + If level>topop Then topop=level EndIf + EndIf + If (state>0) Then oldstate=state EndIf + Done /*while*/; + If (natom==0) Or (oldstate!=4) Then + scopy(t," Expression err: "); + sadd(t,s); + error=message( dico,t) + EndIf + *perror= error; + If error Then + return 1.0 + Else + return accu[topop] + EndIf +EndFunc /*formula*/ + +Intern +Func char fmttype( double x) +Begin +/* I=integer, P=fixedpoint F=floatpoint*/ +/* find out the "natural" type of format for number x*/ + double ax,dx; + short rx; + Bool isint,astronomic; + ax=absf(x); + isint=False; + astronomic=False; + If ax<1e-30 Then + isint=True; + ElsIf ax<32000 Then /*detect integers*/ rx=np_round(x); + dx=(x-rx)/ax; + isint=(absf(dx)<1e-6); + EndIf + If Not isint Then + astronomic= (ax>=1e6) Or (ax<0.01) + EndIf + If isint Then + return 'I' + ElsIf astronomic Then + return 'F' + Else + return 'P' + EndIf +EndFunc + +Intern +Func Bool evaluate( + tdico * dico, + Pchar q, + Pchar t, + Byte mode) +Begin +/* transform t to result q. mode 0: expression, mode 1: simple variable */ + double u=0.0; + short k,j,lq; + char dt,fmt; + Bool numeric, done, nolookup; + Bool err; + Strbig(Llen, v); + scopy(q,""); + numeric=False; err=False; + If mode==1 Then /*string?*/ + stupcase(t); + k=entrynb(dico,t); + nolookup= ( k<=0 ); + While (k>0) And (dico->dat[k].tp=='P') Do + k=dico->dat[k].ivl + Done + /*pointer chain*/ + If k>0 Then + dt=dico->dat[k].tp + Else + dt=' ' + EndIf; + /*data type: Real or String*/ + If dt=='R' Then + u=dico->dat[k].vl; numeric=True + ElsIf dt=='S' Then /*suppose source text "..." at*/ + j=dico->dat[k].ivl; + lq=0; + Repeat + Inc(j); Inc(lq); + dt= /*ibf->bf[j]; */ dico->dat[k].sbbase[j]; + If cpos('3',dico->option)<=0 Then + dt=upcase(dt) + EndIf /* spice-2 */ + done= (dt=='\"') Or (dt<' ') Or (lq>99); + If Not done Then cadd(q,dt) EndIf + Until done EndRep + Else k=0 EndIf + If k <= 0 Then + scopy(v,""); + cadd(v,'\"'); sadd(v,t); + sadd(v,"\" not evaluated. "); + If nolookup Then sadd(v,"Lookup failure.") EndIf + err=message( dico,v) + EndIf + Else + u=formula( dico, t, Addr(err)); + numeric=True + EndIf + If numeric Then + fmt= fmttype(u); + If fmt=='I' Then + stri(np_round(u), q) + Else + strf(u,6,-1,q) + EndIf /* strf() arg 2 doesnt work: always >10 significant digits ! */ + EndIf + return err; +EndFunc + +#if 0 +Intern +Func Bool scanline( + tdico * dico, + Pchar s, Pchar r, + Bool err) +/* scan host code line s for macro substitution. r=result line */ +Begin + short i,k,ls,level,nd, nnest; + Bool spice3; + char c,d; + Strbig(Llen, q); + Strbig(Llen, t); + Str(20, u); + spice3= cpos('3', dico->option) >0; /* we had -3 on the command line */ + i=0; ls=length(s); + scopy(r,""); + err=False; + pscopy(u,s,1,3); + If (ls>7) And steq(u,"**&") Then /*special Comment **&AC #...*/ + pscopy(r,s,1,7); + i=7 + EndIf + While (ils Then + d=chr(0) + Else + d=s[k-1] + EndIf + If d=='(' Then + Inc(level) + ElsIf d==')' Then + Dec(level) + EndIf + Until (k>ls) Or ((d==')') And (level<=0)) EndRep + If k>ls Then + err=message( dico,"Closing \")\" not found."); + Else + pscopy(t,s,i+1, k-i-1); + err=evaluate( dico, q,t,0); + EndIf + i=k; + Else /*simple identifier may also be string*/ + Repeat + Inc(k); + If k>ls Then + d=chr(0) + Else + d=s[k-1] + EndIf + Until (k>ls) Or (d<=' ') EndRep + pscopy(t,s,i,k-i); + err=evaluate( dico, q,t,1); + i=k-1; + EndIf + If Not err Then /*insert the number*/ + sadd(r,q) + Else + message( dico,s) + EndIf + ElsIf c==Nodekey Then /*follows: a node keyword*/ + Repeat + Inc(i) + Until s[i-1]>' ' EndRep + k=i; + Repeat + Inc(k) + Until (k>ls) Or Not alfanum(s[k-1]) EndRep + pscopy(q,s,i,k-i); + nd=parsenode( Addr(dico->nodetab), q); + If Not spice3 Then + stri(nd,q) + EndIf; /* substitute by number */ + sadd(r,q); + i=k-1; + Else + If Not spice3 Then c=upcase(c) EndIf + cadd(r,c); /*c<>Intro*/ + EndIf + Done /*while*/ + return err; +EndFunc +#endif + +/********* interface functions for spice3f5 extension ***********/ + +Intern +Proc compactfloatnb(Pchar v) +/* try to squeeze a floating pt format to 10 characters */ +/* erase superfluous 000 digit streams before E */ +/* bug: truncating, no rounding */ +Begin + short n,k, lex; + Str(20,expo); + n=cpos('E',v); /* if too long, try to delete digits */ + If n >3 Then + pscopy(expo, v, n,length(v)); + lex= length(expo); + k=n-2; /* mantissa is 0...k */ + While (v[k]=='0') And (v[k-1]=='0') Do Dec(k) Done + If (k+1+lex) > 10 Then k= 9-lex EndIf + pscopy(v,v, 1,k+1); + sadd(v,expo); + EndIf +EndProc + +Intern +Func short insertnumber(tdico *dico, short i, Pchar s, Pchar u) +/* insert u in string s in place of the next placeholder number */ +Begin + Str(40,v); + Str(80,msg); + Bool found; + short ls, k; + long accu; + ls= length(s); + scopy(v,u); + compactfloatnb(v); + While length(v)<10 Do + cadd(v,' ') + Done + If length(v)>10 Then + scopy(msg," insertnumber fails: "); + sadd(msg,u); + message( dico, msg) + EndIf + found=False; + While (Not found) And (i0) And (accu<2000) + EndIf + Inc(i) + Done + If found Then /* substitute at i-1 */ + Dec(i); + For k=0; k<10; Inc(k) Do s[i+k]= v[k] Done + i= i+10; + Else + i= ls; + message( dico,"insertnumber: missing slot "); + EndIf + return i +EndFunc + +Func Bool nupa_substitute( tdico *dico, Pchar s, Pchar r, Bool err) +/* s: pointer to original source line. + r: pointer to result line, already heavily modified wrt s + anywhere we find a 10-char numstring in r, substitute it. + bug: wont flag overflow! +*/ +Begin + short i,k,ls,level, nnest, ir; + char c,d; + Strbig(Llen, q); + Strbig(Llen, t); + i=0; + ls=length(s); + err=False; + ir=0; + While (ils Then + d=chr(0) + Else + d=s[k-1] + EndIf + If d=='(' Then + Inc(level) + ElsIf d==')' Then + Dec(level) + EndIf + Until (k>ls) Or ((d==')') And (level<=0)) EndRep + If k>ls Then + err=message( dico,"Closing \")\" not found."); + Else + pscopy(t,s,i+1, k-i-1); + err=evaluate( dico, q,t,0); + EndIf + i=k; + Else /*simple identifier may also be string? */ + Repeat + Inc(k); + If k>ls Then + d=chr(0) + Else + d=s[k-1] + EndIf + Until (k>ls) Or (d<=' ') EndRep + pscopy(t,s,i,k-i); + err=evaluate( dico, q,t,1); + i= k-1; + EndIf + If Not err Then + ir= insertnumber(dico, ir, r,q) + Else + message( dico, "Cannot compute &(expression)") + EndIf + EndIf + Done /*while*/ + return err +EndFunc + +Intern +Func Byte getword( + Pchar s, Pchar t, + Byte after, + short * pi) +/* isolate a word from s after position "after". return i= last read+1 */ +Begin + short i= *pi; + short ls; + Byte key; + i=after; + ls=length(s); + Repeat + Inc(i) + Until (i>=ls) Or alfa(s[i-1]) EndRep + scopy(t,""); + While (i<=ls) And (alfa(s[i-1]) Or num(s[i-1])) Do + cadd(t,upcase(s[i-1])); + Inc(i); + Done + If NotZ(t[0]) Then + key=keyword(keys,t) + Else + key=0 + EndIf + *pi=i; + return key; +EndFunc + +Intern +Func char getexpress( Pchar s, Pchar t, short * pi) +/* returns expression-like string until next separator + Input i=position before expr, output i=just after expr, on separator. + returns tpe=='R' If numeric, 'S' If string only +*/ +Begin + short i= *pi; + short ia,ls,level; + char c,d, tpe; + Bool comment= False; + ls=length(s); + ia=i+1; + While (ials) Or (s[i-1] >' ') EndRep + Else + If s[ia-1]=='{' Then Inc(ia) EndIf + i= ia-1; + Repeat + Inc(i); + If i>ls Then + c=';' + Else + c=s[i-1] + EndIf + If c=='(' Then /*sub-formula*/ + level=1; + Repeat + Inc(i); + If i>ls Then + d=Nul + Else + d=s[i-1] + EndIf + If d=='(' Then + Inc(level) + ElsIf d==')' Then + Dec(level) + EndIf + Until (i>ls) Or ((d==')') And (level<=0)) EndRep + EndIf + /* buggy? */ If (c=='/') Or (c=='-') Then comment= (s[i]==c) EndIf + Until (cpos(c, ",;)}") >0) Or comment EndRep /*legal separators*/ + tpe='R'; + EndIf + pscopy(t,s,ia,i-ia); + If s[i-1]=='}' Then Inc(i) EndIf + If tpe=='S' Then Inc(i) EndIf /* beyond quote */ + *pi=i; + return tpe; +EndFunc + +Func Bool nupa_assignment( tdico *dico, Pchar s, char mode) +/* is called for all 'Param' lines of the input file. + is also called for the params: section of a subckt . + mode='N' define new local variable, else global... + bug: we cannot rely on the transformed line, must re-parse everything! +*/ +Begin +/* s has the format: ident = expression; ident= expression ... */ + Strbig(Llen, t); + Strbig(Llen,u); + short i,j, ls; + Byte key; + Bool error, err; + char dtype; + Word wval=0; + double rval= 0.0; + ls=length(s); + error=False; + i=0; + j= spos("//", s); /* stop before comment if any */ + If j>0 Then ls= j-1 EndIf + /* bug: doesnt work. need to revise getexpress ... !!! */ + i=0; + While (i' ' Do Inc(i) Done + EndIf + While (i0) Then + error=message( dico," Identifier expected") + EndIf + If Not error Then /* assignment expressions */ + While (i<=ls) And (s[i-1] !='=') Do Inc(i) Done + If i>ls Then + error= message( dico," = sign expected .") + EndIf + dtype=getexpress(s,u, Addr(i)); + If dtype=='R' Then + rval=formula( dico, u, Addr(error)); + If error Then + message( dico," Formula() error.") + EndIf + ElsIf dtype=='S' Then + wval= i + EndIf + err=define(dico,t, mode /*was ' ' */ , dtype,rval,wval,Null); + error= error Or err; + EndIf + If (i0 Then pscopy(t,s,1,j-1) Else scopy(t,s) EndIf + stupcase(t); + j= spos("SUBCKT", t); + If j>0 Then + j= j +6; /* fetch its name */ + While (j0 Then + pscopy(t,t, i+7, length(t)); + While j=cpos('=',t), j>0 Do /* isolate idents to the left of =-signs */ + k= j-2; + While (k>=0) And (t[k]<=' ') Do Dec(k) Done + h=k; + While (h>=0) And alfanum(t[h]) Do Dec(h) Done + If alfa(t[h+1]) And (k>h) Then /* we have some id */ + For m=(h+1); m<=k; Inc(m) Do + cadd(idlist,t[m]) + Done + sadd(idlist,"=$;"); + Inc(n); + Else + message( dico,"identifier expected.") + EndIf + pscopy(t,t, j+1, length(t)); + Done + EndIf + /***** next, analyze the circuit call line */ + If Not err Then + narg=0; + j=spos("//",x); + If j>0 Then pscopy(t,x,1,j-1) Else scopy(t,x) EndIf + stupcase(t); + ls=length(t); + j= spos(subname,t); + If j>0 Then + j=j + length(subname) -1; /* 1st position of arglist: j */ + While (j0) And (g ' ' Do Inc(k) Done + pscopy(u,t, h+1, k-h); + j= k; + ElsIf t[k]=='{' Then + getexpress(t,u, Addr(j)); + Dec(j); /* confusion: j was in Turbo Pascal convention */ + Else + Inc(j); + If t[k]>' ' Then + scopy(v,"Subckt call, symbol "); + cadd(v,t[k]); + sadd(v," not understood"); + message( dico,v); + EndIf + EndIf + If NotZ(u[0]) Then + Inc(narg); + k=cpos('$',idlist); + If k>0 Then /* replace dollar with expression string u */ + pscopy(v,idlist,1,k-1); + sadd(v,u); + pscopy(u,idlist, k+1, length(idlist)); + scopy(idlist,v); + sadd(idlist,u); + EndIf + EndIf + Done + Else + message( dico,"Cannot find called subcircuit") + EndIf + EndIf + /***** finally, execute the multi-assignment line */ + dicostack(dico, Push); /* create local symbol scope */ + If narg != n Then + scopy(t," Mismatch: "); + nadd(t,n); + sadd(t," formal but "); + nadd(t,narg); + sadd(t," actual params."); + err= message( dico,t); + message( dico,idlist); + /* Else debugwarn(dico, idlist) */ + EndIf + err= nupa_assignment(dico, idlist, 'N'); + return err +EndFunc + +Proc nupa_subcktexit( tdico *dico) +Begin + dicostack(dico, Pop); +EndProc + diff --git a/src/frontend/subckt.h b/src/frontend/subckt.h index 2a134e1cc..ec81091b5 100644 --- a/src/frontend/subckt.h +++ b/src/frontend/subckt.h @@ -8,7 +8,6 @@ struct line * inp_subcktexpand(struct line *deck); struct line * inp_deckcopy(struct line *deck); -int inp_numnodes(char c); diff --git a/src/include/fteext.h b/src/include/fteext.h index 64d0864bb..2f704e310 100644 --- a/src/include/fteext.h +++ b/src/include/fteext.h @@ -454,7 +454,6 @@ extern struct variable *if_getstat(); extern struct line *inp_deckcopy(); extern struct line *inp_subcktexpand(); -extern int inp_numnodes(char); /* types.c */ diff --git a/src/spicelib/analysis/dctran.c b/src/spicelib/analysis/dctran.c index 7b481a3da..528cb05fc 100644 --- a/src/spicelib/analysis/dctran.c +++ b/src/spicelib/analysis/dctran.c @@ -196,6 +196,7 @@ DCtran(CKTcircuit *ckt, i++; } */ } else { + if(SMPmatSize(ckt->CKTmatrix) < 10) { fprintf(stdout,"\nInitial Transient Solution\n"); fprintf(stdout,"--------------------------\n\n"); fprintf(stdout,"%-30s %15s\n", "Node", "Voltage"); @@ -205,6 +206,7 @@ DCtran(CKTcircuit *ckt, fprintf(stdout,"%-30s %15g\n", node->name, *(ckt->CKTrhsOld+node->number)); }; + } }; fprintf(stdout,"\n"); fflush(stdout); diff --git a/src/spicelib/devices/bsim4/.cvsignore b/src/spicelib/devices/bsim4/.cvsignore new file mode 100644 index 000000000..dc4caac80 --- /dev/null +++ b/src/spicelib/devices/bsim4/.cvsignore @@ -0,0 +1,6 @@ +Makefile.in +Makefile +.deps +.libs +*.lo +*.la diff --git a/src/spicelib/devices/bsim4/B4TERMS_OF_USE b/src/spicelib/devices/bsim4/B4TERMS_OF_USE new file mode 100644 index 000000000..5cc4023bb --- /dev/null +++ b/src/spicelib/devices/bsim4/B4TERMS_OF_USE @@ -0,0 +1,33 @@ + +The terms under which the software is provided are as the following. + +Software is distributed as is, completely without warranty or service +support. The University of California and its employees are not liable +for the condition or performance of the software. + +The University owns the copyright but shall not be liable for any +infringement of copyright or other proprietary rights brought by third +parties against the users of the software. + +The University of California hereby disclaims all implied warranties. + +The University of California grants the users the right to modify, copy, +and redistribute the software and documentation, both within the user's +organization and externally, subject to the following restrictions: + +1. The users agree not to charge for the University of California code + itself but may charge for additions, extensions, or support. + +2. In any product based on the software, the users agree to acknowledge + the UC Berkeley BSIM Research Group that developed the software. This + acknowledgment shall appear in the product documentation. + +3. The users agree to obey all U.S. Government restrictions governing + redistribution or export of the software. + +4. The users agree to reproduce any copyright notice which appears on + the software on any copy or modification of such made available + to others. + +Chenming Hu, and Weidong Liu +Mar. 2000 diff --git a/src/spicelib/devices/bsim4/Makefile.am b/src/spicelib/devices/bsim4/Makefile.am index c9bf85550..a9e115d37 100644 --- a/src/spicelib/devices/bsim4/Makefile.am +++ b/src/spicelib/devices/bsim4/Makefile.am @@ -1,6 +1,6 @@ ## Process this file with automake to produce Makefile.in -noinst_LIBRARIES = libbsim4.a +pkglib_LIBRARIES = libbsim4.a libbsim4_a_SOURCES = \ b4.c \ diff --git a/src/spicelib/devices/bsim4/b4.c b/src/spicelib/devices/bsim4/b4.c index c07fd939a..0666ac73c 100644 --- a/src/spicelib/devices/bsim4/b4.c +++ b/src/spicelib/devices/bsim4/b4.c @@ -1,17 +1,20 @@ -/**** BSIM4.2.1, Released by Xuemei Xi 10/05/2001 ****/ +/**** BSIM4.5.0 Released by Xuemei (Jane) Xi 07/29/2005 ****/ /********** - * Copyright 2001 Regents of the University of California. All rights reserved. - * File: b4.c of BSIM4.2.1. + * Copyright 2005 Regents of the University of California. All rights reserved. + * File: b4.c of BSIM4.5.0. * Author: 2000 Weidong Liu - * Authors: Xuemei Xi, Kanyu M. Cao, Hui Wan, Mansun Chan, Chenming Hu. + * Authors: 2001- Xuemei Xi, Mohan Dunga, Ali Niknejad, Chenming Hu. * Project Director: Prof. Chenming Hu. - * + * Modified by Xuemei Xi, 04/06/2001. * Modified by Xuemei Xi, 10/05/2001. + * Modified by Xuemei Xi, 11/15/2002. + * Modified by Xuemei Xi, 05/09/2003. + * Modified by Xuemei Xi, 03/04/2004. + * Modified by Xuemei Xi, Mohan Dunga, 07/29/2005. **********/ #include "ngspice.h" -#include #include "devdefs.h" #include "bsim4def.h" #include "suffix.h" @@ -19,7 +22,15 @@ IFparm BSIM4pTable[] = { /* parameters */ IOP( "l", BSIM4_L, IF_REAL , "Length"), IOP( "w", BSIM4_W, IF_REAL , "Width"), +IOP( "m", BSIM4_M, IF_REAL , "Separate Parallel multiplier"), IOP( "nf", BSIM4_NF, IF_REAL , "Number of fingers"), +IOP( "sa", BSIM4_SA, IF_REAL , "distance between OD edge to poly of one side "), +IOP( "sb", BSIM4_SB, IF_REAL , "distance between OD edge to poly of the other side"), +IOP( "sd", BSIM4_SD, IF_REAL , "distance between neighbour fingers"), +IOP( "sca", BSIM4_SCA, IF_REAL , "Integral of the first distribution function for scattered well dopant"), +IOP( "scb", BSIM4_SCB, IF_REAL , "Integral of the second distribution function for scattered well dopant"), +IOP( "scc", BSIM4_SCC, IF_REAL , "Integral of the third distribution function for scattered well dopant"), +IOP( "sc", BSIM4_SCA, IF_REAL , "Distance to a single well edge "), IOP( "min", BSIM4_MIN, IF_INTEGER , "Minimize either D or S"), IOP( "ad", BSIM4_AD, IF_REAL , "Drain area"), IOP( "as", BSIM4_AS, IF_REAL , "Source area"), @@ -33,6 +44,10 @@ IOP( "rbsb", BSIM4_RBSB, IF_REAL , "Body resistance"), IOP( "rbpb", BSIM4_RBPB, IF_REAL , "Body resistance"), IOP( "rbps", BSIM4_RBPS, IF_REAL , "Body resistance"), IOP( "rbpd", BSIM4_RBPD, IF_REAL , "Body resistance"), +IOP( "delvto", BSIM4_DELVTO, IF_REAL , "Zero bias threshold voltage variation"), +IOP( "xgw", BSIM4_XGW, IF_REAL, "Distance from gate contact center to device edge"), +IOP( "ngcon", BSIM4_NGCON, IF_REAL, "Number of gate contacts"), + IOP( "trnqsmod", BSIM4_TRNQSMOD, IF_INTEGER, "Transient NQS model selector"), IOP( "acnqsmod", BSIM4_ACNQSMOD, IF_INTEGER, "AC NQS model selector"), @@ -49,6 +64,8 @@ OP( "vth", BSIM4_VON, IF_REAL, "Vth"), OP( "id", BSIM4_CD, IF_REAL, "Ids"), OP( "ibd", BSIM4_CBD, IF_REAL, "Ibd"), OP( "ibs", BSIM4_CBS, IF_REAL, "Ibs"), +OP( "gbd", BSIM4_GBD, IF_REAL, "gbd"), +OP( "gbs", BSIM4_GBS, IF_REAL, "gbs"), OP( "isub", BSIM4_CSUB, IF_REAL, "Isub"), OP( "igidl", BSIM4_IGIDL, IF_REAL, "Igidl"), OP( "igisl", BSIM4_IGISL, IF_REAL, "Igisl"), @@ -83,6 +100,9 @@ OP( "qb", BSIM4_QB, IF_REAL, "Qbulk"), OP( "qd", BSIM4_QD, IF_REAL, "Qdrain"), OP( "qs", BSIM4_QS, IF_REAL, "Qsource"), OP( "qinv", BSIM4_QINV, IF_REAL, "Qinversion"), +OP( "qdef", BSIM4_QDEF, IF_REAL, "Qdef"), +OP( "gcrg", BSIM4_GCRG, IF_REAL, "Gcrg"), +OP( "gtau", BSIM4_GTAU, IF_REAL, "Gtau"), }; IFparm BSIM4mPTable[] = { /* model parameters */ @@ -100,6 +120,7 @@ IOP( "fnoimod", BSIM4_MOD_FNOIMOD, IF_INTEGER, "Flicker noise model selector"), IOP( "tnoimod", BSIM4_MOD_TNOIMOD, IF_INTEGER, "Thermal noise model selector"), IOP( "igcmod", BSIM4_MOD_IGCMOD, IF_INTEGER, "Gate-to-channel Ig model selector"), IOP( "igbmod", BSIM4_MOD_IGBMOD, IF_INTEGER, "Gate-to-body Ig model selector"), +IOP( "tempmod", BSIM4_MOD_TEMPMOD, IF_INTEGER, "Temperature model selector"), IOP( "paramchk", BSIM4_MOD_PARAMCHK, IF_INTEGER, "Model parameter checking selector"), IOP( "binunit", BSIM4_MOD_BINUNIT, IF_INTEGER, "Bin unit selector"), IOP( "version", BSIM4_MOD_VERSION, IF_STRING, "parameter for model version"), @@ -161,6 +182,10 @@ IOP( "ub", BSIM4_MOD_UB, IF_REAL, "Quadratic gate dependence of mobility"), IOP( "ub1", BSIM4_MOD_UB1, IF_REAL, "Temperature coefficient of ub"), IOP( "uc", BSIM4_MOD_UC, IF_REAL, "Body-bias dependence of mobility"), IOP( "uc1", BSIM4_MOD_UC1, IF_REAL, "Temperature coefficient of uc"), +IOP( "ud", BSIM4_MOD_UD, IF_REAL, "Coulomb scattering factor of mobility"), +IOP( "ud1", BSIM4_MOD_UD1, IF_REAL, "Temperature coefficient of ud"), +IOP( "up", BSIM4_MOD_UP, IF_REAL, "Channel length linear factor of mobility"), +IOP( "lp", BSIM4_MOD_LP, IF_REAL, "Channel length exponential factor of mobility"), IOP( "u0", BSIM4_MOD_U0, IF_REAL, "Low-field mobility at Tnom"), IOP( "eu", BSIM4_MOD_EU, IF_REAL, "Mobility exponent"), IOP( "ute", BSIM4_MOD_UTE, IF_REAL, "Temperature coefficient of mobility"), @@ -251,6 +276,15 @@ IOP( "rshg", BSIM4_MOD_RSHG, IF_REAL, "Gate sheet resistance"), IOP( "ngcon", BSIM4_MOD_NGCON, IF_REAL, "Number of gate contacts"), IOP( "xrcrg1", BSIM4_MOD_XRCRG1, IF_REAL, "First fitting parameter the bias-dependent Rg"), IOP( "xrcrg2", BSIM4_MOD_XRCRG2, IF_REAL, "Second fitting parameter the bias-dependent Rg"), +IOP( "lambda", BSIM4_MOD_LAMBDA, IF_REAL, " Velocity overshoot parameter"), +IOP( "vtl", BSIM4_MOD_VTL, IF_REAL, " thermal velocity"), +IOP( "lc", BSIM4_MOD_LC, IF_REAL, " back scattering parameter"), +IOP( "xn", BSIM4_MOD_XN, IF_REAL, " back scattering parameter"), +IOP( "vfbsdoff", BSIM4_MOD_VFBSDOFF, IF_REAL, "S/D flatband voltage offset"), +IOP( "tvfbsdoff", BSIM4_MOD_TVFBSDOFF, IF_REAL, "Temperature parameter for vfbsdoff"), +IOP( "tvoff", BSIM4_MOD_TVOFF, IF_REAL, "Temperature parameter for voff"), + +IOP( "lintnoi", BSIM4_MOD_LINTNOI, IF_REAL, "lint offset for noise calculation"), IOP( "lint", BSIM4_MOD_LINT, IF_REAL, "Length reduction parameter"), IOP( "ll", BSIM4_MOD_LL, IF_REAL, "Length reduction parameter"), IOP( "llc", BSIM4_MOD_LLC, IF_REAL, "Length reduction parameter for CV"), @@ -299,6 +333,7 @@ IOP( "dwj", BSIM4_MOD_DWJ, IF_REAL, "Delta W for S/D junctions"), IOP( "alpha0", BSIM4_MOD_ALPHA0, IF_REAL, "substrate current model parameter"), IOP( "alpha1", BSIM4_MOD_ALPHA1, IF_REAL, "substrate current model parameter"), IOP( "beta0", BSIM4_MOD_BETA0, IF_REAL, "substrate current model parameter"), + IOP( "agidl", BSIM4_MOD_AGIDL, IF_REAL, "Pre-exponential constant for GIDL"), IOP( "bgidl", BSIM4_MOD_BGIDL, IF_REAL, "Exponential constant for GIDL"), IOP( "cgidl", BSIM4_MOD_CGIDL, IF_REAL, "Parameter for body-bias dependence of GIDL"), @@ -332,6 +367,31 @@ IOP( "xjbvs", BSIM4_MOD_XJBVS, IF_REAL, "Fitting parameter for source diode brea IOP( "bvd", BSIM4_MOD_BVD, IF_REAL, "Drain diode breakdown voltage"), IOP( "bvs", BSIM4_MOD_BVS, IF_REAL, "Source diode breakdown voltage"), +IOP( "jtss", BSIM4_MOD_JTSS, IF_REAL, "Source bottom trap-assisted saturation current density"), +IOP( "jtsd", BSIM4_MOD_JTSD, IF_REAL, "Drain bottom trap-assisted saturation current density"), +IOP( "jtssws", BSIM4_MOD_JTSSWS, IF_REAL, "Source STI sidewall trap-assisted saturation current density"), +IOP( "jtsswd", BSIM4_MOD_JTSSWD, IF_REAL, "Drain STI sidewall trap-assisted saturation current density"), +IOP( "jtsswgs", BSIM4_MOD_JTSSWGS, IF_REAL, "Source gate-edge sidewall trap-assisted saturation current density"), +IOP( "jtsswgd", BSIM4_MOD_JTSSWGD, IF_REAL, "Drain gate-edge sidewall trap-assisted saturation current density"), +IOP( "njts", BSIM4_MOD_NJTS, IF_REAL, "Non-ideality factor for bottom junction"), +IOP( "njtssw", BSIM4_MOD_NJTSSW, IF_REAL, "Non-ideality factor for STI sidewall junction"), +IOP( "njtsswg", BSIM4_MOD_NJTSSWG, IF_REAL, "Non-ideality factor for gate-edge sidewall junction"), +IOP( "xtss", BSIM4_MOD_XTSS, IF_REAL, "Power dependence of JTSS on temperature"), +IOP( "xtsd", BSIM4_MOD_XTSD, IF_REAL, "Power dependence of JTSD on temperature"), +IOP( "xtssws", BSIM4_MOD_XTSSWS, IF_REAL, "Power dependence of JTSSWS on temperature"), +IOP( "xtsswd", BSIM4_MOD_XTSSWD, IF_REAL, "Power dependence of JTSSWD on temperature"), +IOP( "xtsswgs", BSIM4_MOD_XTSSWGS, IF_REAL, "Power dependence of JTSSWGS on temperature"), +IOP( "xtsswgd", BSIM4_MOD_XTSSWGD, IF_REAL, "Power dependence of JTSSWGD on temperature"), +IOP( "tnjts", BSIM4_MOD_TNJTS, IF_REAL, "Temperature coefficient for NJTS"), +IOP( "tnjtssw", BSIM4_MOD_TNJTSSW, IF_REAL, "Temperature coefficient for NJTSSW"), +IOP( "tnjtsswg", BSIM4_MOD_TNJTSSWG, IF_REAL, "Temperature coefficient for NJTSSWG"), +IOP( "vtss", BSIM4_MOD_VTSS, IF_REAL, "Source bottom trap-assisted voltage dependent parameter"), +IOP( "vtsd", BSIM4_MOD_VTSD, IF_REAL, "Drain bottom trap-assisted voltage dependent parameter"), +IOP( "vtssws", BSIM4_MOD_VTSSWS, IF_REAL, "Source STI sidewall trap-assisted voltage dependent parameter"), +IOP( "vtsswd", BSIM4_MOD_VTSSWD, IF_REAL, "Drain STI sidewall trap-assisted voltage dependent parameter"), +IOP( "vtsswgs", BSIM4_MOD_VTSSWGS, IF_REAL, "Source gate-edge sidewall trap-assisted voltage dependent parameter"), +IOP( "vtsswgd", BSIM4_MOD_VTSSWGD, IF_REAL, "Drain gate-edge sidewall trap-assisted voltage dependent parameter"), + IOP( "gbmin", BSIM4_MOD_GBMIN, IF_REAL, "Minimum body conductance"), IOP( "rbdb", BSIM4_MOD_RBDB, IF_REAL, "Resistance between bNode and dbNode"), IOP( "rbpb", BSIM4_MOD_RBPB, IF_REAL, "Resistance between bNodePrime and bNode"), @@ -339,6 +399,37 @@ IOP( "rbsb", BSIM4_MOD_RBSB, IF_REAL, "Resistance between bNode and sbNode"), IOP( "rbps", BSIM4_MOD_RBPS, IF_REAL, "Resistance between bNodePrime and sbNode"), IOP( "rbpd", BSIM4_MOD_RBPD, IF_REAL, "Resistance between bNodePrime and bNode"), +IOP( "rbps0", BSIM4_MOD_RBPS0, IF_REAL , "Body resistance RBPS scaling"), +IOP( "rbpsl", BSIM4_MOD_RBPSL, IF_REAL , "Body resistance RBPS L scaling"), +IOP( "rbpsw", BSIM4_MOD_RBPSW, IF_REAL , "Body resistance RBPS W scaling"), +IOP( "rbpsnf", BSIM4_MOD_RBPSNF, IF_REAL , "Body resistance RBPS NF scaling"), + +IOP( "rbpd0", BSIM4_MOD_RBPD0, IF_REAL , "Body resistance RBPD scaling"), +IOP( "rbpdl", BSIM4_MOD_RBPDL, IF_REAL , "Body resistance RBPD L scaling"), +IOP( "rbpdw", BSIM4_MOD_RBPDW, IF_REAL , "Body resistance RBPD W scaling"), +IOP( "rbpdnf", BSIM4_MOD_RBPDNF, IF_REAL , "Body resistance RBPD NF scaling"), + +IOP( "rbpbx0", BSIM4_MOD_RBPBX0, IF_REAL , "Body resistance RBPBX scaling"), +IOP( "rbpbxl", BSIM4_MOD_RBPBXL, IF_REAL , "Body resistance RBPBX L scaling"), +IOP( "rbpbxw", BSIM4_MOD_RBPBXW, IF_REAL , "Body resistance RBPBX W scaling"), +IOP( "rbpbxnf", BSIM4_MOD_RBPBXNF, IF_REAL , "Body resistance RBPBX NF scaling"), +IOP( "rbpby0", BSIM4_MOD_RBPBY0, IF_REAL , "Body resistance RBPBY scaling"), +IOP( "rbpbyl", BSIM4_MOD_RBPBYL, IF_REAL , "Body resistance RBPBY L scaling"), +IOP( "rbpbyw", BSIM4_MOD_RBPBYW, IF_REAL , "Body resistance RBPBY W scaling"), +IOP( "rbpbynf", BSIM4_MOD_RBPBYNF, IF_REAL , "Body resistance RBPBY NF scaling"), + +IOP( "rbsbx0", BSIM4_MOD_RBSBX0, IF_REAL , "Body resistance RBSBX scaling"), +IOP( "rbsby0", BSIM4_MOD_RBSBY0, IF_REAL , "Body resistance RBSBY scaling"), +IOP( "rbdbx0", BSIM4_MOD_RBDBX0, IF_REAL , "Body resistance RBDBX scaling"), +IOP( "rbdby0", BSIM4_MOD_RBDBY0, IF_REAL , "Body resistance RBDBY scaling"), + +IOP( "rbsdbxl", BSIM4_MOD_RBSDBXL, IF_REAL , "Body resistance RBSDBX L scaling"), +IOP( "rbsdbxw", BSIM4_MOD_RBSDBXW, IF_REAL , "Body resistance RBSDBX W scaling"), +IOP( "rbsdbxnf", BSIM4_MOD_RBSDBXNF, IF_REAL , "Body resistance RBSDBX NF scaling"), +IOP( "rbsdbyl", BSIM4_MOD_RBSDBYL, IF_REAL , "Body resistance RBSDBY L scaling"), +IOP( "rbsdbyw", BSIM4_MOD_RBSDBYW, IF_REAL , "Body resistance RBSDBY W scaling"), +IOP( "rbsdbynf", BSIM4_MOD_RBSDBYNF, IF_REAL , "Body resistance RBSDBY NF scaling"), + IOP( "lcdsc", BSIM4_MOD_LCDSC, IF_REAL, "Length dependence of cdsc"), IOP( "lcdscb", BSIM4_MOD_LCDSCB, IF_REAL, "Length dependence of cdscb"), IOP( "lcdscd", BSIM4_MOD_LCDSCD, IF_REAL, "Length dependence of cdscd"), @@ -390,6 +481,10 @@ IOP( "lub", BSIM4_MOD_LUB, IF_REAL, "Length dependence of ub"), IOP( "lub1", BSIM4_MOD_LUB1, IF_REAL, "Length dependence of ub1"), IOP( "luc", BSIM4_MOD_LUC, IF_REAL, "Length dependence of uc"), IOP( "luc1", BSIM4_MOD_LUC1, IF_REAL, "Length dependence of uc1"), +IOP( "lud", BSIM4_MOD_LUD, IF_REAL, "Length dependence of ud"), +IOP( "lud1", BSIM4_MOD_LUD1, IF_REAL, "Length dependence of ud1"), +IOP( "lup", BSIM4_MOD_LUP, IF_REAL, "Length dependence of up"), +IOP( "llp", BSIM4_MOD_LLP, IF_REAL, "Length dependence of lp"), IOP( "lu0", BSIM4_MOD_LU0, IF_REAL, "Length dependence of u0"), IOP( "lute", BSIM4_MOD_LUTE, IF_REAL, "Length dependence of ute"), IOP( "lvoff", BSIM4_MOD_LVOFF, IF_REAL, "Length dependence of voff"), @@ -430,6 +525,7 @@ IOP( "lcle", BSIM4_MOD_LCLE, IF_REAL, "Length dependence of cle"), IOP( "lalpha0", BSIM4_MOD_LALPHA0, IF_REAL, "Length dependence of alpha0"), IOP( "lalpha1", BSIM4_MOD_LALPHA1, IF_REAL, "Length dependence of alpha1"), IOP( "lbeta0", BSIM4_MOD_LBETA0, IF_REAL, "Length dependence of beta0"), + IOP( "lagidl", BSIM4_MOD_LAGIDL, IF_REAL, "Length dependence of agidl"), IOP( "lbgidl", BSIM4_MOD_LBGIDL, IF_REAL, "Length dependence of bgidl"), IOP( "lcgidl", BSIM4_MOD_LCGIDL, IF_REAL, "Length dependence of cgidl"), @@ -462,7 +558,14 @@ IOP( "lnoff", BSIM4_MOD_LNOFF, IF_REAL, "Length dependence of noff"), IOP( "lvoffcv", BSIM4_MOD_LVOFFCV, IF_REAL, "Length dependence of voffcv"), IOP( "lxrcrg1", BSIM4_MOD_LXRCRG1, IF_REAL, "Length dependence of xrcrg1"), IOP( "lxrcrg2", BSIM4_MOD_LXRCRG2, IF_REAL, "Length dependence of xrcrg2"), -IOP( "leu", BSIM4_MOD_LEU, IF_REAL, "Length dependence of eu"), +IOP( "llambda", BSIM4_MOD_LLAMBDA, IF_REAL, "Length dependence of lambda"), +IOP( "lvtl", BSIM4_MOD_LVTL, IF_REAL, " Length dependence of vtl"), +IOP( "lxn", BSIM4_MOD_LXN, IF_REAL, " Length dependence of xn"), +IOP( "leu", BSIM4_MOD_LEU, IF_REAL, " Length dependence of eu"), +IOP( "lvfbsdoff", BSIM4_MOD_LVFBSDOFF, IF_REAL, "Length dependence of vfbsdoff"), +IOP( "ltvfbsdoff", BSIM4_MOD_LTVFBSDOFF, IF_REAL, "Length dependence of tvfbsdoff"), +IOP( "ltvoff", BSIM4_MOD_LTVOFF, IF_REAL, "Length dependence of tvoff"), + IOP( "wcdsc", BSIM4_MOD_WCDSC, IF_REAL, "Width dependence of cdsc"), IOP( "wcdscb", BSIM4_MOD_WCDSCB, IF_REAL, "Width dependence of cdscb"), IOP( "wcdscd", BSIM4_MOD_WCDSCD, IF_REAL, "Width dependence of cdscd"), @@ -514,6 +617,10 @@ IOP( "wub", BSIM4_MOD_WUB, IF_REAL, "Width dependence of ub"), IOP( "wub1", BSIM4_MOD_WUB1, IF_REAL, "Width dependence of ub1"), IOP( "wuc", BSIM4_MOD_WUC, IF_REAL, "Width dependence of uc"), IOP( "wuc1", BSIM4_MOD_WUC1, IF_REAL, "Width dependence of uc1"), +IOP( "wud", BSIM4_MOD_WUD, IF_REAL, "Width dependence of ud"), +IOP( "wud1", BSIM4_MOD_WUD1, IF_REAL, "Width dependence of ud1"), +IOP( "wup", BSIM4_MOD_WUP, IF_REAL, "Width dependence of up"), +IOP( "wlp", BSIM4_MOD_WLP, IF_REAL, "Width dependence of lp"), IOP( "wu0", BSIM4_MOD_WU0, IF_REAL, "Width dependence of u0"), IOP( "wute", BSIM4_MOD_WUTE, IF_REAL, "Width dependence of ute"), IOP( "wvoff", BSIM4_MOD_WVOFF, IF_REAL, "Width dependence of voff"), @@ -554,6 +661,7 @@ IOP( "wcle", BSIM4_MOD_WCLE, IF_REAL, "Width dependence of cle"), IOP( "walpha0", BSIM4_MOD_WALPHA0, IF_REAL, "Width dependence of alpha0"), IOP( "walpha1", BSIM4_MOD_WALPHA1, IF_REAL, "Width dependence of alpha1"), IOP( "wbeta0", BSIM4_MOD_WBETA0, IF_REAL, "Width dependence of beta0"), + IOP( "wagidl", BSIM4_MOD_WAGIDL, IF_REAL, "Width dependence of agidl"), IOP( "wbgidl", BSIM4_MOD_WBGIDL, IF_REAL, "Width dependence of bgidl"), IOP( "wcgidl", BSIM4_MOD_WCGIDL, IF_REAL, "Width dependence of cgidl"), @@ -585,7 +693,13 @@ IOP( "wnoff", BSIM4_MOD_WNOFF, IF_REAL, "Width dependence of noff"), IOP( "wvoffcv", BSIM4_MOD_WVOFFCV, IF_REAL, "Width dependence of voffcv"), IOP( "wxrcrg1", BSIM4_MOD_WXRCRG1, IF_REAL, "Width dependence of xrcrg1"), IOP( "wxrcrg2", BSIM4_MOD_WXRCRG2, IF_REAL, "Width dependence of xrcrg2"), +IOP( "wlambda", BSIM4_MOD_WLAMBDA, IF_REAL, "Width dependence of lambda"), +IOP( "wvtl", BSIM4_MOD_WVTL, IF_REAL, "Width dependence of vtl"), +IOP( "wxn", BSIM4_MOD_WXN, IF_REAL, "Width dependence of xn"), IOP( "weu", BSIM4_MOD_WEU, IF_REAL, "Width dependence of eu"), +IOP( "wvfbsdoff", BSIM4_MOD_WVFBSDOFF, IF_REAL, "Width dependence of vfbsdoff"), +IOP( "wtvfbsdoff", BSIM4_MOD_WTVFBSDOFF, IF_REAL, "Width dependence of tvfbsdoff"), +IOP( "wtvoff", BSIM4_MOD_WTVOFF, IF_REAL, "Width dependence of tvoff"), IOP( "pcdsc", BSIM4_MOD_PCDSC, IF_REAL, "Cross-term dependence of cdsc"), IOP( "pcdscb", BSIM4_MOD_PCDSCB, IF_REAL, "Cross-term dependence of cdscb"), @@ -638,6 +752,10 @@ IOP( "pub", BSIM4_MOD_PUB, IF_REAL, "Cross-term dependence of ub"), IOP( "pub1", BSIM4_MOD_PUB1, IF_REAL, "Cross-term dependence of ub1"), IOP( "puc", BSIM4_MOD_PUC, IF_REAL, "Cross-term dependence of uc"), IOP( "puc1", BSIM4_MOD_PUC1, IF_REAL, "Cross-term dependence of uc1"), +IOP( "pud", BSIM4_MOD_PUD, IF_REAL, "Cross-term dependence of ud"), +IOP( "pud1", BSIM4_MOD_PUD1, IF_REAL, "Cross-term dependence of ud1"), +IOP( "pup", BSIM4_MOD_PUP, IF_REAL, "Cross-term dependence of up"), +IOP( "plp", BSIM4_MOD_PLP, IF_REAL, "Cross-term dependence of lp"), IOP( "pu0", BSIM4_MOD_PU0, IF_REAL, "Cross-term dependence of u0"), IOP( "pute", BSIM4_MOD_PUTE, IF_REAL, "Cross-term dependence of ute"), IOP( "pvoff", BSIM4_MOD_PVOFF, IF_REAL, "Cross-term dependence of voff"), @@ -678,6 +796,7 @@ IOP( "pcle", BSIM4_MOD_PCLE, IF_REAL, "Cross-term dependence of cle"), IOP( "palpha0", BSIM4_MOD_PALPHA0, IF_REAL, "Cross-term dependence of alpha0"), IOP( "palpha1", BSIM4_MOD_PALPHA1, IF_REAL, "Cross-term dependence of alpha1"), IOP( "pbeta0", BSIM4_MOD_PBETA0, IF_REAL, "Cross-term dependence of beta0"), + IOP( "pagidl", BSIM4_MOD_PAGIDL, IF_REAL, "Cross-term dependence of agidl"), IOP( "pbgidl", BSIM4_MOD_PBGIDL, IF_REAL, "Cross-term dependence of bgidl"), IOP( "pcgidl", BSIM4_MOD_PCGIDL, IF_REAL, "Cross-term dependence of cgidl"), @@ -709,13 +828,61 @@ IOP( "pnoff", BSIM4_MOD_PNOFF, IF_REAL, "Cross-term dependence of noff"), IOP( "pvoffcv", BSIM4_MOD_PVOFFCV, IF_REAL, "Cross-term dependence of voffcv"), IOP( "pxrcrg1", BSIM4_MOD_PXRCRG1, IF_REAL, "Cross-term dependence of xrcrg1"), IOP( "pxrcrg2", BSIM4_MOD_PXRCRG2, IF_REAL, "Cross-term dependence of xrcrg2"), +IOP( "plambda", BSIM4_MOD_PLAMBDA, IF_REAL, "Cross-term dependence of lambda"), +IOP( "pvtl", BSIM4_MOD_PVTL, IF_REAL, "Cross-term dependence of vtl"), +IOP( "pxn", BSIM4_MOD_PXN, IF_REAL, "Cross-term dependence of xn"), IOP( "peu", BSIM4_MOD_PEU, IF_REAL, "Cross-term dependence of eu"), +IOP( "pvfbsdoff", BSIM4_MOD_PVFBSDOFF, IF_REAL, "Cross-term dependence of vfbsdoff"), +IOP( "ptvfbsdoff", BSIM4_MOD_PTVFBSDOFF, IF_REAL, "Cross-term dependence of tvfbsdoff"), +IOP( "ptvoff", BSIM4_MOD_PTVOFF, IF_REAL, "Cross-term dependence of tvoff"), + +/* stress effect*/ +IOP( "saref", BSIM4_MOD_SAREF, IF_REAL, "Reference distance between OD edge to poly of one side"), +IOP( "sbref", BSIM4_MOD_SBREF, IF_REAL, "Reference distance between OD edge to poly of the other side"), +IOP( "wlod", BSIM4_MOD_WLOD, IF_REAL, "Width parameter for stress effect"), +IOP( "ku0", BSIM4_MOD_KU0, IF_REAL, "Mobility degradation/enhancement coefficient for LOD"), +IOP( "kvsat", BSIM4_MOD_KVSAT, IF_REAL, "Saturation velocity degradation/enhancement parameter for LOD"), +IOP( "kvth0", BSIM4_MOD_KVTH0, IF_REAL, "Threshold degradation/enhancement parameter for LOD"), +IOP( "tku0", BSIM4_MOD_TKU0, IF_REAL, "Temperature coefficient of KU0"), +IOP( "llodku0", BSIM4_MOD_LLODKU0, IF_REAL, "Length parameter for u0 LOD effect"), +IOP( "wlodku0", BSIM4_MOD_WLODKU0, IF_REAL, "Width parameter for u0 LOD effect"), +IOP( "llodvth", BSIM4_MOD_LLODVTH, IF_REAL, "Length parameter for vth LOD effect"), +IOP( "wlodvth", BSIM4_MOD_WLODVTH, IF_REAL, "Width parameter for vth LOD effect"), +IOP( "lku0", BSIM4_MOD_LKU0, IF_REAL, "Length dependence of ku0"), +IOP( "wku0", BSIM4_MOD_WKU0, IF_REAL, "Width dependence of ku0"), +IOP( "pku0", BSIM4_MOD_PKU0, IF_REAL, "Cross-term dependence of ku0"), +IOP( "lkvth0", BSIM4_MOD_LKVTH0, IF_REAL, "Length dependence of kvth0"), +IOP( "wkvth0", BSIM4_MOD_WKVTH0, IF_REAL, "Width dependence of kvth0"), +IOP( "pkvth0", BSIM4_MOD_PKVTH0, IF_REAL, "Cross-term dependence of kvth0"), +IOP( "stk2", BSIM4_MOD_STK2, IF_REAL, "K2 shift factor related to stress effect on vth"), +IOP( "lodk2", BSIM4_MOD_LODK2, IF_REAL, "K2 shift modification factor for stress effect"), +IOP( "steta0", BSIM4_MOD_STETA0, IF_REAL, "eta0 shift factor related to stress effect on vth"), +IOP( "lodeta0", BSIM4_MOD_LODETA0, IF_REAL, "eta0 shift modification factor for stress effect"), +/* Well Proximity Effect */ +IOP( "web", BSIM4_MOD_WEB, IF_REAL, "Coefficient for SCB"), +IOP( "wec", BSIM4_MOD_WEC, IF_REAL, "Coefficient for SCC"), +IOP( "kvth0we", BSIM4_MOD_KVTH0WE, IF_REAL, "Threshold shift factor for well proximity effect"), +IOP( "k2we", BSIM4_MOD_K2WE, IF_REAL, " K2 shift factor for well proximity effect "), +IOP( "ku0we", BSIM4_MOD_KU0WE, IF_REAL, " Mobility degradation factor for well proximity effect "), +IOP( "scref", BSIM4_MOD_SCREF, IF_REAL, " Reference distance to calculate SCA, SCB and SCC"), +IOP( "wpemod", BSIM4_MOD_WPEMOD, IF_REAL, " Flag for WPE model (WPEMOD=1 to activate this model) "), +IOP( "lkvth0we", BSIM4_MOD_LKVTH0WE, IF_REAL, "Length dependence of kvth0we"), +IOP( "lk2we", BSIM4_MOD_LK2WE, IF_REAL, " Length dependence of k2we "), +IOP( "lku0we", BSIM4_MOD_LKU0WE, IF_REAL, " Length dependence of ku0we "), +IOP( "wkvth0we", BSIM4_MOD_WKVTH0WE, IF_REAL, "Width dependence of kvth0we"), +IOP( "wk2we", BSIM4_MOD_WK2WE, IF_REAL, " Width dependence of k2we "), +IOP( "wku0we", BSIM4_MOD_WKU0WE, IF_REAL, " Width dependence of ku0we "), +IOP( "pkvth0we", BSIM4_MOD_PKVTH0WE, IF_REAL, "Cross-term dependence of kvth0we"), +IOP( "pk2we", BSIM4_MOD_PK2WE, IF_REAL, " Cross-term dependence of k2we "), +IOP( "pku0we", BSIM4_MOD_PKU0WE, IF_REAL, " Cross-term dependence of ku0we "), IOP( "noia", BSIM4_MOD_NOIA, IF_REAL, "Flicker noise parameter"), IOP( "noib", BSIM4_MOD_NOIB, IF_REAL, "Flicker noise parameter"), IOP( "noic", BSIM4_MOD_NOIC, IF_REAL, "Flicker noise parameter"), IOP( "tnoia", BSIM4_MOD_TNOIA, IF_REAL, "Thermal noise parameter"), IOP( "tnoib", BSIM4_MOD_TNOIB, IF_REAL, "Thermal noise parameter"), +IOP( "rnoia", BSIM4_MOD_RNOIA, IF_REAL, "Thermal noise coefficient"), +IOP( "rnoib", BSIM4_MOD_RNOIB, IF_REAL, "Thermal noise coefficient"), IOP( "ntnoi", BSIM4_MOD_NTNOI, IF_REAL, "Thermal noise parameter"), IOP( "em", BSIM4_MOD_EM, IF_REAL, "Flicker noise parameter"), IOP( "ef", BSIM4_MOD_EF, IF_REAL, "Flicker noise frequency exponent"), @@ -739,6 +906,3 @@ int BSIM4pTSize = NUMELEMS(BSIM4pTable); int BSIM4mPTSize = NUMELEMS(BSIM4mPTable); int BSIM4iSize = sizeof(BSIM4instance); int BSIM4mSize = sizeof(BSIM4model); - - - diff --git a/src/spicelib/devices/bsim4/b4acld.c b/src/spicelib/devices/bsim4/b4acld.c index 28dc21b8a..7949daf81 100644 --- a/src/spicelib/devices/bsim4/b4acld.c +++ b/src/spicelib/devices/bsim4/b4acld.c @@ -1,21 +1,19 @@ -/**** BSIM4.2.1, Released by Xuemei Xi 10/05/2001 ****/ +/**** BSIM4.5.0 Released by Xuemei (Jane) Xi 07/29/2005 ****/ /********** - * Copyright 2001 Regents of the University of California. All rights reserved. - * File: b4acld.c of BSIM4.2.1. + * Copyright 2005 Regents of the University of California. All rights reserved. + * File: b4acld.c of BSIM4.5.0. * Author: 2000 Weidong Liu - * Authors: Xuemei Xi, Kanyu M. Cao, Hui Wan, Mansun Chan, Chenming Hu. + * Authors: 2001- Xuemei Xi, Mohan Dunga, Ali Niknejad, Chenming Hu. * Project Director: Prof. Chenming Hu. - * - * Modified by Xuemei Xi 10/05/2001 + * Modified by Xuemei Xi, 10/05/2001. **********/ #include "ngspice.h" -#include #include "cktdefs.h" #include "bsim4def.h" #include "sperror.h" - +#include "suffix.h" int @@ -32,8 +30,8 @@ double xcggbr, xcgdbr, xcgsbr, xcgbbr, xcggbi, xcgdbi, xcgsbi, xcgbbi; double Cggr, Cgdr, Cgsr, Cgbr, Cggi, Cgdi, Cgsi, Cgbi; double xcddbr, xcdgbr, xcdsbr, xcdbbr, xcsdbr, xcsgbr, xcssbr, xcsbbr; double xcddbi, xcdgbi, xcdsbi, xcdbbi, xcsdbi, xcsgbi, xcssbi, xcsbbi; -double xcdbdb, xcsbsb, xcgmgmb, xcgmdb, xcgmsb, xcdgmb, xcsgmb; -double xcgmbb, xcbgmb; +double xcdbdb, xcsbsb=0.0, xcgmgmb=0.0, xcgmdb=0.0, xcgmsb=0.0, xcdgmb, xcsgmb; +double xcgmbb=0.0, xcbgmb; double capbd, capbs, omega; double gstot, gstotd, gstotg, gstots, gstotb, gspr; double gdtot, gdtotd, gdtotg, gdtots, gdtotb, gdpr; @@ -44,22 +42,24 @@ double gIgtotg, gIgtotd, gIgtots, gIgtotb; double cgso, cgdo, cgbo; double gbspsp, gbbdp, gbbsp, gbspg, gbspb; double gbspdp, gbdpdp, gbdpg, gbdpb, gbdpsp; -double T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11; -double Csg, Csd, Css, Csb; +double T0=0.0, T1, T2, T3; +double Csg, Csd, Css; double Cdgr, Cddr, Cdsr, Cdbr, Csgr, Csdr, Cssr, Csbr; double Cdgi, Cddi, Cdsi, Cdbi, Csgi, Csdi, Cssi, Csbi; double gmr, gmi, gmbsr, gmbsi, gdsr, gdsi; -double FwdSumr, RevSumr, Gmr, Gmbsr, Gdsr; -double FwdSumi, RevSumi, Gmi, Gmbsi, Gdsi; +double FwdSumr, RevSumr, Gmr, Gmbsr; +double FwdSumi, RevSumi, Gmi, Gmbsi; struct bsim4SizeDependParam *pParam; -double ggidld, ggidlg, ggidlb,ggisld, ggislg, ggislb, ggisls; +double ggidld, ggidlg, ggidlb, ggislg, ggislb, ggisls; + +double m; omega = ckt->CKTomega; for (; model != NULL; model = model->BSIM4nextModel) { for (here = model->BSIM4instances; here!= NULL; here = here->BSIM4nextInstance) { if (here->BSIM4owner != ARCHme) continue; - pParam = here->pParam; + pParam = here->pParam; capbd = here->BSIM4capbd; capbs = here->BSIM4capbs; cgso = here->BSIM4cgso; @@ -450,6 +450,7 @@ double ggidld, ggidlg, ggidlb,ggisld, ggislg, ggislb, ggisls; /* * Loading AC matrix */ + m = here->BSIM4m; if (!model->BSIM4rdsMod) { gdpr = here->BSIM4drainConductance; @@ -468,122 +469,122 @@ double ggidld, ggidlg, ggidlb,ggisld, ggislg, ggislb, ggisls; geltd = here->BSIM4grgeltd; if (here->BSIM4rgateMod == 1) - { *(here->BSIM4GEgePtr) += geltd; - *(here->BSIM4GPgePtr) -= geltd; - *(here->BSIM4GEgpPtr) -= geltd; + { *(here->BSIM4GEgePtr) += m * geltd; + *(here->BSIM4GPgePtr) -= m * geltd; + *(here->BSIM4GEgpPtr) -= m * geltd; - *(here->BSIM4GPgpPtr +1) += xcggbr; - *(here->BSIM4GPgpPtr) += geltd + xcggbi + gIgtotg; - *(here->BSIM4GPdpPtr +1) += xcgdbr; - *(here->BSIM4GPdpPtr) += xcgdbi + gIgtotd; - *(here->BSIM4GPspPtr +1) += xcgsbr; - *(here->BSIM4GPspPtr) += xcgsbi + gIgtots; - *(here->BSIM4GPbpPtr +1) += xcgbbr; - *(here->BSIM4GPbpPtr) += xcgbbi + gIgtotb; + *(here->BSIM4GPgpPtr +1) += m * xcggbr; + *(here->BSIM4GPgpPtr) += m * (geltd + xcggbi + gIgtotg); + *(here->BSIM4GPdpPtr +1) += m * xcgdbr; + *(here->BSIM4GPdpPtr) += m * (xcgdbi + gIgtotd); + *(here->BSIM4GPspPtr +1) += m * xcgsbr; + *(here->BSIM4GPspPtr) += m * (xcgsbi + gIgtots); + *(here->BSIM4GPbpPtr +1) += m * xcgbbr; + *(here->BSIM4GPbpPtr) += m * (xcgbbi + gIgtotb); } /* WDLiu: gcrg already subtracted from all gcrgg below */ else if (here->BSIM4rgateMod == 2) - { *(here->BSIM4GEgePtr) += gcrg; - *(here->BSIM4GEgpPtr) += gcrgg; - *(here->BSIM4GEdpPtr) += gcrgd; - *(here->BSIM4GEspPtr) += gcrgs; - *(here->BSIM4GEbpPtr) += gcrgb; + { *(here->BSIM4GEgePtr) += m * gcrg; + *(here->BSIM4GEgpPtr) += m * gcrgg; + *(here->BSIM4GEdpPtr) += m * gcrgd; + *(here->BSIM4GEspPtr) += m * gcrgs; + *(here->BSIM4GEbpPtr) += m * gcrgb; - *(here->BSIM4GPgePtr) -= gcrg; - *(here->BSIM4GPgpPtr +1) += xcggbr; - *(here->BSIM4GPgpPtr) -= gcrgg - xcggbi - gIgtotg; - *(here->BSIM4GPdpPtr +1) += xcgdbr; - *(here->BSIM4GPdpPtr) -= gcrgd - xcgdbi - gIgtotd; - *(here->BSIM4GPspPtr +1) += xcgsbr; - *(here->BSIM4GPspPtr) -= gcrgs - xcgsbi - gIgtots; - *(here->BSIM4GPbpPtr +1) += xcgbbr; - *(here->BSIM4GPbpPtr) -= gcrgb - xcgbbi - gIgtotb; + *(here->BSIM4GPgePtr) -= m * gcrg; + *(here->BSIM4GPgpPtr +1) += m * xcggbr; + *(here->BSIM4GPgpPtr) -= m * (gcrgg - xcggbi - gIgtotg); + *(here->BSIM4GPdpPtr +1) += m * xcgdbr; + *(here->BSIM4GPdpPtr) -= m * (gcrgd - xcgdbi - gIgtotd); + *(here->BSIM4GPspPtr +1) += m * xcgsbr; + *(here->BSIM4GPspPtr) -= m * (gcrgs - xcgsbi - gIgtots); + *(here->BSIM4GPbpPtr +1) += m * xcgbbr; + *(here->BSIM4GPbpPtr) -= m * (gcrgb - xcgbbi - gIgtotb); } else if (here->BSIM4rgateMod == 3) - { *(here->BSIM4GEgePtr) += geltd; - *(here->BSIM4GEgmPtr) -= geltd; - *(here->BSIM4GMgePtr) -= geltd; - *(here->BSIM4GMgmPtr) += geltd + gcrg; - *(here->BSIM4GMgmPtr +1) += xcgmgmb; + { *(here->BSIM4GEgePtr) += m * geltd; + *(here->BSIM4GEgmPtr) -= m * geltd; + *(here->BSIM4GMgePtr) -= m * geltd; + *(here->BSIM4GMgmPtr) += m * (geltd + gcrg); + *(here->BSIM4GMgmPtr +1) += m * xcgmgmb; - *(here->BSIM4GMdpPtr) += gcrgd; - *(here->BSIM4GMdpPtr +1) += xcgmdb; - *(here->BSIM4GMgpPtr) += gcrgg; - *(here->BSIM4GMspPtr) += gcrgs; - *(here->BSIM4GMspPtr +1) += xcgmsb; - *(here->BSIM4GMbpPtr) += gcrgb; - *(here->BSIM4GMbpPtr +1) += xcgmbb; + *(here->BSIM4GMdpPtr) += m * gcrgd; + *(here->BSIM4GMdpPtr +1) += m * xcgmdb; + *(here->BSIM4GMgpPtr) += m * gcrgg; + *(here->BSIM4GMspPtr) += m * gcrgs; + *(here->BSIM4GMspPtr +1) += m * xcgmsb; + *(here->BSIM4GMbpPtr) += m * gcrgb; + *(here->BSIM4GMbpPtr +1) += m * xcgmbb; - *(here->BSIM4DPgmPtr +1) += xcdgmb; - *(here->BSIM4GPgmPtr) -= gcrg; - *(here->BSIM4SPgmPtr +1) += xcsgmb; - *(here->BSIM4BPgmPtr +1) += xcbgmb; + *(here->BSIM4DPgmPtr +1) += m * xcdgmb; + *(here->BSIM4GPgmPtr) -= m * gcrg; + *(here->BSIM4SPgmPtr +1) += m * xcsgmb; + *(here->BSIM4BPgmPtr +1) += m * xcbgmb; - *(here->BSIM4GPgpPtr) -= gcrgg - xcggbi - gIgtotg; - *(here->BSIM4GPgpPtr +1) += xcggbr; - *(here->BSIM4GPdpPtr) -= gcrgd - xcgdbi - gIgtotd; - *(here->BSIM4GPdpPtr +1) += xcgdbr; - *(here->BSIM4GPspPtr) -= gcrgs - xcgsbi - gIgtots; - *(here->BSIM4GPspPtr +1) += xcgsbr; - *(here->BSIM4GPbpPtr) -= gcrgb - xcgbbi - gIgtotb; - *(here->BSIM4GPbpPtr +1) += xcgbbr; + *(here->BSIM4GPgpPtr) -= m * (gcrgg - xcggbi - gIgtotg); + *(here->BSIM4GPgpPtr +1) += m * xcggbr; + *(here->BSIM4GPdpPtr) -= m * (gcrgd - xcgdbi - gIgtotd); + *(here->BSIM4GPdpPtr +1) += m * xcgdbr; + *(here->BSIM4GPspPtr) -= m * (gcrgs - xcgsbi - gIgtots); + *(here->BSIM4GPspPtr +1) += m * xcgsbr; + *(here->BSIM4GPbpPtr) -= m * (gcrgb - xcgbbi - gIgtotb); + *(here->BSIM4GPbpPtr +1) += m * xcgbbr; } else - { *(here->BSIM4GPgpPtr +1) += xcggbr; - *(here->BSIM4GPgpPtr) += xcggbi + gIgtotg; - *(here->BSIM4GPdpPtr +1) += xcgdbr; - *(here->BSIM4GPdpPtr) += xcgdbi + gIgtotd; - *(here->BSIM4GPspPtr +1) += xcgsbr; - *(here->BSIM4GPspPtr) += xcgsbi + gIgtots; - *(here->BSIM4GPbpPtr +1) += xcgbbr; - *(here->BSIM4GPbpPtr) += xcgbbi + gIgtotb; + { *(here->BSIM4GPgpPtr +1) += m * xcggbr; + *(here->BSIM4GPgpPtr) += m * (xcggbi + gIgtotg); + *(here->BSIM4GPdpPtr +1) += m * xcgdbr; + *(here->BSIM4GPdpPtr) += m * (xcgdbi + gIgtotd); + *(here->BSIM4GPspPtr +1) += m * xcgsbr; + *(here->BSIM4GPspPtr) += m * (xcgsbi + gIgtots); + *(here->BSIM4GPbpPtr +1) += m * xcgbbr; + *(here->BSIM4GPbpPtr) += m * (xcgbbi + gIgtotb); } if (model->BSIM4rdsMod) - { (*(here->BSIM4DgpPtr) += gdtotg); - (*(here->BSIM4DspPtr) += gdtots); - (*(here->BSIM4DbpPtr) += gdtotb); - (*(here->BSIM4SdpPtr) += gstotd); - (*(here->BSIM4SgpPtr) += gstotg); - (*(here->BSIM4SbpPtr) += gstotb); + { (*(here->BSIM4DgpPtr) += m * gdtotg); + (*(here->BSIM4DspPtr) += m * gdtots); + (*(here->BSIM4DbpPtr) += m * gdtotb); + (*(here->BSIM4SdpPtr) += m * gstotd); + (*(here->BSIM4SgpPtr) += m * gstotg); + (*(here->BSIM4SbpPtr) += m * gstotb); } - *(here->BSIM4DPdpPtr +1) += xcddbr + gdsi + RevSumi; - *(here->BSIM4DPdpPtr) += gdpr + xcddbi + gdsr + here->BSIM4gbd - - gdtotd + RevSumr + gbdpdp - gIdtotd; - *(here->BSIM4DPdPtr) -= gdpr + gdtot; - *(here->BSIM4DPgpPtr +1) += xcdgbr + Gmi; - *(here->BSIM4DPgpPtr) += Gmr + xcdgbi - gdtotg + gbdpg - gIdtotg; - *(here->BSIM4DPspPtr +1) += xcdsbr - gdsi - FwdSumi; - *(here->BSIM4DPspPtr) -= gdsr - xcdsbi + FwdSumr + gdtots - gbdpsp + gIdtots; - *(here->BSIM4DPbpPtr +1) += xcdbbr + Gmbsi; - *(here->BSIM4DPbpPtr) -= gjbd + gdtotb - xcdbbi - Gmbsr - gbdpb + gIdtotb; + *(here->BSIM4DPdpPtr +1) += m * (xcddbr + gdsi + RevSumi); + *(here->BSIM4DPdpPtr) += m * (gdpr + xcddbi + gdsr + here->BSIM4gbd + - gdtotd + RevSumr + gbdpdp - gIdtotd); + *(here->BSIM4DPdPtr) -= m * (gdpr + gdtot); + *(here->BSIM4DPgpPtr +1) += m * (xcdgbr + Gmi); + *(here->BSIM4DPgpPtr) += m * (Gmr + xcdgbi - gdtotg + gbdpg - gIdtotg); + *(here->BSIM4DPspPtr +1) += m * (xcdsbr - gdsi - FwdSumi); + *(here->BSIM4DPspPtr) -= m * (gdsr - xcdsbi + FwdSumr + gdtots - gbdpsp + gIdtots); + *(here->BSIM4DPbpPtr +1) += m * (xcdbbr + Gmbsi); + *(here->BSIM4DPbpPtr) -= m * (gjbd + gdtotb - xcdbbi - Gmbsr - gbdpb + gIdtotb); - *(here->BSIM4DdpPtr) -= gdpr - gdtotd; - *(here->BSIM4DdPtr) += gdpr + gdtot; + *(here->BSIM4DdpPtr) -= m * (gdpr - gdtotd); + *(here->BSIM4DdPtr) += m * (gdpr + gdtot); - *(here->BSIM4SPdpPtr +1) += xcsdbr - gdsi - RevSumi; - *(here->BSIM4SPdpPtr) -= gdsr - xcsdbi + gstotd + RevSumr - gbspdp + gIstotd; - *(here->BSIM4SPgpPtr +1) += xcsgbr - Gmi; - *(here->BSIM4SPgpPtr) -= Gmr - xcsgbi + gstotg - gbspg + gIstotg; - *(here->BSIM4SPspPtr +1) += xcssbr + gdsi + FwdSumi; - *(here->BSIM4SPspPtr) += gspr + xcssbi + gdsr + here->BSIM4gbs - - gstots + FwdSumr + gbspsp - gIstots; - *(here->BSIM4SPsPtr) -= gspr + gstot; - *(here->BSIM4SPbpPtr +1) += xcsbbr - Gmbsi; - *(here->BSIM4SPbpPtr) -= gjbs + gstotb - xcsbbi + Gmbsr - gbspb + gIstotb; + *(here->BSIM4SPdpPtr +1) += m * (xcsdbr - gdsi - RevSumi); + *(here->BSIM4SPdpPtr) -= m * (gdsr - xcsdbi + gstotd + RevSumr - gbspdp + gIstotd); + *(here->BSIM4SPgpPtr +1) += m * (xcsgbr - Gmi); + *(here->BSIM4SPgpPtr) -= m * (Gmr - xcsgbi + gstotg - gbspg + gIstotg); + *(here->BSIM4SPspPtr +1) += m * (xcssbr + gdsi + FwdSumi); + *(here->BSIM4SPspPtr) += m * (gspr + xcssbi + gdsr + here->BSIM4gbs + - gstots + FwdSumr + gbspsp - gIstots); + *(here->BSIM4SPsPtr) -= m * (gspr + gstot); + *(here->BSIM4SPbpPtr +1) += m * (xcsbbr - Gmbsi); + *(here->BSIM4SPbpPtr) -= m * (gjbs + gstotb - xcsbbi + Gmbsr - gbspb + gIstotb); - *(here->BSIM4SspPtr) -= gspr - gstots; - *(here->BSIM4SsPtr) += gspr + gstot; + *(here->BSIM4SspPtr) -= m * (gspr - gstots); + *(here->BSIM4SsPtr) += m * (gspr + gstot); - *(here->BSIM4BPdpPtr +1) += xcbdb; - *(here->BSIM4BPdpPtr) -= gjbd - gbbdp + gIbtotd; - *(here->BSIM4BPgpPtr +1) += xcbgb; - *(here->BSIM4BPgpPtr) -= here->BSIM4gbgs + gIbtotg; - *(here->BSIM4BPspPtr +1) += xcbsb; - *(here->BSIM4BPspPtr) -= gjbs - gbbsp + gIbtots; - *(here->BSIM4BPbpPtr +1) += xcbbb; - *(here->BSIM4BPbpPtr) += gjbd + gjbs - here->BSIM4gbbs - - gIbtotb; + *(here->BSIM4BPdpPtr +1) += m * xcbdb; + *(here->BSIM4BPdpPtr) -= m * (gjbd - gbbdp + gIbtotd); + *(here->BSIM4BPgpPtr +1) += m * xcbgb; + *(here->BSIM4BPgpPtr) -= m * (here->BSIM4gbgs + gIbtotg); + *(here->BSIM4BPspPtr +1) += m * xcbsb; + *(here->BSIM4BPspPtr) -= m * (gjbs - gbbsp + gIbtots); + *(here->BSIM4BPbpPtr +1) += m * xcbbb; + *(here->BSIM4BPbpPtr) += m * (gjbd + gjbs - here->BSIM4gbbs + - gIbtotb); ggidld = here->BSIM4ggidld; ggidlg = here->BSIM4ggidlg; ggidlb = here->BSIM4ggidlb; @@ -592,58 +593,58 @@ double ggidld, ggidlg, ggidlb,ggisld, ggislg, ggislb, ggisls; ggislb = here->BSIM4ggislb; /* stamp gidl */ - (*(here->BSIM4DPdpPtr) += ggidld); - (*(here->BSIM4DPgpPtr) += ggidlg); - (*(here->BSIM4DPspPtr) -= (ggidlg + ggidld) + ggidlb); - (*(here->BSIM4DPbpPtr) += ggidlb); - (*(here->BSIM4BPdpPtr) -= ggidld); - (*(here->BSIM4BPgpPtr) -= ggidlg); - (*(here->BSIM4BPspPtr) += (ggidlg + ggidld) + ggidlb); - (*(here->BSIM4BPbpPtr) -= ggidlb); + (*(here->BSIM4DPdpPtr) += m * ggidld); + (*(here->BSIM4DPgpPtr) += m * ggidlg); + (*(here->BSIM4DPspPtr) -= m * ((ggidlg + ggidld) + ggidlb)); + (*(here->BSIM4DPbpPtr) += m * ggidlb); + (*(here->BSIM4BPdpPtr) -= m * ggidld); + (*(here->BSIM4BPgpPtr) -= m * ggidlg); + (*(here->BSIM4BPspPtr) += m * ((ggidlg + ggidld) + ggidlb)); + (*(here->BSIM4BPbpPtr) -= m * ggidlb); /* stamp gisl */ - (*(here->BSIM4SPdpPtr) -= (ggisls + ggislg) + ggislb); - (*(here->BSIM4SPgpPtr) += ggislg); - (*(here->BSIM4SPspPtr) += ggisls); - (*(here->BSIM4SPbpPtr) += ggislb); - (*(here->BSIM4BPdpPtr) += (ggislg + ggisls) + ggislb); - (*(here->BSIM4BPgpPtr) -= ggislg); - (*(here->BSIM4BPspPtr) -= ggisls); - (*(here->BSIM4BPbpPtr) -= ggislb); + (*(here->BSIM4SPdpPtr) -= m * ((ggisls + ggislg) + ggislb)); + (*(here->BSIM4SPgpPtr) += m * ggislg); + (*(here->BSIM4SPspPtr) += m * ggisls); + (*(here->BSIM4SPbpPtr) += m * ggislb); + (*(here->BSIM4BPdpPtr) += m * ((ggislg + ggisls) + ggislb)); + (*(here->BSIM4BPgpPtr) -= m * ggislg); + (*(here->BSIM4BPspPtr) -= m * ggisls); + (*(here->BSIM4BPbpPtr) -= m * ggislb); if (here->BSIM4rbodyMod) - { (*(here->BSIM4DPdbPtr +1) += xcdbdb); - (*(here->BSIM4DPdbPtr) -= here->BSIM4gbd); - (*(here->BSIM4SPsbPtr +1) += xcsbsb); - (*(here->BSIM4SPsbPtr) -= here->BSIM4gbs); + { (*(here->BSIM4DPdbPtr +1) += m * xcdbdb); + (*(here->BSIM4DPdbPtr) -= m * here->BSIM4gbd); + (*(here->BSIM4SPsbPtr +1) += m * xcsbsb); + (*(here->BSIM4SPsbPtr) -= m * here->BSIM4gbs); - (*(here->BSIM4DBdpPtr +1) += xcdbdb); - (*(here->BSIM4DBdpPtr) -= here->BSIM4gbd); - (*(here->BSIM4DBdbPtr +1) -= xcdbdb); - (*(here->BSIM4DBdbPtr) += here->BSIM4gbd + here->BSIM4grbpd - + here->BSIM4grbdb); - (*(here->BSIM4DBbpPtr) -= here->BSIM4grbpd); - (*(here->BSIM4DBbPtr) -= here->BSIM4grbdb); + (*(here->BSIM4DBdpPtr +1) += m * xcdbdb); + (*(here->BSIM4DBdpPtr) -= m * here->BSIM4gbd); + (*(here->BSIM4DBdbPtr +1) -= m * xcdbdb); + (*(here->BSIM4DBdbPtr) += m * (here->BSIM4gbd + here->BSIM4grbpd + + here->BSIM4grbdb)); + (*(here->BSIM4DBbpPtr) -= m * here->BSIM4grbpd); + (*(here->BSIM4DBbPtr) -= m * here->BSIM4grbdb); - (*(here->BSIM4BPdbPtr) -= here->BSIM4grbpd); - (*(here->BSIM4BPbPtr) -= here->BSIM4grbpb); - (*(here->BSIM4BPsbPtr) -= here->BSIM4grbps); - (*(here->BSIM4BPbpPtr) += here->BSIM4grbpd + here->BSIM4grbps - + here->BSIM4grbpb); + (*(here->BSIM4BPdbPtr) -= m * here->BSIM4grbpd); + (*(here->BSIM4BPbPtr) -= m * here->BSIM4grbpb); + (*(here->BSIM4BPsbPtr) -= m * here->BSIM4grbps); + (*(here->BSIM4BPbpPtr) += m * (here->BSIM4grbpd + here->BSIM4grbps + + here->BSIM4grbpb)); /* WDLiu: (-here->BSIM4gbbs) already added to BPbpPtr */ - (*(here->BSIM4SBspPtr +1) += xcsbsb); - (*(here->BSIM4SBspPtr) -= here->BSIM4gbs); - (*(here->BSIM4SBbpPtr) -= here->BSIM4grbps); - (*(here->BSIM4SBbPtr) -= here->BSIM4grbsb); - (*(here->BSIM4SBsbPtr +1) -= xcsbsb); - (*(here->BSIM4SBsbPtr) += here->BSIM4gbs - + here->BSIM4grbps + here->BSIM4grbsb); + (*(here->BSIM4SBspPtr +1) += m * xcsbsb); + (*(here->BSIM4SBspPtr) -= m * here->BSIM4gbs); + (*(here->BSIM4SBbpPtr) -= m * here->BSIM4grbps); + (*(here->BSIM4SBbPtr) -= m * here->BSIM4grbsb); + (*(here->BSIM4SBsbPtr +1) -= m * xcsbsb); + (*(here->BSIM4SBsbPtr) += m * (here->BSIM4gbs + + here->BSIM4grbps + here->BSIM4grbsb)); - (*(here->BSIM4BdbPtr) -= here->BSIM4grbdb); - (*(here->BSIM4BbpPtr) -= here->BSIM4grbpb); - (*(here->BSIM4BsbPtr) -= here->BSIM4grbsb); - (*(here->BSIM4BbPtr) += here->BSIM4grbsb + here->BSIM4grbdb - + here->BSIM4grbpb); + (*(here->BSIM4BdbPtr) -= m * here->BSIM4grbdb); + (*(here->BSIM4BbpPtr) -= m * here->BSIM4grbpb); + (*(here->BSIM4BsbPtr) -= m * here->BSIM4grbsb); + (*(here->BSIM4BbPtr) += m * (here->BSIM4grbsb + here->BSIM4grbdb + + here->BSIM4grbpb)); } @@ -654,7 +655,7 @@ double ggidld, ggidlg, ggidlb,ggisld, ggislg, ggislb, ggisls; * The charge node is isolated from the instance. */ if (here->BSIM4trnqsMod) - { (*(here->BSIM4QqPtr) += 1.0); + { (*(here->BSIM4QqPtr) += m * 1.0); (*(here->BSIM4QgpPtr) += 0.0); (*(here->BSIM4QdpPtr) += 0.0); (*(here->BSIM4QspPtr) += 0.0); diff --git a/src/spicelib/devices/bsim4/b4ask.c b/src/spicelib/devices/bsim4/b4ask.c index e3353cb57..56641b20c 100644 --- a/src/spicelib/devices/bsim4/b4ask.c +++ b/src/spicelib/devices/bsim4/b4ask.c @@ -1,24 +1,24 @@ -/**** BSIM4.2.1, Released by Xuemei Xi 10/05/2001 ****/ +/**** BSIM4.5.0 Released by Xuemei (Jane) Xi 07/27/2005 ****/ /********** - * Copyright 2001 Regents of the University of California. All rights reserved. - * File: b4ask.c of BSIM4.2.1. + * Copyright 2005 Regents of the University of California. All rights reserved. + * File: b4ask.c of BSIM4.5.0. * Author: 2000 Weidong Liu - * Authors: Xuemei Xi, Kanyu M. Cao, Hui Wan, Mansun Chan, Chenming Hu. + * Authors: 2001- Xuemei Xi, Mohan Dunga, Ali Niknejad, Chenming Hu. * Project Director: Prof. Chenming Hu. - * + * Modified by Xuemei Xi, 04/06/2001. * Modified by Xuemei Xi, 10/05/2001. + * Modified by Xuemei Xi, 05/09/2003. + * Modified by Xuemei Xi, Mohan Dunga, 07/29/2005. **********/ #include "ngspice.h" -#include -#include #include "ifsim.h" #include "cktdefs.h" #include "devdefs.h" #include "bsim4def.h" #include "sperror.h" - +#include "suffix.h" int BSIM4ask(ckt,inst,which,value,select) @@ -37,7 +37,10 @@ BSIM4instance *here = (BSIM4instance*)inst; case BSIM4_W: value->rValue = here->BSIM4w; return(OK); - case BSIM4_NF: + case BSIM4_M: + value->rValue = here->BSIM4m; + return(OK); + case BSIM4_NF: value->rValue = here->BSIM4nf; return(OK); case BSIM4_MIN: @@ -64,6 +67,28 @@ BSIM4instance *here = (BSIM4instance*)inst; case BSIM4_OFF: value->rValue = here->BSIM4off; return(OK); + case BSIM4_SA: + value->rValue = here->BSIM4sa ; + return(OK); + case BSIM4_SB: + value->rValue = here->BSIM4sb ; + return(OK); + case BSIM4_SD: + value->rValue = here->BSIM4sd ; + return(OK); + case BSIM4_SCA: + value->rValue = here->BSIM4sca ; + return(OK); + case BSIM4_SCB: + value->rValue = here->BSIM4scb ; + return(OK); + case BSIM4_SCC: + value->rValue = here->BSIM4scc ; + return(OK); + case BSIM4_SC: + value->rValue = here->BSIM4sc ; + return(OK); + case BSIM4_RBSB: value->rValue = here->BSIM4rbsb; return(OK); @@ -79,6 +104,15 @@ BSIM4instance *here = (BSIM4instance*)inst; case BSIM4_RBPD: value->rValue = here->BSIM4rbpd; return(OK); + case BSIM4_DELVTO: + value->rValue = here->BSIM4delvto; + return(OK); + case BSIM4_XGW: + value->rValue = here->BSIM4xgw; + return(OK); + case BSIM4_NGCON: + value->rValue = here->BSIM4ngcon; + return(OK); case BSIM4_TRNQSMOD: value->iValue = here->BSIM4trnqsMod; return(OK); @@ -205,27 +239,48 @@ BSIM4instance *here = (BSIM4instance*)inst; case BSIM4_GBS: value->rValue = here->BSIM4gbs; return(OK); - case BSIM4_QB: +/* case BSIM4_QB: value->rValue = *(ckt->CKTstate0 + here->BSIM4qb); - return(OK); + return(OK); */ case BSIM4_CQB: value->rValue = *(ckt->CKTstate0 + here->BSIM4cqb); return(OK); - case BSIM4_QG: +/* case BSIM4_QG: value->rValue = *(ckt->CKTstate0 + here->BSIM4qg); - return(OK); + return(OK); */ case BSIM4_CQG: value->rValue = *(ckt->CKTstate0 + here->BSIM4cqg); return(OK); - case BSIM4_QD: +/* case BSIM4_QD: value->rValue = *(ckt->CKTstate0 + here->BSIM4qd); - return(OK); + return(OK); */ case BSIM4_CQD: value->rValue = *(ckt->CKTstate0 + here->BSIM4cqd); return(OK); - case BSIM4_QS: +/* case BSIM4_QS: value->rValue = *(ckt->CKTstate0 + here->BSIM4qs); + return(OK); */ + case BSIM4_QB: + value->rValue = here->BSIM4qbulk; return(OK); + case BSIM4_QG: + value->rValue = here->BSIM4qgate; + return(OK); + case BSIM4_QS: + value->rValue = here->BSIM4qsrc; + return(OK); + case BSIM4_QD: + value->rValue = here->BSIM4qdrn; + return(OK); + case BSIM4_QDEF: + value->rValue = *(ckt->CKTstate0 + here->BSIM4qdef); + return(OK); + case BSIM4_GCRG: + value->rValue = here->BSIM4gcrg; + return(OK); + case BSIM4_GTAU: + value->rValue = here->BSIM4gtau; + return(OK); case BSIM4_CGGB: value->rValue = here->BSIM4cggb; return(OK); diff --git a/src/spicelib/devices/bsim4/b4check.c b/src/spicelib/devices/bsim4/b4check.c index 50fb00be1..6a59e52f4 100644 --- a/src/spicelib/devices/bsim4/b4check.c +++ b/src/spicelib/devices/bsim4/b4check.c @@ -1,24 +1,27 @@ -/**** BSIM4.2.1, Released by Xuemei Xi 10/05/2001 ****/ +/**** BSIM4.5.0 Released by Xuemei (Jane) Xi 07/29/2005 ****/ /********** - * Copyright 2001 Regents of the University of California. All rights reserved. - * File: b4check.c of BSIM4.2.1. + * Copyright 2005 Regents of the University of California. All rights reserved. + * File: b4check.c of BSIM4.5.0. * Author: 2000 Weidong Liu - * Authors: Xuemei Xi, Kanyu M. Cao, Hui Wan, Mansun Chan, Chenming Hu. + * Authors: 2001- Xuemei Xi, Mohan Dunga, Ali Niknejad, Chenming Hu. * Project Director: Prof. Chenming Hu. * Modified by Xuemei Xi, 04/06/2001. * Modified by Xuemei Xi, 10/05/2001. + * Modified by Xuemei Xi, 11/15/2002. + * Modified by Xuemei Xi, 05/09/2003. + * Modified by Xuemei Xi, 03/04/2004. + * Modified by Xuemei Xi, 07/29/2005. **********/ #include "ngspice.h" -#include -#include #include "cktdefs.h" #include "bsim4def.h" #include "trandefs.h" #include "const.h" #include "sperror.h" #include "devdefs.h" +#include "suffix.h" int BSIM4checkModel(model, here, ckt) @@ -33,13 +36,13 @@ FILE *fplog; if ((fplog = fopen("bsim4.out", "w")) != NULL) { pParam = here->pParam; fprintf(fplog, "BSIM4: Berkeley Short Channel IGFET Model-4\n"); - fprintf(fplog, "Developed by Weidong Liu, Xuemei Xi , Xiaodong Jin, Kanyu M. Cao and Prof. Chenming Hu in 2001.\n"); + fprintf(fplog, "Developed by Xuemei (Jane) Xi, Mohan Dunga, Prof. Ali Niknejad and Prof. Chenming Hu in 2003.\n"); fprintf(fplog, "\n"); fprintf(fplog, "++++++++++ BSIM4 PARAMETER CHECKING BELOW ++++++++++\n"); - if (strcmp(model->BSIM4version, "4.2.1") != 0) - { fprintf(fplog, "Warning: This model is BSIM4.2.1; you specified a wrong version number.\n"); - printf("Warning: This model is BSIM4.2.1; you specified a wrong version number.\n"); + if (strcmp(model->BSIM4version, "4.5.0") != 0) + { fprintf(fplog, "Warning: This model is BSIM4.5.0; you specified a wrong version number.\n"); + printf("Warning: This model is BSIM4.5.0; you specified a wrong version number.\n"); } fprintf(fplog, "Model = %s\n", model->BSIM4modName); @@ -51,7 +54,6 @@ FILE *fplog; } } - if (model->BSIM4toxe <= 0.0) { fprintf(fplog, "Fatal: Toxe = %g is not positive.\n", model->BSIM4toxe); @@ -86,6 +88,13 @@ FILE *fplog; pParam->BSIM4lpe0); Fatal_Flag = 1; } + if (model->BSIM4lintnoi > pParam->BSIM4leff/2) + { fprintf(fplog, "Fatal: Lintnoi = %g is too large - Leff for noise is negative.\n", + model->BSIM4lintnoi); + printf("Fatal: Lintnoi = %g is too large - Leff for noise is negative.\n", + model->BSIM4lintnoi); + Fatal_Flag = 1; + } if (pParam->BSIM4lpeb < -pParam->BSIM4leff) { fprintf(fplog, "Fatal: Lpeb = %g is less than -Leff.\n", pParam->BSIM4lpeb); @@ -93,14 +102,6 @@ FILE *fplog; pParam->BSIM4lpeb); Fatal_Flag = 1; } - - if (pParam->BSIM4phin < -0.4) - { fprintf(fplog, "Fatal: Phin = %g is less than -0.4.\n", - pParam->BSIM4phin); - printf("Fatal: Phin = %g is less than -0.4.\n", - pParam->BSIM4phin); - Fatal_Flag = 1; - } if (pParam->BSIM4ndep <= 0.0) { fprintf(fplog, "Fatal: Ndep = %g is not positive.\n", pParam->BSIM4ndep); @@ -108,6 +109,17 @@ FILE *fplog; pParam->BSIM4ndep); Fatal_Flag = 1; } + if (pParam->BSIM4phi <= 0.0) + { fprintf(fplog, "Fatal: Phi = %g is not positive. Please check Phin and Ndep\n", + pParam->BSIM4phi); + fprintf(fplog, " Phin = %g Ndep = %g \n", + pParam->BSIM4phin, pParam->BSIM4ndep); + printf("Fatal: Phi = %g is not positive. Please check Phin and Ndep\n", + pParam->BSIM4phi); + printf(" Phin = %g Ndep = %g \n", + pParam->BSIM4phin, pParam->BSIM4ndep); + Fatal_Flag = 1; + } if (pParam->BSIM4nsub <= 0.0) { fprintf(fplog, "Fatal: Nsub = %g is not positive.\n", pParam->BSIM4nsub); @@ -166,10 +178,10 @@ FILE *fplog; printf("Fatal: (B1 + Weff) = 0 causing divided-by-zero.\n"); Fatal_Flag = 1; } - if (pParam->BSIM4u0temp <= 0.0) - { fprintf(fplog, "Fatal: u0 at current temperature = %g is not positive.\n", pParam->BSIM4u0temp); + if (here->BSIM4u0temp <= 0.0) + { fprintf(fplog, "Fatal: u0 at current temperature = %g is not positive.\n", here->BSIM4u0temp); printf("Fatal: u0 at current temperature = %g is not positive.\n", - pParam->BSIM4u0temp); + here->BSIM4u0temp); Fatal_Flag = 1; } @@ -180,10 +192,10 @@ FILE *fplog; Fatal_Flag = 1; } - if (pParam->BSIM4vsattemp <= 0.0) - { fprintf(fplog, "Fatal: Vsat at current temperature = %g is not positive.\n", pParam->BSIM4vsattemp); + if (here->BSIM4vsattemp <= 0.0) + { fprintf(fplog, "Fatal: Vsat at current temperature = %g is not positive.\n", here->BSIM4vsattemp); printf("Fatal: Vsat at current temperature = %g is not positive.\n", - pParam->BSIM4vsattemp); + here->BSIM4vsattemp); Fatal_Flag = 1; } @@ -198,12 +210,12 @@ FILE *fplog; printf("Fatal: Drout = %g is negative.\n", pParam->BSIM4drout); Fatal_Flag = 1; } - - if (pParam->BSIM4pscbe2 <= 0.0) - { fprintf(fplog, "Warning: Pscbe2 = %g is not positive.\n", - pParam->BSIM4pscbe2); - printf("Warning: Pscbe2 = %g is not positive.\n", pParam->BSIM4pscbe2); - } + + /*if (here->BSIM4m < 1.0) + { fprintf(fplog, "Fatal: Number of multiplier = %g is smaller than one.\n", here->BSIM4m); + printf("Fatal: Number of multiplier = %g is smaller than one.\n", here->BSIM4m); + Fatal_Flag = 1; + }*/ if (here->BSIM4nf < 1.0) { fprintf(fplog, "Fatal: Number of finger = %g is smaller than one.\n", here->BSIM4nf); @@ -211,18 +223,32 @@ FILE *fplog; Fatal_Flag = 1; } + if((here->BSIM4sa > 0.0) && (here->BSIM4sb > 0.0) && + ((here->BSIM4nf == 1.0) || ((here->BSIM4nf > 1.0) && (here->BSIM4sd > 0.0))) ) + { if (model->BSIM4saref <= 0.0) + { fprintf(fplog, "Fatal: SAref = %g is not positive.\n",model->BSIM4saref); + printf("Fatal: SAref = %g is not positive.\n",model->BSIM4saref); + Fatal_Flag = 1; + } + if (model->BSIM4sbref <= 0.0) + { fprintf(fplog, "Fatal: SBref = %g is not positive.\n",model->BSIM4sbref); + printf("Fatal: SBref = %g is not positive.\n",model->BSIM4sbref); + Fatal_Flag = 1; + } + } + if ((here->BSIM4l + model->BSIM4xl) <= model->BSIM4xgl) { fprintf(fplog, "Fatal: The parameter xgl must be smaller than Ldrawn+XL.\n"); printf("Fatal: The parameter xgl must be smaller than Ldrawn+XL.\n"); Fatal_Flag = 1; } - if (model->BSIM4ngcon < 1.0) + if (here->BSIM4ngcon < 1.0) { fprintf(fplog, "Fatal: The parameter ngcon cannot be smaller than one.\n"); printf("Fatal: The parameter ngcon cannot be smaller than one.\n"); Fatal_Flag = 1; } - if ((model->BSIM4ngcon != 1.0) && (model->BSIM4ngcon != 2.0)) - { model->BSIM4ngcon = 1.0; + if ((here->BSIM4ngcon != 1.0) && (here->BSIM4ngcon != 2.0)) + { here->BSIM4ngcon = 1.0; fprintf(fplog, "Warning: Ngcon must be equal to one or two; reset to 1.0.\n"); printf("Warning: Ngcon must be equal to one or two; reset to 1.0.\n"); } @@ -233,27 +259,61 @@ FILE *fplog; printf("Warning: Gbmin = %g is too small.\n", model->BSIM4gbmin); } - if (pParam->BSIM4noff < 0.1) - { fprintf(fplog, "Warning: Noff = %g is too small.\n", - pParam->BSIM4noff); - printf("Warning: Noff = %g is too small.\n", pParam->BSIM4noff); + /* Check saturation parameters */ + if (pParam->BSIM4fprout < 0.0) + { fprintf(fplog, "Fatal: fprout = %g is negative.\n", + pParam->BSIM4fprout); + printf("Fatal: fprout = %g is negative.\n", pParam->BSIM4fprout); + Fatal_Flag = 1; } - if (pParam->BSIM4noff > 4.0) - { fprintf(fplog, "Warning: Noff = %g is too large.\n", - pParam->BSIM4noff); - printf("Warning: Noff = %g is too large.\n", pParam->BSIM4noff); + if (pParam->BSIM4pdits < 0.0) + { fprintf(fplog, "Fatal: pdits = %g is negative.\n", + pParam->BSIM4pdits); + printf("Fatal: pdits = %g is negative.\n", pParam->BSIM4pdits); + Fatal_Flag = 1; + } + if (model->BSIM4pditsl < 0.0) + { fprintf(fplog, "Fatal: pditsl = %g is negative.\n", + model->BSIM4pditsl); + printf("Fatal: pditsl = %g is negative.\n", model->BSIM4pditsl); + Fatal_Flag = 1; } - if (pParam->BSIM4voffcv < -0.5) - { fprintf(fplog, "Warning: Voffcv = %g is too small.\n", - pParam->BSIM4voffcv); - printf("Warning: Voffcv = %g is too small.\n", pParam->BSIM4voffcv); + /* Check gate current parameters */ + if (model->BSIM4igbMod) { + if (pParam->BSIM4nigbinv <= 0.0) + { fprintf(fplog, "Fatal: nigbinv = %g is non-positive.\n", + pParam->BSIM4nigbinv); + printf("Fatal: nigbinv = %g is non-positive.\n", pParam->BSIM4nigbinv); + Fatal_Flag = 1; } - if (pParam->BSIM4voffcv > 0.5) - { fprintf(fplog, "Warning: Voffcv = %g is too large.\n", - pParam->BSIM4voffcv); - printf("Warning: Voffcv = %g is too large.\n", pParam->BSIM4voffcv); + if (pParam->BSIM4nigbacc <= 0.0) + { fprintf(fplog, "Fatal: nigbacc = %g is non-positive.\n", + pParam->BSIM4nigbacc); + printf("Fatal: nigbacc = %g is non-positive.\n", pParam->BSIM4nigbacc); + Fatal_Flag = 1; } + } + if (model->BSIM4igcMod) { + if (pParam->BSIM4nigc <= 0.0) + { fprintf(fplog, "Fatal: nigc = %g is non-positive.\n", + pParam->BSIM4nigc); + printf("Fatal: nigc = %g is non-positive.\n", pParam->BSIM4nigc); + Fatal_Flag = 1; + } + if (pParam->BSIM4poxedge <= 0.0) + { fprintf(fplog, "Fatal: poxedge = %g is non-positive.\n", + pParam->BSIM4poxedge); + printf("Fatal: poxedge = %g is non-positive.\n", pParam->BSIM4poxedge); + Fatal_Flag = 1; + } + if (pParam->BSIM4pigcd <= 0.0) + { fprintf(fplog, "Fatal: pigcd = %g is non-positive.\n", + pParam->BSIM4pigcd); + printf("Fatal: pigcd = %g is non-positive.\n", pParam->BSIM4pigcd); + Fatal_Flag = 1; + } + } /* Check capacitance parameters */ if (pParam->BSIM4clc < 0.0) @@ -262,28 +322,63 @@ FILE *fplog; Fatal_Flag = 1; } - if (pParam->BSIM4moin < 5.0) - { fprintf(fplog, "Warning: Moin = %g is too small.\n", - pParam->BSIM4moin); - printf("Warning: Moin = %g is too small.\n", pParam->BSIM4moin); + /* Check overlap capacitance parameters */ + if (pParam->BSIM4ckappas < 0.02) + { fprintf(fplog, "Warning: ckappas = %g is too small. Set to 0.02\n", + pParam->BSIM4ckappas); + printf("Warning: ckappas = %g is too small.\n", pParam->BSIM4ckappas); + pParam->BSIM4ckappas = 0.02; + } + if (pParam->BSIM4ckappad < 0.02) + { fprintf(fplog, "Warning: ckappad = %g is too small. Set to 0.02\n", + pParam->BSIM4ckappad); + printf("Warning: ckappad = %g is too small.\n", pParam->BSIM4ckappad); + pParam->BSIM4ckappad = 0.02; } - if (pParam->BSIM4moin > 25.0) - { fprintf(fplog, "Warning: Moin = %g is too large.\n", - pParam->BSIM4moin); - printf("Warning: Moin = %g is too large.\n", pParam->BSIM4moin); - } - if(model->BSIM4capMod ==2) { - if (pParam->BSIM4acde < 0.4) - { fprintf(fplog, "Warning: Acde = %g is too small.\n", - pParam->BSIM4acde); - printf("Warning: Acde = %g is too small.\n", pParam->BSIM4acde); - } - if (pParam->BSIM4acde > 1.6) - { fprintf(fplog, "Warning: Acde = %g is too large.\n", - pParam->BSIM4acde); - printf("Warning: Acde = %g is too large.\n", pParam->BSIM4acde); - } + + if (model->BSIM4vtss < 0.0) + { fprintf(fplog, "Fatal: Vtss = %g is negative.\n", + model->BSIM4vtss); + printf("Fatal: Vtss = %g is negative.\n", + model->BSIM4vtss); + Fatal_Flag = 1; } + if (model->BSIM4vtsd < 0.0) + { fprintf(fplog, "Fatal: Vtsd = %g is negative.\n", + model->BSIM4vtsd); + printf("Fatal: Vtsd = %g is negative.\n", + model->BSIM4vtsd); + Fatal_Flag = 1; + } + if (model->BSIM4vtssws < 0.0) + { fprintf(fplog, "Fatal: Vtssws = %g is negative.\n", + model->BSIM4vtssws); + printf("Fatal: Vtssws = %g is negative.\n", + model->BSIM4vtssws); + Fatal_Flag = 1; + } + if (model->BSIM4vtsswd < 0.0) + { fprintf(fplog, "Fatal: Vtsswd = %g is negative.\n", + model->BSIM4vtsswd); + printf("Fatal: Vtsswd = %g is negative.\n", + model->BSIM4vtsswd); + Fatal_Flag = 1; + } + if (model->BSIM4vtsswgs < 0.0) + { fprintf(fplog, "Fatal: Vtsswgs = %g is negative.\n", + model->BSIM4vtsswgs); + printf("Fatal: Vtsswgs = %g is negative.\n", + model->BSIM4vtsswgs); + Fatal_Flag = 1; + } + if (model->BSIM4vtsswgd < 0.0) + { fprintf(fplog, "Fatal: Vtsswgd = %g is negative.\n", + model->BSIM4vtsswgd); + printf("Fatal: Vtsswgd = %g is negative.\n", + model->BSIM4vtsswgd); + Fatal_Flag = 1; + } + if (model->BSIM4paramChk ==1) { @@ -373,7 +468,7 @@ FILE *fplog; printf("Warning: Dvt0 = %g is negative.\n", pParam->BSIM4dvt0); } - if (fabs(1.0e-6 / (pParam->BSIM4w0 + pParam->BSIM4weff)) > 10.0) + if (fabs(1.0e-8 / (pParam->BSIM4w0 + pParam->BSIM4weff)) > 10.0) { fprintf(fplog, "Warning: (W0 + Weff) may be too small.\n"); printf("Warning: (W0 + Weff) may be too small.\n"); } @@ -395,14 +490,14 @@ FILE *fplog; printf("Warning: Cdscd = %g is negative.\n", pParam->BSIM4cdscd); } /* Check DIBL parameters */ - if (pParam->BSIM4eta0 < 0.0) + if (here->BSIM4eta0 < 0.0) { fprintf(fplog, "Warning: Eta0 = %g is negative.\n", - pParam->BSIM4eta0); - printf("Warning: Eta0 = %g is negative.\n", pParam->BSIM4eta0); + here->BSIM4eta0); + printf("Warning: Eta0 = %g is negative.\n", here->BSIM4eta0); } /* Check Abulk parameters */ - if (fabs(1.0e-6 / (pParam->BSIM4b1 + pParam->BSIM4weff)) > 10.0) + if (fabs(1.0e-8 / (pParam->BSIM4b1 + pParam->BSIM4weff)) > 10.0) { fprintf(fplog, "Warning: (B1 + Weff) may be too small.\n"); printf("Warning: (B1 + Weff) may be too small.\n"); } @@ -422,7 +517,6 @@ FILE *fplog; pParam->BSIM4a2); pParam->BSIM4a2 = 1.0; pParam->BSIM4a1 = 0.0; - } if (pParam->BSIM4prwg < 0.0) @@ -432,6 +526,7 @@ FILE *fplog; pParam->BSIM4prwg); pParam->BSIM4prwg = 0.0; } + if (pParam->BSIM4rdsw < 0.0) { fprintf(fplog, "Warning: Rdsw = %g is negative. Set to zero.\n", pParam->BSIM4rdsw); @@ -440,6 +535,7 @@ FILE *fplog; pParam->BSIM4rdsw = 0.0; pParam->BSIM4rds0 = 0.0; } + if (pParam->BSIM4rds0 < 0.0) { fprintf(fplog, "Warning: Rds at current temperature = %g is negative. Set to zero.\n", pParam->BSIM4rds0); @@ -456,29 +552,44 @@ FILE *fplog; pParam->BSIM4rdswmin = 0.0; } + if (pParam->BSIM4pscbe2 <= 0.0) + { fprintf(fplog, "Warning: Pscbe2 = %g is not positive.\n", + pParam->BSIM4pscbe2); + printf("Warning: Pscbe2 = %g is not positive.\n", pParam->BSIM4pscbe2); + } + if (pParam->BSIM4vsattemp < 1.0e3) { fprintf(fplog, "Warning: Vsat at current temperature = %g may be too small.\n", pParam->BSIM4vsattemp); printf("Warning: Vsat at current temperature = %g may be too small.\n", pParam->BSIM4vsattemp); } - if (pParam->BSIM4fprout < 0.0) - { fprintf(fplog, "Fatal: fprout = %g is negative.\n", - pParam->BSIM4fprout); - printf("Fatal: fprout = %g is negative.\n", pParam->BSIM4fprout); - Fatal_Flag = 1; - } - if (pParam->BSIM4pdits < 0.0) - { fprintf(fplog, "Fatal: pdits = %g is negative.\n", - pParam->BSIM4pdits); - printf("Fatal: pdits = %g is negative.\n", pParam->BSIM4pdits); - Fatal_Flag = 1; - } - if (model->BSIM4pditsl < 0.0) - { fprintf(fplog, "Fatal: pditsl = %g is negative.\n", - model->BSIM4pditsl); - printf("Fatal: pditsl = %g is negative.\n", model->BSIM4pditsl); - Fatal_Flag = 1; - } + if((model->BSIM4lambdaGiven) && (pParam->BSIM4lambda > 0.0) ) + { + if (pParam->BSIM4lambda > 1.0e-9) + { fprintf(fplog, "Warning: Lambda = %g may be too large.\n", pParam->BSIM4lambda); + printf("Warning: Lambda = %g may be too large.\n", pParam->BSIM4lambda); + } + } + + if((model->BSIM4vtlGiven) && (pParam->BSIM4vtl > 0.0) ) + { + if (pParam->BSIM4vtl < 6.0e4) + { fprintf(fplog, "Warning: Thermal velocity vtl = %g may be too small.\n", pParam->BSIM4vtl); + printf("Warning: Thermal velocity vtl = %g may be too small.\n", pParam->BSIM4vtl); + } + + if (pParam->BSIM4xn < 3.0) + { fprintf(fplog, "Warning: back scattering coeff xn = %g is too small.\n", pParam->BSIM4xn); + printf("Warning: back scattering coeff xn = %g is too small. Reset to 3.0 \n", pParam->BSIM4xn); + pParam->BSIM4xn = 3.0; + } + + if (model->BSIM4lc < 0.0) + { fprintf(fplog, "Warning: back scattering coeff lc = %g is too small.\n", model->BSIM4lc); + printf("Warning: back scattering coeff lc = %g is too small. Reset to 0.0\n", model->BSIM4lc); + pParam->BSIM4lc = 0.0; + } + } if (pParam->BSIM4pdibl1 < 0.0) { fprintf(fplog, "Warning: Pdibl1 = %g is negative.\n", @@ -491,37 +602,72 @@ FILE *fplog; printf("Warning: Pdibl2 = %g is negative.\n", pParam->BSIM4pdibl2); } - if (pParam->BSIM4nigbinv <= 0.0) - { fprintf(fplog, "Fatal: nigbinv = %g is non-positive.\n", - pParam->BSIM4nigbinv); - printf("Fatal: nigbinv = %g is non-positive.\n", pParam->BSIM4nigbinv); - Fatal_Flag = 1; - } - if (pParam->BSIM4nigbacc <= 0.0) - { fprintf(fplog, "Fatal: nigbacc = %g is non-positive.\n", - pParam->BSIM4nigbacc); - printf("Fatal: nigbacc = %g is non-positive.\n", pParam->BSIM4nigbacc); - Fatal_Flag = 1; - } - if (pParam->BSIM4nigc <= 0.0) - { fprintf(fplog, "Fatal: nigc = %g is non-positive.\n", - pParam->BSIM4nigc); - printf("Fatal: nigc = %g is non-positive.\n", pParam->BSIM4nigc); - Fatal_Flag = 1; - } - if (pParam->BSIM4poxedge <= 0.0) - { fprintf(fplog, "Fatal: poxedge = %g is non-positive.\n", - pParam->BSIM4poxedge); - printf("Fatal: poxedge = %g is non-positive.\n", pParam->BSIM4poxedge); - Fatal_Flag = 1; - } - if (pParam->BSIM4pigcd <= 0.0) - { fprintf(fplog, "Fatal: pigcd = %g is non-positive.\n", - pParam->BSIM4pigcd); - printf("Fatal: pigcd = %g is non-positive.\n", pParam->BSIM4pigcd); - Fatal_Flag = 1; +/* Check stress effect parameters */ + if((here->BSIM4sa > 0.0) && (here->BSIM4sb > 0.0) && + ((here->BSIM4nf == 1.0) || ((here->BSIM4nf > 1.0) && (here->BSIM4sd > 0.0))) ) + { if (model->BSIM4lodk2 <= 0.0) + { fprintf(fplog, "Warning: LODK2 = %g is not positive.\n",model->BSIM4lodk2); + printf("Warning: LODK2 = %g is not positive.\n",model->BSIM4lodk2); + } + if (model->BSIM4lodeta0 <= 0.0) + { fprintf(fplog, "Warning: LODETA0 = %g is not positive.\n",model->BSIM4lodeta0); + printf("Warning: LODETA0 = %g is not positive.\n",model->BSIM4lodeta0); + } + } + +/* Check gate resistance parameters */ + if (here->BSIM4rgateMod == 1) + { if (model->BSIM4rshg <= 0.0) + printf("Warning: rshg should be positive for rgateMod = 1.\n"); + } + else if (here->BSIM4rgateMod == 2) + { if (model->BSIM4rshg <= 0.0) + printf("Warning: rshg <= 0.0 for rgateMod = 2.\n"); + else if (pParam->BSIM4xrcrg1 <= 0.0) + printf("Warning: xrcrg1 <= 0.0 for rgateMod = 2.\n"); + } + if (here->BSIM4rgateMod == 3) + { if (model->BSIM4rshg <= 0.0) + printf("Warning: rshg should be positive for rgateMod = 3.\n"); + else if (pParam->BSIM4xrcrg1 <= 0.0) + printf("Warning: xrcrg1 should be positive for rgateMod = 3.\n"); + } + +/* Check capacitance parameters */ + if (pParam->BSIM4noff < 0.1) + { fprintf(fplog, "Warning: Noff = %g is too small.\n", + pParam->BSIM4noff); + printf("Warning: Noff = %g is too small.\n", pParam->BSIM4noff); } + if (pParam->BSIM4voffcv < -0.5) + { fprintf(fplog, "Warning: Voffcv = %g is too small.\n", + pParam->BSIM4voffcv); + printf("Warning: Voffcv = %g is too small.\n", pParam->BSIM4voffcv); + } + + if (pParam->BSIM4moin < 5.0) + { fprintf(fplog, "Warning: Moin = %g is too small.\n", + pParam->BSIM4moin); + printf("Warning: Moin = %g is too small.\n", pParam->BSIM4moin); + } + if (pParam->BSIM4moin > 25.0) + { fprintf(fplog, "Warning: Moin = %g is too large.\n", + pParam->BSIM4moin); + printf("Warning: Moin = %g is too large.\n", pParam->BSIM4moin); + } + if(model->BSIM4capMod ==2) { + if (pParam->BSIM4acde < 0.1) + { fprintf(fplog, "Warning: Acde = %g is too small.\n", + pParam->BSIM4acde); + printf("Warning: Acde = %g is too small.\n", pParam->BSIM4acde); + } + if (pParam->BSIM4acde > 1.6) + { fprintf(fplog, "Warning: Acde = %g is too large.\n", + pParam->BSIM4acde); + printf("Warning: Acde = %g is too large.\n", pParam->BSIM4acde); + } + } /* Check overlap capacitance parameters */ if (model->BSIM4cgdo < 0.0) @@ -534,7 +680,12 @@ FILE *fplog; printf("Warning: cgso = %g is negative. Set to zero.\n", model->BSIM4cgso); model->BSIM4cgso = 0.0; } - + if (model->BSIM4cgbo < 0.0) + { fprintf(fplog, "Warning: cgbo = %g is negative. Set to zero.\n", model->BSIM4cgbo); + printf("Warning: cgbo = %g is negative. Set to zero.\n", model->BSIM4cgbo); + model->BSIM4cgbo = 0.0; + } + if (model->BSIM4tnoiMod == 1) { if (model->BSIM4tnoia < 0.0) { fprintf(fplog, "Warning: tnoia = %g is negative. Set to zero.\n", model->BSIM4tnoia); printf("Warning: tnoia = %g is negative. Set to zero.\n", model->BSIM4tnoia); @@ -546,12 +697,114 @@ FILE *fplog; model->BSIM4tnoib = 0.0; } - if (model->BSIM4ntnoi < 0.0) + if (model->BSIM4rnoia < 0.0) + { fprintf(fplog, "Warning: rnoia = %g is negative. Set to zero.\n", model->BSIM4rnoia); + printf("Warning: rnoia = %g is negative. Set to zero.\n", model->BSIM4rnoia); + model->BSIM4rnoia = 0.0; + } + if (model->BSIM4rnoib < 0.0) + { fprintf(fplog, "Warning: rnoib = %g is negative. Set to zero.\n", model->BSIM4rnoib); + printf("Warning: rnoib = %g is negative. Set to zero.\n", model->BSIM4rnoib); + model->BSIM4rnoib = 0.0; + } + } + + if (model->BSIM4SjctEmissionCoeff < 0.0) + { fprintf(fplog, "Warning: Njs = %g is negative.\n", + model->BSIM4SjctEmissionCoeff); + printf("Warning: Njs = %g is negative.\n", + model->BSIM4SjctEmissionCoeff); + } + if (model->BSIM4DjctEmissionCoeff < 0.0) + { fprintf(fplog, "Warning: Njd = %g is negative.\n", + model->BSIM4DjctEmissionCoeff); + printf("Warning: Njd = %g is negative.\n", + model->BSIM4DjctEmissionCoeff); + } + if (model->BSIM4njtstemp < 0.0) + { fprintf(fplog, "Warning: Njts = %g is negative at temperature = %g.\n", + model->BSIM4njtstemp, ckt->CKTtemp); + printf("Warning: Njts = %g is negative at temperature = %g.\n", + model->BSIM4njtstemp, ckt->CKTtemp); + } + if (model->BSIM4njtsswtemp < 0.0) + { fprintf(fplog, "Warning: Njtssw = %g is negative at temperature = %g.\n", + model->BSIM4njtsswtemp, ckt->CKTtemp); + printf("Warning: Njtssw = %g is negative at temperature = %g.\n", + model->BSIM4njtsswtemp, ckt->CKTtemp); + } + if (model->BSIM4njtsswgtemp < 0.0) + { fprintf(fplog, "Warning: Njtsswg = %g is negative at temperature = %g.\n", + model->BSIM4njtsswgtemp, ckt->CKTtemp); + printf("Warning: Njtsswg = %g is negative at temperature = %g.\n", + model->BSIM4njtsswgtemp, ckt->CKTtemp); + } + if (model->BSIM4ntnoi < 0.0) { fprintf(fplog, "Warning: ntnoi = %g is negative. Set to zero.\n", model->BSIM4ntnoi); printf("Warning: ntnoi = %g is negative. Set to zero.\n", model->BSIM4ntnoi); model->BSIM4ntnoi = 0.0; } + /* diode model */ + if (model->BSIM4SbulkJctBotGradingCoeff >= 0.99) + { fprintf(fplog, "Warning: MJS = %g is too big. Set to 0.99.\n", model->BSIM4SbulkJctBotGradingCoeff); + printf("Warning: MJS = %g is too big. Set to 0.99.\n", model->BSIM4SbulkJctBotGradingCoeff); + model->BSIM4SbulkJctBotGradingCoeff = 0.99; + } + if (model->BSIM4SbulkJctSideGradingCoeff >= 0.99) + { fprintf(fplog, "Warning: MJSWS = %g is too big. Set to 0.99.\n", model->BSIM4SbulkJctSideGradingCoeff); + printf("Warning: MJSWS = %g is too big. Set to 0.99.\n", model->BSIM4SbulkJctSideGradingCoeff); + model->BSIM4SbulkJctSideGradingCoeff = 0.99; + } + if (model->BSIM4SbulkJctGateSideGradingCoeff >= 0.99) + { fprintf(fplog, "Warning: MJSWGS = %g is too big. Set to 0.99.\n", model->BSIM4SbulkJctGateSideGradingCoeff); + printf("Warning: MJSWGS = %g is too big. Set to 0.99.\n", model->BSIM4SbulkJctGateSideGradingCoeff); + model->BSIM4SbulkJctGateSideGradingCoeff = 0.99; + } + + if (model->BSIM4DbulkJctBotGradingCoeff >= 0.99) + { fprintf(fplog, "Warning: MJD = %g is too big. Set to 0.99.\n", model->BSIM4DbulkJctBotGradingCoeff); + printf("Warning: MJD = %g is too big. Set to 0.99.\n", model->BSIM4DbulkJctBotGradingCoeff); + model->BSIM4DbulkJctBotGradingCoeff = 0.99; + } + if (model->BSIM4DbulkJctSideGradingCoeff >= 0.99) + { fprintf(fplog, "Warning: MJSWD = %g is too big. Set to 0.99.\n", model->BSIM4DbulkJctSideGradingCoeff); + printf("Warning: MJSWD = %g is too big. Set to 0.99.\n", model->BSIM4DbulkJctSideGradingCoeff); + model->BSIM4DbulkJctSideGradingCoeff = 0.99; + } + if (model->BSIM4DbulkJctGateSideGradingCoeff >= 0.99) + { fprintf(fplog, "Warning: MJSWGD = %g is too big. Set to 0.99.\n", model->BSIM4DbulkJctGateSideGradingCoeff); + printf("Warning: MJSWGD = %g is too big. Set to 0.99.\n", model->BSIM4DbulkJctGateSideGradingCoeff); + model->BSIM4DbulkJctGateSideGradingCoeff = 0.99; + } + if (model->BSIM4wpemod == 1) + { + if (model->BSIM4scref <= 0.0) + { fprintf(fplog, "Warning: SCREF = %g is not positive. Set to 1e-6.\n", model->BSIM4scref); + printf("Warning: SCREF = %g is not positive. Set to 1e-6.\n", model->BSIM4scref); + model->BSIM4scref = 1e-6; + } + if (here->BSIM4sca < 0.0) + { fprintf(fplog, "Warning: SCA = %g is negative. Set to 0.0.\n", here->BSIM4sca); + printf("Warning: SCA = %g is negative. Set to 0.0.\n", here->BSIM4sca); + here->BSIM4sca = 0.0; + } + if (here->BSIM4scb < 0.0) + { fprintf(fplog, "Warning: SCB = %g is negative. Set to 0.0.\n", here->BSIM4scb); + printf("Warning: SCB = %g is negative. Set to 0.0.\n", here->BSIM4scb); + here->BSIM4scb = 0.0; + } + if (here->BSIM4scc < 0.0) + { fprintf(fplog, "Warning: SCC = %g is negative. Set to 0.0.\n", here->BSIM4scc); + printf("Warning: SCC = %g is negative. Set to 0.0.\n", here->BSIM4scc); + here->BSIM4scc = 0.0; + } + if (here->BSIM4sc < 0.0) + { fprintf(fplog, "Warning: SC = %g is negative. Set to 0.0.\n", here->BSIM4sc); + printf("Warning: SC = %g is negative. Set to 0.0.\n", here->BSIM4sc); + here->BSIM4sc = 0.0; + } + } }/* loop for the parameter check for warning messages */ fclose(fplog); } diff --git a/src/spicelib/devices/bsim4/b4cvtest.c b/src/spicelib/devices/bsim4/b4cvtest.c index 2626b5a5f..faa18ee48 100644 --- a/src/spicelib/devices/bsim4/b4cvtest.c +++ b/src/spicelib/devices/bsim4/b4cvtest.c @@ -1,25 +1,24 @@ -/**** BSIM4.2.1, Released by Xuemei Xi 10/05/2001 ****/ +/**** BSIM4.5.0 Released by Xuemei (Jane) Xi 07/29/2005 ****/ /********** - * Copyright 2001 Regents of the University of California. All rights reserved. - * File: b4cvtest.c of BSIM4.2.1. + * Copyright 2005 Regents of the University of California. All rights reserved. + * File: b4cvtest.c of BSIM4.5.0. * Author: 2000 Weidong Liu - * Authors: Xuemei Xi, Kanyu M. Cao, Hui Wan, Mansun Chan, Chenming Hu. + * Authors: 2001- Xuemei Xi, Mohan Dunga, Ali Niknejad, Chenming Hu. * Project Director: Prof. Chenming Hu. - * + * Modified by Xuemei Xi, 04/06/2001. * Modified by Xuemei Xi, 10/05/2001. + * Modified by Xuemei Xi, 05/09/2003. **********/ #include "ngspice.h" -#include -#include #include "cktdefs.h" #include "bsim4def.h" #include "trandefs.h" #include "const.h" #include "devdefs.h" #include "sperror.h" - +#include "suffix.h" int @@ -43,10 +42,8 @@ double tol0, tol1, tol2, tol3, tol4, tol5, tol6; for (; model != NULL; model = model->BSIM4nextModel) { for (here = model->BSIM4instances; here != NULL ; here=here->BSIM4nextInstance) - { - if (here->BSIM4owner != ARCHme) continue; - - vds = model->BSIM4type + { if (here->BSIM4owner != ARCHme) continue; + vds = model->BSIM4type * (*(ckt->CKTrhsOld + here->BSIM4dNodePrime) - *(ckt->CKTrhsOld + here->BSIM4sNodePrime)); vgs = model->BSIM4type @@ -113,11 +110,11 @@ double tol0, tol1, tol2, tol3, tol4, tol5, tol6; * delvds + here->BSIM4gIgbb * delvbs; } else - { Idtot = here->BSIM4cd + here->BSIM4cbd - here->BSIM4Igisl; + { Idtot = here->BSIM4cd + here->BSIM4cbd - here->BSIM4Igidl; /* bugfix */ cdhat = Idtot + here->BSIM4gbd * delvbd_jct + here->BSIM4gmbs * delvbd + here->BSIM4gm * delvgd - - here->BSIM4gds * delvds - here->BSIM4ggislg * vgd - - here->BSIM4ggislb * vbd + here->BSIM4ggisls * vds; + - (here->BSIM4gds + here->BSIM4ggidls) * delvds + - here->BSIM4ggidlg * delvgs - here->BSIM4ggidlb * delvbs; Igstot = here->BSIM4Igs + here->BSIM4Igcd; cgshat = Igstot + here->BSIM4gIgsg * delvgs + here->BSIM4gIgcdg * delvgd @@ -182,11 +179,11 @@ double tol0, tol1, tol2, tol3, tol4, tol5, tol6; - here->BSIM4ggislg * delvgd - here->BSIM4ggislb* delvbd + here->BSIM4ggisls * delvds ; } else - { cbhat = Ibtot + here->BSIM4gbs * delvbs_jct + here->BSIM4gbd - * delvbd_jct - (here->BSIM4gbbs + here->BSIM4ggidlb) * delvbd - - (here->BSIM4gbgs + here->BSIM4ggidlg) * delvgd - + (here->BSIM4gbds + here->BSIM4ggidld) * delvds - - here->BSIM4ggislg * delvgs - here->BSIM4ggislb * delvbs + here->BSIM4ggisls * delvds; + { cbhat = Ibtot + here->BSIM4gbs * delvbs_jct + here->BSIM4gbd + * delvbd_jct - (here->BSIM4gbbs + here->BSIM4ggislb) * delvbd + - (here->BSIM4gbgs + here->BSIM4ggislg) * delvgd + + (here->BSIM4gbds + here->BSIM4ggisld - here->BSIM4ggidls) * delvds + - here->BSIM4ggidlg * delvgs - here->BSIM4ggidlb * delvbs; } tol6 = ckt->CKTreltol * MAX(fabs(cbhat), fabs(Ibtot)) + ckt->CKTabstol; diff --git a/src/spicelib/devices/bsim4/b4del.c b/src/spicelib/devices/bsim4/b4del.c index fde0870bc..d49e2e60f 100644 --- a/src/spicelib/devices/bsim4/b4del.c +++ b/src/spicelib/devices/bsim4/b4del.c @@ -1,18 +1,18 @@ -/**** BSIM4.2.1, Released by Xuemei Xi 10/05/2001 ****/ +/**** BSIM4.5.0 Released by Xuemei (Jane) Xi 07/29/2005 ****/ /********** - * Copyright 2001 Regents of the University of California. All rights reserved. - * File: b4del.c of BSIM4.2.1. + * Copyright 2005 Regents of the University of California. All rights reserved. + * File: b4del.c of BSIM4.5.0. * Author: 2000 Weidong Liu - * Authors: Xuemei Xi, Kanyu M. Cao, Hui Wan, Mansun Chan, Chenming Hu. + * Authors: 2001- Xuemei Xi, Mohan Dunga, Ali Niknejad, Chenming Hu. * Project Director: Prof. Chenming Hu. **********/ #include "ngspice.h" -#include #include "bsim4def.h" #include "sperror.h" #include "gendefs.h" +#include "suffix.h" int diff --git a/src/spicelib/devices/bsim4/b4dest.c b/src/spicelib/devices/bsim4/b4dest.c index d1c5f2bd4..eb60d1fe9 100644 --- a/src/spicelib/devices/bsim4/b4dest.c +++ b/src/spicelib/devices/bsim4/b4dest.c @@ -1,16 +1,16 @@ -/**** BSIM4.2.1, Released by Xuemei Xi 10/05/2001 ****/ +/**** BSIM4.5.0 Released by Xuemei (Jane) Xi 07/29/2005 ****/ /********** - * Copyright 2001 Regents of the University of California. All rights reserved. - * File: b4dest.c of BSIM4.2.1. + * Copyright 2005 Regents of the University of California. All rights reserved. + * File: b4dest.c of BSIM4.5.0. * Author: 2000 Weidong Liu - * Authors: Xuemei Xi, Kanyu M. Cao, Hui Wan, Mansun Chan, Chenming Hu. + * Authors: 2001- Xuemei Xi, Mohan Dunga, Ali Niknejad, Chenming Hu. * Project Director: Prof. Chenming Hu. **********/ #include "ngspice.h" -#include #include "bsim4def.h" +#include "suffix.h" void BSIM4destroy(inModel) diff --git a/src/spicelib/devices/bsim4/b4geo.c b/src/spicelib/devices/bsim4/b4geo.c index 616d478db..408d59199 100644 --- a/src/spicelib/devices/bsim4/b4geo.c +++ b/src/spicelib/devices/bsim4/b4geo.c @@ -1,16 +1,14 @@ -/**** BSIM4.2.1, Released by Xuemei Xi 10/05/2001 ****/ +/**** BSIM4.5.0 Released by Xuemei (Jane) Xi 07/29/2005 ****/ /********** - * Copyright 2001 Regents of the University of California. All rights reserved. - * File: b4geo.c of BSIM4.2.1. + * Copyright 2005 Regents of the University of California. All rights reserved. + * File: b4geo.c of BSIM4.5.0. * Author: 2000 Weidong Liu - * Authors: Xuemei Xi, Kanyu M. Cao, Hui Wan, Mansun Chan, Chenming Hu. + * Authors: 2001- Xuemei Xi, Mohan Dunga, Ali Niknejad, Chenming Hu. * Project Director: Prof. Chenming Hu. **********/ #include "ngspice.h" -#include -#include /* * WDLiu: @@ -19,6 +17,11 @@ * for multi-fingers and varous GEO and RGEO options. */ +int +BSIM4RdsEndIso(double, double, double, double, double, double, int, int, double *); +int +BSIM4RdsEndSha(double, double, double, double, double, double, int, int, double *); + int BSIM4NumFingerDiff(nf, minSD, nuIntD, nuEndD, nuIntS, nuEndS) int minSD; @@ -154,7 +157,7 @@ int geo, rgeo, minSD, Type; double nf, Weffcj, Rsh, DMCG, DMCI, DMDG; double *Rtot; { -double Rint, Rend = 0.0; +double Rint=0.0, Rend = 0.0; double nuIntD = 0.0, nuEndD = 0.0, nuIntS = 0.0, nuEndS = 0.0; if (geo < 9) /* since geo = 9 and 10 only happen when nf = even */ diff --git a/src/spicelib/devices/bsim4/b4getic.c b/src/spicelib/devices/bsim4/b4getic.c index 0c1550e04..55c609a42 100644 --- a/src/spicelib/devices/bsim4/b4getic.c +++ b/src/spicelib/devices/bsim4/b4getic.c @@ -1,18 +1,18 @@ -/**** BSIM4.2.1, Released by Xuemei Xi 10/05/2001 ****/ +/**** BSIM4.5.0 Released by Xuemei (Jane) Xi 07/29/2005 ****/ /********** - * Copyright 2001 Regents of the University of California. All rights reserved. - * File: b4getic.c of BSIM4.2.1. + * Copyright 2005 Regents of the University of California. All rights reserved. + * File: b4getic.c of BSIM4.5.0. * Author: 2000 Weidong Liu - * Authors: Xuemei Xi, Kanyu M. Cao, Hui Wan, Mansun Chan, Chenming Hu. + * Authors: 2001- Xuemei Xi, Mohan Dunga, Ali Niknejad, Chenming Hu. * Project Director: Prof. Chenming Hu. **********/ #include "ngspice.h" -#include #include "cktdefs.h" #include "bsim4def.h" #include "sperror.h" +#include "suffix.h" int @@ -25,8 +25,8 @@ BSIM4instance *here; for (; model ; model = model->BSIM4nextModel) { for (here = model->BSIM4instances; here; here = here->BSIM4nextInstance) - { if (here->BSIM4owner != ARCHme) continue; - if (!here->BSIM4icVDSGiven) + { if (here->BSIM4owner != ARCHme) continue; + if (!here->BSIM4icVDSGiven) { here->BSIM4icVDS = *(ckt->CKTrhs + here->BSIM4dNode) - *(ckt->CKTrhs + here->BSIM4sNode); } diff --git a/src/spicelib/devices/bsim4/b4ld.c b/src/spicelib/devices/bsim4/b4ld.c index e89ad662e..519b357af 100644 --- a/src/spicelib/devices/bsim4/b4ld.c +++ b/src/spicelib/devices/bsim4/b4ld.c @@ -1,25 +1,32 @@ -/**** BSIM4.2.1, Released by Xuemei Xi 10/05/2001 ****/ +/**** BSIM4.5.0 Released by Xuemei (Jane) Xi 07/29/2005 ****/ /********** - * Copyright 2001 Regents of the University of California. All rights reserved. - * File: b4ld.c of BSIM4.2.1. + * Copyright 2005 Regents of the University of California. All rights reserved. + * File: b4ld.c of BSIM4.5.0. * Author: 2000 Weidong Liu - * Authors: Xuemei Xi, Kanyu M. Cao, Hui Wan, Mansun Chan, Chenming Hu. + * Authors: 2001- Xuemei Xi, Mohan Dunga, Ali Niknejad, Chenming Hu. * Project Director: Prof. Chenming Hu. - + * Modified by Xuemei Xi, 04/06/2001. * Modified by Xuemei Xi, 10/05/2001. + * Modified by Xuemei Xi, 11/15/2002. + * Modified by Xuemei Xi, 05/09/2003. + * Modified by Xuemei Xi, 02/06/2004. + * Modified by Xuemei Xi, Mohan Dunga, 07/29/2005. **********/ #include "ngspice.h" -#include -#include #include "cktdefs.h" #include "bsim4def.h" #include "trandefs.h" #include "const.h" #include "sperror.h" #include "devdefs.h" - +#include "suffix.h" +/* +#define MAX_EXP 2.688117142e+43 +#define MIN_EXP 3.720075976e-44 +#define EXP_THRESHOLD 100.0 +*/ #define MAX_EXP 5.834617425e14 #define MIN_EXP 1.713908431e-15 #define EXP_THRESHOLD 34.0 @@ -29,16 +36,29 @@ #define DELTA_2 0.02 #define DELTA_3 0.02 #define DELTA_4 0.02 +#define MM 3 /* smooth coeff */ +#define DEXP(A,B,C) { \ + if (A > EXP_THRESHOLD) { \ + B = MAX_EXP*(1.0+(A)-EXP_THRESHOLD); \ + C = MAX_EXP; \ + } else if (A < -EXP_THRESHOLD) { \ + B = MIN_EXP; \ + C = 0; \ + } else { \ + B = exp(A); \ + C = B; \ + } \ + } int BSIM4polyDepletion(double phi, double ngate,double coxe, double Vgs, double *Vgs_eff, double *dVgs_eff_dVg); int BSIM4load(inModel,ckt) GENmodel *inModel; -register CKTcircuit *ckt; +CKTcircuit *ckt; { -register BSIM4model *model = (BSIM4model*)inModel; -register BSIM4instance *here; +BSIM4model *model = (BSIM4model*)inModel; +BSIM4instance *here; double ceqgstot, dgstot_dvd, dgstot_dvg, dgstot_dvs, dgstot_dvb; double ceqgdtot, dgdtot_dvd, dgdtot_dvg, dgdtot_dvs, dgdtot_dvb; @@ -48,14 +68,14 @@ double vgs_eff, vgd_eff, dvgs_eff_dvg, dvgd_eff_dvg; double dRs_dvg, dRd_dvg, dRs_dvb, dRd_dvb; double dT0_dvg, dT1_dvb, dT3_dvg, dT3_dvb; double vses, vdes, vdedo, delvses, delvded, delvdes; -double Isestot, cseshat, Idedtot, cdedhat; +double Isestot=0.0, cseshat=0.0, Idedtot=0.0, cdedhat=0.0; double tol0, tol1, tol2, tol3, tol4, tol5, tol6; double geltd, gcrg, gcrgg, gcrgd, gcrgs, gcrgb, ceqgcrg; double vges, vgms, vgedo, vgmdo, vged, vgmd, delvged, delvgmd; double delvges, delvgms, vgmb; -double gcgmgmb, gcgmdb, gcgmsb, gcdgmb, gcsgmb; -double gcgmbb, gcbgmb, qgmb, qgmid, ceqqgmid; +double gcgmgmb=0.0, gcgmdb=0.0, gcgmsb=0.0, gcdgmb, gcsgmb; +double gcgmbb=0.0, gcbgmb, qgmb, qgmid=0.0, ceqqgmid; double vbd, vbs, vds, vgb, vgd, vgs, vgdo, xfact; double vdbs, vdbd, vsbs, vsbdo, vsbd; @@ -63,9 +83,9 @@ double delvdbs, delvdbd, delvsbs; double delvbd_jct, delvbs_jct, vbs_jct, vbd_jct; double SourceSatCurrent, DrainSatCurrent; -double ag0, qgd, qgs, qgb, von, cbhat, VgstNVt, ExpVgst; -double ceqqb, ceqqd, ceqqg, ceqqjd, ceqqjs, ceq, geq; -double cdrain, cdhat, ceqdrn, ceqbd, ceqbs, ceqjd, ceqjs, gjbd, gjbs; +double ag0, qgb, von, cbhat=0.0, VgstNVt, ExpVgst; +double ceqqb, ceqqd, ceqqg, ceqqjd=0.0, ceqqjs=0.0, ceq, geq; +double cdrain, cdhat=0.0, ceqdrn, ceqbd, ceqbs, ceqjd, ceqjs, gjbd, gjbs; double czbd, czbdsw, czbdswg, czbs, czbssw, czbsswg, evbd, evbs, arg, sarg; double delvbd, delvbs, delvds, delvgd, delvgs; double Vfbeff, dVfbeff_dVg, dVfbeff_dVb, V3, V4; @@ -73,48 +93,46 @@ double gcbdb, gcbgb, gcbsb, gcddb, gcdgb, gcdsb, gcgdb, gcggb, gcgsb, gcsdb; double gcgbb, gcdbb, gcsbb, gcbbb; double gcdbdb, gcsbsb; double gcsgb, gcssb, MJD, MJSWD, MJSWGD, MJS, MJSWS, MJSWGS; -double qgate, qbulk, qdrn, qsrc, cqgate, cqbody, cqdrn; +double qgate=0.0, qbulk=0.0, qdrn=0.0, qsrc, cqgate, cqbody, cqdrn; double Vdb, Vds, Vgs, Vbs, Gmbs, FwdSum, RevSum; double Igidl, Ggidld, Ggidlg, Ggidlb; -double Voxacc, dVoxacc_dVg, dVoxacc_dVb; -double Voxdepinv, dVoxdepinv_dVg, dVoxdepinv_dVd, dVoxdepinv_dVb; -double VxNVt, ExpVxNVt, Vaux, dVaux_dVg, dVaux_dVd, dVaux_dVb; +double Voxacc=0.0, dVoxacc_dVg=0.0, dVoxacc_dVb=0.0; +double Voxdepinv=0.0, dVoxdepinv_dVg=0.0, dVoxdepinv_dVd=0.0, dVoxdepinv_dVb=0.0; +double VxNVt=0.0, ExpVxNVt, Vaux=0.0, dVaux_dVg=0.0, dVaux_dVd=0.0, dVaux_dVb=0.0; double Igc, dIgc_dVg, dIgc_dVd, dIgc_dVb; double Igcs, dIgcs_dVg, dIgcs_dVd, dIgcs_dVb; double Igcd, dIgcd_dVg, dIgcd_dVd, dIgcd_dVb; double Igs, dIgs_dVg, dIgs_dVs, Igd, dIgd_dVg, dIgd_dVd; -double Igbacc, dIgbacc_dVg, dIgbacc_dVd, dIgbacc_dVb; +double Igbacc, dIgbacc_dVg, dIgbacc_dVb; double Igbinv, dIgbinv_dVg, dIgbinv_dVd, dIgbinv_dVb; -double Igb, dIgb_dVg, dIgb_dVd, dIgb_dVb; double Pigcd, dPigcd_dVg, dPigcd_dVd, dPigcd_dVb; double Istoteq, gIstotg, gIstotd, gIstots, gIstotb; double Idtoteq, gIdtotg, gIdtotd, gIdtots, gIdtotb; double Ibtoteq, gIbtotg, gIbtotd, gIbtots, gIbtotb; double Igtoteq, gIgtotg, gIgtotd, gIgtots, gIgtotb; -double Igstot, cgshat, Igdtot, cgdhat, Igbtot, cgbhat; -double Vgs_eff, Vfb, dVbs_dVb, Vth_NarrowW; +double Igstot=0.0, cgshat=0.0, Igdtot=0.0, cgdhat=0.0, Igbtot=0.0, cgbhat=0.0; +double Vgs_eff, Vfb=0.0, Vth_NarrowW; double Phis, dPhis_dVb, sqrtPhis, dsqrtPhis_dVb, Vth, dVth_dVb, dVth_dVd; double Vgst, dVgst_dVg, dVgst_dVb, dVgs_eff_dVg, Nvtms, Nvtmd; -double Vgdt, Vgsaddvth, Vgsaddvth2, Vgsaddvth1o3, Vtm; +double Vtm, Vtm0; double n, dn_dVb, dn_dVd, voffcv, noff, dnoff_dVd, dnoff_dVb; -double ExpArg, ExpArg1, V0, CoxWLcen, QovCox, LINK; -double DeltaPhi, dDeltaPhi_dVg; +double V0, CoxWLcen, QovCox, LINK; +double DeltaPhi, dDeltaPhi_dVg, VgDP, dVgDP_dVg; double Cox, Tox, Tcen, dTcen_dVg, dTcen_dVd, dTcen_dVb; double Ccen, Coxeff, dCoxeff_dVd, dCoxeff_dVg, dCoxeff_dVb; double Denomi, dDenomi_dVg, dDenomi_dVd, dDenomi_dVb; double ueff, dueff_dVg, dueff_dVd, dueff_dVb; -double Esat, dEsat_dVg, dEsat_dVd, dEsat_dVb, Vdsat, Vdsat0; +double Esat, Vdsat; double EsatL, dEsatL_dVg, dEsatL_dVd, dEsatL_dVb; -double Ilimit, Iexp, dIexp_dVg, dIexp_dVd, dIexp_dVb; double dVdsat_dVg, dVdsat_dVb, dVdsat_dVd, Vasat, dAlphaz_dVg, dAlphaz_dVb; -double dVasat_dVg, dVasat_dVb, dVasat_dVd, Va, Va2, dVa_dVd, dVa_dVg, dVa_dVb; +double dVasat_dVg, dVasat_dVb, dVasat_dVd, Va, dVa_dVd, dVa_dVg, dVa_dVb; double Vbseff, dVbseff_dVb, VbseffCV, dVbseffCV_dVb; -double Arg1, Arg2, One_Third_CoxWL, Two_Third_CoxWL, Alphaz, CoxWL; -double T0, dT0_dVg, dT0_dVd, dT0_dVb; +double Arg1, One_Third_CoxWL, Two_Third_CoxWL, Alphaz, CoxWL; +double T0=0.0, dT0_dVg, dT0_dVd, dT0_dVb; double T1, dT1_dVg, dT1_dVd, dT1_dVb; double T2, dT2_dVg, dT2_dVd, dT2_dVb; double T3, dT3_dVg, dT3_dVd, dT3_dVb; -double T4, dT4_dVg, dT4_dVd, dT4_dVb; +double T4, dT4_dVd, dT4_dVb; double T5, dT5_dVg, dT5_dVd, dT5_dVb; double T6, dT6_dVg, dT6_dVd, dT6_dVb; double T7, dT7_dVg, dT7_dVd, dT7_dVb; @@ -126,19 +144,19 @@ double tmp, Abulk, dAbulk_dVb, Abulk0, dAbulk0_dVb; double Cclm, dCclm_dVg, dCclm_dVd, dCclm_dVb; double FP, dFP_dVg, PvagTerm, dPvagTerm_dVg, dPvagTerm_dVd, dPvagTerm_dVb; double VADITS, dVADITS_dVg, dVADITS_dVd; -double Lpe_Vb, DITS_Sft, dDITS_Sft_dVb, dDITS_Sft_dVd; +double Lpe_Vb, dDITS_Sft_dVb, dDITS_Sft_dVd; double VACLM, dVACLM_dVg, dVACLM_dVd, dVACLM_dVb; double VADIBL, dVADIBL_dVg, dVADIBL_dVd, dVADIBL_dVb; double Xdep, dXdep_dVb, lt1, dlt1_dVb, ltw, dltw_dVb, Delt_vth, dDelt_vth_dVb; -double Theta0, dTheta0_dVb, Theta1, dTheta1_dVb; -double Thetarout, dThetarout_dVb, TempRatio, tmp1, tmp2, tmp3, tmp4; -double DIBL_Sft, dDIBL_Sft_dVd, DIBL_fact, Lambda, dLambda_dVg; +double Theta0, dTheta0_dVb; +double TempRatio, tmp1, tmp2, tmp3, tmp4; +double DIBL_Sft, dDIBL_Sft_dVd, Lambda, dLambda_dVg; double Idtot, Ibtot, a1, ScalingFactor; double Vgsteff, dVgsteff_dVg, dVgsteff_dVd, dVgsteff_dVb; double Vdseff, dVdseff_dVg, dVdseff_dVd, dVdseff_dVb; double VdseffCV, dVdseffCV_dVg, dVdseffCV_dVd, dVdseffCV_dVb; -double diffVds, diffVdsCV, dAbulk_dVg; +double diffVds, dAbulk_dVg; double beta, dbeta_dVg, dbeta_dVd, dbeta_dVb; double gche, dgche_dVg, dgche_dVd, dgche_dVb; double fgche1, dfgche1_dVg, dfgche1_dVd, dfgche1_dVb; @@ -150,40 +168,43 @@ double Isub, Gbd, Gbg, Gbb; double VASCBE, dVASCBE_dVg, dVASCBE_dVd, dVASCBE_dVb; double CoxeffWovL; double Rds, dRds_dVg, dRds_dVb, WVCox, WVCoxRds; -double Vgst2Vtm, VdsatCV, dVdsatCV_dVd, dVdsatCV_dVg, dVdsatCV_dVb; +double Vgst2Vtm, VdsatCV; double Leff, Weff, dWeff_dVg, dWeff_dVb; double AbulkCV, dAbulkCV_dVb; -double qcheq, qdef, gqdef, cqdef, cqcheq; -double gcqdb, gcqsb, gcqgb, gcqbb; +double qcheq, qdef, gqdef=0.0, cqdef=0.0, cqcheq=0.0; +double gcqdb=0.0, gcqsb=0.0, gcqgb=0.0, gcqbb=0.0; double dxpart, sxpart, ggtg, ggtd, ggts, ggtb; double ddxpart_dVd, ddxpart_dVg, ddxpart_dVb, ddxpart_dVs; double dsxpart_dVd, dsxpart_dVg, dsxpart_dVb, dsxpart_dVs; double gbspsp, gbbdp, gbbsp, gbspg, gbspb, gbspdp; double gbdpdp, gbdpg, gbdpb, gbdpsp; -double qgdo, qgso, cgdo, cgso, cqbs, cqbd; -double Cgg, Cgd, Cgs, Cgb, Cdg, Cdd, Cds, Cdb, Qg, Qd; -double Csg, Csd, Css, Csb, Cbg, Cbd, Cbs, Cbb, Qs, Qb; -double Cgg1, Cgb1, Cgd1, Cbg1, Cbb1, Cbd1, Csg1, Csd1, Csb1, Qac0, Qsub0; +double qgdo, qgso, cgdo, cgso; +double Cgg, Cgd, Cgb, Cdg, Cdd, Cds; +double Csg, Csd, Css, Csb, Cbg, Cbd, Cbb; +double Cgg1, Cgb1, Cgd1, Cbg1, Cbb1, Cbd1, Qac0, Qsub0; double dQac0_dVg, dQac0_dVb, dQsub0_dVg, dQsub0_dVd, dQsub0_dVb; -double ggidld, ggidlg, ggidlb,ggisld, ggislg, ggislb, ggisls; -double Igisl, Ggisld, Ggislg, Ggislb, Ggisls; +double ggidld, ggidlg, ggidlb, ggislg, ggislb, ggisls; +double Igisl, Ggislg, Ggislb, Ggisls; +double Nvtmrs, Nvtmrssw, Nvtmrsswg; - - +double vs, Fsevl, dvs_dVg, dvs_dVd, dvs_dVb, dFsevl_dVg, dFsevl_dVd, dFsevl_dVb; +double vgdx, vgsx; struct bsim4SizeDependParam *pParam; int ByPass, ChargeComputationNeeded, error, Check, Check1, Check2; +double m; + ScalingFactor = 1.0e-9; ChargeComputationNeeded = ((ckt->CKTmode & (MODEAC | MODETRAN | MODEINITSMSIG)) || ((ckt->CKTmode & MODETRANOP) && (ckt->CKTmode & MODEUIC))) ? 1 : 0; - +ChargeComputationNeeded = 1; for (; model != NULL; model = model->BSIM4nextModel) { for (here = model->BSIM4instances; here != NULL; here = here->BSIM4nextInstance) - { if (here->BSIM4owner != ARCHme) continue; + { if (here->BSIM4owner != ARCHme) continue; Check = Check1 = Check2 = 1; ByPass = 0; pParam = here->pParam; @@ -238,7 +259,7 @@ for (; model != NULL; model = model->BSIM4nextModel) vdes = 0.11; vses = -0.01; vgs = vges = vgms = model->BSIM4type - * pParam->BSIM4vth0 + 0.1; + * here->BSIM4vth0 + 0.1; vbs = vdbs = vsbs = 0.0; } } @@ -383,8 +404,8 @@ for (; model != NULL; model = model->BSIM4nextModel) cbhat = Ibtot + here->BSIM4gbd * delvbd_jct + here->BSIM4gbs * delvbs_jct - (here->BSIM4gbbs + here->BSIM4ggidlb) * delvbs - (here->BSIM4gbgs + here->BSIM4ggidlg) * delvgs - - (here->BSIM4gbds + here->BSIM4ggidld) * delvds - - here->BSIM4ggislg * delvgd - here->BSIM4ggislb* delvbd + here->BSIM4ggisls * delvds ; + - (here->BSIM4gbds + here->BSIM4ggidld - here->BSIM4ggisls) * delvds + - here->BSIM4ggislg * delvgd - here->BSIM4ggislb* delvbd; Igstot = here->BSIM4Igs + here->BSIM4Igcs; cgshat = Igstot + (here->BSIM4gIgsg + here->BSIM4gIgcsg) * delvgs @@ -399,18 +420,18 @@ for (; model != NULL; model = model->BSIM4nextModel) * delvds + here->BSIM4gIgbb * delvbs; } else - { Idtot = here->BSIM4cd + here->BSIM4cbd - here->BSIM4Igisl; + { Idtot = here->BSIM4cd + here->BSIM4cbd - here->BSIM4Igidl; /* bugfix */ cdhat = Idtot + here->BSIM4gbd * delvbd_jct + here->BSIM4gmbs * delvbd + here->BSIM4gm * delvgd - - here->BSIM4gds * delvds - here->BSIM4ggislg * vgd - - here->BSIM4ggislb * vbd + here->BSIM4ggisls * vds; + - (here->BSIM4gds + here->BSIM4ggidls) * delvds + - here->BSIM4ggidlg * delvgs - here->BSIM4ggidlb * delvbs; Ibtot = here->BSIM4cbs + here->BSIM4cbd - here->BSIM4Igidl - here->BSIM4Igisl - here->BSIM4csub; cbhat = Ibtot + here->BSIM4gbs * delvbs_jct + here->BSIM4gbd - * delvbd_jct - (here->BSIM4gbbs + here->BSIM4ggidlb) * delvbd - - (here->BSIM4gbgs + here->BSIM4ggidlg) * delvgd - + (here->BSIM4gbds + here->BSIM4ggidld) * delvds - - here->BSIM4ggislg * delvgs - here->BSIM4ggislb * delvbs + here->BSIM4ggisls * delvds; + * delvbd_jct - (here->BSIM4gbbs + here->BSIM4ggislb) * delvbd + - (here->BSIM4gbgs + here->BSIM4ggislg) * delvgd + + (here->BSIM4gbds + here->BSIM4ggisld - here->BSIM4ggidls) * delvds + - here->BSIM4ggidlg * delvgs - here->BSIM4ggidlb * delvbs; Igstot = here->BSIM4Igs + here->BSIM4Igcd; cgshat = Igstot + here->BSIM4gIgsg * delvgs + here->BSIM4gIgcdg * delvgd @@ -507,7 +528,9 @@ for (; model != NULL; model = model->BSIM4nextModel) vbs_jct = (!here->BSIM4rbodyMod) ? vbs : vsbs; vbd_jct = (!here->BSIM4rbodyMod) ? vbd : vdbd; - qdef = *(ckt->CKTstate0 + here->BSIM4qdef); +/*** qdef should not be kept fixed even if vgs, vds & vbs has converged +**** qdef = *(ckt->CKTstate0 + here->BSIM4qdef); +***/ cdrain = here->BSIM4cd; if ((ckt->CKTmode & (MODETRAN | MODEAC)) || @@ -809,7 +832,7 @@ for (; model != NULL; model = model->BSIM4nextModel) } here->BSIM4gbd = DrainSatCurrent * (devbd_dvb - model->BSIM4xjbvd * T3) + ckt->CKTgmin; - here->BSIM4cbd = DrainSatCurrent * (evbd + here->BSIM4XExpBVS - 1.0 + here->BSIM4cbd = DrainSatCurrent * (evbd + here->BSIM4XExpBVD - 1.0 - model->BSIM4xjbvd * T2) + ckt->CKTgmin * vbd_jct; } else @@ -820,7 +843,105 @@ for (; model != NULL; model = model->BSIM4nextModel) break; default: break; } - } /* End of diode DC model */ + } + + /* trap-assisted tunneling and recombination current for reverse bias */ + Nvtmrssw = model->BSIM4vtm0 * model->BSIM4njtsswtemp; + Nvtmrsswg = model->BSIM4vtm0 * model->BSIM4njtsswgtemp; + Nvtmrs = model->BSIM4vtm0 * model->BSIM4njtstemp; + + if ((model->BSIM4vtss - vbs_jct) < (model->BSIM4vtss * 1e-3)) + { T9 = 1.0e3; + T0 = - vbs_jct / Nvtmrs * T9; + DEXP(T0, T1, T10); + dT1_dVb = T10 / Nvtmrs * T9; + } else { + T9 = 1.0 / (model->BSIM4vtss - vbs_jct); + T0 = -vbs_jct / Nvtmrs * model->BSIM4vtss * T9; + dT0_dVb = model->BSIM4vtss / Nvtmrs * (T9 + vbs_jct * T9 * T9) ; + DEXP(T0, T1, T10); + dT1_dVb = T10 * dT0_dVb; + } + + if ((model->BSIM4vtsd - vbd_jct) < (model->BSIM4vtsd * 1e-3) ) + { T9 = 1.0e3; + T0 = -vbd_jct / Nvtmrs * T9; + DEXP(T0, T2, T10); + dT2_dVb = T10 / Nvtmrs * T9; + } else { + T9 = 1.0 / (model->BSIM4vtsd - vbd_jct); + T0 = -vbd_jct / Nvtmrs * model->BSIM4vtsd * T9; + dT0_dVb = model->BSIM4vtsd / Nvtmrs * (T9 + vbd_jct * T9 * T9) ; + DEXP(T0, T2, T10); + dT2_dVb = T10 * dT0_dVb; + } + + if ((model->BSIM4vtssws - vbs_jct) < (model->BSIM4vtssws * 1e-3) ) + { T9 = 1.0e3; + T0 = -vbs_jct / Nvtmrssw * T9; + DEXP(T0, T3, T10); + dT3_dVb = T10 / Nvtmrssw * T9; + } else { + T9 = 1.0 / (model->BSIM4vtssws - vbs_jct); + T0 = -vbs_jct / Nvtmrssw * model->BSIM4vtssws * T9; + dT0_dVb = model->BSIM4vtssws / Nvtmrssw * (T9 + vbs_jct * T9 * T9) ; + DEXP(T0, T3, T10); + dT3_dVb = T10 * dT0_dVb; + } + + if ((model->BSIM4vtsswd - vbd_jct) < (model->BSIM4vtsswd * 1e-3) ) + { T9 = 1.0e3; + T0 = -vbd_jct / Nvtmrssw * T9; + DEXP(T0, T4, T10); + dT4_dVb = T10 / Nvtmrssw * T9; + } else { + T9 = 1.0 / (model->BSIM4vtsswd - vbd_jct); + T0 = -vbd_jct / Nvtmrssw * model->BSIM4vtsswd * T9; + dT0_dVb = model->BSIM4vtsswd / Nvtmrssw * (T9 + vbd_jct * T9 * T9) ; + DEXP(T0, T4, T10); + dT4_dVb = T10 * dT0_dVb; + } + + if ((model->BSIM4vtsswgs - vbs_jct) < (model->BSIM4vtsswgs * 1e-3) ) + { T9 = 1.0e3; + T0 = -vbs_jct / Nvtmrsswg * T9; + DEXP(T0, T5, T10); + dT5_dVb = T10 / Nvtmrsswg * T9; + } else { + T9 = 1.0 / (model->BSIM4vtsswgs - vbs_jct); + T0 = -vbs_jct / Nvtmrsswg * model->BSIM4vtsswgs * T9; + dT0_dVb = model->BSIM4vtsswgs / Nvtmrsswg * (T9 + vbs_jct * T9 * T9) ; + DEXP(T0, T5, T10); + dT5_dVb = T10 * dT0_dVb; + } + + if ((model->BSIM4vtsswgd - vbd_jct) < (model->BSIM4vtsswgd * 1e-3) ) + { T9 = 1.0e3; + T0 = -vbd_jct / Nvtmrsswg * T9; + DEXP(T0, T6, T10); + dT6_dVb = T10 / Nvtmrsswg * T9; + } else { + T9 = 1.0 / (model->BSIM4vtsswgd - vbd_jct); + T0 = -vbd_jct / Nvtmrsswg * model->BSIM4vtsswgd * T9; + dT0_dVb = model->BSIM4vtsswgd / Nvtmrsswg * (T9 + vbd_jct * T9 * T9) ; + DEXP(T0, T6, T10); + dT6_dVb = T10 * dT0_dVb; + } + + here->BSIM4gbs += here->BSIM4SjctTempRevSatCur * dT1_dVb + + here->BSIM4SswTempRevSatCur * dT3_dVb + + here->BSIM4SswgTempRevSatCur * dT5_dVb; + here->BSIM4cbs -= here->BSIM4SjctTempRevSatCur * (T1 - 1.0) + + here->BSIM4SswTempRevSatCur * (T3 - 1.0) + + here->BSIM4SswgTempRevSatCur * (T5 - 1.0); + here->BSIM4gbd += here->BSIM4DjctTempRevSatCur * dT2_dVb + + here->BSIM4DswTempRevSatCur * dT4_dVb + + here->BSIM4DswgTempRevSatCur * dT6_dVb; + here->BSIM4cbd -= here->BSIM4DjctTempRevSatCur * (T2 - 1.0) + + here->BSIM4DswTempRevSatCur * (T4 - 1.0) + + here->BSIM4DswgTempRevSatCur * (T6 - 1.0); + + /* End of diode DC model */ if (vds >= 0.0) { here->BSIM4mode = 1; @@ -837,40 +958,37 @@ for (; model != NULL; model = model->BSIM4nextModel) Vdb = -vbs; } - T0 = Vbs - pParam->BSIM4vbsc - 0.001; - T1 = sqrt(T0 * T0 - 0.004 * pParam->BSIM4vbsc); + T0 = Vbs - here->BSIM4vbsc - 0.001; + T1 = sqrt(T0 * T0 - 0.004 * here->BSIM4vbsc); if (T0 >= 0.0) - { Vbseff = pParam->BSIM4vbsc + 0.5 * (T0 + T1); + { Vbseff = here->BSIM4vbsc + 0.5 * (T0 + T1); dVbseff_dVb = 0.5 * (1.0 + T0 / T1); } else { T2 = -0.002 / (T1 - T0); - Vbseff = pParam->BSIM4vbsc * (1.0 + T2); - dVbseff_dVb = T2 * pParam->BSIM4vbsc / T1; + Vbseff = here->BSIM4vbsc * (1.0 + T2); + dVbseff_dVb = T2 * here->BSIM4vbsc / T1; } - if (Vbseff < Vbs) - { Vbseff = Vbs; - } - if (Vbseff > 0.0) - { T0 = pParam->BSIM4phi / (pParam->BSIM4phi + Vbseff); - Phis = pParam->BSIM4phi * T0; - dPhis_dVb = -T0 * T0; - sqrtPhis = pParam->BSIM4phis3 / (pParam->BSIM4phi + 0.5 * Vbseff); - dsqrtPhis_dVb = -0.5 * sqrtPhis * sqrtPhis / pParam->BSIM4phis3; - } - else - { Phis = pParam->BSIM4phi - Vbseff; - dPhis_dVb = -1.0; - sqrtPhis = sqrt(Phis); - dsqrtPhis_dVb = -0.5 / sqrtPhis; - } + /* JX: Correction to forward body bias */ + T9 = 0.95 * pParam->BSIM4phi; + T0 = T9 - Vbseff - 0.001; + T1 = sqrt(T0 * T0 + 0.004 * T9); + Vbseff = T9 - 0.5 * (T0 + T1); + dVbseff_dVb *= 0.5 * (1.0 + T0 / T1); + + Phis = pParam->BSIM4phi - Vbseff; + dPhis_dVb = -1.0; + sqrtPhis = sqrt(Phis); + dsqrtPhis_dVb = -0.5 / sqrtPhis; + Xdep = pParam->BSIM4Xdep0 * sqrtPhis / pParam->BSIM4sqrtPhi; dXdep_dVb = (pParam->BSIM4Xdep0 / pParam->BSIM4sqrtPhi) * dsqrtPhis_dVb; Leff = pParam->BSIM4leff; Vtm = model->BSIM4vtm; + Vtm0 = model->BSIM4vtm0; /* Vth Calculation */ T3 = sqrt(Xdep); @@ -927,7 +1045,7 @@ for (; model != NULL; model = model->BSIM4nextModel) T3 = T2 * T2; T4 = T3 + 2.0 * T1 * MIN_EXP; T5 = T1 / T4; - dT1_dVb = -T0 * T1 * dltw_dVb / ltw; /* bugfix -JX */ + dT1_dVb = -T0 * T1 * dltw_dVb / ltw; dT5_dVb = dT1_dVb * (T4 - 2.0 * T1 * (T2 + MIN_EXP)) / T4 / T4; } else @@ -946,7 +1064,7 @@ for (; model != NULL; model = model->BSIM4nextModel) Vth_NarrowW = model->BSIM4toxe * pParam->BSIM4phi / (pParam->BSIM4weff + pParam->BSIM4w0); - T3 = pParam->BSIM4eta0 + pParam->BSIM4etab * Vbseff; + T3 = here->BSIM4eta0 + pParam->BSIM4etab * Vbseff; if (T3 < 1.0e-4) { T9 = 1.0 / (3.0 - 2.0e4 * T3); T3 = (2.0e-4 - T3) * T9; @@ -960,12 +1078,12 @@ for (; model != NULL; model = model->BSIM4nextModel) Lpe_Vb = sqrt(1.0 + pParam->BSIM4lpeb / Leff); - Vth = model->BSIM4type * pParam->BSIM4vth0 + (pParam->BSIM4k1ox * sqrtPhis + Vth = model->BSIM4type * here->BSIM4vth0 + (pParam->BSIM4k1ox * sqrtPhis - pParam->BSIM4k1 * pParam->BSIM4sqrtPhi) * Lpe_Vb - - pParam->BSIM4k2ox * Vbseff - Delt_vth - T2 + (pParam->BSIM4k3 + - here->BSIM4k2ox * Vbseff - Delt_vth - T2 + (pParam->BSIM4k3 + pParam->BSIM4k3b * Vbseff) * Vth_NarrowW + T1 - DIBL_Sft; - dVth_dVb = Lpe_Vb * pParam->BSIM4k1ox * dsqrtPhis_dVb - pParam->BSIM4k2ox + dVth_dVb = Lpe_Vb * pParam->BSIM4k1ox * dsqrtPhis_dVb - here->BSIM4k2ox - dDelt_vth_dVb - dT2_dVb + pParam->BSIM4k3b * Vth_NarrowW - pParam->BSIM4etab * Vds * pParam->BSIM4theta0vb0 * T4 + pParam->BSIM4kt2 * TempRatio; @@ -1010,8 +1128,16 @@ for (; model != NULL; model = model->BSIM4nextModel) T3 = Leff + pParam->BSIM4dvtp0 * (1.0 + T2); dT3_dVd = pParam->BSIM4dvtp0 * dT2_dVd; - T4 = Vtm * log(Leff / T3); - dT4_dVd = -Vtm * dT3_dVd / T3; + if (model->BSIM4tempMod < 2) + { + T4 = Vtm * log(Leff / T3); + dT4_dVd = -Vtm * dT3_dVd / T3; + } + else + { + T4 = model->BSIM4vtm0 * log(Leff / T3); + dT4_dVd = -model->BSIM4vtm0 * dT3_dVd / T3; + } dDITS_Sft_dVd = dn_dVd * T4 + n * dT4_dVd; dDITS_Sft_dVb = T4 * dn_dVb; @@ -1023,7 +1149,7 @@ for (; model != NULL; model = model->BSIM4nextModel) /* Poly Gate Si Depletion Effect */ - T0 = pParam->BSIM4vfb + pParam->BSIM4phi; + T0 = here->BSIM4vfb + pParam->BSIM4phi; BSIM4polyDepletion(T0, pParam->BSIM4ngate, model->BSIM4coxe, vgs, &vgs_eff, &dvgs_eff_dvg); @@ -1140,14 +1266,14 @@ for (; model != NULL; model = model->BSIM4nextModel) dRds_dVb = T4 * dT3_dVb; if (Rds > 0.0) - here->BSIM4grdsw = 1.0 / Rds; + here->BSIM4grdsw = 1.0 / Rds; else here->BSIM4grdsw = 0.0; } /* Calculate Abulk */ T9 = 0.5 * pParam->BSIM4k1ox * Lpe_Vb / sqrtPhis; - T1 = T9 + pParam->BSIM4k2ox - pParam->BSIM4k3b * Vth_NarrowW; + T1 = T9 + here->BSIM4k2ox - pParam->BSIM4k3b * Vth_NarrowW; dT1_dVb = -T9 / sqrtPhis * dsqrtPhis_dVb; T9 = sqrt(pParam->BSIM4xj * Xdep); @@ -1206,8 +1332,10 @@ for (; model != NULL; model = model->BSIM4nextModel) { T0 = Vgsteff + Vth + Vth; T2 = pParam->BSIM4ua + pParam->BSIM4uc * Vbseff; T3 = T0 / model->BSIM4toxe; - T5 = T3 * (T2 + pParam->BSIM4ub * T3); - dDenomi_dVg = (T2 + 2.0 * pParam->BSIM4ub * T3) / model->BSIM4toxe; + T6 = pParam->BSIM4ud / T3 / T3 * Vth * Vth; + T5 = T3 * (T2 + pParam->BSIM4ub * T3) + T6; + T7 = - 2.0 * T6 / T0; + dDenomi_dVg = (T2 + 2.0 * pParam->BSIM4ub * T3) / model->BSIM4toxe + T7; dDenomi_dVd = dDenomi_dVg * 2.0 * dVth_dVd; dDenomi_dVb = dDenomi_dVg * 2.0 * dVth_dVb + pParam->BSIM4uc * T3; } @@ -1216,19 +1344,24 @@ for (; model != NULL; model = model->BSIM4nextModel) T2 = 1.0 + pParam->BSIM4uc * Vbseff; T3 = T0 / model->BSIM4toxe; T4 = T3 * (pParam->BSIM4ua + pParam->BSIM4ub * T3); - T5 = T4 * T2; + T6 = pParam->BSIM4ud / T3 / T3 * Vth * Vth; + T5 = T4 * T2 + T6; + T7 = - 2.0 * T6 / T0; dDenomi_dVg = (pParam->BSIM4ua + 2.0 * pParam->BSIM4ub * T3) * T2 - / model->BSIM4toxe; + / model->BSIM4toxe + T7; dDenomi_dVd = dDenomi_dVg * 2.0 * dVth_dVd; dDenomi_dVb = dDenomi_dVg * 2.0 * dVth_dVb + pParam->BSIM4uc * T4; } else - { T0 = (Vgsteff + pParam->BSIM4vtfbphi1) / model->BSIM4toxe; + { T0 = (Vgsteff + here->BSIM4vtfbphi1) / model->BSIM4toxe; T1 = exp(pParam->BSIM4eu * log(T0)); dT1_dVg = T1 * pParam->BSIM4eu / T0 / model->BSIM4toxe; T2 = pParam->BSIM4ua + pParam->BSIM4uc * Vbseff; - T5 = T1 * T2; - dDenomi_dVg = T2 * dT1_dVg; + T3 = T0 / model->BSIM4toxe; + T6 = pParam->BSIM4ud / T3 / T3 * Vth * Vth; + T5 = T1 * T2 + T6; + T7 = - 2.0 * T6 / T0; + dDenomi_dVg = T2 * dT1_dVg + T7; dDenomi_dVd = 0.0; dDenomi_dVb = T1 * pParam->BSIM4uc; } @@ -1245,17 +1378,17 @@ for (; model != NULL; model = model->BSIM4nextModel) dDenomi_dVb *= T9; } - here->BSIM4ueff = ueff = pParam->BSIM4u0temp / Denomi; + here->BSIM4ueff = ueff = here->BSIM4u0temp / Denomi; T9 = -ueff / Denomi; dueff_dVg = T9 * dDenomi_dVg; dueff_dVd = T9 * dDenomi_dVd; dueff_dVb = T9 * dDenomi_dVb; /* Saturation Drain Voltage Vdsat */ - WVCox = Weff * pParam->BSIM4vsattemp * model->BSIM4coxe; + WVCox = Weff * here->BSIM4vsattemp * model->BSIM4coxe; WVCoxRds = WVCox * Rds; - Esat = 2.0 * pParam->BSIM4vsattemp / ueff; + Esat = 2.0 * here->BSIM4vsattemp / ueff; here->BSIM4EsatL = EsatL = Esat * Leff; T0 = -EsatL /ueff; dEsatL_dVg = T0 * dueff_dVg; @@ -1393,6 +1526,47 @@ for (; model != NULL; model = model->BSIM4nextModel) Vdseff = Vds; diffVds = Vds - Vdseff; here->BSIM4Vdseff = Vdseff; + + /* Velocity Overshoot */ + if((model->BSIM4lambdaGiven) && (model->BSIM4lambda > 0.0) ) + { + T1 = Leff * ueff; + T2 = pParam->BSIM4lambda / T1; + T3 = -T2 / T1 * Leff; + dT2_dVd = T3 * dueff_dVd; + dT2_dVg = T3 * dueff_dVg; + dT2_dVb = T3 * dueff_dVb; + T5 = 1.0 / (Esat * pParam->BSIM4litl); + T4 = -T5 / EsatL; + dT5_dVg = dEsatL_dVg * T4; + dT5_dVd = dEsatL_dVd * T4; + dT5_dVb = dEsatL_dVb * T4; + T6 = 1.0 + diffVds * T5; + dT6_dVg = dT5_dVg * diffVds - dVdseff_dVg * T5; + dT6_dVd = dT5_dVd * diffVds + (1.0 - dVdseff_dVd) * T5; + dT6_dVb = dT5_dVb * diffVds - dVdseff_dVb * T5; + T7 = 2.0 / (T6 * T6 + 1.0); + T8 = 1.0 - T7; + T9 = T6 * T7 * T7; + dT8_dVg = T9 * dT6_dVg; + dT8_dVd = T9 * dT6_dVd; + dT8_dVb = T9 * dT6_dVb; + T10 = 1.0 + T2 * T8; + dT10_dVg = dT2_dVg * T8 + T2 * dT8_dVg; + dT10_dVd = dT2_dVd * T8 + T2 * dT8_dVd; + dT10_dVb = dT2_dVb * T8 + T2 * dT8_dVb; + if(T10 == 1.0) + dT10_dVg = dT10_dVd = dT10_dVb = 0.0; + + dEsatL_dVg *= T10; + dEsatL_dVg += EsatL * dT10_dVg; + dEsatL_dVd *= T10; + dEsatL_dVd += EsatL * dT10_dVd; + dEsatL_dVb *= T10; + dEsatL_dVb += EsatL * dT10_dVb; + EsatL *= T10; + here->BSIM4EsatL = EsatL; + } /* Calculate Vasat */ tmp4 = 1.0 - 0.5 * Abulk * Vdsat / Vgst2Vtm; @@ -1420,7 +1594,7 @@ for (; model != NULL; model = model->BSIM4nextModel) dVasat_dVd = dT0_dVd / T1; /* Calculate Idl first */ - tmp1 = pParam->BSIM4vtfbphi2; + tmp1 = here->BSIM4vtfbphi2; tmp2 = 2.0e8 * model->BSIM4toxp; dT0_dVg = 1.0 / tmp2; T0 = (Vgsteff + tmp1) * dT0_dVg; @@ -1509,7 +1683,7 @@ for (; model != NULL; model = model->BSIM4nextModel) dPvagTerm_dVd = -T9 * dEsatL_dVd; } - if ((pParam->BSIM4pclm > 0.0) && (diffVds > 1.0e-10)) + if ((pParam->BSIM4pclm > MIN_EXP) && (diffVds > 1.0e-10)) { T0 = 1.0 + Rds * Idl; dT0_dVg = dRds_dVg * Idl + Rds * dIdl_dVg; dT0_dVd = Rds * dIdl_dVd; @@ -1541,7 +1715,7 @@ for (; model != NULL; model = model->BSIM4nextModel) } /* Calculate VADIBL */ - if (pParam->BSIM4thetaRout > 0.0) + if (pParam->BSIM4thetaRout > MIN_EXP) { T8 = Abulk * Vdsat; T0 = Vgst2Vtm * T8; dT0_dVg = Vgst2Vtm * Abulk * dVdsat_dVg + T8 @@ -1607,7 +1781,7 @@ for (; model != NULL; model = model->BSIM4nextModel) dT1_dVd = T1 * pParam->BSIM4pditsd; } - if (pParam->BSIM4pdits > 0.0) + if (pParam->BSIM4pdits > MIN_EXP) { T2 = 1.0 + model->BSIM4pditsl * Leff; VADITS = (1.0 + T2 * T1) / pParam->BSIM4pdits; dVADITS_dVg = VADITS * dFP_dVg; @@ -1696,10 +1870,10 @@ for (; model != NULL; model = model->BSIM4nextModel) dT1_dVd = T3 * (1.0 - dVdseff_dVd); dT1_dVb = -T3 * dVdseff_dVb; } - T4 = Idsa * Vdseff; + T4 = Idsa * Vdseff; Isub = T1 * T4; Gbg = T1 * (dIdsa_dVg * Vdseff + Idsa * dVdseff_dVg) - + T4 * dT1_dVg; + + T4 * dT1_dVg; Gbd = T1 * (dIdsa_dVd * Vdseff + Idsa * dVdseff_dVd) + T4 * dT1_dVd; Gbb = T1 * (dIdsa_dVb * Vdseff + Idsa * dVdseff_dVb) @@ -1727,6 +1901,7 @@ for (; model != NULL; model = model->BSIM4nextModel) Gmb = T0 * dIdsa_dVb - Idsa * (dVdseff_dVb + T9 * dVASCBE_dVb) / VASCBE; + tmp1 = Gds + Gm * dVgsteff_dVd; tmp2 = Gmb + Gm * dVgsteff_dVb; tmp3 = Gm; @@ -1738,10 +1913,50 @@ for (; model != NULL; model = model->BSIM4nextModel) + Vdseff * tmp2) * dVbseff_dVb; cdrain = Ids * Vdseff; + + /* Source End Velocity Limit */ + if((model->BSIM4vtlGiven) && (model->BSIM4vtl > 0.0) ) { + T12 = 1.0 / Leff / CoxeffWovL; + T11 = T12 / Vgsteff; + T10 = -T11 / Vgsteff; + vs = cdrain * T11; /* vs */ + dvs_dVg = Gm * T11 + cdrain * T10 * dVgsteff_dVg; + dvs_dVd = Gds * T11 + cdrain * T10 * dVgsteff_dVd; + dvs_dVb = Gmb * T11 + cdrain * T10 * dVgsteff_dVb; + T0 = 2 * MM; + T1 = vs / (pParam->BSIM4vtl * pParam->BSIM4tfactor); + if(T1 > 0.0) + { T2 = 1.0 + exp(T0 * log(T1)); + T3 = (T2 - 1.0) * T0 / vs; + Fsevl = 1.0 / exp(log(T2)/ T0); + dT2_dVg = T3 * dvs_dVg; + dT2_dVd = T3 * dvs_dVd; + dT2_dVb = T3 * dvs_dVb; + T4 = -1.0 / T0 * Fsevl / T2; + dFsevl_dVg = T4 * dT2_dVg; + dFsevl_dVd = T4 * dT2_dVd; + dFsevl_dVb = T4 * dT2_dVb; + } else { + Fsevl = 1.0; + dFsevl_dVg = 0.0; + dFsevl_dVd = 0.0; + dFsevl_dVb = 0.0; + } + Gm *=Fsevl; + Gm += cdrain * dFsevl_dVg; + Gmb *=Fsevl; + Gmb += cdrain * dFsevl_dVb; + Gds *=Fsevl; + Gds += cdrain * dFsevl_dVd; + + cdrain *= Fsevl; + } + here->BSIM4gds = Gds; here->BSIM4gm = Gm; here->BSIM4gmbs = Gmb; here->BSIM4IdovVds = Ids; + if( here->BSIM4IdovVds <= 1.0e-9) here->BSIM4IdovVds = 1.0e-9; /* Calculate Rg */ if ((here->BSIM4rgateMod > 1) || @@ -1901,7 +2116,7 @@ for (; model != NULL; model = model->BSIM4nextModel) here->BSIM4ggidlg = Ggidlg; here->BSIM4ggidlb = Ggidlb; - /* Calculate GISL current: bugfix recommended by TI -JX */ + /* Calculate GISL current */ vgd_eff = here->BSIM4vgd_eff; dvgd_eff_dvg = here->BSIM4dvgd_eff_dvg; @@ -1945,7 +2160,7 @@ for (; model != NULL; model = model->BSIM4nextModel) /* Calculate gate tunneling current */ if ((model->BSIM4igcMod != 0) || (model->BSIM4igbMod != 0)) - { Vfb = pParam->BSIM4vfbzb; + { Vfb = here->BSIM4vfbzb; V3 = Vfb - Vgs_eff + Vbseff - DELTA_3; if (Vfb <= 0.0) T0 = sqrt(V3 * V3 - 4.0 * DELTA_3 * Vfb); @@ -1990,26 +2205,45 @@ for (; model != NULL; model = model->BSIM4nextModel) dVoxdepinv_dVb += dVgsteff_dVb; } + if(model->BSIM4tempMod < 2) + tmp = Vtm; + else /* model->BSIM4tempMod = 2 */ + tmp = Vtm0; if (model->BSIM4igcMod) - { T0 = Vtm * pParam->BSIM4nigc; - VxNVt = (Vgs_eff - model->BSIM4type * pParam->BSIM4vth0) / T0; - if (VxNVt > EXP_THRESHOLD) - { Vaux = Vgs_eff - model->BSIM4type * pParam->BSIM4vth0; - dVaux_dVg = dVgs_eff_dVg; - dVaux_dVd = 0.0; - dVaux_dVb = 0.0; - } - else if (VxNVt < -EXP_THRESHOLD) + { T0 = tmp * pParam->BSIM4nigc; + if(model->BSIM4igcMod == 1) { + VxNVt = (Vgs_eff - model->BSIM4type * here->BSIM4vth0) / T0; + if (VxNVt > EXP_THRESHOLD) + { Vaux = Vgs_eff - model->BSIM4type * here->BSIM4vth0; + dVaux_dVg = dVgs_eff_dVg; + dVaux_dVd = 0.0; + dVaux_dVb = 0.0; + } + } else if (model->BSIM4igcMod == 2) { + VxNVt = (Vgs_eff - here->BSIM4von) / T0; + if (VxNVt > EXP_THRESHOLD) + { Vaux = Vgs_eff - here->BSIM4von; + dVaux_dVg = dVgs_eff_dVg; + dVaux_dVd = -dVth_dVd; + dVaux_dVb = -dVth_dVb; + } + } + if (VxNVt < -EXP_THRESHOLD) { Vaux = T0 * log(1.0 + MIN_EXP); dVaux_dVg = dVaux_dVd = dVaux_dVb = 0.0; } - else + else if ((VxNVt >= -EXP_THRESHOLD) && (VxNVt <= EXP_THRESHOLD)) { ExpVxNVt = exp(VxNVt); Vaux = T0 * log(1.0 + ExpVxNVt); dVaux_dVg = ExpVxNVt / (1.0 + ExpVxNVt); - dVaux_dVd = 0.0; - dVaux_dVb = 0.0; - dVaux_dVg *= dVgs_eff_dVg; + if(model->BSIM4igcMod == 1) { + dVaux_dVd = 0.0; + dVaux_dVb = 0.0; + } else if (model->BSIM4igcMod == 2) { + dVaux_dVd = -dVgs_eff_dVg * dVth_dVd; + dVaux_dVb = -dVgs_eff_dVg * dVth_dVb; + } + dVaux_dVg *= dVgs_eff_dVg; } T2 = Vgs_eff * Vaux; @@ -2055,20 +2289,19 @@ for (; model != NULL; model = model->BSIM4nextModel) T12 = Vgsteff + 1.0e-20; T13 = T11 / T12 / T12; T14 = -T13 / T12; - Pigcd = T13 * (1.0 - 0.5 * Vdseff / T12); + Pigcd = T13 * (1.0 - 0.5 * Vdseff / T12); dPigcd_dVg = T14 * (2.0 + 0.5 * (dVdseff_dVg - * Vgsteff - 3.0 * Vdseff) / T12); - dPigcd_dVd = 0.5 * T14 * dVdseff_dVd - + dPigcd_dVg * dVgsteff_dVd; - dPigcd_dVb = 0.5 * T14 * dVdseff_dVb - + dPigcd_dVg * dVgsteff_dVb; - dPigcd_dVg *= dVgsteff_dVg; + - 3.0 * Vdseff / T12)); + dPigcd_dVd = 0.5 * T14 * dVdseff_dVd; + dPigcd_dVb = 0.5 * T14 * dVdseff_dVb; } - T7 = -Pigcd * Vds; - dT7_dVg = -Vds * dPigcd_dVg; - dT7_dVd = -Pigcd - Vds * dPigcd_dVd; - dT7_dVb = -Vds * dPigcd_dVb; + T7 = -Pigcd * Vdseff; /* bugfix */ + dT7_dVg = -Vdseff * dPigcd_dVg - Pigcd * dVdseff_dVg; + dT7_dVd = -Vdseff * dPigcd_dVd - Pigcd * dVdseff_dVd + dT7_dVg * dVgsteff_dVd; + dT7_dVb = -Vdseff * dPigcd_dVb - Pigcd * dVdseff_dVb + dT7_dVg * dVgsteff_dVb; + dT7_dVg *= dVgsteff_dVg; + dT7_dVb *= dVbseff_dVb; T8 = T7 * T7 + 2.0e-4; dT8_dVg = 2.0 * T7; dT8_dVd = dT8_dVg * dT7_dVd; @@ -2124,7 +2357,7 @@ for (; model != NULL; model = model->BSIM4nextModel) here->BSIM4gIgcdd = dIgcd_dVd; here->BSIM4gIgcdb = dIgcd_dVb * dVbseff_dVb; - T0 = vgs - pParam->BSIM4vfbsd; + T0 = vgs - (pParam->BSIM4vfbsd + pParam->BSIM4vfbsdoff); vgs_eff = sqrt(T0 * T0 + 1.0e-4); dvgs_eff_dvg = T0 / vgs_eff; @@ -2155,7 +2388,7 @@ for (; model != NULL; model = model->BSIM4nextModel) dIgs_dVs = -dIgs_dVg; - T0 = vgd - pParam->BSIM4vfbsd; + T0 = vgd - (pParam->BSIM4vfbsd + pParam->BSIM4vfbsdoff); vgd_eff = sqrt(T0 * T0 + 1.0e-4); dvgd_eff_dvg = T0 / vgd_eff; @@ -2197,7 +2430,7 @@ for (; model != NULL; model = model->BSIM4nextModel) } if (model->BSIM4igbMod) - { T0 = Vtm * pParam->BSIM4nigbacc; + { T0 = tmp * pParam->BSIM4nigbacc; T1 = -Vgs_eff + Vbseff + Vfb; VxNVt = T1 / T0; if (VxNVt > EXP_THRESHOLD) @@ -2249,7 +2482,7 @@ for (; model != NULL; model = model->BSIM4nextModel) dIgbacc_dVb = T11 * (T2 * dT6_dVb + T6 * dT2_dVb); - T0 = Vtm * pParam->BSIM4nigbinv; + T0 = tmp * pParam->BSIM4nigbinv; T1 = Voxdepinv - pParam->BSIM4eigbinv; VxNVt = T1 / T0; if (VxNVt > EXP_THRESHOLD) @@ -2401,7 +2634,7 @@ for (; model != NULL; model = model->BSIM4nextModel) * BSIM4 C-V begins */ - if ((model->BSIM4xpart < 0) || (!ChargeComputationNeeded)) + if ((model->BSIM4xpart < 0) || (!ChargeComputationNeeded)) { qgate = qdrn = qsrc = qbulk = 0.0; here->BSIM4cggb = here->BSIM4cgsb = here->BSIM4cgdb = 0.0; here->BSIM4cdgb = here->BSIM4cdsb = here->BSIM4cddb = 0.0; @@ -2645,7 +2878,7 @@ for (; model != NULL; model = model->BSIM4nextModel) here->BSIM4cbgb = -(here->BSIM4cggb + here->BSIM4cdgb + T12); here->BSIM4cbdb = -(here->BSIM4cgdb - + here->BSIM4cddb + T10); /* bug fix */ + + here->BSIM4cddb + T10); here->BSIM4cbsb = -(here->BSIM4cgsb + here->BSIM4cdsb + tmp); } @@ -2771,7 +3004,7 @@ for (; model != NULL; model = model->BSIM4nextModel) if (model->BSIM4capMod == 1) - { Vfb = pParam->BSIM4vfbzb; + { Vfb = here->BSIM4vfbzb; V3 = Vfb - Vgs_eff + VbseffCV - DELTA_3; if (Vfb <= 0.0) T0 = sqrt(V3 * V3 - 4.0 * DELTA_3 * Vfb); @@ -2943,20 +3176,20 @@ for (; model != NULL; model = model->BSIM4nextModel) /* Charge-Thickness capMod (CTM) begins */ else if (model->BSIM4capMod == 2) - { V3 = pParam->BSIM4vfbzb - Vgs_eff + VbseffCV - DELTA_3; - if (pParam->BSIM4vfbzb <= 0.0) - T0 = sqrt(V3 * V3 - 4.0 * DELTA_3 * pParam->BSIM4vfbzb); + { V3 = here->BSIM4vfbzb - Vgs_eff + VbseffCV - DELTA_3; + if (here->BSIM4vfbzb <= 0.0) + T0 = sqrt(V3 * V3 - 4.0 * DELTA_3 * here->BSIM4vfbzb); else - T0 = sqrt(V3 * V3 + 4.0 * DELTA_3 * pParam->BSIM4vfbzb); + T0 = sqrt(V3 * V3 + 4.0 * DELTA_3 * here->BSIM4vfbzb); T1 = 0.5 * (1.0 + V3 / T0); - Vfbeff = pParam->BSIM4vfbzb - 0.5 * (V3 + T0); + Vfbeff = here->BSIM4vfbzb - 0.5 * (V3 + T0); dVfbeff_dVg = T1 * dVgs_eff_dVg; dVfbeff_dVb = -T1 * dVbseffCV_dVb; Cox = model->BSIM4coxp; Tox = 1.0e8 * model->BSIM4toxp; - T0 = (Vgs_eff - VbseffCV - pParam->BSIM4vfbzb) / Tox; + T0 = (Vgs_eff - VbseffCV - here->BSIM4vfbzb) / Tox; dT0_dVg = dVgs_eff_dVg / Tox; dT0_dVb = -dVbseffCV_dVb / Tox; @@ -2993,7 +3226,7 @@ for (; model != NULL; model = model->BSIM4nextModel) dCoxeff_dVg *= dTcen_dVg; CoxWLcen = CoxWL * Coxeff / model->BSIM4coxe; - Qac0 = CoxWLcen * (Vfbeff - pParam->BSIM4vfbzb); + Qac0 = CoxWLcen * (Vfbeff - here->BSIM4vfbzb); QovCox = Qac0 / Coxeff; dQac0_dVg = CoxWLcen * dVfbeff_dVg + QovCox * dCoxeff_dVg; @@ -3039,8 +3272,15 @@ for (; model != NULL; model = model->BSIM4nextModel) dDeltaPhi_dVg = 2.0 * Vtm * (T1 -T0) / (Denomi + T1 * Vgsteff); /* End of delta Phis */ + /* VgDP = Vgsteff - DeltaPhi */ + T0 = Vgsteff - DeltaPhi - 0.001; + dT0_dVg = 1.0 - dDeltaPhi_dVg; + T1 = sqrt(T0 * T0 + Vgsteff * 0.004); + VgDP = 0.5 * (T0 + T1); + dVgDP_dVg = 0.5 * (dT0_dVg + (T0 * dT0_dVg + 0.002) / T1); + Tox += Tox; /* WDLiu: Tcen reevaluated below due to different Vgsteff */ - T0 = (Vgsteff + pParam->BSIM4vtfbphi2) / Tox; + T0 = (Vgsteff + here->BSIM4vtfbphi2) / Tox; tmp = exp(0.7 * log(T0)); T1 = 1.0 + tmp; T2 = 0.7 * tmp / (T0 * Tox); @@ -3062,10 +3302,10 @@ for (; model != NULL; model = model->BSIM4nextModel) AbulkCV = Abulk0 * pParam->BSIM4abulkCVfactor; dAbulkCV_dVb = pParam->BSIM4abulkCVfactor * dAbulk0_dVb; - VdsatCV = (Vgsteff - DeltaPhi) / AbulkCV; + VdsatCV = VgDP / AbulkCV; T0 = VdsatCV - Vds - DELTA_4; - dT0_dVg = (1.0 - dDeltaPhi_dVg) / AbulkCV; + dT0_dVg = dVgDP_dVg / AbulkCV; dT0_dVb = -VdsatCV * dAbulkCV_dVb / AbulkCV; T1 = sqrt(T0 * T0 + 4.0 * DELTA_4 * VdsatCV); dT1_dVg = (T0 + DELTA_4 + DELTA_4) / T1; @@ -3095,7 +3335,7 @@ for (; model != NULL; model = model->BSIM4nextModel) } T0 = AbulkCV * VdseffCV; - T1 = Vgsteff - DeltaPhi; + T1 = VgDP; T2 = 12.0 * (T1 - 0.5 * T0 + 1.0e-20); T3 = T0 / T2; T4 = 1.0 - 12.0 * T3 * T3; @@ -3104,7 +3344,7 @@ for (; model != NULL; model = model->BSIM4nextModel) qgate = CoxWLcen * (T1 - T0 * (0.5 - T3)); QovCox = qgate / Coxeff; - Cgg1 = CoxWLcen * (T4 * (1.0 - dDeltaPhi_dVg) + Cgg1 = CoxWLcen * (T4 * dVgDP_dVg + T5 * dVdseffCV_dVg); Cgd1 = CoxWLcen * T5 * dVdseffCV_dVd + Cgg1 * dVgsteff_dVd + QovCox * dCoxeff_dVd; @@ -3116,7 +3356,7 @@ for (; model != NULL; model = model->BSIM4nextModel) T7 = 1.0 - AbulkCV; T8 = T2 * T2; T9 = 12.0 * T7 * T0 * T0 / (T8 * AbulkCV); - T10 = T9 * (1.0 - dDeltaPhi_dVg); + T10 = T9 * dVgDP_dVg; T11 = -T7 * T5 / AbulkCV; T12 = -(T9 * T1 / AbulkCV + VdseffCV * (0.5 - T0 / T2)); @@ -3137,7 +3377,7 @@ for (; model != NULL; model = model->BSIM4nextModel) T2 += T2; T3 = T2 * T2; T7 = -(0.25 - 12.0 * T0 * (4.0 * T1 - T0) / T3); - T4 = -(0.5 + 24.0 * T0 * T0 / T3) * (1.0 - dDeltaPhi_dVg); + T4 = -(0.5 + 24.0 * T0 * T0 / T3) * dVgDP_dVg; T5 = T7 * AbulkCV; T6 = T7 * VdseffCV; @@ -3162,7 +3402,7 @@ for (; model != NULL; model = model->BSIM4nextModel) T6 = AbulkCV * (qsrc / T2 + T3 * T8); T7 = T6 * VdseffCV / AbulkCV; - Csg = T5 * (1.0 - dDeltaPhi_dVg) + T6 * dVdseffCV_dVg; + Csg = T5 * dVgDP_dVg + T6 * dVdseffCV_dVg; Csd = Csg * dVgsteff_dVd + T6 * dVdseffCV_dVd + QovCox * dCoxeff_dVd; Csb = Csg * dVgsteff_dVb + T6 * dVdseffCV_dVb @@ -3376,6 +3616,50 @@ finished: if ((here->BSIM4off == 0) || (!(ckt->CKTmode & MODEINITFIX))) { if (Check == 1) { ckt->CKTnoncon++; + +/* "Following #ifndef NEWCONV" to "#endif" is commented out in the former version. + However, since it was satisfactory when I checked, it has left as it is. + Please comment out, supposing you get a problem. */ +#ifndef NEWCONV + } + else + { if (here->BSIM4mode >= 0) + { Idtot = here->BSIM4cd + here->BSIM4csub + + here->BSIM4Igidl - here->BSIM4cbd; + } + else + { Idtot = here->BSIM4cd + here->BSIM4cbd - here->BSIM4Igidl; /* bugfix */ + } + tol0 = ckt->CKTreltol * MAX(fabs(cdhat), fabs(Idtot)) + + ckt->CKTabstol; + tol1 = ckt->CKTreltol * MAX(fabs(cseshat), fabs(Isestot)) + + ckt->CKTabstol; + tol2 = ckt->CKTreltol * MAX(fabs(cdedhat), fabs(Idedtot)) + + ckt->CKTabstol; + tol3 = ckt->CKTreltol * MAX(fabs(cgshat), fabs(Igstot)) + + ckt->CKTabstol; + tol4 = ckt->CKTreltol * MAX(fabs(cgdhat), fabs(Igdtot)) + + ckt->CKTabstol; + tol5 = ckt->CKTreltol * MAX(fabs(cgbhat), fabs(Igbtot)) + + ckt->CKTabstol; + if ((fabs(cdhat - Idtot) >= tol0) || (fabs(cseshat - Isestot) >= tol1) + || (fabs(cdedhat - Idedtot) >= tol2)) + { ckt->CKTnoncon++; + } + else if ((fabs(cgshat - Igstot) >= tol3) || (fabs(cgdhat - Igdtot) >= tol4) + || (fabs(cgbhat - Igbtot) >= tol5)) + { ckt->CKTnoncon++; + } + else + { Ibtot = here->BSIM4cbs + here->BSIM4cbd + - here->BSIM4Igidl - here->BSIM4Igisl - here->BSIM4csub; + tol6 = ckt->CKTreltol * MAX(fabs(cbhat), fabs(Ibtot)) + + ckt->CKTabstol; + if (fabs(cbhat - Ibtot) > tol6) + { ckt->CKTnoncon++; + } + } +#endif /* NEWCONV */ } } *(ckt->CKTstate0 + here->BSIM4vds) = vds; @@ -3395,33 +3679,43 @@ finished: if (!ChargeComputationNeeded) goto line850; - if (model->BSIM4capMod == 0) /* code merge -JX */ + if (here->BSIM4rgateMod == 3) { + vgdx = vgmd; + vgsx = vgms; + } + else /* For rgateMod == 0, 1 and 2 */ + { + vgdx = vgd; + vgsx = vgs; + } + if (model->BSIM4capMod == 0) + { cgdo = pParam->BSIM4cgdo; - qgdo = pParam->BSIM4cgdo * vgd; + qgdo = pParam->BSIM4cgdo * vgdx; cgso = pParam->BSIM4cgso; - qgso = pParam->BSIM4cgso * vgs; + qgso = pParam->BSIM4cgso * vgsx; } else /* For both capMod == 1 and 2 */ - { T0 = vgd + DELTA_1; + { T0 = vgdx + DELTA_1; T1 = sqrt(T0 * T0 + 4.0 * DELTA_1); T2 = 0.5 * (T0 - T1); T3 = pParam->BSIM4weffCV * pParam->BSIM4cgdl; - T4 = sqrt(1.0 - 4.0 * T2 / pParam->BSIM4ckappad); + T4 = sqrt(1.0 - 4.0 * T2 / pParam->BSIM4ckappad); cgdo = pParam->BSIM4cgdo + T3 - T3 * (1.0 - 1.0 / T4) * (0.5 - 0.5 * T0 / T1); - qgdo = (pParam->BSIM4cgdo + T3) * vgd - T3 * (T2 + qgdo = (pParam->BSIM4cgdo + T3) * vgdx - T3 * (T2 + 0.5 * pParam->BSIM4ckappad * (T4 - 1.0)); - T0 = vgs + DELTA_1; + T0 = vgsx + DELTA_1; T1 = sqrt(T0 * T0 + 4.0 * DELTA_1); T2 = 0.5 * (T0 - T1); T3 = pParam->BSIM4weffCV * pParam->BSIM4cgsl; T4 = sqrt(1.0 - 4.0 * T2 / pParam->BSIM4ckappas); cgso = pParam->BSIM4cgso + T3 - T3 * (1.0 - 1.0 / T4) * (0.5 - 0.5 * T0 / T1); - qgso = (pParam->BSIM4cgso + T3) * vgs - T3 * (T2 + qgso = (pParam->BSIM4cgso + T3) * vgsx - T3 * (T2 + 0.5 * pParam->BSIM4ckappas * (T4 - 1.0)); } @@ -3499,7 +3793,7 @@ line755: gcsbb = -(gcsgb + gcsdb + gcssb + gcsgmb); gcbdb = (here->BSIM4cbdb - here->BSIM4capbd) * ag0; gcbsb = (here->BSIM4cbsb - here->BSIM4capbs) * ag0; - gcdbdb = 0.0; + gcdbdb = 0.0; gcsbsb = 0.0; } else { gcdbb = -(here->BSIM4cddb + here->BSIM4cdgb @@ -3621,7 +3915,7 @@ line755: gcsbb = -(gcsgb + gcssb + gcsgmb); gcbdb = -here->BSIM4capbd * ag0; gcbsb = -here->BSIM4capbs * ag0; - gcdbdb = 0.0; + gcdbdb = 0.0; gcsbsb = 0.0; } else { gcdbb = gcsbb = gcbdb = gcbsb = 0.0; @@ -3691,7 +3985,7 @@ line755: gcsbb = -(gcsgb + gcsdb + gcssb + gcsgmb); gcbdb = (here->BSIM4cbsb - here->BSIM4capbd) * ag0; gcbsb = (here->BSIM4cbdb - here->BSIM4capbs) * ag0; - gcdbdb = 0.0; + gcdbdb = 0.0; gcsbsb = 0.0; } else { gcdbb = -(gcdgb + gcddb + gcdsb + gcdgmb) @@ -3717,8 +4011,8 @@ line755: * pParam->BSIM4leffCV; T0 = qdef * ScalingFactor / CoxWL; ggtg = here->BSIM4gtg = T0 * here->BSIM4gcrgg; - ggts = here->BSIM4gtd = T0 * here->BSIM4gcrgs; - ggtd = here->BSIM4gts = T0 * here->BSIM4gcrgd; + ggts = here->BSIM4gts = T0 * here->BSIM4gcrgd; + ggtd = here->BSIM4gtd = T0 * here->BSIM4gcrgs; ggtb = here->BSIM4gtb = T0 * here->BSIM4gcrgb; gqdef = ScalingFactor * ag0; @@ -3810,7 +4104,7 @@ line755: gcsbb = -(gcsgb + gcssb + gcsgmb); gcbdb = -here->BSIM4capbd * ag0; gcbsb = -here->BSIM4capbs * ag0; - gcdbdb = 0.0; + gcdbdb = 0.0; gcsbsb = 0.0; } else { gcdbb = gcsbb = gcbdb = gcbsb = 0.0; @@ -4236,37 +4530,38 @@ line900: * Loading RHS */ + m = here->BSIM4m; - (*(ckt->CKTrhs + here->BSIM4dNodePrime) += (ceqjd - ceqbd + ceqgdtot + (*(ckt->CKTrhs + here->BSIM4dNodePrime) += m * (ceqjd - ceqbd + ceqgdtot - ceqdrn - ceqqd + Idtoteq)); - (*(ckt->CKTrhs + here->BSIM4gNodePrime) -= ceqqg - ceqgcrg + Igtoteq); + (*(ckt->CKTrhs + here->BSIM4gNodePrime) -= m * (ceqqg - ceqgcrg + Igtoteq)); if (here->BSIM4rgateMod == 2) - (*(ckt->CKTrhs + here->BSIM4gNodeExt) -= ceqgcrg); + (*(ckt->CKTrhs + here->BSIM4gNodeExt) -= m * ceqgcrg); else if (here->BSIM4rgateMod == 3) - (*(ckt->CKTrhs + here->BSIM4gNodeMid) -= ceqqgmid + ceqgcrg); + (*(ckt->CKTrhs + here->BSIM4gNodeMid) -= m * (ceqqgmid + ceqgcrg)); if (!here->BSIM4rbodyMod) - { (*(ckt->CKTrhs + here->BSIM4bNodePrime) += (ceqbd + ceqbs - ceqjd + { (*(ckt->CKTrhs + here->BSIM4bNodePrime) += m * (ceqbd + ceqbs - ceqjd - ceqjs - ceqqb + Ibtoteq)); - (*(ckt->CKTrhs + here->BSIM4sNodePrime) += (ceqdrn - ceqbs + ceqjs + (*(ckt->CKTrhs + here->BSIM4sNodePrime) += m * (ceqdrn - ceqbs + ceqjs + ceqqg + ceqqb + ceqqd + ceqqgmid - ceqgstot + Istoteq)); } else - { (*(ckt->CKTrhs + here->BSIM4dbNode) -= (ceqjd + ceqqjd)); - (*(ckt->CKTrhs + here->BSIM4bNodePrime) += (ceqbd + ceqbs - ceqqb + Ibtoteq)); - (*(ckt->CKTrhs + here->BSIM4sbNode) -= (ceqjs + ceqqjs)); - (*(ckt->CKTrhs + here->BSIM4sNodePrime) += (ceqdrn - ceqbs + ceqjs + ceqqd + { (*(ckt->CKTrhs + here->BSIM4dbNode) -= m * (ceqjd + ceqqjd)); + (*(ckt->CKTrhs + here->BSIM4bNodePrime) += m * (ceqbd + ceqbs - ceqqb + Ibtoteq)); + (*(ckt->CKTrhs + here->BSIM4sbNode) -= m * (ceqjs + ceqqjs)); + (*(ckt->CKTrhs + here->BSIM4sNodePrime) += m * (ceqdrn - ceqbs + ceqjs + ceqqd + ceqqg + ceqqb + ceqqjd + ceqqjs + ceqqgmid - ceqgstot + Istoteq)); } if (model->BSIM4rdsMod) - { (*(ckt->CKTrhs + here->BSIM4dNode) -= ceqgdtot); - (*(ckt->CKTrhs + here->BSIM4sNode) += ceqgstot); + { (*(ckt->CKTrhs + here->BSIM4dNode) -= m * ceqgdtot); + (*(ckt->CKTrhs + here->BSIM4sNode) += m * ceqgstot); } if (here->BSIM4trnqsMod) - *(ckt->CKTrhs + here->BSIM4qNode) += (cqcheq - cqdef); + *(ckt->CKTrhs + here->BSIM4qNode) += m * (cqcheq - cqdef); /* @@ -4292,95 +4587,95 @@ line900: T1 = qdef * here->BSIM4gtau; if (here->BSIM4rgateMod == 1) - { (*(here->BSIM4GEgePtr) += geltd); - (*(here->BSIM4GPgePtr) -= geltd); - (*(here->BSIM4GEgpPtr) -= geltd); - (*(here->BSIM4GPgpPtr) += gcggb + geltd - ggtg + gIgtotg); - (*(here->BSIM4GPdpPtr) += gcgdb - ggtd + gIgtotd); - (*(here->BSIM4GPspPtr) += gcgsb - ggts + gIgtots); - (*(here->BSIM4GPbpPtr) += gcgbb - ggtb + gIgtotb); + { (*(here->BSIM4GEgePtr) += m * geltd); + (*(here->BSIM4GPgePtr) -= m * geltd); + (*(here->BSIM4GEgpPtr) -= m * geltd); + (*(here->BSIM4GPgpPtr) += m * (gcggb + geltd - ggtg + gIgtotg)); + (*(here->BSIM4GPdpPtr) += m * (gcgdb - ggtd + gIgtotd)); + (*(here->BSIM4GPspPtr) += m * (gcgsb - ggts + gIgtots)); + (*(here->BSIM4GPbpPtr) += m * (gcgbb - ggtb + gIgtotb)); } /* WDLiu: gcrg already subtracted from all gcrgg below */ else if (here->BSIM4rgateMod == 2) - { (*(here->BSIM4GEgePtr) += gcrg); - (*(here->BSIM4GEgpPtr) += gcrgg); - (*(here->BSIM4GEdpPtr) += gcrgd); - (*(here->BSIM4GEspPtr) += gcrgs); - (*(here->BSIM4GEbpPtr) += gcrgb); + { (*(here->BSIM4GEgePtr) += m * gcrg); + (*(here->BSIM4GEgpPtr) += m * gcrgg); + (*(here->BSIM4GEdpPtr) += m * gcrgd); + (*(here->BSIM4GEspPtr) += m * gcrgs); + (*(here->BSIM4GEbpPtr) += m * gcrgb); - (*(here->BSIM4GPgePtr) -= gcrg); - (*(here->BSIM4GPgpPtr) += gcggb - gcrgg - ggtg + gIgtotg); - (*(here->BSIM4GPdpPtr) += gcgdb - gcrgd - ggtd + gIgtotd); - (*(here->BSIM4GPspPtr) += gcgsb - gcrgs - ggts + gIgtots); - (*(here->BSIM4GPbpPtr) += gcgbb - gcrgb - ggtb + gIgtotb); + (*(here->BSIM4GPgePtr) -= m * gcrg); + (*(here->BSIM4GPgpPtr) += m * (gcggb - gcrgg - ggtg + gIgtotg)); + (*(here->BSIM4GPdpPtr) += m * (gcgdb - gcrgd - ggtd + gIgtotd)); + (*(here->BSIM4GPspPtr) += m * (gcgsb - gcrgs - ggts + gIgtots)); + (*(here->BSIM4GPbpPtr) += m * (gcgbb - gcrgb - ggtb + gIgtotb)); } else if (here->BSIM4rgateMod == 3) - { (*(here->BSIM4GEgePtr) += geltd); - (*(here->BSIM4GEgmPtr) -= geltd); - (*(here->BSIM4GMgePtr) -= geltd); - (*(here->BSIM4GMgmPtr) += geltd + gcrg + gcgmgmb); + { (*(here->BSIM4GEgePtr) += m * geltd); + (*(here->BSIM4GEgmPtr) -= m * geltd); + (*(here->BSIM4GMgePtr) -= m * geltd); + (*(here->BSIM4GMgmPtr) += m * (geltd + gcrg + gcgmgmb)); - (*(here->BSIM4GMdpPtr) += gcrgd + gcgmdb); - (*(here->BSIM4GMgpPtr) += gcrgg); - (*(here->BSIM4GMspPtr) += gcrgs + gcgmsb); - (*(here->BSIM4GMbpPtr) += gcrgb + gcgmbb); + (*(here->BSIM4GMdpPtr) += m * (gcrgd + gcgmdb)); + (*(here->BSIM4GMgpPtr) += m * gcrgg); + (*(here->BSIM4GMspPtr) += m * (gcrgs + gcgmsb)); + (*(here->BSIM4GMbpPtr) += m * (gcrgb + gcgmbb)); - (*(here->BSIM4DPgmPtr) += gcdgmb); - (*(here->BSIM4GPgmPtr) -= gcrg); - (*(here->BSIM4SPgmPtr) += gcsgmb); - (*(here->BSIM4BPgmPtr) += gcbgmb); + (*(here->BSIM4DPgmPtr) += m * gcdgmb); + (*(here->BSIM4GPgmPtr) -= m * gcrg); + (*(here->BSIM4SPgmPtr) += m * gcsgmb); + (*(here->BSIM4BPgmPtr) += m * gcbgmb); - (*(here->BSIM4GPgpPtr) += gcggb - gcrgg - ggtg + gIgtotg); - (*(here->BSIM4GPdpPtr) += gcgdb - gcrgd - ggtd + gIgtotd); - (*(here->BSIM4GPspPtr) += gcgsb - gcrgs - ggts + gIgtots); - (*(here->BSIM4GPbpPtr) += gcgbb - gcrgb - ggtb + gIgtotb); + (*(here->BSIM4GPgpPtr) += m * (gcggb - gcrgg - ggtg + gIgtotg)); + (*(here->BSIM4GPdpPtr) += m * (gcgdb - gcrgd - ggtd + gIgtotd)); + (*(here->BSIM4GPspPtr) += m * (gcgsb - gcrgs - ggts + gIgtots)); + (*(here->BSIM4GPbpPtr) += m * (gcgbb - gcrgb - ggtb + gIgtotb)); } else - { (*(here->BSIM4GPgpPtr) += gcggb - ggtg + gIgtotg); - (*(here->BSIM4GPdpPtr) += gcgdb - ggtd + gIgtotd); - (*(here->BSIM4GPspPtr) += gcgsb - ggts + gIgtots); - (*(here->BSIM4GPbpPtr) += gcgbb - ggtb + gIgtotb); + { (*(here->BSIM4GPgpPtr) += m * (gcggb - ggtg + gIgtotg)); + (*(here->BSIM4GPdpPtr) += m * (gcgdb - ggtd + gIgtotd)); + (*(here->BSIM4GPspPtr) += m * (gcgsb - ggts + gIgtots)); + (*(here->BSIM4GPbpPtr) += m * (gcgbb - ggtb + gIgtotb)); } if (model->BSIM4rdsMod) - { (*(here->BSIM4DgpPtr) += gdtotg); - (*(here->BSIM4DspPtr) += gdtots); - (*(here->BSIM4DbpPtr) += gdtotb); - (*(here->BSIM4SdpPtr) += gstotd); - (*(here->BSIM4SgpPtr) += gstotg); - (*(here->BSIM4SbpPtr) += gstotb); + { (*(here->BSIM4DgpPtr) += m * gdtotg); + (*(here->BSIM4DspPtr) += m * gdtots); + (*(here->BSIM4DbpPtr) += m * gdtotb); + (*(here->BSIM4SdpPtr) += m * gstotd); + (*(here->BSIM4SgpPtr) += m * gstotg); + (*(here->BSIM4SbpPtr) += m * gstotb); } - (*(here->BSIM4DPdpPtr) += gdpr + here->BSIM4gds + here->BSIM4gbd + T1 * ddxpart_dVd - - gdtotd + RevSum + gcddb + gbdpdp + dxpart * ggtd - gIdtotd); - (*(here->BSIM4DPdPtr) -= gdpr + gdtot); - (*(here->BSIM4DPgpPtr) += Gm + gcdgb - gdtotg + gbdpg - gIdtotg - + dxpart * ggtg + T1 * ddxpart_dVg); - (*(here->BSIM4DPspPtr) -= here->BSIM4gds + gdtots - dxpart * ggts + gIdtots - - T1 * ddxpart_dVs + FwdSum - gcdsb - gbdpsp); - (*(here->BSIM4DPbpPtr) -= gjbd + gdtotb - Gmbs - gcdbb - gbdpb + gIdtotb - - T1 * ddxpart_dVb - dxpart * ggtb); + (*(here->BSIM4DPdpPtr) += m * (gdpr + here->BSIM4gds + here->BSIM4gbd + T1 * ddxpart_dVd + - gdtotd + RevSum + gcddb + gbdpdp + dxpart * ggtd - gIdtotd)); + (*(here->BSIM4DPdPtr) -= m * (gdpr + gdtot)); + (*(here->BSIM4DPgpPtr) += m * (Gm + gcdgb - gdtotg + gbdpg - gIdtotg + + dxpart * ggtg + T1 * ddxpart_dVg)); + (*(here->BSIM4DPspPtr) -= m * (here->BSIM4gds + gdtots - dxpart * ggts + gIdtots + - T1 * ddxpart_dVs + FwdSum - gcdsb - gbdpsp)); + (*(here->BSIM4DPbpPtr) -= m * (gjbd + gdtotb - Gmbs - gcdbb - gbdpb + gIdtotb + - T1 * ddxpart_dVb - dxpart * ggtb)); - (*(here->BSIM4DdpPtr) -= gdpr - gdtotd); - (*(here->BSIM4DdPtr) += gdpr + gdtot); + (*(here->BSIM4DdpPtr) -= m * (gdpr - gdtotd)); + (*(here->BSIM4DdPtr) += m * (gdpr + gdtot)); - (*(here->BSIM4SPdpPtr) -= here->BSIM4gds + gstotd + RevSum - gcsdb - gbspdp - - T1 * dsxpart_dVd - sxpart * ggtd + gIstotd); - (*(here->BSIM4SPgpPtr) += gcsgb - Gm - gstotg + gbspg + sxpart * ggtg - + T1 * dsxpart_dVg - gIstotg); - (*(here->BSIM4SPspPtr) += gspr + here->BSIM4gds + here->BSIM4gbs + T1 * dsxpart_dVs - - gstots + FwdSum + gcssb + gbspsp + sxpart * ggts - gIstots); - (*(here->BSIM4SPsPtr) -= gspr + gstot); - (*(here->BSIM4SPbpPtr) -= gjbs + gstotb + Gmbs - gcsbb - gbspb - sxpart * ggtb - - T1 * dsxpart_dVb + gIstotb); + (*(here->BSIM4SPdpPtr) -= m * (here->BSIM4gds + gstotd + RevSum - gcsdb - gbspdp + - T1 * dsxpart_dVd - sxpart * ggtd + gIstotd)); + (*(here->BSIM4SPgpPtr) += m * (gcsgb - Gm - gstotg + gbspg + sxpart * ggtg + + T1 * dsxpart_dVg - gIstotg)); + (*(here->BSIM4SPspPtr) += m * (gspr + here->BSIM4gds + here->BSIM4gbs + T1 * dsxpart_dVs + - gstots + FwdSum + gcssb + gbspsp + sxpart * ggts - gIstots)); + (*(here->BSIM4SPsPtr) -= m * (gspr + gstot)); + (*(here->BSIM4SPbpPtr) -= m * (gjbs + gstotb + Gmbs - gcsbb - gbspb - sxpart * ggtb + - T1 * dsxpart_dVb + gIstotb)); - (*(here->BSIM4SspPtr) -= gspr - gstots); - (*(here->BSIM4SsPtr) += gspr + gstot); + (*(here->BSIM4SspPtr) -= m * (gspr - gstots)); + (*(here->BSIM4SsPtr) += m * (gspr + gstot)); - (*(here->BSIM4BPdpPtr) += gcbdb - gjbd + gbbdp - gIbtotd); - (*(here->BSIM4BPgpPtr) += gcbgb - here->BSIM4gbgs - gIbtotg); - (*(here->BSIM4BPspPtr) += gcbsb - gjbs + gbbsp - gIbtots); - (*(here->BSIM4BPbpPtr) += gjbd + gjbs + gcbbb - here->BSIM4gbbs - - gIbtotb); + (*(here->BSIM4BPdpPtr) += m * (gcbdb - gjbd + gbbdp - gIbtotd)); + (*(here->BSIM4BPgpPtr) += m * (gcbgb - here->BSIM4gbgs - gIbtotg)); + (*(here->BSIM4BPspPtr) += m * (gcbsb - gjbs + gbbsp - gIbtots)); + (*(here->BSIM4BPbpPtr) += m * (gjbd + gjbs + gcbbb - here->BSIM4gbbs + - gIbtotb)); ggidld = here->BSIM4ggidld; ggidlg = here->BSIM4ggidlg; @@ -4390,65 +4685,65 @@ line900: ggislb = here->BSIM4ggislb; /* stamp gidl */ - (*(here->BSIM4DPdpPtr) += ggidld); - (*(here->BSIM4DPgpPtr) += ggidlg); - (*(here->BSIM4DPspPtr) -= (ggidlg + ggidld + ggidlb)); - (*(here->BSIM4DPbpPtr) += ggidlb); - (*(here->BSIM4BPdpPtr) -= ggidld); - (*(here->BSIM4BPgpPtr) -= ggidlg); - (*(here->BSIM4BPspPtr) += (ggidlg + ggidld + ggidlb)); - (*(here->BSIM4BPbpPtr) -= ggidlb); + (*(here->BSIM4DPdpPtr) += m * ggidld); + (*(here->BSIM4DPgpPtr) += m * ggidlg); + (*(here->BSIM4DPspPtr) -= m * (ggidlg + ggidld + ggidlb)); + (*(here->BSIM4DPbpPtr) += m * ggidlb); + (*(here->BSIM4BPdpPtr) -= m * ggidld); + (*(here->BSIM4BPgpPtr) -= m * ggidlg); + (*(here->BSIM4BPspPtr) += m * (ggidlg + ggidld + ggidlb)); + (*(here->BSIM4BPbpPtr) -= m * ggidlb); /* stamp gisl */ - (*(here->BSIM4SPdpPtr) -= (ggisls + ggislg + ggislb)); - (*(here->BSIM4SPgpPtr) += ggislg); - (*(here->BSIM4SPspPtr) += ggisls); - (*(here->BSIM4SPbpPtr) += ggislb); - (*(here->BSIM4BPdpPtr) += (ggislg + ggisls + ggislb)); - (*(here->BSIM4BPgpPtr) -= ggislg); - (*(here->BSIM4BPspPtr) -= ggisls); - (*(here->BSIM4BPbpPtr) -= ggislb); + (*(here->BSIM4SPdpPtr) -= m * (ggisls + ggislg + ggislb)); + (*(here->BSIM4SPgpPtr) += m * ggislg); + (*(here->BSIM4SPspPtr) += m * ggisls); + (*(here->BSIM4SPbpPtr) += m * ggislb); + (*(here->BSIM4BPdpPtr) += m * (ggislg + ggisls + ggislb)); + (*(here->BSIM4BPgpPtr) -= m * ggislg); + (*(here->BSIM4BPspPtr) -= m * ggisls); + (*(here->BSIM4BPbpPtr) -= m * ggislb); if (here->BSIM4rbodyMod) - { (*(here->BSIM4DPdbPtr) += gcdbdb - here->BSIM4gbd); - (*(here->BSIM4SPsbPtr) -= here->BSIM4gbs - gcsbsb); + { (*(here->BSIM4DPdbPtr) += m * (gcdbdb - here->BSIM4gbd)); + (*(here->BSIM4SPsbPtr) -= m * (here->BSIM4gbs - gcsbsb)); - (*(here->BSIM4DBdpPtr) += gcdbdb - here->BSIM4gbd); - (*(here->BSIM4DBdbPtr) += here->BSIM4gbd - gcdbdb - + here->BSIM4grbpd + here->BSIM4grbdb); - (*(here->BSIM4DBbpPtr) -= here->BSIM4grbpd); - (*(here->BSIM4DBbPtr) -= here->BSIM4grbdb); + (*(here->BSIM4DBdpPtr) += m * (gcdbdb - here->BSIM4gbd)); + (*(here->BSIM4DBdbPtr) += m * (here->BSIM4gbd - gcdbdb + + here->BSIM4grbpd + here->BSIM4grbdb)); + (*(here->BSIM4DBbpPtr) -= m * here->BSIM4grbpd); + (*(here->BSIM4DBbPtr) -= m * here->BSIM4grbdb); - (*(here->BSIM4BPdbPtr) -= here->BSIM4grbpd); - (*(here->BSIM4BPbPtr) -= here->BSIM4grbpb); - (*(here->BSIM4BPsbPtr) -= here->BSIM4grbps); - (*(here->BSIM4BPbpPtr) += here->BSIM4grbpd + here->BSIM4grbps - + here->BSIM4grbpb); + (*(here->BSIM4BPdbPtr) -= m * here->BSIM4grbpd); + (*(here->BSIM4BPbPtr) -= m * here->BSIM4grbpb); + (*(here->BSIM4BPsbPtr) -= m * here->BSIM4grbps); + (*(here->BSIM4BPbpPtr) += m * (here->BSIM4grbpd + here->BSIM4grbps + + here->BSIM4grbpb)); /* WDLiu: (gcbbb - here->BSIM4gbbs) already added to BPbpPtr */ - (*(here->BSIM4SBspPtr) += gcsbsb - here->BSIM4gbs); - (*(here->BSIM4SBbpPtr) -= here->BSIM4grbps); - (*(here->BSIM4SBbPtr) -= here->BSIM4grbsb); - (*(here->BSIM4SBsbPtr) += here->BSIM4gbs - gcsbsb - + here->BSIM4grbps + here->BSIM4grbsb); + (*(here->BSIM4SBspPtr) += m * (gcsbsb - here->BSIM4gbs)); + (*(here->BSIM4SBbpPtr) -= m * here->BSIM4grbps); + (*(here->BSIM4SBbPtr) -= m * here->BSIM4grbsb); + (*(here->BSIM4SBsbPtr) += m * (here->BSIM4gbs - gcsbsb + + here->BSIM4grbps + here->BSIM4grbsb)); - (*(here->BSIM4BdbPtr) -= here->BSIM4grbdb); - (*(here->BSIM4BbpPtr) -= here->BSIM4grbpb); - (*(here->BSIM4BsbPtr) -= here->BSIM4grbsb); - (*(here->BSIM4BbPtr) += here->BSIM4grbsb + here->BSIM4grbdb - + here->BSIM4grbpb); + (*(here->BSIM4BdbPtr) -= m * here->BSIM4grbdb); + (*(here->BSIM4BbpPtr) -= m * here->BSIM4grbpb); + (*(here->BSIM4BsbPtr) -= m * here->BSIM4grbsb); + (*(here->BSIM4BbPtr) += m * (here->BSIM4grbsb + here->BSIM4grbdb + + here->BSIM4grbpb)); } if (here->BSIM4trnqsMod) - { (*(here->BSIM4QqPtr) += gqdef + here->BSIM4gtau); - (*(here->BSIM4QgpPtr) += ggtg - gcqgb); - (*(here->BSIM4QdpPtr) += ggtd - gcqdb); - (*(here->BSIM4QspPtr) += ggts - gcqsb); - (*(here->BSIM4QbpPtr) += ggtb - gcqbb); + { (*(here->BSIM4QqPtr) += m * (gqdef + here->BSIM4gtau)); + (*(here->BSIM4QgpPtr) += m * (ggtg - gcqgb)); + (*(here->BSIM4QdpPtr) += m * (ggtd - gcqdb)); + (*(here->BSIM4QspPtr) += m * (ggts - gcqsb)); + (*(here->BSIM4QbpPtr) += m * (ggtb - gcqbb)); - (*(here->BSIM4DPqPtr) += dxpart * here->BSIM4gtau); - (*(here->BSIM4SPqPtr) += sxpart * here->BSIM4gtau); - (*(here->BSIM4GPqPtr) -= here->BSIM4gtau); + (*(here->BSIM4DPqPtr) += m * dxpart * here->BSIM4gtau); + (*(here->BSIM4SPqPtr) += m * sxpart * here->BSIM4gtau); + (*(here->BSIM4GPqPtr) -= m * here->BSIM4gtau); } line1000: ; diff --git a/src/spicelib/devices/bsim4/b4mask.c b/src/spicelib/devices/bsim4/b4mask.c index 7ee477130..49626213d 100644 --- a/src/spicelib/devices/bsim4/b4mask.c +++ b/src/spicelib/devices/bsim4/b4mask.c @@ -1,22 +1,26 @@ -/**** BSIM4.2.1, Released by Xuemei Xi 10/05/2001 ****/ +/**** BSIM4.5.0 Released by Xuemei (Jane) Xi 07/29/2005 ****/ /********** - * Copyright 2001 Regents of the University of California. All rights reserved. - * File: b4mask.c of BSIM4.2.1. + * Copyright 2005 Regents of the University of California. All rights reserved. + * File: b4mask.c of BSIM4.5.0. * Author: 2000 Weidong Liu - * Authors: Xuemei Xi, Kanyu M. Cao, Hui Wan, Mansun Chan, Chenming Hu. + * Authors: 2001- Xuemei Xi, Mohan Dunga, Ali Niknejad, Chenming Hu. * Project Director: Prof. Chenming Hu. + * Modified by Xuemei Xi, 04/06/2001. + * Modified by Xuemei Xi, 10/05/2001. + * Modified by Xuemei Xi, 11/15/2002. + * Modified by Xuemei Xi, 05/09/2003. + * Modified by Xuemei Xi, Mohan Dunga, 07/29/2005. **********/ #include "ngspice.h" -#include #include "ifsim.h" #include "cktdefs.h" #include "devdefs.h" #include "bsim4def.h" #include "sperror.h" - +#include "suffix.h" int BSIM4mAsk(ckt,inst,which,value) @@ -75,6 +79,10 @@ IFvalue *value; case BSIM4_MOD_IGBMOD : value->iValue = model->BSIM4igbMod; return(OK); + case BSIM4_MOD_TEMPMOD : + value->iValue = model->BSIM4tempMod; + return(OK); + case BSIM4_MOD_VERSION : value->sValue = model->BSIM4version; return(OK); @@ -119,6 +127,18 @@ IFvalue *value; case BSIM4_MOD_VSAT: value->rValue = model->BSIM4vsat; return(OK); + case BSIM4_MOD_VTL: + value->rValue = model->BSIM4vtl; + return(OK); + case BSIM4_MOD_XN: + value->rValue = model->BSIM4xn; + return(OK); + case BSIM4_MOD_LC: + value->rValue = model->BSIM4lc; + return(OK); + case BSIM4_MOD_LAMBDA: + value->rValue = model->BSIM4lambda; + return(OK); case BSIM4_MOD_AT: value->rValue = model->BSIM4at; return(OK); @@ -250,6 +270,18 @@ IFvalue *value; case BSIM4_MOD_UC1: value->rValue = model->BSIM4uc1; return(OK); + case BSIM4_MOD_UD: + value->rValue = model->BSIM4ud; + return(OK); + case BSIM4_MOD_UD1: + value->rValue = model->BSIM4ud1; + return(OK); + case BSIM4_MOD_UP: + value->rValue = model->BSIM4up; + return(OK); + case BSIM4_MOD_LP: + value->rValue = model->BSIM4lp; + return(OK); case BSIM4_MOD_U0: value->rValue = model->BSIM4u0; return(OK); @@ -259,6 +291,15 @@ IFvalue *value; case BSIM4_MOD_VOFF: value->rValue = model->BSIM4voff; return(OK); + case BSIM4_MOD_TVOFF: + value->rValue = model->BSIM4tvoff; + return(OK); + case BSIM4_MOD_VFBSDOFF: + value->rValue = model->BSIM4vfbsdoff; + return(OK); + case BSIM4_MOD_TVFBSDOFF: + value->rValue = model->BSIM4tvfbsdoff; + return(OK); case BSIM4_MOD_VOFFL: value->rValue = model->BSIM4voffl; return(OK); @@ -442,6 +483,12 @@ IFvalue *value; case BSIM4_MOD_TNOIB: value->rValue = model->BSIM4tnoib; return(OK); + case BSIM4_MOD_RNOIA: + value->rValue = model->BSIM4rnoia; + return(OK); + case BSIM4_MOD_RNOIB: + value->rValue = model->BSIM4rnoib; + return(OK); case BSIM4_MOD_NTNOI: value->rValue = model->BSIM4ntnoi; return(OK); @@ -473,6 +520,79 @@ IFvalue *value; value->rValue = model->BSIM4vfb; return(OK); + case BSIM4_MOD_JTSS: + value->rValue = model->BSIM4jtss; + return(OK); + case BSIM4_MOD_JTSD: + value->rValue = model->BSIM4jtsd; + return(OK); + case BSIM4_MOD_JTSSWS: + value->rValue = model->BSIM4jtssws; + return(OK); + case BSIM4_MOD_JTSSWD: + value->rValue = model->BSIM4jtsswd; + return(OK); + case BSIM4_MOD_JTSSWGS: + value->rValue = model->BSIM4jtsswgs; + return(OK); + case BSIM4_MOD_JTSSWGD: + value->rValue = model->BSIM4jtsswgd; + return(OK); + case BSIM4_MOD_NJTS: + value->rValue = model->BSIM4njts; + return(OK); + case BSIM4_MOD_NJTSSW: + value->rValue = model->BSIM4njtssw; + return(OK); + case BSIM4_MOD_NJTSSWG: + value->rValue = model->BSIM4njtsswg; + return(OK); + case BSIM4_MOD_XTSS: + value->rValue = model->BSIM4xtss; + return(OK); + case BSIM4_MOD_XTSD: + value->rValue = model->BSIM4xtsd; + return(OK); + case BSIM4_MOD_XTSSWS: + value->rValue = model->BSIM4xtssws; + return(OK); + case BSIM4_MOD_XTSSWD: + value->rValue = model->BSIM4xtsswd; + return(OK); + case BSIM4_MOD_XTSSWGS: + value->rValue = model->BSIM4xtsswgs; + return(OK); + case BSIM4_MOD_XTSSWGD: + value->rValue = model->BSIM4xtsswgd; + return(OK); + case BSIM4_MOD_TNJTS: + value->rValue = model->BSIM4tnjts; + return(OK); + case BSIM4_MOD_TNJTSSW: + value->rValue = model->BSIM4tnjtssw; + return(OK); + case BSIM4_MOD_TNJTSSWG: + value->rValue = model->BSIM4tnjtsswg; + return(OK); + case BSIM4_MOD_VTSS: + value->rValue = model->BSIM4vtss; + return(OK); + case BSIM4_MOD_VTSD: + value->rValue = model->BSIM4vtsd; + return(OK); + case BSIM4_MOD_VTSSWS: + value->rValue = model->BSIM4vtssws; + return(OK); + case BSIM4_MOD_VTSSWD: + value->rValue = model->BSIM4vtsswd; + return(OK); + case BSIM4_MOD_VTSSWGS: + value->rValue = model->BSIM4vtsswgs; + return(OK); + case BSIM4_MOD_VTSSWGD: + value->rValue = model->BSIM4vtsswgd; + return(OK); + case BSIM4_MOD_GBMIN: value->rValue = model->BSIM4gbmin; return(OK); @@ -492,6 +612,87 @@ IFvalue *value; value->rValue = model->BSIM4rbpd; return(OK); + case BSIM4_MOD_RBPS0: + value->rValue = model->BSIM4rbps0; + return(OK); + case BSIM4_MOD_RBPSL: + value->rValue = model->BSIM4rbpsl; + return(OK); + case BSIM4_MOD_RBPSW: + value->rValue = model->BSIM4rbpsw; + return(OK); + case BSIM4_MOD_RBPSNF: + value->rValue = model->BSIM4rbpsnf; + return(OK); + case BSIM4_MOD_RBPD0: + value->rValue = model->BSIM4rbpd0; + return(OK); + case BSIM4_MOD_RBPDL: + value->rValue = model->BSIM4rbpdl; + return(OK); + case BSIM4_MOD_RBPDW: + value->rValue = model->BSIM4rbpdw; + return(OK); + case BSIM4_MOD_RBPDNF: + value->rValue = model->BSIM4rbpdnf; + return(OK); + case BSIM4_MOD_RBPBX0: + value->rValue = model->BSIM4rbpbx0; + return(OK); + case BSIM4_MOD_RBPBXL: + value->rValue = model->BSIM4rbpbxl; + return(OK); + case BSIM4_MOD_RBPBXW: + value->rValue = model->BSIM4rbpbxw; + return(OK); + case BSIM4_MOD_RBPBXNF: + value->rValue = model->BSIM4rbpbxnf; + return(OK); + case BSIM4_MOD_RBPBY0: + value->rValue = model->BSIM4rbpby0; + return(OK); + case BSIM4_MOD_RBPBYL: + value->rValue = model->BSIM4rbpbyl; + return(OK); + case BSIM4_MOD_RBPBYW: + value->rValue = model->BSIM4rbpbyw; + return(OK); + case BSIM4_MOD_RBPBYNF: + value->rValue = model->BSIM4rbpbynf; + return(OK); + + case BSIM4_MOD_RBSBX0: + value->rValue = model->BSIM4rbsbx0; + return(OK); + case BSIM4_MOD_RBSBY0: + value->rValue = model->BSIM4rbsby0; + return(OK); + case BSIM4_MOD_RBDBX0: + value->rValue = model->BSIM4rbdbx0; + return(OK); + case BSIM4_MOD_RBDBY0: + value->rValue = model->BSIM4rbdby0; + return(OK); + case BSIM4_MOD_RBSDBXL: + value->rValue = model->BSIM4rbsdbxl; + return(OK); + case BSIM4_MOD_RBSDBXW: + value->rValue = model->BSIM4rbsdbxw; + return(OK); + case BSIM4_MOD_RBSDBXNF: + value->rValue = model->BSIM4rbsdbxnf; + return(OK); + case BSIM4_MOD_RBSDBYL: + value->rValue = model->BSIM4rbsdbyl; + return(OK); + case BSIM4_MOD_RBSDBYW: + value->rValue = model->BSIM4rbsdbyw; + return(OK); + case BSIM4_MOD_RBSDBYNF: + value->rValue = model->BSIM4rbsdbynf; + return(OK); + + case BSIM4_MOD_CGSL: value->rValue = model->BSIM4cgsl; return(OK); @@ -567,9 +768,6 @@ IFvalue *value; case BSIM4_MOD_RSHG: value->rValue = model->BSIM4rshg; return(OK); - case BSIM4_MOD_NGCON: - value->rValue = model->BSIM4ngcon; - return(OK); case BSIM4_MOD_TCJ: value->rValue = model->BSIM4tcj; return(OK); @@ -737,6 +935,18 @@ IFvalue *value; case BSIM4_MOD_LUC1: value->rValue = model->BSIM4luc1; return(OK); + case BSIM4_MOD_LUD: + value->rValue = model->BSIM4lud; + return(OK); + case BSIM4_MOD_LUD1: + value->rValue = model->BSIM4lud1; + return(OK); + case BSIM4_MOD_LUP: + value->rValue = model->BSIM4lup; + return(OK); + case BSIM4_MOD_LLP: + value->rValue = model->BSIM4llp; + return(OK); case BSIM4_MOD_LU0: value->rValue = model->BSIM4lu0; return(OK); @@ -746,6 +956,9 @@ IFvalue *value; case BSIM4_MOD_LVOFF: value->rValue = model->BSIM4lvoff; return(OK); + case BSIM4_MOD_LTVOFF: + value->rValue = model->BSIM4ltvoff; + return(OK); case BSIM4_MOD_LMINV: value->rValue = model->BSIM4lminv; return(OK); @@ -951,6 +1164,12 @@ IFvalue *value; case BSIM4_MOD_LVOFFCV: value->rValue = model->BSIM4lvoffcv; return(OK); + case BSIM4_MOD_LVFBSDOFF: + value->rValue = model->BSIM4lvfbsdoff; + return(OK); + case BSIM4_MOD_LTVFBSDOFF: + value->rValue = model->BSIM4ltvfbsdoff; + return(OK); /* Width dependence */ case BSIM4_MOD_WCDSC : @@ -1100,6 +1319,18 @@ IFvalue *value; case BSIM4_MOD_WUC1: value->rValue = model->BSIM4wuc1; return(OK); + case BSIM4_MOD_WUD: + value->rValue = model->BSIM4wud; + return(OK); + case BSIM4_MOD_WUD1: + value->rValue = model->BSIM4wud1; + return(OK); + case BSIM4_MOD_WUP: + value->rValue = model->BSIM4wup; + return(OK); + case BSIM4_MOD_WLP: + value->rValue = model->BSIM4wlp; + return(OK); case BSIM4_MOD_WU0: value->rValue = model->BSIM4wu0; return(OK); @@ -1109,6 +1340,9 @@ IFvalue *value; case BSIM4_MOD_WVOFF: value->rValue = model->BSIM4wvoff; return(OK); + case BSIM4_MOD_WTVOFF: + value->rValue = model->BSIM4wtvoff; + return(OK); case BSIM4_MOD_WMINV: value->rValue = model->BSIM4wminv; return(OK); @@ -1314,6 +1548,12 @@ IFvalue *value; case BSIM4_MOD_WVOFFCV: value->rValue = model->BSIM4wvoffcv; return(OK); + case BSIM4_MOD_WVFBSDOFF: + value->rValue = model->BSIM4wvfbsdoff; + return(OK); + case BSIM4_MOD_WTVFBSDOFF: + value->rValue = model->BSIM4wtvfbsdoff; + return(OK); /* Cross-term dependence */ case BSIM4_MOD_PCDSC : @@ -1463,6 +1703,18 @@ IFvalue *value; case BSIM4_MOD_PUC1: value->rValue = model->BSIM4puc1; return(OK); + case BSIM4_MOD_PUD: + value->rValue = model->BSIM4pud; + return(OK); + case BSIM4_MOD_PUD1: + value->rValue = model->BSIM4pud1; + return(OK); + case BSIM4_MOD_PUP: + value->rValue = model->BSIM4pup; + return(OK); + case BSIM4_MOD_PLP: + value->rValue = model->BSIM4plp; + return(OK); case BSIM4_MOD_PU0: value->rValue = model->BSIM4pu0; return(OK); @@ -1472,6 +1724,9 @@ IFvalue *value; case BSIM4_MOD_PVOFF: value->rValue = model->BSIM4pvoff; return(OK); + case BSIM4_MOD_PTVOFF: + value->rValue = model->BSIM4ptvoff; + return(OK); case BSIM4_MOD_PMINV: value->rValue = model->BSIM4pminv; return(OK); @@ -1677,6 +1932,12 @@ IFvalue *value; case BSIM4_MOD_PVOFFCV: value->rValue = model->BSIM4pvoffcv; return(OK); + case BSIM4_MOD_PVFBSDOFF: + value->rValue = model->BSIM4pvfbsdoff; + return(OK); + case BSIM4_MOD_PTVFBSDOFF: + value->rValue = model->BSIM4ptvfbsdoff; + return(OK); case BSIM4_MOD_TNOM : value->rValue = model->BSIM4tnom; @@ -1846,6 +2107,122 @@ IFvalue *value; case BSIM4_MOD_WMAX: value->rValue = model->BSIM4Wmax; return(OK); + + /* stress effect */ + case BSIM4_MOD_SAREF: + value->rValue = model->BSIM4saref; + return(OK); + case BSIM4_MOD_SBREF: + value->rValue = model->BSIM4sbref; + return(OK); + case BSIM4_MOD_WLOD: + value->rValue = model->BSIM4wlod; + return(OK); + case BSIM4_MOD_KU0: + value->rValue = model->BSIM4ku0; + return(OK); + case BSIM4_MOD_KVSAT: + value->rValue = model->BSIM4kvsat; + return(OK); + case BSIM4_MOD_KVTH0: + value->rValue = model->BSIM4kvth0; + return(OK); + case BSIM4_MOD_TKU0: + value->rValue = model->BSIM4tku0; + return(OK); + case BSIM4_MOD_LLODKU0: + value->rValue = model->BSIM4llodku0; + return(OK); + case BSIM4_MOD_WLODKU0: + value->rValue = model->BSIM4wlodku0; + return(OK); + case BSIM4_MOD_LLODVTH: + value->rValue = model->BSIM4llodvth; + return(OK); + case BSIM4_MOD_WLODVTH: + value->rValue = model->BSIM4wlodvth; + return(OK); + case BSIM4_MOD_LKU0: + value->rValue = model->BSIM4lku0; + return(OK); + case BSIM4_MOD_WKU0: + value->rValue = model->BSIM4wku0; + return(OK); + case BSIM4_MOD_PKU0: + value->rValue = model->BSIM4pku0; + return(OK); + case BSIM4_MOD_LKVTH0: + value->rValue = model->BSIM4lkvth0; + return(OK); + case BSIM4_MOD_WKVTH0: + value->rValue = model->BSIM4wkvth0; + return(OK); + case BSIM4_MOD_PKVTH0: + value->rValue = model->BSIM4pkvth0; + return(OK); + case BSIM4_MOD_STK2: + value->rValue = model->BSIM4stk2; + return(OK); + case BSIM4_MOD_LODK2: + value->rValue = model->BSIM4lodk2; + return(OK); + case BSIM4_MOD_STETA0: + value->rValue = model->BSIM4steta0; + return(OK); + case BSIM4_MOD_LODETA0: + value->rValue = model->BSIM4lodeta0; + return(OK); + + /* Well Proximity Effect */ + case BSIM4_MOD_WEB: + value->rValue = model->BSIM4web; + return(OK); + case BSIM4_MOD_WEC: + value->rValue = model->BSIM4wec; + return(OK); + case BSIM4_MOD_KVTH0WE: + value->rValue = model->BSIM4kvth0we; + return(OK); + case BSIM4_MOD_K2WE: + value->rValue = model->BSIM4k2we; + return(OK); + case BSIM4_MOD_KU0WE: + value->rValue = model->BSIM4ku0we; + return(OK); + case BSIM4_MOD_SCREF: + value->rValue = model->BSIM4scref; + return(OK); + case BSIM4_MOD_WPEMOD: + value->rValue = model->BSIM4wpemod; + return(OK); + case BSIM4_MOD_LKVTH0WE: + value->rValue = model->BSIM4lkvth0we; + return(OK); + case BSIM4_MOD_LK2WE: + value->rValue = model->BSIM4lk2we; + return(OK); + case BSIM4_MOD_LKU0WE: + value->rValue = model->BSIM4lku0we; + return(OK); + case BSIM4_MOD_WKVTH0WE: + value->rValue = model->BSIM4wkvth0we; + return(OK); + case BSIM4_MOD_WK2WE: + value->rValue = model->BSIM4wk2we; + return(OK); + case BSIM4_MOD_WKU0WE: + value->rValue = model->BSIM4wku0we; + return(OK); + case BSIM4_MOD_PKVTH0WE: + value->rValue = model->BSIM4pkvth0we; + return(OK); + case BSIM4_MOD_PK2WE: + value->rValue = model->BSIM4pk2we; + return(OK); + case BSIM4_MOD_PKU0WE: + value->rValue = model->BSIM4pku0we; + return(OK); + case BSIM4_MOD_NOIA: value->rValue = model->BSIM4oxideTrapDensityA; return(OK); diff --git a/src/spicelib/devices/bsim4/b4mdel.c b/src/spicelib/devices/bsim4/b4mdel.c index c472a97be..66f16782e 100644 --- a/src/spicelib/devices/bsim4/b4mdel.c +++ b/src/spicelib/devices/bsim4/b4mdel.c @@ -1,18 +1,17 @@ -/**** BSIM4.2.1, Released by Xuemei Xi 10/05/2001 ****/ +/**** BSIM4.5.0 Released by Xuemei (Jane) Xi 07/29/2005 ****/ /********** - * Copyright 2001 Regents of the University of California. All rights reserved. - * File: b4mdel.c of BSIM4.2.1. + * Copyright 2005 Regents of the University of California. All rights reserved. + * File: b4mdel.c of BSIM4.5.0. * Author: 2000 Weidong Liu - * Authors: Xuemei Xi, Kanyu M. Cao, Hui Wan, Mansun Chan, Chenming Hu. + * Authors: 2001- Xuemei Xi, Mohan Dunga, Ali Niknejad, Chenming Hu. * Project Director: Prof. Chenming Hu. **********/ #include "ngspice.h" -#include #include "bsim4def.h" #include "sperror.h" - +#include "suffix.h" int BSIM4mDelete(inModel,modname,kill) diff --git a/src/spicelib/devices/bsim4/b4mpar.c b/src/spicelib/devices/bsim4/b4mpar.c index a4606612e..614b3649a 100644 --- a/src/spicelib/devices/bsim4/b4mpar.c +++ b/src/spicelib/devices/bsim4/b4mpar.c @@ -1,21 +1,24 @@ -/**** BSIM4.2.1, Released by Xuemei Xi 10/05/2001 ****/ +/**** BSIM4.5.0 Released by Xuemei (Jane) Xi 07/29/2005 ****/ /********** - * Copyright 2001 Regents of the University of California. All rights reserved. - * File: b4mpar.c of BSIM4.2.1. + * Copyright 2005 Regents of the University of California. All rights reserved. + * File: b4mpar.c of BSIM4.5.0. * Author: 2000 Weidong Liu - * Authors: Xuemei Xi, Kanyu M. Cao, Hui Wan, Mansun Chan, Chenming Hu. + * Authors: 2001- Xuemei Xi, Mohan Dunga, Ali Niknejad, Chenming Hu. * Project Director: Prof. Chenming Hu. - * - * Modified by Xuemei Xi 04/06/2001 + * Modified by Xuemei Xi, 04/06/2001. + * Modified by Xuemei Xi, 10/05/2001. + * Modified by Xuemei Xi, 11/15/2002. + * Modified by Xuemei Xi, 05/09/2003. + * Modified by Xuemei Xi, 03/04/2004. + * Modified by Xuemei Xi, Mohan Dunga, 07/29/2005. **********/ #include "ngspice.h" -#include #include "bsim4def.h" #include "ifsim.h" #include "sperror.h" -#include "const.h" +#include "suffix.h" int BSIM4mParam(param,value,inMod) @@ -89,6 +92,11 @@ GENmodel *inMod; mod->BSIM4igbMod = value->iValue; mod->BSIM4igbModGiven = TRUE; break; + case BSIM4_MOD_TEMPMOD : + mod->BSIM4tempMod = value->iValue; + mod->BSIM4tempModGiven = TRUE; + break; + case BSIM4_MOD_VERSION : mod->BSIM4version = value->sValue; mod->BSIM4versionGiven = TRUE; @@ -336,10 +344,81 @@ GENmodel *inMod; mod->BSIM4ute = value->rValue; mod->BSIM4uteGiven = TRUE; break; + + case BSIM4_MOD_UD: + mod->BSIM4ud = value->rValue; + mod->BSIM4udGiven = TRUE; + break; + case BSIM4_MOD_UD1: + mod->BSIM4ud1 = value->rValue; + mod->BSIM4ud1Given = TRUE; + break; + case BSIM4_MOD_UP: + mod->BSIM4up = value->rValue; + mod->BSIM4upGiven = TRUE; + break; + case BSIM4_MOD_LP: + mod->BSIM4lp = value->rValue; + mod->BSIM4lpGiven = TRUE; + break; + case BSIM4_MOD_LUD: + mod->BSIM4lud = value->rValue; + mod->BSIM4ludGiven = TRUE; + break; + case BSIM4_MOD_LUD1: + mod->BSIM4lud1 = value->rValue; + mod->BSIM4lud1Given = TRUE; + break; + case BSIM4_MOD_LUP: + mod->BSIM4lup = value->rValue; + mod->BSIM4lupGiven = TRUE; + break; + case BSIM4_MOD_LLP: + mod->BSIM4llp = value->rValue; + mod->BSIM4llpGiven = TRUE; + break; + case BSIM4_MOD_WUD: + mod->BSIM4wud = value->rValue; + mod->BSIM4wudGiven = TRUE; + break; + case BSIM4_MOD_WUD1: + mod->BSIM4wud1 = value->rValue; + mod->BSIM4wud1Given = TRUE; + break; + case BSIM4_MOD_WUP: + mod->BSIM4wup = value->rValue; + mod->BSIM4wupGiven = TRUE; + break; + case BSIM4_MOD_WLP: + mod->BSIM4wlp = value->rValue; + mod->BSIM4wlpGiven = TRUE; + break; + case BSIM4_MOD_PUD: + mod->BSIM4pud = value->rValue; + mod->BSIM4pudGiven = TRUE; + break; + case BSIM4_MOD_PUD1: + mod->BSIM4pud1 = value->rValue; + mod->BSIM4pud1Given = TRUE; + break; + case BSIM4_MOD_PUP: + mod->BSIM4pup = value->rValue; + mod->BSIM4pupGiven = TRUE; + break; + case BSIM4_MOD_PLP: + mod->BSIM4plp = value->rValue; + mod->BSIM4plpGiven = TRUE; + break; + + case BSIM4_MOD_VOFF: mod->BSIM4voff = value->rValue; mod->BSIM4voffGiven = TRUE; break; + case BSIM4_MOD_TVOFF: + mod->BSIM4tvoff = value->rValue; + mod->BSIM4tvoffGiven = TRUE; + break; case BSIM4_MOD_VOFFL: mod->BSIM4voffl = value->rValue; mod->BSIM4vofflGiven = TRUE; @@ -568,6 +647,26 @@ GENmodel *inMod; mod->BSIM4xrcrg1 = value->rValue; mod->BSIM4xrcrg1Given = TRUE; break; + case BSIM4_MOD_XRCRG2 : + mod->BSIM4xrcrg2 = value->rValue; + mod->BSIM4xrcrg2Given = TRUE; + break; + case BSIM4_MOD_LAMBDA : + mod->BSIM4lambda = value->rValue; + mod->BSIM4lambdaGiven = TRUE; + break; + case BSIM4_MOD_VTL : + mod->BSIM4vtl = value->rValue; + mod->BSIM4vtlGiven = TRUE; + break; + case BSIM4_MOD_XN: + mod->BSIM4xn = value->rValue; + mod->BSIM4xnGiven = TRUE; + break; + case BSIM4_MOD_LC: + mod->BSIM4lc = value->rValue; + mod->BSIM4lcGiven = TRUE; + break; case BSIM4_MOD_TNOIA : mod->BSIM4tnoia = value->rValue; mod->BSIM4tnoiaGiven = TRUE; @@ -576,14 +675,182 @@ GENmodel *inMod; mod->BSIM4tnoib = value->rValue; mod->BSIM4tnoibGiven = TRUE; break; + case BSIM4_MOD_RNOIA : + mod->BSIM4rnoia = value->rValue; + mod->BSIM4rnoiaGiven = TRUE; + break; + case BSIM4_MOD_RNOIB : + mod->BSIM4rnoib = value->rValue; + mod->BSIM4rnoibGiven = TRUE; + break; case BSIM4_MOD_NTNOI : mod->BSIM4ntnoi = value->rValue; mod->BSIM4ntnoiGiven = TRUE; break; - case BSIM4_MOD_XRCRG2 : - mod->BSIM4xrcrg2 = value->rValue; - mod->BSIM4xrcrg2Given = TRUE; + case BSIM4_MOD_VFBSDOFF: + mod->BSIM4vfbsdoff = value->rValue; + mod->BSIM4vfbsdoffGiven = TRUE; break; + case BSIM4_MOD_TVFBSDOFF: + mod->BSIM4tvfbsdoff = value->rValue; + mod->BSIM4tvfbsdoffGiven = TRUE; + break; + case BSIM4_MOD_LINTNOI: + mod->BSIM4lintnoi = value->rValue; + mod->BSIM4lintnoiGiven = TRUE; + break; + + /* stress effect */ + case BSIM4_MOD_SAREF : + mod->BSIM4saref = value->rValue; + mod->BSIM4sarefGiven = TRUE; + break; + case BSIM4_MOD_SBREF : + mod->BSIM4sbref = value->rValue; + mod->BSIM4sbrefGiven = TRUE; + break; + case BSIM4_MOD_WLOD : + mod->BSIM4wlod = value->rValue; + mod->BSIM4wlodGiven = TRUE; + break; + case BSIM4_MOD_KU0 : + mod->BSIM4ku0 = value->rValue; + mod->BSIM4ku0Given = TRUE; + break; + case BSIM4_MOD_KVSAT : + mod->BSIM4kvsat = value->rValue; + mod->BSIM4kvsatGiven = TRUE; + break; + case BSIM4_MOD_KVTH0 : + mod->BSIM4kvth0 = value->rValue; + mod->BSIM4kvth0Given = TRUE; + break; + case BSIM4_MOD_TKU0 : + mod->BSIM4tku0 = value->rValue; + mod->BSIM4tku0Given = TRUE; + break; + case BSIM4_MOD_LLODKU0 : + mod->BSIM4llodku0 = value->rValue; + mod->BSIM4llodku0Given = TRUE; + break; + case BSIM4_MOD_WLODKU0 : + mod->BSIM4wlodku0 = value->rValue; + mod->BSIM4wlodku0Given = TRUE; + break; + case BSIM4_MOD_LLODVTH : + mod->BSIM4llodvth = value->rValue; + mod->BSIM4llodvthGiven = TRUE; + break; + case BSIM4_MOD_WLODVTH : + mod->BSIM4wlodvth = value->rValue; + mod->BSIM4wlodvthGiven = TRUE; + break; + case BSIM4_MOD_LKU0 : + mod->BSIM4lku0 = value->rValue; + mod->BSIM4lku0Given = TRUE; + break; + case BSIM4_MOD_WKU0 : + mod->BSIM4wku0 = value->rValue; + mod->BSIM4wku0Given = TRUE; + break; + case BSIM4_MOD_PKU0 : + mod->BSIM4pku0 = value->rValue; + mod->BSIM4pku0Given = TRUE; + break; + case BSIM4_MOD_LKVTH0 : + mod->BSIM4lkvth0 = value->rValue; + mod->BSIM4lkvth0Given = TRUE; + break; + case BSIM4_MOD_WKVTH0 : + mod->BSIM4wkvth0 = value->rValue; + mod->BSIM4wkvth0Given = TRUE; + break; + case BSIM4_MOD_PKVTH0 : + mod->BSIM4pkvth0 = value->rValue; + mod->BSIM4pkvth0Given = TRUE; + break; + case BSIM4_MOD_STK2 : + mod->BSIM4stk2 = value->rValue; + mod->BSIM4stk2Given = TRUE; + break; + case BSIM4_MOD_LODK2 : + mod->BSIM4lodk2 = value->rValue; + mod->BSIM4lodk2Given = TRUE; + break; + case BSIM4_MOD_STETA0 : + mod->BSIM4steta0 = value->rValue; + mod->BSIM4steta0Given = TRUE; + break; + case BSIM4_MOD_LODETA0 : + mod->BSIM4lodeta0 = value->rValue; + mod->BSIM4lodeta0Given = TRUE; + break; + + case BSIM4_MOD_WEB : + mod->BSIM4web = value->rValue; + mod->BSIM4webGiven = TRUE; + break; + case BSIM4_MOD_WEC : + mod->BSIM4wec = value->rValue; + mod->BSIM4wecGiven = TRUE; + break; + case BSIM4_MOD_KVTH0WE : + mod->BSIM4kvth0we = value->rValue; + mod->BSIM4kvth0weGiven = TRUE; + break; + case BSIM4_MOD_K2WE : + mod->BSIM4k2we = value->rValue; + mod->BSIM4k2weGiven = TRUE; + break; + case BSIM4_MOD_KU0WE : + mod->BSIM4ku0we = value->rValue; + mod->BSIM4ku0weGiven = TRUE; + break; + case BSIM4_MOD_SCREF : + mod->BSIM4scref = value->rValue; + mod->BSIM4screfGiven = TRUE; + break; + case BSIM4_MOD_WPEMOD : + mod->BSIM4wpemod = value->rValue; + mod->BSIM4wpemodGiven = TRUE; + break; + case BSIM4_MOD_LKVTH0WE : + mod->BSIM4lkvth0we = value->rValue; + mod->BSIM4lkvth0weGiven = TRUE; + break; + case BSIM4_MOD_LK2WE : + mod->BSIM4lk2we = value->rValue; + mod->BSIM4lk2weGiven = TRUE; + break; + case BSIM4_MOD_LKU0WE : + mod->BSIM4lku0we = value->rValue; + mod->BSIM4lku0weGiven = TRUE; + break; + case BSIM4_MOD_WKVTH0WE : + mod->BSIM4wkvth0we = value->rValue; + mod->BSIM4wkvth0weGiven = TRUE; + break; + case BSIM4_MOD_WK2WE : + mod->BSIM4wk2we = value->rValue; + mod->BSIM4wk2weGiven = TRUE; + break; + case BSIM4_MOD_WKU0WE : + mod->BSIM4wku0we = value->rValue; + mod->BSIM4wku0weGiven = TRUE; + break; + case BSIM4_MOD_PKVTH0WE : + mod->BSIM4pkvth0we = value->rValue; + mod->BSIM4pkvth0weGiven = TRUE; + break; + case BSIM4_MOD_PK2WE : + mod->BSIM4pk2we = value->rValue; + mod->BSIM4pk2weGiven = TRUE; + break; + case BSIM4_MOD_PKU0WE : + mod->BSIM4pku0we = value->rValue; + mod->BSIM4pku0weGiven = TRUE; + break; + case BSIM4_MOD_BETA0 : mod->BSIM4beta0 = value->rValue; mod->BSIM4beta0Given = TRUE; @@ -620,6 +887,105 @@ GENmodel *inMod; mod->BSIM4bvs = value->rValue; mod->BSIM4bvsGiven = TRUE; break; + + /* reverse diode */ + case BSIM4_MOD_JTSS : + mod->BSIM4jtss = value->rValue; + mod->BSIM4jtssGiven = TRUE; + break; + case BSIM4_MOD_JTSD : + mod->BSIM4jtsd = value->rValue; + mod->BSIM4jtsdGiven = TRUE; + break; + case BSIM4_MOD_JTSSWS : + mod->BSIM4jtssws = value->rValue; + mod->BSIM4jtsswsGiven = TRUE; + break; + case BSIM4_MOD_JTSSWD : + mod->BSIM4jtsswd = value->rValue; + mod->BSIM4jtsswdGiven = TRUE; + break; + case BSIM4_MOD_JTSSWGS : + mod->BSIM4jtsswgs = value->rValue; + mod->BSIM4jtsswgsGiven = TRUE; + break; + case BSIM4_MOD_JTSSWGD : + mod->BSIM4jtsswgd = value->rValue; + mod->BSIM4jtsswgdGiven = TRUE; + break; + case BSIM4_MOD_NJTS : + mod->BSIM4njts = value->rValue; + mod->BSIM4njtsGiven = TRUE; + break; + case BSIM4_MOD_NJTSSW : + mod->BSIM4njtssw = value->rValue; + mod->BSIM4njtsswGiven = TRUE; + break; + case BSIM4_MOD_NJTSSWG : + mod->BSIM4njtsswg = value->rValue; + mod->BSIM4njtsswgGiven = TRUE; + break; + case BSIM4_MOD_XTSS : + mod->BSIM4xtss = value->rValue; + mod->BSIM4xtssGiven = TRUE; + break; + case BSIM4_MOD_XTSD : + mod->BSIM4xtsd = value->rValue; + mod->BSIM4xtsdGiven = TRUE; + break; + case BSIM4_MOD_XTSSWS : + mod->BSIM4xtssws = value->rValue; + mod->BSIM4xtsswsGiven = TRUE; + break; + case BSIM4_MOD_XTSSWD : + mod->BSIM4xtsswd = value->rValue; + mod->BSIM4xtsswdGiven = TRUE; + break; + case BSIM4_MOD_XTSSWGS : + mod->BSIM4xtsswgs = value->rValue; + mod->BSIM4xtsswgsGiven = TRUE; + break; + case BSIM4_MOD_XTSSWGD : + mod->BSIM4xtsswgd = value->rValue; + mod->BSIM4xtsswgdGiven = TRUE; + break; + case BSIM4_MOD_TNJTS : + mod->BSIM4tnjts = value->rValue; + mod->BSIM4tnjtsGiven = TRUE; + break; + case BSIM4_MOD_TNJTSSW : + mod->BSIM4tnjtssw = value->rValue; + mod->BSIM4tnjtsswGiven = TRUE; + break; + case BSIM4_MOD_TNJTSSWG : + mod->BSIM4tnjtsswg = value->rValue; + mod->BSIM4tnjtsswgGiven = TRUE; + break; + case BSIM4_MOD_VTSS : + mod->BSIM4vtss = value->rValue; + mod->BSIM4vtssGiven = TRUE; + break; + case BSIM4_MOD_VTSD : + mod->BSIM4vtsd = value->rValue; + mod->BSIM4vtsdGiven = TRUE; + break; + case BSIM4_MOD_VTSSWS : + mod->BSIM4vtssws = value->rValue; + mod->BSIM4vtsswsGiven = TRUE; + break; + case BSIM4_MOD_VTSSWD : + mod->BSIM4vtsswd = value->rValue; + mod->BSIM4vtsswdGiven = TRUE; + break; + case BSIM4_MOD_VTSSWGS : + mod->BSIM4vtsswgs = value->rValue; + mod->BSIM4vtsswgsGiven = TRUE; + break; + case BSIM4_MOD_VTSSWGD : + mod->BSIM4vtsswgd = value->rValue; + mod->BSIM4vtsswgdGiven = TRUE; + break; + case BSIM4_MOD_VFB : mod->BSIM4vfb = value->rValue; mod->BSIM4vfbGiven = TRUE; @@ -650,6 +1016,115 @@ GENmodel *inMod; mod->BSIM4rbpdGiven = TRUE; break; + case BSIM4_MOD_RBPS0 : + mod->BSIM4rbps0 = value->rValue; + mod->BSIM4rbps0Given = TRUE; + break; + case BSIM4_MOD_RBPSL : + mod->BSIM4rbpsl = value->rValue; + mod->BSIM4rbpslGiven = TRUE; + break; + case BSIM4_MOD_RBPSW : + mod->BSIM4rbpsw = value->rValue; + mod->BSIM4rbpswGiven = TRUE; + break; + case BSIM4_MOD_RBPSNF : + mod->BSIM4rbpsnf = value->rValue; + mod->BSIM4rbpsnfGiven = TRUE; + break; + + case BSIM4_MOD_RBPD0 : + mod->BSIM4rbpd0 = value->rValue; + mod->BSIM4rbpd0Given = TRUE; + break; + case BSIM4_MOD_RBPDL : + mod->BSIM4rbpdl = value->rValue; + mod->BSIM4rbpdlGiven = TRUE; + break; + case BSIM4_MOD_RBPDW : + mod->BSIM4rbpdw = value->rValue; + mod->BSIM4rbpdwGiven = TRUE; + break; + case BSIM4_MOD_RBPDNF : + mod->BSIM4rbpdnf = value->rValue; + mod->BSIM4rbpdnfGiven = TRUE; + break; + + case BSIM4_MOD_RBPBX0 : + mod->BSIM4rbpbx0 = value->rValue; + mod->BSIM4rbpbx0Given = TRUE; + break; + case BSIM4_MOD_RBPBXL : + mod->BSIM4rbpbxl = value->rValue; + mod->BSIM4rbpbxlGiven = TRUE; + break; + case BSIM4_MOD_RBPBXW : + mod->BSIM4rbpbxw = value->rValue; + mod->BSIM4rbpbxwGiven = TRUE; + break; + case BSIM4_MOD_RBPBXNF : + mod->BSIM4rbpbxnf = value->rValue; + mod->BSIM4rbpbxnfGiven = TRUE; + break; + case BSIM4_MOD_RBPBY0 : + mod->BSIM4rbpby0 = value->rValue; + mod->BSIM4rbpby0Given = TRUE; + break; + case BSIM4_MOD_RBPBYL : + mod->BSIM4rbpbyl = value->rValue; + mod->BSIM4rbpbylGiven = TRUE; + break; + case BSIM4_MOD_RBPBYW : + mod->BSIM4rbpbyw = value->rValue; + mod->BSIM4rbpbywGiven = TRUE; + break; + case BSIM4_MOD_RBPBYNF : + mod->BSIM4rbpbynf = value->rValue; + mod->BSIM4rbpbynfGiven = TRUE; + break; + case BSIM4_MOD_RBSBX0 : + mod->BSIM4rbsbx0 = value->rValue; + mod->BSIM4rbsbx0Given = TRUE; + break; + case BSIM4_MOD_RBSBY0 : + mod->BSIM4rbsby0 = value->rValue; + mod->BSIM4rbsby0Given = TRUE; + break; + case BSIM4_MOD_RBDBX0 : + mod->BSIM4rbdbx0 = value->rValue; + mod->BSIM4rbdbx0Given = TRUE; + break; + case BSIM4_MOD_RBDBY0 : + mod->BSIM4rbdby0 = value->rValue; + mod->BSIM4rbdby0Given = TRUE; + break; + + + case BSIM4_MOD_RBSDBXL : + mod->BSIM4rbsdbxl = value->rValue; + mod->BSIM4rbsdbxlGiven = TRUE; + break; + case BSIM4_MOD_RBSDBXW : + mod->BSIM4rbsdbxw = value->rValue; + mod->BSIM4rbsdbxwGiven = TRUE; + break; + case BSIM4_MOD_RBSDBXNF : + mod->BSIM4rbsdbxnf = value->rValue; + mod->BSIM4rbsdbxnfGiven = TRUE; + break; + case BSIM4_MOD_RBSDBYL : + mod->BSIM4rbsdbyl = value->rValue; + mod->BSIM4rbsdbylGiven = TRUE; + break; + case BSIM4_MOD_RBSDBYW : + mod->BSIM4rbsdbyw = value->rValue; + mod->BSIM4rbsdbywGiven = TRUE; + break; + case BSIM4_MOD_RBSDBYNF : + mod->BSIM4rbsdbynf = value->rValue; + mod->BSIM4rbsdbynfGiven = TRUE; + break; + case BSIM4_MOD_CGSL : mod->BSIM4cgsl = value->rValue; mod->BSIM4cgslGiven = TRUE; @@ -998,6 +1473,10 @@ GENmodel *inMod; mod->BSIM4lvoff = value->rValue; mod->BSIM4lvoffGiven = TRUE; break; + case BSIM4_MOD_LTVOFF: + mod->BSIM4ltvoff = value->rValue; + mod->BSIM4ltvoffGiven = TRUE; + break; case BSIM4_MOD_LMINV: mod->BSIM4lminv = value->rValue; mod->BSIM4lminvGiven = TRUE; @@ -1214,6 +1693,26 @@ GENmodel *inMod; mod->BSIM4lxrcrg2 = value->rValue; mod->BSIM4lxrcrg2Given = TRUE; break; + case BSIM4_MOD_LLAMBDA : + mod->BSIM4llambda = value->rValue; + mod->BSIM4llambdaGiven = TRUE; + break; + case BSIM4_MOD_LVTL : + mod->BSIM4lvtl = value->rValue; + mod->BSIM4lvtlGiven = TRUE; + break; + case BSIM4_MOD_LXN: + mod->BSIM4lxn = value->rValue; + mod->BSIM4lxnGiven = TRUE; + break; + case BSIM4_MOD_LVFBSDOFF: + mod->BSIM4lvfbsdoff = value->rValue; + mod->BSIM4lvfbsdoffGiven = TRUE; + break; + case BSIM4_MOD_LTVFBSDOFF: + mod->BSIM4ltvfbsdoff = value->rValue; + mod->BSIM4ltvfbsdoffGiven = TRUE; + break; case BSIM4_MOD_LEU : mod->BSIM4leu = value->rValue; mod->BSIM4leuGiven = TRUE; @@ -1222,7 +1721,6 @@ GENmodel *inMod; mod->BSIM4lvfb = value->rValue; mod->BSIM4lvfbGiven = TRUE; break; - case BSIM4_MOD_LCGSL : mod->BSIM4lcgsl = value->rValue; mod->BSIM4lcgslGiven = TRUE; @@ -1491,6 +1989,10 @@ GENmodel *inMod; mod->BSIM4wvoff = value->rValue; mod->BSIM4wvoffGiven = TRUE; break; + case BSIM4_MOD_WTVOFF: + mod->BSIM4wtvoff = value->rValue; + mod->BSIM4wtvoffGiven = TRUE; + break; case BSIM4_MOD_WMINV: mod->BSIM4wminv = value->rValue; mod->BSIM4wminvGiven = TRUE; @@ -1707,6 +2209,26 @@ GENmodel *inMod; mod->BSIM4wxrcrg2 = value->rValue; mod->BSIM4wxrcrg2Given = TRUE; break; + case BSIM4_MOD_WLAMBDA : + mod->BSIM4wlambda = value->rValue; + mod->BSIM4wlambdaGiven = TRUE; + break; + case BSIM4_MOD_WVTL : + mod->BSIM4wvtl = value->rValue; + mod->BSIM4wvtlGiven = TRUE; + break; + case BSIM4_MOD_WXN: + mod->BSIM4wxn = value->rValue; + mod->BSIM4wxnGiven = TRUE; + break; + case BSIM4_MOD_WVFBSDOFF: + mod->BSIM4wvfbsdoff = value->rValue; + mod->BSIM4wvfbsdoffGiven = TRUE; + break; + case BSIM4_MOD_WTVFBSDOFF: + mod->BSIM4wtvfbsdoff = value->rValue; + mod->BSIM4wtvfbsdoffGiven = TRUE; + break; case BSIM4_MOD_WEU : mod->BSIM4weu = value->rValue; mod->BSIM4weuGiven = TRUE; @@ -1715,7 +2237,6 @@ GENmodel *inMod; mod->BSIM4wvfb = value->rValue; mod->BSIM4wvfbGiven = TRUE; break; - case BSIM4_MOD_WCGSL : mod->BSIM4wcgsl = value->rValue; mod->BSIM4wcgslGiven = TRUE; @@ -1984,6 +2505,10 @@ GENmodel *inMod; mod->BSIM4pvoff = value->rValue; mod->BSIM4pvoffGiven = TRUE; break; + case BSIM4_MOD_PTVOFF: + mod->BSIM4ptvoff = value->rValue; + mod->BSIM4ptvoffGiven = TRUE; + break; case BSIM4_MOD_PMINV: mod->BSIM4pminv = value->rValue; mod->BSIM4pminvGiven = TRUE; @@ -2200,6 +2725,26 @@ GENmodel *inMod; mod->BSIM4pxrcrg2 = value->rValue; mod->BSIM4pxrcrg2Given = TRUE; break; + case BSIM4_MOD_PLAMBDA : + mod->BSIM4plambda = value->rValue; + mod->BSIM4plambdaGiven = TRUE; + break; + case BSIM4_MOD_PVTL : + mod->BSIM4pvtl = value->rValue; + mod->BSIM4pvtlGiven = TRUE; + break; + case BSIM4_MOD_PXN: + mod->BSIM4pxn = value->rValue; + mod->BSIM4pxnGiven = TRUE; + break; + case BSIM4_MOD_PVFBSDOFF: + mod->BSIM4pvfbsdoff = value->rValue; + mod->BSIM4pvfbsdoffGiven = TRUE; + break; + case BSIM4_MOD_PTVFBSDOFF: + mod->BSIM4ptvfbsdoff = value->rValue; + mod->BSIM4ptvfbsdoffGiven = TRUE; + break; case BSIM4_MOD_PEU : mod->BSIM4peu = value->rValue; mod->BSIM4peuGiven = TRUE; @@ -2208,7 +2753,6 @@ GENmodel *inMod; mod->BSIM4pvfb = value->rValue; mod->BSIM4pvfbGiven = TRUE; break; - case BSIM4_MOD_PCGSL : mod->BSIM4pcgsl = value->rValue; mod->BSIM4pcgslGiven = TRUE; diff --git a/src/spicelib/devices/bsim4/b4noi.c b/src/spicelib/devices/bsim4/b4noi.c index 434d01713..551867f41 100644 --- a/src/spicelib/devices/bsim4/b4noi.c +++ b/src/spicelib/devices/bsim4/b4noi.c @@ -1,22 +1,25 @@ -/**** BSIM4.2.1, Released by Xuemei Xi 10/05/2001 ****/ +/**** BSIM4.5.0 Released by Xuemei (Jane) Xi 07/29/2005 ****/ /********** - * Copyright 2001 Regents of the University of California. All rights reserved. - * File: b4noi.c of BSIM4.2.1. + * Copyright 2005 Regents of the University of California. All rights reserved. + * File: b4noi.c of BSIM4.5.0. * Author: 2000 Weidong Liu - * Authors: Xuemei Xi, Kanyu M. Cao, Hui Wan, Mansun Chan, Chenming Hu. + * Authors: 2001- Xuemei Xi, Mohan Dunga, Ali Niknejad, Chenming Hu. * Project Director: Prof. Chenming Hu. - + * Modified by Xuemei Xi, 04/06/2001. * Modified by Xuemei Xi, 10/05/2001. + * Modified by Xuemei Xi, 11/15/2002. + * Modified by Xuemei Xi, 05/09/2003. + * Modified by Xuemei Xi, 03/04/2004. + * Modified by Xuemei Xi, 07/29/2005. **********/ #include "ngspice.h" -#include -#include #include "bsim4def.h" #include "cktdefs.h" #include "iferrmsg.h" #include "noisedef.h" +#include "suffix.h" #include "const.h" @@ -36,22 +39,24 @@ BSIM4model *model; BSIM4instance *here; { struct bsim4SizeDependParam *pParam; -double cd, esat, DelClm, EffFreq, N0, Nl; -double T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, Ssi; +double cd, esat, DelClm, EffFreq, N0, Nl, Leff, Leffsq; +double T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, Ssi; pParam = here->pParam; cd = fabs(here->BSIM4cd); - esat = 2.0 * pParam->BSIM4vsattemp / here->BSIM4ueff; + Leff = pParam->BSIM4leff - 2.0 * model->BSIM4lintnoi; + Leffsq = Leff * Leff; + esat = 2.0 * here->BSIM4vsattemp / here->BSIM4ueff; if(model->BSIM4em<=0.0) DelClm = 0.0; /* flicker noise modified -JX */ else { T0 = ((((Vds - here->BSIM4Vdseff) / pParam->BSIM4litl) + model->BSIM4em) / esat); DelClm = pParam->BSIM4litl * log (MAX(T0, N_MINLOG)); + if (DelClm < 0.0) DelClm = 0.0; /* bugfix */ } EffFreq = pow(freq, model->BSIM4ef); T1 = CHARGE * CHARGE * CONSTboltz * cd * temp * here->BSIM4ueff; - T2 = 1.0e10 * EffFreq * here->BSIM4Abulk * model->BSIM4coxe - * pParam->BSIM4leff * pParam->BSIM4leff; + T2 = 1.0e10 * EffFreq * here->BSIM4Abulk * model->BSIM4coxe * Leffsq; N0 = model->BSIM4coxe * here->BSIM4Vgsteff / CHARGE; Nl = model->BSIM4coxe * here->BSIM4Vgsteff * (1.0 - here->BSIM4AbovVgst2Vtm * here->BSIM4Vdseff) / CHARGE; @@ -62,8 +67,7 @@ double T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, Ssi; T5 = model->BSIM4oxideTrapDensityC * 0.5 * (N0 * N0 - Nl * Nl); T6 = CONSTboltz * temp * cd * cd; - T7 = 1.0e10 * EffFreq * pParam->BSIM4leff - * pParam->BSIM4leff * pParam->BSIM4weff; + T7 = 1.0e10 * EffFreq * Leffsq * pParam->BSIM4weff * here->BSIM4nf; T8 = model->BSIM4oxideTrapDensityA + model->BSIM4oxideTrapDensityB * Nl + model->BSIM4oxideTrapDensityC * Nl * Nl; T9 = (Nl + here->BSIM4nstar) * (Nl + here->BSIM4nstar); @@ -89,12 +93,13 @@ double tempInoise; double noizDens[BSIM4NSRCS]; double lnNdens[BSIM4NSRCS]; -double N0, Nl; -double T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13; -double Vds, n, ExpArg, Ssi, Swi; -double tmp, gdpr, gspr, npart_theta, npart_beta, igsquare; +double T0, T1, T2, T5, T10, T11; +double Vds, Ssi, Swi; +double tmp=0.0, gdpr, gspr, npart_theta=0.0, npart_beta=0.0, igsquare, bodymode; -int error, i; +double m; + +int i; /* define the names of the noise sources */ static char *BSIM4nNames[BSIM4NSRCS] = @@ -181,6 +186,7 @@ int error, i; } break; case N_CALC: + m = here->BSIM4m; switch (mode) { case N_DENS: if (model->BSIM4tnoiMod == 0) @@ -201,9 +207,9 @@ int error, i; else { T5 = here->BSIM4Vgsteff / here->BSIM4EsatL; T5 *= T5; - npart_beta = 0.577 * (1.0 + T5 + npart_beta = model->BSIM4rnoia * (1.0 + T5 * model->BSIM4tnoia * pParam->BSIM4leff); - npart_theta = 0.37 * (1.0 + T5 + npart_theta = model->BSIM4rnoib * (1.0 + T5 * model->BSIM4tnoib * pParam->BSIM4leff); if (model->BSIM4rdsMod == 0) @@ -216,35 +222,35 @@ int error, i; } if ((*(ckt->CKTstates[0] + here->BSIM4vds)) >= 0.0) - gspr = gspr * (1.0 + npart_theta * npart_theta * gspr - / here->BSIM4IdovVds); + gspr = gspr / (1.0 + npart_theta * npart_theta * gspr + / here->BSIM4IdovVds); /* bugfix */ else - gdpr = gdpr * (1.0 + npart_theta * npart_theta * gdpr + gdpr = gdpr / (1.0 + npart_theta * npart_theta * gdpr / here->BSIM4IdovVds); } NevalSrc(&noizDens[BSIM4RDNOIZ], &lnNdens[BSIM4RDNOIZ], ckt, THERMNOISE, here->BSIM4dNodePrime, here->BSIM4dNode, - gdpr); + gdpr * m); NevalSrc(&noizDens[BSIM4RSNOIZ], &lnNdens[BSIM4RSNOIZ], ckt, THERMNOISE, here->BSIM4sNodePrime, here->BSIM4sNode, - gspr); + gspr * m); if ((here->BSIM4rgateMod == 1) || (here->BSIM4rgateMod == 2)) { NevalSrc(&noizDens[BSIM4RGNOIZ], &lnNdens[BSIM4RGNOIZ], ckt, THERMNOISE, here->BSIM4gNodePrime, here->BSIM4gNodeExt, - here->BSIM4grgeltd); + here->BSIM4grgeltd * m); } else if (here->BSIM4rgateMod == 3) { NevalSrc(&noizDens[BSIM4RGNOIZ], &lnNdens[BSIM4RGNOIZ], ckt, THERMNOISE, here->BSIM4gNodeMid, here->BSIM4gNodeExt, - here->BSIM4grgeltd); + here->BSIM4grgeltd * m); } else { noizDens[BSIM4RGNOIZ] = 0.0; @@ -252,28 +258,79 @@ int error, i; log(MAX(noizDens[BSIM4RGNOIZ], N_MINLOG)); } + bodymode = 5; + if (here->BSIM4rbodyMod == 2) + { if( ( !model->BSIM4rbps0Given) || + ( !model->BSIM4rbpd0Given) ) + bodymode = 1; + else + if( (!model->BSIM4rbsbx0Given && !model->BSIM4rbsby0Given) || + (!model->BSIM4rbdbx0Given && !model->BSIM4rbdby0Given) ) + bodymode = 3; + } if (here->BSIM4rbodyMod) - { NevalSrc(&noizDens[BSIM4RBPSNOIZ], - &lnNdens[BSIM4RBPSNOIZ], ckt, THERMNOISE, - here->BSIM4bNodePrime, here->BSIM4sbNode, - here->BSIM4grbps); - NevalSrc(&noizDens[BSIM4RBPDNOIZ], - &lnNdens[BSIM4RBPDNOIZ], ckt, THERMNOISE, - here->BSIM4bNodePrime, here->BSIM4dbNode, - here->BSIM4grbpd); - NevalSrc(&noizDens[BSIM4RBPBNOIZ], - &lnNdens[BSIM4RBPBNOIZ], ckt, THERMNOISE, - here->BSIM4bNodePrime, here->BSIM4bNode, - here->BSIM4grbpb); - NevalSrc(&noizDens[BSIM4RBSBNOIZ], - &lnNdens[BSIM4RBSBNOIZ], ckt, THERMNOISE, - here->BSIM4bNode, here->BSIM4sbNode, - here->BSIM4grbsb); - NevalSrc(&noizDens[BSIM4RBDBNOIZ], - &lnNdens[BSIM4RBDBNOIZ], ckt, THERMNOISE, - here->BSIM4bNode, here->BSIM4dbNode, - here->BSIM4grbdb); + { + if(bodymode == 5) + { + NevalSrc(&noizDens[BSIM4RBPSNOIZ], + &lnNdens[BSIM4RBPSNOIZ], ckt, THERMNOISE, + here->BSIM4bNodePrime, here->BSIM4sbNode, + here->BSIM4grbps * m); + NevalSrc(&noizDens[BSIM4RBPDNOIZ], + &lnNdens[BSIM4RBPDNOIZ], ckt, THERMNOISE, + here->BSIM4bNodePrime, here->BSIM4dbNode, + here->BSIM4grbpd * m); + NevalSrc(&noizDens[BSIM4RBPBNOIZ], + &lnNdens[BSIM4RBPBNOIZ], ckt, THERMNOISE, + here->BSIM4bNodePrime, here->BSIM4bNode, + here->BSIM4grbpb * m); + NevalSrc(&noizDens[BSIM4RBSBNOIZ], + &lnNdens[BSIM4RBSBNOIZ], ckt, THERMNOISE, + here->BSIM4bNode, here->BSIM4sbNode, + here->BSIM4grbsb * m); + NevalSrc(&noizDens[BSIM4RBDBNOIZ], + &lnNdens[BSIM4RBDBNOIZ], ckt, THERMNOISE, + here->BSIM4bNode, here->BSIM4dbNode, + here->BSIM4grbdb * m); + } + if(bodymode == 3) + { + NevalSrc(&noizDens[BSIM4RBPSNOIZ], + &lnNdens[BSIM4RBPSNOIZ], ckt, THERMNOISE, + here->BSIM4bNodePrime, here->BSIM4sbNode, + here->BSIM4grbps * m); + NevalSrc(&noizDens[BSIM4RBPDNOIZ], + &lnNdens[BSIM4RBPDNOIZ], ckt, THERMNOISE, + here->BSIM4bNodePrime, here->BSIM4dbNode, + here->BSIM4grbpd * m); + NevalSrc(&noizDens[BSIM4RBPBNOIZ], + &lnNdens[BSIM4RBPBNOIZ], ckt, THERMNOISE, + here->BSIM4bNodePrime, here->BSIM4bNode, + here->BSIM4grbpb * m); + noizDens[BSIM4RBSBNOIZ] = noizDens[BSIM4RBDBNOIZ] = 0.0; + lnNdens[BSIM4RBSBNOIZ] = + log(MAX(noizDens[BSIM4RBSBNOIZ], N_MINLOG)); + lnNdens[BSIM4RBDBNOIZ] = + log(MAX(noizDens[BSIM4RBDBNOIZ], N_MINLOG)); + } + if(bodymode == 1) + { + NevalSrc(&noizDens[BSIM4RBPBNOIZ], + &lnNdens[BSIM4RBPBNOIZ], ckt, THERMNOISE, + here->BSIM4bNodePrime, here->BSIM4bNode, + here->BSIM4grbpb * m); + noizDens[BSIM4RBPSNOIZ] = noizDens[BSIM4RBPDNOIZ] = 0.0; + noizDens[BSIM4RBSBNOIZ] = noizDens[BSIM4RBDBNOIZ] = 0.0; + lnNdens[BSIM4RBPSNOIZ] = + log(MAX(noizDens[BSIM4RBPSNOIZ], N_MINLOG)); + lnNdens[BSIM4RBPDNOIZ] = + log(MAX(noizDens[BSIM4RBPDNOIZ], N_MINLOG)); + lnNdens[BSIM4RBSBNOIZ] = + log(MAX(noizDens[BSIM4RBSBNOIZ], N_MINLOG)); + lnNdens[BSIM4RBDBNOIZ] = + log(MAX(noizDens[BSIM4RBDBNOIZ], N_MINLOG)); + } } else { noizDens[BSIM4RBPSNOIZ] = noizDens[BSIM4RBPDNOIZ] = 0.0; @@ -294,7 +351,7 @@ int error, i; switch(model->BSIM4tnoiMod) { case 0: - T0 = here->BSIM4ueff * fabs(here->BSIM4qinv); + T0 = m * here->BSIM4ueff * fabs(here->BSIM4qinv); T1 = T0 * tmp + pParam->BSIM4leff * pParam->BSIM4leff; NevalSrc(&noizDens[BSIM4IDNOIZ], @@ -304,7 +361,7 @@ int error, i; (T0 / T1) * model->BSIM4ntnoi); break; case 1: - T0 = here->BSIM4gm + here->BSIM4gmbs + here->BSIM4gds; + T0 = m * here->BSIM4gm + here->BSIM4gmbs + here->BSIM4gds; T0 *= T0; igsquare = npart_theta * npart_theta * T0 / here->BSIM4IdovVds; T1 = npart_beta * (here->BSIM4gm @@ -323,7 +380,7 @@ int error, i; switch(model->BSIM4fnoiMod) { case 0: - noizDens[BSIM4FLNOIZ] *= model->BSIM4kf + noizDens[BSIM4FLNOIZ] *= m * model->BSIM4kf * exp(model->BSIM4af * log(MAX(fabs(here->BSIM4cd), N_MINLOG))) @@ -341,14 +398,14 @@ int error, i; data->freq, ckt->CKTtemp); T10 = model->BSIM4oxideTrapDensityA * CONSTboltz * ckt->CKTtemp; - T11 = pParam->BSIM4weff * pParam->BSIM4leff + T11 = pParam->BSIM4weff * here->BSIM4nf * pParam->BSIM4leff * pow(data->freq, model->BSIM4ef) * 1.0e10 * here->BSIM4nstar * here->BSIM4nstar; Swi = T10 / T11 * here->BSIM4cd * here->BSIM4cd; T1 = Swi + Ssi; if (T1 > 0.0) - noizDens[BSIM4FLNOIZ] *= (Ssi * Swi) / T1; + noizDens[BSIM4FLNOIZ] *= m * (Ssi * Swi) / T1; else noizDens[BSIM4FLNOIZ] *= 0.0; break; @@ -358,19 +415,29 @@ int error, i; log(MAX(noizDens[BSIM4FLNOIZ], N_MINLOG)); + if(here->BSIM4mode >= 0) { /* bugfix */ NevalSrc(&noizDens[BSIM4IGSNOIZ], &lnNdens[BSIM4IGSNOIZ], ckt, SHOTNOISE, here->BSIM4gNodePrime, here->BSIM4sNodePrime, - (here->BSIM4Igs + here->BSIM4Igcs)); + m * (here->BSIM4Igs + here->BSIM4Igcs)); NevalSrc(&noizDens[BSIM4IGDNOIZ], &lnNdens[BSIM4IGDNOIZ], ckt, SHOTNOISE, here->BSIM4gNodePrime, here->BSIM4dNodePrime, - (here->BSIM4Igd + here->BSIM4Igcd)); - + m * (here->BSIM4Igd + here->BSIM4Igcd)); + } else { + NevalSrc(&noizDens[BSIM4IGSNOIZ], + &lnNdens[BSIM4IGSNOIZ], ckt, SHOTNOISE, + here->BSIM4gNodePrime, here->BSIM4sNodePrime, + m * (here->BSIM4Igs + here->BSIM4Igcd)); + NevalSrc(&noizDens[BSIM4IGDNOIZ], + &lnNdens[BSIM4IGDNOIZ], ckt, SHOTNOISE, + here->BSIM4gNodePrime, here->BSIM4dNodePrime, + m * (here->BSIM4Igd + here->BSIM4Igcs)); + } NevalSrc(&noizDens[BSIM4IGBNOIZ], &lnNdens[BSIM4IGBNOIZ], ckt, SHOTNOISE, here->BSIM4gNodePrime, here->BSIM4bNodePrime, - here->BSIM4Igb); + m * here->BSIM4Igb); noizDens[BSIM4TOTNOIZ] = noizDens[BSIM4RDNOIZ] diff --git a/src/spicelib/devices/bsim4/b4par.c b/src/spicelib/devices/bsim4/b4par.c index aa4b450e9..58abee1dc 100644 --- a/src/spicelib/devices/bsim4/b4par.c +++ b/src/spicelib/devices/bsim4/b4par.c @@ -1,18 +1,22 @@ -/**** BSIM4.2.1, Released by Xuemei Xi 10/05/2001 ****/ +/**** BSIM4.5.0 Released by Xuemei (Jane) Xi 07/29/2005 ****/ /********** - * Copyright 2001 Regents of the University of California. All rights reserved. - * File: b4par.c of BSIM4.2.1. + * Copyright 2004 Regents of the University of California. All rights reserved. + * File: b4par.c of BSIM4.5.0. * Author: 2000 Weidong Liu - * Authors: Xuemei Xi, Kanyu M. Cao, Hui Wan, Mansun Chan, Chenming Hu. + * Authors: 2001- Xuemei Xi, Mohan Dunga, Ali Niknejad, Chenming Hu. * Project Director: Prof. Chenming Hu. - **********/ + * Modified by Xuemei Xi, 04/06/2001. + * Modified by Xuemei Xi, 11/15/2002. + * Modified by Xuemei Xi, 05/09/2003. + * Modified by Xuemei Xi, Mohan Dunga, 07/29/2005. +**********/ #include "ngspice.h" -#include #include "ifsim.h" #include "bsim4def.h" #include "sperror.h" +#include "suffix.h" int BSIM4param(param,value,inst,select) @@ -31,7 +35,11 @@ IFvalue *select; here->BSIM4l = value->rValue; here->BSIM4lGiven = TRUE; break; - case BSIM4_NF: + case BSIM4_M: + here->BSIM4m = value->rValue; + here->BSIM4mGiven = TRUE; + break; + case BSIM4_NF: here->BSIM4nf = value->rValue; here->BSIM4nfGiven = TRUE; break; @@ -66,6 +74,34 @@ IFvalue *select; case BSIM4_OFF: here->BSIM4off = value->iValue; break; + case BSIM4_SA: + here->BSIM4sa = value->rValue; + here->BSIM4saGiven = TRUE; + break; + case BSIM4_SB: + here->BSIM4sb = value->rValue; + here->BSIM4sbGiven = TRUE; + break; + case BSIM4_SD: + here->BSIM4sd = value->rValue; + here->BSIM4sdGiven = TRUE; + break; + case BSIM4_SCA: + here->BSIM4sca = value->rValue; + here->BSIM4scaGiven = TRUE; + break; + case BSIM4_SCB: + here->BSIM4scb = value->rValue; + here->BSIM4scbGiven = TRUE; + break; + case BSIM4_SCC: + here->BSIM4scc = value->rValue; + here->BSIM4sccGiven = TRUE; + break; + case BSIM4_SC: + here->BSIM4sc = value->rValue; + here->BSIM4scGiven = TRUE; + break; case BSIM4_RBSB: here->BSIM4rbsb = value->rValue; here->BSIM4rbsbGiven = TRUE; @@ -86,6 +122,18 @@ IFvalue *select; here->BSIM4rbpd = value->rValue; here->BSIM4rbpdGiven = TRUE; break; + case BSIM4_DELVTO: + here->BSIM4delvto = value->rValue; + here->BSIM4delvtoGiven = TRUE; + break; + case BSIM4_XGW: + here->BSIM4xgw = value->rValue; + here->BSIM4xgwGiven = TRUE; + break; + case BSIM4_NGCON: + here->BSIM4ngcon = value->rValue; + here->BSIM4ngconGiven = TRUE; + break; case BSIM4_TRNQSMOD: here->BSIM4trnqsMod = value->iValue; here->BSIM4trnqsModGiven = TRUE; diff --git a/src/spicelib/devices/bsim4/b4pzld.c b/src/spicelib/devices/bsim4/b4pzld.c index 7d07f2da1..484ed1452 100644 --- a/src/spicelib/devices/bsim4/b4pzld.c +++ b/src/spicelib/devices/bsim4/b4pzld.c @@ -1,21 +1,20 @@ -/**** BSIM4.2.1, Released by Xuemei Xi 10/05/2001 ****/ +/**** BSIM4.5.0 Released by Xuemei (Jane) Xi 07/29/2005 ****/ /********** - * Copyright 2001 Regents of the University of California. All rights reserved. - * File: b4pzld.c of BSIM4.2.1. + * Copyright 2005 Regents of the University of California. All rights reserved. + * File: b4pzld.c of BSIM4.5.0. * Author: 2000 Weidong Liu - * Authors: Xuemei Xi, Kanyu M. Cao, Hui Wan, Mansun Chan, Chenming Hu. + * Authors: 2001- Xuemei Xi, Mohan Dunga, Ali Niknejad, Chenming Hu. * Project Director: Prof. Chenming Hu. - * Modified by Xuemei Xi, 10/05/2001. **********/ #include "ngspice.h" -#include #include "cktdefs.h" #include "complex.h" #include "sperror.h" #include "bsim4def.h" +#include "suffix.h" int BSIM4pzLoad(inModel,ckt,s) @@ -29,7 +28,7 @@ BSIM4instance *here; double gjbd, gjbs, geltd, gcrg, gcrgg, gcrgd, gcrgs, gcrgb; double xcggb, xcgdb, xcgsb, xcgbb, xcbgb, xcbdb, xcbsb, xcbbb; double xcdgb, xcddb, xcdsb, xcdbb, xcsgb, xcsdb, xcssb, xcsbb; -double gds, gbd, gbs, capbd, capbs, FwdSum, RevSum, Gm, Gmbs; +double gds, capbd, capbs, FwdSum, RevSum, Gm, Gmbs; double gstot, gstotd, gstotg, gstots, gstotb, gspr; double gdtot, gdtotd, gdtotg, gdtots, gdtotb, gdpr; double gIstotg, gIstotd, gIstots, gIstotb; @@ -37,24 +36,25 @@ double gIdtotg, gIdtotd, gIdtots, gIdtotb; double gIbtotg, gIbtotd, gIbtots, gIbtotb; double gIgtotg, gIgtotd, gIgtots, gIgtotb; double cgso, cgdo, cgbo; -double xcdbdb, xcsbsb, xcgmgmb, xcgmdb, xcgmsb, xcdgmb, xcsgmb; -double xcgmbb, xcbgmb; -double dxpart, sxpart, xgtg, xgtd, xgts, xgtb, xcqgb, xcqdb, xcqsb, xcqbb; +double xcdbdb=0.0, xcsbsb=0.0, xcgmgmb=0.0, xcgmdb=0.0, xcgmsb=0.0, xcdgmb=0.0, xcsgmb=0.0; +double xcgmbb=0.0, xcbgmb=0.0; +double dxpart, sxpart, xgtg, xgtd, xgts, xgtb, xcqgb=0.0, xcqdb=0.0, xcqsb=0.0, xcqbb=0.0; double gbspsp, gbbdp, gbbsp, gbspg, gbspb; double gbspdp, gbdpdp, gbdpg, gbdpb, gbdpsp; double ddxpart_dVd, ddxpart_dVg, ddxpart_dVb, ddxpart_dVs; double dsxpart_dVd, dsxpart_dVg, dsxpart_dVb, dsxpart_dVs; -double T0, T1, CoxWL, qcheq, Cdg, Cdd, Cds, Cdb, Csg, Csd, Css, Csb; +double T0=0.0, T1, CoxWL, qcheq, Cdg, Cdd, Cds, Csg, Csd, Css; double ScalingFactor = 1.0e-9; struct bsim4SizeDependParam *pParam; -double ggidld, ggidlg, ggidlb,ggisld, ggislg, ggislb, ggisls; +double ggidld, ggidlg, ggidlb, ggislg, ggislb, ggisls; +double m; for (; model != NULL; model = model->BSIM4nextModel) { for (here = model->BSIM4instances; here!= NULL; here = here->BSIM4nextInstance) - { if (here->BSIM4owner != ARCHme) continue; - pParam = here->pParam; + { if (here->BSIM4owner != ARCHme) continue; + pParam = here->pParam; capbd = here->BSIM4capbd; capbs = here->BSIM4capbs; cgso = here->BSIM4cgso; @@ -483,6 +483,7 @@ double ggidld, ggidlg, ggidlb,ggisld, ggislg, ggislb, ggisls; /* * Loading PZ matrix */ + m = here->BSIM4m; if (!model->BSIM4rdsMod) { gdpr = here->BSIM4drainConductance; @@ -501,165 +502,165 @@ double ggidld, ggidlg, ggidlb,ggisld, ggislg, ggislb, ggisls; geltd = here->BSIM4grgeltd; if (here->BSIM4rgateMod == 1) - { *(here->BSIM4GEgePtr) += geltd; - *(here->BSIM4GPgePtr) -= geltd; - *(here->BSIM4GEgpPtr) -= geltd; + { *(here->BSIM4GEgePtr) += m * geltd; + *(here->BSIM4GPgePtr) -= m * geltd; + *(here->BSIM4GEgpPtr) -= m * geltd; - *(here->BSIM4GPgpPtr ) += xcggb * s->real; - *(here->BSIM4GPgpPtr +1) += xcggb * s->imag; - *(here->BSIM4GPgpPtr) += geltd - xgtg + gIgtotg; - *(here->BSIM4GPdpPtr ) += xcgdb * s->real; - *(here->BSIM4GPdpPtr +1) += xcgdb * s->imag; - *(here->BSIM4GPdpPtr) -= xgtd - gIgtotd; - *(here->BSIM4GPspPtr ) += xcgsb * s->real; - *(here->BSIM4GPspPtr +1) += xcgsb * s->imag; - *(here->BSIM4GPspPtr) -= xgts - gIgtots; - *(here->BSIM4GPbpPtr ) += xcgbb * s->real; - *(here->BSIM4GPbpPtr +1) += xcgbb * s->imag; - *(here->BSIM4GPbpPtr) -= xgtb - gIgtotb; + *(here->BSIM4GPgpPtr ) += m * xcggb * s->real; + *(here->BSIM4GPgpPtr +1) += m * xcggb * s->imag; + *(here->BSIM4GPgpPtr) += m * (geltd - xgtg + gIgtotg); + *(here->BSIM4GPdpPtr ) += m * xcgdb * s->real; + *(here->BSIM4GPdpPtr +1) += m * xcgdb * s->imag; + *(here->BSIM4GPdpPtr) -= m * (xgtd - gIgtotd); + *(here->BSIM4GPspPtr ) += m * xcgsb * s->real; + *(here->BSIM4GPspPtr +1) += m * xcgsb * s->imag; + *(here->BSIM4GPspPtr) -= m * (xgts - gIgtots); + *(here->BSIM4GPbpPtr ) += m * xcgbb * s->real; + *(here->BSIM4GPbpPtr +1) += m * xcgbb * s->imag; + *(here->BSIM4GPbpPtr) -= m * (xgtb - gIgtotb); } else if (here->BSIM4rgateMod == 2) - { *(here->BSIM4GEgePtr) += gcrg; - *(here->BSIM4GEgpPtr) += gcrgg; - *(here->BSIM4GEdpPtr) += gcrgd; - *(here->BSIM4GEspPtr) += gcrgs; - *(here->BSIM4GEbpPtr) += gcrgb; + { *(here->BSIM4GEgePtr) += m * gcrg; + *(here->BSIM4GEgpPtr) += m * gcrgg; + *(here->BSIM4GEdpPtr) += m * gcrgd; + *(here->BSIM4GEspPtr) += m * gcrgs; + *(here->BSIM4GEbpPtr) += m * gcrgb; - *(here->BSIM4GPgePtr) -= gcrg; - *(here->BSIM4GPgpPtr ) += xcggb * s->real; - *(here->BSIM4GPgpPtr +1) += xcggb * s->imag; - *(here->BSIM4GPgpPtr) -= gcrgg + xgtg - gIgtotg; - *(here->BSIM4GPdpPtr ) += xcgdb * s->real; - *(here->BSIM4GPdpPtr +1) += xcgdb * s->imag; - *(here->BSIM4GPdpPtr) -= gcrgd + xgtd - gIgtotd; - *(here->BSIM4GPspPtr ) += xcgsb * s->real; - *(here->BSIM4GPspPtr +1) += xcgsb * s->imag; - *(here->BSIM4GPspPtr) -= gcrgs + xgts - gIgtots; - *(here->BSIM4GPbpPtr ) += xcgbb * s->real; - *(here->BSIM4GPbpPtr +1) += xcgbb * s->imag; - *(here->BSIM4GPbpPtr) -= gcrgb + xgtb - gIgtotb; + *(here->BSIM4GPgePtr) -= m * gcrg; + *(here->BSIM4GPgpPtr ) += m * xcggb * s->real; + *(here->BSIM4GPgpPtr +1) += m * xcggb * s->imag; + *(here->BSIM4GPgpPtr) -= m * (gcrgg + xgtg - gIgtotg); + *(here->BSIM4GPdpPtr ) += m * xcgdb * s->real; + *(here->BSIM4GPdpPtr +1) += m * xcgdb * s->imag; + *(here->BSIM4GPdpPtr) -= m * (gcrgd + xgtd - gIgtotd); + *(here->BSIM4GPspPtr ) += m * xcgsb * s->real; + *(here->BSIM4GPspPtr +1) += m * xcgsb * s->imag; + *(here->BSIM4GPspPtr) -= m * (gcrgs + xgts - gIgtots); + *(here->BSIM4GPbpPtr ) += m * xcgbb * s->real; + *(here->BSIM4GPbpPtr +1) += m * xcgbb * s->imag; + *(here->BSIM4GPbpPtr) -= m * (gcrgb + xgtb - gIgtotb); } else if (here->BSIM4rgateMod == 3) - { *(here->BSIM4GEgePtr) += geltd; - *(here->BSIM4GEgmPtr) -= geltd; - *(here->BSIM4GMgePtr) -= geltd; - *(here->BSIM4GMgmPtr) += geltd + gcrg; - *(here->BSIM4GMgmPtr ) += xcgmgmb * s->real; - *(here->BSIM4GMgmPtr +1) += xcgmgmb * s->imag; + { *(here->BSIM4GEgePtr) += m * geltd; + *(here->BSIM4GEgmPtr) -= m * geltd; + *(here->BSIM4GMgePtr) -= m * geltd; + *(here->BSIM4GMgmPtr) += m * (geltd + gcrg); + *(here->BSIM4GMgmPtr ) += m * xcgmgmb * s->real; + *(here->BSIM4GMgmPtr +1) += m * xcgmgmb * s->imag; - *(here->BSIM4GMdpPtr) += gcrgd; - *(here->BSIM4GMdpPtr ) += xcgmdb * s->real; - *(here->BSIM4GMdpPtr +1) += xcgmdb * s->imag; - *(here->BSIM4GMgpPtr) += gcrgg; - *(here->BSIM4GMspPtr) += gcrgs; - *(here->BSIM4GMspPtr ) += xcgmsb * s->real; - *(here->BSIM4GMspPtr +1) += xcgmsb * s->imag; - *(here->BSIM4GMbpPtr) += gcrgb; - *(here->BSIM4GMbpPtr ) += xcgmbb * s->real; - *(here->BSIM4GMbpPtr +1) += xcgmbb * s->imag; + *(here->BSIM4GMdpPtr) += m * gcrgd; + *(here->BSIM4GMdpPtr ) += m * xcgmdb * s->real; + *(here->BSIM4GMdpPtr +1) += m * xcgmdb * s->imag; + *(here->BSIM4GMgpPtr) += m * gcrgg; + *(here->BSIM4GMspPtr) += m * gcrgs; + *(here->BSIM4GMspPtr ) += m * xcgmsb * s->real; + *(here->BSIM4GMspPtr +1) += m * xcgmsb * s->imag; + *(here->BSIM4GMbpPtr) += m * gcrgb; + *(here->BSIM4GMbpPtr ) += m * xcgmbb * s->real; + *(here->BSIM4GMbpPtr +1) += m * xcgmbb * s->imag; - *(here->BSIM4DPgmPtr ) += xcdgmb * s->real; - *(here->BSIM4DPgmPtr +1) += xcdgmb * s->imag; - *(here->BSIM4GPgmPtr) -= gcrg; - *(here->BSIM4SPgmPtr ) += xcsgmb * s->real; - *(here->BSIM4SPgmPtr +1) += xcsgmb * s->imag; - *(here->BSIM4BPgmPtr ) += xcbgmb * s->real; - *(here->BSIM4BPgmPtr +1) += xcbgmb * s->imag; + *(here->BSIM4DPgmPtr ) += m * xcdgmb * s->real; + *(here->BSIM4DPgmPtr +1) += m * xcdgmb * s->imag; + *(here->BSIM4GPgmPtr) -= m * gcrg; + *(here->BSIM4SPgmPtr ) += m * xcsgmb * s->real; + *(here->BSIM4SPgmPtr +1) += m * xcsgmb * s->imag; + *(here->BSIM4BPgmPtr ) += m * xcbgmb * s->real; + *(here->BSIM4BPgmPtr +1) += m * xcbgmb * s->imag; - *(here->BSIM4GPgpPtr) -= gcrgg + xgtg - gIgtotg; - *(here->BSIM4GPgpPtr ) += xcggb * s->real; - *(here->BSIM4GPgpPtr +1) += xcggb * s->imag; - *(here->BSIM4GPdpPtr) -= gcrgd + xgtd - gIgtotd; - *(here->BSIM4GPdpPtr ) += xcgdb * s->real; - *(here->BSIM4GPdpPtr +1) += xcgdb * s->imag; - *(here->BSIM4GPspPtr) -= gcrgs + xgts - gIgtots; - *(here->BSIM4GPspPtr ) += xcgsb * s->real; - *(here->BSIM4GPspPtr +1) += xcgsb * s->imag; - *(here->BSIM4GPbpPtr) -= gcrgb + xgtb - gIgtotb; - *(here->BSIM4GPbpPtr ) += xcgbb * s->real; - *(here->BSIM4GPbpPtr +1) += xcgbb * s->imag; + *(here->BSIM4GPgpPtr) -= m * (gcrgg + xgtg - gIgtotg); + *(here->BSIM4GPgpPtr ) += m * xcggb * s->real; + *(here->BSIM4GPgpPtr +1) += m * xcggb * s->imag; + *(here->BSIM4GPdpPtr) -= m * (gcrgd + xgtd - gIgtotd); + *(here->BSIM4GPdpPtr ) += m * xcgdb * s->real; + *(here->BSIM4GPdpPtr +1) += m * xcgdb * s->imag; + *(here->BSIM4GPspPtr) -= m * (gcrgs + xgts - gIgtots); + *(here->BSIM4GPspPtr ) += m * xcgsb * s->real; + *(here->BSIM4GPspPtr +1) += m * xcgsb * s->imag; + *(here->BSIM4GPbpPtr) -= m * (gcrgb + xgtb - gIgtotb); + *(here->BSIM4GPbpPtr ) += m * xcgbb * s->real; + *(here->BSIM4GPbpPtr +1) += m * xcgbb * s->imag; } else - { *(here->BSIM4GPdpPtr ) += xcgdb * s->real; - *(here->BSIM4GPdpPtr +1) += xcgdb * s->imag; - *(here->BSIM4GPdpPtr) -= xgtd - gIgtotd; - *(here->BSIM4GPgpPtr ) += xcggb * s->real; - *(here->BSIM4GPgpPtr +1) += xcggb * s->imag; - *(here->BSIM4GPgpPtr) -= xgtg - gIgtotg; - *(here->BSIM4GPspPtr ) += xcgsb * s->real; - *(here->BSIM4GPspPtr +1) += xcgsb * s->imag; - *(here->BSIM4GPspPtr) -= xgts - gIgtots; - *(here->BSIM4GPbpPtr ) += xcgbb * s->real; - *(here->BSIM4GPbpPtr +1) += xcgbb * s->imag; - *(here->BSIM4GPbpPtr) -= xgtb - gIgtotb; + { *(here->BSIM4GPdpPtr ) += m * xcgdb * s->real; + *(here->BSIM4GPdpPtr +1) += m * xcgdb * s->imag; + *(here->BSIM4GPdpPtr) -= m * (xgtd - gIgtotd); + *(here->BSIM4GPgpPtr ) += m * xcggb * s->real; + *(here->BSIM4GPgpPtr +1) += m * xcggb * s->imag; + *(here->BSIM4GPgpPtr) -= m * (xgtg - gIgtotg); + *(here->BSIM4GPspPtr ) += m * xcgsb * s->real; + *(here->BSIM4GPspPtr +1) += m * xcgsb * s->imag; + *(here->BSIM4GPspPtr) -= m * (xgts - gIgtots); + *(here->BSIM4GPbpPtr ) += m * xcgbb * s->real; + *(here->BSIM4GPbpPtr +1) += m * xcgbb * s->imag; + *(here->BSIM4GPbpPtr) -= m * (xgtb - gIgtotb); } if (model->BSIM4rdsMod) - { (*(here->BSIM4DgpPtr) += gdtotg); - (*(here->BSIM4DspPtr) += gdtots); - (*(here->BSIM4DbpPtr) += gdtotb); - (*(here->BSIM4SdpPtr) += gstotd); - (*(here->BSIM4SgpPtr) += gstotg); - (*(here->BSIM4SbpPtr) += gstotb); + { (*(here->BSIM4DgpPtr) += m * gdtotg); + (*(here->BSIM4DspPtr) += m * gdtots); + (*(here->BSIM4DbpPtr) += m * gdtotb); + (*(here->BSIM4SdpPtr) += m * gstotd); + (*(here->BSIM4SgpPtr) += m * gstotg); + (*(here->BSIM4SbpPtr) += m * gstotb); } - *(here->BSIM4DPdpPtr ) += xcddb * s->real; - *(here->BSIM4DPdpPtr +1) += xcddb * s->imag; - *(here->BSIM4DPdpPtr) += gdpr + gds + here->BSIM4gbd + *(here->BSIM4DPdpPtr ) += m * xcddb * s->real; + *(here->BSIM4DPdpPtr +1) += m * xcddb * s->imag; + *(here->BSIM4DPdpPtr) += m * (gdpr + gds + here->BSIM4gbd - gdtotd + RevSum + gbdpdp - gIdtotd - + dxpart * xgtd + T1 * ddxpart_dVd; - *(here->BSIM4DPdPtr) -= gdpr + gdtot; - *(here->BSIM4DPgpPtr ) += xcdgb * s->real; - *(here->BSIM4DPgpPtr +1) += xcdgb * s->imag; - *(here->BSIM4DPgpPtr) += Gm - gdtotg + gbdpg - gIdtotg - + T1 * ddxpart_dVg + dxpart * xgtg; - *(here->BSIM4DPspPtr ) += xcdsb * s->real; - *(here->BSIM4DPspPtr +1) += xcdsb * s->imag; - *(here->BSIM4DPspPtr) -= gds + FwdSum + gdtots - gbdpsp + gIdtots - - T1 * ddxpart_dVs - dxpart * xgts; - *(here->BSIM4DPbpPtr ) += xcdbb * s->real; - *(here->BSIM4DPbpPtr +1) += xcdbb * s->imag; - *(here->BSIM4DPbpPtr) -= gjbd + gdtotb - Gmbs - gbdpb + gIdtotb - - T1 * ddxpart_dVb - dxpart * xgtb; + + dxpart * xgtd + T1 * ddxpart_dVd); + *(here->BSIM4DPdPtr) -= m * (gdpr + gdtot); + *(here->BSIM4DPgpPtr ) += m * xcdgb * s->real; + *(here->BSIM4DPgpPtr +1) += m * xcdgb * s->imag; + *(here->BSIM4DPgpPtr) += m * (Gm - gdtotg + gbdpg - gIdtotg + + T1 * ddxpart_dVg + dxpart * xgtg); + *(here->BSIM4DPspPtr ) += m * xcdsb * s->real; + *(here->BSIM4DPspPtr +1) += m * xcdsb * s->imag; + *(here->BSIM4DPspPtr) -= m * (gds + FwdSum + gdtots - gbdpsp + gIdtots + - T1 * ddxpart_dVs - dxpart * xgts); + *(here->BSIM4DPbpPtr ) += m * xcdbb * s->real; + *(here->BSIM4DPbpPtr +1) += m * xcdbb * s->imag; + *(here->BSIM4DPbpPtr) -= m * (gjbd + gdtotb - Gmbs - gbdpb + gIdtotb + - T1 * ddxpart_dVb - dxpart * xgtb); - *(here->BSIM4DdpPtr) -= gdpr - gdtotd; - *(here->BSIM4DdPtr) += gdpr + gdtot; + *(here->BSIM4DdpPtr) -= m * (gdpr - gdtotd); + *(here->BSIM4DdPtr) += m * (gdpr + gdtot); - *(here->BSIM4SPdpPtr ) += xcsdb * s->real; - *(here->BSIM4SPdpPtr +1) += xcsdb * s->imag; - *(here->BSIM4SPdpPtr) -= gds + gstotd + RevSum - gbspdp + gIstotd - - T1 * dsxpart_dVd - sxpart * xgtd; - *(here->BSIM4SPgpPtr ) += xcsgb * s->real; - *(here->BSIM4SPgpPtr +1) += xcsgb * s->imag; - *(here->BSIM4SPgpPtr) -= Gm + gstotg - gbspg + gIstotg - - T1 * dsxpart_dVg - sxpart * xgtg; - *(here->BSIM4SPspPtr ) += xcssb * s->real; - *(here->BSIM4SPspPtr +1) += xcssb * s->imag; - *(here->BSIM4SPspPtr) += gspr + gds + here->BSIM4gbs - gIstots + *(here->BSIM4SPdpPtr ) += m * xcsdb * s->real; + *(here->BSIM4SPdpPtr +1) += m * xcsdb * s->imag; + *(here->BSIM4SPdpPtr) -= m * (gds + gstotd + RevSum - gbspdp + gIstotd + - T1 * dsxpart_dVd - sxpart * xgtd); + *(here->BSIM4SPgpPtr ) += m * xcsgb * s->real; + *(here->BSIM4SPgpPtr +1) += m * xcsgb * s->imag; + *(here->BSIM4SPgpPtr) -= m * (Gm + gstotg - gbspg + gIstotg + - T1 * dsxpart_dVg - sxpart * xgtg); + *(here->BSIM4SPspPtr ) += m * xcssb * s->real; + *(here->BSIM4SPspPtr +1) += m * xcssb * s->imag; + *(here->BSIM4SPspPtr) += m * (gspr + gds + here->BSIM4gbs - gIstots - gstots + FwdSum + gbspsp - + sxpart * xgts + T1 * dsxpart_dVs; - *(here->BSIM4SPsPtr) -= gspr + gstot; - *(here->BSIM4SPbpPtr ) += xcsbb * s->real; - *(here->BSIM4SPbpPtr +1) += xcsbb * s->imag; - *(here->BSIM4SPbpPtr) -= gjbs + gstotb + Gmbs - gbspb + gIstotb - - T1 * dsxpart_dVb - sxpart * xgtb; + + sxpart * xgts + T1 * dsxpart_dVs); + *(here->BSIM4SPsPtr) -= m * (gspr + gstot); + *(here->BSIM4SPbpPtr ) += m * xcsbb * s->real; + *(here->BSIM4SPbpPtr +1) += m * xcsbb * s->imag; + *(here->BSIM4SPbpPtr) -= m * (gjbs + gstotb + Gmbs - gbspb + gIstotb + - T1 * dsxpart_dVb - sxpart * xgtb); - *(here->BSIM4SspPtr) -= gspr - gstots; - *(here->BSIM4SsPtr) += gspr + gstot; + *(here->BSIM4SspPtr) -= m * (gspr - gstots); + *(here->BSIM4SsPtr) += m * (gspr + gstot); - *(here->BSIM4BPdpPtr ) += xcbdb * s->real; - *(here->BSIM4BPdpPtr +1) += xcbdb * s->imag; - *(here->BSIM4BPdpPtr) -= gjbd - gbbdp + gIbtotd; - *(here->BSIM4BPgpPtr ) += xcbgb * s->real; - *(here->BSIM4BPgpPtr +1) += xcbgb * s->imag; - *(here->BSIM4BPgpPtr) -= here->BSIM4gbgs + gIbtotg; - *(here->BSIM4BPspPtr ) += xcbsb * s->real; - *(here->BSIM4BPspPtr +1) += xcbsb * s->imag; - *(here->BSIM4BPspPtr) -= gjbs - gbbsp + gIbtots; - *(here->BSIM4BPbpPtr ) += xcbbb * s->real; - *(here->BSIM4BPbpPtr +1) += xcbbb * s->imag; - *(here->BSIM4BPbpPtr) += gjbd + gjbs - here->BSIM4gbbs - - gIbtotb; + *(here->BSIM4BPdpPtr ) += m * xcbdb * s->real; + *(here->BSIM4BPdpPtr +1) += m * xcbdb * s->imag; + *(here->BSIM4BPdpPtr) -= m * (gjbd - gbbdp + gIbtotd); + *(here->BSIM4BPgpPtr ) += m * xcbgb * s->real; + *(here->BSIM4BPgpPtr +1) += m * xcbgb * s->imag; + *(here->BSIM4BPgpPtr) -= m * (here->BSIM4gbgs + gIbtotg); + *(here->BSIM4BPspPtr ) += m * xcbsb * s->real; + *(here->BSIM4BPspPtr +1) += m * xcbsb * s->imag; + *(here->BSIM4BPspPtr) -= m * (gjbs - gbbsp + gIbtots); + *(here->BSIM4BPbpPtr ) += m * xcbbb * s->real; + *(here->BSIM4BPbpPtr +1) += m * xcbbb * s->imag; + *(here->BSIM4BPbpPtr) += m * (gjbd + gjbs - here->BSIM4gbbs + - gIbtotb); ggidld = here->BSIM4ggidld; ggidlg = here->BSIM4ggidlg; ggidlb = here->BSIM4ggidlb; @@ -668,87 +669,87 @@ double ggidld, ggidlg, ggidlb,ggisld, ggislg, ggislb, ggisls; ggislb = here->BSIM4ggislb; /* stamp gidl */ - (*(here->BSIM4DPdpPtr) += ggidld); - (*(here->BSIM4DPgpPtr) += ggidlg); - (*(here->BSIM4DPspPtr) -= (ggidlg + ggidld) + ggidlb); - (*(here->BSIM4DPbpPtr) += ggidlb); - (*(here->BSIM4BPdpPtr) -= ggidld); - (*(here->BSIM4BPgpPtr) -= ggidlg); - (*(here->BSIM4BPspPtr) += (ggidlg + ggidld) + ggidlb); - (*(here->BSIM4BPbpPtr) -= ggidlb); + (*(here->BSIM4DPdpPtr) += m * ggidld); + (*(here->BSIM4DPgpPtr) += m * ggidlg); + (*(here->BSIM4DPspPtr) -= m * ((ggidlg + ggidld) + ggidlb)); + (*(here->BSIM4DPbpPtr) += m * ggidlb); + (*(here->BSIM4BPdpPtr) -= m * ggidld); + (*(here->BSIM4BPgpPtr) -= m * ggidlg); + (*(here->BSIM4BPspPtr) += m * ((ggidlg + ggidld) + ggidlb)); + (*(here->BSIM4BPbpPtr) -= m * ggidlb); /* stamp gisl */ - (*(here->BSIM4SPdpPtr) -= (ggisls + ggislg) + ggislb); - (*(here->BSIM4SPgpPtr) += ggislg); - (*(here->BSIM4SPspPtr) += ggisls); - (*(here->BSIM4SPbpPtr) += ggislb); - (*(here->BSIM4BPdpPtr) += (ggislg + ggisls) + ggislb); - (*(here->BSIM4BPgpPtr) -= ggislg); - (*(here->BSIM4BPspPtr) -= ggisls); - (*(here->BSIM4BPbpPtr) -= ggislb); + (*(here->BSIM4SPdpPtr) -= m * ((ggisls + ggislg) + ggislb)); + (*(here->BSIM4SPgpPtr) += m * ggislg); + (*(here->BSIM4SPspPtr) += m * ggisls); + (*(here->BSIM4SPbpPtr) += m * ggislb); + (*(here->BSIM4BPdpPtr) += m * ((ggislg + ggisls) + ggislb)); + (*(here->BSIM4BPgpPtr) -= m * ggislg); + (*(here->BSIM4BPspPtr) -= m * ggisls); + (*(here->BSIM4BPbpPtr) -= m * ggislb); if (here->BSIM4rbodyMod) - { (*(here->BSIM4DPdbPtr ) += xcdbdb * s->real); - (*(here->BSIM4DPdbPtr +1) += xcdbdb * s->imag); - (*(here->BSIM4DPdbPtr) -= here->BSIM4gbd); - (*(here->BSIM4SPsbPtr ) += xcsbsb * s->real); - (*(here->BSIM4SPsbPtr +1) += xcsbsb * s->imag); - (*(here->BSIM4SPsbPtr) -= here->BSIM4gbs); + { (*(here->BSIM4DPdbPtr ) += m * xcdbdb * s->real); + (*(here->BSIM4DPdbPtr +1) += m * xcdbdb * s->imag); + (*(here->BSIM4DPdbPtr) -= m * here->BSIM4gbd); + (*(here->BSIM4SPsbPtr ) += m * xcsbsb * s->real); + (*(here->BSIM4SPsbPtr +1) += m * xcsbsb * s->imag); + (*(here->BSIM4SPsbPtr) -= m * here->BSIM4gbs); - (*(here->BSIM4DBdpPtr ) += xcdbdb * s->real); - (*(here->BSIM4DBdpPtr +1) += xcdbdb * s->imag); - (*(here->BSIM4DBdpPtr) -= here->BSIM4gbd); - (*(here->BSIM4DBdbPtr ) -= xcdbdb * s->real); - (*(here->BSIM4DBdbPtr +1) -= xcdbdb * s->imag); - (*(here->BSIM4DBdbPtr) += here->BSIM4gbd + here->BSIM4grbpd - + here->BSIM4grbdb); - (*(here->BSIM4DBbpPtr) -= here->BSIM4grbpd); - (*(here->BSIM4DBbPtr) -= here->BSIM4grbdb); + (*(here->BSIM4DBdpPtr ) += m * xcdbdb * s->real); + (*(here->BSIM4DBdpPtr +1) += m * xcdbdb * s->imag); + (*(here->BSIM4DBdpPtr) -= m * here->BSIM4gbd); + (*(here->BSIM4DBdbPtr ) -= m * xcdbdb * s->real); + (*(here->BSIM4DBdbPtr +1) -= m * xcdbdb * s->imag); + (*(here->BSIM4DBdbPtr) += m * (here->BSIM4gbd + here->BSIM4grbpd + + here->BSIM4grbdb)); + (*(here->BSIM4DBbpPtr) -= m * here->BSIM4grbpd); + (*(here->BSIM4DBbPtr) -= m * here->BSIM4grbdb); - (*(here->BSIM4BPdbPtr) -= here->BSIM4grbpd); - (*(here->BSIM4BPbPtr) -= here->BSIM4grbpb); - (*(here->BSIM4BPsbPtr) -= here->BSIM4grbps); - (*(here->BSIM4BPbpPtr) += here->BSIM4grbpd + here->BSIM4grbps - + here->BSIM4grbpb); + (*(here->BSIM4BPdbPtr) -= m * here->BSIM4grbpd); + (*(here->BSIM4BPbPtr) -= m * here->BSIM4grbpb); + (*(here->BSIM4BPsbPtr) -= m * here->BSIM4grbps); + (*(here->BSIM4BPbpPtr) += m * (here->BSIM4grbpd + here->BSIM4grbps + + here->BSIM4grbpb)); /* WDL: (-here->BSIM4gbbs) already added to BPbpPtr */ - (*(here->BSIM4SBspPtr ) += xcsbsb * s->real); - (*(here->BSIM4SBspPtr +1) += xcsbsb * s->imag); - (*(here->BSIM4SBspPtr) -= here->BSIM4gbs); - (*(here->BSIM4SBbpPtr) -= here->BSIM4grbps); - (*(here->BSIM4SBbPtr) -= here->BSIM4grbsb); - (*(here->BSIM4SBsbPtr ) -= xcsbsb * s->real); - (*(here->BSIM4SBsbPtr +1) -= xcsbsb * s->imag); - (*(here->BSIM4SBsbPtr) += here->BSIM4gbs - + here->BSIM4grbps + here->BSIM4grbsb); + (*(here->BSIM4SBspPtr ) += m * xcsbsb * s->real); + (*(here->BSIM4SBspPtr +1) += m * xcsbsb * s->imag); + (*(here->BSIM4SBspPtr) -= m * here->BSIM4gbs); + (*(here->BSIM4SBbpPtr) -= m * here->BSIM4grbps); + (*(here->BSIM4SBbPtr) -= m * here->BSIM4grbsb); + (*(here->BSIM4SBsbPtr ) -= m * xcsbsb * s->real); + (*(here->BSIM4SBsbPtr +1) -= m * xcsbsb * s->imag); + (*(here->BSIM4SBsbPtr) += m * (here->BSIM4gbs + + here->BSIM4grbps + here->BSIM4grbsb)); - (*(here->BSIM4BdbPtr) -= here->BSIM4grbdb); - (*(here->BSIM4BbpPtr) -= here->BSIM4grbpb); - (*(here->BSIM4BsbPtr) -= here->BSIM4grbsb); - (*(here->BSIM4BbPtr) += here->BSIM4grbsb + here->BSIM4grbdb - + here->BSIM4grbpb); + (*(here->BSIM4BdbPtr) -= m * here->BSIM4grbdb); + (*(here->BSIM4BbpPtr) -= m * here->BSIM4grbpb); + (*(here->BSIM4BsbPtr) -= m * here->BSIM4grbsb); + (*(here->BSIM4BbPtr) += m * (here->BSIM4grbsb + here->BSIM4grbdb + + here->BSIM4grbpb)); } if (here->BSIM4acnqsMod) - { *(here->BSIM4QqPtr ) += s->real * ScalingFactor; - *(here->BSIM4QqPtr +1) += s->imag * ScalingFactor; - *(here->BSIM4QgpPtr ) -= xcqgb * s->real; - *(here->BSIM4QgpPtr +1) -= xcqgb * s->imag; - *(here->BSIM4QdpPtr ) -= xcqdb * s->real; - *(here->BSIM4QdpPtr +1) -= xcqdb * s->imag; - *(here->BSIM4QbpPtr ) -= xcqbb * s->real; - *(here->BSIM4QbpPtr +1) -= xcqbb * s->imag; - *(here->BSIM4QspPtr ) -= xcqsb * s->real; - *(here->BSIM4QspPtr +1) -= xcqsb * s->imag; + { *(here->BSIM4QqPtr ) += m * s->real * ScalingFactor; + *(here->BSIM4QqPtr +1) += m * s->imag * ScalingFactor; + *(here->BSIM4QgpPtr ) -= m * xcqgb * s->real; + *(here->BSIM4QgpPtr +1) -= m * xcqgb * s->imag; + *(here->BSIM4QdpPtr ) -= m * xcqdb * s->real; + *(here->BSIM4QdpPtr +1) -= m * xcqdb * s->imag; + *(here->BSIM4QbpPtr ) -= m * xcqbb * s->real; + *(here->BSIM4QbpPtr +1) -= m * xcqbb * s->imag; + *(here->BSIM4QspPtr ) -= m * xcqsb * s->real; + *(here->BSIM4QspPtr +1) -= m * xcqsb * s->imag; - *(here->BSIM4GPqPtr) -= here->BSIM4gtau; - *(here->BSIM4DPqPtr) += dxpart * here->BSIM4gtau; - *(here->BSIM4SPqPtr) += sxpart * here->BSIM4gtau; + *(here->BSIM4GPqPtr) -= m * here->BSIM4gtau; + *(here->BSIM4DPqPtr) += m * dxpart * here->BSIM4gtau; + *(here->BSIM4SPqPtr) += m * sxpart * here->BSIM4gtau; - *(here->BSIM4QqPtr) += here->BSIM4gtau; - *(here->BSIM4QgpPtr) += xgtg; - *(here->BSIM4QdpPtr) += xgtd; - *(here->BSIM4QbpPtr) += xgtb; - *(here->BSIM4QspPtr) += xgts; + *(here->BSIM4QqPtr) += m * here->BSIM4gtau; + *(here->BSIM4QgpPtr) += m * xgtg; + *(here->BSIM4QdpPtr) += m * xgtd; + *(here->BSIM4QbpPtr) += m * xgtb; + *(here->BSIM4QspPtr) += m * xgts; } } } diff --git a/src/spicelib/devices/bsim4/b4set.c b/src/spicelib/devices/bsim4/b4set.c index e15e88214..babcd21ad 100644 --- a/src/spicelib/devices/bsim4/b4set.c +++ b/src/spicelib/devices/bsim4/b4set.c @@ -1,18 +1,20 @@ -/**** BSIM4.2.1, Released by Xuemei Xi 10/05/2001 ****/ +/**** BSIM4.5.0 Released by Xuemei (Jane) Xi 07/29/2005 ****/ /********** - * Copyright 2001 Regents of the University of California. All rights reserved. - * File: b4set.c of BSIM4.2.1. + * Copyright 2005 Regents of the University of California. All rights reserved. + * File: b4set.c of BSIM4.5.0. * Author: 2000 Weidong Liu - * Authors: Xuemei Xi, Kanyu M. Cao, Hui Wan, Mansun Chan, Chenming Hu. + * Authors: 2001- Xuemei Xi, Mohan Dunga, Ali Niknejad, Chenming Hu. * Project Director: Prof. Chenming Hu. * Modified by Xuemei Xi, 04/06/2001. * Modified by Xuemei Xi, 10/05/2001. - **********/ + * Modified by Xuemei Xi, 11/15/2002. + * Modified by Xuemei Xi, 05/09/2003. + * Modified by Xuemei Xi, 03/04/2004. + * Modified by Xuemei Xi, Mohan Dunga, 07/29/2005. +**********/ #include "ngspice.h" -#include -#include #include "jobdefs.h" /* Needed because the model searches for noise Analysis */ #include "ftedefs.h" /* " " */ #include "smpdefs.h" @@ -20,7 +22,7 @@ #include "bsim4def.h" #include "const.h" #include "sperror.h" - +#include "suffix.h" #define MAX_EXP 5.834617425e14 #define MIN_EXP 1.713908431e-15 @@ -30,6 +32,11 @@ #define PI 3.141592654 #define Charge_q 1.60219e-19 +int +BSIM4PAeffGeo(double, int, int, double, double, double, double, double *, double *, double *, double *); +int +BSIM4RdseffGeo(double, int, int, int, double, double, double, double, double, int, double *); + int BSIM4setup(matrix,inModel,ckt,states) SMPmatrix *matrix; @@ -41,13 +48,12 @@ BSIM4model *model = (BSIM4model*)inModel; BSIM4instance *here; int error; CKTnode *tmp; -double tmp1, tmp2; int noiseAnalGiven = 0, createNode; /* Criteria for new node creation */ double Rtot, DMCGeff, DMCIeff, DMDGeff; JOB *job; /* Search for a noise analysis request */ - for (job = ((TSKtask *)(ft_curckt->ci_curTask))->jobs;job;job = job->JOBnextJob) { + for (job = ((TSKtask *)ft_curckt->ci_curTask)->jobs;job;job = job->JOBnextJob) { if(strcmp(job->JOBname,"Noise Analysis")==0) { noiseAnalGiven = 1; break; @@ -97,7 +103,7 @@ JOB *job; } if (!model->BSIM4rbodyModGiven) model->BSIM4rbodyMod = 0; - else if ((model->BSIM4rbodyMod != 0) && (model->BSIM4rbodyMod != 1)) + else if ((model->BSIM4rbodyMod != 0) && (model->BSIM4rbodyMod != 1) && (model->BSIM4rbodyMod != 2)) { model->BSIM4rbodyMod = 0; printf("Warning: rbodyMod has been set to its default value: 0.\n"); } @@ -148,7 +154,8 @@ JOB *job; if (!model->BSIM4igcModGiven) model->BSIM4igcMod = 0; - else if ((model->BSIM4igcMod != 0) && (model->BSIM4igcMod != 1)) + else if ((model->BSIM4igcMod != 0) && (model->BSIM4igcMod != 1) + && (model->BSIM4igcMod != 2)) { model->BSIM4igcMod = 0; printf("Warning: igcMod has been set to its default value: 0.\n"); } @@ -158,9 +165,16 @@ JOB *job; { model->BSIM4igbMod = 0; printf("Warning: igbMod has been set to its default value: 0.\n"); } + if (!model->BSIM4tempModGiven) + model->BSIM4tempMod = 0; + else if ((model->BSIM4tempMod != 0) && (model->BSIM4tempMod != 1) + && (model->BSIM4tempMod != 2)) + { model->BSIM4tempMod = 0; + printf("Warning: tempMod has been set to its default value: 0.\n"); + } if (!model->BSIM4versionGiven) - model->BSIM4version = "4.2.1"; + model->BSIM4version = "4.5.0"; if (!model->BSIM4toxrefGiven) model->BSIM4toxref = 30.0e-10; if (!model->BSIM4toxeGiven) @@ -268,6 +282,14 @@ JOB *job; model->BSIM4uc = (model->BSIM4mobMod == 1) ? -0.0465 : -0.0465e-9; if (!model->BSIM4uc1Given) model->BSIM4uc1 = (model->BSIM4mobMod == 1) ? -0.056 : -0.056e-9; + if (!model->BSIM4udGiven) + model->BSIM4ud = 1.0e14; /* unit m**(-2) */ + if (!model->BSIM4ud1Given) + model->BSIM4ud1 = 0.0; + if (!model->BSIM4upGiven) + model->BSIM4up = 0.0; + if (!model->BSIM4lpGiven) + model->BSIM4lp = 1.0e-8; if (!model->BSIM4u0Given) model->BSIM4u0 = (model->BSIM4type == NMOS) ? 0.067 : 0.025; if (!model->BSIM4uteGiven) @@ -304,7 +326,6 @@ JOB *job; model->BSIM4prwg = 1.0; /* in 1/V */ if (!model->BSIM4prwbGiven) model->BSIM4prwb = 0.0; - if (!model->BSIM4prtGiven) if (!model->BSIM4prtGiven) model->BSIM4prt = 0.0; if (!model->BSIM4eta0Given) @@ -340,7 +361,7 @@ JOB *job; if (!model->BSIM4alpha1Given) model->BSIM4alpha1 = 0.0; if (!model->BSIM4beta0Given) - model->BSIM4beta0 = 30.0; + model->BSIM4beta0 = 0.0; if (!model->BSIM4agidlGiven) model->BSIM4agidl = 0.0; if (!model->BSIM4bgidlGiven) @@ -350,27 +371,27 @@ JOB *job; if (!model->BSIM4egidlGiven) model->BSIM4egidl = 0.8; /* V */ if (!model->BSIM4aigcGiven) - model->BSIM4aigc = (model->BSIM4type == NMOS) ? 0.43 : 0.31; + model->BSIM4aigc = (model->BSIM4type == NMOS) ? 1.36e-2 : 9.80e-3; if (!model->BSIM4bigcGiven) - model->BSIM4bigc = (model->BSIM4type == NMOS) ? 0.054 : 0.024; + model->BSIM4bigc = (model->BSIM4type == NMOS) ? 1.71e-3 : 7.59e-4; if (!model->BSIM4cigcGiven) model->BSIM4cigc = (model->BSIM4type == NMOS) ? 0.075 : 0.03; if (!model->BSIM4aigsdGiven) - model->BSIM4aigsd = (model->BSIM4type == NMOS) ? 0.43 : 0.31; + model->BSIM4aigsd = (model->BSIM4type == NMOS) ? 1.36e-2 : 9.80e-3; if (!model->BSIM4bigsdGiven) - model->BSIM4bigsd = (model->BSIM4type == NMOS) ? 0.054 : 0.024; + model->BSIM4bigsd = (model->BSIM4type == NMOS) ? 1.71e-3 : 7.59e-4; if (!model->BSIM4cigsdGiven) model->BSIM4cigsd = (model->BSIM4type == NMOS) ? 0.075 : 0.03; if (!model->BSIM4aigbaccGiven) - model->BSIM4aigbacc = 0.43; + model->BSIM4aigbacc = 1.36e-2; if (!model->BSIM4bigbaccGiven) - model->BSIM4bigbacc = 0.054; + model->BSIM4bigbacc = 1.71e-3; if (!model->BSIM4cigbaccGiven) model->BSIM4cigbacc = 0.075; if (!model->BSIM4aigbinvGiven) - model->BSIM4aigbinv = 0.35; + model->BSIM4aigbinv = 1.11e-2; if (!model->BSIM4bigbinvGiven) - model->BSIM4bigbinv = 0.03; + model->BSIM4bigbinv = 9.49e-4; if (!model->BSIM4cigbinvGiven) model->BSIM4cigbinv = 0.006; if (!model->BSIM4nigcGiven) @@ -403,8 +424,29 @@ JOB *job; model->BSIM4tnoia = 1.5; if (!model->BSIM4tnoibGiven) model->BSIM4tnoib = 3.5; + if (!model->BSIM4rnoiaGiven) + model->BSIM4rnoia = 0.577; + if (!model->BSIM4rnoibGiven) + model->BSIM4rnoib = 0.5164; if (!model->BSIM4ntnoiGiven) model->BSIM4ntnoi = 1.0; + if (!model->BSIM4lambdaGiven) + model->BSIM4lambda = 0.0; + if (!model->BSIM4vtlGiven) + model->BSIM4vtl = 2.0e5; /* unit m/s */ + if (!model->BSIM4xnGiven) + model->BSIM4xn = 3.0; + if (!model->BSIM4lcGiven) + model->BSIM4lc = 5.0e-9; + if (!model->BSIM4vfbsdoffGiven) + model->BSIM4vfbsdoff = 0.0; /* unit v */ + if (!model->BSIM4tvfbsdoffGiven) + model->BSIM4tvfbsdoff = 0.0; + if (!model->BSIM4tvoffGiven) + model->BSIM4tvoff = 0.0; + + if (!model->BSIM4lintnoiGiven) + model->BSIM4lintnoi = 0.0; /* unit m */ if (!model->BSIM4xjbvsGiven) model->BSIM4xjbvs = 1.0; /* no unit */ @@ -414,6 +456,7 @@ JOB *job; model->BSIM4bvs = 10.0; /* V */ if (!model->BSIM4bvdGiven) model->BSIM4bvd = model->BSIM4bvs; + if (!model->BSIM4gbminGiven) model->BSIM4gbmin = 1.0e-12; /* in mho */ if (!model->BSIM4rbdbGiven) @@ -427,6 +470,65 @@ JOB *job; if (!model->BSIM4rbpdGiven) model->BSIM4rbpd = 50.0; + if (!model->BSIM4rbps0Given) + model->BSIM4rbps0 = 50.0; + if (!model->BSIM4rbpslGiven) + model->BSIM4rbpsl = 0.0; + if (!model->BSIM4rbpswGiven) + model->BSIM4rbpsw = 0.0; + if (!model->BSIM4rbpsnfGiven) + model->BSIM4rbpsnf = 0.0; + + if (!model->BSIM4rbpd0Given) + model->BSIM4rbpd0 = 50.0; + if (!model->BSIM4rbpdlGiven) + model->BSIM4rbpdl = 0.0; + if (!model->BSIM4rbpdwGiven) + model->BSIM4rbpdw = 0.0; + if (!model->BSIM4rbpdnfGiven) + model->BSIM4rbpdnf = 0.0; + + if (!model->BSIM4rbpbx0Given) + model->BSIM4rbpbx0 = 100.0; + if (!model->BSIM4rbpbxlGiven) + model->BSIM4rbpbxl = 0.0; + if (!model->BSIM4rbpbxwGiven) + model->BSIM4rbpbxw = 0.0; + if (!model->BSIM4rbpbxnfGiven) + model->BSIM4rbpbxnf = 0.0; + if (!model->BSIM4rbpby0Given) + model->BSIM4rbpby0 = 100.0; + if (!model->BSIM4rbpbylGiven) + model->BSIM4rbpbyl = 0.0; + if (!model->BSIM4rbpbywGiven) + model->BSIM4rbpbyw = 0.0; + if (!model->BSIM4rbpbynfGiven) + model->BSIM4rbpbynf = 0.0; + + + if (!model->BSIM4rbsbx0Given) + model->BSIM4rbsbx0 = 100.0; + if (!model->BSIM4rbsby0Given) + model->BSIM4rbsby0 = 100.0; + if (!model->BSIM4rbdbx0Given) + model->BSIM4rbdbx0 = 100.0; + if (!model->BSIM4rbdby0Given) + model->BSIM4rbdby0 = 100.0; + + + if (!model->BSIM4rbsdbxlGiven) + model->BSIM4rbsdbxl = 0.0; + if (!model->BSIM4rbsdbxwGiven) + model->BSIM4rbsdbxw = 0.0; + if (!model->BSIM4rbsdbxnfGiven) + model->BSIM4rbsdbxnf = 0.0; + if (!model->BSIM4rbsdbylGiven) + model->BSIM4rbsdbyl = 0.0; + if (!model->BSIM4rbsdbywGiven) + model->BSIM4rbsdbyw = 0.0; + if (!model->BSIM4rbsdbynfGiven) + model->BSIM4rbsdbynf = 0.0; + if (!model->BSIM4cgslGiven) model->BSIM4cgsl = 0.0; if (!model->BSIM4cgdlGiven) @@ -534,7 +636,7 @@ JOB *job; if (!model->BSIM4llpe0Given) model->BSIM4llpe0 = 0.0; if (!model->BSIM4llpebGiven) - model->BSIM4llpeb = model->BSIM4llpe0; + model->BSIM4llpeb = 0.0; if (!model->BSIM4ldvtp0Given) model->BSIM4ldvtp0 = 0.0; if (!model->BSIM4ldvtp1Given) @@ -569,6 +671,14 @@ JOB *job; model->BSIM4luc = 0.0; if (!model->BSIM4luc1Given) model->BSIM4luc1 = 0.0; + if (!model->BSIM4ludGiven) + model->BSIM4lud = 0.0; + if (!model->BSIM4lud1Given) + model->BSIM4lud1 = 0.0; + if (!model->BSIM4lupGiven) + model->BSIM4lup = 0.0; + if (!model->BSIM4llpGiven) + model->BSIM4llp = 0.0; if (!model->BSIM4lu0Given) model->BSIM4lu0 = 0.0; if (!model->BSIM4luteGiven) @@ -685,6 +795,19 @@ JOB *job; model->BSIM4leu = 0.0; if (!model->BSIM4lvfbGiven) model->BSIM4lvfb = 0.0; + if (!model->BSIM4llambdaGiven) + model->BSIM4llambda = 0.0; + if (!model->BSIM4lvtlGiven) + model->BSIM4lvtl = 0.0; + if (!model->BSIM4lxnGiven) + model->BSIM4lxn = 0.0; + if (!model->BSIM4lvfbsdoffGiven) + model->BSIM4lvfbsdoff = 0.0; + if (!model->BSIM4ltvfbsdoffGiven) + model->BSIM4ltvfbsdoff = 0.0; + if (!model->BSIM4ltvoffGiven) + model->BSIM4ltvoff = 0.0; + if (!model->BSIM4lcgslGiven) model->BSIM4lcgsl = 0.0; @@ -767,7 +890,7 @@ JOB *job; if (!model->BSIM4wlpe0Given) model->BSIM4wlpe0 = 0.0; if (!model->BSIM4wlpebGiven) - model->BSIM4wlpeb = model->BSIM4wlpe0; + model->BSIM4wlpeb = 0.0; if (!model->BSIM4wdvtp0Given) model->BSIM4wdvtp0 = 0.0; if (!model->BSIM4wdvtp1Given) @@ -802,6 +925,14 @@ JOB *job; model->BSIM4wuc = 0.0; if (!model->BSIM4wuc1Given) model->BSIM4wuc1 = 0.0; + if (!model->BSIM4wudGiven) + model->BSIM4wud = 0.0; + if (!model->BSIM4wud1Given) + model->BSIM4wud1 = 0.0; + if (!model->BSIM4wupGiven) + model->BSIM4wup = 0.0; + if (!model->BSIM4wlpGiven) + model->BSIM4wlp = 0.0; if (!model->BSIM4wu0Given) model->BSIM4wu0 = 0.0; if (!model->BSIM4wuteGiven) @@ -918,6 +1049,18 @@ JOB *job; model->BSIM4weu = 0.0; if (!model->BSIM4wvfbGiven) model->BSIM4wvfb = 0.0; + if (!model->BSIM4wlambdaGiven) + model->BSIM4wlambda = 0.0; + if (!model->BSIM4wvtlGiven) + model->BSIM4wvtl = 0.0; + if (!model->BSIM4wxnGiven) + model->BSIM4wxn = 0.0; + if (!model->BSIM4wvfbsdoffGiven) + model->BSIM4wvfbsdoff = 0.0; + if (!model->BSIM4wtvfbsdoffGiven) + model->BSIM4wtvfbsdoff = 0.0; + if (!model->BSIM4wtvoffGiven) + model->BSIM4wtvoff = 0.0; if (!model->BSIM4wcgslGiven) model->BSIM4wcgsl = 0.0; @@ -1001,7 +1144,7 @@ JOB *job; if (!model->BSIM4plpe0Given) model->BSIM4plpe0 = 0.0; if (!model->BSIM4plpebGiven) - model->BSIM4plpeb = model->BSIM4plpe0; + model->BSIM4plpeb = 0.0; if (!model->BSIM4pdvtp0Given) model->BSIM4pdvtp0 = 0.0; if (!model->BSIM4pdvtp1Given) @@ -1036,6 +1179,14 @@ JOB *job; model->BSIM4puc = 0.0; if (!model->BSIM4puc1Given) model->BSIM4puc1 = 0.0; + if (!model->BSIM4pudGiven) + model->BSIM4pud = 0.0; + if (!model->BSIM4pud1Given) + model->BSIM4pud1 = 0.0; + if (!model->BSIM4pupGiven) + model->BSIM4pup = 0.0; + if (!model->BSIM4plpGiven) + model->BSIM4plp = 0.0; if (!model->BSIM4pu0Given) model->BSIM4pu0 = 0.0; if (!model->BSIM4puteGiven) @@ -1152,6 +1303,18 @@ JOB *job; model->BSIM4peu = 0.0; if (!model->BSIM4pvfbGiven) model->BSIM4pvfb = 0.0; + if (!model->BSIM4plambdaGiven) + model->BSIM4plambda = 0.0; + if (!model->BSIM4pvtlGiven) + model->BSIM4pvtl = 0.0; + if (!model->BSIM4pxnGiven) + model->BSIM4pxn = 0.0; + if (!model->BSIM4pvfbsdoffGiven) + model->BSIM4pvfbsdoff = 0.0; + if (!model->BSIM4ptvfbsdoffGiven) + model->BSIM4ptvfbsdoff = 0.0; + if (!model->BSIM4ptvoffGiven) + model->BSIM4ptvoff = 0.0; if (!model->BSIM4pcgslGiven) model->BSIM4pcgsl = 0.0; @@ -1178,6 +1341,31 @@ JOB *job; if (!model->BSIM4pvoffcvGiven) model->BSIM4pvoffcv = 0.0; + if (!model->BSIM4gamma1Given) + model->BSIM4gamma1 = 0.0; + if (!model->BSIM4lgamma1Given) + model->BSIM4lgamma1 = 0.0; + if (!model->BSIM4wgamma1Given) + model->BSIM4wgamma1 = 0.0; + if (!model->BSIM4pgamma1Given) + model->BSIM4pgamma1 = 0.0; + if (!model->BSIM4gamma2Given) + model->BSIM4gamma2 = 0.0; + if (!model->BSIM4lgamma2Given) + model->BSIM4lgamma2 = 0.0; + if (!model->BSIM4wgamma2Given) + model->BSIM4wgamma2 = 0.0; + if (!model->BSIM4pgamma2Given) + model->BSIM4pgamma2 = 0.0; + if (!model->BSIM4vbxGiven) + model->BSIM4vbx = 0.0; + if (!model->BSIM4lvbxGiven) + model->BSIM4lvbx = 0.0; + if (!model->BSIM4wvbxGiven) + model->BSIM4wvbx = 0.0; + if (!model->BSIM4pvbxGiven) + model->BSIM4pvbx = 0.0; + /* unit degree celcius */ if (!model->BSIM4tnomGiven) model->BSIM4tnom = ckt->CKTnomTemp; @@ -1303,6 +1491,55 @@ JOB *job; if (!model->BSIM4DjctTempExponentGiven) model->BSIM4DjctTempExponent = model->BSIM4SjctTempExponent; + if (!model->BSIM4jtssGiven) + model->BSIM4jtss = 0.0; + if (!model->BSIM4jtsdGiven) + model->BSIM4jtsd = model->BSIM4jtss; + if (!model->BSIM4jtsswsGiven) + model->BSIM4jtssws = 0.0; + if (!model->BSIM4jtsswdGiven) + model->BSIM4jtsswd = model->BSIM4jtssws; + if (!model->BSIM4jtsswgsGiven) + model->BSIM4jtsswgs = 0.0; + if (!model->BSIM4jtsswgdGiven) + model->BSIM4jtsswgd = model->BSIM4jtsswgs; + if (!model->BSIM4njtsGiven) + model->BSIM4njts = 20.0; + if (!model->BSIM4njtsswGiven) + model->BSIM4njtssw = 20.0; + if (!model->BSIM4njtsswgGiven) + model->BSIM4njtsswg = 20.0; + if (!model->BSIM4xtssGiven) + model->BSIM4xtss = 0.02; + if (!model->BSIM4xtsdGiven) + model->BSIM4xtsd = model->BSIM4xtss; + if (!model->BSIM4xtsswsGiven) + model->BSIM4xtssws = 0.02; + if (!model->BSIM4xtsswdGiven) + model->BSIM4xtsswd = model->BSIM4xtssws; + if (!model->BSIM4xtsswgsGiven) + model->BSIM4xtsswgs = 0.02; + if (!model->BSIM4xtsswgdGiven) + model->BSIM4xtsswgd = model->BSIM4xtsswgs; + if (!model->BSIM4tnjtsGiven) + model->BSIM4tnjts = 0.0; + if (!model->BSIM4tnjtsswGiven) + model->BSIM4tnjtssw = 0.0; + if (!model->BSIM4tnjtsswgGiven) + model->BSIM4tnjtsswg = 0.0; + if (!model->BSIM4vtssGiven) + model->BSIM4vtss = 10.0; + if (!model->BSIM4vtsdGiven) + model->BSIM4vtsd = model->BSIM4vtss; + if (!model->BSIM4vtsswsGiven) + model->BSIM4vtssws = 10.0; + if (!model->BSIM4vtsswdGiven) + model->BSIM4vtsswd = model->BSIM4vtssws; + if (!model->BSIM4vtsswgsGiven) + model->BSIM4vtsswgs = 10.0; + if (!model->BSIM4vtsswgdGiven) + model->BSIM4vtsswgd = model->BSIM4vtsswgs; + if (!model->BSIM4oxideTrapDensityAGiven) { if (model->BSIM4type == NMOS) model->BSIM4oxideTrapDensityA = 6.25e41; @@ -1325,6 +1562,89 @@ JOB *job; model->BSIM4af = 1.0; if (!model->BSIM4kfGiven) model->BSIM4kf = 0.0; + + /* stress effect */ + if (!model->BSIM4sarefGiven) + model->BSIM4saref = 1e-6; /* m */ + if (!model->BSIM4sbrefGiven) + model->BSIM4sbref = 1e-6; /* m */ + if (!model->BSIM4wlodGiven) + model->BSIM4wlod = 0; /* m */ + if (!model->BSIM4ku0Given) + model->BSIM4ku0 = 0; /* 1/m */ + if (!model->BSIM4kvsatGiven) + model->BSIM4kvsat = 0; + if (!model->BSIM4kvth0Given) /* m */ + model->BSIM4kvth0 = 0; + if (!model->BSIM4tku0Given) + model->BSIM4tku0 = 0; + if (!model->BSIM4llodku0Given) + model->BSIM4llodku0 = 0; + if (!model->BSIM4wlodku0Given) + model->BSIM4wlodku0 = 0; + if (!model->BSIM4llodvthGiven) + model->BSIM4llodvth = 0; + if (!model->BSIM4wlodvthGiven) + model->BSIM4wlodvth = 0; + if (!model->BSIM4lku0Given) + model->BSIM4lku0 = 0; + if (!model->BSIM4wku0Given) + model->BSIM4wku0 = 0; + if (!model->BSIM4pku0Given) + model->BSIM4pku0 = 0; + if (!model->BSIM4lkvth0Given) + model->BSIM4lkvth0 = 0; + if (!model->BSIM4wkvth0Given) + model->BSIM4wkvth0 = 0; + if (!model->BSIM4pkvth0Given) + model->BSIM4pkvth0 = 0; + if (!model->BSIM4stk2Given) + model->BSIM4stk2 = 0; + if (!model->BSIM4lodk2Given) + model->BSIM4lodk2 = 1.0; + if (!model->BSIM4steta0Given) + model->BSIM4steta0 = 0; + if (!model->BSIM4lodeta0Given) + model->BSIM4lodeta0 = 1.0; + + /* Well Proximity Effect */ + if (!model->BSIM4webGiven) + model->BSIM4web = 0.0; + if (!model->BSIM4wecGiven) + model->BSIM4wec = 0.0; + if (!model->BSIM4kvth0weGiven) + model->BSIM4kvth0we = 0.0; + if (!model->BSIM4k2weGiven) + model->BSIM4k2we = 0.0; + if (!model->BSIM4ku0weGiven) + model->BSIM4ku0we = 0.0; + if (!model->BSIM4screfGiven) + model->BSIM4scref = 1.0E-6; /* m */ + if (!model->BSIM4wpemodGiven) + model->BSIM4wpemod = 0; + else if ((model->BSIM4wpemod != 0) && (model->BSIM4wpemod != 1)) + { model->BSIM4wpemod = 0; + printf("Warning: wpemod has been set to its default value: 0.\n"); + } + if (!model->BSIM4lkvth0weGiven) + model->BSIM4lkvth0we = 0; + if (!model->BSIM4lk2weGiven) + model->BSIM4lk2we = 0; + if (!model->BSIM4lku0weGiven) + model->BSIM4lku0we = 0; + if (!model->BSIM4wkvth0weGiven) + model->BSIM4wkvth0we = 0; + if (!model->BSIM4wk2weGiven) + model->BSIM4wk2we = 0; + if (!model->BSIM4wku0weGiven) + model->BSIM4wku0we = 0; + if (!model->BSIM4pkvth0weGiven) + model->BSIM4pkvth0we = 0; + if (!model->BSIM4pk2weGiven) + model->BSIM4pk2we = 0; + if (!model->BSIM4pku0weGiven) + model->BSIM4pku0we = 0; + DMCGeff = model->BSIM4dmcg - model->BSIM4dmcgt; DMCIeff = model->BSIM4dmci; DMDGeff = model->BSIM4dmdg - model->BSIM4dmcgt; @@ -1335,10 +1655,10 @@ JOB *job; */ for (here = model->BSIM4instances; here != NULL ; - here=here->BSIM4nextInstance) + here=here->BSIM4nextInstance) { - if (here->BSIM4owner == ARCHme) { - /* allocate a chunk of the state vector */ + if (here->BSIM4owner == ARCHme) { + /* allocate a chunk of the state vector */ here->BSIM4states = *states; *states += BSIM4numStates; } @@ -1347,6 +1667,8 @@ JOB *job; here->BSIM4l = 5.0e-6; if (!here->BSIM4wGiven) here->BSIM4w = 5.0e-6; + if (!here->BSIM4mGiven) + here->BSIM4m = 1.0; if (!here->BSIM4nfGiven) here->BSIM4nf = 1.0; if (!here->BSIM4minGiven) @@ -1380,6 +1702,12 @@ JOB *job; here->BSIM4rbps = model->BSIM4rbps; if (!here->BSIM4rbpdGiven) here->BSIM4rbpd = model->BSIM4rbpd; + if (!here->BSIM4delvtoGiven) + here->BSIM4delvto = 0.0; + if (!here->BSIM4xgwGiven) + here->BSIM4xgw = model->BSIM4xgw; + if (!here->BSIM4ngconGiven) + here->BSIM4ngcon = model->BSIM4ngcon; /* Process instance model selectors, some @@ -1387,7 +1715,7 @@ JOB *job; */ if (!here->BSIM4rbodyModGiven) here->BSIM4rbodyMod = model->BSIM4rbodyMod; - else if ((here->BSIM4rbodyMod != 0) && (here->BSIM4rbodyMod != 1)) + else if ((here->BSIM4rbodyMod != 0) && (here->BSIM4rbodyMod != 1) && (here->BSIM4rbodyMod != 2)) { here->BSIM4rbodyMod = model->BSIM4rbodyMod; printf("Warning: rbodyMod has been set to its global value %d.\n", model->BSIM4rbodyMod); @@ -1405,7 +1733,7 @@ JOB *job; if (!here->BSIM4geoModGiven) here->BSIM4geoMod = model->BSIM4geoMod; if (!here->BSIM4rgeoModGiven) - here->BSIM4rgeoMod = 0.0; + here->BSIM4rgeoMod = 0; if (!here->BSIM4trnqsModGiven) here->BSIM4trnqsMod = model->BSIM4trnqsMod; else if ((here->BSIM4trnqsMod != 0) && (here->BSIM4trnqsMod != 1)) @@ -1422,6 +1750,23 @@ JOB *job; model->BSIM4acnqsMod); } + /* stress effect */ + if (!here->BSIM4saGiven) + here->BSIM4sa = 0.0; + if (!here->BSIM4sbGiven) + here->BSIM4sb = 0.0; + if (!here->BSIM4sdGiven) + here->BSIM4sd = 2 * model->BSIM4dmcg; + /* Well Proximity Effect */ + if (!here->BSIM4scaGiven) + here->BSIM4sca = 0.0; + if (!here->BSIM4scbGiven) + here->BSIM4scb = 0.0; + if (!here->BSIM4sccGiven) + here->BSIM4scc = 0.0; + if (!here->BSIM4scGiven) + here->BSIM4sc = 0.0; /* m */ + /* process drain series resistance */ createNode = 0; if ( (model->BSIM4rdsMod != 0) @@ -1437,7 +1782,7 @@ JOB *job; } else if (!here->BSIM4drainSquaresGiven && (here->BSIM4rgeoMod != 0)) { - BSIM4RdseffGeo(here->BSIM4nf, here->BSIM4geoMod, + BSIM4RdseffGeo(here->BSIM4nf*here->BSIM4m, here->BSIM4geoMod, here->BSIM4rgeoMod, here->BSIM4min, here->BSIM4w, model->BSIM4sheetResistance, DMCGeff, DMCIeff, DMDGeff, 0, &Rtot); @@ -1449,6 +1794,16 @@ JOB *job; { error = CKTmkVolt(ckt,&tmp,here->BSIM4name,"drain"); if(error) return(error); here->BSIM4dNodePrime = tmp->number; + if (ckt->CKTcopyNodesets) { + CKTnode *tmpNode; + IFuid tmpName; + if (CKTinst2Node(ckt,here,1,&tmpNode,&tmpName)==OK) { + if (tmpNode->nsGiven) { + tmp->nodeset=tmpNode->nodeset; + tmp->nsGiven=tmpNode->nsGiven; + } + } + } } else { here->BSIM4dNodePrime = here->BSIM4dNode; @@ -1469,7 +1824,7 @@ JOB *job; } else if (!here->BSIM4sourceSquaresGiven && (here->BSIM4rgeoMod != 0)) { - BSIM4RdseffGeo(here->BSIM4nf, here->BSIM4geoMod, + BSIM4RdseffGeo(here->BSIM4nf*here->BSIM4m, here->BSIM4geoMod, here->BSIM4rgeoMod, here->BSIM4min, here->BSIM4w, model->BSIM4sheetResistance, DMCGeff, DMCIeff, DMDGeff, 1, &Rtot); @@ -1481,6 +1836,16 @@ JOB *job; { error = CKTmkVolt(ckt,&tmp,here->BSIM4name,"source"); if(error) return(error); here->BSIM4sNodePrime = tmp->number; + if (ckt->CKTcopyNodesets) { + CKTnode *tmpNode; + IFuid tmpName; + if (CKTinst2Node(ckt,here,3,&tmpNode,&tmpName)==OK) { + if (tmpNode->nsGiven) { + tmp->nodeset=tmpNode->nodeset; + tmp->nsGiven=tmpNode->nsGiven; + } + } + } } else here->BSIM4sNodePrime = here->BSIM4sNode; @@ -1489,15 +1854,15 @@ JOB *job; { error = CKTmkVolt(ckt,&tmp,here->BSIM4name,"gate"); if(error) return(error); here->BSIM4gNodePrime = tmp->number; - if (here->BSIM4rgateMod == 1) - { if (model->BSIM4rshg <= 0.0) - printf("Warning: rshg should be positive for rgateMod = 1.\n"); - } - else if (here->BSIM4rgateMod == 2) - { if (model->BSIM4rshg <= 0.0) - printf("Warning: rshg <= 0.0 for rgateMod = 2!!!\n"); - else if (model->BSIM4xrcrg1 <= 0.0) - printf("Warning: xrcrg1 <= 0.0 for rgateMod = 2!!!\n"); + if (ckt->CKTcopyNodesets) { + CKTnode *tmpNode; + IFuid tmpName; + if (CKTinst2Node(ckt,here,2,&tmpNode,&tmpName)==OK) { + if (tmpNode->nsGiven) { + tmp->nodeset=tmpNode->nodeset; + tmp->nsGiven=tmpNode->nsGiven; + } + } } } else @@ -1507,17 +1872,13 @@ JOB *job; { error = CKTmkVolt(ckt,&tmp,here->BSIM4name,"midgate"); if(error) return(error); here->BSIM4gNodeMid = tmp->number; - if (model->BSIM4rshg <= 0.0) - printf("Warning: rshg should be positive for rgateMod = 3.\n"); - else if (model->BSIM4xrcrg1 <= 0.0) - printf("Warning: xrcrg1 should be positive for rgateMod = 3.\n"); } else here->BSIM4gNodeMid = here->BSIM4gNodeExt; /* internal body nodes for body resistance model */ - if (here->BSIM4rbodyMod) + if ((here->BSIM4rbodyMod ==1) || (here->BSIM4rbodyMod ==2)) { if (here->BSIM4dbNode == 0) { error = CKTmkVolt(ckt,&tmp,here->BSIM4name,"dbody"); if(error) return(error); @@ -1527,6 +1888,16 @@ JOB *job; { error = CKTmkVolt(ckt,&tmp,here->BSIM4name,"body"); if(error) return(error); here->BSIM4bNodePrime = tmp->number; + if (ckt->CKTcopyNodesets) { + CKTnode *tmpNode; + IFuid tmpName; + if (CKTinst2Node(ckt,here,4,&tmpNode,&tmpName)==OK) { + if (tmpNode->nsGiven) { + tmp->nodeset=tmpNode->nodeset; + tmp->nsGiven=tmpNode->nsGiven; + } + } + } } if (here->BSIM4sbNode == 0) { error = CKTmkVolt(ckt,&tmp,here->BSIM4name,"sbody"); @@ -1609,7 +1980,7 @@ if((here->ptr = SMPmakeElt(matrix,here->first,here->second))==(double *)NULL){\ TSTALLOC(BSIM4BPgmPtr, BSIM4bNodePrime, BSIM4gNodeMid) } - if (here->BSIM4rbodyMod) + if ((here->BSIM4rbodyMod ==1) || (here->BSIM4rbodyMod ==2)) { TSTALLOC(BSIM4DPdbPtr, BSIM4dNodePrime, BSIM4dbNode) TSTALLOC(BSIM4SPsbPtr, BSIM4sNodePrime, BSIM4sbNode) @@ -1651,7 +2022,7 @@ BSIM4unsetup(inModel,ckt) GENmodel *inModel; CKTcircuit *ckt; { - +#ifndef HAS_BATCHSIM BSIM4model *model; BSIM4instance *here; @@ -1675,5 +2046,6 @@ BSIM4unsetup(inModel,ckt) } } } +#endif return OK; } diff --git a/src/spicelib/devices/bsim4/b4temp.c b/src/spicelib/devices/bsim4/b4temp.c index c84334d3f..db8034a03 100644 --- a/src/spicelib/devices/bsim4/b4temp.c +++ b/src/spicelib/devices/bsim4/b4temp.c @@ -1,23 +1,26 @@ -/**** BSIM4.2.1, Released by Xuemei Xi 10/05/2001 ****/ +/**** BSIM4.5.0 Released by Xuemei (Jane) Xi 07/29/2005 ****/ /********** - * Copyright 2001 Regents of the University of California. All rights reserved. - * File: b4temp.c of BSIM4.2.1. + * Copyright 2005 Regents of the University of California. All rights reserved. + * File: b4temp.c of BSIM4.5.0. * Author: 2000 Weidong Liu - * Authors: Xuemei Xi, Kanyu M. Cao, Hui Wan, Mansun Chan, Chenming Hu. + * Authors: 2001- Xuemei Xi, Mohan Dunga, Ali Niknejad, Chenming Hu. * Project Director: Prof. Chenming Hu. * Modified by Xuemei Xi, 04/06/2001. * Modified by Xuemei Xi, 10/05/2001. + * Modified by Xuemei Xi, 11/15/2002. + * Modified by Xuemei Xi, 05/09/2003. + * Modified by Xuemei Xi, 03/04/2004. + * Modified by Xuemei Xi, Mohan Dunga, 07/29/2005. **********/ #include "ngspice.h" -#include -#include #include "smpdefs.h" #include "cktdefs.h" #include "bsim4def.h" #include "const.h" #include "sperror.h" +#include "suffix.h" #define Kb 1.3806226e-23 #define KboQ 8.617087e-5 @@ -28,6 +31,22 @@ #define MIN_EXP 1.713908431e-15 #define EXP_THRESHOLD 34.0 #define Charge_q 1.60219e-19 +#define DELTA 1.0E-9 +#define DEXP(A,B) { \ + if (A > EXP_THRESHOLD) { \ + B = MAX_EXP*(1.0+(A)-EXP_THRESHOLD); \ + } else if (A < -EXP_THRESHOLD) { \ + B = MIN_EXP; \ + } else { \ + B = exp(A); \ + } \ + } + + +int +BSIM4PAeffGeo(double, int, int, double, double, double, double, double *, double *, double *, double *); +int +BSIM4RdseffGeo(double, int, int, int, double, double, double, double, double, int, double *); int BSIM4DioIjthVjmEval(Nvtm, Ijth, Isb, XExpBV, Vjm) @@ -52,14 +71,20 @@ CKTcircuit *ckt; { BSIM4model *model = (BSIM4model*) inModel; BSIM4instance *here; -struct bsim4SizeDependParam *pSizeDependParamKnot, *pLastKnot, *pParam; -double tmp, tmp1, tmp2, tmp3, Eg, Eg0, ni; -double T0, T1, T2, T3, T4, T5, T8, T9, Lnew, Wnew; -double delTemp, Temp, TRatio, Inv_L, Inv_W, Inv_LW, Dw, Dl, Vtm0, Tnom; +struct bsim4SizeDependParam *pSizeDependParamKnot, *pLastKnot, *pParam=NULL; +double tmp, tmp1, tmp2, Eg, Eg0, ni; +double T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, Lnew=0.0, Wnew; +double delTemp, Temp, TRatio, Inv_L, Inv_W, Inv_LW, Vtm0, Tnom; double dumPs, dumPd, dumAs, dumAd, PowWeffWr; double DMCGeff, DMCIeff, DMDGeff; double Nvtms, Nvtmd, SourceSatCurrent, DrainSatCurrent; -int Size_Not_Found; +double T10; +double Inv_saref, Inv_sbref, Inv_sa, Inv_sb, rho, Ldrn, dvth0_lod; +double W_tmp, Inv_ODeff, OD_offset, dk2_lod, deta0_lod; +double lnl, lnw, lnnf, rbpbx, rbpby, rbsbx, rbsby, rbdbx, rbdby,bodymode; +double kvsat, wlod, sceff, Wdrn; + +int Size_Not_Found, i; /* loop through all the BSIM4 device models */ for (; model != NULL; model = model->BSIM4nextModel) @@ -117,7 +142,8 @@ int Size_Not_Found; } if (!model->BSIM4cgboGiven) model->BSIM4cgbo = 2.0 * model->BSIM4dwc * model->BSIM4coxe; - + /* va: was memory leakage - free old node, (or better use again?) */ + FREE(model->pSizeDependParamKnot); model->pSizeDependParamKnot = NULL; pLastKnot = NULL; @@ -128,7 +154,7 @@ int Size_Not_Found; model->BSIM4factor1 = sqrt(EPSSI / (model->BSIM4epsrox * EPS0) * model->BSIM4toxe); - Vtm0 = KboQ * Tnom; + Vtm0 = model->BSIM4vtm0 = KboQ * Tnom; Eg0 = 1.16 - 7.02e-4 * Tnom * Tnom / (Tnom + 1108.0); ni = 1.45e10 * (Tnom / 300.15) * sqrt(Tnom / 300.15) * exp(21.5565981 - Eg0 / (2.0 * Vtm0)); @@ -175,7 +201,6 @@ int Size_Not_Found; model->BSIM4SjctSidewallTempSatCurDensity = 0.0; if (model->BSIM4SjctGateSidewallTempSatCurDensity < 0.0) model->BSIM4SjctGateSidewallTempSatCurDensity = 0.0; - if (model->BSIM4DjctTempSatCurDensity < 0.0) model->BSIM4DjctTempSatCurDensity = 0.0; if (model->BSIM4DjctSidewallTempSatCurDensity < 0.0) @@ -337,9 +362,13 @@ int Size_Not_Found; } } + /* stress effect */ + Ldrn = here->BSIM4l; + Wdrn = here->BSIM4w / here->BSIM4nf; + if (Size_Not_Found) { pParam = (struct bsim4SizeDependParam *)malloc( - sizeof(struct bsim4SizeDependParam)); + sizeof(struct bsim4SizeDependParam)); if (pLastKnot == NULL) model->pSizeDependParamKnot = pParam; else @@ -352,7 +381,7 @@ int Size_Not_Found; pParam->NFinger = here->BSIM4nf; Lnew = here->BSIM4l + model->BSIM4xl ; Wnew = here->BSIM4w / here->BSIM4nf + model->BSIM4xw; - + T0 = pow(Lnew, model->BSIM4Lln); T1 = pow(Wnew, model->BSIM4Lwn); tmp1 = model->BSIM4Ll / T0 + model->BSIM4Lw / T1 @@ -361,7 +390,6 @@ int Size_Not_Found; tmp2 = model->BSIM4Llc / T0 + model->BSIM4Lwc / T1 + model->BSIM4Lwlc / (T0 * T1); pParam->BSIM4dlc = model->BSIM4dlc + tmp2; - pParam->BSIM4dlcig = model->BSIM4dlcig + tmp2; T2 = pow(Lnew, model->BSIM4Wln); T3 = pow(Wnew, model->BSIM4Wwn); @@ -649,6 +677,22 @@ int Size_Not_Found; + model->BSIM4luc1 * Inv_L + model->BSIM4wuc1 * Inv_W + model->BSIM4puc1 * Inv_LW; + pParam->BSIM4ud = model->BSIM4ud + + model->BSIM4lud * Inv_L + + model->BSIM4wud * Inv_W + + model->BSIM4pud * Inv_LW; + pParam->BSIM4ud1 = model->BSIM4ud1 + + model->BSIM4lud1 * Inv_L + + model->BSIM4wud1 * Inv_W + + model->BSIM4pud1 * Inv_LW; + pParam->BSIM4up = model->BSIM4up + + model->BSIM4lup * Inv_L + + model->BSIM4wup * Inv_W + + model->BSIM4pup * Inv_LW; + pParam->BSIM4lp = model->BSIM4lp + + model->BSIM4llp * Inv_L + + model->BSIM4wlp * Inv_W + + model->BSIM4plp * Inv_LW; pParam->BSIM4eu = model->BSIM4eu + model->BSIM4leu * Inv_L + model->BSIM4weu * Inv_W @@ -665,6 +709,10 @@ int Size_Not_Found; + model->BSIM4lvoff * Inv_L + model->BSIM4wvoff * Inv_W + model->BSIM4pvoff * Inv_LW; + pParam->BSIM4tvoff = model->BSIM4tvoff + + model->BSIM4ltvoff * Inv_L + + model->BSIM4wtvoff * Inv_W + + model->BSIM4ptvoff * Inv_LW; pParam->BSIM4minv = model->BSIM4minv + model->BSIM4lminv * Inv_L + model->BSIM4wminv * Inv_W @@ -877,6 +925,26 @@ int Size_Not_Found; + model->BSIM4lxrcrg2 * Inv_L + model->BSIM4wxrcrg2 * Inv_W + model->BSIM4pxrcrg2 * Inv_LW; + pParam->BSIM4lambda = model->BSIM4lambda + + model->BSIM4llambda * Inv_L + + model->BSIM4wlambda * Inv_W + + model->BSIM4plambda * Inv_LW; + pParam->BSIM4vtl = model->BSIM4vtl + + model->BSIM4lvtl * Inv_L + + model->BSIM4wvtl * Inv_W + + model->BSIM4pvtl * Inv_LW; + pParam->BSIM4xn = model->BSIM4xn + + model->BSIM4lxn * Inv_L + + model->BSIM4wxn * Inv_W + + model->BSIM4pxn * Inv_LW; + pParam->BSIM4vfbsdoff = model->BSIM4vfbsdoff + + model->BSIM4lvfbsdoff * Inv_L + + model->BSIM4wvfbsdoff * Inv_W + + model->BSIM4pvfbsdoff * Inv_LW; + pParam->BSIM4tvfbsdoff = model->BSIM4tvfbsdoff + + model->BSIM4ltvfbsdoff * Inv_L + + model->BSIM4wtvfbsdoff * Inv_W + + model->BSIM4ptvfbsdoff * Inv_LW; pParam->BSIM4cgsl = model->BSIM4cgsl + model->BSIM4lcgsl * Inv_L @@ -926,63 +994,111 @@ int Size_Not_Found; + model->BSIM4lvoffcv * Inv_L + model->BSIM4wvoffcv * Inv_W + model->BSIM4pvoffcv * Inv_LW; + pParam->BSIM4kvth0we = model->BSIM4kvth0we + + model->BSIM4lkvth0we * Inv_L + + model->BSIM4wkvth0we * Inv_W + + model->BSIM4pkvth0we * Inv_LW; + pParam->BSIM4k2we = model->BSIM4k2we + + model->BSIM4lk2we * Inv_L + + model->BSIM4wk2we * Inv_W + + model->BSIM4pk2we * Inv_LW; + pParam->BSIM4ku0we = model->BSIM4ku0we + + model->BSIM4lku0we * Inv_L + + model->BSIM4wku0we * Inv_W + + model->BSIM4pku0we * Inv_LW; pParam->BSIM4abulkCVfactor = 1.0 + pow((pParam->BSIM4clc / pParam->BSIM4leffCV), pParam->BSIM4cle); T0 = (TRatio - 1.0); - pParam->BSIM4ua = pParam->BSIM4ua + pParam->BSIM4ua1 * T0; - pParam->BSIM4ub = pParam->BSIM4ub + pParam->BSIM4ub1 * T0; - pParam->BSIM4uc = pParam->BSIM4uc + pParam->BSIM4uc1 * T0; - if (pParam->BSIM4u0 > 1.0) - pParam->BSIM4u0 = pParam->BSIM4u0 / 1.0e4; - - pParam->BSIM4u0temp = pParam->BSIM4u0 - * pow(TRatio, pParam->BSIM4ute); - pParam->BSIM4vsattemp = pParam->BSIM4vsat - pParam->BSIM4at - * T0; - if (pParam->BSIM4eu < 0.0) - { pParam->BSIM4eu = 0.0; - printf("Warning: eu has been negative; reset to 0.0.\n"); - } - PowWeffWr = pow(pParam->BSIM4weffCJ * 1.0e6, pParam->BSIM4wr) * here->BSIM4nf; - /* External Rd(V) */ - T1 = pParam->BSIM4rdw + pParam->BSIM4prt * T0; + + T1 = T2 = T3 = T4 = 0.0; + if(model->BSIM4tempMod == 0) { + pParam->BSIM4ua = pParam->BSIM4ua + pParam->BSIM4ua1 * T0; + pParam->BSIM4ub = pParam->BSIM4ub + pParam->BSIM4ub1 * T0; + pParam->BSIM4uc = pParam->BSIM4uc + pParam->BSIM4uc1 * T0; + pParam->BSIM4ud = pParam->BSIM4ud + pParam->BSIM4ud1 * T0; + pParam->BSIM4vsattemp = pParam->BSIM4vsat - pParam->BSIM4at * T0; + T10 = pParam->BSIM4prt * T0; + if(model->BSIM4rdsMod) { + /* External Rd(V) */ + T1 = pParam->BSIM4rdw + T10; + T2 = model->BSIM4rdwmin + T10; + /* External Rs(V) */ + T3 = pParam->BSIM4rsw + T10; + T4 = model->BSIM4rswmin + T10; + } + /* Internal Rds(V) in IV */ + pParam->BSIM4rds0 = (pParam->BSIM4rdsw + T10) + * here->BSIM4nf / PowWeffWr; + pParam->BSIM4rdswmin = (model->BSIM4rdswmin + T10) + * here->BSIM4nf / PowWeffWr; + } else { /* tempMod = 1, 2 */ + pParam->BSIM4ua = pParam->BSIM4ua * (1.0 + pParam->BSIM4ua1 * delTemp) ; + pParam->BSIM4ub = pParam->BSIM4ub * (1.0 + pParam->BSIM4ub1 * delTemp); + pParam->BSIM4uc = pParam->BSIM4uc * (1.0 + pParam->BSIM4uc1 * delTemp); + pParam->BSIM4ud = pParam->BSIM4ud * (1.0 + pParam->BSIM4ud1 * delTemp); + pParam->BSIM4vsattemp = pParam->BSIM4vsat * (1.0 - pParam->BSIM4at * delTemp); + T10 = 1.0 + pParam->BSIM4prt * delTemp; + if(model->BSIM4rdsMod) { + /* External Rd(V) */ + T1 = pParam->BSIM4rdw * T10; + T2 = model->BSIM4rdwmin * T10; + /* External Rs(V) */ + T3 = pParam->BSIM4rsw * T10; + T4 = model->BSIM4rswmin * T10; + } + /* Internal Rds(V) in IV */ + pParam->BSIM4rds0 = pParam->BSIM4rdsw * T10 * here->BSIM4nf / PowWeffWr; + pParam->BSIM4rdswmin = model->BSIM4rdswmin * T10 * here->BSIM4nf / PowWeffWr; + } if (T1 < 0.0) { T1 = 0.0; printf("Warning: Rdw at current temperature is negative; set to 0.\n"); } - T2 = model->BSIM4rdwmin + pParam->BSIM4prt * T0; if (T2 < 0.0) { T2 = 0.0; printf("Warning: Rdwmin at current temperature is negative; set to 0.\n"); } pParam->BSIM4rd0 = T1 / PowWeffWr; pParam->BSIM4rdwmin = T2 / PowWeffWr; - - - /* External Rs(V) */ - T1 = pParam->BSIM4rsw + pParam->BSIM4prt * T0; - if (T1 < 0.0) - { T1 = 0.0; + if (T3 < 0.0) + { T3 = 0.0; printf("Warning: Rsw at current temperature is negative; set to 0.\n"); } - T2 = model->BSIM4rswmin + pParam->BSIM4prt * T0; - if (T2 < 0.0) - { T2 = 0.0; + if (T4 < 0.0) + { T4 = 0.0; printf("Warning: Rswmin at current temperature is negative; set to 0.\n"); } - pParam->BSIM4rs0 = T1 / PowWeffWr; - pParam->BSIM4rswmin = T2 / PowWeffWr; + pParam->BSIM4rs0 = T3 / PowWeffWr; + pParam->BSIM4rswmin = T4 / PowWeffWr; - /* Internal Rds(V) in IV */ - pParam->BSIM4rds0 = (pParam->BSIM4rdsw + pParam->BSIM4prt * T0) - * here->BSIM4nf / PowWeffWr; - pParam->BSIM4rdswmin = (model->BSIM4rdswmin + pParam->BSIM4prt * T0) - * here->BSIM4nf / PowWeffWr; + if (pParam->BSIM4u0 > 1.0) + pParam->BSIM4u0 = pParam->BSIM4u0 / 1.0e4; + + /* mobility channel length dependence */ + T5 = 1.0 - pParam->BSIM4up * exp( - pParam->BSIM4leff / pParam->BSIM4lp); + pParam->BSIM4u0temp = pParam->BSIM4u0 * T5 + * pow(TRatio, pParam->BSIM4ute); + if (pParam->BSIM4eu < 0.0) + { pParam->BSIM4eu = 0.0; + printf("Warning: eu has been negative; reset to 0.0.\n"); + } + + pParam->BSIM4vfbsdoff = pParam->BSIM4vfbsdoff * (1.0 + pParam->BSIM4tvfbsdoff * delTemp); + pParam->BSIM4voff = pParam->BSIM4voff * (1.0 + pParam->BSIM4tvoff * delTemp); + + /* Source End Velocity Limit */ + if((model->BSIM4vtlGiven) && (model->BSIM4vtl > 0.0) ) + { + if(model->BSIM4lc < 0.0) pParam->BSIM4lc = 0.0; + else pParam->BSIM4lc = model->BSIM4lc ; + T0 = pParam->BSIM4leff / (pParam->BSIM4xn * pParam->BSIM4leff + pParam->BSIM4lc); + pParam->BSIM4tfactor = (1.0 - T0) / (1.0 + T0 ); + } pParam->BSIM4cgdo = (model->BSIM4cgdo + pParam->BSIM4cf) * pParam->BSIM4weffCV; @@ -1032,7 +1148,7 @@ int Size_Not_Found; pParam->BSIM4Aechvb = (model->BSIM4type == NMOS) ? 4.97232e-7 : 3.42537e-7; pParam->BSIM4Bechvb = (model->BSIM4type == NMOS) ? 7.45669e11 : 1.16645e12; pParam->BSIM4AechvbEdge = pParam->BSIM4Aechvb * pParam->BSIM4weff - * pParam->BSIM4dlcig * pParam->BSIM4ToxRatioEdge; + * model->BSIM4dlcig * pParam->BSIM4ToxRatioEdge; pParam->BSIM4BechvbEdge = -pParam->BSIM4Bechvb * model->BSIM4toxe * pParam->BSIM4poxedge; pParam->BSIM4Aechvb *= pParam->BSIM4weff * pParam->BSIM4leff @@ -1097,20 +1213,6 @@ int Size_Not_Found; * pParam->BSIM4k2 * sqrt(pParam->BSIM4phi - pParam->BSIM4vbm); } - - if (pParam->BSIM4k2 < 0.0) - { T0 = 0.5 * pParam->BSIM4k1 / pParam->BSIM4k2; - pParam->BSIM4vbsc = 0.9 * (pParam->BSIM4phi - T0 * T0); - if (pParam->BSIM4vbsc > -3.0) - pParam->BSIM4vbsc = -3.0; - else if (pParam->BSIM4vbsc < -30.0) - pParam->BSIM4vbsc = -30.0; - } - else - { pParam->BSIM4vbsc = -30.0; - } - if (pParam->BSIM4vbsc > pParam->BSIM4vbm) - pParam->BSIM4vbsc = pParam->BSIM4vbm; if (!model->BSIM4vfbGiven) { if (model->BSIM4vth0Given) @@ -1122,28 +1224,14 @@ int Size_Not_Found; { pParam->BSIM4vfb = -1.0; } } - if (!model->BSIM4vth0Given) + if (!model->BSIM4vth0Given) { pParam->BSIM4vth0 = model->BSIM4type * (pParam->BSIM4vfb + pParam->BSIM4phi + pParam->BSIM4k1 * pParam->BSIM4sqrtPhi); } - + pParam->BSIM4k1ox = pParam->BSIM4k1 * model->BSIM4toxe / model->BSIM4toxm; - pParam->BSIM4k2ox = pParam->BSIM4k2 * model->BSIM4toxe - / model->BSIM4toxm; - - T3 = model->BSIM4type * pParam->BSIM4vth0 - - pParam->BSIM4vfb - pParam->BSIM4phi; - T4 = T3 + T3; - T5 = 2.5 * T3; - pParam->BSIM4vtfbphi1 = (model->BSIM4type == NMOS) ? T4 : T5; - if (pParam->BSIM4vtfbphi1 < 0.0) - pParam->BSIM4vtfbphi1 = 0.0; - - pParam->BSIM4vtfbphi2 = 4.0 * T3; - if (pParam->BSIM4vtfbphi2 < 0.0) - pParam->BSIM4vtfbphi2 = 0.0; tmp = sqrt(EPSSI / (model->BSIM4epsrox * EPS0) * model->BSIM4toxe * pParam->BSIM4Xdep0); @@ -1196,7 +1284,7 @@ int Size_Not_Found; T3 = T2 * T2; T4 = T3 + 2.0 * T1 * MIN_EXP; T9 = T1 / T4; - } + } else T9 = 1.0 / (MAX_EXP - 2.0); T9 = pParam->BSIM4dvt0 * T9 * tmp1; @@ -1205,20 +1293,214 @@ int Size_Not_Found; / (pParam->BSIM4weff + pParam->BSIM4w0); T0 = sqrt(1.0 + pParam->BSIM4lpe0 / pParam->BSIM4leff); - T5 = pParam->BSIM4k1ox * (T0 - 1.0) * pParam->BSIM4sqrtPhi - + (pParam->BSIM4kt1 + pParam->BSIM4kt1l / pParam->BSIM4leff) - * (TRatio - 1.0); + if((model->BSIM4tempMod == 1) || (model->BSIM4tempMod == 0)) + T3 = (pParam->BSIM4kt1 + pParam->BSIM4kt1l / pParam->BSIM4leff) + * (TRatio - 1.0); + if(model->BSIM4tempMod == 2) + T3 = - pParam->BSIM4kt1 * (TRatio - 1.0); + + T5 = pParam->BSIM4k1ox * (T0 - 1.0) * pParam->BSIM4sqrtPhi + + T3; + pParam->BSIM4vfbzbfactor = - T8 - T9 + pParam->BSIM4k3 * T4 + T5 + - pParam->BSIM4phi - pParam->BSIM4k1 * pParam->BSIM4sqrtPhi; + + /* stress effect */ + + wlod = model->BSIM4wlod; + if (model->BSIM4wlod < 0.0) + { fprintf(stderr, "Warning: WLOD = %g is less than 0. 0.0 is used\n",model->BSIM4wlod); + wlod = 0.0; + } + T0 = pow(Lnew, model->BSIM4llodku0); + W_tmp = Wnew + wlod; + T1 = pow(W_tmp, model->BSIM4wlodku0); + tmp1 = model->BSIM4lku0 / T0 + model->BSIM4wku0 / T1 + + model->BSIM4pku0 / (T0 * T1); + pParam->BSIM4ku0 = 1.0 + tmp1; + + T0 = pow(Lnew, model->BSIM4llodvth); + T1 = pow(W_tmp, model->BSIM4wlodvth); + tmp1 = model->BSIM4lkvth0 / T0 + model->BSIM4wkvth0 / T1 + + model->BSIM4pkvth0 / (T0 * T1); + pParam->BSIM4kvth0 = 1.0 + tmp1; + pParam->BSIM4kvth0 = sqrt(pParam->BSIM4kvth0*pParam->BSIM4kvth0 + DELTA); + + T0 = (TRatio - 1.0); + pParam->BSIM4ku0temp = pParam->BSIM4ku0 * (1.0 + model->BSIM4tku0 *T0) + DELTA; + + Inv_saref = 1.0/(model->BSIM4saref + 0.5*Ldrn); + Inv_sbref = 1.0/(model->BSIM4sbref + 0.5*Ldrn); + pParam->BSIM4inv_od_ref = Inv_saref + Inv_sbref; + pParam->BSIM4rho_ref = model->BSIM4ku0 / pParam->BSIM4ku0temp * pParam->BSIM4inv_od_ref; - tmp3 = model->BSIM4type * pParam->BSIM4vth0 - - T8 - T9 + pParam->BSIM4k3 * T4 + T5; - pParam->BSIM4vfbzb = tmp3 - pParam->BSIM4phi - pParam->BSIM4k1 - * pParam->BSIM4sqrtPhi; /* End of vfbzb */ } /* End of SizeNotFound */ + /* stress effect */ + if( (here->BSIM4sa > 0.0) && (here->BSIM4sb > 0.0) && + ((here->BSIM4nf == 1.0) || ((here->BSIM4nf > 1.0) && (here->BSIM4sd > 0.0))) ) + { Inv_sa = 0; + Inv_sb = 0; + + kvsat = model->BSIM4kvsat; + if (model->BSIM4kvsat < -1.0 ) + { fprintf(stderr, "Warning: KVSAT = %g is too small; -1.0 is used.\n",model->BSIM4kvsat); + kvsat = -1.0; + } + if (model->BSIM4kvsat > 1.0) + { fprintf(stderr, "Warning: KVSAT = %g is too big; 1.0 is used.\n",model->BSIM4kvsat); + kvsat = 1.0; + } + + for(i = 0; i < here->BSIM4nf; i++){ + T0 = 1.0 / here->BSIM4nf / (here->BSIM4sa + 0.5*Ldrn + i * (here->BSIM4sd +Ldrn)); + T1 = 1.0 / here->BSIM4nf / (here->BSIM4sb + 0.5*Ldrn + i * (here->BSIM4sd +Ldrn)); + Inv_sa += T0; + Inv_sb += T1; + } + Inv_ODeff = Inv_sa + Inv_sb; + rho = model->BSIM4ku0 / pParam->BSIM4ku0temp * Inv_ODeff; + T0 = (1.0 + rho)/(1.0 + pParam->BSIM4rho_ref); + here->BSIM4u0temp = pParam->BSIM4u0temp * T0; + + T1 = (1.0 + kvsat * rho)/(1.0 + kvsat * pParam->BSIM4rho_ref); + here->BSIM4vsattemp = pParam->BSIM4vsattemp * T1; + + OD_offset = Inv_ODeff - pParam->BSIM4inv_od_ref; + dvth0_lod = model->BSIM4kvth0 / pParam->BSIM4kvth0 * OD_offset; + dk2_lod = model->BSIM4stk2 / pow(pParam->BSIM4kvth0, model->BSIM4lodk2) * + OD_offset; + deta0_lod = model->BSIM4steta0 / pow(pParam->BSIM4kvth0, model->BSIM4lodeta0) * + OD_offset; + here->BSIM4vth0 = pParam->BSIM4vth0 + dvth0_lod; + + here->BSIM4eta0 = pParam->BSIM4eta0 + deta0_lod; + here->BSIM4k2 = pParam->BSIM4k2 + dk2_lod; + } else { + here->BSIM4u0temp = pParam->BSIM4u0temp; + here->BSIM4vth0 = pParam->BSIM4vth0; + here->BSIM4vsattemp = pParam->BSIM4vsattemp; + here->BSIM4eta0 = pParam->BSIM4eta0; + here->BSIM4k2 = pParam->BSIM4k2; + } + + /* Well Proximity Effect */ + if (model->BSIM4wpemod) + { if( (!here->BSIM4scaGiven) && (!here->BSIM4scbGiven) && (!here->BSIM4sccGiven) ) + { if((here->BSIM4scGiven) && (here->BSIM4sc > 0.0) ) + { T1 = here->BSIM4sc + Wdrn; + T2 = 1.0 / model->BSIM4scref; + here->BSIM4sca = model->BSIM4scref * model->BSIM4scref + / (here->BSIM4sc * T1); + here->BSIM4scb = ( (0.1 * here->BSIM4sc + 0.01 * model->BSIM4scref) + * exp(-10.0 * here->BSIM4sc * T2) + - (0.1 * T1 + 0.01 * model->BSIM4scref) + * exp(-10.0 * T1 * T2) ) / Wdrn; + here->BSIM4scc = ( (0.05 * here->BSIM4sc + 0.0025 * model->BSIM4scref) + * exp(-20.0 * here->BSIM4sc * T2) + - (0.05 * T1 + 0.0025 * model->BSIM4scref) + * exp(-20.0 * T1 * T2) ) / Wdrn; + } else { + fprintf(stderr, "Warning: No WPE as none of SCA, SCB, SCC, SC is given and/or SC not positive.\n"); + } + } + sceff = here->BSIM4sca + model->BSIM4web * here->BSIM4scb + + model->BSIM4wec * here->BSIM4scc; + here->BSIM4vth0 += pParam->BSIM4kvth0we * sceff; + here->BSIM4k2 += pParam->BSIM4k2we * sceff; + T3 = 1.0 + pParam->BSIM4ku0we * sceff; + if (T3 <= 0.0) + { T3 = 0.0; + fprintf(stderr, "Warning: ku0we = %g is negatively too high. Negative mobility! \n", pParam->BSIM4ku0we); + } + here->BSIM4u0temp *= T3; + } + + /* adding delvto */ + here->BSIM4vth0 += here->BSIM4delvto; + here->BSIM4vfb = pParam->BSIM4vfb + model->BSIM4type * here->BSIM4delvto; + + /* Instance variables calculation */ + T3 = model->BSIM4type * here->BSIM4vth0 + - here->BSIM4vfb - pParam->BSIM4phi; + T4 = T3 + T3; + T5 = 2.5 * T3; + here->BSIM4vtfbphi1 = (model->BSIM4type == NMOS) ? T4 : T5; + if (here->BSIM4vtfbphi1 < 0.0) + here->BSIM4vtfbphi1 = 0.0; + + here->BSIM4vtfbphi2 = 4.0 * T3; + if (here->BSIM4vtfbphi2 < 0.0) + here->BSIM4vtfbphi2 = 0.0; + + if (here->BSIM4k2 < 0.0) + { T0 = 0.5 * pParam->BSIM4k1 / here->BSIM4k2; + here->BSIM4vbsc = 0.9 * (pParam->BSIM4phi - T0 * T0); + if (here->BSIM4vbsc > -3.0) + here->BSIM4vbsc = -3.0; + else if (here->BSIM4vbsc < -30.0) + here->BSIM4vbsc = -30.0; + } + else + here->BSIM4vbsc = -30.0; + if (here->BSIM4vbsc > pParam->BSIM4vbm) + here->BSIM4vbsc = pParam->BSIM4vbm; + here->BSIM4k2ox = here->BSIM4k2 * model->BSIM4toxe + / model->BSIM4toxm; + + here->BSIM4vfbzb = pParam->BSIM4vfbzbfactor + + model->BSIM4type * here->BSIM4vth0 ; + here->BSIM4cgso = pParam->BSIM4cgso; here->BSIM4cgdo = pParam->BSIM4cgdo; + + lnl = log(pParam->BSIM4leff * 1.0e6); + lnw = log(pParam->BSIM4weff * 1.0e6); + lnnf = log(here->BSIM4nf); - if (here->BSIM4rbodyMod) + bodymode = 5; + if( ( !model->BSIM4rbps0Given) || + ( !model->BSIM4rbpd0Given) ) + bodymode = 1; + else + if( (!model->BSIM4rbsbx0Given && !model->BSIM4rbsby0Given) || + (!model->BSIM4rbdbx0Given && !model->BSIM4rbdby0Given) ) + bodymode = 3; + + if(here->BSIM4rbodyMod == 2) + { + if (bodymode == 5) + { + rbsbx = exp( log(model->BSIM4rbsbx0) + model->BSIM4rbsdbxl * lnl + + model->BSIM4rbsdbxw * lnw + model->BSIM4rbsdbxnf * lnnf ); + rbsby = exp( log(model->BSIM4rbsby0) + model->BSIM4rbsdbyl * lnl + + model->BSIM4rbsdbyw * lnw + model->BSIM4rbsdbynf * lnnf ); + here->BSIM4rbsb = rbsbx * rbsby / (rbsbx + rbsby); + + + rbdbx = exp( log(model->BSIM4rbdbx0) + model->BSIM4rbsdbxl * lnl + + model->BSIM4rbsdbxw * lnw + model->BSIM4rbsdbxnf * lnnf ); + rbdby = exp( log(model->BSIM4rbdby0) + model->BSIM4rbsdbyl * lnl + + model->BSIM4rbsdbyw * lnw + model->BSIM4rbsdbynf * lnnf ); + here->BSIM4rbdb = rbdbx * rbdby / (rbdbx + rbdby); + } + + if ((bodymode == 3)|| (bodymode == 5)) + { + here->BSIM4rbps = exp( log(model->BSIM4rbps0) + model->BSIM4rbpsl * lnl + + model->BSIM4rbpsw * lnw + model->BSIM4rbpsnf * lnnf ); + here->BSIM4rbpd = exp( log(model->BSIM4rbpd0) + model->BSIM4rbpdl * lnl + + model->BSIM4rbpdw * lnw + model->BSIM4rbpdnf * lnnf ); + } + + rbpbx = exp( log(model->BSIM4rbpbx0) + model->BSIM4rbpbxl * lnl + + model->BSIM4rbpbxw * lnw + model->BSIM4rbpbxnf * lnnf ); + rbpby = exp( log(model->BSIM4rbpby0) + model->BSIM4rbpbyl * lnl + + model->BSIM4rbpbyw * lnw + model->BSIM4rbpbynf * lnnf ); + here->BSIM4rbpb = rbpbx*rbpby/(rbpbx + rbpby); + } + + + if ((here->BSIM4rbodyMod == 1 ) || ((here->BSIM4rbodyMod == 2 ) && (bodymode == 5)) ) { if (here->BSIM4rbdb < 1.0e-3) here->BSIM4grbdb = 1.0e3; /* in mho */ else @@ -1239,6 +1521,34 @@ int Size_Not_Found; here->BSIM4grbpd = 1.0e3; else here->BSIM4grbpd = model->BSIM4gbmin + 1.0 / here->BSIM4rbpd; + + } + + if((here->BSIM4rbodyMod == 2) && (bodymode == 3)) + { + here->BSIM4grbdb = here->BSIM4grbsb = model->BSIM4gbmin; + if (here->BSIM4rbpb < 1.0e-3) + here->BSIM4grbpb = 1.0e3; + else + here->BSIM4grbpb = model->BSIM4gbmin + 1.0 / here->BSIM4rbpb; + if (here->BSIM4rbps < 1.0e-3) + here->BSIM4grbps = 1.0e3; + else + here->BSIM4grbps = model->BSIM4gbmin + 1.0 / here->BSIM4rbps; + if (here->BSIM4rbpd < 1.0e-3) + here->BSIM4grbpd = 1.0e3; + else + here->BSIM4grbpd = model->BSIM4gbmin + 1.0 / here->BSIM4rbpd; + } + + if((here->BSIM4rbodyMod == 2) && (bodymode == 1)) + { + here->BSIM4grbdb = here->BSIM4grbsb = model->BSIM4gbmin; + here->BSIM4grbps = here->BSIM4grbpd = 1.0e3; + if (here->BSIM4rbpb < 1.0e-3) + here->BSIM4grbpb = 1.0e3; + else + here->BSIM4grbpb = model->BSIM4gbmin + 1.0 / here->BSIM4rbpb; } @@ -1246,9 +1556,9 @@ int Size_Not_Found; * Process geomertry dependent parasitics */ - here->BSIM4grgeltd = model->BSIM4rshg * (model->BSIM4xgw - + pParam->BSIM4weffCJ / 3.0 / model->BSIM4ngcon) / - (model->BSIM4ngcon * here->BSIM4nf * + here->BSIM4grgeltd = model->BSIM4rshg * (here->BSIM4xgw + + pParam->BSIM4weffCJ / 3.0 / here->BSIM4ngcon) / + (here->BSIM4ngcon * here->BSIM4nf * (Lnew - model->BSIM4xgl)); if (here->BSIM4grgeltd > 0.0) here->BSIM4grgeltd = 1.0 / here->BSIM4grgeltd; @@ -1473,7 +1783,7 @@ int Size_Not_Found; fprintf(stderr, "Warning: ijthdrev too small and set to 10 times IdbSat.\n"); } here->BSIM4vjdmRev = -model->BSIM4bvd - - Nvtms * log((T2 - 1.0) / model->BSIM4xjbvd); + - Nvtmd * log((T2 - 1.0) / model->BSIM4xjbvd); /* bugfix */ T1 = model->BSIM4xjbvd * exp(-(model->BSIM4bvd + here->BSIM4vjdmRev) / Nvtmd); here->BSIM4IVjdmRev = DrainSatCurrent * (1.0 + T1); @@ -1484,11 +1794,39 @@ int Size_Not_Found; } } + /* GEDL current reverse bias */ + T0 = (TRatio - 1.0); + model->BSIM4njtstemp = model->BSIM4njts * (1.0 + model->BSIM4tnjts * T0); + model->BSIM4njtsswtemp = model->BSIM4njtssw * (1.0 + model->BSIM4tnjtssw * T0); + model->BSIM4njtsswgtemp = model->BSIM4njtsswg * (1.0 + model->BSIM4tnjtsswg * T0); + T7 = Eg0 / model->BSIM4vtm * T0; + T9 = model->BSIM4xtss * T7; + DEXP(T9, T1); + T9 = model->BSIM4xtsd * T7; + DEXP(T9, T2); + T9 = model->BSIM4xtssws * T7; + DEXP(T9, T3); + T9 = model->BSIM4xtsswd * T7; + DEXP(T9, T4); + T9 = model->BSIM4xtsswgs * T7; + DEXP(T9, T5); + T9 = model->BSIM4xtsswgd * T7; + DEXP(T9, T6); + + T10 = pParam->BSIM4weffCJ * here->BSIM4nf; + here->BSIM4SjctTempRevSatCur = T1 * here->BSIM4Aseff * model->BSIM4jtss; + here->BSIM4DjctTempRevSatCur = T2 * here->BSIM4Adeff * model->BSIM4jtsd; + here->BSIM4SswTempRevSatCur = T3 * here->BSIM4Pseff * model->BSIM4jtssws; + here->BSIM4DswTempRevSatCur = T4 * here->BSIM4Pdeff * model->BSIM4jtsswd; + here->BSIM4SswgTempRevSatCur = T5 * T10 * model->BSIM4jtsswgs; + here->BSIM4DswgTempRevSatCur = T6 * T10 * model->BSIM4jtsswgd; + + if (BSIM4checkModel(model, here, ckt)) { IFuid namarray[2]; namarray[0] = model->BSIM4modName; namarray[1] = here->BSIM4name; - (*(SPfrontEnd->IFerror)) (ERR_FATAL, "Fatal error(s) detected during BSIM4.2.1 parameter checking for %s in model %s", namarray); + (*(SPfrontEnd->IFerror)) (ERR_FATAL, "Fatal error(s) detected during BSIM4.5.0 parameter checking for %s in model %s", namarray); return(E_BADPARM); } } /* End instance */ diff --git a/src/spicelib/devices/bsim4/b4trunc.c b/src/spicelib/devices/bsim4/b4trunc.c index d6e881e65..2dfea6ddf 100644 --- a/src/spicelib/devices/bsim4/b4trunc.c +++ b/src/spicelib/devices/bsim4/b4trunc.c @@ -1,19 +1,18 @@ -/**** BSIM4.2.1, Released by Xuemei Xi 10/05/2001 ****/ +/**** BSIM4.5.0 Released by Xuemei (Jane) Xi 07/29/2005 ****/ /********** - * Copyright 2001 Regents of the University of California. All rights reserved. - * File: b4trunc.c of BSIM4.2.1. + * Copyright 2004 Regents of the University of California. All rights reserved. + * File: b4trunc.c of BSIM4.5.0. * Author: 2000 Weidong Liu - * Authors: Xuemei Xi, Kanyu M. Cao, Hui Wan, Mansun Chan, Chenming Hu. + * Authors: 2001- Xuemei Xi, Mohan Dunga, Ali Niknejad, Chenming Hu. * Project Director: Prof. Chenming Hu. **********/ #include "ngspice.h" -#include -#include #include "cktdefs.h" #include "bsim4def.h" #include "sperror.h" +#include "suffix.h" int diff --git a/src/spicelib/devices/bsim4/bsim4def.h b/src/spicelib/devices/bsim4/bsim4def.h index b46a09273..93e9e5119 100644 --- a/src/spicelib/devices/bsim4/bsim4def.h +++ b/src/spicelib/devices/bsim4/bsim4def.h @@ -1,7 +1,11 @@ /********** -Copyright 2001 Regents of the University of California. All rights reserved. +Copyright 2005 Regents of the University of California. All rights reserved. Author: 2000 Weidong Liu. -Modified by Xuemei Xi October 2001 +Modified by Xuemei Xi, 11/15/2002. +Modified by Xuemei Xi, 05/09/2003. +Modified by Xuemei Xi, 03/04/2004. +Modified by Xuemei Xi, Mohan Dunga, 09/24/2004. +Modified by Xuemei Xi, 07/29/2005. File: bsim4def.h **********/ @@ -12,8 +16,8 @@ File: bsim4def.h #include "gendefs.h" #include "cktdefs.h" #include "complex.h" -#include "noisedef.h" - +#include "noisedef.h" + typedef struct sBSIM4instance { struct sBSIM4model *BSIM4modPtr; @@ -79,15 +83,42 @@ typedef struct sBSIM4instance double BSIM4sourcePerimeter; double BSIM4sourceConductance; double BSIM4drainConductance; + /* stress effect instance param */ + double BSIM4sa; + double BSIM4sb; + double BSIM4sd; + double BSIM4sca; + double BSIM4scb; + double BSIM4scc; + double BSIM4sc; + double BSIM4rbdb; double BSIM4rbsb; double BSIM4rbpb; double BSIM4rbps; double BSIM4rbpd; + + double BSIM4delvto; + double BSIM4xgw; + double BSIM4ngcon; + + /* added here to account stress effect instance dependence */ + double BSIM4u0temp; + double BSIM4vsattemp; + double BSIM4vth0; + double BSIM4vfb; + double BSIM4vfbzb; + double BSIM4vtfbphi1; + double BSIM4vtfbphi2; + double BSIM4k2; + double BSIM4vbsc; + double BSIM4k2ox; + double BSIM4eta0; double BSIM4icVDS; double BSIM4icVGS; double BSIM4icVBS; + double BSIM4m; double BSIM4nf; int BSIM4off; int BSIM4mode; @@ -99,6 +130,7 @@ typedef struct sBSIM4instance int BSIM4rgeoMod; int BSIM4min; + /* OP point */ double BSIM4Vgsteff; double BSIM4vgs_eff; @@ -207,6 +239,7 @@ typedef struct sBSIM4instance double BSIM4qbulk; double BSIM4qdrn; double BSIM4qsrc; + double BSIM4qdef; double BSIM4qchqs; double BSIM4taunet; @@ -215,11 +248,18 @@ typedef struct sBSIM4instance double BSIM4gtd; double BSIM4gts; double BSIM4gtb; + double BSIM4SjctTempRevSatCur; + double BSIM4DjctTempRevSatCur; + double BSIM4SswTempRevSatCur; + double BSIM4DswTempRevSatCur; + double BSIM4SswgTempRevSatCur; + double BSIM4DswgTempRevSatCur; struct bsim4SizeDependParam *pParam; unsigned BSIM4lGiven :1; unsigned BSIM4wGiven :1; + unsigned BSIM4mGiven :1; unsigned BSIM4nfGiven :1; unsigned BSIM4minGiven :1; unsigned BSIM4drainAreaGiven :1; @@ -228,11 +268,21 @@ typedef struct sBSIM4instance unsigned BSIM4sourceSquaresGiven :1; unsigned BSIM4drainPerimeterGiven :1; unsigned BSIM4sourcePerimeterGiven :1; + unsigned BSIM4saGiven :1; + unsigned BSIM4sbGiven :1; + unsigned BSIM4sdGiven :1; + unsigned BSIM4scaGiven :1; + unsigned BSIM4scbGiven :1; + unsigned BSIM4sccGiven :1; + unsigned BSIM4scGiven :1; unsigned BSIM4rbdbGiven :1; unsigned BSIM4rbsbGiven :1; unsigned BSIM4rbpbGiven :1; unsigned BSIM4rbpdGiven :1; unsigned BSIM4rbpsGiven :1; + unsigned BSIM4delvtoGiven :1; + unsigned BSIM4xgwGiven :1; + unsigned BSIM4ngconGiven :1; unsigned BSIM4icVDSGiven :1; unsigned BSIM4icVGSGiven :1; unsigned BSIM4icVBSGiven :1; @@ -243,6 +293,7 @@ typedef struct sBSIM4instance unsigned BSIM4geoModGiven :1; unsigned BSIM4rgeoModGiven :1; + double *BSIM4DPdPtr; double *BSIM4DPdpPtr; double *BSIM4DPgpPtr; @@ -419,7 +470,6 @@ struct bsim4SizeDependParam double BSIM4vbx; double BSIM4vbi; double BSIM4vbm; - double BSIM4vbsc; double BSIM4xt; double BSIM4phi; double BSIM4litl; @@ -450,10 +500,15 @@ struct bsim4SizeDependParam double BSIM4ub1; double BSIM4uc; double BSIM4uc1; + double BSIM4ud; + double BSIM4ud1; + double BSIM4up; + double BSIM4lp; double BSIM4u0; double BSIM4eu; double BSIM4ute; double BSIM4voff; + double BSIM4tvoff; double BSIM4minv; double BSIM4vfb; double BSIM4delta; @@ -511,11 +566,24 @@ struct bsim4SizeDependParam double BSIM4poxedge; double BSIM4xrcrg1; double BSIM4xrcrg2; - double BSIM4fpkt; - double BSIM4plcr; - double BSIM4plcrl; - double BSIM4plcrd; + double BSIM4lambda; /* overshoot */ + double BSIM4vtl; /* thermal velocity limit */ + double BSIM4xn; /* back scattering parameter */ + double BSIM4lc; /* back scattering parameter */ + double BSIM4tfactor; /* ballistic transportation factor */ + double BSIM4vfbsdoff; /* S/D flatband offset voltage */ + double BSIM4tvfbsdoff; +/* added for stress effect */ + double BSIM4ku0; + double BSIM4kvth0; + double BSIM4ku0temp; + double BSIM4rho_ref; + double BSIM4inv_od_ref; +/* added for well proximity effect */ + double BSIM4kvth0we; + double BSIM4k2we; + double BSIM4ku0we; /* CV model */ double BSIM4cgsl; @@ -570,9 +638,6 @@ struct bsim4SizeDependParam double BSIM4cof3; double BSIM4cof4; double BSIM4cdep0; - double BSIM4vfbzb; - double BSIM4vtfbphi1; - double BSIM4vtfbphi2; double BSIM4ToxRatio; double BSIM4Aechvb; double BSIM4Bechvb; @@ -582,6 +647,8 @@ struct bsim4SizeDependParam double BSIM4ldeb; double BSIM4k1ox; double BSIM4k2ox; + double BSIM4vfbzbfactor; + struct bsim4SizeDependParam *pNext; }; @@ -609,6 +676,7 @@ typedef struct sBSIM4model int BSIM4geoMod; int BSIM4igcMod; int BSIM4igbMod; + int BSIM4tempMod; int BSIM4binUnit; int BSIM4paramChk; char *BSIM4version; @@ -668,9 +736,14 @@ typedef struct sBSIM4model double BSIM4ub1; double BSIM4uc; double BSIM4uc1; + double BSIM4ud; + double BSIM4ud1; + double BSIM4up; + double BSIM4lp; double BSIM4u0; double BSIM4ute; double BSIM4voff; + double BSIM4tvoff; double BSIM4minv; double BSIM4voffl; double BSIM4delta; @@ -736,8 +809,41 @@ typedef struct sBSIM4model double BSIM4xjbvs; double BSIM4bvd; double BSIM4bvs; + + double BSIM4jtss; + double BSIM4jtsd; + double BSIM4jtssws; + double BSIM4jtsswd; + double BSIM4jtsswgs; + double BSIM4jtsswgd; + double BSIM4njts; + double BSIM4njtssw; + double BSIM4njtsswg; + double BSIM4xtss; + double BSIM4xtsd; + double BSIM4xtssws; + double BSIM4xtsswd; + double BSIM4xtsswgs; + double BSIM4xtsswgd; + double BSIM4tnjts; + double BSIM4tnjtssw; + double BSIM4tnjtsswg; + double BSIM4vtss; + double BSIM4vtsd; + double BSIM4vtssws; + double BSIM4vtsswd; + double BSIM4vtsswgs; + double BSIM4vtsswgd; + double BSIM4xrcrg1; double BSIM4xrcrg2; + double BSIM4lambda; + double BSIM4vtl; + double BSIM4lc; + double BSIM4xn; + double BSIM4vfbsdoff; /* S/D flatband offset voltage */ + double BSIM4lintnoi; /* lint offset for noise calculation */ + double BSIM4tvfbsdoff; double BSIM4vfb; double BSIM4gbmin; @@ -746,8 +852,42 @@ typedef struct sBSIM4model double BSIM4rbpb; double BSIM4rbps; double BSIM4rbpd; + + double BSIM4rbps0; + double BSIM4rbpsl; + double BSIM4rbpsw; + double BSIM4rbpsnf; + + double BSIM4rbpd0; + double BSIM4rbpdl; + double BSIM4rbpdw; + double BSIM4rbpdnf; + + double BSIM4rbpbx0; + double BSIM4rbpbxl; + double BSIM4rbpbxw; + double BSIM4rbpbxnf; + double BSIM4rbpby0; + double BSIM4rbpbyl; + double BSIM4rbpbyw; + double BSIM4rbpbynf; + + double BSIM4rbsbx0; + double BSIM4rbsby0; + double BSIM4rbdbx0; + double BSIM4rbdby0; + + double BSIM4rbsdbxl; + double BSIM4rbsdbxw; + double BSIM4rbsdbxnf; + double BSIM4rbsdbyl; + double BSIM4rbsdbyw; + double BSIM4rbsdbynf; + double BSIM4tnoia; double BSIM4tnoib; + double BSIM4rnoia; + double BSIM4rnoib; double BSIM4ntnoi; /* CV model and Parasitics */ @@ -835,10 +975,15 @@ typedef struct sBSIM4model double BSIM4lub1; double BSIM4luc; double BSIM4luc1; + double BSIM4lud; + double BSIM4lud1; + double BSIM4lup; + double BSIM4llp; double BSIM4lu0; double BSIM4leu; double BSIM4lute; double BSIM4lvoff; + double BSIM4ltvoff; double BSIM4lminv; double BSIM4ldelta; double BSIM4lrdsw; @@ -893,6 +1038,11 @@ typedef struct sBSIM4model double BSIM4lpoxedge; double BSIM4lxrcrg1; double BSIM4lxrcrg2; + double BSIM4llambda; + double BSIM4lvtl; + double BSIM4lxn; + double BSIM4lvfbsdoff; + double BSIM4ltvfbsdoff; /* CV model */ double BSIM4lcgsl; @@ -959,10 +1109,15 @@ typedef struct sBSIM4model double BSIM4wub1; double BSIM4wuc; double BSIM4wuc1; + double BSIM4wud; + double BSIM4wud1; + double BSIM4wup; + double BSIM4wlp; double BSIM4wu0; double BSIM4weu; double BSIM4wute; double BSIM4wvoff; + double BSIM4wtvoff; double BSIM4wminv; double BSIM4wdelta; double BSIM4wrdsw; @@ -1017,6 +1172,11 @@ typedef struct sBSIM4model double BSIM4wpoxedge; double BSIM4wxrcrg1; double BSIM4wxrcrg2; + double BSIM4wlambda; + double BSIM4wvtl; + double BSIM4wxn; + double BSIM4wvfbsdoff; + double BSIM4wtvfbsdoff; /* CV model */ double BSIM4wcgsl; @@ -1083,10 +1243,15 @@ typedef struct sBSIM4model double BSIM4pub1; double BSIM4puc; double BSIM4puc1; + double BSIM4pud; + double BSIM4pud1; + double BSIM4pup; + double BSIM4plp; double BSIM4pu0; double BSIM4peu; double BSIM4pute; double BSIM4pvoff; + double BSIM4ptvoff; double BSIM4pminv; double BSIM4pdelta; double BSIM4prdsw; @@ -1141,6 +1306,11 @@ typedef struct sBSIM4model double BSIM4ppoxedge; double BSIM4pxrcrg1; double BSIM4pxrcrg2; + double BSIM4plambda; + double BSIM4pvtl; + double BSIM4pxn; + double BSIM4pvfbsdoff; + double BSIM4ptvfbsdoff; /* CV model */ double BSIM4pcgsl; @@ -1193,6 +1363,9 @@ typedef struct sBSIM4model double BSIM4DjctEmissionCoeff; double BSIM4SjctTempExponent; double BSIM4DjctTempExponent; + double BSIM4njtstemp; + double BSIM4njtsswtemp; + double BSIM4njtsswgtemp; double BSIM4Lint; double BSIM4Ll; @@ -1218,10 +1391,50 @@ typedef struct sBSIM4model double BSIM4Wmin; double BSIM4Wmax; + /* added for stress effect */ + double BSIM4saref; + double BSIM4sbref; + double BSIM4wlod; + double BSIM4ku0; + double BSIM4kvsat; + double BSIM4kvth0; + double BSIM4tku0; + double BSIM4llodku0; + double BSIM4wlodku0; + double BSIM4llodvth; + double BSIM4wlodvth; + double BSIM4lku0; + double BSIM4wku0; + double BSIM4pku0; + double BSIM4lkvth0; + double BSIM4wkvth0; + double BSIM4pkvth0; + double BSIM4stk2; + double BSIM4lodk2; + double BSIM4steta0; + double BSIM4lodeta0; + + double BSIM4web; + double BSIM4wec; + double BSIM4kvth0we; + double BSIM4k2we; + double BSIM4ku0we; + double BSIM4scref; + double BSIM4wpemod; + double BSIM4lkvth0we; + double BSIM4lk2we; + double BSIM4lku0we; + double BSIM4wkvth0we; + double BSIM4wk2we; + double BSIM4wku0we; + double BSIM4pkvth0we; + double BSIM4pk2we; + double BSIM4pku0we; /* Pre-calculated constants * move to size-dependent param */ double BSIM4vtm; + double BSIM4vtm0; double BSIM4coxe; double BSIM4coxp; double BSIM4cof1; @@ -1276,6 +1489,7 @@ typedef struct sBSIM4model unsigned BSIM4tnoiModGiven :1; unsigned BSIM4igcModGiven :1; unsigned BSIM4igbModGiven :1; + unsigned BSIM4tempModGiven :1; unsigned BSIM4typeGiven :1; unsigned BSIM4toxrefGiven :1; unsigned BSIM4toxeGiven :1; @@ -1335,9 +1549,14 @@ typedef struct sBSIM4model unsigned BSIM4ub1Given :1; unsigned BSIM4ucGiven :1; unsigned BSIM4uc1Given :1; + unsigned BSIM4udGiven :1; + unsigned BSIM4ud1Given :1; + unsigned BSIM4upGiven :1; + unsigned BSIM4lpGiven :1; unsigned BSIM4u0Given :1; unsigned BSIM4uteGiven :1; unsigned BSIM4voffGiven :1; + unsigned BSIM4tvoffGiven :1; unsigned BSIM4vofflGiven :1; unsigned BSIM4minvGiven :1; unsigned BSIM4rdswGiven :1; @@ -1402,6 +1621,32 @@ typedef struct sBSIM4model unsigned BSIM4xjbvsGiven :1; unsigned BSIM4bvdGiven :1; unsigned BSIM4bvsGiven :1; + + unsigned BSIM4jtssGiven :1; + unsigned BSIM4jtsdGiven :1; + unsigned BSIM4jtsswsGiven :1; + unsigned BSIM4jtsswdGiven :1; + unsigned BSIM4jtsswgsGiven :1; + unsigned BSIM4jtsswgdGiven :1; + unsigned BSIM4njtsGiven :1; + unsigned BSIM4njtsswGiven :1; + unsigned BSIM4njtsswgGiven :1; + unsigned BSIM4xtssGiven :1; + unsigned BSIM4xtsdGiven :1; + unsigned BSIM4xtsswsGiven :1; + unsigned BSIM4xtsswdGiven :1; + unsigned BSIM4xtsswgsGiven :1; + unsigned BSIM4xtsswgdGiven :1; + unsigned BSIM4tnjtsGiven :1; + unsigned BSIM4tnjtsswGiven :1; + unsigned BSIM4tnjtsswgGiven :1; + unsigned BSIM4vtssGiven :1; + unsigned BSIM4vtsdGiven :1; + unsigned BSIM4vtsswsGiven :1; + unsigned BSIM4vtsswdGiven :1; + unsigned BSIM4vtsswgsGiven :1; + unsigned BSIM4vtsswgdGiven :1; + unsigned BSIM4vfbGiven :1; unsigned BSIM4gbminGiven :1; unsigned BSIM4rbdbGiven :1; @@ -1409,12 +1654,54 @@ typedef struct sBSIM4model unsigned BSIM4rbpsGiven :1; unsigned BSIM4rbpdGiven :1; unsigned BSIM4rbpbGiven :1; + + unsigned BSIM4rbps0Given :1; + unsigned BSIM4rbpslGiven :1; + unsigned BSIM4rbpswGiven :1; + unsigned BSIM4rbpsnfGiven :1; + + unsigned BSIM4rbpd0Given :1; + unsigned BSIM4rbpdlGiven :1; + unsigned BSIM4rbpdwGiven :1; + unsigned BSIM4rbpdnfGiven :1; + + unsigned BSIM4rbpbx0Given :1; + unsigned BSIM4rbpbxlGiven :1; + unsigned BSIM4rbpbxwGiven :1; + unsigned BSIM4rbpbxnfGiven :1; + unsigned BSIM4rbpby0Given :1; + unsigned BSIM4rbpbylGiven :1; + unsigned BSIM4rbpbywGiven :1; + unsigned BSIM4rbpbynfGiven :1; + + unsigned BSIM4rbsbx0Given :1; + unsigned BSIM4rbsby0Given :1; + unsigned BSIM4rbdbx0Given :1; + unsigned BSIM4rbdby0Given :1; + + unsigned BSIM4rbsdbxlGiven :1; + unsigned BSIM4rbsdbxwGiven :1; + unsigned BSIM4rbsdbxnfGiven :1; + unsigned BSIM4rbsdbylGiven :1; + unsigned BSIM4rbsdbywGiven :1; + unsigned BSIM4rbsdbynfGiven :1; + unsigned BSIM4xrcrg1Given :1; unsigned BSIM4xrcrg2Given :1; unsigned BSIM4tnoiaGiven :1; unsigned BSIM4tnoibGiven :1; + unsigned BSIM4rnoiaGiven :1; + unsigned BSIM4rnoibGiven :1; unsigned BSIM4ntnoiGiven :1; + unsigned BSIM4lambdaGiven :1; + unsigned BSIM4vtlGiven :1; + unsigned BSIM4lcGiven :1; + unsigned BSIM4xnGiven :1; + unsigned BSIM4vfbsdoffGiven :1; + unsigned BSIM4lintnoiGiven :1; + unsigned BSIM4tvfbsdoffGiven :1; + /* CV model and parasitics */ unsigned BSIM4cgslGiven :1; unsigned BSIM4cgdlGiven :1; @@ -1501,10 +1788,15 @@ typedef struct sBSIM4model unsigned BSIM4lub1Given :1; unsigned BSIM4lucGiven :1; unsigned BSIM4luc1Given :1; + unsigned BSIM4ludGiven :1; + unsigned BSIM4lud1Given :1; + unsigned BSIM4lupGiven :1; + unsigned BSIM4llpGiven :1; unsigned BSIM4lu0Given :1; unsigned BSIM4leuGiven :1; unsigned BSIM4luteGiven :1; unsigned BSIM4lvoffGiven :1; + unsigned BSIM4ltvoffGiven :1; unsigned BSIM4lminvGiven :1; unsigned BSIM4lrdswGiven :1; unsigned BSIM4lrswGiven :1; @@ -1559,6 +1851,11 @@ typedef struct sBSIM4model unsigned BSIM4lpoxedgeGiven :1; unsigned BSIM4lxrcrg1Given :1; unsigned BSIM4lxrcrg2Given :1; + unsigned BSIM4llambdaGiven :1; + unsigned BSIM4lvtlGiven :1; + unsigned BSIM4lxnGiven :1; + unsigned BSIM4lvfbsdoffGiven :1; + unsigned BSIM4ltvfbsdoffGiven :1; /* CV model */ unsigned BSIM4lcgslGiven :1; @@ -1625,10 +1922,15 @@ typedef struct sBSIM4model unsigned BSIM4wub1Given :1; unsigned BSIM4wucGiven :1; unsigned BSIM4wuc1Given :1; + unsigned BSIM4wudGiven :1; + unsigned BSIM4wud1Given :1; + unsigned BSIM4wupGiven :1; + unsigned BSIM4wlpGiven :1; unsigned BSIM4wu0Given :1; unsigned BSIM4weuGiven :1; unsigned BSIM4wuteGiven :1; unsigned BSIM4wvoffGiven :1; + unsigned BSIM4wtvoffGiven :1; unsigned BSIM4wminvGiven :1; unsigned BSIM4wrdswGiven :1; unsigned BSIM4wrswGiven :1; @@ -1683,6 +1985,11 @@ typedef struct sBSIM4model unsigned BSIM4wpoxedgeGiven :1; unsigned BSIM4wxrcrg1Given :1; unsigned BSIM4wxrcrg2Given :1; + unsigned BSIM4wlambdaGiven :1; + unsigned BSIM4wvtlGiven :1; + unsigned BSIM4wxnGiven :1; + unsigned BSIM4wvfbsdoffGiven :1; + unsigned BSIM4wtvfbsdoffGiven :1; /* CV model */ unsigned BSIM4wcgslGiven :1; @@ -1749,10 +2056,15 @@ typedef struct sBSIM4model unsigned BSIM4pub1Given :1; unsigned BSIM4pucGiven :1; unsigned BSIM4puc1Given :1; + unsigned BSIM4pudGiven :1; + unsigned BSIM4pud1Given :1; + unsigned BSIM4pupGiven :1; + unsigned BSIM4plpGiven :1; unsigned BSIM4pu0Given :1; unsigned BSIM4peuGiven :1; unsigned BSIM4puteGiven :1; unsigned BSIM4pvoffGiven :1; + unsigned BSIM4ptvoffGiven :1; unsigned BSIM4pminvGiven :1; unsigned BSIM4prdswGiven :1; unsigned BSIM4prswGiven :1; @@ -1807,6 +2119,11 @@ typedef struct sBSIM4model unsigned BSIM4ppoxedgeGiven :1; unsigned BSIM4pxrcrg1Given :1; unsigned BSIM4pxrcrg2Given :1; + unsigned BSIM4plambdaGiven :1; + unsigned BSIM4pvtlGiven :1; + unsigned BSIM4pxnGiven :1; + unsigned BSIM4pvfbsdoffGiven :1; + unsigned BSIM4ptvfbsdoffGiven :1; /* CV model */ unsigned BSIM4pcgslGiven :1; @@ -1893,6 +2210,47 @@ typedef struct sBSIM4model unsigned BSIM4WminGiven :1; unsigned BSIM4WmaxGiven :1; + /* added for stress effect */ + unsigned BSIM4sarefGiven :1; + unsigned BSIM4sbrefGiven :1; + unsigned BSIM4wlodGiven :1; + unsigned BSIM4ku0Given :1; + unsigned BSIM4kvsatGiven :1; + unsigned BSIM4kvth0Given :1; + unsigned BSIM4tku0Given :1; + unsigned BSIM4llodku0Given :1; + unsigned BSIM4wlodku0Given :1; + unsigned BSIM4llodvthGiven :1; + unsigned BSIM4wlodvthGiven :1; + unsigned BSIM4lku0Given :1; + unsigned BSIM4wku0Given :1; + unsigned BSIM4pku0Given :1; + unsigned BSIM4lkvth0Given :1; + unsigned BSIM4wkvth0Given :1; + unsigned BSIM4pkvth0Given :1; + unsigned BSIM4stk2Given :1; + unsigned BSIM4lodk2Given :1; + unsigned BSIM4steta0Given :1; + unsigned BSIM4lodeta0Given :1; + + unsigned BSIM4webGiven :1; + unsigned BSIM4wecGiven :1; + unsigned BSIM4kvth0weGiven :1; + unsigned BSIM4k2weGiven :1; + unsigned BSIM4ku0weGiven :1; + unsigned BSIM4screfGiven :1; + unsigned BSIM4wpemodGiven :1; + unsigned BSIM4lkvth0weGiven :1; + unsigned BSIM4lk2weGiven :1; + unsigned BSIM4lku0weGiven :1; + unsigned BSIM4wkvth0weGiven :1; + unsigned BSIM4wk2weGiven :1; + unsigned BSIM4wku0weGiven :1; + unsigned BSIM4pkvth0weGiven :1; + unsigned BSIM4pk2weGiven :1; + unsigned BSIM4pku0weGiven :1; + + } BSIM4model; @@ -1929,9 +2287,20 @@ typedef struct sBSIM4model #define BSIM4_RBPB 25 #define BSIM4_RBPS 26 #define BSIM4_RBPD 27 - +#define BSIM4_SA 28 +#define BSIM4_SB 29 +#define BSIM4_SD 30 +#define BSIM4_DELVTO 31 +#define BSIM4_XGW 32 +#define BSIM4_NGCON 33 +#define BSIM4_SCA 34 +#define BSIM4_SCB 35 +#define BSIM4_SCC 36 +#define BSIM4_SC 37 +#define BSIM4_M 38 /* Global parameters */ +#define BSIM4_MOD_TEMPMOD 89 #define BSIM4_MOD_IGCMOD 90 #define BSIM4_MOD_IGBMOD 91 #define BSIM4_MOD_ACNQSMOD 92 @@ -2116,7 +2485,20 @@ typedef struct sBSIM4model #define BSIM4_MOD_CIGSD 279 #define BSIM4_MOD_JSWGS 280 #define BSIM4_MOD_JSWGD 281 - +#define BSIM4_MOD_LAMBDA 282 +#define BSIM4_MOD_VTL 283 +#define BSIM4_MOD_LC 284 +#define BSIM4_MOD_XN 285 +#define BSIM4_MOD_RNOIA 286 +#define BSIM4_MOD_RNOIB 287 +#define BSIM4_MOD_VFBSDOFF 288 +#define BSIM4_MOD_LINTNOI 289 +#define BSIM4_MOD_UD 290 +#define BSIM4_MOD_UD1 291 +#define BSIM4_MOD_UP 292 +#define BSIM4_MOD_LP 293 +#define BSIM4_MOD_TVOFF 294 +#define BSIM4_MOD_TVFBSDOFF 295 /* Length dependence */ #define BSIM4_MOD_LCDSC 301 @@ -2244,6 +2626,14 @@ typedef struct sBSIM4model #define BSIM4_MOD_LBIGSD 433 #define BSIM4_MOD_LCIGSD 434 +#define BSIM4_MOD_LLAMBDA 435 +#define BSIM4_MOD_LVTL 436 +#define BSIM4_MOD_LXN 437 +#define BSIM4_MOD_LVFBSDOFF 438 +#define BSIM4_MOD_LUD 439 +#define BSIM4_MOD_LUD1 440 +#define BSIM4_MOD_LUP 441 +#define BSIM4_MOD_LLP 442 /* Width dependence */ #define BSIM4_MOD_WCDSC 481 @@ -2370,7 +2760,14 @@ typedef struct sBSIM4model #define BSIM4_MOD_WAIGSD 612 #define BSIM4_MOD_WBIGSD 613 #define BSIM4_MOD_WCIGSD 614 - +#define BSIM4_MOD_WLAMBDA 615 +#define BSIM4_MOD_WVTL 616 +#define BSIM4_MOD_WXN 617 +#define BSIM4_MOD_WVFBSDOFF 618 +#define BSIM4_MOD_WUD 619 +#define BSIM4_MOD_WUD1 620 +#define BSIM4_MOD_WUP 621 +#define BSIM4_MOD_WLP 622 /* Cross-term dependence */ #define BSIM4_MOD_PCDSC 661 @@ -2505,6 +2902,41 @@ typedef struct sBSIM4model #define BSIM4_MOD_PBIGSD 793 #define BSIM4_MOD_PCIGSD 794 +#define BSIM4_MOD_SAREF 795 +#define BSIM4_MOD_SBREF 796 +#define BSIM4_MOD_KU0 797 +#define BSIM4_MOD_KVSAT 798 +#define BSIM4_MOD_TKU0 799 +#define BSIM4_MOD_LLODKU0 800 +#define BSIM4_MOD_WLODKU0 801 +#define BSIM4_MOD_LLODVTH 802 +#define BSIM4_MOD_WLODVTH 803 +#define BSIM4_MOD_LKU0 804 +#define BSIM4_MOD_WKU0 805 +#define BSIM4_MOD_PKU0 806 +#define BSIM4_MOD_KVTH0 807 +#define BSIM4_MOD_LKVTH0 808 +#define BSIM4_MOD_WKVTH0 809 +#define BSIM4_MOD_PKVTH0 810 +#define BSIM4_MOD_WLOD 811 +#define BSIM4_MOD_STK2 812 +#define BSIM4_MOD_LODK2 813 +#define BSIM4_MOD_STETA0 814 +#define BSIM4_MOD_LODETA0 815 + +#define BSIM4_MOD_WEB 816 +#define BSIM4_MOD_WEC 817 +#define BSIM4_MOD_KVTH0WE 818 +#define BSIM4_MOD_K2WE 819 +#define BSIM4_MOD_KU0WE 820 +#define BSIM4_MOD_SCREF 821 +#define BSIM4_MOD_WPEMOD 822 + +#define BSIM4_MOD_PLAMBDA 825 +#define BSIM4_MOD_PVTL 826 +#define BSIM4_MOD_PXN 827 +#define BSIM4_MOD_PVFBSDOFF 828 + #define BSIM4_MOD_TNOM 831 #define BSIM4_MOD_CGSO 832 #define BSIM4_MOD_CGDO 833 @@ -2575,6 +3007,37 @@ typedef struct sBSIM4model #define BSIM4_MOD_JSWD 898 #define BSIM4_MOD_DLCIG 899 +/* trap-assisted tunneling */ + +#define BSIM4_MOD_JTSS 900 +#define BSIM4_MOD_JTSD 901 +#define BSIM4_MOD_JTSSWS 902 +#define BSIM4_MOD_JTSSWD 903 +#define BSIM4_MOD_JTSSWGS 904 +#define BSIM4_MOD_JTSSWGD 905 +#define BSIM4_MOD_NJTS 906 +#define BSIM4_MOD_NJTSSW 907 +#define BSIM4_MOD_NJTSSWG 908 +#define BSIM4_MOD_XTSS 909 +#define BSIM4_MOD_XTSD 910 +#define BSIM4_MOD_XTSSWS 911 +#define BSIM4_MOD_XTSSWD 912 +#define BSIM4_MOD_XTSSWGS 913 +#define BSIM4_MOD_XTSSWGD 914 +#define BSIM4_MOD_TNJTS 915 +#define BSIM4_MOD_TNJTSSW 916 +#define BSIM4_MOD_TNJTSSWG 917 +#define BSIM4_MOD_VTSS 918 +#define BSIM4_MOD_VTSD 919 +#define BSIM4_MOD_VTSSWS 920 +#define BSIM4_MOD_VTSSWD 921 +#define BSIM4_MOD_VTSSWGS 922 +#define BSIM4_MOD_VTSSWGD 923 +#define BSIM4_MOD_PUD 924 +#define BSIM4_MOD_PUD1 925 +#define BSIM4_MOD_PUP 926 +#define BSIM4_MOD_PLP 927 + /* device questions */ #define BSIM4_DNODE 945 #define BSIM4_GNODEEXT 946 @@ -2642,22 +3105,65 @@ typedef struct sBSIM4model #define BSIM4_IGB 1008 #define BSIM4_IGCS 1009 #define BSIM4_IGCD 1010 +#define BSIM4_QDEF 1011 +#define BSIM4_DELVT0 1012 +#define BSIM4_GCRG 1013 +#define BSIM4_GTAU 1014 +#define BSIM4_MOD_LTVOFF 1051 +#define BSIM4_MOD_LTVFBSDOFF 1052 +#define BSIM4_MOD_WTVOFF 1053 +#define BSIM4_MOD_WTVFBSDOFF 1054 +#define BSIM4_MOD_PTVOFF 1055 +#define BSIM4_MOD_PTVFBSDOFF 1056 + +#define BSIM4_MOD_LKVTH0WE 1061 +#define BSIM4_MOD_LK2WE 1062 +#define BSIM4_MOD_LKU0WE 1063 +#define BSIM4_MOD_WKVTH0WE 1064 +#define BSIM4_MOD_WK2WE 1065 +#define BSIM4_MOD_WKU0WE 1066 +#define BSIM4_MOD_PKVTH0WE 1067 +#define BSIM4_MOD_PK2WE 1068 +#define BSIM4_MOD_PKU0WE 1069 + +#define BSIM4_MOD_RBPS0 1101 +#define BSIM4_MOD_RBPSL 1102 +#define BSIM4_MOD_RBPSW 1103 +#define BSIM4_MOD_RBPSNF 1104 +#define BSIM4_MOD_RBPD0 1105 +#define BSIM4_MOD_RBPDL 1106 +#define BSIM4_MOD_RBPDW 1107 +#define BSIM4_MOD_RBPDNF 1108 + +#define BSIM4_MOD_RBPBX0 1109 +#define BSIM4_MOD_RBPBXL 1110 +#define BSIM4_MOD_RBPBXW 1111 +#define BSIM4_MOD_RBPBXNF 1112 +#define BSIM4_MOD_RBPBY0 1113 +#define BSIM4_MOD_RBPBYL 1114 +#define BSIM4_MOD_RBPBYW 1115 +#define BSIM4_MOD_RBPBYNF 1116 + +#define BSIM4_MOD_RBSBX0 1117 +#define BSIM4_MOD_RBSBY0 1118 +#define BSIM4_MOD_RBDBX0 1119 +#define BSIM4_MOD_RBDBY0 1120 + +#define BSIM4_MOD_RBSDBXL 1121 +#define BSIM4_MOD_RBSDBXW 1122 +#define BSIM4_MOD_RBSDBXNF 1123 +#define BSIM4_MOD_RBSDBYL 1124 +#define BSIM4_MOD_RBSDBYW 1125 +#define BSIM4_MOD_RBSDBYNF 1126 -# #include "bsim4ext.h" -#ifdef __STDC__ extern void BSIM4evaluate(double,double,double,BSIM4instance*,BSIM4model*, double*,double*,double*, double*, double*, double*, double*, double*, double*, double*, double*, double*, double*, double*, double*, double*, double*, double*, CKTcircuit*); extern int BSIM4debug(BSIM4model*, BSIM4instance*, CKTcircuit*, int); extern int BSIM4checkModel(BSIM4model*, BSIM4instance*, CKTcircuit*); -#else /* stdc */ -extern void BSIM4evaluate(); -extern int BSIM4debug(); -extern int BSIM4checkModel(); -#endif /* stdc */ #endif /*BSIM4*/ diff --git a/src/spicelib/devices/bsim4/bsim4ext.h b/src/spicelib/devices/bsim4/bsim4ext.h index 4e4977201..171406ae5 100644 --- a/src/spicelib/devices/bsim4/bsim4ext.h +++ b/src/spicelib/devices/bsim4/bsim4ext.h @@ -1,11 +1,10 @@ /********** -Copyright 2001 Regents of the University of California. All rights reserved. +Copyright 2004 Regents of the University of California. All rights reserved. Author: 2000 Weidong Liu -Author: 2001 Xuemei Xi +Author: 2001- Xuemei Xi File: bsim4ext.h **********/ -#ifdef __STDC__ extern int BSIM4acLoad(GENmodel *,CKTcircuit*); extern int BSIM4ask(CKTcircuit *,GENinstance*,int,IFvalue*,IFvalue*); extern int BSIM4convTest(GENmodel *,CKTcircuit*); @@ -29,26 +28,3 @@ extern int BSIM4temp(GENmodel*,CKTcircuit*); extern int BSIM4trunc(GENmodel*,CKTcircuit*,double*); extern int BSIM4noise(int,int,GENmodel*,CKTcircuit*,Ndata*,double*); extern int BSIM4unsetup(GENmodel*,CKTcircuit*); - -#else /* stdc */ -extern int BSIM4acLoad(); -extern int BSIM4delete(); -extern void BSIM4destroy(); -extern int BSIM4getic(); -extern int BSIM4load(); -extern int BSIM4mDelete(); -extern int BSIM4ask(); -extern int BSIM4mAsk(); -extern int BSIM4convTest(); -extern int BSIM4temp(); -extern int BSIM4mParam(); -extern void BSIM4mosCap(); -extern int BSIM4param(); -extern int BSIM4pzLoad(); -extern int BSIM4setup(); -extern int BSIM4trunc(); -extern int BSIM4noise(); -extern int BSIM4unsetup(); - -#endif /* stdc */ - diff --git a/src/spicelib/devices/bsim4/bsim4init.c b/src/spicelib/devices/bsim4/bsim4init.c index 35f7a01ee..132f11d60 100644 --- a/src/spicelib/devices/bsim4/bsim4init.c +++ b/src/spicelib/devices/bsim4/bsim4init.c @@ -1,6 +1,6 @@ -#include +#include "config.h" -#include +#include "devdefs.h" #include "bsim4itf.h" #include "bsim4ext.h" @@ -40,36 +40,39 @@ SPICEdev BSIM4info = { DEV_DEFAULT }, - DEVparam : BSIM4param, - DEVmodParam : BSIM4mParam, - DEVload : BSIM4load, - DEVsetup : BSIM4setup, - DEVunsetup : BSIM4unsetup, - DEVpzSetup : BSIM4setup, - DEVtemperature: BSIM4temp, - DEVtrunc : BSIM4trunc, - DEVfindBranch : NULL, - DEVacLoad : BSIM4acLoad, - DEVaccept : NULL, - DEVdestroy : BSIM4destroy, - DEVmodDelete : BSIM4mDelete, - DEVdelete : BSIM4delete, - DEVsetic : BSIM4getic, - DEVask : BSIM4ask, - DEVmodAsk : BSIM4mAsk, - DEVpzLoad : BSIM4pzLoad, - DEVconvTest : BSIM4convTest, - DEVsenSetup : NULL, - DEVsenLoad : NULL, - DEVsenUpdate : NULL, - DEVsenAcLoad : NULL, - DEVsenPrint : NULL, - DEVsenTrunc : NULL, - DEVdisto : NULL, - DEVnoise : BSIM4noise, - - DEVinstSize : &BSIM4iSize, - DEVmodSize : &BSIM4mSize + BSIM4param, /* DEVparam */ + BSIM4mParam, /* DEVmodParam */ + BSIM4load, /* DEVload */ + BSIM4setup, /* DEVsetup */ + BSIM4unsetup, /* DEVunsetup */ + BSIM4setup, /* DEVpzSetup */ + BSIM4temp, /* DEVtemperature */ + BSIM4trunc, /* DEVtrunc */ + NULL, /* DEVfindBranch */ + BSIM4acLoad, /* DEVacLoad */ + NULL, /* DEVaccept */ + BSIM4destroy, /* DEVdestroy */ + BSIM4mDelete, /* DEVmodDelete */ + BSIM4delete, /* DEVdelete */ + BSIM4getic, /* DEVsetic */ + BSIM4ask, /* DEVask */ + BSIM4mAsk, /* DEVmodAsk */ + BSIM4pzLoad, /* DEVpzLoad */ + BSIM4convTest, /* DEVconvTest */ + NULL, /* DEVsenSetup */ + NULL, /* DEVsenLoad */ + NULL, /* DEVsenUpdate */ + NULL, /* DEVsenAcLoad */ + NULL, /* DEVsenPrint */ + NULL, /* DEVsenTrunc */ + NULL, /* DEVdisto */ + BSIM4noise, /* DEVnoise */ +#ifdef CIDER + NULL, /* DEVdump */ + NULL, /* DEVacct */ +#endif + &BSIM4iSize, /* DEVinstSize */ + &BSIM4mSize /* DEVmodSize */ }; diff --git a/src/spicelib/devices/bsim4/bsim4itf.h b/src/spicelib/devices/bsim4/bsim4itf.h index 08c4ec852..b4dc51e7e 100644 --- a/src/spicelib/devices/bsim4/bsim4itf.h +++ b/src/spicelib/devices/bsim4/bsim4itf.h @@ -1,7 +1,7 @@ /********** -Copyright 2001 Regents of the University of California. All rights reserved. +Copyright 2004 Regents of the University of California. All rights reserved. Author: 2000 Weidong Liu. -Author: 2001 Xuemei Xi +Author: 2001- Xuemei Xi File: bsim4itf.h **********/