/********************************************************************/
/* CalcularCiclos.c */
/* */
/* Copyright (c) 1997-2006 Rafael Rico (rafael.rico@uah.es) */
/* */
/* This file is part of ADD version 5.10. */
/* */
/* ADD is free software; you can redistribute it and/or modify */
/* it under the terms of the GNU General Public License as */
/* published by the Free Software Foundation; either version 2 of */
/* the License, or (at your option) any later version. */
/* */
/* ADD is distributed in the hope that it will be useful, */
/* but WITHOUT ANY WARRANTY; without even the implied warranty of */
/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the */
/* GNU General Public License for more details. */
/* */
/* You should have received a copy of the GNU General Public */
/* License along with ADD; if not, write to the Free Software */
/* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA */
/* 02111-1307 USA */
/* */
/* --------------------------- History --------------------------- */
/* */
/* Revision 1.2. 01/2006 */
/* Added GPL License and JavaDoc style documentation */
/* */
/* Revision 1.1. 09/2005 */
/* Initial Revision */
/* */
/********************************************************************/
/******************************************************************************/
/* 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>