diff --git a/src/spicelib/devices/bjt/bjt.c b/src/spicelib/devices/bjt/bjt.c index acff3f300..69e5bd36a 100644 --- a/src/spicelib/devices/bjt/bjt.c +++ b/src/spicelib/devices/bjt/bjt.c @@ -27,8 +27,8 @@ IFparm BJTpTable[] = { /* parameters */ IOPU("areab", BJT_AREAB, IF_REAL, "Base area factor"), IOPU("areac", BJT_AREAC, IF_REAL, "Collector area factor"), IOPU("m", BJT_M, IF_REAL, "Parallel Multiplier"), - IP("ic", BJT_IC, IF_REALVEC, "Initial condition vector"), - IP("sens_area",BJT_AREA_SENS,IF_FLAG, "flag to request sensitivity WRT area"), + IP("ic", BJT_IC, IF_REALVEC, "Initial condition vector"), + IP("sens_area", BJT_AREA_SENS,IF_FLAG, "flag to request sensitivity WRT area"), OPU("colnode", BJT_QUEST_COLNODE, IF_INTEGER, "Number of collector node"), OPU("basenode", BJT_QUEST_BASENODE, IF_INTEGER, "Number of base node"), OPU("emitnode", BJT_QUEST_EMITNODE, IF_INTEGER, "Number of emitter node"), @@ -50,23 +50,23 @@ IFparm BJTpTable[] = { /* parameters */ OP("gx", BJT_QUEST_GX, IF_REAL, "Conductance from base to internal base"), OP("go", BJT_QUEST_GO, IF_REAL, "Small signal output conductance"), OPU("geqcb",BJT_QUEST_GEQCB,IF_REAL, "d(Ibe)/d(Vbc)"), - OPU("gccs", BJT_QUEST_GCCS, IF_REAL, "Internal C-S cap. equiv. cond."), + OPU("gcsub",BJT_QUEST_GCSUB, IF_REAL, "Internal Subs. cap. equiv. cond."), + OPU("gdsub", BJT_QUEST_GDSUB, IF_REAL, "Internal Subs. Diode equiv. cond."), OPU("geqbx",BJT_QUEST_GEQBX,IF_REAL, "Internal C-B-base cap. equiv. cond."), - OP("cpi",BJT_QUEST_CPI, IF_REAL, "Internal base to emitter capactance"), - OP("cmu",BJT_QUEST_CMU, IF_REAL, "Internal base to collector capactiance"), + OP("cpi",BJT_QUEST_CPI, IF_REAL, "Internal base to emitter capacitance"), + OP("cmu",BJT_QUEST_CMU, IF_REAL, "Internal base to collector capacitance"), OP("cbx",BJT_QUEST_CBX, IF_REAL, "Base to collector capacitance"), - OP("ccs",BJT_QUEST_CCS, IF_REAL, "Collector to substrate capacitance"), - + OP("csub",BJT_QUEST_CSUB, IF_REAL, "Substrate capacitance"), OPU("cqbe", BJT_QUEST_CQBE, IF_REAL, "Cap. due to charge storage in B-E jct."), OPU("cqbc", BJT_QUEST_CQBC, IF_REAL, "Cap. due to charge storage in B-C jct."), - OPU("cqcs", BJT_QUEST_CQCS, IF_REAL, "Cap. due to charge storage in C-S jct."), + OPU("cqsub", BJT_QUEST_CQSUB, IF_REAL, "Cap. due to charge storage in Subs. jct."), OPU("cqbx", BJT_QUEST_CQBX, IF_REAL, "Cap. due to charge storage in B-X jct."), OPU("cexbc",BJT_QUEST_CEXBC,IF_REAL, "Total Capacitance in B-X junction"), OPU("qbe", BJT_QUEST_QBE, IF_REAL, "Charge storage B-E junction"), OPU("qbc", BJT_QUEST_QBC, IF_REAL, "Charge storage B-C junction"), - OPU("qcs", BJT_QUEST_QCS, IF_REAL, "Charge storage C-S junction"), + OPU("qsub", BJT_QUEST_QSUB, IF_REAL, "Charge storage Subs. junction"), OPU("qbx", BJT_QUEST_QBX, IF_REAL, "Charge storage B-X junction"), OPU("p", BJT_QUEST_POWER,IF_REAL, "Power dissipation"), OPU("sens_dc", BJT_QUEST_SENS_DC, IF_REAL, "dc sensitivity "), @@ -84,6 +84,9 @@ IFparm BJTmPTable[] = { /* model parameters */ OP("type", BJT_MOD_TYPE, IF_STRING, "NPN or PNP"), IOPU("npn", BJT_MOD_NPN, IF_FLAG, "NPN type device"), IOPU("pnp", BJT_MOD_PNP, IF_FLAG, "PNP type device"), + IOPU("subs", BJT_MOD_SUBS, IF_INTEGER, "Vertical or Lateral device"), + IOP("tnom", BJT_MOD_TNOM, IF_REAL, "Parameter measurement temperature"), + IOPR("tref", BJT_MOD_TNOM, IF_REAL, "Parameter measurement temperature"), IOP("is", BJT_MOD_IS, IF_REAL, "Saturation Current"), IOP("bf", BJT_MOD_BF, IF_REAL, "Ideal forward beta"), IOP("nf", BJT_MOD_NF, IF_REAL, "Forward emission coefficient"), @@ -128,8 +131,8 @@ IFparm BJTmPTable[] = { /* model parameters */ IOPR("mc", BJT_MOD_MJC, IF_REAL, "B-C junction grading coefficient"), IOPA("xcjc",BJT_MOD_XCJC, IF_REAL, "Fraction of B-C cap to internal base"), IOPA("tr", BJT_MOD_TR, IF_REAL, "Ideal reverse transit time"), - IOPA("cjs", BJT_MOD_CJS, IF_REAL, "Zero bias C-S capacitance"), - IOPA("ccs", BJT_MOD_CJS, IF_REAL, "Zero bias C-S capacitance"), + IOPA("cjs", BJT_MOD_CJS, IF_REAL, "Zero bias Substrate capacitance"), + IOPR("csub", BJT_MOD_CJS, IF_REAL, "Zero bias Substrate capacitance"), IOPA("vjs", BJT_MOD_VJS, IF_REAL, "Substrate junction built in potential"), IOPR("ps", BJT_MOD_VJS, IF_REAL, "Substrate junction built in potential"), IOPA("mjs", BJT_MOD_MJS, IF_REAL, "Substrate junction grading coefficient"), @@ -138,6 +141,8 @@ IFparm BJTmPTable[] = { /* model parameters */ IOP("eg", BJT_MOD_EG, IF_REAL, "Energy gap for IS temp. dependency"), IOP("xti", BJT_MOD_XTI, IF_REAL, "Temp. exponent for IS"), IOP("fc", BJT_MOD_FC, IF_REAL, "Forward bias junction fit parameter"), + IOP("kf", BJT_MOD_KF, IF_REAL, "Flicker Noise Coefficient"), + IOP("af", BJT_MOD_AF, IF_REAL,"Flicker Noise Exponent"), OPU("invearlyvoltf",BJT_MOD_INVEARLYF,IF_REAL,"Inverse early voltage:forward"), OPU("invearlyvoltr",BJT_MOD_INVEARLYR,IF_REAL,"Inverse early voltage:reverse"), OPU("invrollofff", BJT_MOD_INVROLLOFFF, IF_REAL,"Inverse roll off - forward"), @@ -146,11 +151,10 @@ IFparm BJTmPTable[] = { /* model parameters */ OPU("emitterconduct", BJT_MOD_EMITTERCONDUCT,IF_REAL, "Emitter conductance"), OPU("transtimevbcfact",BJT_MOD_TRANSVBCFACT,IF_REAL,"Transit time VBC factor"), OPU("excessphasefactor",BJT_MOD_EXCESSPHASEFACTOR,IF_REAL, "Excess phase fact."), - IOP("tnom", BJT_MOD_TNOM, IF_REAL, "Parameter measurement temperature"), - - IOPR("tref", BJT_MOD_TNOM, IF_REAL, "Parameter measurement temperature"), - IOP("tlev", BJT_MOD_TLEV, IF_REAL, "Temperature equation selector"), - IOP("tlevc", BJT_MOD_TLEVC, IF_REAL, "Temperature equation selector"), + IOP("iss", BJT_MOD_ISS, IF_REAL, "Substrate Jct. Saturation Current"), + IOP("ns", BJT_MOD_NS, IF_REAL, "Substrate current emission coefficient"), + IOP("tlev", BJT_MOD_TLEV, IF_INTEGER, "Temperature equation selector"), + IOP("tlevc", BJT_MOD_TLEVC, IF_INTEGER, "Temperature equation selector"), IOP("tbf1", BJT_MOD_TBF1, IF_REAL, "BF 1. temperature coefficient"), IOP("tbf2", BJT_MOD_TBF2, IF_REAL, "BF 2. temperature coefficient"), IOP("tbr1", BJT_MOD_TBR1, IF_REAL, "BR 1. temperature coefficient"), @@ -197,9 +201,10 @@ IFparm BJTmPTable[] = { /* model parameters */ IOP("tmje2",BJT_MOD_TMJE2, IF_REAL, "MJE 2. temperature coefficient"), IOP("tmjc1",BJT_MOD_TMJC1, IF_REAL, "MJC 1. temperature coefficient"), IOP("tmjc2",BJT_MOD_TMJC2, IF_REAL, "MJC 2. temperature coefficient"), - - IOP("kf", BJT_MOD_KF, IF_REAL, "Flicker Noise Coefficient"), - IOP("af", BJT_MOD_AF, IF_REAL,"Flicker Noise Exponent") + IOP("tmjs1",BJT_MOD_TMJS1, IF_REAL, "MJS 1. temperature coefficient"), + IOP("tmjs2",BJT_MOD_TMJS2, IF_REAL, "MJS 2. temperature coefficient"), + IOP("tns1", BJT_MOD_TNS1, IF_REAL, "NS 1. temperature coefficient"), + IOP("tns2", BJT_MOD_TNS2, IF_REAL, "NS 2. temperature coefficient") }; char *BJTnames[] = { diff --git a/src/spicelib/devices/bjt/bjtask.c b/src/spicelib/devices/bjt/bjtask.c index dc5fcd7cf..85d1ca03a 100644 --- a/src/spicelib/devices/bjt/bjtask.c +++ b/src/spicelib/devices/bjt/bjtask.c @@ -41,17 +41,17 @@ BJTask(CKTcircuit *ckt, GENinstance *instPtr, int which, IFvalue *value, IFvalue return(OK); case BJT_DTEMP: value->rValue = here->BJTdtemp; - return(OK); + return(OK); case BJT_AREA: value->rValue = here->BJTarea; return(OK); - case BJT_AREAB: + case BJT_AREAB: value->rValue = here->BJTareab; return(OK); - case BJT_AREAC: + case BJT_AREAC: value->rValue = here->BJTareac; return(OK); - case BJT_M: + case BJT_M: value->rValue = here->BJTm; return(OK); case BJT_OFF: @@ -92,140 +92,150 @@ BJTask(CKTcircuit *ckt, GENinstance *instPtr, int which, IFvalue *value, IFvalue return(OK); case BJT_QUEST_CC: value->rValue = *(ckt->CKTstate0 + here->BJTcc); - value->rValue *= here->BJTm; + value->rValue *= here->BJTm; return(OK); case BJT_QUEST_CB: value->rValue = *(ckt->CKTstate0 + here->BJTcb); - value->rValue *= here->BJTm; + if (here->BJTmodPtr->BJTsubs==LATERAL) { + value->rValue -= *(ckt->CKTstate0 + here->BJTcdsub); + if ((ckt->CKTcurrentAnalysis & DOING_TRAN) && + !(ckt->CKTmode & MODETRANOP)) { + value->rValue -= *(ckt->CKTstate0 + here->BJTcqsub); + } + }; + value->rValue *= here->BJTm; return(OK); case BJT_QUEST_GPI: value->rValue = *(ckt->CKTstate0 + here->BJTgpi); - value->rValue *= here->BJTm; + value->rValue *= here->BJTm; return(OK); case BJT_QUEST_GMU: value->rValue = *(ckt->CKTstate0 + here->BJTgmu); - value->rValue *= here->BJTm; + value->rValue *= here->BJTm; return(OK); case BJT_QUEST_GM: value->rValue = *(ckt->CKTstate0 + here->BJTgm); - value->rValue *= here->BJTm; + value->rValue *= here->BJTm; return(OK); case BJT_QUEST_GO: value->rValue = *(ckt->CKTstate0 + here->BJTgo); - value->rValue *= here->BJTm; + value->rValue *= here->BJTm; return(OK); case BJT_QUEST_QBE: value->rValue = *(ckt->CKTstate0 + here->BJTqbe); - value->rValue *= here->BJTm; + value->rValue *= here->BJTm; return(OK); case BJT_QUEST_CQBE: value->rValue = *(ckt->CKTstate0 + here->BJTcqbe); - value->rValue *= here->BJTm; + value->rValue *= here->BJTm; return(OK); case BJT_QUEST_QBC: value->rValue = *(ckt->CKTstate0 + here->BJTqbc); - value->rValue *= here->BJTm; + value->rValue *= here->BJTm; return(OK); case BJT_QUEST_CQBC: value->rValue = *(ckt->CKTstate0 + here->BJTcqbc); - value->rValue *= here->BJTm; + value->rValue *= here->BJTm; return(OK); - case BJT_QUEST_QCS: - value->rValue = *(ckt->CKTstate0 + here->BJTqcs); - value->rValue *= here->BJTm; + case BJT_QUEST_QSUB: + value->rValue = *(ckt->CKTstate0 + here->BJTqsub); + value->rValue *= here->BJTm; return(OK); - case BJT_QUEST_CQCS: - value->rValue = *(ckt->CKTstate0 + here->BJTcqcs); - value->rValue *= here->BJTm; + case BJT_QUEST_CQSUB: + value->rValue = *(ckt->CKTstate0 + here->BJTcqsub); + value->rValue *= here->BJTm; return(OK); case BJT_QUEST_QBX: value->rValue = *(ckt->CKTstate0 + here->BJTqbx); - value->rValue *= here->BJTm; + value->rValue *= here->BJTm; return(OK); case BJT_QUEST_CQBX: value->rValue = *(ckt->CKTstate0 + here->BJTcqbx); - value->rValue *= here->BJTm; + value->rValue *= here->BJTm; return(OK); case BJT_QUEST_GX: value->rValue = *(ckt->CKTstate0 + here->BJTgx); - value->rValue *= here->BJTm; + value->rValue *= here->BJTm; return(OK); case BJT_QUEST_CEXBC: value->rValue = *(ckt->CKTstate0 + here->BJTcexbc); - value->rValue *= here->BJTm; + value->rValue *= here->BJTm; return(OK); case BJT_QUEST_GEQCB: value->rValue = *(ckt->CKTstate0 + here->BJTgeqcb); - value->rValue *= here->BJTm; + value->rValue *= here->BJTm; return(OK); - case BJT_QUEST_GCCS: - value->rValue = *(ckt->CKTstate0 + here->BJTgccs); - value->rValue *= here->BJTm; + case BJT_QUEST_GCSUB: + value->rValue = *(ckt->CKTstate0 + here->BJTgcsub); + value->rValue *= here->BJTm; + return(OK); + case BJT_QUEST_GDSUB: + value->rValue = *(ckt->CKTstate0 + here->BJTgdsub); + value->rValue *= here->BJTm; return(OK); case BJT_QUEST_GEQBX: value->rValue = *(ckt->CKTstate0 + here->BJTgeqbx); - value->rValue *= here->BJTm; + value->rValue *= here->BJTm; return(OK); - case BJT_QUEST_SENS_DC: - if(ckt->CKTsenInfo){ - value->rValue = *(ckt->CKTsenInfo->SEN_Sap[select->iValue + 1]+ - here->BJTsenParmNo); + case BJT_QUEST_SENS_DC: + if(ckt->CKTsenInfo){ + value->rValue = *(ckt->CKTsenInfo->SEN_Sap[select->iValue + 1]+ + here->BJTsenParmNo); } - return(OK); - case BJT_QUEST_SENS_REAL: - if(ckt->CKTsenInfo){ - value->rValue = *(ckt->CKTsenInfo->SEN_RHS[select->iValue + 1]+ - here->BJTsenParmNo); + return(OK); + case BJT_QUEST_SENS_REAL: + if(ckt->CKTsenInfo){ + value->rValue = *(ckt->CKTsenInfo->SEN_RHS[select->iValue + 1]+ + here->BJTsenParmNo); } - return(OK); - case BJT_QUEST_SENS_IMAG: - if(ckt->CKTsenInfo){ - value->rValue = *(ckt->CKTsenInfo->SEN_iRHS[select->iValue + 1]+ - here->BJTsenParmNo); + return(OK); + case BJT_QUEST_SENS_IMAG: + if(ckt->CKTsenInfo){ + value->rValue = *(ckt->CKTsenInfo->SEN_iRHS[select->iValue + 1]+ + here->BJTsenParmNo); } - return(OK); - case BJT_QUEST_SENS_MAG: - if(ckt->CKTsenInfo){ - vr = *(ckt->CKTrhsOld + select->iValue + 1); - vi = *(ckt->CKTirhsOld + select->iValue + 1); - vm = sqrt(vr*vr + vi*vi); - if(vm == 0){ - value->rValue = 0; - return(OK); - } - sr = *(ckt->CKTsenInfo->SEN_RHS[select->iValue + 1]+ - here->BJTsenParmNo); - si = *(ckt->CKTsenInfo->SEN_iRHS[select->iValue + 1]+ - here->BJTsenParmNo); + return(OK); + case BJT_QUEST_SENS_MAG: + if(ckt->CKTsenInfo){ + vr = *(ckt->CKTrhsOld + select->iValue + 1); + vi = *(ckt->CKTirhsOld + select->iValue + 1); + vm = sqrt(vr*vr + vi*vi); + if(vm == 0){ + value->rValue = 0; + return(OK); + } + sr = *(ckt->CKTsenInfo->SEN_RHS[select->iValue + 1]+ + here->BJTsenParmNo); + si = *(ckt->CKTsenInfo->SEN_iRHS[select->iValue + 1]+ + here->BJTsenParmNo); value->rValue = (vr * sr + vi * si)/vm; } - return(OK); - case BJT_QUEST_SENS_PH: - if(ckt->CKTsenInfo){ - vr = *(ckt->CKTrhsOld + select->iValue + 1); - vi = *(ckt->CKTirhsOld + select->iValue + 1); - vm = vr*vr + vi*vi; - if(vm == 0){ - value->rValue = 0; - return(OK); - } - sr = *(ckt->CKTsenInfo->SEN_RHS[select->iValue + 1]+ - here->BJTsenParmNo); - si = *(ckt->CKTsenInfo->SEN_iRHS[select->iValue + 1]+ - here->BJTsenParmNo); - + return(OK); + case BJT_QUEST_SENS_PH: + if(ckt->CKTsenInfo){ + vr = *(ckt->CKTrhsOld + select->iValue + 1); + vi = *(ckt->CKTirhsOld + select->iValue + 1); + vm = vr*vr + vi*vi; + if(vm == 0){ + value->rValue = 0; + return(OK); + } + sr = *(ckt->CKTsenInfo->SEN_RHS[select->iValue + 1]+ + here->BJTsenParmNo); + si = *(ckt->CKTsenInfo->SEN_iRHS[select->iValue + 1]+ + here->BJTsenParmNo); value->rValue = (vr * si - vi * sr)/vm; - } - return(OK); - case BJT_QUEST_SENS_CPLX: - if(ckt->CKTsenInfo){ - itmp = select->iValue + 1; - value->cValue.real= *(ckt->CKTsenInfo->SEN_RHS[itmp]+ - here->BJTsenParmNo); - value->cValue.imag= *(ckt->CKTsenInfo->SEN_iRHS[itmp]+ - here->BJTsenParmNo); - } - return(OK); + } + return(OK); + case BJT_QUEST_SENS_CPLX: + if(ckt->CKTsenInfo){ + itmp = select->iValue + 1; + value->cValue.real= *(ckt->CKTsenInfo->SEN_RHS[itmp]+ + here->BJTsenParmNo); + value->cValue.imag= *(ckt->CKTsenInfo->SEN_iRHS[itmp]+ + here->BJTsenParmNo); + } + return(OK); case BJT_QUEST_CS : if (ckt->CKTcurrentAnalysis & DOING_AC) { errMsg = TMALLOC(char, strlen(msg) + 1); @@ -238,8 +248,11 @@ BJTask(CKTcircuit *ckt, GENinstance *instPtr, int which, IFvalue *value, IFvalue (ckt->CKTmode & MODETRANOP)) { value->rValue = 0; } else { - value->rValue = -*(ckt->CKTstate0 + here->BJTcqcs); + value->rValue = -(here->BJTmodPtr->BJTsubs * + (*(ckt->CKTstate0 + here->BJTcqsub) + + *(ckt->CKTstate0 + here->BJTcdsub))); } + value->rValue *= here->BJTm; return(OK); case BJT_QUEST_CE : if (ckt->CKTcurrentAnalysis & DOING_AC) { @@ -250,11 +263,15 @@ BJTask(CKTcircuit *ckt, GENinstance *instPtr, int which, IFvalue *value, IFvalue } else { value->rValue = -*(ckt->CKTstate0 + here->BJTcc); value->rValue -= *(ckt->CKTstate0 + here->BJTcb); - if ((ckt->CKTcurrentAnalysis & DOING_TRAN) && - !(ckt->CKTmode & MODETRANOP)) { - value->rValue += *(ckt->CKTstate0 + here->BJTcqcs); + if (here->BJTmodPtr->BJTsubs==VERTICAL) { + value->rValue += *(ckt->CKTstate0 + here->BJTcdsub); + if ((ckt->CKTcurrentAnalysis & DOING_TRAN) && + !(ckt->CKTmode & MODETRANOP)) { + value->rValue += *(ckt->CKTstate0 + here->BJTcqsub); + } } } + value->rValue *= here->BJTm; return(OK); case BJT_QUEST_POWER : if (ckt->CKTcurrentAnalysis & DOING_AC) { @@ -263,41 +280,42 @@ BJTask(CKTcircuit *ckt, GENinstance *instPtr, int which, IFvalue *value, IFvalue strcpy(errMsg,msg); return(E_ASKPOWER); } else { - value->rValue = *(ckt->CKTstate0 + here->BJTcc) * - *(ckt->CKTrhsOld + here->BJTcolNode); - value->rValue += *(ckt->CKTstate0 + here->BJTcb) * - *(ckt->CKTrhsOld + here->BJTbaseNode); + value->rValue = fabs( *(ckt->CKTstate0 + here->BJTcc) * + (*(ckt->CKTrhsOld + here->BJTcolNode)- + *(ckt->CKTrhsOld + here->BJTemitNode)) + ); + value->rValue +=fabs( *(ckt->CKTstate0 + here->BJTcb) * + (*(ckt->CKTrhsOld + here->BJTbaseNode)- + *(ckt->CKTrhsOld + here->BJTemitNode)) + ); + value->rValue +=fabs( *(ckt->CKTstate0 + here->BJTcdsub) * + (*(ckt->CKTrhsOld + here->BJTsubstConNode)- + *(ckt->CKTrhsOld + here->BJTsubstNode)) + ); if ((ckt->CKTcurrentAnalysis & DOING_TRAN) && !(ckt->CKTmode & MODETRANOP)) { - value->rValue -= *(ckt->CKTstate0 + here->BJTcqcs) * - *(ckt->CKTrhsOld + here->BJTsubstNode); + value->rValue += *(ckt->CKTstate0 + here->BJTcqsub) * + fabs(*(ckt->CKTrhsOld + here->BJTsubstConNode)- + *(ckt->CKTrhsOld + here->BJTsubstNode)); } - tmp = -*(ckt->CKTstate0 + here->BJTcc); - tmp -= *(ckt->CKTstate0 + here->BJTcb); - if ((ckt->CKTcurrentAnalysis & DOING_TRAN) && - !(ckt->CKTmode & MODETRANOP)) { - tmp += *(ckt->CKTstate0 + here->BJTcqcs); - } - value->rValue += tmp * *(ckt->CKTrhsOld + - here->BJTemitNode); } - value->rValue *= here->BJTm; + value->rValue *= here->BJTm; return(OK); - case BJT_QUEST_CPI: - value->rValue = here->BJTcapbe; - value->rValue *= here->BJTm; + case BJT_QUEST_CPI: + value->rValue = here->BJTcapbe; + value->rValue *= here->BJTm; return(OK); - case BJT_QUEST_CMU: - value->rValue = here->BJTcapbc; - value->rValue *= here->BJTm; + case BJT_QUEST_CMU: + value->rValue = here->BJTcapbc; + value->rValue *= here->BJTm; return(OK); - case BJT_QUEST_CBX: - value->rValue = here->BJTcapbx; - value->rValue *= here->BJTm; + case BJT_QUEST_CBX: + value->rValue = here->BJTcapbx; + value->rValue *= here->BJTm; return(OK); - case BJT_QUEST_CCS: - value->rValue = here->BJTcapcs; - value->rValue *= here->BJTm; + case BJT_QUEST_CSUB: + value->rValue = here->BJTcapsub; + value->rValue *= here->BJTm; return(OK); default: return(E_BADPARM); diff --git a/src/spicelib/devices/bjt/bjtdefs.h b/src/spicelib/devices/bjt/bjtdefs.h index 2c02c091f..fade6dc6f 100644 --- a/src/spicelib/devices/bjt/bjtdefs.h +++ b/src/spicelib/devices/bjt/bjtdefs.h @@ -31,6 +31,10 @@ typedef struct sBJTinstance { int BJTcolPrimeNode; /* number of internal collector node of bjt */ int BJTbasePrimeNode; /* number of internal base node of bjt */ int BJTemitPrimeNode; /* number of internal emitter node of bjt */ + int BJTsubstConNode; /* number of node which substrate is connected to */ + /* Substrate connection is either base prime * + * or collector prime depending on whether * + * the device is VERTICAL or LATERAL */ double BJTarea; /* (emitter) area factor for the bjt */ double BJTareab; /* base area factor for the bjt */ double BJTareac; /* collector area factor for the bjt */ @@ -48,11 +52,15 @@ typedef struct sBJTinstance { double BJTtBEpot; /* temperature adjusted B-E potential */ double BJTtBCcap; /* temperature adjusted B-C capacitance */ double BJTtBCpot; /* temperature adjusted B-C potential */ + double BJTtSubcap; /* temperature adjusted Substrate capacitance */ + double BJTtSubpot; /* temperature adjusted Substrate potential */ double BJTtDepCap; /* temperature adjusted join point in diode curve */ double BJTtf1; /* temperature adjusted polynomial coefficient */ double BJTtf4; /* temperature adjusted polynomial coefficient */ double BJTtf5; /* temperature adjusted polynomial coefficient */ double BJTtVcrit; /* temperature adjusted critical voltage */ + double BJTtSubVcrit; /* temperature adjusted substrate critical voltage */ + double BJTtSubSatCur; /* temperature adjusted subst. saturation current */ double BJTtcollectorConduct; /* temperature adjusted */ double BJTtemitterConduct; /* temperature adjusted */ double BJTtbaseResist; /* temperature adjusted */ @@ -62,15 +70,17 @@ typedef struct sBJTinstance { double BJTtinvEarlyVoltR; /* temperature adjusted */ double BJTtinvRollOffF; /* temperature adjusted */ double BJTtinvRollOffR; /* temperature adjusted */ - double BJTtemissionCoeffF; /* temperature adjusted */ - double BJTtemissionCoeffR; /* temperature adjusted */ - double BJTtleakBEemissionCoeff; /* temperature adjusted */ - double BJTtleakBCemissionCoeff; /* temperature adjusted */ + double BJTtemissionCoeffF; /* temperature adjusted NF */ + double BJTtemissionCoeffR; /* temperature adjusted NR */ + double BJTtleakBEemissionCoeff; /* temperature adjusted NE */ + double BJTtleakBCemissionCoeff; /* temperature adjusted NC */ double BJTttransitTimeHighCurrentF; /* temperature adjusted */ double BJTttransitTimeF; /* temperature adjusted */ double BJTttransitTimeR; /* temperature adjusted */ - double BJTtjunctionExpBE; /* temperature adjusted */ - double BJTtjunctionExpBC; /* temperature adjusted */ + double BJTtjunctionExpBE; /* temperature adjusted MJE */ + double BJTtjunctionExpBC; /* temperature adjusted MJC */ + double BJTtjunctionExpSub; /* temperature adjusted MJS */ + double BJTtemissionCoeffS; /* temperature adjusted NS */ double *BJTcolColPrimePtr; /* pointer to sparse matrix at * (collector,collector prime) */ @@ -110,10 +120,15 @@ typedef struct sBJTinstance { * (emitter prime,emitter prime) */ double *BJTsubstSubstPtr; /* pointer to sparse matrix at * (substrate,substrate) */ - double *BJTcolPrimeSubstPtr; /* pointer to sparse matrix at - * (collector prime,substrate) */ - double *BJTsubstColPrimePtr; /* pointer to sparse matrix at - * (substrate,collector prime) */ + double *BJTsubstConSubstPtr; /* pointer to sparse matrix at + * (Substrate connection, substrate) */ + double *BJTsubstSubstConPtr; /* pointer to sparse matrix at + * (substrate, Substrate connection) */ + double *BJTsubstConSubstConPtr; /* pointer to sparse matrix at + * (Substrate connection, Substrate connection) */ + /* Substrate connection is either base prime * + * or collector prime depending on whether * + * the device is VERTICAL or LATERAL */ double *BJTbaseColPrimePtr; /* pointer to sparse matrix at * (base,collector prime) */ double *BJTcolPrimeBasePtr; /* pointer to sparse matrix at @@ -135,7 +150,7 @@ typedef struct sBJTinstance { set equal to 0 if not a design parameter*/ double BJTcapbe; double BJTcapbc; - double BJTcapcs; + double BJTcapsub; double BJTcapbx; double *BJTsens; @@ -148,10 +163,10 @@ typedef struct sBJTinstance { #define BJTsenCmu BJTsens+30 /* stores the perturbed values of cmu */ #define BJTsenCbx BJTsens+35 /* stores the perturbed values of cbx */ #define BJTsenCmcb BJTsens+40 /* stores the perturbed values of cmcb */ -#define BJTsenCcs BJTsens+45 /* stores the perturbed values of ccs */ +#define BJTsenCsub BJTsens+45 /* stores the perturbed values of csub */ #define BJTdphibedp BJTsens+51 #define BJTdphibcdp BJTsens+52 -#define BJTdphicsdp BJTsens+53 +#define BJTdphisubdp BJTsens+53 #define BJTdphibxdp BJTsens+54 /* @@ -254,11 +269,11 @@ typedef struct sBJTinstance { #define BJTRCNOIZ 0 #define BJTRBNOIZ 1 -#define BJT_RE_NOISE 2 +#define BJT_RE_NOISE 2 #define BJTICNOIZ 3 #define BJTIBNOIZ 4 -#define BJTFLNOIZ 5 -#define BJTTOTNOIZ 6 +#define BJTFLNOIZ 5 +#define BJTTOTNOIZ 6 #define BJTNSRCS 7 /* the number of BJT noise sources */ @@ -284,23 +299,26 @@ typedef struct sBJTinstance { #define BJTcqbe BJTstate+9 #define BJTqbc BJTstate+10 #define BJTcqbc BJTstate+11 -#define BJTqcs BJTstate+12 -#define BJTcqcs BJTstate+13 +#define BJTqsub BJTstate+12 +#define BJTcqsub BJTstate+13 #define BJTqbx BJTstate+14 #define BJTcqbx BJTstate+15 #define BJTgx BJTstate+16 #define BJTcexbc BJTstate+17 #define BJTgeqcb BJTstate+18 -#define BJTgccs BJTstate+19 +#define BJTgcsub BJTstate+19 #define BJTgeqbx BJTstate+20 -#define BJTnumStates 21 +#define BJTvsub BJTstate+21 +#define BJTcdsub BJTstate+22 +#define BJTgdsub BJTstate+23 +#define BJTnumStates 24 -#define BJTsensxpbe BJTstate+21 /* charge sensitivities and their - derivatives. +22 for the derivatives - +#define BJTsensxpbe BJTstate+24 /* charge sensitivities and their + derivatives. +25 for the derivatives - pointer to the beginning of the array */ -#define BJTsensxpbc BJTstate+23 -#define BJTsensxpcs BJTstate+25 -#define BJTsensxpbx BJTstate+27 +#define BJTsensxpbc BJTstate+26 +#define BJTsensxpsub BJTstate+28 +#define BJTsensxpbx BJTstate+30 #define BJTnumSenStates 8 @@ -313,6 +331,7 @@ typedef struct sBJTmodel { /* model structure for a bjt */ * that have this model */ IFuid BJTmodName; /* pointer to character string naming this model */ int BJTtype; + int BJTsubs; double BJTtnom; /* nominal temperature */ double BJTsatCur; /* input - don't use */ @@ -348,7 +367,7 @@ typedef struct sBJTmodel { /* model structure for a bjt */ double BJTjunctionExpBC; double BJTbaseFractionBCcap; double BJTtransitTimeR; - double BJTcapCS; + double BJTcapSub; double BJTpotentialSubstrate; double BJTexponentialSubstrate; double BJTbetaExp; @@ -357,6 +376,8 @@ typedef struct sBJTmodel { /* model structure for a bjt */ double BJTdepletionCapCoeff; double BJTfNcoef; double BJTfNexp; + double BJTsubSatCur; /* input - don't use */ + double BJTemissionCoeffS; unsigned BJTtlev; unsigned BJTtlevc; double BJTtbf1; @@ -405,7 +426,10 @@ typedef struct sBJTmodel { /* model structure for a bjt */ double BJTtmje2; double BJTtmjc1; double BJTtmjc2; - + double BJTtmjs1; + double BJTtmjs2; + double BJTtns1; + double BJTtns2; double BJTinvEarlyVoltF; /* inverse of BJTearlyVoltF */ double BJTinvEarlyVoltR; /* inverse of BJTearlyVoltR */ double BJTinvRollOffF; /* inverse of BJTrollOffF */ @@ -419,6 +443,7 @@ typedef struct sBJTmodel { /* model structure for a bjt */ double BJTf6; double BJTf7; + unsigned BJTsubsGiven : 1; unsigned BJTtnomGiven : 1; unsigned BJTsatCurGiven : 1; unsigned BJTbetaFGiven : 1; @@ -453,7 +478,7 @@ typedef struct sBJTmodel { /* model structure for a bjt */ unsigned BJTjunctionExpBCGiven : 1; unsigned BJTbaseFractionBCcapGiven : 1; unsigned BJTtransitTimeRGiven : 1; - unsigned BJTcapCSGiven : 1; + unsigned BJTcapSubGiven : 1; unsigned BJTpotentialSubstrateGiven : 1; unsigned BJTexponentialSubstrateGiven : 1; unsigned BJTbetaExpGiven : 1; @@ -462,6 +487,8 @@ typedef struct sBJTmodel { /* model structure for a bjt */ unsigned BJTdepletionCapCoeffGiven : 1; unsigned BJTfNcoefGiven : 1; unsigned BJTfNexpGiven :1; + unsigned BJTsubSatCurGiven : 1; + unsigned BJTemissionCoeffSGiven : 1; unsigned BJTtlevGiven : 1; unsigned BJTtlevcGiven : 1; unsigned BJTtbf1Given : 1; @@ -510,6 +537,10 @@ typedef struct sBJTmodel { /* model structure for a bjt */ unsigned BJTtmje2Given : 1; unsigned BJTtmjc1Given : 1; unsigned BJTtmjc2Given : 1; + unsigned BJTtmjs1Given : 1; + unsigned BJTtmjs2Given : 1; + unsigned BJTtns1Given : 1; + unsigned BJTtns2Given : 1; } BJTmodel; #ifndef NPN @@ -517,6 +548,15 @@ typedef struct sBJTmodel { /* model structure for a bjt */ #define PNP -1 #endif /*NPN*/ +/* + * BJT defaults to vertical for both NPN and + * PNP devices. + */ +#ifndef VERTICAL +#define VERTICAL 1 +#define LATERAL -1 +#endif /* VERTICAL */ + /* device parameters */ #define BJT_AREA 1 #define BJT_OFF 2 @@ -573,57 +613,64 @@ typedef struct sBJTmodel { /* model structure for a bjt */ #define BJT_MOD_EG 140 #define BJT_MOD_XTI 141 #define BJT_MOD_FC 142 -#define BJT_MOD_TNOM 143 -#define BJT_MOD_TLEV 144 -#define BJT_MOD_TLEVC 145 -#define BJT_MOD_TBF1 146 -#define BJT_MOD_TBF2 147 -#define BJT_MOD_TBR1 148 -#define BJT_MOD_TBR2 149 -#define BJT_MOD_TIKF1 150 -#define BJT_MOD_TIKF2 151 -#define BJT_MOD_TIKR1 152 -#define BJT_MOD_TIKR2 153 -#define BJT_MOD_TIRB1 154 -#define BJT_MOD_TIRB2 155 -#define BJT_MOD_TNC1 156 -#define BJT_MOD_TNC2 157 -#define BJT_MOD_TNE1 158 -#define BJT_MOD_TNE2 159 -#define BJT_MOD_TNF1 160 -#define BJT_MOD_TNF2 161 -#define BJT_MOD_TNR1 162 -#define BJT_MOD_TNR2 163 -#define BJT_MOD_TRB1 164 -#define BJT_MOD_TRB2 165 -#define BJT_MOD_TRC1 166 -#define BJT_MOD_TRC2 167 -#define BJT_MOD_TRE1 168 -#define BJT_MOD_TRE2 169 -#define BJT_MOD_TRM1 170 -#define BJT_MOD_TRM2 171 -#define BJT_MOD_TVAF1 172 -#define BJT_MOD_TVAF2 173 -#define BJT_MOD_TVAR1 174 -#define BJT_MOD_TVAR2 175 -#define BJT_MOD_CTC 176 -#define BJT_MOD_CTE 177 -#define BJT_MOD_CTS 178 -#define BJT_MOD_TVJC 179 -#define BJT_MOD_TVJE 180 -#define BJT_MOD_TVJS 181 -#define BJT_MOD_AF 182 -#define BJT_MOD_KF 183 -#define BJT_MOD_TITF1 184 -#define BJT_MOD_TITF2 185 -#define BJT_MOD_TTF1 186 -#define BJT_MOD_TTF2 187 -#define BJT_MOD_TTR1 188 -#define BJT_MOD_TTR2 189 -#define BJT_MOD_TMJE1 190 -#define BJT_MOD_TMJE2 191 -#define BJT_MOD_TMJC1 192 -#define BJT_MOD_TMJC2 192 +#define BJT_MOD_AF 143 +#define BJT_MOD_KF 144 +#define BJT_MOD_ISS 145 +#define BJT_MOD_NS 146 +#define BJT_MOD_TNOM 147 +#define BJT_MOD_TLEV 148 +#define BJT_MOD_TLEVC 149 +#define BJT_MOD_TBF1 150 +#define BJT_MOD_TBF2 151 +#define BJT_MOD_TBR1 152 +#define BJT_MOD_TBR2 153 +#define BJT_MOD_TIKF1 154 +#define BJT_MOD_TIKF2 155 +#define BJT_MOD_TIKR1 156 +#define BJT_MOD_TIKR2 157 +#define BJT_MOD_TIRB1 158 +#define BJT_MOD_TIRB2 159 +#define BJT_MOD_TNC1 160 +#define BJT_MOD_TNC2 161 +#define BJT_MOD_TNE1 162 +#define BJT_MOD_TNE2 163 +#define BJT_MOD_TNF1 164 +#define BJT_MOD_TNF2 165 +#define BJT_MOD_TNR1 166 +#define BJT_MOD_TNR2 167 +#define BJT_MOD_TRB1 168 +#define BJT_MOD_TRB2 169 +#define BJT_MOD_TRC1 170 +#define BJT_MOD_TRC2 171 +#define BJT_MOD_TRE1 172 +#define BJT_MOD_TRE2 173 +#define BJT_MOD_TRM1 174 +#define BJT_MOD_TRM2 175 +#define BJT_MOD_TVAF1 176 +#define BJT_MOD_TVAF2 177 +#define BJT_MOD_TVAR1 178 +#define BJT_MOD_TVAR2 179 +#define BJT_MOD_CTC 180 +#define BJT_MOD_CTE 181 +#define BJT_MOD_CTS 182 +#define BJT_MOD_TVJC 183 +#define BJT_MOD_TVJE 184 +#define BJT_MOD_TVJS 185 +#define BJT_MOD_TITF1 186 +#define BJT_MOD_TITF2 187 +#define BJT_MOD_TTF1 188 +#define BJT_MOD_TTF2 189 +#define BJT_MOD_TTR1 190 +#define BJT_MOD_TTR2 191 +#define BJT_MOD_TMJE1 192 +#define BJT_MOD_TMJE2 193 +#define BJT_MOD_TMJC1 194 +#define BJT_MOD_TMJC2 195 +#define BJT_MOD_TMJS1 196 +#define BJT_MOD_TMJS2 197 +#define BJT_MOD_TNS1 198 +#define BJT_MOD_TNS2 199 +#define BJT_MOD_SUBS 200 /* device questions */ #define BJT_QUEST_FT 201 @@ -646,14 +693,14 @@ typedef struct sBJTmodel { /* model structure for a bjt */ #define BJT_QUEST_CQBE 218 #define BJT_QUEST_QBC 219 #define BJT_QUEST_CQBC 220 -#define BJT_QUEST_QCS 221 -#define BJT_QUEST_CQCS 222 +#define BJT_QUEST_QSUB 221 +#define BJT_QUEST_CQSUB 222 #define BJT_QUEST_QBX 223 #define BJT_QUEST_CQBX 224 #define BJT_QUEST_GX 225 #define BJT_QUEST_CEXBC 226 #define BJT_QUEST_GEQCB 227 -#define BJT_QUEST_GCCS 228 +#define BJT_QUEST_GCSUB 228 #define BJT_QUEST_GEQBX 229 #define BJT_QUEST_SENS_REAL 230 #define BJT_QUEST_SENS_IMAG 231 @@ -664,11 +711,11 @@ typedef struct sBJTmodel { /* model structure for a bjt */ #define BJT_QUEST_CE 236 #define BJT_QUEST_CS 237 #define BJT_QUEST_POWER 238 - #define BJT_QUEST_CPI 239 #define BJT_QUEST_CMU 240 #define BJT_QUEST_CBX 241 -#define BJT_QUEST_CCS 242 +#define BJT_QUEST_CSUB 242 +#define BJT_QUEST_GDSUB 243 /* model questions */ #define BJT_MOD_INVEARLYF 301 @@ -679,8 +726,8 @@ typedef struct sBJTmodel { /* model structure for a bjt */ #define BJT_MOD_EMITTERCONDUCT 306 #define BJT_MOD_TRANSVBCFACT 307 #define BJT_MOD_EXCESSPHASEFACTOR 308 -#define BJT_MOD_TYPE 309 - +#define BJT_MOD_TYPE 309 +#define BJT_MOD_QUEST_SUBS 310 #include "bjtext.h" #endif /*BJT*/ diff --git a/src/spicelib/devices/bjt/bjtdset.c b/src/spicelib/devices/bjt/bjtdset.c index ea333526f..fbfca9942 100644 --- a/src/spicelib/devices/bjt/bjtdset.c +++ b/src/spicelib/devices/bjt/bjtdset.c @@ -29,7 +29,7 @@ int BJTdSetup(GENmodel *inModel, CKTcircuit *ckt) double c4; double lcapbe1, lcapbe2, lcapbe3; double lcapbx1, lcapbx2, lcapbx3; - double cb = 0; + double cb = 0.0; double cbc; double cbcn; double cbe; @@ -53,7 +53,7 @@ int BJTdSetup(GENmodel *inModel, CKTcircuit *ckt) double f3; double fcpc; double fcpe; - double gbb1 = 0; + double gbb1 = 0.0; double gbc; double gbcn; double gbe; @@ -62,7 +62,7 @@ int BJTdSetup(GENmodel *inModel, CKTcircuit *ckt) double gben2,gben3; double gbcn2,gbcn3; double gben; - double gbb2 = 0, gbb3 = 0; + double gbb2 = 0.0, gbb3 = 0.0; double oik; double oikr; double ovtf; @@ -145,7 +145,7 @@ int BJTdSetup(GENmodel *inModel, CKTcircuit *ckt) /* loop through all the instances of the model */ for (here = model->BJTinstances; here != NULL ; - here=here->BJTnextInstance) { + here=here->BJTnextInstance) { vt = here->BJTtemp * CONSTKoverQ; @@ -160,7 +160,11 @@ int BJTdSetup(GENmodel *inModel, CKTcircuit *ckt) c2=here->BJTtBEleakCur*here->BJTarea * here->BJTm; vte=here->BJTtleakBEemissionCoeff*vt; oikr=here->BJTtinvRollOffR/(here->BJTarea * here->BJTm); - c4=here->BJTtBCleakCur*here->BJTareab * here->BJTm; + c4=here->BJTtBCleakCur * here->BJTm; + if (model->BJTsubs == VERTICAL) + c4 *= here->BJTareab; + else + c4 *= here->BJTareac; /* lateral transistor */ vtc=here->BJTtleakBCemissionCoeff*vt; xjrb=here->BJTtbaseCurrentHalfResist*here->BJTarea * here->BJTm; @@ -168,70 +172,70 @@ int BJTdSetup(GENmodel *inModel, CKTcircuit *ckt) /* * initialization */ - vbe= model->BJTtype*(*(ckt->CKTrhsOld + here->BJTbasePrimeNode) - - *(ckt->CKTrhsOld + here->BJTemitPrimeNode)); - vbc= model->BJTtype*(*(ckt->CKTrhsOld + here->BJTbaseNode) - - *(ckt->CKTrhsOld + here->BJTcolPrimeNode)); - vbx=model->BJTtype*( - *(ckt->CKTrhsOld+here->BJTbaseNode)- - *(ckt->CKTrhsOld+here->BJTcolPrimeNode)); - vsc=model->BJTtype*( - *(ckt->CKTrhsOld+here->BJTsubstNode)- - *(ckt->CKTrhsOld+here->BJTcolPrimeNode)); + vbe= model->BJTtype*(*(ckt->CKTrhsOld + here->BJTbasePrimeNode) - + *(ckt->CKTrhsOld + here->BJTemitPrimeNode)); + vbc= model->BJTtype*(*(ckt->CKTrhsOld + here->BJTbaseNode) - + *(ckt->CKTrhsOld + here->BJTcolPrimeNode)); + vbx=model->BJTtype*( + *(ckt->CKTrhsOld+here->BJTbaseNode)- + *(ckt->CKTrhsOld+here->BJTcolPrimeNode)); + vsc=model->BJTtype*( + *(ckt->CKTrhsOld+here->BJTsubstNode)- + *(ckt->CKTrhsOld+here->BJTcolPrimeNode)); - vbb=model->BJTtype*( - *(ckt->CKTrhsOld+here->BJTbaseNode) - - *(ckt->CKTrhsOld+here->BJTbasePrimeNode)); + vbb=model->BJTtype*( + *(ckt->CKTrhsOld+here->BJTbaseNode) - + *(ckt->CKTrhsOld+here->BJTbasePrimeNode)); - vbed = vbe; /* this is just a dummy variable - * it is the delayed vbe to be - * used in the delayed gm generator - */ + vbed = vbe; /* this is just a dummy variable + * it is the delayed vbe to be + * used in the delayed gm generator + */ - /* ic = f1(vbe,vbc,vbed) + f2(vbc) + f3(vbc) - * - * we shall calculate the taylor coeffs of ic wrt vbe, - * vbed, and vbc and store them away. the equations f1 f2 - * and f3 are given elsewhere; we shall start off with f1, - * compute derivs. upto third order and then do f2 and f3 - * and add their derivatives. - * - * Since f1 above is a function of three variables, it - * will be convenient to use derivative structures to - * compute the derivatives of f1. For this computation, - * p=vbe, q=vbc, r=vbed. - * - * ib = f1(vbe) + f2(vbc) (not the same f's as above, in - * case you are wondering!) the gbe's gbc's gben's and - * gbcn's are convenient subsidiary variables. - * - * irb = f(vbe, vbc, vbb) - the vbe & vbc dependencies - * arise from the qb term. - * - * qbe = f1(vbe,vbc) + f2(vbe) - * - * derivative structures will be used again in the above - * two equations. p=vbe, q=vbc, r=vbb. - * - * qbc = f(vbc) ; qbx = f(vbx) - * - * qss = f(vsc) */ + /* ic = f1(vbe,vbc,vbed) + f2(vbc) + f3(vbc) + * + * we shall calculate the taylor coeffs of ic wrt vbe, + * vbed, and vbc and store them away. the equations f1 f2 + * and f3 are given elsewhere; we shall start off with f1, + * compute derivs. upto third order and then do f2 and f3 + * and add their derivatives. + * + * Since f1 above is a function of three variables, it + * will be convenient to use derivative structures to + * compute the derivatives of f1. For this computation, + * p=vbe, q=vbc, r=vbed. + * + * ib = f1(vbe) + f2(vbc) (not the same f's as above, in + * case you are wondering!) the gbe's gbc's gben's and + * gbcn's are convenient subsidiary variables. + * + * irb = f(vbe, vbc, vbb) - the vbe & vbc dependencies + * arise from the qb term. + * + * qbe = f1(vbe,vbc) + f2(vbe) + * + * derivative structures will be used again in the above + * two equations. p=vbe, q=vbc, r=vbb. + * + * qbc = f(vbc) ; qbx = f(vbx) + * + * qss = f(vsc) */ /* * determine dc current and derivitives */ - vtn=vt*here->BJTtemissionCoeffF; + vtn=vt*here->BJTtemissionCoeffF; if(vbe > -5*vtn){ evbe=exp(vbe/vtn); cbe=csat*(evbe-1)+ckt->CKTgmin*vbe; gbe=csat*evbe/vtn+ckt->CKTgmin; - gbe2 = csat*evbe/vtn/vtn; - gbe3 = gbe2/vtn; + gbe2 = csat*evbe/vtn/vtn; + gbe3 = gbe2/vtn; - /* note - these are actually derivs, not Taylor - * coeffs. - not divided by 2! and 3! - */ + /* note - these are actually derivs, not Taylor + * coeffs. - not divided by 2! and 3! + */ if (c2 == 0) { cben=0; gben=gben2=gben3=0; @@ -239,12 +243,12 @@ int BJTdSetup(GENmodel *inModel, CKTcircuit *ckt) evben=exp(vbe/vte); cben=c2*(evben-1); gben=c2*evben/vte; - gben2=gben/vte; - gben3=gben2/vte; + gben2=gben/vte; + gben3=gben2/vte; } } else { gbe = -csat/vbe+ckt->CKTgmin; - gbe2=gbe3=gben2=gben3=0; + gbe2=gbe3=gben2=gben3=0; cbe=gbe*vbe; gben = -c2/vbe; cben=gben*vbe; @@ -254,453 +258,461 @@ int BJTdSetup(GENmodel *inModel, CKTcircuit *ckt) evbc=exp(vbc/vtn); cbc=csat*(evbc-1)+ckt->CKTgmin*vbc; gbc=csat*evbc/vtn+ckt->CKTgmin; - gbc2=csat*evbc/vtn/vtn; - gbc3=gbc2/vtn; + gbc2=csat*evbc/vtn/vtn; + gbc3=gbc2/vtn; if (c4 == 0) { cbcn=0; gbcn=0; - gbcn2=gbcn3=0; + gbcn2=gbcn3=0; } else { evbcn=exp(vbc/vtc); cbcn=c4*(evbcn-1); gbcn=c4*evbcn/vtc; - gbcn2=gbcn/vtc; - gbcn3=gbcn2/vtc; + gbcn2=gbcn/vtc; + gbcn3=gbcn2/vtc; } } else { gbc = -csat/vbc+ckt->CKTgmin; - gbc2=gbc3=0; + gbc2=gbc3=0; cbc = gbc*vbc; gbcn = -c4/vbc; - gbcn2=gbcn3=0; + gbcn2=gbcn3=0; cbcn=gbcn*vbc; } /* * determine base charge terms */ - /* q1 is a function of 2 variables p=vbe and q=vbc. r= - * anything - */ + /* q1 is a function of 2 variables p=vbe and q=vbc. r= + * anything + */ q1=1/(1-here->BJTtinvEarlyVoltF*vbc-here->BJTtinvEarlyVoltR*vbe); - dummy = (1-here->BJTtinvEarlyVoltF*vbc- - here->BJTtinvEarlyVoltR*vbe); - EqualDeriv(&d_dummy, &d_p); - d_dummy.value = dummy; - d_dummy.d1_p = - here->BJTtinvEarlyVoltR; - d_dummy.d1_q = - here->BJTtinvEarlyVoltF; + dummy = (1-here->BJTtinvEarlyVoltF*vbc- + here->BJTtinvEarlyVoltR*vbe); + EqualDeriv(&d_dummy, &d_p); + d_dummy.value = dummy; + d_dummy.d1_p = - here->BJTtinvEarlyVoltR; + d_dummy.d1_q = - here->BJTtinvEarlyVoltF; - /* q1 = 1/dummy */ - InvDeriv(&d_q1, &d_dummy); + /* q1 = 1/dummy */ + InvDeriv(&d_q1, &d_dummy); - /* now q1 and its derivatives are set up */ + /* now q1 and its derivatives are set up */ if(oik == 0 && oikr == 0) { qb=q1; - EqualDeriv(&d_qb, &d_q1); + EqualDeriv(&d_qb, &d_q1); } else { q2=oik*cbe+oikr*cbc; - EqualDeriv(&d_q2, &d_p); - d_q2.value = q2; - d_q2.d1_p = oik*gbe; - d_q2.d1_q = oikr*gbc; - d_q2.d2_p2 = oik*gbe2; - d_q2.d2_q2 = oikr*gbc2; - d_q2.d3_p3 = oik*gbe3; - d_q2.d3_q3 = oikr*gbc3; + EqualDeriv(&d_q2, &d_p); + d_q2.value = q2; + d_q2.d1_p = oik*gbe; + d_q2.d1_q = oikr*gbc; + d_q2.d2_p2 = oik*gbe2; + d_q2.d2_q2 = oikr*gbc2; + d_q2.d3_p3 = oik*gbe3; + d_q2.d3_q3 = oikr*gbc3; arg=MAX(0,1+4*q2); - if (arg == 0.) - { - EqualDeriv(&d_arg,&d_p); - d_arg.d1_p = 0.0; - } - else - { - TimesDeriv(&d_arg,&d_q2,4.0); - d_arg.value += 1.; - } + if (arg == 0.) + { + EqualDeriv(&d_arg,&d_p); + d_arg.d1_p = 0.0; + } + else + { + TimesDeriv(&d_arg,&d_q2,4.0); + d_arg.value += 1.; + } sqarg=1; - EqualDeriv(&d_sqarg,&d_p); - d_sqarg.value = 1.0; - d_sqarg.d1_p = 0.0; + EqualDeriv(&d_sqarg,&d_p); + d_sqarg.value = 1.0; + d_sqarg.d1_p = 0.0; if(arg != 0){ - sqarg=sqrt(arg); - SqrtDeriv(&d_sqarg, &d_arg); - } + sqarg=sqrt(arg); + SqrtDeriv(&d_sqarg, &d_arg); + } qb=q1*(1+sqarg)/2; - dummy = 1 + sqarg; - EqualDeriv(&d_dummy, &d_sqarg); - d_dummy.value += 1.0; - MultDeriv(&d_qb, &d_q1, &d_dummy); - TimesDeriv(&d_qb, &d_qb, 0.5); + dummy = 1 + sqarg; + EqualDeriv(&d_dummy, &d_sqarg); + d_dummy.value += 1.0; + MultDeriv(&d_qb, &d_q1, &d_dummy); + TimesDeriv(&d_qb, &d_qb, 0.5); } - ic = (cbe - cbc)/qb; - /* cbe is a fn of vbed only; cbc of vbc; and qb of vbe and vbc */ - /* p=vbe, q=vbc, r=vbed; now dummy = cbe - cbc */ - EqualDeriv(&d_dummy, &d_p); - d_dummy.d1_p = 0.0; - d_dummy.value = cbe-cbc; - d_dummy.d1_r = gbe; - d_dummy.d2_r2 = gbe2; - d_dummy.d3_r3 = gbe3; - d_dummy.d1_q = -gbc; - d_dummy.d2_q2 = -gbc2; - d_dummy.d3_q3 = -gbc3; + ic = (cbe - cbc)/qb; + /* cbe is a fn of vbed only; cbc of vbc; and qb of vbe and vbc */ + /* p=vbe, q=vbc, r=vbed; now dummy = cbe - cbc */ + EqualDeriv(&d_dummy, &d_p); + d_dummy.d1_p = 0.0; + d_dummy.value = cbe-cbc; + d_dummy.d1_r = gbe; + d_dummy.d2_r2 = gbe2; + d_dummy.d3_r3 = gbe3; + d_dummy.d1_q = -gbc; + d_dummy.d2_q2 = -gbc2; + d_dummy.d3_q3 = -gbc3; - DivDeriv(&d_ic, &d_dummy, &d_qb); + DivDeriv(&d_ic, &d_dummy, &d_qb); - d_ic.value -= cbc/here->BJTtBetaR + cbcn; - d_ic.d1_q -= gbc/here->BJTtBetaR + gbcn; - d_ic.d2_q2 -= gbc2/here->BJTtBetaR + gbcn2; - d_ic.d3_q3 -= gbc3/here->BJTtBetaR + gbcn3; + d_ic.value -= cbc/here->BJTtBetaR + cbcn; + d_ic.d1_q -= gbc/here->BJTtBetaR + gbcn; + d_ic.d2_q2 -= gbc2/here->BJTtBetaR + gbcn2; + d_ic.d3_q3 -= gbc3/here->BJTtBetaR + gbcn3; - /* check this point: where is the f2(vbe) contribution to ic ? */ + /* check this point: where is the f2(vbe) contribution to ic ? */ - /* ic derivatives all set up now */ - /* base spread resistance */ + /* ic derivatives all set up now */ + /* base spread resistance */ - if ( !((rbpr == 0.0) && (rbpi == 0.0))) - { - cb=cbe/here->BJTtBetaF+cben+cbc/here->BJTtBetaR+cbcn; - /* we are calculating derivatives w.r.t cb itself */ - /* - gx=rbpr+rbpi/qb; - */ + if ( !((rbpr == 0.0) && (rbpi == 0.0))) + { + cb=cbe/here->BJTtBetaF+cben+cbc/here->BJTtBetaR+cbcn; + /* we are calculating derivatives w.r.t cb itself */ + /* + gx=rbpr+rbpi/qb; + */ - if (cb != 0.0) { - if((xjrb != 0.0) && (rbpi != 0.0)) { - /* p = ib, q, r = anything */ - dummy=MAX(cb/xjrb,1e-9); - EqualDeriv(&d_dummy, &d_p); - d_dummy.value = dummy; - d_dummy.d1_p = 1/xjrb; - SqrtDeriv(&d_dummy, &d_dummy); - TimesDeriv(&d_dummy, &d_dummy, 2.4317); + if (cb != 0.0) { + if((xjrb != 0.0) && (rbpi != 0.0)) { + /* p = ib, q, r = anything */ + dummy=MAX(cb/xjrb,1e-9); + EqualDeriv(&d_dummy, &d_p); + d_dummy.value = dummy; + d_dummy.d1_p = 1/xjrb; + SqrtDeriv(&d_dummy, &d_dummy); + TimesDeriv(&d_dummy, &d_dummy, 2.4317); - /* - dummy2=(-1+sqrt(1+14.59025*MAX(cb/xjrb,1e-9))); - */ - EqualDeriv(&d_dummy2, &d_p); - d_dummy2.value = 1+14.59025*MAX(cb/xjrb,1e-9); - d_dummy2.d1_p = 14.59025/xjrb; - SqrtDeriv(&d_dummy2, &d_dummy2); - d_dummy2.value -= 1.0; + /* + dummy2=(-1+sqrt(1+14.59025*MAX(cb/xjrb,1e-9))); + */ + EqualDeriv(&d_dummy2, &d_p); + d_dummy2.value = 1+14.59025*MAX(cb/xjrb,1e-9); + d_dummy2.d1_p = 14.59025/xjrb; + SqrtDeriv(&d_dummy2, &d_dummy2); + d_dummy2.value -= 1.0; - DivDeriv(&d_z, &d_dummy2, &d_dummy); - TanDeriv(&d_tanz, &d_z); + DivDeriv(&d_z, &d_dummy2, &d_dummy); + TanDeriv(&d_tanz, &d_z); - /* now using dummy = tanz - z and dummy2 = + /* now using dummy = tanz - z and dummy2 = z*tanz*tanz */ - TimesDeriv(&d_dummy, &d_z, -1.0); - PlusDeriv(&d_dummy, &d_dummy, &d_tanz); + TimesDeriv(&d_dummy, &d_z, -1.0); + PlusDeriv(&d_dummy, &d_dummy, &d_tanz); - MultDeriv(&d_dummy2, &d_tanz, &d_tanz); - MultDeriv(&d_dummy2, &d_dummy2, &d_z); + MultDeriv(&d_dummy2, &d_tanz, &d_tanz); + MultDeriv(&d_dummy2, &d_dummy2, &d_z); - DivDeriv(&d_rbb , &d_dummy, &d_dummy2); - TimesDeriv(&d_rbb,&d_rbb, 3.0*rbpi); - d_rbb.value += rbpr; + DivDeriv(&d_rbb , &d_dummy, &d_dummy2); + TimesDeriv(&d_rbb,&d_rbb, 3.0*rbpi); + d_rbb.value += rbpr; - MultDeriv(&d_vbb, &d_rbb, &d_p); + MultDeriv(&d_vbb, &d_rbb, &d_p); - /* power series inversion to get the + /* power series inversion to get the conductance derivatives */ - if (d_vbb.d1_p != 0) { - gbb1 = 1/d_vbb.d1_p; - gbb2 = -(d_vbb.d2_p2*0.5)*gbb1*gbb1; - gbb3 = gbb1*gbb1*gbb1*gbb1*(-(d_vbb.d3_p3/6.0) - + 2*(d_vbb.d2_p2*0.5)*(d_vbb.d2_p2*0.5)*gbb1); - } - else - printf("\nd_vbb.d1_p = 0 in base spread resistance calculations\n"); + if (d_vbb.d1_p != 0) { + gbb1 = 1/d_vbb.d1_p; + gbb2 = -(d_vbb.d2_p2*0.5)*gbb1*gbb1; + gbb3 = gbb1*gbb1*gbb1*gbb1*(-(d_vbb.d3_p3/6.0) + + 2*(d_vbb.d2_p2*0.5)*(d_vbb.d2_p2*0.5)*gbb1); + } + else + printf("\nd_vbb.d1_p = 0 in base spread resistance calculations\n"); - /* r = vbb */ - EqualDeriv(&d_ibb, &d_r); - d_ibb.value = cb; - d_ibb.d1_r = gbb1; - d_ibb.d2_r2 = 2*gbb2; - d_ibb.d3_r3 = 6.0*gbb3; - } - else - { - /* - rbb = rbpr + rbpi/qb; - ibb = vbb /rbb; = f(vbe, vbc, vbb) - */ + /* r = vbb */ + EqualDeriv(&d_ibb, &d_r); + d_ibb.value = cb; + d_ibb.d1_r = gbb1; + d_ibb.d2_r2 = 2*gbb2; + d_ibb.d3_r3 = 6.0*gbb3; + } + else + { + /* + rbb = rbpr + rbpi/qb; + ibb = vbb /rbb; = f(vbe, vbc, vbb) + */ - EqualDeriv(&d_rbb,&d_p); - d_rbb.d1_p = 0.0; - if (rbpi != 0.0) { - InvDeriv(&d_rbb, &d_qb); - TimesDeriv(&d_rbb, &d_rbb,rbpi); - } - d_rbb.value += rbpr; + EqualDeriv(&d_rbb,&d_p); + d_rbb.d1_p = 0.0; + if (rbpi != 0.0) { + InvDeriv(&d_rbb, &d_qb); + TimesDeriv(&d_rbb, &d_rbb,rbpi); + } + d_rbb.value += rbpr; - EqualDeriv(&d_ibb,&d_r); - d_ibb.value = vbb; - DivDeriv(&d_ibb,&d_ibb,&d_rbb); + EqualDeriv(&d_ibb,&d_r); + d_ibb.value = vbb; + DivDeriv(&d_ibb,&d_ibb,&d_rbb); - } - } - else - { - EqualDeriv(&d_ibb,&d_r); - if (rbpr != 0.0) - d_ibb.d1_r = 1/rbpr; - } - } - else - { - EqualDeriv(&d_ibb,&d_p); - d_ibb.d1_p = 0.0; - } + } + } + else + { + EqualDeriv(&d_ibb,&d_r); + if (rbpr != 0.0) + d_ibb.d1_r = 1/rbpr; + } + } + else + { + EqualDeriv(&d_ibb,&d_p); + d_ibb.d1_p = 0.0; + } - /* formulae for base spread resistance over! */ + /* formulae for base spread resistance over! */ - /* ib term */ + /* ib term */ - EqualDeriv(&d_ib, &d_p); - d_ib.d1_p = 0.0; - d_ib.value = cb; - d_ib.d1_p = gbe/here->BJTtBetaF + gben; - d_ib.d2_p2 = gbe2/here->BJTtBetaF + gben2; - d_ib.d3_p3 = gbe3/here->BJTtBetaF + gben3; + EqualDeriv(&d_ib, &d_p); + d_ib.d1_p = 0.0; + d_ib.value = cb; + d_ib.d1_p = gbe/here->BJTtBetaF + gben; + d_ib.d2_p2 = gbe2/here->BJTtBetaF + gben2; + d_ib.d3_p3 = gbe3/here->BJTtBetaF + gben3; - d_ib.d1_q = gbc/here->BJTtBetaR + gbcn; - d_ib.d2_q2 = gbc2/here->BJTtBetaR + gbcn2; - d_ib.d3_q3 = gbc3/here->BJTtBetaR + gbcn3; + d_ib.d1_q = gbc/here->BJTtBetaR + gbcn; + d_ib.d2_q2 = gbc2/here->BJTtBetaR + gbcn2; + d_ib.d3_q3 = gbc3/here->BJTtBetaR + gbcn3; - /* ib term over */ - /* - * charge storage elements - */ - tf=here->BJTttransitTimeF; - tr=here->BJTttransitTimeR; - czbe=here->BJTtBEcap*here->BJTarea * here->BJTm; - pe=here->BJTtBEpot; - xme=here->BJTtjunctionExpBE; - cdis=model->BJTbaseFractionBCcap; - ctot=here->BJTtBCcap*here->BJTareab * here->BJTm; - czbc=ctot*cdis; - czbx=ctot-czbc; - pc=here->BJTtBCpot; - xmc=here->BJTtjunctionExpBC; - fcpe=here->BJTtDepCap; - czcs=model->BJTcapCS*here->BJTareac * here->BJTm; - ps=model->BJTpotentialSubstrate; - xms=model->BJTexponentialSubstrate; - xtf=model->BJTtransitTimeBiasCoeffF; - ovtf=model->BJTtransitTimeVBCFactor; - xjtf=here->BJTttransitTimeHighCurrentF*here->BJTarea * here->BJTm; - if(tf != 0 && vbe >0) { - EqualDeriv(&d_cbe, &d_p); - d_cbe.value = cbe; - d_cbe.d1_p = gbe; - d_cbe.d2_p2 = gbe2; - d_cbe.d3_p3 = gbe3; - if(xtf != 0){ - if(ovtf != 0) { - /* dummy = exp ( vbc*ovtf) */ - EqualDeriv(&d_dummy, &d_q); - d_dummy.value = vbc*ovtf; - d_dummy.d1_q = ovtf; - ExpDeriv(&d_dummy, &d_dummy); - } - else - { - EqualDeriv(&d_dummy,&d_p); - d_dummy.value = 1.0; - d_dummy.d1_p = 0.0; - } - if(xjtf != 0) { - EqualDeriv(&d_dummy2, &d_cbe); - d_dummy2.value += xjtf; - DivDeriv(&d_dummy2, &d_cbe, &d_dummy2); - MultDeriv (&d_dummy2, &d_dummy2, &d_dummy2); - } - else - { - EqualDeriv(&d_dummy2,&d_p); - d_dummy2.value = 1.0; - d_dummy2.d1_p = 0.0; - } - - MultDeriv(&d_tff, &d_dummy, &d_dummy2); - TimesDeriv(&d_tff, &d_tff, tf*xtf); - d_tff.value += tf; - } - else - { - EqualDeriv(&d_tff,&d_p); - d_tff.value = tf; - d_tff.d1_p = 0.0; - } + /* ib term over */ + /* + * charge storage elements + */ + tf=here->BJTttransitTimeF; + tr=here->BJTttransitTimeR; + czbe=here->BJTtBEcap*here->BJTarea * here->BJTm; + pe=here->BJTtBEpot; + xme=here->BJTtjunctionExpBE; + cdis=model->BJTbaseFractionBCcap; + ctot=here->BJTtBCcap * here->BJTm; + if (model->BJTsubs == VERTICAL) + ctot *= here->BJTareab; + else + ctot *= here->BJTareac; + czbc=ctot*cdis; + czbx=ctot-czbc; + pc=here->BJTtBCpot; + xmc=here->BJTtjunctionExpBC; + fcpe=here->BJTtDepCap; + czcs=model->BJTcapSub * here->BJTm; + if (model->BJTsubs == VERTICAL) + czcs *= here->BJTareac; + else + czcs *= here->BJTareab; + ps=model->BJTpotentialSubstrate; + xms=model->BJTexponentialSubstrate; + xtf=model->BJTtransitTimeBiasCoeffF; + ovtf=model->BJTtransitTimeVBCFactor; + xjtf=here->BJTttransitTimeHighCurrentF*here->BJTarea * here->BJTm; + if(tf != 0 && vbe >0) { + EqualDeriv(&d_cbe, &d_p); + d_cbe.value = cbe; + d_cbe.d1_p = gbe; + d_cbe.d2_p2 = gbe2; + d_cbe.d3_p3 = gbe3; + if(xtf != 0){ + if(ovtf != 0) { + /* dummy = exp ( vbc*ovtf) */ + EqualDeriv(&d_dummy, &d_q); + d_dummy.value = vbc*ovtf; + d_dummy.d1_q = ovtf; + ExpDeriv(&d_dummy, &d_dummy); + } + else + { + EqualDeriv(&d_dummy,&d_p); + d_dummy.value = 1.0; + d_dummy.d1_p = 0.0; + } + if(xjtf != 0) { + EqualDeriv(&d_dummy2, &d_cbe); + d_dummy2.value += xjtf; + DivDeriv(&d_dummy2, &d_cbe, &d_dummy2); + MultDeriv (&d_dummy2, &d_dummy2, &d_dummy2); + } + else + { + EqualDeriv(&d_dummy2,&d_p); + d_dummy2.value = 1.0; + d_dummy2.d1_p = 0.0; + } + + MultDeriv(&d_tff, &d_dummy, &d_dummy2); + TimesDeriv(&d_tff, &d_tff, tf*xtf); + d_tff.value += tf; + } + else + { + EqualDeriv(&d_tff,&d_p); + d_tff.value = tf; + d_tff.d1_p = 0.0; + } - /* qbe = tff/qb*cbe */ + /* qbe = tff/qb*cbe */ - /* - dummy = tff/qb; - */ - /* these are the cbe coeffs */ - DivDeriv(&d_dummy, &d_tff, &d_qb); - MultDeriv(&d_qbe, &d_dummy, &d_cbe); + /* + dummy = tff/qb; + */ + /* these are the cbe coeffs */ + DivDeriv(&d_dummy, &d_tff, &d_qb); + MultDeriv(&d_qbe, &d_dummy, &d_cbe); - } - else - { - EqualDeriv(&d_qbe, &d_p); - d_qbe.value = 0.0; - d_qbe.d1_p = 0.0; - } - if (vbe < fcpe) { - arg=1-vbe/pe; - sarg=exp(-xme*log(arg)); - lcapbe1 = czbe*sarg; - lcapbe2 = - 0.5*czbe*xme*sarg/(arg*pe); - lcapbe3 = - czbe*xme*(xme+1)*sarg/(arg*arg*pe*pe*6); - } else { - f1=here->BJTtf1; - f2=model->BJTf2; - f3=model->BJTf3; - czbef2=czbe/f2; - lcapbe1 = czbef2*(f3+xme*vbe/pe); - lcapbe2 = 0.5*xme*czbef2/pe; - lcapbe3 = 0.0; - } - d_qbe.d1_p += lcapbe1; - d_qbe.d2_p2 += lcapbe2*2.; - d_qbe.d3_p3 += lcapbe3*6.; + } + else + { + EqualDeriv(&d_qbe, &d_p); + d_qbe.value = 0.0; + d_qbe.d1_p = 0.0; + } + if (vbe < fcpe) { + arg=1-vbe/pe; + sarg=exp(-xme*log(arg)); + lcapbe1 = czbe*sarg; + lcapbe2 = + 0.5*czbe*xme*sarg/(arg*pe); + lcapbe3 = + czbe*xme*(xme+1)*sarg/(arg*arg*pe*pe*6); + } else { + f1=here->BJTtf1; + f2=model->BJTf2; + f3=model->BJTf3; + czbef2=czbe/f2; + lcapbe1 = czbef2*(f3+xme*vbe/pe); + lcapbe2 = 0.5*xme*czbef2/pe; + lcapbe3 = 0.0; + } + d_qbe.d1_p += lcapbe1; + d_qbe.d2_p2 += lcapbe2*2.; + d_qbe.d3_p3 += lcapbe3*6.; - fcpc=here->BJTtf4; - f1=here->BJTtf5; - f2=model->BJTf6; - f3=model->BJTf7; - if (vbc < fcpc) { - arg=1-vbc/pc; - sarg=exp(-xmc*log(arg)); - lcapbc1 = czbc*sarg; - lcapbc2 = - 0.5*czbc*xmc*sarg/(arg*pc); - lcapbc3 = - czbc*xmc*(xmc+1)*sarg/(arg*arg*pc*pc*6); - } else { - czbcf2=czbc/f2; - lcapbc1 = czbcf2*(f3+xmc*vbc/pc); - lcapbc2 = 0.5*xmc*czbcf2/pc; - lcapbc3 = 0; - } - if(vbx < fcpc) { - arg=1-vbx/pc; - sarg=exp(-xmc*log(arg)); - lcapbx1 = czbx*sarg; - lcapbx2 = - 0.5*czbx*xmc*sarg/(arg*pc); - lcapbx3 = - czbx*xmc*(xmc+1)*sarg/(arg*arg*pc*pc*6); - } else { - czbxf2=czbx/f2; - lcapbx1 = czbxf2*(f3+xmc*vbx/pc); - lcapbx2 = 0.5*xmc*czbxf2/pc; - lcapbx3 = 0; - } - if(vsc < 0){ - arg=1-vsc/ps; - sarg=exp(-xms*log(arg)); - lcapsc1 = czcs*sarg; - lcapsc2 = - 0.5*czcs*xms*sarg/(arg*ps); - lcapsc3 = - czcs*xms*(xms+1)*sarg/(arg*arg*ps*ps*6); - } else { - lcapsc1 = czcs*(1+xms*vsc/ps); - lcapsc2 = czcs*0.5*xms/ps; - lcapsc3 = 0; - } + fcpc=here->BJTtf4; + f1=here->BJTtf5; + f2=model->BJTf6; + f3=model->BJTf7; + if (vbc < fcpc) { + arg=1-vbc/pc; + sarg=exp(-xmc*log(arg)); + lcapbc1 = czbc*sarg; + lcapbc2 = + 0.5*czbc*xmc*sarg/(arg*pc); + lcapbc3 = + czbc*xmc*(xmc+1)*sarg/(arg*arg*pc*pc*6); + } else { + czbcf2=czbc/f2; + lcapbc1 = czbcf2*(f3+xmc*vbc/pc); + lcapbc2 = 0.5*xmc*czbcf2/pc; + lcapbc3 = 0; + } + if(vbx < fcpc) { + arg=1-vbx/pc; + sarg=exp(-xmc*log(arg)); + lcapbx1 = czbx*sarg; + lcapbx2 = + 0.5*czbx*xmc*sarg/(arg*pc); + lcapbx3 = + czbx*xmc*(xmc+1)*sarg/(arg*arg*pc*pc*6); + } else { + czbxf2=czbx/f2; + lcapbx1 = czbxf2*(f3+xmc*vbx/pc); + lcapbx2 = 0.5*xmc*czbxf2/pc; + lcapbx3 = 0; + } + if(vsc < 0){ + arg=1-vsc/ps; + sarg=exp(-xms*log(arg)); + lcapsc1 = czcs*sarg; + lcapsc2 = + 0.5*czcs*xms*sarg/(arg*ps); + lcapsc3 = + czcs*xms*(xms+1)*sarg/(arg*arg*ps*ps*6); + } else { + lcapsc1 = czcs*(1+xms*vsc/ps); + lcapsc2 = czcs*0.5*xms/ps; + lcapsc3 = 0; + } - /* - * store small-signal parameters - */ - here->ic_x = d_ic.d1_p; - here->ic_y = d_ic.d1_q; - here->ic_xd = d_ic.d1_r; - here->ic_x2 = 0.5*model->BJTtype*d_ic.d2_p2; - here->ic_y2 = 0.5*model->BJTtype*d_ic.d2_q2; - here->ic_w2 = 0.5*model->BJTtype*d_ic.d2_r2; - here->ic_xy = model->BJTtype*d_ic.d2_pq; - here->ic_yw = model->BJTtype*d_ic.d2_qr; - here->ic_xw = model->BJTtype*d_ic.d2_pr; - here->ic_x3 = d_ic.d3_p3/6.; - here->ic_y3 = d_ic.d3_q3/6.; - here->ic_w3 = d_ic.d3_r3/6.; - here->ic_x2w = 0.5*d_ic.d3_p2r; - here->ic_x2y = 0.5*d_ic.d3_p2q; - here->ic_y2w = 0.5*d_ic.d3_q2r; - here->ic_xy2 = 0.5*d_ic.d3_pq2; - here->ic_xw2 = 0.5*d_ic.d3_pr2; - here->ic_yw2 = 0.5*d_ic.d3_qr2; - here->ic_xyw = d_ic.d3_pqr; + /* + * store small-signal parameters + */ + here->ic_x = d_ic.d1_p; + here->ic_y = d_ic.d1_q; + here->ic_xd = d_ic.d1_r; + here->ic_x2 = 0.5*model->BJTtype*d_ic.d2_p2; + here->ic_y2 = 0.5*model->BJTtype*d_ic.d2_q2; + here->ic_w2 = 0.5*model->BJTtype*d_ic.d2_r2; + here->ic_xy = model->BJTtype*d_ic.d2_pq; + here->ic_yw = model->BJTtype*d_ic.d2_qr; + here->ic_xw = model->BJTtype*d_ic.d2_pr; + here->ic_x3 = d_ic.d3_p3/6.; + here->ic_y3 = d_ic.d3_q3/6.; + here->ic_w3 = d_ic.d3_r3/6.; + here->ic_x2w = 0.5*d_ic.d3_p2r; + here->ic_x2y = 0.5*d_ic.d3_p2q; + here->ic_y2w = 0.5*d_ic.d3_q2r; + here->ic_xy2 = 0.5*d_ic.d3_pq2; + here->ic_xw2 = 0.5*d_ic.d3_pr2; + here->ic_yw2 = 0.5*d_ic.d3_qr2; + here->ic_xyw = d_ic.d3_pqr; - here->ib_x = d_ib.d1_p; - here->ib_y = d_ib.d1_q; - here->ib_x2 = 0.5*model->BJTtype*d_ib.d2_p2; - here->ib_y2 = 0.5*model->BJTtype*d_ib.d2_q2; - here->ib_xy = model->BJTtype*d_ib.d2_pq; - here->ib_x3 = d_ib.d3_p3/6.; - here->ib_y3 = d_ib.d3_q3/6.; - here->ib_x2y = 0.5*d_ib.d3_p2q; - here->ib_xy2 = 0.5*d_ib.d3_pq2; + here->ib_x = d_ib.d1_p; + here->ib_y = d_ib.d1_q; + here->ib_x2 = 0.5*model->BJTtype*d_ib.d2_p2; + here->ib_y2 = 0.5*model->BJTtype*d_ib.d2_q2; + here->ib_xy = model->BJTtype*d_ib.d2_pq; + here->ib_x3 = d_ib.d3_p3/6.; + here->ib_y3 = d_ib.d3_q3/6.; + here->ib_x2y = 0.5*d_ib.d3_p2q; + here->ib_xy2 = 0.5*d_ib.d3_pq2; - here->ibb_x = d_ibb.d1_p; - here->ibb_y = d_ibb.d1_q; - here->ibb_z = d_ibb.d1_r; - here->ibb_x2 = 0.5*model->BJTtype*d_ibb.d2_p2; - here->ibb_y2 = 0.5*model->BJTtype*d_ibb.d2_q2; - here->ibb_z2 = 0.5*model->BJTtype*d_ibb.d2_r2; - here->ibb_xy = model->BJTtype*d_ibb.d2_pq; - here->ibb_yz = model->BJTtype*d_ibb.d2_qr; - here->ibb_xz = model->BJTtype*d_ibb.d2_pr; - here->ibb_x3 = d_ibb.d3_p3/6.; - here->ibb_y3 = d_ibb.d3_q3/6.; - here->ibb_z3 = d_ibb.d3_r3/6.; - here->ibb_x2z = 0.5*d_ibb.d3_p2r; - here->ibb_x2y = 0.5*d_ibb.d3_p2q; - here->ibb_y2z = 0.5*d_ibb.d3_q2r; - here->ibb_xy2 = 0.5*d_ibb.d3_pq2; - here->ibb_xz2 = 0.5*d_ibb.d3_pr2; - here->ibb_yz2 = 0.5*d_ibb.d3_qr2; - here->ibb_xyz = d_ibb.d3_pqr; + here->ibb_x = d_ibb.d1_p; + here->ibb_y = d_ibb.d1_q; + here->ibb_z = d_ibb.d1_r; + here->ibb_x2 = 0.5*model->BJTtype*d_ibb.d2_p2; + here->ibb_y2 = 0.5*model->BJTtype*d_ibb.d2_q2; + here->ibb_z2 = 0.5*model->BJTtype*d_ibb.d2_r2; + here->ibb_xy = model->BJTtype*d_ibb.d2_pq; + here->ibb_yz = model->BJTtype*d_ibb.d2_qr; + here->ibb_xz = model->BJTtype*d_ibb.d2_pr; + here->ibb_x3 = d_ibb.d3_p3/6.; + here->ibb_y3 = d_ibb.d3_q3/6.; + here->ibb_z3 = d_ibb.d3_r3/6.; + here->ibb_x2z = 0.5*d_ibb.d3_p2r; + here->ibb_x2y = 0.5*d_ibb.d3_p2q; + here->ibb_y2z = 0.5*d_ibb.d3_q2r; + here->ibb_xy2 = 0.5*d_ibb.d3_pq2; + here->ibb_xz2 = 0.5*d_ibb.d3_pr2; + here->ibb_yz2 = 0.5*d_ibb.d3_qr2; + here->ibb_xyz = d_ibb.d3_pqr; - here->qbe_x = d_qbe.d1_p; - here->qbe_y = d_qbe.d1_q; - here->qbe_x2 = 0.5*model->BJTtype*d_qbe.d2_p2; - here->qbe_y2 = 0.5*model->BJTtype*d_qbe.d2_q2; - here->qbe_xy = model->BJTtype*d_qbe.d2_pq; - here->qbe_x3 = d_qbe.d3_p3/6.; - here->qbe_y3 = d_qbe.d3_q3/6.; - here->qbe_x2y = 0.5*d_qbe.d3_p2q; - here->qbe_xy2 = 0.5*d_qbe.d3_pq2; + here->qbe_x = d_qbe.d1_p; + here->qbe_y = d_qbe.d1_q; + here->qbe_x2 = 0.5*model->BJTtype*d_qbe.d2_p2; + here->qbe_y2 = 0.5*model->BJTtype*d_qbe.d2_q2; + here->qbe_xy = model->BJTtype*d_qbe.d2_pq; + here->qbe_x3 = d_qbe.d3_p3/6.; + here->qbe_y3 = d_qbe.d3_q3/6.; + here->qbe_x2y = 0.5*d_qbe.d3_p2q; + here->qbe_xy2 = 0.5*d_qbe.d3_pq2; - here->capbc1 = lcapbc1; - here->capbc2 = lcapbc2; - here->capbc3 = lcapbc3; + here->capbc1 = lcapbc1; + here->capbc2 = lcapbc2; + here->capbc3 = lcapbc3; - here->capbx1 = lcapbx1; - here->capbx2 = lcapbx2; - here->capbx3 = lcapbx3; + here->capbx1 = lcapbx1; + here->capbx2 = lcapbx2; + here->capbx3 = lcapbx3; - here->capsc1 = lcapsc1; - here->capsc2 = lcapsc2; - here->capsc3 = lcapsc3; - } + here->capsc1 = lcapsc1; + here->capsc2 = lcapsc2; + here->capsc3 = lcapsc3; + } } return(OK); } diff --git a/src/spicelib/devices/bjt/bjtload.c b/src/spicelib/devices/bjt/bjtload.c index 4fca609fe..6e2d832ab 100644 --- a/src/spicelib/devices/bjt/bjtload.c +++ b/src/spicelib/devices/bjt/bjtload.c @@ -20,7 +20,7 @@ Modified: 2000 AlansFixes int BJTload(GENmodel *inModel, CKTcircuit *ckt) - /* actually load the current resistance value into the + /* actually load the current resistance value into the * sparse matrix previously provided */ { @@ -36,7 +36,7 @@ BJTload(GENmodel *inModel, CKTcircuit *ckt) double capbc; double capbe; double capbx=0; - double capcs=0; + double capsub=0; double cb; double cbc; double cbcn; @@ -50,9 +50,11 @@ BJTload(GENmodel *inModel, CKTcircuit *ckt) double ceqbc; double ceqbe; double ceqbx; - double ceqcs; + double geqsub; + double ceqsub; double cex; double csat; + double csubsat; double ctot; double czbc; double czbcf2; @@ -60,7 +62,7 @@ BJTload(GENmodel *inModel, CKTcircuit *ckt) double czbef2; double czbx; double czbxf2; - double czcs; + double czsub; double delvbc; double delvbe; double denom; @@ -79,7 +81,7 @@ BJTload(GENmodel *inModel, CKTcircuit *ckt) double gbcn; double gbe; double gben; - double gccs; + double gcsub; double gcpr; double gepr; double geq; @@ -110,13 +112,14 @@ BJTload(GENmodel *inModel, CKTcircuit *ckt) double tr; double vbc; double vbe; - double vbx=0; + double vbx=0.0; double vce; - double vcs=0; + double vsub=0.0; double vt; double vtc; double vte; double vtn; + double vts; #ifndef PREDICTOR double xfact; #endif @@ -126,7 +129,10 @@ BJTload(GENmodel *inModel, CKTcircuit *ckt) double xme; double xms; double xtf; - int icheck; + double evsub; + double gdsub; + double cdsub; + int icheck=1; int ichk1; int error; int SenCond=0; @@ -155,8 +161,8 @@ BJTload(GENmodel *inModel, CKTcircuit *ckt) } - gccs=0; - ceqcs=0; + gcsub=0; + ceqsub=0; geqbx=0; ceqbx=0; geqcb=0; @@ -164,6 +170,7 @@ BJTload(GENmodel *inModel, CKTcircuit *ckt) * dc model paramters */ csat=here->BJTtSatCur*here->BJTarea; + csubsat=here->BJTtSubSatCur*here->BJTarea; rbpr=here->BJTtminBaseResist/here->BJTarea; rbpi=here->BJTtbaseResist/here->BJTarea-rbpr; gcpr=here->BJTtcollectorConduct*here->BJTarea; @@ -172,7 +179,10 @@ BJTload(GENmodel *inModel, CKTcircuit *ckt) c2=here->BJTtBEleakCur*here->BJTarea; vte=here->BJTtleakBEemissionCoeff*vt; oikr=here->BJTtinvRollOffR/here->BJTarea; - c4=here->BJTtBCleakCur*here->BJTareab; + if (model->BJTsubs == VERTICAL) + c4=here->BJTtBCleakCur * here->BJTareab; + else + c4=here->BJTtBCleakCur * here->BJTareac; vtc=here->BJTtleakBCemissionCoeff*vt; td=model->BJTexcessPhaseFactor; xjrb=here->BJTtbaseCurrentHalfResist*here->BJTarea; @@ -189,9 +199,9 @@ BJTload(GENmodel *inModel, CKTcircuit *ckt) vbx=model->BJTtype*( *(ckt->CKTrhsOp+here->BJTbaseNode)- *(ckt->CKTrhsOp+here->BJTcolPrimeNode)); - vcs=model->BJTtype*( + vsub=model->BJTtype*model->BJTsubs*( *(ckt->CKTrhsOp+here->BJTsubstNode)- - *(ckt->CKTrhsOp+here->BJTcolPrimeNode)); + *(ckt->CKTrhsOp+here->BJTsubstConNode)); } else{ vbe = *(ckt->CKTstate0 + here->BJTvbe); @@ -201,17 +211,17 @@ BJTload(GENmodel *inModel, CKTcircuit *ckt) vbx=model->BJTtype*( *(ckt->CKTrhsOld+here->BJTbaseNode)- *(ckt->CKTrhsOld+here->BJTcolPrimeNode)); - vcs=model->BJTtype*( + vsub=model->BJTtype*model->BJTsubs*( *(ckt->CKTrhsOld+here->BJTsubstNode)- - *(ckt->CKTrhsOld+here->BJTcolPrimeNode)); + *(ckt->CKTrhsOld+here->BJTsubstConNode)); } if(ckt->CKTsenInfo->SENmode == ACSEN){ vbx=model->BJTtype*( *(ckt->CKTrhsOp+here->BJTbaseNode)- *(ckt->CKTrhsOp+here->BJTcolPrimeNode)); - vcs=model->BJTtype*( + vsub=model->BJTtype*model->BJTsubs*( *(ckt->CKTrhsOp+here->BJTsubstNode)- - *(ckt->CKTrhsOp+here->BJTcolPrimeNode)); + *(ckt->CKTrhsOp+here->BJTsubstConNode)); } } goto next1; @@ -227,21 +237,21 @@ BJTload(GENmodel *inModel, CKTcircuit *ckt) vbx=model->BJTtype*( *(ckt->CKTrhsOld+here->BJTbaseNode)- *(ckt->CKTrhsOld+here->BJTcolPrimeNode)); - vcs=model->BJTtype*( + vsub=model->BJTtype*model->BJTsubs*( *(ckt->CKTrhsOld+here->BJTsubstNode)- - *(ckt->CKTrhsOld+here->BJTcolPrimeNode)); + *(ckt->CKTrhsOld+here->BJTsubstConNode)); } else if(ckt->CKTmode & MODEINITTRAN) { vbe = *(ckt->CKTstate1 + here->BJTvbe); vbc = *(ckt->CKTstate1 + here->BJTvbc); vbx=model->BJTtype*( *(ckt->CKTrhsOld+here->BJTbaseNode)- *(ckt->CKTrhsOld+here->BJTcolPrimeNode)); - vcs=model->BJTtype*( + vsub=model->BJTtype*model->BJTsubs*( *(ckt->CKTrhsOld+here->BJTsubstNode)- - *(ckt->CKTrhsOld+here->BJTcolPrimeNode)); + *(ckt->CKTrhsOld+here->BJTsubstConNode)); if( (ckt->CKTmode & MODETRAN) && (ckt->CKTmode & MODEUIC) ) { vbx=model->BJTtype*(here->BJTicVBE-here->BJTicVCE); - vcs=0; + vsub=0; } } else if((ckt->CKTmode & MODEINITJCT) && (ckt->CKTmode & MODETRANOP) && (ckt->CKTmode & MODEUIC)){ @@ -249,18 +259,18 @@ BJTload(GENmodel *inModel, CKTcircuit *ckt) vce=model->BJTtype*here->BJTicVCE; vbc=vbe-vce; vbx=vbc; - vcs=0; + vsub=0; } else if((ckt->CKTmode & MODEINITJCT) && (here->BJToff==0)) { vbe=here->BJTtVcrit; vbc=0; - /* ERROR: need to initialize VCS, VBX here */ - vcs=vbx=0; + /* ERROR: need to initialize VSUB, VBX here */ + vsub=vbx=0; } else if((ckt->CKTmode & MODEINITJCT) || ( (ckt->CKTmode & MODEINITFIX) && (here->BJToff!=0))) { vbe=0; vbc=0; - /* ERROR: need to initialize VCS, VBX here */ - vcs=vbx=0; + /* ERROR: need to initialize VSUB, VBX here */ + vsub=vbx=0; } else { #ifndef PREDICTOR if(ckt->CKTmode & MODEINITPRED) { @@ -287,6 +297,10 @@ BJTload(GENmodel *inModel, CKTcircuit *ckt) *(ckt->CKTstate1 + here->BJTgo); *(ckt->CKTstate0 + here->BJTgx) = *(ckt->CKTstate1 + here->BJTgx); + *(ckt->CKTstate0 + here->BJTvsub) = + *(ckt->CKTstate1 + here->BJTvsub); + vsub = (1+xfact)**(ckt->CKTstate1 + here->BJTvsub)- + xfact* *(ckt->CKTstate2 + here->BJTvsub); } else { #endif /* PREDICTOR */ /* @@ -298,6 +312,9 @@ BJTload(GENmodel *inModel, CKTcircuit *ckt) vbc=model->BJTtype*( *(ckt->CKTrhsOld+here->BJTbasePrimeNode)- *(ckt->CKTrhsOld+here->BJTcolPrimeNode)); + vsub=model->BJTtype*model->BJTsubs*( + *(ckt->CKTrhsOld+here->BJTsubstNode)- + *(ckt->CKTrhsOld+here->BJTsubstConNode)); #ifndef PREDICTOR } #endif /* PREDICTOR */ @@ -306,9 +323,9 @@ BJTload(GENmodel *inModel, CKTcircuit *ckt) vbx=model->BJTtype*( *(ckt->CKTrhsOld+here->BJTbaseNode)- *(ckt->CKTrhsOld+here->BJTcolPrimeNode)); - vcs=model->BJTtype*( + vsub=model->BJTtype*model->BJTsubs*( *(ckt->CKTrhsOld+here->BJTsubstNode)- - *(ckt->CKTrhsOld+here->BJTcolPrimeNode)); + *(ckt->CKTrhsOld+here->BJTsubstConNode)); cchat= *(ckt->CKTstate0 + here->BJTcc)+(*(ckt->CKTstate0 + here->BJTgm)+ *(ckt->CKTstate0 + here->BJTgo))*delvbe- (*(ckt->CKTstate0 + here->BJTgo)+*(ckt->CKTstate0 + @@ -353,8 +370,11 @@ BJTload(GENmodel *inModel, CKTcircuit *ckt) go = *(ckt->CKTstate0 + here->BJTgo); gx = *(ckt->CKTstate0 + here->BJTgx); geqcb = *(ckt->CKTstate0 + here->BJTgeqcb); - gccs = *(ckt->CKTstate0 + here->BJTgccs); + gcsub = *(ckt->CKTstate0 + here->BJTgcsub); geqbx = *(ckt->CKTstate0 + here->BJTgeqbx); + vsub = *(ckt->CKTstate0 + here->BJTvsub); + gdsub = *(ckt->CKTstate0 + here->BJTgdsub); + cdsub = *(ckt->CKTstate0 + here->BJTcdsub); goto load; } #endif /*NOBYPASS*/ @@ -366,12 +386,14 @@ BJTload(GENmodel *inModel, CKTcircuit *ckt) here->BJTtVcrit,&icheck); vbc = DEVpnjlim(vbc,*(ckt->CKTstate0 + here->BJTvbc),vt, here->BJTtVcrit,&ichk1); + vsub = DEVpnjlim(vsub,*(ckt->CKTstate0 + here->BJTvsub),vt, + here->BJTtSubVcrit,&ichk1); if (ichk1 == 1) icheck=1; } /* * determine dc current and derivitives */ -next1: vtn=vt*model->BJTemissionCoeffF; +next1: vtn=vt*here->BJTtemissionCoeffF; if(vbe >= -3*vtn){ evbe=exp(vbe/vtn); @@ -401,9 +423,9 @@ next1: vtn=vt*model->BJTemissionCoeffF; gben+=ckt->CKTgmin; cben+=ckt->CKTgmin*vbe; - vtn=vt*model->BJTemissionCoeffR; + vtn=vt*here->BJTtemissionCoeffR; - if(vbc >= -3*vtn) { + if(vbc >= -3*vtn) { evbc=exp(vbc/vtn); cbc=csat*(evbc-1); gbc=csat*evbc/vtn; @@ -431,6 +453,18 @@ next1: vtn=vt*model->BJTemissionCoeffF; gbcn+=ckt->CKTgmin; cbcn+=ckt->CKTgmin*vbc; + vts=vt*here->BJTtemissionCoeffS; + + if(vsub <= -3*vts) { + arg=3*vts/(vsub*CONSTe); + arg = arg * arg * arg; + gdsub = csubsat*3*arg/vsub+ckt->CKTgmin; + cdsub = -csubsat*(1+arg)+ckt->CKTgmin*vsub; + } else { + evsub = exp(MIN(MAX_EXP_ARG,vsub/vts)); + gdsub = csubsat*evsub/vts + ckt->CKTgmin; + cdsub = csubsat*(evsub-1) + ckt->CKTgmin*vsub; + } /* * determine base charge terms */ @@ -503,15 +537,21 @@ next1: vtn=vt*model->BJTemissionCoeffF; pe=here->BJTtBEpot; xme=here->BJTtjunctionExpBE; cdis=model->BJTbaseFractionBCcap; - ctot=here->BJTtBCcap*here->BJTarea; + if (model->BJTsubs == VERTICAL) + ctot=here->BJTtBCcap*here->BJTareab; + else + ctot=here->BJTtBCcap*here->BJTareac; czbc=ctot*cdis; czbx=ctot-czbc; pc=here->BJTtBCpot; xmc=here->BJTtjunctionExpBC; fcpe=here->BJTtDepCap; - czcs=model->BJTcapCS*here->BJTareac; - ps=model->BJTpotentialSubstrate; - xms=model->BJTexponentialSubstrate; + if (model->BJTsubs == VERTICAL) + czsub=here->BJTtSubcap*here->BJTareac; + else + czsub=here->BJTtSubcap*here->BJTareab; + ps=here->BJTtSubpot; + xms=here->BJTtjunctionExpSub; xtf=model->BJTtransitTimeBiasCoeffF; ovtf=model->BJTtransitTimeVBCFactor; xjtf=here->BJTttransitTimeHighCurrentF*here->BJTarea; @@ -579,21 +619,21 @@ next1: vtn=vt*model->BJTemissionCoeffF; (f3*(vbx-fcpc)+(xmc/(pc+pc))*(vbx*vbx-fcpc*fcpc)); capbx=czbxf2*(f3+xmc*vbx/pc); } - if(vcs < 0){ - arg=1-vcs/ps; + if(vsub < 0){ + arg=1-vsub/ps; sarg=exp(-xms*log(arg)); - *(ckt->CKTstate0 + here->BJTqcs) = ps*czcs*(1-arg*sarg)/ + *(ckt->CKTstate0 + here->BJTqsub) = ps*czsub*(1-arg*sarg)/ (1-xms); - capcs=czcs*sarg; + capsub=czsub*sarg; } else { - *(ckt->CKTstate0 + here->BJTqcs) = vcs*czcs*(1+xms*vcs/ + *(ckt->CKTstate0 + here->BJTqsub) = vsub*czsub*(1+xms*vsub/ (2*ps)); - capcs=czcs*(1+xms*vcs/ps); - } - here->BJTcapbe = capbe; - here->BJTcapbc = capbc; - here->BJTcapcs = capcs; - here->BJTcapbx = capbx; + capsub=czsub*(1+xms*vsub/ps); + } + here->BJTcapbe = capbe; + here->BJTcapbc = capbc; + here->BJTcapsub = capsub; + here->BJTcapbx = capbx; /* * store small-signal parameters @@ -603,7 +643,7 @@ next1: vtn=vt*model->BJTemissionCoeffF; if(ckt->CKTmode & MODEINITSMSIG) { *(ckt->CKTstate0 + here->BJTcqbe) = capbe; *(ckt->CKTstate0 + here->BJTcqbc) = capbc; - *(ckt->CKTstate0 + here->BJTcqcs) = capcs; + *(ckt->CKTstate0 + here->BJTcqsub) = capsub; *(ckt->CKTstate0 + here->BJTcqbx) = capbx; *(ckt->CKTstate0 + here->BJTcexbc) = geqcb; if(SenCond){ @@ -614,17 +654,17 @@ next1: vtn=vt*model->BJTemissionCoeffF; *(ckt->CKTstate0 + here->BJTgm) = gm; *(ckt->CKTstate0 + here->BJTgo) = go; *(ckt->CKTstate0 + here->BJTgx) = gx; - *(ckt->CKTstate0 + here->BJTgccs) = gccs; + *(ckt->CKTstate0 + here->BJTgcsub) = gcsub; *(ckt->CKTstate0 + here->BJTgeqbx) = geqbx; } #ifdef SENSDEBUG printf("storing small signal parameters for op\n"); printf("capbe = %.7e ,capbc = %.7e\n",capbe,capbc); - printf("capcs = %.7e ,capbx = %.7e\n",capcs,capbx); + printf("capsub = %.7e ,capbx = %.7e\n",capsub,capbx); printf("geqcb = %.7e ,gpi = %.7e\n",geqcb,gpi); printf("gmu = %.7e ,gm = %.7e\n",gmu,gm); printf("go = %.7e ,gx = %.7e\n",go,gx); - printf("gccs = %.7e ,geqbx = %.7e\n",gccs,geqbx); + printf("gcsub = %.7e ,geqbx = %.7e\n",gcsub,geqbx); printf("cc = %.7e ,cb = %.7e\n",cc,cb); #endif /* SENSDEBUG */ continue; /* go to 1000 */ @@ -646,8 +686,8 @@ next1: vtn=vt*model->BJTemissionCoeffF; *(ckt->CKTstate0 + here->BJTqbc) ; *(ckt->CKTstate1 + here->BJTqbx) = *(ckt->CKTstate0 + here->BJTqbx) ; - *(ckt->CKTstate1 + here->BJTqcs) = - *(ckt->CKTstate0 + here->BJTqcs) ; + *(ckt->CKTstate1 + here->BJTqsub) = + *(ckt->CKTstate0 + here->BJTqsub) ; } error = NIintegrate(ckt,&geq,&ceq,capbe,here->BJTqbe); if(error) return(error); @@ -676,7 +716,7 @@ next1: vtn=vt*model->BJTemissionCoeffF; if ( (!(ckt->CKTmode & MODEINITFIX))||(!(here->BJToff))) { if (icheck == 1) { ckt->CKTnoncon++; - ckt->CKTtroubleElt = (GENinstance *) here; + ckt->CKTtroubleElt = (GENinstance *) here; } } @@ -684,15 +724,15 @@ next1: vtn=vt*model->BJTemissionCoeffF; * charge storage for c-s and b-x junctions */ if(ckt->CKTmode & (MODETRAN | MODEAC)) { - error = NIintegrate(ckt,&gccs,&ceq,capcs,here->BJTqcs); + error = NIintegrate(ckt,&gcsub,&ceq,capsub,here->BJTqsub); if(error) return(error); error = NIintegrate(ckt,&geqbx,&ceq,capbx,here->BJTqbx); if(error) return(error); if(ckt->CKTmode & MODEINITTRAN) { *(ckt->CKTstate1 + here->BJTcqbx) = *(ckt->CKTstate0 + here->BJTcqbx); - *(ckt->CKTstate1 + here->BJTcqcs) = - *(ckt->CKTstate0 + here->BJTcqcs); + *(ckt->CKTstate1 + here->BJTcqsub) = + *(ckt->CKTstate0 + here->BJTcqsub); } } next2: @@ -706,8 +746,11 @@ next2: *(ckt->CKTstate0 + here->BJTgo) = go; *(ckt->CKTstate0 + here->BJTgx) = gx; *(ckt->CKTstate0 + here->BJTgeqcb) = geqcb; - *(ckt->CKTstate0 + here->BJTgccs) = gccs; + *(ckt->CKTstate0 + here->BJTgcsub) = gcsub; *(ckt->CKTstate0 + here->BJTgeqbx) = geqbx; + *(ckt->CKTstate0 + here->BJTvsub) = vsub; + *(ckt->CKTstate0 + here->BJTgdsub) = gdsub; + *(ckt->CKTstate0 + here->BJTcdsub) = cdsub; /* Do not load the Jacobian and the rhs if perturbation is being carried out */ @@ -717,10 +760,11 @@ next2: load: #endif /* - * load current excitation vector - */ - ceqcs=model->BJTtype * (*(ckt->CKTstate0 + here->BJTcqcs) - - vcs * gccs); + * load current excitation vector + */ + geqsub = gcsub + gdsub; + ceqsub=model->BJTtype * model->BJTsubs * + (*(ckt->CKTstate0 + here->BJTcqsub) + cdsub - vsub * geqsub); ceqbx=model->BJTtype * (*(ckt->CKTstate0 + here->BJTcqbx) - vbx * geqbx); ceqbe=model->BJTtype * (cc + cb - vbe * (gm + go + gpi) + vbc * @@ -729,18 +773,20 @@ load: *(ckt->CKTrhs + here->BJTbaseNode) += m * (-ceqbx); *(ckt->CKTrhs + here->BJTcolPrimeNode) += - m * (ceqcs+ceqbx+ceqbc); + m * (ceqbx+ceqbc); + *(ckt->CKTrhs + here->BJTsubstConNode) += m * ceqsub; *(ckt->CKTrhs + here->BJTbasePrimeNode) += m * (-ceqbe-ceqbc); *(ckt->CKTrhs + here->BJTemitPrimeNode) += m * (ceqbe); - *(ckt->CKTrhs + here->BJTsubstNode) += m * (-ceqcs); + *(ckt->CKTrhs + here->BJTsubstNode) += m * (-ceqsub); /* * load y matrix */ *(here->BJTcolColPtr) += m * (gcpr); *(here->BJTbaseBasePtr) += m * (gx+geqbx); *(here->BJTemitEmitPtr) += m * (gepr); - *(here->BJTcolPrimeColPrimePtr) += m * (gmu+go+gcpr+gccs+geqbx); + *(here->BJTcolPrimeColPrimePtr) += m * (gmu+go+gcpr+geqbx); + *(here->BJTsubstConSubstConPtr) += m * (geqsub); *(here->BJTbasePrimeBasePrimePtr) += m * (gx +gpi+gmu+geqcb); *(here->BJTemitPrimeEmitPrimePtr) += m * (gpi+gepr+gm+go); *(here->BJTcolColPrimePtr) += m * (-gcpr); @@ -755,9 +801,9 @@ load: *(here->BJTemitPrimeEmitPtr) += m * (-gepr); *(here->BJTemitPrimeColPrimePtr) += m * (-go+geqcb); *(here->BJTemitPrimeBasePrimePtr) += m * (-gpi-gm-geqcb); - *(here->BJTsubstSubstPtr) += m * (gccs); - *(here->BJTcolPrimeSubstPtr) += m * (-gccs); - *(here->BJTsubstColPrimePtr) += m * (-gccs); + *(here->BJTsubstSubstPtr) += m * (geqsub); + *(here->BJTsubstConSubstPtr) += m * (-geqsub); + *(here->BJTsubstSubstConPtr) += m * (-geqsub); *(here->BJTbaseColPrimePtr) += m * (-geqbx); *(here->BJTcolPrimeBasePtr) += m * (-geqbx); } diff --git a/src/spicelib/devices/bjt/bjtmask.c b/src/spicelib/devices/bjt/bjtmask.c index 376759c73..440e0edfd 100644 --- a/src/spicelib/devices/bjt/bjtmask.c +++ b/src/spicelib/devices/bjt/bjtmask.c @@ -24,6 +24,18 @@ BJTmAsk(CKTcircuit *ckt, GENmodel *instPtr, int which, IFvalue *value) NG_IGNORE(ckt); switch(which) { + case BJT_MOD_TYPE: + if (here->BJTtype == NPN) + value->sValue = "npn"; + else + value->sValue = "pnp"; + return(OK); + case BJT_MOD_SUBS: + if (here->BJTsubs == LATERAL) + value->sValue = "Lateral"; + else + value->sValue = "Vertical"; + return(OK); case BJT_MOD_TNOM: value->rValue = here->BJTtnom-CONSTCtoK; return(OK); @@ -127,7 +139,7 @@ BJTmAsk(CKTcircuit *ckt, GENmodel *instPtr, int which, IFvalue *value) value->rValue = here->BJTtransitTimeR; return(OK); case BJT_MOD_CJS: - value->rValue = here->BJTcapCS; + value->rValue = here->BJTcapSub; return(OK); case BJT_MOD_VJS: value->rValue = here->BJTpotentialSubstrate; @@ -147,6 +159,18 @@ BJTmAsk(CKTcircuit *ckt, GENmodel *instPtr, int which, IFvalue *value) case BJT_MOD_FC: value->rValue = here->BJTdepletionCapCoeff; return(OK); + case BJT_MOD_KF: + if (here->BJTfNcoefGiven) + value->rValue = here->BJTfNcoef; + else + value->rValue = 0.0; + return(OK); + case BJT_MOD_AF: + if (here->BJTfNexpGiven) + value->rValue = here->BJTfNexp; + else + value->rValue = 0.0; + return(OK); case BJT_MOD_INVEARLYF: value->rValue = here->BJTinvEarlyVoltF; return(OK); @@ -171,6 +195,12 @@ BJTmAsk(CKTcircuit *ckt, GENmodel *instPtr, int which, IFvalue *value) case BJT_MOD_EXCESSPHASEFACTOR: value->rValue = here->BJTexcessPhaseFactor; return(OK); + case BJT_MOD_ISS: + value->rValue = here->BJTsubSatCur; + return(OK); + case BJT_MOD_NS: + value->rValue = here->BJTemissionCoeffS; + return(OK); case BJT_MOD_TLEV: value->iValue = here->BJTtlev; return(OK); @@ -285,23 +315,47 @@ BJTmAsk(CKTcircuit *ckt, GENmodel *instPtr, int which, IFvalue *value) case BJT_MOD_TVJS: value->rValue = here->BJTtvjs; return(OK); - case BJT_MOD_KF: - if (here->BJTfNcoefGiven) - value->rValue = here->BJTfNcoef; - else - value->rValue = 0.0; + case BJT_MOD_TITF1: + value->rValue = here->BJTtitf1; return(OK); - case BJT_MOD_AF: - if (here->BJTfNexpGiven) - value->rValue = here->BJTfNexp; - else - value->rValue = 0.0; + case BJT_MOD_TITF2: + value->rValue = here->BJTtitf2; return(OK); - case BJT_MOD_TYPE: - if (here->BJTtype == NPN) - value->sValue = "npn"; - else - value->sValue = "pnp"; + case BJT_MOD_TTF1: + value->rValue = here->BJTttf1; + return(OK); + case BJT_MOD_TTF2: + value->rValue = here->BJTttf2; + return(OK); + case BJT_MOD_TTR1: + value->rValue = here->BJTttr1; + return(OK); + case BJT_MOD_TTR2: + value->rValue = here->BJTttr2; + return(OK); + case BJT_MOD_TMJE1: + value->rValue = here->BJTtmje1; + return(OK); + case BJT_MOD_TMJE2: + value->rValue = here->BJTtmje2; + return(OK); + case BJT_MOD_TMJC1: + value->rValue = here->BJTtmjc1; + return(OK); + case BJT_MOD_TMJC2: + value->rValue = here->BJTtmjc2; + return(OK); + case BJT_MOD_TMJS1: + value->rValue = here->BJTtmjs1; + return(OK); + case BJT_MOD_TMJS2: + value->rValue = here->BJTtmjs2; + return(OK); + case BJT_MOD_TNS1: + value->rValue = here->BJTtns1; + return(OK); + case BJT_MOD_TNS2: + value->rValue = here->BJTtns2; return(OK); default: return(E_BADPARM); diff --git a/src/spicelib/devices/bjt/bjtmpar.c b/src/spicelib/devices/bjt/bjtmpar.c index 8b26d9e48..bed92d9ee 100644 --- a/src/spicelib/devices/bjt/bjtmpar.c +++ b/src/spicelib/devices/bjt/bjtmpar.c @@ -34,6 +34,10 @@ BJTmParam(int param, IFvalue *value, GENmodel *inModel) mods->BJTtype = PNP; } break; + case BJT_MOD_SUBS: + mods->BJTsubs = value->iValue; + mods->BJTsubsGiven = TRUE; + break; case BJT_MOD_TNOM: mods->BJTtnom = value->rValue+CONSTCtoK; mods->BJTtnomGiven = TRUE; @@ -171,8 +175,8 @@ BJTmParam(int param, IFvalue *value, GENmodel *inModel) mods->BJTtransitTimeRGiven = TRUE; break; case BJT_MOD_CJS: - mods->BJTcapCS = value->rValue; - mods->BJTcapCSGiven = TRUE; + mods->BJTcapSub = value->rValue; + mods->BJTcapSubGiven = TRUE; break; case BJT_MOD_VJS: mods->BJTpotentialSubstrate = value->rValue; @@ -198,6 +202,22 @@ BJTmParam(int param, IFvalue *value, GENmodel *inModel) mods->BJTdepletionCapCoeff = value->rValue; mods->BJTdepletionCapCoeffGiven = TRUE; break; + case BJT_MOD_KF: + mods->BJTfNcoef = value->rValue; + mods->BJTfNcoefGiven = TRUE; + break; + case BJT_MOD_AF: + mods->BJTfNexp = value->rValue; + mods->BJTfNexpGiven = TRUE; + break; + case BJT_MOD_ISS: + mods->BJTsubSatCur = value->rValue; + mods->BJTsubSatCurGiven = TRUE; + break; + case BJT_MOD_NS: + mods->BJTemissionCoeffS = value->rValue; + mods->BJTemissionCoeffSGiven = TRUE; + break; case BJT_MOD_TLEV: mods->BJTtlev = value->iValue; mods->BJTtlevGiven = TRUE; @@ -350,13 +370,61 @@ BJTmParam(int param, IFvalue *value, GENmodel *inModel) mods->BJTtvjs = value->rValue; mods->BJTtvjsGiven = TRUE; break; - case BJT_MOD_KF: - mods->BJTfNcoef = value->rValue; - mods->BJTfNcoefGiven = TRUE; + case BJT_MOD_TITF1: + mods->BJTtitf1 = value->rValue; + mods->BJTtitf1Given = TRUE; break; - case BJT_MOD_AF: - mods->BJTfNexp = value->rValue; - mods->BJTfNexpGiven = TRUE; + case BJT_MOD_TITF2: + mods->BJTtitf2 = value->rValue; + mods->BJTtitf2Given = TRUE; + break; + case BJT_MOD_TTF1: + mods->BJTttf1 = value->rValue; + mods->BJTttf1Given = TRUE; + break; + case BJT_MOD_TTF2: + mods->BJTttf2 = value->rValue; + mods->BJTttf2Given = TRUE; + break; + case BJT_MOD_TTR1: + mods->BJTttr1 = value->rValue; + mods->BJTttr1Given = TRUE; + break; + case BJT_MOD_TTR2: + mods->BJTttr2 = value->rValue; + mods->BJTttr2Given = TRUE; + break; + case BJT_MOD_TMJE1: + mods->BJTtmje1 = value->rValue; + mods->BJTtmje1Given = TRUE; + break; + case BJT_MOD_TMJE2: + mods->BJTtmje2 = value->rValue; + mods->BJTtmje2Given = TRUE; + break; + case BJT_MOD_TMJC1: + mods->BJTtmjc1 = value->rValue; + mods->BJTtmjc1Given = TRUE; + break; + case BJT_MOD_TMJC2: + mods->BJTtmjc2 = value->rValue; + mods->BJTtmjc2Given = TRUE; + break; + case BJT_MOD_TMJS1: + mods->BJTtmjs1 = value->rValue; + mods->BJTtmjs1Given = TRUE; + break; + case BJT_MOD_TMJS2: + mods->BJTtmjs2 = value->rValue; + mods->BJTtmjs2Given = TRUE; + break; + case BJT_MOD_TNS1: + mods->BJTtns1 = value->rValue; + mods->BJTtns1Given = TRUE; + break; + case BJT_MOD_TNS2: + mods->BJTtns2 = value->rValue; + mods->BJTtns2Given = TRUE; break; default: return(E_BADPARM); diff --git a/src/spicelib/devices/bjt/bjtsacl.c b/src/spicelib/devices/bjt/bjtsacl.c index e9e04eb64..a59a8c31d 100644 --- a/src/spicelib/devices/bjt/bjtsacl.c +++ b/src/spicelib/devices/bjt/bjtsacl.c @@ -165,11 +165,11 @@ BJTsAcLoad(GENmodel *inModel, CKTcircuit *ckt) *(here->BJTsenCpi)= *(ckt->CKTstate0 + here->BJTcqbe); *(here->BJTsenCmu)= *(ckt->CKTstate0 + here->BJTcqbc); *(here->BJTsenCbx)= *(ckt->CKTstate0 + here->BJTcqbx); - *(here->BJTsenCcs)= *(ckt->CKTstate0 + here->BJTcqcs); + *(here->BJTsenCsub)= *(ckt->CKTstate0 + here->BJTcqsub); *(here->BJTsenCmcb)= *(ckt->CKTstate0 + here->BJTcexbc); } - gcpr = model->BJTcollectorConduct * A0; - gepr = model->BJTemitterConduct * A0; + gcpr = here->BJTtcollectorConduct * A0; + gepr = here->BJTtemitterConduct * A0; gpi= *(here->BJTsenGpi); gmu= *(here->BJTsenGmu); gm= *(here->BJTsenGm); @@ -186,7 +186,7 @@ BJTsAcLoad(GENmodel *inModel, CKTcircuit *ckt) xcpi= *(here->BJTsenCpi) * ckt->CKTomega; xcmu= *(here->BJTsenCmu) * ckt->CKTomega; xcbx= *(here->BJTsenCbx) * ckt->CKTomega; - xccs= *(here->BJTsenCcs) * ckt->CKTomega; + xccs= *(here->BJTsenCsub) * ckt->CKTomega; xcmcb= *(here->BJTsenCmcb) * ckt->CKTomega; @@ -282,7 +282,7 @@ BJTsAcLoad(GENmodel *inModel, CKTcircuit *ckt) *(here->BJTsenCpi + 1)= *(ckt->CKTstate0 + here->BJTcqbe); *(here->BJTsenCmu + 1)= *(ckt->CKTstate0 + here->BJTcqbc); *(here->BJTsenCbx + 1)= *(ckt->CKTstate0 + here->BJTcqbx); - *(here->BJTsenCcs + 1)= *(ckt->CKTstate0 + here->BJTcqcs); + *(here->BJTsenCsub + 1)= *(ckt->CKTstate0 + here->BJTcqsub); *(here->BJTsenCmcb + 1)= *(ckt->CKTstate0 + here->BJTcexbc); } @@ -322,7 +322,7 @@ pertvbx: /* Perturbation of vbx */ *(here->BJTsenCpi + 2)= *(ckt->CKTstate0 + here->BJTcqbe); *(here->BJTsenCmu + 2)= *(ckt->CKTstate0 + here->BJTcqbc); *(here->BJTsenCbx + 2)= *(ckt->CKTstate0 + here->BJTcqbx); - *(here->BJTsenCcs + 2)= *(ckt->CKTstate0 + here->BJTcqcs); + *(here->BJTsenCsub + 2)= *(ckt->CKTstate0 + here->BJTcqsub); *(here->BJTsenCmcb + 2)= *(ckt->CKTstate0 + here->BJTcexbc); } @@ -362,7 +362,7 @@ pertvbe: /* Perturbation of vbe */ *(here->BJTsenCpi + 3)= *(ckt->CKTstate0 + here->BJTcqbe); *(here->BJTsenCmu + 3)= *(ckt->CKTstate0 + here->BJTcqbc); *(here->BJTsenCbx + 3)= *(ckt->CKTstate0 + here->BJTcqbx); - *(here->BJTsenCcs + 3)= *(ckt->CKTstate0 + here->BJTcqcs); + *(here->BJTsenCsub + 3)= *(ckt->CKTstate0 + here->BJTcqsub); *(here->BJTsenCmcb + 3)= *(ckt->CKTstate0 + here->BJTcexbc); } @@ -404,7 +404,7 @@ pertvbc: /* Perturbation of vbc */ *(here->BJTsenCpi + 4)= *(ckt->CKTstate0 + here->BJTcqbe); *(here->BJTsenCmu + 4)= *(ckt->CKTstate0 + here->BJTcqbc); *(here->BJTsenCbx + 4)= *(ckt->CKTstate0 + here->BJTcqbx); - *(here->BJTsenCcs + 4)= *(ckt->CKTstate0 + here->BJTcqcs); + *(here->BJTsenCsub + 4)= *(ckt->CKTstate0 + here->BJTcqsub); *(here->BJTsenCmcb + 4)= *(ckt->CKTstate0 + here->BJTcexbc); } @@ -436,7 +436,7 @@ pertvcs: /* Perturbation of vcs */ */ if ((error = BJTload((GENmodel*)model,ckt)) != 0) return(error); - *(here->BJTsenCcs + 5)= *(ckt->CKTstate0 + here->BJTcqcs); + *(here->BJTsenCsub + 5)= *(ckt->CKTstate0 + here->BJTcqsub); } @@ -444,7 +444,7 @@ pertvcs: /* Perturbation of vcs */ flag = 4; *(ckt->CKTrhsOp + here->BJTsubstNode) -= DELA; - xccs= *(here->BJTsenCcs + 5) * ckt->CKTomega; + xccs= *(here->BJTsenCsub + 5) * ckt->CKTomega; ccs=( -xccs * ivcs) ; iccs= xccs * vcs ; @@ -465,8 +465,8 @@ pertvcs: /* Perturbation of vcs */ goto next2; load: - gcpr=model->BJTcollectorConduct * here->BJTarea; - gepr=model->BJTemitterConduct * here->BJTarea; + gcpr=here->BJTtcollectorConduct * here->BJTarea; + gepr=here->BJTtemitterConduct * here->BJTarea; gpi= *(here->BJTsenGpi + flag+1); gmu= *(here->BJTsenGmu + flag+1); gm= *(here->BJTsenGm + flag+1); @@ -483,7 +483,7 @@ load: xcpi= *(here->BJTsenCpi + flag+1) * ckt->CKTomega; xcmu= *(here->BJTsenCmu + flag+1) * ckt->CKTomega; xcbx= *(here->BJTsenCbx + flag+1) * ckt->CKTomega; - xccs= *(here->BJTsenCcs + flag+1) * ckt->CKTomega; + xccs= *(here->BJTsenCsub + flag+1) * ckt->CKTomega; xcmcb= *(here->BJTsenCmcb + flag+1) * ckt->CKTomega; diff --git a/src/spicelib/devices/bjt/bjtsetup.c b/src/spicelib/devices/bjt/bjtsetup.c index a6dc825fd..35b3d42fd 100644 --- a/src/spicelib/devices/bjt/bjtsetup.c +++ b/src/spicelib/devices/bjt/bjtsetup.c @@ -37,6 +37,13 @@ BJTsetup(SMPmatrix *matrix, GENmodel *inModel, CKTcircuit *ckt, int *states) if(model->BJTtype != NPN && model->BJTtype != PNP) { model->BJTtype = NPN; } + if(!model->BJTsubsGiven || + (model->BJTsubs != VERTICAL && model->BJTsubs != LATERAL)) { + if (model->BJTtype == NPN) + model->BJTsubs = VERTICAL; /* Vertical for NPN */ + else + model->BJTsubs = LATERAL; /* Lateral for PNP */ + } if(!model->BJTsatCurGiven) { model->BJTsatCur = 1e-16; } @@ -103,8 +110,8 @@ BJTsetup(SMPmatrix *matrix, GENmodel *inModel, CKTcircuit *ckt, int *states) if(!model->BJTtransitTimeRGiven) { model->BJTtransitTimeR = 0; } - if(!model->BJTcapCSGiven) { - model->BJTcapCS = 0; + if(!model->BJTcapSubGiven) { + model->BJTcapSub = 0; } if(!model->BJTpotentialSubstrateGiven) { model->BJTpotentialSubstrate = .75; @@ -121,7 +128,18 @@ BJTsetup(SMPmatrix *matrix, GENmodel *inModel, CKTcircuit *ckt, int *states) if(!model->BJTtempExpISGiven) { model->BJTtempExpIS = 3; } - + if(!model->BJTfNcoefGiven) { + model->BJTfNcoef = 0; + } + if(!model->BJTfNexpGiven) { + model->BJTfNexp = 1; + } + if(!model->BJTsubSatCurGiven) { + model->BJTsubSatCur = 0.0; + } + if(!model->BJTemissionCoeffSGiven) { + model->BJTemissionCoeffS = 1.0; + } if(!model->BJTtlevGiven) { model->BJTtlev = 0; } @@ -236,12 +254,47 @@ BJTsetup(SMPmatrix *matrix, GENmodel *inModel, CKTcircuit *ckt, int *states) if(!model->BJTtvjsGiven) { model->BJTtvjs = 0.0; } - - if(!model->BJTfNcoefGiven) { - model->BJTfNcoef = 0; + if(!model->BJTtitf1Given) { + model->BJTtitf1 = 0.0; } - if(!model->BJTfNexpGiven) { - model->BJTfNexp = 1; + if(!model->BJTtitf2Given) { + model->BJTtitf2 = 0.0; + } + if(!model->BJTttf1Given) { + model->BJTttf1 = 0.0; + } + if(!model->BJTttf2Given) { + model->BJTttf2 = 0.0; + } + if(!model->BJTttr1Given) { + model->BJTttr1 = 0.0; + } + if(!model->BJTttr2Given) { + model->BJTttr2 = 0.0; + } + if(!model->BJTtmje1Given) { + model->BJTtmje1 = 0.0; + } + if(!model->BJTtmje2Given) { + model->BJTtmje2 = 0.0; + } + if(!model->BJTtmjc1Given) { + model->BJTtmjc1 = 0.0; + } + if(!model->BJTtmjc2Given) { + model->BJTtmjc2 = 0.0; + } + if(!model->BJTtmjs1Given) { + model->BJTtmjs1 = 0.0; + } + if(!model->BJTtmjs2Given) { + model->BJTtmjs2 = 0.0; + } + if(!model->BJTtns1Given) { + model->BJTtns1 = 0.0; + } + if(!model->BJTtns2Given) { + model->BJTtns2 = 0.0; } /* @@ -367,8 +420,15 @@ if((here->ptr = SMPmakeElt(matrix,here->first,here->second))==(double *)NULL){\ TSTALLOC(BJTbasePrimeBasePrimePtr,BJTbasePrimeNode,BJTbasePrimeNode) TSTALLOC(BJTemitPrimeEmitPrimePtr,BJTemitPrimeNode,BJTemitPrimeNode) TSTALLOC(BJTsubstSubstPtr,BJTsubstNode,BJTsubstNode) - TSTALLOC(BJTcolPrimeSubstPtr,BJTcolPrimeNode,BJTsubstNode) - TSTALLOC(BJTsubstColPrimePtr,BJTsubstNode,BJTcolPrimeNode) + if (model -> BJTsubs == LATERAL) { + here -> BJTsubstConNode = here -> BJTbasePrimeNode; + here -> BJTsubstConSubstConPtr = here -> BJTbasePrimeBasePrimePtr; + } else { + here -> BJTsubstConNode = here -> BJTcolPrimeNode; + here -> BJTsubstConSubstConPtr = here -> BJTcolPrimeColPrimePtr; + } + TSTALLOC(BJTsubstConSubstPtr,BJTsubstConNode,BJTsubstNode) + TSTALLOC(BJTsubstSubstConPtr,BJTsubstNode,BJTsubstConNode) TSTALLOC(BJTbaseColPrimePtr,BJTbaseNode,BJTcolPrimeNode) TSTALLOC(BJTcolPrimeBasePtr,BJTcolPrimeNode,BJTbaseNode) } diff --git a/src/spicelib/devices/bjt/bjtsload.c b/src/spicelib/devices/bjt/bjtsload.c index 53121954c..67fca64ce 100644 --- a/src/spicelib/devices/bjt/bjtsload.c +++ b/src/spicelib/devices/bjt/bjtsload.c @@ -111,7 +111,7 @@ BJTsLoad(GENmodel *inModel, CKTcircuit *ckt) *(SaveState0 + 22) = *(ckt->CKTstate2 + here->BJTcexbc); *(SaveState0 + 23) = here->BJTcapbe; *(SaveState0 + 24) = here->BJTcapbc; - *(SaveState0 + 25) = here->BJTcapcs; + *(SaveState0 + 25) = here->BJTcapsub; *(SaveState0 + 26) = here->BJTcapbx; if(here->BJTsenParmNo == 0) goto next; @@ -130,7 +130,7 @@ BJTsLoad(GENmodel *inModel, CKTcircuit *ckt) qbe0 = *(ckt->CKTstate0 + here->BJTqbe); qbc0 = *(ckt->CKTstate0 + here->BJTqbc); - qcs0 = *(ckt->CKTstate0 + here->BJTqcs); + qcs0 = *(ckt->CKTstate0 + here->BJTqsub); qbx0 = *(ckt->CKTstate0 + here->BJTqbx); /* perturbation of area */ @@ -153,7 +153,7 @@ BJTsLoad(GENmodel *inModel, CKTcircuit *ckt) qbe = *(ckt->CKTstate0 + here->BJTqbe); qbc = *(ckt->CKTstate0 + here->BJTqbc); - qcs = *(ckt->CKTstate0 + here->BJTqcs); + qcs = *(ckt->CKTstate0 + here->BJTqsub); qbx = *(ckt->CKTstate0 + here->BJTqbx); /* compute the gradients of currents */ @@ -182,7 +182,7 @@ BJTsLoad(GENmodel *inModel, CKTcircuit *ckt) *(here->BJTdphibedp) = DqbeDp; *(here->BJTdphibcdp) = DqbcDp; - *(here->BJTdphicsdp) = DqcsDp; + *(here->BJTdphisubdp) = DqcsDp; *(here->BJTdphibxdp) = DqbxDp; #ifdef SENSDEBUG @@ -254,9 +254,9 @@ next: + tag1 * *(ckt->CKTstate1 + here->BJTsensxpbc + 8*(iparmno - 1) + 1); - Osxpcs = tag0 * *(ckt->CKTstate1 + here->BJTsensxpcs + + Osxpcs = tag0 * *(ckt->CKTstate1 + here->BJTsensxpsub + 8*(iparmno - 1)) - + tag1 * *(ckt->CKTstate1 + here->BJTsensxpcs + + + tag1 * *(ckt->CKTstate1 + here->BJTsensxpsub + 8*(iparmno - 1) + 1); Osxpbx = tag0 * *(ckt->CKTstate1 + here->BJTsensxpbx + @@ -318,7 +318,7 @@ restore: *(ckt->CKTstate1 + here->BJTcexbc) = *(SaveState0 + 21); here->BJTcapbe = *(SaveState0 + 23) ; here->BJTcapbc = *(SaveState0 + 24) ; - here->BJTcapcs = *(SaveState0 + 25) ; + here->BJTcapsub = *(SaveState0 + 25) ; here->BJTcapbx = *(SaveState0 + 26) ; } diff --git a/src/spicelib/devices/bjt/bjttemp.c b/src/spicelib/devices/bjt/bjttemp.c index 5c353d305..f17ef4152 100644 --- a/src/spicelib/devices/bjt/bjttemp.c +++ b/src/spicelib/devices/bjt/bjttemp.c @@ -141,8 +141,8 @@ BJTtemp(GENmodel *inModel, CKTcircuit *ckt) here->BJTtemitterConduct = 0; } - here->BJTtminBaseResist = model->BJTminBaseResist*(1+model->BJTtrm1*dt+model->BJTtrm2*dt*dt); here->BJTtbaseResist = model->BJTbaseResist * (1+model->BJTtrb1*dt+model->BJTtrb2*dt*dt); + here->BJTtminBaseResist = model->BJTminBaseResist*(1+model->BJTtrm1*dt+model->BJTtrm2*dt*dt); here->BJTtbaseCurrentHalfResist = model->BJTbaseCurrentHalfResist * (1+model->BJTtirb1*dt+model->BJTtirb2*dt*dt); here->BJTtemissionCoeffF = model->BJTemissionCoeffF * (1+model->BJTtnf1*dt+model->BJTtnf2*dt*dt); here->BJTtemissionCoeffR = model->BJTemissionCoeffR * (1+model->BJTtnr1*dt+model->BJTtnr2*dt*dt); @@ -153,6 +153,8 @@ BJTtemp(GENmodel *inModel, CKTcircuit *ckt) here->BJTttransitTimeR = model->BJTtransitTimeR * (1+model->BJTttr1*dt+model->BJTttr2*dt*dt); here->BJTtjunctionExpBE = model->BJTjunctionExpBE * (1+model->BJTtmje1*dt+model->BJTtmje2*dt*dt); here->BJTtjunctionExpBC = model->BJTjunctionExpBC * (1+model->BJTtmjc1*dt+model->BJTtmjc2*dt*dt); + here->BJTtjunctionExpSub = model->BJTexponentialSubstrate * (1+model->BJTtmjs1*dt+model->BJTtmjs2*dt*dt); + here->BJTtemissionCoeffS = model->BJTemissionCoeffS * (1+model->BJTtns1*dt+model->BJTtns2*dt*dt); vt = here->BJTtemp * CONSTKoverQ; fact2 = here->BJTtemp/REFTEMP; @@ -168,6 +170,7 @@ BJTtemp(GENmodel *inModel, CKTcircuit *ckt) model->BJTtempExpIS*ratlog; factor = exp(factlog); here->BJTtSatCur = model->BJTsatCur * factor; + here->BJTtSubSatCur = model->BJTsubSatCur * factor; if (model->BJTtlev == 0) { bfactor = exp(ratlog*model->BJTbetaExp); @@ -192,42 +195,57 @@ BJTtemp(GENmodel *inModel, CKTcircuit *ckt) pbo = (model->BJTpotentialBE-pbfact)/fact1; gmaold = (model->BJTpotentialBE-pbo)/pbo; here->BJTtBEcap = model->BJTdepletionCapBE/ - (1+model->BJTjunctionExpBE* + (1+here->BJTtjunctionExpBE* (4e-4*(model->BJTtnom-REFTEMP)-gmaold)); here->BJTtBEpot = fact2 * pbo+pbfact; gmanew = (here->BJTtBEpot-pbo)/pbo; - here->BJTtBEcap *= 1+model->BJTjunctionExpBE* + here->BJTtBEcap *= 1+here->BJTtjunctionExpBE* (4e-4*(here->BJTtemp-REFTEMP)-gmanew); } else if (model->BJTtlevc == 1) { here->BJTtBEcap = model->BJTdepletionCapBE* (1+model->BJTcte*dt); } - if (model->BJTtlevc == 0) { pbo = (model->BJTpotentialBC-pbfact)/fact1; gmaold = (model->BJTpotentialBC-pbo)/pbo; here->BJTtBCcap = model->BJTdepletionCapBC/ - (1+model->BJTjunctionExpBC* + (1+here->BJTtjunctionExpBC* (4e-4*(model->BJTtnom-REFTEMP)-gmaold)); here->BJTtBCpot = fact2 * pbo+pbfact; gmanew = (here->BJTtBCpot-pbo)/pbo; - here->BJTtBCcap *= 1+model->BJTjunctionExpBC* + here->BJTtBCcap *= 1+here->BJTtjunctionExpBC* (4e-4*(here->BJTtemp-REFTEMP)-gmanew); } else if (model->BJTtlevc == 1) { here->BJTtBCcap = model->BJTdepletionCapBC* (1+model->BJTctc*dt); } + if (model->BJTtlevc == 0) { + pbo = (model->BJTpotentialSubstrate-pbfact)/fact1; + gmaold = (model->BJTpotentialSubstrate-pbo)/pbo; + here->BJTtSubcap = model->BJTcapSub/ + (1+here->BJTtjunctionExpSub* + (4e-4*(model->BJTtnom-REFTEMP)-gmaold)); + here->BJTtSubpot = fact2 * pbo+pbfact; + gmanew = (here->BJTtSubpot-pbo)/pbo; + here->BJTtSubcap *= 1+here->BJTtjunctionExpSub* + (4e-4*(here->BJTtemp-REFTEMP)-gmanew); + } else if (model->BJTtlevc == 1) { + here->BJTtSubcap = model->BJTcapSub* + (1+model->BJTcts*dt); + } here->BJTtDepCap = model->BJTdepletionCapCoeff * here->BJTtBEpot; here->BJTtf1 = here->BJTtBEpot * (1 - exp((1 - - model->BJTjunctionExpBE) * xfc)) / - (1 - model->BJTjunctionExpBE); + here->BJTtjunctionExpBE) * xfc)) / + (1 - here->BJTtjunctionExpBE); here->BJTtf4 = model->BJTdepletionCapCoeff * here->BJTtBCpot; here->BJTtf5 = here->BJTtBCpot * (1 - exp((1 - - model->BJTjunctionExpBC) * xfc)) / - (1 - model->BJTjunctionExpBC); + here->BJTtjunctionExpBC) * xfc)) / + (1 - here->BJTtjunctionExpBC); here->BJTtVcrit = vt * log(vt / (CONSTroot2*here->BJTtSatCur*here->BJTarea)); + here->BJTtSubVcrit = vt * + log(vt / (CONSTroot2*here->BJTtSubSatCur*here->BJTarea)); } } diff --git a/src/spicelib/devices/bjt/bjttrunc.c b/src/spicelib/devices/bjt/bjttrunc.c index 687492d9a..7547ff6bf 100644 --- a/src/spicelib/devices/bjt/bjttrunc.c +++ b/src/spicelib/devices/bjt/bjttrunc.c @@ -30,7 +30,7 @@ BJTtrunc(GENmodel *inModel, CKTcircuit *ckt, double *timeStep) CKTterr(here->BJTqbe,ckt,timeStep); CKTterr(here->BJTqbc,ckt,timeStep); - CKTterr(here->BJTqcs,ckt,timeStep); + CKTterr(here->BJTqsub,ckt,timeStep); } } return(OK); diff --git a/src/spicelib/devices/dio/dio.c b/src/spicelib/devices/dio/dio.c index 01195aee3..1afe494a8 100644 --- a/src/spicelib/devices/dio/dio.c +++ b/src/spicelib/devices/dio/dio.c @@ -68,8 +68,8 @@ IFparm DIOmPTable[] = { /* model parameters */ IOPR( "ik", DIO_MOD_IKF, IF_REAL, "Forward Knee current"), IOP( "ikr", DIO_MOD_IKR, IF_REAL, "Reverse Knee current"), - IOP( "tlev", DIO_MOD_TLEV, IF_REAL, "Diode temperature equation selector"), - IOP( "tlevc", DIO_MOD_TLEVC, IF_REAL, "Diode temperature equation selector"), + IOP( "tlev", DIO_MOD_TLEV, IF_INTEGER, "Diode temperature equation selector"), + IOP( "tlevc", DIO_MOD_TLEVC, IF_INTEGER, "Diode temperature equation selector"), IOP( "eg", DIO_MOD_EG, IF_REAL, "Activation energy"), IOP( "xti", DIO_MOD_XTI, IF_REAL, "Saturation current temperature exp."), IOP( "cta", DIO_MOD_CTA, IF_REAL, "Area junction temperature coefficient"),