コード例 #1
0
ファイル: evtcall_hybrids.c プロジェクト: gnotuil/ngspice-gss
void EVTcall_hybrids(
    CKTcircuit  *ckt)    /* the main circuit structure */
{

    int     i;
    int     num_hybrids;

    int     *hybrid_index;


    /* Get needed data for fast access */
    num_hybrids = ckt->evt->counts.num_hybrids;
    hybrid_index = ckt->evt->info.hybrid_index;

    /* Call EVTload for all hybrids */
    for(i = 0; i < num_hybrids; i++)
        EVTload(ckt, hybrid_index[i]);

}
コード例 #2
0
ファイル: evtiter.c プロジェクト: a-mehrabian/spice-buffer
int EVTiter(
    CKTcircuit *ckt)    /* the circuit structure */
{

    int         i;
    int         num_changed;

    int         num_to_eval;
    int         num_to_call;

    int         output_index;
    /*    int         output_subindex;*/
    int         inst_index;
    int         node_index;
    int         port_index;

    int         num_outputs;
    int         udn_index;

    int         passes;

    Evt_Ckt_Data_t  *evt;

    Evt_Output_Queue_t  *output_queue;
    Evt_Node_Queue_t    *node_queue;
    Evt_Inst_Queue_t    *inst_queue;

    Evt_Output_Info_t   **output_table;
    Evt_Node_Info_t     **node_table;
    Evt_Port_Info_t     **port_table;

    Evt_Inst_Index_t    *inst_list;

    Evt_Node_Data_t     *node_data;

    Evt_Node_t          *rhs;
    Evt_Node_t          *rhsold;

    Evt_Node_t          *node;

    Mif_Boolean_t       equal;

    char                *err_msg;


    /* Get temporary pointers for fast access */
    evt = ckt->evt;

    output_queue = &(evt->queue.output);
    node_queue = &(evt->queue.node);
    inst_queue = &(evt->queue.inst);

    output_table = evt->info.output_table;
    node_table = evt->info.node_table;
    port_table = evt->info.port_table;

    node_data = evt->data.node;
    rhs = node_data->rhs;
    rhsold = node_data->rhsold;


    /* Loop until no more output change, or too many passes through loop */
    for(passes = 0; passes < evt->limits.max_event_passes; passes++) {


        /* Create list of nodes to evaluate from list of changed outputs */
        num_changed = output_queue->num_changed;
        for(i = 0; i < num_changed; i++) {

            /* Get index of node that output is connected to */
            output_index = output_queue->changed_index[i];
            node_index = output_table[output_index]->node_index;

            /* If not already on list of nodes to evaluate, add it */
            if(! node_queue->to_eval[node_index]) {
                node_queue->to_eval[node_index] = MIF_TRUE;
                node_queue->to_eval_index[(node_queue->num_to_eval)++]
                        = node_index;
            }

            /* Reset the changed flag on the output queue */
            output_queue->changed[output_index] = MIF_FALSE;

        }
        output_queue->num_changed = 0;



        /* Evaluate nodes and for any which have changed, enter */
        /* the instances that receive inputs from them on the list */
        /* of instances to call */

        num_to_eval = node_queue->num_to_eval;
        for(i = 0; i < num_to_eval; i++) {

            /* Get the node index, udn index and number of outputs */
            node_index = node_queue->to_eval_index[i];
            udn_index = node_table[node_index]->udn_index;
            num_outputs = node_table[node_index]->num_outputs;

            /* Resolve the node value if multiple outputs on it */
            /* and test if new node value is different than old value */
            if(num_outputs > 1) {
                g_evt_udn_info[udn_index]->resolve
                        (num_outputs,
                        rhs[node_index].output_value,
                        rhs[node_index].node_value);
                g_evt_udn_info[udn_index]->compare
                        (rhs[node_index].node_value,
                        rhsold[node_index].node_value,
                        &equal);
                if(! equal) {
                    g_evt_udn_info[udn_index]->copy
                            (rhs[node_index].node_value,
                            rhsold[node_index].node_value);
                }
            }
            /* Else, load function has already determined that they were */
            /* not equal */
            else
                equal = MIF_FALSE;

            /* If not equal, make inverted copy in rhsold if */
            /* needed, and place indexes of instances with inputs connected */
            /* to the node in the to_call list of inst queue */
            if(! equal) {
                if(node_table[node_index]->invert) {
                    g_evt_udn_info[udn_index]->copy
                            (rhsold[node_index].node_value,
                            rhsold[node_index].inverted_value);
                    g_evt_udn_info[udn_index]->invert
                            (rhsold[node_index].inverted_value);
                }
                inst_list = node_table[node_index]->inst_list;
                while(inst_list) {
                    inst_index = inst_list->index;
                    if(! inst_queue->to_call[inst_index]) {
                        inst_queue->to_call[inst_index] = MIF_TRUE;
                        inst_queue->to_call_index[(inst_queue->num_to_call)++]
                                = inst_index;
                    }
                    inst_list = inst_list->next;
                } /* end while instances with inputs on node */
            } /* end if not equal */

            /* If transient analysis mode */
            /* Save the node data onto the node results list and mark */
            /* that it has been modified, even if the */
            /* resolved node value has not changed */
            if(g_mif_info.circuit.anal_type == MIF_TRAN) {

                node = *(node_data->tail[node_index]);
                node_data->tail[node_index] = &(node->next);
                EVTnode_copy(ckt, node_index, &(rhsold[node_index]), &(node->next));
                node->next->step = g_mif_info.circuit.evt_step;

                if(! node_data->modified[node_index]) {
                    node_data->modified[node_index] = MIF_TRUE;
                    node_data->modified_index[(node_data->num_modified)++] = node_index;
                }
            }

            /* Reset the to_eval flag on the node queue */
            node_queue->to_eval[node_index] = MIF_FALSE;

        } /* end for number of nodes to evaluate */
        node_queue->num_to_eval = 0;



        /* Call the instances with inputs on nodes that have changed */
        num_to_call = inst_queue->num_to_call;
        for(i = 0; i < num_to_call; i++) {
            inst_index = inst_queue->to_call_index[i];
            inst_queue->to_call[inst_index] = MIF_FALSE;
            EVTload(ckt, inst_index);
        }
        inst_queue->num_to_call = 0;


        /* Record statistics */
        if(g_mif_info.circuit.anal_type == MIF_DC)
            (ckt->evt->data.statistics->op_event_passes)++;


        /* If no outputs changed, iteration is over, so return with success! */
        if(output_queue->num_changed == 0)
            return(0);

    } /* end for */


    /* Too many passes through loop, report problems and exit with error */

    err_msg = TMALLOC(char, 10000);
    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);

    SPfrontEnd->IFerror (ERR_WARNING,
        "Too many iteration passes in event-driven circuits",
        NULL);
    return(E_ITERLIM);

}