Add operating point information to SOA check,

using vbefwd, vbcfwd, and vsubfwd
Operating point heck is enabled by .options warn=2
This commit is contained in:
Holger Vogt 2023-03-24 13:41:06 +01:00
parent 443567dbaf
commit c30af55491
6 changed files with 115 additions and 22 deletions

View File

@ -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")
};

View File

@ -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,
};

View File

@ -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";

View File

@ -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;

View File

@ -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;
}

View File

@ -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++;
}
}
}
}
}