From c858975529462bd964b8f6d874f8f2554d587ef3 Mon Sep 17 00:00:00 2001 From: h_vogt Date: Sun, 18 Sep 2011 09:03:55 +0000 Subject: [PATCH] faster Greens's fft, altermod command --- src/frontend/com_fft.c | 66 +- src/frontend/device.c | 129 +++- src/frontend/spiceif.c | 1645 ++++++++++++++++++++-------------------- 3 files changed, 992 insertions(+), 848 deletions(-) diff --git a/src/frontend/com_fft.c b/src/frontend/com_fft.c index 45f22250d..080e5906f 100644 --- a/src/frontend/com_fft.c +++ b/src/frontend/com_fft.c @@ -7,6 +7,8 @@ Author: 2008 Holger Vogt * Code to do fast fourier transform on data. */ +#define GREEN /* select fast Green's fft */ + #include #include #include @@ -31,6 +33,10 @@ com_fft(wordlist *wl) struct dvec *f, *vlist, *lv = NULL, *vec; struct pnode *names, *first_name; +#ifdef GREEN + int mm; +#endif + double *reald, *imagd; int size, sign, order; double scale, sigma; @@ -50,11 +56,20 @@ com_fft(wordlist *wl) span = time[tlen-1] - time[0]; delta_t = span/(tlen - 1); +#ifdef GREEN + // size of input vector is power of two and larger than spice vector + size = 1; + mm = 0; + while (size < tlen) { + size <<= 1; + mm++; + } +#else /* size of input vector is power of two and larger than spice vector */ size = 1; while (size < tlen) size *= 2; - +#endif /* output vector has length of size/2 */ fpts = size/2; @@ -233,7 +248,19 @@ com_fft(wordlist *wl) reald[j] = 0.0; imagd[j] = 0.0; } - +#ifdef GREEN + // Green's FFT + fftInit(mm); + rffts(reald, mm, 1); + fftFree(); + scale = size; +/* Re(x[0]), Re(x[N/2]), Re(x[1]), Im(x[1]), Re(x[2]), Im(x[2]), ... Re(x[N/2-1]), Im(x[N/2-1]). */ + for (j=0;jpl_name = copy("PSD"); plot_cur->pl_date = copy(datestring( )); - freq = TMALLOC(double, fpts); + freq = TMALLOC(double, fpts + 1); f = alloc(struct dvec); ZERO(f, struct dvec); f->v_name = copy("frequency"); @@ -450,19 +478,19 @@ com_psd(wordlist *wl) f->v_realdata = freq; vec_new(f); - for (i = 0; iv_realdata; /* real input data */ - fdvec[i] = TMALLOC(ngcomplex_t, fpts); /* complex output data */ + fdvec[i] = TMALLOC(ngcomplex_t, fpts + 1); /* complex output data */ f = alloc(struct dvec); ZERO(f, struct dvec); f->v_name = vec_basename(vec); f->v_type = SV_NOTYPE; //vec->v_type; f->v_flags = (VF_COMPLEX | VF_PERMANENT); - f->v_length = fpts; + f->v_length = fpts + 1; f->v_compdata = fdvec[i]; vec_new(f); vec = vec->v_link2; @@ -480,6 +508,7 @@ com_psd(wordlist *wl) // scale = 0.66; for (i = 0; i>1; for (j=0; jwl_word)) { + newfile = TRUE; + } + fileword = fileword->wl_next; + } + if (newfile) + com_alter_mod(wl); + else + com_alter_common(wl, 1); } static void @@ -1097,7 +1111,7 @@ com_alter_common(wordlist *wl, int do_model) 3) 'expression' string. Spaces around the '=' sign have to be removed. This is provided - by inp_remove_excess_ws(). + by inp_remove_excess_ws(). But take care if command is entered manually! If the 'altermod' argument is 'altermod m1 vth0=0.7', 'm1' has to be kept as the element in wl2 before splitting inserts the three new elements. @@ -1112,10 +1126,20 @@ com_alter_common(wordlist *wl, int do_model) while(argument[i]!='=' && argument[i]!='\0'){ i++; } - /* ...and if found split argument into three chars and make a new wordlist */ + /* argument may be '=', then do nothing + or =token + or token= + or token1=token2 + ...and if found split argument into three chars and make a new wordlist */ if(argument[i]!='\0'){ - /* We found '=' */ - eqfound = TRUE; + /* We found '=' */ + eqfound = TRUE; + if (strlen(argument) == 1) { + wl = wl->wl_next; + step = -1; + wl2 = wlin; + } + else if (strlen(argument) > 1) { arglist = TMALLOC(char*, 4); arglist[3] = NULL; arglist[0] = TMALLOC(char, i + 1); @@ -1136,6 +1160,7 @@ com_alter_common(wordlist *wl, int do_model) /* free arglist */ for (n=0; n < 3; n++) tfree(arglist[n]); tfree(arglist); + } } else { /* deal with 'altermod m1 vth0=0.7' by moving forward beyond 'm1' */ @@ -1146,7 +1171,8 @@ com_alter_common(wordlist *wl, int do_model) if(eqfound) { /* step back in the wordlist, if we have moved forward, to catch 'm1' */ - for(n=step;n>0;n--) wl2 = wl2->wl_prev; + for(n=step;n>0;n--) + wl2 = wl2->wl_prev; } else { /* no equal sign found, probably a pre3f4 input format 'alter device value' @@ -1192,7 +1218,7 @@ com_alter_common(wordlist *wl, int do_model) wlin->wl_next = wleq; /* step back until 'alter' or 'altermod' is found, then move one step forward */ - while (!ciprefix(wlin->wl_word,"alter")) + while (!ciprefix("alter",wlin->wl_word)) //while (!ciprefix(wlin->wl_word,"alter")) wlin = wlin->wl_prev; wlin = wlin->wl_next; wl2 = wlin; @@ -1225,7 +1251,7 @@ com_alter_common(wordlist *wl, int do_model) while (words != eqword) { p = words->wl_word; if (param) { - fprintf(cp_err, "Error: excess parameter name \"%s\" ignored.\n", + fprintf(cp_err, "Warning: excess parameter name \"%s\" ignored.\n", p); } else if (dev) { param = words->wl_word; @@ -1252,8 +1278,9 @@ com_alter_common(wordlist *wl, int do_model) words = eqword->wl_next; /* skip next line if words is a vector */ - if(!eq(words->wl_word, "[")) + if(!eq(words->wl_word, "[")) { names = ft_getpnames(words, FALSE); + } else names = NULL; if (!names) { /* Put this to try to resolve the case of @@ -1347,3 +1374,87 @@ devexpand(char *name) wl_sort(wl); return (wl); } + +/* altermod nch file=modelparam.mod + load model file and overwrite model nch with + all new parameters */ +static void com_alter_mod(wordlist *wl) +{ + FILE *modfile; + wordlist *nword, *newcommand; + char *filename=NULL, *modelname, *eqword, *input, *modelline=NULL, *inptoken, *newtype; + struct line *modeldeck, *tmpdeck; + char *readmode = "r"; + modelname = copy(wl->wl_word); + nword = wl->wl_next; + input = wl_flatten(nword); + eqword = strstr(input, "="); + if (eqword) { + eqword++; + while(*eqword == ' ') + eqword++; + if(eqword=='\0') + fprintf(cp_err, "Error: no filename given\n"); + filename = copy(eqword); + } + else { + eqword = strstr(input, "file"); + eqword += 4; + while(*eqword == ' ') + eqword++; + if(eqword=='\0') + fprintf(cp_err, "Error: no filename given\n"); + filename = copy(eqword); + } + modfile = inp_pathopen(filename, readmode); + inp_readall(modfile, &modeldeck, 0, ngdirname(filename), 0); + tfree(input); + tfree(filename); + /* get the first line starting with *model */ + for (tmpdeck = modeldeck; tmpdeck; tmpdeck = tmpdeck->li_next) + if (ciprefix("*model", tmpdeck->li_line)) { + modelline = tmpdeck->li_line; + break; + } + if (modelline) { + char **arglist; + char *newmodelname; + arglist = TMALLOC(char*, 4); + inptoken = gettok(&modelline); /* *model */ + tfree(inptoken); + newmodelname = gettok(&modelline); /* modelname */ + newtype = gettok(&modelline); /* model type */ + /* test if level and type are o.k. */ + /* FIXME: don't know how to do that! */ + /* call each token and do altermod */ + arglist[0] = copy("altermod"); + arglist[1] = modelname; + arglist[3] = NULL; + while ((inptoken = gettok(&modelline)) != NULL) { + /* exclude level and version */ + if (ciprefix("version", inptoken) || ciprefix("level", inptoken)) { + tfree(inptoken); + continue; + } + arglist[2] = inptoken; + /* create a new wordlist from array arglist */ + newcommand = wl_build(arglist); + com_alter_common(newcommand->wl_next, 1); + wl_free(newcommand); + tfree(inptoken); + } + tfree(newmodelname); + tfree(newtype); + } +} + + /* Figure out if right hand side is a model + if (names && (do_model == 1)) { + INPmodel *inpmod = NULL; + if_setparam_model(ft_curckt->ci_ckt, &dev, words->wl_word); + INPgetMod( ft_curckt->ci_ckt, words->wl_word, &inpmod, ft_curckt->ci_symtab ); + if ( inpmod == NULL ) { + fprintf(cp_err, "Error: no such model %s.\n", words->wl_word); + return; + } + }*/ diff --git a/src/frontend/spiceif.c b/src/frontend/spiceif.c index c330aa64f..048bf6d4d 100644 --- a/src/frontend/spiceif.c +++ b/src/frontend/spiceif.c @@ -30,14 +30,14 @@ The fix involves two changes 1. Make 'set temp = 10' change the values in the 'default' block, not whatever the 'current' pointer happens to be pointing at (which is usually the - default block except when one interactive is run immediately + default block except when one interactive is run immediately after another). - 2. Hack CKTnewTask() so that it looks to see whether it is creating + 2. Hack CKTnewTask() so that it looks to see whether it is creating a 'special' - task, in which case it copies the values from + task, in which case it copies the values from ft_curckt->ci_defTask providing - everything looks sane, otherwise it uses the hard-coded + everything looks sane, otherwise it uses the hard-coded 'application defaults'. These are fairly minor changes, and as they don't change the data structures @@ -75,12 +75,12 @@ CDHW*/ /* static declarations */ static struct variable * parmtovar(IFvalue *pv, IFparm *opt); -static IFparm * parmlookup(IFdevice *dev, GENinstance **inptr, char *param, - int do_model, int inout); -static IFvalue * doask(CKTcircuit *ckt, int typecode, GENinstance *dev, GENmodel *mod, - IFparm *opt, int ind); -static int doset(CKTcircuit *ckt, int typecode, GENinstance *dev, GENmodel *mod, - IFparm *opt, struct dvec *val); +static IFparm * parmlookup(IFdevice *dev, GENinstance **inptr, char *param, + int do_model, int inout); +static IFvalue * doask(CKTcircuit *ckt, int typecode, GENinstance *dev, GENmodel *mod, + IFparm *opt, int ind); +static int doset(CKTcircuit *ckt, int typecode, GENinstance *dev, GENmodel *mod, + IFparm *opt, struct dvec *val); static int finddev(CKTcircuit *ck, char *name, GENinstance **devptr, GENmodel **modptr); /*espice fix integration */ @@ -109,7 +109,7 @@ if_inpdeck(struct line *deck, INPtables **tab) return (NULL); } -/*CDHW Create a task DDD with a new UID. ci_defTask will point to it CDHW*/ + /*CDHW Create a task DDD with a new UID. ci_defTask will point to it CDHW*/ err = IFnewUid(ckt, &taskUid, NULL, "default", UID_TASK, NULL); if(err) { @@ -117,49 +117,49 @@ if_inpdeck(struct line *deck, INPtables **tab) return(NULL); } #if (0) - err = ft_sim->newTask (ckt, &(ft_curckt->ci_defTask), taskUid); + err = ft_sim->newTask (ckt, &(ft_curckt->ci_defTask), taskUid); #else /*CDHW*/ - err = ft_sim->newTask (ckt, &(ft_curckt->ci_defTask), taskUid, NULL); + err = ft_sim->newTask (ckt, &(ft_curckt->ci_defTask), taskUid, NULL); #endif if(err) { ft_sperror(err,"newTask"); return(NULL); } -/*CDHW which options available for this simulator? CDHW*/ + /*CDHW which options available for this simulator? CDHW*/ - for(j=0;jnumAnalyses;j++) { + for(j=0; jnumAnalyses; j++) { if(strcmp(ft_sim->analyses[j]->name,"options")==0) { which = j; break; } - } + } if(which != -1) { err = IFnewUid(ckt, &optUid, NULL, "options", UID_ANALYSIS, - NULL); + NULL); if(err) { ft_sperror(err,"newUid"); return(NULL); } err = ft_sim->newAnalysis (ft_curckt->ci_ckt, which, optUid, - &(ft_curckt->ci_defOpt), - ft_curckt->ci_defTask); - -/*CDHW ci_defTask and ci_defOpt point to parameters DDD CDHW*/ - + &(ft_curckt->ci_defOpt), + ft_curckt->ci_defTask); + + /*CDHW ci_defTask and ci_defOpt point to parameters DDD CDHW*/ + if(err) { ft_sperror(err,"createOptions"); return(NULL); } ft_curckt->ci_curOpt = ft_curckt->ci_defOpt; -/*CDHW ci_curOpt and ci_defOpt point to DDD CDHW*/ + /*CDHW ci_curOpt and ci_defOpt point to DDD CDHW*/ } ft_curckt->ci_curTask = ft_curckt->ci_defTask; - + INPpas1( ckt, (card *) deck->li_next, *tab); INPpas2( ckt, (card *) deck->li_next, *tab, ft_curckt->ci_defTask); INPkillMods(); @@ -170,16 +170,16 @@ if_inpdeck(struct line *deck, INPtables **tab) INPpas3(ckt, (card *) deck->li_next, *tab, ft_curckt->ci_defTask, ft_sim->nodeParms, - ft_sim->numNodeParms); + ft_sim->numNodeParms); #ifdef XSPICE -/* gtri - begin - wbk - 6/6/91 - Finish initialization of event driven structures */ + /* gtri - begin - wbk - 6/6/91 - Finish initialization of event driven structures */ err = EVTinit(ckt); if(err) { ft_sperror(err,"EVTinit"); return(NULL); } -/* gtri - end - wbk - 6/6/91 - Finish initialization of event driven structures */ + /* gtri - end - wbk - 6/6/91 - Finish initialization of event driven structures */ #endif return (ckt); @@ -202,165 +202,165 @@ if_run(CKTcircuit *ckt, char *what, wordlist *args, INPtables *tab) int which = -1; IFuid specUid,optUid; char *s; - - + + /* First parse the line... */ /*CDHW Look for an interactive task CDHW*/ - if (eq(what, "tran") - || eq(what, "ac") - || eq(what, "dc") - || eq(what, "op") - || eq(what, "pz") - || eq(what,"disto") - || eq(what, "adjsen") - || eq(what, "sens") - || eq(what,"tf") - || eq(what, "noise") -/* SP: Steady State Analysis */ - || eq(what, "pss")) -/* SP */ + if (eq(what, "tran") + || eq(what, "ac") + || eq(what, "dc") + || eq(what, "op") + || eq(what, "pz") + || eq(what,"disto") + || eq(what, "adjsen") + || eq(what, "sens") + || eq(what,"tf") + || eq(what, "noise") + /* SP: Steady State Analysis */ + || eq(what, "pss")) + /* SP */ { - s = wl_flatten(args); /* va: tfree char's tmalloc'ed in wl_flatten */ + s = wl_flatten(args); /* va: tfree char's tmalloc'ed in wl_flatten */ (void) sprintf(buf, ".%s", s); - tfree(s); + tfree(s); deck.li_next = deck.li_actual = NULL; deck.li_error = NULL; deck.li_linenum = 0; deck.li_line = buf; - -/*CDHW Delete any previous special task CDHW*/ + + /*CDHW Delete any previous special task CDHW*/ if(ft_curckt->ci_specTask) { - if (ft_curckt->ci_specTask == ft_curckt->ci_defTask) { /*CDHW*/ - printf("Oh dear...something bad has happened to the options.\n"); + if (ft_curckt->ci_specTask == ft_curckt->ci_defTask) { /*CDHW*/ + printf("Oh dear...something bad has happened to the options.\n"); } err = ft_sim->deleteTask (ft_curckt->ci_ckt, - ft_curckt->ci_specTask); + ft_curckt->ci_specTask); if(err) { ft_sperror(err,"deleteTask"); return(2); } - ft_curckt->ci_specTask = NULL; - ft_curckt->ci_specOpt = NULL; /*CDHW*/ + ft_curckt->ci_specTask = NULL; + ft_curckt->ci_specOpt = NULL; /*CDHW*/ } - /*CDHW Create an interactive task AAA with a new UID. -ci_specTask will point to it CDHW*/ - + /*CDHW Create an interactive task AAA with a new UID. + ci_specTask will point to it CDHW*/ + err = IFnewUid(ft_curckt->ci_ckt, &specUid, NULL, "special", - UID_TASK,NULL); + UID_TASK,NULL); if(err) { ft_sperror(err,"newUid"); return(2); } #if (0) err = ft_sim->newTask (ft_curckt->ci_ckt, - &(ft_curckt->ci_specTask), specUid); + &(ft_curckt->ci_specTask), specUid); #else /*CDHW*/ err = ft_sim->newTask (ft_curckt->ci_ckt, - &(ft_curckt->ci_specTask), - specUid, &(ft_curckt->ci_defTask)); -#endif + &(ft_curckt->ci_specTask), + specUid, &(ft_curckt->ci_defTask)); +#endif if(err) { ft_sperror(err,"newTask"); return(2); } -/*CDHW which options available for this simulator? CDHW*/ - - for(j=0;jnumAnalyses;j++) { + /*CDHW which options available for this simulator? CDHW*/ + + for(j=0; jnumAnalyses; j++) { if(strcmp(ft_sim->analyses[j]->name,"options")==0) { which = j; break; } - } + } if(which != -1) { /*CDHW options are available CDHW*/ err = IFnewUid(ft_curckt->ci_ckt, &optUid, NULL, "options", - UID_ANALYSIS,NULL); + UID_ANALYSIS,NULL); if(err) { ft_sperror(err,"newUid"); return(2); } err = ft_sim->newAnalysis (ft_curckt->ci_ckt, which, optUid, - &(ft_curckt->ci_specOpt), - ft_curckt->ci_specTask); - -/*CDHW 'options' ci_specOpt points to AAA in this case CDHW*/ - + &(ft_curckt->ci_specOpt), + ft_curckt->ci_specTask); + + /*CDHW 'options' ci_specOpt points to AAA in this case CDHW*/ + if(err) { ft_sperror(err,"createOptions"); return(2); } - + ft_curckt->ci_curOpt = ft_curckt->ci_specOpt; -/*CDHW ci_specTask ci_specOpt and ci_curOpt all point to AAA CDHW*/ - - } - + /*CDHW ci_specTask ci_specOpt and ci_curOpt all point to AAA CDHW*/ + + } + ft_curckt->ci_curTask = ft_curckt->ci_specTask; -/*CDHW ci_curTask and ci_specTask point to the interactive task AAA CDHW*/ - - INPpas2(ckt, (card *) &deck, tab, ft_curckt->ci_specTask); - + /*CDHW ci_curTask and ci_specTask point to the interactive task AAA CDHW*/ + + INPpas2(ckt, (card *) &deck, tab, ft_curckt->ci_specTask); + if (deck.li_error) { fprintf(cp_err, "Warning: %s\n", deck.li_error); - return 2; + return 2; } } - /*CDHW - ** if the task is to 'run' the deck, change ci_curTask and - ** ci_curOpt to point to DDD - ** created by if_inpdeck(), otherwise they point to AAA. - CDHW*/ - + /*CDHW + ** if the task is to 'run' the deck, change ci_curTask and + ** ci_curOpt to point to DDD + ** created by if_inpdeck(), otherwise they point to AAA. + CDHW*/ + if( eq(what,"run") ) { ft_curckt->ci_curTask = ft_curckt->ci_defTask; ft_curckt->ci_curOpt = ft_curckt->ci_defOpt; } -/* -- Find out what we are supposed to do. */ + /* -- Find out what we are supposed to do. */ if ( (eq(what, "tran")) - ||(eq(what, "ac")) - ||(eq(what, "dc")) - ||(eq(what, "op")) - ||(eq(what, "pz")) - ||(eq(what, "disto")) - ||(eq(what, "noise")) - ||(eq(what, "adjsen")) - ||(eq(what, "sens")) - ||(eq(what,"tf")) -/* SP: Steady State Analysis */ - ||(eq(what, "pss")) -/* SP */ - ||(eq(what, "run")) ) { - -/*CDHW Run the analysis pointed to by ci_curTask CDHW*/ - - ft_curckt->ci_curOpt = ft_curckt->ci_defOpt; - if ((err = ft_sim->doAnalyses (ckt, 1, ft_curckt->ci_curTask)) != OK){ + ||(eq(what, "ac")) + ||(eq(what, "dc")) + ||(eq(what, "op")) + ||(eq(what, "pz")) + ||(eq(what, "disto")) + ||(eq(what, "noise")) + ||(eq(what, "adjsen")) + ||(eq(what, "sens")) + ||(eq(what,"tf")) + /* SP: Steady State Analysis */ + ||(eq(what, "pss")) + /* SP */ + ||(eq(what, "run")) ) { + + /*CDHW Run the analysis pointed to by ci_curTask CDHW*/ + + ft_curckt->ci_curOpt = ft_curckt->ci_defOpt; + if ((err = ft_sim->doAnalyses (ckt, 1, ft_curckt->ci_curTask)) != OK) { ft_sperror(err, "doAnalyses"); /* wrd_end(); */ - if (err == E_PAUSE) - return (1); - else - return (2); + if (err == E_PAUSE) + return (1); + else + return (2); } } else if (eq(what, "resume")) { - if ((err = ft_sim->doAnalyses (ckt, 0, ft_curckt->ci_curTask)) != OK){ + if ((err = ft_sim->doAnalyses (ckt, 0, ft_curckt->ci_curTask)) != OK) { ft_sperror(err, "doAnalyses"); /* wrd_end(); */ - if (err == E_PAUSE) - return (1); - else - return (2); + if (err == E_PAUSE) + return (1); + else + return (2); } } else { fprintf(cp_err, "if_run: Internal Error: bad run type %s\n", what); - return (2); + return (2); } return (0); } @@ -395,31 +395,31 @@ if_option(CKTcircuit *ckt, char *name, enum cp_types type, void *value) if (eq(name, "acct")) { ft_acctprint = TRUE; - return 0; + return 0; } else if (eq(name, "noacct")) { ft_noacctprint = TRUE; - return 0; + return 0; } else if (eq(name, "noinit")) { ft_noinitprint = TRUE; - return 0; + return 0; } else if (eq(name, "list")) { ft_listprint = TRUE; - return 0; + return 0; } else if (eq(name, "node")) { ft_nodesprint = TRUE; - return 0; + return 0; } else if (eq(name, "opts")) { ft_optsprint = TRUE; - return 0; + return 0; } else if (eq(name, "nopage")) { - ft_nopage = TRUE; - return 0; + ft_nopage = TRUE; + return 0; } else if (eq(name, "nomod")) { - ft_nomod = TRUE; - return 0; + ft_nomod = TRUE; + return 0; } - for(i=0;inumAnalyses;i++) { + for(i=0; inumAnalyses; i++) { if(strcmp(ft_sim->analyses[i]->name,"options")==0) { which = i; break; @@ -438,99 +438,121 @@ if_option(CKTcircuit *ckt, char *name, enum cp_types type, void *value) /* See if this is unsupported or obsolete. */ for (vv = unsupported; *vv; vv++) if (eq(name, *vv)) { - fprintf(cp_err, - "Warning: option %s is currently unsupported.\n", name); + fprintf(cp_err, + "Warning: option %s is currently unsupported.\n", name); return 1; } for (vv = obsolete; *vv; vv++) if (eq(name, *vv)) { - fprintf(cp_err, - "Warning: option %s is obsolete.\n", name); + fprintf(cp_err, + "Warning: option %s is obsolete.\n", name); return 1; } return 0; } switch (ft_sim->analyses[which]->analysisParms[i].dataType & IF_VARTYPES) { - case IF_REAL: - if (type == CP_REAL) - pval.rValue = *((double *) value); - else if (type == CP_NUM) - pval.rValue = *((int *) value); - else - goto badtype; - break; - case IF_INTEGER: - if (type == CP_NUM) - pval.iValue = *((int *) value); - else if (type == CP_REAL) - pval.iValue = (int)floor((*(double *)value) + 0.5); - else - goto badtype; - break; - case IF_STRING: - if (type == CP_STRING) - pval.sValue = copy((char*) value); - else - goto badtype; - break; - case IF_FLAG: - if (type == CP_BOOL) - pval.iValue = *((bool *) value) ? 1 : 0; - else if (type == CP_NUM) /* FIXME, shall we allow this ? */ - pval.iValue = *((int *) value); - else - goto badtype; - break; - default: - fprintf(cp_err, - "if_option: Internal Error: bad option type %d.\n", - ft_sim->analyses[which]->analysisParms[i].dataType); + case IF_REAL: + if (type == CP_REAL) + pval.rValue = *((double *) value); + else if (type == CP_NUM) + pval.rValue = *((int *) value); + else + goto badtype; + break; + case IF_INTEGER: + if (type == CP_NUM) + pval.iValue = *((int *) value); + else if (type == CP_REAL) + pval.iValue = (int)floor((*(double *)value) + 0.5); + else + goto badtype; + break; + case IF_STRING: + if (type == CP_STRING) + pval.sValue = copy((char*) value); + else + goto badtype; + break; + case IF_FLAG: + if (type == CP_BOOL) + pval.iValue = *((bool *) value) ? 1 : 0; + else if (type == CP_NUM) /* FIXME, shall we allow this ? */ + pval.iValue = *((int *) value); + else + goto badtype; + break; + default: + fprintf(cp_err, + "if_option: Internal Error: bad option type %d.\n", + ft_sim->analyses[which]->analysisParms[i].dataType); } if (!ckt) { - /* XXX No circuit loaded */ - fprintf(cp_err, "Simulation parameter \"%s\" can't be set until\n", - name); - fprintf(cp_err, "a circuit has been loaded.\n"); - return 1; + /* XXX No circuit loaded */ + fprintf(cp_err, "Simulation parameter \"%s\" can't be set until\n", + name); + fprintf(cp_err, "a circuit has been loaded.\n"); + return 1; } #if (0) - if ((err = ft_sim->setAnalysisParm (ckt, ft_curckt->ci_curOpt, - ft_sim->analyses[which]->analysisParms[i].id, &pval, - NULL)) != OK) - ft_sperror(err, "setAnalysisParm(options) ci_curOpt"); + if ((err = ft_sim->setAnalysisParm (ckt, ft_curckt->ci_curOpt, + ft_sim->analyses[which]->analysisParms[i].id, &pval, + NULL)) != OK) + ft_sperror(err, "setAnalysisParm(options) ci_curOpt"); #else /*CDHW*/ - if ((err = ft_sim->setAnalysisParm (ckt, ft_curckt->ci_defOpt, - ft_sim->analyses[which]->analysisParms[i].id, &pval, - NULL)) != OK) - ft_sperror(err, "setAnalysisParm(options) ci_curOpt"); - return 1; + if ((err = ft_sim->setAnalysisParm (ckt, ft_curckt->ci_defOpt, + ft_sim->analyses[which]->analysisParms[i].id, &pval, + NULL)) != OK) + ft_sperror(err, "setAnalysisParm(options) ci_curOpt"); + return 1; #endif badtype: fprintf(cp_err, "Error: bad type given for option %s --\n", name); fprintf(cp_err, "\ttype given was "); switch (type) { - case CP_BOOL: fputs("boolean", cp_err); break; - case CP_NUM: fputs("integer", cp_err); break; - case CP_REAL: fputs("real", cp_err); break; - case CP_STRING: fputs("string", cp_err); break; - case CP_LIST: fputs("list", cp_err); break; - default: fputs("something strange", cp_err); break; + case CP_BOOL: + fputs("boolean", cp_err); + break; + case CP_NUM: + fputs("integer", cp_err); + break; + case CP_REAL: + fputs("real", cp_err); + break; + case CP_STRING: + fputs("string", cp_err); + break; + case CP_LIST: + fputs("list", cp_err); + break; + default: + fputs("something strange", cp_err); + break; } fprintf(cp_err, ", type expected was "); switch(ft_sim->analyses[which]->analysisParms[i].dataType & IF_VARTYPES) { - case IF_REAL: fputs("real.\n", cp_err); break; - case IF_INTEGER:fputs("integer.\n", cp_err); break; - case IF_STRING: fputs("string.\n", cp_err); break; - case IF_FLAG: fputs("flag.\n", cp_err); break; - default: fputs("something strange.\n", cp_err); break; + case IF_REAL: + fputs("real.\n", cp_err); + break; + case IF_INTEGER: + fputs("integer.\n", cp_err); + break; + case IF_STRING: + fputs("string.\n", cp_err); + break; + case IF_FLAG: + fputs("flag.\n", cp_err); + break; + default: + fputs("something strange.\n", cp_err); + break; } if (type == CP_BOOL) -fputs("\t(Note that you must use an = to separate option name and value.)\n", - cp_err); + fputs("\t(Note that you must use an = to separate option name and value.)\n", + cp_err); return 0; } @@ -565,12 +587,12 @@ if_errstring(int code) * 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 + * 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 +static int finddev_special( CKTcircuit *ckt, char *name, @@ -582,18 +604,16 @@ finddev_special( int type = -1; err = ft_sim->findInstance (ckt, &type, devptr, name, NULL, NULL); - if(err == OK) - { - *device_or_model=0; - return(type); + if(err == OK) { + *device_or_model=0; + return(type); } type = -1; *devptr = NULL; err = ft_sim->findModel (ckt, &type, modptr, name); - if(err == OK) - { - *device_or_model=1; - return(type); + if(err == OK) { + *device_or_model=1; + return(type); } *modptr = NULL; *device_or_model=2; @@ -606,8 +626,7 @@ finddev_special( * A.Roldan (espice) */ struct variable * -spif_getparam_special(CKTcircuit *ckt,char **name,char *param,int ind,int do_model) -{ +spif_getparam_special(CKTcircuit *ckt,char **name,char *param,int ind,int do_model) { struct variable *vv = NULL, *tv; IFvalue *pv; IFparm *opt; @@ -620,111 +639,95 @@ spif_getparam_special(CKTcircuit *ckt,char **name,char *param,int ind,int do_mod /* fprintf(cp_err, "Calling if_getparam(%s, %s)\n", *name, param); */ - if (!param || (param && eq(param, "all"))) - { + if (!param || (param && eq(param, "all"))) { INPretrieve(name, ft_curckt->ci_symtab); typecode = finddev_special(ckt, *name, &dev, &mod, &modelo_dispositivo); - if (typecode == -1) - { + 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(!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; + /* 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); } - else - fprintf(cp_err,"Internal Error: no parameter '%s' on device '%s'\n",device->modelParms[i].keyword,device->name); + return (vv); } - return (vv); - } - } - else if (param) - { + } else if (param) { INPretrieve(name, ft_curckt->ci_symtab); typecode = finddev_special(ckt, *name, &dev, &mod, &modelo_dispositivo); - if (typecode == -1) - { + 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) - { + if (!opt) { fprintf(cp_err, "Error: no such parameter %s.\n",param); return (NULL); } @@ -744,8 +747,7 @@ spif_getparam_special(CKTcircuit *ckt,char **name,char *param,int ind,int do_mod */ struct variable * -spif_getparam(CKTcircuit *ckt, char **name, char *param, int ind, int do_model) -{ +spif_getparam(CKTcircuit *ckt, char **name, char *param, int ind, int do_model) { struct variable *vv = NULL, *tv; IFvalue *pv; IFparm *opt; @@ -757,14 +759,14 @@ spif_getparam(CKTcircuit *ckt, char **name, char *param, int ind, int do_model) /* fprintf(cp_err, "Calling if_getparam(%s, %s)\n", *name, param); */ if (param && eq(param, "all")) { - - /* MW. My "special routine here" */ + + /* MW. My "special routine here" */ INPretrieve(name, ft_curckt->ci_symtab); - + typecode = finddev(ckt, *name, &dev, &mod); if (typecode == -1) { fprintf(cp_err, - "Error: no such device or model name %s\n", + "Error: no such device or model name %s\n", *name); return (NULL); } @@ -772,7 +774,7 @@ spif_getparam(CKTcircuit *ckt, char **name, char *param, int ind, int do_model) for (i = 0; i < *(device->numInstanceParms); i++) { opt = &device->instanceParms[i]; if(opt->dataType & IF_REDUNDANT || !opt->description) - continue; + continue; if(!(opt->dataType & IF_ASK)) continue; pv = doask(ckt, typecode, dev, mod, opt, ind); if (pv) { @@ -782,19 +784,19 @@ spif_getparam(CKTcircuit *ckt, char **name, char *param, int ind, int do_model) vv = tv; } else fprintf(cp_err, - "Internal Error: no parameter '%s' on device '%s'\n", - device->instanceParms[i].keyword, - device->name); + "Internal Error: no parameter '%s' on device '%s'\n", + device->instanceParms[i].keyword, + device->name); } return (vv); } else if (param) { - - /* MW. */ + + /* MW. */ INPretrieve(name, ft_curckt->ci_symtab); typecode = finddev(ckt, *name, &dev, &mod); if (typecode == -1) { fprintf(cp_err, - "Error: no such device or model name %s\n", + "Error: no such device or model name %s\n", *name); return (NULL); } @@ -817,81 +819,81 @@ spif_getparam(CKTcircuit *ckt, char **name, char *param, int ind, int do_model) void if_setparam_model(CKTcircuit *ckt, char **name, char *val ) { - GENinstance *dev = NULL; - GENinstance *prevDev = NULL; - GENmodel *curMod = NULL; - GENmodel *newMod = NULL; - INPmodel *inpmod = NULL; - GENinstance *iter; - GENmodel *mods, *prevMod; - int typecode; - - /* retrieve device name from symbol table */ - INPretrieve(name, ft_curckt->ci_symtab); - /* find the specified device */ - typecode = finddev(ckt, *name, &dev, &curMod); - if (typecode == -1) { - fprintf(cp_err, "Error: no such device or model name %s\n", *name); - return; - } - curMod = dev->GENmodPtr; - /* - retrieve the model from the global model table; also add the model to 'ckt' - and indicate model is being used - */ - INPgetMod( ckt, val, &inpmod, ft_curckt->ci_symtab ); - if ( inpmod == NULL ) { - fprintf(cp_err, "Error: no such model %s.\n", val); - return; - } - newMod = inpmod->INPmodfast; + GENinstance *dev = NULL; + GENinstance *prevDev = NULL; + GENmodel *curMod = NULL; + GENmodel *newMod = NULL; + INPmodel *inpmod = NULL; + GENinstance *iter; + GENmodel *mods, *prevMod; + int typecode; + + /* retrieve device name from symbol table */ + INPretrieve(name, ft_curckt->ci_symtab); + /* find the specified device */ + typecode = finddev(ckt, *name, &dev, &curMod); + if (typecode == -1) { + fprintf(cp_err, "Error: no such device or model name %s\n", *name); + return; + } + curMod = dev->GENmodPtr; + /* + retrieve the model from the global model table; also add the model to 'ckt' + and indicate model is being used + */ + INPgetMod( ckt, val, &inpmod, ft_curckt->ci_symtab ); + if ( inpmod == NULL ) { + fprintf(cp_err, "Error: no such model %s.\n", val); + return; + } + newMod = inpmod->INPmodfast; - /* see if new model name same as current model name */ - if ( newMod->GENmodName == curMod->GENmodName ) { - fprintf(cp_err, "Warning: new model same as current model; nothing changed.\n"); - return; - } - if ( newMod->GENmodType != curMod->GENmodType ) { - fprintf(cp_err, "Error: new model %s must be same type as current model.\n", val); - return; - } - - /* fix current model linked list */ - prevDev = NULL; - for( iter = curMod->GENinstances; iter != NULL; iter = iter->GENnextInstance ) { - if ( iter->GENname == dev->GENname ) { - - /* see if at beginning of linked list */ - if ( prevDev == NULL ) curMod->GENinstances = iter->GENnextInstance; - else prevDev->GENnextInstance = iter->GENnextInstance; - - /* update model for device */ - dev->GENmodPtr = newMod; - dev->GENnextInstance = newMod->GENinstances; - newMod->GENinstances = dev; - break; + /* see if new model name same as current model name */ + if ( newMod->GENmodName == curMod->GENmodName ) { + fprintf(cp_err, "Warning: new model same as current model; nothing changed.\n"); + return; } - prevDev = iter; - } - /* see if any devices remaining that reference current model */ - if ( curMod->GENinstances == NULL ) { - prevMod = NULL; - for( mods = ckt->CKThead[typecode]; mods != NULL; mods = mods->GENnextModel ) { - if ( mods->GENmodName == curMod->GENmodName ) { - - /* see if at beginning of linked list */ - if ( prevMod == NULL ) ckt->CKThead[typecode] = mods->GENnextModel; - else prevMod->GENnextModel = mods->GENnextModel; - - INPgetMod( ckt, (char *)mods->GENmodName, &inpmod, ft_curckt->ci_symtab ); - inpmod->INPmodUsed = 0; - FREE(mods); - - break; - } - prevMod = mods; + if ( newMod->GENmodType != curMod->GENmodType ) { + fprintf(cp_err, "Error: new model %s must be same type as current model.\n", val); + return; + } + + /* fix current model linked list */ + prevDev = NULL; + for( iter = curMod->GENinstances; iter != NULL; iter = iter->GENnextInstance ) { + if ( iter->GENname == dev->GENname ) { + + /* see if at beginning of linked list */ + if ( prevDev == NULL ) curMod->GENinstances = iter->GENnextInstance; + else prevDev->GENnextInstance = iter->GENnextInstance; + + /* update model for device */ + dev->GENmodPtr = newMod; + dev->GENnextInstance = newMod->GENinstances; + newMod->GENinstances = dev; + break; + } + prevDev = iter; + } + /* see if any devices remaining that reference current model */ + if ( curMod->GENinstances == NULL ) { + prevMod = NULL; + for( mods = ckt->CKThead[typecode]; mods != NULL; mods = mods->GENnextModel ) { + if ( mods->GENmodName == curMod->GENmodName ) { + + /* see if at beginning of linked list */ + if ( prevMod == NULL ) ckt->CKThead[typecode] = mods->GENnextModel; + else prevMod->GENnextModel = mods->GENnextModel; + + INPgetMod( ckt, (char *)mods->GENmodName, &inpmod, ft_curckt->ci_symtab ); + inpmod->INPmodUsed = 0; + FREE(mods); + + break; + } + prevMod = mods; + } } - } } void @@ -903,103 +905,101 @@ if_setparam(CKTcircuit *ckt, char **name, char *param, struct dvec *val, int do_ GENinstance *dev = NULL; int typecode; - /* PN */ + /* PN */ INPretrieve(name, ft_curckt->ci_symtab); typecode = finddev(ckt, *name, &dev, &mod); if (typecode == -1) { - fprintf(cp_err, "Error: no such device or model name %s\n", *name); - return; + fprintf(cp_err, "Error: no such device or model name %s\n", *name); + return; } device = ft_sim->devices[typecode]; opt = parmlookup(device, &dev, param, do_model, 1); if (!opt) { - if (param) - fprintf(cp_err, "Error: no such parameter %s.\n", param); - else - fprintf(cp_err, "Error: no default parameter.\n"); - return; + if (param) + fprintf(cp_err, "Error: no such parameter %s.\n", param); + else + fprintf(cp_err, "Error: no default parameter.\n"); + return; } if (do_model && !mod) { - mod = dev->GENmodPtr; - dev = NULL; + mod = dev->GENmodPtr; + dev = NULL; } doset(ckt, typecode, dev, mod, opt, val); /* Call to CKTtemp(ckt) will be invoked here only by 'altermod' commands, - to set internal model parameters pParam of each instance for immediate use, - otherwise e.g. model->BSIM3vth0 will be set, but not pParam of any BSIM3 instance. + to set internal model parameters pParam of each instance for immediate use, + otherwise e.g. model->BSIM3vth0 will be set, but not pParam of any BSIM3 instance. Call only if CKTtime > 0 to avoid conflict with previous 'reset' command. - May contain side effects because call is abundant. h_vogt 110101 + May contain side effects because called from many places. h_vogt 110101 */ if ((do_model) && (ckt->CKTtime > 0)) { int error = 0; error = CKTtemp(ckt); - if (error) fprintf(stderr,"Error during changing a device model parameter!\n"); + if (error) fprintf(stderr,"Error during changing a device model parameter!\n"); if (error) controlled_exit(1); } } static struct variable * -parmtovar(IFvalue *pv, IFparm *opt) -{ +parmtovar(IFvalue *pv, IFparm *opt) { struct variable *vv = alloc(struct variable); struct variable *nv; int i = 0; switch (opt->dataType & IF_VARTYPES) { - case IF_INTEGER: - vv->va_type = CP_NUM; - vv->va_num = pv->iValue; - break; - case IF_REAL: - case IF_COMPLEX: - vv->va_type = CP_REAL; - vv->va_real = pv->rValue; - break; - case IF_STRING: - vv->va_type = CP_STRING; - vv->va_string = pv->sValue; - break; - case IF_FLAG: - vv->va_type = CP_BOOL; - vv->va_bool = pv->iValue ? TRUE : FALSE; - break; - case IF_REALVEC: - vv->va_type = CP_LIST; - 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 = CP_REAL; - /* 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", - opt->dataType); - return (NULL); + case IF_INTEGER: + vv->va_type = CP_NUM; + vv->va_num = pv->iValue; + break; + case IF_REAL: + case IF_COMPLEX: + vv->va_type = CP_REAL; + vv->va_real = pv->rValue; + break; + case IF_STRING: + vv->va_type = CP_STRING; + vv->va_string = pv->sValue; + break; + case IF_FLAG: + vv->va_type = CP_BOOL; + vv->va_bool = pv->iValue ? TRUE : FALSE; + break; + case IF_REALVEC: + vv->va_type = CP_LIST; + 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 = CP_REAL; + /* 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", + opt->dataType); + return (NULL); } /* It's not clear whether we want the keyword or the desc here... */ @@ -1027,30 +1027,28 @@ parmlookup(IFdevice *dev, GENinstance **inptr, char *param, int do_model, int in for (i = 0; i < *(dev->numInstanceParms); i++) { if (!param && (dev->instanceParms[i].dataType & IF_PRINCIPAL)) return (&dev->instanceParms[i]); - else if (!param) - continue; + else if (!param) + continue; else if ((((dev->instanceParms[i].dataType & IF_SET) && inout == 1) - || ((dev->instanceParms[i].dataType & IF_ASK) && inout == 0)) - && cieq(dev->instanceParms[i].keyword, param)) - { - if (dev->instanceParms[i].dataType & IF_REDUNDANT) - i -= 1; + || ((dev->instanceParms[i].dataType & IF_ASK) && inout == 0)) + && cieq(dev->instanceParms[i].keyword, param)) { + if (dev->instanceParms[i].dataType & IF_REDUNDANT) + i -= 1; return (&dev->instanceParms[i]); - } + } } - return NULL; + return NULL; } if (dev->numModelParms) { - for (i = 0; i < *(dev->numModelParms); i++) - if ((((dev->modelParms[i].dataType & IF_SET) && inout == 1) - || ((dev->modelParms[i].dataType & IF_ASK) && inout == 0)) - && eq(dev->modelParms[i].keyword, param)) - { - if (dev->modelParms[i].dataType & IF_REDUNDANT) - i -= 1; - return (&dev->modelParms[i]); - } + for (i = 0; i < *(dev->numModelParms); i++) + if ((((dev->modelParms[i].dataType & IF_SET) && inout == 1) + || ((dev->modelParms[i].dataType & IF_ASK) && inout == 0)) + && eq(dev->modelParms[i].keyword, param)) { + if (dev->modelParms[i].dataType & IF_REDUNDANT) + i -= 1; + return (&dev->modelParms[i]); + } } return (NULL); @@ -1071,14 +1069,14 @@ doask(CKTcircuit *ckt, int typecode, GENinstance *dev, GENmodel *mod, IFparm *op pv.iValue = ind; /* Sometimes this will be junk and ignored... */ - /* fprintf(cp_err, "Calling doask(%d, %x, %x, %x)\n", + /* fprintf(cp_err, "Calling doask(%d, %x, %x, %x)\n", typecode, dev, mod, opt); */ if (dev) err = ft_sim->askInstanceQuest (ckt, dev, - opt->id, &pv, NULL); + opt->id, &pv, NULL); else err = ft_sim->askModelQuest (ckt, mod, - opt->id, &pv, NULL); + opt->id, &pv, NULL); if (err != OK) { ft_sperror(err, "if_getparam"); return (NULL); @@ -1106,64 +1104,64 @@ doset(CKTcircuit *ckt, int typecode, GENinstance *dev, GENmodel *mod, IFparm *op /* Count items */ if (opt->dataType & IF_VECTOR) { - n = nval.v.numValue = val->v_length; - - dptr = val->v_realdata; - /* XXXX compdata!!! */ - - switch (opt->dataType & (IF_VARTYPES & ~IF_VECTOR)) { - case IF_FLAG: - case IF_INTEGER: - iptr = nval.v.vec.iVec = NEWN(int, n); - - for (i = 0; i < n; i++) - *iptr++ = (int)floor(*dptr++ + 0.5); - break; - - case IF_REAL: - nval.v.vec.rVec = val->v_realdata; - break; - - default: - fprintf(cp_err, - "Can't assign value to \"%s\" (unsupported vector type)\n", - opt->keyword); - return E_UNSUPP; - } + n = nval.v.numValue = val->v_length; + + dptr = val->v_realdata; + /* XXXX compdata!!! */ + + switch (opt->dataType & (IF_VARTYPES & ~IF_VECTOR)) { + case IF_FLAG: + case IF_INTEGER: + iptr = nval.v.vec.iVec = NEWN(int, n); + + for (i = 0; i < n; i++) + *iptr++ = (int)floor(*dptr++ + 0.5); + break; + + case IF_REAL: + nval.v.vec.rVec = val->v_realdata; + break; + + default: + fprintf(cp_err, + "Can't assign value to \"%s\" (unsupported vector type)\n", + opt->keyword); + return E_UNSUPP; + } } else { - switch (opt->dataType & IF_VARTYPES) { - case IF_FLAG: - case IF_INTEGER: - nval.iValue = (int)floor(*val->v_realdata + 0.5); - break; - - case IF_REAL: -/*kensmith don't blow up with NULL dereference*/ - if (!val->v_realdata) { - fprintf(cp_err,"Unable to determine the value\n"); - return E_UNSUPP; - } - - nval.rValue = *val->v_realdata; - break; - - default: - fprintf(cp_err, - "Can't assign value to \"%s\" (unsupported type)\n", - opt->keyword); - return E_UNSUPP; - } + switch (opt->dataType & IF_VARTYPES) { + case IF_FLAG: + case IF_INTEGER: + nval.iValue = (int)floor(*val->v_realdata + 0.5); + break; + + case IF_REAL: + /*kensmith don't blow up with NULL dereference*/ + if (!val->v_realdata) { + fprintf(cp_err,"Unable to determine the value\n"); + return E_UNSUPP; + } + + nval.rValue = *val->v_realdata; + break; + + default: + fprintf(cp_err, + "Can't assign value to \"%s\" (unsupported type)\n", + opt->keyword); + return E_UNSUPP; + } } - /* fprintf(cp_err, "Calling doask(%d, %x, %x, %x)\n", + /* fprintf(cp_err, "Calling doask(%d, %x, %x, %x)\n", typecode, dev, mod, opt); */ if (dev) err = ft_sim->setInstanceParm (ckt, dev, - opt->id, &nval, NULL); + opt->id, &nval, NULL); else err = ft_sim->setModelParm (ckt, mod, - opt->id, &nval, NULL); + opt->id, &nval, NULL); return err; } @@ -1192,15 +1190,15 @@ finddev(CKTcircuit *ck, char *name, GENinstance **devptr, GENmodel **modptr) /* get an analysis parameter by name instead of id */ -int +int if_analQbyName(CKTcircuit *ckt, int which, JOB *anal, char *name, IFvalue *parm) { int i; - for(i=0;ianalyses[which]->numParms;i++) { + for(i=0; ianalyses[which]->numParms; i++) { if(strcmp(ft_sim->analyses[which]->analysisParms[i].keyword,name)==0) { return( ft_sim->askAnalysisQuest (ckt, anal, - ft_sim->analyses[which]->analysisParms[i].id,parm, - NULL) ); + ft_sim->analyses[which]->analysisParms[i].id,parm, + NULL) ); } } return(E_BADPARM); @@ -1221,8 +1219,8 @@ if_tranparams(struct circ *ci, double *start, double *stop, double *step) IFuid tranUid; if(!ci->ci_curTask) return(FALSE); - for(i=0;inumAnalyses;i++) { - if(strcmp(ft_sim->analyses[i]->name,"TRAN")==0){ + for(i=0; inumAnalyses; i++) { + if(strcmp(ft_sim->analyses[i]->name,"TRAN")==0) { which = i; break; } @@ -1230,10 +1228,10 @@ if_tranparams(struct circ *ci, double *start, double *stop, double *step) if(which == -1) return(FALSE); err = IFnewUid(ci->ci_ckt, &tranUid, NULL, "Transient Analysis", - UID_ANALYSIS, NULL); + UID_ANALYSIS, NULL); if(err != OK) return(FALSE); err = ft_sim->findAnalysis (ci->ci_ckt, &which, &anal, tranUid, - ci->ci_curTask, NULL); + ci->ci_curTask, NULL); if(err != OK) return(FALSE); err = if_analQbyName(ci->ci_ckt,which,anal,"tstart",&tmp); if(err != OK) return(FALSE); @@ -1252,14 +1250,13 @@ if_tranparams(struct circ *ci, double *start, double *stop, double *step) */ struct variable * -if_getstat(CKTcircuit *ckt, char *name) -{ +if_getstat(CKTcircuit *ckt, char *name) { int i; struct variable *v, *vars; IFvalue parm; int which = -1; - for(i=0;inumAnalyses;i++) { + for(i=0; inumAnalyses; i++) { if(strcmp(ft_sim->analyses[i]->name,"options")==0) { which = i; break; @@ -1277,11 +1274,11 @@ if_getstat(CKTcircuit *ckt, char *name) if (i == ft_sim->analyses[which]->numParms) return (NULL); if (ft_sim->askAnalysisQuest (ckt, &(ft_curckt->ci_curTask->taskOptions), - ft_sim->analyses[which]->analysisParms[i].id, &parm, - NULL) == -1) { - fprintf(cp_err, - "if_getstat: Internal Error: can't get %s\n", - name); + ft_sim->analyses[which]->analysisParms[i].id, &parm, + NULL) == -1) { + fprintf(cp_err, + "if_getstat: Internal Error: can't get %s\n", + name); return (NULL); } return (parmtovar(&parm, &(ft_sim->analyses[which]->analysisParms[i]))); @@ -1291,20 +1288,20 @@ if_getstat(CKTcircuit *ckt, char *name) continue; } if (ft_sim->askAnalysisQuest (ckt, &(ft_curckt->ci_curTask->taskOptions), - ft_sim->analyses[which]->analysisParms[i].id, - &parm, NULL) == -1) { - fprintf(cp_err, - "if_getstat: Internal Error: can't get %s\n", - name); + ft_sim->analyses[which]->analysisParms[i].id, + &parm, NULL) == -1) { + fprintf(cp_err, + "if_getstat: Internal Error: can't get %s\n", + name); return (NULL); } if (v) { - v->va_next = parmtovar(&parm, - &(ft_sim->analyses[which]->analysisParms[i])); + v->va_next = parmtovar(&parm, + &(ft_sim->analyses[which]->analysisParms[i])); v = v->va_next; } else { - vars = v = parmtovar(&parm, - &(ft_sim->analyses[which]->analysisParms[i])); + vars = v = parmtovar(&parm, + &(ft_sim->analyses[which]->analysisParms[i])); } } return (vars); @@ -1317,156 +1314,157 @@ if_getstat(CKTcircuit *ckt, char *name) #include /* arg0: circuit file, arg1: data file */ -void com_loadsnap(wordlist *wl) { - int error = 0; - FILE *file; - int tmpI, i, size; - CKTcircuit *my_ckt, *ckt; - - /* - Phesudo code: - - source(file_name); - This should setup all the device structs, voltage nodes, etc. - - call cktsetup; - This is needed to setup vector mamory allocation for vectors and branch nodes - - load_binary_data(info); - Overwrite the allocated numbers, rhs etc, with saved data - */ - - - if (ft_curckt) { - fprintf(cp_err, "Error: there is already a circuit loaded.\n"); - return; - } - - /* source the circuit */ - inp_source(wl->wl_word); - if (!ft_curckt) { - return; - } - - /* allocate all the vectors, with luck! */ - if (!error) - error = CKTsetup(ft_curckt->ci_ckt); - if (!error) - error = CKTtemp(ft_curckt->ci_ckt); - - if(error) { - fprintf(cp_err,"Some error in the CKT setup fncts!\n"); - return; - } +void com_loadsnap(wordlist *wl) +{ + int error = 0; + FILE *file; + int tmpI, i, size; + CKTcircuit *my_ckt, *ckt; - /* so it resumes ... */ - ft_curckt->ci_inprogress = TRUE; + /* + Phesudo code: + source(file_name); + This should setup all the device structs, voltage nodes, etc. - /* now load the binary file */ - - - ckt = ft_curckt->ci_ckt; + call cktsetup; + This is needed to setup vector mamory allocation for vectors and branch nodes + + load_binary_data(info); + Overwrite the allocated numbers, rhs etc, with saved data + */ - file = fopen(wl->wl_next->wl_word,"rb"); - - if(!file) { - fprintf(cp_err, - "Error: Couldn't open \"%s\" for reading\n", - wl->wl_next->wl_word); - return; - } - - fread(&tmpI,sizeof(int),1,file); - if(tmpI != sizeof(CKTcircuit) ) { - fprintf(cp_err,"loaded num: %d, expected num: %ld\n",tmpI,(long)sizeof(CKTcircuit)); - fprintf(cp_err, - "Error: snapshot saved with different version of spice\n"); - fclose(file); - return; - } - - my_ckt = TMALLOC(CKTcircuit, 1); - fread(my_ckt,sizeof(CKTcircuit),1,file); + if (ft_curckt) { + fprintf(cp_err, "Error: there is already a circuit loaded.\n"); + return; + } + + /* source the circuit */ + inp_source(wl->wl_word); + if (!ft_curckt) { + return; + } + + /* allocate all the vectors, with luck! */ + if (!error) + error = CKTsetup(ft_curckt->ci_ckt); + if (!error) + error = CKTtemp(ft_curckt->ci_ckt); + + if(error) { + fprintf(cp_err,"Some error in the CKT setup fncts!\n"); + return; + } + + /* so it resumes ... */ + ft_curckt->ci_inprogress = TRUE; + + + /* now load the binary file */ + + + ckt = ft_curckt->ci_ckt; + + file = fopen(wl->wl_next->wl_word,"rb"); + + if(!file) { + fprintf(cp_err, + "Error: Couldn't open \"%s\" for reading\n", + wl->wl_next->wl_word); + return; + } + + fread(&tmpI,sizeof(int),1,file); + if(tmpI != sizeof(CKTcircuit) ) { + fprintf(cp_err,"loaded num: %d, expected num: %ld\n",tmpI,(long)sizeof(CKTcircuit)); + fprintf(cp_err, + "Error: snapshot saved with different version of spice\n"); + fclose(file); + return; + } + + my_ckt = TMALLOC(CKTcircuit, 1); + + fread(my_ckt,sizeof(CKTcircuit),1,file); #define _t(name) ckt->name = my_ckt->name #define _ta(name,size)\ do{ int __i; for(__i=0;__iCKTmaxOrder+1;i++) { - _foo(ckt->CKTstates[i],double,ckt->CKTnumStates); + + for(i=0; i<=ckt->CKTmaxOrder+1; i++) { + _foo(ckt->CKTstates[i],double,ckt->CKTnumStates); } - + size = SMPmatSize(ckt->CKTmatrix) + 1; _foo(ckt->CKTrhs, double,size); _foo(ckt->CKTrhsOld, double,size); _foo(ckt->CKTrhsSpare, double,size); - _foo(ckt->CKTirhs, double,size); - _foo(ckt->CKTirhsOld, double,size); - _foo(ckt->CKTirhsSpare, double,size); - _foo(ckt->CKTrhsOp, double,size); - _foo(ckt->CKTsenRhs, double,size); + _foo(ckt->CKTirhs, double,size); + _foo(ckt->CKTirhsOld, double,size); + _foo(ckt->CKTirhsSpare, double,size); + _foo(ckt->CKTrhsOp, double,size); + _foo(ckt->CKTsenRhs, double,size); _foo(ckt->CKTseniRhs, double,size); - + _foo(ckt->CKTtimePoints,double,-1); _foo(ckt->CKTdeltaList,double,-1); _foo(ckt->CKTbreaks,double,ckt->CKTbreakSize); - + { /* avoid invalid lvalue assignment errors in the macro _foo() */ - TSKtask * lname = ft_curckt->ci_curTask; - _foo(lname,TSKtask,1); + TSKtask * lname = ft_curckt->ci_curTask; + _foo(lname,TSKtask,1); } /* To stop the Free */ @@ -1516,10 +1514,10 @@ do {\ ft_curckt->ci_curTask->jobs = NULL; _foo(ft_curckt->ci_curTask->TSKname, char, -1); - + { /* avoid invalid lvalue assignment errors in the macro _foo() */ - TRANan * lname = (TRANan *)ft_curckt->ci_curTask->jobs; - _foo(lname,TRANan,1); + TRANan * lname = (TRANan *)ft_curckt->ci_curTask->jobs; + _foo(lname,TRANan,1); } ft_curckt->ci_curTask->jobs->JOBname = NULL; // ckt->CKTcurJob = (&(ft_curckt->ci_curTask->taskOptions)) -> jobs; @@ -1529,76 +1527,77 @@ do {\ _foo(ft_curckt->ci_curTask->jobs->JOBname, char, -1); ft_curckt->ci_curTask->jobs->JOBnextJob = NULL; - + ((TRANan *)ft_curckt->ci_curTask->jobs)->TRANplot = NULL; _foo(ckt->CKTstat,STATistics,1); tfree(my_ckt); fclose(file); - + /* Finally to resume the plot in some fashion */ /* a worked out version of this should be enough */ { - IFuid *nameList; - int numNames; - IFuid timeUid; - - error = CKTnames(ckt,&numNames,&nameList); - if(error){ - fprintf(cp_err,"error in CKTnames\n"); - return; - } - SPfrontEnd->IFnewUid (ckt, &timeUid, NULL, - "time", UID_OTHER, NULL); - error = SPfrontEnd->OUTpBeginPlot (ckt, - ckt->CKTcurJob, - ckt->CKTcurJob->JOBname,timeUid,IF_REAL,numNames,nameList, - IF_REAL,&(((TRANan*)ckt->CKTcurJob)->TRANplot)); - if(error) { - fprintf(cp_err,"error in CKTnames\n"); - return; - } + IFuid *nameList; + int numNames; + IFuid timeUid; + + error = CKTnames(ckt,&numNames,&nameList); + if(error) { + fprintf(cp_err,"error in CKTnames\n"); + return; + } + SPfrontEnd->IFnewUid (ckt, &timeUid, NULL, + "time", UID_OTHER, NULL); + error = SPfrontEnd->OUTpBeginPlot (ckt, + ckt->CKTcurJob, + ckt->CKTcurJob->JOBname,timeUid,IF_REAL,numNames,nameList, + IF_REAL,&(((TRANan*)ckt->CKTcurJob)->TRANplot)); + if(error) { + fprintf(cp_err,"error in CKTnames\n"); + return; + } } - - - + + + return ; } -void com_savesnap(wordlist *wl) { - FILE *file; - int i, size; - CKTcircuit *ckt; - TSKtask *task; - - if (!ft_curckt) { - fprintf(cp_err, "Error: there is no circuit loaded.\n"); - return; - } else if (ft_curckt->ci_ckt == NULL) { /* Set noparse? */ - fprintf(cp_err, "Error: circuit not parsed.\n"); - return; - } +void com_savesnap(wordlist *wl) +{ + FILE *file; + int i, size; + CKTcircuit *ckt; + TSKtask *task; + + if (!ft_curckt) { + fprintf(cp_err, "Error: there is no circuit loaded.\n"); + return; + } else if (ft_curckt->ci_ckt == NULL) { /* Set noparse? */ + fprintf(cp_err, "Error: circuit not parsed.\n"); + return; + } - /* save the data */ - - ckt = ft_curckt->ci_ckt; - - task = ft_curckt->ci_curTask; + /* save the data */ - if(task->jobs->JOBtype != 4) { - fprintf(cp_err,"Only saving of tran analysis is implemented\n"); - return; - } - - file = fopen(wl->wl_word,"wb"); - - if(!file) { - fprintf(cp_err, - "Error: Couldn't open \"%s\" for writing\n",wl->wl_word); - return; - } + ckt = ft_curckt->ci_ckt; + + task = ft_curckt->ci_curTask; + + if(task->jobs->JOBtype != 4) { + fprintf(cp_err,"Only saving of tran analysis is implemented\n"); + return; + } + + file = fopen(wl->wl_word,"wb"); + + if(!file) { + fprintf(cp_err, + "Error: Couldn't open \"%s\" for writing\n",wl->wl_word); + return; + } #undef _foo #define _foo(name,type,num)\ @@ -1614,78 +1613,78 @@ void com_savesnap(wordlist *wl) { fwrite(&__i,sizeof(int),1,file);\ }\ } while(0) - - - _foo(ckt,CKTcircuit,1); - - /* To save list - - double *(CKTstates[8]); - double *CKTrhs; - double *CKTrhsOld; - double *CKTrhsSpare; - double *CKTirhs; - double *CKTirhsOld; - double *CKTirhsSpare; - double *CKTrhsOp; - double *CKTsenRhs; - double *CKTseniRhs; - double *CKTtimePoints; list of all accepted timepoints in - the current transient simulation - double *CKTdeltaList; list of all timesteps in the - current transient simulation - - */ - - - for(i=0;i<=ckt->CKTmaxOrder+1;i++) { - _foo(ckt->CKTstates[i],double,ckt->CKTnumStates); - } - - - - size = SMPmatSize(ckt->CKTmatrix) + 1; - - _foo(ckt->CKTrhs,double,size); - _foo(ckt->CKTrhsOld,double,size); - _foo(ckt->CKTrhsSpare,double,size); - _foo(ckt->CKTirhs,double,size); - _foo(ckt->CKTirhsOld,double,size); - _foo(ckt->CKTirhsSpare,double,size); - _foo(ckt->CKTrhsOp,double,size); - _foo(ckt->CKTsenRhs,double,size); - _foo(ckt->CKTseniRhs,double,size); - - _foo(ckt->CKTtimePoints,double,ckt->CKTtimeListSize); - _foo(ckt->CKTdeltaList,double,ckt->CKTtimeListSize); - - /* need to save the breakpoints, or something */ - - _foo(ckt->CKTbreaks,double,ckt->CKTbreakSize); - - - /* now save the TSK struct, ft_curckt->ci_curTask*/ - - _foo(task,TSKtask,1); - _foo(task->TSKname,char,(strlen(task->TSKname)+1)); - - /* now save the JOB struct task->jobs */ - /* lol, only allow one job, tough! */ - /* Note that JOB is a base class, need to save actual type!! */ - - _foo(task->jobs,TRANan,1); - - _foo(task->jobs->JOBname,char,(strlen(task->jobs->JOBname)+1)); - - - /* Finally the stats */ - - _foo(ckt->CKTstat,STATistics,1); - - - fclose(file); - - return; + + + _foo(ckt,CKTcircuit,1); + + /* To save list + + double *(CKTstates[8]); + double *CKTrhs; + double *CKTrhsOld; + double *CKTrhsSpare; + double *CKTirhs; + double *CKTirhsOld; + double *CKTirhsSpare; + double *CKTrhsOp; + double *CKTsenRhs; + double *CKTseniRhs; + double *CKTtimePoints; list of all accepted timepoints in + the current transient simulation + double *CKTdeltaList; list of all timesteps in the + current transient simulation + + */ + + + for(i=0; i<=ckt->CKTmaxOrder+1; i++) { + _foo(ckt->CKTstates[i],double,ckt->CKTnumStates); + } + + + + size = SMPmatSize(ckt->CKTmatrix) + 1; + + _foo(ckt->CKTrhs,double,size); + _foo(ckt->CKTrhsOld,double,size); + _foo(ckt->CKTrhsSpare,double,size); + _foo(ckt->CKTirhs,double,size); + _foo(ckt->CKTirhsOld,double,size); + _foo(ckt->CKTirhsSpare,double,size); + _foo(ckt->CKTrhsOp,double,size); + _foo(ckt->CKTsenRhs,double,size); + _foo(ckt->CKTseniRhs,double,size); + + _foo(ckt->CKTtimePoints,double,ckt->CKTtimeListSize); + _foo(ckt->CKTdeltaList,double,ckt->CKTtimeListSize); + + /* need to save the breakpoints, or something */ + + _foo(ckt->CKTbreaks,double,ckt->CKTbreakSize); + + + /* now save the TSK struct, ft_curckt->ci_curTask*/ + + _foo(task,TSKtask,1); + _foo(task->TSKname,char,(strlen(task->TSKname)+1)); + + /* now save the JOB struct task->jobs */ + /* lol, only allow one job, tough! */ + /* Note that JOB is a base class, need to save actual type!! */ + + _foo(task->jobs,TRANan,1); + + _foo(task->jobs->JOBname,char,(strlen(task->jobs->JOBname)+1)); + + + /* Finally the stats */ + + _foo(ckt->CKTstat,STATistics,1); + + + fclose(file); + + return; }