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

Subversion Repositories ion

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

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

powered by: WebSVN 2.1.0

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