/********************************************************************/
/* Main.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: Main.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: Main.c */
/* */
/******************************************************************************/
/* Fecha: 19 de septiembre de 2005 */
/******************************************************************************/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "defines.h"
#include "tipos.h"
#include "main.h"
/* configuración */
struct argumentos configuracion;
/* bases de datos */
unsigned int num_nemonicos;
operacion *nemonicos = NULL;
unsigned int num_simbolos;
operando *simbolos = NULL;
unsigned int num_tiempos;
tiempo *ciclos = NULL;
/* recuentos */
unsigned long int *contadornemonicos = NULL;
unsigned long int *contadorlecturas = NULL;
unsigned long int *contadorescrituras = NULL;
/* contadores de instrucciones y ventanas */
unsigned long instruccion, ventana;
/* otros resultados */
double cpimedio = 0.0;
double tiempoejecucion = 0.0;
unsigned long *distribucionpasos = NULL;
/* posibles ubicaciones de datos */
unsigned int num_ubicaciones;
ubicacion *datos = NULL;
/* análisis de dependencias de datos */
int *pizarra_escrituras = NULL;
int **pizarra_lecturas = NULL;
unsigned char *vector = NULL;
struct punterosD matriz;
unsigned char **matrizC = NULL; /* matriz de caminos de dependencias */
char **OrdenParcial = NULL; /* lista de instrucciones según orden parcial de D */
/* parámetros asociados a las matrices */
parametromatriz *pasos = NULL;
parametromatriz *mediapasos = NULL;
parametromatriz *grado = NULL;
parametromatriz *mediagrado = NULL;
parametromatriz *acoplo = NULL;
parametromatriz *mediaacoplo = NULL;
/* declaro aquí mismo algunas funciones sencillas para no repetir secuencias de código */
void ProcesarInstruccion(unsigned int ins, unsigned char secuencia[12], fichainstruccion *tarjetaoperandos)
{
AnalizarOperandosIA16(secuencia, tarjetaoperandos);
if(configuracion.recuentos == SI) ActualizarRecuentos(tarjetaoperandos);
if(configuracion.cpi == SI) CalcularCiclosInstruccion(tarjetaoperandos);
if(configuracion.CPImedio == SI) ActualizarCPImedio(tarjetaoperandos->ciclosALU, tarjetaoperandos->ciclosBIU);
if(configuracion.dependencias == SI)
{
AnalizarDependencias(tarjetaoperandos, ins);
AnotarEscrituras(tarjetaoperandos, ins);
AnotarLecturas(tarjetaoperandos, ins);
/* si tengo que calcular el tiempo de ejecución */
/* debo construir un array con el tipo de instrucción */
/* y su latencia en ciclos */
}
}
void IniciarVentana()
{
if(configuracion.dependencias == SI)
{
IniciarPizarras();
IniciarVectorDependencias();
IniciarMatricesDependencias();
if(configuracion.ordenparcial == SI) IniciarListaOrdenParcial();
if(configuracion.matrizcaminos == SI) IniciarMatrizCaminos();
if(configuracion.pasoscomputacion == SI) IniciarVariableAgregada(pasos);
if(configuracion.gradoparalelismo == SI) IniciarVariableAgregada(grado);;
if(configuracion.acoplamiento == SI) IniciarVariableAgregada(acoplo);
}
}
void ProcesarVentana()
{
if(configuracion.dependencias == SI)
{
GenerarMatrizD(); /* a partir de las matrices desacopladas */
/* EXTRAIGO INFORMACIÓN DE LAS MATRICES */
/* lista orden parcial (la función también puede devolver pasos) */
if(configuracion.ordenparcial == SI) ListaOrdenParcial(matriz.D, OrdenParcial);
/* matriz de caminos (la función también puede devolver pasos) */
if(configuracion.matrizcaminos == SI) CalcularMatrizCaminos(matriz.D, matrizC);
/* pasos de computación */
if(configuracion.pasoscomputacion == SI)
{
/* pasos de computación de todas las matrices de dependencias */
CalcularPasosComputacion(pasos);
if(configuracion.distribucionpasos == SI) ActualizarHistogramaPasos();
/* valor medio de pasos de computación */
CalcularPromedioVariableAgregada(mediapasos, pasos, ventana);
}
/* grado de paralelismo (a partir de los pasos de computación) */
if(configuracion.gradoparalelismo == SI)
{
/* grado de paralelismo a partir de los pasos de computación */
CalcularGradoParalelismoNormalizado(pasos, grado);
/* valor medio del grado de paralelismo */
CalcularPromedioVariableAgregada(mediagrado, grado, ventana);
}
/* acoplamiento */
if(configuracion.acoplamiento == SI);
{
/* grado de paralelismo a partir de los pasos de computación */
CalcularAcoplamiento(acoplo);
/* valor medio del grado de paralelismo */
CalcularPromedioVariableAgregada(mediaacoplo, acoplo, ventana);
}
if(configuracion.tiempo == SI) tiempoejecucion = CalcularTiempo();
}
}
void ReservarMemoriaAnalisisDependencias()
{
CrearPizarras();
CrearVectorDependencias();
CrearMatricesDependencias();
if(configuracion.ordenparcial == SI) CrearListaOrdenParcial();
if(configuracion.matrizcaminos == SI) CrearMatrizCaminos();
if(configuracion.pasoscomputacion == SI)
{
pasos = CrearVariableAgregada();
IniciarVariableAgregada(pasos);
mediapasos = CrearVariableAgregada();
IniciarVariableAgregada(mediapasos);
if(configuracion.distribucionpasos == SI) CrearHistogramaPasos();
}
if(configuracion.gradoparalelismo == SI);
{
grado = CrearVariableAgregada();
IniciarVariableAgregada(grado);
mediagrado = CrearVariableAgregada();
IniciarVariableAgregada(mediagrado);
}
if(configuracion.acoplamiento == SI);
{
acoplo = CrearVariableAgregada();
IniciarVariableAgregada(acoplo);
mediaacoplo = CrearVariableAgregada();
IniciarVariableAgregada(mediaacoplo);
}
}
void LiberarMemoriaAnalisisDependencias()
{
LiberarMemoriaPizarras();
LiberarMemoriaVectorDependencias();
LiberarMemoriaMatricesDependencias();
if(configuracion.ordenparcial == SI) LiberarMemoriaListaOrdenParcial();
if(configuracion.matrizcaminos == SI) LiberarMemoriaMatrizCaminos();
if(configuracion.pasoscomputacion == SI) {free(pasos); free(mediapasos);}
if(configuracion.gradoparalelismo == SI) {free(grado); free(mediagrado);};
if(configuracion.acoplamiento == SI) {free(acoplo); free(mediaacoplo);};
if(configuracion.distribucionpasos == SI) LiberarMemoriaHistogramaPasos();
}
void main(int argc, char *argv[])
{
/* puntero al fichero origen de datos */
FILE *origendatos;
/* total instrucciones y ventanas a procesar */
unsigned long total_ins, total_ven;
/* secuencia en bytes de 2 instrucciones consecutivas */
unsigned char secuencia[2*BYTES_POR_INSTRUCCION];
/* reservo espacio para una estructura de tipo ficha de instrucción */
fichainstruccion tarjetaoperandos;
unsigned int i, ins;
char cadena[MAX_LINE];
char mensaje[MAX_LINE];
unsigned char salvarventana = NO;
char listadoventanas[MAX_LINE];
/* inicio los punteros de las matrices de dependencias a NULL */
/* es una medida higiénica pero no necesaria ya que la reserva de memoria */
/* correspondiente a la declaración se hace rellenando con 0s */
/* ver si es posible con {NULL, NULL...} */
IniciarPunterosMatrices();
/* NOTIFICACIONES DE SUCESOS Y ERRORES */
/* inicio el fichero que va a recibir las notificaciones */
IniciarNotificaciones();
/* CONFIGURACIÓN */
/* cargo la configuración de la aplicación por defecto */
CargarConfiguracionInicial();
/* modifico la configuración de la aplicación en función de los argumentos */
CapturarArgumentos(argc, argv);
/* escribo la configuración en el fichero de notificaciones */
if(configuracion.nivelnotificaciones != EX_CFG) NotificarConfiguracion();
/* BASES DE DATOS */
CargarBasesDatos();
/* CALCULOS A REALIZAR */
if(configuracion.recuentos == SI) CrearContadores();
if(configuracion.dependencias == SI) ReservarMemoriaAnalisisDependencias();
/* FICHEROS A CREAR */
if(configuracion.volcarBD == SI) SalvarBasesDatos();
if(configuracion.crearficheroconfig == SI) CrearFicheroConfiguracion();
/* CABECERA EN LA PANTALLA */
MostrarCabecera();
/* PROCESAMIENTO */
if(configuracion.origen == TRAZA)
{
/* determino el rango de instrucciones a analizar */
DeterminarRango();
/* determino el número total de instrucciones */
total_ins = (unsigned long)(configuracion.ultima - configuracion.primera + 1);
/* determino el número de ventanas de instrucciones */
total_ven = (unsigned long)total_ins/configuracion.ventana;
/* inicio los contadores */
instruccion = 1; /* cuento las instrucciones desde el '1' */
ventana = 0;
/* listado de ventanas a volcar */
strcpy(listadoventanas, configuracion.volcarventana);
/* abro el fichero de traza */
if((origendatos = fopen(configuracion.ficherodatos, "rb")) != NULL)
{
sprintf(mensaje, "[Main] El fichero '%s' se ha abierto con éxito", configuracion.ficherodatos);
Notificar(mensaje, NO_ERROR, ECO_NO);
/* sitúo el puntero del fichero en la instrucción de comienzo */
fseek(origendatos, (configuracion.primera - 1) * BYTES_POR_INSTRUCCION, SEEK_SET);
/* leo el formato de la primera instrucción a tratar */
/* y lo coloco en la parte alta de la secuencia (2ª instrucción) */
for(i=0; i<BYTES_POR_INSTRUCCION; i++) secuencia[i+BYTES_POR_INSTRUCCION] = fgetc(origendatos);
while(total_ven-ventana)
{
ventana++;
/* indicar estado de procesamiento */
PresentarEstadoProcesamiento(total_ven, ventana);
IniciarVentana();
/* ¿salvar información de la ventana en curso? */
if(listadoventanas[0] != '\0') /* si el listado no es vacío */
{
sprintf(cadena, "%lu", ventana);
if(BuscarElementoLista(listadoventanas, cadena) != 0)
{
salvarventana = SI;
EliminarElementoLista(listadoventanas, cadena);
/* construyo una planilla con resultados de la ventana en curso */
IniciarFicheroVentana();
}
else salvarventana = NO;
}
for(ins=0; ins<configuracion.ventana; ins++, instruccion++)
{
/* paso el formato de la parte alta a la baja */
for(i=0; i<BYTES_POR_INSTRUCCION; i++) secuencia[i] = secuencia[i+BYTES_POR_INSTRUCCION];
/* leo el formato de la instrucción siguiente desde la traza */
for(i=0; i<BYTES_POR_INSTRUCCION; i++) secuencia[i+BYTES_POR_INSTRUCCION] = fgetc(origendatos);
ProcesarInstruccion(ins, secuencia, &tarjetaoperandos);
if(configuracion.verinstruccion == SI) MostrarTarjeta(&tarjetaoperandos);
if(salvarventana == SI) Instruccion2FicheroVentana(&tarjetaoperandos);
/* _getch(); */
}
ProcesarVentana();
if(configuracion.verventana == SI) MostrarVentana();
/* salvo las matrices de la ventana en la planilla y sus parámetros */
if(salvarventana == SI) Matrices2FicheroVentana();
}
/* cierro el fichero de traza */
if(fclose(origendatos))
{
sprintf(mensaje, "[Main] El fichero '%s' no se ha podido cerrar", configuracion.ficherodatos);
Notificar(mensaje, ERROR_SEGUIR, ECO_NO);
}
else
{
sprintf(mensaje, "[Main] El fichero '%s' ha sido cerrado con éxito", configuracion.ficherodatos);
Notificar(mensaje, NO_ERROR, ECO_NO);
}
}
else
{
sprintf(mensaje, "[Main] El fichero '%s' no se ha podido abrir", configuracion.ficherodatos);
Notificar(mensaje, ERROR_SALIR, ECO_NO);
}
}
else if(configuracion.origen == SECUENCIA)
{
/* abro el fichero de la secuencia */
if((origendatos = fopen(configuracion.ficherodatos, "r")) != NULL)
{
sprintf(mensaje, "[Main] El fichero '%s' se ha abierto con éxito", configuracion.ficherodatos);
Notificar(mensaje, NO_ERROR, ECO_NO);
/* cuento las instrucciones de la secuencia */
ins = 0;
while(!feof(origendatos))
{
fgets (cadena, MAX_LINE, origendatos);
if (cadena[0]!='\n' && cadena[0]!='#') ins++;
}
configuracion.primera = 1;
configuracion.ultima = ins;
/* determino el número total de instrucciones */
total_ins = (unsigned long)(configuracion.ultima - configuracion.primera + 1);
/* determino el número de ventanas de instrucciones */
total_ven = (unsigned long)total_ins/configuracion.ventana;
/* inicio los contadores */
instruccion = 1; /* cuento las instrucciones desde el '1' */
ventana = 0;
/* listado de ventanas a volcar */
strcpy(listadoventanas, configuracion.volcarventana);
/* coloco el puntero del fichero al principio */
fseek(origendatos, 0L, SEEK_SET);
/* comienzo el análisis de la secuencia */
while(total_ven-ventana)
{
ventana++;
/* indicar estado de procesamiento */
PresentarEstadoProcesamiento(total_ven, ventana);
IniciarVentana();
/* ¿salvar información de la ventana en curso? */
if(listadoventanas[0] != '\0') /* si el listado no es vacío */
{
sprintf(cadena, "%lu", ventana);
if(BuscarElementoLista(listadoventanas, cadena) != 0)
{
salvarventana = SI;
EliminarElementoLista(listadoventanas, cadena);
/* construyo una planilla con resultados de la ventana en curso */
IniciarFicheroVentana();
}
else salvarventana = NO;
}
for(ins=0; ins<configuracion.ventana; ins++, instruccion++)
{
do
{
fgets (cadena, MAX_LINE, origendatos);
}
while (cadena[0]=='\n' || cadena[0]=='#');
/* quito el caracter '\n' (0x0A) final de la cadena correspondiente a una línea de texto */
/* ¡OJO! si abro el fichero en modo binario el final de linea es "\r\n" (0x0D 0x0A) */
*(cadena+strlen(cadena)-1)='\0';
ConvertirHex2Bin(cadena, secuencia, BYTES_POR_INSTRUCCION);
ProcesarInstruccion(ins, secuencia, &tarjetaoperandos);
if(configuracion.verinstruccion == SI) MostrarTarjeta(&tarjetaoperandos);
/* salvo las instrucciones en la planilla de la ventana */
if(salvarventana == SI) Instruccion2FicheroVentana(&tarjetaoperandos);
}
ProcesarVentana();
if(configuracion.verventana == SI) MostrarVentana();
/* salvo las matrices de la ventana en la planilla y sus parámetros */
if(salvarventana == SI) Matrices2FicheroVentana();
}
/* cierro el fichero de la secuencia */
if(fclose(origendatos))
{
sprintf(mensaje, "[Main] El fichero '%s' no se ha podido cerrar", configuracion.ficherodatos);
Notificar(mensaje, ERROR_SEGUIR, ECO_NO);
}
else
{
sprintf(mensaje, "[Main] El fichero '%s' ha sido cerrado con éxito", configuracion.ficherodatos);
Notificar(mensaje, NO_ERROR, ECO_NO);
}
}
else
{
sprintf(mensaje, "[Main] El fichero '%s' no se ha podido abrir", configuracion.ficherodatos);
Notificar(mensaje, ERROR_SALIR, ECO_NO);
}
}
else if(configuracion.origen == CADENAHEX)
{
instruccion = 1;
ventana = 1;
ConvertirHex2Bin(configuracion.cadenahex, secuencia, BYTES_POR_INSTRUCCION);
AnalizarOperandosIA16(secuencia, &tarjetaoperandos);
if(configuracion.cpi == SI) CalcularCiclosInstruccion(&tarjetaoperandos);
/* if(configuracion.verinstruccion == SI) */
/* muestro en la pantalla la información siempre */
MostrarTarjeta(&tarjetaoperandos);
}
/* SALVAR RESULTADOS */
/* salvo los resultados en un fichero de formato EXCEL */
if(configuracion.origen != CADENAHEX) CrearFicheroResultados(configuracion.ficheroresultados);
/* LIBERAR MEMORIA */
/* al final hay que liberar toda la memoria reservada */
LiberarMemoriaBasesDatos();
if(configuracion.recuentos == SI) LiberarMemoriaContadores();
if(configuracion.dependencias == SI) LiberarMemoriaAnalisisDependencias();
}
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>