fix: add missing SPICE functions

This commit is contained in:
DSPOM 2022-07-01 10:48:48 +02:00
parent 07e3f2a964
commit 6dc369c927
8 changed files with 126 additions and 20 deletions

View File

@ -12,7 +12,9 @@ libosdi_la_SOURCES = \
osdiparam.c \
osdiregistry.c \
osdisetup.c \
osdiitf.h
osdiitf.h \
osditrunc.c \
osdipzld.c \
exported.txt

View File

@ -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);

View File

@ -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 *); */

View File

@ -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;
}

View File

@ -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) {

42
src/osdi/osdipzld.c Normal file
View File

@ -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);
}

View File

@ -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)";

36
src/osdi/osditrunc.c Normal file
View File

@ -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;
}