During setup of the models thre have been search scans in the

linked model list modtab. The time used here grows approx.
quadratically with the number of models. If the numbers get large,
e.g. with the IHP Open PDK, setup time make simulation impractical.
Therefore the linked list modtab has been enhanced by a hash table
modtabhash, which allows linear search time and makes simulation
of a 200k transistor circuit with IHP PDK possible. Already
the setup time for 15k transistor circuits has been reduced.
This commit is contained in:
Holger Vogt 2023-10-18 14:34:16 +02:00
parent 9702557f81
commit 8ef0aece58
7 changed files with 78 additions and 19 deletions

View File

@ -14,6 +14,7 @@ Modified: 2000 AlansFixes
#include "ngspice/ftedev.h" #include "ngspice/ftedev.h"
#include "ngspice/ftedebug.h" #include "ngspice/ftedebug.h"
#include "ngspice/dvec.h" #include "ngspice/dvec.h"
#include "ngspice/hash.h"
#include "numparam/numpaif.h" #include "numparam/numpaif.h"
@ -33,6 +34,7 @@ Modified: 2000 AlansFixes
static int dosim(char *what, wordlist *wl); static int dosim(char *what, wordlist *wl);
extern struct INPmodel *modtab; extern struct INPmodel *modtab;
extern NGHASHPTR modtabhash;
extern struct dbcomm *dbs; extern struct dbcomm *dbs;
extern void NIresetwarnmsg(void); extern void NIresetwarnmsg(void);
@ -107,6 +109,7 @@ com_scirc(wordlist *wl)
ft_curckt = p; ft_curckt = p;
/* get the model table for the current circuit, store it in the global variable modtab */ /* get the model table for the current circuit, store it in the global variable modtab */
modtab = ft_curckt->ci_modtab; modtab = ft_curckt->ci_modtab;
modtabhash = ft_curckt->ci_modtabhash;
/* get the database for save, iplot, stop */ /* get the database for save, iplot, stop */
dbs = ft_curckt->ci_dbs; dbs = ft_curckt->ci_dbs;
/* set the numparam dicos structure for use with measure */ /* set the numparam dicos structure for use with measure */

View File

@ -14,6 +14,7 @@ Author: 1985 Wayne A. Christopher, U. C. Berkeley CAD Group
#include "ngspice/ftedebug.h" #include "ngspice/ftedebug.h"
#include "ngspice/dvec.h" #include "ngspice/dvec.h"
#include "ngspice/trandefs.h" #include "ngspice/trandefs.h"
#include "ngspice/hash.h"
#include "circuits.h" #include "circuits.h"
#include "runcoms2.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 void line_free_x(struct card *deck, bool recurse);
extern INPmodel *modtab; extern INPmodel *modtab;
extern NGHASHPTR modtabhash;
#ifdef SHARED_MODULE #ifdef SHARED_MODULE
extern void exec_controls(wordlist *newcontrols); extern void exec_controls(wordlist *newcontrols);
@ -273,10 +275,11 @@ com_remcirc(wordlist *wl)
prev = p; 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; ft_curckt = ft_circuits;
if (ft_curckt) { if (ft_curckt) {
modtab = ft_curckt->ci_modtab; modtab = ft_curckt->ci_modtab;
modtabhash = ft_curckt->ci_modtabhash;
dbs = ft_curckt->ci_dbs; dbs = ft_curckt->ci_dbs;
nupa_set_dicoslist(ft_curckt->ci_dicos); nupa_set_dicoslist(ft_curckt->ci_dicos);
} }

View File

@ -54,6 +54,7 @@ CDHW*/
#include "ngspice/inpdefs.h" #include "ngspice/inpdefs.h"
#include "ngspice/iferrmsg.h" #include "ngspice/iferrmsg.h"
#include "ngspice/ifsim.h" #include "ngspice/ifsim.h"
#include "ngspice/hash.h"
#include "circuits.h" #include "circuits.h"
#include "spiceif.h" #include "spiceif.h"
@ -75,6 +76,7 @@ CDHW*/
#endif #endif
extern INPmodel *modtab; extern INPmodel *modtab;
extern NGHASHPTR modtabhash;
extern bool ft_batchmode; extern bool ft_batchmode;
static struct variable *parmtovar(IFvalue *pv, IFparm *opt); 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. */ /* Parse the .model lines. Enter the model into the global model table modtab. */
modtab = NULL; modtab = NULL;
modtabhash = NULL;
INPpas1(ckt, deck->nextcard, *tab); INPpas1(ckt, deck->nextcard, *tab);
/* store the new model table in the current circuit */ /* store the new model table in the current circuit */
ft_curckt->ci_modtab = modtab; ft_curckt->ci_modtab = modtab;
ft_curckt->ci_modtabhash = modtabhash;
/* Scan through the instance lines and parse the circuit. */ /* Scan through the instance lines and parse the circuit. */
INPpas2(ckt, deck->nextcard, *tab, ft_curckt->ci_defTask); INPpas2(ckt, deck->nextcard, *tab, ft_curckt->ci_defTask);

View File

@ -17,6 +17,7 @@ Author: 1985 Wayne A. Christopher, U. C. Berkeley CAD Group
#include "ngspice/fteparse.h" #include "ngspice/fteparse.h"
#include "ngspice/fteinp.h" #include "ngspice/fteinp.h"
#include "ngspice/fteoptdefs.h" #include "ngspice/fteoptdefs.h"
#include "ngspice/hash.h"
struct ccom; struct ccom;
@ -34,6 +35,7 @@ struct circ {
CKTcircuit *ci_ckt; /* The CKTcircuit structure. */ CKTcircuit *ci_ckt; /* The CKTcircuit structure. */
INPtables *ci_symtab; /* The INP symbol table. */ INPtables *ci_symtab; /* The INP symbol table. */
INPmodel *ci_modtab; /* The INP model 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 dbcomm *ci_dbs; /* The database storing save, iplot, stop data */
struct card *ci_deck; /* The input deck. */ struct card *ci_deck; /* The input deck. */
struct card *ci_origdeck; /* The input deck, before subckt expansion. */ struct card *ci_origdeck; /* The input deck, before subckt expansion. */

View File

@ -39,6 +39,7 @@ static int INPfindParm(char *name, IFparm *table, int numParms);
#endif #endif
extern INPmodel *modtab; extern INPmodel *modtab;
extern NGHASHPTR modtabhash;
static IFparm * static IFparm *
@ -342,6 +343,33 @@ INPgetMod(CKTcircuit *ckt, char *name, INPmodel **model, INPtables *tab)
printf("In INPgetMod, examining model %s ...\n", name); printf("In INPgetMod, examining model %s ...\n", name);
#endif #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) { for (modtmp = modtab; modtmp; modtmp = modtmp->INPnextModel) {
#ifdef TRACE #ifdef TRACE
@ -374,7 +402,7 @@ INPgetMod(CKTcircuit *ckt, char *name, INPmodel **model, INPtables *tab)
return NULL; return NULL;
} }
} }
#endif
#ifdef TRACE #ifdef TRACE
printf("In INPgetMod, didn't find model for %s, using default ...\n", name); printf("In INPgetMod, didn't find model for %s, using default ...\n", name);
#endif #endif

View File

@ -13,6 +13,7 @@ Author: 1985 Thomas L. Quarles
extern INPmodel *modtab; extern INPmodel *modtab;
extern NGHASHPTR modtabhash;
void INPkillMods(void) void INPkillMods(void)
{ {
@ -28,4 +29,11 @@ void INPkillMods(void)
FREE(prev); FREE(prev);
modtab = NULL; modtab = NULL;
ft_curckt->ci_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;
} }

View File

@ -7,10 +7,14 @@ Author: 1985 Thomas L. Quarles
#include <stdio.h> #include <stdio.h>
#include "ngspice/inpdefs.h" #include "ngspice/inpdefs.h"
#include "ngspice/iferrmsg.h" #include "ngspice/iferrmsg.h"
#include "ngspice/hash.h"
#include "inpxx.h" #include "inpxx.h"
/* global input model table. */ /* global input model table. */
INPmodel *modtab = NULL; 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 * 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) int INPmakeMod(char *token, int type, struct card *line)
{ {
register INPmodel **i; register INPmodel *newm;
/* Initialze the hash table. The default key type is string.
/* First cycle through model table and see if model name The default comparison function is strcmp.*/
already exists in there. If it does, just return. */ if (!modtabhash) {
for (i = &modtab; *i != NULL; i = &((*i)->INPnextModel)) { modtabhash = nghash_init(NGHASH_MIN_SIZE);
if (strcmp((*i)->INPmodName, token) == 0) { nghash_unique(modtabhash, TRUE);
}
/* If the model is already there, just return. */
else if (nghash_find(modtabhash, token))
return (OK); return (OK);
}
}
/* Model name was not already in model table. Therefore stick /* Model name was not already in model table. Therefore stick
it in the model table. Then return. */ it in the front of the model table, also into the model hash table.
Then return. */
#ifdef TRACE #ifdef TRACE
/* debug statement */ /* debug statement */
printf("In INPmakeMod, about to insert new model name = %s . . .\n", token); printf("In INPmakeMod, about to insert new model name = %s . . .\n", token);
#endif #endif
*i = TMALLOC(INPmodel, 1); newm = TMALLOC(INPmodel, 1);
if (*i == NULL) if (newm == NULL)
return (E_NOMEM); return (E_NOMEM);
(*i)->INPmodName = token; /* model name */ newm->INPmodName = token; /* model name */
(*i)->INPmodType = type; /* model type */ newm->INPmodType = type; /* model type */
(*i)->INPnextModel = NULL; /* pointer to next model (end of list) */ newm->INPnextModel = modtab; /* pointer to second model */
(*i)->INPmodLine = line; /* model line */ newm->INPmodLine = line; /* model line */
(*i)->INPmodfast = NULL; newm->INPmodfast = NULL;
nghash_insert(modtabhash, token, newm);
modtab = newm;
return (OK); return (OK);
} }