Added the possibility to specify the instance names to be considered from the Reliability Analysis
This commit is contained in:
parent
da6b1b588e
commit
b9ebfe2ce6
|
|
@ -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
|
||||
|
||||
};
|
||||
|
|
|
|||
|
|
@ -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) ;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -834,6 +834,7 @@ typedef struct sBSIM4model
|
|||
|
||||
#ifdef RELAN
|
||||
GENmodel *BSIM4relmodelModel ;
|
||||
GENrelmodelDeviceElem *BSIM4relmodelDeviceList ;
|
||||
#endif
|
||||
|
||||
/* --- end of generic struct GENmodel --- */
|
||||
|
|
|
|||
|
|
@ -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") ;
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue