From a4d3b9dc5db6828b543c851a6fe673fd1aac0736 Mon Sep 17 00:00:00 2001 From: Holger Vogt Date: Wed, 11 Feb 2026 20:13:13 +0100 Subject: [PATCH] Use hash table modtabhash for finding model instead of linked list modtab. This speeds up parsing of (a large number of) code models enormously. --- src/xspice/mif/mifgetmod.c | 140 +++++++++++++++++++------------------ 1 file changed, 72 insertions(+), 68 deletions(-) diff --git a/src/xspice/mif/mifgetmod.c b/src/xspice/mif/mifgetmod.c index a1cd1a7b2..dfaff63ba 100644 --- a/src/xspice/mif/mifgetmod.c +++ b/src/xspice/mif/mifgetmod.c @@ -53,6 +53,7 @@ NON-STANDARD FEATURES #include "ngspice/ifsim.h" #include "ngspice/cpstd.h" #include "ngspice/fteext.h" +#include "ngspice/hash.h" #include "ngspice/mifproto.h" #include "ngspice/mifdefs.h" @@ -61,9 +62,10 @@ NON-STANDARD FEATURES #include "ngspice/suffix.h" -/* This is the table of all models known to the program. +/* This is the table of all models known to the program. It is now defined in inpmkmod.c. */ -extern INPmodel *modtab; +extern INPmodel* modtab; +extern NGHASHPTR modtabhash; /* MIFgetMod @@ -81,27 +83,27 @@ defaulted later by MIFsetup(). The function returns NULL when successful, and an error string on failure. */ -char *MIFgetMod( - CKTcircuit *ckt, /* The circuit structure */ - char *name, /* The name of the model to look for */ - INPmodel **model, /* The model found/created */ - INPtables *tab /* Table of model info from first pass */ - ) +char* MIFgetMod( + CKTcircuit* ckt, /* The circuit structure */ + char* name, /* The name of the model to look for */ + INPmodel** model, /* The model found/created */ + INPtables* tab /* Table of model info from first pass */ +) { - INPmodel *modtmp; - IFvalue * val; + INPmodel* modtmp; + IFvalue* val; register int j; - char * line; - char *parm; - char *err = NULL; + char* line; + char* parm; + char* err = NULL; int error; int i; - char *err1; - char *err2; + char* err1; + char* err2; - MIFmodel *mdfast; + MIFmodel* mdfast; /* =========== First locate the named model in the modtab list ================= */ @@ -112,63 +114,64 @@ char *MIFgetMod( /* maschmann : remove : from name * char *pos; - * if((pos=strchr(name,':'))!=NULL) *pos=0; + * if((pos=strchr(name,':'))!=NULL) *pos=0; */ - /*------------------------------------ - for (i = &modtab; *i != NULL; i = &((*i)->INPnextModel)) { - if (strcmp((*i)->INPmodName, token) == 0) { - return (OK); - } - } - --------------------------*/ + /*------------------------------------ + for (i = &modtab; *i != NULL; i = &((*i)->INPnextModel)) { + if (strcmp((*i)->INPmodName, token) == 0) { + return (OK); + } + } + --------------------------*/ - /* loop through modtable looking for this model (*name) */ - for (modtmp = modtab; modtmp != NULL; modtmp = modtmp->INPnextModel) { + /* loop through modtable looking for this model (*name) */ + // for (modtmp = modtab; modtmp != NULL; modtmp = modtmp->INPnextModel) { #ifdef TRACE /* SDB debug statement */ - printf("In MIFgetMod, checking model against stored model = %s . . .\n", modtmp->INPmodName); + printf("In MIFgetMod, checking model against stored model = %s . . .\n", modtmp->INPmodName); #endif - - if (strcmp(modtmp->INPmodName, name) == 0) { + if (modtabhash) { + modtmp = nghash_find(modtabhash, name); + if (modtmp) { #ifdef TRACE - /* SDB debug statement */ - printf("In MIFgetMod, found model!!!\n"); + /* SDB debug statement */ + printf("In MIFgetMod, found model!!!\n"); #endif - /* ========= found the model in question - now instantiate if necessary ========== */ - /* ============== and return an appropriate pointer to it ===================== */ + /* ========= found the model in question - now instantiate if necessary ========== */ + /* ============== and return an appropriate pointer to it ===================== */ - /* make sure the type is valid before proceeding */ - if (modtmp->INPmodType < 0) { - /* illegal device type, so can't handle */ + /* make sure the type is valid before proceeding */ + if (modtmp->INPmodType < 0) { + /* illegal device type, so can't handle */ - *model = NULL; - return tprintf("MIF: Unknown device type for model %s\n", name); - } + *model = NULL; + return tprintf("MIF: Unknown device type for model %s\n", name); + } /* check to see if this model's parameters have been processed */ - if (!modtmp->INPmodfast) { - struct IFdevice *device; + if (!modtmp->INPmodfast) { + struct IFdevice* device; int num_pars; /* not already processed, so create data struct */ error = ft_sim->newModel(ckt, modtmp->INPmodType, - &(modtmp->INPmodfast), - modtmp->INPmodName); + &(modtmp->INPmodfast), + modtmp->INPmodName); if (error) return INPerror(error); /* Allocate and initialize MIF specific model struct items. */ - mdfast = (MIFmodel*) modtmp->INPmodfast; + mdfast = (MIFmodel*)modtmp->INPmodfast; mdfast->num_param = DEVices[modtmp->INPmodType]->DEVpublic.num_param; - mdfast->param = TMALLOC(Mif_Param_Data_t *, mdfast->num_param); + mdfast->param = TMALLOC(Mif_Param_Data_t*, mdfast->num_param); for (i = 0; i < mdfast->num_param; i++) { mdfast->param[i] = TMALLOC(Mif_Param_Data_t, 1); mdfast->param[i]->is_null = MIF_TRUE; @@ -180,12 +183,12 @@ char *MIFgetMod( * MIFmParam() and MIFsetup(). */ - /* parameter isolation, identification, binding */ + /* parameter isolation, identification, binding */ line = modtmp->INPmodLine->line; - INPgetTok(&line,&parm,1); /* throw away '.model' */ + INPgetTok(&line, &parm, 1); /* throw away '.model' */ tfree(parm); - INPgetNetTok(&line,&parm,1); /* throw away 'modname' */ + INPgetNetTok(&line, &parm, 1); /* throw away 'modname' */ tfree(parm); /* throw away the modtype - we don't treat it as a parameter */ @@ -206,11 +209,11 @@ char *MIFgetMod( if (strcmp(parm, device->modelParms[j].keyword) == 0) { err1 = NULL; val = MIFgetValue(ckt, &line, - device->modelParms[j].dataType, - tab, &err1); + device->modelParms[j].dataType, + tab, &err1); if (err1) { err2 = tprintf("MIF-ERROR - model: %s - %s\n", - name, err1); + name, err1); return err2; } @@ -218,9 +221,9 @@ char *MIFgetMod( error = ft_sim->setModelParm(ckt, - modtmp->INPmodfast, - device->modelParms[j].id, - val, NULL); + modtmp->INPmodfast, + device->modelParms[j].id, + val, NULL); /* free val, allocated by MIFgetValue */ int vtype = @@ -245,9 +248,9 @@ char *MIFgetMod( } if (j >= *(device->numModelParms)) { - char *temp = tprintf("MIF: unrecognized parameter " - "(%s) - ignored", - parm); + char* temp = tprintf("MIF: unrecognized parameter " + "(%s) - ignored", + parm); err = INPerrCat(err, temp); } FREE(parm); @@ -259,25 +262,26 @@ char *MIFgetMod( /* Make some consistency checks. */ for (i = 0; i < mdfast->num_param; i++) { - Mif_Param_Info_t *param_info; - char *emessage; + Mif_Param_Info_t* param_info; + char* emessage; param_info = device->param + i; if (mdfast->param[i]->is_null) { if (!param_info->null_allowed) { emessage = tprintf("Null not allowed for " - "parameter '%s' on model '%s'.", - param_info->name, - mdfast->gen.GENmodName); + "parameter '%s' on model '%s'.", + param_info->name, + mdfast->gen.GENmodName); return emessage; - } else if (param_info->default_value_siz == 0) { + } + else if (param_info->default_value_siz == 0) { if (param_info->type == MIF_STRING) continue; // Allow NULL emessage = tprintf("Parameter '%s' on model '%s' " - "has no default.", - param_info->name, - mdfast->gen.GENmodName); + "has no default.", + param_info->name, + mdfast->gen.GENmodName); return emessage; } } @@ -286,8 +290,8 @@ char *MIFgetMod( *model = modtmp; return NULL; - } /* end if name matches */ - } /* end for all models in modtab linked list */ + } /* end if model name links to model in modtabhash */ + } /* end of modtabhash is available */ /* didn't find model - ERROR - return NULL model */