From 5e6c6371a3ab9d8ac921f20e3b9a723ba6383b0b Mon Sep 17 00:00:00 2001 From: rlar Date: Wed, 9 Nov 2016 18:40:05 +0100 Subject: [PATCH] rewrite scope business, use a tree structure to represent scopeing, instead of edge enumeration. drop a check for "suitable" subckt, the scope dictates which .subckt is refered to. drop a check for redefinition in numparm, numparm is definitly defect, it doesn't know about "scope" The check did only check for some specific situations. todo: - use the scope datastructure in numparm and subckt.c too - free the scope datastructure --- src/frontend/inpcom.c | 352 ++++++++++++++----------------- src/frontend/numparam/numpaif.h | 4 +- src/frontend/numparam/numparam.h | 6 +- src/frontend/numparam/spicenum.c | 2 +- src/frontend/numparam/xpressn.c | 13 +- src/include/ngspice/fteinp.h | 2 +- src/include/ngspice/inpdefs.h | 16 +- 7 files changed, 188 insertions(+), 207 deletions(-) diff --git a/src/frontend/inpcom.c b/src/frontend/inpcom.c index 22d882480..08e8af533 100644 --- a/src/frontend/inpcom.c +++ b/src/frontend/inpcom.c @@ -149,11 +149,12 @@ static char *inp_pathresolve(const char *name); static char *inp_pathresolve_at(char *name, char *dir); static char *search_plain_identifier(char *str, const char *identifier); void tprint(struct line *deck, int numb); -static void inp_add_levels(struct line *deck); -bool inp_check_scope_mod(unsigned short elem_level[], unsigned short mod_level[]); -bool inp_check_scope_sub(unsigned short x_level[], unsigned short subckt_level[]); +static struct nscope *inp_add_levels(struct line *deck); static char inp_get_elem_ident(char *type); -static void inp_rem_unused_models(struct line *deck); +static void inp_rem_unused_models(struct nscope *root, struct line *deck); +static struct line_assoc *find_subckt(struct nscope *scope, const char *name); +static struct modellist *find_model(struct nscope *scope, const char *name); + struct inp_read_t { struct line *cc; @@ -169,9 +170,8 @@ static void inp_poly_err(struct line *deck); static struct line * -xx_new_line(struct line *next, char *line, int linenum, int linenum_orig, unsigned short level[]) +xx_new_line(struct line *next, char *line, int linenum, int linenum_orig, struct nscope *level) { - int i; struct line *x = TMALLOC(struct line, 1); x->li_next = next; @@ -180,13 +180,7 @@ xx_new_line(struct line *next, char *line, int linenum, int linenum_orig, unsign x->li_line = line; x->li_linenum = linenum; x->li_linenum_orig = linenum_orig; - - if (level) - for (i = 0; i < NESTINGDEPTH; i++) - x->level[i] = level[i]; - else - for (i = 0; i < NESTINGDEPTH; i++) - x->level[i] = 0; + x->level = level; return x; } @@ -522,7 +516,7 @@ inp_readall(FILE *fp, char *dir_name, bool comfile, bool intfile) delete_libs(); - inp_add_levels(working); + struct nscope *root = inp_add_levels(working); inp_fix_for_numparam(subckt_w_params, working); @@ -531,7 +525,7 @@ inp_readall(FILE *fp, char *dir_name, bool comfile, bool intfile) comment_out_unused_subckt_models(working); // tprint(working, tpr++); - inp_rem_unused_models(working); + inp_rem_unused_models(root, working); // tprint(working, tpr++); subckt_params_to_param(working); @@ -2752,24 +2746,6 @@ inp_fix_subckt_multiplier(struct names *subckt_w_params, struct line *subckt_car } -/* a bogus search for a .subckt with given name, - * which does not honour scoping rules - */ - -static struct line * -bogus_find_subckt(struct line *d, const char *subckt_name) -{ - const size_t len = strlen(subckt_name); - for (; d; d = d->li_next) - if (ciprefix(".subckt", d->li_line)) { - const char *n = skip_ws(skip_non_ws(d->li_line)); - if ((strncmp(n, subckt_name, len) == 0) && (!n[len] || isspace_c(n[len]))) - break; - } - return d; -} - - static void inp_fix_inst_calls_for_numparam(struct names *subckt_w_params, struct line *deck) { @@ -2793,11 +2769,7 @@ inp_fix_inst_calls_for_numparam(struct names *subckt_w_params, struct line *deck char *subckt_name = inp_get_subckt_name(inst_line); if (found_mult_param(num_inst_params, inst_param_names)) { - struct line *d, *p = NULL; - - // iterate through the deck to find the subckt (last one defined wins) - for (d = deck; (d = bogus_find_subckt(d, subckt_name)) != NULL; d = d->li_next) - p = d; + struct line *p = find_subckt(c->level, subckt_name)->line; if (p) { int num_subckt_params = inp_get_params(p->li_line, subckt_param_names, subckt_param_values); @@ -2833,7 +2805,8 @@ inp_fix_inst_calls_for_numparam(struct names *subckt_w_params, struct line *deck if (find_name(subckt_w_params, subckt_name)) { struct line *d; - for (d = deck; (d = bogus_find_subckt(d, subckt_name)) != NULL; d = d->li_next) { + d = find_subckt(c->level, subckt_name)->line; + { char *subckt_line = d->li_line; subckt_line = skip_non_ws(subckt_line); subckt_line = skip_ws(subckt_line); @@ -2841,32 +2814,6 @@ inp_fix_inst_calls_for_numparam(struct names *subckt_w_params, struct line *deck int num_subckt_params = inp_get_params(subckt_line, subckt_param_names, subckt_param_values); int num_inst_params = inp_get_params(inst_line, inst_param_names, inst_param_values); - // make sure that if have inst params that one matches subckt - if (num_inst_params != 0) { - bool found_param_match = FALSE; - int j, k; - - for (j = 0; j < num_inst_params; j++) { - for (k = 0; k < num_subckt_params; k++) - if (strcmp(subckt_param_names[k], inst_param_names[j]) == 0) { - found_param_match = TRUE; - break; - } - if (found_param_match) - break; - } - - if (!found_param_match && inp_check_scope_sub(c->level, d->level)) { - // comment out .subckt and continue - while (d != NULL && !ciprefix(".ends", d->li_line)) { - *(d->li_line) = '*'; - d = d->li_next; - } - *(d->li_line) = '*'; - continue; - } - } - c->li_line = inp_fix_inst_line(inst_line, num_subckt_params, subckt_param_names, subckt_param_values, num_inst_params, inst_param_names, inst_param_values); for (i = 0; i < num_subckt_params; i++) { tfree(subckt_param_names[i]); @@ -2877,8 +2824,6 @@ inp_fix_inst_calls_for_numparam(struct names *subckt_w_params, struct line *deck tfree(inst_param_names[i]); tfree(inst_param_values[i]); } - - break; } } @@ -5922,10 +5867,9 @@ tprint(struct line *t, int numb) if (*(tmp->li_line) != '*') { fprintf(fd, "%6d %6d %s", tmp->li_linenum_orig, tmp->li_linenum, tmp->li_line); fprintf(fd, " level: "); - int i; - for (i = 0; i < NESTINGDEPTH; i++) { - fprintf(fd, "%3d", tmp->level[i]); - } + struct nscope *x = tmp->level; + for (; x; x = x->next) + fprintf(fd, "/%p", tmp->level); /* fixme */ fprintf(fd, "\n"); } fprintf(fd, "\n*********************************************************************************\n"); @@ -6739,17 +6683,90 @@ inp_meas_current(struct line *deck) } +static struct line_assoc * +find_subckt_1(struct nscope *scope, const char *name) { + struct line_assoc *p = scope->subckts; + for (; p; p = p->next) + if (eq(name, p->name)) + break; + return p; +} + + +static struct line_assoc * +find_subckt(struct nscope *scope, const char *name) { + for(; scope; scope = scope->next) { + struct line_assoc *p = find_subckt_1(scope, name); + if (p) + return p; + } + return NULL; +} + + +static void +add_subckt(struct nscope *scope, struct line *subckt_line) +{ + char *n = skip_ws(skip_non_ws(subckt_line->li_line)); + char *name = copy_substring(n, skip_non_ws(n)); + if (find_subckt_1(scope, name)) { + fprintf(stderr, "redefinition of .subckt %s\n", name); + exit(1); + } + struct line_assoc *entry = TMALLOC(struct line_assoc, 1); + entry->name = name; + entry->line = subckt_line; + entry->next = scope->subckts; + scope->subckts = entry; +} + + +/* linked list of models, includes use info */ +struct modellist +{ + struct line *model; + char *modelname; + bool used; + char elemb; + struct modellist *next; +}; + + +static struct modellist * +find_model_1(struct nscope *scope, const char *name) { + struct modellist *p = scope->models; + for (; p; p = p->next) + if (model_name_match(name, p->modelname)) + break; + return p; +} + + +static struct modellist * +find_model(struct nscope *scope, const char *name) { + for(; scope; scope = scope->next) { + struct modellist *p = find_model_1(scope, name); + if (p) + return p; + } + return NULL; +} + + /* scan through deck and add level information to all struct line * depending on nested subcircuits */ -static void +static struct nscope * inp_add_levels(struct line *deck) { - struct line *card, *card_prev = deck; - int skip_control = 0, subs = 0, i; - unsigned short levelinfo[NESTINGDEPTH]; + struct line *card; + int skip_control = 0; - for (i = 0; i < NESTINGDEPTH; i++) - levelinfo[i] = 0; + struct nscope *root = TMALLOC(struct nscope, 1); + root->next = NULL; + root->subckts = NULL; + root->models = NULL; + + struct nscope *lvl = root; for (card = deck; card; card = card->li_next) { @@ -6768,71 +6785,36 @@ inp_add_levels(struct line *deck) continue; } - if (*curr_line == '*') - continue; - if (*curr_line == '.') { if (ciprefix(".subckt", curr_line)) { - levelinfo[subs++]++; - for (i = 0; i < NESTINGDEPTH; i++) - card->level[i] = levelinfo[i]; - card_prev = card; + add_subckt(lvl, card); + card->level = lvl; + lvl = TMALLOC(struct nscope, 1); + // lvl->name = ..., or just point to the deck + lvl->next = card->level; + lvl->subckts = NULL; + lvl->models = NULL; } else if (ciprefix(".ends", curr_line)) { - subs--; - for (i = 0; i < NESTINGDEPTH; i++) - if (i < subs) - card->level[i] = card_prev->level[i]; - else - card->level[i] = 0; - card_prev = card; + if (lvl == root) { + fprintf(stderr, ".suckt/.ends not balanced\n"); + exit(1); + } + lvl = card->level = lvl->next; } else { - for (i = 0; i < NESTINGDEPTH; i++) - card->level[i] = card_prev->level[i]; - card_prev = card; + card->level = lvl; } } else { - for (i = 0; i < NESTINGDEPTH; i++) - card->level[i] = card_prev->level[i]; - card_prev = card; + card->level = lvl; } } -} + if (lvl != root) + fprintf(stderr, "nesting error\n"); -/* return TRUE if element is within scope of model */ -bool -inp_check_scope_mod(unsigned short elem_level[], unsigned short mod_level[]) -{ - int i; - /* model at top level, accessible from all devices */ - if (mod_level[0] == 0) - return TRUE; - /* model at nesting level */ - for (i = 0; i < NESTINGDEPTH - 1; i++) - if ((elem_level[i] > 0) && (elem_level[i] == mod_level[i]) && (mod_level[i + 1] == 0)) - return TRUE; - if ((elem_level[NESTINGDEPTH - 1] > 0) && (elem_level[NESTINGDEPTH - 1] == mod_level[NESTINGDEPTH - 1])) - return TRUE; - return FALSE; -} - - -/* not yet checked. - * Question: how to express overloading a sub at a lower level ? */ -bool -inp_check_scope_sub(unsigned short x_level[], unsigned short subckt_level[]) -{ - int i; - /* subcircuit at top level, accessible from all x lines */ - if ((subckt_level[0] > 0) && (subckt_level[1] == 0)) - return TRUE; - for (i = 1; i < NESTINGDEPTH - 1; i++) - if ((x_level[i] == subckt_level[i]) && (x_level[i + 1] == 0)) - return TRUE; - return FALSE; + return root; } @@ -6896,23 +6878,41 @@ inp_get_elem_ident(char *type) } -/* linked list of models, includes use info */ -struct modellist +static void +rem_unused_xxx(struct nscope *level) { - struct line *model; - char *modelname; - bool used; - char elemb; - struct modellist *next; -}; + struct modellist *m = level->models; + while (m) { + struct modellist *next_m = m->next; + if (!m->used) + m->model->li_line[0] = '*'; + tfree(m->modelname); + tfree(m); + m = next_m; + } + level->models = NULL; + + struct line_assoc *p = level->subckts; + for (; p; p = p->next) + rem_unused_xxx(p->line->li_next->level); +} + static void -inp_rem_unused_models(struct line *deck) +mark_all_binned(struct nscope *scope, char *name) +{ + struct modellist *p = scope->models; + + for (; p; p = p->next) + if (model_name_match(name, p->modelname)) + p->used = TRUE; +} + + +static void +inp_rem_unused_models(struct nscope *root, struct line *deck) { struct line *card; - struct modellist *modl = NULL, *modl_new; - int nested, i; - struct modellist *modn; int skip_control = 0; /* create a list of .model */ @@ -6937,17 +6937,19 @@ inp_rem_unused_models(struct line *deck) continue; if (ciprefix(".model", curr_line)) { + struct modellist *modl_new; modl_new = TMALLOC(struct modellist, 1); char *model_type = get_model_type(curr_line); modl_new->elemb = inp_get_elem_ident(model_type); modl_new->modelname = get_subckt_model_name(curr_line); modl_new->model = card; modl_new->used = FALSE; - modl_new->next = modl; - modl = modl_new; + modl_new->next = card->level->models; + card->level->models = modl_new; tfree(model_type); } } + /* scan through all element lines that require or may need a model */ for (card = deck; card; card = card->li_next) { @@ -6986,10 +6988,6 @@ inp_rem_unused_models(struct line *deck) break; } - for (nested = 0; nested < NESTINGDEPTH; nested++) - if (card->level[nested] == 0) - break; - /* check if correct model name */ int num_terminals = get_number_terminals(curr_line); /* num_terminals may be 0 for a elements */ @@ -7001,56 +6999,24 @@ inp_rem_unused_models(struct line *deck) elem_model_name = get_model_name(curr_line, num_terminals); if (is_a_modelname(elem_model_name)) { - /* if element is on top level, do faster here */ - if (nested == 0) { - for (modn = modl; modn; modn = modn->next) - /* check if model is at top level, element is o.k., and model name is fitting */ - if ((modn->model->level[0] == 0) && (*curr_line == modn->elemb) && model_name_match(elem_model_name, modn->modelname)) - modn->used = TRUE; - } - else { - /* scan through levels, starting with element level */ - for (i = nested - 1; i >= 0; i--) { - bool got_a_model = FALSE; - for (modn = modl; modn; modn = modn->next) { - /* check if element o.k., model name is fitting, and level is o.k. */ - if ((*curr_line == modn->elemb) && model_name_match(elem_model_name, modn->modelname) && (card->level[i] == modn->model->level[i])) { - modn->used = TRUE; - got_a_model = TRUE; - /* repeat for binning models, leave immediately after lowest possible level matches */ - } - /* model is at top level, element level does not matter */ - if ((i == 0) && (*curr_line == modn->elemb) && model_name_match(elem_model_name, modn->modelname) && (modn->model->level[i] == 0)) { - modn->used = TRUE; - got_a_model = TRUE; - /* repeat for binning models, leave immediately after lowest possible level matches */ - } - } - if (got_a_model) { - tfree(elem_model_name); - goto nextcard; - } - } + + struct modellist *m = find_model(card->level, elem_model_name); + if (m) { + if (*curr_line != m->elemb) + fprintf(stderr, "warning, model type mismatch\n"); + mark_all_binned(m->model->level, elem_model_name); + } else { + fprintf(stderr, "warning, can't find model %s\n", elem_model_name); } + + } else { + fprintf(stderr, "warning, not a valid modelname %s\n", elem_model_name); } + tfree(elem_model_name); } - -nextcard: - ; } - /* discard all unused models */ - for (modn = modl; modn; modn = modn->next) - if (modn->used == FALSE) - modn->model->li_line[0] = '*'; - - /* remove modellist */ - for (modn = modl; modn; ) { - struct modellist *modn_prev; - tfree(modn->modelname); - modn_prev = modn; - modn = modn->next; - tfree(modn_prev); - } + // disable unused .model lines, and free the models assoc lists + rem_unused_xxx(root); } diff --git a/src/frontend/numparam/numpaif.h b/src/frontend/numparam/numpaif.h index 94d2beaff..bf570d2a6 100644 --- a/src/frontend/numparam/numpaif.h +++ b/src/frontend/numparam/numpaif.h @@ -11,10 +11,12 @@ #define NUPASUBDONE 2 #define NUPAEVALDONE 3 +struct nscope; + extern char *nupa_copy(char *s, int linenum); extern int nupa_eval(char *s, int linenum, int orig_linenum); extern int nupa_signal(int sig, char *info); -extern void nupa_scan(char * s, int linenum, int is_subckt, unsigned short level[]); +extern void nupa_scan(char * s, int linenum, int is_subckt, struct nscope *level); extern void nupa_list_params(FILE *cp_out); extern double nupa_get_param(char *param_name, int *found); extern void nupa_add_param(char *param_name, double value); diff --git a/src/frontend/numparam/numparam.h b/src/frontend/numparam/numparam.h index 337c36801..9ce703026 100644 --- a/src/frontend/numparam/numparam.h +++ b/src/frontend/numparam/numparam.h @@ -28,7 +28,7 @@ typedef struct entry_s { int ivl; /* int value or string buffer index */ char *sbbase; /* string buffer base address if any */ struct entry_s *pointer; /* pointer chain */ - unsigned short levelinfo[NESTINGDEPTH]; + struct nscope *levelinfo; } entry_t; @@ -55,7 +55,7 @@ typedef struct { /* the input scanner data structure */ void initdico(dico_t *); int donedico(dico_t *); void dico_free_entry(entry_t *); -bool defsubckt(dico_t *, char *s, int w, char categ, unsigned short level[]); +bool defsubckt(dico_t *, char *s, int w, char categ, struct nscope *level); int findsubckt(dico_t *, char *s, SPICE_DSTRINGPTR subname); bool nupa_substitute(dico_t *, char *s, char *r, bool err); bool nupa_assignment(dico_t *, char *s, char mode); @@ -63,5 +63,5 @@ bool nupa_subcktcall(dico_t *, char *s, char *x, bool err); void nupa_subcktexit(dico_t *); dico_t *nupa_fetchinstance(void); char getidtype(dico_t *, char *s); -entry_t *attrib(dico_t *, NGHASHPTR htable, char *t, char op, unsigned short level[]); +entry_t *attrib(dico_t *, NGHASHPTR htable, char *t, char op, struct nscope *level); void del_attrib(void *); diff --git a/src/frontend/numparam/spicenum.c b/src/frontend/numparam/spicenum.c index 31292beb1..ed37d4429 100644 --- a/src/frontend/numparam/spicenum.c +++ b/src/frontend/numparam/spicenum.c @@ -533,7 +533,7 @@ nupa_done(void) /* SJB - Scan the line for subcircuits */ void -nupa_scan(char *s, int linenum, int is_subckt, unsigned short level[]) +nupa_scan(char *s, int linenum, int is_subckt, struct nscope *level) { if (is_subckt) defsubckt(dicoS, s, linenum, 'U', level); diff --git a/src/frontend/numparam/xpressn.c b/src/frontend/numparam/xpressn.c index 2cd4b3183..876a86f8a 100644 --- a/src/frontend/numparam/xpressn.c +++ b/src/frontend/numparam/xpressn.c @@ -421,7 +421,7 @@ fetchnumentry(dico_t *dico, char *s, bool *perr) /******* writing dictionary entries *********/ entry_t * -attrib(dico_t *dico, NGHASHPTR htable_p, char *t, char op, unsigned short levelinfo[]) +attrib(dico_t *dico, NGHASHPTR htable_p, char *t, char op, struct nscope *levelinfo) { /* seek or attribute dico entry number for string t. Option op='N' : force a new entry, if tos>level and old is valid. @@ -436,14 +436,11 @@ attrib(dico_t *dico, NGHASHPTR htable_p, char *t, char op, unsigned short leveli } if (!entry) { - int i; entry = TMALLOC(entry_t, 1); entry->symbol = strdup(t); entry->tp = '?'; /* signal Unknown */ entry->level = dico->stack_depth; - if (levelinfo) - for (i = 0; i < NESTINGDEPTH; i++) - entry->levelinfo[i] = levelinfo[i]; + entry->levelinfo = levelinfo; nghash_insert(htable_p, t, entry); } @@ -475,7 +472,7 @@ nupa_define(dico_t *dico, double z, /* float value if any */ int w, /* integer value if any */ char *base, /* string pointer if any */ - unsigned short level[]) /* level info */ + struct nscope *level) /* level info */ { /*define t as real or integer, opcode= 'N' impose a new item under local conditions. @@ -531,6 +528,7 @@ nupa_define(dico_t *dico, /* FIXME: better do this recursively in a new function */ /* No new entry defined, but previous entry with same name returned from function attrib(), compare levels, if not equal, o.k. (for now) */ +#if 0 unsigned short newlevel[NESTINGDEPTH]; unsigned short oldlevel[NESTINGDEPTH]; int i; @@ -553,6 +551,7 @@ nupa_define(dico_t *dico, && (newlevel[2] > 0) && (oldlevel[2] > 1) && (newlevel[3] == 0) && (oldlevel[3] == 0)) fprintf(stderr, "Warning: %s is already used,\n cannot be redefined\n", t); +#endif } } @@ -561,7 +560,7 @@ nupa_define(dico_t *dico, bool -defsubckt(dico_t *dico, char *s, int w, char categ, unsigned short level[]) +defsubckt(dico_t *dico, char *s, int w, char categ, struct nscope *level) /* called on 1st pass of spice source code, to enter subcircuit (categ=U) and model (categ=O) names */ diff --git a/src/include/ngspice/fteinp.h b/src/include/ngspice/fteinp.h index 4f8e6623e..65f6faee5 100644 --- a/src/include/ngspice/fteinp.h +++ b/src/include/ngspice/fteinp.h @@ -21,7 +21,7 @@ struct line { char *li_error; struct line *li_next; struct line *li_actual; - unsigned short level[NESTINGDEPTH]; + struct nscope *level; } ; /* Listing types. */ diff --git a/src/include/ngspice/inpdefs.h b/src/include/ngspice/inpdefs.h index cf575c2d3..c95916b39 100644 --- a/src/include/ngspice/inpdefs.h +++ b/src/include/ngspice/inpdefs.h @@ -62,6 +62,20 @@ struct INPtables{ GENmodel *defZmod; }; +struct modellist; + +struct nscope { + struct nscope *next; + struct line_assoc *subckts; + struct modellist *models; +}; + +struct line_assoc { + const char *name; + struct line *line; + struct line_assoc *next; +}; + struct card{ int linenum; int linenum_orig; @@ -69,7 +83,7 @@ struct card{ char *error; card *nextcard; card *actualLine; - unsigned short level[NESTINGDEPTH]; + struct nscope *level; }; /* structure used to save models in after they are read during pass 1 */