Added the possibility to specify the instance names to be considered from the Reliability Analysis

This commit is contained in:
Francesco Lannutti 2015-07-06 00:10:17 +02:00
parent da6b1b588e
commit b9ebfe2ce6
4 changed files with 237 additions and 184 deletions

View File

@ -9,7 +9,12 @@ Author: 1985 Thomas L. Quarles
#include "ngspice/typedefs.h"
#include "ngspice/ifsim.h"
#ifdef RELAN
typedef struct sGENrelmodelDeviceElem {
char *device_name ; /* Name of the device considered by Relmodel */
struct sGENrelmodelDeviceElem *next ; /* Pointer to the next device name */
} GENrelmodelDeviceElem ;
#endif
/* definitions used to describe generic devices */
@ -43,6 +48,7 @@ struct GENmodel { /* model structure for a resistor */
#ifdef RELAN
GENmodel *GENrelmodelModel ; /* Relmodel Companion Model */
GENrelmodelDeviceElem *GENrelmodelDeviceList ; /* List of devices to be considered by Relmodel */
#endif
};

View File

@ -7,196 +7,223 @@ Author: 2015 Francesco Lannutti - July 2015
#include "bsim4def.h"
#include "ngspice/sperror.h"
static int
BSIM4reliability_internal (BSIM4instance *here, CKTcircuit *ckt, unsigned int mode)
{
BSIM4model *model ;
double delta, vds, vgs, von ;
int NowIsON, ret ;
model = here->BSIM4modPtr ;
// Determine if the transistor is ON or OFF
vds = ckt->CKTstate0 [here->BSIM4vds] ;
vgs = ckt->CKTstate0 [here->BSIM4vgs] ;
von = model->BSIM4type * here->BSIM4von ;
if (vds >= 0)
{
// printf ("VDS >= 0\tBSIM4type: %d\tBSIM4instance: %s\tVgs: %-.9g\tVon: %-.9g\t", model->BSIM4type, here->BSIM4name, vgs, von) ;
if (vgs > von)
{
if (here->BSIM4rgateMod == 3)
{
double vges, vgms ;
vges = ckt->CKTstate0 [here->BSIM4vges] ;
vgms = ckt->CKTstate0 [here->BSIM4vgms] ;
if ((vges > von) && (vgms > von))
{
// printf ("Acceso!\n") ;
NowIsON = 1 ;
} else {
// printf ("Spento!\n") ;
NowIsON = 0 ;
}
} else if ((here->BSIM4rgateMod == 1) || (here->BSIM4rgateMod == 2)) {
double vges ;
vges = ckt->CKTstate0 [here->BSIM4vges] ;
if (vges > von)
{
// printf ("Acceso!\n") ;
NowIsON = 1 ;
} else {
// printf ("Spento!\n") ;
NowIsON = 0 ;
}
} else {
// printf ("Acceso!\n") ;
NowIsON = 1 ;
}
} else {
// printf ("Spento!\n") ;
NowIsON = 0 ;
}
} else {
double vgd ;
vgd = vgs - vds ;
// printf ("VDS < 0\tBSIM4type: %d\tBSIM4instance: %s\tVgd: %-.9g\tVon: %-.9g\t", model->BSIM4type, here->BSIM4name, vgd, von) ;
if (vgd > von)
{
if (here->BSIM4rgateMod == 3)
{
double vges, vged, vgms, vgmd ;
vges = ckt->CKTstate0 [here->BSIM4vges] ;
vged = vges - vds ;
vgms = ckt->CKTstate0 [here->BSIM4vgms] ;
vgmd = vgms - vds ;
if ((vged > von) && (vgmd > von))
{
// printf ("Acceso!\n") ;
NowIsON = 1 ;
} else {
// printf ("Spento!\n") ;
NowIsON = 0 ;
}
} else if ((here->BSIM4rgateMod == 1) || (here->BSIM4rgateMod == 2)) {
double vges, vged ;
vges = ckt->CKTstate0 [here->BSIM4vges] ;
vged = vges - vds ;
if (vged > von)
{
// printf ("Acceso!\n") ;
NowIsON = 1 ;
} else {
// printf ("Spento!\n") ;
NowIsON = 0 ;
}
} else {
// printf ("Acceso!\n") ;
NowIsON = 1 ;
}
} else {
// printf ("Spento!\n") ;
NowIsON = 0 ;
}
}
// If it's the first time, initialize 'here->relStruct->IsON'
if (here->relStruct->IsON == -1)
{
here->relStruct->IsON = NowIsON ;
}
if (mode == 0)
{
if (NowIsON)
{
if (here->relStruct->IsON == 1)
{
// Until now, the device was ON - Do NOTHING
delta = -1 ;
} else if (here->relStruct->IsON == 0) {
// Until now, the device was OFF - Calculate recovery
delta = ckt->CKTtime - here->relStruct->time ;
// Calculate Aging - Giogio Liatis' Model
ret = RELMODELcalculateAging ((GENinstance *)here, here->BSIM4modPtr->BSIM4modType, delta, 0) ;
if (ret == 1)
{
return (E_INTERN) ;
}
// Update time and flag - Stress begins
here->relStruct->time = ckt->CKTtime ;
here->relStruct->IsON = 1 ;
} else {
fprintf (stderr, "Reliability Analysis Error\n") ;
}
} else {
if (here->relStruct->IsON == 1)
{
// Until now, the device was ON - Calculate stress
delta = ckt->CKTtime - here->relStruct->time ;
// Calculate Aging - Giorgio Liatis' Model
ret = RELMODELcalculateAging ((GENinstance *)here, here->BSIM4modPtr->BSIM4modType, delta, 1) ;
if (ret == 1)
{
return (E_INTERN) ;
}
// Update time and flag - Recovery begins
here->relStruct->time = ckt->CKTtime ;
here->relStruct->IsON = 0 ;
} else if (here->relStruct->IsON == 0) {
// Until now, the device was OFF - Do NOTHING
delta = -1 ;
} else {
fprintf (stderr, "Reliability Analysis Error\n") ;
}
}
} else if (mode == 1) {
// In this mode, it doesn't matter if NOW the device is in stress or in recovery, since it's the last timestep
if (here->relStruct->IsON == 1)
{
// Calculate stress
delta = ckt->CKTtime - here->relStruct->time ;
ret = RELMODELcalculateAging ((GENinstance *)here, here->BSIM4modPtr->BSIM4modType, delta, 1) ;
if (ret == 1)
{
return (E_INTERN) ;
}
// Update time and flag - Maybe Optional
here->relStruct->time = ckt->CKTtime ;
here->relStruct->IsON = 1 ;
} else if (here->relStruct->IsON == 0) {
// Calculate recovery
delta = ckt->CKTtime - here->relStruct->time ;
ret = RELMODELcalculateAging ((GENinstance *)here, here->BSIM4modPtr->BSIM4modType, delta, 0) ;
if (ret == 1)
{
return (E_INTERN) ;
}
// Update time and flag - Maybe Optional
here->relStruct->time = ckt->CKTtime ;
here->relStruct->IsON = 0 ;
} else {
fprintf (stderr, "Reliability Analysis Error\n") ;
}
printf ("\tTime: %-.9gs\t\t", ckt->CKTtime) ;
printf ("DeltaVth: %-.9gmV\t\t", here->relStruct->deltaVth * 1000) ;
printf ("Device Name: %s\t\t", here->BSIM4name) ;
printf ("Device Type: %s\n\n", model->BSIM4modName) ;
} else {
fprintf (stderr, "Reliability Analysis Error\n") ;
}
return 0 ;
}
int
BSIM4reliability (GENmodel *inModel, CKTcircuit *ckt, unsigned int mode)
{
BSIM4model *model = (BSIM4model *)inModel ;
BSIM4instance *here ;
double delta, vds, vgs, von ;
int NowIsON, ret ;
GENrelmodelDeviceElem *elem ;
/* loop through all the BSIM4 device models */
for ( ; model != NULL ; model = model->BSIM4nextModel)
{
/* loop through all the instances of the model */
for (here = model->BSIM4instances ; here != NULL ; here=here->BSIM4nextInstance)
if (model->BSIM4type == PMOS)
{
if (model->BSIM4type == PMOS)
if (model->BSIM4relmodelDeviceList != NULL)
{
// Determine if the transistor is ON or OFF
vds = ckt->CKTstate0 [here->BSIM4vds] ;
vgs = ckt->CKTstate0 [here->BSIM4vgs] ;
von = model->BSIM4type * here->BSIM4von ;
if (vds >= 0)
for (elem = model->BSIM4relmodelDeviceList ; elem != NULL ; elem = elem->next)
{
// printf ("VDS >= 0\tBSIM4type: %d\tBSIM4instance: %s\tVgs: %-.9g\tVon: %-.9g\t", model->BSIM4type, here->BSIM4name, vgs, von) ;
if (vgs > von)
here = (BSIM4instance *)(CKTfndDev (ckt, elem->device_name)) ;
if (!here)
{
if (here->BSIM4rgateMod == 3)
{
double vges, vgms ;
vges = ckt->CKTstate0 [here->BSIM4vges] ;
vgms = ckt->CKTstate0 [here->BSIM4vgms] ;
if ((vges > von) && (vgms > von))
{
// printf ("Acceso!\n") ;
NowIsON = 1 ;
} else {
// printf ("Spento!\n") ;
NowIsON = 0 ;
}
} else if ((here->BSIM4rgateMod == 1) || (here->BSIM4rgateMod == 2)) {
double vges ;
vges = ckt->CKTstate0 [here->BSIM4vges] ;
if (vges > von)
{
// printf ("Acceso!\n") ;
NowIsON = 1 ;
} else {
// printf ("Spento!\n") ;
NowIsON = 0 ;
}
} else {
// printf ("Acceso!\n") ;
NowIsON = 1 ;
}
SPfrontEnd->IFerrorf (ERR_WARNING, "Error: Cannot find the %s instance of the %s model", elem->device_name, model->BSIM4modName) ;
} else {
// printf ("Spento!\n") ;
NowIsON = 0 ;
}
} else {
double vgd ;
vgd = vgs - vds ;
// printf ("VDS < 0\tBSIM4type: %d\tBSIM4instance: %s\tVgd: %-.9g\tVon: %-.9g\t", model->BSIM4type, here->BSIM4name, vgd, von) ;
if (vgd > von)
{
if (here->BSIM4rgateMod == 3)
{
double vges, vged, vgms, vgmd ;
vges = ckt->CKTstate0 [here->BSIM4vges] ;
vged = vges - vds ;
vgms = ckt->CKTstate0 [here->BSIM4vgms] ;
vgmd = vgms - vds ;
if ((vged > von) && (vgmd > von))
{
// printf ("Acceso!\n") ;
NowIsON = 1 ;
} else {
// printf ("Spento!\n") ;
NowIsON = 0 ;
}
} else if ((here->BSIM4rgateMod == 1) || (here->BSIM4rgateMod == 2)) {
double vges, vged ;
vges = ckt->CKTstate0 [here->BSIM4vges] ;
vged = vges - vds ;
if (vged > von)
{
// printf ("Acceso!\n") ;
NowIsON = 1 ;
} else {
// printf ("Spento!\n") ;
NowIsON = 0 ;
}
} else {
// printf ("Acceso!\n") ;
NowIsON = 1 ;
}
} else {
// printf ("Spento!\n") ;
NowIsON = 0 ;
BSIM4reliability_internal (here, ckt, mode) ;
}
}
// If it's the first time, initialize 'here->relStruct->IsON'
if (here->relStruct->IsON == -1)
} else {
/* loop through all the instances of the model */
for (here = model->BSIM4instances ; here != NULL ; here=here->BSIM4nextInstance)
{
here->relStruct->IsON = NowIsON ;
}
if (mode == 0)
{
if (NowIsON)
{
if (here->relStruct->IsON == 1)
{
// Until now, the device was ON - Do NOTHING
delta = -1 ;
} else if (here->relStruct->IsON == 0) {
// Until now, the device was OFF - Calculate recovery
delta = ckt->CKTtime - here->relStruct->time ;
// Calculate Aging - Giogio Liatis' Model
ret = RELMODELcalculateAging ((GENinstance *)here, here->BSIM4modPtr->BSIM4modType, delta, 0) ;
if (ret == 1)
{
return (E_INTERN) ;
}
// Update time and flag - Stress begins
here->relStruct->time = ckt->CKTtime ;
here->relStruct->IsON = 1 ;
} else {
fprintf (stderr, "Reliability Analysis Error\n") ;
}
} else {
if (here->relStruct->IsON == 1)
{
// Until now, the device was ON - Calculate stress
delta = ckt->CKTtime - here->relStruct->time ;
// Calculate Aging - Giorgio Liatis' Model
ret = RELMODELcalculateAging ((GENinstance *)here, here->BSIM4modPtr->BSIM4modType, delta, 1) ;
if (ret == 1)
{
return (E_INTERN) ;
}
// Update time and flag - Recovery begins
here->relStruct->time = ckt->CKTtime ;
here->relStruct->IsON = 0 ;
} else if (here->relStruct->IsON == 0) {
// Until now, the device was OFF - Do NOTHING
delta = -1 ;
} else {
fprintf (stderr, "Reliability Analysis Error\n") ;
}
}
} else if (mode == 1) {
// In this mode, it doesn't matter if NOW the device is in stress or in recovery, since it's the last timestep
if (here->relStruct->IsON == 1)
{
// Calculate stress
delta = ckt->CKTtime - here->relStruct->time ;
ret = RELMODELcalculateAging ((GENinstance *)here, here->BSIM4modPtr->BSIM4modType, delta, 1) ;
if (ret == 1)
{
return (E_INTERN) ;
}
// Update time and flag - Maybe Optional
here->relStruct->time = ckt->CKTtime ;
here->relStruct->IsON = 1 ;
} else if (here->relStruct->IsON == 0) {
// Calculate recovery
delta = ckt->CKTtime - here->relStruct->time ;
ret = RELMODELcalculateAging ((GENinstance *)here, here->BSIM4modPtr->BSIM4modType, delta, 0) ;
if (ret == 1)
{
return (E_INTERN) ;
}
// Update time and flag - Maybe Optional
here->relStruct->time = ckt->CKTtime ;
here->relStruct->IsON = 0 ;
} else {
fprintf (stderr, "Reliability Analysis Error\n") ;
}
printf ("\tTime: %-.9gs\t\t", ckt->CKTtime) ;
printf ("DeltaVth: %-.9gmV\t\t", here->relStruct->deltaVth * 1000) ;
printf ("Device Name: %s\t\t", here->BSIM4name) ;
printf ("Device Type: %s\n\n", model->BSIM4modName) ;
} else {
fprintf (stderr, "Reliability Analysis Error\n") ;
BSIM4reliability_internal (here, ckt, mode) ;
}
}
}

View File

@ -834,6 +834,7 @@ typedef struct sBSIM4model
#ifdef RELAN
GENmodel *BSIM4relmodelModel ;
GENrelmodelDeviceElem *BSIM4relmodelDeviceList ;
#endif
/* --- end of generic struct GENmodel --- */

View File

@ -18,17 +18,19 @@ extern IFsimulator *ft_sim;
static void
dot_appendmodel (CKTcircuit *ckt, INPtables *tab, card *current)
{
/* .appendmodel from_model to_model */
/* .appendmodel from_model to_model <list_of_devices> */
int type; /* the type the model says it is */
char *line ; /* the part of the current line left to parse */
char *relmodel_name ; /* the relmodel name */
char *appendmodel_name ; /* the appendmodel name */
char *save ; /* saj - used to save the posn of the start of
the parameters if the model is a mosfet */
char *model ; /* the name of the model */
INPmodel *thismodel ; /* pointer to model description for user's model */
GENmodel *mdfast ; /* pointer to the actual model */
int error ; /* error code temporary */
int type ; /* the type the model says it is */
char *line ; /* the part of the current line left to parse */
char *relmodel_name ; /* the relmodel name */
char *appendmodel_name ; /* the appendmodel name */
char *device_name ; /* the device name in the list of devices */
char *save ; /* saj - used to save the posn of the start of
the parameters if the model is a mosfet */
char *model ; /* the name of the model */
INPmodel *thismodel ; /* pointer to model description for user's model */
GENmodel *mdfast ; /* pointer to the actual model */
char* err_msg ;
#ifdef TRACE
@ -122,6 +124,23 @@ dot_appendmodel (CKTcircuit *ckt, INPtables *tab, card *current)
INPgetModBin (ckt, relmodel_name, &thismodel, tab, line) ;
}
thismodel->INPmodfast->GENrelmodelModel = mdfast ; /* Attach 'relmodel' model to 'appendmodel' model */
// Parse the rest of the line, which is a list of devices
thismodel->INPmodfast->GENrelmodelDeviceList = NULL ;
while (*line)
{
INPgetTok (&line, &device_name, 1) ;
error = INPretrieve (&device_name, tab) ;
if (error)
{
printf ("Warning: Cannot find the %s instance of the %s model - Skipping this instance\n\n", device_name, appendmodel_name) ;
} else {
GENrelmodelDeviceElem *GENrelmodelDevice = TMALLOC (GENrelmodelDeviceElem, 1) ;
GENrelmodelDevice->device_name = device_name ;
GENrelmodelDevice->next = thismodel->INPmodfast->GENrelmodelDeviceList ;
thismodel->INPmodfast->GENrelmodelDeviceList = GENrelmodelDevice ;
}
}
} else {
LITERR ("Error: The model 'relmodel' hasn't been defined\n\n") ;
}