Main Page | Modules | Class Hierarchy | Class List | File List | Class Members | File Members | Related Pages | Examples

archc.cpp

00001 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
00002 
00003 /*  ArchC Library for tools generated by the ArchC Pre-processor
00004     Copyright (C) 2002-2004  The ArchC Team
00005 
00006     This library is free software; you can redistribute it and/or
00007     modify it under the terms of the GNU Lesser General Public
00008     License as published by the Free Software Foundation; either
00009     version 2.1 of the License, or (at your option) any later version.
00010 
00011     This library is distributed in the hope that it will be useful,
00012     but WITHOUT ANY WARRANTY; without even the implied warranty of
00013     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00014     Lesser General Public License for more details.
00015 */
00016 /********************************************************/
00017 /* ArchC support functions                              */
00018 /* Author:  Sandro Rigo                                 */
00019 /*                                                      */
00020 /*                                                      */
00021 /* The ArchC Team                                       */
00022 /* Computer Systems Laboratory (LSC)                    */
00023 /* IC-UNICAMP                                           */
00024 /* http://www.lsc.ic.unicamp.br                         */
00025 /********************************************************/
00026  
00027 
00028 #include <sys/types.h>
00029 #include <sys/wait.h>
00030 #include <errno.h>
00031 #include <sys/msg.h>
00032 #include <unistd.h>
00033 #include <sys/ipc.h>
00034 #include <stdlib.h>
00035 #include <elf.h>
00036 #include <sys/stat.h>
00037 #include <fcntl.h>
00038 
00039 #include "ac_decoder.h"
00040 #include "ac_resources.H"
00041 
00042 #ifdef USE_GDB
00043 #include "ac_gdb.H"
00044 extern AC_GDB *gdbstub;
00045 #endif /* USE_GDB */
00046 
00047 #ifdef AC_VERIFY
00048 
00049 //Declaring co-verification message queue
00050 key_t key;
00051 int msqid;
00052 
00053 
00054 #endif
00055 
00056 int ac_stop_flag = 0;
00057 
00058 //Declaring trace variables
00059 ofstream trace_file;
00060 bool ac_do_trace;
00061 
00063 ac_dec_field *fields;
00064 ac_dec_format *formats;
00065 ac_dec_list *dec_list;
00066 ac_dec_instr *instructions;
00067 unsigned char buffer[AC_MAX_BUFFER];
00068 unsigned int quant, decode_pc;
00069 unsigned int ac_heap_ptr;
00070 unsigned dec_cache_size;
00071 ac_storage *IMem;
00072 
00073 //Command line arguments used inside ArchC Simulator
00074 int ac_argc;                       
00075 char **ac_argv;
00076 //Name of the file containing the application to be loaded.
00077 char *appfilename;
00078 
00079 int  ac_load_elf(char* filename, char* data_mem, unsigned int size);  //Loading an ELF binary application file.
00080 void ac_load_obj(char* filename);  //Loading a binary application file.
00081 void ac_load_dlx(char* filename);  //Loading a hex file generated by gcc-dlx
00082 
00083 extern "C" {
00084   int ExpandInstrBuffer( int index){
00085 
00086     int bytes_needed = index - quant +1;
00087     int read, wordsize,i;
00088     
00089     wordsize = (AC_WORDSIZE/8);       //computes the wordsize in bytes
00090     read = bytes_needed/ wordsize;
00091     
00092     if( bytes_needed% wordsize) 
00093       read++;
00094     
00095     for( i=0; i<read; i++)
00096       *((ac_word*)(buffer + quant + wordsize*i)) =  IMem->read( decode_pc +  quant + wordsize*i );
00097 
00098     quant += read;
00099 
00100     return quant;
00101 
00102   }
00103 }
00104 
00105 //Read model options before application
00106 void ac_init_opt( int ac, char* av[]){
00107 
00108   extern const char *project_name;
00109   extern const char *project_file;
00110   extern const char *archc_version;
00111   extern const char *archc_options;
00112 
00113   if(ac > 1){
00114                 
00115     if (!strncmp( av[1], "--help", 6)) {
00116       cerr << "This is a " << project_name << " architecture simulator generated by ArchC.\n";
00117       cerr << "For more information visit http://www.archc.org\n\n";
00118       cerr << "Usage: " << av[0] << " [options]\n\n";
00119       cerr << "Options:\n";
00120       cerr << "  --help                  Display this help message\n";
00121       cerr << "  --version               Display ArchC version and options used when built\n";
00122       cerr << "  --load=<hex_prog>       Load application in hex format\n";
00123       cerr << "  --load_obj=<elf_prog>   Load application in ELF format\n";
00124 #ifdef USE_GDB
00125       cerr << "  --gdb[=<port>]          Disable GDB support\n";
00126 #endif /* USE_GDB */
00127       exit(1);
00128     }
00129     
00130     if (!strncmp( av[1], "--version", 9)) {
00131       cout << project_name << " simulator generated by ArchC " << archc_version
00132            << " from " << project_file << " with options (" << archc_options << ")" << endl;
00133       exit(0);
00134     }
00135   }
00136 }
00137 
00138 //Initialize application
00139 void ac_init_app( int ac, char* av[]){
00140 
00141   int size;
00142   char *appname=0;
00143   extern int ac_argc;
00144   extern char** ac_argv;
00145 
00146   ac_argc = ac-1;   //Skiping program's name
00147   ac_argv = av;
00148   
00149   while(ac > 1){
00150     size = strlen(av[1]);
00151 
00152     //Checking if an application needs to be loaded
00153     if( (size>11) && (!strncmp( av[1], "--load_obj=", 11))){   //Loading a binary app
00154       appname = (char*)malloc(size - 10);
00155       strcpy(appname, av[1]+11);
00156       ac_argv[1] = appname;
00157       appfilename = (char*) malloc(sizeof(char)*(size - 6));
00158       strcpy(appfilename, appname);
00159       //ac_load_obj( appname );
00160     }
00161     else if( (size>7) && (!strncmp( av[1], "--load=", 7))){  //Loading hex file in the ArchC Format
00162       appname = (char*)malloc(size - 6);
00163       strcpy(appname, av[1]+7);
00164       ac_argv[1] = appname;
00165       appfilename = (char*) malloc(sizeof(char)*(size - 6));
00166       strcpy(appfilename, appname);
00167     }
00168     else if( (size>11) && (!strncmp( av[1], "--load_dlx=", 11))){ //Loading hex file produced by gcc-dlx
00169       appname = (char*)malloc(size - 10);
00170       strcpy(appname, av[1]+11);
00171       ac_argv[1] = appname;
00172       ac_load_dlx(appname);
00173     }
00174 #ifdef USE_GDB    
00175     if( (size>=5) && (!strncmp( av[1], "--gdb", 5))){ //Enable GDB support
00176       int port = 0;
00177       if ( size > 6 )
00178         { 
00179           port = atoi( av[1] + 6 );
00180           if ( ( port > 1024 ) && gdbstub )
00181             gdbstub->set_port( port );
00182         }
00183       if ( gdbstub ) 
00184         gdbstub->enable();
00185     }
00186 #endif /* USE_GDB */
00187     
00188     ac --;
00189     av ++;
00190   }
00191 
00192   if (!appname) {
00193     AC_ERROR("No application provided.");
00194     AC_ERROR("Use --load=<hex_prog> or --load_obj=<elf_prog> options to run applications.");
00195     AC_ERROR("Try --help for more options.");
00196     exit(1);
00197   }
00198   ac_argv++;
00199 
00200 }
00201 
00202 unsigned int convert_endian(unsigned int size, unsigned int num)
00203 {
00204   unsigned char *in = (unsigned char*) &num;
00205   unsigned int out = 0;
00206 
00207   if (! AC_MATCH_ENDIAN) {
00208     for(; size>0; size--) {
00209       out <<= 8;
00210       out |= in[0];
00211       in++;
00212     }
00213   }
00214   else {
00215     out = num;
00216   }
00217 
00218   return out;
00219 }
00220 
00221 //Loading binary application
00222 int ac_load_elf(char* filename, char* data_mem, unsigned int data_mem_size)
00223 {
00224   Elf32_Ehdr    ehdr;
00225   Elf32_Phdr    phdr;
00226   int           fd;
00227   unsigned int  i;
00228 
00229   //Open application
00230   if (!filename || ((fd = open(filename, 0)) == -1)) {
00231     AC_ERROR("Openning application file '" << filename << "': " << strerror(errno) << endl);
00232     exit(EXIT_FAILURE);
00233   }
00234 
00235   //Test if it's an ELF file
00236   if ((read(fd, &ehdr, sizeof(ehdr)) != sizeof(ehdr)) ||  // read header
00237       (strncmp((char *)ehdr.e_ident, ELFMAG, 4) != 0) ||          // test elf magic number
00238       0) {
00239     close(fd);
00240     return EXIT_FAILURE;
00241   }
00242 
00243   //It is an ELF file
00244   AC_SAY("Reading ELF application file: " << filename << endl);
00245 
00246   //Get program headers and load segments
00247   lseek(fd, convert_endian(4,ehdr.e_phoff), SEEK_SET);
00248   for (i=0; i<convert_endian(2,ehdr.e_phnum); i++) {
00249 
00250     if (read(fd, &phdr, sizeof(phdr)) != sizeof(phdr)) {
00251       AC_ERROR("reading ELF program header\n");
00252       close(fd);
00253       exit(EXIT_FAILURE);
00254     }
00255 
00256     if (convert_endian(4,phdr.p_type) == PT_LOAD) {
00257       Elf32_Word j;
00258       Elf32_Addr p_vaddr = convert_endian(4,phdr.p_vaddr);
00259       Elf32_Word p_memsz = convert_endian(4,phdr.p_memsz);
00260       Elf32_Word p_filesz = convert_endian(4,phdr.p_filesz);
00261       Elf32_Off  p_offset = convert_endian(4,phdr.p_offset);
00262 
00263       //Error if segment greater then memory
00264       if (data_mem_size < p_vaddr + p_memsz) {
00265         AC_ERROR("not enough memory in ArchC model to load application.\n");
00266         close(fd);
00267         exit(EXIT_FAILURE);
00268       }
00269 
00270       //Set heap to the end of the segment
00271       if (ac_heap_ptr < p_vaddr + p_memsz) ac_heap_ptr = p_vaddr + p_memsz;
00272 
00273       //Load and correct endian
00274       lseek(fd, p_offset, SEEK_SET);
00275       for (j=0; j < p_filesz; j+=sizeof(ac_fetch)) {
00276         int tmp;
00277         read(fd, &tmp, sizeof(ac_fetch));
00278         *(ac_fetch *) (data_mem + p_vaddr + j) = convert_endian(sizeof(ac_fetch), tmp);
00279       }
00280       memset(data_mem + p_vaddr + p_filesz, 0, p_memsz - p_filesz);
00281     }
00282 
00283     //next header/segment
00284     lseek(fd, convert_endian(4,ehdr.e_phoff) + convert_endian(2,ehdr.e_phentsize) * i, SEEK_SET);
00285   }
00286 
00287   //Close file
00288   close(fd);
00289 
00290   return EXIT_SUCCESS;
00291 }
00292 
00293 //Loading binary application
00294 void ac_load_obj( char* filename ){
00295 
00296   int child, status;
00297   char *ARCHC_PATH;
00298   char script[] = "/scripts/ac_load_obj.pl";
00299   char *argv[3]; 
00300   extern char* appfilename;
00301   extern unsigned int ac_heap_ptr;
00302   FILE* tempfile;
00303 
00304   ARCHC_PATH = getenv("ARCHC_PATH");
00305 
00306   if(!ARCHC_PATH){
00307     AC_ERROR("You should set the ARCHC_PATH environment variable.\n");
00308     exit(1);
00309   }
00310 
00311   argv[0] = (char*) malloc(strlen(ARCHC_PATH) + strlen(script) +1);
00312   sprintf(argv[0],"%s%s", ARCHC_PATH, script);
00313   argv[1] = filename;
00314   argv[2] = 0;
00315         
00316   if( !(child = fork()) )
00317     execve(argv[0], argv, NULL);
00318   else{
00319     waitpid(child,&status,0);
00320     if(!WIFEXITED(status))
00321       AC_ERROR("Could not process binary file.");
00322   }
00323         
00324   //Loading from the file generated by scripts
00325   appfilename = "loader.ac";
00326 
00327   //Setting heap pointer
00328   tempfile = fopen("loader.tmp","r");
00329   if( tempfile ){
00330     fscanf(tempfile, "%x", &ac_heap_ptr );
00331     fclose(tempfile);
00332 #ifndef AC_VERIFY
00333     remove("loader.tmp");
00334 #endif
00335   }
00336   else{ //The script could not open the input file
00337     AC_ERROR("Could not open temporary file generated by script: loader.tmp");
00338     AC_ERROR("Simulation aborted.");
00339     exit(1);
00340   }
00341 
00342   free(argv[0]);
00343 }
00344 
00345 //Loading hex file generated by gcc-dlx
00346 void ac_load_dlx( char* filename ){
00347 
00348   int child;
00349   char * argv[] = {"../scripts/ac_load_dlx.pl", filename, 0};
00350   extern char* appfilename;
00351 
00352   if( !(child = fork()) )
00353     execve(argv[0], argv, NULL);
00354   else
00355     waitpid(child,0,0);
00356 
00357   //Loading from the file generated by scripts
00358   appfilename = "loader.ac";
00359 }
00360 
00361 
00362 //Functions used to calculate the instr/s of the simulation
00363 
00364 #include <sys/times.h>
00365 
00366 struct tms ac_run_times;
00367 clock_t ac_run_start_time;
00368 
00369 void InitStat()
00370 {
00371   ac_run_start_time = times(&ac_run_times);
00372 }
00373 
00374 void PrintStat()
00375 {
00376   clock_t ac_run_real;
00377 
00378   //Print statistics
00379   fprintf(stderr, "ArchC: Simulation statistics\n");
00380 
00381   ac_run_real = times(&ac_run_times) - ac_run_start_time;
00382   fprintf(stderr, "    Times: %ld.%02ld user, %ld.%02ld system, %ld.%02ld real\n",
00383           ac_run_times.tms_utime / 100, ac_run_times.tms_utime % 100,
00384           ac_run_times.tms_stime / 100, ac_run_times.tms_stime % 100,
00385           ac_run_real / 100, ac_run_real % 100
00386           );
00387 
00388   fprintf(stderr, "    Number of instructions executed: %llu\n", ac_instr_counter);
00389 
00390   if (ac_run_times.tms_utime > 5) {
00391     double ac_mips = (ac_instr_counter * 100) / ac_run_times.tms_utime;
00392     fprintf(stderr, "    Simulation speed: %.2f K instr/s\n", ac_mips/1000);
00393   }
00394   else {
00395     fprintf(stderr, "    Simulation speed: (too fast to be precise)\n");
00396   }
00397 }
00398 
00399 
00400 //Signal handlers for interrupt and segmentation fault (set in ac_start() )
00401 #include <signal.h>
00402 typedef void (*sighandler_t)(int);
00403 void sigint_handler(int signal)
00404 {
00405   fprintf(stderr, "ArchC: INTERUPTED BY THE SIGNAL %d\n", signal);
00406   PrintStat();
00407   exit(EXIT_FAILURE);
00408 }
00409 void sigsegv_handler(int signal)
00410 {
00411   fprintf(stderr, "ArchC Error: Internal bug (segmentation fault). Sorry.\n");
00412   PrintStat();
00413   exit(EXIT_FAILURE);
00414 }
00415 void sigusr1_handler(int signal)
00416 {
00417   fprintf(stderr, "ArchC: Received signal %d. Printing statistics\n", signal);
00418   PrintStat();
00419   fprintf(stderr, "ArchC: -------------------- Continuing Simulation ------------------\n");
00420 }
00421 
00422 #ifdef USE_GDB
00423 void sigusr2_handler(int signal)
00424 {
00425   fprintf(stderr, "ArchC: Received signal %d. Starting GDB support\n", signal);
00426   gdbstub->enable();
00427   gdbstub->connect();
00428 }
00429 #endif /* USE_GDB */
00430 
00431 //Start simulation
00432 void ac_start(int argc, char *argv[])
00433 {
00434   cerr << "ArchC: -------------------- Starting Simulation --------------------" << endl;
00435 #ifdef USE_GDB
00436   if (gdbstub && !gdbstub->is_disabled()) 
00437     gdbstub->connect();
00438 #endif /* USE_GDB */
00439   InitStat();
00440   signal(SIGINT, sigint_handler);
00441   signal(SIGTERM, sigint_handler);
00442   signal(SIGSEGV, sigsegv_handler);
00443   signal(SIGUSR1, sigusr1_handler);
00444   signal(SIGUSR2, sigusr2_handler);
00445   sc_start(-1);
00446 }
00447 
00448 
00449 //Stop simulation (may receive exit status)
00450 void ac_stop(int status)
00451 {
00452   cerr << "ArchC: -------------------- Simulation Finished --------------------" << endl;
00453   ac_stop_flag = 1;
00454   dup2(2, 1); //any output to stdout is redirected for stderr (ex. SystemC stop message)
00455   sc_stop();
00456 }

Generated on Thu Jun 24 08:30:05 2004 for ArchC by doxygen 1.3.4