From f0d3b7c976a1279c0eaa48bcf4de664e11bafeaf Mon Sep 17 00:00:00 2001 From: pnenzi Date: Thu, 15 Jan 2009 16:46:31 +0000 Subject: [PATCH] Introduced the possibility to look for parameters in models and not only in devices. --- ChangeLog | 11 +++ src/frontend/spiceif.c | 207 ++++++++++++++++++++++++++++++++++++++++- src/frontend/spiceif.h | 1 + src/frontend/vectors.c | 15 ++- src/include/fteext.h | 1 + src/main.c | 6 +- 6 files changed, 232 insertions(+), 9 deletions(-) diff --git a/ChangeLog b/ChangeLog index 77e262df3..33564f21f 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,14 @@ +2009-01-15 Paolo Nenzi + * src/frontend/{spiceif.c, spiceif.h, vectors.c}, src/include/fteext.h, + * src/main.c: + 3: A new function finddev_special() has been introduced to look for + references like @BC107[is] and to verify if we asked for a model + or a device and thus call the spif_getparam_special() correctly + in vectors.c. The new @ syntax is @{model,device}[parameter]. + - A. Roldan - Espice. + Note: I have modified the implementation putting the + spif_getparam_special() in the if_getparam definition in main.c + 2009-01-15 Dietmar Warning * src/include/wstdio.h: read fct. prototype for older MSC compiler * src/misc/alloc.c: heap also needed under windows with tcl diff --git a/src/frontend/spiceif.c b/src/frontend/spiceif.c index d4b833be1..19f1e205e 100644 --- a/src/frontend/spiceif.c +++ b/src/frontend/spiceif.c @@ -81,6 +81,8 @@ static int doset(void *ckt, int typecode, GENinstance *dev, GENmodel *mod, IFparm *opt, struct dvec *val); static int finddev(void *ck, char *name, void **devptr, void **modptr); +/*espice fix integration */ +static int finddev_special(char *ck, char *name, void **devptr, void **modptr, int *device_or_model); /* Input a single deck, and return a pointer to the circuit. */ @@ -550,6 +552,182 @@ if_errstring(int code) return (INPerror(code)); } +/* Get pointers to a device, its model, and its type number given the name. If + * there is no such device, try to find a model with that name + * device_or_model says if we are referencing a device or a model. + * finddev_special(ck, name, devptr, modptr,device_or_model): + * Introduced to look for correct reference in expression like print @BC107 [is] + * and find out whether a model or a device parameter is referenced and properly + * call the spif_getparam_special (ckt, name, param, ind, do_model) function in + * vector.c - A. Roldan (espice). + */ +static int +finddev_special( + char *ck, + char *name, + void **devptr, + void **modptr, + int *device_or_model) +{ + int err; + int type = -1; + + err = (*(ft_sim->findInstance))((void *)ck,&type,devptr,name,NULL,NULL); + if(err == OK) + { + *device_or_model=0; + return(type); + } + type = -1; + *devptr = (void *)NULL; + err = (*(ft_sim->findModel))((void *)ck,&type,modptr,name); + if(err == OK) + { + *device_or_model=1; + return(type); + } + *modptr = (void *)NULL; + *device_or_model=2; + return(-1); + +} + +/* Get a parameter value from the circuit. If name is left unspecified, + * we want a circuit parameter. Now works both for devices and models. + * A.Roldan (espice) + */ +struct variable * +spif_getparam_special(void *ckt,char **name,char *param,int ind,int do_model) +{ + struct variable *vv = NULL, *tv; + IFvalue *pv; + IFparm *opt; + int typecode, i, modelo_dispositivo; + GENinstance *dev=(GENinstance *)NULL; + GENmodel *mod=(GENmodel *)NULL; + IFdevice *device; + + /* fprintf(cp_err, "Calling if_getparam(%s, %s)\n", *name, param); */ + + if (!param || (param && eq(param, "all"))) + { + INPretrieve(name,(INPtables *)ft_curckt->ci_symtab); + typecode = finddev_special(ckt, *name, (void**)&dev, (void**)&mod,&modelo_dispositivo); + if (typecode == -1) + { + fprintf(cp_err,"Error: no such device or model name %s\n",*name); + return (NULL); + } + device = ft_sim->devices[typecode]; + if(!modelo_dispositivo) + { + /* It is a device */ + for (i = 0; i < *(device->numInstanceParms); i++) + { + opt = &device->instanceParms[i]; + if(opt->dataType & IF_REDUNDANT || !opt->description) continue; + if(!(opt->dataType & IF_ASK)) continue; + pv = doask(ckt, typecode, dev, mod, opt, ind); + if (pv) + { + tv = parmtovar(pv, opt); + + /* With the following we pack the name and the acronym of the parameter */ + { + char auxiliar[70],*aux_pointer; + sprintf(auxiliar,"%s [%s]",tv->va_name, device->instanceParms[i].keyword); + aux_pointer=tv->va_name; + free(aux_pointer); + tv->va_name = copy(auxiliar); + } + if (vv) tv->va_next = vv; + vv = tv; + } + else + fprintf(cp_err,"Internal Error: no parameter '%s' on device '%s'\n", + device->instanceParms[i].keyword,device->name); + } + return (vv); + } + else /* Is it a model or a device ? */ + { + /* It is a model */ + for (i = 0; i < *(device->numModelParms); i++) + { + opt = &device->modelParms[i]; + if(opt->dataType & IF_REDUNDANT || !opt->description) continue; + + /* We check that the parameter is interesting and therefore is + * implemented in the corresponding function ModelAsk. Originally + * the argument of "if" was: || (opt->dataType & IF_STRING)) continue; + * so, a model parameter defined like OP("type", MOS_SGT_MOD_TYPE, + * IF_STRING, N-channel or P-channel MOS") would not be printed. + */ + + /* if(!(opt->dataType & IF_ASK ) || (opt->dataType & IF_UNINTERESTING ) || (opt->dataType & IF_STRING)) continue; */ + if(!(opt->dataType & IF_ASK ) || (opt->dataType & IF_UNINTERESTING )) continue; + pv = doask(ckt, typecode, dev, mod, opt, ind); + if (pv) + { + tv = parmtovar(pv, opt); + /* Inside parmtovar: + * 1. tv->va_name = copy(opt->description); + * 2. Copy the type of variable of IFparm into a variable (thus parm-to-var) + * vv->va_type = opt->dataType + * The long description of the parameter: + * IFparm MOS_SGTmPTable[] = { /* model parameters */ + * OP("type", MOS_SGT_MOD_TYPE, IF_STRING, "N-channel or P-channel MOS") + * goes into tv->va_name to put braces around the parameter of the model + * tv->va_name += device->modelParms[i].keyword; + */ + { + char auxiliar[70],*aux_pointer; + sprintf(auxiliar,"%s [%s]",tv->va_name,device->modelParms[i].keyword); + aux_pointer=tv->va_name; + free(aux_pointer); + tv->va_name = copy(auxiliar); + /* strcpy(aux_pointer,auxiliar); */ + } + /* tv->va_string=device->modelParms[i].keyword; Put the name of the variable */ + if (vv) + { + tv->va_next = vv; + } + vv = tv; + } + else + fprintf(cp_err,"Internal Error: no parameter '%s' on device '%s'\n",device->modelParms[i].keyword,device->name); + } + return (vv); + } + } + else if (param) + { + INPretrieve(name,(INPtables *)ft_curckt->ci_symtab); + typecode = finddev_special(ckt, *name, (void**)&dev, (void**)&mod,&modelo_dispositivo); + if (typecode == -1) + { + fprintf(cp_err,"Error: no such device or model name %s\n",*name); + return (NULL); + } + device = ft_sim->devices[typecode]; + opt = parmlookup(device, &dev, param, modelo_dispositivo, 0); + if (!opt) + { + fprintf(cp_err, "Error: no such parameter %s.\n",param); + return (NULL); + } + pv = doask(ckt, typecode, dev, mod, opt, ind); + if (pv) + vv = parmtovar(pv, opt); + return (vv); + } else + return (if_getstat(ckt, *name)); +} + + + + /* Get a parameter value from the circuit. If name is left unspecified, * we want a circuit parameter. */ @@ -764,14 +942,35 @@ parmtovar(IFvalue *pv, IFparm *opt) break; case IF_REALVEC: vv->va_type = VT_LIST; - for (i = 0; i < pv->v.numValue; i++) { + for (i = 0; i < pv->v.numValue; i++) + { nv = alloc(struct variable); nv->va_next = vv->va_vlist; vv->va_vlist = nv; nv->va_type = VT_REAL; - nv->va_real = pv->v.vec.rVec[i]; - } - break; + /* Change this so that the values are printed in order and + * not in inverted order as happens in the conversion process. + * Originally was nv->va_real = pv->v.vec.rVec[i]; + */ + nv->va_real = pv->v.vec.rVec[pv->v.numValue-i-1]; + } + /* It is a linked list where the first node is a variable + * pointing to the different values of the variables. + * + * To access the values of the real variable vector must be + * vv->va_V.vV_real=valor node ppal that is of no use. + * + * In the case of Vin_sin 1 0 sin (0 2 2000) + * and of print @vin_sin[sin] + * + * vv->va_V.vV_list->va_V.vV_real=2000 + * vv->va_V.vV_list->va_next->va_V.vV_real=2 + * vv->va_V.vV_list->va_next->va_next->va_V.vV_real=0 + * So the list is starting from behind, but no problem + * This works fine + */ + + break; default: fprintf(cp_err, "parmtovar: Internal Error: bad PARM type %d.\n", diff --git a/src/frontend/spiceif.h b/src/frontend/spiceif.h index bc7943e0f..be6b66551 100644 --- a/src/frontend/spiceif.h +++ b/src/frontend/spiceif.h @@ -14,6 +14,7 @@ void if_dump(void *ckt, FILE *file); void if_cktfree(void *ckt, char *tab); char * if_errstring(int code); struct variable * spif_getparam(void *ckt, char **name, char *param, int ind, int do_model); +struct variable * spif_getparam_special(void *ckt,char **name,char *param,int ind,int do_model); void if_setparam_model(void *ckt, char **name, char *val); void if_setparam(void *ckt, char **name, char *param, struct dvec *val, int do_model); int if_analQbyName(void *ckt, int which, void *anal, char *name, IFvalue *parm); diff --git a/src/frontend/vectors.c b/src/frontend/vectors.c index 3ac5a1c1e..6cffa70b6 100644 --- a/src/frontend/vectors.c +++ b/src/frontend/vectors.c @@ -476,7 +476,18 @@ vec_copy(struct dvec *v) nv->v_gridtype = v->v_gridtype; nv->v_plottype = v->v_plottype; nv->v_length = v->v_length; - nv->v_rlength = 0; /*XXX???*/ + + /* Modified to copy the rlength of origin to destination vecor + * instead of always putting it to 0. + * As when it comes to make a print does not leave M1 @ @ M1 = 0.0, + * to do so in the event that rlength = 0 not print anything on screen + * nv-> v_rlength = 0; + * Default -> v_rlength = 0 and only if you come from a print or M1 @ + * @ M1 [all] rlength = 1, after control is one of + * if (v-> v_rlength == 0) com_print (wordlist * wl) + */ + nv->v_rlength = v->v_rlength; + nv->v_outindex = 0; /*XXX???*/ nv->v_linestyle = 0; /*XXX???*/ nv->v_color = 0; /*XXX???*/ @@ -621,7 +632,7 @@ vec_free_x(struct dvec *v) pl->pl_scale = NULL; } } - tfree(v->v_name); + if (v->v_name) tfree(v->v_name); if (v->v_realdata) tfree(v->v_realdata); if (v->v_compdata) tfree(v->v_compdata); tfree(v); diff --git a/src/include/fteext.h b/src/include/fteext.h index 2ec80c277..49d5dfde6 100644 --- a/src/include/fteext.h +++ b/src/include/fteext.h @@ -449,6 +449,7 @@ extern int if_sens_run(); extern struct variable *(*if_getparam)(); extern struct variable *nutif_getparam(); extern struct variable *spif_getparam(); +extern struct variable *spif_getparam_special(); extern void if_cktfree(); extern void if_dump(); extern int if_option(); diff --git a/src/main.c b/src/main.c index 81714e669..df4bf664d 100644 --- a/src/main.c +++ b/src/main.c @@ -542,7 +542,7 @@ show_help(void) printf("Usage: %s [OPTION]... [FILE]...\n" "Simulate the electical circuits in FILE.\n" "\n" - " -a --autorun run the loaded netlist\n" + " -a --autorun run the loaded netlist\n" " -b, --batch process FILE in batch mode\n" " -c, --circuitfile=FILE set the circuitfile\n" " -i, --interactive run in interactive mode\n" @@ -749,7 +749,7 @@ main(int argc, char **argv) {"help", 0, 0, 'h'}, {"version", 0, 0, 'v'}, {"batch", 0, 0, 'b'}, - {"autorun", 0, 0, 'a'}, + {"autorun", 0, 0, 'a'}, {"circuitfile", 0, 0, 'c'}, {"interactive", 0, 0, 'i'}, {"no-spiceinit", 0, 0, 'n'}, @@ -873,7 +873,7 @@ main(int argc, char **argv) #endif } /* orflag */ #ifdef SIMULATOR - if_getparam = spif_getparam; + if_getparam = spif_getparam_special; #else if_getparam = nutif_getparam;