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:
parent
9702557f81
commit
8ef0aece58
|
|
@ -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 */
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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. */
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue