diff --git a/src/spicelib/devices/soi3/Makefile.am b/src/spicelib/devices/soi3/Makefile.am new file mode 100644 index 000000000..1cadd6d21 --- /dev/null +++ b/src/spicelib/devices/soi3/Makefile.am @@ -0,0 +1,32 @@ +## Process this file with automake to produce Makefile.in + +pkglib_LTLIBRARIES = libsoi3.la + +libsoi3_la_SOURCES = \ + soi3.c \ + soi3acld.c \ + soi3ask.c \ + soi3cap.c \ + soi3conv.c \ + soi3defs.h \ + soi3del.c \ + soi3dest.c \ + soi3ext.h \ + soi3ic.c \ + soi3init.c \ + soi3init.h \ + soi3itf.h \ + soi3load.c \ + soi3mask.c \ + soi3mdel.c \ + soi3mpar.c \ + soi3nois.c \ + soi3par.c \ + soi3set.c \ + soi3temp.c \ + soi3trun.c + + + +INCLUDES = -I$(top_srcdir)/src/include +MAINTAINERCLEANFILES = Makefile.in diff --git a/src/spicelib/devices/soi3/README b/src/spicelib/devices/soi3/README new file mode 100644 index 000000000..4fa56ee9d --- /dev/null +++ b/src/spicelib/devices/soi3/README @@ -0,0 +1,55 @@ +Licence Agreement (STAG) from DERA + +1. The STAG Computer Model is subject to Copyright owned by the United Kingdom +Secretary of State for Defence acting through the Defence Evaluation and Research Agency +(DERA). It is made available to licensee (hereinafter LICENSEE) on the following conditions:- + +2. Downloading the STAG Model deems acceptance of the terms of the licence. + +3. DERA grants to LICENSEE a royalty free non-exclusive licence to use the furnished STAG +Model. LICENSEE is permitted to copy, distribute, and transfer the STAG Model to +customers for their royalty free use on the same licence terms. + +4. LICENSEE acknowledges that STAG is a research tool still in the development stage, that +it is being supplied "as is", without any accompanying services or improvements from +DERA. + +5. LICENSEE acknowledges that STAG is a Model developed by the Department of +Electronics and Computer Science at the University of Southampton (UOS), England, and is +incorporated within SPICE 3f5, a program developed by the Department of Electrical +Engineering and Computer Science at the University of California, Berkeley, California +(UCB). As such, LICENSEE acknowledges that in addition to the rights licensed by DERA, +UCB itself imposes restrictions on use, copying, and distribution of the SPICE 3f5 program +and its derivatives. + +6. LICENSEE undertakes to obtain any separate licence required for the use of SPICE 3f5 +from UCB. + +7. DERA make no representations or warranties, express or implied. DERA shall not be held +liable for any liability nor for any direct, indirect, or consequential damages with respect to +any claim by LICENSEE or any third party on account of or arising from this Agreement or +use of STAG. + +8. Title to copyright of all portions of STAG developed at UOS and/or DERA together with +associated documentation shall at all times remain with DERA, and LICENSEE agrees to +preserve same. LICENSEE agrees to ensure that this information and appropriate copyright +notice is reproduced with any copies of STAG or any modified versions derived from it. + +9. This agreement shall be construed, interpreted, and applied in accordance with the laws +of England. + +for DERA by: + +J B EDWARDS +IPD5A +10 NOV 1997 + +Intellectual Property Department +Defence Evaluation and Research Agency +St Andrews Road +Malvern +WR14 3PS +United Kingdom + +phone: +44 - 1684 - 894234 +fax: +44 - 1684 - 894146 diff --git a/src/spicelib/devices/soi3/soi3.c b/src/spicelib/devices/soi3/soi3.c new file mode 100644 index 000000000..80a82e0be --- /dev/null +++ b/src/spicelib/devices/soi3/soi3.c @@ -0,0 +1,239 @@ +/********** +STAG version 2.6 +Copyright 2000 owned by the United Kingdom Secretary of State for Defence +acting through the Defence Evaluation and Research Agency. +Developed by : Jim Benson, + Department of Electronics and Computer Science, + University of Southampton, + United Kingdom. +With help from : Nele D'Halleweyn, Bill Redman-White, and Craig Easson. + +Based on STAG version 2.1 +Developed by : Mike Lee, +With help from : Bernard Tenbroek, Bill Redman-White, Mike Uren, Chris Edwards + and John Bunyan. +Acknowledgements : Rupert Howes and Pete Mole. +**********/ + +/* Modified: 2001 Paolo Nenzi */ + +#include "ngspice.h" +#include +#include "devdefs.h" +#include "ifsim.h" +#include "soi3defs.h" +#include "suffix.h" + + + +char *SOI3names[] = { + "Drain", + "Front Gate", + "Source", + "Back Gate", + "Bulk", + "Thermal" +}; + + +IFparm SOI3pTable[] = { /* parameters */ + IOP("l", SOI3_L, IF_REAL, "Length"), + IOP("w", SOI3_W, IF_REAL, "Width"), + IOP("nrd", SOI3_NRD, IF_REAL, "Drain squares"), + IOP("nrs", SOI3_NRS, IF_REAL, "Source squares"), + IP("off", SOI3_OFF, IF_FLAG, "Device initially off"), + IOP("icvds", SOI3_IC_VDS, IF_REAL, "Initial D-S voltage"), + IOP("icvgfs", SOI3_IC_VGFS, IF_REAL, "Initial GF-S voltage"), + IOP("icvgbs", SOI3_IC_VGBS, IF_REAL, "Initial GB-S voltage"), + IOP("icvbs", SOI3_IC_VBS, IF_REAL, "Initial B-S voltage"), + IOP("temp", SOI3_TEMP, IF_REAL, "Instance temperature"), + IOP("rt", SOI3_RT, IF_REAL, "Instance Lumped Thermal Resistance"), + IOP("ct", SOI3_CT, IF_REAL, "Instance Lumped Thermal Capacitance"), + IOP("rt1", SOI3_RT1, IF_REAL, "Second Thermal Resistance"), + IOP("ct1", SOI3_CT1, IF_REAL, "Second Thermal Capacitance"), + IOP("rt2", SOI3_RT2, IF_REAL, "Third Thermal Resistance"), + IOP("ct2", SOI3_CT2, IF_REAL, "Third Thermal Capacitance"), + IOP("rt3", SOI3_RT3, IF_REAL, "Fourth Thermal Resistance"), + IOP("ct3", SOI3_CT3, IF_REAL, "Fourth Thermal Capacitance"), + IOP("rt4", SOI3_RT4, IF_REAL, "Fifth Thermal Resistance"), + IOP("ct4", SOI3_CT4, IF_REAL, "Fifth Thermal Capacitance"), + + IP( "ic", SOI3_IC, IF_REALVEC,"Vector of D-S, GF-S, GB-S, B-S voltages"), +/* IP( "sens_l", SOI3_L_SENS, IF_FLAG, "flag to request sensitivity WRT length"), + IP( "sens_w", SOI3_W_SENS, IF_FLAG, "flag to request sensitivity WRT width"),*/ + OP( "dnode", SOI3_DNODE, IF_INTEGER, "Number of the drain node "), + OP( "gfnode", SOI3_GFNODE, IF_INTEGER, "Number of frt. gate node "), + OP( "snode", SOI3_SNODE, IF_INTEGER, "Number of the source node "), + OP( "gbnode", SOI3_GBNODE, IF_INTEGER, "Number of back gate node "), + OP( "bnode", SOI3_BNODE, IF_INTEGER, "Number of the body node "), + OP( "dnodeprime", SOI3_DNODEPRIME, IF_INTEGER, "Number of int. drain node"), + OP( "snodeprime", SOI3_SNODEPRIME, IF_INTEGER, "Number of int. source node "), + OP( "tnode", SOI3_TNODE, IF_INTEGER, "Number of thermal node "), + OP( "branch", SOI3_BRANCH, IF_INTEGER, "Number of thermal branch "), + OP( "sourceconductance", SOI3_SOURCECONDUCT, IF_REAL, "Conductance of source"), + OP( "drainconductance", SOI3_DRAINCONDUCT, IF_REAL, "Conductance of drain"), + OP( "von", SOI3_VON, IF_REAL, "Effective Threshold Voltage (von) "), + OP( "vfbf", SOI3_VFBF, IF_REAL, "Temperature adjusted flat band voltage"), + OP( "vdsat", SOI3_VDSAT, IF_REAL, "Saturation drain voltage"), + OP( "sourcevcrit", SOI3_SOURCEVCRIT,IF_REAL, "Critical source voltage"), + OP( "drainvcrit", SOI3_DRAINVCRIT, IF_REAL, "Critical drain voltage"), + OP( "id", SOI3_ID, IF_REAL, "Drain current"), + OP( "ibs", SOI3_IBS, IF_REAL, "B-S junction current"), + OP( "ibd", SOI3_IBD, IF_REAL, "B-D junction current"), + OP( "gmbs", SOI3_GMBS, IF_REAL, "Bulk-Source transconductance"), + OP( "gmf", SOI3_GMF, IF_REAL, "Front transconductance"), + OP( "gmb", SOI3_GMB, IF_REAL, "Back transconductance"), + OP( "gds", SOI3_GDS, IF_REAL, "Drain-Source conductance"), + OP( "gbd", SOI3_GBD, IF_REAL, "Bulk-Drain conductance"), + OP( "gbs", SOI3_GBS, IF_REAL, "Bulk-Source conductance"), + OP( "capbd", SOI3_CAPBD, IF_REAL, "Bulk-Drain capacitance"), + OP( "capbs", SOI3_CAPBS, IF_REAL, "Bulk-Source capacitance"), + OP( "cbd0", SOI3_CAPZEROBIASBD, IF_REAL, "Zero-Bias B-D junction capacitance"), + OP( "cbs0", SOI3_CAPZEROBIASBS, IF_REAL, "Zero-Bias B-S junction capacitance"), + OP( "vbd", SOI3_VBD, IF_REAL, "Bulk-Drain voltage"), + OP( "vbs", SOI3_VBS, IF_REAL, "Bulk-Source voltage"), + OP( "vgfs", SOI3_VGFS, IF_REAL, "Front gate-Source voltage"), + OP( "vgbs", SOI3_VGBS, IF_REAL, "Back gate-Source voltage"), + OP( "vds", SOI3_VDS, IF_REAL, "Drain-Source voltage"), + OP( "qgf", SOI3_QGF, IF_REAL, "Front Gate charge storage"), + OP( "iqgf",SOI3_IQGF,IF_REAL,"Current due to front gate charge storage"), +/* + OP( "qgb", SOI3_QGB, IF_REAL, "Back Gate charge storage"), + OP( "iqgb",SOI3_IQGB,IF_REAL,"Current due to back gate charge storage"), +*/ + OP( "qd", SOI3_QD, IF_REAL, "Drain charge storage"), + OP( "iqd",SOI3_IQD,IF_REAL,"Current due to drain charge storage"), + OP( "qs", SOI3_QS, IF_REAL, "Source charge storage"), + OP( "iqs",SOI3_IQS,IF_REAL,"Current due to source charge storage"), + OP( "qbd", SOI3_QBD, IF_REAL, "Bulk-Drain charge storage"), + OP( "iqbd",SOI3_IQBD,IF_REAL,"Current due to bulk-drain charge storage"), + OP( "qbs", SOI3_QBS, IF_REAL, "Bulk-Source charge storage"), + OP( "iqbs",SOI3_IQBS,IF_REAL,"Currnet due to bulk-source charge storage"), +/* extra stuff for newer model -msll Jan96 */ + OP( "vfbb", SOI3_VFBB, IF_REAL, "Temperature adjusted back flat band voltage") + +/*, + OP( "sens_l_dc", SOI3_L_SENS_DC, IF_REAL, "dc sensitivity wrt length"), + OP( "sens_l_real", SOI3_L_SENS_REAL,IF_REAL, + "real part of ac sensitivity wrt length"), + OP( "sens_l_imag", SOI3_L_SENS_IMAG,IF_REAL, + "imag part of ac sensitivity wrt length"), + OP( "sens_l_mag", SOI3_L_SENS_MAG, IF_REAL, + "sensitivity wrt l of ac magnitude"), + OP( "sens_l_ph", SOI3_L_SENS_PH, IF_REAL, + "sensitivity wrt l of ac phase"), + OP( "sens_l_cplx", SOI3_L_SENS_CPLX,IF_COMPLEX, "ac sensitivity wrt length"), + OP( "sens_w_dc", SOI3_W_SENS_DC, IF_REAL, "dc sensitivity wrt width"), + OP( "sens_w_real", SOI3_W_SENS_REAL,IF_REAL, + "real part of ac sensitivity wrt width"), + OP( "sens_w_imag", SOI3_W_SENS_IMAG,IF_REAL, + "imag part of ac sensitivity wrt width"), + OP( "sens_w_mag", SOI3_W_SENS_MAG, IF_REAL, + "sensitivity wrt w of ac magnitude"), + OP( "sens_w_ph", SOI3_W_SENS_PH, IF_REAL, + "sensitivity wrt w of ac phase"), + OP( "sens_w_cplx", SOI3_W_SENS_CPLX,IF_COMPLEX, "ac sensitivity wrt width")*/ +}; + +IFparm SOI3mPTable[] = { /* model parameters */ + IOP("vto", SOI3_MOD_VTO, IF_REAL ,"Threshold voltage"), + IOP("vt0", SOI3_MOD_VTO, IF_REAL ,"Threshold voltage"), + IOP("vfbf", SOI3_MOD_VFBF, IF_REAL ,"Flat band voltage"), + IOP("kp", SOI3_MOD_KP, IF_REAL ,"Transconductance parameter"), + IOP("gamma", SOI3_MOD_GAMMA, IF_REAL ,"Body Factor"), + IOP("phi", SOI3_MOD_PHI, IF_REAL ,"Surface potential"), + IOP("lambda",SOI3_MOD_LAMBDA,IF_REAL ,"Channel length modulation"), + IOP("theta", SOI3_MOD_THETA, IF_REAL ,"Vertical field mobility degradation"), + IOP("rd", SOI3_MOD_RD, IF_REAL ,"Drain ohmic resistance"), + IOP("rs", SOI3_MOD_RS, IF_REAL ,"Source ohmic resistance"), + IOP("cbd", SOI3_MOD_CBD, IF_REAL ,"B-D junction capacitance"), + IOP("cbs", SOI3_MOD_CBS, IF_REAL ,"B-S junction capacitance"), + IOP("is", SOI3_MOD_IS, IF_REAL ,"Bulk junction sat. current"), + IOP("is1", SOI3_MOD_IS1, IF_REAL ,"2nd Bulk junction sat. current"), + IOP("pb", SOI3_MOD_PB, IF_REAL ,"Bulk junction potential"), + IOP("cgfso", SOI3_MOD_CGFSO, IF_REAL ,"Front Gate-source overlap cap."), + IOP("cgfdo", SOI3_MOD_CGFDO, IF_REAL ,"Front Gate-drain overlap cap."), + IOP("cgfbo", SOI3_MOD_CGFBO, IF_REAL ,"Front Gate-bulk overlap cap."), + IOP("cgbso", SOI3_MOD_CGBSO, IF_REAL ,"Back Gate-source overlap cap."), + IOP("cgbdo", SOI3_MOD_CGBDO, IF_REAL ,"Back Gate-drain overlap cap."), + IOP("cgb_bo", SOI3_MOD_CGB_BO, IF_REAL ,"Back Gate-bulk overlap cap."), + IOP("rsh", SOI3_MOD_RSH, IF_REAL ,"Sheet resistance"), + IOP("cj", SOI3_MOD_CJSW, IF_REAL ,"Side junction cap per area"), + IOP("mj", SOI3_MOD_MJSW, IF_REAL ,"Side grading coefficient"), + IOP("js", SOI3_MOD_JS, IF_REAL ,"Bulk jct. sat. current density"), + IOP("js1", SOI3_MOD_JS1, IF_REAL ,"2nd Bulk jct. sat. current density"), + IOP("tof", SOI3_MOD_TOF, IF_REAL ,"Front Oxide thickness"), + IOP("tob", SOI3_MOD_TOB, IF_REAL ,"Back Oxide thickness"), + IOP("tb", SOI3_MOD_TB, IF_REAL ,"Bulk film thickness"), + IOP("ld", SOI3_MOD_LD, IF_REAL ,"Lateral diffusion"), + IOP("u0", SOI3_MOD_U0, IF_REAL ,"Surface mobility"), + IOP("uo", SOI3_MOD_U0, IF_REAL ,"Surface mobility"), + IOP("fc", SOI3_MOD_FC, IF_REAL ,"Forward bias jct. fit parm."), + IP("nsoi", SOI3_MOD_NSOI3, IF_FLAG ,"N type SOI3fet model"), + IP("psoi", SOI3_MOD_PSOI3, IF_FLAG ,"P type SOI3fet model"), + IOP("kox", SOI3_MOD_KOX, IF_REAL ,"Oxide thermal conductivity"), + IOP("shsi", SOI3_MOD_SHSI, IF_REAL ,"Specific heat of silicon"), + IOP("dsi", SOI3_MOD_DSI, IF_REAL ,"Density of silicon"), + IOP("nsub", SOI3_MOD_NSUB, IF_REAL ,"Substrate doping"), + IOP("tpg", SOI3_MOD_TPG, IF_INTEGER,"Gate type"), + IOP("nqff", SOI3_MOD_NQFF, IF_REAL ,"Front fixed oxide charge density"), + IOP("nqfb", SOI3_MOD_NQFB, IF_REAL ,"Back fixed oxide charge density"), + IOP("nssf", SOI3_MOD_NSSF, IF_REAL ,"Front surface state density"), + IOP("nssb", SOI3_MOD_NSSB, IF_REAL ,"Back surface state density"), + IOP("tnom", SOI3_MOD_TNOM, IF_REAL ,"Parameter measurement temp"), + IP("kf", SOI3_MOD_KF, IF_REAL ,"Flicker noise coefficient"), + IP("af", SOI3_MOD_AF, IF_REAL ,"Flicker noise exponent"), +/* extra stuff for newer model - msll Jan96 */ + IOP("sigma", SOI3_MOD_SIGMA, IF_REAL ,"DIBL coefficient"), + IOP("chifb", SOI3_MOD_CHIFB, IF_REAL ,"Temperature coeff of flatband voltage"), + IOP("chiphi",SOI3_MOD_CHIPHI, IF_REAL ,"Temperature coeff of PHI"), + IOP("deltaw",SOI3_MOD_DELTAW,IF_REAL ,"Narrow width factor"), + IOP("deltal",SOI3_MOD_DELTAL,IF_REAL ,"Short channel factor"), + IOP("vsat", SOI3_MOD_VSAT, IF_REAL ,"Saturation velocity"), + IOP("k", SOI3_MOD_K, IF_REAL ,"Thermal exponent"), + IOP("lx", SOI3_MOD_LX, IF_REAL ,"Channel length modulation (alternative)"), + IOP("vp", SOI3_MOD_VP, IF_REAL ,"Channel length modulation (alt. empirical)"), + IOP("eta", SOI3_MOD_ETA, IF_REAL ,"Impact ionization field adjustment factor"), + IOP("alpha0",SOI3_MOD_ALPHA0,IF_REAL ,"First impact ionisation coeff (alpha0)"), + IOP("beta0", SOI3_MOD_BETA0, IF_REAL ,"Second impact ionisation coeff (beta0)"), + IOP("lm", SOI3_MOD_LM, IF_REAL ,"Impact ion. drain region length"), + IOP("lm1", SOI3_MOD_LM1, IF_REAL ,"Impact ion. drain region length coeff"), + IOP("lm2", SOI3_MOD_LM2, IF_REAL ,"Impact ion. drain region length coeff"), + IOP("etad", SOI3_MOD_ETAD, IF_REAL ,"Diode ideality factor"), + IOP("etad1", SOI3_MOD_ETAD1, IF_REAL ,"2nd Diode ideality factor"), + IOP("chibeta",SOI3_MOD_CHIBETA,IF_REAL ,"Impact ionisation temperature coefficient"), + IOP("vfbb", SOI3_MOD_VFBB, IF_REAL ,"Back Flat band voltage"), + IOP("gammab",SOI3_MOD_GAMMAB,IF_REAL ,"Back Body Factor"), + IOP("chid", SOI3_MOD_CHID, IF_REAL ,"Junction temperature factor"), + IOP("chid1", SOI3_MOD_CHID1, IF_REAL ,"2nd Junction temperature factor"), + IOP("dvt", SOI3_MOD_DVT, IF_INTEGER,"Switch for temperature dependence of vt in diodes"), + IOP("nlev", SOI3_MOD_NLEV, IF_INTEGER,"Level switch for flicker noise model"), + IOP("betabjt",SOI3_MOD_BETABJT,IF_REAL ,"Beta for BJT"), + IOP("tauf", SOI3_MOD_TAUFBJT,IF_REAL ,"Forward tau for BJT"), + IOP("taur", SOI3_MOD_TAURBJT,IF_REAL ,"Reverse tau for BJT"), + IOP("betaexp",SOI3_MOD_BETAEXP,IF_REAL ,"Exponent for Beta of BJT"), + IOP("tauexp", SOI3_MOD_TAUEXP,IF_REAL, "Exponent for Transit time of BJT"), + IOP("rsw", SOI3_MOD_RSW, IF_REAL ,"Source resistance width scaling factor"), + IOP("rdw", SOI3_MOD_RDW, IF_REAL ,"Drain resistance width scaling factor"), + IOP("fmin", SOI3_MOD_FMIN, IF_REAL ,"Minimum feature size of technology"), + IOP("vtex", SOI3_MOD_VTEX, IF_REAL ,"Extracted threshold voltage"), + IOP("vdex", SOI3_MOD_VDEX, IF_REAL ,"Drain bias at which vtex extracted"), + IOP("delta0",SOI3_MOD_DELTA0,IF_REAL ,"Surface potential factor for vtex conversion"), + IOP("csf", SOI3_MOD_CSF ,IF_REAL ,"Saturation region charge sharing factor"), + IOP("nplus", SOI3_MOD_NPLUS ,IF_REAL ,"Doping concentration of N+ or P+ regions"), + IOP("rta", SOI3_MOD_RTA ,IF_REAL ,"Thermal resistance area scaling factor"), + IOP("cta", SOI3_MOD_CTA ,IF_REAL ,"Thermal capacitance area scaling factor") + +}; + + + +int SOI3nSize = NUMELEMS(SOI3names); +int SOI3pTSize = NUMELEMS(SOI3pTable); +int SOI3mPTSize = NUMELEMS(SOI3mPTable); +int SOI3iSize = sizeof(SOI3instance); +int SOI3mSize = sizeof(SOI3model); + + + + diff --git a/src/spicelib/devices/soi3/soi3acld.c b/src/spicelib/devices/soi3/soi3acld.c new file mode 100644 index 000000000..0a962002e --- /dev/null +++ b/src/spicelib/devices/soi3/soi3acld.c @@ -0,0 +1,406 @@ +/********** +STAG version 2.6 +Copyright 2000 owned by the United Kingdom Secretary of State for Defence +acting through the Defence Evaluation and Research Agency. +Developed by : Jim Benson, + Department of Electronics and Computer Science, + University of Southampton, + United Kingdom. +With help from : Nele D'Halleweyn, Bill Redman-White, and Craig Easson. + +Based on STAG version 2.1 +Developed by : Mike Lee, +With help from : Bernard Tenbroek, Bill Redman-White, Mike Uren, Chris Edwards + and John Bunyan. +Acknowledgements : Rupert Howes and Pete Mole. +**********/ + +/* Modified: 2001 Paolo Nenzi */ + +#include "ngspice.h" +#include +#include "cktdefs.h" +#include "soi3defs.h" +#include "sperror.h" +#include "suffix.h" + + +int +SOI3acLoad(inModel,ckt) + GENmodel *inModel; + CKTcircuit *ckt; +{ + SOI3model *model = (SOI3model*)inModel; + SOI3instance *here; + int xnrm; + int xrev; + + double cgfgf,cgfd,cgfs,cgfdeltaT; + double cdgf,cdd,cds,cddeltaT; + double csgf,csd,css,csdeltaT; + double cbgf,cbd,cbs,cbdeltaT,cbgb; + double cgbgb,cgbsb,cgbdb; + + double xcgfgf,xcgfd,xcgfs,xcgfdeltaT; + double xcdgf,xcdd,xcds,xcddeltaT; + double xcsgf,xcsd,xcss,xcsdeltaT; + double xcbgf,xcbd,xcbs,xcbdeltaT,xcbgb; + double xcgbgb,xcgbsb,xcgbdb; + + double capbd,capbs; /* diode capacitances */ + + double xcBJTbsbs,xcBJTbsdeltaT; + double xcBJTbdbd,xcBJTbddeltaT; + + double rtargs[5]; + double grt[5]; + double ctargs[5]; + double xct[5]; /* 1/reactance of thermal cap */ + int tnodeindex; + + double cgfb0; + double cgfd0; + double cgfs0; + + double cgbb0; + double cgbd0; + double cgbs0; + + double xcgbd0,xcgbs0; + + double EffectiveLength; + + double omega; + + omega = ckt->CKTomega; + + for( ; model != NULL; model = model->SOI3nextModel) + { + for(here = model->SOI3instances; here!= NULL; + here = here->SOI3nextInstance) + { + + if (here->SOI3mode < 0) + { + xnrm=0; + xrev=1; + } + else + { + xnrm=1; + xrev=0; + } + + EffectiveLength=here->SOI3l - 2*model->SOI3latDiff; + cgfs0 = model->SOI3frontGateSourceOverlapCapFactor * here->SOI3w; + cgfd0 = model->SOI3frontGateDrainOverlapCapFactor * here->SOI3w; + cgfb0 = model->SOI3frontGateBulkOverlapCapFactor * EffectiveLength; + + /* JimB - can use basic device geometry to calculate source/back gate */ + /* and drain/back gate capacitances to a first approximation. Use this*/ + /* default model if capacitance factors aren't given in model netlist. */ + + if(model->SOI3backGateSourceOverlapCapFactorGiven) + { + cgbs0 = model->SOI3backGateSourceOverlapCapFactor * here->SOI3w; + } + else + { + /* As a basic circuit designers approximation, length of drain and */ + /* source regions often taken to have length of twice the minimum */ + /* feature size for that technology. */ + cgbs0 = 2*1e-6*model->SOI3minimumFeatureSize * here->SOI3w + * model->SOI3backOxideCapFactor; + } + if(model->SOI3backGateDrainOverlapCapFactorGiven) + { + cgbd0 = model->SOI3backGateDrainOverlapCapFactor * here->SOI3w; + } + else + { + /* As a basic circuit designer's approximation, length of drain and */ + /* source regions often taken to have length of twice the minimum */ + /* feature size for that technology. */ + cgbd0 = 2*1e-6*model->SOI3minimumFeatureSize * here->SOI3w + * model->SOI3backOxideCapFactor; + } + cgbb0 = model->SOI3backGateBulkOverlapCapFactor * EffectiveLength; + + capbd = here->SOI3capbd; + capbs = here->SOI3capbs; + + cgfgf = *(ckt->CKTstate0 + here->SOI3cgfgf); + cgfd = *(ckt->CKTstate0 + here->SOI3cgfd); + cgfs = *(ckt->CKTstate0 + here->SOI3cgfs); + cgfdeltaT = *(ckt->CKTstate0 + here->SOI3cgfdeltaT); + csgf = *(ckt->CKTstate0 + here->SOI3csgf); + csd = *(ckt->CKTstate0 + here->SOI3csd); + css = *(ckt->CKTstate0 + here->SOI3css); + csdeltaT = *(ckt->CKTstate0 + here->SOI3csdeltaT); + cdgf = *(ckt->CKTstate0 + here->SOI3cdgf); + cdd = *(ckt->CKTstate0 + here->SOI3cdd); + cds = *(ckt->CKTstate0 + here->SOI3cds); + cddeltaT = *(ckt->CKTstate0 + here->SOI3cddeltaT); + cgbgb = *(ckt->CKTstate0 + here->SOI3cgbgb); + cgbsb = *(ckt->CKTstate0 + here->SOI3cgbsb); + cgbdb = *(ckt->CKTstate0 + here->SOI3cgbdb); + cbgf = -(cgfgf + cdgf + csgf); + cbd = -(cgfd + cdd + csd + cgbdb); + cbs = -(cgfs + cds + css + cgbsb); + cbdeltaT = -(cgfdeltaT + cddeltaT + csdeltaT); + cbgb = -cgbgb; + + xcgfgf = (cgfgf + cgfd0 + cgfs0 + cgfb0) * omega; + xcgfd = (cgfd - cgfd0) * omega; + xcgfs = (cgfs - cgfs0) * omega; + xcgfdeltaT = cgfdeltaT * omega; + xcsgf = (csgf - cgfs0) * omega; + xcsd = csd * omega; + xcss = (css + capbs + cgfs0) * omega; + xcsdeltaT = csdeltaT * omega; + xcdgf = (cdgf - cgfd0) * omega; + xcdd = (cdd + capbd + cgfd0) * omega; + xcds = cds * omega; + xcddeltaT = cddeltaT * omega; + xcgbgb = (cgbgb + cgbb0 + cgbd0 + cgbs0) * omega; + xcgbsb = (cgbsb - cgbs0) * omega; + xcgbdb = -cgbd0 * omega; + xcbgf = (cbgf - cgfb0) * omega; + xcbd = (cbd - capbd) * omega; + xcbs = (cbs - capbs) * omega; + xcbdeltaT = cbdeltaT * omega; + xcbgb = cbgb * omega; + + xcgbs0 = cgbs0 * omega; + xcgbd0 = cgbd0 * omega; + + xcBJTbsbs = *(ckt->CKTstate0 + here->SOI3cBJTbsbs) * omega; + xcBJTbsdeltaT = *(ckt->CKTstate0 + here->SOI3cBJTbsdeltaT) * omega; + xcBJTbdbd = *(ckt->CKTstate0 + here->SOI3cBJTbdbd) * omega; + xcBJTbddeltaT = *(ckt->CKTstate0 + here->SOI3cBJTbddeltaT) * omega; + + /* JimB - 15/9/99 */ + /* Code for multiple thermal time constants. Start by moving all */ + /* rt and ct constants into arrays. */ + rtargs[0]=here->SOI3rt; + rtargs[1]=here->SOI3rt1; + rtargs[2]=here->SOI3rt2; + rtargs[3]=here->SOI3rt3; + rtargs[4]=here->SOI3rt4; + + ctargs[0]=here->SOI3ct; + ctargs[1]=here->SOI3ct1; + ctargs[2]=here->SOI3ct2; + ctargs[3]=here->SOI3ct3; + ctargs[4]=here->SOI3ct4; + + /* Set all admittance components to zero. */ + grt[0]=grt[1]=grt[2]=grt[3]=grt[4]=0.0; + xct[0]=xct[1]=xct[2]=xct[3]=xct[4]=0.0; + /* Now calculate conductances and susceptances from rt and ct. */ + /* Don't need to worry about divide by zero when calculating */ + /* grt components, as soi3setup() only creates a thermal node */ + /* if corresponding rt is greater than zero. */ + for(tnodeindex=0;tnodeindexSOI3numThermalNodes;tnodeindex++) + { + xct[tnodeindex] = ctargs[tnodeindex] * ckt->CKTomega; + grt[tnodeindex] = 1/rtargs[tnodeindex]; + } + /* End JimB */ + + /* + * load matrix + */ + + *(here->SOI3GF_gfPtr + 1) += xcgfgf; + *(here->SOI3GB_gbPtr + 1) += xcgbgb; + *(here->SOI3B_bPtr + 1) += -(xcbgf+xcbd+xcbs+xcbgb) + +xcBJTbsbs+xcBJTbdbd; + + *(here->SOI3DP_dpPtr + 1) += xcdd+xcgbd0+xcBJTbdbd; + *(here->SOI3SP_spPtr + 1) += xcss+xcgbs0+xcBJTbsbs; + + *(here->SOI3GF_dpPtr + 1) += xcgfd; + *(here->SOI3GF_spPtr + 1) += xcgfs; + *(here->SOI3GF_bPtr + 1) -= (xcgfgf + xcgfd + xcgfs); + + *(here->SOI3GB_dpPtr + 1) += xcgbdb; + *(here->SOI3GB_spPtr + 1) += xcgbsb; + *(here->SOI3GB_bPtr + 1) -= (xcgbgb + xcgbdb + xcgbsb); + + *(here->SOI3B_gfPtr + 1) += xcbgf; + *(here->SOI3B_gbPtr + 1) += xcbgb; + *(here->SOI3B_dpPtr + 1) += xcbd-xcBJTbdbd; + *(here->SOI3B_spPtr + 1) += xcbs-xcBJTbsbs; + + *(here->SOI3DP_gfPtr + 1) += xcdgf; + *(here->SOI3DP_gbPtr + 1) += -xcgbd0; + *(here->SOI3DP_bPtr + 1) += -(xcdgf + xcdd + xcds + xcBJTbdbd); + *(here->SOI3DP_spPtr + 1) += xcds; + + *(here->SOI3SP_gfPtr + 1) += xcsgf; + *(here->SOI3SP_gbPtr + 1) += -xcgbs0; + *(here->SOI3SP_bPtr + 1) += -(xcsgf + xcsd + xcss + xcBJTbsbs); + *(here->SOI3SP_dpPtr + 1) += xcsd; + +/* if no thermal behaviour specified, then put in zero valued indpt. voltage source + between TOUT and ground */ + if (here->SOI3rt==0) + { + *(here->SOI3TOUT_ibrPtr + 1) += 1.0; + *(here->SOI3IBR_toutPtr + 1) += 1.0; + *(ckt->CKTirhs + (here->SOI3branch)) = 0; + } + else + { + *(here->SOI3TOUT_toutPtr + 1) += xct[0]; + if (here->SOI3numThermalNodes > 1) + { + *(here->SOI3TOUT_tout1Ptr + 1) += -xct[0]; + *(here->SOI3TOUT1_toutPtr + 1) += -xct[0]; + *(here->SOI3TOUT1_tout1Ptr + 1) += xct[0]+xct[1]; + } + if (here->SOI3numThermalNodes > 2) + { + *(here->SOI3TOUT1_tout2Ptr + 1) += -xct[1]; + *(here->SOI3TOUT2_tout1Ptr + 1) += -xct[1]; + *(here->SOI3TOUT2_tout2Ptr + 1) += xct[1]+xct[2]; + } + if (here->SOI3numThermalNodes > 3) + { + *(here->SOI3TOUT2_tout3Ptr + 1) += -xct[2]; + *(here->SOI3TOUT3_tout2Ptr + 1) += -xct[2]; + *(here->SOI3TOUT3_tout3Ptr + 1) += xct[2]+xct[3]; + } + if (here->SOI3numThermalNodes > 4) + { + *(here->SOI3TOUT3_tout4Ptr + 1) += -xct[3]; + *(here->SOI3TOUT4_tout3Ptr + 1) += -xct[3]; + *(here->SOI3TOUT4_tout4Ptr + 1) += xct[3]+xct[4]; + } + *(here->SOI3GF_toutPtr + 1) += xcgfdeltaT*model->SOI3type; + *(here->SOI3DP_toutPtr + 1) += (xcddeltaT - xcBJTbddeltaT)*model->SOI3type; + *(here->SOI3SP_toutPtr + 1) += (xcsdeltaT - xcBJTbsdeltaT)*model->SOI3type; + *(here->SOI3B_toutPtr + 1) += model->SOI3type* + (xcbdeltaT + xcBJTbsdeltaT + xcBJTbddeltaT); + } + + + /* and now real part */ + *(here->SOI3D_dPtr) += (here->SOI3drainConductance); + *(here->SOI3S_sPtr) += (here->SOI3sourceConductance); + *(here->SOI3B_bPtr) += (here->SOI3gbd+here->SOI3gbs - + here->SOI3gMmbs + - here->SOI3gBJTdb_bs - here->SOI3gBJTsb_bd); + + *(here->SOI3DP_dpPtr) += + (here->SOI3drainConductance+here->SOI3gds+ + here->SOI3gbd+xrev*(here->SOI3gmf+here->SOI3gmbs+ + here->SOI3gmb)+xnrm*here->SOI3gMd); + *(here->SOI3SP_spPtr) += + (here->SOI3sourceConductance+here->SOI3gds+ + here->SOI3gbs+xnrm*(here->SOI3gmf+here->SOI3gmbs+ + here->SOI3gmb)+xrev*here->SOI3gMd); + + *(here->SOI3D_dpPtr) += (-here->SOI3drainConductance); + + *(here->SOI3S_spPtr) += (-here->SOI3sourceConductance); + *(here->SOI3B_gfPtr) += -here->SOI3gMmf; + *(here->SOI3B_gbPtr) += -(here->SOI3gMmb); + *(here->SOI3B_dpPtr) += -(here->SOI3gbd) + here->SOI3gBJTsb_bd + + xrev*(here->SOI3gMmf+here->SOI3gMmb+ + here->SOI3gMmbs+here->SOI3gMd) - + xnrm*here->SOI3gMd; + *(here->SOI3B_spPtr) += -(here->SOI3gbs) + here->SOI3gBJTdb_bs + + xnrm*(here->SOI3gMmf+here->SOI3gMmb+ + here->SOI3gMmbs+here->SOI3gMd) - + xrev*here->SOI3gMd; + *(here->SOI3DP_dPtr) += (-here->SOI3drainConductance); + *(here->SOI3SP_sPtr) += (-here->SOI3sourceConductance); + + *(here->SOI3DP_gfPtr) += ((xnrm-xrev)*here->SOI3gmf + + xnrm*here->SOI3gMmf); + *(here->SOI3DP_gbPtr) += ((xnrm-xrev)*here->SOI3gmb + + xnrm*here->SOI3gMmb); + *(here->SOI3DP_bPtr) += (-here->SOI3gbd + here->SOI3gBJTdb_bs + +(xnrm-xrev)*here->SOI3gmbs+ + xnrm*here->SOI3gMmbs); + *(here->SOI3DP_spPtr) += (-here->SOI3gds - here->SOI3gBJTdb_bs + -xnrm*(here->SOI3gmf+here->SOI3gmb+here->SOI3gmbs + + here->SOI3gMmf+here->SOI3gMmb+here->SOI3gMmbs+here->SOI3gMd)); + + *(here->SOI3SP_gfPtr) += (-(xnrm-xrev)*here->SOI3gmf+ + xrev*here->SOI3gMmf); + *(here->SOI3SP_gbPtr) += (-(xnrm-xrev)*here->SOI3gmb+ + xrev*here->SOI3gMmb); + *(here->SOI3SP_bPtr) += (-here->SOI3gbs + here->SOI3gBJTsb_bd + -(xnrm-xrev)*here->SOI3gmbs+ + xrev*here->SOI3gMmbs); + *(here->SOI3SP_dpPtr) += (-here->SOI3gds - here->SOI3gBJTsb_bd + -xrev*(here->SOI3gmf+here->SOI3gmb+here->SOI3gmbs+ + here->SOI3gMmf+here->SOI3gMmb+here->SOI3gMmbs+here->SOI3gMd)); + +/* if no thermal behaviour specified, then put in zero valued indpt. voltage source + between TOUT and ground */ + if (here->SOI3rt==0) + { + *(here->SOI3TOUT_ibrPtr) += 1.0; + *(here->SOI3IBR_toutPtr) += 1.0; + *(ckt->CKTrhs + (here->SOI3branch)) = 0; + } + else + { + *(here->SOI3TOUT_toutPtr) += -(here->SOI3gPdT)+grt[0]; + if (here->SOI3numThermalNodes > 1) + { + *(here->SOI3TOUT_tout1Ptr) += -grt[0]; + *(here->SOI3TOUT1_toutPtr) += -grt[0]; + *(here->SOI3TOUT1_tout1Ptr) += grt[0]+grt[1]; + } + if (here->SOI3numThermalNodes > 2) + { + *(here->SOI3TOUT1_tout2Ptr) += -grt[1]; + *(here->SOI3TOUT2_tout1Ptr) += -grt[1]; + *(here->SOI3TOUT2_tout2Ptr) += grt[1]+grt[2]; + } + if (here->SOI3numThermalNodes > 3) + { + *(here->SOI3TOUT2_tout3Ptr) += -grt[2]; + *(here->SOI3TOUT3_tout2Ptr) += -grt[2]; + *(here->SOI3TOUT3_tout3Ptr) += grt[2]+grt[3]; + } + if (here->SOI3numThermalNodes > 4) + { + *(here->SOI3TOUT3_tout4Ptr) += -grt[3]; + *(here->SOI3TOUT4_tout3Ptr) += -grt[3]; + *(here->SOI3TOUT4_tout4Ptr) += grt[3]+grt[4]; + } + + *(here->SOI3TOUT_dpPtr) += xnrm*(-(here->SOI3gPds*model->SOI3type)) + +xrev*(here->SOI3gPds+here->SOI3gPmf+ + here->SOI3gPmb+here->SOI3gPmbs)* + model->SOI3type; + *(here->SOI3TOUT_gfPtr) += -(here->SOI3gPmf*model->SOI3type); + *(here->SOI3TOUT_gbPtr) += -(here->SOI3gPmb*model->SOI3type); + *(here->SOI3TOUT_bPtr) += -(here->SOI3gPmbs*model->SOI3type); + *(here->SOI3TOUT_spPtr) += xnrm*(here->SOI3gPds+here->SOI3gPmf+ + here->SOI3gPmb+here->SOI3gPmbs)*model->SOI3type + +xrev*(-(here->SOI3gPds*model->SOI3type)); + + *(here->SOI3DP_toutPtr) += (xnrm-xrev)*here->SOI3gt*model->SOI3type; + *(here->SOI3SP_toutPtr) += (xrev-xnrm)*here->SOI3gt*model->SOI3type; +/* need to mult by type in above as conductances will be used with exterior voltages + which will be -ve for PMOS except for gPdT */ +/* now for thermal influence on impact ionisation current and tranisent stuff */ + *(here->SOI3DP_toutPtr) += (xnrm*here->SOI3gMdeltaT - + here->SOI3gbdT + here->SOI3gBJTdb_deltaT)*model->SOI3type; + *(here->SOI3SP_toutPtr) += (xrev*here->SOI3gMdeltaT - + here->SOI3gbsT + here->SOI3gBJTsb_deltaT)*model->SOI3type; + *(here->SOI3B_toutPtr) -= (here->SOI3gMdeltaT - here->SOI3gbsT - + here->SOI3gbdT + here->SOI3gBJTdb_deltaT + + here->SOI3gBJTsb_deltaT)*model->SOI3type; + } + } + } + return(OK); +} diff --git a/src/spicelib/devices/soi3/soi3ask.c b/src/spicelib/devices/soi3/soi3ask.c new file mode 100644 index 000000000..f284e6ae5 --- /dev/null +++ b/src/spicelib/devices/soi3/soi3ask.c @@ -0,0 +1,505 @@ +/********** +STAG version 2.6 +Copyright 2000 owned by the United Kingdom Secretary of State for Defence +acting through the Defence Evaluation and Research Agency. +Developed by : Jim Benson, + Department of Electronics and Computer Science, + University of Southampton, + United Kingdom. +With help from : Nele D'Halleweyn, Bill Redman-White, and Craig Easson. + +Based on STAG version 2.1 +Developed by : Mike Lee, +With help from : Bernard Tenbroek, Bill Redman-White, Mike Uren, Chris Edwards + and John Bunyan. +Acknowledgements : Rupert Howes and Pete Mole. +**********/ + +/* Modified: 2001 Paolo Nenzi */ + +#include "ngspice.h" +#include +#include "const.h" +#include "ifsim.h" +#include "cktdefs.h" +#include "devdefs.h" +#include "soi3defs.h" +#include "sperror.h" +#include "suffix.h" + + +/*ARGSUSED*/ +int +SOI3ask(ckt,inst,which,value,select) + CKTcircuit *ckt; + GENinstance *inst; + int which; + IFvalue *value; + IFvalue *select; +{ + SOI3instance *here = (SOI3instance*)inst; + double vr; + double vi; + double sr; + double si; + double vm; + static char *msg = "Current and power not available for ac analysis"; + switch(which) { + case SOI3_L: + value->rValue = here->SOI3l; + return(OK); + case SOI3_W: + value->rValue = here->SOI3w; + return(OK); + case SOI3_NRS: + value->rValue = here->SOI3sourceSquares; + return(OK); + case SOI3_NRD: + value->rValue = here->SOI3drainSquares; + return(OK); + case SOI3_OFF: + value->rValue = here->SOI3off; + return(OK); + case SOI3_IC_VDS: + value->rValue = here->SOI3icVDS; + return(OK); + case SOI3_IC_VGFS: + value->rValue = here->SOI3icVGFS; + return(OK); + case SOI3_IC_VGBS: + value->rValue = here->SOI3icVGBS; + return(OK); + case SOI3_IC_VBS: + value->rValue = here->SOI3icVBS; + return(OK); + case SOI3_TEMP: + value->rValue = here->SOI3temp-CONSTCtoK; + return(OK); + case SOI3_RT: + value->rValue = here->SOI3rt; + return(OK); + case SOI3_CT: + value->rValue = here->SOI3ct; + return(OK); + case SOI3_DNODE: + value->iValue = here->SOI3dNode; + return(OK); + case SOI3_GFNODE: + value->iValue = here->SOI3gfNode; + return(OK); + case SOI3_SNODE: + value->iValue = here->SOI3sNode; + return(OK); + case SOI3_GBNODE: + value->iValue = here->SOI3gbNode; + return(OK); + case SOI3_BNODE: + value->iValue = here->SOI3bNode; + return(OK); + case SOI3_DNODEPRIME: + value->iValue = here->SOI3dNodePrime; + return(OK); + case SOI3_SNODEPRIME: + value->iValue = here->SOI3sNodePrime; + return(OK); + case SOI3_TNODE: + value->iValue = here->SOI3toutNode; + return(OK); + case SOI3_BRANCH: + value->iValue = here->SOI3branch; + return(OK); + case SOI3_SOURCECONDUCT: + value->rValue = here->SOI3sourceConductance; + return(OK); + case SOI3_DRAINCONDUCT: + value->rValue = here->SOI3drainConductance; + return(OK); + case SOI3_VON: + value->rValue = here->SOI3tVto; + return(OK); + case SOI3_VFBF: + value->rValue = here->SOI3tVfbF; + return(OK); + case SOI3_VDSAT: + value->rValue = here->SOI3vdsat; + return(OK); + case SOI3_SOURCEVCRIT: + value->rValue = here->SOI3sourceVcrit; + return(OK); + case SOI3_DRAINVCRIT: + value->rValue = here->SOI3drainVcrit; + return(OK); + case SOI3_ID: + value->rValue = here->SOI3id; + return(OK); + case SOI3_IBS: + value->rValue = here->SOI3ibs; + return(OK); + case SOI3_IBD: + value->rValue = here->SOI3ibd; + return(OK); + case SOI3_GMBS: + value->rValue = here->SOI3gmbs; + return(OK); + case SOI3_GMF: + value->rValue = here->SOI3gmf; + return(OK); + case SOI3_GMB: + value->rValue = here->SOI3gmb; + return(OK); + case SOI3_GDS: + value->rValue = here->SOI3gds; + return(OK); + case SOI3_GBD: + value->rValue = here->SOI3gbd; + return(OK); + case SOI3_GBS: + value->rValue = here->SOI3gbs; + return(OK); + case SOI3_CAPBD: + value->rValue = here->SOI3capbd; + return(OK); + case SOI3_CAPBS: + value->rValue = here->SOI3capbs; + return(OK); + case SOI3_CAPZEROBIASBD: + value->rValue = here->SOI3Cbd; + return(OK); + case SOI3_CAPZEROBIASBS: + value->rValue = here->SOI3Cbs; + return(OK); + case SOI3_VBD: + value->rValue = *(ckt->CKTstate0 + here->SOI3vbd); + return(OK); + case SOI3_VBS: + value->rValue = *(ckt->CKTstate0 + here->SOI3vbs); + return(OK); + case SOI3_VGFS: + value->rValue = *(ckt->CKTstate0 + here->SOI3vgfs); + return(OK); + case SOI3_VGBS: + value->rValue = *(ckt->CKTstate0 + here->SOI3vgbs); + return(OK); + case SOI3_VDS: + value->rValue = *(ckt->CKTstate0 + here->SOI3vds); + return(OK); + case SOI3_QGF: + value->rValue = *(ckt->CKTstate0 + here->SOI3qgf); + return(OK); + case SOI3_IQGF: + value->rValue = *(ckt->CKTstate0 + here->SOI3iqgf); + return(OK); + case SOI3_QD: + value->rValue = *(ckt->CKTstate0 + here->SOI3qd); + return(OK); + case SOI3_IQD: + value->rValue = *(ckt->CKTstate0 + here->SOI3iqd); + return(OK); + case SOI3_QS: + value->rValue = *(ckt->CKTstate0 + here->SOI3qs); + return(OK); + case SOI3_IQS: + value->rValue = *(ckt->CKTstate0 + here->SOI3iqs); + return(OK); + case SOI3_CGFGF: + value->rValue = *(ckt->CKTstate0 + here->SOI3cgfgf); + return (OK); + case SOI3_CGFD: + value->rValue = *(ckt->CKTstate0 + here->SOI3cgfd); + return (OK); + case SOI3_CGFS: + value->rValue = *(ckt->CKTstate0 + here->SOI3cgfs); + return (OK); + case SOI3_CGFDELTAT: + value->rValue = *(ckt->CKTstate0 + here->SOI3cgfdeltaT); + return (OK); + case SOI3_CDGF: + value->rValue = *(ckt->CKTstate0 + here->SOI3cdgf); + return (OK); + case SOI3_CDD: + value->rValue = *(ckt->CKTstate0 + here->SOI3cdd); + return (OK); + case SOI3_CDS: + value->rValue = *(ckt->CKTstate0 + here->SOI3cds); + return (OK); + case SOI3_CDDELTAT: + value->rValue = *(ckt->CKTstate0 + here->SOI3cddeltaT); + return (OK); + case SOI3_CSGF: + value->rValue = *(ckt->CKTstate0 + here->SOI3csgf); + return (OK); + case SOI3_CSD: + value->rValue = *(ckt->CKTstate0 + here->SOI3csd); + return (OK); + case SOI3_CSS: + value->rValue = *(ckt->CKTstate0 + here->SOI3css); + return (OK); + case SOI3_CSDELTAT: + value->rValue = *(ckt->CKTstate0 + here->SOI3csdeltaT); + return (OK); + case SOI3_QBD: + value->rValue = *(ckt->CKTstate0 + here->SOI3qbd); + return(OK); + case SOI3_IQBD: + value->rValue = *(ckt->CKTstate0 + here->SOI3iqbd); + return(OK); + case SOI3_QBS: + value->rValue = *(ckt->CKTstate0 + here->SOI3qbs); + return(OK); + case SOI3_IQBS: + value->rValue = *(ckt->CKTstate0 + here->SOI3iqbs); + return(OK); +/* extra stuff for newer model - msll Jan96 */ + case SOI3_VFBB: + value->rValue = here->SOI3tVfbB; + return(OK); + case SOI3_RT1: + value->rValue = here->SOI3rt1; + return(OK); + case SOI3_CT1: + value->rValue = here->SOI3ct1; + return(OK); + case SOI3_RT2: + value->rValue = here->SOI3rt2; + return(OK); + case SOI3_CT2: + value->rValue = here->SOI3ct2; + return(OK); + case SOI3_RT3: + value->rValue = here->SOI3rt3; + return(OK); + case SOI3_CT3: + value->rValue = here->SOI3ct3; + return(OK); + case SOI3_RT4: + value->rValue = here->SOI3rt4; + return(OK); + case SOI3_CT4: + value->rValue = here->SOI3ct4; + return(OK); + +/* + case SOI3_L_SENS_DC: + if(ckt->CKTsenInfo && here->SOI3sens_l){ + value->rValue = *(ckt->CKTsenInfo->SEN_Sap[select->iValue + 1]+ + here->SOI3senParmNo); + } + return(OK); + case SOI3_L_SENS_REAL: + if(ckt->CKTsenInfo && here->SOI3sens_l){ + value->rValue = *(ckt->CKTsenInfo->SEN_RHS[select->iValue + 1]+ + here->SOI3senParmNo); + } + return(OK); + case SOI3_L_SENS_IMAG: + if(ckt->CKTsenInfo && here->SOI3sens_l){ + value->rValue = *(ckt->CKTsenInfo->SEN_iRHS[select->iValue + 1]+ + here->SOI3senParmNo); + } + return(OK); + case SOI3_L_SENS_MAG: + if(ckt->CKTsenInfo && here->SOI3sens_l){ + vr = *(ckt->CKTrhsOld + select->iValue + 1); + vi = *(ckt->CKTirhsOld + select->iValue + 1); + vm = sqrt(vr*vr + vi*vi); + if(vm == 0){ + value->rValue = 0; + return(OK); + } + sr = *(ckt->CKTsenInfo->SEN_RHS[select->iValue + 1]+ + here->SOI3senParmNo); + si = *(ckt->CKTsenInfo->SEN_iRHS[select->iValue + 1]+ + here->SOI3senParmNo); + value->rValue = (vr * sr + vi * si)/vm; + } + return(OK); + case SOI3_L_SENS_PH: + if(ckt->CKTsenInfo && here->SOI3sens_l){ + vr = *(ckt->CKTrhsOld + select->iValue + 1); + vi = *(ckt->CKTirhsOld + select->iValue + 1); + vm = vr*vr + vi*vi; + if(vm == 0){ + value->rValue = 0; + return(OK); + } + sr = *(ckt->CKTsenInfo->SEN_RHS[select->iValue + 1]+ + here->SOI3senParmNo); + si = *(ckt->CKTsenInfo->SEN_iRHS[select->iValue + 1]+ + here->SOI3senParmNo); + value->rValue = (vr * si - vi * sr)/vm; + } + return(OK); + case SOI3_L_SENS_CPLX: + if(ckt->CKTsenInfo && here->SOI3sens_l){ + value->cValue.real= + *(ckt->CKTsenInfo->SEN_RHS[select->iValue + 1]+ + here->SOI3senParmNo); + value->cValue.imag= + *(ckt->CKTsenInfo->SEN_iRHS[select->iValue + 1]+ + here->SOI3senParmNo); + } + return(OK); + case SOI3_W_SENS_DC: + if(ckt->CKTsenInfo && here->SOI3sens_w){ + value->rValue = *(ckt->CKTsenInfo->SEN_Sap[select->iValue + 1]+ + here->SOI3senParmNo + here->SOI3sens_l); + } + return(OK); + case SOI3_W_SENS_REAL: + if(ckt->CKTsenInfo && here->SOI3sens_w){ + value->rValue = *(ckt->CKTsenInfo->SEN_RHS[select->iValue + 1]+ + here->SOI3senParmNo + here->SOI3sens_l); + } + return(OK); + case SOI3_W_SENS_IMAG: + if(ckt->CKTsenInfo && here->SOI3sens_w){ + value->rValue = *(ckt->CKTsenInfo->SEN_iRHS[select->iValue + 1]+ + here->SOI3senParmNo + here->SOI3sens_l); + } + return(OK); + case SOI3_W_SENS_MAG: + if(ckt->CKTsenInfo && here->SOI3sens_w){ + vr = *(ckt->CKTrhsOld + select->iValue + 1); + vi = *(ckt->CKTirhsOld + select->iValue + 1); + vm = sqrt(vr*vr + vi*vi); + if(vm == 0){ + value->rValue = 0; + return(OK); + } + sr = *(ckt->CKTsenInfo->SEN_RHS[select->iValue + 1]+ + here->SOI3senParmNo + here->SOI3sens_l); + si = *(ckt->CKTsenInfo->SEN_iRHS[select->iValue + 1]+ + here->SOI3senParmNo + here->SOI3sens_l); + value->rValue = (vr * sr + vi * si)/vm; + } + return(OK); + case SOI3_W_SENS_PH: + if(ckt->CKTsenInfo && here->SOI3sens_w){ + vr = *(ckt->CKTrhsOld + select->iValue + 1); + vi = *(ckt->CKTirhsOld + select->iValue + 1); + vm = vr*vr + vi*vi; + if(vm == 0){ + value->rValue = 0; + return(OK); + } + sr = *(ckt->CKTsenInfo->SEN_RHS[select->iValue + 1]+ + here->SOI3senParmNo + here->SOI3sens_l); + si = *(ckt->CKTsenInfo->SEN_iRHS[select->iValue + 1]+ + here->SOI3senParmNo + here->SOI3sens_l); + value->rValue = (vr * si - vi * sr)/vm; + } + return(OK); + case SOI3_W_SENS_CPLX: + if(ckt->CKTsenInfo && here->SOI3sens_w){ + value->cValue.real= + *(ckt->CKTsenInfo->SEN_RHS[select->iValue + 1]+ + here->SOI3senParmNo + here->SOI3sens_l); + value->cValue.imag= + *(ckt->CKTsenInfo->SEN_iRHS[select->iValue + 1]+ + here->SOI3senParmNo + here->SOI3sens_l); + } + return(OK); */ + +/* + case SOI3_IS : + if (ckt->CKTcurrentAnalysis & DOING_AC) { + errMsg = MALLOC(strlen(msg)+1); + errRtn = "SOI3ask.c"; + strcpy(errMsg,msg); + return(E_ASKCURRENT); + } else { + value->rValue = -here->SOI3id; + value->rValue -= here->SOI3ibd + here->SOI3ibs - + *(ckt->CKTstate0 + here->SOI3iqgfb); + if ((ckt->CKTcurrentAnalysis & DOING_TRAN) && + !(ckt->CKTmode & MODETRANOP)) { + value->rValue -= *(ckt->CKTstate0 + here->SOI3iqgfb) + + *(ckt->CKTstate0 + here->SOI3iqgfd) + + *(ckt->CKTstate0 + here->SOI3iqgfs); + } + } + return(OK); + case SOI3_IB : + if (ckt->CKTcurrentAnalysis & DOING_AC) { + errMsg = MALLOC(strlen(msg)+1); + errRtn = "SOI3ask.c"; + strcpy(errMsg,msg); + return(E_ASKCURRENT); + } else { + value->rValue = here->SOI3ibd + here->SOI3ibs - + *(ckt->CKTstate0 + here->SOI3iqgfb); + } + return(OK); + case SOI3_IGF : + if (ckt->CKTcurrentAnalysis & DOING_AC) { + errMsg = MALLOC(strlen(msg)+1); + errRtn = "SOI3ask.c"; + strcpy(errMsg,msg); + return(E_ASKCURRENT); + } else if (ckt->CKTcurrentAnalysis & (DOING_DCOP | DOING_TRCV)) { + value->rValue = 0; + } else if ((ckt->CKTcurrentAnalysis & DOING_TRAN) && + (ckt->CKTmode & MODETRANOP)) { + value->rValue = 0; + } else { + value->rValue = *(ckt->CKTstate0 + here->SOI3iqgfb) + + *(ckt->CKTstate0 + here->SOI3iqgfd) + *(ckt->CKTstate0 + + here->SOI3iqgfs); + } + return(OK); + case SOI3_IGB : + if (ckt->CKTcurrentAnalysis & DOING_AC) { + errMsg = MALLOC(strlen(msg)+1); + errRtn = "SOI3ask.c"; + strcpy(errMsg,msg); + return(E_ASKCURRENT); + } else if (ckt->CKTcurrentAnalysis & (DOING_DCOP | DOING_TRCV)) { + value->rValue = 0; + } else if ((ckt->CKTcurrentAnalysis & DOING_TRAN) && + (ckt->CKTmode & MODETRANOP)) { + value->rValue = 0; + } else { + value->rValue = *(ckt->CKTstate0 + here->SOI3iqgfb) + + *(ckt->CKTstate0 + here->SOI3iqgfd) + *(ckt->CKTstate0 + + here->SOI3iqgfs); + } + return(OK); + case SOI3_POWER : + if (ckt->CKTcurrentAnalysis & DOING_AC) { + errMsg = MALLOC(strlen(msg)+1); + errRtn = "SOI3ask.c"; + strcpy(errMsg,msg); + return(E_ASKPOWER); + } else { + double temp; + + value->rValue = here->SOI3id * + *(ckt->CKTrhsOld + here->SOI3dNode); + value->rValue += ((here->SOI3ibd + here->SOI3ibs) - + *(ckt->CKTstate0 + here->SOI3iqgfb)) * + *(ckt->CKTrhsOld + here->SOI3bNode); + if ((ckt->CKTcurrentAnalysis & DOING_TRAN) && + !(ckt->CKTmode & MODETRANOP)) { + value->rValue += (*(ckt->CKTstate0 + here->SOI3iqgfb) + + *(ckt->CKTstate0 + here->SOI3iqgfd) + + *(ckt->CKTstate0 + here->SOI3iqgfs)) * + *(ckt->CKTrhsOld + here->SOI3gfNode); + } + temp = -here->SOI3id; + temp -= here->SOI3ibd + here->SOI3ibs ; + if ((ckt->CKTcurrentAnalysis & DOING_TRAN) && + !(ckt->CKTmode & MODETRANOP)) { + temp -= *(ckt->CKTstate0 + here->SOI3iqgfb) + + *(ckt->CKTstate0 + here->SOI3iqgfd) + + *(ckt->CKTstate0 + here->SOI3iqgfs); + } + value->rValue += temp * *(ckt->CKTrhsOld + here->SOI3sNode); + } + return(OK); +*/ + default: + return(E_BADPARM); + } + /* NOTREACHED */ +} + diff --git a/src/spicelib/devices/soi3/soi3cap.c b/src/spicelib/devices/soi3/soi3cap.c new file mode 100644 index 000000000..351bb03d6 --- /dev/null +++ b/src/spicelib/devices/soi3/soi3cap.c @@ -0,0 +1,590 @@ +/********** +STAG version 2.6 +Copyright 2000 owned by the United Kingdom Secretary of State for Defence +acting through the Defence Evaluation and Research Agency. +Developed by : Jim Benson, + Department of Electronics and Computer Science, + University of Southampton, + United Kingdom. +With help from : Nele D'Halleweyn, Bill Redman-White, and Craig Easson. + +Based on STAG version 2.1 +Developed by : Mike Lee, +With help from : Bernard Tenbroek, Bill Redman-White, Mike Uren, Chris Edwards + and John Bunyan. +Acknowledgements : Rupert Howes and Pete Mole. +**********/ + +/* Modified: 2001 Paolo Nenzi */ + +#include "ngspice.h" +#include "cktdefs.h" +#include "suffix.h" +#include "soi3defs.h" +#include "trandefs.h" +#include "const.h" + + +void +SOI3cap(vgB,Phiplusvsb,gammaB, + paramargs, + Bfargs,alpha_args,psi_st0args, + vGTargs, + psi_sLargs,psi_s0args, + ldargs, + Qg,Qb,Qd,QgB, + cggf,cgd,cgs,cgdeltaT, + cbgf,cbd,cbs,cbdeltaT,cbgb, + cdgf,cdd,cds,cddeltaT, + cgbgb,cgbsb + ) + +double vgB,Phiplusvsb,gammaB; +double paramargs[10]; +double Bfargs[2],alpha_args[5]; +double psi_st0args[5]; +double vGTargs[5]; +double psi_sLargs[5],psi_s0args[5]; +double ldargs[5]; + +double *Qg,*Qb,*Qd,*QgB; +double *cggf,*cgd,*cgs,*cgdeltaT; +double *cbgf,*cbd,*cbs,*cbdeltaT,*cbgb; +double *cdgf,*cdd,*cds,*cddeltaT; +double *cgbgb,*cgbsb; + + +/****** Part 1 - declare local variables. ******/ + +{ +double WCox,WCob,L; +double gamma,eta_s,vt,delta,sigma,chiFB; +double Bf,pDBf_Dpsi_st0; +double alpha,Dalpha_Dvgfb,Dalpha_Dvdb,Dalpha_Dvsb,Dalpha_DdeltaT; +double Dpsi_st0_Dvgfb,Dpsi_st0_Dvdb,Dpsi_st0_Dvsb,Dpsi_st0_DdeltaT; +double vGT,DvGT_Dvgfb,DvGT_Dvdb,DvGT_Dvsb,DvGT_DdeltaT; +double psi_sL,Dpsi_sL_Dvgfb,Dpsi_sL_Dvdb,Dpsi_sL_Dvsb,Dpsi_sL_DdeltaT; +double psi_s0,Dpsi_s0_Dvgfb,Dpsi_s0_Dvdb,Dpsi_s0_Dvsb,Dpsi_s0_DdeltaT; +double ld,Dld_Dvgfb,Dld_Dvdb,Dld_Dvsb,Dld_DdeltaT; + +double Lprime,Fc; +double Qbprime,Qcprime,Qdprime,Qgprime,Qb2prime,Qc2prime,Qd2prime,Qg2prime; +double Dlimc,Dlimd; +double Vqd,Vqs; +double F,F2; +double cq,dq; +double dercq,derdq; +double sigmaC,Eqc,Eqd; +double DVqs_Dvgfb,DVqs_Dvdb,DVqs_Dvsb,DVqs_DdeltaT; +double DF_Dvgfb,DF_Dvdb,DF_Dvsb,DF_DdeltaT; +double ccgf,ccd,ccs,ccdeltaT; + +double A0B,EA0B,tmpsb; +double Vgmax0B,VgBx0,EBmax0,tmpmax0,tmpmaxsb; +double VgBy0,EBy0,tmpmin0; +double SgB0; + +double vg,vgacc,Egacc,tmpacc,Qacc; +double csf; + +/****** Part 2 - extract variables passed from soi3load(), which ******/ +/****** have been passed to soi3cap() in *arg arrays. ******/ + +WCox = paramargs[0]; +L = paramargs[1]; +gamma = paramargs[2]; +eta_s = paramargs[3]; +vt = paramargs[4]; +delta = paramargs[5]; +WCob = paramargs[6]; +sigma = paramargs[7]; +chiFB = paramargs[8]; +csf = paramargs[9]; +Bf = Bfargs[0]; +pDBf_Dpsi_st0 = Bfargs[1]; +alpha = alpha_args[0]; +Dalpha_Dvgfb = alpha_args[1]; +Dalpha_Dvdb = alpha_args[2]; +Dalpha_Dvsb = alpha_args[3]; +Dalpha_DdeltaT = alpha_args[4]; + +Dpsi_st0_Dvgfb = psi_st0args[1]; +Dpsi_st0_Dvdb = psi_st0args[2]; +Dpsi_st0_Dvsb = psi_st0args[3]; +Dpsi_st0_DdeltaT = psi_st0args[4]; + +vGT = vGTargs[0]; +DvGT_Dvgfb = vGTargs[1]; +DvGT_Dvdb = vGTargs[2]; +DvGT_Dvsb = vGTargs[3]; +DvGT_DdeltaT = vGTargs[4]; + +psi_sL = psi_sLargs[0]; +Dpsi_sL_Dvgfb = psi_sLargs[1]; +Dpsi_sL_Dvdb = psi_sLargs[2]; +Dpsi_sL_Dvsb = psi_sLargs[3]; +Dpsi_sL_DdeltaT = psi_sLargs[4]; +psi_s0 = psi_s0args[0]; +Dpsi_s0_Dvgfb = psi_s0args[1]; +Dpsi_s0_Dvdb = psi_s0args[2]; +Dpsi_s0_Dvsb = psi_s0args[3]; +Dpsi_s0_DdeltaT = psi_s0args[4]; +ld = ldargs[0]; +Dld_Dvgfb = ldargs[1]; +Dld_Dvdb = ldargs[2]; +Dld_Dvsb = ldargs[3]; +Dld_DdeltaT = ldargs[4]; + + +/****** Part 3 - define some important quantities. ******/ + +sigmaC = 1E-8; + +Vqd = (vGT - alpha*psi_sL); /* This is -qd/Cof */ +Vqs = (vGT - alpha*psi_s0); /* This is -qs/Cof */ +if (Vqs<=0) { /* deep subthreshold contingency */ + F = 1; +} else { + F = Vqd/Vqs; + if (F<0) { /* physically impossible situation */ + F=0; + } +} +F2 = F*F; + +Fc = 1 + ld/L; +Lprime = L/Fc; + + +/****** Part 4 - calculate normalised (see note below) terminal ******/ +/****** charge expressions for the GCA region. ******/ + +/* JimB - important note */ +/* The charge expressions Qcprime, Qd2prime etc in this file are not charges */ +/* but voltages! Each expression is equal to the derived expression for the */ +/* total charge in each region, but divided by a factor WL'Cof. This is */ +/* compensated for later on. */ + +/* Channel charge Qc1 */ +cq = (F*F + F + 1)/(F+1); +Qcprime = -2*Vqs*cq/3; + +if ((-Qcprime/sigmaC) MAX_EXP_ARG) { + vgacc = vg; + tmpacc = 1; +} else { + Egacc = exp(-vg/vt); + vgacc = -vt*log(1+Egacc); + tmpacc = Egacc/(1+Egacc); +} +Qacc = -WCox*L*vgacc; + +/* Now work out GCA region charges */ + +*Qb = WCox*Lprime*Qbprime + Qacc; + +*Qd = WCox*Lprime*Qdprime; + +*Qg = WCox*Lprime*Qgprime - Qacc; + + +/****** Part 7 - calculate normalised (see note below) terminal ******/ +/****** charge expressions for the saturated drain region. ******/ + +Qc2prime = -Vqd; + +/* Basic expression for the intrinsic body charge in the saturation region is */ +/* modified by csf, to reflect the fact that the body charge will be shared */ +/* between the gate and the drain/body depletion region. This factor must be */ +/* between 0 and 1, since it represents the fraction of ld over which qb is */ +/* integrated to give Qb2. */ +Qb2prime = -gamma*csf*(Bf + delta*psi_sL); + +Qd2prime = 0.5*Qc2prime; +/* JimB - 9/1/99. Re-partition drain region charge */ +/* Qd2prime = Qc2prime; */ + +Qg2prime = -Qc2prime-Qb2prime; + +*Qb += WCox*ld*Qb2prime; +*Qd += WCox*ld*Qd2prime; +*Qg += WCox*ld*Qg2prime; + + +/****** Part 8 - calculate full capacitance expressions, accounting ******/ +/****** for both GCA and drain region contributions. As explained ******/ +/****** in part 5, *cbgf, *cbd etc only derivatives of GCA charge ******/ +/****** expression w.r.t. Vx. Now need to include Lprime/ld ******/ +/****** dependence on Vx as well. ******/ + +*cbgf = WCox*(Lprime*(*cbgf) - ld*csf*(pDBf_Dpsi_st0*Dpsi_st0_Dvgfb + delta*Dpsi_sL_Dvgfb + + (psi_sL*Dalpha_Dvgfb/gamma)) + + (Qb2prime - Qbprime/(Fc*Fc))*Dld_Dvgfb + ); +*cbd = WCox*(Lprime*(*cbd) - ld*csf*(pDBf_Dpsi_st0*Dpsi_st0_Dvdb + delta*Dpsi_sL_Dvdb + + (psi_sL*Dalpha_Dvdb/gamma)) + + (Qb2prime - Qbprime/(Fc*Fc))*Dld_Dvdb + ); +*cbs = WCox*(Lprime*(*cbs) - ld*csf*(pDBf_Dpsi_st0*Dpsi_st0_Dvsb + delta*Dpsi_sL_Dvsb + + (psi_sL*Dalpha_Dvsb/gamma)) + + (Qb2prime - Qbprime/(Fc*Fc))*Dld_Dvsb + ); +*cbdeltaT = WCox*(Lprime*(*cbdeltaT) - ld*csf*(pDBf_Dpsi_st0*Dpsi_st0_DdeltaT + delta*Dpsi_sL_DdeltaT + + (psi_sL*Dalpha_DdeltaT/gamma)) + + (Qb2prime - Qbprime/(Fc*Fc))*Dld_DdeltaT + ); + + +ccgf = WCox*(Lprime*(ccgf) - ld*(DvGT_Dvgfb - alpha*Dpsi_sL_Dvgfb - psi_sL*Dalpha_Dvgfb) + + (Qc2prime - Qcprime/(Fc*Fc))*Dld_Dvgfb + ); +ccd = WCox*(Lprime*(ccd) - ld*(DvGT_Dvdb - alpha*Dpsi_sL_Dvdb - psi_sL*Dalpha_Dvdb) + + (Qc2prime - Qcprime/(Fc*Fc))*Dld_Dvdb + ); +ccs = WCox*(Lprime*(ccs) - ld*(DvGT_Dvsb - alpha*Dpsi_sL_Dvsb - psi_sL*Dalpha_Dvsb) + + (Qc2prime - Qcprime/(Fc*Fc))*Dld_Dvsb + ); +ccdeltaT = WCox*(Lprime*(ccdeltaT) - + ld*(DvGT_DdeltaT - alpha*Dpsi_sL_DdeltaT - psi_sL*Dalpha_DdeltaT) + + (Qc2prime - Qcprime/(Fc*Fc))*Dld_DdeltaT + ); + + +/* JimB - 9/1/99. Re-partition drain region charge */ + +/* +*cdgf = WCox*(Lprime*(*cdgf) - ld*(DvGT_Dvgfb - alpha*Dpsi_sL_Dvgfb - psi_sL*Dalpha_Dvgfb) + + (Qd2prime - Qdprime/(Fc*Fc))*Dld_Dvgfb + ); +*cdd = WCox*(Lprime*(*cdd) - ld*(DvGT_Dvdb - alpha*Dpsi_sL_Dvdb - psi_sL*Dalpha_Dvdb) + + (Qd2prime - Qdprime/(Fc*Fc))*Dld_Dvdb + ); +*cds = WCox*(Lprime*(*cds) - ld*(DvGT_Dvsb - alpha*Dpsi_sL_Dvsb - psi_sL*Dalpha_Dvsb) + + (Qd2prime - Qdprime/(Fc*Fc))*Dld_Dvsb + ); +*cddeltaT = WCox*(Lprime*(*cddeltaT) - ld*(DvGT_DdeltaT - + alpha*Dpsi_sL_DdeltaT - psi_sL*Dalpha_DdeltaT) + + (Qd2prime - Qdprime/(Fc*Fc))*Dld_DdeltaT + ); +*/ + +*cdgf = WCox*(Lprime*(*cdgf) - 0.5*ld*(DvGT_Dvgfb - alpha*Dpsi_sL_Dvgfb - psi_sL*Dalpha_Dvgfb) + + (Qd2prime - Qdprime/(Fc*Fc))*Dld_Dvgfb + ); +*cdd = WCox*(Lprime*(*cdd) - 0.5*ld*(DvGT_Dvdb - alpha*Dpsi_sL_Dvdb - psi_sL*Dalpha_Dvdb) + + (Qd2prime - Qdprime/(Fc*Fc))*Dld_Dvdb + ); +*cds = WCox*(Lprime*(*cds) - 0.5*ld*(DvGT_Dvsb - alpha*Dpsi_sL_Dvsb - psi_sL*Dalpha_Dvsb) + + (Qd2prime - Qdprime/(Fc*Fc))*Dld_Dvsb + ); +*cddeltaT = WCox*(Lprime*(*cddeltaT) - 0.5*ld*(DvGT_DdeltaT - + alpha*Dpsi_sL_DdeltaT - psi_sL*Dalpha_DdeltaT) + + (Qd2prime - Qdprime/(Fc*Fc))*Dld_DdeltaT + ); + + +/****** Part 9 - Finally, include accumulation charge derivatives. ******/ + +/* Now include accumulation charge derivs */ + +*cbgf += -WCox*L*tmpacc; +*cbd += -WCox*L*tmpacc*sigma; +*cbs += -WCox*L*tmpacc*(-sigma); +*cbdeltaT += -WCox*L*tmpacc*chiFB; + +*cggf = -(ccgf + *cbgf); +*cgd = -(ccd + *cbd); +*cgs = -(ccs + *cbs); +*cgdeltaT = -(ccdeltaT + *cbdeltaT); + + +/****** Part 10 - Back gate stuff - doesn't work, so commented out. ******/ + +/* front gate stuff is self consistent by itself, now add in back gate stuff + we're not too interested in EXACT back gate behaviour, so this is quite a + rough model. + But even this causes convergence problems in transient - so leave it out + for now. Scope for further work. +*/ +/* +if (Phiplusvsb > vt*MAX_EXP_ARG) { + A0B = Phiplusvsb; + tmpsb = 1; +} else { + EA0B = exp(Phiplusvsb/vt); + A0B = vt*log(1+EA0B); + tmpsb = EA0B/(1+EA0B); +} + +Vgmax0B = A0B + gammaB*sqrt(A0B); + +if ((Vgmax0B-vgB)>vt*MAX_EXP_ARG) { + VgBx0=vgB; + tmpmax0 = 1; + tmpmaxsb = 0; +} else { + EBmax0 = exp((Vgmax0B - vgB)/vt); + VgBx0=Vgmax0B - vt*log(1+EBmax0); + tmpmax0 = EBmax0/(1+EBmax0); + tmpmaxsb = 1/(1+EBmax0); +} + +if (VgBx0>vt*MAX_EXP_ARG) { + VgBy0 = VgBx0; + tmpmin0 = 1; +} else { + EBy0 = exp(VgBx0/vt); + VgBy0 = vt*log(1+EBy0); + tmpmin0 = EBy0/(1+EBy0); +} + +SgB0 = sqrt(gammaB*gammaB + 4*VgBy0); + +*QgB = -WCob*L*gammaB*0.5*(gammaB-SgB0); +*Qb -= *QgB; + +*cgbgb = (WCob*L*gammaB/SgB0)*tmpmin0*tmpmax0; +*cgbsb = (WCob*L*gammaB/SgB0)*tmpmin0*tmpmaxsb*(1+0.5*gammaB/sqrt(A0B))*tmpsb; + +*cbgb = -(*cgbgb); +*cbs -= *cgbsb; +*/ + +*QgB = 0; +*cbgb = 0; +*cgbgb = 0; +*cgbsb = 0; + +} + +void +SOI3capEval(ckt, + Frontcapargs, + Backcapargs, + cgfgf,cgfd,cgfs,cgfdeltaT, + cdgf,cdd,cds,cddeltaT, + csgf,csd,css,csdeltaT, + cbgf,cbd,cbs,cbdeltaT,cbgb, + cgbgb,cgbsb, + gcgfgf,gcgfd,gcgfs,gcgfdeltaT, + gcdgf,gcdd,gcds,gcddeltaT, + gcsgf,gcsd,gcss,gcsdeltaT, + gcbgf,gcbd,gcbs,gcbdeltaT,gcbgb, + gcgbgb,gcgbsb,gcgbdb, + gcgbs0,gcgbd0, + qgatef,qbody,qdrn,qsrc,qgateb) + +register CKTcircuit *ckt; +double Frontcapargs[6]; +double Backcapargs[6]; + + +double cgfgf,cgfd,cgfs,cgfdeltaT; +double cdgf,cdd,cds,cddeltaT; +double csgf,csd,css,csdeltaT; +double cbgf,cbd,cbs,cbdeltaT,cbgb; +double cgbgb,cgbsb; + +double *gcgfgf,*gcgfd,*gcgfs,*gcgfdeltaT; +double *gcdgf,*gcdd,*gcds,*gcddeltaT; +double *gcsgf,*gcsd,*gcss,*gcsdeltaT; +double *gcbgf,*gcbd,*gcbs,*gcbdeltaT,*gcbgb; +double *gcgbgb,*gcgbsb,*gcgbdb; +double *gcgbs0,*gcgbd0; + +double *qgatef; +double *qbody; +double *qdrn; +double *qsrc; +double *qgateb; + +{ +double vgfd,vgfs,vgfb; +double vgbd,vgbs,vgbb; +double cgd0,cgs0,cgb0; +double cgbd0,cgbs0,cgbb0; +double ag0; +double qgd,qgs,qgb; +double qgb_d,qgb_s,qgb_b; + +cgd0 = Frontcapargs[0]; +cgs0 = Frontcapargs[1]; +cgb0 = Frontcapargs[2]; +vgfd = Frontcapargs[3]; +vgfs = Frontcapargs[4]; +vgfb = Frontcapargs[5]; + +cgbd0 = Backcapargs[0]; +cgbs0 = Backcapargs[1]; +cgbb0 = Backcapargs[2]; +vgbd = Backcapargs[3]; +vgbs = Backcapargs[4]; +vgbb = Backcapargs[5]; + +/* stuff below includes overlap caps' conductances */ +ag0 = ckt->CKTag[0]; + +*gcgfgf = (cgfgf + cgd0 + cgs0 + cgb0) * ag0; +*gcgfd = (cgfd - cgd0) * ag0; +*gcgfs = (cgfs - cgs0) * ag0; +*gcgfdeltaT = cgfdeltaT * ag0; + +*gcdgf = (cdgf - cgd0) * ag0; +*gcdd = (cdd + cgd0) * ag0; +*gcds = cds * ag0; +*gcddeltaT = cddeltaT * ag0; + +*gcsgf = (csgf - cgs0) * ag0; +*gcsd = csd * ag0; +*gcss = (css + cgs0) * ag0; +*gcsdeltaT = csdeltaT * ag0; + +*gcbgf = (cbgf - cgb0) * ag0; +*gcbd = cbd * ag0; +*gcbs = cbs * ag0; +*gcbdeltaT = cbdeltaT * ag0; + +*gcbgb = cbgb * ag0; +/* +*gcbgb = (cbgb - cgbb0) * ag0; + + +*gcgbgb = (cgbgb + cgbb0 + cgbd0 + cgbs0) * ag0; +*gcgbsb = (cgbsb - cgbs0) * ag0; +*gcgbdb = -cgbd0 * ag0; + +*gcgbd0 = cgbd0 * ag0; +*gcgbs0 = cgbs0 * ag0; +*/ + +*gcgbgb = cgbgb * ag0; +*gcgbsb = cgbsb * ag0; +*gcgbdb = 0; + +*gcgbd0 = 0; +*gcgbs0 = 0; + +qgd = cgd0 * vgfd; +qgs = cgs0 * vgfs; +qgb = cgb0 * vgfb; + +/* +qgb_d = cgbd0 * vgbd; +qgb_s = cgbs0 * vgbs; +qgb_b = cgbb0 * vgbb; +*/ +qgb_d = 0; +qgb_s = 0; +qgb_b = 0; + +*qgatef = *qgatef + qgd + qgs + qgb; +*qbody = *qbody - qgb - qgb_b; +*qdrn = *qdrn - qgd - qgb_d; +*qgateb = *qgateb + qgb_d + qgb_s + qgb_b; +*qsrc = -(*qgatef + *qbody + *qdrn + *qgateb); +} diff --git a/src/spicelib/devices/soi3/soi3conv.c b/src/spicelib/devices/soi3/soi3conv.c new file mode 100644 index 000000000..156db8af8 --- /dev/null +++ b/src/spicelib/devices/soi3/soi3conv.c @@ -0,0 +1,217 @@ +/********** +STAG version 2.6 +Copyright 2000 owned by the United Kingdom Secretary of State for Defence +acting through the Defence Evaluation and Research Agency. +Developed by : Jim Benson, + Department of Electronics and Computer Science, + University of Southampton, + United Kingdom. +With help from : Nele D'Halleweyn, Bill Redman-White, and Craig Easson. + +Based on STAG version 2.1 +Developed by : Mike Lee, +With help from : Bernard Tenbroek, Bill Redman-White, Mike Uren, Chris Edwards + and John Bunyan. +Acknowledgements : Rupert Howes and Pete Mole. +**********/ + +/* Modified: 2001 Paolo Nenzi */ + +#include "ngspice.h" +#include +#include "cktdefs.h" +#include "soi3defs.h" +#include "sperror.h" +#include "suffix.h" + + +int +SOI3convTest(inModel,ckt) + GENmodel *inModel; + CKTcircuit *ckt; +{ + SOI3model *model = (SOI3model*)inModel; + SOI3instance *here; + double delvbs; + double delvbd; + double delvgfs; + double delvgbs; + double delvds; + double delvgfd; + double delvgbd; + double deldeltaT; + double ibhat; + double idhat; + double iPthat; + double vbs; + double vbd; + double vgfs; + double vgbs; + double vds; + double deltaT; + double vgfd; + double vgbd; + double vgfdo; + double vgbdo; + double tol; + FILE *fp,*fopen(); + + for( ; model != NULL; model = model->SOI3nextModel) { + for(here = model->SOI3instances; here!= NULL; + here = here->SOI3nextInstance) { + + vbs = model->SOI3type * ( + *(ckt->CKTrhs+here->SOI3bNode) - + *(ckt->CKTrhs+here->SOI3sNodePrime)); + vgfs = model->SOI3type * ( + *(ckt->CKTrhs+here->SOI3gfNode) - + *(ckt->CKTrhs+here->SOI3sNodePrime)); + vgbs = model->SOI3type * ( + *(ckt->CKTrhs+here->SOI3gbNode) - + *(ckt->CKTrhs+here->SOI3sNodePrime)); + vds = model->SOI3type * ( + *(ckt->CKTrhs+here->SOI3dNodePrime) - + *(ckt->CKTrhs+here->SOI3sNodePrime)); + deltaT = MAX(0,*(ckt->CKTrhs+here->SOI3toutNode)); + /* voltage deltaT is V(tout) wrt thermal ground */ + vbd=vbs-vds; + vgfd=vgfs-vds; + vgbd=vgbs-vds; + vgfdo = *(ckt->CKTstate0 + here->SOI3vgfs) - + *(ckt->CKTstate0 + here->SOI3vds); + vgbdo = *(ckt->CKTstate0 + here->SOI3vgbs) - + *(ckt->CKTstate0 + here->SOI3vds); + delvbs = vbs - *(ckt->CKTstate0 + here->SOI3vbs); + delvbd = vbd - *(ckt->CKTstate0 + here->SOI3vbd); + delvgfs = vgfs - *(ckt->CKTstate0 + here->SOI3vgfs); + delvgbs = vgbs - *(ckt->CKTstate0 + here->SOI3vgbs); + delvds = vds - *(ckt->CKTstate0 + here->SOI3vds); + delvgfd = vgfd-vgfdo; + delvgbd = vgbd-vgbdo; + deldeltaT = deltaT - *(ckt->CKTstate0 + here->SOI3deltaT); + + /* these are needed for convergence testing */ + + if (here->SOI3mode >= 0) { /* normal */ + idhat= + here->SOI3id- + here->SOI3gbd * delvbd - + here->SOI3gbdT * deldeltaT + /* for -ibd bit of id */ + (here->SOI3gmbs + + here->SOI3gMmbs) * delvbs + + (here->SOI3gmf + + here->SOI3gMmf) * delvgfs + + (here->SOI3gmb + + here->SOI3gMmb) * delvgbs + + (here->SOI3gds + + here->SOI3gMd) * delvds + + (here->SOI3gt + + here->SOI3gMdeltaT) * deldeltaT + + here->SOI3gBJTdb_bs * delvbs + + here->SOI3gBJTdb_deltaT * deldeltaT; + ibhat= + here->SOI3ibs + + here->SOI3ibd + + here->SOI3gbd * delvbd + + here->SOI3gbdT * deldeltaT + + here->SOI3gbs * delvbs + + here->SOI3gbsT * deldeltaT - + here->SOI3iMdb - + here->SOI3gMmbs * delvbs - + (here->SOI3gMmf)* delvgfs - + (here->SOI3gMmb)* delvgbs - + here->SOI3gMd * delvds - + here->SOI3gMdeltaT * deldeltaT - + here->SOI3iBJTsb - + here->SOI3gBJTsb_bd * delvbd - + here->SOI3gBJTsb_deltaT * deldeltaT - + here->SOI3iBJTdb - + here->SOI3gBJTdb_bs * delvbs - + here->SOI3gBJTdb_deltaT * deldeltaT; + } else { /* A over T */ + idhat= + here->SOI3id - + ( here->SOI3gbd + + here->SOI3gmbs) * delvbd - + (here->SOI3gmf) * delvgfd - + (here->SOI3gmb) * delvgbd + + (here->SOI3gds) * delvds - + (here->SOI3gt + + here->SOI3gbdT) * deldeltaT + + here->SOI3gBJTdb_bs * delvbs + + here->SOI3gBJTdb_deltaT * deldeltaT; + ibhat= + here->SOI3ibs + + here->SOI3ibd + + here->SOI3gbd * delvbd + + here->SOI3gbdT * deldeltaT + + here->SOI3gbs * delvbs + + here->SOI3gbsT * deldeltaT - + here->SOI3iMsb - + here->SOI3gMmbs * delvbd - + here->SOI3gMmf * delvgfd - + here->SOI3gMmb * delvgbd + + here->SOI3gMd * delvds - /* gMd should go with vsd */ + here->SOI3gMdeltaT * deldeltaT - + here->SOI3iBJTsb - + here->SOI3gBJTsb_bd * delvbd - + here->SOI3gBJTsb_deltaT * deldeltaT - + here->SOI3iBJTdb - + here->SOI3gBJTdb_bs * delvbs - + here->SOI3gBJTdb_deltaT * deldeltaT; + } + iPthat = + here->SOI3iPt + + here->SOI3gPmbs * delvbs + + here->SOI3gPmf * delvgfs + + here->SOI3gPmb * delvgbs + + here->SOI3gPds * delvds * here->SOI3mode + + here->SOI3gPdT * deldeltaT; + /* + * check convergence + */ + tol=ckt->CKTreltol*MAX(fabs(idhat),fabs(here->SOI3id))+ + ckt->CKTabstol; + if (fabs(idhat-here->SOI3id) >= tol) { + ckt->CKTnoncon++; + /* JimB - Remove line containing ckt->CKTtroubleElt for the */ + /* Simetrix DLL version - element removed from ckt structure */ + ckt->CKTtroubleElt = (GENinstance *) here; + return(OK); /* no reason to continue, we haven't converged */ + } else { + tol=ckt->CKTreltol* + MAX(fabs(ibhat),fabs(here->SOI3ibs+here->SOI3ibd + - here->SOI3iMdb - here->SOI3iMsb + - here->SOI3iBJTdb - here->SOI3iBJTsb))+ + ckt->CKTabstol; + if (fabs(ibhat-(here->SOI3ibs+here->SOI3ibd + - here->SOI3iMdb - here->SOI3iMsb + - here->SOI3iBJTdb - here->SOI3iBJTsb)) > tol) { + ckt->CKTnoncon++; + /* JimB - Remove line containing ckt->CKTtroubleElt for the */ + /* Simetrix DLL version - element removed from ckt structure */ + ckt->CKTtroubleElt = (GENinstance *) here; + return(OK); /* no reason to continue,we haven't converged*/ + } else { + tol=ckt->CKTreltol*MAX(fabs(iPthat), + fabs(here->SOI3iPt))+ckt->CKTabstol; + if (fabs(iPthat-here->SOI3iPt) >= tol) { + ckt->CKTnoncon++; + /* JimB - Remove line containing ckt->CKTtroubleElt for the */ + /* Simetrix DLL version - element removed from ckt structure */ + ckt->CKTtroubleElt = (GENinstance *) here; + return(OK); /* no reason to continue,we haven't converged*/ + } + } + } +/* debug stuff */ +/* fp=fopen("level3.dat","a"); + fprintf(fp,"%2.3f %2.3f %.15e %.15e %.15e %.15e %.15e %.15e %.15e\n", + vgfs-vbs,vds,ckt->CKTtime,here->SOI3debug1,here->SOI3debug2,here->SOI3debug3, + here->SOI3debug4,here->SOI3debug5,here->SOI3debug6); + fclose(fp); +*/ + } + } + return(OK); +} diff --git a/src/spicelib/devices/soi3/soi3defs.h b/src/spicelib/devices/soi3/soi3defs.h new file mode 100644 index 000000000..ef349d2d1 --- /dev/null +++ b/src/spicelib/devices/soi3/soi3defs.h @@ -0,0 +1,800 @@ +/********** +STAG version 2.6 +Copyright 2000 owned by the United Kingdom Secretary of State for Defence +acting through the Defence Evaluation and Research Agency. +Developed by : Jim Benson, + Department of Electronics and Computer Science, + University of Southampton, + United Kingdom. +With help from : Nele D'Halleweyn, Bill Redman-White, and Craig Easson. + +Based on STAG version 2.1 +Developed by : Mike Lee, +With help from : Bernard Tenbroek, Bill Redman-White, Mike Uren, Chris Edwards + and John Bunyan. +Acknowledgements : Rupert Howes and Pete Mole. +**********/ + +#ifndef SOI3 +#define SOI3 + +#include "ifsim.h" +#include "cktdefs.h" +#include "gendefs.h" +#include "complex.h" +#include "noisedef.h" + + +/* declarations for SOI3 MOSFETs */ + +/* information needed for each instance */ + +typedef struct sSOI3instance { + + + struct sSOI3model *sSOI3modPtr; /* backpointer to model */ + struct sSOI3instance *SOI3nextInstance; /* pointer to next instance of + *current model*/ + IFuid SOI3name; /* pointer to character string naming this instance */ + int SOI3owner; /* number of owner process */ + int SOI3states; /* index into state table for this device */ + + + int SOI3dNode; /* number of the drain node of the mosfet */ + int SOI3gfNode; /* number of the front gate node of the mosfet */ + int SOI3sNode; /* number of the source node of the mosfet */ + int SOI3gbNode; /* number of the back gate node of the mosfet */ + int SOI3bNode; /* number of the bulk node of the mosfet */ + int SOI3toutNode; /* number of thermal output node (tout) */ + + int SOI3branch; /* branch number for zero voltage source if no thermal */ + + int SOI3dNodePrime; /* number of the internal drain node of the mosfet */ + int SOI3sNodePrime; /* number of the internal source node of the mosfet */ + + + + int SOI3tout1Node; /* first internal thermal node */ + int SOI3tout2Node; /* second internal thermal node */ + int SOI3tout3Node; /* third internal thermal node */ + int SOI3tout4Node; /* fourth internal thermal node */ + + double SOI3l; /* the length of the channel region */ + double SOI3w; /* the width of the channel region */ + + double SOI3drainSquares; /* the length of the drain in squares */ + double SOI3sourceSquares; /* the length of the source in squares */ + + double SOI3sourceConductance; /*conductance of source(or 0):set in setup*/ + double SOI3drainConductance; /*conductance of drain(or 0):set in setup*/ + double SOI3temp; /* operating temperature of this instance */ + double SOI3rt; /* Thermal resistance */ + double SOI3ct; /* Thermal capacitance */ + double SOI3rt1; /* 1st internal Thermal resistance */ + double SOI3ct1; /* 1st internal Thermal capacitance */ + double SOI3rt2; /* 2nd internal Thermal resistance */ + double SOI3ct2; /* 2nd internal Thermal capacitance */ + double SOI3rt3; /* 3rd internal Thermal resistance */ + double SOI3ct3; /* 3rd internal Thermal capacitance */ + double SOI3rt4; /* 4th internal Thermal resistance */ + double SOI3ct4; /* 4th internal Thermal capacitance */ + + + double SOI3tTransconductance; /* temperature corrected transconductance (KP param) */ + double SOI3ueff; /* passed on to noise model */ + double SOI3tSurfMob; /* temperature corrected surface mobility */ + double SOI3tPhi; /* temperature corrected Phi */ + double SOI3tVto; /* temperature corrected Vto */ + double SOI3tVfbF; /* temperature corrected Vfb */ + double SOI3tVfbB; /* temperature corrected Vfb (back gate) */ + double SOI3tSatCur; /* temperature corrected jnct saturation Cur. */ + double SOI3tSatCur1; /* temperature corrected jnct saturation Cur. */ + double SOI3tSatCurDens; /* temperature corrected jnct saturation Cur. density */ + double SOI3tSatCurDens1; /* temperature corrected jnct saturation Cur. density */ + double SOI3tCbd; /* temperature corrected B-D Capacitance */ + double SOI3tCbs; /* temperature corrected B-S Capacitance */ + double SOI3tCjsw; /* temperature corrected Bulk side Capacitance */ + double SOI3tBulkPot; /* temperature corrected Bulk potential */ + double SOI3tDepCap; /* temperature adjusted transition point in */ + /* the curve matching Fc * Vj */ + double SOI3tVbi; /* temperature adjusted Vbi diode built-in voltage */ + + double SOI3icVBS; /* initial condition B-S voltage */ + double SOI3icVDS; /* initial condition D-S voltage */ + double SOI3icVGFS; /* initial condition GF-S voltage */ + double SOI3icVGBS; /* initial condition GB-S voltage */ + double SOI3von; + double SOI3vdsat; + double SOI3sourceVcrit; /* Vcrit for pos. vds */ + double SOI3drainVcrit; /* Vcrit for pos. vds */ + double SOI3id; /* drain current */ + double SOI3ibs; /* bulk source current */ + double SOI3ibd; /* bulk drain current */ + double SOI3iMdb; /* drain bulk impact ionisation current */ + double SOI3iMsb; /* source bulk impact ionisation cur. (rev mode) */ + double SOI3iPt; /* heat 'current' in thermal circuit */ + double SOI3gmbs; + double SOI3gmf; + double SOI3gmb; + double SOI3gds; + double SOI3gt; /* change of channel current wrt deltaT */ + double SOI3gdsnotherm; /* gds0 at elevated temp - ac use only) */ + double SOI3gMmbs; + double SOI3gMmf; + double SOI3gMmb; + double SOI3gMd; + double SOI3gMdeltaT; + double SOI3iBJTdb; + double SOI3gBJTdb_bs; + double SOI3gBJTdb_deltaT; + double SOI3iBJTsb; + double SOI3gBJTsb_bd; + double SOI3gBJTsb_deltaT; + double SOI3gPmf; /* change of Pt wrt vgfs */ + double SOI3gPmb; /* change of Pt wrt vgbs */ + double SOI3gPmbs; /* change of Pt wrt vbs */ + double SOI3gPds; /* change of Pt wrt vds */ + double SOI3gPdT; /* change of Pt wrt deltaT */ + double SOI3gbd; /* for body drain current */ + double SOI3gbdT; /* for body drain current */ + double SOI3gbs; /* for body source current */ + double SOI3gbsT; /* for body source current */ + double SOI3capbd; + double SOI3capbs; + double SOI3Cbd; + double SOI3Cbs; + double SOI3f2d; + double SOI3f3d; + double SOI3f4d; + double SOI3f2s; + double SOI3f3s; + double SOI3f4s; + double SOI3dDT_dVds; /* sm-sig gT term */ + double SOI3dId_dDT; /* sm-sig source term */ +/*debug stuff*/ + double SOI3debug1; + double SOI3debug2; + double SOI3debug3; + double SOI3debug4; + double SOI3debug5; + double SOI3debug6; +/* extra stuff for newer model - msll Jan96 */ + +/* + * naming convention: + * x = vgs + * y = vbs + * z = vds + * cdr = cdrain + */ + int SOI3mode; /* device mode : 1 = normal, -1 = inverse */ + int SOI3backstate; /* indicates charge condition of back surface */ + int SOI3numThermalNodes; /* Number of thermal nodes required */ + + unsigned SOI3off:1; /* non-zero to indicate device is off for dc analysis*/ + unsigned SOI3tempGiven :1; /* instance temperature specified */ + unsigned SOI3lGiven :1; + unsigned SOI3wGiven :1; + unsigned SOI3drainSquaresGiven :1; + unsigned SOI3sourceSquaresGiven :1; + unsigned SOI3dNodePrimeSet :1; + unsigned SOI3sNodePrimeSet :1; + unsigned SOI3icVBSGiven :1; + unsigned SOI3icVDSGiven :1; + unsigned SOI3icVGFSGiven:1; + unsigned SOI3icVGBSGiven:1; + unsigned SOI3rtGiven:1; + unsigned SOI3ctGiven:1; + unsigned SOI3rt1Given:1; + unsigned SOI3ct1Given:1; + unsigned SOI3rt2Given:1; + unsigned SOI3ct2Given:1; + unsigned SOI3rt3Given:1; + unsigned SOI3ct3Given:1; + unsigned SOI3rt4Given:1; + unsigned SOI3ct4Given:1; + unsigned SOI3vonGiven :1; + unsigned SOI3vdsatGiven :1; + unsigned SOI3modeGiven :1; + + + double *SOI3D_dPtr; /* pointer to sparse matrix element at + * (Drain node,drain node) */ + double *SOI3GF_gfPtr; /* pointer to sparse matrix element at + * (front gate node,front gate node) */ + double *SOI3S_sPtr; /* pointer to sparse matrix element at + * (source node,source node) */ + double *SOI3B_bPtr; /* pointer to sparse matrix element at + * (bulk node,bulk node) */ + double *SOI3GB_gbPtr; /* pointer to sparse matrix element at + * (back gate node,back gate node) */ + double *SOI3DP_dpPtr; /* pointer to sparse matrix element at + * (drain prime node,drain prime node) */ + double *SOI3SP_spPtr; /* pointer to sparse matrix element at + * (source prime node,source prime node) */ + double *SOI3D_dpPtr; /* pointer to sparse matrix element at + * (drain node,drain prime node) */ + double *SOI3GF_bPtr; /* pointer to sparse matrix element at + * (front gate node,bulk node) */ + double *SOI3GB_bPtr; /* pointer to sparse matrix element at + * (back gate node,bulk node) */ + double *SOI3GF_dpPtr; /* pointer to sparse matrix element at + * (front gate node,drain prime node) */ + double *SOI3GB_dpPtr; /* pointer to sparse matrix element at + * (back gate node,drain prime node) */ + double *SOI3GF_spPtr; /* pointer to sparse matrix element at + * (front gate node,source prime node) */ + double *SOI3GB_spPtr; /* pointer to sparse matrix element at + * (back gate node,source prime node) */ + double *SOI3S_spPtr; /* pointer to sparse matrix element at + * (source node,source prime node) */ + double *SOI3B_dpPtr; /* pointer to sparse matrix element at + * (bulk node,drain prime node) */ + double *SOI3B_spPtr; /* pointer to sparse matrix element at + * (bulk node,source prime node) */ + double *SOI3DP_spPtr; /* pointer to sparse matrix element at + * (drain prime node,source prime node) */ + double *SOI3DP_dPtr; /* pointer to sparse matrix element at + * (drain prime node,drain node) */ + double *SOI3B_gfPtr; /* pointer to sparse matrix element at + * (bulk node,front gate node) */ + double *SOI3B_gbPtr; /* pointer to sparse matrix element at + * (bulk node,back gate node) */ + double *SOI3DP_gfPtr; /* pointer to sparse matrix element at + * (drain prime node,front gate node) */ + double *SOI3DP_gbPtr; /* pointer to sparse matrix element at + * (drain prime node,back gate node) */ + double *SOI3SP_gfPtr; /* pointer to sparse matrix element at + * (source prime node,front gate node) */ + double *SOI3SP_gbPtr; /* pointer to sparse matrix element at + * (source prime node,back gate node) */ + double *SOI3SP_sPtr; /* pointer to sparse matrix element at + * (source prime node,source node) */ + double *SOI3DP_bPtr; /* pointer to sparse matrix element at + * (drain prime node,bulk node) */ + double *SOI3SP_bPtr; /* pointer to sparse matrix element at + * (source prime node,bulk node) */ + double *SOI3SP_dpPtr; /* pointer to sparse matrix element at + * (source prime node,drain prime node) */ + +/** Now for Thermal Node **/ + + double *SOI3TOUT_toutPtr; + double *SOI3TOUT_dpPtr; + double *SOI3TOUT_gfPtr; + double *SOI3TOUT_gbPtr; + double *SOI3TOUT_bPtr; + double *SOI3TOUT_spPtr; + + double *SOI3GF_toutPtr; + double *SOI3DP_toutPtr; + double *SOI3SP_toutPtr; + + double *SOI3TOUT_ibrPtr; /* these are for zero voltage source should */ + double *SOI3IBR_toutPtr; /* no thermal behaviour be specified */ + + double *SOI3B_toutPtr; /* for impact ionisation current source */ + + double *SOI3TOUT_tout1Ptr; + double *SOI3TOUT1_toutPtr; + double *SOI3TOUT1_tout1Ptr; + double *SOI3TOUT1_tout2Ptr; + double *SOI3TOUT2_tout1Ptr; + double *SOI3TOUT2_tout2Ptr; + double *SOI3TOUT2_tout3Ptr; + double *SOI3TOUT3_tout2Ptr; + double *SOI3TOUT3_tout3Ptr; + double *SOI3TOUT3_tout4Ptr; + double *SOI3TOUT4_tout3Ptr; + double *SOI3TOUT4_tout4Ptr; + + +/* indices to the array of SOI(3) noise sources */ + +#define SOI3RDNOIZ 0 +#define SOI3RSNOIZ 1 +#define SOI3IDNOIZ 2 +#define SOI3FLNOIZ 3 +#define SOI3TOTNOIZ 4 + +#define SOI3NSRCS 5 /* the number of SOI(3) noise sources */ + +#ifndef NONOISE + double SOI3nVar[NSTATVARS][SOI3NSRCS]; +#else /* NONOISE */ + double **SOI3nVar; +#endif /* NONOISE */ + +} SOI3instance ; + +#define SOI3vbd SOI3states+ 0 /* bulk-drain voltage */ +#define SOI3vbs SOI3states+ 1 /* bulk-source voltage */ +#define SOI3vgfs SOI3states+ 2 /* front gate-source voltage */ +#define SOI3vgbs SOI3states+ 3 /* back gate-source voltage */ +#define SOI3vds SOI3states+ 4 /* drain-source voltage */ +#define SOI3deltaT SOI3states+ 5 /* final temperature difference */ + +#define SOI3qgf SOI3states + 6 /* front gate charge */ +#define SOI3iqgf SOI3states +7 /* front gate current */ + +#define SOI3qgb SOI3states+ 8 /* back gate charge */ +#define SOI3iqgb SOI3states+ 9 /* back gate current */ + +#define SOI3qd SOI3states+ 10 /* drain charge */ +#define SOI3iqd SOI3states+ 11 /* drain current */ + +#define SOI3qs SOI3states+ 14 /* body charge */ +#define SOI3iqs SOI3states+ 15 /* body current */ + +#define SOI3cgfgf SOI3states+ 16 +#define SOI3cgfd SOI3states+ 17 +#define SOI3cgfs SOI3states+ 18 +#define SOI3cgfdeltaT SOI3states+ 19 + +#define SOI3cdgf SOI3states+ 20 +#define SOI3cdd SOI3states+ 21 +#define SOI3cds SOI3states+ 22 +#define SOI3cddeltaT SOI3states+ 23 + +#define SOI3csgf SOI3states+ 24 +#define SOI3csd SOI3states+ 25 +#define SOI3css SOI3states+ 26 +#define SOI3csdeltaT SOI3states+ 27 + +#define SOI3cgbgb SOI3states + 28 +#define SOI3cgbsb SOI3states + 29 +#define SOI3cgbdb SOI3states + 30 + +#define SOI3qbd SOI3states+ 31 /* body-drain capacitor charge */ +#define SOI3iqbd SOI3states+ 32 /* body-drain capacitor current */ + +#define SOI3qbs SOI3states+ 33 /* body-source capacitor charge */ +#define SOI3iqbs SOI3states+ 34 /* body-source capacitor current */ + +#define SOI3qt SOI3states+ 35 /* Energy or 'charge' associated with ct */ +#define SOI3iqt SOI3states+ 36 /* equiv current source for ct */ +#define SOI3qt1 SOI3states+ 37 /* Energy or 'charge' associated with ct */ +#define SOI3iqt1 SOI3states+ 38 /* equiv current source for ct */ +#define SOI3qt2 SOI3states+ 39 /* Energy or 'charge' associated with ct */ +#define SOI3iqt2 SOI3states+ 40 /* equiv current source for ct */ +#define SOI3qt3 SOI3states+ 41 /* Energy or 'charge' associated with ct */ +#define SOI3iqt3 SOI3states+ 42 /* equiv current source for ct */ +#define SOI3qt4 SOI3states+ 43 /* Energy or 'charge' associated with ct */ +#define SOI3iqt4 SOI3states+ 44 /* equiv current source for ct */ + +#define SOI3qBJTbs SOI3states+ 45 +#define SOI3iqBJTbs SOI3states+ 46 + +#define SOI3qBJTbd SOI3states+ 47 +#define SOI3iqBJTbd SOI3states+ 48 + +#define SOI3cBJTbsbs SOI3states+ 49 +#define SOI3cBJTbsdeltaT SOI3states+ 50 + +#define SOI3cBJTbdbd SOI3states+ 51 +#define SOI3cBJTbddeltaT SOI3states+ 52 + +#define SOI3idrain SOI3states+ 53 /* final drain current at timepoint (no define) */ + +#define SOI3deltaT1 SOI3states+ 54 /* final temperature difference */ +#define SOI3deltaT2 SOI3states+ 55 /* final temperature difference */ +#define SOI3deltaT3 SOI3states+ 56 /* final temperature difference */ +#define SOI3deltaT4 SOI3states+ 57 /* final temperature difference */ +#define SOI3deltaT5 SOI3states+ 58 /* final temperature difference */ + +#define SOI3numStates 59 + +/* per model data */ + + /* NOTE: parameters marked 'input - use xxxx' are paramters for + * which a temperature correction is applied in SOI3temp, thus + * the SOI3xxxx value in the per-instance structure should be used + * instead in all calculations + */ + + +typedef struct sSOI3model { /* model structure for an SOI3 MOSFET */ + + + int SOI3modType; /* type index to this device type */ + struct sSOI3model *SOI3nextModel; /* pointer to next possible model + *in linked list */ + SOI3instance * SOI3instances; /* pointer to list of instances + * that have this model */ + IFuid SOI3modName; /* pointer to character string naming this model */ + int SOI3type; /* device type : 1 = nsoi, -1 = psoi */ + double SOI3tnom; /* temperature at which parameters measured */ + double SOI3latDiff; + double SOI3jctSatCurDensity; /* input - use tSatCurDens (jnct)*/ + double SOI3jctSatCurDensity1; /* input - use tSatCurDens1 (jnct)*/ + double SOI3jctSatCur; /* input - use tSatCur (jnct Is)*/ + double SOI3jctSatCur1; /* input - use tSatCur1 (jnct Is)*/ + double SOI3drainResistance; + double SOI3sourceResistance; + double SOI3sheetResistance; + double SOI3transconductance; /* (KP) input - use tTransconductance */ + double SOI3frontGateSourceOverlapCapFactor; + double SOI3frontGateDrainOverlapCapFactor; + double SOI3frontGateBulkOverlapCapFactor; + double SOI3backGateSourceOverlapCapFactor; + double SOI3backGateDrainOverlapCapFactor; + double SOI3backGateBulkOverlapCapFactor; + double SOI3frontOxideCapFactor; /* Cof NO DEFINES */ + double SOI3backOxideCapFactor; /* Cob OR */ + double SOI3bodyCapFactor; /* Cb FLAGS */ + double SOI3C_bb; /* Cb in series with Cob */ + double SOI3C_fb; /* Cb in series with Cof */ + double SOI3C_ssf; /* q*NQFF */ + double SOI3C_ssb; /* q*NQFB */ + double SOI3C_fac; /* C_ob/(C_ob+C_b+C_ssb) */ + double SOI3vt0; /* input - use tVto */ + double SOI3vfbF; /* flat-band voltage. input - use tVfbF */ + double SOI3vfbB; /* back flat-band voltage. input - use tVfbB */ + double SOI3gamma; /* gamma */ + double SOI3gammaB; /* back gamma */ + double SOI3capBD; /* input - use tCbd */ + double SOI3capBS; /* input - use tCbs */ + double SOI3sideWallCapFactor; /* input - use tCjsw */ + double SOI3bulkJctPotential; /* input - use tBulkPot */ + double SOI3bulkJctSideGradingCoeff; /* MJSW */ + double SOI3fwdCapDepCoeff; /* FC */ + double SOI3phi; /* input - use tPhi */ + double SOI3vbi; /* input - use tVbi */ + double SOI3lambda; + double SOI3theta; + double SOI3substrateDoping; /* Nsub */ + double SOI3substrateCharge; /* Qb - no define/flag */ + int SOI3gateType; /* +1=same, -1=different, 0=Al */ + double SOI3frontFixedChargeDensity; + double SOI3backFixedChargeDensity; + double SOI3frontSurfaceStateDensity; + double SOI3backSurfaceStateDensity; + double SOI3frontOxideThickness; + double SOI3backOxideThickness; + double SOI3bodyThickness; + double SOI3surfaceMobility; /* input - use tSurfMob */ + double SOI3oxideThermalConductivity; + double SOI3siliconSpecificHeat; + double SOI3siliconDensity; + double SOI3fNcoef; + double SOI3fNexp; +/* new stuff for newer model - msll Jan96 */ + double SOI3sigma; /* DIBL factor */ + double SOI3chiFB; /* temperature coeff of flatband voltage */ + double SOI3chiPHI; /* temperature coeff of PHI */ + double SOI3deltaW; /* narrow width effect factor */ + double SOI3deltaL; /* short channel effect factor */ + double SOI3vsat; /* input - saturation velocity, use tVsat */ + double SOI3TVF0; /* internal use - precalculation of exp to save time */ + double SOI3k; /* thermal exponent for mobility factor */ + double SOI3lx; /* channel length modulation factor */ + double SOI3vp; /* channel length modulation empirical voltage */ + double SOI3eta; /* Imp. ion. field adjustment factor */ + double SOI3alpha0; /* 1st impact ionisation coeff */ + double SOI3beta0; /* 2nd impact ionisation coeff */ + double SOI3lm; /* impact ion. drain region length cf LX */ + double SOI3lm1; /* impact ion. drain region coeff */ + double SOI3lm2; /* impact ion. drain region coeff */ + double SOI3etad; /* diode ideality factor */ + double SOI3etad1; /* 2nd diode ideality factor */ + double SOI3chibeta; /* temp coeff of BETA0 */ + double SOI3chid; /* temp factor for junction 1 */ + double SOI3chid1; /* temp factor for junction 2 */ + int SOI3dvt; /* switch for temp dependence of vt in diodes */ + int SOI3nLev; /* level switch for noise model */ + double SOI3betaBJT; /* beta for Eber Moll BJT model */ + double SOI3tauFBJT; /* forward BJT transit time */ + double SOI3tauRBJT; /* reverse BJT transit time */ + double SOI3betaEXP; + double SOI3tauEXP; + double SOI3rsw; /* source resistance width scaling factor */ + double SOI3rdw; /* drain resistance width scaling factor */ + double SOI3minimumFeatureSize; /* minimum feature size of simulated process technology */ + double SOI3vtex; /* Extracted threshold voltage */ + double SOI3vdex; /* Drain bias at which vtex extracted */ + double SOI3delta0; /* Surface potential factor for vtex conversion */ + double SOI3satChargeShareFactor; /* Saturation region charge sharing factor */ + double SOI3nplusDoping; /* Doping concentration of N+ or P+ regions */ + double SOI3rta; /* thermal resistance area scaling factor */ + double SOI3cta; /* thermal capacitance area scaling factor */ + + unsigned SOI3typeGiven :1; + unsigned SOI3latDiffGiven :1; + unsigned SOI3jctSatCurDensityGiven :1; + unsigned SOI3jctSatCurDensity1Given :1; + unsigned SOI3jctSatCurGiven :1; + unsigned SOI3jctSatCur1Given :1; + unsigned SOI3drainResistanceGiven :1; + unsigned SOI3sourceResistanceGiven :1; + unsigned SOI3sheetResistanceGiven :1; + unsigned SOI3transconductanceGiven :1; + unsigned SOI3frontGateSourceOverlapCapFactorGiven :1; + unsigned SOI3frontGateDrainOverlapCapFactorGiven :1; + unsigned SOI3frontGateBulkOverlapCapFactorGiven :1; + unsigned SOI3backGateSourceOverlapCapFactorGiven :1; + unsigned SOI3backGateDrainOverlapCapFactorGiven :1; + unsigned SOI3backGateBulkOverlapCapFactorGiven :1; + unsigned SOI3subsBiasFactorGiven :1; + unsigned SOI3bodyFactorGiven :1; + unsigned SOI3vt0Given :1; + unsigned SOI3vfbFGiven :1; + unsigned SOI3vfbBGiven :1; + unsigned SOI3gammaGiven :1; + unsigned SOI3gammaBGiven :1; + unsigned SOI3capBDGiven :1; + unsigned SOI3capBSGiven :1; + unsigned SOI3sideWallCapFactorGiven :1; + unsigned SOI3bulkJctPotentialGiven :1; + unsigned SOI3bulkJctSideGradingCoeffGiven :1; + unsigned SOI3fwdCapDepCoeffGiven :1; + unsigned SOI3phiGiven :1; + unsigned SOI3lambdaGiven :1; + unsigned SOI3thetaGiven :1; + unsigned SOI3substrateDopingGiven :1; + unsigned SOI3gateTypeGiven :1; + unsigned SOI3frontFixedChargeDensityGiven :1; + unsigned SOI3backFixedChargeDensityGiven :1; + unsigned SOI3frontSurfaceStateDensityGiven :1; + unsigned SOI3backSurfaceStateDensityGiven :1; + unsigned SOI3frontOxideThicknessGiven :1; + unsigned SOI3backOxideThicknessGiven :1; + unsigned SOI3bodyThicknessGiven :1; + unsigned SOI3surfaceMobilityGiven :1; + unsigned SOI3tnomGiven :1; + unsigned SOI3oxideThermalConductivityGiven :1; + unsigned SOI3siliconSpecificHeatGiven :1; + unsigned SOI3siliconDensityGiven :1; + unsigned SOI3fNcoefGiven :1; + unsigned SOI3fNexpGiven :1; +/* extra stuff for newer model - msll Jan96 */ + unsigned SOI3sigmaGiven :1; + unsigned SOI3chiFBGiven :1; + unsigned SOI3chiPHIGiven :1; + unsigned SOI3deltaWGiven :1; + unsigned SOI3deltaLGiven :1; + unsigned SOI3vsatGiven :1; + unsigned SOI3kGiven :1; + unsigned SOI3lxGiven :1; + unsigned SOI3vpGiven :1; + unsigned SOI3useLAMBDA :1; + unsigned SOI3etaGiven :1; + unsigned SOI3alpha0Given :1; + unsigned SOI3beta0Given :1; + unsigned SOI3lmGiven :1; + unsigned SOI3lm1Given :1; + unsigned SOI3lm2Given :1; + unsigned SOI3etadGiven :1; + unsigned SOI3etad1Given :1; + unsigned SOI3chibetaGiven :1; + unsigned SOI3chidGiven :1; + unsigned SOI3chid1Given :1; + unsigned SOI3dvtGiven :1; + unsigned SOI3nLevGiven :1; + unsigned SOI3betaBJTGiven :1; + unsigned SOI3tauFBJTGiven :1; + unsigned SOI3tauRBJTGiven :1; + unsigned SOI3betaEXPGiven :1; + unsigned SOI3tauEXPGiven :1; + unsigned SOI3rswGiven :1; + unsigned SOI3rdwGiven :1; + unsigned SOI3minimumFeatureSizeGiven :1; + unsigned SOI3vtexGiven :1; + unsigned SOI3vdexGiven :1; + unsigned SOI3delta0Given :1; + unsigned SOI3satChargeShareFactorGiven :1; + unsigned SOI3nplusDopingGiven :1; + unsigned SOI3rtaGiven :1; + unsigned SOI3ctaGiven :1; + +} SOI3model; + +#ifndef NSOI3 +#define NSOI3 1 +#define PSOI3 -1 +#endif /*NSOI3*/ + +/* device parameters */ +#define SOI3_W 1 +#define SOI3_L 2 +#define SOI3_AS 3 +#define SOI3_AD 4 +#define SOI3_PS 5 +#define SOI3_PD 6 +#define SOI3_NRS 7 +#define SOI3_NRD 8 +#define SOI3_OFF 9 +#define SOI3_IC 10 +#define SOI3_IC_VBS 11 +#define SOI3_IC_VDS 12 +#define SOI3_IC_VGFS 13 +#define SOI3_IC_VGBS 21 +#define SOI3_W_SENS 14 +#define SOI3_L_SENS 15 +#define SOI3_IB 16 +#define SOI3_IGF 17 +#define SOI3_IGB 22 +#define SOI3_IS 18 +#define SOI3_POWER 19 +#define SOI3_TEMP 20 + +/* model parameters */ +#define SOI3_MOD_VTO 101 +#define SOI3_MOD_VFBF 149 +#define SOI3_MOD_KP 102 +#define SOI3_MOD_GAMMA 103 +#define SOI3_MOD_PHI 104 +#define SOI3_MOD_LAMBDA 105 +#define SOI3_MOD_THETA 139 +#define SOI3_MOD_RD 106 +#define SOI3_MOD_RS 107 +#define SOI3_MOD_CBD 108 +#define SOI3_MOD_CBS 109 +#define SOI3_MOD_IS 110 +#define SOI3_MOD_PB 111 +#define SOI3_MOD_CGFSO 112 +#define SOI3_MOD_CGFDO 113 +#define SOI3_MOD_CGFBO 114 +#define SOI3_MOD_CGBSO 144 +#define SOI3_MOD_CGBDO 145 +#define SOI3_MOD_CGB_BO 146 +#define SOI3_MOD_CJ 115 +#define SOI3_MOD_MJ 116 +#define SOI3_MOD_CJSW 117 +#define SOI3_MOD_MJSW 118 +#define SOI3_MOD_JS 119 +#define SOI3_MOD_TOF 120 +#define SOI3_MOD_TOB 133 +#define SOI3_MOD_TB 134 +#define SOI3_MOD_LD 121 +#define SOI3_MOD_RSH 122 +#define SOI3_MOD_U0 123 +#define SOI3_MOD_FC 124 +#define SOI3_MOD_NSUB 125 +#define SOI3_MOD_TPG 126 +#define SOI3_MOD_NQFF 147 +#define SOI3_MOD_NQFB 148 +#define SOI3_MOD_NSSF 127 +#define SOI3_MOD_NSSB 135 +#define SOI3_MOD_NSOI3 128 +#define SOI3_MOD_PSOI3 129 +#define SOI3_MOD_TNOM 130 +#define SOI3_MOD_KF 131 +#define SOI3_MOD_AF 132 +#define SOI3_MOD_KOX 142 +#define SOI3_MOD_SHSI 143 +/* extra stuff for newer model - msll Jan96 */ +#define SOI3_MOD_SIGMA 150 +#define SOI3_MOD_CHIFB 151 +#define SOI3_MOD_CHIPHI 152 +#define SOI3_MOD_DELTAW 153 +#define SOI3_MOD_DELTAL 154 +#define SOI3_MOD_VSAT 155 +#define SOI3_MOD_K 156 +#define SOI3_MOD_LX 157 +#define SOI3_MOD_VP 158 +#define SOI3_MOD_ETA 159 +#define SOI3_MOD_ALPHA0 140 +#define SOI3_MOD_BETA0 141 +#define SOI3_MOD_LM 160 +#define SOI3_MOD_LM1 161 +#define SOI3_MOD_LM2 162 +#define SOI3_MOD_ETAD 163 +#define SOI3_MOD_ETAD1 164 +#define SOI3_MOD_IS1 165 +#define SOI3_MOD_JS1 166 +#define SOI3_MOD_CHIBETA 167 +#define SOI3_MOD_VFBB 168 +#define SOI3_MOD_GAMMAB 169 +#define SOI3_MOD_CHID 170 +#define SOI3_MOD_CHID1 171 +#define SOI3_MOD_DVT 172 +#define SOI3_MOD_NLEV 173 +#define SOI3_MOD_BETABJT 174 +#define SOI3_MOD_TAUFBJT 176 +#define SOI3_MOD_TAURBJT 177 +#define SOI3_MOD_BETAEXP 178 +#define SOI3_MOD_TAUEXP 179 +#define SOI3_MOD_RSW 180 +#define SOI3_MOD_RDW 181 +#define SOI3_MOD_FMIN 382 +#define SOI3_MOD_VTEX 383 +#define SOI3_MOD_VDEX 384 +#define SOI3_MOD_DELTA0 385 +#define SOI3_MOD_CSF 386 +#define SOI3_MOD_DSI 387 +#define SOI3_MOD_NPLUS 388 +#define SOI3_MOD_RTA 389 +#define SOI3_MOD_CTA 390 + +/* device questions */ +#define SOI3_DNODE 201 +#define SOI3_GFNODE 202 +#define SOI3_SNODE 203 +#define SOI3_GBNODE 204 +#define SOI3_BNODE 205 +#define SOI3_DNODEPRIME 206 +#define SOI3_SNODEPRIME 207 +#define SOI3_TNODE 208 +#define SOI3_BRANCH 209 +#define SOI3_SOURCECONDUCT 210 +#define SOI3_DRAINCONDUCT 211 +#define SOI3_VON 212 +#define SOI3_VFBF 213 +#define SOI3_VDSAT 214 +#define SOI3_SOURCEVCRIT 215 +#define SOI3_DRAINVCRIT 216 +#define SOI3_ID 217 +#define SOI3_IBS 218 +#define SOI3_IBD 219 +#define SOI3_GMBS 220 +#define SOI3_GMF 221 +#define SOI3_GMB 222 +#define SOI3_GDS 223 +#define SOI3_GBD 224 +#define SOI3_GBS 225 +#define SOI3_CAPBD 226 +#define SOI3_CAPBS 227 +#define SOI3_CAPZEROBIASBD 228 +#define SOI3_CAPZEROBIASBDSW 229 +#define SOI3_CAPZEROBIASBS 230 +#define SOI3_CAPZEROBIASBSSW 231 +#define SOI3_VBD 232 +#define SOI3_VBS 233 +#define SOI3_VGFS 234 +#define SOI3_VGBS 235 +#define SOI3_VDS 236 +#define SOI3_QGF 237 +#define SOI3_IQGF 238 +#define SOI3_QGB 239 +#define SOI3_IQGB 240 +#define SOI3_QD 241 +#define SOI3_IQD 242 +#define SOI3_QS 243 +#define SOI3_IQS 244 +#define SOI3_QBD 245 +#define SOI3_IQBD 246 +#define SOI3_QBS 247 +#define SOI3_IQBS 248 +#define SOI3_CGFGF 249 +#define SOI3_CGFD 250 +#define SOI3_CGFS 251 +#define SOI3_CGFDELTAT 252 +#define SOI3_CDGF 253 +#define SOI3_CDD 254 +#define SOI3_CDS 255 +#define SOI3_CDDELTAT 256 +#define SOI3_CSGF 257 +#define SOI3_CSD 258 +#define SOI3_CSS 259 +#define SOI3_CSDELTAT 260 +#define SOI3_L_SENS_REAL 261 +#define SOI3_L_SENS_IMAG 262 +#define SOI3_L_SENS_MAG 263 +#define SOI3_L_SENS_PH 264 +#define SOI3_L_SENS_CPLX 265 +#define SOI3_W_SENS_REAL 266 +#define SOI3_W_SENS_IMAG 267 +#define SOI3_W_SENS_MAG 268 +#define SOI3_W_SENS_PH 269 +#define SOI3_W_SENS_CPLX 270 +#define SOI3_L_SENS_DC 271 +#define SOI3_W_SENS_DC 272 +#define SOI3_RT 273 +#define SOI3_CT 274 +/* extra stuff for newer model - msll Jan96 */ +#define SOI3_VFBB 275 +#define SOI3_RT1 276 +#define SOI3_CT1 277 +#define SOI3_RT2 278 +#define SOI3_CT2 279 +#define SOI3_RT3 280 +#define SOI3_CT3 281 +#define SOI3_RT4 282 +#define SOI3_CT4 283 + +/* model questions */ + +#include "soi3ext.h" + +#endif /*SOI3*/ + diff --git a/src/spicelib/devices/soi3/soi3del.c b/src/spicelib/devices/soi3/soi3del.c new file mode 100644 index 000000000..58a4793b9 --- /dev/null +++ b/src/spicelib/devices/soi3/soi3del.c @@ -0,0 +1,50 @@ +/********** +STAG version 2.6 +Copyright 2000 owned by the United Kingdom Secretary of State for Defence +acting through the Defence Evaluation and Research Agency. +Developed by : Jim Benson, + Department of Electronics and Computer Science, + University of Southampton, + United Kingdom. +With help from : Nele D'Halleweyn, Bill Redman-White, and Craig Easson. + +Based on STAG version 2.1 +Developed by : Mike Lee, +With help from : Bernard Tenbroek, Bill Redman-White, Mike Uren, Chris Edwards + and John Bunyan. +Acknowledgements : Rupert Howes and Pete Mole. +**********/ + +/* Modified: 2001 Paolo Nenzi */ + +#include "ngspice.h" +#include +#include "soi3defs.h" +#include "sperror.h" +#include "suffix.h" + + +int +SOI3delete(inModel,name,inst) + GENmodel *inModel; + IFuid name; + GENinstance **inst; +{ + SOI3model *model = (SOI3model *)inModel; + SOI3instance **fast = (SOI3instance **)inst; + SOI3instance **prev = NULL; + SOI3instance *here; + + for( ; model ; model = model->SOI3nextModel) { + prev = &(model->SOI3instances); + for(here = *prev; here ; here = *prev) { + if(here->SOI3name == name || (fast && here==*fast) ) { + *prev= here->SOI3nextInstance; + FREE(here); + return(OK); + } + prev = &(here->SOI3nextInstance); + } + } + return(E_NODEV); +} diff --git a/src/spicelib/devices/soi3/soi3dest.c b/src/spicelib/devices/soi3/soi3dest.c new file mode 100644 index 000000000..e5ae5926d --- /dev/null +++ b/src/spicelib/devices/soi3/soi3dest.c @@ -0,0 +1,51 @@ +/********** +STAG version 2.6 +Copyright 2000 owned by the United Kingdom Secretary of State for Defence +acting through the Defence Evaluation and Research Agency. +Developed by : Jim Benson, + Department of Electronics and Computer Science, + University of Southampton, + United Kingdom. +With help from : Nele D'Halleweyn, Bill Redman-White, and Craig Easson. + +Based on STAG version 2.1 +Developed by : Mike Lee, +With help from : Bernard Tenbroek, Bill Redman-White, Mike Uren, Chris Edwards + and John Bunyan. +Acknowledgements : Rupert Howes and Pete Mole. +**********/ + +/* Modified: 2001 Paolo Nenzi */ + +#include "ngspice.h" +#include +#include "soi3defs.h" +#include "suffix.h" + + +void +SOI3destroy(inModel) + GENmodel **inModel; +{ + SOI3model **model = (SOI3model**)inModel; + SOI3instance *here; + SOI3instance *prev = NULL; + SOI3model *mod = *model; + SOI3model *oldmod = NULL; + + for( ; mod ; mod = mod->SOI3nextModel) { + if(oldmod) FREE(oldmod); + oldmod = mod; + prev = (SOI3instance *)NULL; + for(here = mod->SOI3instances ; here ; here = here->SOI3nextInstance) { + if(prev){ + /* if(prev->SOI3sens) FREE(prev->SOI3sens); */ + FREE(prev); + } + prev = here; + } + if(prev) FREE(prev); + } + if(oldmod) FREE(oldmod); + *model = NULL; +} diff --git a/src/spicelib/devices/soi3/soi3ext.h b/src/spicelib/devices/soi3/soi3ext.h new file mode 100644 index 000000000..e3d518d81 --- /dev/null +++ b/src/spicelib/devices/soi3/soi3ext.h @@ -0,0 +1,95 @@ +/********** +STAG version 2.6 +Copyright 2000 owned by the United Kingdom Secretary of State for Defence +acting through the Defence Evaluation and Research Agency. +Developed by : Jim Benson, + Department of Electronics and Computer Science, + University of Southampton, + United Kingdom. +With help from : Nele D'Halleweyn, Bill Redman-White, and Craig Easson. + +Based on STAG version 2.1 +Developed by : Mike Lee, +With help from : Bernard Tenbroek, Bill Redman-White, Mike Uren, Chris Edwards + and John Bunyan. +Acknowledgements : Rupert Howes and Pete Mole. +**********/ + +#ifdef __STDC__ +extern int SOI3acLoad(GENmodel *,CKTcircuit*); +extern int SOI3ask(CKTcircuit*,GENinstance*,int,IFvalue*,IFvalue*); +extern int SOI3delete(GENmodel*,IFuid,GENinstance**); +extern void SOI3destroy(GENmodel**); +extern int SOI3getic(GENmodel*,CKTcircuit*); +extern int SOI3load(GENmodel*,CKTcircuit*); +extern int SOI3mAsk(CKTcircuit *,GENmodel *,int,IFvalue*); +extern int SOI3mDelete(GENmodel**,IFuid,GENmodel*); +extern int SOI3mParam(int,IFvalue*,GENmodel*); +extern void SOI3cap(double,double,double, + double*,double*,double*,double*,double*,double*, + double*,double*,double*,double*, + double*,double*,double*,double*,double*,double*,double*,double*, + double*,double*,double*,double*,double*,double*,double*,double*,double*); +extern void SOI3capEval(CKTcircuit*,double*,double*, + double,double,double,double, + double,double,double,double, + double,double,double,double, + double,double,double,double,double, + double,double, + double*,double*,double*,double*, + double*,double*,double*,double*, + double*,double*,double*,double*, + double*,double*,double*,double*,double*, + double*,double*,double*, + double*,double*, + double*,double*,double*,double*,double*); +extern int SOI3param(int,IFvalue*,GENinstance*,IFvalue*); +/* extern int SOI3pzLoad(GENmodel*,CKTcircuit*,SPcomplex*); | +extern int SOI3sAcLoad(GENmodel*,CKTcircuit*); | +extern int SOI3sLoad(GENmodel*,CKTcircuit*); | Ignored +extern void SOI3sPrint(GENmodel*,CKTcircuit*); | +extern int SOI3sSetup(SENstruct*,GENmodel*); | +extern int SOI3sUpdate(GENmodel*,CKTcircuit*); | */ +extern int SOI3setup(SMPmatrix*,GENmodel*,CKTcircuit*,int*); +extern int SOI3unsetup(GENmodel*,CKTcircuit*); +extern int SOI3temp(GENmodel*,CKTcircuit*); +extern int SOI3trunc(GENmodel*,CKTcircuit*,double*); + +#ifdef SIMETRIX_VERSION +/* NTL modification 27.4.98 - add lastAttempt */ +extern int SOI3convTest(GENmodel*,CKTcircuit*,int lastAttempt); +/* end NTL modification */ +#else /* SIMETRIX_VERSION */ +extern int SOI3convTest(GENmodel*,CKTcircuit*); +#endif /* SIMETRIX_VERSION */ + +/* extern int SOI3disto(int,GENmodel*,CKTcircuit*); */ +extern int SOI3noise(int,int,GENmodel*,CKTcircuit*,Ndata*,double*); + +#else /* stdc */ +extern int SOI3acLoad(); +extern int SOI3ask(); +extern int SOI3delete(); +extern void SOI3destroy(); +extern int SOI3getic(); +extern int SOI3load(); +extern int SOI3mAsk(); +extern int SOI3mDelete(); +extern int SOI3mParam(); +extern void SOI3cap(); +extern void SOI3capEval(); +extern int SOI3param(); +/* extern int SOI3pzLoad(); | +extern int SOI3sAcLoad(); | +extern int SOI3sLoad(); | ignored +extern void SOI3sPrint(); | +extern int SOI3sSetup(); | +extern int SOI3sUpdate(); */ +extern int SOI3setup(); +extern int SOI3unsetup(); +extern int SOI3temp(); +extern int SOI3trunc(); +extern int SOI3convTest(); +/* extern int SOI3disto(); */ +extern int SOI3noise(); +#endif /* stdc */ diff --git a/src/spicelib/devices/soi3/soi3ic.c b/src/spicelib/devices/soi3/soi3ic.c new file mode 100644 index 000000000..c217a6fca --- /dev/null +++ b/src/spicelib/devices/soi3/soi3ic.c @@ -0,0 +1,65 @@ +/********** +STAG version 2.6 +Copyright 2000 owned by the United Kingdom Secretary of State for Defence +acting through the Defence Evaluation and Research Agency. +Developed by : Jim Benson, + Department of Electronics and Computer Science, + University of Southampton, + United Kingdom. +With help from : Nele D'Halleweyn, Bill Redman-White, and Craig Easson. + +Based on STAG version 2.1 +Developed by : Mike Lee, +With help from : Bernard Tenbroek, Bill Redman-White, Mike Uren, Chris Edwards + and John Bunyan. +Acknowledgements : Rupert Howes and Pete Mole. +**********/ + +/* Modified: 2001 Paolo Nenzi */ + +#include "ngspice.h" +#include +#include "cktdefs.h" +#include "soi3defs.h" +#include "sperror.h" +#include "suffix.h" + + +int +SOI3getic(inModel,ckt) + GENmodel *inModel; + CKTcircuit *ckt; +{ + SOI3model *model = (SOI3model *)inModel; + SOI3instance *here; + /* + * grab initial conditions out of rhs array. User specified, so use + * external nodes to get values + */ + + for( ; model ; model = model->SOI3nextModel) { + for(here = model->SOI3instances; here ; here = here->SOI3nextInstance) { + if(!here->SOI3icVBSGiven) { + here->SOI3icVBS = + *(ckt->CKTrhs + here->SOI3bNode) - + *(ckt->CKTrhs + here->SOI3sNode); + } + if(!here->SOI3icVDSGiven) { + here->SOI3icVDS = + *(ckt->CKTrhs + here->SOI3dNode) - + *(ckt->CKTrhs + here->SOI3sNode); + } + if(!here->SOI3icVGFSGiven) { + here->SOI3icVGFS = + *(ckt->CKTrhs + here->SOI3gfNode) - + *(ckt->CKTrhs + here->SOI3sNode); + } + if(!here->SOI3icVGBSGiven) { + here->SOI3icVGBS = + *(ckt->CKTrhs + here->SOI3gbNode) - + *(ckt->CKTrhs + here->SOI3sNode); + } + } + } + return(OK); +} diff --git a/src/spicelib/devices/soi3/soi3init.c b/src/spicelib/devices/soi3/soi3init.c new file mode 100644 index 000000000..3a9744878 --- /dev/null +++ b/src/spicelib/devices/soi3/soi3init.c @@ -0,0 +1,65 @@ +#include + +#include + +#include "soi3itf.h" +#include "soi3ext.h" +#include "soi3init.h" + + +SPICEdev SOI3info = { + { + "SOI3", + "Basic Thick Film SOI3 model", + + &SOI3nSize, + &SOI3nSize, + SOI3names, + + &SOI3pTSize, + SOI3pTable, + + &SOI3mPTSize, + SOI3mPTable, + DEV_DEFAULT + }, + + DEVparam : SOI3param, + DEVmodParam : SOI3mParam, + DEVload : SOI3load, + DEVsetup : SOI3setup, + DEVunsetup : SOI3unsetup, + DEVpzSetup : SOI3setup, + DEVtemperature: SOI3temp, + DEVtrunc : SOI3trunc, + DEVfindBranch : NULL, + DEVacLoad : SOI3acLoad, + DEVaccept : NULL, + DEVdestroy : SOI3destroy, + DEVmodDelete : SOI3mDelete, + DEVdelete : SOI3delete, + DEVsetic : SOI3getic, + DEVask : SOI3ask, + DEVmodAsk : SOI3mAsk, + DEVpzLoad : NULL, + DEVconvTest : SOI3convTest, + DEVsenSetup : NULL, + DEVsenLoad : NULL, + DEVsenUpdate : NULL, + DEVsenAcLoad : NULL, + DEVsenPrint : NULL, + DEVsenTrunc : NULL, + DEVdisto : NULL, + DEVnoise : SOI3noise, + + DEVinstSize : &SOI3iSize, + DEVmodSize : &SOI3mSize + +}; + + +SPICEdev * +get_soi3_info(void) +{ + return &SOI3info; +} diff --git a/src/spicelib/devices/soi3/soi3init.h b/src/spicelib/devices/soi3/soi3init.h new file mode 100644 index 000000000..0a957206e --- /dev/null +++ b/src/spicelib/devices/soi3/soi3init.h @@ -0,0 +1,13 @@ +#ifndef _SOI3INIT_H +#define _SOI3INIT_H + +extern IFparm SOI3pTable[ ]; +extern IFparm SOI3mPTable[ ]; +extern char *SOI3names[ ]; +extern int SOI3pTSize; +extern int SOI3mPTSize; +extern int SOI3nSize; +extern int SOI3iSize; +extern int SOI3mSize; + +#endif diff --git a/src/spicelib/devices/soi3/soi3itf.h b/src/spicelib/devices/soi3/soi3itf.h new file mode 100644 index 000000000..b91193d39 --- /dev/null +++ b/src/spicelib/devices/soi3/soi3itf.h @@ -0,0 +1,26 @@ +/********** +STAG version 2.6 +Copyright 2000 owned by the United Kingdom Secretary of State for Defence +acting through the Defence Evaluation and Research Agency. +Developed by : Jim Benson, + Department of Electronics and Computer Science, + University of Southampton, + United Kingdom. +With help from : Nele D'Halleweyn, Bill Redman-White, and Craig Easson. + +Based on STAG version 2.1 +Developed by : Mike Lee, +With help from : Bernard Tenbroek, Bill Redman-White, Mike Uren, Chris Edwards + and John Bunyan. +Acknowledgements : Rupert Howes and Pete Mole. +**********/ + +/* Modified: 2001 Paolo Nenzi */ + +#ifndef DEV_SOI3 +#define DEV_SOI3 + +SPICEdev *get_soi3_info(void); + + +#endif diff --git a/src/spicelib/devices/soi3/soi3load.c b/src/spicelib/devices/soi3/soi3load.c new file mode 100644 index 000000000..9317e078b --- /dev/null +++ b/src/spicelib/devices/soi3/soi3load.c @@ -0,0 +1,2560 @@ +/********** +STAG version 2.6 +Copyright 2000 owned by the United Kingdom Secretary of State for Defence +acting through the Defence Evaluation and Research Agency. +Developed by : Jim Benson, + Department of Electronics and Computer Science, + University of Southampton, + United Kingdom. +With help from : Nele D'Halleweyn, Bill Redman-White, and Craig Easson. + +Based on STAG version 2.1 +Developed by : Mike Lee, +With help from : Bernard Tenbroek, Bill Redman-White, Mike Uren, Chris Edwards + and John Bunyan. +Acknowledgements : Rupert Howes and Pete Mole. +**********/ + +/* Modified: 2001 Paolo Nenzi */ + +#include "ngspice.h" +#include +#include "cktdefs.h" +#include "devdefs.h" +#include "soi3defs.h" +#include "trandefs.h" +#include "const.h" +#include "sperror.h" +#include "suffix.h" + +extern double DEVsoipnjlim(double vnew, double vold,double vt,double vcrit,int *icheck); +/* extern double DEVsoipnjlim(); */ + +int +SOI3load(inModel,ckt) + GENmodel *inModel; + register CKTcircuit *ckt; + /* actually load the current value into the + * sparse matrix previously provided + */ +{ + register SOI3model *model = (SOI3model *) inModel; + register SOI3instance *here; + double Beta; + double DrainSatCur; /* for drain pn junction */ + double SourceSatCur; /* for source pn junction */ + double DrainSatCur1; /* for 2nd drain pn junction */ + double SourceSatCur1; /* for 2nd source pn junction */ + double EffectiveLength,logL; + double FrontGateBulkOverlapCap; + double FrontGateDrainOverlapCap; + double FrontGateSourceOverlapCap; + double BackGateBulkOverlapCap; + double BackGateDrainOverlapCap; + double BackGateSourceOverlapCap; + double Frontcapargs[6]; + double Backcapargs[6]; + double FrontOxideCap; + double BackOxideCap; + double arg; + double ibhat; + double idhat; + double iPthat; /* needed for convergence */ + double ieqPt; /* value of equivalent current source */ + double idrain; + double idreq; + double ieq; + double ieqct,ieqct1,ieqct2,ieqct3,ieqct4; + double ieqbd; + double ieqbs; + double iMdbeq; + double iMsbeq; + double iBJTdbeq; + double iBJTsbeq; + double delvbd; + double delvbs; + double delvds; + double delvgfd; + double delvgfs; + double delvgbd; + double delvgbs; + double deldeltaT; + double evbd,evbd1; + double evbs,evbs1; + double rtargs[5]; + double grt[5]; + double gct[5]; + int tnodeindex; + double geq; + double sarg; + double sargsw; + double tol; + double vbd; + double vbs; + double vds; +/* the next lot are so we can cast the problem with the body node as ref */ + double vsb; + double vdb; + double vgbb; +/* now back to our regular programming */ +/* vgfb exists already for gate cap calc */ + double deltaT,deltaT1,deltaT2,deltaT3,deltaT4,deltaT5; + double vdsat; + double vgfb; + double vgfd; + double vgbd; + double vgfdo; + double vgbdo; + double vgfs; + double vgbs; + double von; + double vt; + double xfact; + int xnrm; + int xrev; + +/* now stuff needed for new charge model */ + double paramargs[10]; + double Bfargs[2],alpha_args[5]; + double psi_st0args[5]; + double vGTargs[5]; + double psi_sLargs[5],psi_s0args[5]; + double ldargs[5]; + double qgatef,qdrn,qsrc,qbody,qgateb; + double ieqqgf,ieqqd,ieqqs,ieqqgb; + double cgfgf,cgfd,cgfs,cgfdeltaT; + double cdgf,cdd,cds,cddeltaT; + double csgf,csd,css,csdeltaT; + double cbgf,cbd,cbs,cbdeltaT,cbgb; + double cgbgb,cgbsb,cgbdb; + double gcgfgf,gcgfd,gcgfs,gcgfdeltaT; + double gcdgf,gcdd,gcds,gcddeltaT; + double gcsgf,gcsd,gcss,gcsdeltaT; + double gcbgf,gcbd,gcbs,gcbdeltaT,gcbgb; + double gcgbgb,gcgbsb,gcgbdb; + double gcgbs0,gcgbd0; + + double alphaBJT; + double tauFBJTeff,tauRBJTeff; + double ISts,IS1ts,IStd,IS1td; + double ieqqBJTbs,ieqqBJTbd; + double gcBJTbsbs,gcBJTbsdeltaT; + double gcBJTbdbd,gcBJTbddeltaT; + double ag0; + + int Check; + int ByPass; + + double tempv; + + int error; +#ifdef CAPBYPASS + int senflag; +#endif /* CAPBYPASS */ + int SenCond; + + /* JimB - 4/1/99. New variables for junction */ + /* depletion capacitance model. */ + double Esj, Vsj, Xs; + double Edj, Vdj, Xd; + double DXs_Dvgfb, DXs_Dvdb, DXs_Dvsb, DXs_DdeltaT; + double DXd_Dvgfb, DXd_Dvdb, DXd_Dvsb, DXd_DdeltaT; + + + for( ; model != NULL; model = model->SOI3nextModel ) { + + /* loop through all the instances of the model */ + for (here = model->SOI3instances; here != NULL ; + here=here->SOI3nextInstance) { + + vt = CONSTKoverQ * here->SOI3temp; + Check=1; + ByPass=0; + + /* first, we compute a few useful values - these could be + * pre-computed, but for historical reasons are still done + * here. They may be moved at the expense of instance size + */ + + EffectiveLength=here->SOI3l - 2*model->SOI3latDiff; + logL = log(EffectiveLength); + if (here->SOI3tSatCurDens == 0) { + DrainSatCur = here->SOI3tSatCur; + SourceSatCur = here->SOI3tSatCur; + } else { + DrainSatCur = here->SOI3tSatCurDens * + here->SOI3w; + SourceSatCur = here->SOI3tSatCurDens * + here->SOI3w; + } + if (here->SOI3tSatCurDens1 == 0) { + DrainSatCur1 = here->SOI3tSatCur1; + SourceSatCur1 = here->SOI3tSatCur1; + } else { + DrainSatCur1 = here->SOI3tSatCurDens1 * + here->SOI3w; + SourceSatCur1 = here->SOI3tSatCurDens1 * + here->SOI3w; + } +/* NB Junction sat. cur. density is NOW PER UNIT WIDTH */ + + FrontGateSourceOverlapCap = model->SOI3frontGateSourceOverlapCapFactor * + here->SOI3w; + FrontGateDrainOverlapCap = model->SOI3frontGateDrainOverlapCapFactor * + here->SOI3w; + FrontGateBulkOverlapCap = model->SOI3frontGateBulkOverlapCapFactor * + EffectiveLength; + BackGateSourceOverlapCap = model->SOI3backGateSourceOverlapCapFactor * + here->SOI3w; + BackGateDrainOverlapCap = model->SOI3backGateDrainOverlapCapFactor * + here->SOI3w; + BackGateBulkOverlapCap = model->SOI3backGateBulkOverlapCapFactor * + EffectiveLength; + + Beta = here->SOI3tTransconductance * here->SOI3w/EffectiveLength; + /* reset mu_eff to ambient temp value in SI units */ + here->SOI3ueff = here->SOI3tTransconductance/ + model->SOI3frontOxideCapFactor; + FrontOxideCap = model->SOI3frontOxideCapFactor * EffectiveLength * + here->SOI3w; + BackOxideCap = model->SOI3backOxideCapFactor * EffectiveLength * + here->SOI3w; + /* + * ok - now to do the start-up operations + * + * we must get values for vbs, vds, vgfs and vgbs from somewhere + * so we either predict them or recover them from last iteration + * These are the two most common cases - either a prediction + * step or the general iteration step and they + * share some code, so we put them first - others later on + */ + + /* yeah, but we'll then use vsb and vdb for the real work */ + +/* we will use conventional voltages to save * + * work rewriting the convergence criteria */ + + if((ckt->CKTmode & (MODEINITFLOAT | MODEINITPRED | MODEINITSMSIG + | MODEINITTRAN)) || + ( (ckt->CKTmode & MODEINITFIX) && (!here->SOI3off) ) ) + { +#ifndef PREDICTOR + if(ckt->CKTmode & (MODEINITPRED | MODEINITTRAN) ) + { + + /* predictor step */ + + xfact=ckt->CKTdelta/ckt->CKTdeltaOld[1]; + *(ckt->CKTstate0 + here->SOI3vbs) = + *(ckt->CKTstate1 + here->SOI3vbs); + vbs = (1+xfact)* (*(ckt->CKTstate1 + here->SOI3vbs)) + -(xfact * (*(ckt->CKTstate2 + here->SOI3vbs))); + *(ckt->CKTstate0 + here->SOI3vgfs) = + *(ckt->CKTstate1 + here->SOI3vgfs); + vgfs = (1+xfact)* (*(ckt->CKTstate1 + here->SOI3vgfs)) + -(xfact * (*(ckt->CKTstate2 + here->SOI3vgfs))); + *(ckt->CKTstate0 + here->SOI3vgbs) = + *(ckt->CKTstate1 + here->SOI3vgbs); + vgbs = (1+xfact)* (*(ckt->CKTstate1 + here->SOI3vgbs)) + -(xfact * (*(ckt->CKTstate2 + here->SOI3vgbs))); + *(ckt->CKTstate0 + here->SOI3vds) = + *(ckt->CKTstate1 + here->SOI3vds); + vds = (1+xfact)* (*(ckt->CKTstate1 + here->SOI3vds)) + -(xfact * (*(ckt->CKTstate2 + here->SOI3vds))); + *(ckt->CKTstate0 + here->SOI3vbd) = + *(ckt->CKTstate0 + here->SOI3vbs)- + *(ckt->CKTstate0 + here->SOI3vds); + *(ckt->CKTstate0 + here->SOI3deltaT) = + *(ckt->CKTstate1 + here->SOI3deltaT); + deltaT = MAX(0,(1+xfact)* (*(ckt->CKTstate1 + here->SOI3deltaT)) + -(xfact * (*(ckt->CKTstate2 + here->SOI3deltaT)))); + /* need to stop deltaT being -ve */ + + /* JimB - 19/5/99 */ + if (here->SOI3numThermalNodes == 0) + { + deltaT1=deltaT2=deltaT3=deltaT4=deltaT5=0.0; + } + if (here->SOI3numThermalNodes == 1) + { + deltaT1=deltaT; + deltaT2=deltaT3=deltaT4=deltaT5=0.0; + } + if (here->SOI3numThermalNodes == 2) + { + deltaT1 = MAX(0,(1+xfact)* (*(ckt->CKTstate1 + here->SOI3deltaT1)) + -(xfact * (*(ckt->CKTstate2 + here->SOI3deltaT1)))); + deltaT2 = MAX(0,(1+xfact)* (*(ckt->CKTstate1 + here->SOI3deltaT2)) + -(xfact * (*(ckt->CKTstate2 + here->SOI3deltaT2)))); + deltaT3=deltaT4=deltaT5=0.0; + } + if (here->SOI3numThermalNodes == 3) + { + deltaT1 = MAX(0,(1+xfact)* (*(ckt->CKTstate1 + here->SOI3deltaT1)) + -(xfact * (*(ckt->CKTstate2 + here->SOI3deltaT1)))); + deltaT2 = MAX(0,(1+xfact)* (*(ckt->CKTstate1 + here->SOI3deltaT2)) + -(xfact * (*(ckt->CKTstate2 + here->SOI3deltaT2)))); + deltaT3 = MAX(0,(1+xfact)* (*(ckt->CKTstate1 + here->SOI3deltaT3)) + -(xfact * (*(ckt->CKTstate2 + here->SOI3deltaT3)))); + deltaT4=deltaT5=0.0; + } + if (here->SOI3numThermalNodes == 4) + { + deltaT1 = MAX(0,(1+xfact)* (*(ckt->CKTstate1 + here->SOI3deltaT1)) + -(xfact * (*(ckt->CKTstate2 + here->SOI3deltaT1)))); + deltaT2 = MAX(0,(1+xfact)* (*(ckt->CKTstate1 + here->SOI3deltaT2)) + -(xfact * (*(ckt->CKTstate2 + here->SOI3deltaT2)))); + deltaT3 = MAX(0,(1+xfact)* (*(ckt->CKTstate1 + here->SOI3deltaT3)) + -(xfact * (*(ckt->CKTstate2 + here->SOI3deltaT3)))); + deltaT4 = MAX(0,(1+xfact)* (*(ckt->CKTstate1 + here->SOI3deltaT4)) + -(xfact * (*(ckt->CKTstate2 + here->SOI3deltaT4)))); + deltaT5=0.0; + } + if (here->SOI3numThermalNodes == 5) + { + deltaT1 = MAX(0,(1+xfact)* (*(ckt->CKTstate1 + here->SOI3deltaT1)) + -(xfact * (*(ckt->CKTstate2 + here->SOI3deltaT1)))); + deltaT2 = MAX(0,(1+xfact)* (*(ckt->CKTstate1 + here->SOI3deltaT2)) + -(xfact * (*(ckt->CKTstate2 + here->SOI3deltaT2)))); + deltaT3 = MAX(0,(1+xfact)* (*(ckt->CKTstate1 + here->SOI3deltaT3)) + -(xfact * (*(ckt->CKTstate2 + here->SOI3deltaT3)))); + deltaT4 = MAX(0,(1+xfact)* (*(ckt->CKTstate1 + here->SOI3deltaT4)) + -(xfact * (*(ckt->CKTstate2 + here->SOI3deltaT4)))); + deltaT5 =MAX(0,deltaT-deltaT1-deltaT2-deltaT3-deltaT4); + } + + *(ckt->CKTstate0 + here->SOI3idrain) = + *(ckt->CKTstate1 + here->SOI3idrain); + *(ckt->CKTstate0 + here->SOI3cgfgf) = + *(ckt->CKTstate1 + here->SOI3cgfgf); + *(ckt->CKTstate0 + here->SOI3cgfd) = + *(ckt->CKTstate1 + here->SOI3cgfd); + *(ckt->CKTstate0 + here->SOI3cgfs) = + *(ckt->CKTstate1 + here->SOI3cgfs); + *(ckt->CKTstate0 + here->SOI3cgfdeltaT) = + *(ckt->CKTstate1 + here->SOI3cgfdeltaT); + *(ckt->CKTstate0 + here->SOI3csgf) = + *(ckt->CKTstate1 + here->SOI3csgf); + *(ckt->CKTstate0 + here->SOI3csd) = + *(ckt->CKTstate1 + here->SOI3csd); + *(ckt->CKTstate0 + here->SOI3css) = + *(ckt->CKTstate1 + here->SOI3css); + *(ckt->CKTstate0 + here->SOI3csdeltaT) = + *(ckt->CKTstate1 + here->SOI3csdeltaT); + *(ckt->CKTstate0 + here->SOI3cdgf) = + *(ckt->CKTstate1 + here->SOI3cdgf); + *(ckt->CKTstate0 + here->SOI3cdd) = + *(ckt->CKTstate1 + here->SOI3cdd); + *(ckt->CKTstate0 + here->SOI3cds) = + *(ckt->CKTstate1 + here->SOI3cds); + *(ckt->CKTstate0 + here->SOI3cddeltaT) = + *(ckt->CKTstate1 + here->SOI3cddeltaT); + *(ckt->CKTstate0 + here->SOI3cgbgb) = + *(ckt->CKTstate1 + here->SOI3cgbgb); + *(ckt->CKTstate0 + here->SOI3cgbsb) = + *(ckt->CKTstate1 + here->SOI3cgbsb); + *(ckt->CKTstate0 + here->SOI3cgbdb) = + *(ckt->CKTstate1 + here->SOI3cgbdb); + *(ckt->CKTstate0 + here->SOI3cBJTbsbs) = + *(ckt->CKTstate1 + here->SOI3cBJTbsbs); + *(ckt->CKTstate0 + here->SOI3cBJTbsdeltaT) = + *(ckt->CKTstate1 + here->SOI3cBJTbsdeltaT); + *(ckt->CKTstate0 + here->SOI3cBJTbdbd) = + *(ckt->CKTstate1 + here->SOI3cBJTbdbd); + *(ckt->CKTstate0 + here->SOI3cBJTbddeltaT) = + *(ckt->CKTstate1 + here->SOI3cBJTbddeltaT); + } + else + { +#endif /* PREDICTOR */ + + /* general iteration */ + + vbs = model->SOI3type * ( + *(ckt->CKTrhsOld+here->SOI3bNode) - + *(ckt->CKTrhsOld+here->SOI3sNodePrime)); + vgfs = model->SOI3type * ( + *(ckt->CKTrhsOld+here->SOI3gfNode) - + *(ckt->CKTrhsOld+here->SOI3sNodePrime)); + vgbs = model->SOI3type * ( + *(ckt->CKTrhsOld+here->SOI3gbNode) - + *(ckt->CKTrhsOld+here->SOI3sNodePrime)); + vds = model->SOI3type * ( + *(ckt->CKTrhsOld+here->SOI3dNodePrime) - + *(ckt->CKTrhsOld+here->SOI3sNodePrime)); + deltaT = MAX(0,*(ckt->CKTrhsOld+here->SOI3toutNode)); + /* voltage deltaT is V(tout) wrt ground + and shoule be positive */ +/* the next lot are needed for the (extra) thermal capacitances */ + /* JimB - 19/5/99 */ + if (here->SOI3numThermalNodes == 0) + { + deltaT1=deltaT2=deltaT3=deltaT4=deltaT5=0; + } + if (here->SOI3numThermalNodes == 1) + { + deltaT1=deltaT; + deltaT2=deltaT3=deltaT4=deltaT5=0; + } + if (here->SOI3numThermalNodes == 2) + { + deltaT2 = MAX(0,*(ckt->CKTrhsOld+here->SOI3tout1Node)); + deltaT1 = deltaT - deltaT2; + deltaT3=deltaT4=deltaT5=0; + } + if (here->SOI3numThermalNodes == 3) + { + deltaT3 = MAX(0,*(ckt->CKTrhsOld+here->SOI3tout2Node)); + deltaT2 = MAX(0,*(ckt->CKTrhsOld+here->SOI3tout1Node) - deltaT3); + deltaT1 = deltaT - deltaT2 - deltaT3; + deltaT4=deltaT5=0; + } + if (here->SOI3numThermalNodes == 4) + { + deltaT4 = MAX(0,*(ckt->CKTrhsOld+here->SOI3tout3Node)); + deltaT3 = MAX(0,*(ckt->CKTrhsOld+here->SOI3tout2Node) - deltaT4); + deltaT2 = MAX(0,*(ckt->CKTrhsOld+here->SOI3tout1Node) - deltaT3); + deltaT1 = deltaT - deltaT2 - deltaT3 - deltaT4; + deltaT5=0; + } + if (here->SOI3numThermalNodes == 5) + { + deltaT5 = MAX(0,*(ckt->CKTrhsOld+here->SOI3tout4Node)); + deltaT4 = MAX(0,*(ckt->CKTrhsOld+here->SOI3tout3Node) - deltaT5); + deltaT3 = MAX(0,*(ckt->CKTrhsOld+here->SOI3tout2Node) - deltaT4); + deltaT2 = MAX(0,*(ckt->CKTrhsOld+here->SOI3tout1Node) - deltaT3); + deltaT1 = deltaT - deltaT2 - deltaT3 - deltaT4 - deltaT5; + } +#ifndef PREDICTOR + } +#endif /* PREDICTOR */ + + + /* now some common crunching for some more useful quantities */ + /* bloody useful in our case */ + + vbd=vbs-vds; + vdb=-vbd; + vsb=-vbs; + + vgfd=vgfs-vds; + vgbd=vgbs-vds; + vgbb=vgbs-vbs; + vgfdo = *(ckt->CKTstate0 + here->SOI3vgfs) - + *(ckt->CKTstate0 + here->SOI3vds); + vgbdo = *(ckt->CKTstate0 + here->SOI3vgbs) - + *(ckt->CKTstate0 + here->SOI3vds); + delvbs = vbs - *(ckt->CKTstate0 + here->SOI3vbs); + delvbd = vbd - *(ckt->CKTstate0 + here->SOI3vbd); + delvgfs = vgfs - *(ckt->CKTstate0 + here->SOI3vgfs); + delvgbs = vgbs - *(ckt->CKTstate0 + here->SOI3vgbs); + delvds = vds - *(ckt->CKTstate0 + here->SOI3vds); + delvgfd = vgfd-vgfdo; + delvgbd = vgbd-vgbdo; + deldeltaT = deltaT - *(ckt->CKTstate0 + here->SOI3deltaT); + + /* these are needed for convergence testing */ + /* we're keeping these the same as convergence on + vgfs, vbs, vbd, vgbs, deltaT is equiv to conv. + on vgfb, vsb, vdb, vgb_b, deltaT */ + + if (here->SOI3mode >= 0) { /* normal */ + idhat= + here->SOI3id- + here->SOI3gbd * delvbd - + here->SOI3gbdT * deldeltaT + /* for -ibd bit of id */ + (here->SOI3gmbs + + here->SOI3gMmbs) * delvbs + + (here->SOI3gmf + + here->SOI3gMmf) * delvgfs + + (here->SOI3gmb + + here->SOI3gMmb) * delvgbs + + (here->SOI3gds + + here->SOI3gMd) * delvds + + (here->SOI3gt + + here->SOI3gMdeltaT) * deldeltaT + + here->SOI3gBJTdb_bs * delvbs + + here->SOI3gBJTdb_deltaT * deldeltaT; + ibhat= + here->SOI3ibs + + here->SOI3ibd + + here->SOI3gbd * delvbd + + here->SOI3gbdT * deldeltaT + + here->SOI3gbs * delvbs + + here->SOI3gbsT * deldeltaT - + here->SOI3iMdb - + here->SOI3gMmbs * delvbs - + here->SOI3gMmf * delvgfs - + here->SOI3gMmb * delvgbs - + here->SOI3gMd * delvds - + here->SOI3gMdeltaT * deldeltaT - + here->SOI3iBJTsb - + here->SOI3gBJTsb_bd * delvbd - + here->SOI3gBJTsb_deltaT * deldeltaT - + here->SOI3iBJTdb - + here->SOI3gBJTdb_bs * delvbs - + here->SOI3gBJTdb_deltaT * deldeltaT; + } else { /* A over T */ + idhat= + here->SOI3id - + ( here->SOI3gbd + + here->SOI3gmbs) * delvbd - + (here->SOI3gmf) * delvgfd - + (here->SOI3gmb) * delvgbd + + (here->SOI3gds) * delvds - + (here->SOI3gt + + here->SOI3gbdT) * deldeltaT + + here->SOI3gBJTdb_bs * delvbs + + here->SOI3gBJTdb_deltaT * deldeltaT; + ibhat= + here->SOI3ibs + + here->SOI3ibd + + here->SOI3gbd * delvbd + + here->SOI3gbdT * deldeltaT + + here->SOI3gbs * delvbs + + here->SOI3gbsT * deldeltaT - + here->SOI3iMsb - + here->SOI3gMmbs * delvbd - + here->SOI3gMmf * delvgfd - + here->SOI3gMmb * delvgbd + + here->SOI3gMd * delvds - /* gMd should go with vsd */ + here->SOI3gMdeltaT * deldeltaT - + here->SOI3iBJTsb - + here->SOI3gBJTsb_bd * delvbd - + here->SOI3gBJTsb_deltaT * deldeltaT - + here->SOI3iBJTdb - + here->SOI3gBJTdb_bs * delvbs - + here->SOI3gBJTdb_deltaT * deldeltaT; + } +/* thermal current source comparator */ + iPthat =here->SOI3iPt + + here->SOI3gPmbs * delvbs + + here->SOI3gPmf * delvgfs + + here->SOI3gPmb * delvgbs + + here->SOI3gPds * delvds * here->SOI3mode + + here->SOI3gPdT * deldeltaT; +/* + +*/ + +#ifdef DETAILPROF +asm(" .globl mosptb"); +asm("mosptb:"); +#endif /*DETAILPROF*/ + + /* now lets see if we can bypass (ugh) */ + /* the following mess should be one if statement, but + * many compilers can't handle it all at once, so it + * is split into several successive if statements + */ + /* bypass just needs to check any four voltages have not changed + so leave as before to avoid hassle */ + tempv = MAX(fabs(ibhat),fabs(here->SOI3ibs + + here->SOI3ibd-here->SOI3iMsb + - here->SOI3iMdb - here->SOI3iBJTdb + - here->SOI3iBJTsb))+ckt->CKTabstol; + if((!(ckt->CKTmode & (MODEINITPRED|MODEINITTRAN|MODEINITSMSIG) + )) && (ckt->CKTbypass) ) + if ( (fabs(ibhat-(here->SOI3ibs + + here->SOI3ibd-here->SOI3iMdb + - here->SOI3iMsb - here->SOI3iBJTdb + - here->SOI3iBJTsb)) < ckt->CKTreltol * + tempv)) + if( (fabs(delvbs) < (ckt->CKTreltol * MAX(fabs(vbs), + fabs(*(ckt->CKTstate0+here->SOI3vbs)))+ + ckt->CKTvoltTol))) + if ( (fabs(delvbd) < (ckt->CKTreltol * MAX(fabs(vbd), + fabs(*(ckt->CKTstate0+here->SOI3vbd)))+ + ckt->CKTvoltTol)) ) + if( (fabs(delvgfs) < (ckt->CKTreltol * MAX(fabs(vgfs), + fabs(*(ckt->CKTstate0+here->SOI3vgfs)))+ + ckt->CKTvoltTol))) + if( (fabs(delvgbs) < (ckt->CKTreltol * MAX(fabs(vgbs), + fabs(*(ckt->CKTstate0+here->SOI3vgbs)))+ + ckt->CKTvoltTol))) + if ( (fabs(delvds) < (ckt->CKTreltol * MAX(fabs(vds), + fabs(*(ckt->CKTstate0+here->SOI3vds)))+ + ckt->CKTvoltTol)) ) + if ( (fabs(deldeltaT) < (ckt->CKTreltol * MAX(fabs(deltaT), + fabs(*(ckt->CKTstate0+here->SOI3deltaT)))+ + ckt->CKTvoltTol)) ) + if( (fabs(iPthat- here->SOI3iPt) < + ckt->CKTreltol * MAX(fabs(iPthat),fabs( + here->SOI3iPt)) + ckt->CKTabstol) ) + if( (fabs(idhat- here->SOI3id) < + ckt->CKTreltol * MAX(fabs(idhat),fabs( + here->SOI3id)) + ckt->CKTabstol) ) { + /* bypass code */ + /* nothing interesting has changed since last + * iteration on this device, so we just + * copy all the values computed last iteration out + * and keep going + */ + vbs = *(ckt->CKTstate0 + here->SOI3vbs); + vbd = *(ckt->CKTstate0 + here->SOI3vbd); + vgfs = *(ckt->CKTstate0 + here->SOI3vgfs); + vgbs = *(ckt->CKTstate0 + here->SOI3vgbs); + vds = *(ckt->CKTstate0 + here->SOI3vds); + deltaT = *(ckt->CKTstate0 + here->SOI3deltaT); + deltaT1 = *(ckt->CKTstate0 + here->SOI3deltaT1); + deltaT2 = *(ckt->CKTstate0 + here->SOI3deltaT2); + deltaT3 = *(ckt->CKTstate0 + here->SOI3deltaT3); + deltaT4 = *(ckt->CKTstate0 + here->SOI3deltaT4); + deltaT5 = *(ckt->CKTstate0 + here->SOI3deltaT5); + /* and now the extra ones */ + vsb=-vbs; + vdb=-vbd; + vgfb = vgfs - vbs; + vgbb = vgbs - vbs; + + /* JimB - 15/9/99 */ + /* Code for multiple thermal time constants. Start by moving all */ + /* rt constants into arrays. */ + rtargs[0]=here->SOI3rt; + rtargs[1]=here->SOI3rt1; + rtargs[2]=here->SOI3rt2; + rtargs[3]=here->SOI3rt3; + rtargs[4]=here->SOI3rt4; + + /* Set all conductance components to zero. */ + grt[0]=grt[1]=grt[2]=grt[3]=grt[4]=0.0; + /* Now calculate conductances from rt. */ + /* Don't need to worry about divide by zero when calculating */ + /* grt components, as soi3setup() only creates a thermal node */ + /* if corresponding rt is greater than zero. */ + for(tnodeindex=0;tnodeindexSOI3numThermalNodes;tnodeindex++) + { + grt[tnodeindex]=1/rtargs[tnodeindex]; + } + /* End JimB */ + + vgfd = vgfs - vds; + vgbd = vgbs - vds; + if (here->SOI3mode==1) + { + idrain = here->SOI3id + here->SOI3ibd - here->SOI3iMdb + - here->SOI3iBJTdb; + } + else + { + idrain = -here->SOI3id - here->SOI3ibd + + here->SOI3iBJTdb; + } + + /* Pt doesn't need changing as it's in here->SOI3iPt */ + + if((ckt->CKTmode & (MODETRAN | MODEAC)) || + (ckt->CKTmode & MODETRANOP)) + { + cgfgf = *(ckt->CKTstate0 + here->SOI3cgfgf); + cgfd = *(ckt->CKTstate0 + here->SOI3cgfd); + cgfs = *(ckt->CKTstate0 + here->SOI3cgfs); + cgfdeltaT = *(ckt->CKTstate0 + here->SOI3cgfdeltaT); + csgf = *(ckt->CKTstate0 + here->SOI3csgf); + csd = *(ckt->CKTstate0 + here->SOI3csd); + css = *(ckt->CKTstate0 + here->SOI3css); + csdeltaT = *(ckt->CKTstate0 + here->SOI3csdeltaT); + cdgf = *(ckt->CKTstate0 + here->SOI3cdgf); + cdd = *(ckt->CKTstate0 + here->SOI3cdd); + cds = *(ckt->CKTstate0 + here->SOI3cds); + cddeltaT = *(ckt->CKTstate0 + here->SOI3cddeltaT); + cgbgb = *(ckt->CKTstate0 + here->SOI3cgbgb); + cgbsb = *(ckt->CKTstate0 + here->SOI3cgbsb); + cgbdb = *(ckt->CKTstate0 + here->SOI3cgbdb); + cbgf = -(cgfgf + cdgf + csgf); + cbd = -(cgfd + cdd + csd + cgbdb); + cbs = -(cgfs + cds + css + cgbsb); + cbdeltaT = -(cgfdeltaT + cddeltaT + csdeltaT); + cbgb = -cgbgb; + qgatef = *(ckt->CKTstate0 + here->SOI3qgf); + qdrn = *(ckt->CKTstate0 + here->SOI3qd); + qsrc = *(ckt->CKTstate0 + here->SOI3qs); + qgateb = *(ckt->CKTstate0 + here->SOI3qgb); + qbody = -(qgatef + qdrn + qsrc + qgateb); + ByPass = 1; + goto bypass1; + } + goto bypass2; + } +/* + +*/ + +#ifdef DETAILPROF +asm(" .globl mosptc"); +asm("mosptc:"); +#endif /*DETAILPROF*/ + /* ok - bypass is out, do it the hard way */ + + von = model->SOI3type * here->SOI3von; + +#ifndef NODELIMITING + /* + * limiting + * we want to keep device voltages from changing + * so fast that the exponentials churn out overflows + * and similar rudeness + */ + + if(*(ckt->CKTstate0 + here->SOI3vds) >=0) + { + vgfs = DEVfetlim(vgfs,*(ckt->CKTstate0 + here->SOI3vgfs) + ,von); + vds = vgfs - vgfd; + vds = DEVlimvds(vds,*(ckt->CKTstate0 + here->SOI3vds)); + vgfd = vgfs - vds; + } + else + { + vgfd = DEVfetlim(vgfd,vgfdo,von); + vds = vgfs - vgfd; + if(!(ckt->CKTfixLimit)) + { + vds = -DEVlimvds(-vds,-(*(ckt->CKTstate0 + + here->SOI3vds))); + } + vgfs = vgfd + vds; + } + if(vds >= 0) + { + vbs = DEVsoipnjlim(vbs,*(ckt->CKTstate0 + here->SOI3vbs), + vt,here->SOI3sourceVcrit,&Check); + vbd = vbs-vds; + } + else + { + vbd = DEVsoipnjlim(vbd,*(ckt->CKTstate0 + here->SOI3vbd), + vt,here->SOI3drainVcrit,&Check); + vbs = vbd + vds; + } + + + /* and now some limiting of the temperature rise */ + if (deltaT>(10 + *(ckt->CKTstate0 + here->SOI3deltaT))) + { + deltaT = 10 + *(ckt->CKTstate0 + here->SOI3deltaT); + + /* need limiting, therefore must also impose limits on other + thermal voltages. + */ + + /* JimB - 19/5/99 */ + if (here->SOI3numThermalNodes == 0) + { + deltaT1=deltaT2=deltaT3=deltaT4=deltaT5=0; + } + if (here->SOI3numThermalNodes == 1) + { + deltaT1=deltaT; + deltaT2=deltaT3=deltaT4=deltaT5=0; + } + if (here->SOI3numThermalNodes == 2) + { + deltaT2 = MAX(0,*(ckt->CKTrhsOld+here->SOI3tout1Node)); + deltaT1 = deltaT - deltaT2; + deltaT3=deltaT4=deltaT5=0; + } + if (here->SOI3numThermalNodes == 3) + { + deltaT3 = MAX(0,*(ckt->CKTrhsOld+here->SOI3tout2Node)); + deltaT2 = MAX(0,*(ckt->CKTrhsOld+here->SOI3tout1Node) - deltaT3); + deltaT1 = deltaT - deltaT2 - deltaT3; + deltaT4=deltaT5=0; + } + if (here->SOI3numThermalNodes == 4) + { + deltaT4 = MAX(0,*(ckt->CKTrhsOld+here->SOI3tout3Node)); + deltaT3 = MAX(0,*(ckt->CKTrhsOld+here->SOI3tout2Node) - deltaT4); + deltaT2 = MAX(0,*(ckt->CKTrhsOld+here->SOI3tout1Node) - deltaT3); + deltaT1 = deltaT - deltaT2 - deltaT3 - deltaT4; + deltaT5=0; + } + if (here->SOI3numThermalNodes == 5) + { + deltaT5 = MAX(0,*(ckt->CKTrhsOld+here->SOI3tout4Node)); + deltaT4 = MAX(0,*(ckt->CKTrhsOld+here->SOI3tout3Node) - deltaT5); + deltaT3 = MAX(0,*(ckt->CKTrhsOld+here->SOI3tout2Node) - deltaT4); + deltaT2 = MAX(0,*(ckt->CKTrhsOld+here->SOI3tout1Node) - deltaT3); + deltaT1 = deltaT - deltaT2 - deltaT3 - deltaT4 - deltaT5; + } + + Check = 1; + } +#endif /*NODELIMITING*/ +/* + +*/ + +#ifdef DETAILPROF +asm(" .globl mosptd"); +asm("mosptd:"); +#endif /*DETAILPROF*/ + } else { + + /* ok - not one of the simple cases, so we have to + * look at all of the possibilities for why we were + * called. We still just initialize the three voltages + */ + + if((ckt->CKTmode & MODEINITJCT) && !here->SOI3off) + { + vds= model->SOI3type * here->SOI3icVDS; + vgfs= model->SOI3type * here->SOI3icVGFS; + vgbs= model->SOI3type * here->SOI3icVGBS; + vbs= model->SOI3type * here->SOI3icVBS; + deltaT=deltaT1=deltaT2=deltaT3=deltaT4=deltaT5=0.0; + if((vds==0) && (vgfs==0) && (vbs==0) && (vgbs==0) && + ((ckt->CKTmode & + (MODETRAN|MODEDCOP|MODEDCTRANCURVE)) || + (!(ckt->CKTmode & MODEUIC)))) + { + vbs = -1; + vgfs = model->SOI3type * here->SOI3tVto; + vds = 0; + vgbs = 0; + deltaT=deltaT1=deltaT2=deltaT3=deltaT4=deltaT5=0.0; + } + } + else + { + vbs=vgfs=vds=vgbs=deltaT=deltaT1=deltaT2=deltaT3=deltaT4=deltaT5=0.0; + } + } +/* + +*/ + +#ifdef DETAILPROF +asm(" .globl mospte"); +asm("mospte:"); +#endif /*DETAILPROF*/ + + /* + * now all the preliminaries are over - we can start doing the + * real work + */ + vbd = vbs - vds; + vgfd = vgfs - vds; + vgbd = vgbs - vds; + vgfb = vgfs - vbs; + vgbb = vgbs - vbs; + vsb = -vbs; + vdb = -vbd; + + + /* now to determine whether the user was able to correctly + * identify the source and drain of his device + */ + if(vds >= 0) { + /* normal mode */ + here->SOI3mode = 1; + } else { + /* inverse mode */ + here->SOI3mode = -1; + } +/* + +*/ + +#ifdef DETAILPROF +asm(" .globl mosptf"); +asm("mosptf:"); +#endif /*DETAILPROF*/ + { /* begin block */ + + /* + * This block works out drain current and derivatives. + * It does this via the calculation of the surface potential + * which is a bit complex mostly for reasons of continuity + * and robustness - c'est la vie. + * + */ + + /* the following variables are local to this code block until + * it is obvious that they can be made global + */ + double vg; + double eta_s; /* 1+Citf/Cof */ + double gamma,sigma; + double Egy,vgy,Sgy; + double psi_ss; + double AL,A0,LL,L0; + double ALx,A0x,EAL,EA0; + double logterm0,logtermL; + double Vgconst0,VgconstL; + double Egx0,EgxL; + double vgx0,vgxL; + double psi_si0,psi_siL,psi_st0; + double Esi0,EsiL,Ess0; + double theta2; + double TVF; /* thermal velocity-saturation factor */ + double Mmob; + double sqt0,sqt0one; + double alpha,delta,Bf; + double vGBF,vGT,vGBT; + double PSI; + double S; + double psi_sLsat; + double Esd0,EsdL; + + double psi_s0,psi_sL; + double fL,f0; + double DfL_Dvgfb,DfL_Dvdb,DfL_Dvsb,DfL_DdeltaT; + double Df0_Dvgfb,Df0_Dvdb,Df0_Dvsb,Df0_DdeltaT; + double ld,Dld_Dvgfb,Dld_Dvdb,Dld_Dvsb,Dld_DdeltaT; + + double ich0; + + double pDpsi_si0_Dvgx0,pDpsi_siL_DvgxL; + double Dvgx0_Dvgfb,pDvgx0_Dvg,Dvgx0_Dvsb,Dvgx0_Dvdb,Dvgx0_DdeltaT; + double DvgxL_Dvgfb,pDvgxL_Dvg,DvgxL_Dvsb,DvgxL_Dvdb,DvgxL_DdeltaT; + double pDpsi_si0_Dvsb,pDpsi_siL_Dvdb; + double Dpsi_si0_Dvgfb,Dpsi_si0_Dvsb,Dpsi_si0_Dvdb; + double Dpsi_siL_Dvgfb,Dpsi_siL_Dvsb,Dpsi_siL_Dvdb; + double Dpsi_ss_Dvgfb,Dpsi_ss_Dvsb,Dpsi_ss_Dvdb; + double Dpsi_st0_Dvgfb,Dpsi_st0_Dvsb,Dpsi_st0_Dvdb; + double pDdelta_Dpsi_st0; + double Dalpha_Dvgfb,Dalpha_Dvdb,Dalpha_Dvsb,Dalpha_DdeltaT; + double DPSI_Dvgfb,DPSI_Dvdb,DPSI_Dvsb,DPSI_DdeltaT; + double pDBf_Dpsi_st0,DvGT_Dvgfb,DvGT_Dvsb,DvGT_Dvdb,DvGT_DdeltaT; + double D,DS_Dvgfb,DS_Dvsb,DS_Dvdb,DS_DdeltaT; + double Dpsi_sLsat_Dvgfb,Dpsi_sLsat_Dvsb,Dpsi_sLsat_Dvdb; + double gmg,gmd,gms,gmt; + double Dpsi_si0_DdeltaT,Dpsi_siL_DdeltaT; + double Dpsi_ss_DdeltaT,Dpsi_st0_DdeltaT; + double Dpsi_sLsat_DdeltaT; + double Dpsi_sL_Dvgfb,Dpsi_s0_Dvgfb,Dpsi_sL_Dvdb,Dpsi_s0_Dvdb; + double Dpsi_sL_Dvsb,Dpsi_s0_Dvsb,Dpsi_sL_DdeltaT,Dpsi_s0_DdeltaT; + double Vm,Em,Vmx; + double DVmx_Dvgfb,DVmx_Dvdb,DVmx_Dvsb,DVmx_DdeltaT; + double Vm1,Em1,Vm1x; + double DVm1x_Dvgfb,DVm1x_Dvdb,DVm1x_Dvsb,DVm1x_DdeltaT; + double vgeff,lm,lmeff,lmeff2,Elm,Dlm_Dvgfb,Dlm_Dvdb,Dlm_Dvsb,Dlm_DdeltaT; + + double Mminus1=0; + double EM,betaM; + double gMg,gMd,gMs; + double Fm; /* mobility degradation factor */ + double Y; /* channel length modulation factor */ + double tmp,tmp1; /* temporary var to aid pre-calculation */ + double TMF; /* thermal mobility factor */ + int vgx0trans,vgxLtrans; /* flags to indicate if vg transform performed */ + int psi_s0_trans,psi_sL_trans; + int Ess0_trans,Esd0_trans,EsdL_trans; + int A0trans,ALtrans; + + double vT,EchiD,EchiD1; + double BetaBJTeff; + +/* Now we use a nasty trick - if device is A over T, must "swap" drain and source + potentials. we do a literal switch and change it back for the outside world. */ + if (here->SOI3mode == -1) { + tmp = vsb; + vsb = vdb; + vdb = tmp; + } + +/* Intrinsic Electrical Bit - has a bit of thermal due to TTC */ + sigma = model->SOI3sigma/(EffectiveLength); + eta_s = 1 + (model->SOI3C_ssf/model->SOI3frontOxideCapFactor); + vg = vgfb - here->SOI3tVfbF * model->SOI3type + + sigma*(here->SOI3mode*vds) + - model->SOI3chiFB*deltaT; + gamma = model->SOI3gamma * (1 + (model->SOI3deltaW)/(here->SOI3w)) + * (1 - (model->SOI3deltaL)/EffectiveLength); +/* must introduce some limiting to prevent exp overflow */ + if (vg > (vt*MAX_EXP_ARG)) { + vgy = vg; + } else { + Egy = exp(vg/vt); + vgy = vt*log(1+Egy); + } + Sgy = sqrt((vgy/eta_s) + (gamma*gamma)/(4*eta_s*eta_s)); + psi_ss = (Sgy-0.5*gamma/eta_s)*(Sgy-0.5*gamma/eta_s); + A0 = here->SOI3tPhi + vsb; + AL = here->SOI3tPhi + vdb; + if (A0 > (vt*MAX_EXP_ARG)) { + A0x = A0; + A0trans = 0; + } else { + EA0 = exp(A0/vt); + A0x = vt * log(1+EA0); + A0trans = 1; + } + if (AL > (vt*MAX_EXP_ARG)) { + ALx = AL; + ALtrans = 0; + } else { + EAL = exp(AL/vt); + ALx = vt * log(1+EAL); + ALtrans = 1; + } +/* if vg is very large then don't need to transform + vg into vgx. +*/ + Vgconst0 = eta_s*A0x - vt*(eta_s - 1) + gamma*sqrt(A0x); + if ((vg-Vgconst0) < (5 * vt * MAX_EXP_ARG)) { + vgx0trans = 1; + Egx0 = exp((vg - Vgconst0)/(5*vt)); + vgx0 = (5*vt) * log(1 + Egx0) + Vgconst0; + } else { + vgx0trans = 0; /* no transform performed */ + vgx0 = vg; + } + + + VgconstL = eta_s*ALx - vt*(eta_s - 1) + gamma*sqrt(ALx); + if ((vg-VgconstL) < (5 * vt * MAX_EXP_ARG)) { + vgxLtrans = 1; + EgxL = exp((vg - VgconstL)/(5*vt)); + vgxL = (5*vt) * log(1 + EgxL) + VgconstL; + } else { + vgxLtrans = 0; /* no transform performed */ + vgxL = vg; + } + + L0 = vgx0 - eta_s*(A0 - vt); + LL = vgxL - eta_s*(AL - vt); + logterm0 = ((L0/gamma)*(L0/gamma) - A0)/vt; + logtermL = ((LL/gamma)*(LL/gamma) - AL)/vt; + if (logterm0<=0) { /* can only happen due to numerical problems with sqrt*/ + psi_si0 = A0 + model->SOI3chiPHI*deltaT + vt*log(vt/(gamma*gamma)); + } else { + psi_si0 = A0 + model->SOI3chiPHI*deltaT + vt*log(logterm0); + } + if (logtermL<=0) { + psi_siL = AL + model->SOI3chiPHI*deltaT + vt*log(vt/(gamma*gamma)); + } else { + psi_siL = AL + model->SOI3chiPHI*deltaT + vt*log(logtermL); + } + + if ((psi_si0-psi_ss) < vt*MAX_EXP_ARG) { + Ess0 = exp((psi_si0-psi_ss)/vt); + Ess0_trans = 1; + if (psi_si0 > (vt * MAX_EXP_ARG)) { /* psi_si0 is BIG */ + psi_st0 = psi_si0 - vt*log(1+Ess0); + psi_s0_trans = 0; + } else { + Esi0 = exp(psi_si0/vt); + psi_st0 = vt*log(1+(Esi0/(1+Ess0))); + psi_s0_trans = 1; + } + } else { + psi_st0 = psi_ss; + Ess0_trans = 0; + psi_s0_trans = 0; + } + +/* now for psi_sLsat - has thermal influence ! (if vel sat is included) */ + TMF = exp(-model->SOI3k*log(1+(deltaT/here->SOI3temp))); + sqt0 = sqrt(psi_st0+1E-25); + sqt0one = sqrt(1+psi_st0); +/* delta is formulated this way so we can change it here and nowhere else */ + delta = 0.5/sqt0one; + pDdelta_Dpsi_st0 = -0.25/((1+psi_st0)*sqt0one); + alpha = eta_s+gamma*delta; + vGBF = vg - psi_st0; + Bf = sqt0 - delta*psi_st0; + vGT = vg - gamma*Bf; + vGBT = vGT + alpha*vt; + + if(model->SOI3vsat == 0) { + theta2 = 0; + TVF = 0.0; /* could be any nominal value */ + } else { + TVF = 0.8*exp((here->SOI3temp+deltaT)/600); + theta2 = (here->SOI3tSurfMob/(model->SOI3vsat))*1e-2 /*cm to m*/ + *TMF*(1+TVF)/(EffectiveLength*(1+model->SOI3TVF0)); + /* theta2=1/(L.Ec) */ + } + Mmob = theta2 - 0.5*model->SOI3theta; + + PSI = MAX(0,(vGT/alpha) - psi_st0); + S = 0.5*(1+sqrt(1 + (2*Mmob*PSI)/(1+model->SOI3theta*vGBF))); + psi_sLsat = psi_st0 + PSI/S; + + if ((psi_si0 - psi_sLsat)<(vt*MAX_EXP_ARG)) { + Esd0 = exp((psi_si0 - psi_sLsat)/vt); + Esd0_trans = 1; + if (psi_s0_trans) { + psi_s0 = vt*log(1+Esi0/(1+Esd0)); + } else { + psi_s0 = psi_si0 - vt*log(1+Esd0); + } + } else { + psi_s0 = psi_sLsat; + Esd0_trans = 0; + } + + if ((psi_siL - psi_sLsat)<(vt*MAX_EXP_ARG)) { + EsdL = exp((psi_siL - psi_sLsat)/vt); + EsdL_trans = 1; + if (psi_siL < (vt * MAX_EXP_ARG)) { + EsiL = exp(psi_siL/vt); + psi_sL = vt*log(1+EsiL/(1+EsdL)); + psi_sL_trans = 1; + } else { + psi_sL = psi_siL - vt*log(1+EsdL); + psi_sL_trans = 0; + } + } else { + psi_sL = psi_sLsat; + EsdL_trans = 0; + } +/* if, after all that, we have impossible situation due to numerical limiting schemes ... */ + + if (psi_s0>psi_sL) { + psi_sL = psi_s0; + } + +/* now we can finally work out surface potential for source and drain end */ + +/* now surface potential is ready */ + + f0 = (vGBT - 0.5*alpha*psi_s0)*psi_s0; + fL = (vGBT - 0.5*alpha*psi_sL)*psi_sL; + + ich0 = Beta * (fL - f0); /* This is "intrinsic" bit */ + +/* now for derivatives - they're a bit of a nightmare * + * notation pD... means PARTIAL derivative whilst D... * + * means FULL derivative */ + +/* first sub-threshold */ + + if (vg > (vt*MAX_EXP_ARG)) { + Dpsi_ss_Dvgfb = (1-0.5*gamma/(eta_s*Sgy))/eta_s; + } else { + Dpsi_ss_Dvgfb = (1-0.5*gamma/(eta_s*Sgy))*(Egy/(1+Egy))/eta_s; + } + Dpsi_ss_Dvsb = Dpsi_ss_Dvgfb*(-sigma); + Dpsi_ss_Dvdb = Dpsi_ss_Dvgfb*(sigma); + Dpsi_ss_DdeltaT = Dpsi_ss_Dvgfb*(-model->SOI3chiFB); + +/* now for strong inversion */ + + pDpsi_si0_Dvgx0 = 2*vt*L0/(L0*L0-gamma*gamma*A0); + pDpsi_siL_DvgxL = 2*vt*LL/(LL*LL-gamma*gamma*AL); + + /* if vg is transformed, must have deriv accordingly, else it is 1 */ + + if (vgx0trans) { + Dvgx0_Dvgfb = pDvgx0_Dvg = Egx0/(1+Egx0); + if (A0trans) { + /* JimB - 27/8/98 */ + /* Get divide by zero errors when A0x is equal to zero */ + /* Temporary fix - add small constant to denominator */ +/* Dvgx0_Dvsb = pDvgx0_Dvg * (-sigma) + + (1-pDvgx0_Dvg)*(eta_s+0.5*gamma/sqrt(A0x))* + (EA0/(1+EA0)); */ + Dvgx0_Dvsb = pDvgx0_Dvg * (-sigma) + + (1-pDvgx0_Dvg)*(eta_s+0.5*gamma/(sqrt(A0x)+1e-25))* + (EA0/(1+EA0)); + /* End JimB */ + } else { + /* JimB - 27/8/97 */ + /* Temporary fix - add small constant to denominator */ + /*Dvgx0_Dvsb = pDvgx0_Dvg * (-sigma) + + (1-pDvgx0_Dvg)*(eta_s+0.5*gamma/sqrt(A0)); */ + Dvgx0_Dvsb = pDvgx0_Dvg * (-sigma) + + (1-pDvgx0_Dvg)*(eta_s+0.5*gamma/(sqrt(A0)+1e-25)); + /* End JimB */ + } + Dvgx0_Dvdb = pDvgx0_Dvg*(sigma); + Dvgx0_DdeltaT = pDvgx0_Dvg*(-model->SOI3chiFB); + } else { + Dvgx0_Dvgfb = pDvgx0_Dvg = 1; + Dvgx0_Dvsb = (-sigma); + Dvgx0_Dvdb = (sigma); + Dvgx0_DdeltaT = (-model->SOI3chiFB); + } + + if (vgxLtrans) { + DvgxL_Dvgfb = pDvgxL_Dvg = EgxL/(1+EgxL); + DvgxL_Dvsb = pDvgxL_Dvg * (-sigma); + if (ALtrans) { + /* JimB - 27/8/98 */ + /* Get divide by zero errors when ALx is equal to zero */ + /* Temporary fix - add small constant to denominator */ + /*DvgxL_Dvdb = pDvgxL_Dvg * (sigma) + + (1-pDvgxL_Dvg)*(eta_s+0.5*gamma/sqrt(ALx))* + (EAL/(1+EAL)); */ + DvgxL_Dvdb = pDvgxL_Dvg * (sigma) + + (1-pDvgxL_Dvg)*(eta_s+0.5*gamma/(sqrt(ALx)+1e-25))* + (EAL/(1+EAL)); + /* End JimB */ + } else { + /* JimB - 27/8/97 */ + /* Temporary fix - add small constant to denominator */ +/* DvgxL_Dvdb = pDvgxL_Dvg * (sigma) + + (1-pDvgxL_Dvg)*(eta_s+0.5*gamma/sqrt(AL)); */ + DvgxL_Dvdb = pDvgxL_Dvg * (sigma) + + (1-pDvgxL_Dvg)*(eta_s+0.5*gamma/(sqrt(AL)+1e-25)); + /* End JimB */ + } + DvgxL_DdeltaT = pDvgxL_Dvg * (-model->SOI3chiFB); + } else { + DvgxL_Dvgfb = 1; + DvgxL_Dvsb = (-sigma); + DvgxL_Dvdb = (sigma); + DvgxL_DdeltaT = (-model->SOI3chiFB); + } + + pDpsi_si0_Dvsb = 1 - (2*vt*eta_s*L0+vt*gamma*gamma)/(L0*L0-gamma*gamma*A0); + pDpsi_siL_Dvdb = 1 - (2*vt*eta_s*LL+vt*gamma*gamma)/(LL*LL-gamma*gamma*AL); + + Dpsi_si0_Dvgfb = pDpsi_si0_Dvgx0*Dvgx0_Dvgfb; + Dpsi_si0_Dvsb = pDpsi_si0_Dvgx0*Dvgx0_Dvsb + pDpsi_si0_Dvsb; + Dpsi_si0_Dvdb = pDpsi_si0_Dvgx0*Dvgx0_Dvdb; + Dpsi_si0_DdeltaT = model->SOI3chiPHI + + pDpsi_si0_Dvgx0*Dvgx0_DdeltaT; + + Dpsi_siL_Dvgfb = pDpsi_siL_DvgxL*DvgxL_Dvgfb; + Dpsi_siL_Dvsb = pDpsi_siL_DvgxL*DvgxL_Dvsb; + Dpsi_siL_Dvdb = pDpsi_siL_DvgxL*DvgxL_Dvdb + pDpsi_siL_Dvdb; + Dpsi_siL_DdeltaT = model->SOI3chiPHI + + pDpsi_siL_DvgxL*DvgxL_DdeltaT; + +/* now we can get full deriv of first guess + but also, partials of psi_s0 and psi_sL, the + final values have similar structure, so do + them now as well */ + + /* deriv of psi_s etc wrt psi_si must be according to transform used */ + + if (Ess0_trans) { + if (psi_s0_trans) { + tmp = (Esi0/(1+Ess0+Esi0))/(1+Ess0); + tmp1 = (Esi0/(1+Ess0+Esi0))*(Ess0/(1+Ess0)); + } else { + tmp = 1/(1+Ess0); + tmp1 = Ess0*tmp; + } + Dpsi_st0_Dvgfb = tmp*Dpsi_si0_Dvgfb + tmp1*Dpsi_ss_Dvgfb; + Dpsi_st0_Dvsb = tmp*Dpsi_si0_Dvsb + tmp1*Dpsi_ss_Dvsb; + Dpsi_st0_Dvdb = tmp*Dpsi_si0_Dvdb + tmp1*Dpsi_ss_Dvdb; + Dpsi_st0_DdeltaT = tmp*Dpsi_si0_DdeltaT + tmp1*Dpsi_ss_DdeltaT; + } else { + Dpsi_st0_Dvgfb = Dpsi_ss_Dvgfb; + Dpsi_st0_Dvdb = Dpsi_ss_Dvdb; + Dpsi_st0_Dvsb = Dpsi_ss_Dvsb; + Dpsi_st0_DdeltaT = Dpsi_ss_DdeltaT; + } + +/* now some itsy bitsy quantities useful all over the shop */ + /* Ddelta_Dpsi_st0 is defined earlier with delta to allow + change of delta expression in one place */ + + pDBf_Dpsi_st0 = 0.5/sqt0 - psi_st0*pDdelta_Dpsi_st0 - delta; + + DvGT_Dvgfb = 1 - gamma*pDBf_Dpsi_st0*Dpsi_st0_Dvgfb; + DvGT_Dvsb = (-sigma) - gamma*pDBf_Dpsi_st0*Dpsi_st0_Dvsb; + DvGT_Dvdb = (sigma) - gamma*pDBf_Dpsi_st0*Dpsi_st0_Dvdb; + DvGT_DdeltaT = (-model->SOI3chiFB) - gamma*pDBf_Dpsi_st0*Dpsi_st0_DdeltaT; + + Dalpha_Dvgfb = gamma*pDdelta_Dpsi_st0*Dpsi_st0_Dvgfb; + Dalpha_Dvsb = gamma*pDdelta_Dpsi_st0*Dpsi_st0_Dvsb; + Dalpha_Dvdb = gamma*pDdelta_Dpsi_st0*Dpsi_st0_Dvdb; + Dalpha_DdeltaT = gamma*pDdelta_Dpsi_st0*Dpsi_st0_DdeltaT; + +/* Now for saturation stuff psi_sLsat */ +/* NB no need for special case, theta2=0 ==> Mmob=-theta/2 */ + + if (PSI != 0) { /* stops unnecessary math if PSI = 0 */ + DPSI_Dvgfb = (DvGT_Dvgfb - (vGT/alpha)*Dalpha_Dvgfb + )/alpha - Dpsi_st0_Dvgfb; + DPSI_Dvsb = (DvGT_Dvsb - (vGT/alpha)*Dalpha_Dvsb + )/alpha - Dpsi_st0_Dvsb; + DPSI_Dvdb = (DvGT_Dvdb - (vGT/alpha)*Dalpha_Dvdb + )/alpha - Dpsi_st0_Dvdb; + DPSI_DdeltaT = (DvGT_DdeltaT - (vGT/alpha)*Dalpha_DdeltaT + )/alpha - Dpsi_st0_DdeltaT; + + D = 2*(1+model->SOI3theta*vGBF)* + sqrt(1 + (2*Mmob*PSI)/(1+model->SOI3theta*vGBF)); + + DS_Dvgfb = (Mmob/D)*DPSI_Dvgfb - + (Mmob*PSI*(model->SOI3theta)/(D*(1+model->SOI3theta*vGBF))) + *(1-Dpsi_st0_Dvgfb); + DS_Dvsb = (Mmob/D)*DPSI_Dvsb - + (Mmob*PSI*(model->SOI3theta)/(D*(1+model->SOI3theta*vGBF))) + *((-sigma)-Dpsi_st0_Dvsb); + DS_Dvdb = (Mmob/D)*DPSI_Dvdb - + (Mmob*PSI*(model->SOI3theta)/(D*(1+model->SOI3theta*vGBF))) + *((sigma)-Dpsi_st0_Dvdb); + DS_DdeltaT = (Mmob/D)*DPSI_DdeltaT - + (Mmob*PSI*(model->SOI3theta)/(D*(1+model->SOI3theta*vGBF))) + *((-model->SOI3chiFB)-Dpsi_st0_DdeltaT) - + (PSI/D)*theta2*(model->SOI3k/(deltaT+here->SOI3temp) - + TVF/(600*(1+TVF))); + + Dpsi_sLsat_Dvgfb = Dpsi_st0_Dvgfb + + DPSI_Dvgfb/S - + PSI*DS_Dvgfb/(S*S); + Dpsi_sLsat_Dvsb = Dpsi_st0_Dvsb + + DPSI_Dvsb/S - + PSI*DS_Dvsb/(S*S); + Dpsi_sLsat_Dvdb = Dpsi_st0_Dvdb + + DPSI_Dvdb/S - + PSI*DS_Dvdb/(S*S); + Dpsi_sLsat_DdeltaT = Dpsi_st0_DdeltaT + + DPSI_DdeltaT/S - + PSI*DS_DdeltaT/(S*S); + } else { + Dpsi_sLsat_Dvgfb = Dpsi_st0_Dvgfb; + Dpsi_sLsat_Dvsb = Dpsi_st0_Dvsb; + Dpsi_sLsat_Dvdb = Dpsi_st0_Dvdb; + Dpsi_sLsat_DdeltaT = Dpsi_st0_DdeltaT; + } + + if (Esd0_trans) { + if (psi_s0_trans) { + tmp = (Esi0/(1+Esd0+Esi0))/(1+Esd0); + tmp1 = (Esi0/(1+Esd0+Esi0))*(Esd0/(1+Esd0)); + } else { + tmp = 1/(1+Esd0); + tmp1 = Esd0*tmp; + } + Dpsi_s0_Dvgfb = tmp*Dpsi_si0_Dvgfb + tmp1*Dpsi_sLsat_Dvgfb; + Dpsi_s0_Dvdb = tmp*Dpsi_si0_Dvdb + tmp1*Dpsi_sLsat_Dvdb; + Dpsi_s0_Dvsb = tmp*Dpsi_si0_Dvsb + tmp1*Dpsi_sLsat_Dvsb; + Dpsi_s0_DdeltaT = tmp*Dpsi_si0_DdeltaT + tmp1*Dpsi_sLsat_DdeltaT; + } else { + Dpsi_s0_Dvgfb = Dpsi_sLsat_Dvgfb; + Dpsi_s0_Dvdb = Dpsi_sLsat_Dvdb; + Dpsi_s0_Dvsb = Dpsi_sLsat_Dvsb; + Dpsi_s0_DdeltaT = Dpsi_sLsat_DdeltaT; + } + + if (EsdL_trans) { + if (psi_sL_trans) { + tmp = (EsiL/(1+EsdL+EsiL))/(1+EsdL); + tmp1 = (EsiL/(1+EsdL+EsiL))*(EsdL/(1+EsdL)); + } else { + tmp = 1/(1+EsdL); + tmp1 = EsdL*tmp; + } + Dpsi_sL_Dvgfb = tmp*Dpsi_siL_Dvgfb + tmp1*Dpsi_sLsat_Dvgfb; + Dpsi_sL_Dvdb = tmp*Dpsi_siL_Dvdb + tmp1*Dpsi_sLsat_Dvdb; + Dpsi_sL_Dvsb = tmp*Dpsi_siL_Dvsb + tmp1*Dpsi_sLsat_Dvsb; + Dpsi_sL_DdeltaT = tmp*Dpsi_siL_DdeltaT + tmp1*Dpsi_sLsat_DdeltaT; + } else { + Dpsi_sL_Dvgfb = Dpsi_sLsat_Dvgfb; + Dpsi_sL_Dvdb = Dpsi_sLsat_Dvdb; + Dpsi_sL_Dvsb = Dpsi_sLsat_Dvsb; + Dpsi_sL_DdeltaT = Dpsi_sLsat_DdeltaT; + } + +/* now for the whole kaboodle */ + + DfL_Dvgfb = psi_sL*(DvGT_Dvgfb + vt*Dalpha_Dvgfb) - + psi_sL*psi_sL*0.5*Dalpha_Dvgfb + + (vGBT - alpha*psi_sL)*Dpsi_sL_Dvgfb; + Df0_Dvgfb = psi_s0*(DvGT_Dvgfb + vt*Dalpha_Dvgfb) - + psi_s0*psi_s0*0.5*Dalpha_Dvgfb + + (vGBT - alpha*psi_s0)*Dpsi_s0_Dvgfb; + + DfL_Dvdb = psi_sL*(DvGT_Dvdb + vt*Dalpha_Dvdb) - + psi_sL*psi_sL*0.5*Dalpha_Dvdb + + (vGBT - alpha*psi_sL)*Dpsi_sL_Dvdb; + Df0_Dvdb = psi_s0*(DvGT_Dvdb + vt*Dalpha_Dvdb) - + psi_s0*psi_s0*0.5*Dalpha_Dvdb + + (vGBT - alpha*psi_s0)*Dpsi_s0_Dvdb; + + DfL_Dvsb = psi_sL*(DvGT_Dvsb + vt*Dalpha_Dvsb) - + psi_sL*psi_sL*0.5*Dalpha_Dvsb + + (vGBT - alpha*psi_sL)*Dpsi_sL_Dvsb; + Df0_Dvsb = psi_s0*(DvGT_Dvsb + vt*Dalpha_Dvsb) - + psi_s0*psi_s0*0.5*Dalpha_Dvsb + + (vGBT - alpha*psi_s0)*Dpsi_s0_Dvsb; + + DfL_DdeltaT = psi_sL*(DvGT_DdeltaT + vt*Dalpha_DdeltaT) - + psi_sL*psi_sL*0.5*Dalpha_DdeltaT + + (vGBT - alpha*psi_sL)*Dpsi_sL_DdeltaT; + Df0_DdeltaT = psi_s0*(DvGT_DdeltaT + vt*Dalpha_DdeltaT) - + psi_s0*psi_s0*0.5*Dalpha_DdeltaT + + (vGBT - alpha*psi_s0)*Dpsi_s0_DdeltaT; + +/* put them all together and what have you got ...? */ + + gmg = Beta*(DfL_Dvgfb - Df0_Dvgfb); + + gmd = Beta*(DfL_Dvdb - Df0_Dvdb); + + gms = Beta*(DfL_Dvsb - Df0_Dvsb); + + gmt = Beta*(DfL_DdeltaT - Df0_DdeltaT); + +/* End Intrinsic Electrical Bit */ + + +/* + * High Field Mobility Effects + */ + Fm = 1 + model->SOI3theta*(vg - 0.5*(psi_sL + psi_s0)) + + theta2 * (psi_sL - psi_s0); + ich0 = ich0/Fm; + here->SOI3ueff = here->SOI3ueff/Fm; + gmg = (gmg-ich0*(model->SOI3theta* + (1-0.5*(Dpsi_sL_Dvgfb + Dpsi_s0_Dvgfb)) + + theta2*(Dpsi_sL_Dvgfb - Dpsi_s0_Dvgfb) + ) + )/Fm; + gmd = (gmd-ich0*(model->SOI3theta* + (sigma-0.5*(Dpsi_sL_Dvdb + Dpsi_s0_Dvdb)) + + theta2*(Dpsi_sL_Dvdb - Dpsi_s0_Dvdb) + ) + )/Fm; + gms = (gms-ich0*(model->SOI3theta* + (-sigma-0.5*(Dpsi_sL_Dvsb + Dpsi_s0_Dvsb)) + + theta2*(Dpsi_sL_Dvsb - Dpsi_s0_Dvsb) + ) + )/Fm; + gmt = (gmt-ich0*(model->SOI3theta* + ((-model->SOI3chiFB)-0.5*(Dpsi_sL_DdeltaT + Dpsi_s0_DdeltaT) + ) + + theta2*(Dpsi_sL_DdeltaT - Dpsi_s0_DdeltaT - + (psi_sL - psi_s0)*(model->SOI3k/(deltaT+here->SOI3temp) - + TVF/(600*(1+TVF)) + ) + ) + ) + )/Fm; + +/* + * End High Field Mobility Effects + */ + +/* Now to define bits which affect the drain region */ +/* + * Channel Length Modulation + */ + + Vm = (here->SOI3mode*vds) + psi_s0 - psi_sLsat; + if (model->SOI3useLAMBDA) { + Vmx = Vm; + DVmx_Dvgfb = (Dpsi_s0_Dvgfb - Dpsi_sLsat_Dvgfb); + DVmx_Dvdb = (1 + Dpsi_s0_Dvdb - Dpsi_sLsat_Dvdb); + DVmx_Dvsb = (Dpsi_s0_Dvsb - Dpsi_sLsat_Dvsb - 1); + DVmx_DdeltaT = (Dpsi_s0_DdeltaT - Dpsi_sLsat_DdeltaT); + ld = model->SOI3lambda*Vmx; + tmp = model->SOI3lambda; + } else { + if (Vm > (vt*MAX_EXP_ARG)) { + Vmx = Vm; + tmp = 1; + } else { + Em = exp(Vm/vt); + Vmx = vt * log(1 + Em) + 1e-25; + tmp = (Em/(1+Em)); + } + DVmx_Dvgfb = tmp * (Dpsi_s0_Dvgfb - Dpsi_sLsat_Dvgfb); + DVmx_Dvdb = tmp * (1 + Dpsi_s0_Dvdb - Dpsi_sLsat_Dvdb); + DVmx_Dvsb = tmp * (Dpsi_s0_Dvsb - Dpsi_sLsat_Dvsb - 1); + DVmx_DdeltaT = tmp * (Dpsi_s0_DdeltaT - Dpsi_sLsat_DdeltaT); + ld = model->SOI3lx * log(1 + Vmx/model->SOI3vp); + tmp = model->SOI3lx/(model->SOI3vp + Vmx); + } + + Y = 1 + (ld/EffectiveLength); + + Dld_Dvgfb = tmp * DVmx_Dvgfb; + Dld_Dvdb = tmp * DVmx_Dvdb; + Dld_Dvsb = tmp * DVmx_Dvsb; + Dld_DdeltaT = tmp * DVmx_DdeltaT; + + gmg = gmg * Y + (ich0/EffectiveLength) * Dld_Dvgfb; + gmd = gmd * Y + (ich0/EffectiveLength) * Dld_Dvdb; + gms = gms * Y + (ich0/EffectiveLength) * Dld_Dvsb; + gmt = gmt * Y + (ich0/EffectiveLength) * Dld_DdeltaT; + + ich0 = ich0 * Y; + /* Need to do ich0 last as its old value is needed for gds */ + +/* + * End Channel Length Modulation + */ + + here->SOI3gdsnotherm = here->SOI3gds; + + /************** Thermal Mobility Stuff **************/ + + /* thermal effect on intrinsic electrical circuit */ + idrain = ich0 * TMF; /* idrain has new value now */ + here->SOI3ueff *= TMF; + gmg = gmg * TMF; +/* here->SOI3gmb = here->SOI3gmb * TMF; */ + gms = gms * TMF; + gmd = gmd * TMF; + /* deltaT is indpt voltage now */ + gmt = gmt*TMF - (model->SOI3k/(deltaT+here->SOI3temp)) * idrain; + ich0 = idrain; + + /* + * finished intrinsic electrical + */ +/* + * Impact Ionisation current sources + */ + + Vm1 = (here->SOI3mode*vds) + model->SOI3eta*(psi_s0 - psi_sLsat); + if (Vm1 > (vt*MAX_EXP_ARG)) { + Vm1x = Vm1; + tmp = 1; + } else { + Em1 = exp(MIN(MAX_EXP_ARG,Vm1/vt)); + Vm1x = vt * log(1 + Em1) + 1e-25; + tmp = (Em1/(1+Em1)); + } + DVm1x_Dvgfb = tmp*model->SOI3eta*(Dpsi_s0_Dvgfb - Dpsi_sLsat_Dvgfb); + DVm1x_Dvdb = tmp*(model->SOI3eta*(Dpsi_s0_Dvdb - Dpsi_sLsat_Dvdb) + 1); + DVm1x_Dvsb = tmp*(model->SOI3eta*(Dpsi_s0_Dvsb - Dpsi_sLsat_Dvsb) - 1); + DVm1x_DdeltaT = tmp*model->SOI3eta*(Dpsi_s0_DdeltaT - Dpsi_sLsat_DdeltaT); + + vgeff = vg - vsb - eta_s*here->SOI3tPhi - gamma*sqrt(here->SOI3tPhi); + lm = model->SOI3lm + model->SOI3lm1*(here->SOI3mode*vds-vgeff) + + model->SOI3lm2*(here->SOI3mode*vds-vgeff)*(here->SOI3mode*vds-vgeff); + Elm = exp(MIN(MAX_EXP_ARG,lm/MAX(1e-10,(model->SOI3lm/40)))); + lmeff = (model->SOI3lm/40)*log(1+Elm); + betaM = 100*(model->SOI3beta0 + model->SOI3chibeta*deltaT); + EM = exp(MIN(MAX_EXP_ARG,-(lmeff*betaM)/Vm1x)); + Mminus1 = (100*model->SOI3alpha0/betaM) * Vm1x * EM; + if (here->SOI3mode==1) { + here->SOI3iMdb=Mminus1*ich0; + here->SOI3iMsb=0; + } else { + here->SOI3iMsb=Mminus1*ich0; + here->SOI3iMdb=0; + } + tmp = (Elm/(1+Elm))* + (model->SOI3lm1 + 2*model->SOI3lm2*(here->SOI3mode*vds-vgeff)); + Dlm_Dvgfb = -tmp; + Dlm_Dvdb = tmp*(1-sigma); + Dlm_Dvsb = tmp*(sigma); + Dlm_DdeltaT = tmp*(model->SOI3chiFB); + tmp = (ich0/Vm1x); + tmp1 = (1+(lmeff*betaM/Vm1x)); + gMg = Mminus1 * (gmg + tmp * (tmp1*DVm1x_Dvgfb - betaM*Dlm_Dvgfb)); + gMd = Mminus1 * (gmd + tmp * (tmp1*DVm1x_Dvdb - betaM*Dlm_Dvdb)); + gMs = Mminus1 * (gms + tmp * (tmp1*DVm1x_Dvsb - betaM*Dlm_Dvsb)); + + here->SOI3gMmf = gMg; + here->SOI3gMmb = 0; + here->SOI3gMmbs= -(gMs + gMg + gMd); + here->SOI3gMd = gMd; + here->SOI3gMdeltaT = Mminus1*(gmt+ + tmp*(tmp1*DVm1x_DdeltaT - betaM*Dlm_DdeltaT - + lmeff*model->SOI3chibeta*100) + - (ich0*model->SOI3chibeta*100/betaM) + ); + +/* + * End Impact Ionisation current sources + */ + +/***** time to convert to conventional names for (trans)conductances *****/ + + here->SOI3gmf = gmg; + here->SOI3gmb = 0; /* FOR NOW */ + here->SOI3gmbs = -(gms + gmg + gmd); + here->SOI3gds = gmd; + here->SOI3gt = gmt; + vdsat = psi_sLsat - psi_s0; + + /* now for thermal subcircuit values */ + tmp = (here->SOI3drainConductance==0?0:(1/(here->SOI3drainConductance))); + tmp += (here->SOI3sourceConductance==0?0:(1/(here->SOI3sourceConductance))); + /* tmp = RS+RD */ + here->SOI3iPt = (here->SOI3mode*vds + idrain*tmp)*idrain; + here->SOI3gPmf = (here->SOI3mode*vds + 2*idrain*tmp)*here->SOI3gmf; + here->SOI3gPmb = (here->SOI3mode*vds + 2*idrain*tmp)*here->SOI3gmb; + here->SOI3gPmbs = (here->SOI3mode*vds + 2*idrain*tmp)*here->SOI3gmbs; + here->SOI3gPds = idrain + (here->SOI3mode*vds + 2*idrain*tmp)*here->SOI3gds; + here->SOI3gPdT = (here->SOI3mode*vds + 2*idrain*tmp)*here->SOI3gt; + + /* JimB - 15/9/99 */ + /* Code for multiple thermal time constants. Start by moving all */ + /* rt constants into arrays. */ + rtargs[0]=here->SOI3rt; + rtargs[1]=here->SOI3rt1; + rtargs[2]=here->SOI3rt2; + rtargs[3]=here->SOI3rt3; + rtargs[4]=here->SOI3rt4; + + /* Set all conductance components to zero. */ + grt[0]=grt[1]=grt[2]=grt[3]=grt[4]=0.0; + /* Now calculate conductances from rt. */ + /* Don't need to worry about divide by zero when calculating */ + /* grt components, as soi3setup() only creates a thermal node */ + /* if corresponding rt is greater than zero. */ + for(tnodeindex=0;tnodeindexSOI3numThermalNodes;tnodeindex++) + { + grt[tnodeindex]=1/rtargs[tnodeindex]; + } + /* End JimB */ + +/* now end nasty trick - if vsb and vdb have been switched, reverse them back */ + if (here->SOI3mode == -1) + { + tmp = vsb; + vsb = vdb; + vdb = tmp; + } + + /* + * bulk-source and bulk-drain diodes + * includes parasitic BJT and 2nd diode + * + */ + + tmp = here->SOI3temp+deltaT; + tmp1 = here->SOI3temp + model->SOI3dvt * deltaT; + vT = CONSTKoverQ * tmp1; + + if ((model->SOI3betaEXP) != 1.0) + { + if ((model->SOI3betaEXP) != 2.0) + { + BetaBJTeff = model->SOI3betaBJT * + exp(-(model->SOI3betaEXP)*logL); + } + else + { + BetaBJTeff = model->SOI3betaBJT/ + (EffectiveLength*EffectiveLength); + } + } + else + { + BetaBJTeff = model->SOI3betaBJT/EffectiveLength; + } + + alphaBJT = BetaBJTeff/(BetaBJTeff + 1); + + EchiD = exp(MIN(MAX_EXP_ARG, + (model->SOI3chid * deltaT)/(here->SOI3temp*tmp) + ) + ); + EchiD1 = exp(MIN(MAX_EXP_ARG, + (model->SOI3chid1 * deltaT)/(here->SOI3temp*tmp) + ) + ); + ISts = SourceSatCur*EchiD; + IS1ts = SourceSatCur1*EchiD1; + + evbs = exp(MIN(MAX_EXP_ARG,vbs/((model->SOI3etad)*vT))); + evbs1 = exp(MIN(MAX_EXP_ARG,vbs/((model->SOI3etad1)*vT))); +/* First Junction */ + here->SOI3ibs = ISts * (evbs-1); + here->SOI3gbs = ISts*evbs/((model->SOI3etad)*vT); + here->SOI3gbsT = ISts*((evbs-1)*model->SOI3chid/(tmp*tmp) - + evbs*vbs*model->SOI3dvt/((model->SOI3etad)*vT*tmp1)); +/* Now Bipolar */ + here->SOI3iBJTdb = alphaBJT * ISts * (evbs-1); + here->SOI3gBJTdb_bs = alphaBJT * here->SOI3gbs; + here->SOI3gBJTdb_deltaT = alphaBJT * here->SOI3gbsT; +/* Now second junction and gmin */ + /* JimB - make gmin code consistent */ + here->SOI3ibs += IS1ts * (evbs1-1) + ckt->CKTgmin*vbs; + here->SOI3gbs += IS1ts*evbs1/((model->SOI3etad1)*vT) + ckt->CKTgmin; + /* End JimB */ + here->SOI3gbsT += IS1ts*((evbs1-1)*model->SOI3chid1/(tmp*tmp) - + evbs1*vbs*model->SOI3dvt/((model->SOI3etad1)*vT*tmp1) + ); + + + IStd = DrainSatCur*EchiD; + IS1td = DrainSatCur1*EchiD1; + + evbd = exp(MIN(MAX_EXP_ARG,vbd/((model->SOI3etad)*vT))); + evbd1 = exp(MIN(MAX_EXP_ARG,vbd/((model->SOI3etad1)*vT))); +/* First Junction */ + here->SOI3ibd = IStd *(evbd-1); + here->SOI3gbd = IStd*evbd/((model->SOI3etad)*vT); + here->SOI3gbdT = IStd*((evbd-1)*model->SOI3chid/(tmp*tmp) - + evbd*vbd*model->SOI3dvt/((model->SOI3etad)*vT*tmp1)); +/* Now Bipolar */ + here->SOI3iBJTsb = alphaBJT * IStd *(evbd-1); + here->SOI3gBJTsb_bd = alphaBJT * here->SOI3gbd; + here->SOI3gBJTsb_deltaT = alphaBJT * here->SOI3gbdT; +/* Now second junction and gmin */ + /* JimB - make gmin code consistent */ + here->SOI3ibd += IS1td *(evbd1-1) + ckt->CKTgmin*vbd; + here->SOI3gbd += IS1td*evbd1/((model->SOI3etad1)*vT) + ckt->CKTgmin; + /* End JimB */ + here->SOI3gbdT += IS1td*((evbd1-1)*model->SOI3chid1/(tmp*tmp) - + evbd1*vbd*model->SOI3dvt/((model->SOI3etad1)*vT*tmp1) + ); + + +/* initialise von for voltage limiting purposes */ + von = (here->SOI3tVfbF * model->SOI3type) + psi_s0 + gamma*sqt0 + + sigma*(here->SOI3mode*vds) + - model->SOI3chiFB*deltaT; + +/* finally if we're going to do charge/capacitance calcs, store + * some stuff to pass to function. Need to use arrays 'cos there's + * a limit to how many parameters you can pass in standard C + */ + paramargs[0] = here->SOI3w*model->SOI3frontOxideCapFactor; + paramargs[1] = EffectiveLength; + paramargs[2] = gamma; + paramargs[3] = eta_s; + paramargs[4] = vt; + paramargs[5] = delta; + paramargs[6] = here->SOI3w*model->SOI3backOxideCapFactor; + paramargs[7] = sigma; + paramargs[8] = model->SOI3chiFB; + paramargs[9] = model->SOI3satChargeShareFactor; + Bfargs[0] = Bf; + Bfargs[1] = pDBf_Dpsi_st0; + alpha_args[0] = alpha; + alpha_args[1] = Dalpha_Dvgfb; + alpha_args[2] = Dalpha_Dvdb; + alpha_args[3] = Dalpha_Dvsb; + alpha_args[4] = Dalpha_DdeltaT; + psi_st0args[0] = psi_st0; + psi_st0args[1] = Dpsi_st0_Dvgfb; + psi_st0args[2] = Dpsi_st0_Dvdb; + psi_st0args[3] = Dpsi_st0_Dvsb; + psi_st0args[4] = Dpsi_st0_DdeltaT; + vGTargs[0] = vGT; + vGTargs[1] = DvGT_Dvgfb; + vGTargs[2] = DvGT_Dvdb; + vGTargs[3] = DvGT_Dvsb; + vGTargs[4] = DvGT_DdeltaT; + psi_sLargs[0] = psi_sL; + psi_sLargs[1] = Dpsi_sL_Dvgfb; + psi_sLargs[2] = Dpsi_sL_Dvdb; + psi_sLargs[3] = Dpsi_sL_Dvsb; + psi_sLargs[4] = Dpsi_sL_DdeltaT; + psi_s0args[0] = psi_s0; + psi_s0args[1] = Dpsi_s0_Dvgfb; + psi_s0args[2] = Dpsi_s0_Dvdb; + psi_s0args[3] = Dpsi_s0_Dvsb; + psi_s0args[4] = Dpsi_s0_DdeltaT; + ldargs[0] = ld; + ldargs[1] = Dld_Dvgfb; + ldargs[2] = Dld_Dvdb; + ldargs[3] = Dld_Dvsb; + ldargs[4] = Dld_DdeltaT; +/* debug stuff */ + here->SOI3debug1 = psi_sL; + here->SOI3debug2 = psi_s0; + here->SOI3debug3 = fL; + here->SOI3debug4 = f0; + here->SOI3debug5 = gmd; + here->SOI3debug6 = gms; + + } /* end block */ + + +/* + +*/ + +#ifdef DETAILPROF +asm(" .globl mosptg"); +asm("mosptg:"); +#endif /*DETAILPROF*/ + + /* now deal with n vs p polarity */ + + here->SOI3von = model->SOI3type * von; + here->SOI3vdsat = model->SOI3type * vdsat; + /* line 490 */ + /* + * COMPUTE EQUIVALENT DRAIN CURRENT SOURCE + * + OLD here->SOI3id=here->SOI3mode * idrain - here->SOI3ibd; + */ + if (here->SOI3mode==1) { + here->SOI3id= idrain - here->SOI3ibd + here->SOI3iMdb + + here->SOI3iBJTdb; + } else { + here->SOI3id= -idrain - here->SOI3ibd + + here->SOI3iBJTdb; + } + + + /* JimB - 4/1/99 */ + /* Tidy up depletion capacitance code, and remove unwanted */ + /* compile options. */ + + if (ckt->CKTmode & (MODETRAN | MODETRANOP | MODEINITSMSIG)) + { + /* + * Now we do the hard part of the bulk-drain and bulk-source + * diode - we evaluate the non-linear capacitance and + * charge + * + * The basic equations are not hard, but the implementation + * is somewhat long in an attempt to avoid log/exponential + * evaluations. This is because most users use the default + * grading coefficients of 0.5, and sqrt is MUCH faster than + * an exp(log()), so we use this special case to buy time - + * as much as 10% of total job time! + */ + + /******** Bulk-source depletion capacitance ********/ + +#ifdef CAPBYPASS + if(((ckt->CKTmode & (MODEINITPRED | MODEINITTRAN) ) || + fabs(delvbs) >= ckt->CKTreltol * MAX(fabs(vbs), + fabs(*(ckt->CKTstate0+here->SOI3vbs)))+ + ckt->CKTvoltTol)) +#endif /*CAPBYPASS*/ + { + if(here->SOI3Cbs != 0) + { + if (vbs < here->SOI3tDepCap) + { + arg=1-vbs/here->SOI3tBulkPot; + if(model->SOI3bulkJctSideGradingCoeff == 0.5) + { + sarg = 1/sqrt(arg); + } + else + { + sarg = exp(-model->SOI3bulkJctSideGradingCoeff* + log(arg)); + } + *(ckt->CKTstate0 + here->SOI3qbs) = + here->SOI3tBulkPot*(here->SOI3Cbs* + (1-arg*sarg)/(1-model->SOI3bulkJctSideGradingCoeff)); + here->SOI3capbs=here->SOI3Cbs*sarg; + } + else + { + *(ckt->CKTstate0 + here->SOI3qbs) = here->SOI3f4s + + vbs*(here->SOI3f2s+vbs*(here->SOI3f3s/2)); + here->SOI3capbs=here->SOI3f2s+here->SOI3f3s*vbs; + } + } + else + { + *(ckt->CKTstate0 + here->SOI3qbs) = 0; + here->SOI3capbs=0; + } + } + + /******** End bulk-source depletion capcitance ********/ + + /******** Bulk-drain depletion capacitance ********/ + +#ifdef CAPBYPASS + if(((ckt->CKTmode & (MODEINITPRED | MODEINITTRAN) ) || + fabs(delvbd) >= ckt->CKTreltol * MAX(fabs(vbd), + fabs(*(ckt->CKTstate0+here->SOI3vbd)))+ + ckt->CKTvoltTol)) +#endif /*CAPBYPASS*/ + { + if(here->SOI3Cbd != 0) + { + if (vbd < here->SOI3tDepCap) + { + arg=1-vbd/here->SOI3tBulkPot; + if(model->SOI3bulkJctSideGradingCoeff == 0.5) + { + sarg = 1/sqrt(arg); + } + else + { + sarg = exp(-model->SOI3bulkJctSideGradingCoeff* + log(arg)); + } + *(ckt->CKTstate0 + here->SOI3qbd) = + here->SOI3tBulkPot*(here->SOI3Cbd* + (1-arg*sarg)/(1-model->SOI3bulkJctSideGradingCoeff)); + here->SOI3capbd=here->SOI3Cbd*sarg; + } + else + { + *(ckt->CKTstate0 + here->SOI3qbd) = here->SOI3f4d + + vbd * (here->SOI3f2d + vbd *(here->SOI3f3d/2)); + here->SOI3capbd=here->SOI3f2d + vbd * here->SOI3f3d; + } + } + else + { + *(ckt->CKTstate0 + here->SOI3qbd) = 0; + here->SOI3capbd = 0; + } + } + + /******** End bulk-drain depletion capacitance ********/ + + +/* Need to work out charge on thermal cap */ + *(ckt->CKTstate0 + here->SOI3qt) = here->SOI3ct * deltaT1; + *(ckt->CKTstate0 + here->SOI3qt1) = here->SOI3ct1 * deltaT2; + *(ckt->CKTstate0 + here->SOI3qt2) = here->SOI3ct2 * deltaT3; + *(ckt->CKTstate0 + here->SOI3qt3) = here->SOI3ct3 * deltaT4; + *(ckt->CKTstate0 + here->SOI3qt4) = here->SOI3ct4 * deltaT5; +/* ct is constant, so integral is trivial */ +/* + +*/ + +#ifdef DETAILPROF +asm(" .globl mospth"); +asm("mospth:"); +#endif /*DETAILPROF*/ + + if ( (ckt->CKTmode & MODETRAN) || ( (ckt->CKTmode&MODEINITTRAN) + && !(ckt->CKTmode&MODEUIC)) ) { + /* (above only excludes tranop, since we're only at this + * point if tran or tranop ) + */ + + /* + * calculate equivalent conductances and currents for + * depletion capacitors + */ + + /* integrate the capacitors and save results */ + + error = NIintegrate(ckt,&geq,&ieq,here->SOI3capbd, + here->SOI3qbd); + if(error) return(error); + here->SOI3gbd += geq; + here->SOI3ibd += *(ckt->CKTstate0 + here->SOI3iqbd); + here->SOI3id -= *(ckt->CKTstate0 + here->SOI3iqbd); + error = NIintegrate(ckt,&geq,&ieq,here->SOI3capbs, + here->SOI3qbs); + if(error) return(error); + here->SOI3gbs += geq; + here->SOI3ibs += *(ckt->CKTstate0 + here->SOI3iqbs); + } + } +/* + +*/ + +#ifdef DETAILPROF +asm(" .globl mospti"); +asm("mospti:"); +#endif /*DETAILPROF*/ + +/* if(SenCond) goto next2; */ + + + /* + * check convergence + */ + if ( (here->SOI3off == 0) || + (!(ckt->CKTmode & (MODEINITFIX|MODEINITSMSIG))) ){ + if (Check == 1) { + ckt->CKTnoncon++; + } + } +/* + +*/ + /* + * new capacitor model + */ + if ((ckt->CKTmode & (MODETRAN | MODEAC | MODEINITSMSIG)) || + ((ckt->CKTmode & MODETRANOP) && (ckt->CKTmode & MODEUIC)) + ){ + /* + * calculate charges and capacitances + */ + /* + * Partially Depleted model => back surface neglected + * so back capacitances are ignored. + */ + /* + * All the args assume vsb and vdb are 'correct' + * so must make sure we're getting right values + * back. + */ + if (here->SOI3mode > 0) + { + SOI3cap((vgbb-here->SOI3tVfbB),(here->SOI3tPhi + vsb),model->SOI3gammaB, + paramargs, + Bfargs,alpha_args,psi_st0args, + vGTargs, + psi_sLargs,psi_s0args, + ldargs, + &qgatef,&qbody,&qdrn,&qgateb, + &cgfgf,&cgfd,&cgfs,&cgfdeltaT, + &cbgf,&cbd,&cbs,&cbdeltaT,&cbgb, + &cdgf,&cdd,&cds,&cddeltaT, + &cgbgb,&cgbsb); + csgf = -(cgfgf + cdgf + cbgf); + csd = -(cgfd + cdd + cbd); + css = -(cgfs + cds + cbs); + csdeltaT = -(cgfdeltaT + cddeltaT + cbdeltaT); + cgbdb = 0; + } + else + { + SOI3cap((vgbb-here->SOI3tVfbB),(here->SOI3tPhi + vdb),model->SOI3gammaB, + paramargs, + Bfargs,alpha_args,psi_st0args, + vGTargs, + psi_sLargs,psi_s0args, + ldargs, + &qgatef,&qbody,&qsrc,&qgateb, + &cgfgf,&cgfs,&cgfd,&cgfdeltaT, + &cbgf,&cbs,&cbd,&cbdeltaT,&cbgb, + &csgf,&css,&csd,&csdeltaT, + &cgbgb,&cgbdb); + cdgf = -(cgfgf + csgf + cbgf); + cdd = -(cgfd + csd + cbd); + cds = -(cgfs + css + cbs); + cddeltaT = -(cgfdeltaT + csdeltaT + cbdeltaT); + cgbsb = 0; + } + + *(ckt->CKTstate0 + here->SOI3cgfgf) = cgfgf; + *(ckt->CKTstate0 + here->SOI3cgfd) = cgfd; + *(ckt->CKTstate0 + here->SOI3cgfs) = cgfs; + *(ckt->CKTstate0 + here->SOI3cgfdeltaT) = cgfdeltaT; + + *(ckt->CKTstate0 + here->SOI3csgf) = csgf; + *(ckt->CKTstate0 + here->SOI3csd) = csd; + *(ckt->CKTstate0 + here->SOI3css) = css; + *(ckt->CKTstate0 + here->SOI3csdeltaT) = csdeltaT; + + *(ckt->CKTstate0 + here->SOI3cdgf) = cdgf; + *(ckt->CKTstate0 + here->SOI3cdd) = cdd; + *(ckt->CKTstate0 + here->SOI3cds) = cds; + *(ckt->CKTstate0 + here->SOI3cddeltaT) = cddeltaT; + + *(ckt->CKTstate0 + here->SOI3cgbgb) = cgbgb; + *(ckt->CKTstate0 + here->SOI3cgbsb) = cgbsb; + *(ckt->CKTstate0 + here->SOI3cgbdb) = cgbdb; +/* got charges and caps now, must get equiv conductances/current sources + * but first work out charge and caps for BJT charge storage + */ + + if ((model->SOI3tauEXP) != 2.0) + { + if ((model->SOI3tauEXP) != 1.0) + { + tauFBJTeff = model->SOI3tauFBJT * + exp((model->SOI3tauEXP)*logL); + tauRBJTeff = model->SOI3tauRBJT * + exp((model->SOI3tauEXP)*logL); + } + else + { + tauFBJTeff = model->SOI3tauFBJT*EffectiveLength; + tauRBJTeff = model->SOI3tauRBJT*EffectiveLength; + } + } + else + { + tauFBJTeff = model->SOI3tauFBJT*(EffectiveLength*EffectiveLength); + tauRBJTeff = model->SOI3tauRBJT*(EffectiveLength*EffectiveLength); + } + + *(ckt->CKTstate0 + here->SOI3qBJTbs) = tauFBJTeff * + here->SOI3iBJTdb; + *(ckt->CKTstate0 + here->SOI3cBJTbsbs) = tauFBJTeff * + here->SOI3gBJTdb_bs; + *(ckt->CKTstate0 + here->SOI3cBJTbsdeltaT) = tauFBJTeff * + here->SOI3gBJTdb_deltaT; + + *(ckt->CKTstate0 + here->SOI3qBJTbd) = tauRBJTeff * + here->SOI3iBJTsb; + *(ckt->CKTstate0 + here->SOI3cBJTbdbd) = tauRBJTeff * + here->SOI3gBJTsb_bd; + *(ckt->CKTstate0 + here->SOI3cBJTbddeltaT) = tauRBJTeff * + here->SOI3gBJTsb_deltaT; + } /* end of charge/cap calculations */ + +/* + +*/ +#ifdef DETAILPROF +asm(" .globl mosptj"); +asm("mosptj:"); +#endif /*DETAILPROF*/ + + /* save things away for next time */ + + *(ckt->CKTstate0 + here->SOI3vbs) = vbs; + *(ckt->CKTstate0 + here->SOI3vbd) = vbd; + *(ckt->CKTstate0 + here->SOI3vgfs) = vgfs; + *(ckt->CKTstate0 + here->SOI3vgbs) = vgbs; + *(ckt->CKTstate0 + here->SOI3vds) = vds; + *(ckt->CKTstate0 + here->SOI3deltaT) = deltaT; + *(ckt->CKTstate0 + here->SOI3deltaT1) = deltaT1; + *(ckt->CKTstate0 + here->SOI3deltaT2) = deltaT2; + *(ckt->CKTstate0 + here->SOI3deltaT3) = deltaT3; + *(ckt->CKTstate0 + here->SOI3deltaT4) = deltaT4; + *(ckt->CKTstate0 + here->SOI3deltaT5) = deltaT5; + *(ckt->CKTstate0 + here->SOI3idrain) = idrain; + + if((!(ckt->CKTmode & (MODETRAN | MODEAC))) && + ((!(ckt->CKTmode & MODETRANOP)) || + (!(ckt->CKTmode & MODEUIC))) && (!(ckt->CKTmode + & MODEINITSMSIG))) goto bypass2; +bypass1: + + if (here->SOI3mode>0) { + Frontcapargs[0] = FrontGateDrainOverlapCap; + Frontcapargs[1] = FrontGateSourceOverlapCap; + Frontcapargs[2] = FrontGateBulkOverlapCap; + Frontcapargs[3] = vgfd; + Frontcapargs[4] = vgfs; + Frontcapargs[5] = vgfb; + Backcapargs[0] = BackGateDrainOverlapCap; + Backcapargs[1] = BackGateSourceOverlapCap; + Backcapargs[2] = BackGateBulkOverlapCap; + Backcapargs[3] = vgbd; + Backcapargs[4] = vgbs; + Backcapargs[5] = vgbb; + SOI3capEval(ckt, + Frontcapargs, + Backcapargs, + cgfgf,cgfd,cgfs,cgfdeltaT, + cdgf,cdd,cds,cddeltaT, + csgf,csd,css,csdeltaT, + cbgf,cbd,cbs,cbdeltaT,cbgb, + cgbgb,cgbsb, + &gcgfgf,&gcgfd,&gcgfs,&gcgfdeltaT, + &gcdgf,&gcdd,&gcds,&gcddeltaT, + &gcsgf,&gcsd,&gcss,&gcsdeltaT, + &gcbgf,&gcbd,&gcbs,&gcbdeltaT,&gcbgb, + &gcgbgb,&gcgbsb,&gcgbdb, + &gcgbs0,&gcgbd0, + &qgatef,&qbody,&qdrn,&qsrc,&qgateb); + } else { + Frontcapargs[0] = FrontGateSourceOverlapCap; + Frontcapargs[1] = FrontGateDrainOverlapCap; + Frontcapargs[2] = FrontGateBulkOverlapCap; + Frontcapargs[3] = vgfs; + Frontcapargs[4] = vgfd; + Frontcapargs[5] = vgfb; + Backcapargs[0] = BackGateSourceOverlapCap; + Backcapargs[1] = BackGateDrainOverlapCap; + Backcapargs[2] = BackGateBulkOverlapCap; + Backcapargs[3] = vgbs; + Backcapargs[4] = vgbd; + Backcapargs[5] = vgbb; + SOI3capEval(ckt, + Frontcapargs, + Backcapargs, + cgfgf,cgfs,cgfd,cgfdeltaT, + csgf,css,csd,csdeltaT, + cdgf,cds,cdd,cddeltaT, + cbgf,cbs,cbd,cbdeltaT,cbgb, + cgbgb,cgbdb, + &gcgfgf,&gcgfs,&gcgfd,&gcgfdeltaT, + &gcsgf,&gcss,&gcsd,&gcsdeltaT, + &gcdgf,&gcds,&gcdd,&gcddeltaT, + &gcbgf,&gcbs,&gcbd,&gcbdeltaT,&gcbgb, + &gcgbgb,&gcgbdb,&gcgbsb, + &gcgbd0,&gcgbs0, + &qgatef,&qbody,&qsrc,&qdrn,&qgateb); + } + ag0 = ckt->CKTag[0]; + gcBJTbsbs = ag0 * *(ckt->CKTstate0+here->SOI3cBJTbsbs); + gcBJTbsdeltaT = ag0 * *(ckt->CKTstate0+here->SOI3cBJTbsdeltaT); + gcBJTbdbd = ag0 * *(ckt->CKTstate0+here->SOI3cBJTbdbd); + gcBJTbddeltaT = ag0 * *(ckt->CKTstate0+here->SOI3cBJTbddeltaT); + + if (ByPass) goto line860; /* already stored charges */ + + *(ckt->CKTstate0 + here->SOI3qgf) = qgatef; + *(ckt->CKTstate0 + here->SOI3qd) = qdrn; + *(ckt->CKTstate0 + here->SOI3qs) = qsrc; + *(ckt->CKTstate0 + here->SOI3qgb) = qgateb; + /* NB, we've kept charge/cap associated with diodes separately */ + + if((!(ckt->CKTmode & (MODEAC | MODETRAN))) && + (ckt->CKTmode & MODETRANOP ) && (ckt->CKTmode & + MODEUIC )) goto bypass2; + + /* store small signal parameters */ + if(ckt->CKTmode & MODEINITSMSIG ) { + *(ckt->CKTstate0+here->SOI3cgfgf) = cgfgf; + *(ckt->CKTstate0+here->SOI3cgfd) = cgfd; + *(ckt->CKTstate0+here->SOI3cgfs) = cgfs; + *(ckt->CKTstate0+here->SOI3cgfdeltaT) = cgfdeltaT; + *(ckt->CKTstate0+here->SOI3cdgf) = cdgf; + *(ckt->CKTstate0+here->SOI3cdd) = cdd; + *(ckt->CKTstate0+here->SOI3cds) = cds; + *(ckt->CKTstate0+here->SOI3cddeltaT) = cddeltaT; + *(ckt->CKTstate0+here->SOI3csgf) = csgf; + *(ckt->CKTstate0+here->SOI3csd) = csd; + *(ckt->CKTstate0+here->SOI3css) = css; + *(ckt->CKTstate0+here->SOI3csdeltaT) = csdeltaT; + *(ckt->CKTstate0+here->SOI3cgbgb) = cgbgb; + *(ckt->CKTstate0+here->SOI3cgbsb) = cgbsb; + *(ckt->CKTstate0+here->SOI3cgbdb) = cgbdb; + goto End; + } + + if (ckt->CKTmode & MODEINITTRAN) { + *(ckt->CKTstate1 + here->SOI3qgf) = + *(ckt->CKTstate0 + here->SOI3qgf); + *(ckt->CKTstate1 + here->SOI3qd) = + *(ckt->CKTstate0 + here->SOI3qd); + *(ckt->CKTstate1 + here->SOI3qs) = + *(ckt->CKTstate0 + here->SOI3qs); + *(ckt->CKTstate1 + here->SOI3qgb) = + *(ckt->CKTstate0 + here->SOI3qgb); + *(ckt->CKTstate1 + here->SOI3qBJTbs) = + *(ckt->CKTstate0 + here->SOI3qBJTbs); + *(ckt->CKTstate1 + here->SOI3qBJTbd) = + *(ckt->CKTstate0 + here->SOI3qBJTbd); + } + + /* + * numerical integration of intrinsic caps + * and BJT caps + */ + error = NIintegrate(ckt,&geq,&ieq,0.0,here->SOI3qgf); + if(error) return(error); + error = NIintegrate(ckt,&geq,&ieq,0.0,here->SOI3qd); + if(error) return(error); + error = NIintegrate(ckt,&geq,&ieq,0.0,here->SOI3qs); + if(error) return(error); + error = NIintegrate(ckt,&geq,&ieq,0.0,here->SOI3qgb); + if(error) return(error); + + error = NIintegrate(ckt,&geq,&ieq,0.0,here->SOI3qBJTbs); + if(error) return(error); + error = NIintegrate(ckt,&geq,&ieq,0.0,here->SOI3qBJTbd); + if(error) return(error); + goto line860; + +bypass2: + + /* + * initialize to zero charge conductances + * and current (DC and TRANOP) + */ + ieqqgf = ieqqd = ieqqs = ieqqgb = 0.0; + gcgfgf = gcgfd = gcgfs = gcgfdeltaT = 0.0; + gcdgf = gcdd = gcds = gcddeltaT = 0.0; + gcsgf = gcsd = gcss = gcsdeltaT = 0.0; + gcbgf = gcbd = gcbs = gcbdeltaT = gcbgb = 0.0; + gcgbgb = gcgbsb = gcgbdb = 0.0; + gcgbd0 = gcgbs0 = 0.0; + gct[0]=gct[1]=gct[2]=gct[3]=gct[4]=0.0; + ieqct=ieqct1=ieqct2=ieqct3=ieqct4=0.0; + ieqqBJTbs = ieqqBJTbd = 0.0; + gcBJTbsbs = gcBJTbsdeltaT = gcBJTbdbd = gcBJTbddeltaT = 0.0; + goto LoadUp; + +line860: + + /* evaluate equivalent charge currents */ + + ieqqgf = *(ckt->CKTstate0 + here->SOI3iqgf) - + gcgfgf * vgfb - gcgfd * vdb - gcgfs * vsb - gcgfdeltaT * deltaT; + ieqqd = *(ckt->CKTstate0 + here->SOI3iqd) - + gcdgf * vgfb - gcdd * vdb - gcds * vsb - gcddeltaT * deltaT + + gcgbd0 * vgbd; + ieqqs = *(ckt->CKTstate0 + here->SOI3iqs) - + gcsgf * vgfb - gcsd * vdb - gcss * vsb - gcsdeltaT * deltaT + + gcgbs0 * vgbs; + ieqqgb = *(ckt->CKTstate0 + here->SOI3iqgb) - + gcgbgb * vgbb - gcgbdb * vdb - gcgbsb * vsb; + + ieqqBJTbs = *(ckt->CKTstate0 + here->SOI3iqBJTbs) - + gcBJTbsbs * vbs - gcBJTbsdeltaT * deltaT; + ieqqBJTbd = *(ckt->CKTstate0 + here->SOI3iqBJTbd) - + gcBJTbdbd * vbd - gcBJTbddeltaT * deltaT; + + /* now for the thermal capacitance + is constant and linear so no need + to fart about with equiv current */ + + + error = NIintegrate(ckt,&gct[0],&ieqct,here->SOI3ct, + here->SOI3qt); + if(error) return(error); + error = NIintegrate(ckt,&gct[1],&ieqct1,here->SOI3ct1, + here->SOI3qt1); + if(error) return(error); + error = NIintegrate(ckt,&gct[2],&ieqct2,here->SOI3ct2, + here->SOI3qt2); + if(error) return(error); + error = NIintegrate(ckt,&gct[3],&ieqct3,here->SOI3ct3, + here->SOI3qt3); + if(error) return(error); + error = NIintegrate(ckt,&gct[4],&ieqct4,here->SOI3ct4, + here->SOI3qt4); + if(error) return(error); + +LoadUp: + + /* + * load current vector + */ + ieqbs = model->SOI3type * + (here->SOI3ibs-(here->SOI3gbs-ckt->CKTgmin)*vbs + -(here->SOI3gbsT)*deltaT); + ieqbd = model->SOI3type * + (here->SOI3ibd-(here->SOI3gbd-ckt->CKTgmin)*vbd + -(here->SOI3gbdT)*deltaT); + iBJTdbeq = model->SOI3type * + (here->SOI3iBJTdb -(here->SOI3gBJTdb_bs)*vbs + -(here->SOI3gBJTdb_deltaT)*deltaT); + iBJTsbeq = model->SOI3type * + (here->SOI3iBJTsb -(here->SOI3gBJTsb_bd)*vbd + -(here->SOI3gBJTsb_deltaT)*deltaT); + ieqPt = here->SOI3iPt - (here->SOI3gPds*(here->SOI3mode*vds)+ + here->SOI3gPmf*(here->SOI3mode==1?vgfs:vgfd)+ + here->SOI3gPmb*(here->SOI3mode==1?vgbs:vgbd)+ + here->SOI3gPmbs*(here->SOI3mode==1?vbs:vbd)+ + here->SOI3gPdT*(deltaT)); + if (here->SOI3mode >= 0) { + xnrm=1; + xrev=0; + idreq=model->SOI3type*(idrain-here->SOI3gds*vds- + here->SOI3gmf*vgfs-here->SOI3gmbs*vbs- + here->SOI3gmb*vgbs-here->SOI3gt*deltaT); + iMdbeq=model->SOI3type*(here->SOI3iMdb-here->SOI3gMd*vds- + here->SOI3gMmf*vgfs-here->SOI3gMmbs*vbs- + here->SOI3gMmb*vgbs-here->SOI3gMdeltaT*deltaT); + iMsbeq=0; + } else { + xnrm=0; + xrev=1; + idreq = -(model->SOI3type)*(idrain-here->SOI3gds*(-vds)- + here->SOI3gmf*vgfd-here->SOI3gmbs*vbd- + here->SOI3gmb*vgbd-here->SOI3gt*deltaT); + iMsbeq= (model->SOI3type)*(here->SOI3iMsb-here->SOI3gMd*(-vds)- + here->SOI3gMmf*vgfd-here->SOI3gMmbs*vbd- + here->SOI3gMmb*vgbd-here->SOI3gMdeltaT*deltaT); + iMdbeq = 0; + } + *(ckt->CKTrhs + here->SOI3gfNode) -= + (model->SOI3type * ieqqgf); + *(ckt->CKTrhs + here->SOI3gbNode) -= + (model->SOI3type * ieqqgb); + *(ckt->CKTrhs + here->SOI3bNode) += -(ieqbs + ieqbd) + + iMdbeq + iMsbeq /* one is 0 */ + +iBJTdbeq + iBJTsbeq + + model->SOI3type * (ieqqgf + ieqqd + ieqqs + ieqqgb) + - model->SOI3type * (ieqqBJTbs + ieqqBJTbd); + *(ckt->CKTrhs + here->SOI3dNodePrime) += (ieqbd-idreq) - + iMdbeq - iBJTdbeq + - model->SOI3type * (ieqqd) + + model->SOI3type * (ieqqBJTbd); + *(ckt->CKTrhs + here->SOI3sNodePrime) += (idreq + ieqbs) - + iMsbeq - iBJTsbeq + - model->SOI3type * (ieqqs) + + model->SOI3type * (ieqqBJTbs); + *(ckt->CKTrhs + here->SOI3toutNode) += ieqPt-ieqct; + if (here->SOI3numThermalNodes > 1) + { + *(ckt->CKTrhs + here->SOI3tout1Node) += ieqct-ieqct1; + } + if (here->SOI3numThermalNodes > 2) + { + *(ckt->CKTrhs + here->SOI3tout2Node) += ieqct1-ieqct2; + } + if (here->SOI3numThermalNodes > 3) + { + *(ckt->CKTrhs + here->SOI3tout3Node) += ieqct2-ieqct3; + } + if (here->SOI3numThermalNodes > 2) + { + *(ckt->CKTrhs + here->SOI3tout4Node) += ieqct3-ieqct4; + } + + + /* + * load y matrix + */ + *(here->SOI3D_dPtr) += (here->SOI3drainConductance); + *(here->SOI3GF_gfPtr) += gcgfgf; + *(here->SOI3GB_gbPtr) += gcgbgb; + *(here->SOI3S_sPtr) += (here->SOI3sourceConductance); + *(here->SOI3B_bPtr) += (here->SOI3gbd+here->SOI3gbs - + here->SOI3gMmbs + - here->SOI3gBJTdb_bs - here->SOI3gBJTsb_bd) - + (gcbgf+gcbd+gcbs+gcbgb) + +gcBJTbsbs+gcBJTbdbd; + + *(here->SOI3DP_dpPtr) += + (here->SOI3drainConductance+here->SOI3gds+ + here->SOI3gbd+xrev*(here->SOI3gmf+here->SOI3gmbs+ + here->SOI3gmb)+xnrm*here->SOI3gMd + gcdd)+ + gcgbd0 + gcBJTbdbd; + *(here->SOI3SP_spPtr) += + (here->SOI3sourceConductance+here->SOI3gds+ + here->SOI3gbs+xnrm*(here->SOI3gmf+here->SOI3gmbs+ + here->SOI3gmb)+xrev*here->SOI3gMd + gcss)+ + gcgbs0 + gcBJTbsbs; + + *(here->SOI3D_dpPtr) += (-here->SOI3drainConductance); + *(here->SOI3GF_dpPtr) += gcgfd; + *(here->SOI3GF_spPtr) += gcgfs; + *(here->SOI3GF_bPtr) -= (gcgfgf + gcgfd + gcgfs); + + *(here->SOI3GB_dpPtr) += gcgbdb; + *(here->SOI3GB_spPtr) += gcgbsb; + *(here->SOI3GB_bPtr) -= (gcgbgb + gcgbdb + gcgbsb); + + *(here->SOI3S_spPtr) += (-here->SOI3sourceConductance); + *(here->SOI3B_gfPtr) += -here->SOI3gMmf + gcbgf; + *(here->SOI3B_gbPtr) += -(here->SOI3gMmb) + gcbgb; + *(here->SOI3B_dpPtr) += -(here->SOI3gbd) + here->SOI3gBJTsb_bd + + xrev*(here->SOI3gMmf+here->SOI3gMmb+ + here->SOI3gMmbs+here->SOI3gMd) - + xnrm*here->SOI3gMd + + gcbd - gcBJTbdbd; + *(here->SOI3B_spPtr) += -(here->SOI3gbs) + here->SOI3gBJTdb_bs + + xnrm*(here->SOI3gMmf+here->SOI3gMmb+ + here->SOI3gMmbs+here->SOI3gMd) - + xrev*here->SOI3gMd + + gcbs - gcBJTbsbs; + *(here->SOI3DP_dPtr) += (-here->SOI3drainConductance); + *(here->SOI3SP_sPtr) += (-here->SOI3sourceConductance); + + *(here->SOI3DP_gfPtr) += ((xnrm-xrev)*here->SOI3gmf + gcdgf+ + xnrm*here->SOI3gMmf); + *(here->SOI3DP_gbPtr) += ((xnrm-xrev)*here->SOI3gmb + + xnrm*here->SOI3gMmb) - gcgbd0; + *(here->SOI3DP_bPtr) += (-here->SOI3gbd + here->SOI3gBJTdb_bs + +(xnrm-xrev)*here->SOI3gmbs+ + xnrm*here->SOI3gMmbs) - + (gcdgf + gcdd + gcds + gcBJTbdbd); + *(here->SOI3DP_spPtr) += (-here->SOI3gds - here->SOI3gBJTdb_bs + -xnrm*(here->SOI3gmf+here->SOI3gmb+here->SOI3gmbs + + here->SOI3gMmf+here->SOI3gMmb+here->SOI3gMmbs+here->SOI3gMd)) + + gcds; + + *(here->SOI3SP_gfPtr) += (-(xnrm-xrev)*here->SOI3gmf+ + xrev*here->SOI3gMmf) + + gcsgf; + *(here->SOI3SP_gbPtr) += (-(xnrm-xrev)*here->SOI3gmb+ + xrev*here->SOI3gMmb) - gcgbs0; + *(here->SOI3SP_bPtr) += (-here->SOI3gbs + here->SOI3gBJTsb_bd + -(xnrm-xrev)*here->SOI3gmbs+ + xrev*here->SOI3gMmbs) - + (gcsgf + gcsd + gcss + gcBJTbsbs); + *(here->SOI3SP_dpPtr) += (-here->SOI3gds - here->SOI3gBJTsb_bd + -xrev*(here->SOI3gmf+here->SOI3gmb+here->SOI3gmbs+ + here->SOI3gMmf+here->SOI3gMmb+here->SOI3gMmbs+here->SOI3gMd)) + + gcsd; + +/* if no thermal behaviour specified, then put in zero valued indpt. voltage source + between TOUT and ground */ + if (here->SOI3rt==0) + { + *(here->SOI3TOUT_ibrPtr) += 1.0 ; + *(here->SOI3IBR_toutPtr) += 1.0 ; + *(ckt->CKTrhs + (here->SOI3branch)) = 0 ; + } + else + { + *(here->SOI3TOUT_toutPtr) += -(here->SOI3gPdT)+grt[0]+gct[0]; + + if (here->SOI3numThermalNodes > 1) + { + *(here->SOI3TOUT_tout1Ptr) += -grt[0]-gct[0]; + *(here->SOI3TOUT1_toutPtr) += -grt[0]-gct[0]; + *(here->SOI3TOUT1_tout1Ptr) += grt[0]+grt[1]+gct[0]+gct[1]; + } + if (here->SOI3numThermalNodes > 2) + { + *(here->SOI3TOUT1_tout2Ptr) += -grt[1]-gct[1]; + *(here->SOI3TOUT2_tout1Ptr) += -grt[1]-gct[1]; + *(here->SOI3TOUT2_tout2Ptr) += grt[1]+grt[2]+gct[1]+gct[2]; + } + if (here->SOI3numThermalNodes > 3) + { + *(here->SOI3TOUT2_tout3Ptr) += -grt[2]-gct[2]; + *(here->SOI3TOUT3_tout2Ptr) += -grt[2]-gct[2]; + *(here->SOI3TOUT3_tout3Ptr) += grt[2]+grt[3]+gct[2]+gct[3]; + } + if (here->SOI3numThermalNodes > 4) + { + *(here->SOI3TOUT3_tout4Ptr) += -grt[3]-gct[3]; + *(here->SOI3TOUT4_tout3Ptr) += -grt[3]-gct[3]; + *(here->SOI3TOUT4_tout4Ptr) += grt[3]+grt[4]+gct[3]+gct[4]; + } + + *(here->SOI3TOUT_dpPtr) += xnrm*(-(here->SOI3gPds*model->SOI3type)) + +xrev*(here->SOI3gPds+here->SOI3gPmf+ + here->SOI3gPmb+here->SOI3gPmbs)* + model->SOI3type; + *(here->SOI3TOUT_gfPtr) += -(here->SOI3gPmf*model->SOI3type); + *(here->SOI3TOUT_gbPtr) += -(here->SOI3gPmb*model->SOI3type); + *(here->SOI3TOUT_bPtr) += -(here->SOI3gPmbs*model->SOI3type); + *(here->SOI3TOUT_spPtr) += xnrm*(here->SOI3gPds+here->SOI3gPmf+ + here->SOI3gPmb+here->SOI3gPmbs)*model->SOI3type + +xrev*(-(here->SOI3gPds*model->SOI3type)); + + *(here->SOI3DP_toutPtr) += (xnrm-xrev)*here->SOI3gt*model->SOI3type; + *(here->SOI3SP_toutPtr) += (xrev-xnrm)*here->SOI3gt*model->SOI3type; +/* need to mult by type in above as conductances will be used with exterior voltages + which will be -ve for PMOS except for gPdT */ +/* now for thermal influence on impact ionisation current and tranisent stuff */ + *(here->SOI3GF_toutPtr) += gcgfdeltaT*model->SOI3type; + *(here->SOI3DP_toutPtr) += (xnrm*here->SOI3gMdeltaT + gcddeltaT - + here->SOI3gbdT + here->SOI3gBJTdb_deltaT + - gcBJTbddeltaT)*model->SOI3type; + *(here->SOI3SP_toutPtr) += (xrev*here->SOI3gMdeltaT + gcsdeltaT - + here->SOI3gbsT + here->SOI3gBJTsb_deltaT + - gcBJTbsdeltaT)*model->SOI3type; + *(here->SOI3B_toutPtr) -= (here->SOI3gMdeltaT - gcbdeltaT - + here->SOI3gbsT - here->SOI3gbdT + + here->SOI3gBJTdb_deltaT + + here->SOI3gBJTsb_deltaT + -gcBJTbsdeltaT-gcBJTbddeltaT)*model->SOI3type; + } +End: ; + } + } + return(OK); +} + +void common_handler(int sig,int code,struct sigcontext *scp,char * addr) +{; +} + + /* DEVsoipnjlim(vnew,vold,vt,vcrit,icheck) + * limit the per-iteration change of PN junction voltages + */ + +double +DEVsoipnjlim(vnew,vold,vt,vcrit,icheck) + + double vnew; + double vold; + double vt; + double vcrit; + int *icheck; + +{ + double arg; + + if((vnew > vcrit) && (fabs(vnew - vold) > (vt + vt))) { + if(vold > 0) { + arg = 1 + (vnew - vold) / vt; + if(arg > 0) { + vnew = vold + vt * log(arg); + } else { + vnew = vcrit; + } + } else { + vnew = vt *log(vnew/vt); + } + *icheck = 1; + } else { + if (fabs(vnew - vold) < (vt + vt)) { + *icheck = 0; + } else { + if (vnew>vold) { + *icheck = 0; + } else { + arg = 1 + (vold - vnew) / vt; + vnew = vold - vt*log(arg); + *icheck = 1; + } + } + } + return(vnew); +} diff --git a/src/spicelib/devices/soi3/soi3mask.c b/src/spicelib/devices/soi3/soi3mask.c new file mode 100644 index 000000000..50136982c --- /dev/null +++ b/src/spicelib/devices/soi3/soi3mask.c @@ -0,0 +1,286 @@ +/********** +STAG version 2.6 +Copyright 2000 owned by the United Kingdom Secretary of State for Defence +acting through the Defence Evaluation and Research Agency. +Developed by : Jim Benson, + Department of Electronics and Computer Science, + University of Southampton, + United Kingdom. +With help from : Nele D'Halleweyn, Bill Redman-White, and Craig Easson. + +Based on STAG version 2.1 +Developed by : Mike Lee, +With help from : Bernard Tenbroek, Bill Redman-White, Mike Uren, Chris Edwards + and John Bunyan. +Acknowledgements : Rupert Howes and Pete Mole. +**********/ + +/* Modified: Paolo Nenzi 2001 */ + +#include "ngspice.h" +#include +#include "const.h" +#include "ifsim.h" +#include "cktdefs.h" +#include "devdefs.h" +#include "soi3defs.h" +#include "sperror.h" +#include "suffix.h" + + +/*ARGSUSED*/ +int +SOI3mAsk(ckt,inst,which,value) + CKTcircuit *ckt; + GENmodel *inst; + int which; + IFvalue *value; +{ + SOI3model *model = (SOI3model *)inst; + switch(which) { + case SOI3_MOD_VTO: + value->rValue = model->SOI3vt0; + return(OK); + case SOI3_MOD_VFBF: + value->rValue = model->SOI3vfbF; + return(OK); + case SOI3_MOD_KP: + value->rValue = model->SOI3transconductance; + return(OK); + case SOI3_MOD_GAMMA: + value->rValue = model->SOI3gamma; + return(OK); + case SOI3_MOD_PHI: + value->rValue = model->SOI3phi; + return(OK); + case SOI3_MOD_LAMBDA: + value->rValue = model->SOI3lambda; + return(OK); + case SOI3_MOD_THETA: + value->rValue = model->SOI3theta; + return(OK); + case SOI3_MOD_RD: + value->rValue = model->SOI3drainResistance; + return(OK); + case SOI3_MOD_RS: + value->rValue = model->SOI3sourceResistance; + return(OK); + case SOI3_MOD_CBD: + value->rValue = model->SOI3capBD; + return(OK); + case SOI3_MOD_CBS: + value->rValue = model->SOI3capBS; + return(OK); + case SOI3_MOD_IS: + value->rValue = model->SOI3jctSatCur; + return(OK); + case SOI3_MOD_IS1: + value->rValue = model->SOI3jctSatCur1; + return(OK); + case SOI3_MOD_PB: + value->rValue = model->SOI3bulkJctPotential; + return(OK); + case SOI3_MOD_CGFSO: + value->rValue = model->SOI3frontGateSourceOverlapCapFactor; + return(OK); + case SOI3_MOD_CGFDO: + value->rValue = model->SOI3frontGateDrainOverlapCapFactor; + return(OK); + case SOI3_MOD_CGFBO: + value->rValue = model->SOI3frontGateBulkOverlapCapFactor; + return(OK); + case SOI3_MOD_CGBSO: + value->rValue = model->SOI3backGateSourceOverlapCapFactor; + return(OK); + case SOI3_MOD_CGBDO: + value->rValue = model->SOI3backGateDrainOverlapCapFactor; + return(OK); + case SOI3_MOD_CGB_BO: + value->rValue = model->SOI3backGateBulkOverlapCapFactor; + return(OK); + case SOI3_MOD_RSH: + value->rValue = model->SOI3sheetResistance; + return(OK); + case SOI3_MOD_CJSW: + value->rValue = model->SOI3sideWallCapFactor; + return(OK); + case SOI3_MOD_MJSW: + value->rValue = model->SOI3bulkJctSideGradingCoeff; + return(OK); + case SOI3_MOD_JS: + value->rValue = model->SOI3jctSatCurDensity; + return(OK); + case SOI3_MOD_JS1: + value->rValue = model->SOI3jctSatCurDensity1; + return(OK); + case SOI3_MOD_TOF: + value->rValue = model->SOI3frontOxideThickness; + return(OK); + case SOI3_MOD_TOB: + value->rValue = model->SOI3backOxideThickness; + return(OK); + case SOI3_MOD_TB: + value->rValue = model->SOI3bodyThickness; + return(OK); + case SOI3_MOD_LD: + value->rValue = model->SOI3latDiff; + return(OK); + case SOI3_MOD_U0: + value->rValue = model->SOI3surfaceMobility; + return(OK); + case SOI3_MOD_FC: + value->rValue = model->SOI3fwdCapDepCoeff; + return(OK); + case SOI3_MOD_KOX: + value->rValue = model->SOI3oxideThermalConductivity; + return(OK); + case SOI3_MOD_SHSI: + value->rValue = model->SOI3siliconSpecificHeat; + return(OK); + case SOI3_MOD_DSI: + value->rValue = model->SOI3siliconDensity; + return(OK); + case SOI3_MOD_NSUB: + value->rValue = model->SOI3substrateDoping; + return(OK); + case SOI3_MOD_TPG: + value->iValue = model->SOI3gateType; + return(OK); + case SOI3_MOD_NQFF: + value->rValue = model->SOI3frontFixedChargeDensity; + return(OK); + case SOI3_MOD_NQFB: + value->rValue = model->SOI3backFixedChargeDensity; + return(OK); + case SOI3_MOD_NSSF: + value->rValue = model->SOI3frontSurfaceStateDensity; + return(OK); + case SOI3_MOD_NSSB: + value->rValue = model->SOI3backSurfaceStateDensity; + return(OK); + case SOI3_MOD_TNOM: + value->rValue = model->SOI3tnom-CONSTCtoK; + return(OK); +/* extra stuff for newer model - msll Jan96 */ + case SOI3_MOD_SIGMA: + value->rValue = model->SOI3sigma; + return(OK); + case SOI3_MOD_CHIFB: + value->rValue = model->SOI3chiFB; + return(OK); + case SOI3_MOD_CHIPHI: + value->rValue = model->SOI3chiPHI; + return(OK); + case SOI3_MOD_DELTAW: + value->rValue = model->SOI3deltaW; + return(OK); + case SOI3_MOD_DELTAL: + value->rValue = model->SOI3deltaL; + return(OK); + case SOI3_MOD_VSAT: + value->rValue = model->SOI3vsat; + return(OK); + case SOI3_MOD_K: + value->rValue = model->SOI3k; + return(OK); + case SOI3_MOD_LX: + value->rValue = model->SOI3lx; + return(OK); + case SOI3_MOD_VP: + value->rValue = model->SOI3vp; + return(OK); + case SOI3_MOD_ETA: + value->rValue = model->SOI3eta; + return(OK); + case SOI3_MOD_ALPHA0: + value->rValue = model->SOI3alpha0; + return(OK); + case SOI3_MOD_BETA0: + value->rValue = model->SOI3beta0; + return(OK); + case SOI3_MOD_LM: + value->rValue = model->SOI3lm; + return(OK); + case SOI3_MOD_LM1: + value->rValue = model->SOI3lm1; + return(OK); + case SOI3_MOD_LM2: + value->rValue = model->SOI3lm2; + return(OK); + case SOI3_MOD_ETAD: + value->rValue = model->SOI3etad; + return(OK); + case SOI3_MOD_ETAD1: + value->rValue = model->SOI3etad1; + return(OK); + case SOI3_MOD_CHIBETA: + value->rValue = model->SOI3chibeta; + return(OK); + case SOI3_MOD_VFBB: + value->rValue = model->SOI3vfbB; + return(OK); + case SOI3_MOD_GAMMAB: + value->rValue = model->SOI3gammaB; + return(OK); + case SOI3_MOD_CHID: + value->rValue = model->SOI3chid; + return(OK); + case SOI3_MOD_CHID1: + value->rValue = model->SOI3chid1; + return(OK); + case SOI3_MOD_DVT: + value->iValue = model->SOI3dvt; + return(OK); + case SOI3_MOD_NLEV: + value->iValue = model->SOI3nLev; + return(OK); + case SOI3_MOD_BETABJT: + value->rValue = model->SOI3betaBJT; + return(OK); + case SOI3_MOD_TAUFBJT: + value->rValue = model->SOI3tauFBJT; + return(OK); + case SOI3_MOD_TAURBJT: + value->rValue = model->SOI3tauRBJT; + return(OK); + case SOI3_MOD_BETAEXP: + value->rValue = model->SOI3betaEXP; + return(OK); + case SOI3_MOD_TAUEXP: + value->rValue = model->SOI3tauEXP; + return(OK); + case SOI3_MOD_RSW: + value->rValue = model->SOI3rsw; + return(OK); + case SOI3_MOD_RDW: + value->rValue = model->SOI3rdw; + return(OK); + case SOI3_MOD_FMIN: + value->rValue = model->SOI3minimumFeatureSize; + return(OK); + case SOI3_MOD_VTEX: + value->rValue = model->SOI3vtex; + return(OK); + case SOI3_MOD_VDEX: + value->rValue = model->SOI3vdex; + return(OK); + case SOI3_MOD_DELTA0: + value->rValue = model->SOI3delta0; + return(OK); + case SOI3_MOD_CSF: + value->rValue = model->SOI3satChargeShareFactor; + return(OK); + case SOI3_MOD_NPLUS: + value->rValue = model->SOI3nplusDoping; + return(OK); + case SOI3_MOD_RTA: + value->rValue = model->SOI3rta; + return(OK); + case SOI3_MOD_CTA: + value->rValue = model->SOI3cta; + return(OK); + default: + return(E_BADPARM); + } + /* NOTREACHED */ +} diff --git a/src/spicelib/devices/soi3/soi3mdel.c b/src/spicelib/devices/soi3/soi3mdel.c new file mode 100644 index 000000000..be6c05c06 --- /dev/null +++ b/src/spicelib/devices/soi3/soi3mdel.c @@ -0,0 +1,56 @@ +/********** +STAG version 2.6 +Copyright 2000 owned by the United Kingdom Secretary of State for Defence +acting through the Defence Evaluation and Research Agency. +Developed by : Jim Benson, + Department of Electronics and Computer Science, + University of Southampton, + United Kingdom. +With help from : Nele D'Halleweyn, Bill Redman-White, and Craig Easson. + +Based on STAG version 2.1 +Developed by : Mike Lee, +With help from : Bernard Tenbroek, Bill Redman-White, Mike Uren, Chris Edwards + and John Bunyan. +Acknowledgements : Rupert Howes and Pete Mole. +**********/ + +/* Modified: 2001 Paolo Nenzi */ + +#include "ngspice.h" +#include +#include "soi3defs.h" +#include "sperror.h" +#include "suffix.h" + + +int +SOI3mDelete(inModel,modname,kill) + GENmodel **inModel; + IFuid modname; + GENmodel *kill; +{ + SOI3model **model = (SOI3model **)inModel; + SOI3model *modfast = (SOI3model *)kill; + SOI3instance *here; + SOI3instance *prev = NULL; + SOI3model **oldmod; + oldmod = model; + for( ; *model ; model = &((*model)->SOI3nextModel)) { + if( (*model)->SOI3modName == modname || + (modfast && *model == modfast) ) goto delgot; + oldmod = model; + } + return(E_NOMOD); + +delgot: + *oldmod = (*model)->SOI3nextModel; /* cut deleted device out of list */ + for(here = (*model)->SOI3instances ; here ; here = here->SOI3nextInstance) { + if(prev) FREE(prev); + prev = here; + } + if(prev) FREE(prev); + FREE(*model); + return(OK); + +} diff --git a/src/spicelib/devices/soi3/soi3mpar.c b/src/spicelib/devices/soi3/soi3mpar.c new file mode 100644 index 000000000..4ff0417ba --- /dev/null +++ b/src/spicelib/devices/soi3/soi3mpar.c @@ -0,0 +1,390 @@ +/********** +STAG version 2.6 +Copyright 2000 owned by the United Kingdom Secretary of State for Defence +acting through the Defence Evaluation and Research Agency. +Developed by : Jim Benson, + Department of Electronics and Computer Science, + University of Southampton, + United Kingdom. +With help from : Nele D'Halleweyn, Bill Redman-White, and Craig Easson. + +Based on STAG version 2.1 +Developed by : Mike Lee, +With help from : Bernard Tenbroek, Bill Redman-White, Mike Uren, Chris Edwards + and John Bunyan. +Acknowledgements : Rupert Howes and Pete Mole. +**********/ + +/* Modified: 2001 Paolo Nenzi */ + +#include "ngspice.h" +#include +#include "const.h" +#include "ifsim.h" +#include "soi3defs.h" +#include "sperror.h" +#include "suffix.h" + +int +SOI3mParam(param,value,inModel) + int param; + IFvalue *value; + GENmodel *inModel; +{ + register SOI3model *model = (SOI3model *)inModel; + switch(param) { + case SOI3_MOD_VTO: + model->SOI3vt0 = value->rValue; + model->SOI3vt0Given = TRUE; + break; + case SOI3_MOD_VFBF: + model->SOI3vfbF = value->rValue; + model->SOI3vfbFGiven = TRUE; + break; + case SOI3_MOD_KP: + model->SOI3transconductance = value->rValue; + model->SOI3transconductanceGiven = TRUE; + break; + case SOI3_MOD_GAMMA: + model->SOI3gamma = value->rValue; + model->SOI3gammaGiven = TRUE; + break; + case SOI3_MOD_PHI: + model->SOI3phi = value->rValue; + model->SOI3phiGiven = TRUE; + break; + case SOI3_MOD_LAMBDA: + model->SOI3lambda = value->rValue; + model->SOI3lambdaGiven = TRUE; + break; + case SOI3_MOD_THETA: + model->SOI3theta = value->rValue; + model->SOI3thetaGiven = TRUE; + break; + case SOI3_MOD_RD: + model->SOI3drainResistance = value->rValue; + model->SOI3drainResistanceGiven = TRUE; + break; + case SOI3_MOD_RS: + model->SOI3sourceResistance = value->rValue; + model->SOI3sourceResistanceGiven = TRUE; + break; + case SOI3_MOD_CBD: + model->SOI3capBD = value->rValue; + model->SOI3capBDGiven = TRUE; + break; + case SOI3_MOD_CBS: + model->SOI3capBS = value->rValue; + model->SOI3capBSGiven = TRUE; + break; + case SOI3_MOD_IS: + model->SOI3jctSatCur = value->rValue; + model->SOI3jctSatCurGiven = TRUE; + break; + case SOI3_MOD_IS1: + model->SOI3jctSatCur1 = value->rValue; + model->SOI3jctSatCur1Given = TRUE; + break; + case SOI3_MOD_PB: + model->SOI3bulkJctPotential = value->rValue; + model->SOI3bulkJctPotentialGiven = TRUE; + break; + case SOI3_MOD_CGFSO: + model->SOI3frontGateSourceOverlapCapFactor = value->rValue; + model->SOI3frontGateSourceOverlapCapFactorGiven = TRUE; + break; + case SOI3_MOD_CGFDO: + model->SOI3frontGateDrainOverlapCapFactor = value->rValue; + model->SOI3frontGateDrainOverlapCapFactorGiven = TRUE; + break; + case SOI3_MOD_CGFBO: + model->SOI3frontGateBulkOverlapCapFactor = value->rValue; + model->SOI3frontGateBulkOverlapCapFactorGiven = TRUE; + break; + case SOI3_MOD_CGBSO: + model->SOI3backGateSourceOverlapCapFactor = value->rValue; + model->SOI3backGateSourceOverlapCapFactorGiven = TRUE; + break; + case SOI3_MOD_CGBDO: + model->SOI3backGateDrainOverlapCapFactor = value->rValue; + model->SOI3backGateDrainOverlapCapFactorGiven = TRUE; + break; + case SOI3_MOD_CGB_BO: + model->SOI3backGateBulkOverlapCapFactor = value->rValue; + model->SOI3backGateBulkOverlapCapFactorGiven = TRUE; + break; +/* case SOI3_MOD_CJ: + model->SOI3bulkCapFactor = value->rValue; + model->SOI3bulkCapFactorGiven = TRUE; + break; + case SOI3_MOD_MJ: + model->SOI3bulkJctBotGradingCoeff = value->rValue; + model->SOI3bulkJctBotGradingCoeffGiven = TRUE; + break; */ + case SOI3_MOD_RSH: + model->SOI3sheetResistance = value->rValue; + model->SOI3sheetResistanceGiven = TRUE; + break; + case SOI3_MOD_CJSW: + model->SOI3sideWallCapFactor = value->rValue; + model->SOI3sideWallCapFactorGiven = TRUE; + break; + case SOI3_MOD_MJSW: + model->SOI3bulkJctSideGradingCoeff = value->rValue; + model->SOI3bulkJctSideGradingCoeffGiven = TRUE; + break; + case SOI3_MOD_JS: + model->SOI3jctSatCurDensity = value->rValue; + model->SOI3jctSatCurDensityGiven = TRUE; + break; + case SOI3_MOD_JS1: + model->SOI3jctSatCurDensity1 = value->rValue; + model->SOI3jctSatCurDensity1Given = TRUE; + break; + case SOI3_MOD_TOF: + model->SOI3frontOxideThickness = value->rValue; + model->SOI3frontOxideThicknessGiven = TRUE; + break; + case SOI3_MOD_TOB: + model->SOI3backOxideThickness = value->rValue; + model->SOI3backOxideThicknessGiven = TRUE; + break; + case SOI3_MOD_TB: + model->SOI3bodyThickness = value->rValue; + model->SOI3bodyThicknessGiven = TRUE; + break; + case SOI3_MOD_LD: + model->SOI3latDiff = value->rValue; + model->SOI3latDiffGiven = TRUE; + break; + case SOI3_MOD_U0: + model->SOI3surfaceMobility = value->rValue; + model->SOI3surfaceMobilityGiven = TRUE; + break; + case SOI3_MOD_FC: + model->SOI3fwdCapDepCoeff = value->rValue; + model->SOI3fwdCapDepCoeffGiven = TRUE; + break; + case SOI3_MOD_NSOI3: + if(value->iValue) { + model->SOI3type = 1; + model->SOI3typeGiven = TRUE; + } + break; + case SOI3_MOD_PSOI3: + if(value->iValue) { + model->SOI3type = -1; + model->SOI3typeGiven = TRUE; + } + break; + case SOI3_MOD_KOX: + model->SOI3oxideThermalConductivity = value->rValue; + model->SOI3oxideThermalConductivityGiven = TRUE; + break; + case SOI3_MOD_SHSI: + model->SOI3siliconSpecificHeat = value->rValue; + model->SOI3siliconSpecificHeatGiven = TRUE; + break; + case SOI3_MOD_DSI: + model->SOI3siliconDensity = value->rValue; + model->SOI3siliconDensityGiven = TRUE; + break; + case SOI3_MOD_NSUB: + model->SOI3substrateDoping = value->rValue; + model->SOI3substrateDopingGiven = TRUE; + break; + case SOI3_MOD_TPG: + model->SOI3gateType = value->iValue; + model->SOI3gateTypeGiven = TRUE; + break; + case SOI3_MOD_NQFF: + model->SOI3frontFixedChargeDensity = value->rValue; + model->SOI3frontFixedChargeDensityGiven = TRUE; + break; + case SOI3_MOD_NQFB: + model->SOI3backFixedChargeDensity = value->rValue; + model->SOI3backFixedChargeDensityGiven = TRUE; + break; + case SOI3_MOD_NSSF: + model->SOI3frontSurfaceStateDensity = value->rValue; + model->SOI3frontSurfaceStateDensityGiven = TRUE; + break; + case SOI3_MOD_NSSB: + model->SOI3backSurfaceStateDensity = value->rValue; + model->SOI3backSurfaceStateDensityGiven = TRUE; + break; + case SOI3_MOD_TNOM: + model->SOI3tnom = value->rValue+CONSTCtoK; + model->SOI3tnomGiven = TRUE; + break; + case SOI3_MOD_KF: + model->SOI3fNcoef = value->rValue; + model->SOI3fNcoefGiven = TRUE; + break; + case SOI3_MOD_AF: + model->SOI3fNexp = value->rValue; + model->SOI3fNexpGiven = TRUE; + break; +/* extra stuff for newer model - msll Jan96 */ + case SOI3_MOD_SIGMA: + model->SOI3sigma = value->rValue; + model->SOI3sigmaGiven = TRUE; + break; + case SOI3_MOD_CHIFB: + model->SOI3chiFB = value->rValue; + model->SOI3chiFBGiven = TRUE; + break; + case SOI3_MOD_CHIPHI: + model->SOI3chiPHI = value->rValue; + model->SOI3chiPHIGiven = TRUE; + break; + case SOI3_MOD_DELTAW: + model->SOI3deltaW = value->rValue; + model->SOI3deltaWGiven = TRUE; + break; + case SOI3_MOD_DELTAL: + model->SOI3deltaL = value->rValue; + model->SOI3deltaLGiven = TRUE; + break; + case SOI3_MOD_VSAT: + model->SOI3vsat = value->rValue; + model->SOI3vsatGiven = TRUE; + break; + case SOI3_MOD_K: + model->SOI3k = value->rValue; + model->SOI3kGiven = TRUE; + break; + case SOI3_MOD_LX: + model->SOI3lx = value->rValue; + model->SOI3lxGiven = TRUE; + break; + case SOI3_MOD_VP: + model->SOI3vp = value->rValue; + model->SOI3vpGiven = TRUE; + break; + case SOI3_MOD_ETA: + model->SOI3eta = value->rValue; + model->SOI3etaGiven = TRUE; + break; + case SOI3_MOD_ALPHA0: + model->SOI3alpha0 = value->rValue; + model->SOI3alpha0Given = TRUE; + break; + case SOI3_MOD_BETA0: + model->SOI3beta0 = value->rValue; + model->SOI3beta0Given = TRUE; + break; + case SOI3_MOD_LM: + model->SOI3lm = value->rValue; + model->SOI3lmGiven = TRUE; + break; + case SOI3_MOD_LM1: + model->SOI3lm1 = value->rValue; + model->SOI3lm1Given = TRUE; + break; + case SOI3_MOD_LM2: + model->SOI3lm2 = value->rValue; + model->SOI3lm2Given = TRUE; + break; + case SOI3_MOD_ETAD: + model->SOI3etad = value->rValue; + model->SOI3etadGiven = TRUE; + break; + case SOI3_MOD_ETAD1: + model->SOI3etad1 = value->rValue; + model->SOI3etad1Given = TRUE; + break; + case SOI3_MOD_CHIBETA: + model->SOI3chibeta = value->rValue; + model->SOI3chibetaGiven = TRUE; + break; + case SOI3_MOD_VFBB: + model->SOI3vfbB = value->rValue; + model->SOI3vfbBGiven = TRUE; + break; + case SOI3_MOD_GAMMAB: + model->SOI3gammaB = value->rValue; + model->SOI3gammaBGiven = TRUE; + break; + case SOI3_MOD_CHID: + model->SOI3chid = value->rValue; + model->SOI3chidGiven = TRUE; + break; + case SOI3_MOD_CHID1: + model->SOI3chid1 = value->rValue; + model->SOI3chid1Given = TRUE; + break; + case SOI3_MOD_DVT: + model->SOI3dvt = value->iValue; + model->SOI3dvtGiven = TRUE; + break; + case SOI3_MOD_NLEV: + model->SOI3nLev = value->iValue; + model->SOI3nLevGiven = TRUE; + break; + case SOI3_MOD_BETABJT: + model->SOI3betaBJT = value->rValue; + model->SOI3betaBJTGiven = TRUE; + break; + case SOI3_MOD_TAUFBJT: + model->SOI3tauFBJT = value->rValue; + model->SOI3tauFBJTGiven = TRUE; + break; + case SOI3_MOD_TAURBJT: + model->SOI3tauRBJT = value->rValue; + model->SOI3tauRBJTGiven = TRUE; + break; + case SOI3_MOD_BETAEXP: + model->SOI3betaEXP = value->rValue; + model->SOI3betaEXPGiven = TRUE; + break; + case SOI3_MOD_TAUEXP: + model->SOI3tauEXP = value->rValue; + model->SOI3tauEXPGiven = TRUE; + break; + case SOI3_MOD_RSW: + model->SOI3rsw = value->rValue; + model->SOI3rswGiven = TRUE; + break; + case SOI3_MOD_RDW: + model->SOI3rdw = value->rValue; + model->SOI3rdwGiven = TRUE; + break; + case SOI3_MOD_FMIN: + model->SOI3minimumFeatureSize = value->rValue; + model->SOI3minimumFeatureSizeGiven = TRUE; + break; + case SOI3_MOD_VTEX: + model->SOI3vtex = value->rValue; + model->SOI3vtexGiven = TRUE; + break; + case SOI3_MOD_VDEX: + model->SOI3vdex = value->rValue; + model->SOI3vdexGiven = TRUE; + break; + case SOI3_MOD_DELTA0: + model->SOI3delta0 = value->rValue; + model->SOI3delta0Given = TRUE; + break; + case SOI3_MOD_CSF: + model->SOI3satChargeShareFactor = value->rValue; + model->SOI3satChargeShareFactorGiven = TRUE; + break; + case SOI3_MOD_NPLUS: + model->SOI3nplusDoping = value->rValue; + model->SOI3nplusDopingGiven = TRUE; + break; + case SOI3_MOD_RTA: + model->SOI3rta = value->rValue; + model->SOI3rtaGiven = TRUE; + break; + case SOI3_MOD_CTA: + model->SOI3cta = value->rValue; + model->SOI3ctaGiven = TRUE; + break; + + default: + return(E_BADPARM); + } + return(OK); +} diff --git a/src/spicelib/devices/soi3/soi3nois.c b/src/spicelib/devices/soi3/soi3nois.c new file mode 100644 index 000000000..9372bc466 --- /dev/null +++ b/src/spicelib/devices/soi3/soi3nois.c @@ -0,0 +1,279 @@ +/********** +STAG version 2.6 +Copyright 2000 owned by the United Kingdom Secretary of State for Defence +acting through the Defence Evaluation and Research Agency. +Developed by : Jim Benson, + Department of Electronics and Computer Science, + University of Southampton, + United Kingdom. +With help from : Nele D'Halleweyn, Bill Redman-White, and Craig Easson. + +Based on STAG version 2.1 +Developed by : Mike Lee, +With help from : Bernard Tenbroek, Bill Redman-White, Mike Uren, Chris Edwards + and John Bunyan. +Acknowledgements : Rupert Howes and Pete Mole. +**********/ + +/* Modified: 2001 Paolo Nenzi */ + +#include "ngspice.h" +#include +#include "soi3defs.h" +#include "cktdefs.h" +#include "iferrmsg.h" +#include "noisedef.h" +#include "const.h" +#include "suffix.h" + + + +/* This routine is VERY closely based on the standard MOS noise function. + * SOI3noise (mode, operation, firstModel, ckt, data, OnDens) + * This routine names and evaluates all of the noise sources + * associated with MOSFET's. It starts with the model *firstModel and + * traverses all of its insts. It then proceeds to any other models + * on the linked list. The total output noise density generated by + * all of the MOSFET's is summed with the variable "OnDens". + */ + +extern void NevalSrc(); +extern double Nintegrate(); + +int +SOI3noise (mode, operation, genmodel, ckt, data, OnDens) + int mode; + int operation; + GENmodel *genmodel; + CKTcircuit *ckt; + register Ndata *data; + double *OnDens; +{ + SOI3model *firstModel = (SOI3model *) genmodel; + register SOI3model *model; + register SOI3instance *inst; + char name[N_MXVLNTH]; + double tempOnoise; + double tempInoise; + double noizDens[SOI3NSRCS]; + double lnNdens[SOI3NSRCS]; + double gain; + double EffectiveLength; + int error; + int i; + + /* define the names of the noise sources */ + + static char *SOI3nNames[SOI3NSRCS] = { /* Note that we have to keep the order */ + "_rd", /* noise due to rd */ /* consistent with the index definitions */ + "_rs", /* noise due to rs */ /* in SOI3defs.h */ + "_id", /* noise due to id */ + "_1overf", /* flicker (1/f) noise */ + "" /* total transistor noise */ + }; + + for (model=firstModel; model != NULL; model=model->SOI3nextModel) { + for (inst=model->SOI3instances; inst != NULL; inst=inst->SOI3nextInstance) { + switch (operation) { + + case N_OPEN: + + /* see if we have to to produce a summary report */ + /* if so, name all the noise generators */ + + if (((NOISEAN*)ckt->CKTcurJob)->NStpsSm != 0) { + switch (mode) { + + case N_DENS: + for (i=0; i < SOI3NSRCS; i++) { + + (void)sprintf(name,"onoise_%s%s",inst->SOI3name,SOI3nNames[i]); + +data->namelist = (IFuid *)trealloc((char *)data->namelist,(data->numPlots + 1)*sizeof(IFuid)); +if (!data->namelist) return(E_NOMEM); + (*(SPfrontEnd->IFnewUid))(ckt, + &(data->namelist[data->numPlots++]), + (IFuid)NULL,name,UID_OTHER,(void **)NULL); + /* we've added one more plot */ + + + } + break; + + case INT_NOIZ: + for (i=0; i < SOI3NSRCS; i++) { + + (void)sprintf(name,"onoise_total_%s%s",inst->SOI3name,SOI3nNames[i]); + +data->namelist = (IFuid *)trealloc((char *)data->namelist,(data->numPlots + 1)*sizeof(IFuid)); +if (!data->namelist) return(E_NOMEM); + (*(SPfrontEnd->IFnewUid))(ckt, + &(data->namelist[data->numPlots++]), + (IFuid)NULL,name,UID_OTHER,(void **)NULL); + /* we've added one more plot */ + + (void)sprintf(name,"inoise_total_%s%s",inst->SOI3name,SOI3nNames[i]); + + +data->namelist = (IFuid *)trealloc((char *)data->namelist,(data->numPlots + 1)*sizeof(IFuid)); +if (!data->namelist) return(E_NOMEM); + (*(SPfrontEnd->IFnewUid))(ckt, + &(data->namelist[data->numPlots++]), + (IFuid)NULL,name,UID_OTHER,(void **)NULL); + /* we've added one more plot */ + + + + } + break; + } + } + break; + + case N_CALC: + switch (mode) { + + case N_DENS: +/* just get gain from eval routine. Do thermal + * noise ourselves as we have local temperature + * rise. Also can use channel charge so model + * is valid in ALL regions and not just saturation. + */ + EffectiveLength=inst->SOI3l - 2*model->SOI3latDiff; + NevalSrc(&noizDens[SOI3RDNOIZ],(double*)NULL, + ckt,N_GAIN,inst->SOI3dNodePrime,inst->SOI3dNode, + (double)0.0); + noizDens[SOI3RDNOIZ] *= 4 * CONSTboltz * + (ckt->CKTtemp + *(ckt->CKTstate0 + inst->SOI3deltaT)) * + inst->SOI3drainConductance; + lnNdens[SOI3RDNOIZ] = log(MAX(noizDens[SOI3RDNOIZ],N_MINLOG)); + + NevalSrc(&noizDens[SOI3RSNOIZ],(double*)NULL, + ckt,N_GAIN,inst->SOI3sNodePrime,inst->SOI3sNode, + (double)0.0); + noizDens[SOI3RSNOIZ] *= 4 * CONSTboltz * + (ckt->CKTtemp + *(ckt->CKTstate0 + inst->SOI3deltaT)) * + inst->SOI3sourceConductance; + lnNdens[SOI3RSNOIZ] = log(MAX(noizDens[SOI3RSNOIZ],N_MINLOG)); + + NevalSrc(&gain,(double*)NULL,ckt, + N_GAIN,inst->SOI3dNodePrime, inst->SOI3sNodePrime, + (double)0.0); + + noizDens[SOI3IDNOIZ] = (gain * 4 * CONSTboltz * + (ckt->CKTtemp + *(ckt->CKTstate0 + inst->SOI3deltaT)) * + inst->SOI3ueff * + fabs(*(ckt->CKTstate0 + inst->SOI3qd) + + *(ckt->CKTstate0 + inst->SOI3qs)))/ + (EffectiveLength*EffectiveLength); + lnNdens[SOI3IDNOIZ] = log(MAX(noizDens[SOI3IDNOIZ],N_MINLOG)); + + switch (model->SOI3nLev) { + case 2: + noizDens[SOI3FLNOIZ] = gain * model->SOI3fNcoef * + (inst->SOI3gmf)*(inst->SOI3gmf)/ + (model->SOI3frontOxideCapFactor * + inst->SOI3w * EffectiveLength * + exp(model->SOI3fNexp * + log(MAX(fabs(data->freq),N_MINLOG))) + ); + break; + + case 1: + noizDens[SOI3FLNOIZ] = gain * model->SOI3fNcoef * + exp(model->SOI3fNexp * + log(MAX(fabs(inst->SOI3id),N_MINLOG))) / + (data->freq * EffectiveLength * inst->SOI3w * + model->SOI3frontOxideCapFactor); + break; + + case 0: + default: + noizDens[SOI3FLNOIZ] = gain * model->SOI3fNcoef * + exp(model->SOI3fNexp * + log(MAX(fabs(inst->SOI3id),N_MINLOG))) / + (data->freq * EffectiveLength * EffectiveLength * + model->SOI3frontOxideCapFactor); + break; + } + + + + + lnNdens[SOI3FLNOIZ] = + log(MAX(noizDens[SOI3FLNOIZ],N_MINLOG)); + + noizDens[SOI3TOTNOIZ] = noizDens[SOI3RDNOIZ] + + noizDens[SOI3RSNOIZ] + + noizDens[SOI3IDNOIZ] + + noizDens[SOI3FLNOIZ]; + lnNdens[SOI3TOTNOIZ] = + log(MAX(noizDens[SOI3TOTNOIZ], N_MINLOG)); + + *OnDens += noizDens[SOI3TOTNOIZ]; + + if (data->delFreq == 0.0) { + + /* if we haven't done any previous integration, we need to */ + /* initialize our "history" variables */ + + for (i=0; i < SOI3NSRCS; i++) { + inst->SOI3nVar[LNLSTDENS][i] = lnNdens[i]; + } + + /* clear out our integration variables if it's the first pass */ + + if (data->freq == ((NOISEAN*)ckt->CKTcurJob)->NstartFreq) { + for (i=0; i < SOI3NSRCS; i++) { + inst->SOI3nVar[OUTNOIZ][i] = 0.0; + inst->SOI3nVar[INNOIZ][i] = 0.0; + } + } + } else { /* data->delFreq != 0.0 (we have to integrate) */ + for (i=0; i < SOI3NSRCS; i++) { + if (i != SOI3TOTNOIZ) { + tempOnoise = Nintegrate(noizDens[i], lnNdens[i], + inst->SOI3nVar[LNLSTDENS][i], data); + tempInoise = Nintegrate(noizDens[i] * data->GainSqInv , + lnNdens[i] + data->lnGainInv, + inst->SOI3nVar[LNLSTDENS][i] + data->lnGainInv, + data); + inst->SOI3nVar[LNLSTDENS][i] = lnNdens[i]; + data->outNoiz += tempOnoise; + data->inNoise += tempInoise; + if (((NOISEAN*)ckt->CKTcurJob)->NStpsSm != 0) { + inst->SOI3nVar[OUTNOIZ][i] += tempOnoise; + inst->SOI3nVar[OUTNOIZ][SOI3TOTNOIZ] += tempOnoise; + inst->SOI3nVar[INNOIZ][i] += tempInoise; + inst->SOI3nVar[INNOIZ][SOI3TOTNOIZ] += tempInoise; + } + } + } + } + if (data->prtSummary) { + for (i=0; i < SOI3NSRCS; i++) { /* print a summary report */ + data->outpVector[data->outNumber++] = noizDens[i]; + } + } + break; + + case INT_NOIZ: /* already calculated, just output */ + if (((NOISEAN*)ckt->CKTcurJob)->NStpsSm != 0) { + for (i=0; i < SOI3NSRCS; i++) { + data->outpVector[data->outNumber++] = inst->SOI3nVar[OUTNOIZ][i]; + data->outpVector[data->outNumber++] = inst->SOI3nVar[INNOIZ][i]; + } + } /* if */ + break; + } /* switch (mode) */ + break; + + case N_CLOSE: + return (OK); /* do nothing, the main calling routine will close */ + break; /* the plots */ + } /* switch (operation) */ + } /* for inst */ + } /* for model */ + +return(OK); +} diff --git a/src/spicelib/devices/soi3/soi3par.c b/src/spicelib/devices/soi3/soi3par.c new file mode 100644 index 000000000..efcea9b79 --- /dev/null +++ b/src/spicelib/devices/soi3/soi3par.c @@ -0,0 +1,153 @@ +/********** +STAG version 2.6 +Copyright 2000 owned by the United Kingdom Secretary of State for Defence +acting through the Defence Evaluation and Research Agency. +Developed by : Jim Benson, + Department of Electronics and Computer Science, + University of Southampton, + United Kingdom. +With help from : Nele D'Halleweyn, Bill Redman-White, and Craig Easson. + +Based on STAG version 2.1 +Developed by : Mike Lee, +With help from : Bernard Tenbroek, Bill Redman-White, Mike Uren, Chris Edwards + and John Bunyan. +Acknowledgements : Rupert Howes and Pete Mole. +**********/ + +/* Modified: 2001 Paolo Nenzi */ + +#include "ngspice.h" +#include +#include "const.h" +#include "ifsim.h" +#include "soi3defs.h" +#include "sperror.h" +#include "suffix.h" + + +/* ARGSUSED */ +int +SOI3param(param,value,inst,select) + int param; + IFvalue *value; + GENinstance *inst; + IFvalue *select; +{ + SOI3instance *here = (SOI3instance *)inst; + switch(param) { + case SOI3_L: + here->SOI3l = value->rValue; + here->SOI3lGiven = TRUE; + break; + case SOI3_W: + here->SOI3w = value->rValue; + here->SOI3wGiven = TRUE; + break; + case SOI3_NRD: + here->SOI3drainSquares = value->rValue; + here->SOI3drainSquaresGiven = TRUE; + break; + case SOI3_NRS: + here->SOI3sourceSquares = value->rValue; + here->SOI3sourceSquaresGiven = TRUE; + break; + case SOI3_OFF: + here->SOI3off = value->iValue; + break; + case SOI3_IC_VDS: + here->SOI3icVDS = value->rValue; + here->SOI3icVDSGiven = TRUE; + break; + case SOI3_IC_VGFS: + here->SOI3icVGFS = value->rValue; + here->SOI3icVGFSGiven = TRUE; + break; + case SOI3_IC_VGBS: + here->SOI3icVGBS = value->rValue; + here->SOI3icVGBSGiven = TRUE; + break; + case SOI3_IC_VBS: + here->SOI3icVBS = value->rValue; + here->SOI3icVBSGiven = TRUE; + break; + case SOI3_TEMP: + here->SOI3temp = value->rValue+CONSTCtoK; + here->SOI3tempGiven = TRUE; + break; + case SOI3_RT: + here->SOI3rt = value->rValue; + here->SOI3rtGiven = TRUE; + break; + case SOI3_CT: + here->SOI3ct = value->rValue; + here->SOI3ctGiven = TRUE; + break; + case SOI3_RT1: + here->SOI3rt1 = value->rValue; + here->SOI3rt1Given = TRUE; + break; + case SOI3_CT1: + here->SOI3ct1 = value->rValue; + here->SOI3ct1Given = TRUE; + break; + case SOI3_RT2: + here->SOI3rt2 = value->rValue; + here->SOI3rt2Given = TRUE; + break; + case SOI3_CT2: + here->SOI3ct2 = value->rValue; + here->SOI3ct2Given = TRUE; + break; + case SOI3_RT3: + here->SOI3rt3 = value->rValue; + here->SOI3rt3Given = TRUE; + break; + case SOI3_CT3: + here->SOI3ct3 = value->rValue; + here->SOI3ct3Given = TRUE; + break; + case SOI3_RT4: + here->SOI3rt4 = value->rValue; + here->SOI3rt4Given = TRUE; + break; + case SOI3_CT4: + here->SOI3ct4 = value->rValue; + here->SOI3ct4Given = TRUE; + break; + case SOI3_IC: + switch(value->v.numValue){ + case 4: + here->SOI3icVBS = *(value->v.vec.rVec+3); + here->SOI3icVBSGiven = TRUE; + case 3: + here->SOI3icVGBS = *(value->v.vec.rVec+2); + here->SOI3icVGBSGiven = TRUE; + case 2: + here->SOI3icVGFS = *(value->v.vec.rVec+1); + here->SOI3icVGFSGiven = TRUE; + case 1: + here->SOI3icVDS = *(value->v.vec.rVec); + here->SOI3icVDSGiven = TRUE; + break; + default: + return(E_BADPARM); + } + break; +/* case SOI3_L_SENS: + if(value->iValue) { + here->SOI3senParmNo = 1; + here->SOI3sens_l = 1; + } + break; + case SOI3_W_SENS: + if(value->iValue) { + here->SOI3senParmNo = 1; + here->SOI3sens_w = 1; + } + break; */ + default: + return(E_BADPARM); + } + return(OK); +} diff --git a/src/spicelib/devices/soi3/soi3set.c b/src/spicelib/devices/soi3/soi3set.c new file mode 100644 index 000000000..110105663 --- /dev/null +++ b/src/spicelib/devices/soi3/soi3set.c @@ -0,0 +1,751 @@ +/********** +STAG version 2.6 +Copyright 2000 owned by the United Kingdom Secretary of State for Defence +acting through the Defence Evaluation and Research Agency. +Developed by : Jim Benson, + Department of Electronics and Computer Science, + University of Southampton, + United Kingdom. +With help from : Nele D'Halleweyn, Bill Redman-White, and Craig Easson. + +Based on STAG version 2.1 +Developed by : Mike Lee, +With help from : Bernard Tenbroek, Bill Redman-White, Mike Uren, Chris Edwards + and John Bunyan. +Acknowledgements : Rupert Howes and Pete Mole. +**********/ + +/* Modified: 2001 Paolo Nenzi */ + +#include "ngspice.h" +#include +#include "smpdefs.h" +#include "cktdefs.h" +#include "soi3defs.h" +#include "sperror.h" +#include "suffix.h" + + +int +SOI3setup(matrix,inModel,ckt,states) + SMPmatrix *matrix; + GENmodel *inModel; + CKTcircuit *ckt; + int *states; +{ + SOI3model *model = (SOI3model *)inModel; + SOI3instance *here; + int error; + CKTnode *tmp; + + /* JimB - new variable for RT and CT scaling */ + double thermal_area; + + double rtargs[5]; + double * rtptr; + int node_count; + + /****** Part 1 - set any model parameters that are not present in ******/ + /****** the netlist to default values. ******/ + + /* loop through all the SOI3 device models */ + for( ; model != NULL; model = model->SOI3nextModel ) { + + if(!model->SOI3typeGiven) { + model->SOI3type = NSOI3; + } + if(!model->SOI3latDiffGiven) { + model->SOI3latDiff = 0; + } + if(!model->SOI3jctSatCurDensityGiven) { + model->SOI3jctSatCurDensity = 1.0e-10; + } + if(!model->SOI3jctSatCurDensity1Given) { + model->SOI3jctSatCurDensity1 = 0.0; + } + if(!model->SOI3jctSatCurGiven) { + model->SOI3jctSatCur = 0.0; + } + if(!model->SOI3jctSatCur1Given) { + model->SOI3jctSatCur1 = 0.0; + } + if(!model->SOI3transconductanceGiven) { + model->SOI3transconductance = 2e-5; + } + if(!model->SOI3frontGateSourceOverlapCapFactorGiven) { + model->SOI3frontGateSourceOverlapCapFactor = 0; + } + if(!model->SOI3frontGateDrainOverlapCapFactorGiven) { + model->SOI3frontGateDrainOverlapCapFactor = 0; + } + if(!model->SOI3frontGateBulkOverlapCapFactorGiven) { + model->SOI3frontGateBulkOverlapCapFactor = 0; + } + if(!model->SOI3backGateSourceOverlapCapFactorGiven) { + model->SOI3backGateSourceOverlapCapFactor = 0; + } + if(!model->SOI3backGateDrainOverlapCapFactorGiven) { + model->SOI3backGateDrainOverlapCapFactor = 0; + } + if(!model->SOI3backGateBulkOverlapCapFactorGiven) { + model->SOI3backGateBulkOverlapCapFactor = 0; + } + if(!model->SOI3sideWallCapFactorGiven) { + model->SOI3sideWallCapFactor = 0; + } + if(!model->SOI3bulkJctPotentialGiven) { + model->SOI3bulkJctPotential = 0.8; + } + if(!model->SOI3bulkJctSideGradingCoeffGiven) { + model->SOI3bulkJctSideGradingCoeff = 0.5; + } + if(!model->SOI3fwdCapDepCoeffGiven) { + model->SOI3fwdCapDepCoeff = 0.5; + } + if(!model->SOI3lambdaGiven) { + model->SOI3lambda = 0; + } + if(!model->SOI3thetaGiven) { + model->SOI3theta = 0; + } + /* JimB - If SiO2 thermal conductivity given in netlist then use */ + /* that value, otherwise use literature value. (Units W/K*m). */ + if(!model->SOI3oxideThermalConductivityGiven) { + model->SOI3oxideThermalConductivity = 1.4; + } + /* JimB - If Si specific heat given in netlist then use that value, */ + /* otherwise use literature value. (Units J/kg*K). */ + if(!model->SOI3siliconSpecificHeatGiven) { + model->SOI3siliconSpecificHeat = 700; + } + /* JimB - If density of Si given in netlist then use that value, */ + /* otherwise use literature value. (kg/m^3). */ + if(!model->SOI3siliconDensityGiven) { + model->SOI3siliconDensity = 2330; + } + if(!model->SOI3frontFixedChargeDensityGiven) { + model->SOI3frontFixedChargeDensity = 0; + } + if(!model->SOI3backFixedChargeDensityGiven) { + model->SOI3backFixedChargeDensity = 0; + } + if(!model->SOI3frontSurfaceStateDensityGiven) { + model->SOI3frontSurfaceStateDensity = 0; + } + if(!model->SOI3backSurfaceStateDensityGiven) { + model->SOI3backSurfaceStateDensity = 0; + } + if(!model->SOI3gammaGiven) { + model->SOI3gamma = 0; + } + if(!model->SOI3fNcoefGiven) { + model->SOI3fNcoef = 0; + } + if(!model->SOI3fNexpGiven) { + model->SOI3fNexp = 1; + } +/* extra stuff for newer model - msll Jan96 */ + if(!model->SOI3sigmaGiven) { + model->SOI3sigma = 0; + } + if(!model->SOI3chiFBGiven) { + model->SOI3chiFB = 0; + } + if(!model->SOI3chiPHIGiven) { + model->SOI3chiPHI = 0; + } + if(!model->SOI3deltaWGiven) { + model->SOI3deltaW = 0; + } + if(!model->SOI3deltaLGiven) { + model->SOI3deltaL = 0; + } + if(!model->SOI3vsatGiven) { + model->SOI3vsat = 0; /* special case - must check for it */ + } + if(!model->SOI3kGiven) { + model->SOI3k = 1.5; /* defaults to old SPICE value */ + } + if(!model->SOI3lxGiven) { + model->SOI3lx = 0; + } + if(!model->SOI3vpGiven) { + model->SOI3vp = 0; + } + if(!model->SOI3gammaBGiven) { + model->SOI3gammaB = 0; + } +/* now check to determine which CLM model to use */ + if((model->SOI3lx != 0) && (model->SOI3lambda != 0)) { + (*(SPfrontEnd->IFerror))(ERR_WARNING, + "%s: Non-zero values for BOTH LAMBDA and LX. \nDefaulting to simple LAMBDA model", + &model->SOI3modName); + model->SOI3useLAMBDA = TRUE; + } + +/* if only lx given and vp!=0, use froody model, else basic */ + if ((model->SOI3lxGiven) && (model->SOI3lx != 0) && + (!model->SOI3lambdaGiven) && (model->SOI3vp != 0)) { + model->SOI3useLAMBDA = FALSE; + } else { + model->SOI3useLAMBDA = TRUE; + } + if(!model->SOI3etaGiven) { + model->SOI3eta = 1.0; /* normal field for imp. ion. */ + } + if(!model->SOI3alpha0Given) { + model->SOI3alpha0=0; + } + if(!model->SOI3beta0Given) { + model->SOI3beta0=1.92e6; + } + if(!model->SOI3lmGiven) { + model->SOI3lm = 0; + } + if(!model->SOI3lm1Given) { + model->SOI3lm1 = 0; + } + if(!model->SOI3lm2Given) { + model->SOI3lm2 = 0; + } + if((!model->SOI3etadGiven) || (model->SOI3etad == 0 )) { + model->SOI3etad = 1.0; + } + if((!model->SOI3etad1Given) || (model->SOI3etad1 == 0 )) { + model->SOI3etad1 = 1.0; + } + if(!model->SOI3chibetaGiven) { + model->SOI3chibeta = 0.0; + } + if(!model->SOI3dvtGiven) { + model->SOI3dvt = 1; + } + if(!model->SOI3nLevGiven) { + model->SOI3nLev = 0; + } + if(!model->SOI3betaBJTGiven) { + model->SOI3betaBJT = 0.0; + } + if(!model->SOI3tauFBJTGiven) { + model->SOI3tauFBJT = 0.0; + } + if(!model->SOI3tauRBJTGiven) { + model->SOI3tauRBJT = 0.0; + } + if(!model->SOI3betaEXPGiven) { + model->SOI3betaEXP = 2.0; + } + if(!model->SOI3tauEXPGiven) { + model->SOI3tauEXP = 0.0; + } + if(!model->SOI3rswGiven) { + model->SOI3rsw = 0.0; + } + if(!model->SOI3rdwGiven) { + model->SOI3rdw = 0.0; + } + if(!model->SOI3minimumFeatureSizeGiven) { + model->SOI3minimumFeatureSize = 0.0; + } + if(!model->SOI3vtexGiven) { + model->SOI3vtex = 0.0; + } + if(!model->SOI3vdexGiven) { + model->SOI3vdex = 0.0; + } + if(!model->SOI3delta0Given) { + model->SOI3delta0 = 0.0; + } + if(!model->SOI3satChargeShareFactorGiven) { + model->SOI3satChargeShareFactor = 0.5; + } + if(!model->SOI3nplusDopingGiven) { + model->SOI3nplusDoping = 1e20; + } + if(!model->SOI3rtaGiven) { + model->SOI3rta = 0; + } + if(!model->SOI3ctaGiven) { + model->SOI3cta = 0; + } + + + /****** Part 2 - set any instance parameters that are not present ******/ + /****** in the netlist to default values. ******/ + + /* loop through all the instances of the model */ + for (here = model->SOI3instances; here != NULL ; + here=here->SOI3nextInstance) { + + CKTnode *tmpNode; + IFuid tmpName; + + + + if(!here->SOI3icVBSGiven) { + here->SOI3icVBS = 0; + } + if(!here->SOI3icVDSGiven) { + here->SOI3icVDS = 0; + } + if(!here->SOI3icVGFSGiven) { + here->SOI3icVGFS = 0; + } + if(!here->SOI3icVGBSGiven) { + here->SOI3icVGBS = 0; + } + if(!here->SOI3drainSquaresGiven || here->SOI3drainSquares==0) { + here->SOI3drainSquares=1; + } + if(!here->SOI3sourceSquaresGiven || here->SOI3sourceSquares==0) { + here->SOI3sourceSquares=1; + } + + /****** Part 3 - Initialise transconductances. ******/ + + /* initialise gM's */ + here->SOI3iMdb= 0.0; + here->SOI3iMsb= 0.0; + here->SOI3gMmbs = 0.0; + here->SOI3gMmf = 0.0; + here->SOI3gMmb = 0.0; + here->SOI3gMd = 0.0; + here->SOI3gMdeltaT = 0.0; + /* allocate a chunk of the state vector */ + here->SOI3states = *states; + *states += SOI3numStates; +/* if(ckt->CKTsenInfo && (ckt->CKTsenInfo->SENmode & TRANSEN) ){ + *states += 10 * (ckt->CKTsenInfo->SENparms); + } +*/ + + /****** Part 4 - check resistance values for internal nodes, ******/ + /****** to see which internal nodes need to be created. ******/ + + /* Start with internal source and drain nodes */ + + if((model->SOI3drainResistance != 0 + || (model->SOI3sheetResistance != 0 && + here->SOI3drainSquares != 0) + || model->SOI3rdw != 0) + && here->SOI3dNodePrime == 0) + { + error = CKTmkVolt(ckt,&tmp,here->SOI3name,"drain"); + if(error) + { + return(error); + } + here->SOI3dNodePrime = tmp->number; + + if (ckt->CKTcopyNodesets) { + if (CKTinst2Node(ckt,here,1,&tmpNode,&tmpName)==OK) { + if (tmpNode->nsGiven) { + tmp->nodeset=tmpNode->nodeset; + tmp->nsGiven=tmpNode->nsGiven; + } + } + } + + } + else + { + here->SOI3dNodePrime = here->SOI3dNode; + } + + if((model->SOI3sourceResistance != 0 || + (model->SOI3sheetResistance != 0 && + here->SOI3sourceSquares != 0) || + model->SOI3rsw != 0) && + here->SOI3sNodePrime==0) + { + error = CKTmkVolt(ckt,&tmp,here->SOI3name,"source"); + if(error) + { + return(error); + } + here->SOI3sNodePrime = tmp->number; + + if (ckt->CKTcopyNodesets) { + if (CKTinst2Node(ckt,here,1,&tmpNode,&tmpName)==OK) { + if (tmpNode->nsGiven) { + tmp->nodeset=tmpNode->nodeset; + tmp->nsGiven=tmpNode->nsGiven; + } + } + } + + + } + else + { + here->SOI3sNodePrime = here->SOI3sNode; + } + + /* Now for thermal node */ + + /* JimB - If minimum feature size has non-zero value, then this */ + /* will be used to calculate thermal area of SiO2 - this gives */ + /* more accurate values of RT for short-channel devices. Assume*/ + /* 4*fmin added to L, and 2*fmin added to W (fmin in microns). */ + thermal_area = (here->SOI3w + 2*1e-6*model->SOI3minimumFeatureSize) + * (here->SOI3l + 4*1e-6*model->SOI3minimumFeatureSize); + + /* Now calculate RT and CT. */ + + /* If RT is given on instance line, use it, otherwise calculate from */ + /* above variables. */ + if (!here->SOI3rtGiven) + { + if (model->SOI3rtaGiven) + { + here->SOI3rt = model->SOI3rta/thermal_area; + } + else + { + if (model->SOI3oxideThermalConductivity != 0) + { + here->SOI3rt = model->SOI3backOxideThickness / + (model->SOI3oxideThermalConductivity * thermal_area); + } + else + /* If conductivity set to zero in netlist, switch off self-heating. */ + { + here->SOI3rt = 0; + } + } + } + if (!here->SOI3rt1Given) + { + here->SOI3rt1=0; + } + if (!here->SOI3rt2Given) + { + here->SOI3rt2=0; + } + if (!here->SOI3rt3Given) + { + here->SOI3rt3=0; + } + if (!here->SOI3rt4Given) + { + here->SOI3rt4=0; + } + + /* Now same thing for CT, but less complex as CT=0 does not cause problems */ + if (!here->SOI3ctGiven) + { + if (model->SOI3ctaGiven) + { + here->SOI3ct = model->SOI3cta*thermal_area; + } + else + { + here->SOI3ct = model->SOI3siliconDensity * model->SOI3siliconSpecificHeat * + thermal_area * model->SOI3bodyThickness; + } + } + if (!here->SOI3ct1Given) + { + here->SOI3ct1=0; + } + if (!here->SOI3ct2Given) + { + here->SOI3ct2=0; + } + if (!here->SOI3ct3Given) + { + here->SOI3ct3=0; + } + if (!here->SOI3ct4Given) + { + here->SOI3ct4=0; + } + + /* JimB - 15/9/99 */ + rtargs[0]=here->SOI3rt; + rtargs[1]=here->SOI3rt1; + rtargs[2]=here->SOI3rt2; + rtargs[3]=here->SOI3rt3; + rtargs[4]=here->SOI3rt4; + rtptr = rtargs; /* Set pointer to start address of rtargs array. */ + node_count=0; + + while ( (*rtptr) && (node_count<5) ) + { + node_count++; + if (node_count<5) + { + rtptr++; /* Increment pointer to next array element. */ + } + } + here->SOI3numThermalNodes=node_count; + + /* Thermal node is now external and so is automatically created by CKTcreate in INP2A. + It is also bound to the created node's number. However, if rt=0 then no thermal so + make tout be the thermal ground. Can't simply use CKTbindNode 'cos the row and column + associated with the original node has already been created. Thus problems will occur + during pivoting. Instead put zero voltage source here. First create branch for it.*/ + + if ((here->SOI3rt == 0) && (here->SOI3branch == 0)) + { + error = CKTmkCur(ckt,&tmp,here->SOI3name,"branch"); + + if(error) + { + return(error); + } + here->SOI3branch = tmp->number; + + if (ckt->CKTcopyNodesets) { + if (CKTinst2Node(ckt,here,1,&tmpNode,&tmpName)==OK) { + if (tmpNode->nsGiven) { + tmp->nodeset=tmpNode->nodeset; + tmp->nsGiven=tmpNode->nsGiven; + } + } + } + + } + else + { /* have thermal - now how many time constants ? */ + if ((here->SOI3numThermalNodes > 1) && + (here->SOI3tout1Node == 0)) + { + error = CKTmkVolt(ckt,&tmp,here->SOI3name,"tout1"); + if (error) return (error); + here->SOI3tout1Node = tmp->number; + + if (ckt->CKTcopyNodesets) { + if (CKTinst2Node(ckt,here,1,&tmpNode,&tmpName)==OK) { + if (tmpNode->nsGiven) { + tmp->nodeset=tmpNode->nodeset; + tmp->nsGiven=tmpNode->nsGiven; + } + } + } + + + } + else + { + here->SOI3tout1Node = 0; + } + if ((here->SOI3numThermalNodes > 2) && + (here->SOI3tout2Node == 0)) + { + error = CKTmkVolt(ckt,&tmp,here->SOI3name,"tout2"); + if (error) return (error); + here->SOI3tout2Node = tmp->number; + + if (ckt->CKTcopyNodesets) { + if (CKTinst2Node(ckt,here,1,&tmpNode,&tmpName)==OK) { + if (tmpNode->nsGiven) { + tmp->nodeset=tmpNode->nodeset; + tmp->nsGiven=tmpNode->nsGiven; + } + } + } + + + } + else + { + here->SOI3tout2Node = 0; + } + if ((here->SOI3numThermalNodes > 3) && + (here->SOI3tout3Node == 0)) + { + error = CKTmkVolt(ckt,&tmp,here->SOI3name,"tout3"); + if (error) return (error); + here->SOI3tout3Node = tmp->number; + + if (ckt->CKTcopyNodesets) { + if (CKTinst2Node(ckt,here,1,&tmpNode,&tmpName)==OK) { + if (tmpNode->nsGiven) { + tmp->nodeset=tmpNode->nodeset; + tmp->nsGiven=tmpNode->nsGiven; + } + } + } + + + + } + else + { + here->SOI3tout3Node = 0; + } + if ((here->SOI3numThermalNodes > 4) && + (here->SOI3tout4Node == 0)) + { + error = CKTmkVolt(ckt,&tmp,here->SOI3name,"tout4"); + if (error) return (error); + here->SOI3tout4Node = tmp->number; + + if (ckt->CKTcopyNodesets) { + if (CKTinst2Node(ckt,here,1,&tmpNode,&tmpName)==OK) { + if (tmpNode->nsGiven) { + tmp->nodeset=tmpNode->nodeset; + tmp->nsGiven=tmpNode->nsGiven; + } + } + } + + } + else + { + here->SOI3tout4Node = 0; + } + } + + +/****** Part 5 - allocate memory to matrix elements corresponding to ******/ +/****** pairs of nodes. ******/ + +/* macro to make elements with built in test for out of memory */ + +#define TSTALLOC(ptr,first,second) \ +if((here->ptr = SMPmakeElt(matrix,here->first,here->second))==(double *)NULL){\ + return(E_NOMEM);\ +} + + TSTALLOC(SOI3D_dPtr,SOI3dNode,SOI3dNode) + TSTALLOC(SOI3GF_gfPtr,SOI3gfNode,SOI3gfNode) + TSTALLOC(SOI3S_sPtr,SOI3sNode,SOI3sNode) + TSTALLOC(SOI3GB_gbPtr,SOI3gbNode,SOI3gbNode) + TSTALLOC(SOI3B_bPtr,SOI3bNode,SOI3bNode) + TSTALLOC(SOI3DP_dpPtr,SOI3dNodePrime,SOI3dNodePrime) + TSTALLOC(SOI3SP_spPtr,SOI3sNodePrime,SOI3sNodePrime) + TSTALLOC(SOI3D_dpPtr,SOI3dNode,SOI3dNodePrime) + TSTALLOC(SOI3GF_bPtr,SOI3gfNode,SOI3bNode) + TSTALLOC(SOI3GF_dpPtr,SOI3gfNode,SOI3dNodePrime) + TSTALLOC(SOI3GF_spPtr,SOI3gfNode,SOI3sNodePrime) + TSTALLOC(SOI3GB_bPtr,SOI3gbNode,SOI3bNode) + TSTALLOC(SOI3GB_dpPtr,SOI3gbNode,SOI3dNodePrime) + TSTALLOC(SOI3GB_spPtr,SOI3gbNode,SOI3sNodePrime) + TSTALLOC(SOI3S_spPtr,SOI3sNode,SOI3sNodePrime) + TSTALLOC(SOI3B_dpPtr,SOI3bNode,SOI3dNodePrime) + TSTALLOC(SOI3B_spPtr,SOI3bNode,SOI3sNodePrime) + TSTALLOC(SOI3DP_spPtr,SOI3dNodePrime,SOI3sNodePrime) + TSTALLOC(SOI3DP_dPtr,SOI3dNodePrime,SOI3dNode) + TSTALLOC(SOI3B_gfPtr,SOI3bNode,SOI3gfNode) + TSTALLOC(SOI3DP_gfPtr,SOI3dNodePrime,SOI3gfNode) + TSTALLOC(SOI3SP_gfPtr,SOI3sNodePrime,SOI3gfNode) + TSTALLOC(SOI3B_gbPtr,SOI3bNode,SOI3gbNode) + TSTALLOC(SOI3DP_gbPtr,SOI3dNodePrime,SOI3gbNode) + TSTALLOC(SOI3SP_gbPtr,SOI3sNodePrime,SOI3gbNode) + TSTALLOC(SOI3SP_sPtr,SOI3sNodePrime,SOI3sNode) + TSTALLOC(SOI3DP_bPtr,SOI3dNodePrime,SOI3bNode) + TSTALLOC(SOI3SP_bPtr,SOI3sNodePrime,SOI3bNode) + TSTALLOC(SOI3SP_dpPtr,SOI3sNodePrime,SOI3dNodePrime) + + if (here->SOI3rt == 0) + { + TSTALLOC(SOI3TOUT_ibrPtr,SOI3toutNode,SOI3branch) + TSTALLOC(SOI3IBR_toutPtr,SOI3branch,SOI3toutNode) + } + else + { + TSTALLOC(SOI3TOUT_toutPtr,SOI3toutNode,SOI3toutNode) + if (here->SOI3numThermalNodes > 1) + { + TSTALLOC(SOI3TOUT_tout1Ptr,SOI3toutNode,SOI3tout1Node) + TSTALLOC(SOI3TOUT1_toutPtr,SOI3tout1Node,SOI3toutNode) + TSTALLOC(SOI3TOUT1_tout1Ptr,SOI3tout1Node,SOI3tout1Node) + } + if (here->SOI3numThermalNodes > 2) + { + TSTALLOC(SOI3TOUT1_tout2Ptr,SOI3tout1Node,SOI3tout2Node) + TSTALLOC(SOI3TOUT2_tout1Ptr,SOI3tout2Node,SOI3tout1Node) + TSTALLOC(SOI3TOUT2_tout2Ptr,SOI3tout2Node,SOI3tout2Node) + } + if (here->SOI3numThermalNodes > 3) + { + TSTALLOC(SOI3TOUT2_tout3Ptr,SOI3tout2Node,SOI3tout3Node) + TSTALLOC(SOI3TOUT3_tout2Ptr,SOI3tout3Node,SOI3tout2Node) + TSTALLOC(SOI3TOUT3_tout3Ptr,SOI3tout3Node,SOI3tout3Node) + } + if (here->SOI3numThermalNodes > 4) + { + TSTALLOC(SOI3TOUT3_tout4Ptr,SOI3tout3Node,SOI3tout4Node) + TSTALLOC(SOI3TOUT4_tout3Ptr,SOI3tout4Node,SOI3tout3Node) + TSTALLOC(SOI3TOUT4_tout4Ptr,SOI3tout4Node,SOI3tout4Node) + } + + TSTALLOC(SOI3TOUT_toutPtr,SOI3toutNode,SOI3toutNode) + TSTALLOC(SOI3TOUT_dpPtr,SOI3toutNode,SOI3dNodePrime) + TSTALLOC(SOI3TOUT_gfPtr,SOI3toutNode,SOI3gfNode) + TSTALLOC(SOI3TOUT_gbPtr,SOI3toutNode,SOI3gbNode) + TSTALLOC(SOI3TOUT_bPtr,SOI3toutNode,SOI3bNode) + TSTALLOC(SOI3TOUT_spPtr,SOI3toutNode,SOI3sNodePrime) + + TSTALLOC(SOI3GF_toutPtr,SOI3gfNode,SOI3toutNode) + TSTALLOC(SOI3DP_toutPtr,SOI3dNodePrime,SOI3toutNode) + TSTALLOC(SOI3SP_toutPtr,SOI3sNodePrime,SOI3toutNode) + + TSTALLOC(SOI3B_toutPtr,SOI3bNode,SOI3toutNode) + } + } + } + return(OK); +} + +/* JimB - SIMetrix is based on SPICE3e2. Since */ +/* unsetup is a SPICE3f5 function, only use it in */ +/* the standard version */ + +int +SOI3unsetup(inModel,ckt) + GENmodel *inModel; + CKTcircuit *ckt; +{ + SOI3model *model; + SOI3instance *here; + + for (model = (SOI3model *)inModel; model != NULL; + model = model->SOI3nextModel) + { + for (here = model->SOI3instances; here != NULL; + here=here->SOI3nextInstance) + { + if (here->SOI3dNodePrime + && here->SOI3dNodePrime != here->SOI3dNode) + { + CKTdltNNum(ckt, here->SOI3dNodePrime); + here->SOI3dNodePrime= 0; + } + if (here->SOI3sNodePrime + && here->SOI3sNodePrime != here->SOI3sNode) + { + CKTdltNNum(ckt, here->SOI3sNodePrime); + here->SOI3sNodePrime= 0; + } + if (here->SOI3branch) + { + CKTdltNNum(ckt, here->SOI3branch); + here->SOI3branch=0; + } + if (here->SOI3tout1Node) + { + CKTdltNNum(ckt, here->SOI3tout1Node); + here->SOI3tout1Node = 0; + } + if (here->SOI3tout2Node) + { + CKTdltNNum(ckt, here->SOI3tout2Node); + here->SOI3tout2Node = 0; + } + if (here->SOI3tout3Node) + { + CKTdltNNum(ckt, here->SOI3tout3Node); + here->SOI3tout3Node = 0; + } + if (here->SOI3tout4Node) + { + CKTdltNNum(ckt, here->SOI3tout4Node); + here->SOI3tout4Node = 0; + } + } + } + return OK; +} diff --git a/src/spicelib/devices/soi3/soi3temp.c b/src/spicelib/devices/soi3/soi3temp.c new file mode 100644 index 000000000..8304fa95f --- /dev/null +++ b/src/spicelib/devices/soi3/soi3temp.c @@ -0,0 +1,597 @@ +/********** +STAG version 2.6 +Copyright 2000 owned by the United Kingdom Secretary of State for Defence +acting through the Defence Evaluation and Research Agency. +Developed by : Jim Benson, + Department of Electronics and Computer Science, + University of Southampton, + United Kingdom. +With help from : Nele D'Halleweyn, Bill Redman-White, and Craig Easson. + +Based on STAG version 2.1 +Developed by : Mike Lee, +With help from : Bernard Tenbroek, Bill Redman-White, Mike Uren, Chris Edwards + and John Bunyan. +Acknowledgements : Rupert Howes and Pete Mole. +**********/ + +/* Modified: 2001 Paolo Nenzi */ + +#include "ngspice.h" +#include +#include "cktdefs.h" +#include "soi3defs.h" +#include "const.h" +#include "sperror.h" +#include "suffix.h" + + +int +SOI3temp(inModel,ckt) + GENmodel *inModel; + CKTcircuit *ckt; +{ + SOI3model *model = (SOI3model *)inModel; + SOI3instance *here; + +/* All variables ending in 1 denote that they pertain to the model + and so use model->SOI3tnom for temperature - the others use + here->SOI3temp. REFTEMP is temp at which hard-coded quantities + are given. */ + + double egfet,egfet1; /* Band Gap */ + double fact1,fact2; /* temperature/REFTEMP */ + double kt,kt1; /* kT @ various temps */ + double arg1; /* ??? */ + double ratio,ratio4; /* (temp/tnom) and (temp/tnom)^(3/2) */ + double phio; /* temp adjusted phi PHI0*/ + double pbo; + double gmanew,gmaold; + double capfact; + double pbfact1,pbfact; /* ??? */ + double vt,vtnom; + double wkfngfs; /* work function difference phi(gate,Si) */ + double wkfngf; /* work fn of front gate */ + double wkfngbs; /* work fn diff of back gate = 0 usu. */ + double fermig; /* fermi level of gate */ + double fermis; /* fermi level of Si */ + double xd_max; /* Minimum Si film thickness for this model to be valid */ + double eta_s; + + /* JimB - new variables for improved threshold voltage conversion model. */ + + double Edelta0; + double psi_delta0; + + /* loop through all the transistor models */ + for( ; model != NULL; model = model->SOI3nextModel) + { + + /* perform model defaulting */ + if(!model->SOI3tnomGiven) + { + model->SOI3tnom = ckt->CKTnomTemp; + } + + fact1 = model->SOI3tnom/REFTEMP; + vtnom = model->SOI3tnom*CONSTKoverQ; + kt1 = CONSTboltz * model->SOI3tnom; + egfet1 = 1.16-(7.02e-4*model->SOI3tnom*model->SOI3tnom)/ + (model->SOI3tnom+1108); + arg1 = -egfet1/(kt1+kt1)+1.1150877/(CONSTboltz*(REFTEMP+REFTEMP)); + /* this is -Egnom + Egref. - sign due to it being in bracket with log(fact1) + 'cos we wanted log(1/fact1). */ + pbfact1 = -2*vtnom *(1.5*log(fact1)+CHARGE*arg1); + /* 2 comes from fact phi=2*phi_F + ^ */ + + /* now model parameter preprocessing */ + + if(!model->SOI3frontOxideThicknessGiven || + model->SOI3frontOxideThickness == 0 || + !model->SOI3backOxideThicknessGiven || + model->SOI3backOxideThickness == 0 || + !model->SOI3bodyThicknessGiven || + model->SOI3bodyThickness == 0) + { + (*(SPfrontEnd->IFerror))(ERR_FATAL, + "%s: SOI3 device film thickness must be supplied", + &model->SOI3modName); + return(E_BADPARM); + } + else /* Oxide and film thicknesses are supplied. */ + { + model->SOI3frontOxideCapFactor = 3.9 * 8.854214871e-12/ + model->SOI3frontOxideThickness; + model->SOI3backOxideCapFactor = 3.9 * 8.854214871e-12/ + model->SOI3backOxideThickness; + model->SOI3bodyCapFactor = 11.7 * 8.854214871e-12/ + model->SOI3bodyThickness; + model->SOI3C_ssf = CHARGE*model->SOI3frontSurfaceStateDensity*1e4; + model->SOI3C_ssb = CHARGE*model->SOI3backSurfaceStateDensity*1e4; + eta_s = 1 + model->SOI3C_ssf/model->SOI3frontOxideCapFactor; + + if(!model->SOI3transconductanceGiven) + { + if(!model->SOI3surfaceMobilityGiven) + { + model->SOI3surfaceMobility=600; + } + model->SOI3transconductance = model->SOI3surfaceMobility * + model->SOI3frontOxideCapFactor * 1e-4 /*(m**2/cm**2) + for mobility */; + } + + if(model->SOI3substrateDopingGiven) + { /* work everything out */ + if(model->SOI3substrateDoping*1e6 /*(cm**3/m**3)*/ >1.45e16) + { + if(!model->SOI3phiGiven) + { + model->SOI3phi = 2*vtnom* + log(model->SOI3substrateDoping* + 1e6/*(cm**3/m**3)*//1.45e16); + model->SOI3phi = MAX(0.1,model->SOI3phi); + } +/* Now that we have ascertained both the doping * + * and the body film thickness, check to see * + * if we have a thick film device. If not, complain ! */ + xd_max=2*sqrt((2* 11.7 * 8.854214871e-12 * model->SOI3phi)/ + (CHARGE*1e6 /*(cm**3/m**3)*/ * model->SOI3substrateDoping)); + + if(model->SOI3bodyThickness < xd_max) + { + (*(SPfrontEnd->IFerror))(ERR_WARNING, + "%s: Body Film thickness may be too small \nfor this model to be valid", + &model->SOI3modName); + /* return(E_PAUSE); don't want to stop, + just issue a warning */ + } +/* End of thick film check - msll 21/2/94 + Changed to only give warning - msll 31/10/95 */ + if(!model->SOI3vfbFGiven) + { + if(!model->SOI3frontFixedChargeDensityGiven) + model->SOI3frontFixedChargeDensity = 0; + fermis = model->SOI3type * 0.5 * model->SOI3phi; + wkfngf = 3.2; + if(!model->SOI3gateTypeGiven) model->SOI3gateType=1; + if(model->SOI3gateType != 0) + { + fermig = model->SOI3type *model->SOI3gateType*0.5*egfet1; + wkfngf = 3.25 + 0.5 * egfet1 - fermig; + } + wkfngfs = wkfngf - (3.25 + 0.5 * egfet1 +fermis); + + /* Fixed oxide charge is normally +ve for both + n and p-channel, so need -ve voltage to neutralise it */ + model->SOI3vfbF = wkfngfs - + model->SOI3frontFixedChargeDensity * + 1e4 /*(cm**2/m**2)*/ * + CHARGE/model->SOI3frontOxideCapFactor; + } + if(!model->SOI3vfbBGiven) + { + wkfngbs = (1-model->SOI3type)*0.5*model->SOI3phi; + /* assume p-sub */ + model->SOI3vfbB = wkfngbs - + model->SOI3backFixedChargeDensity * + 1e4 /*(cm**2/m**2)*/ * + CHARGE/model->SOI3backOxideCapFactor; + } + + if(!model->SOI3gammaGiven) + { + model->SOI3gamma = sqrt(2 * 11.70 * 8.854214871e-12 * + CHARGE * model->SOI3substrateDoping * + 1e6 /*(cm**3/m**3)*/)/model->SOI3frontOxideCapFactor; + } + + if(!model->SOI3gammaBGiven) + { + model->SOI3gammaB = sqrt(2 * 11.70 * 8.854214871e-12 * + CHARGE * model->SOI3substrateDoping * + 1e6 /*(cm**3/m**3)*/)/model->SOI3backOxideCapFactor; + } + if(model->SOI3vt0Given) + { /* NSUB given AND VT0 given - change vfbF */ + model->SOI3vfbF = model->SOI3vt0 - model->SOI3type * + (eta_s*model->SOI3phi + + model->SOI3gamma*sqrt(model->SOI3phi)); + } + else + { + if(model->SOI3vtexGiven) + { /* JimB - Improved threshold voltage conversion model. */ + if (model->SOI3delta0 < 0) + { + model->SOI3delta0 = 0; + } + if (model->SOI3vdex < 0) + { + /* Use convention that Vd at which Vtex was extracted */ + /* is always +ve. */ + model->SOI3vdex = -model->SOI3vdex; + } + /* Exponential term delta*phiF/phit (SOI3phi = 2phiF) */ + Edelta0 = exp(MIN(MAX_EXP_ARG, + (model->SOI3delta0*model->SOI3phi)/(2*vtnom)) + ); + /* Modified surface potential term (2+delta)*phiF + vdex/2 */ + /* (SOI3phi = 2phiF) */ + psi_delta0 = ((2+model->SOI3delta0)*model->SOI3phi/2) + + model->SOI3vdex/2; + model->SOI3vfbF = model->SOI3vtex - model->SOI3type * + (eta_s*psi_delta0 + model->SOI3gamma* + sqrt(psi_delta0 + vtnom*Edelta0) + ); + } + } + } + else /* Substrate doping less than intrinsic silicon, so set to zero. */ + { + model->SOI3substrateDoping = 0; + (*(SPfrontEnd->IFerror))(ERR_FATAL, + "%s: Nsub < Ni",&model->SOI3modName); + return(E_BADPARM); + } + } + else /* NSUB not given, have to assume that VT0, PHI and GAMMA are given */ + { + xd_max=(2* 11.7 * 8.854214871e-12*sqrt(model->SOI3phi))/ + (model->SOI3gamma*model->SOI3frontOxideCapFactor); + if(model->SOI3bodyThickness < xd_max) + { + (*(SPfrontEnd->IFerror))(ERR_WARNING, + "%s :Body Film thickness may be too small \nfor this model to be valid", + &model->SOI3modName); + /* return(E_PAUSE); */ + } +/* End of thick film check - msll 21/2/94 + Changed to only give warning - msll 31/10/95 */ + + /* If vtext given in netlist, but no vt0. */ + if( (model->SOI3vtexGiven) && (!model->SOI3vt0Given) ) + { /* JimB - Improved threshold voltage conversion model. */ + if (model->SOI3delta0 < 0) + { + model->SOI3delta0 = 0; + } + if (model->SOI3vdex < 0) + { + /* Use convention that Vd at which Vtex was extracted */ + /* is always +ve. */ + model->SOI3vdex = -model->SOI3vdex; + } + /* Exponential term delta*phiF/phit (SOI3phi = 2phiF) */ + Edelta0 = exp(MIN(MAX_EXP_ARG, + (model->SOI3delta0*model->SOI3phi)/(2*vtnom)) + ); + /* Modified surface potential term (2+delta)*phiF + vdex/2 */ + /* (SOI3phi = 2phiF) */ + psi_delta0 = ((2+model->SOI3delta0)*model->SOI3phi/2) + + model->SOI3vdex/2; + model->SOI3vfbF = model->SOI3vtex - model->SOI3type * + (eta_s*psi_delta0 + model->SOI3gamma* + sqrt(psi_delta0 + vtnom*Edelta0) + ); + } + else /* If no vtex, then use vt0, either netlist or default value. */ + { /* Use standard threshold voltage model. */ + model->SOI3vfbF = model->SOI3vt0 - model->SOI3type * + (eta_s*model->SOI3phi + model->SOI3gamma*sqrt(model->SOI3phi)); + } + if (!model->SOI3vfbBGiven) + { + model->SOI3vfbB = 0; /* NSUB not given, vfbB not given */ + } + } + } + if((model->SOI3vsatGiven)&&(model->SOI3vsat != 0)) + { + model->SOI3TVF0 = 0.8*exp(model->SOI3tnom/600); + } + else + { + model->SOI3TVF0 = 0; + } + + + /* loop through all instances of the model */ + for(here = model->SOI3instances; here!= NULL; + here = here->SOI3nextInstance) + { + + double czbd; /* zero voltage bulk-drain capacitance */ + double czbs; /* zero voltage bulk-source capacitance */ + double cj0; /* default value of zero voltage bulk-source/drain capacitance*/ + double Nratio; /* ratio of Nsub*Nplus/Nsub+Nplus */ + double arg; /* 1 - fc */ + double sarg; /* (1-fc) ^^ (-mj) */ + + /* perform the parameter defaulting */ + if(!here->SOI3tempGiven) + { + here->SOI3temp = ckt->CKTtemp; + } + vt = here->SOI3temp * CONSTKoverQ; + ratio = here->SOI3temp/model->SOI3tnom; + fact2 = here->SOI3temp/REFTEMP; + kt = here->SOI3temp * CONSTboltz; + egfet = 1.16-(7.02e-4*here->SOI3temp*here->SOI3temp)/ + (here->SOI3temp+1108); + if (!model->SOI3chidGiven) + { + model->SOI3chid = CHARGE*egfet/CONSTboltz; + } + if (!model->SOI3chid1Given) + { + model->SOI3chid1 = CHARGE*egfet/CONSTboltz; + } + arg = -egfet/(kt+kt)+1.1150877/(CONSTboltz*(REFTEMP+REFTEMP)); + pbfact = -2*vt *(1.5*log(fact2)+CHARGE*arg); + + if(!here->SOI3lGiven) + { + here->SOI3l = ckt->CKTdefaultMosL; + } + if(!here->SOI3wGiven) + { + here->SOI3w = ckt->CKTdefaultMosW; + } + + if(here->SOI3l - 2 * model->SOI3latDiff <=0) + { + (*(SPfrontEnd->IFerror))(ERR_WARNING, + "%s: Effective channel length less than zero \nIncreasing \ + this instance length by 2*LD to remove effect of LD", + &(here->SOI3name)); + here->SOI3l += 2*model->SOI3latDiff; + } + ratio4 = exp(model->SOI3k*log(ratio)); /* ratio4 = (temp/tnom)^k */ + /* i.e. mobilitites prop to */ + /* T^-(k) where k=1.5 for old SPICE */ + here->SOI3tTransconductance = model->SOI3transconductance / ratio4; + here->SOI3tSurfMob = model->SOI3surfaceMobility/ratio4; + phio= (model->SOI3phi-pbfact1)/fact1; /* this is PHI @ REFTEMP */ + here->SOI3tPhi = fact2 * phio + pbfact; + here->SOI3tVfbF = model->SOI3vfbF + + (model->SOI3type * model->SOI3gateType * 0.5*(egfet1-egfet)) + + (model->SOI3type * 0.5 * (model->SOI3phi - here->SOI3tPhi)); + here->SOI3tVfbB = model->SOI3vfbB + + (1-model->SOI3type)*0.5*(here->SOI3tPhi-model->SOI3phi); + + here->SOI3tVto = here->SOI3tVfbF + model->SOI3type * + (model->SOI3gamma * sqrt(here->SOI3tPhi) + eta_s*here->SOI3tPhi); + + here->SOI3tSatCur = model->SOI3jctSatCur* + exp(-egfet/vt+egfet1/vtnom); + here->SOI3tSatCur1 = model->SOI3jctSatCur1* + exp(-egfet/vt+egfet1/vtnom); + here->SOI3tSatCurDens = model->SOI3jctSatCurDensity * + exp(-egfet/vt+egfet1/vtnom); + here->SOI3tSatCurDens1 = model->SOI3jctSatCurDensity1 * + exp(-egfet/vt+egfet1/vtnom); + + pbo = (model->SOI3bulkJctPotential - pbfact1)/fact1; + gmaold = (model->SOI3bulkJctPotential-pbo)/pbo; + capfact = 1/(1+model->SOI3bulkJctSideGradingCoeff* + (4e-4*(model->SOI3tnom-REFTEMP)-gmaold)); + here->SOI3tCbd = model->SOI3capBD * capfact; + here->SOI3tCbs = model->SOI3capBS * capfact; + here->SOI3tCjsw = model->SOI3sideWallCapFactor * capfact; + here->SOI3tBulkPot = fact2 * pbo+pbfact; + gmanew = (here->SOI3tBulkPot-pbo)/pbo; + capfact = (1+model->SOI3bulkJctSideGradingCoeff* + (4e-4*(here->SOI3temp-REFTEMP)-gmanew)); + here->SOI3tCbd *= capfact; + here->SOI3tCbs *= capfact; + here->SOI3tCjsw *= capfact; + here->SOI3tDepCap = model->SOI3fwdCapDepCoeff * here->SOI3tBulkPot; + + if (here->SOI3tSatCurDens == 0) + { + if (here->SOI3tSatCur == 0) + { + here->SOI3sourceVcrit = here->SOI3drainVcrit = + vt*log(vt/(CONSTroot2*1.0e-15)); + } + else + { + here->SOI3sourceVcrit = here->SOI3drainVcrit = + vt*log(vt/(CONSTroot2*here->SOI3tSatCur)); + } + } + else + { + here->SOI3drainVcrit = + vt * log( vt / (CONSTroot2 * + here->SOI3tSatCurDens * (here->SOI3w))); + here->SOI3sourceVcrit = + vt * log( vt / (CONSTroot2 * + here->SOI3tSatCurDens * (here->SOI3w))); + } + + if(model->SOI3capBDGiven) + { + czbd = here->SOI3tCbd; + } + else + { + if(model->SOI3sideWallCapFactorGiven) + { + czbd = here->SOI3tCjsw * (here->SOI3w*model->SOI3bodyThickness); + } + /* JimB - 2/1/99. Calculate default value for Cj0 */ + /* using PN junction theory. */ + else + { + Nratio = (1e6*model->SOI3nplusDoping * model->SOI3substrateDoping)/ + (model->SOI3nplusDoping + model->SOI3substrateDoping); + cj0 = sqrt((Nratio * 11.7 * 8.854214871e-12 * CHARGE)/ + (2 * here->SOI3tBulkPot)); + + /* JimB - temperature dependence code */ + gmaold = (model->SOI3bulkJctPotential-pbo)/pbo; + capfact = 1/(1+model->SOI3bulkJctSideGradingCoeff* + (4e-4*(model->SOI3tnom-REFTEMP)-gmaold)); + cj0 *= capfact; + gmanew = (here->SOI3tBulkPot-pbo)/pbo; + capfact = (1+model->SOI3bulkJctSideGradingCoeff* + (4e-4*(here->SOI3temp-REFTEMP)-gmanew)); + cj0 *= capfact; + + czbd = cj0 * (here->SOI3w*model->SOI3bodyThickness); + } + } + + arg = 1-model->SOI3fwdCapDepCoeff; + sarg = exp( (-model->SOI3bulkJctSideGradingCoeff) * log(arg) ); + here->SOI3Cbd = czbd; + here->SOI3f2d = czbd*(1-model->SOI3fwdCapDepCoeff* + (1+model->SOI3bulkJctSideGradingCoeff))* + sarg/arg; + here->SOI3f3d = czbd * model->SOI3bulkJctSideGradingCoeff * sarg/arg / + here->SOI3tBulkPot; + here->SOI3f4d = czbd*here->SOI3tBulkPot*(1-arg*sarg)/ + (1-model->SOI3bulkJctSideGradingCoeff) + -here->SOI3f3d/2* + (here->SOI3tDepCap*here->SOI3tDepCap) + -here->SOI3tDepCap * here->SOI3f2d; + + if(model->SOI3capBSGiven) + { + czbs=here->SOI3tCbs; + } + else + { + if(model->SOI3sideWallCapFactorGiven) + { + czbs=here->SOI3tCjsw * (here->SOI3w*model->SOI3bodyThickness); + } + /* JimB - 2/1/99. Calculate default value for Cj0 */ + /* using PN junction theory. */ + else + { + Nratio = (1e6*model->SOI3nplusDoping * model->SOI3substrateDoping)/ + (model->SOI3nplusDoping + model->SOI3substrateDoping); + cj0 = sqrt((Nratio * 11.7 * 8.854214871e-12 * CHARGE)/ + (2 * here->SOI3tBulkPot)); + + /* JimB - temperature dependence code */ + gmaold = (model->SOI3bulkJctPotential-pbo)/pbo; + capfact = 1/(1+model->SOI3bulkJctSideGradingCoeff* + (4e-4*(model->SOI3tnom-REFTEMP)-gmaold)); + cj0 *= capfact; + gmanew = (here->SOI3tBulkPot-pbo)/pbo; + capfact = (1+model->SOI3bulkJctSideGradingCoeff* + (4e-4*(here->SOI3temp-REFTEMP)-gmanew)); + cj0 *= capfact; + + czbs = cj0 * (here->SOI3w*model->SOI3bodyThickness); + } + } + arg = 1-model->SOI3fwdCapDepCoeff; + sarg = exp( (-model->SOI3bulkJctSideGradingCoeff) * log(arg) ); + here->SOI3Cbs = czbs; + here->SOI3f2s = czbs*(1-model->SOI3fwdCapDepCoeff* + (1+model->SOI3bulkJctSideGradingCoeff))* + sarg/arg; + here->SOI3f3s = czbs * model->SOI3bulkJctSideGradingCoeff * sarg/arg / + here->SOI3tBulkPot; + here->SOI3f4s = czbs*here->SOI3tBulkPot*(1-arg*sarg)/ + (1-model->SOI3bulkJctSideGradingCoeff) + -here->SOI3f3s/2* + (here->SOI3tDepCap*here->SOI3tDepCap) + -here->SOI3tDepCap * here->SOI3f2s; + + if(model->SOI3drainResistanceGiven) + { + if(model->SOI3drainResistance != 0) + { + here->SOI3drainConductance = 1/model->SOI3drainResistance; + } + else + { + here->SOI3drainConductance = 0; + } + } + else if (model->SOI3sheetResistanceGiven) + { + if(model->SOI3sheetResistance != 0) + { + here->SOI3drainConductance = + 1/(model->SOI3sheetResistance*here->SOI3drainSquares); + } + else + { + here->SOI3drainConductance = 0; + } + } + else if(model->SOI3rdwGiven) + { + if (model->SOI3rdw != 0) + { + /* JimB - 1e6 multiplying factor converts W from m to microns */ + here->SOI3drainConductance = + (here->SOI3w/model->SOI3rdw)*1e6; + } + else + { + here->SOI3drainConductance = 0; + } + } + else + { + here->SOI3drainConductance = 0; + } + + if(model->SOI3sourceResistanceGiven) + { + if(model->SOI3sourceResistance != 0) + { + here->SOI3sourceConductance = 1/model->SOI3sourceResistance; + } + else + { + here->SOI3sourceConductance = 0; + } + } + else if (model->SOI3sheetResistanceGiven) + { + if(model->SOI3sheetResistance != 0) + { + here->SOI3sourceConductance = + 1/(model->SOI3sheetResistance*here->SOI3sourceSquares); + } + else + { + here->SOI3sourceConductance = 0; + } + } + else if(model->SOI3rswGiven) + { + if (model->SOI3rsw != 0) + { + /* JimB - 1e6 multiplying factor converts W from m to microns */ + here->SOI3sourceConductance = + (here->SOI3w/model->SOI3rsw)*1e6; + } + else + { + here->SOI3sourceConductance = 0; + } + } + else + { + here->SOI3sourceConductance = 0; + } +/* extra stuff for newer model - msll Jan96 */ + } /* finish looping through all instances of the model*/ + } /* finish looping through all the transistor models */ + return(OK); +} + + + + diff --git a/src/spicelib/devices/soi3/soi3trun.c b/src/spicelib/devices/soi3/soi3trun.c new file mode 100644 index 000000000..43fb72c03 --- /dev/null +++ b/src/spicelib/devices/soi3/soi3trun.c @@ -0,0 +1,47 @@ +/********** +STAG version 2.6 +Copyright 2000 owned by the United Kingdom Secretary of State for Defence +acting through the Defence Evaluation and Research Agency. +Developed by : Jim Benson, + Department of Electronics and Computer Science, + University of Southampton, + United Kingdom. +With help from : Nele D'Halleweyn, Bill Redman-White, and Craig Easson. + +Based on STAG version 2.1 +Developed by : Mike Lee, +With help from : Bernard Tenbroek, Bill Redman-White, Mike Uren, Chris Edwards + and John Bunyan. +Acknowledgements : Rupert Howes and Pete Mole. +**********/ + +/* Modified: 2001 Paolo Nenzi */ + +#include "ngspice.h" +#include +#include "cktdefs.h" +#include "soi3defs.h" +#include "sperror.h" +#include "suffix.h" + + +int +SOI3trunc(inModel,ckt,timeStep) + GENmodel *inModel; + register CKTcircuit *ckt; + double *timeStep; +{ + register SOI3model *model = (SOI3model *)inModel; + register SOI3instance *here; + + for( ; model != NULL; model = model->SOI3nextModel) + { + for(here=model->SOI3instances;here!=NULL;here = here->SOI3nextInstance) + { + CKTterr(here->SOI3qgf,ckt,timeStep); + CKTterr(here->SOI3qd,ckt,timeStep); + CKTterr(here->SOI3qs,ckt,timeStep); + } + } + return(OK); +}