diff --git a/src/frontend/inp.c b/src/frontend/inp.c index b164bc1fe..aba8450d1 100644 --- a/src/frontend/inp.c +++ b/src/frontend/inp.c @@ -960,8 +960,8 @@ inp_spsource(FILE *fp, bool comfile, char *filename, bool intfile) So again try to remove unused MOS models. All binning models are still here when w or l have been determined by an expression. */ - if (newcompat.hs || newcompat.spe) - rem_unused_mos_models(deck->nextcard); +// if (newcompat.hs || newcompat.spe) +// rem_unused_mos_models(deck->nextcard); /* now load deck into ft_curckt -- the current circuit. */ if(inp_dodeck(deck, tt, wl_first, FALSE, options, filename) != 0) diff --git a/src/frontend/runcoms.c b/src/frontend/runcoms.c index 9d52e192e..613be5d9e 100644 --- a/src/frontend/runcoms.c +++ b/src/frontend/runcoms.c @@ -14,6 +14,7 @@ Modified: 2000 AlansFixes #include "ngspice/ftedev.h" #include "ngspice/ftedebug.h" #include "ngspice/dvec.h" +#include "ngspice/hash.h" #include "numparam/numpaif.h" @@ -33,6 +34,7 @@ Modified: 2000 AlansFixes static int dosim(char *what, wordlist *wl); extern struct INPmodel *modtab; +extern NGHASHPTR modtabhash; extern struct dbcomm *dbs; extern void NIresetwarnmsg(void); @@ -107,6 +109,7 @@ com_scirc(wordlist *wl) ft_curckt = p; /* get the model table for the current circuit, store it in the global variable modtab */ modtab = ft_curckt->ci_modtab; + modtabhash = ft_curckt->ci_modtabhash; /* get the database for save, iplot, stop */ dbs = ft_curckt->ci_dbs; /* set the numparam dicos structure for use with measure */ diff --git a/src/frontend/runcoms2.c b/src/frontend/runcoms2.c index ac6c9dead..baf43ee79 100644 --- a/src/frontend/runcoms2.c +++ b/src/frontend/runcoms2.c @@ -14,6 +14,7 @@ Author: 1985 Wayne A. Christopher, U. C. Berkeley CAD Group #include "ngspice/ftedebug.h" #include "ngspice/dvec.h" #include "ngspice/trandefs.h" +#include "ngspice/hash.h" #include "circuits.h" #include "runcoms2.h" @@ -33,6 +34,7 @@ Author: 1985 Wayne A. Christopher, U. C. Berkeley CAD Group extern void line_free_x(struct card *deck, bool recurse); extern INPmodel *modtab; +extern NGHASHPTR modtabhash; #ifdef SHARED_MODULE extern void exec_controls(wordlist *newcontrols); @@ -273,10 +275,11 @@ com_remcirc(wordlist *wl) prev = p; } - /* make first entry in ft_circuits the actual circuit (or NULL) */ + /* make first entry in ft_circuits the current circuit (or NULL) */ ft_curckt = ft_circuits; if (ft_curckt) { modtab = ft_curckt->ci_modtab; + modtabhash = ft_curckt->ci_modtabhash; dbs = ft_curckt->ci_dbs; nupa_set_dicoslist(ft_curckt->ci_dicos); } diff --git a/src/frontend/spiceif.c b/src/frontend/spiceif.c index 724e4f879..c135b37db 100644 --- a/src/frontend/spiceif.c +++ b/src/frontend/spiceif.c @@ -54,6 +54,7 @@ CDHW*/ #include "ngspice/inpdefs.h" #include "ngspice/iferrmsg.h" #include "ngspice/ifsim.h" +#include "ngspice/hash.h" #include "circuits.h" #include "spiceif.h" @@ -75,6 +76,7 @@ CDHW*/ #endif extern INPmodel *modtab; +extern NGHASHPTR modtabhash; extern bool ft_batchmode; static struct variable *parmtovar(IFvalue *pv, IFparm *opt); @@ -160,9 +162,11 @@ if_inpdeck(struct card *deck, INPtables **tab) /* Parse the .model lines. Enter the model into the global model table modtab. */ modtab = NULL; + modtabhash = NULL; INPpas1(ckt, deck->nextcard, *tab); /* store the new model table in the current circuit */ ft_curckt->ci_modtab = modtab; + ft_curckt->ci_modtabhash = modtabhash; /* Scan through the instance lines and parse the circuit. */ INPpas2(ckt, deck->nextcard, *tab, ft_curckt->ci_defTask); diff --git a/src/include/ngspice/cmproto.h b/src/include/ngspice/cmproto.h index 129fbc23a..7ab6ffbd5 100644 --- a/src/include/ngspice/cmproto.h +++ b/src/include/ngspice/cmproto.h @@ -126,4 +126,6 @@ FILE *fopen_with_path(const char *path, const char *mode); #define CM_IGNORE(x) (void) (x) +void cm_cexit(const int); + #endif /* include guard */ diff --git a/src/include/ngspice/dllitf.h b/src/include/ngspice/dllitf.h index b3a68c65d..1d9295d81 100644 --- a/src/include/ngspice/dllitf.h +++ b/src/include/ngspice/dllitf.h @@ -83,6 +83,7 @@ struct coreInfo_t { void * ((*dllitf_tmalloc)(size_t)); void * ((*dllitf_trealloc)(const void *, size_t)); void ((*dllitf_txfree)(const void *)); + void ((*dllitf_cexit)(const int)); #ifdef KLU int ((*dllitf_MIFbindCSC) (GENmodel *, CKTcircuit *)) ; diff --git a/src/include/ngspice/ftedefs.h b/src/include/ngspice/ftedefs.h index 471f1c9b2..639707250 100644 --- a/src/include/ngspice/ftedefs.h +++ b/src/include/ngspice/ftedefs.h @@ -17,6 +17,7 @@ Author: 1985 Wayne A. Christopher, U. C. Berkeley CAD Group #include "ngspice/fteparse.h" #include "ngspice/fteinp.h" #include "ngspice/fteoptdefs.h" +#include "ngspice/hash.h" struct ccom; @@ -34,6 +35,7 @@ struct circ { CKTcircuit *ci_ckt; /* The CKTcircuit structure. */ INPtables *ci_symtab; /* The INP symbol table. */ INPmodel *ci_modtab; /* The INP model table. */ + NGHASHPTR ci_modtabhash; /* The INP model hash table. */ struct dbcomm *ci_dbs; /* The database storing save, iplot, stop data */ struct card *ci_deck; /* The input deck. */ struct card *ci_origdeck; /* The input deck, before subckt expansion. */ diff --git a/src/spicelib/parser/inpgmod.c b/src/spicelib/parser/inpgmod.c index 6450abf6d..44dc93989 100644 --- a/src/spicelib/parser/inpgmod.c +++ b/src/spicelib/parser/inpgmod.c @@ -39,6 +39,7 @@ static int INPfindParm(char *name, IFparm *table, int numParms); #endif extern INPmodel *modtab; +extern NGHASHPTR modtabhash; static IFparm * @@ -342,6 +343,33 @@ INPgetMod(CKTcircuit *ckt, char *name, INPmodel **model, INPtables *tab) printf("In INPgetMod, examining model %s ...\n", name); #endif + modtmp = nghash_find(modtabhash, name); + if (modtmp) { + /* found the model in question - now instantiate if necessary */ + /* and return an appropriate pointer to it */ + +/* if illegal device type */ + if (modtmp->INPmodType < 0) { +#ifdef TRACE + printf("In INPgetMod, illegal device type for model %s ...\n", name); +#endif + * model = NULL; + return tprintf("Unknown device type for model %s\n", name); + } + + /* create unless model is already defined */ + if (!modtmp->INPmodfast) { + int error = create_model(ckt, modtmp, tab); + if (error) { + *model = NULL; + return INPerror(error); + } + } + + *model = modtmp; + return NULL; + } +#if (0) for (modtmp = modtab; modtmp; modtmp = modtmp->INPnextModel) { #ifdef TRACE @@ -374,7 +402,7 @@ INPgetMod(CKTcircuit *ckt, char *name, INPmodel **model, INPtables *tab) return NULL; } } - +#endif #ifdef TRACE printf("In INPgetMod, didn't find model for %s, using default ...\n", name); #endif diff --git a/src/spicelib/parser/inpkmods.c b/src/spicelib/parser/inpkmods.c index 8e356a840..1c0f75be3 100644 --- a/src/spicelib/parser/inpkmods.c +++ b/src/spicelib/parser/inpkmods.c @@ -1,8 +1,8 @@ /********** Copyright 1990 Regents of the University of California. All rights reserved. -Author: 1985 Thomas L. Quarles +Author: 1985 Thomas L. Quarles, 2023 Holger Vogt **********/ -/* +/* Deletes the model table modtab and the hash table modtabhash. */ #include "ngspice/ngspice.h" @@ -11,21 +11,27 @@ Author: 1985 Thomas L. Quarles #include "ngspice/ftedefs.h" #include "inpxx.h" - -extern INPmodel *modtab; +extern INPmodel* modtab; +extern NGHASHPTR modtabhash; void INPkillMods(void) { - INPmodel *modtmp; - INPmodel *prev = NULL; + INPmodel* modtmp; + INPmodel* prev = NULL; for (modtmp = modtab; modtmp != NULL; modtmp = modtmp->INPnextModel) { - if (prev) - FREE(prev); - prev = modtmp; + if (prev) + FREE(prev); + prev = modtmp; } if (prev) - FREE(prev); + FREE(prev); modtab = NULL; ft_curckt->ci_modtab = NULL; + /* free the hash table */ + if (modtabhash) { + nghash_free(modtabhash, NULL, NULL); + modtabhash = NULL; + } + ft_curckt->ci_modtabhash = NULL; } diff --git a/src/spicelib/parser/inpmkmod.c b/src/spicelib/parser/inpmkmod.c index 456c4f5e4..055d7a66b 100644 --- a/src/spicelib/parser/inpmkmod.c +++ b/src/spicelib/parser/inpmkmod.c @@ -7,10 +7,14 @@ Author: 1985 Thomas L. Quarles #include #include "ngspice/inpdefs.h" #include "ngspice/iferrmsg.h" +#include "ngspice/hash.h" #include "inpxx.h" /* global input model table. */ INPmodel *modtab = NULL; +/* Global input model hash table. + The modelname is the key, the return value is the pointer to the model. */ +NGHASHPTR modtabhash = NULL; /*-------------------------------------------------------------- * This fcn takes the model name and looks to see if it is already @@ -21,33 +25,40 @@ INPmodel *modtab = NULL; int INPmakeMod(char *token, int type, struct card *line) { - register INPmodel **i; - - /* First cycle through model table and see if model name - already exists in there. If it does, just return. */ - for (i = &modtab; *i != NULL; i = &((*i)->INPnextModel)) { - if (strcmp((*i)->INPmodName, token) == 0) { - return (OK); - } + register INPmodel *newm; + /* Initialze the hash table. The default key type is string. + The default comparison function is strcmp.*/ + if (!modtabhash) { + modtabhash = nghash_init(NGHASH_MIN_SIZE); + nghash_unique(modtabhash, TRUE); } + /* If the model is already there, just return. */ + else if (nghash_find(modtabhash, token)) + return (OK); - /* Model name was not already in model table. Therefore stick - it in the model table. Then return. */ + /* Model name was not already in model table. Therefore stick + it in the front of the model table, also into the model hash table. + Then return. */ #ifdef TRACE /* debug statement */ printf("In INPmakeMod, about to insert new model name = %s . . .\n", token); #endif - *i = TMALLOC(INPmodel, 1); - if (*i == NULL) + newm = TMALLOC(INPmodel, 1); + if (newm == NULL) return (E_NOMEM); - (*i)->INPmodName = token; /* model name */ - (*i)->INPmodType = type; /* model type */ - (*i)->INPnextModel = NULL; /* pointer to next model (end of list) */ - (*i)->INPmodLine = line; /* model line */ - (*i)->INPmodfast = NULL; + newm->INPmodName = token; /* model name */ + newm->INPmodType = type; /* model type */ + newm->INPnextModel = modtab; /* pointer to second model */ + newm->INPmodLine = line; /* model line */ + newm->INPmodfast = NULL; + + nghash_insert(modtabhash, token, newm); + + modtab = newm; + return (OK); } diff --git a/src/spicelib/parser/inpptree.c b/src/spicelib/parser/inpptree.c index 063bbd5f9..22d298489 100644 --- a/src/spicelib/parser/inpptree.c +++ b/src/spicelib/parser/inpptree.c @@ -12,6 +12,7 @@ Author: 1987 Wayne A. Christopher, U. C. Berkeley CAD Group #include "ngspice/iferrmsg.h" #include "ngspice/inpdefs.h" #include "ngspice/inpptree.h" +#include "ngspice/randnumb.h" #include "inpxx.h" #include "inpptree-parser.h" @@ -36,6 +37,8 @@ static INPparseNode *PTdifferentiate(INPparseNode * p, int varnum); static void free_tree(INPparseNode *); static void printTree(INPparseNode *); +static double gauss(double nominal_val, double rel_variation, double sigma); + /* * LAW for INPparseNode* generator and consumer functions: @@ -1145,6 +1148,30 @@ INPparseNode *PT_mkfnode(const char *fname, INPparseNode * arg) return mkfirst(NULL, arg); } + /* This is used only to evaluate fcn gauss(a1, a2, a3) in .model files, where + temper is used also. a1, a2, and a3 have to be constant double values. */ + if (!strcmp("gauss", buf)) { + if (arg->type == PT_COMMA && arg->left->type == PT_COMMA) { + + INPparseNode* arg1 = arg->left->left; + INPparseNode* arg2 = arg->left->right; + INPparseNode* arg3 = arg->right; + double a1 = arg1->constant; + double a2 = arg2->constant; + double a3 = arg3->constant; + + if (a2 == 0.0 || a3 == 0.0) { + fprintf(stderr, "Error: bogus gauss form\n"); + return mkfirst(NULL, arg); //return mkcon(a1); + } + + return mkcon(gauss(a1, a2, a3)); + } + + fprintf(stderr, "Error: bogus gauss form\n"); + return mkfirst(NULL, arg); + } + for (i = 0; i < NUM_FUNCS; i++) if (!strcmp(funcs[i].name, buf)) break; @@ -1626,6 +1653,16 @@ void free_tree(INPparseNode *pt) txfree(pt); } +static double +gauss(double nominal_val, double rel_variation, double sigma) +{ + double stdvar; + if (rel_variation <= 0 || sigma <= 0) + return nominal_val; + stdvar = nominal_val * rel_variation / sigma; + return (nominal_val + stdvar * gauss1()); +} + /* Debugging stuff. */ diff --git a/src/xspice/cm/cmexport.c b/src/xspice/cm/cmexport.c index 2240eaf01..0e65a1f75 100644 --- a/src/xspice/cm/cmexport.c +++ b/src/xspice/cm/cmexport.c @@ -81,7 +81,8 @@ struct coreInfo_t coreInfo = txfree, tmalloc, trealloc, - txfree + txfree, + cm_cexit #else GC_malloc, tcalloc, diff --git a/src/xspice/cm/cmutil.c b/src/xspice/cm/cmutil.c index c1953192c..ee69a0f99 100644 --- a/src/xspice/cm/cmutil.c +++ b/src/xspice/cm/cmutil.c @@ -36,7 +36,7 @@ INTERFACES cm_complex_subtract() cm_complex_multiply() cm_complex_divide() - + cm_cexit() REFERENCED FILES @@ -51,6 +51,8 @@ NON-STANDARD FEATURES #include #include #include "ngspice/cm.h" + +extern void controlled_exit(const int); /* Corner Smoothing Function ************************************ * * @@ -525,4 +527,7 @@ Complex_t cm_complex_divide(Complex_t x, Complex_t y) return(c); } - +void cm_cexit(const int exitcode) +{ + controlled_exit(exitcode); +} diff --git a/src/xspice/icm/dlmain.c b/src/xspice/icm/dlmain.c index c64668991..87f6050f9 100644 --- a/src/xspice/icm/dlmain.c +++ b/src/xspice/icm/dlmain.c @@ -430,6 +430,10 @@ void txfree(const void *ptr) { (coreitf->dllitf_txfree)(ptr); } +void cm_cexit(const int exitcode) { + (coreitf->dllitf_cexit)(exitcode); +} + #ifdef KLU int MIFbindCSC (GENmodel *inModel, CKTcircuit *ckt) { return (coreitf->dllitf_MIFbindCSC) (inModel, ckt) ;