/********************************************************************/ /* 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 #include #include #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); }