/********************************************************************/
/* 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>