update osdi version
This commit is contained in:
parent
321ea03444
commit
c60ab4203d
|
|
@ -185,7 +185,6 @@ endif
|
|||
|
||||
if OSDI_WANTED
|
||||
ngspice_LDADD += osdi/libosdi.la
|
||||
ngspice_LDFLAGS += -Wl,--dynamic-list=$(top_srcdir)/src/osdi/exported.txt
|
||||
endif
|
||||
|
||||
ngspice_LDADD += \
|
||||
|
|
|
|||
|
|
@ -15,7 +15,7 @@ libosdi_la_SOURCES = \
|
|||
osdiitf.h \
|
||||
osditrunc.c \
|
||||
osdipzld.c \
|
||||
exported.txt
|
||||
osdicallbacks.c
|
||||
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -1,6 +0,0 @@
|
|||
{
|
||||
extern "C"
|
||||
{
|
||||
osdi_log;
|
||||
};
|
||||
};
|
||||
|
|
@ -36,6 +36,17 @@
|
|||
#define CALC_REACT_JACOBIAN 8
|
||||
#define CALC_NOISE 16
|
||||
#define CALC_OP 32
|
||||
#define CALC_RESIST_LIM_RHS 64
|
||||
#define CALC_REACT_LIM_RHS 128
|
||||
#define ENABLE_LIM 256
|
||||
#define INIT_LIM 512
|
||||
#define ANALYSIS_NOISE 1024
|
||||
#define ANALYSIS_DC 2048
|
||||
#define ANALYSIS_AC 4096
|
||||
#define ANALYSIS_TRAN 8192
|
||||
#define ANALYSIS_IC 16384
|
||||
#define ANALYSIS_STATIC 32768
|
||||
#define ANALYSIS_NODESET 65536
|
||||
|
||||
#define EVAL_RET_FLAG_LIM 1
|
||||
#define EVAL_RET_FLAG_FATAL 2
|
||||
|
|
@ -56,6 +67,12 @@
|
|||
|
||||
|
||||
|
||||
typedef struct OsdiLimFunction {
|
||||
char *name;
|
||||
uint32_t num_args;
|
||||
void *func_ptr;
|
||||
}OsdiLimFunction;
|
||||
|
||||
typedef struct OsdiSimParas {
|
||||
char **names;
|
||||
double *vals;
|
||||
|
|
@ -67,6 +84,8 @@ typedef struct OsdiSimInfo {
|
|||
OsdiSimParas paras;
|
||||
double abstime;
|
||||
double *prev_solve;
|
||||
double *prev_state;
|
||||
double *next_state;
|
||||
uint32_t flags;
|
||||
}OsdiSimInfo;
|
||||
|
||||
|
|
@ -102,6 +121,8 @@ typedef struct OsdiNode {
|
|||
char *residual_units;
|
||||
uint32_t resist_residual_off;
|
||||
uint32_t react_residual_off;
|
||||
uint32_t resist_limit_rhs_off;
|
||||
uint32_t react_limit_rhs_off;
|
||||
bool is_flow;
|
||||
}OsdiNode;
|
||||
|
||||
|
|
@ -144,6 +165,9 @@ typedef struct OsdiDescriptor {
|
|||
uint32_t node_mapping_offset;
|
||||
uint32_t jacobian_ptr_resist_offset;
|
||||
|
||||
uint32_t num_states;
|
||||
uint32_t state_idx_off;
|
||||
|
||||
uint32_t bound_step_offset;
|
||||
|
||||
uint32_t instance_size;
|
||||
|
|
@ -162,6 +186,8 @@ typedef struct OsdiDescriptor {
|
|||
double *ln_noise_dens);
|
||||
void (*load_residual_resist)(void *inst, void* model, double *dst);
|
||||
void (*load_residual_react)(void *inst, void* model, double *dst);
|
||||
void (*load_limit_rhs_resist)(void *inst, void* model, double *dst);
|
||||
void (*load_limit_rhs_react)(void *inst, void* model, double *dst);
|
||||
void (*load_spice_rhs_dc)(void *inst, void* model, double *dst,
|
||||
double* prev_solve);
|
||||
void (*load_spice_rhs_tran)(void *inst, void* model, double *dst,
|
||||
|
|
@ -173,5 +199,3 @@ typedef struct OsdiDescriptor {
|
|||
|
||||
|
||||
|
||||
extern void osdi_log(void *handle, char* msg, uint32_t lvl);
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,88 @@
|
|||
#include "ngspice/devdefs.h"
|
||||
#include "osdidefs.h"
|
||||
|
||||
void osdi_log(void *handle_, char *msg, uint32_t lvl) {
|
||||
OsdiNgspiceHandle *handle = handle_;
|
||||
FILE *dst = stdout;
|
||||
switch (lvl & LOG_LVL_MASK) {
|
||||
case LOG_LVL_DEBUG:
|
||||
printf("OSDI(debug) %s: ", handle->name);
|
||||
break;
|
||||
case LOG_LVL_DISPLAY:
|
||||
printf("OSDI %s: ", handle->name);
|
||||
break;
|
||||
case LOG_LVL_INFO:
|
||||
printf("OSDI(info) %s: ", handle->name);
|
||||
break;
|
||||
case LOG_LVL_WARN:
|
||||
fprintf(stderr, "OSDI(warn) %s: ", handle->name);
|
||||
dst = stderr;
|
||||
break;
|
||||
case LOG_LVL_ERR:
|
||||
fprintf(stderr, "OSDI(err) %s: ", handle->name);
|
||||
dst = stderr;
|
||||
break;
|
||||
case LOG_LVL_FATAL:
|
||||
fprintf(stderr, "OSDI(fatal) %s: ", handle->name);
|
||||
dst = stderr;
|
||||
break;
|
||||
default:
|
||||
fprintf(stderr, "OSDI(unkown) %s", handle->name);
|
||||
break;
|
||||
}
|
||||
|
||||
if (lvl & LOG_FMT_ERR) {
|
||||
fprintf(dst, "failed to format\"%s\"\n", msg);
|
||||
} else {
|
||||
fprintf(dst, "%s", msg);
|
||||
}
|
||||
}
|
||||
|
||||
double osdi_pnjlim(bool init, bool *check, double vnew, double vold, double vt,
|
||||
double vcrit) {
|
||||
if (init) {
|
||||
*check = true;
|
||||
return vcrit;
|
||||
}
|
||||
int icheck = 0;
|
||||
double res = DEVpnjlim(vnew, vold, vt, vcrit, &icheck);
|
||||
*check = icheck != 0;
|
||||
return res;
|
||||
}
|
||||
|
||||
double osdi_limvds(bool init, bool *check, double vnew, double vold) {
|
||||
if (init) {
|
||||
*check = true;
|
||||
return 0.1;
|
||||
}
|
||||
double res = DEVlimvds(vnew, vold);
|
||||
if (res != vnew) {
|
||||
*check = true;
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
double osdi_fetlim(bool init, bool *check, double vnew, double vold,
|
||||
double vto) {
|
||||
if (init) {
|
||||
*check = true;
|
||||
return vto + 0.1;
|
||||
}
|
||||
double res = DEVfetlim(vnew, vold, vto);
|
||||
if (res != vnew) {
|
||||
*check = true;
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
double osdi_limitlog(bool init, bool *check, double vnew, double vold,
|
||||
double LIM_TOL) {
|
||||
if (init) {
|
||||
*check = true;
|
||||
return 0.0;
|
||||
}
|
||||
int icheck = 0;
|
||||
double res = DEVlimitlog(vnew, vold, LIM_TOL, &icheck);
|
||||
*check = icheck != 0;
|
||||
return res;
|
||||
}
|
||||
|
|
@ -30,7 +30,6 @@ typedef struct OsdiExtraInstData {
|
|||
double temp;
|
||||
bool temp_given;
|
||||
bool dt_given;
|
||||
bool lim;
|
||||
bool finish;
|
||||
|
||||
} __attribute__((aligned(sizeof(max_align_t)))) OsdiExtraInstData;
|
||||
|
|
@ -52,3 +51,17 @@ typedef struct OsdiNgspiceHandle {
|
|||
|
||||
/* values returned by $simparam*/
|
||||
OsdiSimParas get_simparams(const CKTcircuit *ckt);
|
||||
|
||||
typedef void (*osdi_log_ptr)(void *handle, char *msg, uint32_t lvl);
|
||||
void osdi_log(void *handle_, char *msg, uint32_t lvl);
|
||||
|
||||
typedef void (*osdi_log_ptr)(void *handle, char *msg, uint32_t lvl);
|
||||
|
||||
double osdi_pnjlim(bool init, bool *icheck, double vnew, double vold, double vt,
|
||||
double vcrit);
|
||||
|
||||
double osdi_limvds(bool init, bool *icheck, double vnew, double vold);
|
||||
double osdi_limitlog(bool init, bool *icheck, double vnew, double vold,
|
||||
double LIM_TOL);
|
||||
double osdi_fetlim(bool init, bool *icheck, double vnew, double vold,
|
||||
double vto);
|
||||
|
|
|
|||
|
|
@ -177,40 +177,3 @@ extern SPICEdev *osdi_create_spicedev(const OsdiRegistryEntry *entry) {
|
|||
|
||||
return OSDIinfo;
|
||||
}
|
||||
|
||||
extern void osdi_log(void *handle_, char *msg, uint32_t lvl) {
|
||||
OsdiNgspiceHandle *handle = handle_;
|
||||
FILE *dst = stdout;
|
||||
switch (lvl & LOG_LVL_MASK) {
|
||||
case LOG_LVL_DEBUG:
|
||||
printf("OSDI(debug) %s: ", handle->name);
|
||||
break;
|
||||
case LOG_LVL_DISPLAY:
|
||||
printf("OSDI %s: ", handle->name);
|
||||
break;
|
||||
case LOG_LVL_INFO:
|
||||
printf("OSDI(info) %s: ", handle->name);
|
||||
break;
|
||||
case LOG_LVL_WARN:
|
||||
fprintf(stderr, "OSDI(warn) %s: ", handle->name);
|
||||
dst = stderr;
|
||||
break;
|
||||
case LOG_LVL_ERR:
|
||||
fprintf(stderr, "OSDI(err) %s: ", handle->name);
|
||||
dst = stderr;
|
||||
break;
|
||||
case LOG_LVL_FATAL:
|
||||
fprintf(stderr, "OSDI(fatal) %s: ", handle->name);
|
||||
dst = stderr;
|
||||
break;
|
||||
default:
|
||||
fprintf(stderr, "OSDI(unkown) %s", handle->name);
|
||||
break;
|
||||
}
|
||||
|
||||
if (lvl & LOG_FMT_ERR) {
|
||||
fprintf(dst, "failed to format\"%s\"\n", msg);
|
||||
} else {
|
||||
fprintf(dst, "%s", msg);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -49,14 +49,19 @@ extern int OSDIload(GENmodel *inModel, CKTcircuit *ckt) {
|
|||
|
||||
bool is_init_smsig = ckt->CKTmode & MODEINITSMSIG;
|
||||
bool is_sweep = ckt->CKTmode & MODEDCTRANCURVE;
|
||||
bool is_dc = ckt->CKTmode & (MODEDCOP | MODEDCTRANCURVE);
|
||||
bool is_ac = ckt->CKTmode & (MODEAC | MODEINITSMSIG);
|
||||
bool is_tran = ckt->CKTmode & (MODETRAN);
|
||||
bool is_tran_op = ckt->CKTmode & (MODETRANOP);
|
||||
bool is_init_tran = ckt->CKTmode & MODEINITTRAN;
|
||||
bool is_init_junc = ckt->CKTmode & MODEINITJCT;
|
||||
|
||||
OsdiSimInfo sim_info = {
|
||||
.paras = get_simparams(ckt),
|
||||
.abstime = is_tran ? ckt->CKTtime : 0.0,
|
||||
.prev_solve = ckt->CKTrhsOld,
|
||||
.prev_state = ckt->CKTstates[0],
|
||||
.next_state = ckt->CKTstates[0],
|
||||
.flags = CALC_RESIST_JACOBIAN,
|
||||
};
|
||||
|
||||
|
|
@ -64,20 +69,37 @@ extern int OSDIload(GENmodel *inModel, CKTcircuit *ckt) {
|
|||
sim_info.flags |= CALC_OP;
|
||||
}
|
||||
|
||||
if (!is_init_smsig) {
|
||||
sim_info.flags |= CALC_RESIST_RESIDUAL;
|
||||
if (is_dc) {
|
||||
sim_info.flags |= ANALYSIS_DC | ANALYSIS_STATIC;
|
||||
}
|
||||
|
||||
if (is_tran || is_ac) {
|
||||
sim_info.flags |= CALC_REACT_JACOBIAN;
|
||||
if (!is_init_smsig) {
|
||||
sim_info.flags |= CALC_RESIST_RESIDUAL | ENABLE_LIM | CALC_RESIST_LIM_RHS;
|
||||
}
|
||||
|
||||
if (is_tran) {
|
||||
sim_info.flags |= CALC_REACT_RESIDUAL;
|
||||
sim_info.flags |= CALC_REACT_JACOBIAN | CALC_REACT_RESIDUAL |
|
||||
CALC_REACT_LIM_RHS | ANALYSIS_TRAN;
|
||||
}
|
||||
|
||||
if (is_tran_op) {
|
||||
sim_info.flags |= ANALYSIS_TRAN;
|
||||
}
|
||||
|
||||
if (is_ac) {
|
||||
sim_info.flags |= CALC_REACT_JACOBIAN | ANALYSIS_AC;
|
||||
}
|
||||
|
||||
if (is_init_tran) {
|
||||
sim_info.flags |= ANALYSIS_IC | ANALYSIS_STATIC;
|
||||
}
|
||||
|
||||
if (is_init_junc) {
|
||||
sim_info.flags |= INIT_LIM;
|
||||
}
|
||||
|
||||
if (ckt->CKTmode & MODEACNOISE) {
|
||||
sim_info.flags |= CALC_NOISE;
|
||||
sim_info.flags |= CALC_NOISE | ANALYSIS_NOISE;
|
||||
}
|
||||
|
||||
int ret = OK;
|
||||
|
|
@ -119,7 +141,9 @@ extern int OSDIload(GENmodel *inModel, CKTcircuit *ckt) {
|
|||
extra_inst_data->finish = true;
|
||||
}
|
||||
if (ret_flags & EVAL_RET_FLAG_LIM) {
|
||||
extra_inst_data->lim = true;
|
||||
ckt->CKTnoncon++;
|
||||
ckt->CKTtroubleElt = gen_inst;
|
||||
|
||||
}
|
||||
if (ret_flags & EVAL_RET_FLAG_STOP) {
|
||||
ret = (E_PAUSE);
|
||||
|
|
@ -138,7 +162,7 @@ extern int OSDIload(GENmodel *inModel, CKTcircuit *ckt) {
|
|||
(uint32_t *)(((char *)inst) + descr->node_mapping_offset);
|
||||
|
||||
/* use numeric integration to obtain the remainer of the RHS*/
|
||||
int state = gen_inst->GENstate;
|
||||
int state = gen_inst->GENstate + (int) descr->num_states;
|
||||
for (uint32_t i = 0; i < descr->num_nodes; i++) {
|
||||
if (descr->nodes[i].react_residual_off != UINT32_MAX) {
|
||||
|
||||
|
|
|
|||
|
|
@ -205,6 +205,23 @@ static size_t calc_osdi_instance_data_off(const OsdiDescriptor *descr) {
|
|||
} \
|
||||
const ty *name = (ty *)sym;
|
||||
|
||||
#define INIT_CALLBACK(name, ty) \
|
||||
sym = GET_SYM(handle, STRINGIFY(name)); \
|
||||
if (sym) { \
|
||||
ty *slot = (ty *)sym; \
|
||||
*slot = name; \
|
||||
}
|
||||
|
||||
#define IS_LIM_FUN(fun_name, num_args_, val) \
|
||||
if (strcmp(lim_table[i].name, fun_name) == 0) { \
|
||||
if (lim_table[i].num_args == num_args_) { \
|
||||
lim_table[i].func_ptr = (void *)val; \
|
||||
continue; \
|
||||
} else { \
|
||||
expected_args = num_args_; \
|
||||
} \
|
||||
}
|
||||
|
||||
static NGHASHPTR known_object_files = NULL;
|
||||
#define DUMMYDATA ((void *)42)
|
||||
/**
|
||||
|
|
@ -229,7 +246,8 @@ extern OsdiObjectFile load_object_file(const char *input) {
|
|||
}
|
||||
const char *path = resolve_input_path(input);
|
||||
if (!path) {
|
||||
printf("Error opening osdi lib \"%s\": No such file or directory!\n", input);
|
||||
printf("Error opening osdi lib \"%s\": No such file or directory!\n",
|
||||
input);
|
||||
return INVALID_OBJECT;
|
||||
}
|
||||
|
||||
|
|
@ -261,6 +279,37 @@ extern OsdiObjectFile load_object_file(const char *input) {
|
|||
GET_CONST(OSDI_NUM_DESCRIPTORS, uint32_t);
|
||||
GET_PTR(OSDI_DESCRIPTORS, OsdiDescriptor);
|
||||
|
||||
INIT_CALLBACK(osdi_log, osdi_log_ptr)
|
||||
|
||||
uint32_t lim_table_len = 0;
|
||||
sym = GET_SYM(handle, "OSDI_LIM_TABLE_LEN");
|
||||
if (sym) {
|
||||
lim_table_len = *((uint32_t *)sym);
|
||||
}
|
||||
|
||||
sym = GET_SYM(handle, "OSDI_LIM_TABLE");
|
||||
OsdiLimFunction *lim_table = NULL;
|
||||
if (sym) {
|
||||
lim_table = (OsdiLimFunction *)sym;
|
||||
} else {
|
||||
lim_table_len = 0;
|
||||
}
|
||||
|
||||
for (uint32_t i = 0; i < lim_table_len; i++) {
|
||||
int expected_args = -1;
|
||||
IS_LIM_FUN("pnjlim", 2, osdi_pnjlim)
|
||||
IS_LIM_FUN("limvds", 0, osdi_limvds)
|
||||
IS_LIM_FUN("fetlim", 1, osdi_fetlim)
|
||||
IS_LIM_FUN("limitlog", 1, osdi_limitlog)
|
||||
if (expected_args == -1) {
|
||||
printf("warning(osdi): unkown $limit function \"%s\"", lim_table[i].name);
|
||||
} else {
|
||||
printf("warning(osdi): unexpected number of arguments %i (expected %i) "
|
||||
"for \"%s\", ignoring...",
|
||||
lim_table[i].num_args, expected_args, lim_table[i].name);
|
||||
}
|
||||
}
|
||||
|
||||
OsdiRegistryEntry *dst = TMALLOC(OsdiRegistryEntry, OSDI_NUM_DESCRIPTORS);
|
||||
|
||||
for (uint32_t i = 0; i < OSDI_NUM_DESCRIPTORS; i++) {
|
||||
|
|
|
|||
|
|
@ -134,6 +134,16 @@ static void write_node_mapping(const OsdiDescriptor *descr, void *inst,
|
|||
}
|
||||
}
|
||||
|
||||
/* NGSPICE state vectors for an instance are always continous so we just write
|
||||
* state_start .. state_start + num_state to state_idx */
|
||||
static void write_state_ids(const OsdiDescriptor *descr, void *inst,
|
||||
uint32_t state_start) {
|
||||
uint32_t *state_idx = (uint32_t *)(((char *)inst) + descr->state_idx_off);
|
||||
for (uint32_t i = 0; i < descr->num_states; i++) {
|
||||
state_idx[i] = state_start + i;
|
||||
}
|
||||
}
|
||||
|
||||
static int init_matrix(SMPmatrix *matrix, const OsdiDescriptor *descr,
|
||||
void *inst) {
|
||||
uint32_t *node_mapping =
|
||||
|
|
@ -184,7 +194,7 @@ int OSDIsetup(SMPmatrix *matrix, GENmodel *inModel, CKTcircuit *ckt,
|
|||
uint32_t *node_ids = TMALLOC(uint32_t, descr->num_nodes);
|
||||
|
||||
/* determine the number of states required by each instance */
|
||||
int num_states = 0;
|
||||
int num_states = (int)descr->num_states;
|
||||
for (uint32_t i = 0; i < descr->num_nodes; i++) {
|
||||
if (descr->nodes[i].react_residual_off != UINT32_MAX) {
|
||||
num_states += 2;
|
||||
|
|
@ -269,6 +279,7 @@ int OSDIsetup(SMPmatrix *matrix, GENmodel *inModel, CKTcircuit *ckt,
|
|||
|
||||
/* reserve space in the state vector*/
|
||||
gen_inst->GENstate = *states;
|
||||
write_state_ids(descr, inst, (uint32_t)*states);
|
||||
*states += num_states;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -86,8 +86,9 @@ ACan(CKTcircuit *ckt, int restart)
|
|||
fprintf(stderr, "ERROR: AC startfreq <= 0\n");
|
||||
return E_PARMVAL;
|
||||
}
|
||||
job->ACfreqDelta =
|
||||
exp(log(10.0)/job->ACnumberSteps);
|
||||
double num_steps = floor(fabs(log10(job->ACstopFreq/job->ACstartFreq))*job->ACnumberSteps);
|
||||
job->ACfreqDelta = exp((log(job->ACstopFreq/job->ACstartFreq))/ num_steps);
|
||||
|
||||
break;
|
||||
case OCTAVE:
|
||||
if (job->ACstartFreq <= 0) {
|
||||
|
|
|
|||
|
|
@ -22,6 +22,10 @@ extern uint32_t OSDI_VERSION_MAJOR;
|
|||
extern uint32_t OSDI_VERSION_MINOR;
|
||||
extern uint32_t OSDI_NUM_DESCRIPTORS;
|
||||
extern OsdiDescriptor OSDI_DESCRIPTORS[1];
|
||||
extern OsdiLimFunction OSDI_LIM_TABLE[1];
|
||||
extern uint32_t OSDI_LIM_TABLE_LEN;
|
||||
|
||||
#define sqrt2 1.4142135623730950488016887242097
|
||||
|
||||
#define IGNORE(x) (void)x
|
||||
|
||||
|
|
@ -88,6 +92,10 @@ typedef struct DiodeInstace {
|
|||
bool mfactor_given;
|
||||
double temperature;
|
||||
double residual_resist[NUM_NODES];
|
||||
double lim_rhs_resist_A;
|
||||
double lim_rhs_resist_CI;
|
||||
double lim_rhs_react_A;
|
||||
double lim_rhs_react_CI;
|
||||
double residual_react_A;
|
||||
double residual_react_CI;
|
||||
double jacobian_resist[NUM_MATRIX];
|
||||
|
|
@ -96,6 +104,7 @@ typedef struct DiodeInstace {
|
|||
double *jacobian_ptr_resist[NUM_MATRIX];
|
||||
double *jacobian_ptr_react[NUM_MATRIX];
|
||||
uint32_t node_off[NUM_NODES];
|
||||
uint32_t state_idx;
|
||||
} DiodeInstace;
|
||||
|
||||
#define EXP_LIM 80.0
|
||||
|
|
@ -273,6 +282,9 @@ static void setup_instance(void *handle, void *inst_, void *model_,
|
|||
*res = (OsdiInitInfo){.flags = 0, .num_errors = 0, .errors = NULL};
|
||||
}
|
||||
|
||||
#define CONSTsqrt2 1.4142135623730950488016887242097
|
||||
typedef double (*pnjlim_t)(bool, bool *, double, double, double, double);
|
||||
|
||||
// implementation of the eval function as defined in the OSDI spec
|
||||
static uint32_t eval(void *handle, void *inst_, void *model_,
|
||||
OsdiSimInfo *info) {
|
||||
|
|
@ -297,6 +309,7 @@ static uint32_t eval(void *handle, void *inst_, void *model_,
|
|||
}
|
||||
}
|
||||
|
||||
uint32_t ret_flags = 0;
|
||||
////////////////////////////////
|
||||
// evaluate model equations
|
||||
////////////////////////////////
|
||||
|
|
@ -311,6 +324,22 @@ static uint32_t eval(void *handle, void *inst_, void *model_,
|
|||
double is_t = model->Is * pow(tdev_tnom, model->zetais);
|
||||
double vt = t_dev * pk / pq;
|
||||
|
||||
double delvaci = 0.0;
|
||||
if (info->flags & ENABLE_LIM && OSDI_LIM_TABLE[0].func_ptr) {
|
||||
double vte = inst->temperature * pk / pq;
|
||||
bool icheck = false;
|
||||
double vaci_old = info->prev_state[inst->state_idx];
|
||||
pnjlim_t pnjlim = OSDI_LIM_TABLE[0].func_ptr;
|
||||
double vaci_new = pnjlim(info->flags & INIT_LIM, &icheck, vaci, vaci_old,
|
||||
vte, vte * log(vte / (sqrt2 * model->Is)));
|
||||
printf("%g %g\n", vaci, vaci_new);
|
||||
delvaci = vaci_new - vaci;
|
||||
vaci = vaci_new;
|
||||
info->prev_state[inst->state_idx] = vaci;
|
||||
} else {
|
||||
printf("ok?");
|
||||
}
|
||||
|
||||
// derivatives w.r.t. temperature
|
||||
double rs_dt = model->zetars * model->Rs *
|
||||
pow(tdev_tnom, model->zetars - 1.0) / model->Tnom;
|
||||
|
|
@ -398,12 +427,24 @@ static uint32_t eval(void *handle, void *inst_, void *model_,
|
|||
inst->residual_resist[TNODE] = -ith * mfactor + irth * mfactor;
|
||||
}
|
||||
|
||||
if (info->flags & CALC_RESIST_LIM_RHS) {
|
||||
// write resist rhs
|
||||
inst->lim_rhs_resist_A = gd * mfactor * delvaci;
|
||||
inst->lim_rhs_resist_CI = -gd * mfactor * delvaci;
|
||||
}
|
||||
|
||||
if (info->flags & CALC_REACT_RESIDUAL) {
|
||||
// write react rhs
|
||||
inst->residual_react_A = qd * mfactor;
|
||||
inst->residual_react_CI = -qd * mfactor;
|
||||
}
|
||||
|
||||
if (info->flags & CALC_REACT_LIM_RHS) {
|
||||
// write resist rhs
|
||||
inst->lim_rhs_react_A = qd_vaci * mfactor * delvaci;
|
||||
inst->lim_rhs_react_CI = -qd_vaci * mfactor * delvaci;
|
||||
}
|
||||
|
||||
//////////////////
|
||||
// write Jacobian
|
||||
//////////////////
|
||||
|
|
@ -449,7 +490,7 @@ static uint32_t eval(void *handle, void *inst_, void *model_,
|
|||
inst->jacobian_react[CI_TNODE] = -qd_dtj * mfactor;
|
||||
}
|
||||
|
||||
return 0;
|
||||
return ret_flags;
|
||||
}
|
||||
|
||||
// TODO implementation of the load_noise function as defined in the OSDI spec
|
||||
|
|
@ -486,6 +527,25 @@ static void load_residual_react(void *inst_, void *model, double *dst) {
|
|||
dst[inst->node_off[CI]] += inst->residual_react_CI;
|
||||
}
|
||||
|
||||
// implementation of the load_lim_rhs_resist function as defined in the OSDI
|
||||
// spec
|
||||
static void load_lim_rhs_resist(void *inst_, void *model, double *dst) {
|
||||
DiodeInstace *inst = (DiodeInstace *)inst_;
|
||||
|
||||
IGNORE(model);
|
||||
dst[inst->node_off[A]] += inst->lim_rhs_resist_A;
|
||||
dst[inst->node_off[CI]] += inst->lim_rhs_resist_CI;
|
||||
}
|
||||
|
||||
// implementation of the load_lim_rhs_react function as defined in the OSDI spec
|
||||
static void load_lim_rhs_react(void *inst_, void *model, double *dst) {
|
||||
DiodeInstace *inst = (DiodeInstace *)inst_;
|
||||
|
||||
IGNORE(model);
|
||||
dst[inst->node_off[A]] += inst->lim_rhs_react_A;
|
||||
dst[inst->node_off[CI]] += inst->lim_rhs_react_CI;
|
||||
}
|
||||
|
||||
#define LOAD_MATRIX_RESIST(name) \
|
||||
*inst->jacobian_ptr_resist[name] += inst->jacobian_resist[name];
|
||||
|
||||
|
|
@ -558,13 +618,15 @@ static void load_spice_rhs_dc(void *inst_, void *model, double *dst,
|
|||
double vc = prev_solve[inst->node_off[C]];
|
||||
double vdtj = prev_solve[inst->node_off[TNODE]];
|
||||
|
||||
dst[inst->node_off[A]] +=
|
||||
inst->jacobian_resist[A_A] * va + inst->jacobian_resist[A_TNODE] * vdtj +
|
||||
inst->jacobian_resist[A_CI] * vci - inst->residual_resist[A];
|
||||
dst[inst->node_off[A]] += inst->jacobian_resist[A_A] * va +
|
||||
inst->jacobian_resist[A_TNODE] * vdtj +
|
||||
inst->jacobian_resist[A_CI] * vci +
|
||||
inst->lim_rhs_resist_A - inst->residual_resist[A];
|
||||
|
||||
dst[inst->node_off[CI]] += inst->jacobian_resist[CI_A] * va +
|
||||
inst->jacobian_resist[CI_TNODE] * vdtj +
|
||||
inst->jacobian_resist[CI_CI] * vci -
|
||||
inst->jacobian_resist[CI_CI] * vci +
|
||||
inst->lim_rhs_resist_CI -
|
||||
inst->residual_resist[CI];
|
||||
|
||||
dst[inst->node_off[C]] +=
|
||||
|
|
@ -592,13 +654,15 @@ static void load_spice_rhs_tran(void *inst_, void *model, double *dst,
|
|||
load_spice_rhs_dc(inst_, model, dst, prev_solve);
|
||||
|
||||
// add contributions due to reactive elements
|
||||
dst[inst->node_off[A]] += alpha * (inst->jacobian_react[A_A] * va +
|
||||
inst->jacobian_react[A_CI] * vci +
|
||||
inst->jacobian_react[A_TNODE] * vdtj);
|
||||
dst[inst->node_off[A]] +=
|
||||
alpha *
|
||||
(inst->jacobian_react[A_A] * va + inst->jacobian_react[A_CI] * vci +
|
||||
inst->jacobian_react[A_TNODE] * vdtj + inst->lim_rhs_react_A);
|
||||
|
||||
dst[inst->node_off[CI]] += alpha * (inst->jacobian_react[CI_CI] * vci +
|
||||
inst->jacobian_react[CI_A] * va +
|
||||
inst->jacobian_react[CI_TNODE] * vdtj);
|
||||
dst[inst->node_off[CI]] +=
|
||||
alpha *
|
||||
(inst->jacobian_react[CI_CI] * vci + inst->jacobian_react[CI_A] * va +
|
||||
inst->jacobian_react[CI_TNODE] * vdtj + inst->lim_rhs_react_CI);
|
||||
}
|
||||
|
||||
#define RESIST_RESIDUAL_OFF(NODE) \
|
||||
|
|
@ -640,8 +704,8 @@ const OsdiNode nodes[NUM_NODES] = {
|
|||
#define JACOBI_ENTRY(N1, N2) \
|
||||
{ \
|
||||
.nodes = {N1, N2}, .flags = JACOBIAN_ENTRY_RESIST | JACOBIAN_ENTRY_REACT, \
|
||||
.react_ptr_off = \
|
||||
offsetof(DiodeInstace, jacobian_ptr_react) + sizeof(double*) * N1##_##N2 \
|
||||
.react_ptr_off = offsetof(DiodeInstace, jacobian_ptr_react) + \
|
||||
sizeof(double *) * N1##_##N2 \
|
||||
}
|
||||
|
||||
#define RESIST_JACOBI_ENTRY(N1, N2) \
|
||||
|
|
@ -813,21 +877,30 @@ OsdiDescriptor OSDI_DESCRIPTORS[1] = {{
|
|||
// step size bound
|
||||
.bound_step_offset = UINT32_MAX,
|
||||
|
||||
.num_states = 1,
|
||||
.state_idx_off = offsetof(DiodeInstace, state_idx),
|
||||
|
||||
// memory
|
||||
.instance_size = sizeof(DiodeInstace),
|
||||
.model_size = sizeof(DiodeModel),
|
||||
|
||||
// setup
|
||||
.access = &osdi_access,
|
||||
.setup_model = &setup_model,
|
||||
.setup_instance = &setup_instance,
|
||||
.eval = &eval,
|
||||
.load_noise = &load_noise,
|
||||
.load_residual_resist = &load_residual_resist,
|
||||
.load_residual_react = &load_residual_react,
|
||||
.load_spice_rhs_dc = &load_spice_rhs_dc,
|
||||
.load_spice_rhs_tran = &load_spice_rhs_tran,
|
||||
.load_jacobian_resist = &load_jacobian_resist,
|
||||
.load_jacobian_react = &load_jacobian_react,
|
||||
.load_jacobian_tran = &load_jacobian_tran,
|
||||
.access = osdi_access,
|
||||
.setup_model = setup_model,
|
||||
.setup_instance = setup_instance,
|
||||
.eval = eval,
|
||||
.load_noise = load_noise,
|
||||
.load_residual_resist = load_residual_resist,
|
||||
.load_residual_react = load_residual_react,
|
||||
.load_spice_rhs_dc = load_spice_rhs_dc,
|
||||
.load_spice_rhs_tran = load_spice_rhs_tran,
|
||||
.load_jacobian_resist = load_jacobian_resist,
|
||||
.load_jacobian_react = load_jacobian_react,
|
||||
.load_jacobian_tran = load_jacobian_tran,
|
||||
.load_limit_rhs_react = load_lim_rhs_react,
|
||||
.load_limit_rhs_resist = load_lim_rhs_resist,
|
||||
}};
|
||||
|
||||
OsdiLimFunction OSDI_LIM_TABLE[1] = {{.name = "pnjlim", .num_args = 2}};
|
||||
|
||||
uint32_t OSDI_LIM_TABLE_LEN = 1;
|
||||
|
|
|
|||
Loading…
Reference in New Issue