⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 ipctiein.c

📁 ngspice又一个电子CAD仿真软件代码.功能更全
💻 C
字号:
/*============================================================================FILE    IPCtiein.cMEMBER OF process XSPICECopyright 1991Georgia Tech Research CorporationAtlanta, Georgia 30332All Rights ReservedPROJECT A-8503AUTHORS    9/12/91  Bill KuhnMODIFICATIONS    <date> <person name> <nature of modifications>SUMMARY    Provides a protocol independent interface between the simulator    and the IPC method used to interface to CAE packages.INTERFACES    g_ipc   (global variable)    ipc_handle_stop()    ipc_handle_returni()    ipc_handle_mintime()    ipc_handle_vtrans()    ipc_send_stdout()    ipc_send_stderr()    ipc_send_std_files()    ipc_screen_name()    ipc_get_devices()    ipc_free_devices()    ipc_check_pause_stop()REFERENCED FILES    None.NON-STANDARD FEATURES    None.============================================================================*/#define CONFIG#include "ngspice.h"#include <stdio.h>#include <ctype.h>#include <string.h>//#include "util.h"#include "inpdefs.h"#include "gendefs.h"#include "cktdefs.h"#include "bjt/bjtdefs.h"#include "jfet/jfetdefs.h"#include "mos1/mos1defs.h"#include "mos2/mos2defs.h"#include "mos3/mos3defs.h"#include "mifproto.h"#include "ipc.h"#include "ipctiein.h"/*Global variable g_ipc is used by the SPICE mods that take care ofinterprocess communications activities.*/Ipc_Tiein_t  g_ipc = {    IPC_FALSE,                  /* enabled */    IPC_MODE_INTERACTIVE,       /* mode */    IPC_ANAL_DCOP,              /* analysis mode */    IPC_FALSE,                  /* parse_error */    IPC_FALSE,                  /* run_error */    IPC_FALSE,                  /* errchk_sent */    IPC_FALSE,                  /* returni */    0.0,                        /* mintime */    0.0,                        /* lasttime */    0.0,                        /* cpu time */    NULL,                       /* send array */    NULL,                       /* log file */    {                           /* vtrans struct */        0,                          /* size */        NULL,                       /* vsrc_name array */        NULL,                       /* device_name array */    },    IPC_FALSE,                  /* stop analysis */};/*ipc_handle_stopThis function sets a flag in the g_ipc variable to signal thata stop message has been received over the IPC channel.*/void ipc_handle_stop(void){    g_ipc.stop_analysis = IPC_TRUE;}/*ipc_handle_returniThis function sets a flag in the g_ipc variable to signal thata message has been received over the IPC channel specifying thatcurrent values are to be returned in the results data sets.*/void ipc_handle_returni(void){    g_ipc.returni = IPC_TRUE;}/*ipc_handle_mintimeThis function sets a value in the g_ipc variable that specifieshow often data is to be returned as it is computed.  If thesimulator takes timestep backups, data may still be returnedmore often that that specified by 'mintime' so that glitchesare not missed.*/void ipc_handle_mintime(double time){    g_ipc.mintime = time;}/*ipc_handle_vtransThis function processes arguments from a #VTRANS card received overthe IPC channel.  The data on the card specifies that a particularzero-valued voltage source name should be translated to the specifiedinstance name for which it was setup to monitor currents.*/void ipc_handle_vtrans(    char *vsrc,   /* The name of the voltage source to be translated */    char *dev)    /* The device name the vsource name should be translated to */{    int i;    int size;    if(g_ipc.vtrans.size == 0) {        g_ipc.vtrans.size = 1;        g_ipc.vtrans.vsrc_name = (void *) MALLOC(sizeof(char *));        g_ipc.vtrans.device_name = (void *) MALLOC(sizeof(char *));        g_ipc.vtrans.vsrc_name[0] = MIFcopy(vsrc);        g_ipc.vtrans.device_name[0] = MIFcopy(dev);    }    else {        g_ipc.vtrans.size++;        size = g_ipc.vtrans.size;        i = g_ipc.vtrans.size - 1;        g_ipc.vtrans.vsrc_name = (void *) REALLOC(g_ipc.vtrans.vsrc_name,                                                  size * sizeof(char *));        g_ipc.vtrans.device_name = (void *) REALLOC(g_ipc.vtrans.device_name,                                                    size * sizeof(char *));        g_ipc.vtrans.vsrc_name[i] = MIFcopy(vsrc);        g_ipc.vtrans.device_name[i] = MIFcopy(dev);    }}/*ipc_send_stdoutThis function sends the data written to stdout over the IPC channel.This stream was previously redirected to a temporary file duringthe simulation.*/void ipc_send_stdout(void){    int c;    int len;    char    buf[IPC_MAX_LINE_LEN+1];    /* rewind the redirected stdout stream */    rewind(stdout);    /* Begin reading from the top of file and send lines */    /* over the IPC channel.                             */    /* Don't send newlines.  Also, if line is > IPC_MAX_LINE_LEN chars */    /* we must wrap it because Mspice can't handle it              */    len = 0;    while( (c=fgetc(stdout)) != EOF) {        if(c != '\n') {            buf[len] = c;            len++;        }        if((c == '\n') || (len == IPC_MAX_LINE_LEN)) {            buf[len] = '\0';            ipc_send_line(buf);            len = 0;        }    }    if(len > 0) {        buf[len] = '\0';        ipc_send_line(buf);    }    /* Finally, rewind file again to discard the data already sent */    rewind(stdout);}/*ipc_send_stderrThis function sends the data written to stderr over the IPC channel.This stream was previously redirected to a temporary file duringthe simulation.*/void ipc_send_stderr(void){    int c;    int len;    char    buf[IPC_MAX_LINE_LEN+1];    /* rewind the redirected stderr stream */    rewind(stderr);    /* Begin reading from the top of file and send lines */    /* over the IPC channel.                             */    /* Don't send newlines.  Also, if line is > IPC_MAX_LINE_LEN chars */    /* we must wrap it because Mspice can't handle it              */    len = 0;    while( (c=fgetc(stderr)) != EOF) {        if(c != '\n') {            buf[len] = c;            len++;        }        if((c == '\n') || (len == IPC_MAX_LINE_LEN)) {            buf[len] = '\0';            ipc_send_line(buf);            len = 0;        }    }    if(len > 0) {        buf[len] = '\0';        ipc_send_line(buf);    }    /* Finally, rewind file again to discard the data already sent */    rewind(stderr);}/*ipc_send_std_filesThis function sends the data written to stdout and stderr over theIPC channel.  These streams were previously redirected to temporaryfiles during the simulation.*/Ipc_Status_t ipc_send_std_files(){    ipc_send_stdout();    ipc_send_stderr();    return(ipc_flush());}/*ipc_screen_nameThis function screens names of instances and nodes to limit thedata returned over the IPC channel.*/Ipc_Boolean_t ipc_screen_name(char *name, char *mapped_name){    char    *endp;    int     i;    int     len;    long    l;    /* Return FALSE if name is in a subcircuit */    for(i = 0; name[i] != '\0'; i++) {        if(name[i] == ':')            return(IPC_FALSE);    }    /* Determine if name is numeric and what value is */    l = strtol(name, &endp, 10);    /* If numeric */    if(*endp == '\0') {        /* Return FALSE if >100,000 -> added by ms_server in ATESSE 1.0 */        if(l >= 100000)            return(IPC_FALSE);        /* Otherwise, copy name to mapped name and return true */        else {            strcpy(mapped_name,name);            return(IPC_TRUE);        }    }    /* If node is an internal node from a semiconductor (indicated by a      */    /* trailing #collector, #source, ...), do not return its current.        */    /* Otherwise, map to upper case and eliminate trailing "#branch" if any. */    for(i = 0; name[i]; i++) {        if(name[i] == '#') {            if(strcmp(name + i, "#branch") == 0)                break;            else                return(IPC_FALSE);        }        else {            if(islower(name[i]))                mapped_name[i] = toupper(name[i]);            else                mapped_name[i] = name[i];        }    }    mapped_name[i] = '\0';    len = i;    /* If len != 8 or 6'th char not equal to $, then doesn't need vtrans */    /* Otherwise, translate to device name that it monitors */    if(len != 8)        return(IPC_TRUE);    else if(name[5] != '$')        return(IPC_TRUE);    else {        /* Scan list of prefixes in VTRANS table and convert name */        for(i = 0; i < g_ipc.vtrans.size; i++) {            if(strncmp(mapped_name, g_ipc.vtrans.vsrc_name[i], 5) == 0) {                strcpy(mapped_name, g_ipc.vtrans.device_name[i]);                return(IPC_TRUE);            }        }        return(IPC_TRUE);    }    return(IPC_TRUE);}/*ipc_get_devicesThis function is used to setup the OUTinterface data structure thatdetermines what instances will have data returned over the IPC channel.*/int ipc_get_devices(    void        *circuit,     /* The circuit structure */    char        *device,      /* The device name as it appears in the info struct */    char        ***names,     /* Array of name strings to be built */    double      **modtypes)   /* Array of types to be built */{    int         index;    int         num_instances;    GENmodel    *model;    GENinstance *here;    CKTcircuit  *ckt;    char        *inst_name;    int         inst_name_len;    int         i;    BJTmodel         *BJTmod;    JFETmodel        *JFETmod;    MOS1model        *MOS1mod;    MOS2model        *MOS2mod;    MOS3model        *MOS3mod;    /* Initialize local variables */    ckt = (CKTcircuit *) circuit;    num_instances = 0;    /* Get the index into the circuit structure linked list of models */    index = INPtypelook(device);    /* Iterate through all models of this type */    for(model = ckt->CKThead[index]; model; model = model->GENnextModel) {        /* Iterate through all instance of this model */        for(here = model->GENinstances; here; here = here->GENnextInstance) {            /* Get the name of the instance */            inst_name = here->GENname;            inst_name_len = strlen(inst_name);            /* Skip if it is a inside a subcircuit */            for(i = 0; i < inst_name_len; i++)                if(inst_name[i] == ':')                    break;            if(i < inst_name_len)                continue;            /* Otherwise, add the name to the list */            num_instances++;            if(num_instances == 1)                *names = (char **) MALLOC(sizeof(char *));            else                *names = (char **) REALLOC(*names, num_instances * sizeof(char *));            (*names)[num_instances-1] = MIFcopy(inst_name);            /* Then get the type if it is a Q J or M */            if(num_instances == 1)                *modtypes = (double *) MALLOC(sizeof(double));            else                *modtypes = (double *) REALLOC((char *) *modtypes,                                        num_instances * sizeof(double));            if(strcmp(device,"BJT") == 0) {                BJTmod = (BJTmodel *) model;                (*modtypes)[num_instances-1] = BJTmod->BJTtype;            }            else if(strcmp(device,"JFET") == 0) {                JFETmod = (JFETmodel *) model;                (*modtypes)[num_instances-1] = JFETmod->JFETtype;            }            else if(strcmp(device,"Mos1") == 0) {                MOS1mod = (MOS1model *) model;                (*modtypes)[num_instances-1] = MOS1mod->MOS1type;            }            else if(strcmp(device,"Mos2") == 0) {                MOS2mod = (MOS2model *) model;                (*modtypes)[num_instances-1] = MOS2mod->MOS2type;            }            else if(strcmp(device,"Mos3") == 0) {                MOS3mod = (MOS3model *) model;                (*modtypes)[num_instances-1] = MOS3mod->MOS3type;            }            else {                (*modtypes)[num_instances-1] = 1.0;            }        } /* end for all instances */    } /* end for all models */    return(num_instances);}/*ipc_free_devicesThis function frees temporary data created by ipc_get_devices().*/void ipc_free_devices(    int         num_items,    /* Number of things to free */    char        **names,     /* Array of name strings to be built */    double      *modtypes)   /* Array of types to be built */{    int         i;    for(i = 0; i < num_items; i++)	{        FREE(names[i]);		names[i] = 0;	}    if(num_items > 0) 	{        FREE(names);        FREE(modtypes);		names = NULL;		modtypes = NULL;    }}/*ipc_check_pause_stopThis function is called at various times during a simulation to checkfor incoming messages of the form >STOP or >PAUSE signaling thatsimulation should be stopped or paused.  Processing of the messagesis handled by ipc_get_line().*/void ipc_check_pause_stop(void){    char        buf[1025];    int         len;    /* If already seen stop analysis, don't call ipc_get_line, just return. */    /* This is provided so that the function can be called multiple times */    /* during the process of stopping */    if(g_ipc.stop_analysis)        return;    /* Otherwise do a non-blocking call to ipc_get_line() to check for messages. */    /* We assume that the only possible messages at this point are >PAUSE */    /* and >STOP, so we don't do anything with the returned text if any */    ipc_get_line(buf, &len, IPC_NO_WAIT);}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -