codemodel instance parameters, working

This commit is contained in:
Florian Ballenegger 2020-10-01 16:39:59 +02:00
parent 7c0688cca4
commit 1b64cebf9a
16 changed files with 282 additions and 107 deletions

View File

@ -1968,14 +1968,28 @@ static char *get_model_type(char *line)
return gettok_noparens(&beg_ptr);
}
static inline char *skip_back_non_ws_nonc(const char *s, const char *start, char c) { while (s > start && !isspace_c(s[-1]) && (s[-1]!=c)) s--; return (char *) s; }
static char *get_adevice_model_name(char *line)
{
char *ptr_end, *ptr_beg;
ptr_end = skip_back_ws(strchr(line, '\0'), line);
ptr_beg = skip_back_non_ws(ptr_end, line);
char *prev;
/* F.B. added backward skipping param=val */
for(ptr_end=strchr(line, '\0'); ptr_end>line; ) {
ptr_end = skip_back_ws(ptr_end, line);
ptr_beg = skip_back_non_ws_nonc(ptr_end, line, '=');
prev = skip_back_ws(ptr_beg, line);
if(prev>line && prev[-1]=='=') {
prev = skip_back_ws(prev-1, line); /* backskip \s*= */
ptr_end=skip_back_non_ws(prev, line); /* backskip param= */
} else
break; /* found model */
}
if(ptr_beg == line)
return copy_substring(ptr_beg,ptr_beg); /* did not found the model */
printf("adev mod name: %s\n", ptr_beg);
return copy_substring(ptr_beg, ptr_end);
}
@ -8297,7 +8311,7 @@ static void inp_check_syntax(struct card *deck)
}
else {
if (!check_ch) {
fprintf(stderr, "Warning: Unusal leading characters like '%c' or others out of '= [] ? () & %\"!:,'\n", *cut_line);
fprintf(stderr, "Warning: Unusal leading characters like '%c' or others out of '= [] ? () & %%\"!:,'\n", *cut_line);
fprintf(stderr, " in netlist or included files, will be replaced with '*'\n");
check_ch = 1; /* just one warning */
}

View File

@ -97,6 +97,7 @@ static int numdevs(char *s);
static wordlist *modtranslate(struct card *deck, char *subname, wordlist *new_modnames);
static void devmodtranslate(struct card *deck, char *subname, wordlist * const orig_modnames);
static int inp_numnodes(char c);
static char *search_adevice_model_name(char *line);
#define N_GLOBAL_NODES 1005
@ -1041,24 +1042,19 @@ translate(struct card *deck, char *formal, char *actual, char *scname, const cha
translate_inst_name(&buffer, scname, name, NULL);
bxx_putc(&buffer, ' ');
if(name)
tfree(name);
/* search where the model name is and store in 'next_name' pointer */
next_name = search_adevice_model_name(s);
if(next_name==NULL)
next_name=strchr(s,'\0'); /* not found, but process anyway */
/* Now translate the nodes, looking ahead one token to recognize */
/* when we reach the model name which should not be translated */
/* here. */
next_name = MIFgettok(&s);
for (;;) {
/* rotate the tokens and get the the next one */
if (name)
tfree(name);
name = next_name;
next_name = MIFgettok(&s);
/* if next token is NULL, name holds the model name, so exit */
if (next_name == NULL)
break;
/* Now translate the nodes */
while(s<next_name) {
name = MIFgettok(&s);
/* Process the token in name. If it is special, then don't */
/* translate it. */
switch (*name) {
@ -1073,8 +1069,7 @@ translate(struct card *deck, char *formal, char *actual, char *scname, const cha
/* don't translate the port type identifier */
if (name)
tfree(name);
name = next_name;
next_name = MIFgettok(&s);
name = MIFgettok(&s);
bxx_put_cstring(&buffer, name);
break;
@ -1085,14 +1080,13 @@ translate(struct card *deck, char *formal, char *actual, char *scname, const cha
}
bxx_putc(&buffer, ' ');
}
/* copy in the last token, which is the model name */
if (name) {
bxx_put_cstring(&buffer, name);
tfree(name);
}
if (name)
tfree(name);
};
/* copy the model name and the rest of the line */
bxx_put_cstring(&buffer, s);
break; /* case 'a' */
/* gtri - end - wbk - 10/23/90 */
@ -1614,6 +1608,32 @@ translate_mod_name(struct bxx_buffer *buffer, char *modname, char *subname, stru
bxx_printf(buffer, "%s:%s", subname, modname);
}
#ifdef XSPICE
static inline char *skip_back_non_ws_nonc(const char *s, const char *start, char c) { while (s > start && !isspace_c(s[-1]) && (s[-1]!=c)) s--; return (char *) s; }
/* F.B: function to locate the model name in a A device (xspice coremodel) */
/* a similar function is found in inpcomp.c */
static char *search_adevice_model_name(char *line)
{
char *ptr_end, *ptr_beg;
char *prev;
for(ptr_end=strchr(line, '\0'); ptr_end>line; ) {
ptr_end = skip_back_ws(ptr_end, line);
ptr_beg = skip_back_non_ws_nonc(ptr_end, line, '=');
prev = skip_back_ws(ptr_beg, line);
if(prev>line && prev[-1]=='=') {
prev = skip_back_ws(prev-1, line); /* backskip \s*= */
ptr_end=skip_back_non_ws(prev, line); /* backskip param= */
} else
break; /* found model */
}
if(ptr_beg == line)
return NULL;
return ptr_beg;
}
#endif
static void
devmodtranslate(struct card *s, char *subname, wordlist * const orig_modnames)
@ -1658,42 +1678,24 @@ devmodtranslate(struct card *s, char *subname, wordlist * const orig_modnames)
/* SDB debug statement */
printf("In devmodtranslate, found codemodel, line= %s\n", t);
#endif
/* first do refdes. */
name = gettok(&t); /* get refdes */
bxx_printf(&buffer, "%s ", name);
tfree(name);
/* now do remainder of line. */
next_name = gettok(&t);
for (;;) {
name = next_name;
next_name = gettok(&t);
if (next_name == NULL) {
/* if next_name is NULL, we are at the line end.
* name holds the model name. Therefore, break */
break;
} else {
/* next_name holds something. Write name into the buffer and continue. */
bxx_printf(&buffer, "%s ", name);
tfree(name);
}
} /* while */
translate_mod_name(&buffer, name, subname, orig_modnames);
tfree(name);
bxx_putc(&buffer, ' ');
#ifdef TRACE
/* SDB debug statement */
printf("In devmodtranslate, translated codemodel line= %s\n", buffer);
#endif
bxx_put_cstring(&buffer, t);
tfree(s->line);
s->line = copy(bxx_buffer(&buffer));
next_name = search_adevice_model_name(t);
if(next_name && *next_name!='!') { /* if start with !, will use a default model */
bxx_put_substring(&buffer, t, next_name); /* put everything before model name */
t = next_name;
name = gettok(&t); /* get modname */
if(name==NULL) break; /* for safety but should not happen */
translate_mod_name(&buffer, name, subname, orig_modnames);
tfree(name);
bxx_putc(&buffer, ' '); /* put a space after model name */
bxx_put_cstring(&buffer, t); /* put the end of the line */
#ifdef TRACE
/* SDB debug statement */
printf("In devmodtranslate, translated codemodel line= %s\n", buffer);
#endif
/* replace the line in the card */
tfree(s->line);
s->line = copy(bxx_buffer(&buffer));
}
break;
#endif /* XSPICE */

View File

@ -79,6 +79,7 @@ struct coreInfo_t {
/* added for instance parameters */
int ((*dllitf_MIFParam)(int, IFvalue *, GENinstance*, IFvalue *));
void* nulltermination; /* For binary compatibility in future extensions */
};
#endif

View File

@ -368,6 +368,7 @@ struct Mif_Private {
int num_inst_var; /* Number of instance variables */
Mif_Inst_Var_Data_t **inst_var; /* Information about each inst variable */
Mif_Callback_t *callback; /* Callback function */
/* new field for instance parameters - added to the end for binary compatibility */
Mif_Param_Data_t **iparam; /* Information about each inst parameter */
};

View File

@ -115,9 +115,11 @@ struct Mif_Param_Info {
Mif_Boolean_t has_upper_bound; /* True if there is an array size upper bound */
int upper_bound; /* Array size upper bound */
Mif_Boolean_t null_allowed; /* True if null is allowed for this parameter */
#if 0
Mif_Boolean_t has_model_scope; /* True if the parameter is a model parameter */
Mif_Boolean_t has_inst_scope; /* True if the parameter is an instance parameter */
int inst_param_index; /* Index of instance parameter */
#endif
};

View File

@ -25,7 +25,7 @@ CKTparam(CKTcircuit *ckt, GENinstance *fast, int param, IFvalue *val, IFvalue *s
type = fast->GENmodPtr->GENmodType;
if(DEVices[type]->DEVparam) {
return(DEVices[type]->DEVparam (param, val, fast, selector));
} else {
} else {printf("no DEVparam function for type %d %s\n",type,fast->GENmodPtr->GENmodName);
return(E_BADPARM);
}
}

View File

@ -142,7 +142,7 @@ extern struct coreInfo_t coreInfo; /* cmexport.c */
#ifdef NDEV
#include "ndev/ndevitf.h"
#endif
#define TRACE
static SPICEdev *(*static_devices[])(void) = {
/* URC device MUST precede both resistors and capacitors */
get_urc_info,
@ -415,7 +415,7 @@ int load_opus(const char *name)
SPICEdev **devs;
Evt_Udn_Info_t **udns;
funptr_t fetch;
printf("loading code model lib %s\n", name);
lib = dlopen(name, RTLD_NOW);
if (!lib) {
msg = dlerror();

View File

@ -75,7 +75,7 @@ struct coreInfo_t coreInfo =
txfree,
tmalloc,
trealloc,
txfree
txfree,
#else
GC_malloc,
tcalloc,
@ -83,6 +83,8 @@ struct coreInfo_t coreInfo =
no_free,
GC_malloc,
GC_realloc,
no_free
no_free,
#endif
MIFParam,
NULL
};

View File

@ -113,6 +113,18 @@ static int buf_len;
typedef enum {CONN, PARAM, STATIC_VAR} Id_Kind_t;
static int inst_param_index(int param)
{
int i, iparam;
for (i = 0; (i < param) && (i < mod_ifs_table->num_param); i++)
if(mod_ifs_table->param[i].scope != CMPP_MODEL)
iparam++;
if(iparam>=mod_ifs_table->num_param)
yyerror ("Internal error: Instance parameter not found");
return iparam;
}
/*--------------------------------------------------------------------------*/
static char *subscript (Sub_Id_t sub_id)
{
@ -452,8 +464,8 @@ macro : TOK_INIT
fprintf (mod_yyout, "mif_private->param[%d]->element[%s]",
i, subscript ($3));
else
fprintf (mod_yyout, "mif_private->iparam[mif_private->param[%d]->inst_param_index]->element[%s]",
i, subscript ($3));
fprintf (mod_yyout, "mif_private->iparam[%d]->element[%s]",
inst_param_index(i), subscript ($3));
put_type (mod_yyout, mod_ifs_table->param[i].type);
}
| TOK_PARAM_SIZE TOK_LPAREN id TOK_RPAREN

View File

@ -892,6 +892,7 @@ static int write_param_info(
str = boolean_to_str(p_param_cur->null_allowed);
rc |= fprintf(fp, " %s,\n", str);
#if 0
/* F.B. info about instance parameters */
str = boolean_to_str(p_param_cur->scope != CMPP_INSTANCE);
rc |= fprintf(fp, " %s,\n", str);
@ -899,7 +900,8 @@ static int write_param_info(
rc |= fprintf(fp, " %s,\n", str);
str = integer_to_str(p_param_cur->scope == CMPP_MODEL ? -1 : inst_param_index);
rc |= fprintf(fp, " %s,\n", str);
#endif
if(p_param_cur->scope != CMPP_MODEL)
inst_param_index++;
@ -1100,7 +1102,7 @@ static int write_SPICEdev(
/* Write the names of the generic code model functions */
rc |= fprintf(fp,
" .DEVparam = NULL,\n"
" .DEVparam = MIFParam,\n"
" .DEVmodParam = MIFmParam,\n"
" .DEVload = MIFload,\n"
" .DEVsetup = MIFsetup,\n"

View File

@ -110,6 +110,8 @@ static void gc_end(void);
static char *alltokens[BSIZE_SP];
static int curtoknr = 0;
static int MIFinp2_params(char *line, CKTcircuit *ckt, INPtables *tab, struct card *current, GENinstance* inst, int type);
/* ********************************************************************* */
@ -157,7 +159,8 @@ and error checks are performed.
At this point, nothing should be left in 'line'
-------------------------------------------------------------------------*/
extern INPmodel *modtab;
#define TRACE
void
MIF_INP2A (
CKTcircuit *ckt, /* circuit structure to put mod/inst structs in */
@ -199,7 +202,8 @@ MIF_INP2A (
/* SDB debug statement */
printf("In MIF_INP2A, line to process = %s . . . \n", current->line);
#endif
printf("->modtab %p\n", modtab);
/* get the line text from the card struct */
line = current->line;
@ -209,18 +213,33 @@ MIF_INP2A (
/* get the name of the instance and add it to the symbol table */
name = copy(MIFgettok(&line));
INPinsert(&name, tab);
printf("->modtab %p\n", modtab);
/* locate the last token on the line (i.e. model name) and put it into "model" */
/* locate the model name */
while(*line != '\0') {
model = MIFgettok(&line);
char* linetmp;
tmp_token = MIFgettok(&line);
linetmp=line;
do
linetmp--;
while(linetmp > current->line && isspace_c(*linetmp));
if(*linetmp == '=')
break;
printf("model updated to %s, char %c, modtab %p\n", tmp_token, *linetmp,modtab);
model = tmp_token;
}
printf("->modtab %p\n", modtab);
/* make sure the model name was there. */
if(model == NULL) {
LITERR("Missing model on A type device");
gc_end();
return;
}
/* if model name starts with !, use or create a default model */
/* TODO */
/* Locate model from pass 1. If it hasn't been processed yet, */
/* allocate a structure in ckt for it, process its parameters */
@ -230,7 +249,7 @@ MIF_INP2A (
gc_end();
return;
}
printf("Device type %d\n", thismodel->INPmodType);
/* get the integer index into the DEVices data array for this */
/* model */
type = thismodel->INPmodType;
@ -589,6 +608,10 @@ MIF_INP2A (
}
}
}
/* parse the end of the line for reading instance parameters */
MIFinp2_params(line, ckt, tab, current, (GENinstance*) fast[0], type);
gc_end();
}
@ -1028,6 +1051,48 @@ MIFget_port(
}
static int
MIFinp2_params(char *line, CKTcircuit *ckt, INPtables *tab, struct card *current, GENinstance* inst, int type)
{
int error; /* error code temporary */
char *name;
int i;
IFvalue ptemp; /* a value structure */
IFvalue *parm;
while(*line)
{
INPgetTok(&line, &name, 0);
if(*line!='=') {
printf("Expect param=val format for %s, got %c\n", name, *line);
LITERR("Expect param=val format\n");
return(0);
}
line++; /* skip '=' */
for(i=0;i<*(DEVices[type]->DEVpublic.numInstanceParms);i++)
if(strcmp(name, DEVices[type]->DEVpublic.instanceParms[i].keyword)==0)
break;
if(0) tfree(name); /* don't it need anymore, we still know the keyword */
if(i<*(DEVices[type]->DEVpublic.numInstanceParms))
{
int dataType = DEVices[type]->DEVpublic.instanceParms[i].dataType;
if(0) printf("will set parameter %s to xspice instance\n", DEVices[type]->DEVpublic.instanceParms[i].keyword);
parm = INPgetValue(ckt, &line, dataType, tab);
printf("MIFinp2_params set %s id=%d i#%d\n", name, DEVices[type]->DEVpublic.instanceParms[i].id,i);
IFC(setInstanceParm, (ckt, (GENinstance*)inst, DEVices[type]->DEVpublic.instanceParms[i].id, parm, NULL));
/*GCA(INPapName, (ckt, job->JOBtype, job, ana->analysisParms[i].keyword, parm)); */
}
else
{
LITERR("Unrecognized parameter\n");
return(0);
}
}
}
#undef MIFgettok
#undef MIFget_token

View File

@ -291,7 +291,7 @@ int MIFaskInstParam(
value_type &= IF_VARTYPES;
/* get index into inst->iparam */
inst_index = DEVices[mod_type]->DEVpublic.param[param_index].inst_param_index;
inst_index = i;
if(inst_index <0)
return(E_BADPARM);

View File

@ -79,6 +79,7 @@ the .model card are not filled in by this function. They are
defaulted later by MIFsetup(). The function returns NULL when
successful, and an error string on failure.
*/
#define TRACE
char *MIFgetMod(
CKTcircuit *ckt, /* The circuit structure */
@ -126,7 +127,6 @@ char *MIFgetMod(
/* loop through modtable looking for this model (*name) */
for (modtmp = modtab; modtmp != NULL; modtmp = modtmp->INPnextModel) {
#ifdef TRACE
/* SDB debug statement */
printf("In MIFgetMod, checking model against stored model = %s . . .\n", modtmp->INPmodName);

View File

@ -57,7 +57,7 @@ MIFParam(int param_index, IFvalue *value, GENinstance *inst_in, IFvalue *select)
/* Arrange for access to MIF specific data in the model */
inst = (MIFinstance*) inst_in;
model = MIFmodPtr(inst);
printf("Mif param %d\n", param_index);
/* Get model type */
mod_type = model->MIFmodType;
if((mod_type < 0) || (mod_type >= DEVmaxnum))
@ -68,25 +68,14 @@ MIFParam(int param_index, IFvalue *value, GENinstance *inst_in, IFvalue *select)
if((param_index < 0) || (param_index >= model->num_param))
return(E_BADPARM);
if(!DEVices[mod_type]->DEVpublic.param[param_index].has_inst_scope)
/* search the instance parameter index */
for(iparam=0;iparam<*(DEVices[mod_type]->DEVpublic.numInstanceParms);iparam++)
if(DEVices[mod_type]->DEVpublic.instanceParms[iparam].id == param_index)
break;
if((iparam < 0) || (iparam >= *(DEVices[mod_type]->DEVpublic.numInstanceParms)))
return(E_BADPARM);
iparam = DEVices[mod_type]->DEVpublic.param[param_index].inst_param_index;
if((iparam < 0) || (iparam >= inst->num_iparam))
return(E_BADPARM);
/* find param_index */
/*
param_index=-1;
for(i=0;i<DEVices[mod_type]->DEVpublic.num_param;i++)
if(DEVices[mod_type]->DEVpublic.param[i].inst_param_index == iparam)
{
param_index=i;
break;
}
if(param_index<0)
return(E_BADPARM); */
/* get value type to know which members of unions to access */
value_type = DEVices[mod_type]->DEVpublic.modelParms[param_index].dataType;
value_type &= IF_VARTYPES;

View File

@ -140,9 +140,13 @@ MIFsetup(
/* For each parameter not given explicitly on the .model */
/* card, default it */
for(i = 0; i < model->num_param; i++) {
if(model->param[i]->is_null && DEVices[mod_type]->DEVpublic.param[i].has_model_scope) {
for(int imp=0; imp<*(DEVices[mod_type]->DEVpublic.numModelParms);imp++)
{
i = DEVices[mod_type]->DEVpublic.modelParms[imp].id;
if(i<0 || i>= model->num_param)
continue;
if(model->param[i]->is_null) {
/* setup a pointer for quick access */
param_info = &(DEVices[mod_type]->DEVpublic.param[i]);
@ -201,7 +205,87 @@ MIFsetup(
} /* end for number of parameters */
/* For each instance, initialize stuff used by cm_... functions */
/* For each instance, set default value for instance parameter */
/* if parameter is both for instance and model, copy model value */
for(here = MIFinstances(model); here != NULL; here = MIFnextInstance(here)) {
for(int ip=0; ip<*(DEVices[mod_type]->DEVpublic.numInstanceParms);ip++)
{
i = DEVices[mod_type]->DEVpublic.instanceParms[ip].id;
if(i<0 || i>= model->num_param)
break; /* not an instance parameter from ifspec.ifs */
if(here->iparam[ip]->is_null) {
int alsomodidx;
/* setup a pointer for quick access */
param_info = &(DEVices[mod_type]->DEVpublic.param[i]);
/* look if it is also a model parameter */
for(alsomodidx=0; alsomodidx<*(DEVices[mod_type]->DEVpublic.numModelParms);alsomodidx++)
if(DEVices[mod_type]->DEVpublic.modelParms[alsomodidx].id == i)
break;
if(alsomodidx<*(DEVices[mod_type]->DEVpublic.numModelParms))
{
/* copy from model */
size = model->param[i]->size;
here->iparam[ip]->is_null = 0;
here->iparam[ip]->size = size;
here->iparam[ip]->element = TMALLOC(Mif_Value_t, size);
for(j = 0; j < size; j++)
here->iparam[ip]->element[j] = model->param[i]->element[j];
}
else
{
/* copy default value from ifspec.ifs */
/* determine the size and allocate the parameter element(s) */
if(! param_info->is_array) {
here->iparam[ip]->size = 1;
here->iparam[ip]->element = TMALLOC(Mif_Value_t, 1);
} else { /* parameter is an array */
/* MIF_INP2A() parser assures that there is an associated array connection */
size = here->conn[param_info->conn_ref]->size;
here->iparam[ip]->size = size;
here->iparam[ip]->element = TMALLOC(Mif_Value_t, size);
} /* end if parameter is an array */
/* set the parameter element(s) to default value */
for(j = 0; j < here->iparam[ip]->size; j++) {
switch(param_info->type) {
case MIF_BOOLEAN:
here->iparam[ip]->element[j].bvalue = param_info->default_value.bvalue;
break;
case MIF_INTEGER:
here->iparam[ip]->element[j].ivalue = param_info->default_value.ivalue;
break;
case MIF_REAL:
here->iparam[ip]->element[j].rvalue = param_info->default_value.rvalue;
break;
case MIF_COMPLEX:
here->iparam[ip]->element[j].cvalue = param_info->default_value.cvalue;
break;
case MIF_STRING:
here->iparam[ip]->element[j].svalue = param_info->default_value.svalue;
break;
default:
return(E_BADPARM);
}
} /* end for number of elements in param array */
} /* end copy from default */
} /* end param is null */
} /* end for ip instance parameter */
} /* end for instance here */
/* For each instance, initialize stuff used by cm_... functions */
for(here = MIFinstances(model); here != NULL; here = MIFnextInstance(here)) {

View File

@ -84,4 +84,5 @@ struct coreInfo_t coreInfo =
no_free,
#endif
MIFParam,
NULL
};