Add a hash table to store the degradation monitor results per instance.

Transfer all data to the degmonitor cfunc.mod to reconstruct the
(MOS) device instance name in the code model. Use this instance
name as key for the hash table. Data is stored in loc->result.
This commit is contained in:
Holger Vogt 2026-01-29 23:19:58 +01:00
parent 40587ead4e
commit 6a0b8b16ce
5 changed files with 54 additions and 18 deletions

View File

@ -21,7 +21,7 @@ License: Modified BSD
#define DEGMODMAX 64
/* global pointer: results from first tran run */
NGHASHPTR degdatahash;
NGHASHPTR degdatahash = NULL;
struct agemod {
char* devmodel;
@ -192,8 +192,8 @@ int adddegmonitors(struct card* deck) {
*/
char* aline = tprintf("adegmon%d_%s %%v([%s]) mon%d degmon%d\n",
degmonno, instname, fournodes, degmonno, degmonno);
char* mline = tprintf(".model degmon%d degmon (tfuture=%e %s devmod=\"%s\"\n",
degmonno, tfuture, clength, modname);
char* mline = tprintf(".model degmon%d degmon (tfuture=%e %s devmod=\"%s\" instname=\"%s\"\n",
degmonno, tfuture, clength, modname, instname);
tfree(clength);
insert_new_line(deck, aline, 0, deck->linenum_orig, deck->linesource);
insert_new_line(deck, mline, 0, deck->linenum_orig, deck->linesource);
@ -212,7 +212,7 @@ int adddegmonitors(struct card* deck) {
}
}
/* initialze the result data storage */
degdatahash = nghash_init(degmonno);
degdatahash = nghash_init(64);
return degmonno;
}

View File

@ -47,6 +47,7 @@ NON-STANDARD FEATURES
#include "ngspice/typedefs.h"
#include "ngspice/miftypes.h"
#include "ngspice/hash.h"
#ifdef KLU
#include "ngspice/smpdefs.h"
@ -335,6 +336,7 @@ typedef struct Mif_Circ_Data_s {
double t[8]; /* History of last 8 analysis times t[0]=time */
double tstep; /* tran simulation tstep */
double tstop; /* tran simulation tstop */
NGHASHPTR deghash; /* result data degradation monitor */
} Mif_Circ_Data_t;

View File

@ -75,7 +75,7 @@ struct agemod {
double paramvals[DEGPARAMAX];
bool paramread[DEGPARAMAX];
NGHASHPTR paramhash;
} *agemodptr;
};
/* This struct is model-specific: We need three data sets for dlt_vth [0],
d_idlin [1], and d_idsat [2] */
@ -83,7 +83,7 @@ typedef struct {
double constfac[3]; /* intermediate factor */
double sintegral[3]; /* intermediate intgral */
double prevtime[3]; /* previous time */
int devtype; /* device type 1: nms, -1: pmos */
int devtype; /* device type 1: nmos, -1: pmos */
double VGS0; /* degradation model parameter */
double A[3]; /* degradation model parameter */
double Ea[3]; /* degradation model parameter */
@ -92,6 +92,8 @@ typedef struct {
double L2[3]; /* degradation model parameter */
double n[3]; /* degradation model parameter */
double c[3]; /* degradation model parameter */
double result[3]; /* degradation simulation result */
char *parentname; /* name of parent device for degmon */
} degLocal_Data_t;
@ -299,6 +301,10 @@ void cm_degmon(ARGS) /* structure holding parms,
degLocal_Data_t *loc; /* Pointer to local static data, not to be included
in the state vector */
/* Pointer to global hash table, saving the
degradation sim results of the first tran sim. */
NGHASHPTR glohash = mif_private->circuit.deghash;
if (ANALYSIS == MIF_AC) {
return;
}
@ -311,7 +317,7 @@ void cm_degmon(ARGS) /* structure holding parms,
tsim = TSTOP;
if (INIT==1) {
char inam[1024];
double Temp = TEMPERATURE + 273.15;
int err = -1, ii;
struct agemod *agemods = cm_get_deg_params();
@ -361,7 +367,26 @@ void cm_degmon(ARGS) /* structure holding parms,
cm_message_send("Error: could not extract device type from model name\n");
cm_cexit(1);
}
/* retrieve the parent instance name, e.g.
a.xtop.xcolumnblock.xcolumn@0@.xperiph2.xclkwe.xwenand.adegmon63_xi1_pmos
-->
n.xtop.xcolumnblock.xcolumn@0@.xperiph2.xclkwe.xwenand.xi1_pmos.nsg13_lv_pmos
*/
char *ipath = strdup(INSTMODNAME);
char *colon = strchr(ipath, ':');
if (!colon) {
cm_message_printf("Error: no colon, incompatible model name %s\n", ipath);
cm_cexit(1);
}
*colon = '\0';
char *xinstname = PARAM(instname);
snprintf(inam, 1024, "n.%s.%s.n%s", ipath, xinstname, devmod);
loc->parentname = strdup(inam);
tfree(ipath);
/*
cm_message_send(loc->parentname);
cm_message_send(devmod);
cm_message_send(INSTNAME);
cm_message_send(INSTMODNAME);
*/
@ -424,15 +449,23 @@ void cm_degmon(ARGS) /* structure holding parms,
OUTPUT(mon) = sintegral;
if (T(0) > 0.99999 * tsim) {
/** debugging **/
char *thisinstance = INSTNAME;
// cm_message_printf("%s\n", thisinstance);
/**** model equations 2 ****/
sintegral = sintegral * tfut / tsim;
deg = 1. / (c * (pow(sintegral, -1.* n)));
/***************************/
cm_message_printf("no. %d, Degradation deg = %e\n", ii, deg);
// cm_message_printf("no. %d, Degradation deg = %e\n", ii, deg);
sintegral = 1e99; // flag final time step
loc->result[ii] = deg;
}
loc->sintegral[ii] = sintegral;
loc->prevtime[ii] = prevtime;
}
/* save the degradation data for this instance */
if (T(0) > 0.99999 * tsim) {
nghash_insert(glohash, loc->parentname, loc->result);
}
}
}

View File

@ -53,14 +53,14 @@ Null_Allowed: yes yes
PARAMETER_TABLE:
Parameter_Name: tfuture
Description: "future time"
Data_Type: real
Default_Value: 315336e4
Limits: -
Vector: no
Vector_Bounds: -
Null_Allowed: yes
Parameter_Name: tfuture instname
Description: "future time" "parent instance"
Data_Type: real string
Default_Value: 315336e4 -
Limits: - -
Vector: no no
Vector_Bounds: - -
Null_Allowed: yes no
STATIC_VAR_TABLE:

View File

@ -50,6 +50,7 @@ NON-STANDARD FEATURES
#include "ngspice/cktdefs.h"
#include "ngspice/devdefs.h"
#include "ngspice/sperror.h"
#include "ngspice/hash.h"
#include "ngspice/evt.h"
@ -73,8 +74,7 @@ static void MIFauto_partial(
);
extern NGHASHPTR degdatahash;
/*
@ -214,6 +214,7 @@ MIFload(
cm_data.circuit.call_type = MIF_ANALOG;
cm_data.circuit.temperature = ckt->CKTtemp - 273.15;
cm_data.circuit.deghash = degdatahash;
g_mif_info.circuit.call_type = MIF_ANALOG;
g_mif_info.ckt = ckt;