sim_error.c 7.25 KB
/*
 * Copyright (C) 1996-1998 by the Board of Trustees
 *    of Leland Stanford Junior University.
 * 
 * This file is part of the SimOS distribution. 
 * See LICENSE file for terms of the license. 
 *
 */

/*****************************************************************
 * error.c
 *
 * Error handling routines
 *
 * Author: $Author: blythe $
 * Date:   $Date: 2002/06/25 11:56:03 $
 *****************************************************************/

#include <sys/types.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdarg.h>
#include <unistd.h>
#include "sim_error.h"
#include "cpu_interface.h"
#include "tcl_init.h"

FILE *cpulogF = 0;

int loopOnError = 1;
int CPUErrorLoop = 1;
int SimErrorKeepLogs =0;

void SimErrorInit(char *log_file)
{
  char filename[256];
  ASSERT( !cpulogF );

  if( SimErrorKeepLogs && (access(log_file,F_OK)==0) ) {
    int CPnum;
    for (CPnum = 1; ; CPnum++) { 
      sprintf(filename, "%s.%03i", log_file, CPnum);
      if (access(filename, F_OK) == 0) {
	if (CPnum > 999) { CPUError("Too many opened log files"); }
	continue;
      }
      if( rename(log_file, filename) ) {
         perror("Rename log file error");
      } else {
	/* renamed file */
      }
      break;
    }
  }
  cpulogF = fopen(log_file,"w");
  if (cpulogF == NULL) {
    sprintf(filename, "fopen of %s", log_file);
    perror(filename);
    exit(1);
  }
}

void CPUError(char* string, ...)
{
  va_list ap;
  char llstring[1024];

  SubstituteLLx(llstring, string, 1024);
  va_start(ap, string);
  fprintf(stderr, "\nERROR, pid=%i :",(int)getpid());
  vfprintf(stderr, llstring, ap);
  va_end(ap);

  fprintf(stderr, "\n");
  fprintf(stderr, "\r");

  if (!CPUVec.CycleCount || CPUVec.CycleCount(0)==0) {
     loopOnError = 0;
  }

  if (loopOnError) {
     while (CPUErrorLoop) {
#ifdef sgi
        sginap(20);
#else
        sleep(1);
#endif  
     }
  } else {
     exit(-1);
  }
}

void Sim_Error(char* string, ...)
{
   fprintf(stderr,"Sim_Error called. Please replace with CPUError!!! \n");
   fprintf(stderr, "\nERROR, pid=%i :",(int)getpid());
  if (loopOnError) {
     while (CPUErrorLoop) {
#ifdef sgi
        sginap(20);
#else
        sleep(1);
#endif  
     }
  } else {
     exit(-1);
  }
}

   

void CPUWarning( char *text,...)
{
  va_list ap;
  char lltext[1024];
  va_start(ap,text);

  SubstituteLLx(lltext, text, 1024);
  vfprintf(stderr, lltext, ap);
  vCPUPrint(lltext, ap);
  fprintf(stderr, "\r");
  fflush(stderr);

  va_end(ap);
}

void Sim_Warning( char *text,...)
{
  va_list ap;
  char lltext[1024];
  va_start(ap,text);

  SubstituteLLx(lltext, text, 1024);
  vfprintf(stderr, lltext, ap);
  vCPUPrint(lltext, ap);
  fprintf(stderr, "\r");
  fflush(stderr);

  va_end(ap);
}




/*****************************************************************
 * Don't print anything using CPUPrint or CPUWarning here or you can
 * end up stepping on yourself by opening the cpu log twice. 
 *****************************************************************/



void vCPUPrint(char *text, va_list ap)
{
#ifdef __alpha
   char out[1024];
   SubstituteLLx(out,text,1024);
   ASSERT(cpulogF);
   vfprintf(cpulogF,out,ap);
   fflush(cpulogF);
#else
   ASSERT(cpulogF);
   vfprintf(cpulogF,text,ap);
   fflush(cpulogF);
#endif
}

void CPUPrint( char *text,...)
{

  va_list ap;
  va_start(ap,text);
  vCPUPrint(text,ap);
  va_end(ap);
}

void CPUPrintFlush(void)
{
   if( cpulogF ) {
      fflush(cpulogF);
   }
}

void CPUPut(char* string, ...)
{
  va_list ap;
  char llstring[1024];
  
  va_start(ap, string);
  SubstituteLLx(llstring, string, 1024);
  vfprintf(stderr, llstring, ap);
  va_end(ap);
  fprintf(stderr, "\r");
  fflush(stderr);
}

void lCPUPut(char* string, ...)
{
  va_list ap;
  
  va_start(ap, string);
  vCPUPrint(string, ap);
  va_end(ap);
}

/*
 * Debugging help
 */

void CPU_nop(void)
{
   /* nop */
}


void CPURestartLog(void)
{
   cpulogF = NULL;
   CPUPrint(" Restarting Log  PID=%i \n", getpid());
}


/*****************************************************************
 * DEBUGGING SUPPORT
 * Taken from Nachos' utility.cc
 *****************************************************************/
/*****************************************************************
 * Use Tcl to print more detail to the log... including process ID 
 ****************************************************************/
void 
LogEntry(char *symbol, int cpuNum, char *text,...)
{
    va_list ap;
    SimTime x=0;
    char cpuName[32];
    char *pid, *proc;

    sprintf(cpuName,"%d",cpuNum);    
    pid = Tcl_GetVar2(TCLInterp,"PID",cpuName,0);
    proc = Tcl_GetVar2(TCLInterp,"PROCESS",cpuName,0);
    if (!pid)  { pid = "-1";}
    if (!proc) { proc = "NONAME";}

    if (CPUVec.CycleCount) { 
       x = CPUVec.CycleCount(cpuNum);
    }
    CPUPrint("LOG %lld\t%-12s\tcpu=%i\t%s-%s\t ",
             (uint64)x,
             symbol,
             cpuNum,
             pid, proc);

    va_start(ap,text);
    vCPUPrint(text,ap);
    va_end(ap);
} 
    


/****************************************************************
 * DebugInit
 * Initialize so that only DEBUG messages with a flag in flagList 
 * will be printed. If the flag is "+", we enable all DEBUG messages.
 *****************************************************************/

static char *enableFlags = NULL; 

void
DebugInit(char *flagList)
{
    enableFlags = flagList;
}

/*****************************************************************
 * DebugIsEnabled
 * Return TRUE if DEBUG messages with "flag" are to be printed.
 ****************************************************************/
static bool
DebugIsEnabled(char flag)
{
   if (enableFlags != NULL) {
      return (strchr(enableFlags, flag) != 0) || (strchr(enableFlags, '+') != 0);
   } else {
      return FALSE;
   }
}


/*****************************************************************
 * Debug
 * Print a debug message, if flag is enabled.  Like printf,
 * only with an extra argument on the front.
 ****************************************************************/
void 
Debug(char flag, char *format, ...)
{
   if (DebugIsEnabled(flag)) {
      char llformat[1024];
      va_list ap;
      va_start(ap, format);

      SubstituteLLx(llformat,format,1024);

      /* Make this go to stderr also...  */
      vfprintf(stderr, llformat, ap);

      vCPUPrint(llformat, ap);
      fprintf(stderr, "\r");
      fflush(stderr);
      va_end(ap);

   }
}

/*****************************************************************
 * DebugDetail
 * Print a detailed debug message, if flag is enabled.  Like printf,
 * only with an extra argument on the front.
 ****************************************************************/
void
DebugDetail(char flag, char *symbol, int cpuNum, char *text,...)
{
   if (DebugIsEnabled(flag)) {
      va_list ap;
      SimTime x=0;
      char cpuName[32];
      char *pid, *proc;
    
      sprintf(cpuName,"%d",cpuNum);    
      pid = Tcl_GetVar2(TCLInterp,"PID",cpuName,0);
      proc = Tcl_GetVar2(TCLInterp,"PROCESS",cpuName,0);
      if (!pid)  { pid = "-1";}
      if (!proc) { proc = "NONAME";}
      
      if (CPUVec.CycleCount) { 
         x = CPUVec.CycleCount(cpuNum);
      }
      CPUPrint("LOG %lld\t%-12s\tcpu=%i\t%s-%s\t ",
               (uint64)x,
               symbol,
               cpuNum,
               pid, proc);
      
      va_start(ap,text);
      vCPUPrint(text,ap);
      va_end(ap);
   } 
}