Change the code that makes variables from device/model parameters
(spiceif.c) and vectors from variables (vectors.c) so that array and string-valued parameters and the resulting variables are handled correctly. Fix a memory leak in converting array parameters; that requires a change in cplask.c so that CPL devices behave the same way as others. Add a "device" variant of the Compose command so that generated vectors are available in scripts.
This commit is contained in:
parent
02172448e7
commit
cb69d8b96b
|
|
@ -226,6 +226,36 @@ com_compose(wordlist *wl)
|
||||||
}
|
}
|
||||||
|
|
||||||
length *= blocksize;
|
length *= blocksize;
|
||||||
|
} else if (eq(wl->wl_word, "device") && resname[0] == '@') {
|
||||||
|
/* Make vector(s) from device parameters; also works with models. */
|
||||||
|
|
||||||
|
result = vec_get(resname);
|
||||||
|
|
||||||
|
/* With @dev[all] a chain of vectors is returned. */
|
||||||
|
|
||||||
|
while (result) {
|
||||||
|
char *cp;
|
||||||
|
|
||||||
|
/* Change name so it is not an array reference. */
|
||||||
|
|
||||||
|
for (cp = result->v_name; cp && *cp; ++cp) {
|
||||||
|
if (*cp == '[')
|
||||||
|
*cp = '_';
|
||||||
|
if (*cp == ']') {
|
||||||
|
*cp = '\0';
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Set dimension info */
|
||||||
|
|
||||||
|
result->v_numdims = 1;
|
||||||
|
result->v_dims[0] = length;
|
||||||
|
|
||||||
|
result->v_flags |= VF_PERMANENT;
|
||||||
|
result = result->v_link2;
|
||||||
|
}
|
||||||
|
goto done;
|
||||||
#ifdef XSPICE
|
#ifdef XSPICE
|
||||||
} else if (eq(wl->wl_word, "xspice")) {
|
} else if (eq(wl->wl_word, "xspice")) {
|
||||||
/* Make vectors from an event node. */
|
/* Make vectors from an event node. */
|
||||||
|
|
@ -240,7 +270,6 @@ com_compose(wordlist *wl)
|
||||||
result->v_scale->v_flags |= VF_PERMANENT;
|
result->v_scale->v_flags |= VF_PERMANENT;
|
||||||
vec_new(result->v_scale);
|
vec_new(result->v_scale);
|
||||||
cp_addkword(CT_VECTOR, result->v_scale->v_name);
|
cp_addkword(CT_VECTOR, result->v_scale->v_name);
|
||||||
txfree(resname); // It was copied
|
|
||||||
goto finished;
|
goto finished;
|
||||||
#endif
|
#endif
|
||||||
} else {
|
} else {
|
||||||
|
|
|
||||||
|
|
@ -79,7 +79,8 @@ extern INPmodel *modtab;
|
||||||
extern NGHASHPTR modtabhash;
|
extern NGHASHPTR modtabhash;
|
||||||
extern bool ft_batchmode;
|
extern bool ft_batchmode;
|
||||||
|
|
||||||
static struct variable *parmtovar(IFvalue *pv, IFparm *opt);
|
static struct variable *parmtovar(IFvalue *pv, IFparm *opt,
|
||||||
|
int use_description);
|
||||||
static IFparm *parmlookup(IFdevice *dev, GENinstance **inptr, char *param,
|
static IFparm *parmlookup(IFdevice *dev, GENinstance **inptr, char *param,
|
||||||
int do_model, int inout);
|
int do_model, int inout);
|
||||||
static IFvalue *doask(CKTcircuit *ckt, int typecode, GENinstance *dev, GENmodel *mod,
|
static IFvalue *doask(CKTcircuit *ckt, int typecode, GENinstance *dev, GENmodel *mod,
|
||||||
|
|
@ -688,17 +689,12 @@ spif_getparam_special(CKTcircuit *ckt, char **name, char *param, int ind, int do
|
||||||
continue;
|
continue;
|
||||||
pv = doask(ckt, typecode, dev, mod, opt, ind);
|
pv = doask(ckt, typecode, dev, mod, opt, ind);
|
||||||
if (pv) {
|
if (pv) {
|
||||||
tv = parmtovar(pv, opt);
|
tv = parmtovar(pv, opt, 0);
|
||||||
|
if (tv) {
|
||||||
/* With the following we pack the name and the acronym of the parameter */
|
if (vv)
|
||||||
{
|
tv->va_next = vv;
|
||||||
char *x = tv->va_name;
|
vv = tv;
|
||||||
tv->va_name = tprintf("%s [%s]", tv->va_name, device->instanceParms[i].keyword);
|
|
||||||
tfree(x);
|
|
||||||
}
|
}
|
||||||
if (vv)
|
|
||||||
tv->va_next = vv;
|
|
||||||
vv = tv;
|
|
||||||
} else {
|
} else {
|
||||||
fprintf(cp_err,
|
fprintf(cp_err,
|
||||||
"Internal Error: no parameter '%s' on device '%s'\n",
|
"Internal Error: no parameter '%s' on device '%s'\n",
|
||||||
|
|
@ -725,26 +721,12 @@ spif_getparam_special(CKTcircuit *ckt, char **name, char *param, int ind, int do
|
||||||
continue;
|
continue;
|
||||||
pv = doask(ckt, typecode, dev, mod, opt, ind);
|
pv = doask(ckt, typecode, dev, mod, opt, ind);
|
||||||
if (pv) {
|
if (pv) {
|
||||||
tv = parmtovar(pv, opt);
|
tv = parmtovar(pv, opt, 0);
|
||||||
/* Inside parmtovar:
|
if (tv) {
|
||||||
* 1. tv->va_name = copy(opt->description);
|
if (vv)
|
||||||
* 2. Copy the type of variable of IFparm into a variable (thus parm-to-var)
|
tv->va_next = vv;
|
||||||
* vv->va_type = opt->dataType
|
vv = tv;
|
||||||
* 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 *x = tv->va_name;
|
|
||||||
tv->va_name = tprintf("%s [%s]", tv->va_name, device->modelParms[i].keyword);
|
|
||||||
tfree(x);
|
|
||||||
}
|
}
|
||||||
/* tv->va_string = device->modelParms[i].keyword; Put the name of the variable */
|
|
||||||
if (vv)
|
|
||||||
tv->va_next = vv;
|
|
||||||
vv = tv;
|
|
||||||
} else {
|
} else {
|
||||||
fprintf(cp_err,
|
fprintf(cp_err,
|
||||||
"Internal Error: no parameter '%s' on device '%s'\n",
|
"Internal Error: no parameter '%s' on device '%s'\n",
|
||||||
|
|
@ -768,7 +750,7 @@ spif_getparam_special(CKTcircuit *ckt, char **name, char *param, int ind, int do
|
||||||
}
|
}
|
||||||
pv = doask(ckt, typecode, dev, mod, opt, ind);
|
pv = doask(ckt, typecode, dev, mod, opt, ind);
|
||||||
if (pv)
|
if (pv)
|
||||||
vv = parmtovar(pv, opt);
|
vv = parmtovar(pv, opt, 0);
|
||||||
return (vv);
|
return (vv);
|
||||||
} else {
|
} else {
|
||||||
return (if_getstat(ckt, *name));
|
return (if_getstat(ckt, *name));
|
||||||
|
|
@ -814,10 +796,12 @@ spif_getparam(CKTcircuit *ckt, char **name, char *param, int ind, int do_model)
|
||||||
continue;
|
continue;
|
||||||
pv = doask(ckt, typecode, dev, mod, opt, ind);
|
pv = doask(ckt, typecode, dev, mod, opt, ind);
|
||||||
if (pv) {
|
if (pv) {
|
||||||
tv = parmtovar(pv, opt);
|
tv = parmtovar(pv, opt, 0);
|
||||||
if (vv)
|
if (tv) {
|
||||||
tv->va_next = vv;
|
if (vv)
|
||||||
vv = tv;
|
tv->va_next = vv;
|
||||||
|
vv = tv;
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
fprintf(cp_err,
|
fprintf(cp_err,
|
||||||
"Internal Error: no parameter '%s' on device '%s'\n",
|
"Internal Error: no parameter '%s' on device '%s'\n",
|
||||||
|
|
@ -843,7 +827,7 @@ spif_getparam(CKTcircuit *ckt, char **name, char *param, int ind, int do_model)
|
||||||
}
|
}
|
||||||
pv = doask(ckt, typecode, dev, mod, opt, ind);
|
pv = doask(ckt, typecode, dev, mod, opt, ind);
|
||||||
if (pv)
|
if (pv)
|
||||||
vv = parmtovar(pv, opt);
|
vv = parmtovar(pv, opt, 0);
|
||||||
return (vv);
|
return (vv);
|
||||||
} else {
|
} else {
|
||||||
return (if_getstat(ckt, *name));
|
return (if_getstat(ckt, *name));
|
||||||
|
|
@ -991,49 +975,90 @@ if_setparam(CKTcircuit *ckt, char **name, char *param, struct dvec *val, int do_
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Make a linked list where the first node is a CP_LIST variable
|
||||||
|
* pointing to the different values of the vector variables.
|
||||||
|
*
|
||||||
|
*
|
||||||
|
* 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
|
||||||
|
*/
|
||||||
|
|
||||||
static struct variable *
|
static struct variable *
|
||||||
parmtovar(IFvalue *pv, IFparm *opt)
|
parmtolist(IFvalue *pv, IFparm *opt, char *name)
|
||||||
{
|
{
|
||||||
/* It is not clear whether we want to name the variable
|
struct variable *list = NULL;
|
||||||
* by `keyword' or by `description' */
|
int i;
|
||||||
|
|
||||||
|
for (i = pv->v.numValue; --i >= 0;) {
|
||||||
|
switch (opt->dataType & (IF_VARTYPES & ~IF_VECTOR)) {
|
||||||
|
case IF_INTEGER:
|
||||||
|
list = var_alloc_num(NULL, pv->v.vec.iVec[i], list);
|
||||||
|
break;
|
||||||
|
case IF_REAL:
|
||||||
|
case IF_COMPLEX:
|
||||||
|
list = var_alloc_real(NULL, pv->v.vec.rVec[i], list);
|
||||||
|
break;
|
||||||
|
case IF_STRING:
|
||||||
|
list = var_alloc_string(NULL, copy(pv->v.vec.sVec[i]), list);
|
||||||
|
break;
|
||||||
|
case IF_FLAG:
|
||||||
|
list = var_alloc_bool(NULL, pv->v.vec.iVec[i] ? TRUE : FALSE,
|
||||||
|
list);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
fprintf(cp_err,
|
||||||
|
"parmtolist: Internal Error: bad PARM type "
|
||||||
|
"%#x for %s (%s).\n",
|
||||||
|
opt->dataType, opt->keyword, opt->description);
|
||||||
|
if (name)
|
||||||
|
free(name);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (i || pv->v.numValue == 0)
|
||||||
|
list = var_alloc_vlist(name, list, NULL);
|
||||||
|
if (pv->v.vec.iVec) { // All the union members are pointers
|
||||||
|
free(pv->v.vec.iVec);
|
||||||
|
pv->v.vec.iVec = NULL;
|
||||||
|
}
|
||||||
|
return list;
|
||||||
|
}
|
||||||
|
|
||||||
|
static struct variable *
|
||||||
|
parmtovar(IFvalue *pv, IFparm *opt, int use_description)
|
||||||
|
{
|
||||||
|
char *name;
|
||||||
|
|
||||||
|
name = use_description ? opt->description : opt->keyword;
|
||||||
|
if (name)
|
||||||
|
name = copy(name);
|
||||||
|
if (opt->dataType & IF_VECTOR)
|
||||||
|
return parmtolist(pv, opt, name);
|
||||||
|
|
||||||
switch (opt->dataType & IF_VARTYPES) {
|
switch (opt->dataType & IF_VARTYPES) {
|
||||||
case IF_INTEGER:
|
case IF_INTEGER:
|
||||||
return var_alloc_num(copy(opt->description), pv->iValue, NULL);
|
return var_alloc_num(name, pv->iValue, NULL);
|
||||||
case IF_REAL:
|
case IF_REAL:
|
||||||
case IF_COMPLEX:
|
case IF_COMPLEX:
|
||||||
return var_alloc_real(copy(opt->description), pv->rValue, NULL);
|
return var_alloc_real(name, pv->rValue, NULL);
|
||||||
case IF_STRING:
|
case IF_STRING:
|
||||||
return var_alloc_string(copy(opt->description), pv->sValue, NULL);
|
return var_alloc_string(name, copy(pv->sValue), NULL);
|
||||||
case IF_FLAG:
|
case IF_FLAG:
|
||||||
return var_alloc_bool(copy(opt->description), pv->iValue ? TRUE : FALSE, NULL);
|
return var_alloc_bool(name, pv->iValue ? TRUE : FALSE,
|
||||||
case IF_REALVEC: {
|
NULL);
|
||||||
struct variable *list = NULL;
|
|
||||||
int i;
|
|
||||||
for (i = pv->v.numValue; --i >= 0;)
|
|
||||||
list = var_alloc_real(NULL, pv->v.vec.rVec[i], list);
|
|
||||||
return var_alloc_vlist(copy(opt->description), list, NULL);
|
|
||||||
/* 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
|
|
||||||
*/
|
|
||||||
}
|
|
||||||
default:
|
default:
|
||||||
fprintf(cp_err,
|
fprintf(cp_err,
|
||||||
"parmtovar: Internal Error: bad PARM type %d.\n",
|
"parmtovar: Internal Error: bad PARM type %#x for %s (%s).\n",
|
||||||
opt->dataType);
|
opt->dataType, opt->keyword, opt->description);
|
||||||
|
if (name)
|
||||||
|
free(name);
|
||||||
return (NULL);
|
return (NULL);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -1317,7 +1342,7 @@ if_getstat(CKTcircuit *ckt, char *name)
|
||||||
return (NULL);
|
return (NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
return (parmtovar(&parm, if_parm));
|
return (parmtovar(&parm, if_parm, 1));
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
|
|
||||||
|
|
@ -1339,7 +1364,7 @@ if_getstat(CKTcircuit *ckt, char *name)
|
||||||
return (NULL);
|
return (NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
*v = parmtovar(&parm, if_parm);
|
*v = parmtovar(&parm, if_parm, 1);
|
||||||
v = &((*v)->va_next);
|
v = &((*v)->va_next);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -580,8 +580,8 @@ vec_get(const char *vec_name) {
|
||||||
struct dvec *d, *end = NULL, *newv = NULL;
|
struct dvec *d, *end = NULL, *newv = NULL;
|
||||||
struct plot *pl;
|
struct plot *pl;
|
||||||
char buf[BSIZE_SP], *s, *wd, *word, *whole, *name = NULL, *param;
|
char buf[BSIZE_SP], *s, *wd, *word, *whole, *name = NULL, *param;
|
||||||
int i = 0;
|
int i = 0;
|
||||||
struct variable *vv;
|
struct variable *vv, *v;
|
||||||
|
|
||||||
wd = word = copy(vec_name); /* Gets mangled below... */
|
wd = word = copy(vec_name); /* Gets mangled below... */
|
||||||
|
|
||||||
|
|
@ -638,6 +638,8 @@ vec_get(const char *vec_name) {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!d && (*word == SPECCHAR)) { /* "@" */
|
if (!d && (*word == SPECCHAR)) { /* "@" */
|
||||||
|
int multiple;
|
||||||
|
|
||||||
/* This is a special quantity... */
|
/* This is a special quantity... */
|
||||||
if (ft_nutmeg) {
|
if (ft_nutmeg) {
|
||||||
fprintf(cp_err,
|
fprintf(cp_err,
|
||||||
|
|
@ -646,6 +648,12 @@ vec_get(const char *vec_name) {
|
||||||
return (NULL); /* va: use NULL */
|
return (NULL); /* va: use NULL */
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!ft_curckt) {
|
||||||
|
fprintf(cp_err, "Error: No circuit loaded.\n");
|
||||||
|
tfree(wd);
|
||||||
|
return (NULL);
|
||||||
|
}
|
||||||
|
|
||||||
whole = copy(word);
|
whole = copy(word);
|
||||||
name = ++word;
|
name = ++word;
|
||||||
for (param = name; *param && (*param != '['); param++)
|
for (param = name; *param && (*param != '['); param++)
|
||||||
|
|
@ -660,157 +668,131 @@ vec_get(const char *vec_name) {
|
||||||
param = NULL;
|
param = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This is what is done in case of "alter r1 resistance = 1234"
|
||||||
|
* r1 resistance, 0
|
||||||
|
* if_setparam(ft_curckt->ci_ckt, &dev, param, dv, do_model);
|
||||||
|
*/
|
||||||
|
|
||||||
if (ft_curckt) {
|
vv = if_getparam(ft_curckt->ci_ckt, &name, param, 0, 0);
|
||||||
/*
|
if (!vv) {
|
||||||
* This is what is done in case of "alter r1 resistance = 1234"
|
|
||||||
* r1 resistance, 0
|
|
||||||
* if_setparam(ft_curckt->ci_ckt, &dev, param, dv, do_model);
|
|
||||||
*/
|
|
||||||
|
|
||||||
/* vv = if_getparam (ft_curckt->ci_ckt, &name, param, 0, 0); */
|
|
||||||
vv = if_getparam(ft_curckt->ci_ckt, &name, param, 0, 0);
|
|
||||||
if (!vv) {
|
|
||||||
tfree(whole);
|
|
||||||
tfree(wd);
|
|
||||||
return (NULL);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
fprintf(cp_err, "Error: No circuit loaded.\n");
|
|
||||||
tfree(whole);
|
tfree(whole);
|
||||||
tfree(wd);
|
tfree(wd);
|
||||||
return (NULL);
|
return (NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
d = dvec_alloc(copy(whole), /* MW. The same as word before */
|
/* If vec_name was "@dev", "@model", "@dev[all]" or @model[all]",
|
||||||
SV_NOTYPE,
|
* if_getparam() returns a list.
|
||||||
VF_REAL, /* No complex values yet... */
|
|
||||||
1, NULL);
|
|
||||||
|
|
||||||
/* In case the represented variable is a REAL vector this takes
|
|
||||||
* the actual value of the first element of the linked list which
|
|
||||||
* does not make sense.
|
|
||||||
* This is an error.
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/* This will copy the contents of the structure vv in another structure
|
multiple = (vv->va_next != NULL);
|
||||||
* dvec (FTEDATA.H) that do not have INTEGER so that those parameters
|
if (multiple && param)
|
||||||
* defined as IF_INTEGER are not given their value when using
|
*--param = '\0';
|
||||||
* print @pot[pos_node]
|
|
||||||
* To fix this, it is necessary to define:
|
|
||||||
* OPU( "pos_node", POT_QUEST_POS_NODE, IF_REAL,"Positive node of potenciometer"),
|
|
||||||
* int POTnegNode; // number of negative node of potenciometer (Nodo_3)
|
|
||||||
* case POT_QUEST_POS_NODE:
|
|
||||||
* value->rValue = (double)fast->POTposNode;
|
|
||||||
* return (OK);
|
|
||||||
* Works but with the format 1.00000E0
|
|
||||||
*/
|
|
||||||
|
|
||||||
/* We must make a change in format between the data that carries a variable to
|
for (v = vv; v; v = v->va_next) {
|
||||||
* put in a dvec.
|
struct dvec *nd;
|
||||||
*/
|
char *vec_name, new_name[256];
|
||||||
|
|
||||||
/*
|
if (multiple) {
|
||||||
* #define va_bool va_V.vV_bool
|
snprintf(new_name, sizeof new_name, "@%s[%s]",
|
||||||
* #define va_num va_V.vV_num
|
name, v->va_name);
|
||||||
* #define va_real va_V.vV_real
|
vec_name = new_name;
|
||||||
* #define va_string va_V.vV_string
|
} else {
|
||||||
* #define va_vlist va_V.vV_list
|
vec_name = whole;
|
||||||
* enum cp_types {
|
|
||||||
* CP_BOOL,
|
|
||||||
* CP_NUM,
|
|
||||||
* CP_REAL,
|
|
||||||
* CP_STRING,
|
|
||||||
* CP_LIST
|
|
||||||
° };
|
|
||||||
*/
|
|
||||||
|
|
||||||
/* The variable is a vector */
|
|
||||||
if (vv->va_type == CP_LIST) {
|
|
||||||
/* Compute the length of the vector,
|
|
||||||
* used with the parameters of isrc and vsrc
|
|
||||||
*/
|
|
||||||
struct variable *nv;
|
|
||||||
|
|
||||||
/* Count the number of nodes in the list */
|
|
||||||
i = 0;
|
|
||||||
for (nv = vv->va_vlist; nv; nv = nv->va_next) {
|
|
||||||
i++;
|
|
||||||
}
|
}
|
||||||
|
nd = dvec_alloc(copy(vec_name),
|
||||||
|
SV_NOTYPE,
|
||||||
|
VF_REAL, /* No complex values yet... */
|
||||||
|
1, NULL);
|
||||||
|
|
||||||
dvec_realloc(d, i, NULL); /* Resize to # nodes */
|
switch (v->va_type) {
|
||||||
|
case CP_BOOL:
|
||||||
|
*nd->v_realdata = (double)v->va_bool;
|
||||||
|
break;
|
||||||
|
case CP_NUM:
|
||||||
|
*nd->v_realdata = (double)v->va_num;
|
||||||
|
break;
|
||||||
|
case CP_REAL:
|
||||||
|
*nd->v_realdata = v->va_real;
|
||||||
|
break;
|
||||||
|
case CP_STRING:
|
||||||
|
fprintf(stderr,
|
||||||
|
"ERROR: can not handle string value "
|
||||||
|
"of '%s' in vec_get(%s)\nIgnoring...\n",
|
||||||
|
v->va_name, vec_name);
|
||||||
|
dvec_free(nd);
|
||||||
|
continue;
|
||||||
|
break;
|
||||||
|
case CP_LIST:
|
||||||
|
{
|
||||||
|
struct variable *nv;
|
||||||
|
enum cp_types ft;
|
||||||
|
|
||||||
/* Step through the list again, setting values this time */
|
/* Array values are presented as a list.
|
||||||
i = 0;
|
* Compute the length of the vector, and check that
|
||||||
for (nv = vv->va_vlist; nv; nv = nv->va_next) {
|
* it is homogenous:
|
||||||
d->v_realdata[i++] = nv->va_real;
|
* used with the parameters of isrc and vsrc
|
||||||
}
|
*/
|
||||||
|
|
||||||
/* To be able to identify the vector to represent
|
|
||||||
* belongs to a special "conunto" and should be printed in a
|
|
||||||
* special way.
|
|
||||||
*/
|
|
||||||
d->v_dims[1] = 1;
|
|
||||||
}
|
|
||||||
else if (vv->va_type == CP_NUM) { /* Variable is an integer */
|
|
||||||
*d->v_realdata = (double) vv->va_num;
|
|
||||||
}
|
|
||||||
else if (vv->va_type == CP_REAL) { /* Variable is a real */
|
|
||||||
if (!(vv->va_next)) {
|
|
||||||
/* Only a real data
|
|
||||||
* usually normal
|
|
||||||
*/
|
|
||||||
*d->v_realdata = vv->va_real;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
/* Real data set
|
|
||||||
* When you print a model @ [all]
|
|
||||||
* Just print numerical values, not the string
|
|
||||||
*/
|
|
||||||
struct variable *nv;
|
|
||||||
/* We go to print the list of values
|
|
||||||
* nv->va_name = Parameter description
|
|
||||||
* nv->va_string = Parameter
|
|
||||||
* nv->va_real= Value
|
|
||||||
*/
|
|
||||||
nv = vv;
|
|
||||||
for (i = 1; ; i++) {
|
|
||||||
switch (nv->va_type) {
|
|
||||||
case CP_REAL:
|
|
||||||
fprintf(stdout, "%s=%g\n", nv->va_name, nv->va_real);
|
|
||||||
break;
|
|
||||||
case CP_STRING:
|
|
||||||
fprintf(stdout, "%s=%s\n", nv->va_name, nv->va_string);
|
|
||||||
break;
|
|
||||||
case CP_NUM:
|
|
||||||
fprintf(stdout, "%s=%d\n", nv->va_name, nv->va_num);
|
|
||||||
break;
|
|
||||||
case CP_BOOL:
|
|
||||||
fprintf(stdout, "%s=%d\n", nv->va_name, nv->va_bool);
|
|
||||||
break;
|
|
||||||
default: {
|
|
||||||
fprintf(stderr, "ERROR: enumeration value `CP_LIST' not handled in vec_get\nIgnoring...\n");
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
nv = nv->va_next;
|
|
||||||
|
|
||||||
|
i = 0;
|
||||||
|
nv = v->va_vlist;
|
||||||
if (!nv) {
|
if (!nv) {
|
||||||
break;
|
dvec_free(nd);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
ft = nv->va_type;
|
||||||
|
for (; nv; nv = nv->va_next) {
|
||||||
|
/* Count the number of nodes in the list */
|
||||||
|
|
||||||
|
i++;
|
||||||
|
if (nv->va_type != ft)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (nv || ft == CP_STRING || ft == CP_LIST) {
|
||||||
|
fprintf(stderr,
|
||||||
|
"ERROR: can not handle mixed, string or list "
|
||||||
|
"value of '%s' in vec_get(%s)\nIgnoring...\n",
|
||||||
|
v->va_name, vec_name);
|
||||||
|
dvec_free(nd);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
dvec_realloc(nd, i, NULL); /* Resize to # nodes */
|
||||||
|
|
||||||
|
/* Step through the list again, setting values this time */
|
||||||
|
|
||||||
|
i = 0;
|
||||||
|
for (nv = v->va_vlist; nv; nv = nv->va_next) {
|
||||||
|
switch (ft) {
|
||||||
|
case CP_BOOL:
|
||||||
|
nd->v_realdata[i++] = (double)nv->va_bool;
|
||||||
|
break;
|
||||||
|
case CP_NUM:
|
||||||
|
nd->v_realdata[i++] = (double)nv->va_num;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
case CP_REAL:
|
||||||
|
nd->v_realdata[i++] = nv->va_real;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* To be able to identify the vector to represent
|
||||||
|
* belongs to a special "conunto" and should be printed
|
||||||
|
* in a special way.
|
||||||
|
*/
|
||||||
|
nd->v_dims[1] = 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
break;
|
||||||
/* To distinguish those does not take anything for print screen to
|
|
||||||
* make a print or M1 @ @ M1 [all] leaving only the correct data
|
|
||||||
* and not the last
|
|
||||||
*/
|
|
||||||
d->v_rlength = 1;
|
|
||||||
}
|
}
|
||||||
|
/* Chain it on. */
|
||||||
|
|
||||||
|
vec_new(nd);
|
||||||
|
nd->v_link2 = d;
|
||||||
|
d = nd;
|
||||||
}
|
}
|
||||||
|
|
||||||
free_struct_variable(vv);
|
free_struct_variable(vv);
|
||||||
tfree(wd);
|
tfree(wd);
|
||||||
vec_new(d);
|
|
||||||
tfree(whole);
|
tfree(whole);
|
||||||
return d;
|
return d;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -24,12 +24,18 @@ CPLask(CKTcircuit *ckt, GENinstance *inst, int which, IFvalue *value, IFvalue *s
|
||||||
NG_IGNORE(select);
|
NG_IGNORE(select);
|
||||||
|
|
||||||
switch(which) {
|
switch(which) {
|
||||||
|
/* String tables are expected to be freed, but not the strings. */
|
||||||
|
|
||||||
case CPL_POS_NODE:
|
case CPL_POS_NODE:
|
||||||
value->v.vec.sVec = here->in_node_names;
|
value->v.vec.sVec = TMALLOC(char *, here->dimension);
|
||||||
|
memcpy(value->v.vec.sVec, here->in_node_names,
|
||||||
|
here->dimension * sizeof (char *));
|
||||||
value->v.numValue = here->dimension;
|
value->v.numValue = here->dimension;
|
||||||
return(OK);
|
return(OK);
|
||||||
case CPL_NEG_NODE:
|
case CPL_NEG_NODE:
|
||||||
value->v.vec.sVec = here->out_node_names;
|
value->v.vec.sVec = TMALLOC(char *, here->dimension);
|
||||||
|
memcpy(value->v.vec.sVec, here->out_node_names,
|
||||||
|
here->dimension * sizeof (char *));
|
||||||
value->v.numValue = here->dimension;
|
value->v.numValue = here->dimension;
|
||||||
return(OK);
|
return(OK);
|
||||||
case CPL_DIM:
|
case CPL_DIM:
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue