fix: add missing SPICE functions
This commit is contained in:
parent
07e3f2a964
commit
6dc369c927
|
|
@ -12,7 +12,9 @@ libosdi_la_SOURCES = \
|
|||
osdiparam.c \
|
||||
osdiregistry.c \
|
||||
osdisetup.c \
|
||||
osdiitf.h
|
||||
osdiitf.h \
|
||||
osditrunc.c \
|
||||
osdipzld.c \
|
||||
exported.txt
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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 *); */
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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) {
|
||||
|
|
|
|||
|
|
@ -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 <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
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);
|
||||
}
|
||||
|
|
@ -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)";
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
Loading…
Reference in New Issue