diff --git a/configure.ac b/configure.ac index 039ccd01d..7c4169939 100644 --- a/configure.ac +++ b/configure.ac @@ -146,6 +146,10 @@ AC_ARG_ENABLE([oldapps], AC_ARG_ENABLE([xspice], [AS_HELP_STRING([--enable-xspice], [Enable XSPICE enhancements])]) +# --enable-osdi: define OSDI in the code. This is for osdi support +AC_ARG_ENABLE([osdi], + [AS_HELP_STRING([--enable-osdi], [Enable OSDI integration])]) + # --enable-cider: define CIDER in the code. This is for CIDER support AC_ARG_ENABLE([cider], [AS_HELP_STRING([--enable-cider], [Enable CIDER enhancements])]) @@ -1158,6 +1162,12 @@ AC_SUBST([XSPICEDLLIBS]) AM_CONDITIONAL([XSPICE_WANTED], [test "x$enable_xspice" = xyes]) +if test "x$enable_osdi" = xyes; then + AC_MSG_RESULT([OSDI features included]) + AC_DEFINE([OSDI], [1], [The OSDI enhancements]) +fi + +AM_CONDITIONAL([OSDI_WANTED], [test "x$enable_osdi" = xyes]) # Add CIDER enhancements to ngspice. if test "x$enable_cider" = xyes; then @@ -1373,7 +1383,6 @@ AC_CONFIG_FILES([Makefile src/spicelib/devices/hfet1/Makefile src/spicelib/devices/hfet2/Makefile src/spicelib/devices/hicum2/Makefile - src/spicelib/devices/osdi/Makefile src/spicelib/devices/hisim2/Makefile src/spicelib/devices/hisimhv1/Makefile src/spicelib/devices/hisimhv2/Makefile @@ -1439,6 +1448,7 @@ AC_CONFIG_FILES([Makefile src/xspice/enh/Makefile src/xspice/ipc/Makefile src/xspice/idn/Makefile + src/osdi/Makefile tests/Makefile tests/bsim1/Makefile tests/bsim2/Makefile diff --git a/src/Makefile.am b/src/Makefile.am index f125ba2ae..96170761c 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -7,6 +7,10 @@ if XSPICE_WANTED SUBDIRS += xspice endif +if OSDI_WANTED +SUBDIRS += osdi +endif + if CIDER_WANTED SUBDIRS += ciderlib endif @@ -70,7 +74,6 @@ DYNAMIC_DEVICELIBS = \ spicelib/devices/hfet1/libhfet.la \ spicelib/devices/hfet2/libhfet2.la \ spicelib/devices/hicum2/libhicum2.la \ - spicelib/devices/osdi/libosdi.la \ spicelib/devices/hisim2/libhisim2.la \ spicelib/devices/hisimhv1/libhisimhv1.la \ spicelib/devices/hisimhv2/libhisimhv2.la \ @@ -98,6 +101,8 @@ DYNAMIC_DEVICELIBS = \ @VLADEV@ + + ## Build ngspice first: ## compile the icon: @@ -176,6 +181,10 @@ ngspice_LDADD += \ ciderlib/support/libcidersuprt.la endif +if OSDI_WANTED +ngspice_LDADD += osdi/libosdi.la +endif + ngspice_LDADD += \ maths/deriv/libderiv.la \ maths/cmaths/libcmaths.la \ @@ -458,6 +467,11 @@ libspice_la_LIBADD += \ ciderlib/support/libcidersuprt.la endif + +if OSDI_WANTED +libspice_la_LIBADD += osdi/libosdi.la +endif + libspice_la_LIBADD += \ maths/deriv/libderiv.la \ maths/cmaths/libcmaths.la \ @@ -577,6 +591,9 @@ libngspice_la_LIBADD += \ ciderlib/support/libcidersuprt.la endif + +libngspice_la_LIBADD += osdi/libosdi.la + libngspice_la_LIBADD += \ maths/deriv/libderiv.la \ maths/cmaths/libcmaths.la \ diff --git a/src/frontend/com_dl.c b/src/frontend/com_dl.c index 00ef5b6e3..2cdca00a7 100644 --- a/src/frontend/com_dl.c +++ b/src/frontend/com_dl.c @@ -18,6 +18,21 @@ void com_codemodel(wordlist *wl) } #endif +#ifdef OSDI +void com_osdi(wordlist *wl) +{ + wordlist *ww; + for (ww = wl; ww; ww = ww->wl_next) + if (load_osdi(ww->wl_word)) { + fprintf(cp_err, "Error: Library %s couldn't be loaded!\n", ww->wl_word); + if (ft_stricterror) + controlled_exit(EXIT_BAD); + } +} +#endif + + + #ifdef DEVLIB void com_use(wordlist *wl) diff --git a/src/frontend/com_dl.h b/src/frontend/com_dl.h index fcb9b1ce8..91028de3c 100644 --- a/src/frontend/com_dl.h +++ b/src/frontend/com_dl.h @@ -5,6 +5,10 @@ void com_codemodel(wordlist *wl); #endif +#ifdef OSDI +void com_osdi(wordlist *wl); +#endif + #ifdef DEVLIB void com_use(wordlist *wl); #endif diff --git a/src/frontend/commands.c b/src/frontend/commands.c index c6754ef08..028f24071 100644 --- a/src/frontend/commands.c +++ b/src/frontend/commands.c @@ -268,6 +268,12 @@ struct comm spcp_coms[] = { NULL, "library library ... : Loads the code model libraries." } , #endif +#ifdef OSDI + { "osdi", com_osdi, FALSE, TRUE, + { 040000, 040000, 040000, 040000 }, E_BEGINNING, 1, LOTS, + NULL, + "library library ... : Loads a osdi library." } , +#endif #ifdef DEVLIB { "use", com_use, FALSE, TRUE, { 040000, 040000, 040000, 040000 }, E_BEGINNING, 1, LOTS, diff --git a/src/frontend/gens.c b/src/frontend/gens.c index bddd8dcc5..d9df16a3a 100644 --- a/src/frontend/gens.c +++ b/src/frontend/gens.c @@ -163,7 +163,7 @@ dgen_next(dgen **dgx) if (!dg->dev_list) { if ((dg->flags & DGEN_ALLDEVS) || ((dg->flags & DGEN_DEFDEVS) && - (ft_sim->devices[dg->dev_type_no]->flags & DEV_DEFAULT_CHECK))) + (ft_sim->devices[dg->dev_type_no]->flags & DEV_DEFAULT))) { done = 1; } else { diff --git a/src/frontend/inp.c b/src/frontend/inp.c index 0935b4c6c..b58d35e10 100644 --- a/src/frontend/inp.c +++ b/src/frontend/inp.c @@ -18,6 +18,7 @@ Author: 1985 Wayne A. Christopher #include "ngspice/fteinp.h" #include "inp.h" +#include "ngspice/osdiitf.h" #include "runcoms.h" #include "inpcom.h" #include "circuits.h" @@ -570,7 +571,6 @@ inp_spsource(FILE *fp, bool comfile, char *filename, bool intfile) if (fp) { cp_vset("inputdir", CP_STRING, dir_name); } - tfree(dir_name); /* if nothing came back from inp_readall, e.g. after calling ngspice without parameters, just close fp and return to caller */ @@ -745,8 +745,16 @@ inp_spsource(FILE *fp, bool comfile, char *filename, bool intfile) before the circuit structure is set up */ if (pre_controls) { pre_controls = wl_reverse(pre_controls); - for (wl = pre_controls; wl; wl = wl->wl_next) + for (wl = pre_controls; wl; wl = wl->wl_next){ +#ifdef OSDI + inputdir = dir_name; +#endif cp_evloop(wl->wl_word); + } + +#ifdef OSDI + inputdir = NULL; +#endif wl_free(pre_controls); } @@ -1112,18 +1120,29 @@ inp_spsource(FILE *fp, bool comfile, char *filename, bool intfile) of commands. Thus this is delegated to a function using a third thread, that only starts when the background thread has finished (sharedspice.c).*/ #ifdef SHARED_MODULE - for (wl = controls; wl; wl = wl->wl_next) + for (wl = controls; wl; wl = wl->wl_next){ +#ifdef OSDI + inputdir = dir_name; +#endif if (cp_getvar("controlswait", CP_BOOL, NULL, 0)) { exec_controls(wl_copy(wl)); break; } else cp_evloop(wl->wl_word); + } #else - for (wl = controls; wl; wl = wl->wl_next) + for (wl = controls; wl; wl = wl->wl_next){ +#ifdef OSDI + inputdir = dir_name; +#endif cp_evloop(wl->wl_word); + } #endif wl_free(controls); +#ifdef OSDI + inputdir = NULL; +#endif } /* Now reset everything. Pop the control stack, and fix up the IO @@ -1135,6 +1154,9 @@ inp_spsource(FILE *fp, bool comfile, char *filename, bool intfile) cp_curerr = lasterr; tfree(tt); + tfree(dir_name); + + return 0; } diff --git a/src/include/ngspice/devdefs.h b/src/include/ngspice/devdefs.h index 3fc0451ce..832aa4751 100644 --- a/src/include/ngspice/devdefs.h +++ b/src/include/ngspice/devdefs.h @@ -183,9 +183,6 @@ extern int DEVmaxnum; /* size of DEVices array */ -#define DEV_STATIC 0x1 -#define DEV_DEFAULT_CHECK 0x2 -#define DEV_DEFAULT (DEV_DEFAULT_CHECK | DEV_STATIC) -#define DEV_OSDI 0x4 +#define DEV_DEFAULT 0x1 #endif diff --git a/src/include/ngspice/ifsim.h b/src/include/ngspice/ifsim.h index 4d62605b8..cf019be2e 100644 --- a/src/include/ngspice/ifsim.h +++ b/src/include/ngspice/ifsim.h @@ -299,6 +299,10 @@ struct IFdevice { #endif int flags; /* DEV_ */ + +#ifdef OSDI + const void *registry_entry; +#endif }; diff --git a/src/include/ngspice/inpdefs.h b/src/include/ngspice/inpdefs.h index 74c305a59..49488ea88 100644 --- a/src/include/ngspice/inpdefs.h +++ b/src/include/ngspice/inpdefs.h @@ -120,7 +120,6 @@ double INPevaluateRKM_R(char **, int *, int); double INPevaluateRKM_C(char **, int *, int); double INPevaluateRKM_L(char **, int *, int); char *INPfindLev(char *, int *); -char *INPfindModule(char *); char *INPgetMod(CKTcircuit *, char *, INPmodel **, INPtables *); char *INPgetModBin(CKTcircuit *, char *, INPmodel **, INPtables *, char *); int INPgetTok(char **, char **, int); @@ -146,7 +145,6 @@ int INPtermInsert(CKTcircuit *, char **, INPtables *, CKTnode **); int INPtermSearch(CKTcircuit*, char**, INPtables*, CKTnode**); int INPmkTerm(CKTcircuit *, char **, INPtables *, CKTnode **); int INPtypelook(char *); -int INPtypelook_flag(char *, int); int INP2dot(CKTcircuit *, INPtables *, struct card *, TSKtask *, CKTnode *); INPtables *INPtabInit(int); void INPkillMods(void); diff --git a/src/include/ngspice/ngspice.h b/src/include/ngspice/ngspice.h index 0a80c2b30..74535553e 100644 --- a/src/include/ngspice/ngspice.h +++ b/src/include/ngspice/ngspice.h @@ -279,7 +279,6 @@ extern char *Help_Path; extern char *Lib_Path; extern char *Inp_Path; extern char *Infile_Path; -extern char *OSDI_Path; #ifdef TCL_MODULE diff --git a/src/include/ngspice/osdiitf.h b/src/include/ngspice/osdiitf.h new file mode 100644 index 000000000..5d77019e0 --- /dev/null +++ b/src/include/ngspice/osdiitf.h @@ -0,0 +1,25 @@ +/* + * Copyright© 2022 SemiMod UG. All rights reserved. + */ + +#pragma once + +#include "ngspice/devdefs.h" +#include + +typedef struct OsdiRegistryEntry { + const void *descriptor; + uint32_t inst_offset; + uint32_t dt; + uint32_t temp; +} OsdiRegistryEntry; + +typedef struct OsdiObjectFile { + OsdiRegistryEntry *entrys; + int num_entries; +} OsdiObjectFile; + +extern OsdiObjectFile load_object_file(const char *path); +extern SPICEdev *osdi_create_spicedev(const OsdiRegistryEntry *entry); + +extern char *inputdir; diff --git a/src/misc/ivars.c b/src/misc/ivars.c index fed992bb9..5c8afcaa9 100644 --- a/src/misc/ivars.c +++ b/src/misc/ivars.c @@ -72,8 +72,6 @@ ivars(char *argv0) mkvar(&Help_Path, Spice_Lib_Dir, "helpdir", "SPICE_HELP_DIR"); /* where spinit is found */ mkvar(&Lib_Path, Spice_Lib_Dir, "scripts", "SPICE_SCRIPTS"); - /* used to search for OSDI models*/ - mkvar(&OSDI_Path, Spice_Lib_Dir, "osdi", "SPICE_OSDI"); /* used to call ngspice with aspice command, not used in Windows mode */ mkvar(&Spice_Path, Spice_Exec_Dir, "ngspice", "SPICE_PATH"); tfree(temp); @@ -115,5 +113,4 @@ destroy_ivars(void) tfree(Lib_Path); tfree(Spice_Path); tfree(Inp_Path); - tfree(OSDI_Path); } diff --git a/src/spicelib/devices/osdi/Makefile.am b/src/osdi/Makefile.am similarity index 100% rename from src/spicelib/devices/osdi/Makefile.am rename to src/osdi/Makefile.am diff --git a/src/spicelib/devices/osdi/osdi.h b/src/osdi/osdi.h similarity index 100% rename from src/spicelib/devices/osdi/osdi.h rename to src/osdi/osdi.h diff --git a/src/spicelib/devices/osdi/osdiacld.c b/src/osdi/osdiacld.c similarity index 88% rename from src/spicelib/devices/osdi/osdiacld.c rename to src/osdi/osdiacld.c index a311d9dfa..9a00f2402 100644 --- a/src/spicelib/devices/osdi/osdiacld.c +++ b/src/osdi/osdiacld.c @@ -19,8 +19,8 @@ int OSDIacLoad(GENmodel *inModel, CKTcircuit *ckt) { GENmodel *gen_model; GENinstance *gen_inst; - OsdiRegistryEntry entry = osdi_reg_entry_model(inModel); - const OsdiDescriptor *descr = entry.descriptor; + OsdiRegistryEntry *entry = osdi_reg_entry_model(inModel); + const OsdiDescriptor *descr = entry->descriptor; for (gen_model = inModel; gen_model; gen_model = gen_model->GENnextModel) { for (gen_inst = gen_model->GENinstances; gen_inst; gen_inst = gen_inst->GENnextInstance) { diff --git a/src/osdi/osdidefs.h b/src/osdi/osdidefs.h new file mode 100644 index 000000000..ab2d8ae62 --- /dev/null +++ b/src/osdi/osdidefs.h @@ -0,0 +1,51 @@ +/* + * Copyright© 2022 SemiMod UG. All rights reserved. + */ + +#pragma once + +#include "ngspice/cktdefs.h" +#include "ngspice/complex.h" +#include "ngspice/fteext.h" +#include "ngspice/gendefs.h" +#include "ngspice/ifsim.h" +#include "ngspice/ngspice.h" +#include "ngspice/noisedef.h" +#include "ngspice/typedefs.h" + +#include "osdi.h" +#include "osdiext.h" + +#include "stddef.h" +#include +#include + +typedef struct OsdiModelData { + GENmodel gen; + max_align_t data; +} OsdiModelData; + +typedef struct OsdiExtraInstData { + double dt; + double temp; + bool temp_given; + bool dt_given; + bool lim; + bool finish; + +} __attribute__((aligned(sizeof(max_align_t)))) OsdiExtraInstData; + +size_t osdi_instance_data_off(const OsdiRegistryEntry *entry); +void *osdi_instance_data(const OsdiRegistryEntry *entry, GENinstance *inst); +OsdiExtraInstData *osdi_extra_instance_data(const OsdiRegistryEntry *entry, + GENinstance *inst); +size_t osdi_model_data_off(void); +void *osdi_model_data(GENmodel *model); +void *osdi_model_data_from_inst(GENinstance *inst); +OsdiRegistryEntry *osdi_reg_entry_model(const GENmodel *model); +OsdiRegistryEntry *osdi_reg_entry_inst(const GENinstance *inst); + +typedef struct OsdiNgspiceHandle { + uint32_t kind; + char *name; +} OsdiNgspiceHandle; diff --git a/src/spicelib/devices/osdi/osdiext.h b/src/osdi/osdiext.h similarity index 93% rename from src/spicelib/devices/osdi/osdiext.h rename to src/osdi/osdiext.h index dd4d035b7..59086f9d5 100644 --- a/src/spicelib/devices/osdi/osdiext.h +++ b/src/osdi/osdiext.h @@ -8,7 +8,7 @@ #include "ngspice/smpdefs.h" #include -#include "osdiitf.h" +#include "ngspice/osdiitf.h" extern int OSDImParam(int, IFvalue *, GENmodel *); extern int OSDIparam(int, IFvalue *, GENinstance *, IFvalue *); @@ -17,7 +17,7 @@ extern int OSDIunsetup(GENmodel *, CKTcircuit *); 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 OSDIacLoad(GENmodel *, CKTcircuit *); /* extern int OSDIconvTest(GENmodel*,CKTcircuit*); */ /* extern int OSDImDelete(GENmodel*); */ /* extern int OSDIgetic(GENmodel*,CKTcircuit*); */ diff --git a/src/spicelib/devices/osdi/osdiinit.c b/src/osdi/osdiinit.c similarity index 82% rename from src/spicelib/devices/osdi/osdiinit.c rename to src/osdi/osdiinit.c index cd8938eb5..d7e6028c4 100644 --- a/src/spicelib/devices/osdi/osdiinit.c +++ b/src/osdi/osdiinit.c @@ -11,18 +11,16 @@ #include "ngspice/ngspice.h" #include "ngspice/typedefs.h" -#include "../dev.h" - #include "osdidefs.h" #include #include #include -/** +/* * This function converts the information in (a list of) OsdiParamOpvar in * descr->param_opvar to the internal ngspice representation (IFparm). - * */ + */ static int write_param_info(IFparm **dst, const OsdiDescriptor *descr, uint32_t start, uint32_t end) { for (uint32_t i = start; i < end; i++) { @@ -76,8 +74,8 @@ static int write_param_info(IFparm **dst, const OsdiDescriptor *descr, * populating the SPICEdev struct with descriptor specific metadata and pointers * to the descriptor independent functions. * */ -static SPICEdev *osdi_init_descr(uint32_t id) { - const OsdiDescriptor *descr = registry[id].descriptor; +extern SPICEdev *osdi_create_spicedev(const OsdiRegistryEntry *entry) { + const OsdiDescriptor *descr = entry->descriptor; // allocate and fill terminal names array char **termNames = TMALLOC(char *, descr->num_terminals); @@ -88,31 +86,31 @@ static SPICEdev *osdi_init_descr(uint32_t id) { // allocate and fill instance params (and opvars) int *num_instance_para_names = TMALLOC(int, 1); for (uint32_t i = 0; i < descr->num_instance_params; i++) { - *num_instance_para_names += 1 + descr->param_opvar[i].num_alias; + *num_instance_para_names += (int) (1 + descr->param_opvar[i].num_alias); } for (uint32_t i = descr->num_params; i < descr->num_opvars + descr->num_params; i++) { - *num_instance_para_names += 1 + descr->param_opvar[i].num_alias; + *num_instance_para_names += (int) (1 + descr->param_opvar[i].num_alias); } - if (registry[id].dt != UINT32_MAX) { + if (entry->dt != UINT32_MAX) { *num_instance_para_names += 1; } - if (registry[id].temp != UINT32_MAX) { + if (entry->temp != UINT32_MAX) { *num_instance_para_names += 1; } IFparm *instance_para_names = TMALLOC(IFparm, *num_instance_para_names); IFparm *dst = instance_para_names; - if (registry[id].dt != UINT32_MAX) { - dst[0] = (IFparm){"dt", (int)registry[id].dt, IF_REAL | IF_SET, + if (entry->dt != UINT32_MAX) { + dst[0] = (IFparm){"dt", (int)entry->dt, IF_REAL | IF_SET, "Instance delta temperature"}; dst += 1; } - if (registry[id].temp != UINT32_MAX) { - dst[0] = (IFparm){"temp", (int)registry[id].temp, IF_REAL | IF_SET, + if (entry->temp != UINT32_MAX) { + dst[0] = (IFparm){"temp", (int)entry->temp, IF_REAL | IF_SET, "Instance temperature"}; dst += 1; } @@ -123,7 +121,7 @@ static SPICEdev *osdi_init_descr(uint32_t id) { // allocate and fill model params int *num_model_para_names = TMALLOC(int, 1); for (uint32_t i = descr->num_instance_params; i < descr->num_params; i++) { - *num_model_para_names += 1 + descr->param_opvar[i].num_alias; + *num_model_para_names += (int) (1 + descr->param_opvar[i].num_alias); } IFparm *model_para_names = TMALLOC(IFparm, *num_model_para_names); dst = model_para_names; @@ -144,10 +142,11 @@ static SPICEdev *osdi_init_descr(uint32_t id) { .instanceParms = instance_para_names, .numModelParms = num_model_para_names, .modelParms = model_para_names, - .flags = DEV_DEFAULT_CHECK | DEV_OSDI, + .flags = DEV_DEFAULT, + .registry_entry = (void*) entry, }; - size_t inst_off = registry[id].inst_offset; + size_t inst_off = entry->inst_offset; int *inst_size = TMALLOC(int, 1); *inst_size = @@ -171,11 +170,3 @@ static SPICEdev *osdi_init_descr(uint32_t id) { return OSDIinfo; } - -extern void osdi_get_info(uint32_t off, uint32_t num_descriptors) { - SPICEdev **dst = devices() + off; - registry_off = off; - for (uint32_t i = 0; i < num_descriptors; i++) { - dst[i] = osdi_init_descr(i); - } -} diff --git a/src/spicelib/devices/osdi/osdiload.c b/src/osdi/osdiload.c similarity index 97% rename from src/spicelib/devices/osdi/osdiload.c rename to src/osdi/osdiload.c index 986319fa0..09b920202 100644 --- a/src/spicelib/devices/osdi/osdiload.c +++ b/src/osdi/osdiload.c @@ -65,8 +65,8 @@ extern int OSDIload(GENmodel *inModel, CKTcircuit *ckt) { .names_str = sim_params_str, .vals_str = NULL}; - OsdiRegistryEntry entry = osdi_reg_entry_model(inModel); - const OsdiDescriptor *descr = entry.descriptor; + 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); diff --git a/src/spicelib/devices/osdi/osdiparam.c b/src/osdi/osdiparam.c similarity index 90% rename from src/spicelib/devices/osdi/osdiparam.c rename to src/osdi/osdiparam.c index eebc76811..fdf0b12e4 100644 --- a/src/spicelib/devices/osdi/osdiparam.c +++ b/src/osdi/osdiparam.c @@ -76,19 +76,19 @@ extern int OSDIparam(int param, IFvalue *value, GENinstance *instPtr, IFvalue *select) { NG_IGNORE(select); - OsdiRegistryEntry entry = osdi_reg_entry_inst(instPtr); - const OsdiDescriptor *descr = entry.descriptor; + OsdiRegistryEntry *entry = osdi_reg_entry_inst(instPtr); + const OsdiDescriptor *descr = entry->descriptor; if (param > (int)descr->num_instance_params) { // special handleing for temperature parameters OsdiExtraInstData *inst = osdi_extra_instance_data(entry, instPtr); - if (param == (int)entry.dt) { + if (param == (int)entry->dt) { inst->dt = value->rValue; inst->dt_given = true; return (OK); } - if (param == (int)entry.temp) { + if (param == (int)entry->temp) { inst->temp = value->rValue; inst->temp_given = true; return (OK); @@ -106,8 +106,8 @@ extern int OSDIparam(int param, IFvalue *value, GENinstance *instPtr, extern int OSDImParam(int param, IFvalue *value, GENmodel *modelPtr) { NG_IGNORE(select); - OsdiRegistryEntry entry = osdi_reg_entry_model(modelPtr); - const OsdiDescriptor *descr = entry.descriptor; + OsdiRegistryEntry *entry = osdi_reg_entry_model(modelPtr); + const OsdiDescriptor *descr = entry->descriptor; if (param > (int)descr->num_params || param < (int)descr->num_instance_params) { @@ -140,11 +140,11 @@ extern int OSDIask(CKTcircuit *ckt, GENinstance *instPtr, int id, NG_IGNORE(select); NG_IGNORE(ckt); - OsdiRegistryEntry entry = osdi_reg_entry_inst(instPtr); + OsdiRegistryEntry *entry = osdi_reg_entry_inst(instPtr); void *inst = osdi_instance_data(entry, instPtr); void *model = osdi_model_data_from_inst(instPtr); - const OsdiDescriptor *descr = entry.descriptor; + const OsdiDescriptor *descr = entry->descriptor; if (id > (int)(descr->num_params + descr->num_instance_params)) { return (E_BADPARM); diff --git a/src/osdi/osdiregistry.c b/src/osdi/osdiregistry.c new file mode 100644 index 000000000..1c8336e2b --- /dev/null +++ b/src/osdi/osdiregistry.c @@ -0,0 +1,372 @@ +/* + * Copyright© 2022 SemiMod UG. All rights reserved. + */ + +#include "ngspice/hash.h" +#include "ngspice/memory.h" +#include "ngspice/stringutil.h" +#include "osdidefs.h" + +#include + +#include "osdi.h" +#include +#include +#include +#include + +#if (!defined HAS_WINGUI) && (!defined __MINGW32__) && (!defined _MSC_VER) + +#include /* to load libraries*/ +#define OPENLIB(path) dlopen(path, RTLD_LAZY | RTLD_LOCAL) +#define GET_SYM(lib, sym) dlsym(lib, sym) +#define FREE_DLERR_MSG(msg) + +#else /* ifdef HAS_WINGUI */ + +#undef BOOLEAN +#include +#define OPENLIB(path) LoadLibrary(path) +#define GET_SYM(lib, sym) ((void *)GetProcAddress(lib, sym)) +char *dlerror(void); +#define FREE_DLERR_MSG(msg) free_dlerr_msg(msg) +static void free_dlerr_msg(char *msg); + +#endif /* ifndef HAS_WINGUI */ + +char *inputdir = NULL; + +/* Returns true if path is an absolute path and false if it is a + * relative path. No check is done for the existance of the path. */ +inline static bool is_absolute_pathname(const char *path) { +#ifdef _WIN32 + return !PathIsRelativeA(path); +#else + return path[0] == DIR_TERM; +#endif +} /* end of funciton is_absolute_pathname */ + +/*-------------------------------------------------------------------------* + Look up the variable sourcepath and try everything in the list in order + if the file isn't in . and it isn't an abs path name. + *-------------------------------------------------------------------------*/ + +static char *resolve_path(const char *name) { + struct stat st; + +#if defined(_WIN32) + + /* If variable 'mingwpath' is set: convert mingw /d/... to d:/... */ + if (cp_getvar("mingwpath", CP_BOOL, NULL, 0) && name[0] == DIR_TERM_LINUX && + isalpha_c(name[1]) && name[2] == DIR_TERM_LINUX) { + DS_CREATE(ds, 100); + if (ds_cat_str(&ds, name) != 0) { + fprintf(stderr, "Unable to copy string while resolving path"); + controlled_exit(EXIT_FAILURE); + } + char *const buf = ds_get_buf(&ds); + buf[0] = buf[1]; + buf[1] = ':'; + char *const resolved_path = inp_pathresolve(buf); + ds_free(&ds); + return resolved_path; + } + +#endif + + /* just try it */ + if (stat(name, &st) == 0) + return copy(name); + +#if !defined(EXT_ASC) && (defined(__MINGW32__) || defined(_MSC_VER)) + wchar_t wname[BSIZE_SP]; + if (MultiByteToWideChar(CP_UTF8, 0, name, -1, wname, + 2 * (int)strlen(name) + 1) == 0) { + fprintf(stderr, "UTF-8 to UTF-16 conversion failed with 0x%x\n", + GetLastError()); + fprintf(stderr, "%s could not be converted\n", name); + return NULL; + } + if (_waccess(wname, 0) == 0) + return copy(name); +#endif + + return (char *)NULL; +} /* end of function inp_pathresolve */ + +static char *resolve_input_path(const char *name) { + /* if name is an absolute path name, + * or if we haven't anything to prepend anyway + */ + if (is_absolute_pathname(name)) { + return resolve_path(name); + } + + if (name[0] == '~' && name[1] == '/') { + char *const y = cp_tildexpand(name); + if (y) { + char *const r = resolve_path(y); + txfree(y); + return r; + } + } + + /* + * If called from a script inputdir != NULL so try relativ to that dir + * Otherwise try relativ to the current workdir + */ + + if (inputdir) { + DS_CREATE(ds, 100); + int rc_ds = 0; + rc_ds |= ds_cat_str(&ds, inputdir); /* copy the dir name */ + const size_t n = ds_get_length(&ds); /* end of copied dir name */ + + /* Append a directory separator if not present already */ + const char ch_last = n > 0 ? inputdir[n - 1] : '\0'; + if (ch_last != DIR_TERM +#ifdef _WIN32 + && ch_last != DIR_TERM_LINUX +#endif + ) { + rc_ds |= ds_cat_char(&ds, DIR_TERM); + } + rc_ds |= ds_cat_str(&ds, name); /* append the file name */ + + if (rc_ds != 0) { + (void)fprintf(cp_err, "Unable to build \"dir\" path name " + "in inp_pathresolve_at"); + controlled_exit(EXIT_FAILURE); + } + + char *const r = resolve_path(ds_get_buf(&ds)); + ds_free(&ds); + return r; + } else { + DS_CREATE(ds, 100); + if (ds_cat_printf(&ds, ".%c%s", DIR_TERM, name) != 0) { + (void)fprintf(cp_err, + "Unable to build \".\" path name in inp_pathresolve_at"); + controlled_exit(EXIT_FAILURE); + } + char *const r = resolve_path(ds_get_buf(&ds)); + ds_free(&ds); + if (r != (char *)NULL) { + return r; + } + } + + return NULL; +} /* end of function inp_pathresolve_at */ + +/** + * Calculates the offset that the OSDI instance data has from the beginning of + * the instance data allocated by ngspice. This offset is non trivial because + * ngspice must store the terminal pointers before the remaining instance + * data. As a result the offset is not constant and a variable amount of + * padding must be inserted to ensure correct alginment. + */ +static size_t calc_osdi_instance_data_off(const OsdiDescriptor *descr) { + size_t res = sizeof(GENinstance) /* generic data */ + + descr->num_terminals * sizeof(int); + size_t padding = sizeof(max_align_t) - res % sizeof(max_align_t); + if (padding == sizeof(max_align_t)) { + padding = 0; + } + return res + padding; +} + +#define INVALID_OBJECT \ + (OsdiObjectFile) { .num_entries = -1 } + +#define EMPTY_OBJECT \ + (OsdiObjectFile) {} + +#define ERR_AND_RET \ + error = dlerror(); \ + printf("Error opening osdi lib \"%s\": %s\n", path, error); \ + FREE_DLERR_MSG(error); \ + return INVALID_OBJECT; + +#define STRINGIFY(x) #x +#define TOSTRING(x) STRINGIFY(x) + +#define GET_CONST(name, ty) \ + sym = GET_SYM(handle, STRINGIFY(name)); \ + if (!sym) { \ + ERR_AND_RET \ + } \ + const ty name = *((ty *)sym); + +#define GET_PTR(name, ty) \ + sym = GET_SYM(handle, STRINGIFY(name)); \ + if (!sym) { \ + ERR_AND_RET \ + } \ + const ty *name = (ty *)sym; + +static NGHASHPTR known_object_files = NULL; +#define DUMMYDATA ((void *)42) +/** + * Loads an object file from the hard drive with the platform equivalent of + * dlopen. This function checks that the OSDI version of the object file is + * valid and then writes all data into the `registry`. + * If any errors occur an appropriate message is written to errMsg + * + * @param PATH path A path to the shared object file + * @param uint32_t* len The amount of entries already written into `registry` + * @param uint32_t* capacity The amount of space available in `registry` + * before reallocation is required + * @returns -1 on error, 0 otherwise + */ +extern OsdiObjectFile load_object_file(const char *input) { + void *handle; + char *error; + const void *sym; + /* ensure the hashtable exists */ + if (!known_object_files) { + known_object_files = nghash_init_pointer(8); + } + const char *path = resolve_input_path(input); + if (!path) { + printf("Error opening osdi lib \"%s\": No such file or directory!\n", input); + FREE_DLERR_MSG(error); + return INVALID_OBJECT; + } + + handle = OPENLIB(path); + if (!handle) { + ERR_AND_RET + } + + /* Keep track of loaded shared object files to avoid loading the same model + * multiple times. We use the handle as a key because the same SO will always + * return the SAME pointer as long as dlclose is not called. + * nghash_insert returns NULL if the key (handle) was not already in the table + * and the data (DUMMYDATA) that was previously insered (!= NULL) otherwise*/ + if (nghash_insert(known_object_files, handle, DUMMYDATA)) { + return EMPTY_OBJECT; + } + + GET_CONST(OSDI_VERSION_MAJOR, uint32_t); + GET_CONST(OSDI_VERSION_MINOR, uint32_t); + + if (OSDI_VERSION_MAJOR != OSDI_VERSION_MAJOR_CURR || + OSDI_VERSION_MINOR != OSDI_VERSION_MINOR_CURR) { + printf("NGSPICE only supports OSDI v%d.%d but \"%s\" targets v%d.%d!", + OSDI_VERSION_MAJOR_CURR, OSDI_VERSION_MINOR_CURR, path, + OSDI_VERSION_MAJOR, OSDI_VERSION_MINOR); + return INVALID_OBJECT; + } + + GET_CONST(OSDI_NUM_DESCRIPTORS, uint32_t); + GET_PTR(OSDI_DESCRIPTORS, OsdiDescriptor); + + OsdiRegistryEntry *dst = TMALLOC(OsdiRegistryEntry, OSDI_NUM_DESCRIPTORS); + + for (uint32_t i = 0; i < OSDI_NUM_DESCRIPTORS; i++) { + const OsdiDescriptor *descr = &OSDI_DESCRIPTORS[i]; + + uint32_t dt = descr->num_params + descr->num_opvars; + uint32_t temp = descr->num_params + descr->num_opvars + 1; + for (uint32_t param_id = 0; param_id < descr->num_params; param_id++) { + OsdiParamOpvar *param = &descr->param_opvar[param_id]; + for (uint32_t j = 0; j < 1 + param->num_alias; j++) { + char *name = param->name[j]; + if (!strcmp(name, "dt")) { + dt = UINT32_MAX; + } else if (!strcasecmp(name, "dtemp") || !strcasecmp(name, "dt")) { + dt = param_id; + } else if (!strcmp(name, "temp")) { + temp = UINT32_MAX; + } else if (!strcasecmp(name, "temp") || + !strcasecmp(name, "temperature")) { + temp = param_id; + } + } + } + + size_t inst_off = calc_osdi_instance_data_off(descr); + dst[i] = (OsdiRegistryEntry){ + .descriptor = descr, + .inst_offset = (uint32_t)inst_off, + .dt = dt, + .temp = temp, + }; + } + + return (OsdiObjectFile){ + .entrys = dst, + .num_entries = (int)OSDI_NUM_DESCRIPTORS, + }; +} + +inline size_t osdi_instance_data_off(const OsdiRegistryEntry *entry) { + return entry->inst_offset; +} + +inline void *osdi_instance_data(const OsdiRegistryEntry *entry, + GENinstance *inst) { + return (void *)(((char *)inst) + osdi_instance_data_off(entry)); +} + +inline OsdiExtraInstData * +osdi_extra_instance_data(const OsdiRegistryEntry *entry, GENinstance *inst) { + OsdiDescriptor *descr = (OsdiDescriptor *)entry->descriptor; + return (OsdiExtraInstData *)(((char *)inst) + entry->inst_offset + + descr->instance_size); +} + +inline size_t osdi_model_data_off(void) { + return offsetof(OsdiModelData, data); +} + +inline void *osdi_model_data(GENmodel *model) { + return (void *)&((OsdiModelData *)model)->data; +} + +inline void *osdi_model_data_from_inst(GENinstance *inst) { + return osdi_model_data(inst->GENmodPtr); +} + +inline OsdiRegistryEntry *osdi_reg_entry_model(const GENmodel *model) { + return (OsdiRegistryEntry *)ft_sim->devices[model->GENmodType] + ->registry_entry; +} + +inline OsdiRegistryEntry *osdi_reg_entry_inst(const GENinstance *inst) { + return osdi_reg_entry_model(inst->GENmodPtr); +} + +#if defined(__MINGW32__) || defined(HAS_WINGUI) || defined(_MSC_VER) + +/* For reporting error message if formatting fails */ +static const char errstr_fmt[] = + "Unable to find message in dlerr(). System code = %lu"; +static char errstr[sizeof errstr_fmt - 3 + 3 * sizeof(unsigned long)]; + +char *dlerror(void) { + LPVOID lpMsgBuf; + + DWORD rc = FormatMessage( + FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | + FORMAT_MESSAGE_IGNORE_INSERTS, + NULL, GetLastError(), MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), + (LPTSTR)&lpMsgBuf, 0, NULL); + + if (rc == 0) { /* FormatMessage failed */ + (void)sprintf(errstr, errstr_fmt, (unsigned long)GetLastError()); + return errstr; + } + + return lpMsgBuf; /* Return the formatted message */ +} /* end of function dlerror */ + +/* Free message related to dynamic loading */ +static void free_dlerr_msg(char *msg) { + if (msg != errstr) { /* msg is an allocation */ + LocalFree(msg); + } +} /* end of function free_dlerr_msg */ + +#endif /* Windows emulation of dlerr */ diff --git a/src/spicelib/devices/osdi/osdisetup.c b/src/osdi/osdisetup.c similarity index 95% rename from src/spicelib/devices/osdi/osdisetup.c rename to src/osdi/osdisetup.c index a86c9e474..747eff132 100644 --- a/src/spicelib/devices/osdi/osdisetup.c +++ b/src/osdi/osdisetup.c @@ -172,8 +172,8 @@ int OSDIsetup(SMPmatrix *matrix, GENmodel *inModel, CKTcircuit *ckt, GENinstance *gen_inst; int err; - OsdiRegistryEntry entry = osdi_reg_entry_model(inModel); - const OsdiDescriptor *descr = entry.descriptor; + OsdiRegistryEntry *entry = osdi_reg_entry_model(inModel); + const OsdiDescriptor *descr = entry->descriptor; /* setup a temporary buffer */ uint32_t *node_ids = TMALLOC(uint32_t, descr->num_nodes); @@ -280,8 +280,8 @@ extern int OSDItemp(GENmodel *inModel, CKTcircuit *ckt) { int res; GENinstance *gen_inst; - OsdiRegistryEntry entry = osdi_reg_entry_model(inModel); - const OsdiDescriptor *descr = entry.descriptor; + OsdiRegistryEntry *entry = osdi_reg_entry_model(inModel); + const OsdiDescriptor *descr = entry->descriptor; for (gen_model = inModel; gen_model != NULL; gen_model = gen_model->GENnextModel) { @@ -332,8 +332,8 @@ extern int OSDIunsetup(GENmodel *inModel, CKTcircuit *ckt) { GENinstance *gen_inst; int num; - OsdiRegistryEntry entry = osdi_reg_entry_model(inModel); - const OsdiDescriptor *descr = entry.descriptor; + OsdiRegistryEntry *entry = osdi_reg_entry_model(inModel); + const OsdiDescriptor *descr = entry->descriptor; for (gen_model = inModel; gen_model != NULL; gen_model = gen_model->GENnextModel) { @@ -342,6 +342,11 @@ extern int OSDIunsetup(GENmodel *inModel, CKTcircuit *ckt) { gen_inst = gen_inst->GENnextInstance) { void *inst = osdi_instance_data(entry, gen_inst); + // reset is collapsible + bool *is_collapsible = + (bool *)(((char *)inst) + descr->is_collapsible_offset); + memset(is_collapsible, 0, sizeof(bool) * descr->num_collapsible); + uint32_t *node_mapping = (uint32_t *)(((char *)inst) + descr->node_mapping_offset); for (uint32_t i = 0; i < descr->num_nodes; i++) { diff --git a/src/spicelib/devices/Makefile.am b/src/spicelib/devices/Makefile.am index 80dc9830f..bc6674611 100644 --- a/src/spicelib/devices/Makefile.am +++ b/src/spicelib/devices/Makefile.am @@ -28,7 +28,6 @@ SUBDIRS = \ hfet1 \ hfet2 \ hicum2 \ - osdi \ hisim2 \ hisimhv1 \ hisimhv2 \ @@ -64,7 +63,6 @@ SUBDIRS += nbjt nbjt2 numd numd2 numos endif DIST_SUBDIRS = \ - osdi \ asrc \ bjt \ bsim1 \ diff --git a/src/spicelib/devices/dev.c b/src/spicelib/devices/dev.c index e50984737..5dbb01210 100644 --- a/src/spicelib/devices/dev.c +++ b/src/spicelib/devices/dev.c @@ -27,25 +27,21 @@ * HAVE NO OBLIGATIONS TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, * ENHANCEMENTS, OR MODIFICATIONS. */ -#include "ngspice/ngspice.h" #include "assert.h" +#include "ngspice/ngspice.h" -#include "ngspice/iferrmsg.h" #include "ngspice/devdefs.h" #include "ngspice/ifsim.h" #include "dev.h" #include "ngspice/memory.h" /* to alloc, realloc devices*/ -#include "osdi/osdiitf.h" - - #ifdef XSPICE /*saj headers for xspice*/ #include /* for strcpy, strcat*/ #if (!defined HAS_WINGUI) && (!defined __MINGW32__) && (!defined _MSC_VER) #include /* to load libraries*/ -typedef void * funptr_t; +typedef void *funptr_t; #define FREE_DLERR_MSG(msg) #else /* ifdef HAS_WINGUI */ #undef BOOLEAN @@ -56,32 +52,35 @@ funptr_t dlsym(void *, const char *); char *dlerror(void); #define FREE_DLERR_MSG(msg) free_dlerr_msg(msg) static void free_dlerr_msg(char *msg); -#define RTLD_LAZY 1 /* lazy function call binding */ -#define RTLD_NOW 2 /* immediate function call binding */ -#define RTLD_GLOBAL 4 /* symbols in this dlopen'ed obj are visible to other - * dlopen'ed objs */ +#define RTLD_LAZY 1 /* lazy function call binding */ +#define RTLD_NOW 2 /* immediate function call binding */ +#define RTLD_GLOBAL \ + 4 /* symbols in this dlopen'ed obj are visible to other \ + * dlopen'ed objs */ #endif /* ifndef HAS_WINGUI */ #include "ngspice/dllitf.h" /* the coreInfo Structure*/ #include "ngspice/evtudn.h" /*Use defined nodes */ -Evt_Udn_Info_t **g_evt_udn_info = NULL; +Evt_Udn_Info_t **g_evt_udn_info = NULL; int g_evt_num_udn_types = 0; /*The digital node type */ extern Evt_Udn_Info_t idn_digital_info; int add_device(int n, SPICEdev **devs, int flag); -int add_udn(int,Evt_Udn_Info_t **); +int add_udn(int, Evt_Udn_Info_t **); -extern struct coreInfo_t coreInfo; /* cmexport.c */ +extern struct coreInfo_t coreInfo; /* cmexport.c */ #endif - #include "asrc/asrcitf.h" #include "bjt/bjtitf.h" #include "bsim1/bsim1itf.h" #include "bsim2/bsim2itf.h" #include "bsim3/bsim3itf.h" +#include "bsim3soi_dd/b3soidditf.h" +#include "bsim3soi_fd/b3soifditf.h" +#include "bsim3soi_pd/b3soipditf.h" #include "bsim3v0/bsim3v0itf.h" #include "bsim3v1/bsim3v1itf.h" #include "bsim3v32/bsim3v32itf.h" @@ -89,13 +88,11 @@ extern struct coreInfo_t coreInfo; /* cmexport.c */ #include "bsim4v5/bsim4v5itf.h" #include "bsim4v6/bsim4v6itf.h" #include "bsim4v7/bsim4v7itf.h" -#include "bsim3soi_pd/b3soipditf.h" -#include "bsim3soi_fd/b3soifditf.h" -#include "bsim3soi_dd/b3soidditf.h" #include "bsimsoi/b4soiitf.h" #include "cap/capitf.h" #include "cccs/cccsitf.h" #include "ccvs/ccvsitf.h" +#include "cpl/cplitf.h" #include "csw/cswitf.h" #include "dio/dioitf.h" #include "hfet1/hfetitf.h" @@ -116,7 +113,6 @@ extern struct coreInfo_t coreInfo; /* cmexport.c */ #include "mos3/mos3itf.h" #include "mos6/mos6itf.h" #include "mos9/mos9itf.h" -#include "cpl/cplitf.h" #include "res/resitf.h" #include "soi3/soi3itf.h" #include "sw/switf.h" @@ -126,16 +122,16 @@ extern struct coreInfo_t coreInfo; /* cmexport.c */ #include "vbic/vbicitf.h" #include "vccs/vccsitf.h" #include "vcvs/vcvsitf.h" -#include "vsrc/vsrcitf.h" #include "vdmos/vdmositf.h" +#include "vsrc/vsrcitf.h" #ifdef ADMS -#include "adms/hicum0/hicum0itf.h" -#include "adms/mextram/bjt504titf.h" -#include "adms/ekv/ekvitf.h" -#include "adms/psp102/psp102itf.h" -#include "adms/psp103/psp103itf.h" #include "adms/bsimbulk/bsimbulkitf.h" #include "adms/bsimcmg/bsimcmgitf.h" +#include "adms/ekv/ekvitf.h" +#include "adms/hicum0/hicum0itf.h" +#include "adms/mextram/bjt504titf.h" +#include "adms/psp102/psp102itf.h" +#include "adms/psp103/psp103itf.h" #include "adms/r2_cmc/r2_cmcitf.h" #endif #ifdef CIDER @@ -214,14 +210,14 @@ static SPICEdev *(*static_devices[])(void) = { #endif #ifdef ADMS - (SPICEdev *(*)(void)) get_hicum0_info, - (SPICEdev *(*)(void)) get_bjt504t_info, - (SPICEdev *(*)(void)) get_ekv_info, - (SPICEdev *(*)(void)) get_psp102_info, - (SPICEdev *(*)(void)) get_psp103_info, - (SPICEdev *(*)(void)) get_bsimbulk_info, - (SPICEdev *(*)(void)) get_bsimcmg_info, - (SPICEdev *(*)(void)) get_r2_cmc_info, + (SPICEdev * (*)(void)) get_hicum0_info, + (SPICEdev * (*)(void)) get_bjt504t_info, + (SPICEdev * (*)(void)) get_ekv_info, + (SPICEdev * (*)(void)) get_psp102_info, + (SPICEdev * (*)(void)) get_psp103_info, + (SPICEdev * (*)(void)) get_bsimbulk_info, + (SPICEdev * (*)(void)) get_bsimcmg_info, + (SPICEdev * (*)(void)) get_r2_cmc_info, #endif #ifdef NDEV @@ -233,99 +229,84 @@ static SPICEdev *(*static_devices[])(void) = { static int DEVNUM = NUMELEMS(static_devices); /*Make this dynamic for later attempt to make all devices dynamic*/ -SPICEdev **DEVices=NULL; +SPICEdev **DEVices = NULL; /*Flag to indicate what device type it is, *0 = normal spice device *1 = xspice device */ #ifdef XSPICE -int *DEVicesfl=NULL; -int DEVflag(int type){ - if(type < DEVNUM && type >= 0) +int *DEVicesfl = NULL; +int DEVflag(int type) { + if (type < DEVNUM && type >= 0) return DEVicesfl[type]; else return -1; } #endif - - -void -spice_destroy_devices(void) -{ +void spice_destroy_devices(void) { #ifdef XSPICE - tfree(g_evt_udn_info); - tfree(DEVicesfl); + tfree(g_evt_udn_info); + tfree(DEVicesfl); #endif - tfree(DEVices); - DEVNUM = 0; + tfree(DEVices); + DEVNUM = 0; } - -void -spice_init_devices(void) -{ - int i; - /* Safeguard against double initialization */ - DEVNUM = NUMELEMS(static_devices); +void spice_init_devices(void) { + int i; + /* Safeguard against double initialization */ + DEVNUM = NUMELEMS(static_devices); #ifdef XSPICE - /* Initialize the structs and add digital node type */ - g_evt_udn_info = TMALLOC(Evt_Udn_Info_t *, 1); - g_evt_num_udn_types = 1; - g_evt_udn_info[0] = &idn_digital_info; + /* Initialize the structs and add digital node type */ + g_evt_udn_info = TMALLOC(Evt_Udn_Info_t *, 1); + g_evt_num_udn_types = 1; + g_evt_udn_info[0] = &idn_digital_info; - DEVicesfl = TMALLOC(int, DEVNUM); - /* tmalloc should automatically zero the array! */ + DEVicesfl = TMALLOC(int, DEVNUM); + /* tmalloc should automatically zero the array! */ #endif - // load the object files and allocate additional space for OSDI devices - // this could also be done later with realloc - int num_osdi_devices = osdi_load_devices(); - if (num_osdi_devices < 0) { - // TODO error handeling - printf("FATAL error during osdi device load\n %s\n", errMsg); - exit(1); - } - DEVices = TMALLOC(SPICEdev *, DEVNUM + num_osdi_devices); + DEVices = TMALLOC(SPICEdev *, DEVNUM); - for (i = 0; i < DEVNUM; i++) - DEVices[i] = static_devices[i](); - - osdi_get_info((uint32_t)DEVNUM, (uint32_t)num_osdi_devices); - DEVNUM += num_osdi_devices; + for (i = 0; i < DEVNUM; i++) + DEVices[i] = static_devices[i](); } -int num_devices(void) -{ - return DEVNUM; -} +int num_devices(void) { return DEVNUM; } -IFdevice ** devices_ptr(void) -{ - return (IFdevice **) DEVices; -} - -SPICEdev ** devices(void) -{ - return DEVices; -} +IFdevice **devices_ptr(void) { return (IFdevice **)DEVices; } +SPICEdev **devices(void) { return DEVices; } #ifdef DEVLIB /*not yet usable*/ #ifdef ADMS -#define DEVICES_USED {"asrc", "bjt", "vbic", "bsim1", "bsim2", "bsim3", "bsim3v32", "bsim3v2", "bsim3v1", "bsim4", "bsim4v5", "bsim4v6", "bsim4v7", \ - "bsim4soi", "bsim3soipd", "bsim3soifd", "bsim3soidd", "hisim2", "hisimhv1", "hisimhv2", \ - "cap", "cccs", "ccvs", "csw", "dio", "hfet", "hfet2", "ind", "isrc", "jfet", "ltra", "mes", "mesa" ,"mos1", "mos2", "mos3", \ - "mos6", "mos9", "res", "soi3", "sw", "tra", "urc", "vccs", "vcvs", "vsrc", "hicum0", "bjt504t", "ekv", "psp102", "psp103", "bsimbulk", "bsimcmg"} +#define DEVICES_USED \ + { \ + "asrc", "bjt", "vbic", "bsim1", "bsim2", "bsim3", "bsim3v32", "bsim3v2", \ + "bsim3v1", "bsim4", "bsim4v5", "bsim4v6", "bsim4v7", "bsim4soi", \ + "bsim3soipd", "bsim3soifd", "bsim3soidd", "hisim2", "hisimhv1", \ + "hisimhv2", "cap", "cccs", "ccvs", "csw", "dio", "hfet", "hfet2", \ + "ind", "isrc", "jfet", "ltra", "mes", "mesa", "mos1", "mos2", "mos3", \ + "mos6", "mos9", "res", "soi3", "sw", "tra", "urc", "vccs", "vcvs", \ + "vsrc", "hicum0", "bjt504t", "ekv", "psp102", "psp103", "bsimbulk", \ + "bsimcmg" \ + } #else -#define DEVICES_USED {"asrc", "bjt", "vbic", "bsim1", "bsim2", "bsim3", "bsim3v32", "bsim3v2", "bsim3v1", "bsim4", "bsim4v5", "bsim4v6", "bsim4v7", \ - "bsim4soi", "bsim3soipd", "bsim3soifd", "bsim3soidd", "hisim2", "hisimhv1", "hisimhv2", \ - "cap", "cccs", "ccvs", "csw", "dio", "hfet", "hfet2", "ind", "isrc", "jfet", "ltra", "mes", "mesa" ,"mos1", "mos2", "mos3", \ - "mos6", "mos9", "res", "soi3", "sw", "tra", "urc", "vccs", "vcvs", "vsrc", "hicum2"} +#define DEVICES_USED \ + { \ + "asrc", "bjt", "vbic", "bsim1", "bsim2", "bsim3", "bsim3v32", "bsim3v2", \ + "bsim3v1", "bsim4", "bsim4v5", "bsim4v6", "bsim4v7", "bsim4soi", \ + "bsim3soipd", "bsim3soifd", "bsim3soidd", "hisim2", "hisimhv1", \ + "hisimhv2", "cap", "cccs", "ccvs", "csw", "dio", "hfet", "hfet2", \ + "ind", "isrc", "jfet", "ltra", "mes", "mesa", "mos1", "mos2", "mos3", \ + "mos6", "mos9", "res", "soi3", "sw", "tra", "urc", "vccs", "vcvs", \ + "vsrc", "hicum2" \ + } #endif int load_dev(char *name) { char *msg; @@ -335,57 +316,54 @@ int load_dev(char *name) { SPICEdev *device; strcpy(libname, "lib"); - strcat(libname,name); - strcat(libname,".so"); + strcat(libname, name); + strcat(libname, ".so"); - lib = dlopen(libname,RTLD_NOW); - if(!lib){ + lib = dlopen(libname, RTLD_NOW); + if (!lib) { msg = dlerror(); printf("%s\n", msg); return 1; } strcpy(libname, "get_"); - strcat(libname,name); - strcat(libname,"_info"); - fetch = dlsym(lib,libname); + strcat(libname, name); + strcat(libname, "_info"); + fetch = dlsym(lib, libname); - if(!fetch){ + if (!fetch) { msg = dlerror(); printf("%s\n", msg); return 1; } - device = ((SPICEdev * (*)(void)) fetch) (); - add_device(1,&device,0); + device = ((SPICEdev * (*)(void)) fetch)(); + add_device(1, &device, 0); return 0; } -void load_alldevs(void){ +void load_alldevs(void) { char *devs[] = DEVICES_USED; int num = NUMELEMS(devs); int i; - for(i=0; i< num;i++) + for (i = 0; i < num; i++) load_dev(devs[i]); return; } #endif -/*-------------------- XSPICE additions below ----------------------*/ -#ifdef XSPICE -#include "ngspice/mif.h" -#include "ngspice/cm.h" -#include "ngspice/cpextern.h" -#include "ngspice/fteext.h" /* for ft_sim */ +#if defined(XSPICE) || defined(OSDI) + #include "ngspice/cktdefs.h" /* for DEVmaxnum */ +#include "ngspice/fteext.h" /* for ft_sim */ static void relink(void) { -/* - * This replacement done by SDB on 6.11.2003 - * - * ft_sim->numDevices = num_devices(); - * DEVmaxnum = num_devices(); - */ + /* + * This replacement done by SDB on 6.11.2003 + * + * ft_sim->numDevices = num_devices(); + * DEVmaxnum = num_devices(); + */ ft_sim->numDevices = DEVNUM; DEVmaxnum = DEVNUM; @@ -393,190 +371,203 @@ static void relink(void) { return; } -int add_device(int n, SPICEdev **devs, int flag){ +#endif + +/*-------------------- XSPICE additions below ----------------------*/ +#ifdef XSPICE +#include "ngspice/cm.h" +#include "ngspice/cpextern.h" +#include "ngspice/mif.h" +int add_device(int n, SPICEdev **devs, int flag) { int i; int dnum = DEVNUM + n; DEVices = TREALLOC(SPICEdev *, DEVices, dnum); DEVicesfl = TREALLOC(int, DEVicesfl, dnum); - for(i = 0; i < n;i++){ + for (i = 0; i < n; i++) { #ifdef TRACE - printf("Added device: %s\n",devs[i]->DEVpublic.name); + printf("Added device: %s\n", devs[i]->DEVpublic.name); #endif - DEVices[DEVNUM+i] = devs[i]; + DEVices[DEVNUM + i] = devs[i]; - DEVices[DEVNUM+i]->DEVinstSize = &MIFiSize; - DEVices[DEVNUM+i]->DEVmodSize = &MIFmSize; + DEVices[DEVNUM + i]->DEVinstSize = &MIFiSize; + DEVices[DEVNUM + i]->DEVmodSize = &MIFmSize; - DEVicesfl[DEVNUM+i] = flag; + DEVicesfl[DEVNUM + i] = flag; } DEVNUM += n; relink(); return 0; } -int add_udn(int n,Evt_Udn_Info_t **udns){ +int add_udn(int n, Evt_Udn_Info_t **udns) { int i; int utypes = g_evt_num_udn_types + n; - g_evt_udn_info = TREALLOC(Evt_Udn_Info_t *, g_evt_udn_info, utypes); - for(i = 0; i < n;i++){ + g_evt_udn_info = TREALLOC(Evt_Udn_Info_t *, g_evt_udn_info, utypes); + for (i = 0; i < n; i++) { #ifdef TRACE - printf("Added udn: %s\n",udns[i]->name); + printf("Added udn: %s\n", udns[i]->name); #endif - g_evt_udn_info[g_evt_num_udn_types+i] = udns[i]; + g_evt_udn_info[g_evt_num_udn_types + i] = udns[i]; } g_evt_num_udn_types += n; return 0; } +int load_opus(const char *name) { + void *lib; + char *msg; + int num; + SPICEdev **devs; + Evt_Udn_Info_t **udns; + funptr_t fetch; -int load_opus(const char *name) -{ - void *lib; - char *msg; - int num; - SPICEdev **devs; - Evt_Udn_Info_t **udns; - funptr_t fetch; + lib = dlopen(name, RTLD_NOW); + if (!lib) { + msg = dlerror(); + printf("Error opening code model \"%s\": %s\n", name, msg); + FREE_DLERR_MSG(msg); + return 1; + } - lib = dlopen(name, RTLD_NOW); - if (!lib) { - msg = dlerror(); - printf("Error opening code model \"%s\": %s\n", name, msg); - FREE_DLERR_MSG(msg); - return 1; + /* Get code models defined by the library */ + if ((fetch = dlsym(lib, "CMdevNum")) != (funptr_t)NULL) { + num = *(*(int *(*)(void))fetch)(); + fetch = dlsym(lib, "CMdevs"); + if (fetch != (funptr_t)NULL) { + devs = (*(SPICEdev * *(*)(void)) fetch)(); + } else { + msg = dlerror(); + printf("Error getting the list of devices: %s\n", msg); + FREE_DLERR_MSG(msg); + return 1; } + } else { + msg = dlerror(); + printf("Error finding the number of devices: %s\n", msg); + FREE_DLERR_MSG(msg); + return 1; + } - - /* Get code models defined by the library */ - if ((fetch = dlsym(lib, "CMdevNum")) != (funptr_t) NULL) { - num = *(*(int * (*)(void)) fetch)(); - fetch = dlsym(lib, "CMdevs"); - if (fetch != (funptr_t) NULL) { - devs = (*(SPICEdev ** (*)(void)) fetch)(); - } - else { - msg = dlerror(); - printf("Error getting the list of devices: %s\n", - msg); - FREE_DLERR_MSG(msg); - return 1; - } - } - else { - msg = dlerror(); - printf("Error finding the number of devices: %s\n", msg); - FREE_DLERR_MSG(msg); - return 1; - } - - add_device(num, devs, 1); + add_device(num, devs, 1); #ifdef TRACE - printf("Got %d devices.\n", num); + printf("Got %d devices.\n", num); #endif - - /* Get user-defined ndes defined by the library */ - if ((fetch = dlsym(lib, "CMudnNum")) != (funptr_t) NULL) { - num = *(*(int * (*)(void)) fetch)(); - fetch = dlsym(lib, "CMudns"); - if (fetch != (funptr_t) NULL) { - udns = (*(Evt_Udn_Info_t ** (*)(void)) fetch)(); - } - else { - msg = dlerror(); - printf("Error getting the list of user-defined types: %s\n", - msg); - FREE_DLERR_MSG(msg); - return 1; - } - } - else { - msg = dlerror(); - printf("Error finding the number of user-defined types: %s\n", msg); - FREE_DLERR_MSG(msg); - return 1; + /* Get user-defined ndes defined by the library */ + if ((fetch = dlsym(lib, "CMudnNum")) != (funptr_t)NULL) { + num = *(*(int *(*)(void))fetch)(); + fetch = dlsym(lib, "CMudns"); + if (fetch != (funptr_t)NULL) { + udns = (*(Evt_Udn_Info_t * *(*)(void)) fetch)(); + } else { + msg = dlerror(); + printf("Error getting the list of user-defined types: %s\n", msg); + FREE_DLERR_MSG(msg); + return 1; } + } else { + msg = dlerror(); + printf("Error finding the number of user-defined types: %s\n", msg); + FREE_DLERR_MSG(msg); + return 1; + } - add_udn(num, udns); + add_udn(num, udns); #ifdef TRACE - printf("Got %d udns.\n", num); + printf("Got %d udns.\n", num); #endif - /* Give the code model access to facilities provided by ngspice. */ - if ((fetch = dlsym(lib,"CMgetCoreItfPtr")) != (funptr_t) NULL) { - const struct coreInfo_t ** const core = - (const struct coreInfo_t **const) - (*(struct coreInfo_t ** (*)(void)) fetch)(); - *core = &coreInfo; - } - else { - msg = dlerror(); - printf("Error getting interface pointer: %s\n", msg); - FREE_DLERR_MSG(msg); - return 1; - } + /* Give the code model access to facilities provided by ngspice. */ + if ((fetch = dlsym(lib, "CMgetCoreItfPtr")) != (funptr_t)NULL) { + const struct coreInfo_t **const core = (const struct coreInfo_t **const)(*( + struct coreInfo_t * *(*)(void)) fetch)(); + *core = &coreInfo; + } else { + msg = dlerror(); + printf("Error getting interface pointer: %s\n", msg); + FREE_DLERR_MSG(msg); + return 1; + } - return 0; + return 0; } /* end of function load_opus */ - - #if defined(__MINGW32__) || defined(HAS_WINGUI) || defined(_MSC_VER) /* For reporting error message if formatting fails */ static const char errstr_fmt[] = - "Unable to find message in dlerr(). System code = %lu"; + "Unable to find message in dlerr(). System code = %lu"; static char errstr[sizeof errstr_fmt - 3 + 3 * sizeof(unsigned long)]; /* Emulations of POSIX dlopen(), dlsym(), and dlerror(). */ -void *dlopen(const char *name, int type) -{ - NG_IGNORE(type); - return LoadLibrary(name); +void *dlopen(const char *name, int type) { + NG_IGNORE(type); + return LoadLibrary(name); } -funptr_t dlsym(void *hDll, const char *funcname) -{ - return GetProcAddress(hDll, funcname); +funptr_t dlsym(void *hDll, const char *funcname) { + return GetProcAddress(hDll, funcname); } -char *dlerror(void) -{ - LPVOID lpMsgBuf; +char *dlerror(void) { + LPVOID lpMsgBuf; - DWORD rc = FormatMessage( - FORMAT_MESSAGE_ALLOCATE_BUFFER | - FORMAT_MESSAGE_FROM_SYSTEM | - FORMAT_MESSAGE_IGNORE_INSERTS, - NULL, - GetLastError(), - MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), - (LPTSTR) &lpMsgBuf, - 0, - NULL - ); + DWORD rc = FormatMessage( + FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | + FORMAT_MESSAGE_IGNORE_INSERTS, + NULL, GetLastError(), MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), + (LPTSTR)&lpMsgBuf, 0, NULL); - if (rc == 0) { /* FormatMessage failed */ - (void) sprintf(errstr, errstr_fmt, (unsigned long) GetLastError()); - return errstr; - } + if (rc == 0) { /* FormatMessage failed */ + (void)sprintf(errstr, errstr_fmt, (unsigned long)GetLastError()); + return errstr; + } - return lpMsgBuf; /* Return the formatted message */ + return lpMsgBuf; /* Return the formatted message */ } /* end of function dlerror */ - - /* Free message related to dynamic loading */ -static void free_dlerr_msg(char *msg) -{ - if (msg != errstr) { /* msg is an allocation */ - LocalFree(msg); - } +static void free_dlerr_msg(char *msg) { + if (msg != errstr) { /* msg is an allocation */ + LocalFree(msg); + } } /* end of function free_dlerr_msg */ - - #endif /* Windows emulation of dlopen, dlsym, and dlerr */ #endif /*-------------------- end of XSPICE additions ----------------------*/ + +#ifdef OSDI + +#include "ngspice/osdiitf.h" + +static int add_device(int n, OsdiRegistryEntry *devs) { + int i; + int dnum = DEVNUM + n; + DEVices = TREALLOC(SPICEdev *, DEVices, dnum); +#ifdef XSPICE + DEVicesfl = TREALLOC(int, DEVicesfl, dnum); +#endif + for (i = 0; i < n; i++) { +#ifdef TRACE + printf("Added device: %s\n", devs[i]->DEVpublic.name); +#endif + DEVices[DEVNUM + i] = osdi_create_spicedev(&devs[i]); + } + DEVNUM += n; + relink(); + return 0; +} + +int load_osdi(const char *path) { + OsdiObjectFile file = load_object_file(path); + if (file.num_entries < 0) { + return file.num_entries; + } + + add_device(file.num_entries, file.entrys); + return 0; +} + +#endif diff --git a/src/spicelib/devices/dev.h b/src/spicelib/devices/dev.h index 3356d04b7..e4ec3f1bf 100644 --- a/src/spicelib/devices/dev.h +++ b/src/spicelib/devices/dev.h @@ -15,5 +15,9 @@ int DEVflag(int type); void load_alldevs(void); int load_dev(char *name); #endif + +#ifdef OSDI +int load_osdi(const char *); +#endif #endif diff --git a/src/spicelib/devices/osdi/osdidefs.h b/src/spicelib/devices/osdi/osdidefs.h deleted file mode 100644 index af078667b..000000000 --- a/src/spicelib/devices/osdi/osdidefs.h +++ /dev/null @@ -1,80 +0,0 @@ -/* - * Copyright© 2022 SemiMod UG. All rights reserved. - */ - -#pragma once - -#include "ngspice/cktdefs.h" -#include "ngspice/complex.h" -#include "ngspice/gendefs.h" -#include "ngspice/ifsim.h" -#include "ngspice/ngspice.h" -#include "ngspice/noisedef.h" -#include "ngspice/typedefs.h" - -#include "osdi.h" -#include "osdiext.h" - -#include "stddef.h" -#include -#include - -typedef struct OsdiModelData { - GENmodel gen; - max_align_t data; -} OsdiModelData; - -typedef struct OsdiExtraInstData { - double dt; - double temp; - bool temp_given; - bool dt_given; - bool lim; - bool finish; - -} __attribute__((aligned(sizeof(max_align_t)))) OsdiExtraInstData; - -typedef struct OsdiRegistryEntry { - const OsdiDescriptor *descriptor; - uint32_t inst_offset; - uint32_t dt; - uint32_t temp; -} OsdiRegistryEntry; - -extern OsdiRegistryEntry *registry; -extern uint32_t registry_off; - -inline size_t osdi_instance_data_off(OsdiRegistryEntry entry) { - return entry.inst_offset; -} -inline void *osdi_instance_data(OsdiRegistryEntry entry, GENinstance *inst) { - return (void *)(((char *)inst) + osdi_instance_data_off(entry)); -} -inline OsdiExtraInstData *osdi_extra_instance_data(OsdiRegistryEntry entry, - GENinstance *inst) { - return (OsdiExtraInstData *)(((char *)inst) + entry.inst_offset + - entry.descriptor->instance_size); -} - -inline size_t osdi_model_data_off() { return offsetof(OsdiModelData, data); } - -inline void *osdi_model_data(GENmodel *model) { - return (void *)&((OsdiModelData *)model)->data; -} - -inline void *osdi_model_data_from_inst(GENinstance *inst) { - return osdi_model_data(inst->GENmodPtr); -} - -inline OsdiRegistryEntry osdi_reg_entry_model(GENmodel *model) { - return registry[(uint32_t)model->GENmodType - registry_off]; -} - -inline OsdiRegistryEntry osdi_reg_entry_inst(GENinstance *inst) { - return osdi_reg_entry_model(inst->GENmodPtr); -} - -typedef struct OsdiNgspiceHandle { - uint32_t kind; - char *name; -} OsdiNgspiceHandle; diff --git a/src/spicelib/devices/osdi/osdiitf.h b/src/spicelib/devices/osdi/osdiitf.h deleted file mode 100644 index 86a187c5f..000000000 --- a/src/spicelib/devices/osdi/osdiitf.h +++ /dev/null @@ -1,18 +0,0 @@ -/* - * Copyright© 2022 SemiMod UG. All rights reserved. - */ - -#pragma once - -#include - -/** - * Loads a list of object files into the global OSDI registry. - * This function must only be called once at program startup. - * - * @param PATH *object_files The paths of the object files - * @param uint32_t num_files The number of object files to load - * @returns The number of loaded descriptors - */ -extern int osdi_load_devices(void); -extern void osdi_get_info(uint32_t off, uint32_t num_descriptors); diff --git a/src/spicelib/devices/osdi/osdiregistry.c b/src/spicelib/devices/osdi/osdiregistry.c deleted file mode 100644 index 4a8e59ffa..000000000 --- a/src/spicelib/devices/osdi/osdiregistry.c +++ /dev/null @@ -1,243 +0,0 @@ -/* - * Copyright© 2022 SemiMod UG. All rights reserved. - */ - -#include "ngspice/memory.h" -#include "ngspice/stringutil.h" -#include "osdidefs.h" - -#include "ngspice/iferrmsg.h" -#include "osdi.h" -#include -#include -#include - -#if defined(_MSC_VER) -#include -#define getcwd() _getcwd -#elif defined(__GNUC__) -#include -#endif - -// TODO: platform portability - -#include "dirent.h" -#include - -char *OSDI_Path = NULL; -OsdiRegistryEntry *registry = NULL; -uint32_t registry_off = 0; - -/** - * Calculates the offset that the OSDI instance data has from the beginning of - * the instance data allocated by ngspice. This offset is non trivial because - * ngspice must store the terminal pointers before the remaining instance data. - * As a result the offset is not constant and a variable amount of padding must - * be inserted to ensure correct alginment. - */ -static size_t calc_osdi_instance_data_off(const OsdiDescriptor *descr) { - size_t res = sizeof(GENinstance) /* generic data */ - + descr->num_terminals * sizeof(int); - size_t padding = sizeof(max_align_t) - res % sizeof(max_align_t); - if (padding == sizeof(max_align_t)) { - padding = 0; - } - return res + padding; -} - -/** - * Loads an object file from the hard drive with the platform equivalent of - * dlopen. This function checks that the OSDI version of the object file is - * valid and then writes all data into the `registry`. - * If any errors occur an appropriate message is written to errMsg - * - * @param PATH path A path to the shared object file - * @param uint32_t* len The amount of entries already written into `registry` - * @param uint32_t* capacity The amount of space available in `registry` before - * reallocation is required - * @returns -1 on error, 0 otherwise - */ -static int load_object_file(char *path, uint32_t *len, uint32_t *capacity) { - void *handle; - char *error; - handle = dlopen(path, RTLD_LAZY | RTLD_LOCAL); - if (!handle) { - errMsg = dlerror(); - return -1; - } - dlerror(); /* Clear any existing error */ - - const uint32_t *OSDI_VERSION_MAJOR = dlsym(handle, "OSDI_VERSION_MAJOR"); - if ((error = dlerror()) != NULL) { - errMsg = dlerror(); - return -1; - } - - const uint32_t *OSDI_VERSION_MINOR = dlsym(handle, "OSDI_VERSION_MINOR"); - if ((error = dlerror()) != NULL) { - errMsg = - tprintf("Failed to load OSDI object file \"%s\": %s", path, dlerror()); - return -1; - } - - if (*OSDI_VERSION_MAJOR != OSDI_VERSION_MAJOR_CURR || - *OSDI_VERSION_MINOR != OSDI_VERSION_MINOR_CURR) { - errMsg = - tprintf("NGSPICE only supports OSDI v%d.%d but \"%s\" targets v%d.%d!", - OSDI_VERSION_MAJOR_CURR, OSDI_VERSION_MINOR_CURR, path, - *OSDI_VERSION_MAJOR, *OSDI_VERSION_MINOR); - return -1; - } - - const uint32_t *OSDI_NUM_DESCRIPTORS = dlsym(handle, "OSDI_NUM_DESCRIPTORS"); - if ((error = dlerror()) != NULL) { - errMsg = dlerror(); - return -1; - } - - const OsdiDescriptor *OSDI_DESCRIPTORS = dlsym(handle, "OSDI_DESCRIPTORS"); - if ((error = dlerror()) != NULL) { - errMsg = dlerror(); - return -1; - } - - if ((*len + *OSDI_NUM_DESCRIPTORS) > *capacity) { - *capacity *= 2; - registry = realloc(registry, *capacity); - } - - for (uint32_t i = 0; i < *OSDI_NUM_DESCRIPTORS; i++) { - const OsdiDescriptor *descr = &OSDI_DESCRIPTORS[i]; - - uint32_t dt = descr->num_params + descr->num_opvars; - uint32_t temp = descr->num_params + descr->num_opvars + 1; - for (uint32_t param_id = 0; param_id < descr->num_params; param_id++) { - OsdiParamOpvar *param = &descr->param_opvar[param_id]; - for (uint32_t j = 0; j < 1 + param->num_alias; j++) { - char *name = param->name[j]; - if (!strcmp(name, "dt")) { - dt = UINT32_MAX; - } else if (!strcasecmp(name, "dtemp") || !strcasecmp(name, "dt")) { - dt = param_id; - } else if (!strcmp(name, "temp")) { - temp = UINT32_MAX; - } else if (!strcasecmp(name, "temp") || - !strcasecmp(name, "temperature")) { - temp = param_id; - } - } - } - - size_t inst_off = calc_osdi_instance_data_off(descr); - registry[i + *len] = (OsdiRegistryEntry){ - .descriptor = descr, - .inst_offset = (uint32_t)inst_off, - .dt = dt, - .temp = temp, - }; - } - - *len += *OSDI_NUM_DESCRIPTORS; - - return 0; -} - -static char **osdi_search_dir(char *dir, char **dst, uint32_t *len, - uint32_t *cap) { - DIR *wdir = opendir(dir); - if (wdir == NULL) { - return dst; - } - struct direct *de; - while ((de = readdir(wdir)) != NULL) { - if (!(de->d_ino & (DT_REG | DT_LNK))) { - continue; - } - const char *filename = de->d_name; - const char *ext = strrchr(filename, '.'); - - if (!ext || ext == filename) { - continue; - } else { - ext += 1; - } - if (strcmp(ext, "so") != 0) { - continue; - } - if (*len >= *cap) { - *cap *= 2; - dst = realloc(dst, *cap * sizeof(char *)); - } - char *path = tprintf("%s%s%s", dir, DIR_PATHSEP, filename); - - if (de->d_ino & DT_LNK) { - char *full_path = realpath(path, NULL); - tfree(path); - path = full_path; - } - - dst[*len] = path; - *len += 1; - } - return dst; -} - -static char **osdi_search_devices(uint32_t *len) { - uint32_t cap = 8; - *len = 0; - char **dst = TMALLOC(char *, cap); - dst = osdi_search_dir(OSDI_Path, dst, len, &cap); - char *cwd = getcwd(NULL, 0); - if (cwd) { - char *local_osdi_dir = tprintf("%s%s%s", cwd, DIR_PATHSEP, "osdi"); - dst = osdi_search_dir(local_osdi_dir, dst, len, &cap); - tfree(cwd); - tfree(local_osdi_dir); - } - return dst; -} - -/** - * Loads a list of object files into the global OSDI registry. - * This function must only be called once at program startup. - * - * @param PATH *object_files The paths of the object files - * @param uint32_t num_files The number of object files to load - * @returns The number of loaded descriptors - */ -static int osdi_load_devices_from_files(char **object_files, - uint32_t num_files) { - uint32_t len = 0; - uint32_t capacity = num_files + 8; - registry = TMALLOC(OsdiRegistryEntry, capacity); - for (uint32_t i = 0; i < num_files; i++) { - int res = load_object_file(object_files[i], &len, &capacity); - if (res) { - return res; - } - } - registry = realloc(registry, len); - return (int)len; -} - -extern int osdi_load_devices(void) { - uint32_t len = 0; - char **files = osdi_search_devices(&len); - int res = osdi_load_devices_from_files(files, len); - // free paths - for (uint32_t i = 0; i < len; i++) { - tfree(files[i]); - } - tfree(files); - return res; -} - -size_t osdi_instance_data_off(OsdiRegistryEntry entry); -void *osdi_instance_data(OsdiRegistryEntry entry, GENinstance *inst); -OsdiExtraInstData *osdi_extra_instance_data(OsdiRegistryEntry entry, - GENinstance *inst); -size_t osdi_model_data_off(void); -void *osdi_model_data(GENmodel *model); -void *osdi_model_data_from_inst(GENinstance *inst); -OsdiRegistryEntry osdi_reg_entry_model(GENmodel *model); -OsdiRegistryEntry osdi_reg_entry_inst(GENinstance *inst); diff --git a/src/spicelib/parser/Makefile.am b/src/spicelib/parser/Makefile.am index e2cece066..fa693d835 100644 --- a/src/spicelib/parser/Makefile.am +++ b/src/spicelib/parser/Makefile.am @@ -8,7 +8,6 @@ EXTRA_DIST = inpptree-parser-y.h libinp_la_SOURCES = \ ifeval.c \ ifnewuid.c \ - inp2a.c \ inp2b.c \ inp2c.c \ inp2d.c \ @@ -72,6 +71,11 @@ libinp_la_SOURCES = \ sperror.c \ inpxx.h + +if OSDI_WANTED +libinp_la_SOURCES += inp2a.c +endif + AM_CPPFLAGS = @AM_CPPFLAGS@ -I$(top_srcdir)/src/include -I$(top_srcdir)/src/frontend AM_CFLAGS = $(STATIC) AM_YFLAGS = -d diff --git a/src/spicelib/parser/inp2a.c b/src/spicelib/parser/inp2a.c index 786fb718d..124504385 100644 --- a/src/spicelib/parser/inp2a.c +++ b/src/spicelib/parser/inp2a.c @@ -4,16 +4,21 @@ Author: 1988 Thomas L. Quarles Modified: 2001 Paolo Nenzi (Cider Integration) **********/ +#include "ngspice/ngspice.h" + #include "ngspice/devdefs.h" #include "ngspice/fteext.h" #include "ngspice/ifsim.h" #include "ngspice/inpdefs.h" #include "ngspice/inpmacs.h" -#include "ngspice/ngspice.h" #include "inpxx.h" #include +#ifdef XSPICE +#include "ngspice/mifproto.h" +#endif + void INP2A(CKTcircuit *ckt, INPtables *tab, struct card *current) { /* Mname [L=] * [W=] [AD=] [AS=] [PD=] @@ -68,8 +73,13 @@ void INP2A(CKTcircuit *ckt, INPtables *tab, struct card *current) { mdfast = thismodel->INPmodfast; IFdevice *dev = ft_sim->devices[type]; - if (!(dev->flags & DEV_OSDI)) { + if (!dev->registry_entry) { + +#ifdef XSPICE + MIF_INP2A(ckt, tab, current); +#else LITERR("incorrect model type! Expected OSDI device"); +#endif return; } diff --git a/src/spicelib/parser/inpdomod.c b/src/spicelib/parser/inpdomod.c index b63f911b9..986e7f7f3 100644 --- a/src/spicelib/parser/inpdomod.c +++ b/src/spicelib/parser/inpdomod.c @@ -3,13 +3,10 @@ Copyright 1990 Regents of the University of California. All rights reserved. Author: 1985 Thomas L. Quarles **********/ -#include "ngspice/fteext.h" #include "ngspice/ngspice.h" #include "ngspice/iferrmsg.h" #include "ngspice/inpdefs.h" -#include "ngspice/devdefs.h" #include "inpxx.h" -#include /*-------------------------------------------------------------- * This fcn takes the model card & examines it. Depending upon @@ -45,22 +42,6 @@ char *INPdomodel(CKTcircuit *ckt, struct card *image, INPtables * tab) INPinsert(&modname, tab); /* stick model name into table */ INPgetTok(&line, &type_name, 1); /* get model type */ - if (!strcmp(type_name, "osdi") || !strcmp(type_name, "veriloga") || - !strcmp(type_name, "va")) { - char *module; - INPgetTok(&line, &module, 1); /* get model type */ - if (module) { - type = INPtypelook_flag(module, DEV_OSDI); - if (type < 0) { - err = tprintf( - "%s module %s was not found in any of the loaded libraries\n", - type_name, module); - } - } else { - err = tprintf("Device type %s requires a module\n", type_name); - } - INPmakeMod(modname, type, image); - } else /* ----- Check if model is a BJT --------- */ if (strcmp(type_name, "npn") == 0 || strcmp(type_name, "pnp") == 0) { err = INPfindLev(line,&lev); @@ -698,7 +679,7 @@ char *INPdomodel(CKTcircuit *ckt, struct card *image, INPtables * tab) /* -------- Default action --------- */ else { -#ifndef XSPICE +#if !defined(XSPICE) && !defined(OSDI) type = -1; err = tprintf("unknown model type %s - ignored\n", type_name); #else diff --git a/src/spicelib/parser/inpfindl.c b/src/spicelib/parser/inpfindl.c index f69110d98..72d515195 100644 --- a/src/spicelib/parser/inpfindl.c +++ b/src/spicelib/parser/inpfindl.c @@ -13,7 +13,6 @@ Modified: 1999 Paolo Nenzi - Now we can use a two digits level code - #include "ngspice/ngspice.h" #include "ngspice/inpdefs.h" #include "inpxx.h" -#include char *INPfindLev(char *line, int *level) { @@ -69,41 +68,3 @@ char *INPfindLev(char *line, int *level) return (NULL); } } - - - -char *INPfindModule(char *line) { - char *where; - - /* - *where = line; - */ - - where = strstr(line, "module"); - - if (where != NULL) { /* found a level keyword on the line */ - - where += 6; /* skip the module keyword */ - while ((*where == ' ') || (*where == '\t') || - (*where == '=')) { /* legal white space - ignore */ - where++; - } - char *end = where; - while (isalpha(*end) || isdigit(*end) || *end == '_' || - *end == '$') { /* find end of word */ - end++; - } - - - return dup_string(where, (size_t)end - (size_t)where); - } - - else { /* no module on the line => default */ -#ifdef TRACE - fprintf(stderr, - "Warning -- Module not specified on line \"%s\"\nUsing level 1.\n", - line); -#endif - return (NULL); - } -} diff --git a/src/spicelib/parser/inpgmod.c b/src/spicelib/parser/inpgmod.c index 2ddc182b4..8a87af644 100644 --- a/src/spicelib/parser/inpgmod.c +++ b/src/spicelib/parser/inpgmod.c @@ -114,13 +114,15 @@ create_model(CKTcircuit *ckt, INPmodel *modtmp, INPtables *tab) INPgetNetTok(&line, &parm, 1); /* throw away 'modname' */ tfree(parm); +#ifdef OSDI /* osdi models don't accept their device type as an argument */ - if (device->flags & DEV_OSDI){ + if (device->registry_entry){ INPgetNetTok(&line, &parm, 1); /* throw away osdi */ tfree(parm); INPgetNetTok(&line, &parm, 1); /* throw away module name */ tfree(parm); } +#endif while (*line) { INPgetTok(&line, &parm, 1); diff --git a/src/spicelib/parser/inppas2.c b/src/spicelib/parser/inppas2.c index 333104d2b..11e32aafb 100644 --- a/src/spicelib/parser/inppas2.c +++ b/src/spicelib/parser/inppas2.c @@ -99,7 +99,12 @@ void INPpas2(CKTcircuit *ckt, struct card *data, INPtables * tab, TSKtask *task) /* blank line (tab leading) */ break; -#ifdef XSPICE +#ifdef OSDI + case 'A': /* Aname */ + // OSDI handles xspice + INP2A(ckt, tab, current); + break; +#elif XSPICE /* gtri - add - wbk - 10/23/90 - add case for 'A' devices */ case 'A': /* Aname */ @@ -245,13 +250,6 @@ void INPpas2(CKTcircuit *ckt, struct card *data, INPtables * tab, TSKtask *task) case 'B': /* Bname [V=expr] [I=expr] */ /* Arbitrary source. */ - INP2B(ckt, tab, current); - break; - - case 'A': - /* Bname [V=expr] [I=expr] */ - /* Arbitrary source. */ - INP2A(ckt, tab, current); break; case '.': /* . Many possibilities */ diff --git a/src/spicelib/parser/inptyplk.c b/src/spicelib/parser/inptyplk.c index 9bae9e344..8763427f9 100644 --- a/src/spicelib/parser/inptyplk.c +++ b/src/spicelib/parser/inptyplk.c @@ -12,10 +12,9 @@ Author: 1985 Thomas L. Quarles #include "ngspice/cpdefs.h" #include "ngspice/fteext.h" #include "ngspice/ifsim.h" -#include "ngspice/devdefs.h" #include "inpxx.h" -int INPtypelook_flag(char *type, int flag) +int INPtypelook(char *type) { int i; @@ -35,7 +34,7 @@ int INPtypelook_flag(char *type, int flag) printf("In INPtypelook, checking model type = %s against existing model = %s, . . .\n", type, ft_sim->devices[i]->name); #endif - if (ft_sim->devices[i] && strcasecmp(type, ft_sim->devices[i]->name) == 0 && ft_sim->devices[i]->flags & flag) { + if (ft_sim->devices[i] && strcasecmp(type, ft_sim->devices[i]->name) == 0) { /* found the device - return it */ #ifdef TRACE @@ -54,13 +53,3 @@ int INPtypelook_flag(char *type, int flag) return -1; } - -// backwards compatability: only look for static devices -int INPtypelook(char *type) -{ - return INPtypelook_flag(type, DEV_STATIC); - -} - - - diff --git a/src/spicelib/parser/inpxx.h b/src/spicelib/parser/inpxx.h index 6d42b5669..ce21fa796 100644 --- a/src/spicelib/parser/inpxx.h +++ b/src/spicelib/parser/inpxx.h @@ -8,7 +8,9 @@ /* inp2xx.c */ +#ifdef OSDI void INP2A(CKTcircuit *ckt, INPtables *tab, struct card *current); +#endif void INP2B(CKTcircuit *ckt, INPtables *tab, struct card *current); void INP2C(CKTcircuit *ckt, INPtables *tab, struct card *current); void INP2D(CKTcircuit *ckt, INPtables *tab, struct card *current);