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/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 */

View File

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

View File

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

View File

@ -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. */

View File

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

View File

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

View File

@ -7,10 +7,14 @@ Author: 1985 Thomas L. Quarles
#include <stdio.h>
#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);
}