00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
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
00046
00047 #ifdef AC_VERIFY
00048
00049
00050 key_t key;
00051 int msqid;
00052
00053
00054 #endif
00055
00056 int ac_stop_flag = 0;
00057
00058
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
00074 int ac_argc;
00075 char **ac_argv;
00076
00077 char *appfilename;
00078
00079 int ac_load_elf(char* filename, char* data_mem, unsigned int size);
00080 void ac_load_obj(char* filename);
00081 void ac_load_dlx(char* filename);
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);
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
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
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
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;
00147 ac_argv = av;
00148
00149 while(ac > 1){
00150 size = strlen(av[1]);
00151
00152
00153 if( (size>11) && (!strncmp( av[1], "--load_obj=", 11))){
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
00160 }
00161 else if( (size>7) && (!strncmp( av[1], "--load=", 7))){
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))){
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))){
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
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*) #
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
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
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
00236 if ((read(fd, &ehdr, sizeof(ehdr)) != sizeof(ehdr)) ||
00237 (strncmp((char *)ehdr.e_ident, ELFMAG, 4) != 0) ||
00238 0) {
00239 close(fd);
00240 return EXIT_FAILURE;
00241 }
00242
00243
00244 AC_SAY("Reading ELF application file: " << filename << endl);
00245
00246
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
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
00271 if (ac_heap_ptr < p_vaddr + p_memsz) ac_heap_ptr = p_vaddr + p_memsz;
00272
00273
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
00284 lseek(fd, convert_endian(4,ehdr.e_phoff) + convert_endian(2,ehdr.e_phentsize) * i, SEEK_SET);
00285 }
00286
00287
00288 close(fd);
00289
00290 return EXIT_SUCCESS;
00291 }
00292
00293
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
00325 appfilename = "loader.ac";
00326
00327
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{
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
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
00358 appfilename = "loader.ac";
00359 }
00360
00361
00362
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
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
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
00430
00431
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
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
00450 void ac_stop(int status)
00451 {
00452 cerr << "ArchC: -------------------- Simulation Finished --------------------" << endl;
00453 ac_stop_flag = 1;
00454 dup2(2, 1);
00455 sc_stop();
00456 }