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

📄 evtop.c

📁 ngspice又一个电子CAD仿真软件代码.功能更全
💻 C
字号:
/*============================================================================FILE    EVTop.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    This file contains function EVTop which is used to perform an    operating point analysis in place of CKTop when there are    event-driven instances in the circuit.  It alternates between doing    event-driven iterations with EVTiter and doing analog iterations with    NIiter/CKTop until no more event-driven outputs change.INTERFACES    EVTop()REFERENCED FILES    None.NON-STANDARD FEATURES    None.============================================================================*/#include <stdio.h>#include "ngspice.h"#include "cktdefs.h"//#include "util.h"#include "sperror.h"#include "mif.h"#include "evt.h"#include "evtproto.h"#include "evtudn.h"static void EVTnode_compare(    CKTcircuit    *ckt,    int           node_index,    Evt_Node_t    *node1,    Evt_Node_t    *node2,    Mif_Boolean_t *equal);/*EVTopThis function is used to perform an operating point analysisin place of CKTop when there are event-driven instances in thecircuit.  It alternates between doing event-driven iterationswith EVTiter and doing analog iterations with NIiter/CKTopuntil no more event-driven outputs change.*/int EVTop(    CKTcircuit     *ckt,          /* The circuit structure */    long           firstmode,     /* The SPICE 3C1 CKTop() firstmode parameter */    long           continuemode,  /* The SPICE 3C1 CKTop() continuemode paramter */    int            max_iter,      /* The SPICE 3C1 CKTop() max iteration parameter */    Mif_Boolean_t  first_call)    /* Is this the first time through? */{    int         i;    int         num_insts;    int         converged;    int         output_index;    int         port_index;    char        *err_msg;    Mif_Boolean_t       firstime;    Evt_Inst_Queue_t    *inst_queue;    Evt_Output_Queue_t  *output_queue;    Evt_Output_Info_t   **output_table;    Evt_Port_Info_t     **port_table;    /* get data to local storage for fast access */    num_insts = ckt->evt->counts.num_insts;    inst_queue = &(ckt->evt->queue.inst);    /* Initialize to_call entries in event inst queue */    /* to force calling all event/hybrid instance the first */    /* time through */    if(first_call) {        for(i = 0; i < num_insts; i++) {            inst_queue->to_call[i] = MIF_TRUE;            inst_queue->to_call_index[i] = i;        }        inst_queue->num_to_call = num_insts;    }    /* Alternate between event-driven and analog solutions until */    /* there are no changed event-driven outputs */    firstime = MIF_TRUE;    for(;;) {        /* Call EVTiter to establish initial outputs from */        /* event/hybrid instances with states (e.g. flip-flops) */        ckt->CKTmode = firstmode;        converged = EVTiter(ckt);        if(converged != 0)            return(converged);        /* Now do analog solution for current state of hybrid outputs */        /* If first analog solution, call CKTop */        if(firstime) {            firstime = MIF_FALSE;            converged = CKTop(ckt,                              firstmode,                              continuemode,                              max_iter);            if(converged != 0)                return(converged);        }        /* Otherwise attempt to converge with mode = continuemode */        else {            ckt->CKTmode = continuemode;            converged = NIiter(ckt,max_iter);            if(converged != 0) {                converged = CKTop(ckt,                              firstmode,                              continuemode,                              max_iter);                if(converged != 0)                    return(converged);            }        }        /* Call all hybrids to allow new event outputs to be posted */        EVTcall_hybrids(ckt);        /* Increment count of successful alternations */        (ckt->evt->data.statistics->op_alternations)++;        /* If .option card specified not to alternate solutions, exit */        /* immediately with this first pass solution */        if(! ckt->evt->options.op_alternate)            return(0);        /* If no hybrid instances produced different event outputs, */        /* alternation is completed, so exit */        if(ckt->evt->queue.output.num_changed == 0)            return(0);        /* If too many alternations, exit with error */        if(ckt->evt->data.statistics->op_alternations >=                ckt->evt->limits.max_op_alternations) {            (*(SPfrontEnd->IFerror)) (ERR_WARNING,                "Too many analog/event-driven solution alternations",                (IFuid *) NULL);            err_msg = MALLOC(10000);            output_queue = &(ckt->evt->queue.output);            output_table = ckt->evt->info.output_table;            port_table = ckt->evt->info.port_table;            for(i = 0; i < output_queue->num_changed; i++) {                output_index = output_queue->changed_index[i];                port_index = output_table[output_index]->port_index;                sprintf(err_msg, "\n    Instance: %s\n    Connection: %s\n    Port: %d",                        port_table[port_index]->inst_name,                        port_table[port_index]->conn_name,                        port_table[port_index]->port_num);                ENHreport_conv_prob(ENH_EVENT_NODE,                                    port_table[port_index]->node_name,                                    err_msg);            }            FREE(err_msg);            return(E_ITERLIM);        }    } /* end forever */}/*EVTop_saveSave result from operating point iteration into the node data area.*/void EVTop_save(    CKTcircuit    *ckt,  /* The circuit structure */    Mif_Boolean_t op,    /* True if from a DCOP analysis, false if TRANOP, etc. */    double        step){    int         i;    int         num_nodes;    Mif_Boolean_t       equal;    Evt_Node_Data_t     *node_data;    Evt_Node_t          *rhsold;    Evt_Node_t          **head;    Evt_Node_t          **here;    /*	char buff[128];*/    /* Get pointers for fast access */    node_data = ckt->evt->data.node;    rhsold = node_data->rhsold;    head = node_data->head;    /* For number of event nodes, copy rhsold to node data */    /* and set the op member if appropriate */    num_nodes = ckt->evt->counts.num_nodes;    for(i = 0; i < num_nodes; i++) 	{        /* if head is null, just copy there */        if(head[i] == NULL) 		{            EVTnode_copy(ckt, i, &(rhsold[i]), &(head[i]));			            head[i]->op = op;            head[i]->step = step;			        }        /* Otherwise, add to the end of the list */        else 		{            /* Locate end of list */            here = &(head[i]);            for(;;) 			{                if((*here)->next)                    here = &((*here)->next);                else                    break;            }            /* Compare entry at end of list to rhsold */			            EVTnode_compare(ckt, i, &(rhsold[i]), *here, &equal);			            /* If new value in rhsold is different, add it to the list */            if(!equal) 			{                here = &((*here)->next);                EVTnode_copy(ckt, i, &(rhsold[i]), here);                (*here)->op = op;                (*here)->step = step;            }        } /* end else add to end of list */    }  /* end for number of nodes */}/* ************************************************************ *//*EVTnode_compareThis function compares the resolved values of the old andnew states on a node.  The actual comparison is done bycalling the appropriate user-defined node compare function.*/static void EVTnode_compare(    CKTcircuit    *ckt,        /* The circuit structure */    int           node_index,  /* The index for the node in question */    Evt_Node_t    *node1,      /* The first value */    Evt_Node_t    *node2,      /* The second value */    Mif_Boolean_t *equal)      /* The computed result */{    Evt_Node_Data_t     *node_data;    Evt_Node_Info_t     **node_table;    int                 udn_index;    /* Get data for fast access */    node_data = ckt->evt->data.node;    node_table = ckt->evt->info.node_table;    udn_index = node_table[node_index]->udn_index;    /* Do compare based on changes in resolved node value only */    (*(g_evt_udn_info[udn_index]->compare)) (            node1->node_value,            node2->node_value,            equal);}

⌨️ 快捷键说明

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