OpenCores
URL https://opencores.org/ocsvn/ion/ion/trunk

Subversion Repositories ion

[/] [ion/] [trunk/] [tools/] [slite/] [src/] [slite.c] - Blame information for rev 18

Go to most recent revision | Details | Compare with Previous | View Log

Line No. Rev Author Line
1 2 ja_rd
/*------------------------------------------------------------------------------
2
* slite.c -- MIPS-I simulator based on Steve Rhoad's "mlite"
3
*
4
* This is a slightly modified version of Steve Rhoad's "mlite" simulator, which
5
* is part of his PLASMA project (original date: 1/31/01).
6
*
7
*-------------------------------------------------------------------------------
8
* Usage:
9
*     slite <code file name> <data file name>
10
*
11
* The program will allocate a chunk of RAM (MEM_SIZE bytes) and map it to
12
* address 0x00000000 of the simulated CPU.
13
* Then it will read the 'code file' (as a big-endian plain binary) onto address
14
* 0x0 of the simulated CPU memory, and 'data file' on address 0x10000.
15
* Finally, will reset the CPU and enter the interactive debugger.
16
*
17
* (Note that the above is only necessary if the system does not have caches,
18
* because of the Harvard architecture. With caches in place, program loading
19
* would be antirely conventional).
20
*
21
* A simulation log file will be dumped to file "sw_sim_log.txt". This log can be
22
* used to compare with an equivalent log dumped by the hardware simulation, as
23
* a simple way to validate the hardware for a given program. See the project
24
* readme files for details.
25
*
26
*-------------------------------------------------------------------------------
27
* KNOWN BUGS:
28
*
29
* 1.- Load delay slot simulation does not work
30
*
31
* Some programs don't work when load delay slots are simulated (by setting
32
* "s->load_delay_slot = 1" in function main).
33
*
34
* The actual HW core does no longer use load delay slots but load interlocking
35
* so it may be better to just remove this feature.
36
*
37
*-------------------------------------------------------------------------------
38
* @date 2011-jan-16
39
*
40
*-------------------------------------------------------------------------------
41
* COPYRIGHT:    Software placed into the public domain by the author.
42
*               Software 'as is' without warranty.  Author liable for nothing.
43
*
44
* IMPORTANT: Assumes host is little endian.
45
*-----------------------------------------------------------------------------*/
46
 
47
#include <stdio.h>
48 11 ja_rd
#include <stdlib.h>
49
#include <stdint.h>
50 2 ja_rd
#include <string.h>
51
#include <ctype.h>
52
#include <assert.h>
53
 
54
/** Set to !=0 to disable file logging */
55
#define FILE_LOGGING_DISABLED (0)
56
/** Define to enable cache simulation (unimplemented) */
57
//#define ENABLE_CACHE
58
 
59
 
60
#define MEM_SIZE (1024*1024*2)
61
#define ntohs(A) ( ((A)>>8) | (((A)&0xff)<<8) )
62
#define htons(A) ntohs(A)
63
#define ntohl(A) ( ((A)>>24) | (((A)&0xff0000)>>8) | (((A)&0xff00)<<8) | ((A)<<24) )
64
#define htonl(A) ntohl(A)
65
 
66
/*---- OS-dependent support functions and definitions ------------------------*/
67
#ifndef WIN32
68
//Support for Linux
69
#define putch putchar
70
#include <termios.h>
71
#include <unistd.h>
72
 
73
void Sleep(unsigned int value)
74
{
75
   usleep(value * 1000);
76
}
77
 
78
int kbhit(void)
79
{
80
   struct termios oldt, newt;
81
   struct timeval tv;
82
   fd_set read_fd;
83
 
84
   tcgetattr(STDIN_FILENO, &oldt);
85
   newt = oldt;
86
   newt.c_lflag &= ~(ICANON | ECHO);
87
   tcsetattr(STDIN_FILENO, TCSANOW, &newt);
88
   tv.tv_sec=0;
89
   tv.tv_usec=0;
90
   FD_ZERO(&read_fd);
91
   FD_SET(0,&read_fd);
92
   if(select(1, &read_fd, NULL, NULL, &tv) == -1)
93
      return 0;
94
   //tcsetattr(STDIN_FILENO, TCSANOW, &oldt);
95
   if(FD_ISSET(0,&read_fd))
96
      return 1;
97
   return 0;
98
}
99
 
100
int getch(void)
101
{
102
   struct termios oldt, newt;
103
   int ch;
104
 
105
   tcgetattr(STDIN_FILENO, &oldt);
106
   newt = oldt;
107
   newt.c_lflag &= ~(ICANON | ECHO);
108
   tcsetattr(STDIN_FILENO, TCSANOW, &newt);
109
   ch = getchar();
110
   //tcsetattr(STDIN_FILENO, TCSANOW, &oldt);
111
   return ch;
112
}
113
#else
114
//Support for Windows
115
#include <conio.h>
116
extern void __stdcall Sleep(unsigned long value);
117
#endif
118
/*---- End of OS-dependent support functions and definitions -----------------*/
119
 
120
/*---- Hardware system parameters --------------------------------------------*/
121
 
122
/* Much of this is a remnant from Plasma's mlite and is  no longer used. */
123
/* FIXME Refactor HW system params */
124
 
125
 
126
#define UART_WRITE        0x20000000
127
#define UART_READ         0x20000000
128
#define IRQ_MASK          0x20000010
129
#define IRQ_STATUS        0x20000020
130
#define CONFIG_REG        0x20000070
131
#define MMU_PROCESS_ID    0x20000080
132
#define MMU_FAULT_ADDR    0x20000090
133
#define MMU_TLB           0x200000a0
134
 
135
#define IRQ_UART_READ_AVAILABLE  0x001
136
#define IRQ_UART_WRITE_AVAILABLE 0x002
137
#define IRQ_COUNTER18_NOT        0x004
138
#define IRQ_COUNTER18            0x008
139
#define IRQ_MMU                  0x200
140
 
141
#define MMU_ENTRIES 4
142
#define MMU_MASK (1024*4-1)
143 5 ja_rd
/*----------------------------------------------------------------------------*/
144 2 ja_rd
 
145 5 ja_rd
/* These are flags that will be used to notify the main cycle function of any
146
   failed assertions in its subfunctions. */
147
#define ASRT_UNALIGNED_READ         (1<<0)
148
#define ASRT_UNALIGNED_WRITE        (1<<1)
149
 
150
char *assertion_messages[2] = {
151
   "Unaligned read",
152
   "Unaligned write"
153
};
154
 
155
 
156 2 ja_rd
/** Length of debugging jump target queue */
157
#define TRACE_BUFFER_SIZE (32)
158
 
159
typedef struct {
160
   unsigned int buf[TRACE_BUFFER_SIZE];   /**< queue of last jump targets */
161
   unsigned int next;                     /**< internal queue head pointer */
162
   FILE *log;                             /**< text log file or NULL */
163
   int pr[32];                            /**< last value of register bank */
164
   int hi, lo, epc;                       /**< last value of internal regs */
165
} Trace;
166
 
167
typedef struct
168
{
169
   unsigned int virtualAddress;
170
   unsigned int physicalAddress;
171
} MmuEntry;
172
 
173
typedef struct {
174
   int load_delay_slot;
175
   int delay;
176 5 ja_rd
   unsigned delayed_reg;
177
   int delayed_data;
178
 
179
   unsigned failed_assertions;            /**< assertion bitmap */
180
   unsigned faulty_address;               /**< addr that failed assertion */
181
 
182 2 ja_rd
   int r[32];
183
   int opcode;
184
   int pc, pc_next, epc;
185
   unsigned int hi;
186
   unsigned int lo;
187
   int status;
188
   int userMode;
189
   int processId;
190 5 ja_rd
   int exceptionId;        /**< DEPRECATED, to be removed */
191 2 ja_rd
   int faultAddr;
192
   int irqStatus;
193
   int skip;
194
   Trace t;
195
   unsigned char *mem;
196
   int wakeup;
197
   int big_endian;
198
   MmuEntry mmuEntry[MMU_ENTRIES];
199
} State;
200
 
201
static char *opcode_string[]={
202
   "SPECIAL","REGIMM","J","JAL","BEQ","BNE","BLEZ","BGTZ",
203
   "ADDI","ADDIU","SLTI","SLTIU","ANDI","ORI","XORI","LUI",
204
   "COP0","COP1","COP2","COP3","BEQL","BNEL","BLEZL","BGTZL",
205
   "?","?","?","?","?","?","?","?",
206
   "LB","LH","LWL","LW","LBU","LHU","LWR","?",
207
   "SB","SH","SWL","SW","?","?","SWR","CACHE",
208
   "LL","LWC1","LWC2","LWC3","?","LDC1","LDC2","LDC3"
209
   "SC","SWC1","SWC2","SWC3","?","SDC1","SDC2","SDC3"
210
};
211
 
212
static char *special_string[]={
213
   "SLL","?","SRL","SRA","SLLV","?","SRLV","SRAV",
214
   "JR","JALR","MOVZ","MOVN","SYSCALL","BREAK","?","SYNC",
215
   "MFHI","MTHI","MFLO","MTLO","?","?","?","?",
216
   "MULT","MULTU","DIV","DIVU","?","?","?","?",
217
   "ADD","ADDU","SUB","SUBU","AND","OR","XOR","NOR",
218
   "?","?","SLT","SLTU","?","DADDU","?","?",
219
   "TGE","TGEU","TLT","TLTU","TEQ","?","TNE","?",
220
   "?","?","?","?","?","?","?","?"
221
};
222
 
223
static char *regimm_string[]={
224
   "BLTZ","BGEZ","BLTZL","BGEZL","?","?","?","?",
225
   "TGEI","TGEIU","TLTI","TLTIU","TEQI","?","TNEI","?",
226
   "BLTZAL","BEQZAL","BLTZALL","BGEZALL","?","?","?","?",
227
   "?","?","?","?","?","?","?","?"
228
};
229
 
230
static unsigned int HWMemory[8];
231
 
232
/*---- Local function prototypes ---------------------------------------------*/
233
 
234
/* Debug and logging */
235
void init_trace_buffer(State *s, const char *log_file_name);
236
void close_trace_buffer(State *s);
237
void dump_trace_buffer(State *s);
238
void log_cycle(State *s);
239
void log_read(State *s, int full_address, int word_value, int size, int log);
240 5 ja_rd
void log_failed_assertions(State *s);
241 2 ja_rd
 
242
/* Hardware simulation */
243
int mem_read(State *s, int size, unsigned int address, int log);
244
void mem_write(State *s, int size, int unsigned address, unsigned value);
245
void start_load(State *s, int rt, int data);
246
 
247 16 ja_rd
 
248 2 ja_rd
/*---- Local functions -------------------------------------------------------*/
249
 
250
/** Log to file a memory read operation (not including target reg change) */
251
void log_read(State *s, int full_address, int word_value, int size, int log){
252
   if(s->t.log!=NULL && log!=0){
253
      if(size==4){ size=0x04; }
254
      else if(size==2){ size=0x02; }
255
      else { size=0x01; }
256
      fprintf(s->t.log, "(%08X) [%08X] <**>=%08X RD\n",
257
              s->pc, full_address, /*size,*/ word_value);
258
   }
259
}
260
 
261
/** Read memory, optionally logging */
262
int mem_read(State *s, int size, unsigned int address, int log)
263
{
264
   unsigned int value=0, word_value=0, ptr;
265
   unsigned int full_address = address;
266
 
267
   s->irqStatus |= IRQ_UART_WRITE_AVAILABLE;
268
   switch(address)
269
   {
270
      case UART_READ:
271
         word_value = 0x00000001;
272
         log_read(s, full_address, word_value, size, log);
273
         return word_value;
274
         /* FIXME Take input from text file */
275
         /*
276
         if(kbhit()){
277
            HWMemory[0] = getch();
278
         }
279
         s->irqStatus &= ~IRQ_UART_READ_AVAILABLE; //clear bit
280
         return HWMemory[0];
281
         */
282
      case IRQ_MASK:
283
         return HWMemory[1];
284
      case IRQ_MASK + 4:
285
         Sleep(10);
286
         return 0;
287
      case IRQ_STATUS:
288
         /*if(kbhit())
289
            s->irqStatus |= IRQ_UART_READ_AVAILABLE;
290
         return s->irqStatus;
291
         */
292
         /* FIXME Optionally simulate UART TX delay */
293
         word_value = 0x00000003; /* Ready to TX and RX */
294
         log_read(s, full_address, word_value, size, log);
295
         return word_value;
296
      case MMU_PROCESS_ID:
297
         return s->processId;
298
      case MMU_FAULT_ADDR:
299
         return s->faultAddr;
300
   }
301
 
302
   ptr = (unsigned int)s->mem + (address % MEM_SIZE);
303
 
304
   if(0x10000000 <= address && address < 0x10000000 + 1024*1024)
305
      ptr += 1024*1024;
306
 
307
   word_value = *(int*)(ptr&0xfffffffc);
308
   if(s->big_endian)
309
            word_value = ntohl(word_value);
310
   switch(size)
311
   {
312
      case 4:
313
         if(address & 3){
314
            printf("Unaligned access PC=0x%x address=0x%x\n",
315
                   (int)s->pc, (int)address);
316 5 ja_rd
         }
317
         /* We don't want the program to just quit, we want to log the fault */
318
         /* assert((address & 3) == 0); */
319
         if((address & 3) != 0){
320
            s->failed_assertions |= ASRT_UNALIGNED_READ;
321
            s->faulty_address = address;
322
            address = address & 0xfffffffc;
323 2 ja_rd
         }
324
         value = *(int*)ptr;
325
         if(s->big_endian)
326
            value = ntohl(value);
327
         break;
328 5 ja_rd
      case 2:
329
         /* We don't want the program to just quit, we want to log the fault */
330
         /* assert((address & 1) == 0); */
331
         if((address & 1) != 0){
332
            s->failed_assertions |= ASRT_UNALIGNED_READ;
333
            s->faulty_address = address;
334
            address = address & 0xfffffffe;
335
         }
336 2 ja_rd
         value = *(unsigned short*)ptr;
337
         if(s->big_endian)
338
            value = ntohs((unsigned short)value);
339
         break;
340
      case 1:
341
         value = *(unsigned char*)ptr;
342
         break;
343
      default:
344
         printf("ERROR");
345
   }
346
 
347
   log_read(s, full_address, word_value, size, log);
348
   return(value);
349
}
350
 
351
/** Write memory */
352
void mem_write(State *s, int size, unsigned address, unsigned value)
353
{
354
   unsigned int ptr, mask, dvalue, b0, b1, b2, b3;
355
 
356
   if(s->t.log!=NULL){
357
      b0 = value & 0x000000ff;
358
      b1 = value & 0x0000ff00;
359
      b2 = value & 0x00ff0000;
360
      b3 = value & 0xff000000;
361
 
362
      switch(size){
363
         case 4:  mask = 0x0f;
364
                  dvalue = value;
365
                  break;
366
 
367
         case 2:  if((address&0x2)==0){
368
                     mask = 0xc;
369
                     dvalue = b1<<16 | b0<<16;
370
                  }
371
                  else{
372
                     mask = 0x3;
373
                     dvalue = b1 | b0;
374
                  }
375
                  break;
376
         case 1:  switch(address%4){
377
                  case 0 : mask = 0x8;
378
                           dvalue = b0<<24;
379
                           break;
380
                  case 1 : mask = 0x4;
381
                           dvalue = b0<<16;
382
                           break;
383
                  case 2 : mask = 0x2;
384
                           dvalue = b0<<8;
385
                           break;
386
                  case 3 : mask = 0x1;
387
                           dvalue = b0;
388
                           break;
389
                  }
390
                  break;
391
         default:
392
            printf("BUG: mem write size invalid (%08x)\n", s->pc);
393
            exit(2);
394
 
395
      }
396
      fprintf(s->t.log, "(%08X) [%08X] |%02X|=%08X WR\n", s->pc, address, mask, dvalue);
397
   }
398
 
399
   switch(address)
400
   {
401
      case UART_WRITE:
402
         putch(value);
403
         fflush(stdout);
404
         return;
405
      case IRQ_MASK:
406
         HWMemory[1] = value;
407
         return;
408
      case IRQ_STATUS:
409
         s->irqStatus = value;
410
         return;
411
      case CONFIG_REG:
412
         return;
413
      case MMU_PROCESS_ID:
414
         //printf("processId=%d\n", value);
415
         s->processId = value;
416
         return;
417
   }
418
 
419
   if(MMU_TLB <= address && address <= MMU_TLB+MMU_ENTRIES * 8)
420
   {
421
      //printf("TLB 0x%x 0x%x\n", address - MMU_TLB, value);
422
      ptr = (unsigned int)s->mmuEntry + address - MMU_TLB;
423
      *(int*)ptr = value;
424
      s->irqStatus &= ~IRQ_MMU;
425
      return;
426
   }
427
 
428
   ptr = (unsigned int)s->mem + (address % MEM_SIZE);
429
 
430
   if(0x10000000 <= address && address < 0x10000000 + 1024*1024)
431
      ptr += 1024*1024;
432
 
433
   switch(size)
434
   {
435 5 ja_rd
      case 4:
436
         /* We don't want the program to just quit, we want to log the fault */
437
         /* assert((address & 3) == 0); */
438
         if((address & 3) != 0){
439
            s->failed_assertions |= ASRT_UNALIGNED_WRITE;
440
            s->faulty_address = address;
441
            address = address & (~0x03);
442
         }
443 2 ja_rd
         if(s->big_endian)
444
            value = htonl(value);
445
         *(int*)ptr = value;
446
         break;
447 5 ja_rd
      case 2:
448
         /* We don't want the program to just quit, we want to log the fault */
449
         /* assert((address & 1) == 0); */
450
         if((address & 1) != 0){
451
            s->failed_assertions |= ASRT_UNALIGNED_WRITE;
452
            s->faulty_address = address;
453
            address = address & (~0x01);
454
         }
455 2 ja_rd
         if(s->big_endian)
456
            value = htons((unsigned short)value);
457
         *(short*)ptr = (unsigned short)value;
458
         break;
459
      case 1:
460
         *(char*)ptr = (unsigned char)value;
461
         break;
462
      default:
463
         printf("ERROR");
464
   }
465
}
466
 
467
/*---- Optional MMU and cache implementation ---------------------------------*/
468
 
469
/*
470
   The actual core does not have a cache so all of the original Plasma mlite.c
471
   code for cache simulation has been removed.
472
*/
473
 
474
#ifdef ENABLE_CACHE
475
#error Cache simulation missing!
476
#else
477
static void cache_init(void) {}
478
#endif
479
/*---- End optional cache implementation -------------------------------------*/
480
 
481
 
482
/** Simulates MIPS-I multiplier unsigned behavior*/
483
void mult_big(unsigned int a,
484
              unsigned int b,
485
              unsigned int *hi,
486
              unsigned int *lo)
487
{
488
   unsigned int ahi, alo, bhi, blo;
489
   unsigned int c0, c1, c2;
490
   unsigned int c1_a, c1_b;
491
 
492
   ahi = a >> 16;
493
   alo = a & 0xffff;
494
   bhi = b >> 16;
495
   blo = b & 0xffff;
496
 
497
   c0 = alo * blo;
498
   c1_a = ahi * blo;
499
   c1_b = alo * bhi;
500
   c2 = ahi * bhi;
501
 
502
   c2 += (c1_a >> 16) + (c1_b >> 16);
503
   c1 = (c1_a & 0xffff) + (c1_b & 0xffff) + (c0 >> 16);
504
   c2 += (c1 >> 16);
505
   c0 = (c1 << 16) + (c0 & 0xffff);
506
   *hi = c2;
507
   *lo = c0;
508
}
509
 
510
/** Simulates MIPS-I multiplier signed behavior*/
511
void mult_big_signed(int a,
512
                     int b,
513
                     unsigned int *hi,
514
                     unsigned int *lo)
515 11 ja_rd
{
516
   int64_t xa, xb, xr, temp;
517
   int32_t rh, rl;
518
 
519
   xa = a;
520
   xb = b;
521
   xr = xa * xb;
522
 
523
   temp = (xr >> 32) & 0xffffffff;
524
   rh = temp;
525
   temp = (xr >> 0) & 0xffffffff;
526
   rl = temp;
527
 
528
   *hi = rh;
529
   *lo = rl;
530 2 ja_rd
}
531
 
532
/** Load data from memory (used to simulate load delay slots) */
533
void start_load(State *s, int rt, int data){
534
   if(s->load_delay_slot){
535
      s->delayed_reg = rt;
536
      s->delay = 1;
537
      s->delayed_data = data;
538
   }
539
   else{
540
      /* load delay slot not simulated */
541
      s->r[rt] = data;
542
   }
543
}
544
 
545
/** Execute one cycle of the CPU (including any interlock stall cycles) */
546
void cycle(State *s, int show_mode)
547
{
548
   unsigned int opcode;
549
   unsigned int op, rs, rt, rd, re, func, imm, target;
550
   int imm_sex;
551
   int imm_shift, branch=0, lbranch=2, skip2=0;
552
   int *r=s->r;
553
   unsigned int *u=(unsigned int*)s->r;
554
   unsigned int ptr, epc, rSave;
555
 
556
   if(!show_mode){
557
      log_cycle(s);
558
   }
559
 
560
   opcode = mem_read(s, 4, s->pc, 0);
561
   op = (opcode >> 26) & 0x3f;
562
   rs = (opcode >> 21) & 0x1f;
563
   rt = (opcode >> 16) & 0x1f;
564
   rd = (opcode >> 11) & 0x1f;
565
   re = (opcode >> 6) & 0x1f;
566
   func = opcode & 0x3f;
567
   imm = opcode & 0xffff;
568
   imm_sex = (imm&0x8000)? 0xffff0000 | imm : imm;
569
   imm_shift = (((int)(short)imm) << 2) - 4;
570
   target = (opcode << 6) >> 4;
571
   ptr = (short)imm + r[rs];
572
   r[0] = 0;
573
   if(show_mode)
574
   {
575
      printf("%8.8x %8.8x ", s->pc, opcode);
576
      if(op == 0)
577
         printf("%8s ", special_string[func]);
578
      else if(op == 1)
579
         printf("%8s ", regimm_string[rt]);
580
      else
581
         printf("%8s ", opcode_string[op]);
582
      printf("$%2.2d $%2.2d $%2.2d $%2.2d ", rs, rt, rd, re);
583
      printf("%4.4x", imm);
584
      if(show_mode == 1)
585
         printf(" r[%2.2d]=%8.8x r[%2.2d]=%8.8x", rs, r[rs], rt, r[rt]);
586
      printf("\n");
587
   }
588
   if(show_mode > 5)
589 7 ja_rd
      return;
590
   /* epc will point to the victim instruction, i.e. THIS instruction */
591
   epc = s->pc;
592
   if(s->pc_next != s->pc + 4){
593
      /* FIXME traps in delay slots not supported yet */
594
      //epc = epc - 4;  /* trap in branch delay slot */
595
   }
596 2 ja_rd
 
597
   s->pc = s->pc_next;
598
   s->pc_next = s->pc_next + 4;
599
   if(s->skip)
600
   {
601
      s->skip = 0;
602
      return;
603
   }
604
   rSave = r[rt];
605
   switch(op)
606
   {
607
      case 0x00:/*SPECIAL*/
608
         switch(func)
609
         {
610
            case 0x00:/*SLL*/  r[rd]=r[rt]<<re;          break;
611
            case 0x02:/*SRL*/  r[rd]=u[rt]>>re;          break;
612
            case 0x03:/*SRA*/  r[rd]=r[rt]>>re;          break;
613
            case 0x04:/*SLLV*/ r[rd]=r[rt]<<r[rs];       break;
614
            case 0x06:/*SRLV*/ r[rd]=u[rt]>>r[rs];       break;
615
            case 0x07:/*SRAV*/ r[rd]=r[rt]>>r[rs];       break;
616
            case 0x08:/*JR*/   s->pc_next=r[rs];         break;
617
            case 0x09:/*JALR*/ r[rd]=s->pc_next; s->pc_next=r[rs]; break;
618
            case 0x0a:/*MOVZ*/ if(!r[rt]) r[rd]=r[rs];   break;  /*IV*/
619
            case 0x0b:/*MOVN*/ if(r[rt]) r[rd]=r[rs];    break;  /*IV*/
620
            case 0x0c:/*SYSCALL*/ /* epc|=1; WHY? */
621
                                  s->exceptionId=1; break;
622
            case 0x0d:/*BREAK*/   /* epc|=1; WHY? */
623
                                  s->exceptionId=1; break;
624
            case 0x0f:/*SYNC*/ s->wakeup=1;              break;
625
            case 0x10:/*MFHI*/ r[rd]=s->hi;              break;
626
            case 0x11:/*FTHI*/ s->hi=r[rs];              break;
627
            case 0x12:/*MFLO*/ r[rd]=s->lo;              break;
628
            case 0x13:/*MTLO*/ s->lo=r[rs];              break;
629
            case 0x18:/*MULT*/ mult_big_signed(r[rs],r[rt],&s->hi,&s->lo); break;
630
            case 0x19:/*MULTU*/ mult_big(r[rs],r[rt],&s->hi,&s->lo); break;
631
            case 0x1a:/*DIV*/  s->lo=r[rs]/r[rt]; s->hi=r[rs]%r[rt]; break;
632
            case 0x1b:/*DIVU*/ s->lo=u[rs]/u[rt]; s->hi=u[rs]%u[rt]; break;
633
            case 0x20:/*ADD*/  r[rd]=r[rs]+r[rt];        break;
634
            case 0x21:/*ADDU*/ r[rd]=r[rs]+r[rt];        break;
635
            case 0x22:/*SUB*/  r[rd]=r[rs]-r[rt];        break;
636
            case 0x23:/*SUBU*/ r[rd]=r[rs]-r[rt];        break;
637
            case 0x24:/*AND*/  r[rd]=r[rs]&r[rt];        break;
638
            case 0x25:/*OR*/   r[rd]=r[rs]|r[rt];        break;
639
            case 0x26:/*XOR*/  r[rd]=r[rs]^r[rt];        break;
640
            case 0x27:/*NOR*/  r[rd]=~(r[rs]|r[rt]);     break;
641
            case 0x2a:/*SLT*/  r[rd]=r[rs]<r[rt];        break;
642
            case 0x2b:/*SLTU*/ r[rd]=u[rs]<u[rt];        break;
643
            case 0x2d:/*DADDU*/r[rd]=r[rs]+u[rt];        break;
644
            case 0x31:/*TGEU*/ break;
645
            case 0x32:/*TLT*/  break;
646
            case 0x33:/*TLTU*/ break;
647
            case 0x34:/*TEQ*/  break;
648
            case 0x36:/*TNE*/  break;
649
            default: printf("ERROR0(*0x%x~0x%x)\n", s->pc, opcode);
650
               s->wakeup=1;
651
         }
652
         break;
653
      case 0x01:/*REGIMM*/
654
         switch(rt) {
655
            case 0x10:/*BLTZAL*/ r[31]=s->pc_next;
656
            case 0x00:/*BLTZ*/   branch=r[rs]<0;    break;
657
            case 0x11:/*BGEZAL*/ r[31]=s->pc_next;
658
            case 0x01:/*BGEZ*/   branch=r[rs]>=0;   break;
659
            case 0x12:/*BLTZALL*/r[31]=s->pc_next;
660
            case 0x02:/*BLTZL*/  lbranch=r[rs]<0;   break;
661
            case 0x13:/*BGEZALL*/r[31]=s->pc_next;
662
            case 0x03:/*BGEZL*/  lbranch=r[rs]>=0;  break;
663
            default: printf("ERROR1\n"); s->wakeup=1;
664
          }
665
         break;
666
      case 0x03:/*JAL*/    r[31]=s->pc_next;
667
      case 0x02:/*J*/      s->pc_next=(s->pc&0xf0000000)|target; break;
668
      case 0x04:/*BEQ*/    branch=r[rs]==r[rt];     break;
669
      case 0x05:/*BNE*/    branch=r[rs]!=r[rt];     break;
670
      case 0x06:/*BLEZ*/   branch=r[rs]<=0;         break;
671
      case 0x07:/*BGTZ*/   branch=r[rs]>0;          break;
672
      case 0x08:/*ADDI*/   r[rt]=r[rs]+(short)imm;  break;
673
      case 0x09:/*ADDIU*/  u[rt]=u[rs]+(short)imm;  break;
674
      case 0x0a:/*SLTI*/   r[rt]=r[rs]<(short)imm;  break;
675
      case 0x0b:/*SLTIU*/  u[rt]=u[rs]<(unsigned int)(short)imm; break;
676
      case 0x0c:/*ANDI*/   r[rt]=r[rs]&imm;         break;
677
      case 0x0d:/*ORI*/    r[rt]=r[rs]|imm;         break;
678
      case 0x0e:/*XORI*/   r[rt]=r[rs]^imm;         break;
679
      case 0x0f:/*LUI*/    r[rt]=(imm<<16);         break;
680
      case 0x10:/*COP0*/
681
         if((opcode & (1<<23)) == 0)  //move from CP0
682
         {
683
            if(rd == 12)
684
               r[rt]=s->status;
685
            else
686
               r[rt]=s->epc;
687
         }
688
         else                         //move to CP0
689
         {
690
            s->status=r[rt]&1;
691
            if(s->processId && (r[rt]&2))
692
            {
693
               s->userMode|=r[rt]&2;
694
               //printf("CpuStatus=%d %d %d\n", r[rt], s->status, s->userMode);
695
               //s->wakeup = 1;
696
               //printf("pc=0x%x\n", epc);
697
            }
698
         }
699
         break;
700
//      case 0x11:/*COP1*/ break;
701
//      case 0x12:/*COP2*/ break;
702
//      case 0x13:/*COP3*/ break;
703
      case 0x14:/*BEQL*/   lbranch=r[rs]==r[rt];    break;
704
      case 0x15:/*BNEL*/   lbranch=r[rs]!=r[rt];    break;
705
      case 0x16:/*BLEZL*/  lbranch=r[rs]<=0;        break;
706
      case 0x17:/*BGTZL*/  lbranch=r[rs]>0;         break;
707
//      case 0x1c:/*MAD*/  break;   /*IV*/
708
      case 0x20:/*LB*/     //r[rt]=(signed char)mem_read(s,1,ptr,1);  break;
709
                           start_load(s, rt,(signed char)mem_read(s,1,ptr,1));
710
                           break;
711
 
712
      case 0x21:/*LH*/     //r[rt]=(signed short)mem_read(s,2,ptr,1); break;
713
                           start_load(s, rt, (signed short)mem_read(s,2,ptr,1));
714
                           break;
715
      case 0x22:/*LWL*/    //target=8*(ptr&3);
716
                           //r[rt]=(r[rt]&~(0xffffffff<<target))|
717
                           //      (mem_read(s,4,ptr&~3)<<target); break;
718
                           break;
719
      case 0x23:/*LW*/     //r[rt]=mem_read(s,4,ptr,1);   break;
720
                           start_load(s, rt, mem_read(s,4,ptr,1));
721
                           break;
722
      case 0x24:/*LBU*/    //r[rt]=(unsigned char)mem_read(s,1,ptr,1); break;
723
                           start_load(s, rt, (unsigned char)mem_read(s,1,ptr,1));
724
                           break;
725
      case 0x25:/*LHU*/    //r[rt]= (unsigned short)mem_read(s,2,ptr,1);
726
                           start_load(s, rt, (unsigned short)mem_read(s,2,ptr,1));
727
                           break;
728
      case 0x26:/*LWR*/
729
                           //target=32-8*(ptr&3);
730
                           //r[rt]=(r[rt]&~((unsigned int)0xffffffff>>target))|
731
                           //((unsigned int)mem_read(s,4,ptr&~3)>>target);
732
                           break;
733
      case 0x28:/*SB*/     mem_write(s,1,ptr,r[rt]);  break;
734
      case 0x29:/*SH*/     mem_write(s,2,ptr,r[rt]);  break;
735
      case 0x2a:/*SWL*/
736
                           //mem_write(s,1,ptr,r[rt]>>24);
737
                           //mem_write(s,1,ptr+1,r[rt]>>16);
738
                           //mem_write(s,1,ptr+2,r[rt]>>8);
739
                           //mem_write(s,1,ptr+3,r[rt]); break;
740
      case 0x2b:/*SW*/     mem_write(s,4,ptr,r[rt]);  break;
741
      case 0x2e:/*SWR*/    break; //fixme
742
      case 0x2f:/*CACHE*/  break;
743
      case 0x30:/*LL*/     //r[rt]=mem_read(s,4,ptr);   break;
744
                           start_load(s, rt, mem_read(s,4,ptr,1));
745
                           break;
746
 
747
//      case 0x31:/*LWC1*/ break;
748
//      case 0x32:/*LWC2*/ break;
749
//      case 0x33:/*LWC3*/ break;
750
//      case 0x35:/*LDC1*/ break;
751
//      case 0x36:/*LDC2*/ break;
752
//      case 0x37:/*LDC3*/ break;
753
//      case 0x38:/*SC*/     *(int*)ptr=r[rt]; r[rt]=1; break;
754
      case 0x38:/*SC*/     mem_write(s,4,ptr,r[rt]); r[rt]=1; break;
755
//      case 0x39:/*SWC1*/ break;
756
//      case 0x3a:/*SWC2*/ break;
757
//      case 0x3b:/*SWC3*/ break;
758
//      case 0x3d:/*SDC1*/ break;
759
//      case 0x3e:/*SDC2*/ break;
760
//      case 0x3f:/*SDC3*/ break;
761
      default: printf("ERROR2 address=0x%x opcode=0x%x\n", s->pc, opcode);
762
         s->wakeup=1;
763
   }
764
   s->pc_next += (branch || lbranch == 1) ? imm_shift : 0;
765
   s->pc_next &= ~3;
766
   s->skip = (lbranch == 0) | skip2;
767
 
768 5 ja_rd
   /* If there was trouble, log it */
769
   if(s->failed_assertions!=0){
770
      log_failed_assertions(s);
771
      s->failed_assertions=0;
772
   }
773
 
774
 
775 2 ja_rd
   /* if there's a delayed load pending, do it now: load reg with memory data */
776
   if(s->load_delay_slot){
777
      /*--- simulate real core's load interlock ---*/
778
      if(s->delay<=0){
779
         if(s->delayed_reg>0){
780
            s->r[s->delayed_reg] = s->delayed_data;
781
         }
782
         s->delayed_reg = 0;
783
      }
784
      else{
785
         s->delay = s->delay - 1;
786
      }
787
   }
788
   else{
789
      /*--- delay slot or interlocking not simulated ---*/
790
      /*
791
      if(s->delay){
792
         r[s->delayed_reg] = s->delayed_data;
793
         s->delay=0;
794
      }
795
      */
796
   }
797
 
798 7 ja_rd
   /* Handle exceptions */
799 2 ja_rd
   if(s->exceptionId)
800
   {
801
      r[rt] = rSave;
802
      s->epc = epc;
803
      s->pc_next = 0x3c;
804
      s->skip = 1;
805
      s->exceptionId = 0;
806
      s->userMode = 0;
807
      //s->wakeup = 1;
808
      return;
809
   }
810
}
811
 
812
/** Dump CPU state to console */
813
void show_state(State *s)
814
{
815
   int i,j;
816 16 ja_rd
   printf("pid=%d userMode=%d, epc=0x%x\n", s->processId, s->userMode, s->epc);
817
   printf("hi=0x%08x lo=0x%08x\n", s->hi, s->lo);
818 2 ja_rd
   for(i = 0; i < 4; ++i)
819
   {
820
      printf("%2.2d ", i * 8);
821
      for(j = 0; j < 8; ++j)
822
      {
823
         printf("%8.8x ", s->r[i*8+j]);
824
      }
825
      printf("\n");
826
   }
827
   //printf("%8.8lx %8.8lx %8.8lx %8.8lx\n", s->pc, s->pc_next, s->hi, s->lo);
828
   j = s->pc;
829
   for(i = -4; i <= 8; ++i)
830
   {
831
      printf("%c", i==0 ? '*' : ' ');
832
      s->pc = j + i * 4;
833
      cycle(s, 10);
834
   }
835
   s->pc = j;
836
}
837
 
838
/** Show debug monitor prompt and execute user command */
839
void do_debug(State *s)
840
{
841
   int ch;
842
   int i, j=0, watch=0, addr;
843
   s->pc_next = s->pc + 4;
844
   s->skip = 0;
845
   s->delayed_reg = 0;
846
   s->wakeup = 0;
847
   show_state(s);
848
   ch = ' ';
849
   for(;;)
850
   {
851
      if(ch != 'n')
852
      {
853
         if(watch)
854
            printf("0x%8.8x=0x%8.8x\n", watch, mem_read(s, 4, watch,0));
855
         printf("1=Debug 2=Trace 3=Step 4=BreakPt 5=Go 6=Memory ");
856
         printf("7=Watch 8=Jump 9=Quit A=dump > ");
857
      }
858
      ch = getch();
859
      if(ch != 'n')
860
         printf("\n");
861
      switch(ch)
862
      {
863
      case 'a': case 'A':
864
         dump_trace_buffer(s); break;
865
      case '1': case 'd': case ' ':
866
         cycle(s, 0); show_state(s); break;
867
      case 'n':
868
         cycle(s, 1); break;
869
      case '2': case 't':
870
         cycle(s, 0); printf("*"); cycle(s, 10); break;
871
      case '3': case 's':
872
         printf("Count> ");
873
         scanf("%d", &j);
874
         for(i = 0; i < j; ++i)
875
            cycle(s, 1);
876
         show_state(s);
877
         break;
878
      case '4': case 'b':
879
         printf("Line> ");
880
         scanf("%x", &j);
881
         printf("break point=0x%x\n", j);
882
         break;
883
      case '5': case 'g':
884
         s->wakeup = 0;
885
         cycle(s, 0);
886
         while(s->wakeup == 0)
887
         {
888
            if(s->pc == j){
889
               printf("\n\nStop: pc = 0x%08x\n\n", j);
890
               break;
891
            }
892
            cycle(s, 0);
893
         }
894
         show_state(s);
895
         break;
896
      case 'G':
897
         s->wakeup = 0;
898
         cycle(s, 1);
899
         while(s->wakeup == 0)
900
         {
901
            if(s->pc == j)
902
               break;
903
            cycle(s, 1);
904
         }
905
         show_state(s);
906
         break;
907
      case '6': case 'm':
908
         printf("Memory> ");
909
         scanf("%x", &j);
910
         for(i = 0; i < 8; ++i)
911
         {
912
            printf("%8.8x ", mem_read(s, 4, j+i*4, 0));
913
         }
914
         printf("\n");
915
         break;
916
      case '7': case 'w':
917
         printf("Watch> ");
918
         scanf("%x", &watch);
919
         break;
920
      case '8': case 'j':
921
         printf("Jump> ");
922
         scanf("%x", &addr);
923
         s->pc = addr;
924
         s->pc_next = addr + 4;
925
         show_state(s);
926
         break;
927
      case '9': case 'q':
928
         return;
929
      }
930
   }
931
}
932
 
933
/** Read binary code and data files */
934
int read_program(State *s, char *code_name, char *data_name){
935
   FILE *in;
936
   int bytes, i;
937
   unsigned char *buffer;
938
 
939
   /* Read code file (.text + .reginfo + .rodata) */
940
   in = fopen(code_name, "rb");
941
   if(in == NULL)
942
   {
943
      printf("Can't open file %s!\n",code_name);
944
      getch();
945
      return(0);
946
   }
947
   bytes = fread(s->mem, 1, MEM_SIZE, in);
948
   fclose(in);
949
   in = NULL;
950
   printf("Code [size= %6d, start= 0x%08x]\n", bytes, 0);
951
 
952
   /* Read data file (.data + .bss) if necessary */
953
   if(data_name!=NULL){
954
      in = fopen(data_name, "rb");
955
      if(in == NULL)
956
      {
957
         printf("Can't open file %s!\n",data_name);
958
         getch();
959
         return(0);
960
      }
961
      /* FIXME Section '.data' start hardcoded to 0x10000 */
962
      buffer = (unsigned char*)malloc(MEM_SIZE);
963
 
964
      bytes = fread(buffer, 1, MEM_SIZE, in);
965
      fclose(in);
966
      printf("Data [size= %6d, start= 0x%08x]\n", bytes, 0x10000);
967
 
968
      for(i=0;i<bytes;i++){
969
         s->mem[0x10000+i] = buffer[i];
970
      }
971
      free(buffer);
972
   }
973
 
974
   return 1;
975
}
976
 
977
/*----------------------------------------------------------------------------*/
978
 
979
int main(int argc,char *argv[])
980
{
981
   State state, *s=&state;
982
   int index;
983
   char *code_filename;
984
   char *data_filename;
985
 
986
   printf("MIPS-I emulator\n");
987
   memset(s, 0, sizeof(State));
988
   s->big_endian = 1;
989
   s->load_delay_slot = 0;
990
   s->mem = (unsigned char*)malloc(MEM_SIZE);
991
   memset(s->mem, 0, MEM_SIZE);
992
 
993
 
994
   if(argc==3){
995
      code_filename = argv[1];
996
      data_filename = argv[2];
997
   }
998
   else if(argc==2){
999
      code_filename = argv[1];
1000
      data_filename = NULL;
1001
   }
1002
   else{
1003
      printf("Usage:");
1004
      printf("    slite file.exe <bin code file> [<bin data file>]\n");
1005
      return 0;
1006
   }
1007
 
1008
   if(!read_program(s, code_filename, data_filename)) return 0;
1009
 
1010
   init_trace_buffer(s, "sw_sim_log.txt");
1011
   memcpy(s->mem + 1024*1024, s->mem, 1024*1024);  //internal 8KB SRAM
1012
   cache_init(); /* stub */
1013
 
1014
   /* NOTE: Original mlite supported loading little-endian code, which this
1015
      program doesn't. The endianess-conversion code has been removed.
1016
   */
1017
 
1018 5 ja_rd
   /* Simulate a CPU reset */
1019
   /* FIXME cpu reset function needed */
1020
   s->pc = 0x0;      /* reset start vector */
1021
   s->failed_assertions = 0; /* no failed assertions pending */
1022
 
1023 2 ja_rd
   /* FIXME PC fixup at address zero has to be removed */
1024
   index = mem_read(s, 4, 0, 0);
1025
   if((index & 0xffffff00) == 0x3c1c1000){
1026
      s->pc = 0x10000000;
1027
   }
1028
 
1029
   /* Enter debug command interface; will only exit clean with user command */
1030
   do_debug(s);
1031
 
1032
   /* Close and deallocate everything and quit */
1033
   close_trace_buffer(s);
1034
   free(s->mem);
1035
   return(0);
1036
}
1037
 
1038
/*----------------------------------------------------------------------------*/
1039
 
1040
 
1041
void init_trace_buffer(State *s, const char *log_file_name){
1042
   int i;
1043
 
1044
#if FILE_LOGGING_DISABLED
1045
   s->t.log = NULL;
1046
   return;
1047
#else
1048
   for(i=0;i<TRACE_BUFFER_SIZE;i++){
1049
      s->t.buf[i]=0xffffffff;
1050
   }
1051
   s->t.next = 0;
1052
 
1053
   /* if file logging is enabled, open log file */
1054
   if(log_file_name!=NULL){
1055
      s->t.log = fopen(log_file_name, "w");
1056
      if(s->t.log==NULL){
1057
         printf("Error opening log file '%s', file logging disabled\n", log_file_name);
1058
      }
1059
   }
1060
   else{
1061
      s->t.log = NULL;
1062
   }
1063
#endif
1064
}
1065
 
1066
/** Dumps last jump targets as a chunk of hex numbers (older is left top) */
1067
void dump_trace_buffer(State *s){
1068
   int i, col;
1069
 
1070
   for(i=0, col=0;i<TRACE_BUFFER_SIZE;i++, col++){
1071
      printf("%08x ", s->t.buf[s->t.next + i]);
1072
      if((col % 8)==7){
1073
         printf("\n");
1074
      }
1075
   }
1076
}
1077
 
1078
/** Logs last cycle's activity (changes in state and/or loads/stores) */
1079
void log_cycle(State *s){
1080
   static unsigned int last_pc = 0;
1081
   int i;
1082
 
1083
   /* store PC in trace buffer only if there was a jump */
1084
   if(s->pc != (last_pc+4)){
1085
      s->t.buf[s->t.next] = s->pc;
1086
      s->t.next = (s->t.next + 1) % TRACE_BUFFER_SIZE;
1087
   }
1088
   last_pc = s->pc;
1089
 
1090
   /* if file logging is enabled, dump a trace log to file */
1091
   if(s->t.log!=NULL){
1092
      for(i=0;i<32;i++){
1093
         if(s->t.pr[i] != s->r[i]){
1094
            fprintf(s->t.log, "(%08X) [%02X]=%08X\n", s->pc, i, s->r[i]);
1095
         }
1096
         s->t.pr[i] = s->r[i];
1097
      }
1098
      if(s->lo != s->t.lo){
1099
         fprintf(s->t.log, "(%08X) [LO]=%08X\n", s->pc, s->lo);
1100
      }
1101
      s->t.lo = s->lo;
1102
 
1103
      if(s->hi != s->t.hi){
1104
         fprintf(s->t.log, "(%08X) [HI]=%08X\n", s->pc, s->hi);
1105
      }
1106
      s->t.hi = s->hi;
1107
 
1108
      if(s->epc != s->t.epc){
1109
         fprintf(s->t.log, "(%08X) [EP]=%08X\n", s->pc, s->epc);
1110
      }
1111
      s->t.epc = s->epc;
1112
   }
1113
}
1114
 
1115
/** Frees debug buffers and closes log file */
1116
void close_trace_buffer(State *s){
1117
   if(s->t.log){
1118
      fclose(s->t.log);
1119
   }
1120
}
1121 5 ja_rd
 
1122
/** Logs a message for each failed assertion, each in a line */
1123
void log_failed_assertions(State *s){
1124
   unsigned bitmap = s->failed_assertions;
1125
   int i = 0;
1126
 
1127
   /* This loop will crash the program if the message table is too short...*/
1128
   if(s->t.log != NULL){
1129
      for(i=0;i<32;i++){
1130
         if(bitmap & 0x1){
1131
            fprintf(s->t.log, "ASSERTION FAILED: [%08x] %s\n",
1132
                    s->faulty_address,
1133
                    assertion_messages[i]);
1134
         }
1135
         bitmap = bitmap >> 1;
1136
      }
1137
   }
1138
}

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.