From a2ba74bcace6c4045e0704b25eb7000383008f7b Mon Sep 17 00:00:00 2001 From: pnenzi Date: Wed, 25 Apr 2001 17:50:50 +0000 Subject: [PATCH] Added three new devices from macspice3f4 (A. Wilson). These devices are not yet in a usable state. They seems to be partial porting. --- src/spicelib/devices/hfet1/Makefile.am | 29 + src/spicelib/devices/hfet1/hfet.c | 120 +++ src/spicelib/devices/hfet1/hfetacl.c | 88 +++ src/spicelib/devices/hfet1/hfetask.c | 132 ++++ src/spicelib/devices/hfet1/hfetdefs.h | 466 +++++++++++ src/spicelib/devices/hfet1/hfetdel.c | 39 + src/spicelib/devices/hfet1/hfetdest.c | 31 + src/spicelib/devices/hfet1/hfetext.h | 34 + src/spicelib/devices/hfet1/hfetgetic.c | 37 + src/spicelib/devices/hfet1/hfetinit.c | 65 ++ src/spicelib/devices/hfet1/hfetinit.h | 13 + src/spicelib/devices/hfet1/hfetitf.h | 7 + src/spicelib/devices/hfet1/hfetload.c | 787 +++++++++++++++++++ src/spicelib/devices/hfet1/hfetmask.c | 245 ++++++ src/spicelib/devices/hfet1/hfetmdel.c | 45 ++ src/spicelib/devices/hfet1/hfetmpar.c | 290 +++++++ src/spicelib/devices/hfet1/hfetparam.c | 60 ++ src/spicelib/devices/hfet1/hfetsetup.c | 432 +++++++++++ src/spicelib/devices/hfet1/hfettemp.c | 96 +++ src/spicelib/devices/hfet1/hfettrunc.c | 26 + src/spicelib/devices/hfet2/Makefile.am | 29 + src/spicelib/devices/hfet2/hfet2.c | 94 +++ src/spicelib/devices/hfet2/hfet2acl.c | 64 ++ src/spicelib/devices/hfet2/hfet2ask.c | 132 ++++ src/spicelib/devices/hfet2/hfet2defs.h | 318 ++++++++ src/spicelib/devices/hfet2/hfet2del.c | 39 + src/spicelib/devices/hfet2/hfet2dest.c | 32 + src/spicelib/devices/hfet2/hfet2ext.h | 38 + src/spicelib/devices/hfet2/hfet2getic.c | 32 + src/spicelib/devices/hfet2/hfet2init.c | 65 ++ src/spicelib/devices/hfet2/hfet2init.h | 13 + src/spicelib/devices/hfet2/hfet2itf.h | 7 + src/spicelib/devices/hfet2/hfet2load.c | 456 +++++++++++ src/spicelib/devices/hfet2/hfet2mask.c | 160 ++++ src/spicelib/devices/hfet2/hfet2mdel.c | 45 ++ src/spicelib/devices/hfet2/hfet2mpar.c | 177 +++++ src/spicelib/devices/hfet2/hfet2param.c | 60 ++ src/spicelib/devices/hfet2/hfet2setup.c | 233 ++++++ src/spicelib/devices/hfet2/hfet2temp.c | 56 ++ src/spicelib/devices/hfet2/hfet2trunc.c | 27 + src/spicelib/devices/mesa/Makefile.am | 29 + src/spicelib/devices/mesa/mesa.c | 130 ++++ src/spicelib/devices/mesa/mesaacl.c | 97 +++ src/spicelib/devices/mesa/mesaask.c | 140 ++++ src/spicelib/devices/mesa/mesadefs.h | 467 +++++++++++ src/spicelib/devices/mesa/mesadel.c | 39 + src/spicelib/devices/mesa/mesadest.c | 35 + src/spicelib/devices/mesa/mesaext.h | 37 + src/spicelib/devices/mesa/mesagetic.c | 41 + src/spicelib/devices/mesa/mesainit.c | 65 ++ src/spicelib/devices/mesa/mesainit.h | 13 + src/spicelib/devices/mesa/mesaitf.h | 9 + src/spicelib/devices/mesa/mesaload.c | 987 ++++++++++++++++++++++++ src/spicelib/devices/mesa/mesamask.c | 223 ++++++ src/spicelib/devices/mesa/mesamdel.c | 45 ++ src/spicelib/devices/mesa/mesamparam.c | 273 +++++++ src/spicelib/devices/mesa/mesaparam.c | 69 ++ src/spicelib/devices/mesa/mesasetup.c | 417 ++++++++++ src/spicelib/devices/mesa/mesatemp.c | 177 +++++ src/spicelib/devices/mesa/mesatrunc.c | 30 + 60 files changed, 8442 insertions(+) create mode 100644 src/spicelib/devices/hfet1/Makefile.am create mode 100644 src/spicelib/devices/hfet1/hfet.c create mode 100644 src/spicelib/devices/hfet1/hfetacl.c create mode 100644 src/spicelib/devices/hfet1/hfetask.c create mode 100644 src/spicelib/devices/hfet1/hfetdefs.h create mode 100644 src/spicelib/devices/hfet1/hfetdel.c create mode 100644 src/spicelib/devices/hfet1/hfetdest.c create mode 100644 src/spicelib/devices/hfet1/hfetext.h create mode 100644 src/spicelib/devices/hfet1/hfetgetic.c create mode 100644 src/spicelib/devices/hfet1/hfetinit.c create mode 100644 src/spicelib/devices/hfet1/hfetinit.h create mode 100644 src/spicelib/devices/hfet1/hfetitf.h create mode 100644 src/spicelib/devices/hfet1/hfetload.c create mode 100644 src/spicelib/devices/hfet1/hfetmask.c create mode 100644 src/spicelib/devices/hfet1/hfetmdel.c create mode 100644 src/spicelib/devices/hfet1/hfetmpar.c create mode 100644 src/spicelib/devices/hfet1/hfetparam.c create mode 100644 src/spicelib/devices/hfet1/hfetsetup.c create mode 100644 src/spicelib/devices/hfet1/hfettemp.c create mode 100644 src/spicelib/devices/hfet1/hfettrunc.c create mode 100644 src/spicelib/devices/hfet2/Makefile.am create mode 100644 src/spicelib/devices/hfet2/hfet2.c create mode 100644 src/spicelib/devices/hfet2/hfet2acl.c create mode 100644 src/spicelib/devices/hfet2/hfet2ask.c create mode 100644 src/spicelib/devices/hfet2/hfet2defs.h create mode 100644 src/spicelib/devices/hfet2/hfet2del.c create mode 100644 src/spicelib/devices/hfet2/hfet2dest.c create mode 100644 src/spicelib/devices/hfet2/hfet2ext.h create mode 100644 src/spicelib/devices/hfet2/hfet2getic.c create mode 100644 src/spicelib/devices/hfet2/hfet2init.c create mode 100644 src/spicelib/devices/hfet2/hfet2init.h create mode 100644 src/spicelib/devices/hfet2/hfet2itf.h create mode 100644 src/spicelib/devices/hfet2/hfet2load.c create mode 100644 src/spicelib/devices/hfet2/hfet2mask.c create mode 100644 src/spicelib/devices/hfet2/hfet2mdel.c create mode 100644 src/spicelib/devices/hfet2/hfet2mpar.c create mode 100644 src/spicelib/devices/hfet2/hfet2param.c create mode 100644 src/spicelib/devices/hfet2/hfet2setup.c create mode 100644 src/spicelib/devices/hfet2/hfet2temp.c create mode 100644 src/spicelib/devices/hfet2/hfet2trunc.c create mode 100644 src/spicelib/devices/mesa/Makefile.am create mode 100644 src/spicelib/devices/mesa/mesa.c create mode 100644 src/spicelib/devices/mesa/mesaacl.c create mode 100644 src/spicelib/devices/mesa/mesaask.c create mode 100644 src/spicelib/devices/mesa/mesadefs.h create mode 100644 src/spicelib/devices/mesa/mesadel.c create mode 100644 src/spicelib/devices/mesa/mesadest.c create mode 100644 src/spicelib/devices/mesa/mesaext.h create mode 100644 src/spicelib/devices/mesa/mesagetic.c create mode 100644 src/spicelib/devices/mesa/mesainit.c create mode 100644 src/spicelib/devices/mesa/mesainit.h create mode 100644 src/spicelib/devices/mesa/mesaitf.h create mode 100644 src/spicelib/devices/mesa/mesaload.c create mode 100644 src/spicelib/devices/mesa/mesamask.c create mode 100644 src/spicelib/devices/mesa/mesamdel.c create mode 100644 src/spicelib/devices/mesa/mesamparam.c create mode 100644 src/spicelib/devices/mesa/mesaparam.c create mode 100644 src/spicelib/devices/mesa/mesasetup.c create mode 100644 src/spicelib/devices/mesa/mesatemp.c create mode 100644 src/spicelib/devices/mesa/mesatrunc.c diff --git a/src/spicelib/devices/hfet1/Makefile.am b/src/spicelib/devices/hfet1/Makefile.am new file mode 100644 index 000000000..8d5ba5c2a --- /dev/null +++ b/src/spicelib/devices/hfet1/Makefile.am @@ -0,0 +1,29 @@ +## Process this file with automake to produce Makefile.in + +pkglib_LTLIBRARIES = libhfet.la + +libhfet_la_SOURCES = \ + hfet.c \ + hfetacl.c \ + hfetask.c \ + hfetdefs.h \ + hfetdel.c \ + hfetdest.c \ + hfetext.h \ + hfetgetic.c \ + hfetinit.c \ + hfetinit.h \ + hfetitf.h \ + hfetload.c \ + hfetmask.c \ + hfetmdel.c \ + hfetmpar.c \ + hfetparam.c \ + hfetsetup.c \ + hfettemp.c \ + hfettrunc.c + + + +INCLUDES = -I$(top_srcdir)/src/include +MAINTAINERCLEANFILES = Makefile.in diff --git a/src/spicelib/devices/hfet1/hfet.c b/src/spicelib/devices/hfet1/hfet.c new file mode 100644 index 000000000..9453412dc --- /dev/null +++ b/src/spicelib/devices/hfet1/hfet.c @@ -0,0 +1,120 @@ +#include "ngspice.h" +#include +#include "ifsim.h" +#include "devdefs.h" +#include "hfetdefs.h" +#include "suffix.h" + + +IFparm HFETApTable[] = { /* parameters */ + OP("off", HFETA_OFF, IF_FLAG ,"Device initially off"), + IOP("l", HFETA_LENGTH, IF_REAL ,"Length of device"), + IOP("w", HFETA_WIDTH, IF_REAL ,"Width of device"), + IOP("icvds", HFETA_IC_VDS, IF_REAL ,"Initial D-S voltage"), + IOP("icvgs", HFETA_IC_VGS, IF_REAL ,"Initial G-S voltage"), + IOP("temp", HFETA_TEMP, IF_REAL ,"Instance temperature"), + OP("dnode", HFETA_DRAINNODE, IF_INTEGER,"Number of drain node"), + OP("gnode", HFETA_GATENODE, IF_INTEGER,"Number of gate node"), + OP("snode", HFETA_SOURCENODE, IF_INTEGER,"Number of source node"), + OP("dprimenode",HFETA_DRAINPRIMENODE, IF_INTEGER,"Number of internal drain node"), + OP("sprimenode",HFETA_SOURCEPRIMENODE,IF_INTEGER,"Number of internal source node"), + OP("vgs", HFETA_VGS, IF_REAL,"Gate-Source voltage"), + OP("vgd", HFETA_VGD, IF_REAL,"Gate-Drain voltage"), + OP("cg", HFETA_CG, IF_REAL,"Gate capacitance"), + OP("cd", HFETA_CD, IF_REAL,"Drain capacitance"), + OP("cgd", HFETA_CGD, IF_REAL,"Gate_Drain capacitance"), + OP("gm", HFETA_GM, IF_REAL,"Transconductance"), + OP("gds", HFETA_GDS, IF_REAL,"Drain-Source conductance"), + OP("ggs", HFETA_GGS, IF_REAL,"Gate-Source conductance"), + OP("ggd", HFETA_GGD, IF_REAL,"Gate-Drain conductance"), + OP("qgs", HFETA_QGS, IF_REAL,"Gate-Source charge storage"), + OP("cqgs", HFETA_CQGS, IF_REAL,"Capacitance due to gate-source charge storage"), + OP("qgd", HFETA_QGD, IF_REAL,"Gate-Drain charge storage"), + OP("cqgd", HFETA_CQGD, IF_REAL,"Capacitance due to gate-drain charge storage"), + OP("cs", HFETA_CS, IF_REAL ,"Source current"), + OP("p", HFETA_POWER, IF_REAL ,"Power dissipated by the mesfet") + +}; + +IFparm HFETAmPTable[] = { /* model parameters */ + IOP( "vt0", HFETA_MOD_VTO, IF_REAL,"Pinch-off voltage"), + IOP( "vto", HFETA_MOD_VTO, IF_REAL,"Pinch-off voltage"), + IOP( "lambda", HFETA_MOD_LAMBDA, IF_REAL,"Output conductance parameter"), + IOP( "rd", HFETA_MOD_RD, IF_REAL,"Drain ohmic resistance"), + IOP( "rs", HFETA_MOD_RS, IF_REAL,"Source ohmic resistance"), + IOP( "rg", HFETA_MOD_RG, IF_REAL,"Gate ohmic resistance"), + IOP( "rdi", HFETA_MOD_RDI, IF_REAL,"Drain ohmic resistance"), + IOP( "rsi", HFETA_MOD_RSI, IF_REAL,"Source ohmic resistance"), + IOP( "rgs", HFETA_MOD_RGS, IF_REAL,"Gate-source ohmic resistance"), + IOP( "rgd", HFETA_MOD_RGD, IF_REAL,"Gate-drain ohmic resistance"), + IOP( "ri", HFETA_MOD_RI, IF_REAL,""), + IOP( "rf", HFETA_MOD_RF, IF_REAL,""), + IOP( "eta", HFETA_MOD_ETA, IF_REAL,"Subthreshold ideality factor"), + IOP( "m", HFETA_MOD_M, IF_REAL,"Knee shape parameter"), + IOP( "mc", HFETA_MOD_MC, IF_REAL,"Knee shape parameter"), + IOP( "gamma", HFETA_MOD_GAMMA, IF_REAL,"Knee shape parameter"), + IOP( "sigma0", HFETA_MOD_SIGMA0, IF_REAL,"Threshold voltage coefficient"), + IOP( "vsigmat", HFETA_MOD_VSIGMAT,IF_REAL,""), + IOP( "vsigma", HFETA_MOD_VSIGMA, IF_REAL,""), + IOP( "mu", HFETA_MOD_MU, IF_REAL,"Moblity"), + IOP( "di", HFETA_MOD_DI, IF_REAL,"Depth of device"), + IOP( "delta", HFETA_MOD_DELTA, IF_REAL,""), + IOP( "vs", HFETA_MOD_VS, IF_REAL,"Saturation velocity"), + IOP( "nmax", HFETA_MOD_NMAX, IF_REAL,""), + IOP( "deltad", HFETA_MOD_DELTAD, IF_REAL,"Thickness correction"), + IOP( "js1d", HFETA_MOD_JS1D, IF_REAL,""), + IOP( "js2d", HFETA_MOD_JS2D, IF_REAL,""), + IOP( "js1s", HFETA_MOD_JS1S, IF_REAL,""), + IOP( "js2s", HFETA_MOD_JS2S, IF_REAL,""), + IOP( "m1d", HFETA_MOD_M1D, IF_REAL,""), + IOP( "m2d", HFETA_MOD_M2D, IF_REAL,""), + IOP( "m1s", HFETA_MOD_M1S, IF_REAL,""), + IOP( "m2s", HFETA_MOD_M2S, IF_REAL,""), + IOP( "epsi", HFETA_MOD_EPSI, IF_REAL,""), + IOP( "p", HFETA_MOD_P, IF_REAL,""), + IOP( "cm3", HFETA_MOD_CM3, IF_REAL,""), + IOP( "a1", HFETA_MOD_A1, IF_REAL,""), + IOP( "a2", HFETA_MOD_A2, IF_REAL,""), + IOP( "mv1", HFETA_MOD_MV1, IF_REAL,""), + IOP( "kappa", HFETA_MOD_KAPPA, IF_REAL,""), + IOP( "delf", HFETA_MOD_DELF, IF_REAL,""), + IOP( "fgds", HFETA_MOD_FGDS, IF_REAL,""), + IOP( "tf", HFETA_MOD_TF, IF_REAL,""), + IOP( "cds", HFETA_MOD_CDS, IF_REAL,""), + IOP( "phib", HFETA_MOD_PHIB, IF_REAL,""), + IOP( "talpha", HFETA_MOD_TALPHA, IF_REAL,""), + IOP( "mt1", HFETA_MOD_MT1, IF_REAL,""), + IOP( "mt2", HFETA_MOD_MT2, IF_REAL,""), + IOP( "ck1", HFETA_MOD_CK1, IF_REAL,""), + IOP( "ck2", HFETA_MOD_CK2, IF_REAL,""), + IOP( "cm1", HFETA_MOD_CM1, IF_REAL,""), + IOP( "cm2", HFETA_MOD_CM2, IF_REAL,""), + IOP( "astar", HFETA_MOD_ASTAR, IF_REAL,""), + IOP( "eta1", HFETA_MOD_ETA1, IF_REAL,""), + IOP( "d1", HFETA_MOD_D1, IF_REAL,""), + IOP( "vt1", HFETA_MOD_VT1, IF_REAL,""), + IOP( "eta2", HFETA_MOD_ETA2, IF_REAL,""), + IOP( "d2", HFETA_MOD_D2, IF_REAL,""), + IOP( "vt2", HFETA_MOD_VT2, IF_REAL,""), + IOP( "ggr", HFETA_MOD_GGR, IF_REAL,""), + IOP( "del", HFETA_MOD_DEL, IF_REAL,""), + IOP( "gatemod", HFETA_MOD_GATEMOD,IF_INTEGER,""), + IOP( "klambda", HFETA_MOD_KLAMBDA, IF_REAL,""), + IOP( "kmu", HFETA_MOD_KMU, IF_REAL,""), + IOP( "kvto", HFETA_MOD_KVTO, IF_REAL,""), + OP( "type", HFETA_MOD_TYPE, IF_STRING, "NHFET or PHFET"), + IOP( "nhfet", HFETA_MOD_NHFET, IF_FLAG,"N HFET device"), + IOP( "phfet", HFETA_MOD_PHFET, IF_FLAG,"P HFET device"), +}; + +char *HFETAnames[] = { + "Drain", + "Gate", + "Source" +}; + +int HFETAnSize = NUMELEMS(HFETAnames); +int HFETApTSize = NUMELEMS(HFETApTable); +int HFETAmPTSize = NUMELEMS(HFETAmPTable); +int HFETAiSize = sizeof(HFETAinstance); +int HFETAmSize = sizeof(HFETAmodel); diff --git a/src/spicelib/devices/hfet1/hfetacl.c b/src/spicelib/devices/hfet1/hfetacl.c new file mode 100644 index 000000000..859c87f56 --- /dev/null +++ b/src/spicelib/devices/hfet1/hfetacl.c @@ -0,0 +1,88 @@ + +#include "ngspice.h" +#include +#include "cktdefs.h" +#include "hfetdefs.h" +#include "sperror.h" +#include "suffix.h" + + +int +HFETAacLoad(inModel,ckt) + GENmodel *inModel; + CKTcircuit *ckt; +{ + HFETAmodel *model = (HFETAmodel*)inModel; + HFETAinstance *here; + double gm; + double gds; + double xds; + double ggs; + double xgs; + double ggd; + double xgd; + double ggspp; + double ggdpp; + double f; + + for( ; model != NULL; model = model->HFETAnextModel ) + { + for( here = model->HFETAinstances; here != NULL; + here = here->HFETAnextInstance) + { + gm = *(ckt->CKTstate0 + here->HFETAgm); + gds = *(ckt->CKTstate0 + here->HFETAgds); + xds = CDS*ckt->CKTomega; + ggs = *(ckt->CKTstate0 + here->HFETAggs); + xgs = *(ckt->CKTstate0 + here->HFETAqgs) * ckt->CKTomega; + ggd = *(ckt->CKTstate0 + here->HFETAggd); + xgd = *(ckt->CKTstate0 + here->HFETAqgd) * ckt->CKTomega; + ggspp = *(ckt->CKTstate0 + here->HFETAggspp); + ggdpp = *(ckt->CKTstate0 + here->HFETAggdpp); + if(model->HFETAkappaGiven && here->HFETAdelf != 0.0) { + f = ckt->CKTomega/2/M_PI; + gds = gds*(1+0.5*model->HFETAkappa*(1+tanh((f-here->HFETAfgds)/here->HFETAdelf))); + } + *(here->HFETAdrainDrainPtr) += model->HFETAdrainConduct; + *(here->HFETAsourceSourcePtr) += model->HFETAsourceConduct; + *(here->HFETAgatePrimeGatePrimePtr) += (ggd+ggs+ggspp+ggdpp+model->HFETAgateConduct); + *(here->HFETAdrainPrimeDrainPrimePtr) += (gds+ggd+model->HFETAdrainConduct+model->HFETAgf); + *(here->HFETAsourcePrimeSourcePrimePtr) += (gds+gm+ggs+model->HFETAsourceConduct+model->HFETAgi); + *(here->HFETAsourcePrmPrmSourcePrmPrmPtr) += (model->HFETAgi+ggspp); + *(here->HFETAdrainPrmPrmDrainPrmPrmPtr) += (model->HFETAgf+ggdpp); + *(here->HFETAdrainDrainPrimePtr) -= model->HFETAdrainConduct; + *(here->HFETAdrainPrimeDrainPtr) -= model->HFETAdrainConduct; + *(here->HFETAsourceSourcePrimePtr) -= model->HFETAsourceConduct; + *(here->HFETAsourcePrimeSourcePtr) -= model->HFETAsourceConduct; + *(here->HFETAgatePrimeDrainPrimePtr) -= ggd; + *(here->HFETAdrainPrimeGatePrimePtr) += (gm-ggd); + *(here->HFETAgatePrimeSourcePrimePtr) -= ggs; + *(here->HFETAsourcePrimeGatePrimePtr) += (-ggs-gm); + *(here->HFETAdrainPrimeSourcePrimePtr) += (-gds-gm); + *(here->HFETAsourcePrimeDrainPrimePtr) -= gds; + *(here->HFETAsourcePrimeSourcePrmPrmPtr) -= model->HFETAgi; + *(here->HFETAsourcePrmPrmSourcePrimePtr) -= model->HFETAgi; + *(here->HFETAgatePrimeSourcePrmPrmPtr) -= ggspp; + *(here->HFETAsourcePrmPrmGatePrimePtr) -= ggspp; + *(here->HFETAdrainPrimeDrainPrmPrmPtr) -= model->HFETAgf; + *(here->HFETAdrainPrmPrmDrainPrimePtr) -= model->HFETAgf; + *(here->HFETAgatePrimeDrainPrmPrmPtr) -= ggdpp; + *(here->HFETAdrainPrmPrmGatePrimePtr) -= ggdpp; + *(here->HFETAgateGatePtr) += model->HFETAgateConduct; + *(here->HFETAgateGatePrimePtr) -= model->HFETAgateConduct; + *(here->HFETAgatePrimeGatePtr) -= model->HFETAgateConduct; + *(here->HFETAgatePrimeGatePrimePtr+1) += xgd+xgs; + *(here->HFETAdrainPrmPrmDrainPrmPrmPtr+1) += xgd; + *(here->HFETAsourcePrmPrmSourcePrmPrmPtr+1) += xgs; + *(here->HFETAgatePrimeDrainPrmPrmPtr+1) -= xgd; + *(here->HFETAgatePrimeSourcePrmPrmPtr+1) -= xgs; + *(here->HFETAdrainPrmPrmGatePrimePtr+1) -= xgd; + *(here->HFETAsourcePrmPrmGatePrimePtr+1) -= xgs; + *(here->HFETAdrainPrimeDrainPrimePtr+1) += xds; + *(here->HFETAsourcePrimeSourcePrimePtr+1) += xds; + *(here->HFETAdrainPrimeSourcePrimePtr+1) -= xds; + *(here->HFETAsourcePrimeDrainPrimePtr+1) -= xds; + } + } + return(OK); +} diff --git a/src/spicelib/devices/hfet1/hfetask.c b/src/spicelib/devices/hfet1/hfetask.c new file mode 100644 index 000000000..0aa7d9822 --- /dev/null +++ b/src/spicelib/devices/hfet1/hfetask.c @@ -0,0 +1,132 @@ +/********** +Copyright 1990 Regents of the University of California. All rights reserved. +Author: 1987 Thomas L. Quarles +**********/ +/* +Imported into HFETA source: Paolo Nenzi 2001 + */ + +#include "ngspice.h" +#include +#include "cktdefs.h" +#include "devdefs.h" +#include "ifsim.h" +#include "hfetdefs.h" +#include "sperror.h" +#include "suffix.h" + + +/* ARGSUSED */ +int +HFETAask(ckt,inst,which,value,select) + CKTcircuit *ckt; + GENinstance *inst; + int which; + IFvalue *value; + IFvalue *select; +{ + HFETAinstance *here = (HFETAinstance*)inst; + static char *msg = "Current and power not available in ac analysis"; + switch(which) { + case HFETA_LENGTH: + value->rValue = here->HFETAlength; + return (OK); + case HFETA_WIDTH: + value->rValue = here->HFETAwidth; + case HFETA_IC_VDS: + value->rValue = here->HFETAicVDS; + return (OK); + case HFETA_IC_VGS: + value->rValue = here->HFETAicVGS; + return (OK); + case HFETA_OFF: + value->iValue = here->HFETAoff; + return (OK); + case HFETA_DRAINNODE: + value->iValue = here->HFETAdrainNode; + return (OK); + case HFETA_GATENODE: + value->iValue = here->HFETAgateNode; + return (OK); + case HFETA_SOURCENODE: + value->iValue = here->HFETAsourceNode; + return (OK); + case HFETA_DRAINPRIMENODE: + value->iValue = here->HFETAdrainPrimeNode; + return (OK); + case HFETA_SOURCEPRIMENODE: + value->iValue = here->HFETAsourcePrimeNode; + return (OK); + case HFETA_TEMP: + value->rValue = here->HFETAtemp; + case HFETA_VGS: + value->rValue = *(ckt->CKTstate0 + here->HFETAvgs); + return (OK); + case HFETA_VGD: + value->rValue = *(ckt->CKTstate0 + here->HFETAvgd); + return (OK); + case HFETA_CG: + value->rValue = *(ckt->CKTstate0 + here->HFETAcg); + return (OK); + case HFETA_CD: + value->rValue = *(ckt->CKTstate0 + here->HFETAcd); + return (OK); + case HFETA_CGD: + value->rValue = *(ckt->CKTstate0 + here->HFETAcgd); + return (OK); + case HFETA_GM: + value->rValue = *(ckt->CKTstate0 + here->HFETAgm); + return (OK); + case HFETA_GDS: + value->rValue = *(ckt->CKTstate0 + here->HFETAgds); + return (OK); + case HFETA_GGS: + value->rValue = *(ckt->CKTstate0 + here->HFETAggs); + return (OK); + case HFETA_GGD: + value->rValue = *(ckt->CKTstate0 + here->HFETAggd); + return (OK); + case HFETA_QGS: + value->rValue = *(ckt->CKTstate0 + here->HFETAqgs); + return (OK); + case HFETA_CQGS: + value->rValue = *(ckt->CKTstate0 + here->HFETAcqgs); + return (OK); + case HFETA_QGD: + value->rValue = *(ckt->CKTstate0 + here->HFETAqgd); + return (OK); + case HFETA_CQGD: + value->rValue = *(ckt->CKTstate0 + here->HFETAcqgd); + return (OK); + case HFETA_CS : + if (ckt->CKTcurrentAnalysis & DOING_AC) { + errMsg = MALLOC(strlen(msg)+1); + errRtn = "HFETAask"; + strcpy(errMsg,msg); + return(E_ASKCURRENT); + } else { + value->rValue = -*(ckt->CKTstate0 + here->HFETAcd); + value->rValue -= *(ckt->CKTstate0 + here->HFETAcg); + } + return(OK); + case HFETA_POWER : + if (ckt->CKTcurrentAnalysis & DOING_AC) { + errMsg = MALLOC(strlen(msg)+1); + errRtn = "HFETAask"; + strcpy(errMsg,msg); + return(E_ASKPOWER); + } else { + value->rValue = *(ckt->CKTstate0 + here->HFETAcd) * + *(ckt->CKTrhsOld + here->HFETAdrainNode); + value->rValue += *(ckt->CKTstate0 + here->HFETAcg) * + *(ckt->CKTrhsOld + here->HFETAgateNode); + value->rValue -= (*(ckt->CKTstate0+here->HFETAcd) + + *(ckt->CKTstate0 + here->HFETAcg)) * + *(ckt->CKTrhsOld + here->HFETAsourceNode); + } + return(OK); + default: + return (E_BADPARM); + } + /* NOTREACHED */ +} diff --git a/src/spicelib/devices/hfet1/hfetdefs.h b/src/spicelib/devices/hfet1/hfetdefs.h new file mode 100644 index 000000000..72ed92093 --- /dev/null +++ b/src/spicelib/devices/hfet1/hfetdefs.h @@ -0,0 +1,466 @@ +#ifndef HFETA +#define HFETA + +#include "ifsim.h" +#include "cktdefs.h" +#include "gendefs.h" +#include "complex.h" +#include "noisedef.h" + +#define HFETAnumStates 24 + +typedef struct sHFETAinstance { + struct sHFETAmodel *HFETAmodPtr; + struct sHFETAinstance *HFETAnextInstance; + IFuid HFETAname; + int HFETAowner; /* number of owner process */ + int HFETAstate; /* index into state table for this device */ + + int HFETAdrainNode; + int HFETAgateNode; + int HFETAsourceNode; + int HFETAdrainPrimeNode; + int HFETAgatePrimeNode; + int HFETAsourcePrimeNode; + int HFETAdrainPrmPrmNode; + int HFETAsourcePrmPrmNode; + double HFETAlength; + double HFETAwidth; + double HFETAicVDS; + double HFETAicVGS; + double HFETAtemp; + double HFETAtVto; + double HFETAtMu; + double HFETAtLambda; + double HFETAtLambdahf; + double *HFETAdrainDrainPrimePtr; + double *HFETAgatePrimeDrainPrimePtr; + double *HFETAgatePrimeSourcePrimePtr; + double *HFETAsourceSourcePrimePtr; + double *HFETAdrainPrimeDrainPtr; + double *HFETAdrainPrimeGatePrimePtr; + double *HFETAdrainPrimeSourcePrimePtr; + double *HFETAsourcePrimeGatePrimePtr; + double *HFETAsourcePrimeSourcePtr; + double *HFETAsourcePrimeDrainPrimePtr; + double *HFETAdrainDrainPtr; + double *HFETAgatePrimeGatePrimePtr; + double *HFETAsourceSourcePtr; + double *HFETAdrainPrimeDrainPrimePtr; + double *HFETAsourcePrimeSourcePrimePtr; + double *HFETAdrainPrmPrmDrainPrmPrmPtr; + double *HFETAdrainPrmPrmDrainPrimePtr; + double *HFETAdrainPrimeDrainPrmPrmPtr; + double *HFETAdrainPrmPrmGatePrimePtr; + double *HFETAgatePrimeDrainPrmPrmPtr; + double *HFETAsourcePrmPrmSourcePrmPrmPtr; + double *HFETAsourcePrmPrmSourcePrimePtr; + double *HFETAsourcePrimeSourcePrmPrmPtr; + double *HFETAsourcePrmPrmGatePrimePtr; + double *HFETAgatePrimeSourcePrmPrmPtr; + double *HFETAgateGatePtr; + double *HFETAgateGatePrimePtr; + double *HFETAgatePrimeGatePtr; + + +#define HFETAvgs HFETAstate +#define HFETAvgd HFETAstate+1 +#define HFETAcg HFETAstate+2 +#define HFETAcd HFETAstate+3 +#define HFETAcgd HFETAstate+4 +#define HFETAcgs HFETAstate+5 +#define HFETAgm HFETAstate+6 +#define HFETAgds HFETAstate+7 +#define HFETAggs HFETAstate+8 +#define HFETAggd HFETAstate+9 +#define HFETAqgs HFETAstate+10 +#define HFETAcqgs HFETAstate+11 +#define HFETAqgd HFETAstate+12 +#define HFETAcqgd HFETAstate+13 +#define HFETAvgspp HFETAstate+14 +#define HFETAggspp HFETAstate+15 +#define HFETAcgspp HFETAstate+16 +#define HFETAvgdpp HFETAstate+17 +#define HFETAggdpp HFETAstate+18 +#define HFETAcgdpp HFETAstate+19 +#define HFETAqds HFETAstate+20 +#define HFETAcqds HFETAstate+21 +#define HFETAgmg HFETAstate+22 +#define HFETAgmd HFETAstate+23 + + + + int HFETAoff; + unsigned HFETAlengthGiven : 1; + unsigned HFETAwidthGiven : 1; + unsigned HFETAicVDSGiven : 1; + unsigned HFETAicVGSGiven : 1; + unsigned HFETAtempGiven : 1; + int HFETAmode; + + double HFETAn0; + double HFETAn01; + double HFETAn02; + double HFETAgchi0; + double HFETAcf; + double HFETAis1d; + double HFETAis2d; + double HFETAis1s; + double HFETAis2s; + double HFETAiso; + double HFETAimax; + double HFETAvcrit; + double HFETAdelf; + double HFETAfgds; + double HFETAggrwl; + +} HFETAinstance ; + + +/* per model data */ + +typedef struct sHFETAmodel { + int HFETAmodType; + struct sHFETAmodel *HFETAnextModel; + HFETAinstance *HFETAinstances; + IFuid HFETAmodName; + int HFETAtype; + int HFETAgatemod; + + double HFETAthreshold; + double HFETAlambda; + double HFETAeta; + double HFETAm; + double HFETAmc; + double HFETAgamma; + double HFETAsigma0; + double HFETAvsigmat; + double HFETAvsigma; + double HFETAmu; + double HFETAdi; + double HFETAdelta; + double HFETAvs; + double HFETAnmax; + double HFETAdeltad; + double HFETAjs1d; + double HFETAjs2d; + double HFETAjs1s; + double HFETAjs2s; + double HFETAm1d; + double HFETAm2d; + double HFETAm1s; + double HFETAm2s; + double HFETArd; + double HFETArs; + double HFETArg; + double HFETArdi; + double HFETArsi; + double HFETArgs; + double HFETArgd; + double HFETAri; + double HFETArf; + double HFETAepsi; + double HFETAa1; + double HFETAa2; + double HFETAmv1; + double HFETAp; + double HFETAkappa; + double HFETAdelf; + double HFETAfgds; + double HFETAtf; + double HFETAcds; + double HFETAphib; + double HFETAtalpha; + double HFETAmt1; + double HFETAmt2; + double HFETAck1; + double HFETAck2; + double HFETAcm1; + double HFETAcm2; + double HFETAcm3; + double HFETAastar; + double HFETAeta1; + double HFETAd1; + double HFETAvt1; + double HFETAeta2; + double HFETAd2; + double HFETAvt2; + double HFETAggr; + double HFETAdel; + double HFETAklambda; + double HFETAkmu; + double HFETAkvto; + + double HFETAdrainConduct; + double HFETAsourceConduct; + double HFETAgateConduct; + double HFETAgi; + double HFETAgf; + double HFETAdeltaSqr; + + unsigned HFETAgatemodGiven:1; + unsigned HFETAthresholdGiven:1; + unsigned HFETAlambdaGiven:1; + unsigned HFETAetaGiven:1; + unsigned HFETAmGiven:1; + unsigned HFETAmcGiven:1; + unsigned HFETAgammaGiven:1; + unsigned HFETAsigma0Given:1; + unsigned HFETAvsigmatGiven:1; + unsigned HFETAvsigmaGiven:1; + unsigned HFETAmuGiven:1; + unsigned HFETAdiGiven:1; + unsigned HFETAdeltaGiven:1; + unsigned HFETAvsGiven:1; + unsigned HFETAnmaxGiven:1; + unsigned HFETAdeltadGiven:1; + unsigned HFETAjs1dGiven:1; + unsigned HFETAjs2dGiven:1; + unsigned HFETAjs1sGiven:1; + unsigned HFETAjs2sGiven:1; + unsigned HFETAm1dGiven:1; + unsigned HFETAm2dGiven:1; + unsigned HFETAm1sGiven:1; + unsigned HFETAm2sGiven:1; + unsigned HFETArdGiven:1; + unsigned HFETArsGiven:1; + unsigned HFETArgGiven:1; + unsigned HFETArdiGiven:1; + unsigned HFETArsiGiven:1; + unsigned HFETArgsGiven:1; + unsigned HFETArgdGiven:1; + unsigned HFETAriGiven:1; + unsigned HFETArfGiven:1; + unsigned HFETAepsiGiven:1; + unsigned HFETAa1Given:1; + unsigned HFETAa2Given:1; + unsigned HFETAmv1Given:1; + unsigned HFETApGiven:1; + unsigned HFETAkappaGiven:1; + unsigned HFETAdelfGiven:1; + unsigned HFETAfgdsGiven:1; + unsigned HFETAtfGiven:1; + unsigned HFETAcdsGiven:1; + unsigned HFETAphibGiven:1; + unsigned HFETAtalphaGiven:1; + unsigned HFETAmt1Given:1; + unsigned HFETAmt2Given:1; + unsigned HFETAck1Given:1; + unsigned HFETAck2Given:1; + unsigned HFETAcm1Given:1; + unsigned HFETAcm2Given:1; + unsigned HFETAcm3Given:1; + unsigned HFETAastarGiven:1; + unsigned HFETAeta1Given:1; + unsigned HFETAd1Given:1; + unsigned HFETAvt1Given:1; + unsigned HFETAeta2Given:1; + unsigned HFETAd2Given:1; + unsigned HFETAvt2Given:1; + unsigned HFETAggrGiven:1; + unsigned HFETAdelGiven:1; + unsigned HFETAklambdaGiven:1; + unsigned HFETAkmuGiven:1; + unsigned HFETAkvtoGiven:1; + +} HFETAmodel; + +#ifndef NHFET +#define NHFET 1 +#define PHFET -1 +#endif + +/* device parameters */ +#define HFETA_LENGTH 1 +#define HFETA_WIDTH 2 +#define HFETA_IC_VDS 3 +#define HFETA_IC_VGS 4 +#define HFETA_TEMP 5 +#define HFETA_IC 6 +#define HFETA_OFF 7 +#define HFETA_CS 8 +#define HFETA_POWER 9 + +/* model parameters */ +#define HFETA_MOD_VTO 101 +#define HFETA_MOD_LAMBDA 102 +#define HFETA_MOD_RD 103 +#define HFETA_MOD_RS 104 +#define HFETA_MOD_RG 105 +#define HFETA_MOD_RGS 106 +#define HFETA_MOD_RGD 107 +#define HFETA_MOD_RI 108 +#define HFETA_MOD_RF 109 +#define HFETA_MOD_ETA 110 +#define HFETA_MOD_M 111 +#define HFETA_MOD_MC 112 +#define HFETA_MOD_GAMMA 113 +#define HFETA_MOD_SIGMA0 114 +#define HFETA_MOD_VSIGMAT 115 +#define HFETA_MOD_VSIGMA 116 +#define HFETA_MOD_MU 117 +#define HFETA_MOD_DI 118 +#define HFETA_MOD_DELTA 119 +#define HFETA_MOD_VS 120 +#define HFETA_MOD_NMAX 121 +#define HFETA_MOD_DELTAD 122 +#define HFETA_MOD_JS1D 123 +#define HFETA_MOD_JS2D 124 +#define HFETA_MOD_JS1S 125 +#define HFETA_MOD_JS2S 126 +#define HFETA_MOD_M1D 127 +#define HFETA_MOD_M2D 128 +#define HFETA_MOD_M1S 129 +#define HFETA_MOD_M2S 130 +#define HFETA_MOD_EPSI 132 +#define HFETA_MOD_RDI 133 +#define HFETA_MOD_RSI 134 +#define HFETA_MOD_A1 135 +#define HFETA_MOD_A2 136 +#define HFETA_MOD_MV1 137 +#define HFETA_MOD_P 138 +#define HFETA_MOD_KAPPA 139 +#define HFETA_MOD_DELF 140 +#define HFETA_MOD_FGDS 141 +#define HFETA_MOD_TF 142 +#define HFETA_MOD_CDS 143 +#define HFETA_MOD_PHIB 144 +#define HFETA_MOD_TALPHA 145 +#define HFETA_MOD_MT1 146 +#define HFETA_MOD_MT2 147 +#define HFETA_MOD_CK1 148 +#define HFETA_MOD_CK2 149 +#define HFETA_MOD_CM1 150 +#define HFETA_MOD_CM2 151 +#define HFETA_MOD_CM3 152 +#define HFETA_MOD_ASTAR 153 +#define HFETA_MOD_ETA1 154 +#define HFETA_MOD_D1 155 +#define HFETA_MOD_VT1 156 +#define HFETA_MOD_ETA2 157 +#define HFETA_MOD_D2 158 +#define HFETA_MOD_VT2 159 +#define HFETA_MOD_GGR 160 +#define HFETA_MOD_DEL 161 +#define HFETA_MOD_GATEMOD 162 +#define HFETA_MOD_KLAMBDA 163 +#define HFETA_MOD_KMU 164 +#define HFETA_MOD_KVTO 165 +#define HFETA_MOD_NHFET 166 +#define HFETA_MOD_PHFET 167 +#define HFETA_MOD_TYPE 168 + +/* device questions */ + +#define HFETA_DRAINNODE 201 +#define HFETA_GATENODE 202 +#define HFETA_SOURCENODE 203 +#define HFETA_DRAINPRIMENODE 204 +#define HFETA_SOURCEPRIMENODE 205 + +#define HFETA_VGS 206 +#define HFETA_VGD 207 +#define HFETA_CG 208 +#define HFETA_CD 209 +#define HFETA_CGD 210 +#define HFETA_GM 211 +#define HFETA_GDS 212 +#define HFETA_GGS 213 +#define HFETA_GGD 214 +#define HFETA_QGS 215 +#define HFETA_CQGS 216 +#define HFETA_QGD 217 +#define HFETA_CQGD 218 + +/* model questions */ + +#define HFETA_MOD_DRAINCONDUCT 301 +#define HFETA_MOD_SOURCECONDUCT 302 +#define HFETA_MOD_DEPLETIONCAP 303 +#define HFETA_MOD_VCRIT 304 + + +#define L (here->HFETAlength) +#define W (here->HFETAwidth) +#define VTO (model->HFETAthreshold) +#define LAMBDA (model->HFETAlambda) +#define RDI (model->HFETArdi) +#define RSI (model->HFETArsi) +#define RD (model->HFETArd) +#define RS (model->HFETArs) +#define RG (model->HFETArg) +#define RF (model->HFETArf) +#define RI (model->HFETAri) +#define RGS (model->HFETArgs) +#define RGD (model->HFETArgd) +#define ETA (model->HFETAeta) +#define M (model->HFETAm) +#define MC (model->HFETAmc) +#define GAMMA (model->HFETAgamma) +#define SIGMA0 (model->HFETAsigma0) +#define VSIGMAT (model->HFETAvsigmat) +#define VSIGMA (model->HFETAvsigma) +#define MU (model->HFETAmu) +#define DI (model->HFETAdi) +#define DELTAD (model->HFETAdeltad) +#define DELTASQR (model->HFETAdeltaSqr) +#define VS (model->HFETAvs) +#define NMAX (model->HFETAnmax) +#define EPSI (model->HFETAepsi) +#define JS1D (model->HFETAjs1d) +#define JS2D (model->HFETAjs2d) +#define JS1S (model->HFETAjs1s) +#define JS2S (model->HFETAjs2s) +#define M1D (model->HFETAm1d) +#define M2D (model->HFETAm2d) +#define M1S (model->HFETAm1s) +#define M2S (model->HFETAm2s) +#define ASTAR (model->HFETAastar) +#define PHIB (model->HFETAphib) +#define TALPHA (model->HFETAtalpha) +#define MT1 (model->HFETAmt1) +#define MT2 (model->HFETAmt2) +#define CK1 (model->HFETAck1) +#define CK2 (model->HFETAck2) +#define CM1 (model->HFETAcm1) +#define CM2 (model->HFETAcm2) +#define CM3 (model->HFETAcm3) +#define A1 (model->HFETAa1) +#define A2 (model->HFETAa2) +#define MV1 (model->HFETAmv1) +#define PM (model->HFETAp) +#define CDS (model->HFETAcds) +#define ETA1 (model->HFETAeta1) +#define D1 (model->HFETAd1) +#define IN_VT1 (model->HFETAvt1) /* VT1 was defined in termios.h */ +#define ETA2 (model->HFETAeta2) +#define D2 (model->HFETAd2) +#define VT2 (model->HFETAvt2) +#define GGR (model->HFETAggr) +#define DEL (model->HFETAdel) +#define KLAMBDA (model->HFETAklambda) +#define KMU (model->HFETAkmu) +#define KVTO (model->HFETAkvto) + +#define GCHI0 (here->HFETAgchi0) +#define N0 (here->HFETAn0) +#define N01 (here->HFETAn01) +#define N02 (here->HFETAn02) +#define CF (here->HFETAcf) +#define IMAX (here->HFETAimax) +#define ISO (here->HFETAiso) +#define TEMP (here->HFETAtemp) +#define IS1D (here->HFETAis1d) +#define IS2D (here->HFETAis2d) +#define IS1S (here->HFETAis1s) +#define IS2S (here->HFETAis2s) +#define FGDS (here->HFETAfgds) +#define DELF (here->HFETAdelf) +#define GGRWL (here->HFETAggrwl) +#define TLAMBDA (here->HFETAtLambda) +#define TMU (here->HFETAtMu) +#define TVTO (here->HFETAtVto) + +#include "hfetext.h" + +#endif /*HFETA*/ diff --git a/src/spicelib/devices/hfet1/hfetdel.c b/src/spicelib/devices/hfet1/hfetdel.c new file mode 100644 index 000000000..36a69b378 --- /dev/null +++ b/src/spicelib/devices/hfet1/hfetdel.c @@ -0,0 +1,39 @@ +/********** +Copyright 1990 Regents of the University of California. All rights reserved. +Author: 1985 S. Hwang +**********/ +/* +Imported into hfeta model: Paolo Nenzi 2001 +*/ + +#include "ngspice.h" +#include +#include "hfetdefs.h" +#include "sperror.h" +#include "suffix.h" + + +int +HFETAdelete(inModel,name,inst) + GENmodel *inModel; + IFuid name; + GENinstance **inst; +{ + HFETAmodel *model = (HFETAmodel*)inModel; + HFETAinstance **fast = (HFETAinstance**)inst; + HFETAinstance **prev = NULL; + HFETAinstance *here; + + for( ; model ; model = model->HFETAnextModel) { + prev = &(model->HFETAinstances); + for(here = *prev; here ; here = *prev) { + if(here->HFETAname == name || (fast && here==*fast) ) { + *prev= here->HFETAnextInstance; + FREE(here); + return(OK); + } + prev = &(here->HFETAnextInstance); + } + } + return(E_NODEV); +} diff --git a/src/spicelib/devices/hfet1/hfetdest.c b/src/spicelib/devices/hfet1/hfetdest.c new file mode 100644 index 000000000..9869b401a --- /dev/null +++ b/src/spicelib/devices/hfet1/hfetdest.c @@ -0,0 +1,31 @@ + +#include "ngspice.h" +#include +#include "hfetdefs.h" +#include "suffix.h" + + +void +HFETAdestroy(inModel) +GENmodel **inModel; +{ + HFETAmodel **model = (HFETAmodel**)inModel; + HFETAinstance *here; + HFETAinstance *prev = NULL; + HFETAmodel *mod = *model; + HFETAmodel *oldmod = NULL; + + for( ; mod ; mod = mod->HFETAnextModel) { + if(oldmod) FREE(oldmod); + oldmod = mod; + prev = (HFETAinstance *)NULL; + for(here = mod->HFETAinstances ; here ; here = here->HFETAnextInstance) { + if(prev) FREE(prev); + prev = here; + } + if(prev) FREE(prev); + } + if(oldmod) FREE(oldmod); + *model = NULL; + return; +} diff --git a/src/spicelib/devices/hfet1/hfetext.h b/src/spicelib/devices/hfet1/hfetext.h new file mode 100644 index 000000000..c65cc3e01 --- /dev/null +++ b/src/spicelib/devices/hfet1/hfetext.h @@ -0,0 +1,34 @@ +#ifdef __STDC__ +extern int HFETAacLoad(GENmodel*,CKTcircuit*); +extern int HFETAask(CKTcircuit*,GENinstance*,int,IFvalue*,IFvalue*); +extern int HFETAdelete(GENmodel*,IFuid,GENinstance**); +extern void HFETAdestroy(GENmodel**); +extern int HFETAgetic(GENmodel*,CKTcircuit*); +extern int HFETAload(GENmodel*,CKTcircuit*); +extern int HFETAmAsk(CKTcircuit*,GENmodel*,int,IFvalue*); +extern int HFETAmDelete(GENmodel**,IFuid,GENmodel*); +extern int HFETAmParam(int,IFvalue*,GENmodel*); +extern int HFETAparam(int,IFvalue*,GENinstance*,IFvalue*); +extern int HFETAsetup(SMPmatrix*,GENmodel*,CKTcircuit*,int*); +extern int HFETAtemp(GENmodel*,CKTcircuit*); +extern int HFETAtrunc(GENmodel*,CKTcircuit*,double*); +extern int HFETAunsetup(GENmodel*,CKTcircuit*); + +#else /*stdc*/ +extern int HFETAacLoad(); +extern int HFETAask(); +extern int HFETAdelete(); +extern void HFETAdestroy(); +extern int HFETAgetic(); +extern int HFETAload(); +extern int HFETAmAsk(); +extern int HFETAmDelete(); +extern int HFETAmParam(); +extern int HFETAparam(); +extern int HFETAsetup(); +extern int HFETAtemp(); +extern int HFETAtrunc(); +extern int HFETAunsetup(); + + +#endif \ No newline at end of file diff --git a/src/spicelib/devices/hfet1/hfetgetic.c b/src/spicelib/devices/hfet1/hfetgetic.c new file mode 100644 index 000000000..30836a269 --- /dev/null +++ b/src/spicelib/devices/hfet1/hfetgetic.c @@ -0,0 +1,37 @@ + +#include "ngspice.h" +#include +#include "cktdefs.h" +#include "hfetdefs.h" +#include "sperror.h" +#include "suffix.h" + + +int +HFETAgetic(inModel,ckt) +GENmodel *inModel; +CKTcircuit *ckt; +{ + HFETAmodel *model = (HFETAmodel*)inModel; + HFETAinstance *here; + /* + * grab initial conditions out of rhs array. User specified, so use + * external nodes to get values + */ + + for( ; model ; model = model->HFETAnextModel) { + for(here = model->HFETAinstances; here ; here = here->HFETAnextInstance) { + if(!here->HFETAicVDSGiven) { + here->HFETAicVDS = + *(ckt->CKTrhs + here->HFETAdrainNode) - + *(ckt->CKTrhs + here->HFETAsourceNode); + } + if(!here->HFETAicVGSGiven) { + here->HFETAicVGS = + *(ckt->CKTrhs + here->HFETAgateNode) - + *(ckt->CKTrhs + here->HFETAsourceNode); + } + } + } + return(OK); +} diff --git a/src/spicelib/devices/hfet1/hfetinit.c b/src/spicelib/devices/hfet1/hfetinit.c new file mode 100644 index 000000000..345ce7047 --- /dev/null +++ b/src/spicelib/devices/hfet1/hfetinit.c @@ -0,0 +1,65 @@ +#include + +#include + +#include "hfetitf.h" +#include "hfetext.h" +#include "hfetinit.h" + + +SPICEdev HFETAinfo = { + { + "HFET1", + "HFET1 Model", + + &HFETAnSize, + &HFETAnSize, + HFETAnames, + + &HFETApTSize, + HFETApTable, + + &HFETAmPTSize, + HFETAmPTable, + DEV_DEFAULT + }, + + DEVparam : HFETAparam, + DEVmodParam : HFETAmParam, + DEVload : HFETAload, + DEVsetup : HFETAsetup, + DEVunsetup : HFETAunsetup, + DEVpzSetup : HFETAsetup, + DEVtemperature: HFETAtemp, + DEVtrunc : HFETAtrunc, + DEVfindBranch : NULL, + DEVacLoad : HFETAacLoad, + DEVaccept : NULL, + DEVdestroy : HFETAdestroy, + DEVmodDelete : HFETAmDelete, + DEVdelete : HFETAdelete, + DEVsetic : HFETAgetic, + DEVask : HFETAask, + DEVmodAsk : HFETAmAsk, + DEVpzLoad : NULL, + DEVconvTest : NULL, + DEVsenSetup : NULL, + DEVsenLoad : NULL, + DEVsenUpdate : NULL, + DEVsenAcLoad : NULL, + DEVsenPrint : NULL, + DEVsenTrunc : NULL, + DEVdisto : NULL, + DEVnoise : NULL, + + DEVinstSize : &HFETAiSize, + DEVmodSize : &HFETAmSize + +}; + + +SPICEdev * +get_hfeta_info(void) +{ + return &HFETAinfo; +} diff --git a/src/spicelib/devices/hfet1/hfetinit.h b/src/spicelib/devices/hfet1/hfetinit.h new file mode 100644 index 000000000..5d82bdae0 --- /dev/null +++ b/src/spicelib/devices/hfet1/hfetinit.h @@ -0,0 +1,13 @@ +#ifndef _HFETAINIT_H +#define _HFETAINIT_H + +extern IFparm HFETApTable[ ]; +extern IFparm HFETAmPTable[ ]; +extern char *HFETAnames[ ]; +extern int HFETApTSize; +extern int HFETAmPTSize; +extern int HFETAnSize; +extern int HFETAiSize; +extern int HFETAmSize; + +#endif diff --git a/src/spicelib/devices/hfet1/hfetitf.h b/src/spicelib/devices/hfet1/hfetitf.h new file mode 100644 index 000000000..cd9b3db79 --- /dev/null +++ b/src/spicelib/devices/hfet1/hfetitf.h @@ -0,0 +1,7 @@ +#ifndef DEV_HFETA +#define DEV_HFETA + +SPICEdev *get_hfeta_info(void); + +#endif + diff --git a/src/spicelib/devices/hfet1/hfetload.c b/src/spicelib/devices/hfet1/hfetload.c new file mode 100644 index 000000000..672c3a369 --- /dev/null +++ b/src/spicelib/devices/hfet1/hfetload.c @@ -0,0 +1,787 @@ +#include "ngspice.h" +#include +#include "devdefs.h" +#include "cktdefs.h" +#include "hfetdefs.h" +#include "const.h" +#include "trandefs.h" +#include "sperror.h" +#include "suffix.h" +/* +#define true 1 +#define false 0 +*/ + +//#define PHIB 0.5 +double diode(double); + +static void leak(double gmin, double vt, double v, double rs, double is1, + double is2, double m1, double m2, double *il, double *gl); + +static void hfeta(HFETAmodel *model, HFETAinstance *here, CKTcircuit *ckt, + double vgs, double vds, double *cdrain, double *gm, + double *gds, double *capgs, double *capgd, + double *cgd, double *gmg, double *gmd, + double *cgs, double *ggs); + +void Pause(void); + +int HFETAload(inModel, ckt) +GENmodel *inModel; +register CKTcircuit *ckt; +{ + register HFETAmodel *model = (HFETAmodel*)inModel; + register HFETAinstance *here; + double capgd; + double capgs; + double cd; + double cdhat; + double cdrain; + double cdreq; + double ceq; + double ceqgd; + double ceqgs; + double cg; + double cgd=0; + double cgs=0; + double cghat; + double delvds; + double delvgd; + double delvgs; + double delvgdpp=0; + double delvgspp=0; + double gds; + double geq; + double ggd=0; + double ggs=0; + double gm; + double vcrit; + double vds; + double vgd; + double vgs; + double vgs1; + double vgd1; + double vds1; + double xfact; + double temp; + double vt; + double vgspp=0; + double vgdpp=0; + double cgspp=0; + double cgdpp=0; + double ggspp=0; + double ggdpp=0; + double gmg=0; + double gmd=0; + + int inverse=FALSE; + int icheck; + int error; + + for( ; model != NULL; model = model->HFETAnextModel ) { + for (here = model->HFETAinstances; here != NULL ; + here=here->HFETAnextInstance) { + vcrit = here->HFETAvcrit; + vt = CONSTKoverQ * here->HFETAtemp; + icheck = 0; + if( ckt->CKTmode & MODEINITSMSIG) { + vgs = *(ckt->CKTstate0 + here->HFETAvgs); + vgd = *(ckt->CKTstate0 + here->HFETAvgd); + vgspp = *(ckt->CKTstate0 + here->HFETAvgspp); + vgdpp = *(ckt->CKTstate0 + here->HFETAvgdpp); + } else if (ckt->CKTmode & MODEINITTRAN) { + vgs = *(ckt->CKTstate1 + here->HFETAvgs); + vgd = *(ckt->CKTstate1 + here->HFETAvgd); + vgspp = *(ckt->CKTstate1 + here->HFETAvgspp); + vgdpp = *(ckt->CKTstate1 + here->HFETAvgdpp); + } else if ( (ckt->CKTmode & MODEINITJCT) && + (ckt->CKTmode & MODETRANOP) && + (ckt->CKTmode & MODEUIC) ) { + vds = model->HFETAtype*here->HFETAicVDS; + vgs = model->HFETAtype*here->HFETAicVGS; + vgd = vgs-vds; + vgspp = vgs; + vgdpp = vgd; + } else if ( (ckt->CKTmode & MODEINITJCT) && + (here->HFETAoff == 0) ) { + vgs = -1; + vgd = -1; + vgspp = 0; + vgdpp = 0; + } else if( (ckt->CKTmode & MODEINITJCT) || + ((ckt->CKTmode & MODEINITFIX) && (here->HFETAoff))) { + vgs = 0; + vgd = 0; + vgspp = 0; + vgdpp = 0; + } else { +#ifndef PREDICTOR + if(ckt->CKTmode & MODEINITPRED) { + xfact = ckt->CKTdelta/ckt->CKTdeltaOld[2]; + *(ckt->CKTstate0 + here->HFETAvgs) = + *(ckt->CKTstate1 + here->HFETAvgs); + vgs = (1+xfact) * *(ckt->CKTstate1 + here->HFETAvgs) - + xfact * *(ckt->CKTstate2 + here->HFETAvgs); + *(ckt->CKTstate0 + here->HFETAvgspp) = + *(ckt->CKTstate1 + here->HFETAvgspp); + vgspp = (1+xfact) * *(ckt->CKTstate1 + here->HFETAvgspp) - + xfact * *(ckt->CKTstate2 + here->HFETAvgspp); + *(ckt->CKTstate0 + here->HFETAvgd) = + *(ckt->CKTstate1 + here->HFETAvgd); + vgd = (1+xfact)* *(ckt->CKTstate1 + here->HFETAvgd) - + xfact * *(ckt->CKTstate2 + here->HFETAvgd); + *(ckt->CKTstate0 + here->HFETAvgdpp) = + *(ckt->CKTstate1 + here->HFETAvgdpp); + vgdpp = (1+xfact) * *(ckt->CKTstate1 + here->HFETAvgdpp) - + xfact * *(ckt->CKTstate2 + here->HFETAvgdpp); + *(ckt->CKTstate0 + here->HFETAcg) = + *(ckt->CKTstate1 + here->HFETAcg); + *(ckt->CKTstate0 + here->HFETAcd) = + *(ckt->CKTstate1 + here->HFETAcd); + *(ckt->CKTstate0 + here->HFETAcgd) = + *(ckt->CKTstate1 + here->HFETAcgd); + *(ckt->CKTstate0 + here->HFETAcgs) = + *(ckt->CKTstate1 + here->HFETAcgs); + *(ckt->CKTstate0 + here->HFETAcgspp) = + *(ckt->CKTstate1 + here->HFETAcgspp); + *(ckt->CKTstate0 + here->HFETAcgdpp) = + *(ckt->CKTstate1 + here->HFETAcgdpp); + *(ckt->CKTstate0 + here->HFETAgm) = + *(ckt->CKTstate1 + here->HFETAgm); + *(ckt->CKTstate0 + here->HFETAgds) = + *(ckt->CKTstate1 + here->HFETAgds); + *(ckt->CKTstate0 + here->HFETAggs) = + *(ckt->CKTstate1 + here->HFETAggs); + *(ckt->CKTstate0 + here->HFETAggspp) = + *(ckt->CKTstate1 + here->HFETAggspp); + *(ckt->CKTstate0 + here->HFETAggd) = + *(ckt->CKTstate1 + here->HFETAggd); + *(ckt->CKTstate0 + here->HFETAggdpp) = + *(ckt->CKTstate1 + here->HFETAggdpp); + *(ckt->CKTstate0 + here->HFETAgmg) = + *(ckt->CKTstate1 + here->HFETAgmg); + *(ckt->CKTstate0 + here->HFETAgmd) = + *(ckt->CKTstate1 + here->HFETAgmd); + } else { +#endif /* PREDICTOR */ + /* + * compute new nonlinear branch voltages + */ + vgs = model->HFETAtype* + (*(ckt->CKTrhsOld+ here->HFETAgatePrimeNode)- + *(ckt->CKTrhsOld+ + here->HFETAsourcePrimeNode)); + vgd = model->HFETAtype* + (*(ckt->CKTrhsOld+here->HFETAgatePrimeNode)- + *(ckt->CKTrhsOld+ + here->HFETAdrainPrimeNode)); + vgspp = model->HFETAtype* + (*(ckt->CKTrhsOld+ here->HFETAgatePrimeNode)- + *(ckt->CKTrhsOld+ + here->HFETAsourcePrmPrmNode)); + vgdpp = model->HFETAtype* + (*(ckt->CKTrhsOld+ here->HFETAgatePrimeNode)- + *(ckt->CKTrhsOld+ + here->HFETAdrainPrmPrmNode)); + +#ifndef PREDICTOR + } +#endif /* PREDICTOR */ + delvgs=vgs - *(ckt->CKTstate0 + here->HFETAvgs); + delvgd=vgd - *(ckt->CKTstate0 + here->HFETAvgd); + delvds=delvgs - delvgd; + delvgspp=vgspp - *(ckt->CKTstate0 + here->HFETAvgspp); + delvgdpp=vgdpp - *(ckt->CKTstate0 + here->HFETAvgdpp); + cghat= *(ckt->CKTstate0 + here->HFETAcg) + + *(ckt->CKTstate0 + here->HFETAgmg)*delvgs - + *(ckt->CKTstate0 + here->HFETAgmd)*delvds + + *(ckt->CKTstate0 + here->HFETAggd)*delvgd + + *(ckt->CKTstate0 + here->HFETAggs)*delvgs + + *(ckt->CKTstate0 + here->HFETAggdpp)*delvgdpp + + *(ckt->CKTstate0 + here->HFETAggspp)*delvgspp; + cdhat= *(ckt->CKTstate0 + here->HFETAcd) + + *(ckt->CKTstate0 + here->HFETAgm)*delvgs + + *(ckt->CKTstate0 + here->HFETAgds)*delvds - + *(ckt->CKTstate0 + here->HFETAggd)*delvgd - + (*(ckt->CKTstate0 + here->HFETAgmg)*delvgs - + *(ckt->CKTstate0 + here->HFETAgmd)*delvds); + /* + * bypass if solution has not changed + */ + if((ckt->CKTbypass) && + (!(ckt->CKTmode & MODEINITPRED)) && + (fabs(delvgs) < ckt->CKTreltol*MAX(fabs(vgs), + fabs(*(ckt->CKTstate0 + here->HFETAvgs)))+ + ckt->CKTvoltTol) ) + if ( (fabs(delvgd) < ckt->CKTreltol*MAX(fabs(vgd), + fabs(*(ckt->CKTstate0 + here->HFETAvgd)))+ + ckt->CKTvoltTol)) + if ( (fabs(delvgspp) < ckt->CKTreltol*MAX(fabs(vgspp), + fabs(*(ckt->CKTstate0 + here->HFETAvgspp)))+ + ckt->CKTvoltTol)) + if ( (fabs(delvgdpp) < ckt->CKTreltol*MAX(fabs(vgdpp), + fabs(*(ckt->CKTstate0 + here->HFETAvgdpp)))+ + ckt->CKTvoltTol)) + if ( (fabs(cghat-*(ckt->CKTstate0 + here->HFETAcg)) + < ckt->CKTreltol*MAX(fabs(cghat), + fabs(*(ckt->CKTstate0 + here->HFETAcg)))+ + ckt->CKTabstol) ) if ( /* hack - expression too big */ + (fabs(cdhat-*(ckt->CKTstate0 + here->HFETAcd)) + < ckt->CKTreltol*MAX(fabs(cdhat), + fabs(*(ckt->CKTstate0 + here->HFETAcd)))+ + ckt->CKTabstol) ) { + + /* we can do a bypass */ + vgs = *(ckt->CKTstate0 + here->HFETAvgs); + vgd = *(ckt->CKTstate0 + here->HFETAvgd); + vds = vgs-vgd; + vgspp = *(ckt->CKTstate0 + here->HFETAvgspp); + vgdpp = *(ckt->CKTstate0 + here->HFETAvgdpp); + cg = *(ckt->CKTstate0 + here->HFETAcg); + cd = *(ckt->CKTstate0 + here->HFETAcd); + cgd = *(ckt->CKTstate0 + here->HFETAcgd); + cgs = *(ckt->CKTstate0 + here->HFETAcgs); + cgdpp = *(ckt->CKTstate0 + here->HFETAcgdpp); + cgspp = *(ckt->CKTstate0 + here->HFETAcgspp); + gm = *(ckt->CKTstate0 + here->HFETAgm); + gds = *(ckt->CKTstate0 + here->HFETAgds); + ggs = *(ckt->CKTstate0 + here->HFETAggs); + ggd = *(ckt->CKTstate0 + here->HFETAggd); + ggdpp = *(ckt->CKTstate0 + here->HFETAggdpp); + ggspp = *(ckt->CKTstate0 + here->HFETAggspp); + gmg = *(ckt->CKTstate0 + here->HFETAgmg); + gmd = *(ckt->CKTstate0 + here->HFETAgmd); + goto load; + } + /* + * limit nonlinear branch voltages + */ + vgs = DEVfetlim(vgs,*(ckt->CKTstate0 + here->HFETAvgs),TVTO); + vgd = DEVfetlim(vgd,*(ckt->CKTstate0 + here->HFETAvgd),TVTO); + } + /* + * determine dc current and derivatives + */ + vds = vgs-vgd; + if(model->HFETAgatemod == 0) { + double arg; + double earg; + if(IS1S == 0 || IS2S == 0) { + cgs = 0; + ggs = 0; + } else + leak(ckt->CKTgmin,vt,vgs,RGS,IS1S,IS2S,M1S,M2S,&cgs,&ggs); + arg = -vgs*DEL/vt; + earg = exp(arg); + cgs += GGRWL*vgs*earg; + ggs += GGRWL*earg*(1-arg); + if(IS1D == 0 || IS2D == 0) { + cgd = 0; + ggd = 0; + } else + leak(ckt->CKTgmin,vt,vgd,RGD,IS1D,IS2D,M1D,M2D,&cgd,&ggd); + arg = -vgd*DEL/vt; + earg = exp(arg); + cgd += GGRWL*vgd*earg; + ggd += GGRWL*earg*(1-arg); + } else + ggd = 0; + if(vds < 0) { + vds = -vds; + inverse = TRUE; + } + hfeta(model,here,ckt,vds>0?vgs:vgd,vds,&cdrain,&gm,&gds,&capgs,&capgd, + &cgd,&gmg,&gmd,&cgs,&ggs); + cg = cgs+cgd; + if(inverse) { + cdrain = -cdrain; + vds = -vds; + temp = capgs; + capgs = capgd; + capgd = temp; + } + /* + * compute equivalent drain current source + */ + cd = cdrain - cgd; + if ( (ckt->CKTmode & (MODETRAN|MODEINITSMSIG)) || + ((ckt->CKTmode & MODETRANOP) && (ckt->CKTmode & MODEUIC)) ){ + /* + * charge storage elements + */ + vgs1 = *(ckt->CKTstate1 + here->HFETAvgspp); + vgd1 = *(ckt->CKTstate1 + here->HFETAvgdpp); + vds1 = *(ckt->CKTstate1 + here->HFETAvgs)- + *(ckt->CKTstate1 + here->HFETAvgd); + + if(ckt->CKTmode & MODEINITTRAN) { + *(ckt->CKTstate1 + here->HFETAqgs) = capgs*vgspp; + *(ckt->CKTstate1 + here->HFETAqgd) = capgd*vgdpp; + *(ckt->CKTstate1 + here->HFETAqds) = CDS*vds; + } + *(ckt->CKTstate0+here->HFETAqgs) = *(ckt->CKTstate1 + here->HFETAqgs) + + capgs*(vgspp-vgs1); + *(ckt->CKTstate0+here->HFETAqgd) = *(ckt->CKTstate1 + here->HFETAqgd) + + capgd*(vgdpp-vgd1); + *(ckt->CKTstate0+here->HFETAqds) = *(ckt->CKTstate1 + here->HFETAqds) + + CDS*(vds-vds1); + + /* + * store small-signal parameters + */ + if( (!(ckt->CKTmode & MODETRANOP)) || + (!(ckt->CKTmode & MODEUIC)) ) { + if(ckt->CKTmode & MODEINITSMSIG) { + *(ckt->CKTstate0 + here->HFETAqgs) = capgs; + *(ckt->CKTstate0 + here->HFETAqgd) = capgd; + *(ckt->CKTstate0 + here->HFETAqds) = CDS; + continue; /*go to 1000*/ + } + /* + * transient analysis + */ + if(ckt->CKTmode & MODEINITTRAN) { + *(ckt->CKTstate1 + here->HFETAqgs) = + *(ckt->CKTstate0 + here->HFETAqgs); + *(ckt->CKTstate1 + here->HFETAqgd) = + *(ckt->CKTstate0 + here->HFETAqgd); + *(ckt->CKTstate1 + here->HFETAqds) = + *(ckt->CKTstate0 + here->HFETAqds); + } + error = NIintegrate(ckt,&geq,&ceq,capgs,here->HFETAqgs); + if(error) return(error); + ggspp = geq; + cgspp = *(ckt->CKTstate0 + here->HFETAcqgs); + cg = cg + cgspp; + error = NIintegrate(ckt,&geq,&ceq,capgd,here->HFETAqgd); + if(error) return(error); + ggdpp = geq; + cgdpp = *(ckt->CKTstate0 + here->HFETAcqgd); + cg = cg + cgdpp; + cd = cd - cgdpp; + error = NIintegrate(ckt,&geq,&ceq,CDS,here->HFETAqds); + if(error) return(error); + gds += geq; + cd += *(ckt->CKTstate0 + here->HFETAcqds); + if (ckt->CKTmode & MODEINITTRAN) { + *(ckt->CKTstate1 + here->HFETAcqgs) = + *(ckt->CKTstate0 + here->HFETAcqgs); + *(ckt->CKTstate1 + here->HFETAcqgd) = + *(ckt->CKTstate0 + here->HFETAcqgd); + *(ckt->CKTstate1 + here->HFETAcqds) = + *(ckt->CKTstate0 + here->HFETAcqds); + } + } + } + /* + * check convergence + */ + if( (!(ckt->CKTmode & MODEINITFIX)) | (!(ckt->CKTmode & MODEUIC))) { + if( (icheck == 1) + || (fabs(cghat-cg) >= ckt->CKTreltol* + MAX(fabs(cghat),fabs(cg))+ckt->CKTabstol) || + (fabs(cdhat-cd) > ckt->CKTreltol* + MAX(fabs(cdhat),fabs(cd))+ckt->CKTabstol) + + ) { + ckt->CKTnoncon++; + ckt->CKTtroubleElt = (GENinstance *) here; + } + } + *(ckt->CKTstate0 + here->HFETAvgs) = vgs; + *(ckt->CKTstate0 + here->HFETAvgd) = vgd; + *(ckt->CKTstate0 + here->HFETAvgspp) = vgspp; + *(ckt->CKTstate0 + here->HFETAvgdpp) = vgdpp; + *(ckt->CKTstate0 + here->HFETAcg) = cg; + *(ckt->CKTstate0 + here->HFETAcd) = cd; + *(ckt->CKTstate0 + here->HFETAcgd) = cgd; + *(ckt->CKTstate0 + here->HFETAcgs) = cgs; + *(ckt->CKTstate0 + here->HFETAcgspp) = cgspp; + *(ckt->CKTstate0 + here->HFETAcgdpp) = cgdpp; + *(ckt->CKTstate0 + here->HFETAgm) = gm; + *(ckt->CKTstate0 + here->HFETAgds) = gds; + *(ckt->CKTstate0 + here->HFETAggs) = ggs; + *(ckt->CKTstate0 + here->HFETAggd) = ggd; + *(ckt->CKTstate0 + here->HFETAggspp) = ggspp; + *(ckt->CKTstate0 + here->HFETAggdpp) = ggdpp; + *(ckt->CKTstate0 + here->HFETAgmg) = gmg; + *(ckt->CKTstate0 + here->HFETAgmd) = gmd; + + /* + * load current vector + */ +load: + ceqgd = model->HFETAtype*(cgd+cgdpp-ggd*vgd-gmg*vgs-gmd*vds-ggdpp*vgdpp); + ceqgs = model->HFETAtype*(cgs + cgspp - ggs*vgs - ggspp*vgspp); + cdreq = model->HFETAtype*(cd + cgd + cgdpp - gds*vds - gm*vgs); + *(ckt->CKTrhs + here->HFETAgatePrimeNode) += (-ceqgs-ceqgd); + ceqgd = model->HFETAtype*(cgd-ggd*vgd-gmg*vgs-gmd*vds); + *(ckt->CKTrhs + here->HFETAdrainPrimeNode) += (-cdreq+ceqgd); + ceqgd = model->HFETAtype*(cgdpp-ggdpp*vgdpp); + *(ckt->CKTrhs + here->HFETAdrainPrmPrmNode) += ceqgd; + ceqgs = model->HFETAtype*(cgs-ggs*vgs); + *(ckt->CKTrhs + here->HFETAsourcePrimeNode) += (cdreq+ceqgs); + ceqgs = model->HFETAtype*(cgspp-ggspp*vgspp); + *(ckt->CKTrhs + here->HFETAsourcePrmPrmNode) += ceqgs; + + /* + * load y matrix + */ + + *(here->HFETAdrainDrainPtr) += model->HFETAdrainConduct; + *(here->HFETAsourceSourcePtr) += model->HFETAsourceConduct; + *(here->HFETAgatePrimeGatePrimePtr) += (ggd+ggs+ggspp+ggdpp+gmg+model->HFETAgateConduct); + *(here->HFETAdrainPrimeDrainPrimePtr) += (gds+ggd-gmd+model->HFETAdrainConduct+model->HFETAgf); + *(here->HFETAsourcePrimeSourcePrimePtr) += (gds+gm+ggs+model->HFETAsourceConduct+model->HFETAgi); + *(here->HFETAsourcePrmPrmSourcePrmPrmPtr) += (model->HFETAgi+ggspp); + *(here->HFETAdrainPrmPrmDrainPrmPrmPtr) += (model->HFETAgf+ggdpp); + *(here->HFETAdrainDrainPrimePtr) -= model->HFETAdrainConduct; + *(here->HFETAdrainPrimeDrainPtr) -= model->HFETAdrainConduct; + *(here->HFETAsourceSourcePrimePtr) -= model->HFETAsourceConduct; + *(here->HFETAsourcePrimeSourcePtr) -= model->HFETAsourceConduct; + *(here->HFETAgatePrimeDrainPrimePtr) += -ggd+gmd; + *(here->HFETAdrainPrimeGatePrimePtr) += (gm-ggd-gmg); + *(here->HFETAgatePrimeSourcePrimePtr) -= ggs+gmg+gmd; + *(here->HFETAsourcePrimeGatePrimePtr) += (-ggs-gm); + *(here->HFETAdrainPrimeSourcePrimePtr) += (-gds-gm+gmg+gmd); + *(here->HFETAsourcePrimeDrainPrimePtr) -= gds; + *(here->HFETAsourcePrimeSourcePrmPrmPtr) -= model->HFETAgi; + *(here->HFETAsourcePrmPrmSourcePrimePtr) -= model->HFETAgi; + *(here->HFETAgatePrimeSourcePrmPrmPtr) -= ggspp; + *(here->HFETAsourcePrmPrmGatePrimePtr) -= ggspp; + *(here->HFETAdrainPrimeDrainPrmPrmPtr) -= model->HFETAgf; + *(here->HFETAdrainPrmPrmDrainPrimePtr) -= model->HFETAgf; + *(here->HFETAgatePrimeDrainPrmPrmPtr) -= ggdpp; + *(here->HFETAdrainPrmPrmGatePrimePtr) -= ggdpp; + *(here->HFETAgateGatePtr) += model->HFETAgateConduct; + *(here->HFETAgateGatePrimePtr) -= model->HFETAgateConduct; + *(here->HFETAgatePrimeGatePtr) -= model->HFETAgateConduct; + + + } + } + return(OK); +} + + + + +static void leak(double gmin, double vt, double v, double rs, double is1, double is2, + double m1, double m2, double *il, double *gl) + +{ + + double vt1 = vt*m1; + double vt2 = vt*m2; + + if(v > -10*vt1) { + double dvdi0; + double iaprox; + double iaprox1; + double iaprox2; + double v0; + double vteff = vt1 + vt2; + double iseff = is2*pow((is1/is2),(m1/(m1+m2))); + if(rs > 0) { + double unorm = (v + rs*is1)/vt1 + log(rs*is1/vt1); + iaprox1 = vt1*diode(unorm)/rs - is1; + unorm = (v + rs*iseff)/vteff + log(rs*iseff/vteff); + iaprox2 = vteff*diode(unorm)/rs - iseff; + } else { + iaprox1 = is1*(exp(v/vt1) - 1); + iaprox2 = iseff*(exp(v/vteff) - 1); + } + if((iaprox1*iaprox2) != 0.0) + iaprox = 1./(1./iaprox1 + 1./iaprox2); + else + iaprox = 0.5*(iaprox1 + iaprox2); + + dvdi0 = rs + vt1/(iaprox+is1) + vt2/(iaprox+is2); + v0 = rs*iaprox; + v0 += vt1*log(iaprox/is1 + 1) + vt2*log(iaprox/is2 + 1); + //*il = __max(-is1,iaprox + (v - v0)/dvdi0)*0.99999; + *il = MAX(-is1,iaprox + (v - v0)/dvdi0)*0.99999; + *gl = 1./(rs + vt1/(*il+is1) + vt2/(*il+is2)); + } else { + *gl = gmin; + *il = (*gl)*v-is1; + } + +} + + + + + +static void hfeta(HFETAmodel *model, HFETAinstance *here, CKTcircuit *ckt, + double vgs, double vds, double *cdrain, double *gm, + double *gds, double *capgs, double *capgd, + double *cgd, double *gmg, double *gmd, + double *cgs, double *ggs) + +{ + + double vt; + double vgt; + double vgt0; + double sigma; + double vgte; + double isat; + double isatm; + double ns; + double nsm; + double a; + double b; + double c; + double d; + double e; + double f; + double g; + double h; + double p; + double q; + double s; + double t; + double u; + double nsc; + double nsn; + double temp; + double etavth; + double gch; + double gchi; + double gchim; + double vsate; + double vdse; + double cg1; + double cgc; + double rt; + double vl; + double delidgch; + double delgchgchi; + double delgchins; + double delnsnsm; + double delnsmvgt; + double delvgtevgt; + double delidvsate; + double delvsateisat; + double delisatisatm; + double delisatmvgte; + double delisatmgchim; + double delvsategch; + double delidvds; + double delvgtvgs; + double delvsatevgt; + + vt = CONSTKoverQ*TEMP; + etavth = ETA*vt; + vl = VS/TMU*L; + rt = RSI+RDI; + vgt0 = vgs - TVTO; + s = exp((vgt0-VSIGMAT)/VSIGMA); + sigma = SIGMA0/(1+s); + vgt = vgt0+sigma*vds; + u = 0.5*vgt/vt-1; + t = sqrt(model->HFETAdeltaSqr+u*u); + vgte = vt*(2+u+t); + b = exp(vgt/etavth); + if(model->HFETAeta2Given && model->HFETAd2Given) { + nsc = N02*exp((vgt+TVTO-VT2)/(ETA2*vt)); + nsn = 2*N0*log(1+0.5*b); + nsm = nsn*nsc/(nsn+nsc); + } else { + nsm = 2*N0*log(1+0.5*b); + } + if(nsm < 1.0e-38) { + *cdrain = 0; + *gm = 0.0; + *gds = 0.0; + *capgs = CF; + *capgd = CF; + goto cgd_calc; + } + c = pow(nsm/NMAX,GAMMA); + q = pow(1+c,1.0/GAMMA); + ns = nsm/q; + gchi = GCHI0*ns; + gch = gchi/(1+gchi*rt); + gchim = GCHI0*nsm; + h = sqrt(1+2*gchim*RSI + vgte*vgte/(vl*vl)); + p = 1+gchim*RSI+h; + isatm = gchim*vgte/p; + g = pow(isatm/IMAX,GAMMA); + isat = isatm/pow(1+g,1/GAMMA); + vsate = isat/gch; + d = pow(vds/vsate,M); + e = pow(1+d,1.0/M); + delidgch = vds*(1+TLAMBDA*vds)/e; + *cdrain = gch*delidgch; + delidvsate = (*cdrain)*d/vsate/(1+d); + delidvds = gch*(1+2*TLAMBDA*vds)/e-(*cdrain)* + pow(vds/vsate,M-1)/(vsate*(1+d)); + a = 1+gchi*rt; + delgchgchi = 1.0/(a*a); + delgchins = GCHI0; + delnsnsm = ns/nsm*(1-c/(1+c)); + delvgtevgt = 0.5*(1+u/t); + delnsmvgt = N0/etavth/(1.0/b + 0.5); + if(model->HFETAeta2Given && model->HFETAd2Given) + delnsmvgt = nsc*(nsc*delnsmvgt+nsn*nsn/(ETA2*vt))/((nsc+nsn)*(nsc+nsn)); + delvsateisat = 1.0/gch; + delisatisatm = isat/isatm*(1-g/(1+g)); + delisatmvgte = gchim*(p - vgte*vgte/(vl*vl*h))/(p*p); + delvsategch = -vsate/gch; + delisatmgchim = vgte*(p - gchim*RSI*(1+1.0/h))/(p*p); + delvgtvgs = 1-vds*SIGMA0/VSIGMA*s/((1+s)*(1+s)); + p = delgchgchi*delgchins*delnsnsm*delnsmvgt; + delvsatevgt = (delvsateisat*delisatisatm*(delisatmvgte*delvgtevgt + + delisatmgchim*GCHI0*delnsmvgt)+delvsategch*p); + g = delidgch*p + delidvsate*delvsatevgt; + *gm = g*delvgtvgs; + *gds = delidvds + g*sigma; + + // Capacitance calculations + temp = ETA1*vt; + cg1 = 1/(D1/EPSI+temp*exp(-(vgs-IN_VT1)/temp)); + cgc = W*L*(CHARGE*delnsnsm*delnsmvgt*delvgtvgs+cg1); + vdse = vds*pow(1+pow(vds/vsate,MC),-1.0/MC); + a = (vsate-vdse)/(2*vsate-vdse); + a = a*a; + temp = 2.0/3.0; + p = PM + (1-PM)*exp(-vds/vsate); + *capgs = CF+2*temp*cgc*(1-a)/(1+p); + a = vsate/(2*vsate-vdse); + a = a*a; + *capgd = CF+2*p*temp*cgc*(1-a)/(1+p); +/* + { + char buf[128]; + FILE *fp; + fp = fopen("d:\\temp\\debug.txt","at"); + sprintf(buf,"%f\t%f\t%e\t%e\n",vgs,vds,W*L*CHARGE*delnsnsm*delnsmvgt*delvgtvgs,cgc); + fputs(buf,fp); + fclose(fp); + } +*/ +cgd_calc: + + if(model->HFETAgatemod != 0) { + // Gate-drain current calculation + double vkneet; + double vmax; + double td; + double delcgdvgs; + double delcgdtd; + double deltdvdse; + double deltdvkneet; + double delvdsevmax; + double delvdsevds; + double dvdsevgs; + double dvdsevds; + double dtdvgs; + double dtdvds; + + vkneet = CK1*vsate+CK2; + vmax = CM1*vsate+CM2; + a = pow(vds/vmax,MT2); + b = pow(1+a,1/MT2); + vdse = vds/b; + c = pow(vdse/vkneet,MT1); + d = pow(1+c,1/MT1); + td = TEMP+TALPHA*vdse*vdse/d; + e = CONSTKoverQ*td*M2D; + p = PHIB/(CONSTboltz*td); + f = exp(-p); + q = (vgs-vdse)/e; + g = exp(q); + h = ISO*td*td*f*g; + *cgd = h - ISO*TEMP*TEMP*exp(-PHIB/(CONSTboltz*TEMP)); + delcgdvgs = h/e; + delcgdtd = h*(p-q+2)/td; + deltdvdse = TALPHA*vdse*(2-c/(1+c))/d; + deltdvkneet = (td-TEMP)*c/((1+c)*vkneet); + delvdsevmax = vdse*a/((1+a)*vmax); + delvdsevds = (1-a/(1+a))/b; + temp = delvsatevgt*delvgtvgs; + dvdsevgs = delvdsevmax*CM1*temp; + dtdvgs = deltdvdse*dvdsevgs+deltdvkneet*CK1*temp; + *gmg = delcgdvgs+delcgdtd*dtdvgs; + temp = delvsatevgt*sigma; + dvdsevds = delvdsevds+delvdsevmax*CM1*temp; + dtdvds = deltdvdse*dvdsevds+deltdvkneet*CK1*temp; + *gmd = -delcgdvgs*dvdsevds+delcgdtd*dtdvds; + } else { + gmg = 0; + gmd = 0; + } + + if(model->HFETAgatemod != 0) { + // Gate-source current calculation + double evgs; + double vtn = vt*M2S; + double csat = ISO*TEMP*TEMP*exp(-PHIB/(CONSTboltz*TEMP)); + if (vgs <= -5*vt) { + *ggs = -csat/vgs+ckt->CKTgmin; + *cgs = (*ggs)*vgs; + } else { + evgs = exp(vgs/vtn); + *ggs = csat*evgs/vtn+ckt->CKTgmin; + *cgs = csat*(evgs-1)+ckt->CKTgmin*vgs; + } + } + + if(model->HFETAgatemod != 0 && (A1 != 0.0 || A2 != 0.0)) { + // Correction current calculations + double vmax; + double delvdsevmax; + double delvdsevds; + double dvdsevgs; + double dvdsevds; + vmax = CM3*vsate; + a = pow(vds/vmax,MV1); + b = pow(1+a,1/MV1); + vdse = vds/b; + delvdsevmax = vdse*a/((1+a)*vmax); + delvdsevds = (1-a/(1+a))/b; + dvdsevgs = delvdsevmax*CM3*delvsatevgt*delvgtvgs; + dvdsevds = delvdsevds+delvdsevmax*CM3*delvsatevgt*sigma; + c = vgte*vdse; + d = 1+A2*c; + e = vdse*delvgtevgt; + f = A2*(*cgd); + *cdrain += A1*(d*(*cgd) - (*cgs)); + *gds += A1*(d*(*gmd)+f*(vgte*dvdsevds+e*sigma)); + *gm += A1*(d*(*gmg)+f*(vgte*dvdsevgs+e*delvgtvgs) - (*ggs)); + } + +} + + +double diode(double u) +{ + +#define U0 (-2.303) +#define A (2.221) +#define B (6.804) +#define C (1.685) + double it; + double ut; + double b; + double c; + double i; + double expu=exp(u); + + if(u <= U0) + { + it = expu*(1-expu); + }else + { + b = 0.5*(u-U0); + it = u + A*exp((U0-u)/B) - log(b+sqrt(b*b + 0.25*C*C)); + } + + ut = it + log(it); + b = u-ut; + c = 1+it; + i = it*(1 + b/c + 0.5*b*b/c/c/c); + return(i); +} diff --git a/src/spicelib/devices/hfet1/hfetmask.c b/src/spicelib/devices/hfet1/hfetmask.c new file mode 100644 index 000000000..0c942afbd --- /dev/null +++ b/src/spicelib/devices/hfet1/hfetmask.c @@ -0,0 +1,245 @@ +/********** +Copyright 1990 Regents of the University of California. All rights reserved. +Author: 1987 Thomas L. Quarles +**********/ +/* +Imported into HFETA model: Paolo Nenzi 2001 + */ + +#include "ngspice.h" +#include +#include "cktdefs.h" +#include "devdefs.h" +#include "ifsim.h" +#include "hfetdefs.h" +#include "sperror.h" +#include "suffix.h" + + +/* ARGSUSED */ +int +HFETAmAsk(ckt,inst,which,value) + CKTcircuit *ckt; + GENmodel *inst; + int which; + IFvalue *value; +{ + HFETAmodel *here = (HFETAmodel*)inst; + switch(which) { + case HFETA_MOD_VTO: + value->rValue = here->HFETAthreshold; + return (OK); + case HFETA_MOD_LAMBDA: + value->rValue = here->HFETAlambda; + return (OK); + case HFETA_MOD_RD: + value->rValue = here->HFETArd; + return (OK); + case HFETA_MOD_RS: + value->rValue = here->HFETArs; + return (OK); + case HFETA_MOD_RG: + value->rValue = here->HFETArg; + return (OK); + case HFETA_MOD_RDI: + value->rValue = here->HFETArdi; + return (OK); + case HFETA_MOD_RSI: + value->rValue = here->HFETArsi; + return (OK); + case HFETA_MOD_RGS: + value->rValue = here->HFETArgs; + return (OK); + case HFETA_MOD_RGD: + value->rValue = here->HFETArgd; + return (OK); + case HFETA_MOD_RI: + value->rValue = here->HFETAri; + return (OK); + case HFETA_MOD_RF: + value->rValue = here->HFETArf; + return (OK); + case HFETA_MOD_ETA: + value->rValue = here->HFETAeta; + return (OK); + case HFETA_MOD_M: + value->rValue = here->HFETAm; + return (OK); + case HFETA_MOD_MC: + value->rValue = here->HFETAmc; + return (OK); + case HFETA_MOD_GAMMA: + value->rValue = here->HFETAgamma; + return (OK); + case HFETA_MOD_SIGMA0: + value->rValue = here->HFETAsigma0; + return (OK); + case HFETA_MOD_VSIGMAT: + value->rValue = here->HFETAvsigmat; + return (OK); + case HFETA_MOD_VSIGMA: + value->rValue = here->HFETAvsigma; + return (OK); + case HFETA_MOD_MU: + value->rValue = here->HFETAmu; + return (OK); + case HFETA_MOD_DI: + value->rValue = here->HFETAdi; + return (OK); + case HFETA_MOD_DELTA: + value->rValue = here->HFETAdelta; + return (OK); + case HFETA_MOD_VS: + value->rValue = here->HFETAvs; + return (OK); + case HFETA_MOD_NMAX: + value->rValue = here->HFETAnmax; + return (OK); + case HFETA_MOD_DELTAD: + value->rValue = here->HFETAdeltad; + return (OK); + case HFETA_MOD_JS1D: + value->rValue = here->HFETAjs1d; + return (OK); + case HFETA_MOD_JS2D: + value->rValue = here->HFETAjs2d; + return (OK); + case HFETA_MOD_JS1S: + value->rValue = here->HFETAjs1s; + return (OK); + case HFETA_MOD_JS2S: + value->rValue = here->HFETAjs2s; + return (OK); + case HFETA_MOD_M1D: + value->rValue = here->HFETAm1d; + return (OK); + case HFETA_MOD_M2D: + value->rValue = here->HFETAm2d; + return (OK); + case HFETA_MOD_M1S: + value->rValue = here->HFETAm1s; + return (OK); + case HFETA_MOD_M2S: + value->rValue = here->HFETAm2s; + return (OK); + case HFETA_MOD_EPSI: + value->rValue = here->HFETAepsi; + return (OK); + case HFETA_MOD_P: + value->rValue = here->HFETAp; + return (OK); + case HFETA_MOD_CM3: + value->rValue = here->HFETAcm3; + return (OK); + case HFETA_MOD_A1: + value->rValue = here->HFETAa1; + return (OK); + case HFETA_MOD_A2: + value->rValue = here->HFETAa2; + return (OK); + case HFETA_MOD_MV1: + value->rValue = here->HFETAmv1; + return (OK); + case HFETA_MOD_KAPPA: + value->rValue = here->HFETAkappa; + return (OK); + case HFETA_MOD_DELF: + value->rValue = here->HFETAdelf; + return (OK); + case HFETA_MOD_FGDS: + value->rValue = here->HFETAfgds; + return (OK); + case HFETA_MOD_TF: + value->rValue = here->HFETAtf; + return (OK); + case HFETA_MOD_CDS: + value->rValue = here->HFETAcds; + return (OK); + case HFETA_MOD_PHIB: + value->rValue = here->HFETAphib; + return (OK); + + case HFETA_MOD_TALPHA: + value->rValue = here->HFETAtalpha; + return (OK); + case HFETA_MOD_MT1: + value->rValue = here->HFETAmt1; + return (OK); + case HFETA_MOD_MT2: + value->rValue = here->HFETAmt2; + return (OK); + case HFETA_MOD_CK1: + value->rValue = here->HFETAck1; + return (OK); + case HFETA_MOD_CK2: + value->rValue = here->HFETAck2; + return (OK); + case HFETA_MOD_CM1: + value->rValue = here->HFETAcm1; + return (OK); + case HFETA_MOD_CM2: + value->rValue = here->HFETAcm2; + return (OK); + case HFETA_MOD_ASTAR: + value->rValue = here->HFETAastar; + return (OK); + case HFETA_MOD_ETA1: + value->rValue = here->HFETAeta1; + return (OK); + case HFETA_MOD_D1: + value->rValue = here->HFETAd1; + return (OK); + case HFETA_MOD_VT1: + value->rValue = here->HFETAvt1; + return (OK); + case HFETA_MOD_ETA2: + value->rValue = here->HFETAeta2; + return (OK); + case HFETA_MOD_D2: + value->rValue = here->HFETAd2; + return (OK); + case HFETA_MOD_VT2: + value->rValue = here->HFETAvt2; + return (OK); + case HFETA_MOD_GGR: + value->rValue = here->HFETAggr; + return (OK); + case HFETA_MOD_DEL: + value->rValue = here->HFETAdel; + return (OK); + case HFETA_MOD_GATEMOD: + value->iValue = here->HFETAgatemod; + return (OK); + case HFETA_MOD_KLAMBDA: + value->rValue = here->HFETAklambda; + return (OK); + case HFETA_MOD_KMU: + value->rValue = here->HFETAkmu; + return (OK); + case HFETA_MOD_KVTO: + value->rValue = here->HFETAkvto; + return (OK); + + case HFETA_MOD_DRAINCONDUCT: + value->rValue = here->HFETAdrainConduct; + return (OK); + case HFETA_MOD_SOURCECONDUCT: + value->rValue = here->HFETAsourceConduct; + return (OK); + /* case HFETA_MOD_DEPLETIONCAP: + value->rValue = here->HFETA???; + return(OK); */ + /* case HFETA_MOD_VCRIT: + value->rValue = here->HFETAvcrit; + return (OK); */ + + case HFETA_MOD_TYPE: + if (here->HFETAtype == NHFET) + value->sValue = "nhfet"; + else + value->sValue = "phfet"; + default: + return (E_BADPARM); + } + /* NOTREACHED */ +} diff --git a/src/spicelib/devices/hfet1/hfetmdel.c b/src/spicelib/devices/hfet1/hfetmdel.c new file mode 100644 index 000000000..2dd7aa40e --- /dev/null +++ b/src/spicelib/devices/hfet1/hfetmdel.c @@ -0,0 +1,45 @@ +/********** +Copyright 1990 Regents of the University of California. All rights reserved. +Author: 1985 S. Hwang +**********/ +/* +Imported into hfeta model: Paolo Nenzi 2001 + */ + +#include "ngspice.h" +#include +#include "hfetdefs.h" +#include "sperror.h" +#include "suffix.h" + + +int +HFETAmDelete(inModel,modname,kill) + GENmodel **inModel; + IFuid modname; + GENmodel *kill; +{ + HFETAmodel **model = (HFETAmodel**)inModel; + HFETAmodel *modfast = (HFETAmodel*)kill; + HFETAinstance *here; + HFETAinstance *prev = NULL; + HFETAmodel **oldmod; + oldmod = model; + for( ; *model ; model = &((*model)->HFETAnextModel)) { + if( (*model)->HFETAmodName == modname || + (modfast && *model == modfast) ) goto delgot; + oldmod = model; + } + return(E_NOMOD); + +delgot: + *oldmod = (*model)->HFETAnextModel; /* cut deleted device out of list */ + for(here = (*model)->HFETAinstances ; here ; here = here->HFETAnextInstance) { + if(prev) FREE(prev); + prev = here; + } + if(prev) FREE(prev); + FREE(*model); + return(OK); + +} diff --git a/src/spicelib/devices/hfet1/hfetmpar.c b/src/spicelib/devices/hfet1/hfetmpar.c new file mode 100644 index 000000000..4a3a05b8f --- /dev/null +++ b/src/spicelib/devices/hfet1/hfetmpar.c @@ -0,0 +1,290 @@ + +#include "ngspice.h" +#include +#include "const.h" +#include "ifsim.h" +#include "hfetdefs.h" +#include "sperror.h" +#include "suffix.h" + + +int +HFETAmParam(param,value,inModel) + int param; + IFvalue *value; + GENmodel *inModel; +{ + HFETAmodel *model = (HFETAmodel*)inModel; + switch(param) + { + case HFETA_MOD_VTO: + model->HFETAthresholdGiven = TRUE; + model->HFETAthreshold = value->rValue; + break; + case HFETA_MOD_LAMBDA: + model->HFETAlambdaGiven = TRUE; + model->HFETAlambda = value->rValue; + break; + case HFETA_MOD_RD: + model->HFETArdGiven = TRUE; + model->HFETArd = value->rValue; + break; + case HFETA_MOD_RS: + model->HFETArsGiven = TRUE; + model->HFETArs = value->rValue; + break; + case HFETA_MOD_RG: + model->HFETArgGiven = TRUE; + model->HFETArg = value->rValue; + break; + case HFETA_MOD_RDI: + model->HFETArdiGiven = TRUE; + model->HFETArdi = value->rValue; + break; + case HFETA_MOD_RSI: + model->HFETArsiGiven = TRUE; + model->HFETArsi = value->rValue; + break; + case HFETA_MOD_RGS: + model->HFETArgsGiven = TRUE; + model->HFETArgs = value->rValue; + break; + case HFETA_MOD_RGD: + model->HFETArgdGiven = TRUE; + model->HFETArgd = value->rValue; + break; + case HFETA_MOD_RI: + model->HFETAriGiven = TRUE; + model->HFETAri = value->rValue; + break; + case HFETA_MOD_RF: + model->HFETArfGiven = TRUE; + model->HFETArf = value->rValue; + break; + case HFETA_MOD_ETA: + model->HFETAetaGiven = TRUE; + model->HFETAeta = value->rValue; + break; + case HFETA_MOD_M: + model->HFETAmGiven = TRUE; + model->HFETAm = value->rValue; + break; + case HFETA_MOD_MC: + model->HFETAmcGiven = TRUE; + model->HFETAmc = value->rValue; + break; + case HFETA_MOD_GAMMA: + model->HFETAgammaGiven = TRUE; + model->HFETAgamma = value->rValue; + break; + case HFETA_MOD_SIGMA0: + model->HFETAsigma0Given = TRUE; + model->HFETAsigma0 = value->rValue; + break; + case HFETA_MOD_VSIGMAT: + model->HFETAvsigmatGiven = TRUE; + model->HFETAvsigmat = value->rValue; + break; + case HFETA_MOD_VSIGMA: + model->HFETAvsigmaGiven = TRUE; + model->HFETAvsigma = value->rValue; + break; + case HFETA_MOD_MU: + model->HFETAmuGiven = TRUE; + model->HFETAmu = value->rValue; + break; + case HFETA_MOD_DI: + model->HFETAdiGiven = TRUE; + model->HFETAdi = value->rValue; + break; + case HFETA_MOD_DELTA: + model->HFETAdeltaGiven = TRUE; + model->HFETAdelta = value->rValue; + break; + case HFETA_MOD_VS: + model->HFETAvsGiven = TRUE; + model->HFETAvs = value->rValue; + break; + case HFETA_MOD_NMAX: + model->HFETAnmaxGiven = TRUE; + model->HFETAnmax = value->rValue; + break; + case HFETA_MOD_DELTAD: + model->HFETAdeltadGiven = TRUE; + model->HFETAdeltad = value->rValue; + break; + case HFETA_MOD_JS1D: + model->HFETAjs1dGiven = TRUE; + model->HFETAjs1d = value->rValue; + break; + case HFETA_MOD_JS2D: + model->HFETAjs2dGiven = TRUE; + model->HFETAjs2d = value->rValue; + break; + case HFETA_MOD_JS1S: + model->HFETAjs1sGiven = TRUE; + model->HFETAjs1s = value->rValue; + break; + case HFETA_MOD_JS2S: + model->HFETAjs2sGiven = TRUE; + model->HFETAjs2s = value->rValue; + break; + case HFETA_MOD_M1D: + model->HFETAm1dGiven = TRUE; + model->HFETAm1d = value->rValue; + break; + case HFETA_MOD_M2D: + model->HFETAm2dGiven = TRUE; + model->HFETAm2d = value->rValue; + break; + case HFETA_MOD_M1S: + model->HFETAm1sGiven = TRUE; + model->HFETAm1s = value->rValue; + break; + case HFETA_MOD_M2S: + model->HFETAm2sGiven = TRUE; + model->HFETAm2s = value->rValue; + break; + case HFETA_MOD_EPSI: + model->HFETAepsiGiven = TRUE; + model->HFETAepsi = value->rValue; + break; + case HFETA_MOD_A1: + model->HFETAa1Given = TRUE; + model->HFETAa1 = value->rValue; + break; + case HFETA_MOD_A2: + model->HFETAa2Given = TRUE; + model->HFETAa2 = value->rValue; + break; + case HFETA_MOD_MV1: + model->HFETAmv1Given = TRUE; + model->HFETAmv1 = value->rValue; + break; + case HFETA_MOD_P: + model->HFETApGiven = TRUE; + model->HFETAp = value->rValue; + break; + case HFETA_MOD_KAPPA: + model->HFETAkappaGiven = TRUE; + model->HFETAkappa = value->rValue; + break; + case HFETA_MOD_DELF: + model->HFETAdelfGiven = TRUE; + model->HFETAdelf = value->rValue; + break; + case HFETA_MOD_FGDS: + model->HFETAfgdsGiven = TRUE; + model->HFETAfgds = value->rValue; + break; + case HFETA_MOD_TF: + model->HFETAtfGiven = TRUE; + model->HFETAtf = value->rValue+CONSTCtoK; + break; + case HFETA_MOD_CDS: + model->HFETAcdsGiven = TRUE; + model->HFETAcds = value->rValue; + break; + case HFETA_MOD_PHIB: + model->HFETAphibGiven = TRUE; + model->HFETAphib = value->rValue*CHARGE; + break; + case HFETA_MOD_TALPHA: + model->HFETAtalphaGiven = TRUE; + model->HFETAtalpha = value->rValue; + break; + case HFETA_MOD_MT1: + model->HFETAmt1Given = TRUE; + model->HFETAmt1 = value->rValue; + break; + case HFETA_MOD_MT2: + model->HFETAmt2Given = TRUE; + model->HFETAmt2 = value->rValue; + break; + case HFETA_MOD_CK1: + model->HFETAck1Given = TRUE; + model->HFETAck1 = value->rValue; + break; + case HFETA_MOD_CK2: + model->HFETAck2Given = TRUE; + model->HFETAck2 = value->rValue; + break; + case HFETA_MOD_CM1: + model->HFETAcm1Given = TRUE; + model->HFETAcm1 = value->rValue; + break; + case HFETA_MOD_CM2: + model->HFETAcm2Given = TRUE; + model->HFETAcm2 = value->rValue; + break; + case HFETA_MOD_CM3: + model->HFETAcm3Given = TRUE; + model->HFETAcm3 = value->rValue; + break; + case HFETA_MOD_ASTAR: + model->HFETAastarGiven = TRUE; + model->HFETAastar = value->rValue; + break; + case HFETA_MOD_ETA1: + model->HFETAeta1Given = TRUE; + model->HFETAeta1 = value->rValue; + break; + case HFETA_MOD_D1: + model->HFETAd1Given = TRUE; + model->HFETAd1 = value->rValue; + break; + case HFETA_MOD_VT1: + model->HFETAvt1Given = TRUE; + model->HFETAvt1 = value->rValue; + break; + case HFETA_MOD_ETA2: + model->HFETAeta2Given = TRUE; + model->HFETAeta2 = value->rValue; + break; + case HFETA_MOD_D2: + model->HFETAd2Given = TRUE; + model->HFETAd2 = value->rValue; + break; + case HFETA_MOD_VT2: + model->HFETAvt2Given = TRUE; + model->HFETAvt2 = value->rValue; + break; + case HFETA_MOD_GGR: + model->HFETAggrGiven = TRUE; + model->HFETAggr = value->rValue; + break; + case HFETA_MOD_DEL: + model->HFETAdelGiven = TRUE; + model->HFETAdel = value->rValue; + break; + case HFETA_MOD_GATEMOD: + model->HFETAgatemodGiven = TRUE; + model->HFETAgatemod = value->iValue; + break; + case HFETA_MOD_KLAMBDA: + model->HFETAklambdaGiven = TRUE; + KLAMBDA = value->rValue; + break; + case HFETA_MOD_KMU: + model->HFETAkmuGiven = TRUE; + KMU = value->rValue; + break; + case HFETA_MOD_KVTO: + model->HFETAkvtoGiven = TRUE; + KVTO = value->rValue; + break; + case HFETA_MOD_NHFET: + if(value->iValue) { + model->HFETAtype = NHFET; + } + break; + case HFETA_MOD_PHFET: + if(value->iValue) { + model->HFETAtype = PHFET; + } + break; + default: + return(E_BADPARM); + } + return(OK); +} diff --git a/src/spicelib/devices/hfet1/hfetparam.c b/src/spicelib/devices/hfet1/hfetparam.c new file mode 100644 index 000000000..5fef5ff9c --- /dev/null +++ b/src/spicelib/devices/hfet1/hfetparam.c @@ -0,0 +1,60 @@ + +#include "ngspice.h" +#include +#include "ifsim.h" +#include "hfetdefs.h" +#include "sperror.h" +#include "suffix.h" + + +/* ARGSUSED */ +int +HFETAparam(param,value,inst,select) + int param; + IFvalue *value; + GENinstance *inst; + IFvalue *select; +{ + HFETAinstance *here = (HFETAinstance*)inst; + switch(param) { + case HFETA_LENGTH: + here->HFETAlength = value->rValue; + here->HFETAlengthGiven = TRUE; + break; + case HFETA_WIDTH: + here->HFETAwidth = value->rValue; + here->HFETAwidthGiven = TRUE; + break; + case HFETA_IC_VDS: + here->HFETAicVDS = value->rValue; + here->HFETAicVDSGiven = TRUE; + break; + case HFETA_IC_VGS: + here->HFETAicVGS = value->rValue; + here->HFETAicVGSGiven = TRUE; + break; + case HFETA_OFF: + here->HFETAoff = value->iValue; + break; + case HFETA_IC: + switch(value->v.numValue) { + case 2: + here->HFETAicVGS = *(value->v.vec.rVec+1); + here->HFETAicVGSGiven = TRUE; + case 1: + here->HFETAicVDS = *(value->v.vec.rVec); + here->HFETAicVDSGiven = TRUE; + break; + default: + return(E_BADPARM); + } + break; + case HFETA_TEMP: + here->HFETAtemp = value->rValue+CONSTCtoK; + here->HFETAtempGiven = TRUE; + break; + default: + return(E_BADPARM); + } + return(OK); +} diff --git a/src/spicelib/devices/hfet1/hfetsetup.c b/src/spicelib/devices/hfet1/hfetsetup.c new file mode 100644 index 000000000..5b5f36f7e --- /dev/null +++ b/src/spicelib/devices/hfet1/hfetsetup.c @@ -0,0 +1,432 @@ + +#include "ngspice.h" +#include +#include "smpdefs.h" +#include "cktdefs.h" +#include "hfetdefs.h" +#include "const.h" +#include "sperror.h" +#include "suffix.h" + +//#define HFETAphibGiven +//#define CHARGE 1.60219e-19 + +int +HFETAsetup(matrix,inModel,ckt,states) + SMPmatrix *matrix; + GENmodel *inModel; + CKTcircuit *ckt; + int *states; + /* load the diode structure with those pointers needed later + * for fast matrix loading + */ +{ + HFETAmodel *model = (HFETAmodel*)inModel; + HFETAinstance *here; + int error; + CKTnode *tmp; + + + /* loop through all the diode models */ + for( ; model != NULL; model = model->HFETAnextModel ) { + if( (model->HFETAtype != NHFET) && (model->HFETAtype != PHFET) ) { + model->HFETAtype = NHFET; + } + if(!model->HFETAthresholdGiven) { + if(model->HFETAtype == NHFET) + model->HFETAthreshold = 0.15; + else + model->HFETAthreshold = -0.15; + } + if(!model->HFETAdiGiven) { + model->HFETAdi = 0.04e-6; + } + if(!model->HFETAlambdaGiven) { + model->HFETAlambda = 0.15; + } + if(!model->HFETAetaGiven) { + if(model->HFETAtype == NHFET) + model->HFETAeta = 1.28; + else + model->HFETAeta = 1.4; + } + if(!model->HFETAmGiven) { + model->HFETAm = 3.0; + } + if(!model->HFETAmcGiven) { + model->HFETAmc = 3.0; + } + if(!model->HFETAgammaGiven) { + model->HFETAgamma = 3.0; + } + if(!model->HFETAsigma0Given) { + model->HFETAsigma0 = 0.057; + } + if(!model->HFETAvsigmatGiven) { + model->HFETAvsigmat = 0.3; + } + if(!model->HFETAvsigmaGiven) { + model->HFETAvsigma = 0.1; + } + if(!model->HFETAmuGiven) { + if(model->HFETAtype == NHFET) + model->HFETAmu = 0.4; + else + model->HFETAmu = 0.03; + } + if(!model->HFETAdeltaGiven) { + model->HFETAdelta = 3.0; + } + if(!model->HFETAvsGiven) { + if(model->HFETAtype == NHFET) + model->HFETAvs = 1.5e5; + else + model->HFETAvs = 0.8e5; + } + if(!model->HFETAnmaxGiven) { + model->HFETAnmax = 2e16; + } + if(!model->HFETAdeltadGiven) { + model->HFETAdeltad = 4.5e-9; + } + if(!model->HFETAjs1dGiven) { + model->HFETAjs1d = 1.0; + } + if(!model->HFETAjs2dGiven) { + model->HFETAjs2d = 1.15e6; + } + if(!model->HFETAjs1sGiven) { + model->HFETAjs1s = 1.0; + } + if(!model->HFETAjs2sGiven) { + model->HFETAjs2s = 1.15e6; + } + if(!model->HFETAm1dGiven) { + model->HFETAm1d = 1.32; + } + if(!model->HFETAm2dGiven) { + model->HFETAm2d = 6.9; + } + if(!model->HFETAm1sGiven) { + model->HFETAm1s = 1.32; + } + if(!model->HFETAm2sGiven) { + model->HFETAm2s = 6.9; + } + if(!model->HFETArdGiven) { + model->HFETArd = 0; + } + if(!model->HFETArsGiven) { + model->HFETArs = 0; + } + if(!model->HFETArdiGiven) { + model->HFETArdi = 0; + } + if(!model->HFETArsiGiven) { + model->HFETArsi = 0; + } + if(!model->HFETArgsGiven) { + model->HFETArgs = 90; + } + if(!model->HFETArgdGiven) { + model->HFETArgd = 90; + } + if(!model->HFETAriGiven) { + model->HFETAri = 0; + } + if(!model->HFETArfGiven) { + model->HFETArf = 0; + } + if(!model->HFETAepsiGiven) { + model->HFETAepsi = 12.244*8.85418e-12; + } + if(!model->HFETAa1Given) { + model->HFETAa1 = 0; + } + if(!model->HFETAa2Given) { + model->HFETAa2 = 0; + } + if(!model->HFETAmv1Given) { + model->HFETAmv1 = 3; + } + if(!model->HFETApGiven) { + model->HFETAp = 1; + } + if(!model->HFETAkappaGiven) { + model->HFETAkappa = 0; + } + if(!model->HFETAdelfGiven) { + model->HFETAdelf = 0; + } + if(!model->HFETAfgdsGiven) { + model->HFETAfgds = 0; + } + if(!model->HFETAtfGiven) { + model->HFETAtf = ckt->CKTtemp; + } + if(!model->HFETAcdsGiven) { + model->HFETAcds = 0; + } + if(!model->HFETAphibGiven) { + model->HFETAphib = 0.5*CHARGE; + } + if(!model->HFETAtalphaGiven) { + model->HFETAtalpha = 1200; + } + if(!model->HFETAmt1Given) { + model->HFETAmt1 = 3.5; + } + if(!model->HFETAmt2Given) { + model->HFETAmt2 = 9.9; + } + if(!model->HFETAck1Given) { + model->HFETAck1 = 1; + } + if(!model->HFETAck2Given) { + model->HFETAck2 = 0; + } + if(!model->HFETAcm1Given) { + model->HFETAcm1 = 3; + } + if(!model->HFETAcm2Given) { + model->HFETAcm2 = 0; + } + if(!model->HFETAcm3Given) { + model->HFETAcm3 = 0.17; + } + if(!model->HFETAastarGiven) { + model->HFETAastar = 4.0e4; + } + if(!model->HFETAeta1Given) { + model->HFETAeta1 = 2; + } + if(!model->HFETAd1Given) { + model->HFETAd1 = 0.03e-6; + } + if(!model->HFETAeta2Given) { + model->HFETAeta2 = 2; + } + if(!model->HFETAd2Given) { + model->HFETAd2 = 0.2e-6; + } + if(!model->HFETAvt2Given) { + // initialized in HFETAtemp + model->HFETAvt2 = 0; + } + + if(!model->HFETAggrGiven) { + model->HFETAggr = 40; + } + if(!model->HFETAdelGiven) { + model->HFETAdel = 0.04; + } + if(!model->HFETAklambdaGiven) + KLAMBDA = 0; + if(!model->HFETAkmuGiven) + KMU = 0; + if(!model->HFETAkvtoGiven) + KVTO = 0; + + /* loop through all the instances of the model */ + for (here = model->HFETAinstances; here != NULL ; + here=here->HFETAnextInstance) { + + if(!here->HFETAlengthGiven) { + here->HFETAlength = 1e-6; + } + if(!here->HFETAwidthGiven) { + here->HFETAwidth = 20e-6; + } + if(!here->HFETAtempGiven) { + here->HFETAtemp = ckt->CKTtemp; + } + + here->HFETAstate = *states; + // *states += 24; + *states += HFETAnumStates; + +matrixpointers: + if(model->HFETArs != 0 && here->HFETAsourcePrimeNode==0) { + error = CKTmkVolt(ckt,&tmp,here->HFETAname,"source"); + if(error) return(error); + here->HFETAsourcePrimeNode = tmp->number; + +/* XXX: Applied AlansFixes */ + if (ckt->CKTcopyNodesets) { + CKTnode *tmpNode; + IFuid tmpName; + + if (CKTinst2Node(ckt,here,3,&tmpNode,&tmpName)==OK) { + if (tmpNode->nsGiven) { + tmp->nodeset=tmpNode->nodeset; + tmp->nsGiven=tmpNode->nsGiven; + } + } + } + + } else { + here->HFETAsourcePrimeNode = here->HFETAsourceNode; + } + + if(model->HFETArd != 0 && here->HFETAdrainPrimeNode==0) { + error = CKTmkVolt(ckt,&tmp,here->HFETAname,"drain"); + if(error) return(error); + here->HFETAdrainPrimeNode = tmp->number; + +/* XXX: Applied AlansFixes */ + if (ckt->CKTcopyNodesets) { + CKTnode *tmpNode; + IFuid tmpName; + + if (CKTinst2Node(ckt,here,1,&tmpNode,&tmpName)==OK) { + if (tmpNode->nsGiven) { + tmp->nodeset=tmpNode->nodeset; + tmp->nsGiven=tmpNode->nsGiven; + } + } + } + + } else { + here->HFETAdrainPrimeNode = here->HFETAdrainNode; + } + + if(model->HFETArg != 0 && here->HFETAgatePrimeNode==0) { + error = CKTmkVolt(ckt,&tmp,here->HFETAname,"gate"); + if(error) return(error); + here->HFETAgatePrimeNode = tmp->number; + +/* XXX: Applied AlansFixes */ + if (ckt->CKTcopyNodesets) { + CKTnode *tmpNode; + IFuid tmpName; + + if (CKTinst2Node(ckt,here,1,&tmpNode,&tmpName)==OK) { + if (tmpNode->nsGiven) { + tmp->nodeset=tmpNode->nodeset; + tmp->nsGiven=tmpNode->nsGiven; + } + } + } + + } else { + here->HFETAgatePrimeNode = here->HFETAgateNode; + } + if(model->HFETArf != 0 && here->HFETAdrainPrmPrmNode==0) { + error = CKTmkVolt(ckt,&tmp,here->HFETAname,"gd"); + if(error) return(error); + here->HFETAdrainPrmPrmNode = tmp->number; + +/* XXX: Applied AlansFixes */ + if (ckt->CKTcopyNodesets) { + CKTnode *tmpNode; + IFuid tmpName; + + if (CKTinst2Node(ckt,here,1,&tmpNode,&tmpName)==OK) { + if (tmpNode->nsGiven) { + tmp->nodeset=tmpNode->nodeset; + tmp->nsGiven=tmpNode->nsGiven; + } + } + } + + } else { + here->HFETAdrainPrmPrmNode = here->HFETAdrainPrimeNode; + } + + if(model->HFETAri != 0 && here->HFETAsourcePrmPrmNode==0) { + error = CKTmkVolt(ckt,&tmp,here->HFETAname,"gs"); + if(error) return(error); + here->HFETAsourcePrmPrmNode = tmp->number; + +/* XXX: Applied AlanFixes */ + if (ckt->CKTcopyNodesets) { + CKTnode *tmpNode; + IFuid tmpName; + + if (CKTinst2Node(ckt,here,1,&tmpNode,&tmpName)==OK) { + if (tmpNode->nsGiven) { + tmp->nodeset=tmpNode->nodeset; + tmp->nsGiven=tmpNode->nsGiven; + } + } + } + + } else { + here->HFETAsourcePrmPrmNode = here->HFETAsourcePrimeNode; + } + +/* 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(HFETAdrainDrainPrimePtr,HFETAdrainNode,HFETAdrainPrimeNode) + TSTALLOC(HFETAgatePrimeDrainPrimePtr,HFETAgatePrimeNode,HFETAdrainPrimeNode) + TSTALLOC(HFETAgatePrimeSourcePrimePtr,HFETAgatePrimeNode,HFETAsourcePrimeNode) + TSTALLOC(HFETAsourceSourcePrimePtr,HFETAsourceNode,HFETAsourcePrimeNode) + TSTALLOC(HFETAdrainPrimeDrainPtr,HFETAdrainPrimeNode,HFETAdrainNode) + TSTALLOC(HFETAdrainPrimeGatePrimePtr,HFETAdrainPrimeNode,HFETAgatePrimeNode) + TSTALLOC(HFETAdrainPrimeSourcePrimePtr,HFETAdrainPrimeNode,HFETAsourcePrimeNode) + TSTALLOC(HFETAsourcePrimeGatePrimePtr,HFETAsourcePrimeNode,HFETAgatePrimeNode) + TSTALLOC(HFETAsourcePrimeSourcePtr,HFETAsourcePrimeNode,HFETAsourceNode) + TSTALLOC(HFETAsourcePrimeDrainPrimePtr,HFETAsourcePrimeNode,HFETAdrainPrimeNode) + TSTALLOC(HFETAdrainDrainPtr,HFETAdrainNode,HFETAdrainNode) + TSTALLOC(HFETAgatePrimeGatePrimePtr,HFETAgatePrimeNode,HFETAgatePrimeNode) + TSTALLOC(HFETAsourceSourcePtr,HFETAsourceNode,HFETAsourceNode) + TSTALLOC(HFETAdrainPrimeDrainPrimePtr,HFETAdrainPrimeNode,HFETAdrainPrimeNode) + TSTALLOC(HFETAsourcePrimeSourcePrimePtr,HFETAsourcePrimeNode,HFETAsourcePrimeNode) + TSTALLOC(HFETAdrainPrimeDrainPrmPrmPtr,HFETAdrainPrimeNode,HFETAdrainPrmPrmNode) + TSTALLOC(HFETAdrainPrmPrmDrainPrimePtr,HFETAdrainPrmPrmNode,HFETAdrainPrimeNode) + TSTALLOC(HFETAdrainPrmPrmGatePrimePtr,HFETAdrainPrmPrmNode,HFETAgatePrimeNode) + TSTALLOC(HFETAgatePrimeDrainPrmPrmPtr,HFETAgatePrimeNode,HFETAdrainPrmPrmNode) + TSTALLOC(HFETAdrainPrmPrmDrainPrmPrmPtr,HFETAdrainPrmPrmNode,HFETAdrainPrmPrmNode) + TSTALLOC(HFETAsourcePrimeSourcePrmPrmPtr,HFETAsourcePrimeNode,HFETAsourcePrmPrmNode) + TSTALLOC(HFETAsourcePrmPrmSourcePrimePtr,HFETAsourcePrmPrmNode,HFETAsourcePrimeNode) + TSTALLOC(HFETAsourcePrmPrmGatePrimePtr,HFETAsourcePrmPrmNode,HFETAgatePrimeNode) + TSTALLOC(HFETAgatePrimeSourcePrmPrmPtr,HFETAgatePrimeNode,HFETAsourcePrmPrmNode) + TSTALLOC(HFETAsourcePrmPrmSourcePrmPrmPtr,HFETAsourcePrmPrmNode,HFETAsourcePrmPrmNode) + TSTALLOC(HFETAgateGatePtr,HFETAgateNode,HFETAgateNode) + TSTALLOC(HFETAgateGatePrimePtr,HFETAgateNode,HFETAgatePrimeNode) + TSTALLOC(HFETAgatePrimeGatePtr,HFETAgatePrimeNode,HFETAgateNode) + } + } + return(OK); +} + +int +HFETAunsetup(inModel,ckt) + GENmodel *inModel; + CKTcircuit *ckt; +{ + HFETAmodel *model; + HFETAinstance *here; + + for (model = (HFETAmodel *)inModel; model != NULL; + model = model->HFETAnextModel) + { + for (here = model->HFETAinstances; here != NULL; + here=here->HFETAnextInstance) + { + if (here->HFETAdrainPrimeNode + && here->HFETAdrainPrimeNode != here->HFETAdrainNode) + { + CKTdltNNum(ckt, here->HFETAdrainPrimeNode); + here->HFETAdrainPrimeNode = 0; + } + if (here->HFETAsourcePrimeNode + && here->HFETAsourcePrimeNode != here->HFETAsourceNode) + { + CKTdltNNum(ckt, here->HFETAsourcePrimeNode); + here->HFETAsourcePrimeNode = 0; + } + } if (here->HFETAgatePrimeNode + && here->HFETAgatePrimeNode != here->HFETAgateNode) + { + CKTdltNNum(ckt, here->HFETAgatePrimeNode); + here->HFETAgatePrimeNode = 0; + } + } + return OK; +} + diff --git a/src/spicelib/devices/hfet1/hfettemp.c b/src/spicelib/devices/hfet1/hfettemp.c new file mode 100644 index 000000000..66ec1b6cf --- /dev/null +++ b/src/spicelib/devices/hfet1/hfettemp.c @@ -0,0 +1,96 @@ + +#include "ngspice.h" +#include +#include "smpdefs.h" +#include "cktdefs.h" +#include "hfetdefs.h" +#include "const.h" +#include "sperror.h" +#include "suffix.h" + + +/* ARGSUSED */ +int +HFETAtemp(inModel,ckt) + GENmodel *inModel; + CKTcircuit *ckt; +{ + HFETAmodel *model = (HFETAmodel*)inModel; + HFETAinstance *here; + double vt; + double temp; + + /* loop through all the diode models */ + for( ; model != NULL; model = model->HFETAnextModel ) { + if(model->HFETArd != 0) { + model->HFETAdrainConduct = 1/model->HFETArd; + } else { + model->HFETAdrainConduct = 0; + } + if(model->HFETArs != 0) { + model->HFETAsourceConduct = 1/model->HFETArs; + } else { + model->HFETAsourceConduct = 0; + } + if(model->HFETArg != 0) { + model->HFETAgateConduct = 1/model->HFETArg; + } else { + model->HFETAgateConduct = 0; + } + if(model->HFETAri != 0) { + model->HFETAgi = 1/model->HFETAri; + } else { + model->HFETAgi = 0; + } + if(model->HFETArf != 0) { + model->HFETAgf = 1/model->HFETArf; + } else { + model->HFETAgf = 0; + } + model->HFETAdeltaSqr = model->HFETAdelta*model->HFETAdelta; + model->HFETAthreshold *= model->HFETAtype; + + if(!model->HFETAvt2Given) + VT2 = VTO; + if(!model->HFETAvt1Given) + IN_VT1 = VTO+CHARGE*NMAX*DI/EPSI; + + for (here = model->HFETAinstances; here != NULL ; + here=here->HFETAnextInstance) { + vt = CONSTKoverQ*TEMP; + TLAMBDA = LAMBDA + KLAMBDA*(TEMP-ckt->CKTnomTemp); + TMU = MU - KMU*(TEMP-ckt->CKTnomTemp); + TVTO = VTO - KVTO*(TEMP-ckt->CKTnomTemp); + N0 = EPSI*ETA*vt/2/CHARGE/(DI+DELTAD); + N01 = EPSI*ETA1*vt/2/CHARGE/D1; + if(model->HFETAeta2Given) + N02 = EPSI*ETA2*vt/2/CHARGE/D2; + else + N02 = 0.0; + GCHI0 = CHARGE*W*TMU/L; + CF = 0.5*EPSI*W; + IMAX = CHARGE*NMAX*VS*W; + IS1D = JS1D*W*L/2; + IS2D = JS2D*W*L/2; + IS1S = JS1S*W*L/2; + IS2S = JS2S*W*L/2; + ISO = ASTAR*W*L/2; + GGRWL = GGR*L*W/2; + temp = exp(TEMP/model->HFETAtf); + FGDS = model->HFETAfgds*temp; + DELF = model->HFETAdelf*temp; + if(model->HFETAgatemod == 0) { + if(IS1S != 0) + here->HFETAvcrit = vt*log(vt/(CONSTroot2*IS1S)); + else + here->HFETAvcrit = DBL_MAX; + } else { + if(ISO != 0.0) + here->HFETAvcrit = vt*log(vt/(CONSTroot2*ISO)); + else + here->HFETAvcrit = DBL_MAX; + } + } + } + return(OK); +} diff --git a/src/spicelib/devices/hfet1/hfettrunc.c b/src/spicelib/devices/hfet1/hfettrunc.c new file mode 100644 index 000000000..31f9c392c --- /dev/null +++ b/src/spicelib/devices/hfet1/hfettrunc.c @@ -0,0 +1,26 @@ + +#include "ngspice.h" +#include +#include "cktdefs.h" +#include "hfetdefs.h" +#include "sperror.h" +#include "suffix.h" + + +int +HFETAtrunc(inModel,ckt,timeStep) + GENmodel *inModel; + CKTcircuit *ckt; + double *timeStep; +{ + HFETAmodel *model = (HFETAmodel*)inModel; + HFETAinstance *here; + + for( ; model != NULL; model = model->HFETAnextModel) { + for(here=model->HFETAinstances;here!=NULL;here = here->HFETAnextInstance){ + CKTterr(here->HFETAqgs,ckt,timeStep); + CKTterr(here->HFETAqgd,ckt,timeStep); + } + } + return(OK); +} diff --git a/src/spicelib/devices/hfet2/Makefile.am b/src/spicelib/devices/hfet2/Makefile.am new file mode 100644 index 000000000..7ea86fa7b --- /dev/null +++ b/src/spicelib/devices/hfet2/Makefile.am @@ -0,0 +1,29 @@ +## Process this file with automake to produce Makefile.in + +pkglib_LTLIBRARIES = libhfet2.la + +libhfet2_la_SOURCES = \ + hfet2.c \ + hfet2acl.c \ + hfet2ask.c \ + hfet2defs.h \ + hfet2del.c \ + hfet2dest.c \ + hfet2ext.h \ + hfet2getic.c \ + hfet2init.c \ + hfet2init.h \ + hfet2itf.h \ + hfet2load.c \ + hfet2mask.c \ + hfet2mdel.c \ + hfet2mpar.c \ + hfet2param.c \ + hfet2setup.c \ + hfet2temp.c \ + hfet2trunc.c + + + +INCLUDES = -I$(top_srcdir)/src/include +MAINTAINERCLEANFILES = Makefile.in diff --git a/src/spicelib/devices/hfet2/hfet2.c b/src/spicelib/devices/hfet2/hfet2.c new file mode 100644 index 000000000..fdaf30222 --- /dev/null +++ b/src/spicelib/devices/hfet2/hfet2.c @@ -0,0 +1,94 @@ + +#include "ngspice.h" +#include +#include "ifsim.h" +#include "devdefs.h" +#include "hfet2defs.h" +#include "suffix.h" + + +IFparm HFET2pTable[] = { /* parameters */ + OP("off", HFET2_OFF, IF_FLAG ,""), + IOP("l", HFET2_LENGTH, IF_REAL ,""), + IOP("w", HFET2_WIDTH, IF_REAL ,""), + IOP("icvds", HFET2_IC_VDS, IF_REAL ,""), + IOP("icvgs", HFET2_IC_VGS, IF_REAL ,""), + IOP("temp", HFET2_TEMP, IF_REAL ,""), + OP("dnode", HFET2_DRAINNODE, IF_INTEGER ,""), + OP("gnode", HFET2_GATENODE, IF_INTEGER ,""), + OP("snode", HFET2_SOURCENODE, IF_INTEGER ,""), + OP("dprimenode",HFET2_DRAINPRIMENODE, IF_INTEGER ,""), + OP("sprimenode",HFET2_SOURCEPRIMENODE,IF_INTEGER ,""), + OP("vgs", HFET2_VGS, IF_REAL ,""), + OP("vgd", HFET2_VGD, IF_REAL ,""), + OP("cg", HFET2_CG, IF_REAL ,""), + OP("cd", HFET2_CD, IF_REAL ,""), + OP("cgd", HFET2_CGD, IF_REAL ,""), + OP("gm", HFET2_GM, IF_REAL ,""), + OP("gds", HFET2_GDS, IF_REAL ,""), + OP("ggs", HFET2_GGS, IF_REAL ,""), + OP("ggd", HFET2_GGD, IF_REAL ,""), + OP("qgs", HFET2_QGS, IF_REAL ,""), + OP("cqgs", HFET2_CQGS, IF_REAL ,""), + OP("qgd", HFET2_QGD, IF_REAL ,""), + OP("cqgd", HFET2_CQGD, IF_REAL ,""), + OP("cs", HFET2_CS, IF_REAL ,""), + OP("p", HFET2_POWER, IF_REAL ,"") + +}; + +IFparm HFET2mPTable[] = { /* model parameters */ + OP( "type", HFET2_MOD_TYPE, IF_STRING,"NHFET or PHFET"), + IOP( "nhfet", HFET2_MOD_NHFET, IF_FLAG,"N type HFET model"), + IOP( "phfet", HFET2_MOD_PHFET, IF_FLAG,"P type HFET model"), + IOP( "cf", HFET2_MOD_CF, IF_REAL,""), + IOP( "d1", HFET2_MOD_D1, IF_REAL,""), + IOP( "d2", HFET2_MOD_D2, IF_REAL,""), + IOP( "del", HFET2_MOD_DEL, IF_REAL,""), + IOP( "delta", HFET2_MOD_DELTA, IF_REAL,""), + IOP( "deltad", HFET2_MOD_DELTAD, IF_REAL,"Thickness correction"), + IOP( "di", HFET2_MOD_DI, IF_REAL,"Depth of device"), + IOP( "epsi", HFET2_MOD_EPSI, IF_REAL,""), + IOP( "eta", HFET2_MOD_ETA, IF_REAL,"Subthreshold ideality factor"), + IOP( "eta1", HFET2_MOD_ETA1, IF_REAL,""), + IOP( "eta2", HFET2_MOD_ETA2, IF_REAL,""), + IOP( "gamma", HFET2_MOD_GAMMA, IF_REAL,"Knee shape parameter"), + IOP( "ggr", HFET2_MOD_GGR, IF_REAL,""), + IOP( "js", HFET2_MOD_JS, IF_REAL,""), + IOP( "klambda", HFET2_MOD_KLAMBDA, IF_REAL,""), + IOP( "kmu", HFET2_MOD_KMU, IF_REAL,""), + IOP( "knmax", HFET2_MOD_KNMAX, IF_REAL,""), + IOP( "kvto", HFET2_MOD_KVTO, IF_REAL,""), + IOP( "lambda", HFET2_MOD_LAMBDA, IF_REAL,"Output conductance parameter"), + IOP( "m", HFET2_MOD_M, IF_REAL,"Knee shape parameter"), + IOP( "mc", HFET2_MOD_MC, IF_REAL,"Knee shape parameter"), + IOP( "mu", HFET2_MOD_MU, IF_REAL,"Moblity"), + IOP( "n", HFET2_MOD_N, IF_REAL,""), + IOP( "nmax", HFET2_MOD_NMAX, IF_REAL,""), + IOP( "p", HFET2_MOD_P, IF_REAL,""), + IOP( "rd", HFET2_MOD_RD, IF_REAL,"Drain ohmic resistance"), + IOP( "rdi", HFET2_MOD_RDI, IF_REAL,"Drain ohmic resistance"), + IOP( "rs", HFET2_MOD_RS, IF_REAL,"Source ohmic resistance"), + IOP( "rsi", HFET2_MOD_RSI, IF_REAL,"Source ohmic resistance"), + IOP( "sigma0", HFET2_MOD_SIGMA0, IF_REAL,"DIBL parameter"), + IOP( "vs", HFET2_MOD_VS, IF_REAL,"Saturation velocity"), + IOP( "vsigma", HFET2_MOD_VSIGMA, IF_REAL,""), + IOP( "vsigmat", HFET2_MOD_VSIGMAT, IF_REAL,""), + IOP( "vt0", HFET2_MOD_VTO, IF_REAL,""), + IOP( "vt1", HFET2_MOD_VT1, IF_REAL,""), + IOP( "vt2", HFET2_MOD_VT2, IF_REAL,""), + IOP( "vto", HFET2_MOD_VTO, IF_REAL,"") + +}; + +char *HFET2names[] = { + "Drain", + "Gate", + "Source" +}; + +int HFET2nSize = NUMELEMS(HFET2names); +int HFET2pTSize = NUMELEMS(HFET2pTable); +int HFET2mPTSize = NUMELEMS(HFET2mPTable); +int HFET2iSize = sizeof(HFET2instance); +int HFET2mSize = sizeof(HFET2model); diff --git a/src/spicelib/devices/hfet2/hfet2acl.c b/src/spicelib/devices/hfet2/hfet2acl.c new file mode 100644 index 000000000..aedd25391 --- /dev/null +++ b/src/spicelib/devices/hfet2/hfet2acl.c @@ -0,0 +1,64 @@ + +#include "ngspice.h" +#include +#include "cktdefs.h" +#include "hfet2defs.h" +#include "sperror.h" +#include "suffix.h" + + +int HFET2acLoad(inModel, ckt) +GENmodel *inModel; +CKTcircuit *ckt; +{ + + HFET2model *model = (HFET2model*)inModel; + HFET2instance *here; + double gdpr; + double gspr; + double gm; + double gds; + double ggs; + double xgs; + double ggd; + double xgd; + + for( ; model != NULL; model = model->HFET2nextModel ) + { + for( here = model->HFET2instances; here != NULL; here = here->HFET2nextInstance) + { + gdpr=model->HFET2drainConduct; + gspr=model->HFET2sourceConduct; + gm= *(ckt->CKTstate0 + here->HFET2gm) ; + gds= *(ckt->CKTstate0 + here->HFET2gds) ; + ggs= *(ckt->CKTstate0 + here->HFET2ggs) ; + xgs= *(ckt->CKTstate0 + here->HFET2qgs) * ckt->CKTomega ; + ggd= *(ckt->CKTstate0 + here->HFET2ggd) ; + xgd= *(ckt->CKTstate0 + here->HFET2qgd) * ckt->CKTomega ; + *(here->HFET2drainDrainPtr ) += gdpr; + *(here->HFET2gateGatePtr ) += ggd+ggs; + *(here->HFET2gateGatePtr +1) += xgd+xgs; + *(here->HFET2sourceSourcePtr ) += gspr; + *(here->HFET2drainPrimeDrainPrimePtr ) += gdpr+gds+ggd; + *(here->HFET2drainPrimeDrainPrimePtr +1) += xgd; + *(here->HFET2sourcePriHFET2ourcePrimePtr ) += gspr+gds+gm+ggs; + *(here->HFET2sourcePriHFET2ourcePrimePtr +1) += xgs; + *(here->HFET2drainDrainPrimePtr ) -= gdpr; + *(here->HFET2gateDrainPrimePtr ) -= ggd; + *(here->HFET2gateDrainPrimePtr +1) -= xgd; + *(here->HFET2gateSourcePrimePtr ) -= ggs; + *(here->HFET2gateSourcePrimePtr +1) -= xgs; + *(here->HFET2sourceSourcePrimePtr ) -= gspr; + *(here->HFET2drainPrimeDrainPtr ) -= gdpr; + *(here->HFET2drainPrimeGatePtr ) += (-ggd+gm); + *(here->HFET2drainPrimeGatePtr +1) -= xgd; + *(here->HFET2drainPriHFET2ourcePrimePtr ) += (-gds-gm); + *(here->HFET2sourcePrimeGatePtr ) += (-ggs-gm); + *(here->HFET2sourcePrimeGatePtr +1) -= xgs; + *(here->HFET2sourcePriHFET2ourcePtr ) -= gspr; + *(here->HFET2sourcePrimeDrainPrimePtr ) -= gds; + } + } + return(OK); + +} diff --git a/src/spicelib/devices/hfet2/hfet2ask.c b/src/spicelib/devices/hfet2/hfet2ask.c new file mode 100644 index 000000000..d40d41982 --- /dev/null +++ b/src/spicelib/devices/hfet2/hfet2ask.c @@ -0,0 +1,132 @@ +/********** +Copyright 1990 Regents of the University of California. All rights reserved. +Author: 1987 Thomas L. Quarles +**********/ +/* +Imported into HFET2 source: Paolo Nenzi 2001 + */ + +#include "ngspice.h" +#include +#include "cktdefs.h" +#include "devdefs.h" +#include "ifsim.h" +#include "hfet2defs.h" +#include "sperror.h" +#include "suffix.h" + + +/* ARGSUSED */ +int +HFET2ask(ckt,inst,which,value,select) + CKTcircuit *ckt; + GENinstance *inst; + int which; + IFvalue *value; + IFvalue *select; +{ + HFET2instance *here = (HFET2instance*)inst; + static char *msg = "Current and power not available in ac analysis"; + switch(which) { + case HFET2_LENGTH: + value->rValue = here->HFET2length; + return (OK); + case HFET2_WIDTH: + value->rValue = here->HFET2width; + case HFET2_IC_VDS: + value->rValue = here->HFET2icVDS; + return (OK); + case HFET2_IC_VGS: + value->rValue = here->HFET2icVGS; + return (OK); + case HFET2_OFF: + value->iValue = here->HFET2off; + return (OK); + case HFET2_DRAINNODE: + value->iValue = here->HFET2drainNode; + return (OK); + case HFET2_GATENODE: + value->iValue = here->HFET2gateNode; + return (OK); + case HFET2_SOURCENODE: + value->iValue = here->HFET2sourceNode; + return (OK); + case HFET2_DRAINPRIMENODE: + value->iValue = here->HFET2drainPrimeNode; + return (OK); + case HFET2_SOURCEPRIMENODE: + value->iValue = here->HFET2sourcePrimeNode; + return (OK); + case HFET2_TEMP: + value->rValue = here->HFET2temp; + case HFET2_VGS: + value->rValue = *(ckt->CKTstate0 + here->HFET2vgs); + return (OK); + case HFET2_VGD: + value->rValue = *(ckt->CKTstate0 + here->HFET2vgd); + return (OK); + case HFET2_CG: + value->rValue = *(ckt->CKTstate0 + here->HFET2cg); + return (OK); + case HFET2_CD: + value->rValue = *(ckt->CKTstate0 + here->HFET2cd); + return (OK); + case HFET2_CGD: + value->rValue = *(ckt->CKTstate0 + here->HFET2cgd); + return (OK); + case HFET2_GM: + value->rValue = *(ckt->CKTstate0 + here->HFET2gm); + return (OK); + case HFET2_GDS: + value->rValue = *(ckt->CKTstate0 + here->HFET2gds); + return (OK); + case HFET2_GGS: + value->rValue = *(ckt->CKTstate0 + here->HFET2ggs); + return (OK); + case HFET2_GGD: + value->rValue = *(ckt->CKTstate0 + here->HFET2ggd); + return (OK); + case HFET2_QGS: + value->rValue = *(ckt->CKTstate0 + here->HFET2qgs); + return (OK); + case HFET2_CQGS: + value->rValue = *(ckt->CKTstate0 + here->HFET2cqgs); + return (OK); + case HFET2_QGD: + value->rValue = *(ckt->CKTstate0 + here->HFET2qgd); + return (OK); + case HFET2_CQGD: + value->rValue = *(ckt->CKTstate0 + here->HFET2cqgd); + return (OK); + case HFET2_CS : + if (ckt->CKTcurrentAnalysis & DOING_AC) { + errMsg = MALLOC(strlen(msg)+1); + errRtn = "HFET2ask"; + strcpy(errMsg,msg); + return(E_ASKCURRENT); + } else { + value->rValue = -*(ckt->CKTstate0 + here->HFET2cd); + value->rValue -= *(ckt->CKTstate0 + here->HFET2cg); + } + return(OK); + case HFET2_POWER : + if (ckt->CKTcurrentAnalysis & DOING_AC) { + errMsg = MALLOC(strlen(msg)+1); + errRtn = "HFET2ask"; + strcpy(errMsg,msg); + return(E_ASKPOWER); + } else { + value->rValue = *(ckt->CKTstate0 + here->HFET2cd) * + *(ckt->CKTrhsOld + here->HFET2drainNode); + value->rValue += *(ckt->CKTstate0 + here->HFET2cg) * + *(ckt->CKTrhsOld + here->HFET2gateNode); + value->rValue -= (*(ckt->CKTstate0+here->HFET2cd) + + *(ckt->CKTstate0 + here->HFET2cg)) * + *(ckt->CKTrhsOld + here->HFET2sourceNode); + } + return(OK); + default: + return (E_BADPARM); + } + /* NOTREACHED */ +} diff --git a/src/spicelib/devices/hfet2/hfet2defs.h b/src/spicelib/devices/hfet2/hfet2defs.h new file mode 100644 index 000000000..842bf1362 --- /dev/null +++ b/src/spicelib/devices/hfet2/hfet2defs.h @@ -0,0 +1,318 @@ + +#ifndef HFET2 +#define HFET2 + +#include "ifsim.h" +#include "cktdefs.h" +#include "gendefs.h" +#include "complex.h" +#include "noisedef.h" + + +typedef struct sHFET2instance { + struct sHFET2model *HFET2modPtr; + struct sHFET2instance *HFET2nextInstance; + IFuid HFET2name; + int HFET2owner; /* number of owner process */ + int HFET2state; /* index into state table for this device */ + + int HFET2drainNode; + int HFET2gateNode; + int HFET2sourceNode; + int HFET2drainPrimeNode; + int HFET2sourcePrimeNode; + double HFET2length; + double HFET2width; + double HFET2temp; + double HFET2tLambda; + double HFET2tMu; + double HFET2tNmax; + double HFET2tVto; + double HFET2icVDS; + double HFET2icVGS; + double *HFET2drainDrainPrimePtr; + double *HFET2gateDrainPrimePtr; + double *HFET2gateSourcePrimePtr; + double *HFET2sourceSourcePrimePtr; + double *HFET2drainPrimeDrainPtr; + double *HFET2drainPrimeGatePtr; + double *HFET2drainPriHFET2ourcePrimePtr; + double *HFET2sourcePrimeGatePtr; + double *HFET2sourcePriHFET2ourcePtr; + double *HFET2sourcePrimeDrainPrimePtr; + double *HFET2drainDrainPtr; + double *HFET2gateGatePtr; + double *HFET2sourceSourcePtr; + double *HFET2drainPrimeDrainPrimePtr; + double *HFET2sourcePriHFET2ourcePrimePtr; + + +#define HFET2vgs HFET2state +#define HFET2vgd HFET2state+1 +#define HFET2cg HFET2state+2 +#define HFET2cd HFET2state+3 +#define HFET2cgd HFET2state+4 +#define HFET2gm HFET2state+5 +#define HFET2gds HFET2state+6 +#define HFET2ggs HFET2state+7 +#define HFET2ggd HFET2state+8 +#define HFET2qgs HFET2state+9 +#define HFET2cqgs HFET2state+10 +#define HFET2qgd HFET2state+11 +#define HFET2cqgd HFET2state+12 + + int HFET2mode; + int HFET2off; + + unsigned HFET2icVDSGiven : 1; + unsigned HFET2icVGSGiven : 1; + unsigned HFET2lengthGiven : 1; + unsigned HFET2widthGiven : 1; + unsigned HFET2tempGiven : 1; + + double HFET2n0; + double HFET2n01; + double HFET2n02; + double HFET2gchi0; + double HFET2imax; + double HFET2vcrit; + double HFET2ggrlw; + double HFET2jslw; + +} HFET2instance ; + + + +typedef struct sHFET2model { + int HFET2modType; + struct sHFET2model *HFET2nextModel; + HFET2instance * HFET2instances; + IFuid HFET2modName; + int HFET2type; + + double HFET2cf; + double HFET2d1; + double HFET2d2; + double HFET2del; + double HFET2delta; + double HFET2deltad; + double HFET2di; + double HFET2epsi; + double HFET2eta; + double HFET2eta1; + double HFET2eta2; + double HFET2gamma; + double HFET2ggr; + double HFET2js; + double HFET2klambda; + double HFET2kmu; + double HFET2knmax; + double HFET2kvto; + double HFET2lambda; + double HFET2m; + double HFET2mc; + double HFET2mu; + double HFET2n; + double HFET2nmax; + double HFET2p; + double HFET2rd; + double HFET2rdi; + double HFET2rs; + double HFET2rsi; + double HFET2sigma0; + double HFET2vs; + double HFET2vsigma; + double HFET2vsigmat; + double HFET2vt1; + double HFET2vt2; + double HFET2vto; + + double HFET2drainConduct; + double HFET2sourceConduct; + double HFET2deltaSqr; + + unsigned HFET2cfGiven : 1; + unsigned HFET2d1Given : 1; + unsigned HFET2d2Given : 1; + unsigned HFET2delGiven : 1; + unsigned HFET2deltaGiven : 1; + unsigned HFET2deltadGiven : 1; + unsigned HFET2diGiven : 1; + unsigned HFET2epsiGiven : 1; + unsigned HFET2etaGiven : 1; + unsigned HFET2eta1Given : 1; + unsigned HFET2eta2Given : 1; + unsigned HFET2gammaGiven : 1; + unsigned HFET2ggrGiven : 1; + unsigned HFET2jsGiven : 1; + unsigned HFET2klambdaGiven : 1; + unsigned HFET2kmuGiven : 1; + unsigned HFET2knmaxGiven : 1; + unsigned HFET2kvtoGiven : 1; + unsigned HFET2lambdaGiven : 1; + unsigned HFET2mGiven : 1; + unsigned HFET2mcGiven : 1; + unsigned HFET2muGiven : 1; + unsigned HFET2nGiven : 1; + unsigned HFET2nmaxGiven : 1; + unsigned HFET2pGiven : 1; + unsigned HFET2rdGiven : 1; + unsigned HFET2rdiGiven : 1; + unsigned HFET2rsGiven : 1; + unsigned HFET2rsiGiven : 1; + unsigned HFET2sigma0Given : 1; + unsigned HFET2vsGiven : 1; + unsigned HFET2vsigmaGiven : 1; + unsigned HFET2vsigmatGiven : 1; + unsigned HFET2vt1Given : 1; + unsigned HFET2vt2Given : 1; + unsigned HFET2vtoGiven : 1; + +} HFET2model; + + +#ifndef NHFET +#define NHFET 1 +#define PHFET -1 +#endif /*NMF*/ + +/* device parameters */ +#define HFET2_LENGTH 1 +#define HFET2_WIDTH 2 +#define HFET2_IC_VDS 3 +#define HFET2_IC_VGS 4 +#define HFET2_IC 5 +#define HFET2_OFF 6 +#define HFET2_CS 7 +#define HFET2_POWER 8 +#define HFET2_TEMP 9 + +/* model parameters */ +#define HFET2_MOD_NHFET 101 +#define HFET2_MOD_PHFET 102 +#define HFET2_MOD_CF 103 +#define HFET2_MOD_D1 104 +#define HFET2_MOD_D2 105 +#define HFET2_MOD_DEL 106 +#define HFET2_MOD_DELTA 107 +#define HFET2_MOD_DELTAD 108 +#define HFET2_MOD_DI 109 +#define HFET2_MOD_EPSI 110 +#define HFET2_MOD_ETA 111 +#define HFET2_MOD_ETA1 112 +#define HFET2_MOD_ETA2 113 +#define HFET2_MOD_GAMMA 114 +#define HFET2_MOD_GGR 115 +#define HFET2_MOD_JS 116 +#define HFET2_MOD_KLAMBDA 117 +#define HFET2_MOD_KMU 118 +#define HFET2_MOD_KNMAX 119 +#define HFET2_MOD_KVTO 120 +#define HFET2_MOD_LAMBDA 121 +#define HFET2_MOD_M 122 +#define HFET2_MOD_MC 123 +#define HFET2_MOD_MU 124 +#define HFET2_MOD_N 125 +#define HFET2_MOD_NMAX 126 +#define HFET2_MOD_P 127 +#define HFET2_MOD_RD 128 +#define HFET2_MOD_RDI 129 +#define HFET2_MOD_RS 130 +#define HFET2_MOD_RSI 131 +#define HFET2_MOD_SIGMA0 132 +#define HFET2_MOD_VS 133 +#define HFET2_MOD_VSIGMA 134 +#define HFET2_MOD_VSIGMAT 135 +#define HFET2_MOD_VT1 136 +#define HFET2_MOD_VT2 137 +#define HFET2_MOD_VTO 138 +#define HFET2_MOD_TYPE 139 + +/* device questions */ + +#define HFET2_DRAINNODE 201 +#define HFET2_GATENODE 202 +#define HFET2_SOURCENODE 203 +#define HFET2_DRAINPRIMENODE 204 +#define HFET2_SOURCEPRIMENODE 205 + +#define HFET2_VGS 206 +#define HFET2_VGD 207 +#define HFET2_CG 208 +#define HFET2_CD 209 +#define HFET2_CGD 210 +#define HFET2_GM 211 +#define HFET2_GDS 212 +#define HFET2_GGS 213 +#define HFET2_GGD 214 +#define HFET2_QGS 215 +#define HFET2_CQGS 216 +#define HFET2_QGD 217 +#define HFET2_CQGD 218 + +/* model questions */ + +#define HFET2_MOD_DRAINCONDUCT 301 +#define HFET2_MOD_SOURCECONDUCT 302 +#define HFET2_MOD_DEPLETIONCAP 303 +#define HFET2_MOD_VCRIT 304 + +#define CF (model->HFET2cf) +#define D1 (model->HFET2d1) +#define D2 (model->HFET2d2) +#define DEL (model->HFET2del) +#define DELTA (model->HFET2delta) +#define DELTAD (model->HFET2deltad) +#define DI (model->HFET2di) +#define EPSI (model->HFET2epsi) +#define ETA (model->HFET2eta) +#define ETA1 (model->HFET2eta1) +#define ETA2 (model->HFET2eta2) +#define GAMMA (model->HFET2gamma) +#define GGR (model->HFET2ggr) +#define JS (model->HFET2js) +#define KLAMBDA (model->HFET2klambda) +#define KMU (model->HFET2kmu) +#define KNMAX (model->HFET2knmax) +#define KVTO (model->HFET2kvto) +#define LAMBDA (model->HFET2lambda) +#define M (model->HFET2m) +#define MC (model->HFET2mc) +#define MU (model->HFET2mu) +#define N (model->HFET2n) +#define NMAX (model->HFET2nmax) +#define PP (model->HFET2p) +#define RD (model->HFET2rd) +#define RDI (model->HFET2rdi) +#define RS (model->HFET2rs) +#define RSI (model->HFET2rsi) +#define SIGMA0 (model->HFET2sigma0) +#define TYPE (model->HFET2type) +#define VS (model->HFET2vs) +#define VSIGMA (model->HFET2vsigma) +#define VSIGMAT (model->HFET2vsigmat) +#define HFET2_VT1 (model->HFET2vt1) /* Fix a redefinition in include files */ +#define VT2 (model->HFET2vt2) +#define VTO (model->HFET2vto) + +#define DELTA2 (model->HFET2deltaSqr) + +#define GCHI0 (here->HFET2gchi0) +#define GGRLW (here->HFET2ggrlw) +#define JSLW (here->HFET2jslw) +#define IMAX (here->HFET2imax) +#define L (here->HFET2length) +#define N0 (here->HFET2n0) +#define N01 (here->HFET2n01) +#define N02 (here->HFET2n02) +#define TEMP (here->HFET2temp) +#define TLAMBDA (here->HFET2tLambda) +#define TMU (here->HFET2tMu) +#define TNMAX (here->HFET2tNmax) +#define TVTO (here->HFET2tVto) +#define VCRIT (here->HFET2vcrit) +#define W (here->HFET2width) + +#include "hfet2ext.h" + +#endif /*HFET2*/ diff --git a/src/spicelib/devices/hfet2/hfet2del.c b/src/spicelib/devices/hfet2/hfet2del.c new file mode 100644 index 000000000..0eac5dabf --- /dev/null +++ b/src/spicelib/devices/hfet2/hfet2del.c @@ -0,0 +1,39 @@ +/********** +Copyright 1990 Regents of the University of California. All rights reserved. +Author: 1985 S. Hwang +**********/ +/* +Imported into hfet2 model: Paolo Nenzi 2001 +*/ + +#include "ngspice.h" +#include +#include "hfet2defs.h" +#include "sperror.h" +#include "suffix.h" + + +int +HFET2delete(inModel,name,inst) + GENmodel *inModel; + IFuid name; + GENinstance **inst; +{ + HFET2model *model = (HFET2model*)inModel; + HFET2instance **fast = (HFET2instance**)inst; + HFET2instance **prev = NULL; + HFET2instance *here; + + for( ; model ; model = model->HFET2nextModel) { + prev = &(model->HFET2instances); + for(here = *prev; here ; here = *prev) { + if(here->HFET2name == name || (fast && here==*fast) ) { + *prev= here->HFET2nextInstance; + FREE(here); + return(OK); + } + prev = &(here->HFET2nextInstance); + } + } + return(E_NODEV); +} diff --git a/src/spicelib/devices/hfet2/hfet2dest.c b/src/spicelib/devices/hfet2/hfet2dest.c new file mode 100644 index 000000000..1af55e904 --- /dev/null +++ b/src/spicelib/devices/hfet2/hfet2dest.c @@ -0,0 +1,32 @@ + +#include "ngspice.h" +#include +#include "hfet2defs.h" +#include "suffix.h" + + +void HFET2destroy(inModel) +GENmodel **inModel; +{ + + HFET2model **model = (HFET2model**)inModel; + HFET2instance *here; + HFET2instance *prev = NULL; + HFET2model *mod = *model; + HFET2model *oldmod = NULL; + + for( ; mod ; mod = mod->HFET2nextModel) { + if(oldmod) FREE(oldmod); + oldmod = mod; + prev = (HFET2instance *)NULL; + for(here = mod->HFET2instances ; here ; here = here->HFET2nextInstance) { + if(prev) FREE(prev); + prev = here; + } + if(prev) FREE(prev); + } + if(oldmod) FREE(oldmod); + *model = NULL; + return; + +} diff --git a/src/spicelib/devices/hfet2/hfet2ext.h b/src/spicelib/devices/hfet2/hfet2ext.h new file mode 100644 index 000000000..9604af910 --- /dev/null +++ b/src/spicelib/devices/hfet2/hfet2ext.h @@ -0,0 +1,38 @@ +/********** +Copyright 1993: T. Ytterdal, K. Lee, M. Shur and T. A. Fjeldly. All rights reserved. +Author: Trond Ytterdal +**********/ + +#ifdef __STDC__ +extern int HFET2acLoad(GENmodel*,CKTcircuit*); +extern int HFET2ask(CKTcircuit*,GENinstance*,int,IFvalue*,IFvalue*); +extern int HFET2delete(GENmodel*,IFuid,GENinstance**); +extern void HFET2destroy(GENmodel**); +extern int HFET2getic(GENmodel*,CKTcircuit*); +extern int HFET2load(GENmodel*,CKTcircuit*); +extern int HFET2mAsk(CKTcircuit*,GENmodel*,int,IFvalue*); +extern int HFET2mDelete(GENmodel**,IFuid,GENmodel*); +extern int HFET2mParam(int,IFvalue*,GENmodel*); +extern int HFET2param(int,IFvalue*,GENinstance*,IFvalue*); +extern int HFET2setup(SMPmatrix*,GENmodel*,CKTcircuit*,int*); +extern int HFET2temp(GENmodel*,CKTcircuit*); +extern int HFET2trunc(GENmodel*,CKTcircuit*,double*); +extern int HFET2unsetup( GENmodel*,CKTcircuit*); + +#else /* stdc */ +extern int HFET2acLoad(); +extern int HFET2ask(); +extern int HFET2delete(); +extern void HFET2destroy(); +extern int HFET2getic(); +extern int HFET2load(); +extern int HFETAmAsk(); +extern int HFETAmDelete(); +extern int HFET2mParam(); +extern int HFET2param(); +extern int HFET2setup(); +extern int HFET2temp(); +extern int HFET2trunc(); +extern int HFET2unsetup(); +#endif + diff --git a/src/spicelib/devices/hfet2/hfet2getic.c b/src/spicelib/devices/hfet2/hfet2getic.c new file mode 100644 index 000000000..e3e0ab7b8 --- /dev/null +++ b/src/spicelib/devices/hfet2/hfet2getic.c @@ -0,0 +1,32 @@ + +#include "ngspice.h" +#include +#include "cktdefs.h" +#include "hfet2defs.h" +#include "sperror.h" +#include "suffix.h" + + +int HFET2getic(inModel, ckt) +GENmodel *inModel; +CKTcircuit *ckt; +{ + + HFET2model *model = (HFET2model*)inModel; + HFET2instance *here; + + for( ; model ; model = model->HFET2nextModel) { + for(here = model->HFET2instances; here ; here = here->HFET2nextInstance) { + if(!here->HFET2icVDSGiven) { + here->HFET2icVDS = *(ckt->CKTrhs + here->HFET2drainNode) - + *(ckt->CKTrhs + here->HFET2sourceNode); + } + if(!here->HFET2icVGSGiven) { + here->HFET2icVGS = *(ckt->CKTrhs + here->HFET2gateNode) - + *(ckt->CKTrhs + here->HFET2sourceNode); + } + } + } + return(OK); + +} diff --git a/src/spicelib/devices/hfet2/hfet2init.c b/src/spicelib/devices/hfet2/hfet2init.c new file mode 100644 index 000000000..55bfb6dd9 --- /dev/null +++ b/src/spicelib/devices/hfet2/hfet2init.c @@ -0,0 +1,65 @@ +#include + +#include + +#include "hfet2itf.h" +#include "hfet2ext.h" +#include "hfet2init.h" + + +SPICEdev HFET2info = { + { + "HFET2", + "HFET2 Model", + + &HFET2nSize, + &HFET2nSize, + HFET2names, + + &HFET2pTSize, + HFET2pTable, + + &HFET2mPTSize, + HFET2mPTable, + DEV_DEFAULT + }, + + DEVparam : HFET2param, + DEVmodParam : HFET2mParam, + DEVload : HFET2load, + DEVsetup : HFET2setup, + DEVunsetup : HFET2unsetup, + DEVpzSetup : HFET2setup, + DEVtemperature: HFET2temp, + DEVtrunc : HFET2trunc, + DEVfindBranch : NULL, + DEVacLoad : HFET2acLoad, + DEVaccept : NULL, + DEVdestroy : HFET2destroy, + DEVmodDelete : HFET2mDelete, + DEVdelete : HFET2delete, + DEVsetic : HFET2getic, + DEVask : HFET2ask, + DEVmodAsk : HFET2mAsk, + DEVpzLoad : NULL, + DEVconvTest : NULL, + DEVsenSetup : NULL, + DEVsenLoad : NULL, + DEVsenUpdate : NULL, + DEVsenAcLoad : NULL, + DEVsenPrint : NULL, + DEVsenTrunc : NULL, + DEVdisto : NULL, + DEVnoise : NULL, + + DEVinstSize : &HFET2iSize, + DEVmodSize : &HFET2mSize + +}; + + +SPICEdev * +get_hfet2_info(void) +{ + return &HFET2info; +} diff --git a/src/spicelib/devices/hfet2/hfet2init.h b/src/spicelib/devices/hfet2/hfet2init.h new file mode 100644 index 000000000..30ec34c6c --- /dev/null +++ b/src/spicelib/devices/hfet2/hfet2init.h @@ -0,0 +1,13 @@ +#ifndef _HFET2INIT_H +#define _HFET2INIT_H + +extern IFparm HFET2pTable[ ]; +extern IFparm HFET2mPTable[ ]; +extern char *HFET2names[ ]; +extern int HFET2pTSize; +extern int HFET2mPTSize; +extern int HFET2nSize; +extern int HFET2iSize; +extern int HFET2mSize; + +#endif diff --git a/src/spicelib/devices/hfet2/hfet2itf.h b/src/spicelib/devices/hfet2/hfet2itf.h new file mode 100644 index 000000000..ef62a26b6 --- /dev/null +++ b/src/spicelib/devices/hfet2/hfet2itf.h @@ -0,0 +1,7 @@ +#ifndef DEV_HFET2 +#define DEV_HFET2 + +SPICEdev *get_hfet2_info(void); + +#endif + diff --git a/src/spicelib/devices/hfet2/hfet2load.c b/src/spicelib/devices/hfet2/hfet2load.c new file mode 100644 index 000000000..609cc2973 --- /dev/null +++ b/src/spicelib/devices/hfet2/hfet2load.c @@ -0,0 +1,456 @@ + +#include "ngspice.h" +#include +#include "devdefs.h" +#include "cktdefs.h" +#include "hfet2defs.h" +#include "const.h" +#include "trandefs.h" +#include "sperror.h" +#include "suffix.h" + +void Pause(void); + +static void hfeta2(HFET2model *model, HFET2instance *here, CKTcircuit *ckt, + double vgs, double vds, double *cdrain, double *gm, + double *gds, double *capgs, double *capgd); + + +int HFET2load(inModel, ckt) +GENmodel *inModel; +register CKTcircuit *ckt; +{ + + register HFET2model *model = (HFET2model*)inModel; + register HFET2instance *here; + double capgd; + double capgs; + double cd; + double cdhat; + double cdrain; + double cdreq; + double ceq; + double ceqgd; + double ceqgs; + double cg; + double cgd; + double cghat; + double delvds; + double delvgd; + double delvgs; + double gdpr; + double gds; + double geq; + double ggd; + double ggs; + double gm; + double gspr; + double vcrit; + double vds; + double vgd; + double vgd1; + double vgs; + double vgs1; + double vt; + double vto; + double xfact; + int icheck; + int ichk1; + int error; + int inverse; + + for( ; model != NULL; model = model->HFET2nextModel ) { + for(here = model->HFET2instances; here != NULL; here=here->HFET2nextInstance) { + gdpr = model->HFET2drainConduct; + gspr = model->HFET2sourceConduct; + vcrit = VCRIT; + vto = TVTO; + vt = CONSTKoverQ*TEMP; + icheck = 1; + if( ckt->CKTmode & MODEINITSMSIG) { + vgs = *(ckt->CKTstate0 + here->HFET2vgs); + vgd = *(ckt->CKTstate0 + here->HFET2vgd); + } else if(ckt->CKTmode & MODEINITTRAN) { + vgs = *(ckt->CKTstate1 + here->HFET2vgs); + vgd = *(ckt->CKTstate1 + here->HFET2vgd); + } else if((ckt->CKTmode & MODEINITJCT) && (ckt->CKTmode & MODETRANOP) && + (ckt->CKTmode & MODEUIC) ) { + vds = model->HFET2type*here->HFET2icVDS; + vgs = model->HFET2type*here->HFET2icVGS; + vgd = vgs-vds; + } else if ( (ckt->CKTmode & MODEINITJCT) && (here->HFET2off == 0) ) { + vgs = -1; + vgd = -1; + } else if((ckt->CKTmode & MODEINITJCT) || + ((ckt->CKTmode & MODEINITFIX) && (here->HFET2off))) { + vgs = 0; + vgd = 0; + } else { +#ifndef PREDICTOR + if(ckt->CKTmode & MODEINITPRED) { + xfact = ckt->CKTdelta/ckt->CKTdeltaOld[2]; + *(ckt->CKTstate0 + here->HFET2vgs) = + *(ckt->CKTstate1 + here->HFET2vgs); + vgs = (1+xfact) * *(ckt->CKTstate1 + here->HFET2vgs) - + xfact * *(ckt->CKTstate2 + here->HFET2vgs); + *(ckt->CKTstate0 + here->HFET2vgd) = + *(ckt->CKTstate1 + here->HFET2vgd); + vgd = (1+xfact)* *(ckt->CKTstate1 + here->HFET2vgd) - + xfact * *(ckt->CKTstate2 + here->HFET2vgd); + *(ckt->CKTstate0 + here->HFET2cg) = + *(ckt->CKTstate1 + here->HFET2cg); + *(ckt->CKTstate0 + here->HFET2cd) = + *(ckt->CKTstate1 + here->HFET2cd); + *(ckt->CKTstate0 + here->HFET2cgd) = + *(ckt->CKTstate1 + here->HFET2cgd); + *(ckt->CKTstate0 + here->HFET2gm) = + *(ckt->CKTstate1 + here->HFET2gm); + *(ckt->CKTstate0 + here->HFET2gds) = + *(ckt->CKTstate1 + here->HFET2gds); + *(ckt->CKTstate0 + here->HFET2ggs) = + *(ckt->CKTstate1 + here->HFET2ggs); + *(ckt->CKTstate0 + here->HFET2ggd) = + *(ckt->CKTstate1 + here->HFET2ggd); + } else { +#endif /* PREDICTOR */ + vgs = model->HFET2type* + (*(ckt->CKTrhsOld+ here->HFET2gateNode)- *(ckt->CKTrhsOld+ + here->HFET2sourcePrimeNode)); + vgd = model->HFET2type* + (*(ckt->CKTrhsOld+here->HFET2gateNode)- *(ckt->CKTrhsOld+ + here->HFET2drainPrimeNode)); +#ifndef PREDICTOR + } +#endif /* PREDICTOR */ + delvgs=vgs - *(ckt->CKTstate0 + here->HFET2vgs); + delvgd=vgd - *(ckt->CKTstate0 + here->HFET2vgd); + delvds=delvgs - delvgd; + cghat= *(ckt->CKTstate0 + here->HFET2cg) + + *(ckt->CKTstate0 + here->HFET2ggd)*delvgd + + *(ckt->CKTstate0 + here->HFET2ggs)*delvgs; + cdhat= *(ckt->CKTstate0 + here->HFET2cd) + + *(ckt->CKTstate0 + here->HFET2gm)*delvgs + + *(ckt->CKTstate0 + here->HFET2gds)*delvds - + *(ckt->CKTstate0 + here->HFET2ggd)*delvgd; + + // bypass if solution has not changed + + if((ckt->CKTbypass) && + (!(ckt->CKTmode & MODEINITPRED)) && + (fabs(delvgs) < ckt->CKTreltol*MAX(fabs(vgs), + fabs(*(ckt->CKTstate0 + here->HFET2vgs)))+ + ckt->CKTvoltTol) ) + if ( (fabs(delvgd) < ckt->CKTreltol*MAX(fabs(vgd), + fabs(*(ckt->CKTstate0 + here->HFET2vgd)))+ + ckt->CKTvoltTol)) + if ( (fabs(cghat-*(ckt->CKTstate0 + here->HFET2cg)) + < ckt->CKTreltol*MAX(fabs(cghat), + fabs(*(ckt->CKTstate0 + here->HFET2cg)))+ + ckt->CKTabstol) ) if ( /* hack - expression too big */ + (fabs(cdhat-*(ckt->CKTstate0 + here->HFET2cd)) + < ckt->CKTreltol*MAX(fabs(cdhat), + fabs(*(ckt->CKTstate0 + here->HFET2cd)))+ + ckt->CKTabstol) ) { + + /* we can do a bypass */ + vgs= *(ckt->CKTstate0 + here->HFET2vgs); + vgd= *(ckt->CKTstate0 + here->HFET2vgd); + vds= vgs-vgd; + cg= *(ckt->CKTstate0 + here->HFET2cg); + cd= *(ckt->CKTstate0 + here->HFET2cd); + cgd= *(ckt->CKTstate0 + here->HFET2cgd); + gm= *(ckt->CKTstate0 + here->HFET2gm); + gds= *(ckt->CKTstate0 + here->HFET2gds); + ggs= *(ckt->CKTstate0 + here->HFET2ggs); + ggd= *(ckt->CKTstate0 + here->HFET2ggd); + goto load; + } + + // limit nonlinear branch voltages + + ichk1=1; + vgs = DEVpnjlim(vgs,*(ckt->CKTstate0 + here->HFET2vgs),CONSTvt0,vcrit, &icheck); + vgd = DEVpnjlim(vgd,*(ckt->CKTstate0 + here->HFET2vgd),CONSTvt0,vcrit,&ichk1); + if(ichk1 == 1) { + icheck=1; + } + vgs = DEVfetlim(vgs,*(ckt->CKTstate0 + here->HFET2vgs),TVTO); + vgd = DEVfetlim(vgd,*(ckt->CKTstate0 + here->HFET2vgd),TVTO); + } + cg = 0; + cgd = 0; + ggd = 0; + ggs = 0; + vds = vgs-vgd; + { + double arg = -vgs*DEL/vt; + double earg = exp(arg); + double vtn = N*vt; + double expe = exp(vgs/vtn); + ggs = JSLW*expe/vtn+GGRLW*earg*(1-arg); + cg = JSLW*(expe-1)+GGRLW*vgs*earg; + arg = -vgd*DEL/vt; + earg = exp(arg); + expe = exp(vgd/vtn); + ggd = JSLW*expe/vtn+GGRLW*earg*(1-arg); + cgd = JSLW*(expe-1)+GGRLW*vgd*earg; + cg += cgd; + } + if(vds < 0) { + vds = -vds; + inverse = 1; + } else + inverse = 0; + hfeta2(model,here,ckt,vds>0?vgs:vgd,vds,&cdrain,&gm,&gds,&capgs,&capgd); + if(inverse) { + double temp; + cdrain = -cdrain; + vds = -vds; + temp = capgs; + capgs = capgd; + capgd = temp; + } + cd = cdrain - cgd; + if((ckt->CKTmode & (MODETRAN|MODEINITSMSIG)) || ((ckt->CKTmode & MODETRANOP) && + (ckt->CKTmode & MODEUIC)) ){ + // charge storage elements + vgs1 = *(ckt->CKTstate1 + here->HFET2vgs); + vgd1 = *(ckt->CKTstate1 + here->HFET2vgd); + + if(ckt->CKTmode & MODEINITTRAN) { + *(ckt->CKTstate1 + here->HFET2qgs) = capgs*vgs; + *(ckt->CKTstate1 + here->HFET2qgd) = capgd*vgd; + } + *(ckt->CKTstate0+here->HFET2qgs) = *(ckt->CKTstate1+here->HFET2qgs) + + capgs*(vgs-vgs1); + *(ckt->CKTstate0+here->HFET2qgd) = *(ckt->CKTstate1+here->HFET2qgd) + + capgd*(vgd-vgd1); + + // store small-signal parameters + + if( (!(ckt->CKTmode & MODETRANOP)) || (!(ckt->CKTmode & MODEUIC)) ) { + if(ckt->CKTmode & MODEINITSMSIG) { + *(ckt->CKTstate0 + here->HFET2qgs) = capgs; + *(ckt->CKTstate0 + here->HFET2qgd) = capgd; + continue; /*go to 1000*/ + } + + // transient analysis + + if(ckt->CKTmode & MODEINITTRAN) { + *(ckt->CKTstate1 + here->HFET2qgs) = *(ckt->CKTstate0 + here->HFET2qgs); + *(ckt->CKTstate1 + here->HFET2qgd) = *(ckt->CKTstate0 + here->HFET2qgd); + } + error = NIintegrate(ckt,&geq,&ceq,capgs,here->HFET2qgs); + if(error) return(error); + ggs = ggs + geq; + cg = cg + *(ckt->CKTstate0 + here->HFET2cqgs); + error = NIintegrate(ckt,&geq,&ceq,capgd,here->HFET2qgd); + if(error) return(error); + ggd = ggd + geq; + cg = cg + *(ckt->CKTstate0 + here->HFET2cqgd); + cd = cd - *(ckt->CKTstate0 + here->HFET2cqgd); + cgd = cgd + *(ckt->CKTstate0 + here->HFET2cqgd); + if (ckt->CKTmode & MODEINITTRAN) { + *(ckt->CKTstate1 + here->HFET2cqgs) = *(ckt->CKTstate0 + here->HFET2cqgs); + *(ckt->CKTstate1 + here->HFET2cqgd) = *(ckt->CKTstate0 + here->HFET2cqgd); + } + } + } + + // check convergence + + if( (!(ckt->CKTmode & MODEINITFIX)) | (!(ckt->CKTmode & MODEUIC))) { + if((icheck == 1) + || (fabs(cghat-cg) >= ckt->CKTreltol* + MAX(fabs(cghat),fabs(cg))+ckt->CKTabstol) || + (fabs(cdhat-cd) > ckt->CKTreltol* + MAX(fabs(cdhat),fabs(cd))+ckt->CKTabstol) + ) { + ckt->CKTnoncon++; + } + } + *(ckt->CKTstate0 + here->HFET2vgs) = vgs; + *(ckt->CKTstate0 + here->HFET2vgd) = vgd; + *(ckt->CKTstate0 + here->HFET2cg) = cg; + *(ckt->CKTstate0 + here->HFET2cd) = cd; + *(ckt->CKTstate0 + here->HFET2cgd) = cgd; + *(ckt->CKTstate0 + here->HFET2gm) = gm; + *(ckt->CKTstate0 + here->HFET2gds) = gds; + *(ckt->CKTstate0 + here->HFET2ggs) = ggs; + *(ckt->CKTstate0 + here->HFET2ggd) = ggd; + + // load current vector + +load: + ceqgd=model->HFET2type*(cgd-ggd*vgd); + ceqgs=model->HFET2type*((cg-cgd)-ggs*vgs); + cdreq=model->HFET2type*((cd+cgd)-gds*vds-gm*vgs); + *(ckt->CKTrhs + here->HFET2gateNode) += (-ceqgs-ceqgd); + *(ckt->CKTrhs + here->HFET2drainPrimeNode) += (-cdreq+ceqgd); + *(ckt->CKTrhs + here->HFET2sourcePrimeNode) += (cdreq+ceqgs); + + // load y matrix + + *(here->HFET2drainDrainPrimePtr) += (-gdpr); + *(here->HFET2gateDrainPrimePtr) += (-ggd); + *(here->HFET2gateSourcePrimePtr) += (-ggs); + *(here->HFET2sourceSourcePrimePtr) += (-gspr); + *(here->HFET2drainPrimeDrainPtr) += (-gdpr); + *(here->HFET2drainPrimeGatePtr) += (gm-ggd); + *(here->HFET2drainPriHFET2ourcePrimePtr) += (-gds-gm); + *(here->HFET2sourcePrimeGatePtr) += (-ggs-gm); + *(here->HFET2sourcePriHFET2ourcePtr) += (-gspr); + *(here->HFET2sourcePrimeDrainPrimePtr) += (-gds); + *(here->HFET2drainDrainPtr) += (gdpr); + *(here->HFET2gateGatePtr) += (ggd+ggs); + *(here->HFET2sourceSourcePtr) += (gspr); + *(here->HFET2drainPrimeDrainPrimePtr) += (gdpr+gds+ggd); + *(here->HFET2sourcePriHFET2ourcePrimePtr) += (gspr+gds+gm+ggs); + } + } + return(OK); + +} + + + + +static void hfeta2(HFET2model *model, HFET2instance *here, CKTcircuit *ckt, + double vgs, double vds, double *cdrain, double *gm, + double *gds, double *capgs, double *capgd) + +{ + + double vt; + double vgt; + double vgt0; + double sigma; + double vgte; + double isat; + double isatm; + double ns; + double nsm; + double a; + double b; + double c; + double d; + double e; + double g; + double h; + double p; + double q; + double s; + double t; + double u; + double nsc; + double nsn; + double temp; + double etavth; + double gch; + double gchi; + double gchim; + double vsate; + double vdse; + double cg1; + double cgc; + double rt; + double vl; + double delidgch; + double delgchgchi; + double delgchins; + double delnsnsm; + double delnsmvgt; + double delvgtevgt; + double delidvsate; + double delvsateisat; + double delisatisatm; + double delisatmvgte; + double delisatmgchim; + double delvsategch; + double delidvds; + double delvgtvgs; + double delvsatevgt; + + vt = CONSTKoverQ*TEMP; + etavth = ETA*vt; + vl = VS/TMU*L; + rt = RSI+RDI; + vgt0 = vgs - TVTO; + s = exp((vgt0-VSIGMAT)/VSIGMA); + sigma = SIGMA0/(1+s); + vgt = vgt0+sigma*vds; + u = 0.5*vgt/vt-1; + t = sqrt(DELTA2+u*u); + vgte = vt*(2+u+t); + b = exp(vgt/etavth); + if(model->HFET2eta2Given && model->HFET2d2Given) { + nsc = N02*exp((vgt+TVTO-VT2)/(ETA2*vt)); + nsn = 2*N0*log(1+0.5*b); + nsm = nsn*nsc/(nsn+nsc); + } else { + nsm = 2*N0*log(1+0.5*b); + } + if(nsm < 1.0e-38) { + *cdrain = 0; + *gm = 0.0; + *gds = 0.0; + *capgs = CF; + *capgd = CF; + return; + } + c = pow(nsm/TNMAX,GAMMA); + q = pow(1+c,1.0/GAMMA); + ns = nsm/q; + gchi = GCHI0*ns; + gch = gchi/(1+gchi*rt); + gchim = GCHI0*nsm; + h = sqrt(1+2*gchim*RSI + vgte*vgte/(vl*vl)); + p = 1+gchim*RSI+h; + isatm = gchim*vgte/p; + g = pow(isatm/IMAX,GAMMA); + isat = isatm/pow(1+g,1/GAMMA); + vsate = isat/gch; + d = pow(vds/vsate,M); + e = pow(1+d,1.0/M); + delidgch = vds*(1+TLAMBDA*vds)/e; + *cdrain = gch*delidgch; + delidvsate = (*cdrain)*d/vsate/(1+d); + delidvds = gch*(1+2*TLAMBDA*vds)/e-(*cdrain)* + pow(vds/vsate,M-1)/(vsate*(1+d)); + a = 1+gchi*rt; + delgchgchi = 1.0/(a*a); + delgchins = GCHI0; + delnsnsm = ns/nsm*(1-c/(1+c)); + delvgtevgt = 0.5*(1+u/t); + delnsmvgt = N0/etavth/(1.0/b + 0.5); + if(model->HFET2eta2Given && model->HFET2d2Given) + delnsmvgt = nsc*(nsc*delnsmvgt+nsn*nsn/(ETA2*vt))/((nsc+nsn)*(nsc+nsn)); + delvsateisat = 1.0/gch; + delisatisatm = isat/isatm*(1-g/(1+g)); + delisatmvgte = gchim*(p - vgte*vgte/(vl*vl*h))/(p*p); + delvsategch = -vsate/gch; + delisatmgchim = vgte*(p - gchim*RSI*(1+1.0/h))/(p*p); + delvgtvgs = 1-vds*SIGMA0/VSIGMA*s/((1+s)*(1+s)); + p = delgchgchi*delgchins*delnsnsm*delnsmvgt; + delvsatevgt = (delvsateisat*delisatisatm*(delisatmvgte*delvgtevgt + + delisatmgchim*GCHI0*delnsmvgt)+delvsategch*p); + g = delidgch*p + delidvsate*delvsatevgt; + *gm = g*delvgtvgs; + *gds = delidvds + g*sigma; + + // Capacitance calculations + temp = ETA1*vt; + cg1 = 1/(D1/EPSI+temp*exp(-(vgs-HFET2_VT1)/temp)); + cgc = W*L*(CHARGE*delnsnsm*delnsmvgt*delvgtvgs+cg1); + vdse = vds*pow(1+pow(vds/vsate,MC),-1.0/MC); + a = (vsate-vdse)/(2*vsate-vdse); + a = a*a; + temp = 2.0/3.0; + p = PP + (1-PP)*exp(-vds/vsate); + *capgs = CF+2*temp*cgc*(1-a)/(1+p); + a = vsate/(2*vsate-vdse); + a = a*a; + *capgd = CF+2*p*temp*cgc*(1-a)/(1+p); + +} diff --git a/src/spicelib/devices/hfet2/hfet2mask.c b/src/spicelib/devices/hfet2/hfet2mask.c new file mode 100644 index 000000000..0b1e54a31 --- /dev/null +++ b/src/spicelib/devices/hfet2/hfet2mask.c @@ -0,0 +1,160 @@ +/********** +Copyright 1990 Regents of the University of California. All rights reserved. +Author: 1987 Thomas L. Quarles +**********/ +/* +Imported into HFET2 model: Paolo Nenzi 2001 + */ + +#include "ngspice.h" +#include +#include "cktdefs.h" +#include "devdefs.h" +#include "ifsim.h" +#include "hfet2defs.h" +#include "sperror.h" +#include "suffix.h" + + +/* ARGSUSED */ +int +HFET2mAsk(ckt,inst,which,value) + CKTcircuit *ckt; + GENmodel *inst; + int which; + IFvalue *value; +{ + HFET2model *here = (HFET2model*)inst; + switch(which) { + case HFET2_MOD_VTO: + value->rValue = here->HFET2vto; + return (OK); + case HFET2_MOD_LAMBDA: + value->rValue = here->HFET2lambda; + return (OK); + case HFET2_MOD_RD: + value->rValue = here->HFET2rd; + return (OK); + case HFET2_MOD_RS: + value->rValue = here->HFET2rs; + return (OK); + case HFET2_MOD_RDI: + value->rValue = here->HFET2rdi; + return (OK); + case HFET2_MOD_RSI: + value->rValue = here->HFET2rsi; + return (OK); + case HFET2_MOD_ETA: + value->rValue = here->HFET2eta; + return (OK); + case HFET2_MOD_M: + value->rValue = here->HFET2m; + return (OK); + case HFET2_MOD_MC: + value->rValue = here->HFET2mc; + return (OK); + case HFET2_MOD_GAMMA: + value->rValue = here->HFET2gamma; + return (OK); + case HFET2_MOD_SIGMA0: + value->rValue = here->HFET2sigma0; + return (OK); + case HFET2_MOD_VSIGMAT: + value->rValue = here->HFET2vsigmat; + return (OK); + case HFET2_MOD_VSIGMA: + value->rValue = here->HFET2vsigma; + return (OK); + case HFET2_MOD_MU: + value->rValue = here->HFET2mu; + return (OK); + case HFET2_MOD_DI: + value->rValue = here->HFET2di; + return (OK); + case HFET2_MOD_DELTA: + value->rValue = here->HFET2delta; + return (OK); + case HFET2_MOD_VS: + value->rValue = here->HFET2vs; + return (OK); + case HFET2_MOD_NMAX: + value->rValue = here->HFET2nmax; + return (OK); + case HFET2_MOD_DELTAD: + value->rValue = here->HFET2deltad; + return (OK); + case HFET2_MOD_P: + value->rValue = here->HFET2p; + return (OK); + case HFET2_MOD_JS: + value->rValue = here->HFET2js; + return (OK); + case HFET2_MOD_ETA1: + value->rValue = here->HFET2eta1; + return (OK); + case HFET2_MOD_D1: + value->rValue = here->HFET2d1; + return (OK); + case HFET2_MOD_VT1: + value->rValue = here->HFET2vt1; + return (OK); + case HFET2_MOD_ETA2: + value->rValue = here->HFET2eta2; + return (OK); + case HFET2_MOD_D2: + value->rValue = here->HFET2d2; + return (OK); + case HFET2_MOD_VT2: + value->rValue = here->HFET2vt2; + return (OK); + case HFET2_MOD_GGR: + value->rValue = here->HFET2ggr; + return (OK); + case HFET2_MOD_DEL: + value->rValue = here->HFET2del; + return (OK); + case HFET2_MOD_KLAMBDA: + value->rValue = here->HFET2klambda; + return (OK); + case HFET2_MOD_KMU: + value->rValue = here->HFET2kmu; + return (OK); + case HFET2_MOD_KVTO: + value->rValue = here->HFET2kvto; + return (OK); + case HFET2_MOD_EPSI: + value->rValue = here->HFET2epsi; + return (OK); + case HFET2_MOD_KNMAX: + value->rValue = here->HFET2knmax; + return (OK); + case HFET2_MOD_N: + value->rValue = here->HFET2n; + return (OK); + case HFET2_MOD_CF: + value->rValue = here->HFET2cf; + return (OK); + + case HFET2_MOD_DRAINCONDUCT: + value->rValue = here->HFET2drainConduct; + return (OK); + case HFET2_MOD_SOURCECONDUCT: + value->rValue = here->HFET2sourceConduct; + return (OK); + /* case HFET2_MOD_DEPLETIONCAP: + value->rValue = here->HFET2???; + return(OK); */ + /* case HFET2_MOD_VCRIT: + value->rValue = here->HFET2vcrit; + return (OK); */ + + case HFET2_MOD_TYPE: + if (here->HFET2type == NHFET) + value->sValue = "nhfet"; + else + value->sValue = "phfet"; + default: + return (E_BADPARM); + } + /* NOTREACHED */ +} diff --git a/src/spicelib/devices/hfet2/hfet2mdel.c b/src/spicelib/devices/hfet2/hfet2mdel.c new file mode 100644 index 000000000..661bd59ad --- /dev/null +++ b/src/spicelib/devices/hfet2/hfet2mdel.c @@ -0,0 +1,45 @@ +/********** +Copyright 1990 Regents of the University of California. All rights reserved. +Author: 1985 S. Hwang +**********/ +/* +Imported into hfet2 model: Paolo Nenzi 2001 + */ + +#include "ngspice.h" +#include +#include "hfet2defs.h" +#include "sperror.h" +#include "suffix.h" + + +int +HFET2mDelete(inModel,modname,kill) + GENmodel **inModel; + IFuid modname; + GENmodel *kill; +{ + HFET2model **model = (HFET2model**)inModel; + HFET2model *modfast = (HFET2model*)kill; + HFET2instance *here; + HFET2instance *prev = NULL; + HFET2model **oldmod; + oldmod = model; + for( ; *model ; model = &((*model)->HFET2nextModel)) { + if( (*model)->HFET2modName == modname || + (modfast && *model == modfast) ) goto delgot; + oldmod = model; + } + return(E_NOMOD); + +delgot: + *oldmod = (*model)->HFET2nextModel; /* cut deleted device out of list */ + for(here = (*model)->HFET2instances ; here ; here = here->HFET2nextInstance) { + if(prev) FREE(prev); + prev = here; + } + if(prev) FREE(prev); + FREE(*model); + return(OK); + +} diff --git a/src/spicelib/devices/hfet2/hfet2mpar.c b/src/spicelib/devices/hfet2/hfet2mpar.c new file mode 100644 index 000000000..f372c3a5c --- /dev/null +++ b/src/spicelib/devices/hfet2/hfet2mpar.c @@ -0,0 +1,177 @@ + +#include "ngspice.h" +#include +#include "ifsim.h" +#include "hfet2defs.h" +#include "sperror.h" +#include "suffix.h" + + +int HFET2mParam(param, value, inModel) +int param; +IFvalue *value; +GENmodel *inModel; +{ + + HFET2model *model = (HFET2model*)inModel; + switch(param) { + case HFET2_MOD_CF: + model->HFET2cfGiven = TRUE; + CF = value->rValue; + break; + case HFET2_MOD_D1: + model->HFET2d1Given = TRUE; + D1 = value->rValue; + break; + case HFET2_MOD_D2: + model->HFET2d2Given = TRUE; + D2 = value->rValue; + break; + case HFET2_MOD_DEL: + model->HFET2delGiven = TRUE; + DEL = value->rValue; + break; + case HFET2_MOD_DELTA: + model->HFET2deltaGiven = TRUE; + DELTA = value->rValue; + break; + case HFET2_MOD_DELTAD: + model->HFET2deltadGiven = TRUE; + DELTAD = value->rValue; + break; + case HFET2_MOD_DI: + model->HFET2diGiven = TRUE; + DI = value->rValue; + break; + case HFET2_MOD_EPSI: + model->HFET2epsiGiven = TRUE; + EPSI = value->rValue; + break; + case HFET2_MOD_ETA: + model->HFET2etaGiven = TRUE; + ETA = value->rValue; + break; + case HFET2_MOD_ETA1: + model->HFET2eta1Given = TRUE; + ETA1 = value->rValue; + break; + case HFET2_MOD_ETA2: + model->HFET2eta2Given = TRUE; + ETA2 = value->rValue; + break; + case HFET2_MOD_GAMMA: + model->HFET2gammaGiven = TRUE; + GAMMA = value->rValue; + break; + case HFET2_MOD_GGR: + model->HFET2ggrGiven = TRUE; + GGR = value->rValue; + break; + case HFET2_MOD_JS: + model->HFET2jsGiven = TRUE; + JS = value->rValue; + break; + case HFET2_MOD_KLAMBDA: + model->HFET2klambdaGiven = TRUE; + KLAMBDA = value->rValue; + break; + case HFET2_MOD_KMU: + model->HFET2kmuGiven = TRUE; + KMU = value->rValue; + break; + case HFET2_MOD_KNMAX: + model->HFET2knmaxGiven = TRUE; + KNMAX = value->rValue; + break; + case HFET2_MOD_KVTO: + model->HFET2kvtoGiven = TRUE; + KVTO = value->rValue; + break; + case HFET2_MOD_LAMBDA: + model->HFET2lambdaGiven = TRUE; + LAMBDA = value->rValue; + break; + case HFET2_MOD_M: + model->HFET2mGiven = TRUE; + M = value->rValue; + break; + case HFET2_MOD_MC: + model->HFET2mcGiven = TRUE; + MC = value->rValue; + break; + case HFET2_MOD_MU: + model->HFET2muGiven = TRUE; + MU = value->rValue; + break; + case HFET2_MOD_N: + model->HFET2nGiven = TRUE; + N = value->rValue; + break; + case HFET2_MOD_NMAX: + model->HFET2nmaxGiven = TRUE; + NMAX = value->rValue; + break; + case HFET2_MOD_P: + model->HFET2pGiven = TRUE; + PP = value->rValue; + break; + case HFET2_MOD_RD: + model->HFET2rdGiven = TRUE; + RD = value->rValue; + break; + case HFET2_MOD_RDI: + model->HFET2rdiGiven = TRUE; + RDI = value->rValue; + break; + case HFET2_MOD_RS: + model->HFET2rsGiven = TRUE; + RS = value->rValue; + break; + case HFET2_MOD_RSI: + model->HFET2rsiGiven = TRUE; + RSI = value->rValue; + break; + case HFET2_MOD_SIGMA0: + model->HFET2sigma0Given = TRUE; + SIGMA0 = value->rValue; + break; + case HFET2_MOD_VS: + model->HFET2vsGiven = TRUE; + VS = value->rValue; + break; + case HFET2_MOD_VSIGMA: + model->HFET2vsigmaGiven = TRUE; + VSIGMA = value->rValue; + break; + case HFET2_MOD_VSIGMAT: + model->HFET2vsigmatGiven = TRUE; + VSIGMAT = value->rValue; + break; + case HFET2_MOD_VT1: + model->HFET2vt1Given = TRUE; + HFET2_VT1 = value->rValue; + break; + case HFET2_MOD_VT2: + model->HFET2vt2Given = TRUE; + VT2 = value->rValue; + break; + case HFET2_MOD_VTO: + model->HFET2vtoGiven = TRUE; + VTO = value->rValue; + break; + case HFET2_MOD_NHFET: + if(value->iValue) { + TYPE = NHFET; + } + break; + case HFET2_MOD_PHFET: + if(value->iValue) { + TYPE = PHFET; + } + break; + default: + return(E_BADPARM); + } + return(OK); + +} diff --git a/src/spicelib/devices/hfet2/hfet2param.c b/src/spicelib/devices/hfet2/hfet2param.c new file mode 100644 index 000000000..b23a2bbd0 --- /dev/null +++ b/src/spicelib/devices/hfet2/hfet2param.c @@ -0,0 +1,60 @@ + +#include "ngspice.h" +#include +#include "ifsim.h" +#include "hfet2defs.h" +#include "sperror.h" +#include "suffix.h" + + +int HFET2param(param, value, inst, select) +int param; +IFvalue *value; +GENinstance *inst; +IFvalue *select; +{ + + HFET2instance *here = (HFET2instance*)inst; + switch(param) { + case HFET2_LENGTH: + L = value->rValue; + here->HFET2lengthGiven = TRUE; + break; + case HFET2_IC_VDS: + here->HFET2icVDS = value->rValue; + here->HFET2icVDSGiven = TRUE; + break; + case HFET2_IC_VGS: + here->HFET2icVGS = value->rValue; + here->HFET2icVGSGiven = TRUE; + break; + case HFET2_OFF: + here->HFET2off = value->iValue; + break; + case HFET2_IC: + switch(value->v.numValue) { + case 2: + here->HFET2icVGS = *(value->v.vec.rVec+1); + here->HFET2icVGSGiven = TRUE; + case 1: + here->HFET2icVDS = *(value->v.vec.rVec); + here->HFET2icVDSGiven = TRUE; + break; + default: + return(E_BADPARM); + } + break; + case HFET2_TEMP: + TEMP = value->rValue+CONSTCtoK; + here->HFET2tempGiven = TRUE; + break; + case HFET2_WIDTH: + W = value->rValue; + here->HFET2widthGiven = TRUE; + break; + default: + return(E_BADPARM); + } + return(OK); + +} diff --git a/src/spicelib/devices/hfet2/hfet2setup.c b/src/spicelib/devices/hfet2/hfet2setup.c new file mode 100644 index 000000000..67d306231 --- /dev/null +++ b/src/spicelib/devices/hfet2/hfet2setup.c @@ -0,0 +1,233 @@ + +#include "ngspice.h" +#include +#include "smpdefs.h" +#include "cktdefs.h" +#include "hfet2defs.h" +#include "const.h" +#include "sperror.h" +#include "suffix.h" + + +int HFET2setup(matrix, inModel, ckt, states) +SMPmatrix *matrix; +GENmodel *inModel; +CKTcircuit *ckt; +int *states; +{ + + HFET2model *model = (HFET2model*)inModel; + HFET2instance *here; + int error; + CKTnode *tmp; + + for( ; model != NULL; model = model->HFET2nextModel ) { + if((TYPE != NHFET) && (TYPE != PHFET) ) + TYPE = NHFET; + if(!model->HFET2cfGiven) + CF = 0; + if(!model->HFET2d1Given) + D1 = 0.03e-6; + if(!model->HFET2d2Given) + D2 = 0.2e-6; + if(!model->HFET2delGiven) + DEL = 0.04; + if(!model->HFET2deltaGiven) + DELTA = 3.0; + if(!model->HFET2deltadGiven) + DELTAD = 4.5e-9; + if(!model->HFET2diGiven) + DI = 0.04e-6; + if(!model->HFET2epsiGiven) + EPSI = 12.244*8.85418e-12; + if(!model->HFET2etaGiven) + if(TYPE == NHFET) + ETA = 1.28; + else + ETA = 1.4; + if(!model->HFET2eta1Given) + ETA1 = 2; + if(!model->HFET2eta2Given) + ETA2 = 2; + if(!model->HFET2gammaGiven) + GAMMA = 3.0; + if(!model->HFET2ggrGiven) + GGR = 0; + if(!model->HFET2jsGiven) + JS = 0; + if(!model->HFET2klambdaGiven) + KLAMBDA = 0; + if(!model->HFET2kmuGiven) + KMU = 0; + if(!model->HFET2knmaxGiven) + KNMAX = 0; + if(!model->HFET2kvtoGiven) + KVTO = 0; + if(!model->HFET2lambdaGiven) + LAMBDA = 0.15; + if(!model->HFET2mGiven) + M = 3.0; + if(!model->HFET2mcGiven) + MC = 3.0; + if(!model->HFET2muGiven) + if(TYPE == NHFET) + MU = 0.4; + else + MU = 0.03; + if(!model->HFET2nGiven) + N = 5.0; + if(!model->HFET2nmaxGiven) + NMAX = 2e16; + if(!model->HFET2pGiven) + PP = 1; + if(!model->HFET2rdGiven) + RD = 0; + if(!model->HFET2rdiGiven) + RDI = 0; + if(!model->HFET2rsGiven) + RS = 0; + if(!model->HFET2rsiGiven) + RSI = 0; + if(!model->HFET2sigma0Given) + SIGMA0 = 0.057; + if(!model->HFET2vsGiven) + if(TYPE == NHFET) + VS = 1.5e5; + else + VS = 0.8e5; + if(!model->HFET2vsigmaGiven) + VSIGMA = 0.1; + if(!model->HFET2vsigmatGiven) + VSIGMAT = 0.3; + if(!model->HFET2vt1Given) + // initialized in HFET2temp + HFET2_VT1 = 0; + if(!model->HFET2vt2Given) + // initialized in HFET2temp + VT2 = 0; + if(!model->HFET2vtoGiven) { + if(model->HFET2type == NHFET) + VTO = 0.15; + else + VTO = -0.15; + } + + /* loop through all the instances of the model */ + + + for (here = model->HFET2instances; here != NULL; here=here->HFET2nextInstance) { + + CKTnode *tmpNode; + IFuid tmpName; + + here->HFET2state = *states; + *states += 13; + + if(!here->HFET2lengthGiven) + L = 1e-6; + if(!here->HFET2tempGiven) + TEMP = ckt->CKTtemp; + if(!here->HFET2widthGiven) + W = 20e-6; + + if(model->HFET2rs != 0 && here->HFET2sourcePrimeNode==0) { + error = CKTmkVolt(ckt,&tmp,here->HFET2name,"source"); + if(error) return(error); + here->HFET2sourcePrimeNode = tmp->number; + + if (ckt->CKTcopyNodesets) { + if (CKTinst2Node(ckt,here,3,&tmpNode,&tmpName)==OK) { + if (tmpNode->nsGiven) { + tmp->nodeset=tmpNode->nodeset; + tmp->nsGiven=tmpNode->nsGiven; + } + } + } + + } else { + here->HFET2sourcePrimeNode = here->HFET2sourceNode; + } + if(model->HFET2rd != 0 && here->HFET2drainPrimeNode==0) { + error = CKTmkVolt(ckt,&tmp,here->HFET2name,"drain"); + if(error) return(error); + here->HFET2drainPrimeNode = 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->HFET2drainPrimeNode = here->HFET2drainNode; + } + +/* 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(HFET2drainDrainPrimePtr,HFET2drainNode,HFET2drainPrimeNode) + TSTALLOC(HFET2gateDrainPrimePtr,HFET2gateNode,HFET2drainPrimeNode) + TSTALLOC(HFET2gateSourcePrimePtr,HFET2gateNode,HFET2sourcePrimeNode) + TSTALLOC(HFET2sourceSourcePrimePtr,HFET2sourceNode,HFET2sourcePrimeNode) + TSTALLOC(HFET2drainPrimeDrainPtr,HFET2drainPrimeNode,HFET2drainNode) + TSTALLOC(HFET2drainPrimeGatePtr,HFET2drainPrimeNode,HFET2gateNode) + TSTALLOC(HFET2drainPriHFET2ourcePrimePtr,HFET2drainPrimeNode,HFET2sourcePrimeNode) + TSTALLOC(HFET2sourcePrimeGatePtr,HFET2sourcePrimeNode,HFET2gateNode) + TSTALLOC(HFET2sourcePriHFET2ourcePtr,HFET2sourcePrimeNode,HFET2sourceNode) + TSTALLOC(HFET2sourcePrimeDrainPrimePtr,HFET2sourcePrimeNode,HFET2drainPrimeNode) + TSTALLOC(HFET2drainDrainPtr,HFET2drainNode,HFET2drainNode) + TSTALLOC(HFET2gateGatePtr,HFET2gateNode,HFET2gateNode) + TSTALLOC(HFET2sourceSourcePtr,HFET2sourceNode,HFET2sourceNode) + TSTALLOC(HFET2drainPrimeDrainPrimePtr,HFET2drainPrimeNode,HFET2drainPrimeNode) + TSTALLOC(HFET2sourcePriHFET2ourcePrimePtr,HFET2sourcePrimeNode,HFET2sourcePrimeNode) + + } + } + return(OK); + +} + + +int +HFET2unsetup(inModel,ckt) + GENmodel *inModel; + CKTcircuit *ckt; +{ + HFET2model *model; + HFET2instance *here; + + for (model = (HFET2model *)inModel; model != NULL; + model = model->HFET2nextModel) + { + for (here = model->HFET2instances; here != NULL; + here=here->HFET2nextInstance) + { + if (here->HFET2drainPrimeNode + && here->HFET2drainPrimeNode != here->HFET2drainNode) + { + CKTdltNNum(ckt, here->HFET2drainPrimeNode); + here->HFET2drainPrimeNode = 0; + } + if (here->HFET2sourcePrimeNode + && here->HFET2sourcePrimeNode != here->HFET2sourceNode) + { + CKTdltNNum(ckt, here->HFET2sourcePrimeNode); + here->HFET2sourcePrimeNode = 0; + } + /*if (here->HFET2gateNode + && here->HFET2gateNode != here->HFET2gateNode) + { + CKTdltNNum(ckt, here->HFET2gateNode); + here->HFET2gateNode = 0; + }*/ + } + + } + return OK; +} \ No newline at end of file diff --git a/src/spicelib/devices/hfet2/hfet2temp.c b/src/spicelib/devices/hfet2/hfet2temp.c new file mode 100644 index 000000000..e512a5713 --- /dev/null +++ b/src/spicelib/devices/hfet2/hfet2temp.c @@ -0,0 +1,56 @@ + +#include "ngspice.h" +#include +#include "smpdefs.h" +#include "cktdefs.h" +#include "hfet2defs.h" +#include "const.h" +#include "sperror.h" +#include "suffix.h" + + +int HFET2temp(inModel, ckt) +GENmodel *inModel; +CKTcircuit *ckt; +{ + + HFET2instance *here; + HFET2model *model = (HFET2model*)inModel; + + for( ; model != NULL; model = model->HFET2nextModel ) { + if(model->HFET2rd != 0) + model->HFET2drainConduct = 1/model->HFET2rd; + else + model->HFET2drainConduct = 0; + if(model->HFET2rs != 0) + model->HFET2sourceConduct = 1/model->HFET2rs; + else + model->HFET2sourceConduct = 0; + if(!model->HFET2vt1Given) + HFET2_VT1 = VTO+CHARGE*NMAX*DI/EPSI; + if(!model->HFET2vt2Given) + VT2 = VTO; + DELTA2 = DELTA*DELTA; + for (here = model->HFET2instances; here != NULL; here=here->HFET2nextInstance) { + double vt = CONSTKoverQ*TEMP; + double tdiff = TEMP - ckt->CKTnomTemp; + TLAMBDA = LAMBDA + KLAMBDA*tdiff; + TMU = MU - KMU*tdiff; + TNMAX = NMAX - KNMAX*tdiff; + TVTO = TYPE*VTO - KVTO*tdiff; + JSLW = JS*L*W/2; + GGRLW = GGR*L*W/2; + N0 = EPSI*ETA*vt/2/CHARGE/(DI+DELTAD); + N01 = EPSI*ETA1*vt/2/CHARGE/D1; + if(model->HFET2eta2Given) + N02 = EPSI*ETA2*vt/2/CHARGE/D2; + else + N02 = 0.0; + GCHI0 = CHARGE*W*TMU/L; + IMAX = CHARGE*TNMAX*VS*W; + VCRIT = vt*log(vt/(CONSTroot2 * 1e-11)); + } + } + return(OK); + +} diff --git a/src/spicelib/devices/hfet2/hfet2trunc.c b/src/spicelib/devices/hfet2/hfet2trunc.c new file mode 100644 index 000000000..ce74da535 --- /dev/null +++ b/src/spicelib/devices/hfet2/hfet2trunc.c @@ -0,0 +1,27 @@ + +#include "ngspice.h" +#include +#include "cktdefs.h" +#include "hfet2defs.h" +#include "sperror.h" +#include "suffix.h" + + +int HFET2trunc(inModel, ckt, tiHFET2tep) +GENmodel *inModel; +CKTcircuit *ckt; +double *tiHFET2tep; +{ + + HFET2model *model = (HFET2model*)inModel; + HFET2instance *here; + + for( ; model != NULL; model = model->HFET2nextModel) { + for(here=model->HFET2instances;here!=NULL;here = here->HFET2nextInstance){ + CKTterr(here->HFET2qgs,ckt,tiHFET2tep); + CKTterr(here->HFET2qgd,ckt,tiHFET2tep); + } + } + return(OK); + +} diff --git a/src/spicelib/devices/mesa/Makefile.am b/src/spicelib/devices/mesa/Makefile.am new file mode 100644 index 000000000..1e5c48fed --- /dev/null +++ b/src/spicelib/devices/mesa/Makefile.am @@ -0,0 +1,29 @@ +## Process this file with automake to produce Makefile.in + +pkglib_LTLIBRARIES = libmesa.la + +libmesa_la_SOURCES = \ + mesa.c \ + mesaacl.c \ + mesaask.c \ + mesadefs.h \ + mesadel.c \ + mesadest.c \ + mesaext.h \ + mesagetic.c \ + mesainit.c \ + mesainit.h \ + mesaitf.h \ + mesaload.c \ + mesamask.c \ + mesamdel.c \ + mesamparam.c \ + mesaparam.c \ + mesasetup.c \ + mesatemp.c \ + mesatrunc.c + + + +INCLUDES = -I$(top_srcdir)/src/include +MAINTAINERCLEANFILES = Makefile.in diff --git a/src/spicelib/devices/mesa/mesa.c b/src/spicelib/devices/mesa/mesa.c new file mode 100644 index 000000000..bdc3a887e --- /dev/null +++ b/src/spicelib/devices/mesa/mesa.c @@ -0,0 +1,130 @@ +/********** +Copyright 1993: T. Ytterdal, K. Lee, M. Shur and T. A. Fjeldly. All rights reserved. +Author: Trond Ytterdal +**********/ + +#include "ngspice.h" +#include +#include "ifsim.h" +#include "devdefs.h" +#include "mesadefs.h" +#include "suffix.h" + + +IFparm MESApTable[] = { /* parameters */ + OP("off", MESA_OFF, IF_FLAG ,"Device initially off"), + IOP("l", MESA_LENGTH, IF_REAL ,"Length of device"), + IOP("w", MESA_WIDTH, IF_REAL ,"Width of device"), + IOP("icvds", MESA_IC_VDS, IF_REAL ,"Initial D-S voltage"), + IOP("icvgs", MESA_IC_VGS, IF_REAL ,"Initial G-S voltage"), + IOP("td", MESA_TD, IF_REAL ,"Instance drain temperature"), + IOP("ts", MESA_TS, IF_REAL ,"Instance source temperature"), + OP("dnode", MESA_DRAINNODE, IF_INTEGER,"Number of drain node"), + OP("gnode", MESA_GATENODE, IF_INTEGER,"Number of gate node"), + OP("snode", MESA_SOURCENODE, IF_INTEGER,"Number of source node"), + OP("dprimenode",MESA_DRAINPRIMENODE, IF_INTEGER,"Number of internal drain node"), + OP("sprimenode",MESA_SOURCEPRIMENODE,IF_INTEGER,"Number of internal source node"), + OP("gprimenode",MESA_GATEPRIMENODE, IF_INTEGER,"Number of internal gate node"), + OP("vgs", MESA_VGS, IF_REAL,"Gate-Source voltage"), + OP("vgd", MESA_VGD, IF_REAL,"Gate-Drain voltage"), + OP("cg", MESA_CG, IF_REAL,"Gate capacitance"), + OP("cd", MESA_CD, IF_REAL,"Drain capacitance"), + OP("cgd", MESA_CGD, IF_REAL,"Gate_Drain capacitance"), + OP("gm", MESA_GM, IF_REAL,"Transconductance"), + OP("gds", MESA_GDS, IF_REAL,"Drain-Source conductance"), + OP("ggs", MESA_GGS, IF_REAL,"Gate-Source conductance"), + OP("ggd", MESA_GGD, IF_REAL,"Gate-Drain conductance"), + OP("qgs", MESA_QGS, IF_REAL,"Gate-Source charge storage"), + OP("cqgs", MESA_CQGS, IF_REAL,"Capacitance due to gate-source charge storage"), + OP("qgd", MESA_QGD, IF_REAL,"Gate-Drain charge storage"), + OP("cqgd", MESA_CQGD, IF_REAL,"Capacitance due to gate-drain charge storage"), + OP("cs", MESA_CS, IF_REAL,"Source current"), + OP("p", MESA_POWER, IF_REAL,"Power dissipated by the mesfet") + +}; + +IFparm MESAmPTable[] = { /* model parameters */ + IOP( "vt0", MESA_MOD_VTO, IF_REAL,"Pinch-off voltage"), + IOP( "vto", MESA_MOD_VTO, IF_REAL,"Pinch-off voltage"), + IOP( "lambda", MESA_MOD_LAMBDA, IF_REAL,"Output conductance parameter"), + IOP( "lambdahf",MESA_MOD_LAMBDAHF, IF_REAL,"Output conductance parameter at high frequencies"), + IOP( "beta", MESA_MOD_BETA, IF_REAL,"Transconductance parameter"), + IOP( "vs", MESA_MOD_VS, IF_REAL,"Saturation velocity"), + IOP( "rd", MESA_MOD_RD, IF_REAL,"Drain ohmic resistance"), + IOP( "rs", MESA_MOD_RS, IF_REAL,"Source ohmic resistance"), + IOP( "rg", MESA_MOD_RG, IF_REAL,"Gate ohmic resistance"), + IOP( "ri", MESA_MOD_RI, IF_REAL,"Gate-source ohmic resistance"), + IOP( "rf", MESA_MOD_RF, IF_REAL,"Gate-drain ohmic resistance"), + IOP( "rdi", MESA_MOD_RDI, IF_REAL,"Intrinsic source ohmic resistance"), + IOP( "rsi", MESA_MOD_RSI, IF_REAL,"Intrinsic drain ohmic resistance"), + IOP( "phib", MESA_MOD_PHIB, IF_REAL,"Effective Schottky barrier height at room temperature"), + IOP( "phib1", MESA_MOD_PHIB1, IF_REAL,""), + IOP( "tphib", MESA_MOD_PHIB1, IF_REAL,""), + IOP( "astar", MESA_MOD_ASTAR, IF_REAL,"Effective Richardson constant"), + IOP( "ggr", MESA_MOD_GGR, IF_REAL,"Reverse diode conductance"), + IOP( "del", MESA_MOD_DEL, IF_REAL,""), + IOP( "xchi", MESA_MOD_XCHI, IF_REAL,""), + IOP( "tggr", MESA_MOD_XCHI, IF_REAL,""), + IOP( "n", MESA_MOD_N, IF_REAL,"Emission coefficient"), + IOP( "eta", MESA_MOD_ETA, IF_REAL,"Subthreshold ideality factor"), + IOP( "m", MESA_MOD_M, IF_REAL,"Knee shape parameter"), + IOP( "mc", MESA_MOD_MC, IF_REAL,"Knee shape parameter"), + IOP( "alpha", MESA_MOD_ALPHA, IF_REAL,""), + IOP( "sigma0", MESA_MOD_SIGMA0, IF_REAL,"Threshold voltage coefficient"), + IOP( "vsigmat",MESA_MOD_VSIGMAT,IF_REAL,""), + IOP( "vsigma", MESA_MOD_VSIGMA, IF_REAL,""), + IOP( "mu", MESA_MOD_MU, IF_REAL,"Mobility"), + IOP( "theta", MESA_MOD_THETA, IF_REAL,""), + IOP( "mu1", MESA_MOD_MU1, IF_REAL,"Second moblity parameter"), + IOP( "mu2", MESA_MOD_MU2, IF_REAL,"Third moblity parameter"), + IOP( "d", MESA_MOD_D, IF_REAL,"Depth of device"), + IOP( "nd", MESA_MOD_ND, IF_REAL,"Doping density"), + IOP( "du", MESA_MOD_DU, IF_REAL,"Depth of device"), + IOP( "ndu", MESA_MOD_NDU, IF_REAL,"Doping density"), + IOP( "th", MESA_MOD_TH, IF_REAL,"Thickness of delta doped layer"), + IOP( "ndelta", MESA_MOD_NDELTA, IF_REAL,"Delta doped layer doping density"), + IOP( "delta", MESA_MOD_DELTA, IF_REAL,""), + IOP( "tc", MESA_MOD_TC, IF_REAL,"Transconductance compression factor"), + IOP( "tvto", MESA_MOD_TVTO, IF_REAL,"Temperature coefficient for vto"), + IOP( "alphat", MESA_MOD_TVTO, IF_REAL,""), + IOP( "tlambda",MESA_MOD_TLAMBDA,IF_REAL,"Temperature coefficient for lambda"), + IOP( "teta0", MESA_MOD_TETA0, IF_REAL,"First temperature coefficient for eta"), + IOP( "teta1", MESA_MOD_TETA1, IF_REAL,"Second temperature coefficient for eta"), + IOP( "tmu", MESA_MOD_TMU, IF_REAL,"Temperature coefficient for mobility"), + IOP( "xtm0", MESA_MOD_XTM0, IF_REAL,"First exponent for temp dependence of mobility"), + IOP( "xtm1", MESA_MOD_XTM1, IF_REAL,"Second exponent for temp dependence of mobility"), + IOP( "xtm2", MESA_MOD_XTM2, IF_REAL,"Third exponent for temp dependence of mobility"), + IOP( "ks", MESA_MOD_KS, IF_REAL,"Sidegating coefficient"), + IOP( "vsg", MESA_MOD_VSG, IF_REAL,"Sidegating voltage"), + IOP( "tf", MESA_MOD_TF, IF_REAL,"Characteristic temperature determined by traps"), + IOP( "flo", MESA_MOD_FLO, IF_REAL,""), + IOP( "delfo", MESA_MOD_DELFO, IF_REAL,""), + IOP( "ag", MESA_MOD_AG, IF_REAL,""), + IOP( "rtc1", MESA_MOD_TC1, IF_REAL,""), + IOP( "rtc2", MESA_MOD_TC2, IF_REAL,""), + IOP( "zeta", MESA_MOD_ZETA, IF_REAL,""), + IOP( "level", MESA_MOD_LEVEL, IF_REAL,""), + IOP( "nmax", MESA_MOD_NMAX, IF_REAL,""), + IOP( "gamma", MESA_MOD_GAMMA, IF_REAL,""), + IOP( "epsi", MESA_MOD_EPSI, IF_REAL,""), + IOP( "cas", MESA_MOD_CAS, IF_REAL,""), + IOP( "cbs", MESA_MOD_CBS, IF_REAL,""), + OP( "type", MESA_MOD_TYPE, IF_FLAG,"N-type or P-type MESfet model"), + IP( "pmf", MESA_MOD_PMF, IF_FLAG,"P type MESfet model"), + IP( "nmf", MESA_MOD_NMF, IF_FLAG,"N type MESfet model"), + OP( "gd", MESA_MOD_DRAINCONDUCT, IF_REAL,"Drain conductance"), + OP( "gs", MESA_MOD_SOURCECONDUCT, IF_REAL,"Source conductance"), + OP( "vcrit", MESA_MOD_VCRIT, IF_REAL,"Critical voltage"), +}; + +char *MESAnames[] = { + "Drain", + "Gate", + "Source" +}; + +int MESAnSize = NUMELEMS(MESAnames); +int MESApTSize = NUMELEMS(MESApTable); +int MESAmPTSize = NUMELEMS(MESAmPTable); +int MESAiSize = sizeof(MESAinstance); +int MESAmSize = sizeof(MESAmodel); diff --git a/src/spicelib/devices/mesa/mesaacl.c b/src/spicelib/devices/mesa/mesaacl.c new file mode 100644 index 000000000..efe4c8c6d --- /dev/null +++ b/src/spicelib/devices/mesa/mesaacl.c @@ -0,0 +1,97 @@ +/********** +Copyright 1993: T. Ytterdal, K. Lee, M. Shur and T. A. Fjeldly. All rights reserved. +Author: Trond Ytterdal +**********/ + +#include "ngspice.h" +#include +#include "cktdefs.h" +#include "mesadefs.h" +#include "sperror.h" +#include "suffix.h" + + +int +MESAacLoad(inModel,ckt) + GENmodel *inModel; + CKTcircuit *ckt; +{ + MESAmodel *model = (MESAmodel*)inModel; + MESAinstance *here; + double gm; + double gds; + double ggspp; + double ggdpp; + double ggs; + double xgs; + double ggd; + double xgd; + double f; + double lambda; + double vds; + double delidgch; + double delidvds; + + for( ; model != NULL; model = model->MESAnextModel ) { + for( here = model->MESAinstances; here != NULL; + here = here->MESAnextInstance) { + f = ckt->CKTomega/2/M_PI; + if(here->MESAdelf == 0) + lambda = here->MESAtLambda; + else + lambda = here->MESAtLambda+0.5*(here->MESAtLambdahf-here->MESAtLambda)* + (1+tanh((f-here->MESAfl)/here->MESAdelf)); + vds= *(ckt->CKTstate0 + here->MESAvgs) - + *(ckt->CKTstate0 + here->MESAvgd); + delidgch = here->MESAdelidgch0*(1+lambda*vds); + delidvds = here->MESAdelidvds0*(1+2*lambda*vds) - + here->MESAdelidvds1; + gm = (delidgch*here->MESAgm0+here->MESAgm1)*here->MESAgm2; + gds = delidvds+here->MESAgds0; + + ggspp=*(ckt->CKTstate0 + here->MESAggspp); + ggdpp=*(ckt->CKTstate0 + here->MESAggdpp); + ggs= *(ckt->CKTstate0 + here->MESAggs) ; + xgs= *(ckt->CKTstate0 + here->MESAqgs) * ckt->CKTomega ; + ggd= *(ckt->CKTstate0 + here->MESAggd) ; + xgd= *(ckt->CKTstate0 + here->MESAqgd) * ckt->CKTomega ; + + *(here->MESAdrainDrainPtr) += here->MESAdrainConduct; + *(here->MESAsourceSourcePtr) += here->MESAsourceConduct; + *(here->MESAgateGatePtr) += here->MESAgateConduct; + *(here->MESAsourcePrmPrmSourcePrmPrmPtr) += (here->MESAtGi+ggspp); + *(here->MESAdrainPrmPrmDrainPrmPrmPtr) += (here->MESAtGf+ggdpp); + *(here->MESAdrainDrainPrimePtr) -= here->MESAdrainConduct; + *(here->MESAdrainPrimeDrainPtr) -= here->MESAdrainConduct; + *(here->MESAsourceSourcePrimePtr) -= here->MESAsourceConduct; + *(here->MESAsourcePrimeSourcePtr) -= here->MESAsourceConduct; + *(here->MESAgateGatePrimePtr) -= here->MESAgateConduct; + *(here->MESAgatePrimeGatePtr) -= here->MESAgateConduct; + *(here->MESAgatePrimeDrainPrimePtr) += (-ggd); + *(here->MESAgatePrimeSourcePrimePtr) += (-ggs); + *(here->MESAdrainPrimeGatePrimePtr) += (gm-ggd); + *(here->MESAdrainPrimeSourcePrimePtr) += (-gds-gm); + *(here->MESAsourcePrimeGatePrimePtr) += (-ggs-gm); + *(here->MESAsourcePrimeDrainPrimePtr) += (-gds); + *(here->MESAgatePrimeGatePrimePtr) += (ggd+ggs+here->MESAgateConduct+ggspp+ggdpp); + *(here->MESAdrainPrimeDrainPrimePtr) += (gds+ggd+here->MESAdrainConduct+here->MESAtGf); + *(here->MESAsourcePrimeSourcePrimePtr) += (gds+gm+ggs+here->MESAsourceConduct+here->MESAtGi); + *(here->MESAsourcePrimeSourcePrmPrmPtr) -= here->MESAtGi; + *(here->MESAsourcePrmPrmSourcePrimePtr) -= here->MESAtGi; + *(here->MESAgatePrimeSourcePrmPrmPtr) -= ggspp; + *(here->MESAsourcePrmPrmGatePrimePtr) -= ggspp; + *(here->MESAdrainPrimeDrainPrmPrmPtr) -= here->MESAtGf; + *(here->MESAdrainPrmPrmDrainPrimePtr) -= here->MESAtGf; + *(here->MESAgatePrimeDrainPrmPrmPtr) -= ggdpp; + *(here->MESAdrainPrmPrmGatePrimePtr) -= ggdpp; + *(here->MESAsourcePrmPrmSourcePrmPrmPtr+1) += xgs; + *(here->MESAdrainPrmPrmDrainPrmPrmPtr+1) += xgd; + *(here->MESAgatePrimeGatePrimePtr+1) += xgd+xgs; + *(here->MESAgatePrimeDrainPrmPrmPtr+1) -= xgd; + *(here->MESAdrainPrmPrmGatePrimePtr+1) -= xgd; + *(here->MESAgatePrimeSourcePrmPrmPtr+1) -= xgs; + *(here->MESAsourcePrmPrmGatePrimePtr+1) -= xgs; + } + } + return(OK); +} diff --git a/src/spicelib/devices/mesa/mesaask.c b/src/spicelib/devices/mesa/mesaask.c new file mode 100644 index 000000000..931f88342 --- /dev/null +++ b/src/spicelib/devices/mesa/mesaask.c @@ -0,0 +1,140 @@ +/********** +Copyright 1990 Regents of the University of California. All rights reserved. +Author: 1987 Thomas L. Quarles +**********/ +/* +Imported into MESA model: 2001 Paolo Nenzi + */ + +#include "ngspice.h" +#include +#include "cktdefs.h" +#include "devdefs.h" +#include "ifsim.h" +#include "mesadefs.h" +#include "sperror.h" +#include "suffix.h" + + +/* ARGSUSED */ +int +MESAask(ckt,inst,which,value,select) + CKTcircuit *ckt; + GENinstance *inst; + int which; + IFvalue *value; + IFvalue *select; +{ + MESAinstance *here = (MESAinstance*)inst; + static char *msg = "Current and power not available in ac analysis"; + switch(which) { + case MESA_LENGTH: + value->rValue = here->MESAlength; + return (OK); + case MESA_WIDTH: + value->rValue = here->MESAwidth; + return (OK); + case MESA_IC_VDS: + value->rValue = here->MESAicVDS; + return (OK); + case MESA_IC_VGS: + value->rValue = here->MESAicVGS; + return (OK); + case MESA_OFF: + value->iValue = here->MESAoff; + return (OK); + case MESA_TD: + value->rValue = here->MESAtd; + return (OK); + case MESA_TS: + value->rValue = here->MESAts; + return (OK); + case MESA_DRAINNODE: + value->iValue = here->MESAdrainNode; + return (OK); + case MESA_GATENODE: + value->iValue = here->MESAgateNode; + return (OK); + case MESA_SOURCENODE: + value->iValue = here->MESAsourceNode; + return (OK); + case MESA_DRAINPRIMENODE: + value->iValue = here->MESAdrainPrimeNode; + return (OK); + case MESA_SOURCEPRIMENODE: + value->iValue = here->MESAsourcePrimeNode; + return (OK); + case MESA_GATEPRIMENODE: + value->iValue = here->MESAgatePrimeNode; + return (OK); + case MESA_VGS: + value->rValue = *(ckt->CKTstate0 + here->MESAvgs); + return (OK); + case MESA_VGD: + value->rValue = *(ckt->CKTstate0 + here->MESAvgd); + return (OK); + case MESA_CG: + value->rValue = *(ckt->CKTstate0 + here->MESAcg); + return (OK); + case MESA_CD: + value->rValue = *(ckt->CKTstate0 + here->MESAcd); + return (OK); + case MESA_CGD: + value->rValue = *(ckt->CKTstate0 + here->MESAcgd); + return (OK); + case MESA_GM: + value->rValue = *(ckt->CKTstate0 + here->MESAgm); + return (OK); + case MESA_GDS: + value->rValue = *(ckt->CKTstate0 + here->MESAgds); + return (OK); + case MESA_GGS: + value->rValue = *(ckt->CKTstate0 + here->MESAggs); + return (OK); + case MESA_GGD: + value->rValue = *(ckt->CKTstate0 + here->MESAggd); + return (OK); + case MESA_QGS: + value->rValue = *(ckt->CKTstate0 + here->MESAqgs); + return (OK); + case MESA_CQGS: + value->rValue = *(ckt->CKTstate0 + here->MESAcqgs); + return (OK); + case MESA_QGD: + value->rValue = *(ckt->CKTstate0 + here->MESAqgd); + return (OK); + case MESA_CQGD: + value->rValue = *(ckt->CKTstate0 + here->MESAcqgd); + return (OK); + case MESA_CS : + if (ckt->CKTcurrentAnalysis & DOING_AC) { + errMsg = MALLOC(strlen(msg)+1); + errRtn = "MESAask"; + strcpy(errMsg,msg); + return(E_ASKCURRENT); + } else { + value->rValue = -*(ckt->CKTstate0 + here->MESAcd); + value->rValue -= *(ckt->CKTstate0 + here->MESAcg); + } + return(OK); + case MESA_POWER : + if (ckt->CKTcurrentAnalysis & DOING_AC) { + errMsg = MALLOC(strlen(msg)+1); + errRtn = "MESAask"; + strcpy(errMsg,msg); + return(E_ASKPOWER); + } else { + value->rValue = *(ckt->CKTstate0 + here->MESAcd) * + *(ckt->CKTrhsOld + here->MESAdrainNode); + value->rValue += *(ckt->CKTstate0 + here->MESAcg) * + *(ckt->CKTrhsOld + here->MESAgateNode); + value->rValue -= (*(ckt->CKTstate0+here->MESAcd) + + *(ckt->CKTstate0 + here->MESAcg)) * + *(ckt->CKTrhsOld + here->MESAsourceNode); + } + return(OK); + default: + return (E_BADPARM); + } + /* NOTREACHED */ +} diff --git a/src/spicelib/devices/mesa/mesadefs.h b/src/spicelib/devices/mesa/mesadefs.h new file mode 100644 index 000000000..2daf7b6fc --- /dev/null +++ b/src/spicelib/devices/mesa/mesadefs.h @@ -0,0 +1,467 @@ +/********** +Copyright 1993: T. Ytterdal, K. Lee, M. Shur and T. A. Fjeldly. All rights reserved. +Author: Trond Ytterdal +**********/ + +#ifndef MESA +#define MESA + +#include "ifsim.h" +#include "cktdefs.h" +#include "gendefs.h" +#include "complex.h" +#include "noisedef.h" + + /* structures used to describe MESFET Transistors */ + + +/* information used to describe a single instance */ + +typedef struct sMESAinstance { + struct sMESAmodel *MESAmodPtr; /* backpointer to model */ + struct sMESAinstance *MESAnextInstance; /* pointer to next instance of + * current model*/ + IFuid MESAname; /* pointer to character string naming this instance */ + int MESAowner; /* number of owner process */ + int MESAstate; /* pointer to start of state vector for MESAfet */ + + int MESAdrainNode; /* number of drain node of MESAfet */ + int MESAgateNode; /* number of gate node of MESAfet */ + int MESAsourceNode; /* number of source node of MESAfet */ + int MESAdrainPrimeNode; /* number of internal drain node of MESAfet */ + int MESAgatePrimeNode; /* number of internal gate node of MESAfet */ + int MESAsourcePrimeNode; /* number of internal source node of MESAfet */ + int MESAsourcePrmPrmNode; + int MESAdrainPrmPrmNode; + double MESAlength; /* length of MESAfet */ + double MESAwidth; /* width of MESAfet */ + double MESAicVDS; /* initial condition voltage D-S*/ + double MESAicVGS; /* initial condition voltage G-S*/ + double MESAtd; /* drain temperature */ + double MESAts; /* source temperature */ + double MESAtVto; + double MESAtLambda; + double MESAtLambdahf; + double MESAtEta; + double MESAtMu; + double MESAtPhib; + double MESAtTheta; + double MESAtRsi; + double MESAtRdi; + double MESAtRs; + double MESAtRd; + double MESAtRg; + double MESAtRi; + double MESAtRf; + double MESAtGi; + double MESAtGf; + double MESAdrainConduct; + double MESAsourceConduct; + double MESAgateConduct; + double *MESAdrainDrainPrimePtr; + double *MESAgatePrimeDrainPrimePtr; + double *MESAgatePrimeSourcePrimePtr; + double *MESAsourceSourcePrimePtr; + double *MESAdrainPrimeDrainPtr; + double *MESAdrainPrimeGatePrimePtr; + double *MESAdrainPrimeSourcePrimePtr; + double *MESAsourcePrimeGatePrimePtr; + double *MESAsourcePrimeSourcePtr; + double *MESAsourcePrimeDrainPrimePtr; + double *MESAdrainDrainPtr; + double *MESAgatePrimeGatePrimePtr; + double *MESAsourceSourcePtr; + double *MESAdrainPrimeDrainPrimePtr; + double *MESAsourcePrimeSourcePrimePtr; + double *MESAgateGatePrimePtr; + double *MESAgatePrimeGatePtr; + double *MESAgateGatePtr; + double *MESAsourcePrmPrmSourcePrmPrmPtr; + double *MESAsourcePrmPrmSourcePrimePtr; + double *MESAsourcePrimeSourcePrmPrmPtr; + double *MESAsourcePrmPrmGatePrimePtr; + double *MESAgatePrimeSourcePrmPrmPtr; + double *MESAdrainPrmPrmDrainPrmPrmPtr; + double *MESAdrainPrmPrmDrainPrimePtr; + double *MESAdrainPrimeDrainPrmPrmPtr; + double *MESAdrainPrmPrmGatePrimePtr; + double *MESAgatePrimeDrainPrmPrmPtr; + +#define MESAvgs MESAstate +#define MESAvgd MESAstate+1 +#define MESAcg MESAstate+2 +#define MESAcd MESAstate+3 +#define MESAcgd MESAstate+4 +#define MESAcgs MESAstate+5 +#define MESAgm MESAstate+6 +#define MESAgds MESAstate+7 +#define MESAggs MESAstate+8 +#define MESAggd MESAstate+9 +#define MESAqgs MESAstate+10 +#define MESAcqgs MESAstate+11 +#define MESAqgd MESAstate+12 +#define MESAcqgd MESAstate+13 +#define MESAvgspp MESAstate+14 +#define MESAggspp MESAstate+15 +#define MESAcgspp MESAstate+16 +#define MESAvgdpp MESAstate+17 +#define MESAggdpp MESAstate+18 +#define MESAcgdpp MESAstate+19 + + int MESAoff; + unsigned MESAlengthGiven : 1; + unsigned MESAwidthGiven : 1; + unsigned MESAicVDSGiven : 1; + unsigned MESAicVGSGiven : 1; + unsigned MESAtdGiven : 1; + unsigned MESAtsGiven : 1; + +int MESAmode; + +/* + * naming convention: + * x = vgs + * y = vgd + * z = vds + * cdr = cdrain + */ + +#define MESANDCOEFFS 27 + +#ifndef NODISTO + double MESAdCoeffs[MESANDCOEFFS]; +#else /* NODISTO */ + double *MESAdCoeffs; +#endif /* NODISTO */ + +#ifndef CONFIG + +#define cdr_x MESAdCoeffs[0] +#define cdr_z MESAdCoeffs[1] +#define cdr_x2 MESAdCoeffs[2] +#define cdr_z2 MESAdCoeffs[3] +#define cdr_xz MESAdCoeffs[4] +#define cdr_x3 MESAdCoeffs[5] +#define cdr_z3 MESAdCoeffs[6] +#define cdr_x2z MESAdCoeffs[7] +#define cdr_xz2 MESAdCoeffs[8] + +#define ggs3 MESAdCoeffs[9] +#define ggd3 MESAdCoeffs[10] +#define ggs2 MESAdCoeffs[11] +#define ggd2 MESAdCoeffs[12] + +#define qgs_x2 MESAdCoeffs[13] +#define qgs_y2 MESAdCoeffs[14] +#define qgs_xy MESAdCoeffs[15] +#define qgs_x3 MESAdCoeffs[16] +#define qgs_y3 MESAdCoeffs[17] +#define qgs_x2y MESAdCoeffs[18] +#define qgs_xy2 MESAdCoeffs[19] + +#define qgd_x2 MESAdCoeffs[20] +#define qgd_y2 MESAdCoeffs[21] +#define qgd_xy MESAdCoeffs[22] +#define qgd_x3 MESAdCoeffs[23] +#define qgd_y3 MESAdCoeffs[24] +#define qgd_x2y MESAdCoeffs[25] +#define qgd_xy2 MESAdCoeffs[26] + +#endif + +/* indices to the array of MESAFET noise sources */ + +#define MESARDNOIZ 0 +#define MESARSNOIZ 1 +#define MESAIDNOIZ 2 +#define MESAFLNOIZ 3 +#define MESATOTNOIZ 4 + +#define MESANSRCS 5 /* the number of MESAFET noise sources */ + +#ifndef NONOISE + double MESAnVar[NSTATVARS][MESANSRCS]; +#else /* NONOISE */ + double **MESAnVar; +#endif /* NONOISE */ + double MESAcsatfs; + double MESAcsatfd; + double MESAggrwl; + double MESAgchi0; + double MESAbeta; + double MESAisatb0; + double MESAimax; + double MESAcf; + double MESAfl; + double MESAdelf; + double MESAgds0; + double MESAgm0; + double MESAgm1; + double MESAgm2; + double MESAdelidvds0; + double MESAdelidvds1; + double MESAdelidgch0; + double MESAn0; + double MESAnsb0; + double MESAvcrits; + double MESAvcritd; +} MESAinstance ; + + +/* per model data */ + +typedef struct sMESAmodel { /* model structure for a MESAfet */ + int MESAmodType; /* type index of this device type */ + struct sMESAmodel *MESAnextModel; /* pointer to next possible model in + * linked list */ + MESAinstance * MESAinstances; /* pointer to list of instances + * that have this model */ + IFuid MESAmodName; /* pointer to character string naming this model */ + int MESAtype; + + double MESAthreshold; + double MESAlambda; + double MESAbeta; + double MESAvs; + double MESAeta; + double MESAm; + double MESAmc; + double MESAalpha; + double MESAsigma0; + double MESAvsigmat; + double MESAvsigma; + double MESAmu; + double MESAtheta; + double MESAmu1; + double MESAmu2; + double MESAd; + double MESAnd; + double MESAdu; + double MESAndu; + double MESAth; + double MESAndelta; + double MESAdelta; + double MESAtc; + double MESArdi; + double MESArsi; + double MESAdrainResist; + double MESAsourceResist; + double MESAgateResist; + double MESAri; + double MESArf; + double MESAphib; + double MESAphib1; + double MESAastar; + double MESAggr; + double MESAdel; + double MESAxchi; + double MESAn; + double MESAtvto; + double MESAtlambda; + double MESAteta0; + double MESAteta1; + double MESAtmu; + double MESAxtm0; + double MESAxtm1; + double MESAxtm2; + double MESAks; + double MESAvsg; + double MESAlambdahf; + double MESAtf; + double MESAflo; + double MESAdelfo; + double MESAag; + double MESAtc1; + double MESAtc2; + double MESAzeta; + double MESAlevel; + double MESAnmax; + double MESAgamma; + double MESAepsi; + double MESAcbs; + double MESAcas; + + double MESAsigma; + double MESAvpo; + double MESAvpou; + double MESAvpod; + double MESAdeltaSqr; + + unsigned MESAthresholdGiven:1; + unsigned MESAlambdaGiven:1; + unsigned MESAbetaGiven:1; + unsigned MESAvsGiven:1; + unsigned MESAetaGiven:1; + unsigned MESAmGiven:1; + unsigned MESAmcGiven:1; + unsigned MESAalphaGiven:1; + unsigned MESAsigma0Given:1; + unsigned MESAvsigmatGiven:1; + unsigned MESAvsigmaGiven:1; + unsigned MESAmuGiven:1; + unsigned MESAthetaGiven:1; + unsigned MESAmu1Given:1; + unsigned MESAmu2Given:1; + unsigned MESAdGiven:1; + unsigned MESAndGiven:1; + unsigned MESAduGiven:1; + unsigned MESAnduGiven:1; + unsigned MESAthGiven:1; + unsigned MESAndeltaGiven:1; + unsigned MESAdeltaGiven:1; + unsigned MESAtcGiven:1; + unsigned MESArdiGiven:1; + unsigned MESArsiGiven:1; + unsigned MESAdrainResistGiven:1; + unsigned MESAsourceResistGiven:1; + unsigned MESAgateResistGiven:1; + unsigned MESAriGiven:1; + unsigned MESArfGiven:1; + unsigned MESAphibGiven:1; + unsigned MESAphib1Given:1; + unsigned MESAastarGiven:1; + unsigned MESAggrGiven:1; + unsigned MESAdelGiven:1; + unsigned MESAxchiGiven:1; + unsigned MESAnGiven:1; + unsigned MESAtvtoGiven:1; + unsigned MESAtlambdaGiven:1; + unsigned MESAteta0Given:1; + unsigned MESAteta1Given:1; + unsigned MESAtmuGiven:1; + unsigned MESAxtm0Given:1; + unsigned MESAxtm1Given:1; + unsigned MESAxtm2Given:1; + unsigned MESAksGiven:1; + unsigned MESAvsgGiven:1; + unsigned MESAlambdahfGiven:1; + unsigned MESAtfGiven:1; + unsigned MESAfloGiven:1; + unsigned MESAdelfoGiven:1; + unsigned MESAagGiven:1; + unsigned MESAtc1Given:1; + unsigned MESAtc2Given:1; + unsigned MESAzetaGiven:1; + unsigned MESAlevelGiven:1; + unsigned MESAnmaxGiven:1; + unsigned MESAgammaGiven:1; + unsigned MESAepsiGiven:1; + unsigned MESAcbsGiven:1; + unsigned MESAcasGiven:1; + +} MESAmodel; + +#ifndef NMF + +#define NMF 1 +#define PMF -1 +#endif + +/* device parameters */ +#define MESA_LENGTH 1 +#define MESA_WIDTH 2 +#define MESA_IC_VDS 3 +#define MESA_IC_VGS 4 +#define MESA_TD 5 +#define MESA_TS 6 +#define MESA_IC 7 +#define MESA_OFF 8 +#define MESA_CS 9 +#define MESA_POWER 10 + +/* model parameters */ +#define MESA_MOD_VTO 101 +#define MESA_MOD_VS 102 +#define MESA_MOD_LAMBDA 103 +#define MESA_MOD_RD 104 +#define MESA_MOD_RS 105 +#define MESA_MOD_RG 106 +#define MESA_MOD_RI 107 +#define MESA_MOD_RF 108 +#define MESA_MOD_RDI 109 +#define MESA_MOD_RSI 110 +#define MESA_MOD_PHIB 111 +#define MESA_MOD_PHIB1 112 +#define MESA_MOD_ASTAR 113 +#define MESA_MOD_GGR 114 +#define MESA_MOD_DEL 115 +#define MESA_MOD_XCHI 116 +#define MESA_MOD_N 117 +#define MESA_MOD_ETA 118 +#define MESA_MOD_M 119 +#define MESA_MOD_MC 120 +#define MESA_MOD_SIGMA0 121 +#define MESA_MOD_VSIGMAT 122 +#define MESA_MOD_VSIGMA 123 +#define MESA_MOD_MU 124 +#define MESA_MOD_MU1 125 +#define MESA_MOD_MU2 126 +#define MESA_MOD_D 127 +#define MESA_MOD_ND 128 +#define MESA_MOD_DELTA 129 +#define MESA_MOD_TC 130 +#define MESA_MOD_NMF 131 +#define MESA_MOD_TVTO 132 +#define MESA_MOD_TLAMBDA 134 +#define MESA_MOD_TETA0 135 +#define MESA_MOD_TETA1 136 +#define MESA_MOD_TMU 137 +#define MESA_MOD_XTM0 138 +#define MESA_MOD_XTM1 139 +#define MESA_MOD_XTM2 140 +#define MESA_MOD_KS 141 +#define MESA_MOD_VSG 142 +#define MESA_MOD_LAMBDAHF 143 +#define MESA_MOD_TF 144 +#define MESA_MOD_FLO 145 +#define MESA_MOD_DELFO 146 +#define MESA_MOD_AG 147 +#define MESA_MOD_THETA 148 +#define MESA_MOD_ALPHA 149 +#define MESA_MOD_TC1 150 +#define MESA_MOD_TC2 151 +#define MESA_MOD_ZETA 152 +#define MESA_MOD_BETA 153 +#define MESA_MOD_DU 154 +#define MESA_MOD_NDU 155 +#define MESA_MOD_TH 156 +#define MESA_MOD_NDELTA 157 +#define MESA_MOD_LEVEL 158 +#define MESA_MOD_NMAX 159 +#define MESA_MOD_GAMMA 160 +#define MESA_MOD_EPSI 161 +#define MESA_MOD_CBS 162 +#define MESA_MOD_CAS 163 +#define MESA_MOD_PMF 164 +#define MESA_MOD_TYPE 165 + +#define MESA_DRAINNODE 201 +#define MESA_GATENODE 202 +#define MESA_SOURCENODE 203 +#define MESA_DRAINPRIMENODE 204 +#define MESA_SOURCEPRIMENODE 205 +#define MESA_GATEPRIMENODE 206 + +#define MESA_VGS 207 +#define MESA_VGD 208 +#define MESA_CG 209 +#define MESA_CD 210 +#define MESA_CGD 211 +#define MESA_GM 212 +#define MESA_GDS 213 +#define MESA_GGS 214 +#define MESA_GGD 215 +#define MESA_QGS 216 +#define MESA_CQGS 217 +#define MESA_QGD 218 +#define MESA_CQGD 219 + +#define MESA_MOD_DRAINCONDUCT 301 +#define MESA_MOD_SOURCECONDUCT 302 +#define MESA_MOD_GATECONDUCT 303 +#define MESA_MOD_DEPLETIONCAP 304 +#define MESA_MOD_VCRIT 305 + +#include "mesaext.h" + +#endif /*MESA*/ diff --git a/src/spicelib/devices/mesa/mesadel.c b/src/spicelib/devices/mesa/mesadel.c new file mode 100644 index 000000000..7df0bcfd9 --- /dev/null +++ b/src/spicelib/devices/mesa/mesadel.c @@ -0,0 +1,39 @@ +/********** +Copyright 1990 Regents of the University of California. All rights reserved. +Author: 1985 S. Hwang +**********/ +/* +Imported into mesa model: 2001 Paolo Nenzi + */ + +#include "ngspice.h" +#include +#include "mesadefs.h" +#include "sperror.h" +#include "suffix.h" + + +int +MESAdelete(inModel,name,inst) + GENmodel *inModel; + IFuid name; + GENinstance **inst; +{ + MESAmodel *model = (MESAmodel*)inModel; + MESAinstance **fast = (MESAinstance**)inst; + MESAinstance **prev = NULL; + MESAinstance *here; + + for( ; model ; model = model->MESAnextModel) { + prev = &(model->MESAinstances); + for(here = *prev; here ; here = *prev) { + if(here->MESAname == name || (fast && here==*fast) ) { + *prev= here->MESAnextInstance; + FREE(here); + return(OK); + } + prev = &(here->MESAnextInstance); + } + } + return(E_NODEV); +} diff --git a/src/spicelib/devices/mesa/mesadest.c b/src/spicelib/devices/mesa/mesadest.c new file mode 100644 index 000000000..56cd32313 --- /dev/null +++ b/src/spicelib/devices/mesa/mesadest.c @@ -0,0 +1,35 @@ +/********** +Copyright 1993: T. Ytterdal, K. Lee, M. Shur and T. A. Fjeldly. All rights reserved. +Author: Trond Ytterdal +**********/ + +#include "ngspice.h" +#include +#include "mesadefs.h" +#include "suffix.h" + + +void +MESAdestroy(inModel) + GENmodel **inModel; +{ + MESAmodel **model = (MESAmodel**)inModel; + MESAinstance *here; + MESAinstance *prev = NULL; + MESAmodel *mod = *model; + MESAmodel *oldmod = NULL; + + for( ; mod ; mod = mod->MESAnextModel) { + if(oldmod) FREE(oldmod); + oldmod = mod; + prev = (MESAinstance *)NULL; + for(here = mod->MESAinstances ; here ; here = here->MESAnextInstance) { + if(prev) FREE(prev); + prev = here; + } + if(prev) FREE(prev); + } + if(oldmod) FREE(oldmod); + *model = NULL; + return; +} diff --git a/src/spicelib/devices/mesa/mesaext.h b/src/spicelib/devices/mesa/mesaext.h new file mode 100644 index 000000000..39db02e25 --- /dev/null +++ b/src/spicelib/devices/mesa/mesaext.h @@ -0,0 +1,37 @@ +/********** +Copyright 1993: T. Ytterdal, K. Lee, M. Shur and T. A. Fjeldly. All rights reserved. +Author: Trond Ytterdal +**********/ + +#ifdef __STDC__ +extern int MESAacLoad(GENmodel*,CKTcircuit*); +extern int MESAask(CKTcircuit*,GENinstance*,int,IFvalue*,IFvalue*); +extern int MESAdelete(GENmodel*,IFuid,GENinstance**); +extern void MESAdestroy(GENmodel**); +extern int MESAgetic(GENmodel*,CKTcircuit*); +extern int MESAload(GENmodel*,CKTcircuit*); +extern int MESAmAsk(CKTcircuit*,GENmodel*,int,IFvalue*); +extern int MESAmDelete(GENmodel**,IFuid,GENmodel*); +extern int MESAmParam(int,IFvalue*,GENmodel*); +extern int MESAparam(int,IFvalue*,GENinstance*,IFvalue*); +extern int MESAsetup(SMPmatrix*,GENmodel*,CKTcircuit*,int*); +extern int MESAtemp(GENmodel*,CKTcircuit*); +extern int MESAtrunc(GENmodel*,CKTcircuit*,double*); +extern int MESAunsetup(GENmodel*,CKTcircuit*); + +#else /*stdc*/ +extern int MESAacLoad(); +extern int MESAask(); +extern int MESAdelete(); +extern void MESAdestroy(); +extern int MESAgetic(); +extern int MESAload(); +extern int MESAmAsk(); +extern int MESAmDelete(); +extern int MESAmParam(); +extern int MESAparam(); +extern int MESAsetup(); +extern int MESAtemp(); +extern int MESAtrunc(); +extern int MESAunsetup(); +#endif diff --git a/src/spicelib/devices/mesa/mesagetic.c b/src/spicelib/devices/mesa/mesagetic.c new file mode 100644 index 000000000..160ab4429 --- /dev/null +++ b/src/spicelib/devices/mesa/mesagetic.c @@ -0,0 +1,41 @@ +/********** +Copyright 1993: T. Ytterdal, K. Lee, M. Shur and T. A. Fjeldly. All rights reserved. +Author: Trond Ytterdal +**********/ + +#include "ngspice.h" +#include +#include "cktdefs.h" +#include "mesadefs.h" +#include "sperror.h" +#include "suffix.h" + + +int +MESAgetic(inModel,ckt) + GENmodel *inModel; + CKTcircuit *ckt; +{ + MESAmodel *model = (MESAmodel*)inModel; + MESAinstance *here; + /* + * grab initial conditions out of rhs array. User specified, so use + * external nodes to get values + */ + + for( ; model ; model = model->MESAnextModel) { + for(here = model->MESAinstances; here ; here = here->MESAnextInstance) { + if(!here->MESAicVDSGiven) { + here->MESAicVDS = + *(ckt->CKTrhs + here->MESAdrainNode) - + *(ckt->CKTrhs + here->MESAsourceNode); + } + if(!here->MESAicVGSGiven) { + here->MESAicVGS = + *(ckt->CKTrhs + here->MESAgateNode) - + *(ckt->CKTrhs + here->MESAsourceNode); + } + } + } + return(OK); +} diff --git a/src/spicelib/devices/mesa/mesainit.c b/src/spicelib/devices/mesa/mesainit.c new file mode 100644 index 000000000..5e1cc38ad --- /dev/null +++ b/src/spicelib/devices/mesa/mesainit.c @@ -0,0 +1,65 @@ +#include + +#include + +#include "mesaitf.h" +#include "mesaext.h" +#include "mesainit.h" + + +SPICEdev MESAinfo = { + { + "MESA", + "GaAs MESFET model", + + &MESAnSize, + &MESAnSize, + MESAnames, + + &MESApTSize, + MESApTable, + + &MESAmPTSize, + MESAmPTable, + DEV_DEFAULT + }, + + DEVparam : MESAparam, + DEVmodParam : MESAmParam, + DEVload : MESAload, + DEVsetup : MESAsetup, + DEVunsetup : MESAunsetup, + DEVpzSetup : MESAsetup, + DEVtemperature: MESAtemp, + DEVtrunc : MESAtrunc, + DEVfindBranch : NULL, + DEVacLoad : MESAacLoad, + DEVaccept : NULL, + DEVdestroy : MESAdestroy, + DEVmodDelete : MESAmDelete, + DEVdelete : MESAdelete, + DEVsetic : MESAgetic, + DEVask : MESAask, + DEVmodAsk : MESAmAsk, + DEVpzLoad : NULL, + DEVconvTest : NULL, + DEVsenSetup : NULL, + DEVsenLoad : NULL, + DEVsenUpdate : NULL, + DEVsenAcLoad : NULL, + DEVsenPrint : NULL, + DEVsenTrunc : NULL, + DEVdisto : NULL, + DEVnoise : NULL, + + DEVinstSize : &MESAiSize, + DEVmodSize : &MESAmSize + +}; + + +SPICEdev * +get_mesa_info(void) +{ + return &MESAinfo; +} diff --git a/src/spicelib/devices/mesa/mesainit.h b/src/spicelib/devices/mesa/mesainit.h new file mode 100644 index 000000000..aa4420569 --- /dev/null +++ b/src/spicelib/devices/mesa/mesainit.h @@ -0,0 +1,13 @@ +#ifndef _MESAINIT_H +#define _MESAINIT_H + +extern IFparm MESApTable[ ]; +extern IFparm MESAmPTable[ ]; +extern char *MESAnames[ ]; +extern int MESApTSize; +extern int MESAmPTSize; +extern int MESAnSize; +extern int MESAiSize; +extern int MESAmSize; + +#endif diff --git a/src/spicelib/devices/mesa/mesaitf.h b/src/spicelib/devices/mesa/mesaitf.h new file mode 100644 index 000000000..36493b837 --- /dev/null +++ b/src/spicelib/devices/mesa/mesaitf.h @@ -0,0 +1,9 @@ +/********** +Copyright 1990 Regents of the University of California. All rights reserved. +**********/ +#ifndef DEV_MESA +#define DEV_MESA + +SPICEdev *get_mesa_info(void); + +#endif diff --git a/src/spicelib/devices/mesa/mesaload.c b/src/spicelib/devices/mesa/mesaload.c new file mode 100644 index 000000000..cd6444cef --- /dev/null +++ b/src/spicelib/devices/mesa/mesaload.c @@ -0,0 +1,987 @@ +/********** +Copyright 1993: T. Ytterdal, K. Lee, M. Shur and T. A. Fjeldly. All rights reserved. +Author: Trond Ytterdal +**********/ + +#include "ngspice.h" +#include +#include "devdefs.h" +#include "cktdefs.h" +#include "mesadefs.h" +#include "const.h" +#include "trandefs.h" +#include "sperror.h" +#include "suffix.h" + +/* +#define true 1 +#define false 0 +*/ + +#define EPSILONGAAS (12.244*8.85418e-12) + +#define W (here->MESAwidth) +#define L (here->MESAlength) + +static void mesa1(MESAmodel*, MESAinstance*, double, double, double, + double*, double*, double*, double*,double*); + +static void mesa2(MESAmodel*, MESAinstance*, double, double, double, + double*, double*, double*, double*,double*); + +static void mesa3(MESAmodel*, MESAinstance*, double, double, double, + double*, double*, double*, double*,double*); + +void Pause(void); + +int +MESAload(inModel,ckt) + GENmodel *inModel; + //register CKTcircuit *ckt; + CKTcircuit *ckt; +{ + MESAmodel *model = (MESAmodel*)inModel; + MESAinstance *here; + double capgd; + double capgs; + double cd; + double cdhat; + double cdrain; + double cdreq; + double ceq; + double ceqgd; + double ceqgs; + double cg; + double cgd; + double cgs; + double cghat; + double arg; + double earg; + double delvds; + double delvgd; + double delvgs; + double delvgspp=0; + double delvgdpp=0; + double evgd; + double evgs; + double gds; + double geq; + double ggd; + double ggs; + double gm; + double ggspp=0; + double cgspp=0; + double ggdpp=0; + double cgdpp=0; + double vcrits; + double vcritd; + double vds=0; + double vgd=0; + double vgs=0; + double vgspp=0; + double vgdpp=0; + double vgs1=0; + double vgd1=0; + double xfact; + double temp; + double vted; + double vtes; + double vtd; + double vts; + double von; + double ccorr; + int inverse=FALSE; + int icheck; + int ichk1; + int error; + + /* loop through all the models */ + for( ; model != NULL; model = model->MESAnextModel ) { + + /* loop through all the instances of the model */ + for (here = model->MESAinstances; here != NULL ; + here=here->MESAnextInstance) { + + /* + * dc model parameters + */ + vcrits = here->MESAvcrits; + vcritd = here->MESAvcritd; + vtd = CONSTKoverQ * here->MESAtd; + vts = CONSTKoverQ * here->MESAts; + vted = model->MESAn*vtd; + vtes = model->MESAn*vts; + /* + * initialization + */ + icheck = 1; + if( ckt->CKTmode & MODEINITSMSIG) { + vgs = *(ckt->CKTstate0 + here->MESAvgs); + vgd = *(ckt->CKTstate0 + here->MESAvgd); + vgspp = *(ckt->CKTstate0 + here->MESAvgspp); + vgdpp = *(ckt->CKTstate0 + here->MESAvgdpp); + } else if (ckt->CKTmode & MODEINITTRAN) { + vgs = *(ckt->CKTstate1 + here->MESAvgs); + vgd = *(ckt->CKTstate1 + here->MESAvgd); + vgspp = *(ckt->CKTstate1 + here->MESAvgspp); + vgdpp = *(ckt->CKTstate1 + here->MESAvgdpp); + } else if ( (ckt->CKTmode & MODEINITJCT) && + (ckt->CKTmode & MODETRANOP) && + (ckt->CKTmode & MODEUIC) ) { + vds = here->MESAicVDS; + vgs = here->MESAicVGS; + vgd = vgs-vds; + vgspp = vgs; + vgdpp = vgd; + } else if ( (ckt->CKTmode & MODEINITJCT) && + (here->MESAoff == 0) ) { + vgs = -1; + vgd = -1; + vgspp = 0; + vgdpp = 0; + } else if( (ckt->CKTmode & MODEINITJCT) || + ((ckt->CKTmode & MODEINITFIX) && (here->MESAoff))) { + vgs = 0; + vgd = 0; + vgspp = 0; + vgdpp = 0; + } else { +#ifndef PREDICTOR + if(ckt->CKTmode & MODEINITPRED) { + xfact = ckt->CKTdelta/ckt->CKTdeltaOld[2]; + *(ckt->CKTstate0 + here->MESAvgs) = + *(ckt->CKTstate1 + here->MESAvgs); + vgs = (1+xfact) * *(ckt->CKTstate1 + here->MESAvgs) - + xfact * *(ckt->CKTstate2 + here->MESAvgs); + *(ckt->CKTstate0 + here->MESAvgspp) = + *(ckt->CKTstate1 + here->MESAvgspp); + vgspp = (1+xfact) * *(ckt->CKTstate1 + here->MESAvgspp) - + xfact * *(ckt->CKTstate2 + here->MESAvgspp); + *(ckt->CKTstate0 + here->MESAvgd) = + *(ckt->CKTstate1 + here->MESAvgd); + vgd = (1+xfact)* *(ckt->CKTstate1 + here->MESAvgd) - + xfact * *(ckt->CKTstate2 + here->MESAvgd); + *(ckt->CKTstate0 + here->MESAvgdpp) = + *(ckt->CKTstate1 + here->MESAvgdpp); + vgdpp = (1+xfact) * *(ckt->CKTstate1 + here->MESAvgdpp) - + xfact * *(ckt->CKTstate2 + here->MESAvgdpp); + *(ckt->CKTstate0 + here->MESAcg) = + *(ckt->CKTstate1 + here->MESAcg); + *(ckt->CKTstate0 + here->MESAcd) = + *(ckt->CKTstate1 + here->MESAcd); + *(ckt->CKTstate0 + here->MESAcgd) = + *(ckt->CKTstate1 + here->MESAcgd); + *(ckt->CKTstate0 + here->MESAcgs) = + *(ckt->CKTstate1 + here->MESAcgs); + *(ckt->CKTstate0 + here->MESAgm) = + *(ckt->CKTstate1 + here->MESAgm); + *(ckt->CKTstate0 + here->MESAgds) = + *(ckt->CKTstate1 + here->MESAgds); + *(ckt->CKTstate0 + here->MESAggs) = + *(ckt->CKTstate1 + here->MESAggs); + *(ckt->CKTstate0 + here->MESAggd) = + *(ckt->CKTstate1 + here->MESAggd); + *(ckt->CKTstate0 + here->MESAggspp) = + *(ckt->CKTstate1 + here->MESAggspp); + *(ckt->CKTstate0 + here->MESAcgspp) = + *(ckt->CKTstate1 + here->MESAcgspp); + *(ckt->CKTstate0 + here->MESAggdpp) = + *(ckt->CKTstate1 + here->MESAggdpp); + *(ckt->CKTstate0 + here->MESAcgdpp) = + *(ckt->CKTstate1 + here->MESAcgdpp); + } else { +#endif /* PREDICTOR */ + /* + * compute new nonlinear branch voltages + */ + vgs = (*(ckt->CKTrhsOld+ here->MESAgatePrimeNode)- + *(ckt->CKTrhsOld+here->MESAsourcePrimeNode)); + vgd = (*(ckt->CKTrhsOld+here->MESAgatePrimeNode)- + *(ckt->CKTrhsOld+here->MESAdrainPrimeNode)); + vgspp = (*(ckt->CKTrhsOld+here->MESAgatePrimeNode)- + *(ckt->CKTrhsOld+here->MESAsourcePrmPrmNode)); + vgdpp = (*(ckt->CKTrhsOld+here->MESAgatePrimeNode)- + *(ckt->CKTrhsOld+here->MESAdrainPrmPrmNode)); + +#ifndef PREDICTOR + } +#endif /* PREDICTOR */ + delvgs=vgs - *(ckt->CKTstate0 + here->MESAvgs); + delvgd=vgd - *(ckt->CKTstate0 + here->MESAvgd); + delvds=delvgs - delvgd; + delvgspp = vgspp - *(ckt->CKTstate0 + here->MESAvgspp); + delvgdpp = vgdpp - *(ckt->CKTstate0 + here->MESAvgdpp); + cghat= *(ckt->CKTstate0 + here->MESAcg) + + *(ckt->CKTstate0 + here->MESAggd)*delvgd + + *(ckt->CKTstate0 + here->MESAggs)*delvgs + + *(ckt->CKTstate0 + here->MESAggspp)*delvgspp+ + *(ckt->CKTstate0 + here->MESAggdpp)*delvgdpp; + cdhat= *(ckt->CKTstate0 + here->MESAcd) + + *(ckt->CKTstate0 + here->MESAgm)*delvgs + + *(ckt->CKTstate0 + here->MESAgds)*delvds - + *(ckt->CKTstate0 + here->MESAggd)*delvgd; + /* + * bypass if solution has not changed + */ + if((ckt->CKTbypass) && + (!(ckt->CKTmode & MODEINITPRED)) && + (fabs(delvgs) < ckt->CKTreltol*MAX(fabs(vgs), + fabs(*(ckt->CKTstate0 + here->MESAvgs)))+ + ckt->CKTvoltTol) ) + if((fabs(delvgd) < ckt->CKTreltol*MAX(fabs(vgd), + fabs(*(ckt->CKTstate0 + here->MESAvgd)))+ + ckt->CKTvoltTol)) + if((fabs(delvgspp) < ckt->CKTreltol*MAX(fabs(vgspp), + fabs(*(ckt->CKTstate0 + here->MESAvgspp)))+ + ckt->CKTvoltTol)) + if((fabs(delvgdpp) < ckt->CKTreltol*MAX(fabs(vgdpp), + fabs(*(ckt->CKTstate0 + here->MESAvgdpp)))+ + ckt->CKTvoltTol)) + if((fabs(cghat-*(ckt->CKTstate0 + here->MESAcg)) + < ckt->CKTreltol*MAX(fabs(cghat), + fabs(*(ckt->CKTstate0 + here->MESAcg)))+ + ckt->CKTabstol)) + if((fabs(cdhat-*(ckt->CKTstate0 + here->MESAcd)) + < ckt->CKTreltol*MAX(fabs(cdhat), + fabs(*(ckt->CKTstate0 + here->MESAcd)))+ + ckt->CKTabstol)) { + + /* we can do a bypass */ + vgs= *(ckt->CKTstate0 + here->MESAvgs); + vgd= *(ckt->CKTstate0 + here->MESAvgd); + vds= vgs-vgd; + vgspp = *(ckt->CKTstate0 + here->MESAvgspp); + vgdpp = *(ckt->CKTstate0 + here->MESAvgdpp); + cg= *(ckt->CKTstate0 + here->MESAcg); + cd= *(ckt->CKTstate0 + here->MESAcd); + cgs= *(ckt->CKTstate0 + here->MESAcgs); + cgd= *(ckt->CKTstate0 + here->MESAcgd); + gm= *(ckt->CKTstate0 + here->MESAgm); + gds= *(ckt->CKTstate0 + here->MESAgds); + ggs= *(ckt->CKTstate0 + here->MESAggs); + ggd= *(ckt->CKTstate0 + here->MESAggd); + ggspp = *(ckt->CKTstate0 + here->MESAggspp); + cgspp = *(ckt->CKTstate0 + here->MESAcgspp); + ggdpp = *(ckt->CKTstate0 + here->MESAggdpp); + cgdpp = *(ckt->CKTstate0 + here->MESAcgdpp); + goto load; + } + /* + * limit nonlinear branch voltages + */ + ichk1=1; + vgs = DEVpnjlim(vgs,*(ckt->CKTstate0 + here->MESAvgs),vtes, + vcrits, &icheck); + vgd = DEVpnjlim(vgd,*(ckt->CKTstate0 + here->MESAvgd),vted, + vcritd,&ichk1); + if (ichk1 == 1) { + icheck=1; + } + vgs = DEVfetlim(vgs,*(ckt->CKTstate0 + here->MESAvgs), + here->MESAtVto); + vgd = DEVfetlim(vgd,*(ckt->CKTstate0 + here->MESAvgd), + here->MESAtVto); + if(here->MESAsourcePrmPrmNode == here->MESAsourcePrimeNode) + vgspp = vgs; + if(here->MESAdrainPrmPrmNode == here->MESAdrainPrimeNode) + vgdpp = vgd; + } + /* + * determine dc current and derivatives + */ + vds = vgs-vgd; + + arg = -vgs*model->MESAdel/vts; + earg = exp(arg); + evgs = exp(vgs/vtes); + ggs = here->MESAcsatfs*evgs/vtes+here->MESAggrwl*earg*(1-arg)+ckt->CKTgmin; + cgs = here->MESAcsatfs*(evgs-1)+here->MESAggrwl*vgs*earg+ + ckt->CKTgmin*vgs; + cg = cgs; + + arg = -vgd*model->MESAdel/vtd; + earg = exp(arg); + evgd = exp(vgd/vted); + ggd = here->MESAcsatfd*evgd/vted+here->MESAggrwl*earg*(1-arg)+ckt->CKTgmin; + cgd = here->MESAcsatfd*(evgd-1)+here->MESAggrwl*vgd*earg+ + ckt->CKTgmin*vgd; + cg = cg+cgd; + + if(vds < 0) { + vds = -vds; + inverse = TRUE; + } + von = here->MESAtVto+model->MESAks*(*(ckt->CKTrhsOld+here->MESAsourcePrimeNode)-model->MESAvsg); + if(model->MESAlevel == 2) + mesa1(model,here,inverse?vgd:vgs,vds,von,&cdrain,&gm,&gds,&capgs,&capgd); + else if(model->MESAlevel == 3) + mesa2(model,here,inverse?vgd:vgs,vds,von,&cdrain,&gm,&gds,&capgs,&capgd); + else if(model->MESAlevel == 4) + mesa3(model,here,inverse?vgd:vgs,vds,von,&cdrain,&gm,&gds,&capgs,&capgd); + if(inverse) { + cdrain = -cdrain; + vds = -vds; + temp = capgs; + capgs = capgd; + capgd = temp; + } + /* + * compute equivalent drain current source + */ + cd = cdrain - cgd; + if ( (ckt->CKTmode & (MODETRAN|MODEINITSMSIG)) || + ((ckt->CKTmode & MODETRANOP) && (ckt->CKTmode & MODEUIC)) ){ + /* + * charge storage elements + */ + vgs1 = *(ckt->CKTstate1 + here->MESAvgspp); + vgd1 = *(ckt->CKTstate1 + here->MESAvgdpp); + + if(ckt->CKTmode & MODEINITTRAN) { + *(ckt->CKTstate1 + here->MESAqgs) = capgs*vgspp; + *(ckt->CKTstate1 + here->MESAqgd) = capgd*vgdpp; + } + *(ckt->CKTstate0+here->MESAqgs) = *(ckt->CKTstate1 + here->MESAqgs) + + capgs*(vgspp-vgs1); + *(ckt->CKTstate0+here->MESAqgd) = *(ckt->CKTstate1 + here->MESAqgd) + + capgd*(vgdpp-vgd1); + + /* + * store small-signal parameters + */ + if( (!(ckt->CKTmode & MODETRANOP)) || + (!(ckt->CKTmode & MODEUIC)) ) { + if(ckt->CKTmode & MODEINITSMSIG) { + *(ckt->CKTstate0 + here->MESAqgs) = capgs; + *(ckt->CKTstate0 + here->MESAqgd) = capgd; + continue; /*go to 1000*/ + } + /* + * transient analysis + */ + if(ckt->CKTmode & MODEINITTRAN) { + *(ckt->CKTstate1 + here->MESAqgs) = + *(ckt->CKTstate0 + here->MESAqgs); + *(ckt->CKTstate1 + here->MESAqgd) = + *(ckt->CKTstate0 + here->MESAqgd); + } + error = NIintegrate(ckt,&geq,&ceq,capgs,here->MESAqgs); + if(error) return(error); + ggspp = geq; + cgspp = *(ckt->CKTstate0 + here->MESAcqgs); + cg = cg + cgspp; + error = NIintegrate(ckt,&geq,&ceq,capgd,here->MESAqgd); + if(error) return(error); + ggdpp = geq; + cgdpp = *(ckt->CKTstate0 + here->MESAcqgd); + cg = cg + cgdpp; + cd = cd - cgdpp; + if (ckt->CKTmode & MODEINITTRAN) { + *(ckt->CKTstate1 + here->MESAcqgs) = + *(ckt->CKTstate0 + here->MESAcqgs); + *(ckt->CKTstate1 + here->MESAcqgd) = + *(ckt->CKTstate0 + here->MESAcqgd); + } + } + } + /* + * check convergence + */ + if( (!(ckt->CKTmode & MODEINITFIX)) | (!(ckt->CKTmode & MODEUIC))) { + if( (icheck == 1) + || (fabs(cghat-cg) >= ckt->CKTreltol* + MAX(fabs(cghat),fabs(cg))+ckt->CKTabstol) || + (fabs(cdhat-cd) > ckt->CKTreltol* + MAX(fabs(cdhat),fabs(cd))+ckt->CKTabstol) + ) { + ckt->CKTnoncon++; + } + } + *(ckt->CKTstate0 + here->MESAvgs) = vgs; + *(ckt->CKTstate0 + here->MESAvgspp) = vgspp; + *(ckt->CKTstate0 + here->MESAvgd) = vgd; + *(ckt->CKTstate0 + here->MESAvgdpp) = vgdpp; + *(ckt->CKTstate0 + here->MESAcg) = cg; + *(ckt->CKTstate0 + here->MESAcd) = cd; + *(ckt->CKTstate0 + here->MESAcgd) = cgd; + *(ckt->CKTstate0 + here->MESAcgs) = cgs; + *(ckt->CKTstate0 + here->MESAgm) = gm; + *(ckt->CKTstate0 + here->MESAgds) = gds; + *(ckt->CKTstate0 + here->MESAggs) = ggs; + *(ckt->CKTstate0 + here->MESAggd) = ggd; + *(ckt->CKTstate0 + here->MESAggspp) = ggspp; + *(ckt->CKTstate0 + here->MESAcgspp) = cgspp; + *(ckt->CKTstate0 + here->MESAggdpp) = ggdpp; + *(ckt->CKTstate0 + here->MESAcgdpp) = cgdpp; + + /* + * load current vector + */ +load: + ccorr = model->MESAag*(cgs-cgd); + ceqgd = cgd + cgdpp - ggd*vgd - ggdpp*vgdpp; + ceqgs = cgs + cgspp - ggs*vgs - ggspp*vgspp; + cdreq=((cd+cgd+cgdpp)-gds*vds-gm*vgs); + *(ckt->CKTrhs + here->MESAgatePrimeNode) += (-ceqgs-ceqgd); + ceqgd = (cgd-ggd*vgd); + *(ckt->CKTrhs + here->MESAdrainPrimeNode) += (-cdreq+ceqgd+ccorr); + ceqgd = (cgdpp-ggdpp*vgdpp); + *(ckt->CKTrhs + here->MESAdrainPrmPrmNode) += ceqgd; + ceqgs = (cgs-ggs*vgs); + *(ckt->CKTrhs + here->MESAsourcePrimeNode) += (cdreq+ceqgs-ccorr); + ceqgs = (cgspp-ggspp*vgspp); + *(ckt->CKTrhs + here->MESAsourcePrmPrmNode) += ceqgs; + + /* + * load y matrix + */ + *(here->MESAdrainDrainPtr) += here->MESAdrainConduct; + *(here->MESAsourceSourcePtr) += here->MESAsourceConduct; + *(here->MESAgateGatePtr) += here->MESAgateConduct; + *(here->MESAsourcePrmPrmSourcePrmPrmPtr) += (here->MESAtGi+ggspp); + *(here->MESAdrainPrmPrmDrainPrmPrmPtr) += (here->MESAtGf+ggdpp); + *(here->MESAgatePrimeGatePrimePtr) += (ggd+ggs+here->MESAgateConduct+ggspp+ggdpp); + *(here->MESAdrainPrimeDrainPrimePtr) += (gds+ggd+here->MESAdrainConduct+here->MESAtGf); + *(here->MESAsourcePrimeSourcePrimePtr) += (gds+gm+ggs+here->MESAsourceConduct+here->MESAtGi); + *(here->MESAdrainDrainPrimePtr) -= here->MESAdrainConduct; + *(here->MESAdrainPrimeDrainPtr) -= here->MESAdrainConduct; + *(here->MESAsourceSourcePrimePtr) -= here->MESAsourceConduct; + *(here->MESAsourcePrimeSourcePtr) -= here->MESAsourceConduct; + *(here->MESAgateGatePrimePtr) -= here->MESAgateConduct; + *(here->MESAgatePrimeGatePtr) -= here->MESAgateConduct; + *(here->MESAgatePrimeDrainPrimePtr) -= ggd; + *(here->MESAgatePrimeSourcePrimePtr) -= ggs; + *(here->MESAdrainPrimeGatePrimePtr) += (gm-ggd); + *(here->MESAdrainPrimeSourcePrimePtr) += (-gds-gm); + *(here->MESAsourcePrimeGatePrimePtr) += (-ggs-gm); + *(here->MESAsourcePrimeDrainPrimePtr) -= gds; + *(here->MESAsourcePrimeSourcePrmPrmPtr) -= here->MESAtGi; + *(here->MESAsourcePrmPrmSourcePrimePtr) -= here->MESAtGi; + *(here->MESAgatePrimeSourcePrmPrmPtr) -= ggspp; + *(here->MESAsourcePrmPrmGatePrimePtr) -= ggspp; + *(here->MESAdrainPrimeDrainPrmPrmPtr) -= here->MESAtGf; + *(here->MESAdrainPrmPrmDrainPrimePtr) -= here->MESAtGf; + *(here->MESAgatePrimeDrainPrmPrmPtr) -= ggdpp; + *(here->MESAdrainPrmPrmGatePrimePtr) -= ggdpp; + } + } + return(OK); +} + + +#define ETA (here->MESAtEta) +#define MU0 (here->MESAtMu) +#define RS (here->MESAtRsi) +#define RD (here->MESAtRdi) +#define SIGMA0 (model->MESAsigma0) +#define VSIGMAT (model->MESAvsigmat) +#define VSIGMA (model->MESAvsigma) +#define THETA (model->MESAtheta) +#define VS (model->MESAvs) +#define ND (model->MESAnd) +#define D (model->MESAd) +#define TC (model->MESAtc) +#define MC (model->MESAmc) +#define M0 (model->MESAm) +#define ALPHA (model->MESAalpha) +#define LAMBDA (here->MESAtLambda) +#define NDELTA (model->MESAndelta) +#define TH (model->MESAth) +#define NDU (model->MESAndu) +#define DU (model->MESAdu) +#define NMAX (model->MESAnmax) +#define GAMMA (model->MESAgamma) + + +static void mesa1(MESAmodel *model, MESAinstance *here, double vgs, + double vds, double von, double *cdrain, + double *gm, double *gds, double *capgs, double *capgd) + +{ + + double vt; + double etavth; + double vl; + double rt; + double mu; + double beta; + double vgt; + double vgt0; + double sigma; + double vgte; + double isat; + double isata; + double isatb; + double ns; + double a; + double b; + double c; + double d; + double e; + double f; + double g; + double h; + double m; + double p; + double q; + double r; + double s; + double t; + double u; + double v; + double w; + double temp; + double gch; + double gchi; + double vsate; + double vdse; + double cgc; + double sqrt1; + double delidgch; + double delgchgchi; + double delgchins; + double delnsvgt; + double delnsvgte; + double delvgtevgt; + double delidvsate; + double delvsateisat; + double delisatisata; + double delisatavgte; + double delisatabeta; + double delisatisatb; + double delvsategch; + double delidvds; + double ddevgte; + double dvgtvgs; + double dgchivgt; + double dvgtevds; + double dgchivds; + double disatavgt; + double disatavds; + double disatbvgt; + double dvsatevgt; + double dvsatevds; + double gmmadd; + double gdsmadd; + + + vt = CONSTKoverQ * here->MESAts; + etavth = ETA*vt; + rt = RS+RD; + vgt0 = vgs - von; + s = exp((vgt0-VSIGMAT)/VSIGMA); + sigma = SIGMA0/(1+s); + vgt = vgt0+sigma*vds; + mu = MU0+THETA*vgt; + vl = VS/mu*here->MESAlength; + beta = here->MESAbeta/(model->MESAvpo+3*vl); + u = vgt/vt-1; + t = sqrt(model->MESAdeltaSqr+u*u); + vgte = 0.5*vt*(2+u+t); + a = 2*beta*vgte; + b = exp(-vgt/etavth); + if(vgte > model->MESAvpo) + sqrt1 = 0; + else + sqrt1 = sqrt(1-vgte/model->MESAvpo); + ns = 1.0/(1.0/ND/D/(1-sqrt1) + 1.0/here->MESAn0*b); + if(ns < 1.0e-38) { + *cdrain = 0; + *gm = 0.0; + *gds = 0.0; + *capgs = here->MESAcf; + *capgd = here->MESAcf; + return; + } + gchi = here->MESAgchi0*mu*ns; + gch = gchi/(1+gchi*rt); + f = sqrt(1+2*a*RS); + d = 1+a*RS + f; + e = 1+TC*vgte; + isata = a*vgte/(d*e); + isatb = here->MESAisatb0*mu*exp(vgt/etavth); + isat = isata*isatb/(isata+isatb); + vsate = isat/gch; + vdse = vds*pow(1+pow(vds/vsate,MC),-1.0/MC); + m = M0+ALPHA*vgte; + g = pow(vds/vsate,m); + h = pow(1+g,1.0/m); + here->MESAdelidgch0 = vds/h; + delidgch = here->MESAdelidgch0*(1+LAMBDA*vds); + *cdrain = gch*delidgch; + if(vgt > model->MESAvpo) + temp = 0; + else + temp = sqrt(1-vgt/model->MESAvpo); + cgc = W*L*EPSILONGAAS/(temp+b)/D; + c = (vsate-vdse)/(2*vsate-vdse); + c = c*c; + *capgs = here->MESAcf+2.0/3.0*cgc*(1-c); + c = vsate/(2*vsate-vdse); + c = c*c; + *capgd = here->MESAcf+2.0/3.0*cgc*(1-c); + temp = 1+gchi*rt; + delgchgchi = 1.0/(temp*temp); + delgchins = here->MESAgchi0*mu; + delnsvgt = ns*ns*1.0/here->MESAn0/etavth*b; + q = 1 - sqrt1; + if(sqrt1 == 0) + delnsvgte = 0; + else + delnsvgte = 0.5*ns*ns/(model->MESAvpo*ND*D*sqrt1*q*q); + delvgtevgt = 0.5*(1+u/t); + here->MESAdelidvds0 = gch/h; + if(vds != 0.0) + here->MESAdelidvds1 = (*cdrain)*pow(vds/vsate,m-1)/(vsate*(1+g)); + else + here->MESAdelidvds1 = 0.0; + delidvds = here->MESAdelidvds0*(1+2*LAMBDA*vds) - here->MESAdelidvds1; + delidvsate = (*cdrain)*g/(vsate*(1+g)); + delvsateisat = 1.0/gch; + r = isata+isatb; + r = r*r; + delisatisata = isatb*isatb/r; + v = 1.0+1.0/f; + ddevgte = 2*beta*RS*v*e+d*TC; + temp = d*d*e*e; + delisatavgte = (2*a*d*e - a*vgte*ddevgte)/temp; + delisatabeta = 2*vgte*vgte*(d*e-a*e*RS*v)/temp; + delisatisatb = isata*isata/r; + delvsategch = -vsate/gch; + dvgtvgs = 1 - SIGMA0*vds*s/VSIGMA/((1+s)*(1+s)); + temp = here->MESAgchi0*ns*THETA; + dgchivgt = delgchins*(delnsvgte*delvgtevgt+delnsvgt)+temp; + dvgtevds = delvgtevgt*sigma; + dgchivds = delgchins*(delnsvgte*dvgtevds+delnsvgt*sigma)+temp*sigma; + temp = delisatabeta*3*beta*vl*THETA/(mu*(model->MESAvpo+3*vl)); + disatavgt = delisatavgte*delvgtevgt+temp; + disatavds = delisatavgte*dvgtevds+temp*sigma; + disatbvgt = isatb/etavth+isatb/mu*THETA; + p = delgchgchi*dgchivgt; + w = delgchgchi*dgchivds; + dvsatevgt = delvsateisat*(delisatisata*disatavgt+delisatisatb*disatbvgt)+delvsategch*p; + dvsatevds = delvsateisat*(delisatisata*disatavds+delisatisatb*disatbvgt*sigma)+delvsategch*w; + if(ALPHA != 0) { + if(vds == 0) + gmmadd = 0; + else + gmmadd = (*cdrain)*(log(1+g)/(m*m)-g*log(vds/vsate)/(m*(1+g)))* + ALPHA*delvgtevgt; + gdsmadd = gmmadd*sigma; + } else { + gmmadd = 0; + gdsmadd = 0; + } + here->MESAgm0 = p; + here->MESAgm1 = delidvsate*dvsatevgt; + here->MESAgm2 = dvgtvgs; + g = delidgch*p+here->MESAgm1; + *gm = (g+gmmadd)*dvgtvgs; + here->MESAgds0 = delidvsate*dvsatevds+delidgch*w+gdsmadd; + *gds = delidvds+here->MESAgds0; + +} + + + +static void mesa2(MESAmodel *model, MESAinstance *here, double vgs, + double vds, double von, double *cdrain, double *gm, + double *gds, double *capgs, double *capgd) + +{ + + double vt; + double rt; + double vgt; + double etavth; + double vgt0; + double sigma; + double vgte; + double isat; + double isata; + double isatb; + double nsa; + double nsb; + double ns; + double a; + double b; + double c; + double d; + double e; + double f; + double g; + double h; + double p; + double q; + double r; + double s; + double t; + double gch; + double gchi; + double vsate; + double vdse; + double ca; + double cb; + double cgc; + double delidgch; + double delgchgchi; + double delgchins; + double delnsvgt; + double delnsbvgt; + double delnsavgte; + double delvgtevgt; + double delidvsate; + double delvsateisat; + double delisatisata; + double delisatavgte; + double delisatisatb; + double delvsategch; + double delisatbvgt; + double delvsatevgt; + double delidvds; + double ddevgte; + double delvgtvgs; + + + vt = CONSTKoverQ * here->MESAts; + etavth = ETA*vt; + rt = RS+RD; + vgt0 = vgs - von; + s = exp((vgt0-VSIGMAT)/VSIGMA); + sigma = SIGMA0/(1+s); + vgt = vgt0+sigma*vds; + t = vgt/vt-1; + q = sqrt(model->MESAdeltaSqr+t*t); + vgte = 0.5*vt*(2+t+q); + a = 2*model->MESAbeta*vgte; + if(vgt > model->MESAvpod) { + if(vgte > model->MESAvpo) { + nsa = NDELTA*TH + NDU*DU; + ca = EPSILONGAAS/DU; + delnsavgte = 0; + } else { + r = sqrt((model->MESAvpo-vgte)/model->MESAvpou); + nsa = NDELTA*TH + NDU*DU*(1-r); + ca = EPSILONGAAS/DU/r; + delnsavgte = NDU*DU/model->MESAvpou/2.0/r; + } + } else { + if(model->MESAvpod - vgte < 0) { + nsa = NDELTA*TH*(1-DU/TH); + ca = EPSILONGAAS/DU; + delnsavgte = 0; + } else { + r = sqrt(1+NDU/NDELTA*(model->MESAvpod - vgte)/model->MESAvpou); + nsa = NDELTA*TH*(1-DU/TH*(r-1)); + ca = EPSILONGAAS/DU/r; + delnsavgte = DU*NDU/2.0/model->MESAvpou/r; + } + } + b = exp(vgt/etavth); + cb = EPSILONGAAS/(DU+TH)*b; + nsb = here->MESAnsb0*b; + delnsbvgt = nsb/etavth; + ns = nsa*nsb/(nsa+nsb); + if(ns < 1.0e-38) { + *cdrain = 0; + *gm = 0.0; + *gds = 0.0; + *capgs = here->MESAcf; + *capgd = here->MESAcf; + return; + } + gchi = here->MESAgchi0*ns; + gch = gchi/(1+gchi*rt); + f = sqrt(1+2*a*RS); + d = 1+a*RS + f; + e = 1+TC*vgte; + isata = a*vgte/d/e; + isatb = here->MESAisatb0*b; + isat = isata*isatb/(isata+isatb); + vsate = isat/gch; + vdse = vds*pow(1+pow(vds/vsate,MC),-1.0/MC); + g = pow(vds/vsate,M0); + h = pow(1+g,1.0/M0); + here->MESAdelidgch0 = vds/h; + delidgch = here->MESAdelidgch0*(1+LAMBDA*vds); + *cdrain = gch*delidgch; + cgc = W*L*ca*cb/(ca+cb); + c = (vsate-vdse)/(2*vsate-vdse); + c = c*c; + *capgs = here->MESAcf+2.0/3.0*cgc*(1-c); + c = vsate/(2*vsate-vdse); + c = c*c; + *capgd = here->MESAcf+2.0/3.0*cgc*(1-c); + c = vgt/vt-1; + delvgtevgt = 0.5*(1+t/q); + here->MESAdelidvds0 = gch/h; + if(vds != 0.0) + here->MESAdelidvds1 = (*cdrain)*pow(vds/vsate,M0-1)/vsate/(1+g); + else + here->MESAdelidvds1 = 0.0; + delidvds = here->MESAdelidvds0*(1+2*LAMBDA*vds) - + here->MESAdelidvds1; + delgchgchi = 1.0/(1+gchi*rt)/(1+gchi*rt); + delgchins = here->MESAgchi0; + r = nsa+nsb; + r = r*r; + delnsvgt = (nsb*nsb*delvgtevgt*delnsavgte + nsa*nsa*delnsbvgt)/r; + delidvsate = (*cdrain)*g/vsate/(1+g); + delvsateisat = 1.0/gch; + r = isata+isatb; + r = r*r; + delisatisata = isatb*isatb/r; + ddevgte = 2*model->MESAbeta*RS*(1+1.0/f)*e+d*TC; + delisatavgte = (2*a*d*e - a*vgte*ddevgte)/d/d/e/e; + delisatisatb = isata*isata/r; + delisatbvgt = isatb/etavth; + delvsategch = -vsate/gch; + delvgtvgs = 1-SIGMA0*vds*s/VSIGMA/(1+s)/(1+s); + p = delgchgchi*delgchins*delnsvgt; + delvsatevgt = delvsateisat*(delisatisata*delisatavgte*delvgtevgt + + delisatisatb*delisatbvgt) + delvsategch*p; + here->MESAgm0 = p; + here->MESAgm1 = delidvsate*delvsatevgt; + here->MESAgm2 = delvgtvgs; + g = delidgch*p + here->MESAgm1; + *gm = g*delvgtvgs; + here->MESAgds0 = g*sigma; + *gds = delidvds+here->MESAgds0; + +} + + + +static void mesa3(MESAmodel *model, MESAinstance *here, double vgs, + double vds, double von, double *cdrain, double *gm, + double *gds, double *capgs, double *capgd) + +{ + + double vt; + double vgt; + double vgt0; + double sigma; + double vgte; + double isat; + double isatm; + double ns; + double nsm; + double a; + double b; + double c; + double d; + double e; + double g; + double h; + double p; + double q; + double s; + double t; + double u; + double temp; + double etavth; + double gch; + double gchi; + double gchim; + double vsate; + double vdse; + double cgc; + double cgcm; + double rt; + double vl; + double delidgch; + double delgchgchi; + double delgchins; + double delnsnsm; + double delnsmvgt; + double delvgtevgt; + double delidvsate; + double delvsateisat; + double delisatisatm; + double delisatmvgte; + double delisatmgchim; + double delvsategch; + double delidvds; + double delvgtvgs; + double delvsatevgt; + + vt = CONSTKoverQ * here->MESAts; + etavth = ETA*vt; + vl = VS/MU0*L; + rt = RS+RD; + vgt0 = vgs - von; + s = exp((vgt0-VSIGMAT)/VSIGMA); + sigma = SIGMA0/(1+s); + vgt = vgt0+sigma*vds; + u = 0.5*vgt/vt-1; + t = sqrt(model->MESAdeltaSqr+u*u); + vgte = vt*(2+u+t); + b = exp(vgt/etavth); + nsm = 2*here->MESAn0*log(1+0.5*b); + if(nsm < 1.0e-38) { + *cdrain = 0; + *gm = 0.0; + *gds = 0.0; + *capgs = here->MESAcf; + *capgd = here->MESAcf; + return; + } + c = pow(nsm/NMAX,GAMMA); + q = pow(1+c,1.0/GAMMA); + ns = nsm/q; + gchi = here->MESAgchi0*ns; + gch = gchi/(1+gchi*rt); + gchim = here->MESAgchi0*nsm; + h = sqrt(1+2*gchim*model->MESArsi + vgte*vgte/(vl*vl)); + p = 1+gchim*RS+h; + isatm = gchim*vgte/p; + g = pow(isatm/here->MESAimax,GAMMA); + isat = isatm/pow(1+g,1/GAMMA); + vsate = isat/gch; + vdse = vds*pow(1+pow(vds/vsate,MC),-1.0/MC); + d = pow(vds/vsate,M0); + e = pow(1+d,1.0/M0); + delidgch = vds*(1+LAMBDA*vds)/e; + *cdrain = gch*delidgch; + cgcm = 1.0/(1/model->MESAcas*D/model->MESAepsi + + 1/model->MESAcbs*etavth/CHARGE/here->MESAn0*exp(-vgt/etavth)); + cgc = W*L*cgcm/pow(1+c,1+1.0/GAMMA); +/* + { + char buf[256]; + void far pascal OutputDebugString(char*); + sprintf(buf,"\n%f\t%e\0",vgs,cgc); + OutputDebugString(buf); + } +*/ + a = (vsate-vdse)/(2*vsate-vdse); + a = a*a; + temp = 2.0/3.0; + *capgs = here->MESAcf+temp*cgc*(1-a); + a = vsate/(2*vsate-vdse); + a = a*a; + *capgd = here->MESAcf+temp*cgc*(1-a); + delidvsate = (*cdrain)*d/vsate/(1+d); + delidvds = gch*(1+2*LAMBDA*vds)/e-(*cdrain)* + pow(vds/vsate,M0-1)/(vsate*(1+d)); + a = 1+gchi*rt; + delgchgchi = 1.0/(a*a); + delgchins = here->MESAgchi0; + delnsnsm = ns/nsm*(1-c/(1+c)); + delnsmvgt = here->MESAn0/etavth/(1.0/b + 0.5); + delvgtevgt = 0.5*(1+u/t); + delvsateisat = 1.0/gch; + delisatisatm = isat/isatm*(1-g/(1+g)); + delisatmvgte = gchim*(p - vgte*vgte/(vl*vl*h))/(p*p); + delvsategch = -vsate/gch; + delisatmgchim = vgte*(p - gchim*RS*(1+1.0/h))/(p*p); + delvgtvgs = 1-vds*SIGMA0/VSIGMA*s/((1+s)*(1+s)); + p = delgchgchi*delgchins*delnsnsm*delnsmvgt; + delvsatevgt = (delvsateisat*delisatisatm*(delisatmvgte*delvgtevgt + + delisatmgchim*here->MESAgchi0*delnsmvgt)+delvsategch*p); + g = delidgch*p + delidvsate*delvsatevgt; + *gm = g*delvgtvgs; + *gds = delidvds + g*sigma; + +} diff --git a/src/spicelib/devices/mesa/mesamask.c b/src/spicelib/devices/mesa/mesamask.c new file mode 100644 index 000000000..85e9d2809 --- /dev/null +++ b/src/spicelib/devices/mesa/mesamask.c @@ -0,0 +1,223 @@ +/********** +Copyright 1990 Regents of the University of California. All rights reserved. +Author: 1987 Thomas L. Quarles +**********/ +/* + */ + +#include "ngspice.h" +#include +#include "cktdefs.h" +#include "devdefs.h" +#include "ifsim.h" +#include "mesadefs.h" +#include "sperror.h" +#include "suffix.h" + + +/* ARGSUSED */ +int +MESAmAsk(ckt,inst,which,value) + CKTcircuit *ckt; + GENmodel *inst; + int which; + IFvalue *value; +{ + MESAmodel *here = (MESAmodel*)inst; + switch(which) { + case MESA_MOD_VTO: + value->rValue = here->MESAthreshold; + return (OK); + case MESA_MOD_VS: + value->rValue = here->MESAvs; + return (OK); + case MESA_MOD_ALPHA: + value->rValue = here->MESAalpha; + return (OK); + case MESA_MOD_BETA: + value->rValue = here->MESAbeta; + return (OK); + case MESA_MOD_LAMBDA: + value->rValue = here->MESAlambda; + return (OK); + case MESA_MOD_RG: + value->rValue = here->MESAgateResist; + return (OK); + case MESA_MOD_RD: + value->rValue = here->MESAdrainResist; + return (OK); + case MESA_MOD_RS: + value->rValue = here->MESAsourceResist; + return (OK); + case MESA_MOD_RI: + value->rValue = here->MESAri; + return (OK); + case MESA_MOD_RF: + value->rValue = here->MESArf; + return (OK); + case MESA_MOD_RDI: + value->rValue = here->MESArdi; + return (OK); + case MESA_MOD_RSI: + value->rValue = here->MESArsi; + return (OK); + case MESA_MOD_PHIB: + value->rValue = here->MESAphib; + return (OK); + case MESA_MOD_PHIB1: + value->rValue = here->MESAphib1; + return (OK); + case MESA_MOD_ASTAR: + value->rValue = here->MESAastar; + return (OK); + case MESA_MOD_GGR: + value->rValue = here->MESAggr; + return (OK); + case MESA_MOD_DEL: + value->rValue = here->MESAdel; + return (OK); + case MESA_MOD_XCHI: + value->rValue = here->MESAxchi; + return (OK); + case MESA_MOD_N: + value->rValue = here->MESAn; + return (OK); + case MESA_MOD_ETA: + value->rValue = here->MESAeta; + return (OK); + case MESA_MOD_M: + value->rValue = here->MESAm; + return (OK); + case MESA_MOD_MC: + value->rValue = here->MESAmc; + return (OK); + case MESA_MOD_SIGMA0: + value->rValue = here->MESAsigma0; + return (OK); + case MESA_MOD_VSIGMAT: + value->rValue = here->MESAvsigmat; + return (OK); + case MESA_MOD_VSIGMA: + value->rValue = here->MESAvsigma; + return (OK); + case MESA_MOD_MU: + value->rValue = here->MESAmu; + return (OK); + case MESA_MOD_MU1: + value->rValue = here->MESAmu1; + return (OK); + case MESA_MOD_MU2: + value->rValue = here->MESAmu2; + return (OK); + case MESA_MOD_D: + value->rValue = here->MESAd; + return (OK); + case MESA_MOD_ND: + value->rValue = here->MESAnd; + return (OK); + case MESA_MOD_DELTA: + value->rValue = here->MESAdelta; + return (OK); + case MESA_MOD_TC: + value->rValue = here->MESAtc; + return (OK); + case MESA_MOD_TVTO: + value->rValue = here->MESAtvto; + return (OK); + case MESA_MOD_TLAMBDA: + value->rValue = here->MESAtlambda; + return (OK); + case MESA_MOD_TETA0: + value->rValue = here->MESAteta0; + return (OK); + case MESA_MOD_TETA1: + value->rValue = here->MESAteta1; + return (OK); + case MESA_MOD_TMU: + value->rValue = here->MESAtmu; + return (OK); + case MESA_MOD_XTM0: + value->rValue = here->MESAxtm0; + return (OK); + case MESA_MOD_XTM1: + value->rValue = here->MESAxtm1; + return (OK); + case MESA_MOD_XTM2: + value->rValue = here->MESAxtm2; + return (OK); + case MESA_MOD_KS: + value->rValue = here->MESAks; + return (OK); + case MESA_MOD_VSG: + value->rValue = here->MESAvsg; + return (OK); + case MESA_MOD_LAMBDAHF: + value->rValue = here->MESAlambdahf; + return (OK); + case MESA_MOD_TF: + value->rValue = here->MESAtf; + return (OK); + case MESA_MOD_FLO: + value->rValue = here->MESAflo; + return (OK); + case MESA_MOD_DELFO: + value->rValue = here->MESAdelfo; + return (OK); + case MESA_MOD_AG: + value->rValue = here->MESAag; + return (OK); + case MESA_MOD_THETA: + value->rValue = here->MESAtheta; + return (OK); + case MESA_MOD_TC1: + value->rValue = here->MESAtc1; + return (OK); + case MESA_MOD_TC2: + value->rValue = here->MESAtc2; + return (OK); + case MESA_MOD_ZETA: + value->rValue = here->MESAzeta; + return (OK); + case MESA_MOD_DU: + value->rValue = here->MESAdu; + return (OK); + + + + case MESA_MOD_NDU: + value->rValue = here->MESAndu; + return (OK); + case MESA_MOD_TH: + value->rValue = here->MESAth; + return (OK); + case MESA_MOD_NDELTA: + value->rValue = here->MESAndelta; + return (OK); + case MESA_MOD_LEVEL: + value->rValue = here->MESAlevel; + return (OK); + case MESA_MOD_NMAX: + value->rValue = here->MESAnmax; + return (OK); + case MESA_MOD_GAMMA: + value->rValue = here->MESAgamma; + return (OK); + case MESA_MOD_EPSI: + value->rValue = here->MESAepsi; + return (OK); + case MESA_MOD_CBS: + value->rValue = here->MESAcbs; + return (OK); + case MESA_MOD_CAS: + value->rValue = here->MESAcas; + return (OK); + case MESA_MOD_TYPE: + if (here->MESAtype == NMF) + value->sValue = "nmf"; + else + value->sValue = "pmf"; + default: + return (E_BADPARM); + } + /* NOTREACHED */ +} diff --git a/src/spicelib/devices/mesa/mesamdel.c b/src/spicelib/devices/mesa/mesamdel.c new file mode 100644 index 000000000..e5cbdf136 --- /dev/null +++ b/src/spicelib/devices/mesa/mesamdel.c @@ -0,0 +1,45 @@ +/********** +Copyright 1990 Regents of the University of California. All rights reserved. +Author: 1985 S. Hwang +**********/ +/* + Imported into mesa model: 2001 Paolo Nenzi + */ + +#include "ngspice.h" +#include +#include "mesadefs.h" +#include "sperror.h" +#include "suffix.h" + + +int +MESAmDelete(inModel,modname,kill) + GENmodel **inModel; + IFuid modname; + GENmodel *kill; +{ + MESAmodel **model = (MESAmodel**)inModel; + MESAmodel *modfast = (MESAmodel*)kill; + MESAinstance *here; + MESAinstance *prev = NULL; + MESAmodel **oldmod; + oldmod = model; + for( ; *model ; model = &((*model)->MESAnextModel)) { + if( (*model)->MESAmodName == modname || + (modfast && *model == modfast) ) goto delgot; + oldmod = model; + } + return(E_NOMOD); + +delgot: + *oldmod = (*model)->MESAnextModel; /* cut deleted device out of list */ + for(here = (*model)->MESAinstances ; here ; here = here->MESAnextInstance) { + if(prev) FREE(prev); + prev = here; + } + if(prev) FREE(prev); + FREE(*model); + return(OK); + +} diff --git a/src/spicelib/devices/mesa/mesamparam.c b/src/spicelib/devices/mesa/mesamparam.c new file mode 100644 index 000000000..1a13a328c --- /dev/null +++ b/src/spicelib/devices/mesa/mesamparam.c @@ -0,0 +1,273 @@ +/********** +Copyright 1993: T. Ytterdal, K. Lee, M. Shur and T. A. Fjeldly. All rights reserved. +Author: Trond Ytterdal +**********/ + +#include "ngspice.h" +#include +#include "const.h" +#include "ifsim.h" +#include "mesadefs.h" +#include "sperror.h" +#include "suffix.h" + + +int +MESAmParam(param,value,inModel) + int param; + IFvalue *value; + GENmodel *inModel; +{ + MESAmodel *model = (MESAmodel*)inModel; + switch(param) { + case MESA_MOD_VTO: + model->MESAthresholdGiven = TRUE; + model->MESAthreshold = value->rValue; + break; + case MESA_MOD_BETA: + model->MESAbetaGiven = TRUE; + model->MESAbeta = value->rValue; + break; + case MESA_MOD_VS: + model->MESAvsGiven = TRUE; + model->MESAvs = value->rValue; + break; + case MESA_MOD_LAMBDA: + model->MESAlambdaGiven = TRUE; + model->MESAlambda = value->rValue; + break; + case MESA_MOD_RD: + model->MESAdrainResistGiven = TRUE; + model->MESAdrainResist = value->rValue; + break; + case MESA_MOD_RS: + model->MESAsourceResistGiven = TRUE; + model->MESAsourceResist = value->rValue; + break; + case MESA_MOD_RG: + model->MESAgateResistGiven = TRUE; + model->MESAgateResist = value->rValue; + break; + case MESA_MOD_RI: + model->MESAriGiven = TRUE; + model->MESAri = value->rValue; + break; + case MESA_MOD_RF: + model->MESArfGiven = TRUE; + model->MESArf = value->rValue; + break; + case MESA_MOD_RDI: + model->MESArdiGiven = TRUE; + model->MESArdi = value->rValue; + break; + case MESA_MOD_RSI: + model->MESArsiGiven = TRUE; + model->MESArsi = value->rValue; + break; + case MESA_MOD_PHIB: + model->MESAphibGiven = TRUE; + model->MESAphib = value->rValue*CHARGE; + break; + case MESA_MOD_PHIB1: + model->MESAphib1Given = TRUE; + model->MESAphib1 = value->rValue*CHARGE; + break; + case MESA_MOD_ASTAR: + model->MESAastarGiven = TRUE; + model->MESAastar = value->rValue; + break; + case MESA_MOD_GGR: + model->MESAggrGiven = TRUE; + model->MESAggr = value->rValue; + break; + case MESA_MOD_DEL: + model->MESAdelGiven = TRUE; + model->MESAdel = value->rValue; + break; + case MESA_MOD_XCHI: + model->MESAxchiGiven = TRUE; + model->MESAxchi = value->rValue; + break; + case MESA_MOD_N: + model->MESAnGiven = TRUE; + model->MESAn = value->rValue; + break; + case MESA_MOD_ETA: + model->MESAetaGiven = TRUE; + model->MESAeta = value->rValue; + break; + case MESA_MOD_M: + model->MESAmGiven = TRUE; + model->MESAm = value->rValue; + break; + case MESA_MOD_MC: + model->MESAmcGiven = TRUE; + model->MESAmc = value->rValue; + break; + case MESA_MOD_ALPHA: + model->MESAalphaGiven = TRUE; + model->MESAalpha = value->rValue; + break; + case MESA_MOD_SIGMA0: + model->MESAsigma0Given = TRUE; + model->MESAsigma0 = value->rValue; + break; + case MESA_MOD_VSIGMAT: + model->MESAvsigmatGiven = TRUE; + model->MESAvsigmat = value->rValue; + break; + case MESA_MOD_VSIGMA: + model->MESAvsigmaGiven = TRUE; + model->MESAvsigma = value->rValue; + break; + case MESA_MOD_MU: + model->MESAmuGiven = TRUE; + model->MESAmu = value->rValue; + break; + case MESA_MOD_THETA: + model->MESAthetaGiven = TRUE; + model->MESAtheta = value->rValue; + break; + case MESA_MOD_MU1: + model->MESAmu1Given = TRUE; + model->MESAmu1 = value->rValue; + break; + case MESA_MOD_MU2: + model->MESAmu2Given = TRUE; + model->MESAmu2 = value->rValue; + break; + case MESA_MOD_D: + model->MESAdGiven = TRUE; + model->MESAd = value->rValue; + break; + case MESA_MOD_ND: + model->MESAndGiven = TRUE; + model->MESAnd = value->rValue; + break; + case MESA_MOD_DU: + model->MESAduGiven = TRUE; + model->MESAdu = value->rValue; + break; + case MESA_MOD_NDU: + model->MESAnduGiven = TRUE; + model->MESAndu = value->rValue; + break; + case MESA_MOD_TH: + model->MESAthGiven = TRUE; + model->MESAth = value->rValue; + break; + case MESA_MOD_NDELTA: + model->MESAndeltaGiven = TRUE; + model->MESAndelta = value->rValue; + break; + case MESA_MOD_DELTA: + model->MESAdeltaGiven = TRUE; + model->MESAdelta = value->rValue; + break; + case MESA_MOD_TC: + model->MESAtcGiven = TRUE; + model->MESAtc = value->rValue; + break; + case MESA_MOD_NMF: + break; + case MESA_MOD_TVTO: + model->MESAtvtoGiven = TRUE; + model->MESAtvto = value->rValue; + break; + case MESA_MOD_TLAMBDA: + model->MESAtlambdaGiven = TRUE; + model->MESAtlambda = value->rValue+CONSTCtoK; + break; + case MESA_MOD_TETA0: + model->MESAteta0Given = TRUE; + model->MESAteta0 = value->rValue+CONSTCtoK; + break; + case MESA_MOD_TETA1: + model->MESAteta1Given = TRUE; + model->MESAteta1 = value->rValue+CONSTCtoK; + break; + case MESA_MOD_TMU: + model->MESAtmuGiven = TRUE; + model->MESAtmu = value->rValue+CONSTCtoK; + break; + case MESA_MOD_XTM0: + model->MESAxtm0Given = TRUE; + model->MESAxtm0 = value->rValue; + break; + case MESA_MOD_XTM1: + model->MESAxtm1Given = TRUE; + model->MESAxtm1 = value->rValue; + break; + case MESA_MOD_XTM2: + model->MESAxtm2Given = TRUE; + model->MESAxtm2 = value->rValue; + break; + case MESA_MOD_KS: + model->MESAksGiven = TRUE; + model->MESAks = value->rValue; + break; + case MESA_MOD_VSG: + model->MESAvsgGiven = TRUE; + model->MESAvsg = value->rValue; + break; + case MESA_MOD_LAMBDAHF: + model->MESAlambdahfGiven = TRUE; + model->MESAlambdahf = value->rValue; + break; + case MESA_MOD_TF: + model->MESAtfGiven = TRUE; + model->MESAtf = value->rValue+CONSTCtoK; + break; + case MESA_MOD_FLO: + model->MESAfloGiven = TRUE; + model->MESAflo = value->rValue; + break; + case MESA_MOD_DELFO: + model->MESAdelfoGiven = TRUE; + model->MESAdelfo = value->rValue; + break; + case MESA_MOD_AG: + model->MESAagGiven = TRUE; + model->MESAag = value->rValue; + break; + case MESA_MOD_TC1: + model->MESAtc1Given = TRUE; + model->MESAtc1 = value->rValue; + break; + case MESA_MOD_TC2: + model->MESAtc2Given = TRUE; + model->MESAtc2 = value->rValue; + break; + case MESA_MOD_ZETA: + model->MESAzetaGiven = TRUE; + model->MESAzeta = value->rValue; + break; + case MESA_MOD_LEVEL: + model->MESAlevelGiven = TRUE; + model->MESAlevel = value->rValue; + break; + case MESA_MOD_NMAX: + model->MESAnmaxGiven = TRUE; + model->MESAnmax = value->rValue; + break; + case MESA_MOD_GAMMA: + model->MESAgammaGiven = TRUE; + model->MESAgamma = value->rValue; + break; + case MESA_MOD_EPSI: + model->MESAepsiGiven = TRUE; + model->MESAepsi = value->rValue; + break; + case MESA_MOD_CBS: + model->MESAcbsGiven = TRUE; + model->MESAcbs = value->rValue; + break; + case MESA_MOD_CAS: + model->MESAcasGiven = TRUE; + model->MESAcas = value->rValue; + break; + default: + return(E_BADPARM); + } + return(OK); +} diff --git a/src/spicelib/devices/mesa/mesaparam.c b/src/spicelib/devices/mesa/mesaparam.c new file mode 100644 index 000000000..87e8aa2d8 --- /dev/null +++ b/src/spicelib/devices/mesa/mesaparam.c @@ -0,0 +1,69 @@ +/********** +Copyright 1993: T. Ytterdal, K. Lee, M. Shur and T. A. Fjeldly. All rights reserved. +Author: Trond Ytterdal +**********/ + +#include "ngspice.h" +#include +#include "const.h" +#include "ifsim.h" +#include "mesadefs.h" +#include "sperror.h" +#include "suffix.h" + + +/* ARGSUSED */ +int +MESAparam(param,value,inst,select) + int param; + IFvalue *value; + GENinstance *inst; + IFvalue *select; +{ + MESAinstance *here = (MESAinstance*)inst; + switch(param) { + case MESA_LENGTH: + here->MESAlength = value->rValue; + here->MESAlengthGiven = TRUE; + break; + case MESA_WIDTH: + here->MESAwidth = value->rValue; + here->MESAwidthGiven = TRUE; + break; + case MESA_IC_VDS: + here->MESAicVDS = value->rValue; + here->MESAicVDSGiven = TRUE; + break; + case MESA_IC_VGS: + here->MESAicVGS = value->rValue; + here->MESAicVGSGiven = TRUE; + break; + case MESA_OFF: + here->MESAoff = value->iValue; + break; + case MESA_IC: + switch(value->v.numValue) { + case 2: + here->MESAicVGS = *(value->v.vec.rVec+1); + here->MESAicVGSGiven = TRUE; + case 1: + here->MESAicVDS = *(value->v.vec.rVec); + here->MESAicVDSGiven = TRUE; + break; + default: + return(E_BADPARM); + } + break; + case MESA_TD: + here->MESAtd = value->rValue+CONSTCtoK; + here->MESAtdGiven = TRUE; + break; + case MESA_TS: + here->MESAts = value->rValue+CONSTCtoK; + here->MESAtsGiven = TRUE; + break; + default: + return(E_BADPARM); + } + return(OK); +} diff --git a/src/spicelib/devices/mesa/mesasetup.c b/src/spicelib/devices/mesa/mesasetup.c new file mode 100644 index 000000000..3a9d6c799 --- /dev/null +++ b/src/spicelib/devices/mesa/mesasetup.c @@ -0,0 +1,417 @@ +/********** +Copyright 1993: T. Ytterdal, K. Lee, M. Shur and T. A. Fjeldly. All rights reserved. +Author: Trond Ytterdal +Modified: 2001 AlansFixes +**********/ + +#include "ngspice.h" +#include +#include "smpdefs.h" +#include "cktdefs.h" +#include "mesadefs.h" +#include "const.h" +#include "sperror.h" +#include "suffix.h" + + +int +MESAsetup(matrix,inModel,ckt,states) + register SMPmatrix *matrix; + register GENmodel *inModel; + register CKTcircuit *ckt; + int *states; + + /* load the diode structure with those pointers needed later + * for fast matrix loading + */ +{ + register MESAmodel *model = (MESAmodel*)inModel; + register MESAinstance *here; + int error; + CKTnode *tmp; + + + /* loop through all the diode models */ + for( ; model != NULL; model = model->MESAnextModel ) { + if(!model->MESAthresholdGiven) { + model->MESAthreshold = -1.26; + } + if(!model->MESAdGiven) { + model->MESAd = 0.12e-6; + } + if(!model->MESAduGiven) { + model->MESAdu = 0.035e-6; + } + if(!model->MESAlambdaGiven) { + model->MESAlambda = 0.045; + } + if(!model->MESAvsGiven) { + model->MESAvs = 1.5e5; + } + if(!model->MESAbetaGiven) { + model->MESAbeta = 0.0085; + } + if(!model->MESAetaGiven) { + model->MESAeta = 1.73; + } + if(!model->MESAmGiven) { + model->MESAm = 2.5; + } + if(!model->MESAmcGiven) { + model->MESAmc = 3.0; + } + if(!model->MESAalphaGiven) { + model->MESAalpha = 0.0; + } + if(!model->MESAsigma0Given) { + model->MESAsigma0 = 0.081; + } + if(!model->MESAvsigmatGiven) { + model->MESAvsigmat = 1.01; + } + if(!model->MESAvsigmaGiven) { + model->MESAvsigma = 0.1; + } + if(!model->MESAmuGiven) { + model->MESAmu = 0.23; + } + if(!model->MESAthetaGiven) { + model->MESAtheta = 0; + } + if(!model->MESAmu1Given) { + model->MESAmu1 = 0; + } + if(!model->MESAmu2Given) { + model->MESAmu2 = 0; + } + if(!model->MESAndGiven) { + model->MESAnd = 2.0e23; + } + if(!model->MESAnduGiven) { + model->MESAndu = 1e22; + } + if(!model->MESAndeltaGiven) { + model->MESAndelta = 6e24; + } + if(!model->MESAthGiven) { + model->MESAth = 0.01e-6; + } + if(!model->MESAdeltaGiven) { + model->MESAdelta = 5.0; + } + if(!model->MESAtcGiven) { + model->MESAtc = 0.0; + } + if(!model->MESAdrainResistGiven) { + model->MESAdrainResist = 0; + } + if(!model->MESAsourceResistGiven) { + model->MESAsourceResist = 0; + } + if(!model->MESAgateResistGiven) { + model->MESAgateResist = 0; + } + if(!model->MESAriGiven) { + model->MESAri = 0; + } + if(!model->MESArfGiven) { + model->MESArf = 0; + } + if(!model->MESArdiGiven) { + model->MESArdi = 0; + } + if(!model->MESArsiGiven) { + model->MESArsi = 0; + } + if(!model->MESAphibGiven) { + model->MESAphib = 0.5*CHARGE; + } + if(!model->MESAphib1Given) { + model->MESAphib1 = 0; + } + if(!model->MESAastarGiven) { + model->MESAastar = 4.0e4; + } + if(!model->MESAggrGiven) { + model->MESAggr = 40; + } + if(!model->MESAdelGiven) { + model->MESAdel = 0.04; + } + if(!model->MESAxchiGiven) { + model->MESAxchi = 0.033; + } + if(!model->MESAnGiven) { + model->MESAn = 1; + } + if(!model->MESAtvtoGiven) { + model->MESAtvto = 0; + } + if(!model->MESAtlambdaGiven) { + model->MESAtlambda = DBL_MAX; + } + if(!model->MESAteta0Given) { + model->MESAteta0 = DBL_MAX; + } + if(!model->MESAteta1Given) { + model->MESAteta1 = 0; + } + if(!model->MESAtmuGiven) { + model->MESAtmu = 300.15; + } + if(!model->MESAxtm0Given) { + model->MESAxtm0 = 0; + } + if(!model->MESAxtm1Given) { + model->MESAxtm1 = 0; + } + if(!model->MESAxtm2Given) { + model->MESAxtm2 = 0; + } + if(!model->MESAksGiven) { + model->MESAks = 0; + } + if(!model->MESAvsgGiven) { + model->MESAvsg = 0; + } + if(!model->MESAtfGiven) { + model->MESAtf = ckt->CKTtemp; + } + if(!model->MESAfloGiven) { + model->MESAflo = 0; + } + if(!model->MESAdelfoGiven) { + model->MESAdelfo = 0; + } + if(!model->MESAagGiven) { + model->MESAag = 0; + } + if(!model->MESAtc1Given) { + model->MESAtc1 = 0; + } + if(!model->MESAtc2Given) { + model->MESAtc2 = 0; + } + if(!model->MESAzetaGiven) { + model->MESAzeta = 1; + } + if(!model->MESAlevelGiven) { + model->MESAlevel = 2; + } + if(!model->MESAnmaxGiven) { + model->MESAnmax = 2e16; + } + if(!model->MESAgammaGiven) { + model->MESAgamma = 3.0; + } + if(!model->MESAepsiGiven) { + model->MESAepsi = 12.244*8.85418e-12; + } + if(!model->MESAcasGiven) { + model->MESAcas = 1; + } + if(!model->MESAcbsGiven) { + model->MESAcbs = 1; + } + + /* loop through all the instances of the model */ + for (here = model->MESAinstances; here != NULL ; + here=here->MESAnextInstance) { + + if(!here->MESAlengthGiven) { + here->MESAlength = 1e-6; + } + if(!here->MESAwidthGiven) { + here->MESAwidth = 20e-6; + } + if(!here->MESAtdGiven) { + here->MESAtd = ckt->CKTtemp; + } + if(!here->MESAtsGiven) { + here->MESAts = ckt->CKTtemp; + } + + here->MESAstate = *states; + *states += 20; + + if(model->MESAsourceResist != 0 && here->MESAsourcePrimeNode==0) { + error = CKTmkVolt(ckt,&tmp,here->MESAname,"source"); + if(error) return(error); + here->MESAsourcePrimeNode = tmp->number; + + if (ckt->CKTcopyNodesets) { + CKTnode *tmpNode; + IFuid tmpName; + + if (CKTinst2Node(ckt,here,3,&tmpNode,&tmpName)==OK) { + if (tmpNode->nsGiven) { + tmp->nodeset=tmpNode->nodeset; + tmp->nsGiven=tmpNode->nsGiven; + } + } + } + + } else { + here->MESAsourcePrimeNode = here->MESAsourceNode; + } + + if(model->MESAdrainResist != 0 && here->MESAdrainPrimeNode==0) { + error = CKTmkVolt(ckt,&tmp,here->MESAname,"drain"); + if(error) return(error); + here->MESAdrainPrimeNode = tmp->number; + + if (ckt->CKTcopyNodesets) { + CKTnode *tmpNode; + IFuid tmpName; + + if (CKTinst2Node(ckt,here,3,&tmpNode,&tmpName)==OK) { + if (tmpNode->nsGiven) { + tmp->nodeset=tmpNode->nodeset; + tmp->nsGiven=tmpNode->nsGiven; + } + } + } + + } else { + here->MESAdrainPrimeNode = here->MESAdrainNode; + } + if(model->MESAgateResist != 0 && here->MESAgatePrimeNode==0) { + error = CKTmkVolt(ckt,&tmp,here->MESAname,"gate"); + if(error) return(error); + here->MESAgatePrimeNode = tmp->number; + + if (ckt->CKTcopyNodesets) { + CKTnode *tmpNode; + IFuid tmpName; + + if (CKTinst2Node(ckt,here,1,&tmpNode,&tmpName)==OK) { + if (tmpNode->nsGiven) { + tmp->nodeset=tmpNode->nodeset; + tmp->nsGiven=tmpNode->nsGiven; + } + } + } + + + } else { + here->MESAgatePrimeNode = here->MESAgateNode; + } + + + if(model->MESAri != 0 && here->MESAsourcePrmPrmNode==0) { + error = CKTmkVolt(ckt,&tmp,here->MESAname,"gs"); + if(error) return(error); + here->MESAsourcePrmPrmNode = tmp->number; + + if (ckt->CKTcopyNodesets) { + CKTnode *tmpNode; + IFuid tmpName; + + if (CKTinst2Node(ckt,here,1,&tmpNode,&tmpName)==OK) { + if (tmpNode->nsGiven) { + tmp->nodeset=tmpNode->nodeset; + tmp->nsGiven=tmpNode->nsGiven; + } + } + } + + } else { + here->MESAsourcePrmPrmNode = here->MESAsourcePrimeNode; + } + if(model->MESArf != 0 && here->MESAdrainPrmPrmNode==0) { + error = CKTmkVolt(ckt,&tmp,here->MESAname,"gd"); + if(error) return(error); + here->MESAdrainPrmPrmNode = tmp->number; + + if (ckt->CKTcopyNodesets) { + CKTnode *tmpNode; + IFuid tmpName; + + if (CKTinst2Node(ckt,here,1,&tmpNode,&tmpName)==OK) { + if (tmpNode->nsGiven) { + tmp->nodeset=tmpNode->nodeset; + tmp->nsGiven=tmpNode->nsGiven; + } + } + } + + } else { + here->MESAdrainPrmPrmNode = here->MESAdrainPrimeNode; + } + +#define TSTALLOC(ptr,first,second) \ +if((here->ptr = SMPmakeElt(matrix,here->first,here->second))==(double *)NULL){\ + return(E_NOMEM);\ +} + + TSTALLOC(MESAdrainDrainPtr,MESAdrainNode,MESAdrainNode) + TSTALLOC(MESAdrainPrimeDrainPrimePtr,MESAdrainPrimeNode,MESAdrainPrimeNode) + TSTALLOC(MESAdrainPrmPrmDrainPrmPrmPtr,MESAdrainPrmPrmNode,MESAdrainPrmPrmNode) + TSTALLOC(MESAgateGatePtr,MESAgateNode,MESAgateNode) + TSTALLOC(MESAgatePrimeGatePrimePtr,MESAgatePrimeNode,MESAgatePrimeNode) + TSTALLOC(MESAsourceSourcePtr,MESAsourceNode,MESAsourceNode) + TSTALLOC(MESAsourcePrimeSourcePrimePtr,MESAsourcePrimeNode,MESAsourcePrimeNode) + TSTALLOC(MESAsourcePrmPrmSourcePrmPrmPtr,MESAsourcePrmPrmNode,MESAsourcePrmPrmNode) + TSTALLOC(MESAdrainDrainPrimePtr,MESAdrainNode,MESAdrainPrimeNode) + TSTALLOC(MESAdrainPrimeDrainPtr,MESAdrainPrimeNode,MESAdrainNode) + TSTALLOC(MESAgatePrimeDrainPrimePtr,MESAgatePrimeNode,MESAdrainPrimeNode) + TSTALLOC(MESAdrainPrimeGatePrimePtr,MESAdrainPrimeNode,MESAgatePrimeNode) + TSTALLOC(MESAgatePrimeSourcePrimePtr,MESAgatePrimeNode,MESAsourcePrimeNode) + TSTALLOC(MESAsourcePrimeGatePrimePtr,MESAsourcePrimeNode,MESAgatePrimeNode) + TSTALLOC(MESAsourceSourcePrimePtr,MESAsourceNode,MESAsourcePrimeNode) + TSTALLOC(MESAsourcePrimeSourcePtr,MESAsourcePrimeNode,MESAsourceNode) + TSTALLOC(MESAdrainPrimeSourcePrimePtr,MESAdrainPrimeNode,MESAsourcePrimeNode) + TSTALLOC(MESAsourcePrimeDrainPrimePtr,MESAsourcePrimeNode,MESAdrainPrimeNode) + TSTALLOC(MESAgatePrimeGatePtr,MESAgatePrimeNode,MESAgateNode) + TSTALLOC(MESAgateGatePrimePtr,MESAgateNode,MESAgatePrimeNode) + TSTALLOC(MESAsourcePrmPrmSourcePrimePtr,MESAsourcePrmPrmNode,MESAsourcePrimeNode) + TSTALLOC(MESAsourcePrimeSourcePrmPrmPtr,MESAsourcePrimeNode,MESAsourcePrmPrmNode) + TSTALLOC(MESAsourcePrmPrmGatePrimePtr,MESAsourcePrmPrmNode,MESAgatePrimeNode) + TSTALLOC(MESAgatePrimeSourcePrmPrmPtr,MESAgatePrimeNode,MESAsourcePrmPrmNode) + TSTALLOC(MESAdrainPrmPrmDrainPrimePtr,MESAdrainPrmPrmNode,MESAdrainPrimeNode) + TSTALLOC(MESAdrainPrimeDrainPrmPrmPtr,MESAdrainPrimeNode,MESAdrainPrmPrmNode) + TSTALLOC(MESAdrainPrmPrmGatePrimePtr,MESAdrainPrmPrmNode,MESAgatePrimeNode) + TSTALLOC(MESAgatePrimeDrainPrmPrmPtr,MESAgatePrimeNode,MESAdrainPrmPrmNode) + } + } + return(OK); +} + + +int +MESAunsetup(inModel,ckt) + GENmodel *inModel; + CKTcircuit *ckt; +{ + MESAmodel *model; + MESAinstance *here; + + for (model = (MESAmodel *)inModel; model != NULL; + model = model->MESAnextModel) + { + for (here = model->MESAinstances; here != NULL; + here=here->MESAnextInstance) + { + if (here->MESAdrainPrimeNode + && here->MESAdrainPrimeNode != here->MESAdrainNode) + { + CKTdltNNum(ckt, here->MESAdrainPrimeNode); + here->MESAdrainPrimeNode = 0; + } + if (here->MESAsourcePrimeNode + && here->MESAsourcePrimeNode != here->MESAsourceNode) + { + CKTdltNNum(ckt, here->MESAsourcePrimeNode); + here->MESAsourcePrimeNode = 0; + } + if (here->MESAgatePrimeNode + && here->MESAgatePrimeNode != here->MESAgateNode) + { + CKTdltNNum(ckt, here->MESAgatePrimeNode); + here->MESAgatePrimeNode = 0; + } + + } + } + return OK; +} \ No newline at end of file diff --git a/src/spicelib/devices/mesa/mesatemp.c b/src/spicelib/devices/mesa/mesatemp.c new file mode 100644 index 000000000..3940bed9d --- /dev/null +++ b/src/spicelib/devices/mesa/mesatemp.c @@ -0,0 +1,177 @@ +/********** +Copyright 1993: T. Ytterdal, K. Lee, M. Shur and T. A. Fjeldly. All rights reserved. +Author: Trond Ytterdal +**********/ + +#include "ngspice.h" +#include +#include "smpdefs.h" +#include "cktdefs.h" +#include "mesadefs.h" +#include "const.h" +#include "sperror.h" +#include "suffix.h" + + +#define EPSILONGAAS (12.244*8.85418e-12) + +int +MESAtemp(inModel,ckt) + GENmodel *inModel; + CKTcircuit *ckt; +{ + + register MESAmodel *model = (MESAmodel*)inModel; + register MESAinstance *here; + double temp; + double vt; + double d; + + + for( ; model != NULL; model = model->MESAnextModel ) { + if(!model->MESAlambdahfGiven) + model->MESAlambdahf = model->MESAlambda; + if(model->MESAlevel == 2) + model->MESAvpo = CHARGE*model->MESAnd*model->MESAd*model->MESAd/ + 2/EPSILONGAAS; + else { + model->MESAvpou = CHARGE*model->MESAndu*model->MESAdu*model->MESAdu/ + 2/EPSILONGAAS; + model->MESAvpod = CHARGE*model->MESAndelta*model->MESAth* + (2*model->MESAdu + model->MESAth)/2/EPSILONGAAS; + model->MESAvpo = model->MESAvpou+model->MESAvpod; + } + model->MESAdeltaSqr = model->MESAdelta*model->MESAdelta; + + for (here = model->MESAinstances; here != NULL ; + here=here->MESAnextInstance) { + vt = CONSTKoverQ * here->MESAts; + if(model->MESAmu1 == 0 && model->MESAmu2 == 0) + here->MESAtMu = model->MESAmu*pow(here->MESAts/ + model->MESAtmu,model->MESAxtm0); + else { + double muimp = model->MESAmu*pow(here->MESAts/ + model->MESAtmu,model->MESAxtm0); + double mupo = model->MESAmu1*pow(model->MESAtmu/ + here->MESAts,model->MESAxtm1) + + model->MESAmu2*pow(model->MESAtmu/ + here->MESAts,model->MESAxtm2); + here->MESAtMu = 1/(1/muimp+1/mupo); + } + here->MESAtTheta = model->MESAtheta; + here->MESAtPhib = model->MESAphib-model->MESAphib1*(here->MESAts-ckt->CKTnomTemp); + here->MESAtVto = model->MESAthreshold-model->MESAtvto*(here->MESAts-ckt->CKTnomTemp); + here->MESAimax = CHARGE*model->MESAnmax*model->MESAvs*here->MESAwidth; + + if(model->MESAlevel == 2) + here->MESAgchi0 = CHARGE*here->MESAwidth/here->MESAlength; + else + here->MESAgchi0 = CHARGE*here->MESAwidth/here->MESAlength*here->MESAtMu; + here->MESAbeta = 2*EPSILONGAAS*model->MESAvs*model->MESAzeta*here->MESAwidth/ + model->MESAd; + here->MESAtEta = model->MESAeta*(1+here->MESAts/model->MESAteta0)+ + model->MESAteta1/here->MESAts; + here->MESAtLambda= model->MESAlambda*(1-here->MESAts/model->MESAtlambda); + here->MESAtLambdahf = model->MESAlambdahf*(1-here->MESAts/model->MESAtlambda); + if(model->MESAlevel == 3) + d = model->MESAdu; + else + d = model->MESAd; + if(model->MESAlevel == 4) + here->MESAn0 = model->MESAepsi*here->MESAtEta*vt/2/CHARGE/d; + else + here->MESAn0 = EPSILONGAAS*here->MESAtEta*vt/CHARGE/d; + here->MESAnsb0 = EPSILONGAAS*here->MESAtEta*vt/CHARGE/ + (model->MESAdu + model->MESAth); + here->MESAisatb0 = CHARGE*here->MESAn0*vt* + here->MESAwidth/here->MESAlength; + if(model->MESAlevel == 4) + here->MESAcf = 0.5*model->MESAepsi*here->MESAwidth; + else + here->MESAcf = 0.5*EPSILONGAAS*here->MESAwidth; + here->MESAcsatfs = 0.5*model->MESAastar*here->MESAts* + here->MESAts*exp(-here->MESAtPhib/(CONSTboltz*here->MESAts))* + here->MESAlength*here->MESAwidth; + here->MESAcsatfd = 0.5*model->MESAastar*here->MESAtd* + here->MESAtd*exp(-here->MESAtPhib/(CONSTboltz*here->MESAtd))* + here->MESAlength*here->MESAwidth; + here->MESAggrwl = model->MESAggr*here->MESAlength*here->MESAwidth* + exp(model->MESAxchi*(here->MESAts-ckt->CKTnomTemp)); + if(here->MESAcsatfs != 0) + here->MESAvcrits = vt*log(vt/(CONSTroot2 * here->MESAcsatfs)); + else + here->MESAvcrits = DBL_MAX; + if(here->MESAcsatfd != 0) { + double vtd = CONSTKoverQ * here->MESAtd; + here->MESAvcritd = vtd*log(vtd/(CONSTroot2 * here->MESAcsatfd)); + } else + here->MESAvcritd = DBL_MAX; + temp = exp(here->MESAts/model->MESAtf); + here->MESAfl = model->MESAflo*temp; + here->MESAdelf = model->MESAdelfo*temp; + if(model->MESArdi != 0.0) + here->MESAtRdi = model->MESArdi*(1+ + model->MESAtc1*(here->MESAtd-ckt->CKTnomTemp)+ + model->MESAtc2*(here->MESAtd-ckt->CKTnomTemp)*(here->MESAtd-ckt->CKTnomTemp)); + else + here->MESAtRdi = 0; + if(model->MESArsi != 0.0) + here->MESAtRsi = model->MESArsi*(1+ + model->MESAtc1*(here->MESAts-ckt->CKTnomTemp)+ + model->MESAtc2*(here->MESAts-ckt->CKTnomTemp)*(here->MESAts-ckt->CKTnomTemp)); + else + here->MESAtRsi = 0; + if(model->MESAgateResist != 0.0) + here->MESAtRg = model->MESAgateResist*(1+ + model->MESAtc1*(here->MESAts-ckt->CKTnomTemp)+ + model->MESAtc2*(here->MESAts-ckt->CKTnomTemp)*(here->MESAts-ckt->CKTnomTemp)); + else + here->MESAtRg = 0; + if(model->MESAsourceResist != 0.0) + here->MESAtRs = model->MESAsourceResist*(1+ + model->MESAtc1*(here->MESAts-ckt->CKTnomTemp)+ + model->MESAtc2*(here->MESAts-ckt->CKTnomTemp)*(here->MESAts-ckt->CKTnomTemp)); + else + here->MESAtRs = 0; + if(model->MESAdrainResist != 0.0) + here->MESAtRd = model->MESAdrainResist*(1+ + model->MESAtc1*(here->MESAtd-ckt->CKTnomTemp)+ + model->MESAtc2*(here->MESAtd-ckt->CKTnomTemp)*(here->MESAtd-ckt->CKTnomTemp)); + else + here->MESAtRd = 0; + if(model->MESAri != 0.0) + here->MESAtRi = model->MESAri*(1+ + model->MESAtc1*(here->MESAts-ckt->CKTnomTemp)+ + model->MESAtc2*(here->MESAts-ckt->CKTnomTemp)*(here->MESAts-ckt->CKTnomTemp)); + else + here->MESAtRi = 0; + if(model->MESArf != 0.0) + here->MESAtRf = model->MESArf*(1+ + model->MESAtc1*(here->MESAtd-ckt->CKTnomTemp)+ + model->MESAtc2*(here->MESAtd-ckt->CKTnomTemp)*(here->MESAtd-ckt->CKTnomTemp)); + else + here->MESAtRf = 0; + if(here->MESAtRd != 0) + here->MESAdrainConduct = 1/here->MESAtRd; + else + here->MESAdrainConduct = 0; + if(here->MESAtRs != 0) + here->MESAsourceConduct = 1/here->MESAtRs; + else + here->MESAsourceConduct = 0; + if(here->MESAtRg != 0) + here->MESAgateConduct = 1/here->MESAtRg; + else + here->MESAgateConduct = 0; + if(here->MESAtRi != 0) + here->MESAtGi = 1/here->MESAtRi; + else + here->MESAtGi = 0; + if(here->MESAtRf != 0) + here->MESAtGf = 1/here->MESAtRf; + else + here->MESAtGf = 0; + } + } + return(OK); +} diff --git a/src/spicelib/devices/mesa/mesatrunc.c b/src/spicelib/devices/mesa/mesatrunc.c new file mode 100644 index 000000000..43ac9b005 --- /dev/null +++ b/src/spicelib/devices/mesa/mesatrunc.c @@ -0,0 +1,30 @@ +/********** +Copyright 1993: T. Ytterdal, K. Lee, M. Shur and T. A. Fjeldly. All rights reserved. +Author: Trond Ytterdal +**********/ + +#include "ngspice.h" +#include +#include "cktdefs.h" +#include "mesadefs.h" +#include "sperror.h" +#include "suffix.h" + + +int +MESAtrunc(inModel,ckt,timeStep) + GENmodel *inModel; + CKTcircuit *ckt; + double *timeStep; +{ + MESAmodel *model = (MESAmodel*)inModel; + MESAinstance *here; + + for( ; model != NULL; model = model->MESAnextModel) { + for(here=model->MESAinstances;here!=NULL;here = here->MESAnextInstance){ + CKTterr(here->MESAqgs,ckt,timeStep); + CKTterr(here->MESAqgd,ckt,timeStep); + } + } + return(OK); +}