diff --git a/src/spicelib/devices/vbic/vbic.c b/src/spicelib/devices/vbic/vbic.c index 7463cfa71..2ac939058 100644 --- a/src/spicelib/devices/vbic/vbic.c +++ b/src/spicelib/devices/vbic/vbic.c @@ -187,6 +187,9 @@ IFparm VBICmPTable[] = { /* model parameters */ IOPR("bvce", VBIC_MOD_VCE_MAX, IF_REAL, "maximum voltage C-E branch"), IOP("vsub_max", VBIC_MOD_VSUB_MAX, IF_REAL, "maximum voltage C-substrate branch"), IOPR("bvsub", VBIC_MOD_VSUB_MAX, IF_REAL, "maximum voltage C-substrate branch"), + IOP("vbefwd", VBIC_MOD_VBEFWD_MAX, IF_REAL, "maximum forward voltage B-E junction"), + IOP("vbcfwd", VBIC_MOD_VBCFWD_MAX, IF_REAL, "maximum forward voltage B-C junction"), + IOP("vsubfwd", VBIC_MOD_VSUBFWD_MAX, IF_REAL, "maximum forward voltage C-substrate junction"), IOP("selft", VBIC_MOD_SELFT, IF_INTEGER, "0: self-heating off, 1: self-heating on") }; diff --git a/src/spicelib/devices/vbic/vbicdefs.h b/src/spicelib/devices/vbic/vbicdefs.h index 2f771084e..fd28eebf0 100644 --- a/src/spicelib/devices/vbic/vbicdefs.h +++ b/src/spicelib/devices/vbic/vbicdefs.h @@ -486,6 +486,9 @@ typedef struct sVBICmodel { /* model structure for a vbic */ double VBICvbcMax; /* maximum voltage over B-C junction */ double VBICvceMax; /* maximum voltage over C-E branch */ double VBICvsubMax; /* maximum voltage over C-substrate branch */ + double VBICvbcfwdMax; /* maximum forward voltage over B-C junction */ + double VBICvbefwdMax; /* maximum forward voltage over C-E branch */ + double VBICvsubfwdMax; /* maximum forward voltage over C-substrate branch */ unsigned VBICtnomGiven : 1; unsigned VBICextCollResistGiven : 1; @@ -602,6 +605,9 @@ typedef struct sVBICmodel { /* model structure for a vbic */ unsigned VBICvbcMaxGiven : 1; unsigned VBICvceMaxGiven : 1; unsigned VBICvsubMaxGiven : 1; + unsigned VBICvbcfwdMaxGiven : 1; + unsigned VBICvbefwdMaxGiven : 1; + unsigned VBICvsubfwdMaxGiven : 1; } VBICmodel; #ifndef NPN @@ -739,6 +745,9 @@ enum { VBIC_MOD_VBC_MAX, VBIC_MOD_VCE_MAX, VBIC_MOD_VSUB_MAX, + VBIC_MOD_VBEFWD_MAX, + VBIC_MOD_VBCFWD_MAX, + VBIC_MOD_VSUBFWD_MAX, VBIC_MOD_SELFT, }; diff --git a/src/spicelib/devices/vbic/vbicmask.c b/src/spicelib/devices/vbic/vbicmask.c index 18142d917..757ee7771 100644 --- a/src/spicelib/devices/vbic/vbicmask.c +++ b/src/spicelib/devices/vbic/vbicmask.c @@ -366,6 +366,15 @@ VBICmAsk(CKTcircuit *ckt, GENmodel *instPtr, int which, IFvalue *value) case VBIC_MOD_VSUB_MAX: value->rValue = here->VBICvsubMax; return(OK); + case VBIC_MOD_VBEFWD_MAX: + value->rValue = here->VBICvbefwdMax; + return(OK); + case VBIC_MOD_VBCFWD_MAX: + value->rValue = here->VBICvbcfwdMax; + return(OK); + case VBIC_MOD_VSUBFWD_MAX: + value->rValue = here->VBICvsubfwdMax; + return(OK); case VBIC_MOD_TYPE: if (here->VBICtype == NPN) value->sValue = "npn"; diff --git a/src/spicelib/devices/vbic/vbicmpar.c b/src/spicelib/devices/vbic/vbicmpar.c index efd8a8fdf..cac58ad3f 100644 --- a/src/spicelib/devices/vbic/vbicmpar.c +++ b/src/spicelib/devices/vbic/vbicmpar.c @@ -513,6 +513,18 @@ VBICmParam(int param, IFvalue *value, GENmodel *inModel) mods->VBICvsubMax = value->rValue; mods->VBICvsubMaxGiven = TRUE; break; + case VBIC_MOD_VBEFWD_MAX: + mods->VBICvbefwdMax = value->rValue; + mods->VBICvbefwdMaxGiven = TRUE; + break; + case VBIC_MOD_VBCFWD_MAX: + mods->VBICvbcfwdMax = value->rValue; + mods->VBICvbcfwdMaxGiven = TRUE; + break; + case VBIC_MOD_VSUBFWD_MAX: + mods->VBICvsubfwdMax = value->rValue; + mods->VBICvsubfwdMaxGiven = TRUE; + break; case VBIC_MOD_SELFT: mods->VBICselft = value->iValue; mods->VBICselftGiven = TRUE; diff --git a/src/spicelib/devices/vbic/vbicsetup.c b/src/spicelib/devices/vbic/vbicsetup.c index a0945d47c..bbb90f7ae 100644 --- a/src/spicelib/devices/vbic/vbicsetup.c +++ b/src/spicelib/devices/vbic/vbicsetup.c @@ -391,6 +391,18 @@ VBICsetup(SMPmatrix *matrix, GENmodel *inModel, CKTcircuit *ckt, int *states) if(!model->VBICvceMaxGiven) { model->VBICvceMax = 1e99; } + if(!model->VBICvsubMaxGiven) { + model->VBICvsubMax = 1e99; + } + if (!model->VBICvbefwdMaxGiven) { + model->VBICvbefwdMax = 0.2; + } + if (!model->VBICvbcfwdMaxGiven) { + model->VBICvbcfwdMax = 0.2; + } + if (!model->VBICvsubfwdMaxGiven) { + model->VBICvsubfwdMax = 0.2; + } if(!model->VBICselftGiven) { model->VBICselft = 0; } diff --git a/src/spicelib/devices/vbic/vbicsoachk.c b/src/spicelib/devices/vbic/vbicsoachk.c index f6d6b4a25..b67a944a2 100644 --- a/src/spicelib/devices/vbic/vbicsoachk.c +++ b/src/spicelib/devices/vbic/vbicsoachk.c @@ -19,13 +19,14 @@ VBICsoaCheck(CKTcircuit *ckt, GENmodel *inModel) VBICinstance *here; double vbe, vbc, vce, vsub; /* actual bjt voltages */ int maxwarns; - static int warns_vbe = 0, warns_vbc = 0, warns_vce = 0, warns_vsub = 0; + static int warns_vbe = 0, warns_vbc = 0, warns_vce = 0, warns_vsub = 0, warns_op = 0; if (!ckt) { warns_vbe = 0; warns_vbc = 0; warns_vce = 0; warns_vsub = 0; + warns_op = 0; return OK; } @@ -33,48 +34,95 @@ VBICsoaCheck(CKTcircuit *ckt, GENmodel *inModel) for (; model; model = VBICnextModel(model)) { - for (here = VBICinstances(model); here; here=VBICnextInstance(here)) { + for (here = VBICinstances(model); here; here = VBICnextInstance(here)) { - vbe = fabs(ckt->CKTrhsOld [here->VBICbaseNode] - - ckt->CKTrhsOld [here->VBICemitNode]); - vbc = fabs(ckt->CKTrhsOld [here->VBICbaseNode] - - ckt->CKTrhsOld [here->VBICcollNode]); - vce = fabs(ckt->CKTrhsOld [here->VBICcollNode] - - ckt->CKTrhsOld [here->VBICemitNode]); - vsub = fabs(ckt->CKTrhsOld [here->VBICcollNode] - - ckt->CKTrhsOld [here->VBICsubsNode]); + vbe = fabs(ckt->CKTrhsOld[here->VBICbaseNode] - + ckt->CKTrhsOld[here->VBICemitNode]); + vbc = fabs(ckt->CKTrhsOld[here->VBICbaseNode] - + ckt->CKTrhsOld[here->VBICcollNode]); + vce = fabs(ckt->CKTrhsOld[here->VBICcollNode] - + ckt->CKTrhsOld[here->VBICemitNode]); + vsub = fabs(ckt->CKTrhsOld[here->VBICcollNode] - + ckt->CKTrhsOld[here->VBICsubsNode]); if (vbe > model->VBICvbeMax) if (warns_vbe < maxwarns) { - soa_printf(ckt, (GENinstance*) here, - "|Vbe|=%g has exceeded Vbe_max=%g\n", - vbe, model->VBICvbeMax); + soa_printf(ckt, (GENinstance*)here, + "|Vbe|=%g has exceeded Vbe_max=%g\n", + vbe, model->VBICvbeMax); warns_vbe++; } if (vbc > model->VBICvbcMax) if (warns_vbc < maxwarns) { - soa_printf(ckt, (GENinstance*) here, - "|Vbc|=%g has exceeded Vbc_max=%g\n", - vbc, model->VBICvbcMax); + soa_printf(ckt, (GENinstance*)here, + "|Vbc|=%g has exceeded Vbc_max=%g\n", + vbc, model->VBICvbcMax); warns_vbc++; } if (vce > model->VBICvceMax) if (warns_vce < maxwarns) { - soa_printf(ckt, (GENinstance*) here, - "|Vce|=%g has exceeded Vce_max=%g\n", - vce, model->VBICvceMax); + soa_printf(ckt, (GENinstance*)here, + "|Vce|=%g has exceeded Vce_max=%g\n", + vce, model->VBICvceMax); warns_vce++; } if (vsub > model->VBICvsubMax) if (warns_vsub < maxwarns) { - soa_printf(ckt, (GENinstance*) here, - "|Vce|=%g has exceeded Vce_max=%g\n", - vsub, model->VBICvsubMax); + soa_printf(ckt, (GENinstance*)here, + "|Vce|=%g has exceeded Vce_max=%g\n", + vsub, model->VBICvsubMax); warns_vsub++; } + + /* substrate diode is forward biased */ + if (model->VBICtype * (ckt->CKTrhsOld[here->VBICsubsNode] - + ckt->CKTrhsOld[here->VBICcollNode]) > model->VBICvsubfwdMax) { + /* substrate leakage */ + if (warns_vsub < maxwarns) { + soa_printf(ckt, (GENinstance*)here, + "substrate juntion is forward biased\n"); + warns_vsub++; + } + } + + /* operating point information */ + if (ckt->CKTsoaCheck == 2) { + if (vbe <= model->VBICvbefwdMax && vbc <= model->VBICvbefwdMax) { + /*off*/ + if (warns_op < maxwarns) { + soa_printf(ckt, (GENinstance*)here, + "device is off\n"); + warns_op++; + } + } + else if (vbe > model->VBICvbefwdMax && vbc > model->VBICvbefwdMax) { + /*saturation*/ + if (warns_op < maxwarns) { + soa_printf(ckt, (GENinstance*)here, + "device is in sturation\n"); + warns_op++; + } + } + else if (vbe > model->VBICvbefwdMax && vbc <= model->VBICvbefwdMax) { + /*forward*/ + if (warns_op < maxwarns) { + soa_printf(ckt, (GENinstance*)here, + "device is forward biased\n"); + warns_op++; + } + } + else if (vbe <= model->VBICvbefwdMax && vbc > model->VBICvbefwdMax) { + /*reverse*/ + if (warns_op < maxwarns) { + soa_printf(ckt, (GENinstance*)here, + "device is reverse biased\n"); + warns_op++; + } + } + } } }