From 6dc369c92708fd88c9d4bc39689effd989d73325 Mon Sep 17 00:00:00 2001 From: DSPOM Date: Fri, 1 Jul 2022 10:48:48 +0200 Subject: [PATCH] fix: add missing SPICE functions --- src/osdi/Makefile.am | 4 +++- src/osdi/osdi.h | 12 ++++++++++-- src/osdi/osdiext.h | 6 +++--- src/osdi/osdiinit.c | 9 +++++++-- src/osdi/osdiload.c | 22 ++++++++++++---------- src/osdi/osdipzld.c | 42 ++++++++++++++++++++++++++++++++++++++++++ src/osdi/osdisetup.c | 15 +++++++++++++-- src/osdi/osditrunc.c | 36 ++++++++++++++++++++++++++++++++++++ 8 files changed, 126 insertions(+), 20 deletions(-) create mode 100644 src/osdi/osdipzld.c create mode 100644 src/osdi/osditrunc.c diff --git a/src/osdi/Makefile.am b/src/osdi/Makefile.am index 77ee8a9c5..2a22c3b99 100644 --- a/src/osdi/Makefile.am +++ b/src/osdi/Makefile.am @@ -12,7 +12,9 @@ libosdi_la_SOURCES = \ osdiparam.c \ osdiregistry.c \ osdisetup.c \ - osdiitf.h + osdiitf.h \ + osditrunc.c \ + osdipzld.c \ exported.txt diff --git a/src/osdi/osdi.h b/src/osdi/osdi.h index 3716dc101..07fabd841 100644 --- a/src/osdi/osdi.h +++ b/src/osdi/osdi.h @@ -63,6 +63,13 @@ typedef struct OsdiSimParas { char **vals_str; }OsdiSimParas; +typedef struct OsdiSimInfo { + OsdiSimParas paras; + double abstime; + double *prev_solve; + uint32_t flags; +}OsdiSimInfo; + typedef union OsdiInitErrorPayload { uint32_t parameter_id; }OsdiInitErrorPayload; @@ -137,6 +144,8 @@ typedef struct OsdiDescriptor { uint32_t node_mapping_offset; uint32_t jacobian_ptr_resist_offset; + uint32_t bound_step_offset; + uint32_t instance_size; uint32_t model_size; @@ -148,8 +157,7 @@ typedef struct OsdiDescriptor { double temperature, uint32_t num_terminals, OsdiSimParas *sim_params, OsdiInitInfo *res); - uint32_t (*eval)(void *handle, void *inst, void *model, uint32_t flags, - double *prev_solve, OsdiSimParas *sim_params); + uint32_t (*eval)(void *handle, void *inst, void *model, OsdiSimInfo *info); void (*load_noise)(void *inst, void *model, double freq, double *noise_dens, double *ln_noise_dens); void (*load_residual_resist)(void *inst, void* model, double *dst); diff --git a/src/osdi/osdiext.h b/src/osdi/osdiext.h index 59086f9d5..7b24675ad 100644 --- a/src/osdi/osdiext.h +++ b/src/osdi/osdiext.h @@ -18,12 +18,12 @@ extern int OSDIask(CKTcircuit *, GENinstance *, int, IFvalue *, IFvalue *); extern int OSDIload(GENmodel *, CKTcircuit *); extern int OSDItemp(GENmodel *, CKTcircuit *); extern int OSDIacLoad(GENmodel *, CKTcircuit *); +extern int OSDItrunc(GENmodel *, CKTcircuit *, double *); +extern int OSDIpzLoad(GENmodel*, CKTcircuit*, SPcomplex*); + /* extern int OSDIconvTest(GENmodel*,CKTcircuit*); */ /* extern int OSDImDelete(GENmodel*); */ /* extern int OSDIgetic(GENmodel*,CKTcircuit*); */ /* extern int OSDImAsk(CKTcircuit*,GENmodel*,int,IFvalue*); */ -/* extern int OSDIpzLoad(GENmodel*, CKTcircuit*, SPcomplex*); */ -/* extern int OSDIunsetup(GENmodel*,CKTcircuit*); */ -/* extern int OSDItrunc(GENmodel*,CKTcircuit*,double*); */ /* extern int OSDInoise(int,int,GENmodel*,CKTcircuit*,Ndata*,double*); */ /* extern int OSDIsoaCheck(CKTcircuit *, GENmodel *); */ diff --git a/src/osdi/osdiinit.c b/src/osdi/osdiinit.c index 17e29d1db..44c1ce578 100644 --- a/src/osdi/osdiinit.c +++ b/src/osdi/osdiinit.c @@ -163,12 +163,17 @@ extern SPICEdev *osdi_create_spicedev(const OsdiRegistryEntry *entry) { // fill generic functions OSDIinfo->DEVparam = OSDIparam; OSDIinfo->DEVmodParam = OSDImParam; - OSDIinfo->DEVsetup = OSDIsetup; OSDIinfo->DEVask = OSDIask; + OSDIinfo->DEVsetup = OSDIsetup; + OSDIinfo->DEVpzSetup = OSDIsetup; OSDIinfo->DEVtemperature = OSDItemp; + OSDIinfo->DEVunsetup = OSDIunsetup; OSDIinfo->DEVload = OSDIload; OSDIinfo->DEVacLoad = OSDIacLoad; - OSDIinfo->DEVunsetup = OSDIunsetup; + OSDIinfo->DEVpzLoad = OSDIpzLoad; + OSDIinfo->DEVtrunc = OSDItrunc; + + return OSDIinfo; } diff --git a/src/osdi/osdiload.c b/src/osdi/osdiload.c index c59af340e..d5a8743fb 100644 --- a/src/osdi/osdiload.c +++ b/src/osdi/osdiload.c @@ -54,28 +54,31 @@ extern int OSDIload(GENmodel *inModel, CKTcircuit *ckt) { bool is_tran = ckt->CKTmode & (MODETRAN) || is_tran_op; bool is_init_tran = ckt->CKTmode & MODEINITTRAN; - uint32_t flags = CALC_RESIST_JACOBIAN; - - OsdiSimParas sim_params_ = get_simparams(ckt); + OsdiSimInfo sim_info = { + .paras = get_simparams(ckt), + .abstime = (is_tran || is_tran_op) ? ckt->CKTtime : 0.0, + .prev_solve = ckt->CKTrhsOld, + .flags = CALC_RESIST_JACOBIAN, + }; if (is_init_smsig || is_sweep) { - flags |= CALC_OP; + sim_info.flags |= CALC_OP; } if (!is_init_smsig) { - flags |= CALC_RESIST_RESIDUAL; + sim_info.flags |= CALC_RESIST_RESIDUAL; } if (is_tran || is_ac || is_tran_op) { - flags |= CALC_REACT_JACOBIAN; + sim_info.flags |= CALC_REACT_JACOBIAN; } if (is_tran || is_tran_op) { - flags |= CALC_REACT_RESIDUAL; + sim_info.flags |= CALC_REACT_RESIDUAL; } if (ckt->CKTmode & MODEACNOISE) { - flags |= CALC_NOISE; + sim_info.flags |= CALC_NOISE; } int ret = OK; @@ -94,8 +97,7 @@ extern int OSDIload(GENmodel *inModel, CKTcircuit *ckt) { data here*/ handle = (OsdiNgspiceHandle){.kind = 3, .name = gen_inst->GENname}; /* TODO initial conditions? */ - uint32_t ret_flags = descr->eval(&handle, inst, model, flags, - ckt->CKTrhsOld, &sim_params_); + uint32_t ret_flags = descr->eval(&handle, inst, model, &sim_info); /* call to $fatal in Verilog-A abort!*/ if (ret_flags & EVAL_RET_FLAG_FATAL) { diff --git a/src/osdi/osdipzld.c b/src/osdi/osdipzld.c new file mode 100644 index 000000000..a1611d6a6 --- /dev/null +++ b/src/osdi/osdipzld.c @@ -0,0 +1,42 @@ +/* + * Copyright© 2022 SemiMod UG. All rights reserved. + */ + +#include "ngspice/iferrmsg.h" +#include "ngspice/memory.h" +#include "ngspice/ngspice.h" +#include "ngspice/typedefs.h" + +#include "osdi.h" +#include "osdidefs.h" + +#include +#include +#include + +int OSDIpzLoad(GENmodel *inModel, CKTcircuit *ckt, SPcomplex *s) { + NG_IGNORE(ckt); + + GENmodel *gen_model; + GENinstance *gen_inst; + + OsdiRegistryEntry *entry = osdi_reg_entry_model(inModel); + const OsdiDescriptor *descr = entry->descriptor; + for (gen_model = inModel; gen_model; gen_model = gen_model->GENnextModel) { + void *model = osdi_model_data(gen_model); + + for (gen_inst = gen_model->GENinstances; gen_inst; + gen_inst = gen_inst->GENnextInstance) { + void *inst = osdi_instance_data(entry, gen_inst); + // nothing to calculate just load the matrix entries calculated during + // operating point iterations + // the load_jacobian_tran function migh seem weird here but all this does + // is adding J_resist + J_react * a to every matrix entry (real part). + // J_resist are the conductances (normal matrix entries) and J_react the + // capcitances + descr->load_jacobian_tran(inst, model, s->real); + descr->load_jacobian_react(inst, model, s->imag); + } + } + return (OK); +} diff --git a/src/osdi/osdisetup.c b/src/osdi/osdisetup.c index 7d944ccb6..167cf7463 100644 --- a/src/osdi/osdisetup.c +++ b/src/osdi/osdisetup.c @@ -323,9 +323,20 @@ extern int OSDItemp(GENmodel *inModel, CKTcircuit *ckt) { } handle = (OsdiNgspiceHandle){.kind = 2, .name = gen_inst->GENname}; - // TODO optional terminals + /* find number of connected ports to allow evaluation of $port_connected + * and to handle node collapsing correctly later + * */ + int *terminals = (int *)(gen_inst + 1); + uint32_t connected_terminals = descr->num_terminals; + for (uint32_t i = 0; i < descr->num_terminals; i++) { + if (terminals[i] == -1) { + connected_terminals = i; + break; + } + } + descr->setup_instance((void *)&handle, inst, model, temp, - descr->num_terminals, sim_params, &init_info); + connected_terminals, sim_params, &init_info); res = handle_init_info(init_info, descr); if (res) { errRtn = "OSDI setup_instance (OSDItemp)"; diff --git a/src/osdi/osditrunc.c b/src/osdi/osditrunc.c new file mode 100644 index 000000000..a3044fa3d --- /dev/null +++ b/src/osdi/osditrunc.c @@ -0,0 +1,36 @@ +/* + * Copyright© 2022 SemiMod UG. All rights reserved. + */ + +#include "ngspice/cktdefs.h" +#include "osdidefs.h" + +int OSDItrunc(GENmodel *in_model, CKTcircuit *ckt, double *timestep) { + OsdiRegistryEntry *entry = osdi_reg_entry_model(in_model); + const OsdiDescriptor *descr = entry->descriptor; + uint32_t offset = descr->bound_step_offset; + bool has_boundstep = offset != UINT32_MAX; + offset += entry->inst_offset; + + for (GENmodel *model = in_model; model; model = model->GENnextModel) { + for (GENinstance *inst = model->GENinstances; inst; + inst = inst->GENnextInstance) { + + if (has_boundstep) { + double *del = (double *)(((char *)inst) + offset); + if (*del < *timestep) { + *timestep = *del; + } + } + + int state = inst->GENstate; + for (uint32_t i = 0; i < descr->num_nodes; i++) { + if (descr->nodes[i].react_residual_off != UINT32_MAX) { + CKTterr(state, ckt, timestep); + state += 2; + } + } + } + } + return 0; +}