457 lines
16 KiB
C
457 lines
16 KiB
C
/**********
|
|
Copyright 1990 Regents of the University of California. All rights reserved.
|
|
Author: 1986 Thomas L. Quarles
|
|
**********/
|
|
|
|
#ifndef IFSIMULATOR
|
|
#define IFSIMULATOR
|
|
|
|
|
|
/*
|
|
* structure: IFparm
|
|
*
|
|
*
|
|
* The structure used to describe all values passed
|
|
* between the front end and the simulator when there is any
|
|
* possibility one argument of the function could have more
|
|
* than one type.
|
|
*
|
|
* keyword is provided for the front end and is the token
|
|
* the user is expected to label the data with.
|
|
*
|
|
* id is an integer intended to uniquely identify the parameter
|
|
* to the simulator
|
|
*
|
|
* dataType is an integer which indicates the type of argument
|
|
* that must be passed for this parameter
|
|
*
|
|
* description is a longer description intended for help menus
|
|
* the description should all fit on one line, but should
|
|
* give a knowledgable user a good idea what the parameter is
|
|
* used for.
|
|
*/
|
|
|
|
typedef struct sIFparm {
|
|
char *keyword;
|
|
int id;
|
|
int dataType;
|
|
char *description;
|
|
} IFparm;
|
|
|
|
/*
|
|
*
|
|
* datatype: IFuid
|
|
*
|
|
* unique identifier for all name-type data in the simulator.
|
|
* this permits the front end to use something other than
|
|
* a unique, fully qualified character string to identify
|
|
* an object.
|
|
*
|
|
*/
|
|
|
|
typedef char *IFuid;
|
|
|
|
/*
|
|
*
|
|
* types for IFnewUid
|
|
*
|
|
*/
|
|
|
|
#define UID_ANALYSIS 0x1
|
|
#define UID_TASK 0x2
|
|
#define UID_INSTANCE 0x4
|
|
#define UID_MODEL 0x8
|
|
#define UID_SIGNAL 0x10
|
|
#define UID_OTHER 0x20
|
|
|
|
|
|
/*
|
|
* dataType values:
|
|
*
|
|
* Note: These structures are put together by ORing together the
|
|
* appropriate bits from the fields below as is shown for the vector
|
|
* types.
|
|
* IF_REQUIRED indicates that the parameter must be specified.
|
|
* The front end does not NEED to check for this, but can to save time,
|
|
* since failure to do so will cause the simulator to fail.
|
|
* IF_SET indicates that the specified item is an input parameter.
|
|
* IF_ASK indicates that the specified item is something the simulator
|
|
* can provide information about.
|
|
* IF_SET and IF_ASK are NOT mutually exclusive.
|
|
* if IF_SET and IF_ASK are both zero, it indicates a parameter that
|
|
* the simulator recoginizes are being a reasonable paremeter, but
|
|
* which this simulator does not implement.
|
|
*/
|
|
|
|
#define IF_FLAG 0x1
|
|
#define IF_INTEGER 0x2
|
|
#define IF_REAL 0x4
|
|
#define IF_COMPLEX 0x8
|
|
#define IF_NODE 0x10
|
|
#define IF_STRING 0x20
|
|
#define IF_INSTANCE 0x40
|
|
#define IF_PARSETREE 0x80
|
|
|
|
/* indicates that for a query the integer field will have a selector
|
|
* in it to pick a sub-field */
|
|
#define IF_SELECT 0x800
|
|
#define IF_VSELECT 0x400
|
|
|
|
/* indicates a vector of the specified type */
|
|
#define IF_VECTOR 0x8000
|
|
|
|
#define IF_FLAGVEC (IF_FLAG|IF_VECTOR)
|
|
#define IF_INTVEC (IF_INTEGER|IF_VECTOR)
|
|
#define IF_REALVEC (IF_REAL|IF_VECTOR)
|
|
#define IF_CPLXVEC (IF_COMPLEX|IF_VECTOR)
|
|
#define IF_NODEVEC (IF_NODE|IF_VECTOR)
|
|
#define IF_STRINGVEC (IF_STRING|IF_VECTOR)
|
|
#define IF_INSTVEC (IF_INSTANCE|IF_VECTOR)
|
|
|
|
#define IF_REQUIRED 0x4000
|
|
|
|
#define IF_VARTYPES 0x80ff
|
|
|
|
#define IF_SET 0x2000
|
|
#define IF_ASK 0x1000
|
|
|
|
/* If you AND with IF_UNIMP_MASK and get 0, it is recognized, but not
|
|
* implemented
|
|
*/
|
|
#define IF_UNIMP_MASK (~0xfff)
|
|
|
|
/* Used by sensetivity to check if a parameter is or is not useful */
|
|
#define IF_REDUNDANT 0x0010000
|
|
#define IF_PRINCIPAL 0x0020000
|
|
#define IF_AC 0x0040000
|
|
#define IF_AC_ONLY 0x0080000
|
|
#define IF_NOISE 0x0100000
|
|
#define IF_NONSENSE 0x0200000
|
|
|
|
#define IF_SETQUERY 0x0400000
|
|
#define IF_ORQUERY 0x0800000
|
|
#define IF_CHKQUERY 0x1000000
|
|
|
|
/* For "show" command: do not print value in a table by default */
|
|
#define IF_UNINTERESTING 0x2000000
|
|
|
|
/* Structure: IFparseTree
|
|
*
|
|
* This structure is returned by the parser for a IF_PARSETREE valued
|
|
* parameter and describes the information that the simulator needs
|
|
* to know about the parse tree in order to use it.
|
|
* It is expected that the front end will have a more extensive
|
|
* structure which this structure will be a prefix of.
|
|
*
|
|
* Note that the function pointer is provided as a hook for
|
|
* versions which may want to compile code for the parse trees
|
|
* if they are used heavily.
|
|
*
|
|
*/
|
|
|
|
typedef struct sIFparseTree {
|
|
int numVars; /* number of variables used */
|
|
int *varTypes; /* array of types of variables */
|
|
union uIFvalue * vars; /* array of structures describing values */
|
|
#ifdef __STDC__
|
|
int ((*IFeval)(struct sIFparseTree*,double,double*,double*,double*));
|
|
#else
|
|
int ((*IFeval)()); /* function to call to get evaluated */
|
|
#endif /* STDC */
|
|
} IFparseTree;
|
|
|
|
|
|
/*
|
|
* Structure: IFvalue
|
|
*
|
|
* structure used to pass the values corresponding to the above
|
|
* dataType. All types are passed in one of these structures, with
|
|
* relatively simple rules concerning the handling of the structure.
|
|
*
|
|
* whoever makes the subroutine call allocates a single instance of the
|
|
* structure. The basic data structure belongs to you, and you
|
|
* should arrange to free it when appropriate.
|
|
*
|
|
* The responsibilities of the data supplier are:
|
|
* Any vectors referenced by the structure are to be tmalloc()'d
|
|
* and are assumed to have been turned over to the recipient and
|
|
* thus should not be re-used or tfree()'d.
|
|
*
|
|
* The responsibilities of the data recipient are:
|
|
* scalar valued data is to be copied by the recipient
|
|
* vector valued data is now the property of the recipient,
|
|
* and must be tfree()'d when no longer needed.
|
|
*
|
|
* Character strings are a special case: Since it is assumed
|
|
* that all character strings are directly descended from input
|
|
* tokens, it is assumed that they are static, thus nobody
|
|
* frees them until the circuit is deleted, when the front end
|
|
* may do so.
|
|
*
|
|
* EVERYBODY's responsibility is to be SURE that the right data
|
|
* is filled in and read out of the structure as per the IFparm
|
|
* structure describing the parameter being passed. Programs
|
|
* neglecting this rule are fated to die of data corruption
|
|
*
|
|
*/
|
|
|
|
/*
|
|
* Some preliminary definitions:
|
|
*
|
|
* IFnode's are returned by the simulator, thus we don't really
|
|
* know what they look like, just that we get to carry pointers
|
|
* to them around all the time, and will need to save them occasionally
|
|
*
|
|
*/
|
|
|
|
|
|
typedef void * IFnode;
|
|
|
|
/*
|
|
* and of course, the standard complex data type
|
|
*/
|
|
typedef struct sIFcomplex {
|
|
double real;
|
|
double imag;
|
|
} IFcomplex;
|
|
|
|
|
|
typedef union uIFvalue {
|
|
int iValue; /* integer or flag valued data */
|
|
double rValue; /* real valued data */
|
|
IFcomplex cValue; /* complex valued data */
|
|
char *sValue; /* string valued data */
|
|
IFuid uValue; /* UID valued data */
|
|
IFnode nValue; /* node valued data */
|
|
IFparseTree *tValue; /* parse tree */
|
|
struct {
|
|
int numValue; /* length of vector */
|
|
union {
|
|
int *iVec; /* pointer to integer vector */
|
|
double *rVec; /* pointer to real vector */
|
|
IFcomplex *cVec;/* pointer to complex vector */
|
|
char **sVec; /* pointer to string vector */
|
|
IFuid *uVec; /* pointer to UID vector */
|
|
IFnode *nVec; /* pointer to node vector */
|
|
}vec;
|
|
}v;
|
|
} IFvalue;
|
|
|
|
|
|
/*
|
|
* structure: IFdevice
|
|
*
|
|
* This structure contains all the information available to the
|
|
* front end about a particular device. The simulator will
|
|
* present the front end with an array of pointers to these structures
|
|
* which it will use to determine legal device types and parameters.
|
|
*
|
|
* Note to simulators: you are passing an array of pointers to
|
|
* these structures, so you may in fact make this the first component
|
|
* in a larger, more complex structure which includes other data
|
|
* which you need, but which is not needed in the common
|
|
* front end interface.
|
|
*
|
|
*/
|
|
|
|
typedef struct sIFdevice {
|
|
char *name; /* name of this type of device */
|
|
char *description; /* description of this type of device */
|
|
|
|
int *terms; /* number of terminals on this device */
|
|
int *numNames; /* number of names in termNames */
|
|
char **termNames; /* pointer to array of pointers to names */
|
|
/* array contains 'terms' pointers */
|
|
|
|
int *numInstanceParms; /* number of instance parameter descriptors */
|
|
IFparm *instanceParms; /* array of instance parameter descriptors */
|
|
|
|
int *numModelParms; /* number of model parameter descriptors */
|
|
IFparm *modelParms; /* array of model parameter descriptors */
|
|
|
|
int flags; /* DEV_ */
|
|
|
|
} IFdevice;
|
|
|
|
|
|
/*
|
|
* Structure: IFanalysis
|
|
*
|
|
* This structure contains all the information available to the
|
|
* front end about a particular analysis type. The simulator will
|
|
* present the front end with an array of pointers to these structures
|
|
* which it will use to determine legal analysis types and parameters.
|
|
*
|
|
* Note to simulators: As for IFdevice above, you pass an array of pointers
|
|
* to these, so you can make this structure a prefix to a larger structure
|
|
* which you use internally.
|
|
*
|
|
*/
|
|
|
|
typedef struct sIFanalysis {
|
|
char *name; /* name of this analysis type */
|
|
char *description; /* description of this type of analysis */
|
|
|
|
int numParms; /* number of analysis parameter descriptors */
|
|
IFparm *analysisParms; /* array of analysis parameter descriptors */
|
|
|
|
} IFanalysis;
|
|
|
|
|
|
/*
|
|
* Structure: IFsimulator
|
|
*
|
|
* This is what we have been leading up to all along.
|
|
* This structure describes a simulator to the front end, and is
|
|
* returned from the SIMinit command to the front end.
|
|
* This is where all those neat structures we described in the first
|
|
* few hundred lines of this file come from.
|
|
*
|
|
*/
|
|
|
|
typedef struct sIFsimulator {
|
|
char *simulator; /* the simulator's name */
|
|
char *description; /* description of this simulator */
|
|
char *version; /* version or revision level of simulator*/
|
|
|
|
int ((*newCircuit)(void **));
|
|
/* create new circuit */
|
|
int ((*deleteCircuit)(void *));
|
|
/* destroy old circuit's data structures*/
|
|
|
|
int ((*newNode)(void *,void**,IFuid));
|
|
/* create new node */
|
|
int ((*groundNode)(void*,void**,IFuid));
|
|
/* create ground node */
|
|
int ((*bindNode)(void *,void*,int,void*));
|
|
/* bind a node to a terminal */
|
|
int ((*findNode)(void *,void**,IFuid));
|
|
/* find a node by name */
|
|
int ((*instToNode)(void *,void *,int,void **,IFuid *));
|
|
/* find the node attached to a terminal */
|
|
int ((*setNodeParm)(void*,void*,int,IFvalue*,IFvalue*));
|
|
/* set a parameter on a node */
|
|
int ((*askNodeQuest)(void*,void*,int,IFvalue*,IFvalue*));
|
|
/* ask a question about a node */
|
|
int ((*deleteNode)(void*,void*));
|
|
/* delete a node from the circuit */
|
|
|
|
int ((*newInstance)(void*,void*,void**,IFuid));
|
|
/* create new instance */
|
|
int ((*setInstanceParm)(void*,void*,int,IFvalue*,IFvalue*));
|
|
/* set a parameter on an instance */
|
|
int ((*askInstanceQuest)(void*,void*,int,IFvalue*,IFvalue*));
|
|
/* ask a question about an instance */
|
|
int ((*findInstance)(void*,int*,void**,IFuid,void*,IFuid));
|
|
/* find a specific instance */
|
|
int ((*deleteInstance)(void*,void*));
|
|
/* delete an instance from the circuit */
|
|
|
|
int ((*newModel)(void*,int,void**,IFuid));
|
|
/* create new model */
|
|
int ((*setModelParm)(void*,void*,int,IFvalue*,IFvalue*));
|
|
/* set a parameter on a model */
|
|
int ((*askModelQuest)(void*,void*,int,IFvalue*,IFvalue*));
|
|
/* ask a questions about a model */
|
|
int ((*findModel)(void*,int*,void**,IFuid));
|
|
/* find a specific model */
|
|
int ((*deleteModel)(void*,void*));
|
|
/* delete a model from the circuit*/
|
|
|
|
int ((*newTask)(void*,void**,IFuid));
|
|
/* create a new task */
|
|
int ((*newAnalysis)(void*,int,IFuid,void**,void*));
|
|
/* create new analysis within a task */
|
|
int ((*setAnalysisParm)(void*,void*,int,IFvalue*,IFvalue*));
|
|
/* set a parameter on an analysis */
|
|
int ((*askAnalysisQuest)(void*,void*,int,IFvalue*,IFvalue*));
|
|
/* ask a question about an analysis */
|
|
int ((*findAnalysis)(void*,int*,void**,IFuid,void*,IFuid));
|
|
/* find a specific analysis */
|
|
int ((*findTask)(void*,void**,IFuid));
|
|
/* find a specific task */
|
|
int ((*deleteTask)(void*,void*));
|
|
/* delete a task */
|
|
|
|
int ((*doAnalyses)(void*,int,void*));
|
|
char *((*nonconvErr)(void*,char *)); /* return nonconvergence error */
|
|
|
|
int numDevices; /* number of device types supported */
|
|
IFdevice **devices; /* array of device type descriptors */
|
|
|
|
int numAnalyses; /* number of analysis types supported */
|
|
IFanalysis **analyses; /* array of analysis type descriptors */
|
|
|
|
int numNodeParms; /* number of node parameters supported */
|
|
IFparm *nodeParms; /* array of node parameter descriptors */
|
|
|
|
int numSpecSigs; /* number of special signals legal in parse trees */
|
|
char **specSigs; /* names of special signals legal in parse trees */
|
|
|
|
} IFsimulator;
|
|
|
|
/*
|
|
* Structure: IFfrontEnd
|
|
*
|
|
* This structure provides the simulator with all the information
|
|
* it needs about the front end. This is the entire set of
|
|
* front end and back end related routines the simulator
|
|
* should know about.
|
|
*
|
|
*/
|
|
|
|
typedef struct sIFfrontEnd {
|
|
int ((*IFnewUid)(void*,IFuid*,IFuid,char*,int,void**));
|
|
/* create a new UID in the circuit */
|
|
int ((*IFdelUid)(void*,IFuid,int));
|
|
/* create a new UID in the circuit */
|
|
int ((*IFpauseTest)(void));
|
|
/* should we stop now? */
|
|
double ((*IFseconds)(void));
|
|
/* what time is it? */
|
|
int ((*IFerror)(int,char*,IFuid*));
|
|
/* output an error or warning message */
|
|
int ((*OUTpBeginPlot)(void*,void*,IFuid,IFuid,int,
|
|
int,IFuid*,int,void**));
|
|
/* start pointwise output plot */
|
|
int ((*OUTpData)(void*,IFvalue*,IFvalue*));
|
|
/* data for pointwise plot */
|
|
int ((*OUTwBeginPlot)(void*,void*,IFuid,IFuid,int,
|
|
int,IFuid*,int,void**));
|
|
/* start windowed output plot */
|
|
int ((*OUTwReference)(void*,IFvalue*,void**));
|
|
/* independent vector for windowed plot */
|
|
int ((*OUTwData)(void*,int,IFvalue*,void*));
|
|
/* data for windowed plot */
|
|
int ((*OUTwEnd)(void*));
|
|
/* signal end of windows */
|
|
int ((*OUTendPlot)(void*));
|
|
/* end of plot */
|
|
int ((*OUTbeginDomain)(void*,IFuid,int,IFvalue*));
|
|
/* start nested domain */
|
|
int ((*OUTendDomain)(void*));
|
|
/* end nested domain */
|
|
int ((*OUTattributes)(void *,IFuid*,int,IFvalue*));
|
|
/* specify output attributes of node */
|
|
} IFfrontEnd;
|
|
|
|
/* flags for the first argument to IFerror */
|
|
#define ERR_WARNING 0x1
|
|
#define ERR_FATAL 0x2
|
|
#define ERR_PANIC 0x4
|
|
#define ERR_INFO 0x8
|
|
|
|
/* valid values for the second argument to doAnalyses */
|
|
|
|
/* continue the analysis from where we left off */
|
|
#define RESUME 0
|
|
/* start everything over from the beginning of this task*/
|
|
#define RESTART 1
|
|
/* abandon the current analysis and go on the the next in the task*/
|
|
#define SKIPTONEXT 2
|
|
|
|
#define OUT_SCALE_LIN 1
|
|
#define OUT_SCALE_LOG 2
|
|
|
|
#endif /*IFSIMULATOR*/
|