instance parameters for xspice, initial commit
This commit is contained in:
parent
a0389bb547
commit
7c0688cca4
|
|
@ -76,6 +76,9 @@ struct coreInfo_t {
|
|||
void * ((*dllitf_tmalloc)(size_t));
|
||||
void * ((*dllitf_trealloc)(const void *, size_t));
|
||||
void ((*dllitf_txfree)(const void *));
|
||||
|
||||
/* added for instance parameters */
|
||||
int ((*dllitf_MIFParam)(int, IFvalue *, GENinstance*, IFvalue *));
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -368,7 +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 */
|
||||
|
||||
Mif_Param_Data_t **iparam; /* Information about each inst parameter */
|
||||
};
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -85,6 +85,9 @@ struct MIFinstance {
|
|||
int inst_index; /* Index into inst_table in evt struct in ckt */
|
||||
Mif_Callback_t callback; /* instance callback function */
|
||||
|
||||
/* F.B: add instance parameters ? */
|
||||
int num_iparam; /* number of instance parameters on the code model */
|
||||
Mif_Param_Data_t **iparam; /* array of structs for each instance parameter */
|
||||
};
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -115,7 +115,9 @@ 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 */
|
||||
|
||||
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 */
|
||||
};
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -91,6 +91,12 @@ extern int MIFload(
|
|||
CKTcircuit *ckt
|
||||
);
|
||||
|
||||
extern int MIFParam(
|
||||
int iparam,
|
||||
IFvalue *value,
|
||||
GENinstance *inst,
|
||||
IFvalue *select
|
||||
);
|
||||
|
||||
extern int MIFmParam(
|
||||
int param_index,
|
||||
|
|
|
|||
|
|
@ -132,6 +132,16 @@ typedef struct {
|
|||
} Complex_t;
|
||||
|
||||
|
||||
/*
|
||||
* The scope of a parameter
|
||||
*/
|
||||
|
||||
typedef enum {
|
||||
CMPP_MODEL,
|
||||
CMPP_INSTANCE,
|
||||
CMPP_BOTH,
|
||||
} Param_Scope_t;
|
||||
|
||||
|
||||
/*
|
||||
* Values of different types.
|
||||
|
|
@ -223,6 +233,7 @@ typedef struct {
|
|||
bool has_upper_bound; /* True if there is an array size upper bound */
|
||||
int upper_bound; /* Array size upper bound */
|
||||
bool null_allowed; /* True if null is allowed for this parameter */
|
||||
Param_Scope_t scope; /* is instance or model parameter */
|
||||
|
||||
} Param_Info_t;
|
||||
|
||||
|
|
|
|||
|
|
@ -62,7 +62,7 @@ double yydval;
|
|||
|
||||
%}
|
||||
|
||||
%start BOOL CTYPE DIR DTYPE
|
||||
%start BOOL CTYPE DIR DTYPE SCOPE
|
||||
|
||||
%x comment stringl
|
||||
|
||||
|
|
@ -120,6 +120,7 @@ null_allowed{W}*: {BEGIN BOOL; return TOK_NULL_ALLOWED;}
|
|||
parameter_name{W}*: {return TOK_PARAMETER_NAME;}
|
||||
parameter_table{W}*: {return TOK_PARAMETER_TABLE;}
|
||||
spice_model_name{W}*: {return TOK_SPICE_MODEL_NAME;}
|
||||
parameter_scope{W}*: {BEGIN SCOPE; return TOK_PARAMETER_SCOPE;}
|
||||
|
||||
<BOOL>yes {return TOK_BOOL_YES;}
|
||||
<BOOL>no {return TOK_BOOL_NO;}
|
||||
|
|
@ -148,6 +149,10 @@ false {return TOK_BOOL_NO;}
|
|||
<DTYPE>string {return TOK_DTYPE_STRING;}
|
||||
<DTYPE>pointer {return TOK_DTYPE_POINTER;}
|
||||
|
||||
<SCOPE>model {return TOK_SCOPE_MODEL;}
|
||||
<SCOPE>instance {return TOK_SCOPE_INSTANCE;}
|
||||
<SCOPE>both {return TOK_SCOPE_BOTH;}
|
||||
|
||||
"<" {return TOK_LANGLE;}
|
||||
">" {return TOK_RANGLE;}
|
||||
"[" {return TOK_LBRACKET;}
|
||||
|
|
|
|||
|
|
@ -496,6 +496,11 @@ check_end_item_num (void)
|
|||
%token TOK_SPICE_MODEL_NAME
|
||||
%token TOK_STRING_LITERAL
|
||||
|
||||
%token TOK_PARAMETER_SCOPE
|
||||
%token TOK_SCOPE_MODEL
|
||||
%token TOK_SCOPE_INSTANCE
|
||||
%token TOK_SCOPE_BOTH
|
||||
|
||||
%union {
|
||||
Ctype_List_t *ctype_list;
|
||||
Dir_t dir;
|
||||
|
|
@ -509,6 +514,7 @@ check_end_item_num (void)
|
|||
int ival;
|
||||
double rval;
|
||||
Complex_t cval;
|
||||
Param_Scope_t scope;
|
||||
}
|
||||
|
||||
%type <ctype_list> ctype_list delimited_ctype_list
|
||||
|
|
@ -523,6 +529,7 @@ check_end_item_num (void)
|
|||
%type <ival> integer
|
||||
%type <rval> real
|
||||
%type <cval> complex
|
||||
%type <scope> scope
|
||||
|
||||
%start ifs_file
|
||||
|
||||
|
|
@ -739,6 +746,13 @@ parameter_table_item : TOK_PARAMETER_NAME list_of_ids
|
|||
FOR_ITEM (i) {
|
||||
TBL->param[i].null_allowed = ITEM_BUF(i).btype;
|
||||
}}
|
||||
| TOK_PARAMETER_SCOPE list_of_scopes
|
||||
{int i;
|
||||
END;
|
||||
FOR_ITEM (i) {
|
||||
TBL->param[i].scope = ITEM_BUF(i).scope;
|
||||
}
|
||||
}
|
||||
;
|
||||
|
||||
static_var_table : /* empty */
|
||||
|
|
@ -798,6 +812,14 @@ direction : TOK_DIR_IN {$$ = CMPP_IN;}
|
|||
| TOK_DIR_INOUT {$$ = CMPP_INOUT;}
|
||||
;
|
||||
|
||||
list_of_scopes : /* empty */
|
||||
| list_of_scopes scope {ITEM; BUF.scope = $2;}
|
||||
;
|
||||
|
||||
scope : TOK_SCOPE_MODEL {$$ = CMPP_MODEL;}
|
||||
| TOK_SCOPE_INSTANCE {$$ = CMPP_INSTANCE;}
|
||||
| TOK_SCOPE_BOTH {$$ = CMPP_BOTH;}
|
||||
|
||||
list_of_bool : /* empty */
|
||||
| list_of_bool btype {ITEM; BUF.btype = $2;}
|
||||
;
|
||||
|
|
|
|||
|
|
@ -448,7 +448,11 @@ macro : TOK_INIT
|
|||
{fprintf (mod_yyout, "mif_private->circuit.t[%s]", $3);}
|
||||
| TOK_PARAM TOK_LPAREN subscriptable_id TOK_RPAREN
|
||||
{int i = valid_subid ($3, PARAM);
|
||||
fprintf (mod_yyout, "mif_private->param[%d]->element[%s]",
|
||||
if(mod_ifs_table->param[i].scope == CMPP_MODEL)
|
||||
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));
|
||||
put_type (mod_yyout, mod_ifs_table->param[i].type);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -106,7 +106,7 @@ int write_ifs_c_file(
|
|||
|
||||
/* Open the ifspec.c file for write access */
|
||||
if ((filename = gen_filename(filename_in, "w")) == (char *) NULL) {
|
||||
print_error("ERROR - Unable to build path to \"%s\".", filename);
|
||||
print_error("ERROR - Unable to build path to \"%s\".", filename_in);
|
||||
xrc = -1;
|
||||
goto EXITPOINT;
|
||||
}
|
||||
|
|
@ -290,11 +290,15 @@ static int write_pTable(
|
|||
int i;
|
||||
bool is_array;
|
||||
Data_Type_t type;
|
||||
|
||||
int iparam_index;
|
||||
|
||||
/* Only write the pTable if there is something to put in it. */
|
||||
/* Otherwise, we will put NULL in the SPICEdev structure in its slot */
|
||||
if (ifs_table->num_inst_var == 0) {
|
||||
for(i = 0; i < ifs_table->num_param; i++)
|
||||
if(ifs_table->param[i].scope != CMPP_MODEL)
|
||||
break; /* has at least one instance parameter */
|
||||
if(i==ifs_table->num_param) /* has no instance parameter */
|
||||
if (ifs_table->num_inst_var == 0) { /* has no static var */
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
@ -306,6 +310,68 @@ static int write_pTable(
|
|||
"static IFparm MIFpTable[] = {\n");
|
||||
|
||||
|
||||
/* F.B: add instance parameters as IOP */
|
||||
/* Use the index of the element in the parameter info array */
|
||||
/* as the SPICE3 integer tag. */
|
||||
/* i.e for the same parameter, the same tag is used for both model and instance */
|
||||
iparam_index=0;
|
||||
Param_Info_t *param = ifs_table->param;
|
||||
for(i = 0; i < ifs_table->num_param; i++) {
|
||||
Param_Info_t *param_cur = param + i;
|
||||
|
||||
/* skip if it is a model parameter */
|
||||
if(param_cur->scope == CMPP_MODEL)
|
||||
continue;
|
||||
|
||||
/* Use the SPICE3 IOP macro since instance parameters are input/output */
|
||||
|
||||
rc |= fprintf(fp, " IOP(");
|
||||
|
||||
/* Put in the name of the parameter and the integer tag */
|
||||
rc |= fprintf(fp, "\"%s\", ", param_cur->name);
|
||||
rc |= fprintf(fp, "%d, ", i);
|
||||
|
||||
/* Format SPICE3 type according to parameter type field */
|
||||
|
||||
const bool is_array = param_cur->is_array;
|
||||
const Data_Type_t type = param_cur->type;
|
||||
|
||||
if (is_array) {
|
||||
rc |= fprintf(fp, "(");
|
||||
}
|
||||
|
||||
if (type == CMPP_BOOLEAN) {
|
||||
rc |= fprintf(fp, "IF_FLAG"); /* no BOOLEAN in SPICE3 */
|
||||
}
|
||||
else if (type == CMPP_INTEGER) {
|
||||
rc |= fprintf(fp, "IF_INTEGER");
|
||||
}
|
||||
else if (type == CMPP_REAL) {
|
||||
rc |= fprintf(fp, "IF_REAL");
|
||||
}
|
||||
else if (type == CMPP_COMPLEX) {
|
||||
rc |= fprintf(fp, "IF_COMPLEX");
|
||||
}
|
||||
else if (type == CMPP_STRING) {
|
||||
rc |= fprintf(fp, "IF_STRING");
|
||||
}
|
||||
else {
|
||||
print_error("INTERNAL ERROR - write_mPTable() - Impossible data type.");
|
||||
xrc = -1;
|
||||
}
|
||||
|
||||
if (is_array) {
|
||||
rc |= fprintf(fp, "|IF_VECTOR)");
|
||||
}
|
||||
|
||||
|
||||
/* Put in the description string and finish this line off */
|
||||
rc |= fprintf(fp, ", \"%s\"),\n", ifs_table->param[i].description);
|
||||
|
||||
iparam_index++;
|
||||
} /* end of loop over parameters */
|
||||
|
||||
|
||||
/* Write out an entry for each instance variable in the table */
|
||||
|
||||
/* Use the index of the element in the instance variable info array */
|
||||
|
|
@ -363,6 +429,11 @@ static int write_pTable(
|
|||
/* Put in the description string and finish this line off */
|
||||
rc |= fprintf(fp, ", \"%s\"),\n", ifs_table->inst_var[i].description);
|
||||
} /* end of loop over instance variables */
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/* Finish off the structure */
|
||||
rc |= fprintf(fp, "};\n\n");
|
||||
|
|
@ -422,7 +493,11 @@ static int write_mPTable(
|
|||
Param_Info_t *param = ifs_table->param;
|
||||
for(i = 0; i < ifs_table->num_param; i++) {
|
||||
Param_Info_t *param_cur = param + i;
|
||||
|
||||
|
||||
/* skip if it is an instance parameter */
|
||||
if(param_cur->scope == CMPP_INSTANCE)
|
||||
continue;
|
||||
|
||||
/* Use the SPICE3 IOP macro since model parameters are input/output */
|
||||
|
||||
rc |= fprintf(fp, " IOP(");
|
||||
|
|
@ -684,6 +759,7 @@ static int write_param_info(
|
|||
int xrc = 0;
|
||||
int i;
|
||||
const char *str;
|
||||
int inst_param_index = 0;
|
||||
|
||||
|
||||
/* Only write the paramTable if there is something to put in it. */
|
||||
|
|
@ -815,7 +891,18 @@ static int write_param_info(
|
|||
|
||||
str = boolean_to_str(p_param_cur->null_allowed);
|
||||
rc |= fprintf(fp, " %s,\n", str);
|
||||
|
||||
|
||||
/* F.B. info about instance parameters */
|
||||
str = boolean_to_str(p_param_cur->scope != CMPP_INSTANCE);
|
||||
rc |= fprintf(fp, " %s,\n", str);
|
||||
str = boolean_to_str(p_param_cur->scope != CMPP_MODEL);
|
||||
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);
|
||||
|
||||
if(p_param_cur->scope != CMPP_MODEL)
|
||||
inst_param_index++;
|
||||
|
||||
rc |= fprintf(fp, " },\n");
|
||||
|
||||
} /* for number of parameters */
|
||||
|
|
@ -931,13 +1018,20 @@ static int write_SPICEdev(
|
|||
{
|
||||
int rc = 0; /* init print rc to nonnegative (no error) */
|
||||
int xrc = 0;
|
||||
|
||||
int i, ninstparams;
|
||||
|
||||
/* Extern the code model function name */
|
||||
rc |= fprintf(fp,
|
||||
"\n"
|
||||
"extern void %s(Mif_Private_t *);\n",
|
||||
ifs_table->name.c_fcn_name);
|
||||
|
||||
|
||||
/* count instance parameters */
|
||||
ninstparams=0;
|
||||
for(i = 0; i < ifs_table->num_param; i++)
|
||||
if(ifs_table->param[i].scope != CMPP_MODEL)
|
||||
ninstparams++;
|
||||
|
||||
/* SPICE now needs these static integers */
|
||||
rc |= fprintf(fp,
|
||||
"\n"
|
||||
|
|
@ -947,7 +1041,7 @@ static int write_SPICEdev(
|
|||
"static int val_numModelParms = %d;\n"
|
||||
"static int val_sizeofMIFinstance = sizeof(MIFinstance);\n"
|
||||
"static int val_sizeofMIFmodel = sizeof(MIFmodel);\n",
|
||||
ifs_table->num_inst_var, ifs_table->num_param);
|
||||
ifs_table->num_inst_var + ninstparams, ifs_table->num_param);
|
||||
|
||||
/* Write out the structure beginning */
|
||||
|
||||
|
|
@ -969,10 +1063,10 @@ static int write_SPICEdev(
|
|||
" .termNames = NULL,\n"
|
||||
" .numInstanceParms = &val_numInstanceParms,\n");
|
||||
|
||||
if(ifs_table->num_inst_var > 0)
|
||||
rc |= fprintf(fp, " .instanceParms = MIFpTable,\n");
|
||||
else
|
||||
if((ninstparams == 0) && (ifs_table->num_inst_var == 0))
|
||||
rc |= fprintf(fp, " .instanceParms = NULL,\n");
|
||||
else
|
||||
rc |= fprintf(fp, " .instanceParms = MIFpTable,\n");
|
||||
|
||||
rc |= fprintf(fp, " .numModelParms = &val_numModelParms,\n");
|
||||
if(ifs_table->num_param > 0)
|
||||
|
|
|
|||
|
|
@ -223,6 +223,7 @@ int EVTload(
|
|||
cm_data.conn = inst->conn;
|
||||
cm_data.num_param = inst->num_param;
|
||||
cm_data.param = inst->param;
|
||||
cm_data.iparam = inst->iparam;
|
||||
cm_data.num_inst_var = inst->num_inst_var;
|
||||
cm_data.inst_var = inst->inst_var;
|
||||
cm_data.callback = &(inst->callback);
|
||||
|
|
|
|||
|
|
@ -23,7 +23,7 @@
|
|||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
// Do not modify anything below this line
|
||||
// Do not modify anything below this line (F.B.: added MIFparam however)
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
SPICEdev *cmDEVices[] = {
|
||||
|
|
@ -164,6 +164,15 @@ int MIFmParam(
|
|||
return (coreitf->dllitf_MIFmParam)(param_index,value,inModel);
|
||||
}
|
||||
|
||||
int MIFParam(
|
||||
int param_index,
|
||||
IFvalue *value,
|
||||
GENinstance *inst,
|
||||
IFvalue *select
|
||||
) {
|
||||
return (coreitf->dllitf_MIFParam)(param_index,value,inst,select);
|
||||
}
|
||||
|
||||
int MIFask(
|
||||
CKTcircuit *ckt,
|
||||
GENinstance *inst,
|
||||
|
|
|
|||
|
|
@ -19,6 +19,7 @@ libmifxsp_la_SOURCES = \
|
|||
mifdelete.c \
|
||||
mifmdelete.c \
|
||||
mifdestr.c \
|
||||
mifpara.c \
|
||||
mif.c
|
||||
|
||||
AM_CPPFLAGS = @AM_CPPFLAGS@ -I$(top_srcdir)/src/include
|
||||
|
|
|
|||
|
|
@ -682,7 +682,20 @@ static void MIFinit_inst(
|
|||
|
||||
fast->num_param = mdfast->num_param;
|
||||
fast->param = mdfast->param;
|
||||
|
||||
|
||||
/* allocate instance parameter data */
|
||||
fast->num_iparam = *(DEVices[mod_type]->DEVpublic.numInstanceParms) - DEVices[mod_type]->DEVpublic.num_inst_var;
|
||||
if(fast->num_iparam>0)
|
||||
fast->iparam = TMALLOC(Mif_Param_Data_t* ,fast->num_iparam);
|
||||
else
|
||||
fast->iparam = NULL;
|
||||
for(i = 0; i < fast->num_iparam; i++) {
|
||||
fast->iparam[i] = TMALLOC(Mif_Param_Data_t, 1);
|
||||
fast->iparam[i]->is_null = MIF_TRUE;
|
||||
fast->iparam[i]->size = 0;
|
||||
fast->iparam[i]->element = NULL;
|
||||
}
|
||||
|
||||
/* initialize any additional instance data */
|
||||
fast->initialized = MIF_FALSE;
|
||||
fast->analog = MIF_FALSE;
|
||||
|
|
|
|||
|
|
@ -51,8 +51,22 @@ NON-STANDARD FEATURES
|
|||
#include "ngspice/mifproto.h"
|
||||
#include "ngspice/mifdefs.h"
|
||||
|
||||
#include "ngspice/mifparse.h"
|
||||
|
||||
/* #include "suffix.h" */
|
||||
|
||||
/* forward prototypes */
|
||||
int MIFaskInstVar(
|
||||
MIFinstance *inst, /* The instance to get the value from */
|
||||
int inst_index, /* The inst var to get */
|
||||
IFvalue *value /* The value returned */
|
||||
);
|
||||
int MIFaskInstParam(
|
||||
MIFinstance *inst, /* The instance to get the value from */
|
||||
int param_index, /* The parameter to get */
|
||||
IFvalue *value /* The value returned */
|
||||
);
|
||||
|
||||
|
||||
/*
|
||||
MIFask
|
||||
|
|
@ -77,13 +91,7 @@ int MIFask(
|
|||
MIFinstance *inst;
|
||||
MIFmodel *model;
|
||||
int mod_type;
|
||||
int value_type;
|
||||
int i;
|
||||
int size;
|
||||
|
||||
int inst_index;
|
||||
|
||||
Mif_Boolean_t is_array;
|
||||
|
||||
NG_IGNORE(ckt);
|
||||
NG_IGNORE(select);
|
||||
|
|
@ -94,21 +102,46 @@ int MIFask(
|
|||
/* Arrange for access to MIF specific data in the model */
|
||||
model = MIFmodPtr(inst);
|
||||
|
||||
|
||||
/* Get model type */
|
||||
mod_type = model->MIFmodType;
|
||||
if((mod_type < 0) || (mod_type >= DEVmaxnum))
|
||||
return(E_BADPARM);
|
||||
|
||||
/* Adjust parameter tag to actual index into inst info array */
|
||||
inst_index = which - model->num_param;
|
||||
/* see if is trying to get an instance variable or an instance parameter */
|
||||
if(which>= model->num_param)
|
||||
return MIFaskInstVar(inst, which - model->num_param, value);
|
||||
else
|
||||
return MIFaskInstParam(inst, which, value);
|
||||
}
|
||||
|
||||
/* Check instance index for validity */
|
||||
if((inst_index < 0) || (inst_index >= inst->num_inst_var))
|
||||
|
||||
int MIFaskInstVar(
|
||||
MIFinstance *inst, /* The instance to get the value from */
|
||||
int inst_index, /* The inst var to get */
|
||||
IFvalue *value /* The value returned */
|
||||
)
|
||||
{
|
||||
MIFmodel *model;
|
||||
int mod_type;
|
||||
int value_type;
|
||||
int i;
|
||||
int size;
|
||||
|
||||
Mif_Boolean_t is_array;
|
||||
|
||||
model = MIFmodPtr(inst);
|
||||
/* Get model type */
|
||||
mod_type = model->MIFmodType;
|
||||
if((mod_type < 0) || (mod_type >= DEVmaxnum))
|
||||
return(E_BADPARM);
|
||||
|
||||
/* get value type to know which members of unions to access */
|
||||
value_type = DEVices[mod_type]->DEVpublic.instanceParms[inst_index].dataType;
|
||||
/* get value type to know which members of unions to access */
|
||||
for(i=0;i<*(DEVices[mod_type]->DEVpublic.numInstanceParms);i++)
|
||||
if(DEVices[mod_type]->DEVpublic.instanceParms[i].id == model->num_param+inst_index)
|
||||
break;
|
||||
if(i>=*(DEVices[mod_type]->DEVpublic.numInstanceParms))
|
||||
return(E_BADPARM);
|
||||
value_type = DEVices[mod_type]->DEVpublic.instanceParms[i].dataType;
|
||||
value_type &= IF_VARTYPES;
|
||||
|
||||
|
||||
|
|
@ -223,3 +256,153 @@ int MIFask(
|
|||
|
||||
return(OK);
|
||||
}
|
||||
|
||||
|
||||
|
||||
int MIFaskInstParam(
|
||||
MIFinstance *inst, /* The instance to get the value from */
|
||||
int param_index, /* The parameter to get */
|
||||
IFvalue *value /* The value returned */
|
||||
)
|
||||
{
|
||||
MIFmodel *model;
|
||||
int mod_type;
|
||||
int value_type;
|
||||
int i;
|
||||
int size;
|
||||
|
||||
int inst_index;
|
||||
|
||||
Mif_Boolean_t is_array;
|
||||
|
||||
model = MIFmodPtr(inst);
|
||||
/* Get model type */
|
||||
mod_type = model->MIFmodType;
|
||||
if((mod_type < 0) || (mod_type >= DEVmaxnum))
|
||||
return(E_BADPARM);
|
||||
|
||||
/* get value type to know which members of unions to access */
|
||||
for(i=0;i<*(DEVices[mod_type]->DEVpublic.numInstanceParms);i++)
|
||||
if(DEVices[mod_type]->DEVpublic.instanceParms[i].id == param_index)
|
||||
break;
|
||||
if(i>=*(DEVices[mod_type]->DEVpublic.numInstanceParms))
|
||||
return(E_BADPARM);
|
||||
value_type = DEVices[mod_type]->DEVpublic.instanceParms[i].dataType;
|
||||
value_type &= IF_VARTYPES;
|
||||
|
||||
/* get index into inst->iparam */
|
||||
inst_index = DEVices[mod_type]->DEVpublic.param[param_index].inst_param_index;
|
||||
if(inst_index <0)
|
||||
return(E_BADPARM);
|
||||
|
||||
/* determine if the parameter is an array or not */
|
||||
is_array = value_type & IF_VECTOR;
|
||||
|
||||
|
||||
/* Transfer the values to the SPICE3C1 value union from the param elements */
|
||||
/* This is analagous to what SPICE3 does with other device types */
|
||||
|
||||
|
||||
if(! is_array) {
|
||||
|
||||
switch(value_type) {
|
||||
|
||||
case IF_FLAG:
|
||||
value->iValue = inst->iparam[inst_index]->element[0].bvalue;
|
||||
break;
|
||||
|
||||
case IF_INTEGER:
|
||||
value->iValue = inst->iparam[inst_index]->element[0].ivalue;
|
||||
break;
|
||||
|
||||
case IF_REAL:
|
||||
value->rValue = inst->iparam[inst_index]->element[0].rvalue;
|
||||
break;
|
||||
|
||||
case IF_STRING:
|
||||
/* Make copy of string. We don't trust caller to not free it */
|
||||
/* These copies could get expensive! */
|
||||
value->sValue = MIFcopy(inst->iparam[inst_index]->element[0].svalue);
|
||||
break;
|
||||
|
||||
case IF_COMPLEX:
|
||||
/* we don't trust the caller to have a parallel complex structure */
|
||||
/* so copy the real and imaginary parts explicitly */
|
||||
value->cValue.real = inst->iparam[inst_index]->element[0].cvalue.real;
|
||||
value->cValue.imag = inst->iparam[inst_index]->element[0].cvalue.imag;
|
||||
break;
|
||||
|
||||
default:
|
||||
return(E_BADPARM);
|
||||
|
||||
}
|
||||
}
|
||||
else { /* it is an array */
|
||||
|
||||
size = inst->iparam[inst_index]->size;
|
||||
if(size < 0)
|
||||
size = 0;
|
||||
|
||||
value->v.numValue = size;
|
||||
|
||||
switch(value_type) {
|
||||
|
||||
/* Note that we malloc space each time this function is called. */
|
||||
/* This is what TRAask.c does, so we do it too, even though */
|
||||
/* we don't know if it is ever freed... */
|
||||
|
||||
case IF_FLAGVEC:
|
||||
if(size <= 0)
|
||||
break;
|
||||
value->v.vec.iVec = TMALLOC(int, size);
|
||||
for(i = 0; i < size; i++)
|
||||
value->v.vec.iVec[i] = inst->iparam[inst_index]->element[i].bvalue;
|
||||
break;
|
||||
|
||||
case IF_INTVEC:
|
||||
if(size <= 0)
|
||||
break;
|
||||
value->v.vec.iVec = TMALLOC(int, size);
|
||||
for(i = 0; i < size; i++)
|
||||
value->v.vec.iVec[i] = inst->iparam[inst_index]->element[i].ivalue;
|
||||
break;
|
||||
|
||||
case IF_REALVEC:
|
||||
if(size <= 0)
|
||||
break;
|
||||
value->v.vec.rVec = TMALLOC(double, size);
|
||||
for(i = 0; i < size; i++)
|
||||
value->v.vec.rVec[i] = inst->iparam[inst_index]->element[i].rvalue;
|
||||
break;
|
||||
|
||||
case IF_STRINGVEC:
|
||||
if(size <= 0)
|
||||
break;
|
||||
value->v.vec.sVec = TMALLOC(char *, size);
|
||||
for(i = 0; i < size; i++)
|
||||
/* Make copy of string. We don't trust caller to not free it */
|
||||
/* These copies could get expensive! */
|
||||
value->v.vec.sVec[i] = MIFcopy(inst->iparam[inst_index]->element[i].svalue);
|
||||
break;
|
||||
|
||||
case IF_CPLXVEC:
|
||||
if(size <= 0)
|
||||
break;
|
||||
/* we don't trust the caller to have a parallel complex structure */
|
||||
/* so copy the real and imaginary parts explicitly */
|
||||
value->v.vec.cVec = TMALLOC(IFcomplex, size);
|
||||
for(i = 0; i < size; i++) {
|
||||
value->v.vec.cVec[i].real = inst->iparam[inst_index]->element[i].cvalue.real;
|
||||
value->v.vec.cVec[i].imag = inst->iparam[inst_index]->element[i].cvalue.imag;
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
return(E_BADPARM);
|
||||
|
||||
} /* end switch */
|
||||
|
||||
} /* end else */
|
||||
|
||||
return(OK);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -86,6 +86,7 @@ MIFdelete(GENinstance *gen_inst)
|
|||
cm_data.conn = here->conn;
|
||||
cm_data.num_param = here->num_param;
|
||||
cm_data.param = here->param;
|
||||
cm_data.iparam = here->iparam;
|
||||
cm_data.num_inst_var = here->num_inst_var;
|
||||
cm_data.inst_var = here->inst_var;
|
||||
cm_data.callback = &(here->callback);
|
||||
|
|
@ -170,7 +171,23 @@ MIFdelete(GENinstance *gen_inst)
|
|||
}
|
||||
FREE(here->inst_var);
|
||||
|
||||
/* Free the instance params stuff allocated in mif_inp2.c */
|
||||
for (i = 0; i < here->num_iparam; i++) {
|
||||
/* delete content of union 'element' if it contains a string */
|
||||
if (here->iparam[i]->element) {
|
||||
if (here->iparam[i]->eltype == IF_STRING)
|
||||
FREE(here->iparam[i]->element[0].svalue);
|
||||
else if (here->iparam[i]->eltype == IF_STRINGVEC)
|
||||
for (int j = 0; j < here->iparam[i]->size; j++)
|
||||
FREE(here->iparam[i]->element[j].svalue);
|
||||
FREE(here->iparam[i]->element);
|
||||
}
|
||||
FREE(here->iparam[i]);
|
||||
}
|
||||
FREE(here->iparam);
|
||||
|
||||
/* ************************************************************* */
|
||||
/* Before instance parameters was added there was this comment: */
|
||||
/* Dont free params here. They are not currently implemented on */
|
||||
/* a per-instance basis, so their allocated space is owned by */
|
||||
/* the parent model, not the instance. Param stuff will be freed */
|
||||
|
|
|
|||
|
|
@ -435,6 +435,7 @@ MIFload(
|
|||
cm_data.conn = here->conn;
|
||||
cm_data.num_param = here->num_param;
|
||||
cm_data.param = here->param;
|
||||
cm_data.iparam = here->iparam;
|
||||
cm_data.num_inst_var = here->num_inst_var;
|
||||
cm_data.inst_var = here->inst_var;
|
||||
cm_data.callback = &(here->callback);
|
||||
|
|
|
|||
|
|
@ -0,0 +1,203 @@
|
|||
/*============================================================================
|
||||
FILE MIFPara.c
|
||||
|
||||
Derived from MIFmPara.c by Florian Ballenegger
|
||||
|
||||
Original copyright:
|
||||
|
||||
MEMBER OF process XSPICE
|
||||
|
||||
Copyright 1991
|
||||
Georgia Tech Research Corporation
|
||||
Atlanta, Georgia 30332
|
||||
All Rights Reserved
|
||||
|
||||
PROJECT A-8503
|
||||
|
||||
AUTHORS
|
||||
|
||||
9/12/91 Bill Kuhn
|
||||
|
||||
SUMMARY
|
||||
|
||||
This file contains the function used to assign the value of a parameter
|
||||
read from the .model card into the appropriate structure in the model.
|
||||
|
||||
============================================================================*/
|
||||
|
||||
#include "ngspice/ngspice.h"
|
||||
#include "ngspice/const.h"
|
||||
#include "ngspice/ifsim.h"
|
||||
#include "ngspice/devdefs.h"
|
||||
#include "ngspice/sperror.h"
|
||||
|
||||
#include "ngspice/mifproto.h"
|
||||
#include "ngspice/mifparse.h"
|
||||
#include "ngspice/mifdefs.h"
|
||||
#include "ngspice/mifcmdat.h"
|
||||
|
||||
|
||||
|
||||
/* ARGSUSED */
|
||||
int
|
||||
MIFParam(int param_index, IFvalue *value, GENinstance *inst_in, IFvalue *select)
|
||||
{
|
||||
|
||||
MIFmodel *model;
|
||||
MIFinstance *inst;
|
||||
int mod_type;
|
||||
int value_type;
|
||||
int i;
|
||||
int iparam;
|
||||
Mif_Boolean_t is_array;
|
||||
|
||||
|
||||
NG_IGNORE(select);
|
||||
|
||||
/* Arrange for access to MIF specific data in the model */
|
||||
inst = (MIFinstance*) inst_in;
|
||||
model = MIFmodPtr(inst);
|
||||
|
||||
/* Get model type */
|
||||
mod_type = model->MIFmodType;
|
||||
if((mod_type < 0) || (mod_type >= DEVmaxnum))
|
||||
return(E_BADPARM);
|
||||
|
||||
|
||||
/* Check parameter index for validity */
|
||||
if((param_index < 0) || (param_index >= model->num_param))
|
||||
return(E_BADPARM);
|
||||
|
||||
if(!DEVices[mod_type]->DEVpublic.param[param_index].has_inst_scope)
|
||||
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;
|
||||
|
||||
|
||||
/* determine if the parameter is an array or not */
|
||||
is_array = value_type & IF_VECTOR;
|
||||
|
||||
/* initialize the parameter is_null and size elements and allocate elements */
|
||||
inst->iparam[iparam]->is_null = MIF_FALSE;
|
||||
/* element may exist already, if called from 'alter' */
|
||||
FREE(inst->iparam[iparam]->element);
|
||||
if(is_array) {
|
||||
inst->iparam[iparam]->size = value->v.numValue;
|
||||
inst->iparam[iparam]->element = TMALLOC(Mif_Value_t, value->v.numValue);
|
||||
}
|
||||
else {
|
||||
inst->iparam[iparam]->size = 1;
|
||||
inst->iparam[iparam]->element = TMALLOC(Mif_Value_t, 1);
|
||||
}
|
||||
|
||||
|
||||
/* Transfer the values from the SPICE3C1 value union to the param elements */
|
||||
/* This is analagous to what SPICE3 does with other device types */
|
||||
|
||||
|
||||
if(! is_array) {
|
||||
|
||||
switch(value_type) {
|
||||
|
||||
case IF_FLAG:
|
||||
inst->iparam[iparam]->element[0].bvalue = value->iValue;
|
||||
inst->iparam[iparam]->eltype = IF_FLAG;
|
||||
break;
|
||||
|
||||
case IF_INTEGER:
|
||||
inst->iparam[iparam]->element[0].ivalue = value->iValue;
|
||||
inst->iparam[iparam]->eltype = IF_INTEGER;
|
||||
break;
|
||||
|
||||
case IF_REAL:
|
||||
inst->iparam[iparam]->element[0].rvalue = value->rValue;
|
||||
inst->iparam[iparam]->eltype = IF_REAL;
|
||||
break;
|
||||
|
||||
case IF_STRING:
|
||||
/* we don't trust the caller to keep the string alive, so copy it */
|
||||
inst->iparam[iparam]->element[0].svalue =
|
||||
TMALLOC(char, 1 + strlen(value->sValue));
|
||||
strcpy(inst->iparam[iparam]->element[0].svalue, value->sValue);
|
||||
inst->iparam[iparam]->eltype = IF_STRING;
|
||||
break;
|
||||
|
||||
case IF_COMPLEX:
|
||||
/* we don't trust the caller to have a parallel complex structure */
|
||||
/* so copy the real and imaginary parts explicitly */
|
||||
inst->iparam[iparam]->element[0].cvalue.real = value->cValue.real;
|
||||
inst->iparam[iparam]->element[0].cvalue.imag = value->cValue.imag;
|
||||
inst->iparam[iparam]->eltype = IF_COMPLEX;
|
||||
break;
|
||||
|
||||
default:
|
||||
return(E_BADPARM);
|
||||
|
||||
}
|
||||
}
|
||||
else { /* it is an array */
|
||||
|
||||
for(i = 0; i < value->v.numValue; i++) {
|
||||
|
||||
switch(value_type) {
|
||||
|
||||
case IF_FLAGVEC:
|
||||
inst->iparam[iparam]->element[i].bvalue = value->v.vec.iVec[i];
|
||||
inst->iparam[iparam]->eltype = IF_FLAGVEC;
|
||||
break;
|
||||
|
||||
case IF_INTVEC:
|
||||
inst->iparam[iparam]->element[i].ivalue = value->v.vec.iVec[i];
|
||||
inst->iparam[iparam]->eltype = IF_INTVEC;
|
||||
break;
|
||||
|
||||
case IF_REALVEC:
|
||||
inst->iparam[iparam]->element[i].rvalue = value->v.vec.rVec[i];
|
||||
inst->iparam[iparam]->eltype = IF_REALVEC;
|
||||
break;
|
||||
|
||||
case IF_STRINGVEC:
|
||||
/* we don't trust the caller to keep the string alive, so copy it */
|
||||
inst->iparam[iparam]->element[i].svalue =
|
||||
TMALLOC(char, 1 + strlen(value->v.vec.sVec[i]));
|
||||
strcpy(inst->iparam[iparam]->element[i].svalue, value->v.vec.sVec[i]);
|
||||
inst->iparam[iparam]->eltype = IF_STRINGVEC;
|
||||
break;
|
||||
|
||||
case IF_CPLXVEC:
|
||||
/* we don't trust the caller to have a parallel complex structure */
|
||||
/* so copy the real and imaginary parts explicitly */
|
||||
inst->iparam[iparam]->element[i].cvalue.real = value->v.vec.cVec[i].real;
|
||||
inst->iparam[iparam]->element[i].cvalue.imag = value->v.vec.cVec[i].imag;
|
||||
inst->iparam[iparam]->eltype = IF_CPLXVEC;
|
||||
break;
|
||||
|
||||
default:
|
||||
return(E_BADPARM);
|
||||
|
||||
} /* end switch */
|
||||
|
||||
} /* end for number of elements of vector */
|
||||
|
||||
} /* end else */
|
||||
|
||||
return(OK);
|
||||
}
|
||||
|
|
@ -142,7 +142,7 @@ MIFsetup(
|
|||
|
||||
for(i = 0; i < model->num_param; i++) {
|
||||
|
||||
if(model->param[i]->is_null) {
|
||||
if(model->param[i]->is_null && DEVices[mod_type]->DEVpublic.param[i].has_model_scope) {
|
||||
|
||||
/* setup a pointer for quick access */
|
||||
param_info = &(DEVices[mod_type]->DEVpublic.param[i]);
|
||||
|
|
@ -545,6 +545,7 @@ MIFunsetup(GENmodel *inModel,CKTcircuit *ckt)
|
|||
cm_data.conn = here->conn;
|
||||
cm_data.num_param = here->num_param;
|
||||
cm_data.param = here->param;
|
||||
cm_data.iparam = here->iparam;
|
||||
cm_data.num_inst_var = here->num_inst_var;
|
||||
cm_data.inst_var = here->inst_var;
|
||||
cm_data.callback = &(here->callback);
|
||||
|
|
|
|||
|
|
@ -73,7 +73,7 @@ struct coreInfo_t coreInfo =
|
|||
txfree,
|
||||
tmalloc,
|
||||
trealloc,
|
||||
txfree
|
||||
txfree,
|
||||
#else
|
||||
GC_malloc,
|
||||
tcalloc,
|
||||
|
|
@ -81,6 +81,7 @@ struct coreInfo_t coreInfo =
|
|||
no_free,
|
||||
GC_malloc,
|
||||
GC_realloc,
|
||||
no_free
|
||||
no_free,
|
||||
#endif
|
||||
MIFParam,
|
||||
};
|
||||
|
|
|
|||
Loading…
Reference in New Issue