Exemplo n.º 1
0
int EVTload(
    CKTcircuit *ckt,        /* The circuit structure */
    int        inst_index)  /* The instance to call code model for */
{

    int                 i;
    int                 j;

    int                 num_conn;
    int                 num_port;
    int                 mod_type;

    Mif_Conn_Data_t     *conn;
    Mif_Port_Data_t     *port;

    Mif_Private_t       cm_data;

    MIFinstance         *inst;

    Evt_Node_Data_t     *node_data;

    void                *value_ptr;


    /* ***************************** */
    /* Prepare the code model inputs */
    /* ***************************** */

    /* Get pointer to instance data structure and other data */
    /* needed for fast access */
    inst = ckt->evt->info.inst_table[inst_index]->inst_ptr;
    node_data = ckt->evt->data.node;

    /* Setup circuit data in struct to be passed to code model function */

    if(inst->initialized)
        cm_data.circuit.init = MIF_FALSE;
    else
        cm_data.circuit.init = MIF_TRUE;

    cm_data.circuit.anal_init = MIF_FALSE;
    cm_data.circuit.anal_type = g_mif_info.circuit.anal_type;

    if(g_mif_info.circuit.anal_type == MIF_TRAN)
        cm_data.circuit.time = g_mif_info.circuit.evt_step;
    else
        cm_data.circuit.time = 0.0;

    cm_data.circuit.call_type = MIF_EVENT_DRIVEN;
    cm_data.circuit.temperature = ckt->CKTtemp - 273.15;


    /* Setup data needed by cm_... functions */

    g_mif_info.ckt = ckt;
    g_mif_info.instance = inst;
    g_mif_info.errmsg = "";
    g_mif_info.circuit.call_type = MIF_EVENT_DRIVEN;

    if(inst->initialized)
        g_mif_info.circuit.init = MIF_FALSE;
    else
        g_mif_info.circuit.init = MIF_TRUE;


    /* If after initialization and in transient analysis mode */
    /* create a new state for the instance */

    if((g_mif_info.circuit.anal_type == MIF_TRAN) && inst->initialized)
        EVTcreate_state(ckt, inst_index);


    /* Loop through all connections on the instance and setup */
    /* load, total_load, and msg on all ports, and changed flag */
    /* and output pointer on all outputs */

    num_conn = inst->num_conn;
    for(i = 0; i < num_conn; i++) {

        conn = inst->conn[i];

        /* if connection is null, continue to next */
        if(conn->is_null)
            continue;

        /* Loop through each port on the connection */
        num_port = conn->size;
        for(j = 0; j < num_port; j++) {

            port = conn->port[j];

            /* Skip if port is null */
            if(port->is_null)
                continue;

            /* If port type is Digital or User-Defined */
            if((port->type == MIF_DIGITAL) || (port->type == MIF_USER_DEFINED)) {

                /* Initialize the msg pointer on the port to NULL, */
                /* initialize the load value to zero, and get the total load */
                port->msg = NULL;
                port->load = 0.0;
                port->total_load = node_data->total_load[port->evt_data.node_index];

                /* If connection is an output, initialize changed to true */
                /* and create a new output event object in the free list */
                /* if transient analysis mode */
                if(conn->is_output) {
                    port->changed = MIF_TRUE;
                    if(g_mif_info.circuit.anal_type == MIF_TRAN) {
                        EVTcreate_output_event(ckt,
                                         port->evt_data.node_index,
                                         port->evt_data.output_index,
                                         &value_ptr);
                        port->output.pvalue = value_ptr;
                    }
                }
            }
            else {
                /* Get the analog input value.  All we need to do is */
                /* set it to zero if mode is INITJCT.  Otherwise, value */
                /* should still be around from last successful analog call */
                if(ckt->CKTmode & MODEINITJCT)
                    port->input.rvalue = 0.0;
            }

        } /* end for number of ports */
    } /* end for number of connections */


    /* Prepare the structure to be passed to the code model */
    cm_data.num_conn = inst->num_conn;
    cm_data.conn = inst->conn;
    cm_data.num_param = inst->num_param;
    cm_data.param = inst->param;
    cm_data.num_inst_var = inst->num_inst_var;
    cm_data.inst_var = inst->inst_var;
    cm_data.callback = &(inst->callback);


    /* ******************* */
    /* Call the code model */
    /* ******************* */

    mod_type = MIFmodPtr(inst)->MIFmodType;
    DEVices[mod_type]->DEVpublic.cm_func (&cm_data);


    /* ****************************** */
    /* Process the code model outputs */
    /* ****************************** */

    /* Loop through all connections and ports and process the msgs */
    /* and event outputs */

    num_conn = inst->num_conn;
    for(i = 0; i < num_conn; i++) {

        conn = inst->conn[i];
        if(conn->is_null)
            continue;

        /* Loop through each port on the connection */
        num_port = conn->size;
        for(j = 0; j < num_port; j++) {

            port = conn->port[j];

            /* Skip if port is null */
            if(port->is_null)
                continue;

            /* Process the message if any */
            if(port->msg)
                EVTadd_msg(ckt, port->evt_data.port_index, port->msg);

            /* If this is the initialization pass, process the load factor */
            if(! inst->initialized) {
                node_data->total_load[port->evt_data.node_index] +=
                        port->load;
            }

            /* If connection is not an event output, continue to next port */
            if(! conn->is_output)
                continue;
            if((port->type != MIF_DIGITAL) && (port->type != MIF_USER_DEFINED))
                continue;

            /* If output changed, process it */
            EVTprocess_output(ckt, port->changed,
                                   port->evt_data.output_index,
                                   port->invert, port->delay);

            /* And prevent erroneous models from overwriting it during */
            /* analog iterations */
            if(g_mif_info.circuit.anal_type == MIF_TRAN)
                port->output.pvalue = NULL;

        } /* end for number of ports */
    } /* end for number of connections */


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

    /* Mark that the instance has been called once */
    inst->initialized = MIF_TRUE;

    return(OK);
}
Exemplo n.º 2
0
static void EVTdequeue_output(
    CKTcircuit  *ckt,          /* The circuit structure */
    double      time)          /* The event time of the events to dequeue */
{

    int         i;
    int         j;

    int         num_pending;
    int         index;
    int         output_index;

    double      next_time;
    double      event_time;

    Evt_Output_Queue_t  *output_queue;

    Evt_Output_Event_t  *output;
    Evt_Output_Event_t  **output_ptr;


    /* Get pointers for fast access */
    output_queue = &(ckt->evt->queue.output);

    /* Exit if nothing pending on output queue or if next_time */
    /* != specified time */
    if(output_queue->num_pending == 0)
        return;
    if(output_queue->next_time != time)
        return;

    /* Scan the list of outputs pending */
    num_pending = output_queue->num_pending;
    for(i = 0; i < num_pending; i++) {

        /* Get the index of the output */
        index = output_queue->pending_index[i];

        /* Get pointer to next event in queue at this index */
        output = *(output_queue->current[index]);

        /* If event time does not match current time, skip */
        if(output->event_time != time)
            continue;

        /* It must match, so pull the event from the queue and process it */
        EVTprocess_output(ckt, index, output->value);

        /* Move current to point to next non-removed item in list */
        output_ptr = &(output->next);
        output = *output_ptr;
        while(output) {
            if(! output->removed)
                break;
            output_ptr = &(output->next);
            output = *output_ptr;
        }
        output_queue->current[index] = output_ptr;

        /* Mark that this index in the queue has been modified */
        if(! output_queue->modified[index]) {
            output_queue->modified[index] = MIF_TRUE;
            output_queue->modified_index[(output_queue->num_modified)++] = index;
        }
    }


    /* Update/compact the pending list and update the next_time */
    next_time = 1e30;
    for(i = 0, j = 0; i < num_pending; i++) {
        output_index = output_queue->pending_index[i];
        output = *(output_queue->current[output_index]);
        /* If nothing in queue at last_step, remove this index from the pending list */
        if(! output) {
            output_queue->pending[output_index] = MIF_FALSE;
            (output_queue->num_pending)--;
        }
        /* else, keep the index and update the next time */
        else {
            output_queue->pending_index[j] = output_queue->pending_index[i];
            j++;
            event_time = output->event_time;
            if(event_time < next_time)
                next_time = event_time;
        }
    }
    output_queue->next_time = next_time;


}