/*************************************************************************** JSPICE3 adaptation of Spice3e2 - Copyright (c) Stephen R. Whiteley 1992 Copyright 1990 Regents of the University of California. All rights reserved. Authors: 1985 Thomas L. Quarles 1992 Stephen R. Whiteley ****************************************************************************/ #ifndef IFSIMULATOR #define IFSIMULATOR /* * We don't always have access to an ANSI C compiler yet, so we * make the following convenient definition */ #ifdef __STDC__ /* using an ansi C compiler, so we have the void* construct */ typedef void GENERIC; #else /* not using an ansi C compiler, so we have to use char* as the */ /* most generic pointer type */ typedef char GENERIC; #endif /* * 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 GENERIC *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 0x3000 /* 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 pointers are provided as hooks 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 */ char *line; /* the parsed function string */ union uIFvalue * vars; /* array of structures describing values */ #ifdef __STDC__ int ((*IFinit)(struct sIFparseTree*,double,double)); int ((*IFeval)(struct sIFparseTree*,double,double*,double*, double*,double*)); void ((*IFfree)(struct sIFparseTree*)); #else int ((*IFinit)()); /* function to call to init for run */ int ((*IFeval)()); /* function to call to get evaluated */ void ((*IFfree)()); /* function to destroy parse tree */ #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 malloc()'d * and are assumed to have been turned over to the recipient and * thus should not be re-used or free()'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 free()'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 GENERIC * 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; /* * sructure: IFkeys * * This structure is used in the IFdevice structure below. Each device * can have multiple implementations, listed in the IFkeys structure. * Each implementation is keyed by the 'key' character in the input * line. numTerms is the number of nodes in the implementation, * and termNames is a list of terminal names. numDevs is the number * of controlling devices (as for a current controlled source). soft * evaluates true if the number of terms is not fixed (in which case * numTerms is the maximum). * */ typedef struct sIFkeys { char key; /* keying character in input */ int numTerms; /* number of terminals in this type of instance */ char **termNames; /* pointer to array of pointers to names */ int soft; /* nonzero if number of terms not fixed */ int numDevs; /* number of controlling devices */ } IFkeys; /* * 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 *numKeys; /* number of implementations */ IFkeys *keys; /* list of device implementations */ /* * levelMask is a bit field which determines the model levels (1-32) * supported by this device, LSB 1 => level 1, etc. modelKeys is a list * of strings which name the model for this device. parse is the function * which actually parses the input line for this device (old INP2? routine). */ unsigned levelMask; /* model level mask, LSB => 1 */ char **modelKeys; /* list of model names */ #ifdef __STDC__ /* input parser function */ void (*parse)(int,GENERIC*,GENERIC*,GENERIC*); #else void (*parse)(); #endif 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 */ } 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 */ #ifdef __STDC__ int ((*newCircuit)(GENERIC **)); /* create new circuit */ int ((*deleteCircuit)(GENERIC *)); /* destroy old circuit's data structures*/ int ((*newNode)(GENERIC *,GENERIC**,IFuid)); /* create new node */ int ((*groundNode)(GENERIC*,GENERIC**,IFuid)); /* create ground node */ int ((*bindNode)(GENERIC *,GENERIC*,int,GENERIC*)); /* bind a node to a terminal */ int ((*findNode)(GENERIC *,GENERIC**,IFuid)); /* find a node by name */ int ((*instToNode)(GENERIC *,GENERIC *,int,GENERIC **,IFuid *)); /* find the node attached to a terminal */ int ((*setNodeParm)(GENERIC*,GENERIC*,int,IFvalue*,IFvalue*)); /* set a parameter on a node */ int ((*askNodeQuest)(GENERIC*,GENERIC*,int,IFvalue*,IFvalue*)); /* ask a question about a node */ int ((*deleteNode)(GENERIC*,GENERIC*)); /* delete a node from the circuit */ int ((*newInstance)(GENERIC*,GENERIC*,GENERIC**,IFuid)); /* create new instance */ int ((*setInstanceParm)(GENERIC*,GENERIC*,int,IFvalue*,IFvalue*)); /* set a parameter on an instance */ int ((*askInstanceQuest)(GENERIC*,GENERIC*,int,IFvalue*,IFvalue*)); /* ask a question about an instance */ int ((*findInstance)(GENERIC*,int*,GENERIC**,IFuid,GENERIC*,IFuid)); /* find a specific instance */ int ((*deleteInstance)(GENERIC*,GENERIC*)); /* delete an instance from the circuit */ int ((*newModel)(GENERIC*,int,GENERIC**,IFuid)); /* create new model */ int ((*setModelParm)(GENERIC*,GENERIC*,int,IFvalue*,IFvalue*)); /* set a parameter on a model */ int ((*askModelQuest)(GENERIC*,GENERIC*,int,IFvalue*,IFvalue*)); /* ask a questions about a model */ int ((*findModel)(GENERIC*,int*,GENERIC**,IFuid)); /* find a specific model */ int ((*deleteModel)(GENERIC*,GENERIC*)); /* delete a model from the circuit*/ int ((*newTask)(GENERIC*,GENERIC**,IFuid)); /* create a new task */ int ((*newAnalysis)(GENERIC*,int,IFuid,GENERIC**,GENERIC*)); /* create new analysis within a task */ int ((*setAnalysisParm)(GENERIC*,GENERIC*,int,IFvalue*,IFvalue*)); /* set a parameter on an analysis */ int ((*askAnalysisQuest)(GENERIC*,GENERIC*,int,IFvalue*,IFvalue*)); /* ask a question about an analysis */ int ((*findAnalysis)(GENERIC*,int*,GENERIC**,IFuid,GENERIC*,IFuid)); /* find a specific analysis */ int ((*findTask)(GENERIC*,GENERIC**,IFuid)); /* find a specific task */ int ((*deleteTask)(GENERIC*,GENERIC*)); /* delete a task */ int ((*doAnalyses)(GENERIC*,int,GENERIC*)); char *((*nonconvErr)(GENERIC*,char *)); /* return nonconvergence error */ #else int ((*newCircuit)()); /* create new circuit */ int ((*deleteCircuit)()); /* destroy old ckt's data structures */ int ((*newNode)()); /* create new node */ int ((*groundNode)()); /* create ground node */ int ((*bindNode)()); /* bind a node to a terminal */ int ((*findNode)()); /* find a node by name */ int ((*instToNode)()); /* find the node attached to a terminal */ int ((*setNodeParm)()); /* set a parameter on a node */ int ((*askNodeQuest)()); /* ask a question about a node */ int ((*deleteNode)()); /* delete a node from the circuit */ int ((*newInstance)()); /* create new instance */ int ((*setInstanceParm)()); /* set a parameter on an instance */ int ((*askInstanceQuest)()); /* ask a question about an instance */ int ((*findInstance)()); /* find a specific instance */ int ((*deleteInstance)()); /* delete an instance from the circuit */ int ((*newModel)()); /* create new model */ int ((*setModelParm)()); /* set a parameter on a model */ int ((*askModelQuest)()); /* ask a questions about a model */ int ((*findModel)()); /* find a specific model */ int ((*deleteModel)()); /* delete a model from the circuit*/ int ((*newTask)()); /* create a new task */ int ((*newAnalysis)()); /* create new analysis within a task */ int ((*setAnalysisParm)()); /* set a parameter on an analysis */ int ((*askAnalysisQuest)()); /* ask a question about an analysis */ int ((*findAnalysis)()); /* find a specific analysis */ int ((*findTask)()); /* find a specific task */ int ((*deleteTask)()); /* delete a task */ int ((*doAnalyses)()); /* run a specified task */ char *((*nonconvErr)()); /* return nonconvergence error */ #endif /* STDC */ 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 */ char *ptXalias; /* alias for 'x' in parse tree */ } 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 { #ifdef __STDC__ int ((*IFnewUid)(GENERIC*,IFuid*,IFuid,char*,int,GENERIC**)); /* 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 ((*OUTbeginPlot)(GENERIC*)); /* start pointwise output plot */ int ((*OUTdata)(GENERIC*,IFvalue*,IFvalue*)); /* data for pointwise plot */ int ((*OUTsetDims)(GENERIC*,int*,int)); /* modify the plot dimensionality */ int ((*OUTendPlot)(GENERIC*)); /* end of plot */ #else /* not STDC */ int ((*IFnewUid)()); /* create a new UID in the circuit */ int ((*IFpauseTest)()); /* should we stop now? */ double ((*IFseconds)()); /* what time is it? */ int ((*IFerror)()); /* output an error or warning message */ int ((*OUTbeginPlot)()); /* start pointwise output plot */ int ((*OUTdata)()); /* data for pointwise plot */ int ((*OUTsetDims)()); /* modify the plot dimensionality */ int ((*OUTendPlot)()); /* end of plot */ #endif /* STDC */ int *OUTendit; /* if nonzero, quit the current analysis as if finished */ } 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 #endif /*IFSIMULATOR*/