File:  [Repository ATC2] / ADD_ver_10 / Source Code / Source Files / CalcularCiclos.c
Revision 1.2: download - view: text, annotated - select for diffs
Tue Feb 28 14:54:21 2006 UTC (18 years, 8 months ago) by rico
Branches: MAIN
CVS tags: HEAD
*** empty log message ***

/********************************************************************/
/*  CalcularCiclos.c                                                */
/*                                                                  */
/*                                                                  */
/*  Copyright (c) 1997-2006 Rafael Rico      (rafael.rico@uah.es)   */
/*                                                                  */
/*  Este fichero forma parte de ADD                                 */
/*  (Analizador de Dependencias de Datos)                           */
/*  Version 5.10.                                                   */
/*                                                                  */
/*                                                                  */
/*  ADD es software libre. Puede redistribuirlo y/o modificarlo     */
/*  bajo los términos de la Licencia Pública General de GNU         */
/*  según es publicada por la Free Software Foundation, bien bajo   */
/*  la versión 2 de dicha Licencia o bien (según su elección)       */
/*  bajo cualquier versión posterior.                               */
/*                                                                  */
/*  ADD se distribuye con la esperanza de que sea útil,             */
/*  pero SIN NINGUNA GARANTÍA, incluso sin la garantía MERCANTIL    */
/*  implícita y sin garantizar la CONVENIENCIA PARA UN PROPÓSITO    */
/*  PARTICULAR. Véase la Licencia Pública General de GNU para       */
/*  más detalles.                                                   */
/*                                                                  */
/*  Debería haber recibido una copia de la Licencia Pública General */
/*  junto con ADD. Si no ha sido así, escriba a la Free Software    */
/*  Foundation, Inc., 51 Franklin St, Fifth Floor,                  */
/*  Boston, MA  02110-1301  EEUU.                                   */
/*                                                                  */
/*  -------------------------- Historia --------------------------- */
/*                                                                  */
/*  $Id: CalcularCiclos.c,v 1.2 2006/02/28 14:54:21 rico Exp $                                                            */
/*                                                                  */
/*  Revisión 1.2. 01/2006                                           */
/*  Se añade la licencia GPL y documentación en estilo Javadoc      */
/*                                                                  */
/*  Revisión 1.1. 09/2005                                           */
/*  Versión inicial                                                 */
/*                                                                  */
/********************************************************************/

/******************************************************************************/
/* MÓDULO: CalcularCiclos.c                                                   */
/*                                                                            */
/* Este módulo calcula el tiempo de ejecución en ciclos de cada instrucción   */
/* a partir de la operación, el tipo de operando, el tipo de acceso (lectura  */
/* o escritura), el tipo de cómputo de direcciones de memoria (en su caso) y  */
/* si el salto se toma o no (en su caso).                                     */
/******************************************************************************/
/* Fecha: 16 de septiembre de 2005                                            */
/******************************************************************************/

#include <stdio.h>
#include <string.h>
#include <ctype.h>

#include "defines.h"
#include "tipos.h"
#include "calcularciclos.h"

/* bases de datos */
extern unsigned int num_nemonicos;
extern operacion *nemonicos;
extern unsigned int num_simbolos;
extern operando *simbolos;
extern unsigned int num_tiempos;
extern tiempo *ciclos;

/* contador de instrucciones */
extern unsigned long instruccion;

/* otros resultados */
extern double cpimedio;


/* esta función devuelve el número de ciclos invertido en calcular la dirección efectiva */
/* y normaliza la cadena según el timpo de operando y acceso */

char ComputarDireccion(char *cadena)
{
    int id;
    char ciclos_tiempo;
    int desplazamiento = NO;
    char mensaje[MAX_LINE];

    switch(cadena[0])
    {
        case '\0':    /* sin operando; aquí se supone que no debería entrar */
        ciclos_tiempo = 0;
        break;

        case '[':    /* operando memoria */
        if(isxdigit(cadena[2])) strcpy(cadena, "[XXXX]");    /* es un desplazamiento absoluto */
        else        /* ubicaciones de memoria basadas en registros */
        {
            if(cadena[3]==']')        /* registro base o índice solamente */
            {
                if(cadena[4]=='\0') desplazamiento = NO;
                else desplazamiento = SI;
                cadena[4]='\0';        /* termino la cadena sin del posible desplazamiento */
            }
            else
            {
                if(cadena[6]=='\0') desplazamiento = NO;
                else desplazamiento = SI;
                cadena[6]='\0';        /* termino la cadena sin del posible desplazamiento */
            }
        }

        id = BDBuscarCadena(TABLA_CICLOS, CAMPO_IDENTIFICADOR, cadena);
    
        if(id == -1)
        {
            /* emito un error al fichero de log */ 
            sprintf(mensaje, "[ComputarDireccion] La cadena '%s' no se ha encontrado en Tabla Ciclos", cadena);
            Notificar(mensaje, ERROR_SALIR, ECO_NO);
        }
        ciclos_tiempo = ciclos[id].ciclos;
        
        if(desplazamiento == SI)    /* si hay desplzamiento añado su tiempo */
        {
            id = BDBuscarCadena(TABLA_CICLOS, CAMPO_IDENTIFICADOR, "DESPLZ");
    
            if(id == -1)
            {
                /* emito un error al fichero de log */ 
                sprintf(mensaje, "[ComputarDireccion] La cadena '%s' no se ha encontrado en Tabla Ciclos", "DESPLZ");
                Notificar(mensaje, ERROR_SALIR, ECO_NO);
            }
            ciclos_tiempo += ciclos[id].ciclos;
        }
        strcpy(cadena, "MEM");    /* cambio la cadena por la de acceso a MEMORIA */
        break;

        default:    /* registros, inmediatos, o direcciones físicas */
        if(isxdigit(cadena[1]))    /* es un número hexadecimal */
        {
            switch(strlen(cadena))
            {
                case 2:    /* inmediato de 1 byte */
                strcpy(cadena, "INM8");
                break;

                case 4:    /* inmediato de 2 bytes */
                strcpy(cadena, "INM16");
                break;

                case 9:    /* dirección física */
                strcpy(cadena, "B:D");
                break;
            }
        }
        else
        {
            if(cadena[1]=='L' || cadena[1]=='H') strcpy(cadena, "REG8");
            else strcpy(cadena, "REG16");
        }
        ciclos_tiempo = 0;
        break;
    }
    return ciclos_tiempo;
}


/* esta función asigna los ciclos ALU y los ciclos BIU correspondientes */
/* a partir de la ficha de la instrucción */

void CalcularCiclosInstruccion(fichainstruccion *tarjetaoperandos)
{
    int id;
    char op1[MAX_OPE], op2[MAX_OPE];
    char pesa_inm = SI;        /* indico si un inmediato pesa en ciclos o no */
    char ciclos_tiempo;
    char mensaje[MAX_LINE];


    /* TIEMPO DEBIDO A LA OPERACIÓN */

    /* busco en la tabla de ciclos */

    id = BDBuscarCadena(TABLA_CICLOS, CAMPO_IDENTIFICADOR, tarjetaoperandos->nemonico);
    
    if(id == -1)
    {
        /* emito un error al fichero de log */ 
        sprintf(mensaje, "[CalcularCiclos] La cadena '%s' no se ha encontrado en Tabla Ciclos", tarjetaoperandos->nemonico);
        Notificar(mensaje, ERROR_SALIR, ECO_NO);
    }

    tarjetaoperandos->ciclosALU = ciclos[id].ciclos;

    /* ahora busco en la tabla de nemónicos */

    id = BDBuscarCadena(TABLA_NEMONICOS, CAMPO_NEMONICO, tarjetaoperandos->nemonico);
    
    if(id == -1)
    {
        /* emito un error al fichero de log */ 
        sprintf(mensaje, "[CalcularCiclos] La cadena '%s' no se ha encontrado en Tabla Nemónicos", tarjetaoperandos->nemonico);
        Notificar(mensaje, ERROR_SALIR, ECO_NO);
    }

    /* TIEMPO DEBIDO AL CÓMPUTO DE DIRECCIONES */
    strcpy(op2, tarjetaoperandos->op2);
    ciclos_tiempo = ComputarDireccion(op2); 

    strcpy(op1, tarjetaoperandos->op1);
    ciclos_tiempo += ComputarDireccion(op1); 

    /* he obtenido los operandos normalizados */

    /* TIEMPO DEBIDO AL TIPO DE OPERANDO Y TIPO DE ACCESO */

    /* tamaño de acceso a memoria y tipo de acceso */
    if(!strcmp(op2, "MEM"))
    {    
        if(strcmp(op1, "REG8") && strcmp(op1, "INM8")) strcat(op2, "16");
        else strcat(op2, "8");
        /* tipo de acceso: lectura o escritura */
        switch(nemonicos[id].modo_op2)
        {
            case LEIDO:    /* leido */
            strcat(op2, "L");
            break;
            
            case ESCRITO:    /* escrito */
            strcat(op2, "E");
            break;

            case LEIDOYESCRITO:    /* leido y escrito */
            strcat(op2, "LE");
            break;
        }
    }
    if(!strcmp(op1, "MEM"))
    {    
        if(strcmp(op2, "REG8") && strcmp(op2, "INM8")) strcat(op1, "16");
        else strcat(op1, "8");
        /* tipo de acceso: lectura o escritura */
        switch(nemonicos[id].modo_op1)
        {
            case LEIDO:    /* leido */
            strcat(op1, "L");
            break;
            
            case ESCRITO:    /* escrito */
            strcat(op1, "E");
            break;

            case LEIDOYESCRITO:    /* leido y escrito */
            strcat(op1, "LE");
            break;
        }
    }

    /* indico si los inmediatos pesan o no en ciclos (los de los saltos, etc. no pesan) */
    if(nemonicos[id].tipo < SALTO_INCONDICIONAL) pesa_inm = SI;
    else pesa_inm = NO;

    /* busco en la tabla de ciclos los operandos normalizados */

    if(op2[0]!='\0')        /* fuente */
    {
        id = BDBuscarCadena(TABLA_CICLOS, CAMPO_IDENTIFICADOR, op2);
    
        if(id == -1)
        {
            /* emito un error al fichero de log */ 
            sprintf(mensaje, "[CalcularCiclos] La cadena '%s' no se ha encontrado en Tabla Ciclos", op2);
            Notificar(mensaje, ERROR_SALIR, ECO_NO);
        }

        ciclos_tiempo += ciclos[id].ciclos;
    }

    if(op1[0]!='\0')        /* destino */
    {
        id = BDBuscarCadena(TABLA_CICLOS, CAMPO_IDENTIFICADOR, op1);
    
        if(id == -1)
        {
            /* emito un error al fichero de log */ 
            sprintf(mensaje, "[CalcularCiclos] La cadena '%s' no se ha encontrado en Tabla Ciclos", op1);
            Notificar(mensaje, ERROR_SALIR, ECO_NO);
        }

        /* los inmediatos que no pesan sólo pueden estar en el destino */
        if(pesa_inm == SI) ciclos_tiempo += ciclos[id].ciclos;
    }

    /* TIEMPO DEBIDO A LOS PREFIJOS */

    if(strcmp(tarjetaoperandos->prefijo, ""))
    {
        id = BDBuscarCadena(TABLA_CICLOS, CAMPO_IDENTIFICADOR, tarjetaoperandos->prefijo);
    
        if(id == -1)
        {
            /* emito un error al fichero de log */ 
            sprintf(mensaje, "[CalcularCiclos] La cadena '%s' no se ha encontrado en Tabla Ciclos", tarjetaoperandos->prefijo);
            Notificar(mensaje, ERROR_SALIR, ECO_NO);
        }

        ciclos_tiempo += ciclos[id].ciclos;
    }

    tarjetaoperandos->ciclosBIU = ciclos_tiempo;

    /* TIEMPO ASOCIADO A LOS SALTOS CONDICIONALES */

    if(tarjetaoperandos->salto == 2)    /* salto condicional TOMADO */
    {
        id = BDBuscarCadena(TABLA_CICLOS, CAMPO_IDENTIFICADOR, "TOMADO");
    
        if(id == -1)
        {
            /* emito un error al fichero de log */ 
            sprintf(mensaje, "[CalcularCiclos] La cadena '%s' no se ha encontrado en Tabla Ciclos", "TOMADO");
            Notificar(mensaje, ERROR_SALIR, ECO_NO);
        }

        tarjetaoperandos->ciclosALU += ciclos[id].ciclos;
    }
}


/* esta función actualiza el promedio de CPI a partir del tiempo de */
/* ejecución en ciclos ALU + ciclos BIU de la instrucción en curso */

void ActualizarCPImedio(unsigned short int ciclosALU, unsigned short int ciclosBIU)
{
    unsigned int ciclos;

    ciclos = ciclosALU + ciclosBIU;

    cpimedio = CalcularNuevoPromedio (cpimedio, (double)ciclos, instruccion);
}



FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>