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

Subversion Repositories ion

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

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
*-------------------------------------------------------------------------------
30
* @date 2011-jan-16
31
*
32
*-------------------------------------------------------------------------------
33
* COPYRIGHT:    Software placed into the public domain by the author.
34
*               Software 'as is' without warranty.  Author liable for nothing.
35
*
36
* IMPORTANT: Assumes host is little endian.
37
*-----------------------------------------------------------------------------*/
38
 
39
#include <stdio.h>
40 11 ja_rd
#include <stdlib.h>
41
#include <stdint.h>
42 2 ja_rd
#include <string.h>
43
#include <ctype.h>
44
#include <assert.h>
45
 
46 31 ja_rd
/** Set to !=0 to disable file logging (much faster simulation) */
47 2 ja_rd
#define FILE_LOGGING_DISABLED (0)
48
/** Define to enable cache simulation (unimplemented) */
49
//#define ENABLE_CACHE
50 31 ja_rd
 
51
 
52
/*---- Definition of simulated system parameters -----------------------------*/
53
 
54 61 ja_rd
#define VECTOR_RESET (0xbfc00000)
55
#define VECTOR_TRAP  (0xbfc00180)
56
 
57
/** Definition of a memory block */
58 31 ja_rd
typedef struct s_block {
59
    uint32_t start;
60
    uint32_t size;
61 44 ja_rd
    uint32_t mask;
62 61 ja_rd
    uint32_t read_only;
63 31 ja_rd
    uint8_t  *mem;
64 61 ja_rd
    char     *area_name;
65 31 ja_rd
} t_block;
66 105 ja_rd
 
67
#define NUM_MEM_BLOCKS      (4)
68 108 ja_rd
#define NUM_MEM_MAPS        (3)
69 105 ja_rd
 
70
/** Definition of a memory map */
71
/* FIXME i/o addresses missing, hardcoded */
72
typedef struct s_map {
73
    t_block blocks[NUM_MEM_BLOCKS];
74
} t_map;
75
 
76 31 ja_rd
 
77
 
78 61 ja_rd
/*  Here's where we define the memory areas (blocks) of the system.
79
 
80
    The blocks should be defined in this order: BRAM, XRAM, FLASH
81
 
82
    BRAM is FPGA block ram initialized with bootstrap code
83
    XRAM is external SRAM
84
    FLASH is external flash
85
 
86
    Give any area a size of 0x0 to leave it unused.
87
 
88
    When a binary file is specified in the cmd line for one of these areas, it
89
    will be used to initialize it, checking bounds.
90
 
91
    Memory decoding is done in the order the blocks are defined; the address
92
    is anded with field .mask and then compared to field .start. If they match
93
    the address modulo the field .size is used to index the memory block, giving
94
    a 'mirror' effect. All of this simulates how the actual hardware works.
95
    Make sure the blocks don't overlap or the scheme will fail.
96 44 ja_rd
*/
97 31 ja_rd
 
98 105 ja_rd
#define MAP_DEFAULT (0)
99 108 ja_rd
#define MAP_UCLINUX (1)
100
#define MAP_SMALL   (2)
101 105 ja_rd
 
102
t_map memory_maps[NUM_MEM_MAPS] = {
103
    {/* Experimental memory map (default) */
104
        {/* Bootstrap BRAM, read only */
105
        {VECTOR_RESET,  0x00004800, 0xf8000000, 1, NULL, "Boot BRAM"},
106
        /* main external ram block  */
107
        {0x00000000,    0x00080000, 0xf8000000, 0, NULL, "XRAM0"},
108
        /* main external ram block  */
109
        {0x80000000,    0x00080000, 0xf8000000, 0, NULL, "XRAM1"},
110
        /* external flash block */
111
        {0xb0000000,    0x00040000, 0xf8000000, 0, NULL, "Flash"},
112
        }
113
    },
114
 
115
    {/* uClinux memory map */
116
        {/* Bootstrap BRAM, read only */
117
        {VECTOR_RESET,  0x00001000, 0xf8000000, 1, NULL, "Boot BRAM"},
118
        /* main external ram block  */
119
        {0x80000000,    0x00200000, 0xf8000000, 0, NULL, "XRAM0"},
120
        {0x00000000,    0x00400000, 0xf8000000, 0, NULL, "XRAM1"},
121
        /* external flash block */
122
        {0xb0000000,    0x00100000, 0xf8000000, 0, NULL, "Flash"},
123
        }
124 108 ja_rd
    },
125
 
126
    {/* Experimental memory map with small XRAM */
127
        {/* Bootstrap BRAM, read only */
128
        {VECTOR_RESET,  0x00004800, 0xf8000000, 1, NULL, "Boot BRAM"},
129
        /* main external ram block  */
130
        {0x00000000,    0x00001000, 0xf8000000, 0, NULL, "XRAM0"},
131
        /* main external ram block  */
132
        {0x80000000,    0x00001000, 0xf8000000, 0, NULL, "XRAM1"},
133
        /* external flash block */
134
        {0xb0000000,    0x00040000, 0xf8000000, 0, NULL, "Flash"},
135
        }
136 105 ja_rd
    },
137 31 ja_rd
};
138 105 ja_rd
 
139 31 ja_rd
 
140 61 ja_rd
/*---- end of system parameters ----------------------------------------------*/
141
 
142
 
143
/** Values for the command line arguments */
144
typedef struct s_args {
145 105 ja_rd
    /** memory map to be used */
146
    uint32_t memory_map;
147
    /** implement unaligned load/stores (don't just trap them) */
148
    uint32_t do_unaligned;
149
    /** start simulation without showing monitor prompt and quit on
150
        end condition -- useful for batch runs */
151
    uint32_t no_prompt;
152
    /** breakpoint address (0xffffffff if unused) */
153
    uint32_t breakpoint;
154
    /** a code fetch from this address starts logging */
155 93 ja_rd
    uint32_t log_trigger_address;
156 105 ja_rd
    /** full name of log file */
157 93 ja_rd
    char *log_file_name;
158 105 ja_rd
    /** bin file to load to each area or null */
159
    char *bin_filename[NUM_MEM_BLOCKS];
160
    /** offset into area (in bytes) where bin wile will be loaded */
161
    uint32_t offset[NUM_MEM_BLOCKS];
162 61 ja_rd
} t_args;
163
/** Parse cmd line args globally accessible */
164
t_args cmd_line_args;
165
 
166
 
167
/*---- Endianess conversion macros -------------------------------------------*/
168 2 ja_rd
 
169
#define ntohs(A) ( ((A)>>8) | (((A)&0xff)<<8) )
170
#define htons(A) ntohs(A)
171
#define ntohl(A) ( ((A)>>24) | (((A)&0xff0000)>>8) | (((A)&0xff00)<<8) | ((A)<<24) )
172
#define htonl(A) ntohl(A)
173
 
174
/*---- OS-dependent support functions and definitions ------------------------*/
175
#ifndef WIN32
176
//Support for Linux
177
#define putch putchar
178
#include <termios.h>
179
#include <unistd.h>
180
 
181 31 ja_rd
void slite_sleep(unsigned int value){
182
    usleep(value * 1000);
183 2 ja_rd
}
184
 
185 31 ja_rd
int kbhit(void){
186
    struct termios oldt, newt;
187
    struct timeval tv;
188
    fd_set read_fd;
189 2 ja_rd
 
190 31 ja_rd
    tcgetattr(STDIN_FILENO, &oldt);
191
    newt = oldt;
192
    newt.c_lflag &= ~(ICANON | ECHO);
193
    tcsetattr(STDIN_FILENO, TCSANOW, &newt);
194
    tv.tv_sec=0;
195
    tv.tv_usec=0;
196
    FD_ZERO(&read_fd);
197
    FD_SET(0,&read_fd);
198
    if(select(1, &read_fd, NULL, NULL, &tv) == -1){
199
        return 0;
200
    }
201
    //tcsetattr(STDIN_FILENO, TCSANOW, &oldt);
202
    if(FD_ISSET(0,&read_fd)){
203
        return 1;
204
    }
205
    return 0;
206 2 ja_rd
}
207
 
208 31 ja_rd
int getch(void){
209
    struct termios oldt, newt;
210
    int ch;
211 2 ja_rd
 
212 31 ja_rd
    tcgetattr(STDIN_FILENO, &oldt);
213
    newt = oldt;
214
    newt.c_lflag &= ~(ICANON | ECHO);
215
    tcsetattr(STDIN_FILENO, TCSANOW, &newt);
216
    ch = getchar();
217
    //tcsetattr(STDIN_FILENO, TCSANOW, &oldt);
218
    return ch;
219 2 ja_rd
}
220
#else
221
//Support for Windows
222
#include <conio.h>
223 31 ja_rd
extern void __stdcall Sleep(unsigned long value);
224
 
225
void slite_sleep(unsigned int value){
226
    Sleep(value);
227
}
228
 
229 2 ja_rd
#endif
230
/*---- End of OS-dependent support functions and definitions -----------------*/
231
 
232
/*---- Hardware system parameters --------------------------------------------*/
233
 
234
/* Much of this is a remnant from Plasma's mlite and is  no longer used. */
235
/* FIXME Refactor HW system params */
236
 
237 105 ja_rd
#define DBG_REGS          (0x20010000)
238
 
239 2 ja_rd
#define UART_WRITE        0x20000000
240
#define UART_READ         0x20000000
241
#define IRQ_MASK          0x20000010
242
#define IRQ_STATUS        0x20000020
243
#define CONFIG_REG        0x20000070
244
#define MMU_PROCESS_ID    0x20000080
245
#define MMU_FAULT_ADDR    0x20000090
246
#define MMU_TLB           0x200000a0
247
 
248
#define IRQ_UART_READ_AVAILABLE  0x001
249
#define IRQ_UART_WRITE_AVAILABLE 0x002
250
#define IRQ_COUNTER18_NOT        0x004
251
#define IRQ_COUNTER18            0x008
252
#define IRQ_MMU                  0x200
253
 
254 5 ja_rd
/*----------------------------------------------------------------------------*/
255 2 ja_rd
 
256 5 ja_rd
/* These are flags that will be used to notify the main cycle function of any
257
   failed assertions in its subfunctions. */
258
#define ASRT_UNALIGNED_READ         (1<<0)
259
#define ASRT_UNALIGNED_WRITE        (1<<1)
260
 
261
char *assertion_messages[2] = {
262
   "Unaligned read",
263
   "Unaligned write"
264
};
265
 
266
 
267 2 ja_rd
/** Length of debugging jump target queue */
268
#define TRACE_BUFFER_SIZE (32)
269
 
270 31 ja_rd
typedef struct s_trace {
271 2 ja_rd
   unsigned int buf[TRACE_BUFFER_SIZE];   /**< queue of last jump targets */
272
   unsigned int next;                     /**< internal queue head pointer */
273
   FILE *log;                             /**< text log file or NULL */
274 93 ja_rd
   int log_triggered;                     /**< !=0 if log has been triggered */
275
   uint32_t log_trigger_address;          /**< */
276 2 ja_rd
   int pr[32];                            /**< last value of register bank */
277
   int hi, lo, epc;                       /**< last value of internal regs */
278 31 ja_rd
} t_trace;
279 2 ja_rd
 
280 31 ja_rd
typedef struct s_state {
281 5 ja_rd
   unsigned failed_assertions;            /**< assertion bitmap */
282
   unsigned faulty_address;               /**< addr that failed assertion */
283 105 ja_rd
   uint32_t do_unaligned;                 /**< !=0 to enable unaligned L/S */
284
   uint32_t breakpoint;                   /**< BP address of 0xffffffff */
285 27 ja_rd
 
286
   int delay_slot;              /**< !=0 if prev. instruction was a branch */
287 5 ja_rd
 
288 2 ja_rd
   int r[32];
289
   int opcode;
290 53 ja_rd
   int pc, pc_next, epc;
291
   uint32_t op_addr;            /**< address of opcode being simulated */
292 2 ja_rd
   unsigned int hi;
293
   unsigned int lo;
294 27 ja_rd
   int status;
295
   unsigned cp0_cause;
296 2 ja_rd
   int userMode;
297
   int processId;
298 53 ja_rd
   int exceptionId;             /**< DEPRECATED, to be removed */
299 2 ja_rd
   int faultAddr;
300
   int irqStatus;
301
   int skip;
302 31 ja_rd
   t_trace t;
303
   //unsigned char *mem;
304
   t_block blocks[NUM_MEM_BLOCKS];
305 2 ja_rd
   int wakeup;
306
   int big_endian;
307 31 ja_rd
} t_state;
308 2 ja_rd
 
309
static char *opcode_string[]={
310
   "SPECIAL","REGIMM","J","JAL","BEQ","BNE","BLEZ","BGTZ",
311
   "ADDI","ADDIU","SLTI","SLTIU","ANDI","ORI","XORI","LUI",
312
   "COP0","COP1","COP2","COP3","BEQL","BNEL","BLEZL","BGTZL",
313
   "?","?","?","?","?","?","?","?",
314
   "LB","LH","LWL","LW","LBU","LHU","LWR","?",
315
   "SB","SH","SWL","SW","?","?","SWR","CACHE",
316
   "LL","LWC1","LWC2","LWC3","?","LDC1","LDC2","LDC3"
317
   "SC","SWC1","SWC2","SWC3","?","SDC1","SDC2","SDC3"
318
};
319
 
320
static char *special_string[]={
321
   "SLL","?","SRL","SRA","SLLV","?","SRLV","SRAV",
322
   "JR","JALR","MOVZ","MOVN","SYSCALL","BREAK","?","SYNC",
323
   "MFHI","MTHI","MFLO","MTLO","?","?","?","?",
324
   "MULT","MULTU","DIV","DIVU","?","?","?","?",
325
   "ADD","ADDU","SUB","SUBU","AND","OR","XOR","NOR",
326
   "?","?","SLT","SLTU","?","DADDU","?","?",
327
   "TGE","TGEU","TLT","TLTU","TEQ","?","TNE","?",
328
   "?","?","?","?","?","?","?","?"
329
};
330
 
331
static char *regimm_string[]={
332
   "BLTZ","BGEZ","BLTZL","BGEZL","?","?","?","?",
333
   "TGEI","TGEIU","TLTI","TLTIU","TEQI","?","TNEI","?",
334
   "BLTZAL","BEQZAL","BLTZALL","BGEZALL","?","?","?","?",
335
   "?","?","?","?","?","?","?","?"
336
};
337
 
338
static unsigned int HWMemory[8];
339
 
340
/*---- Local function prototypes ---------------------------------------------*/
341
 
342
/* Debug and logging */
343 93 ja_rd
void init_trace_buffer(t_state *s, t_args *args);
344 31 ja_rd
void close_trace_buffer(t_state *s);
345
void dump_trace_buffer(t_state *s);
346
void log_cycle(t_state *s);
347
void log_read(t_state *s, int full_address, int word_value, int size, int log);
348
void log_failed_assertions(t_state *s);
349 93 ja_rd
uint32_t log_enabled(t_state *s);
350
void trigger_log(t_state *s);
351 2 ja_rd
 
352 61 ja_rd
int32_t parse_cmd_line(uint32_t argc, char **argv, t_args *args);
353
void usage(void);
354
 
355 31 ja_rd
/* CPU model */
356
void free_cpu(t_state *s);
357 105 ja_rd
int init_cpu(t_state *s, t_args *args);
358
void reset_cpu(t_state *s);
359
void unimplemented(t_state *s, const char *txt);
360
void reverse_endianess(uint8_t *data, uint32_t bytes);
361 31 ja_rd
 
362 2 ja_rd
/* Hardware simulation */
363 31 ja_rd
int mem_read(t_state *s, int size, unsigned int address, int log);
364
void mem_write(t_state *s, int size, unsigned address, unsigned value, int log);
365 53 ja_rd
void start_load(t_state *s, uint32_t addr, int rt, int data);
366 2 ja_rd
 
367 16 ja_rd
 
368 2 ja_rd
/*---- Local functions -------------------------------------------------------*/
369
 
370
/** Log to file a memory read operation (not including target reg change) */
371 31 ja_rd
void log_read(t_state *s, int full_address, int word_value, int size, int log){
372 93 ja_rd
    if(log_enabled(s) && log!=0){
373 53 ja_rd
        fprintf(s->t.log, "(%08X) [%08X] <**>=%08X RD\n",
374
              s->op_addr, full_address, word_value);
375
    }
376 2 ja_rd
}
377
 
378
/** Read memory, optionally logging */
379 31 ja_rd
int mem_read(t_state *s, int size, unsigned int address, int log){
380
    unsigned int value=0, word_value=0, i, ptr;
381
    unsigned int full_address = address;
382 2 ja_rd
 
383 31 ja_rd
    s->irqStatus |= IRQ_UART_WRITE_AVAILABLE;
384
    switch(address){
385
    case UART_READ:
386
        /* FIXME Take input from text file */
387 93 ja_rd
        while(!kbhit());
388
        HWMemory[0] = getch();
389
        //s->irqStatus &= ~IRQ_UART_READ_AVAILABLE; //clear bit
390
        printf("%c", HWMemory[0]);
391
        return (HWMemory[0] << 24) | 0x03;
392 31 ja_rd
    case IRQ_MASK:
393
       return HWMemory[1];
394
    case IRQ_MASK + 4:
395
       slite_sleep(10);
396
       return 0;
397
    case IRQ_STATUS:
398
       /*if(kbhit())
399
          s->irqStatus |= IRQ_UART_READ_AVAILABLE;
400
       return s->irqStatus;
401
       */
402
       /* FIXME Optionally simulate UART TX delay */
403
       word_value = 0x00000003; /* Ready to TX and RX */
404 53 ja_rd
       //log_read(s, full_address, word_value, size, log);
405 31 ja_rd
       return word_value;
406
    case MMU_PROCESS_ID:
407
       return s->processId;
408
    case MMU_FAULT_ADDR:
409
       return s->faultAddr;
410
    }
411
 
412
    /* point ptr to the byte in the block, or NULL is the address is unmapped */
413
    ptr = 0;
414
    for(i=0;i<NUM_MEM_BLOCKS;i++){
415 61 ja_rd
        if((address & s->blocks[i].mask) ==
416
           (s->blocks[i].start & s->blocks[i].mask)){
417 44 ja_rd
            ptr = (unsigned)(s->blocks[i].mem) +
418
                  ((address - s->blocks[i].start) % s->blocks[i].size);
419 31 ja_rd
            break;
420
        }
421
    }
422
    if(!ptr){
423
        /* address out of mapped blocks: log and return zero */
424 93 ja_rd
        if(log_enabled(s) && log!=0){
425 31 ja_rd
            fprintf(s->t.log, "(%08X) [%08X] <**>=%08X RD UNMAPPED\n",
426
                s->pc, full_address, 0);
427
        }
428
        return 0;
429
    }
430
 
431
    /* get the whole word */
432
    word_value = *(int*)(ptr&0xfffffffc);
433
    if(s->big_endian){
434
        word_value = ntohl(word_value);
435
    }
436 2 ja_rd
 
437 31 ja_rd
    switch(size){
438
    case 4:
439
        if(address & 3){
440 2 ja_rd
            printf("Unaligned access PC=0x%x address=0x%x\n",
441 31 ja_rd
                (int)s->pc, (int)address);
442
        }
443
        if((address & 3) != 0){
444
            /* unaligned word, log fault */
445 5 ja_rd
            s->failed_assertions |= ASRT_UNALIGNED_READ;
446
            s->faulty_address = address;
447
            address = address & 0xfffffffc;
448 31 ja_rd
        }
449
        value = *(int*)ptr;
450
        if(s->big_endian){
451
            value = ntohl(value);
452
        }
453
        break;
454
    case 2:
455
        if((address & 1) != 0){
456
            /* unaligned halfword, log fault */
457 5 ja_rd
            s->failed_assertions |= ASRT_UNALIGNED_READ;
458
            s->faulty_address = address;
459
            address = address & 0xfffffffe;
460 31 ja_rd
        }
461
        value = *(unsigned short*)ptr;
462
        if(s->big_endian){
463
            value = ntohs((unsigned short)value);
464
        }
465
        break;
466
    case 1:
467
        value = *(unsigned char*)ptr;
468
        break;
469
    default:
470
        /* FIXME this is a bug, should quit */
471
        printf("ERROR");
472
    }
473 2 ja_rd
 
474 53 ja_rd
    //log_read(s, full_address, value, size, log);
475 31 ja_rd
    return(value);
476 2 ja_rd
}
477
 
478
/** Write memory */
479 31 ja_rd
void mem_write(t_state *s, int size, unsigned address, unsigned value, int log){
480
    unsigned int i, ptr, mask, dvalue, b0, b1, b2, b3;
481 2 ja_rd
 
482 93 ja_rd
    if(log_enabled(s)){
483 31 ja_rd
        b0 = value & 0x000000ff;
484
        b1 = value & 0x0000ff00;
485
        b2 = value & 0x00ff0000;
486
        b3 = value & 0xff000000;
487 2 ja_rd
 
488 31 ja_rd
        switch(size){
489
        case 4:  mask = 0x0f;
490
            dvalue = value;
491
            break;
492
        case 2:
493
            if((address&0x2)==0){
494
                mask = 0xc;
495
                dvalue = b1<<16 | b0<<16;
496
            }
497
            else{
498
               mask = 0x3;
499
               dvalue = b1 | b0;
500
            }
501
            break;
502
        case 1:
503
            switch(address%4){
504
            case 0 : mask = 0x8;
505
                dvalue = b0<<24;
506
                break;
507
            case 1 : mask = 0x4;
508
                dvalue = b0<<16;
509
                break;
510
            case 2 : mask = 0x2;
511
                dvalue = b0<<8;
512
                break;
513
            case 3 : mask = 0x1;
514
                dvalue = b0;
515
                break;
516
            }
517
            break;
518
        default:
519 2 ja_rd
            printf("BUG: mem write size invalid (%08x)\n", s->pc);
520
            exit(2);
521 31 ja_rd
        }
522 2 ja_rd
 
523 31 ja_rd
        fprintf(s->t.log, "(%08X) [%08X] |%02X|=%08X WR\n",
524 93 ja_rd
                s->op_addr, address&0xfffffffc, mask, dvalue);
525 31 ja_rd
    }
526 105 ja_rd
 
527
    if((address&0xffff0000)==DBG_REGS){
528
        printf("[%04x]=%08x\n", address & 0xffff, value);
529
    }
530 2 ja_rd
 
531 31 ja_rd
    switch(address){
532
    case UART_WRITE:
533
        putch(value);
534
        fflush(stdout);
535
        return;
536
    case IRQ_MASK:
537
        HWMemory[1] = value;
538
        return;
539
    case IRQ_STATUS:
540
        s->irqStatus = value;
541
        return;
542
    case CONFIG_REG:
543
        return;
544
    case MMU_PROCESS_ID:
545
        //printf("processId=%d\n", value);
546
        s->processId = value;
547
        return;
548
    }
549 2 ja_rd
 
550 31 ja_rd
    ptr = 0;
551
    for(i=0;i<NUM_MEM_BLOCKS;i++){
552 61 ja_rd
        if((address & s->blocks[i].mask) ==
553
                  (s->blocks[i].start & s->blocks[i].mask)){
554 44 ja_rd
            ptr = (unsigned)(s->blocks[i].mem) +
555
                            ((address - s->blocks[i].start) % s->blocks[i].size);
556 61 ja_rd
 
557
            if(s->blocks[i].read_only){
558 93 ja_rd
                if(log_enabled(s) && log!=0){
559 61 ja_rd
                    fprintf(s->t.log, "(%08X) [%08X] |%02X|=%08X WR READ ONLY\n",
560
                    s->op_addr, address, mask, dvalue);
561
                    return;
562
                }
563
            }
564 31 ja_rd
            break;
565
        }
566
    }
567
    if(!ptr){
568
        /* address out of mapped blocks: log and return zero */
569 93 ja_rd
        if(log_enabled(s) && log!=0){
570 31 ja_rd
            fprintf(s->t.log, "(%08X) [%08X] |%02X|=%08X WR UNMAPPED\n",
571 53 ja_rd
                s->op_addr, address, mask, dvalue);
572 31 ja_rd
        }
573
        return;
574
    }
575 2 ja_rd
 
576 31 ja_rd
    switch(size){
577
    case 4:
578
        if((address & 3) != 0){
579
            /* unaligned word, log fault */
580 5 ja_rd
            s->failed_assertions |= ASRT_UNALIGNED_WRITE;
581
            s->faulty_address = address;
582
            address = address & (~0x03);
583 31 ja_rd
        }
584
        if(s->big_endian){
585
            value = htonl(value);
586
        }
587
        *(int*)ptr = value;
588
        break;
589
    case 2:
590
        if((address & 1) != 0){
591
            /* unaligned halfword, log fault */
592 5 ja_rd
            s->failed_assertions |= ASRT_UNALIGNED_WRITE;
593
            s->faulty_address = address;
594
            address = address & (~0x01);
595 31 ja_rd
        }
596
        if(s->big_endian){
597
            value = htons((unsigned short)value);
598
        }
599
        *(short*)ptr = (unsigned short)value;
600
        break;
601
    case 1:
602
        *(char*)ptr = (unsigned char)value;
603
        break;
604
    default:
605
        /* FIXME this is a bug, should quit */
606
        printf("ERROR");
607
    }
608 2 ja_rd
}
609
 
610 105 ja_rd
/*-- unaligned store and load instructions -----------------------------------*/
611
/*
612
 These are meant to be left unimplemented and trapped. These functions simulate
613
 the unaligned r/w instructions until proper trap handlers are written.
614
*/
615
 
616
void mem_swl(t_state *s, uint32_t address, uint32_t value, uint32_t log){
617
    uint32_t data, offset;
618
 
619
    if(!s->do_unaligned) return unimplemented(s, "SWL");
620
 
621
    offset = (address & 0x03);
622
    address = (address & (~0x03));
623
    data = value;
624
 
625
    while(offset<4){
626
        mem_write(s,1,address+offset,(data>>24) & 0xff,0);
627
        data = data << 8;
628
        offset++;
629
    }
630
}
631
 
632
void mem_swr(t_state *s, uint32_t address, uint32_t value, uint32_t log){
633
    uint32_t data, offset;
634
 
635
    if(!s->do_unaligned) return unimplemented(s, "SWR");
636
 
637
    offset = (address & 0x03);
638
    address = (address & (~0x03));
639
    data = value;
640
 
641
    while(offset>=0){
642
        mem_write(s,1,address+offset,data & 0xff,0);
643
        data = data >> 8;
644
        offset--;
645
    }
646
}
647
 
648
void mem_lwr(t_state *s, uint32_t address, uint32_t reg_index, uint32_t log){
649
    uint32_t offset, data;
650
    uint32_t disp[4] = {24,         16,         8,          0};
651
    uint32_t mask[4] = {0x000000ff, 0x0000ffff, 0x00ffffff, 0xffffffff};
652
 
653
    if(!s->do_unaligned) return unimplemented(s, "LWR");
654
 
655
    offset = (address & 0x03);
656
    address = (address & (~0x03));
657
 
658
    data = mem_read(s, 4, address, 0);
659
    data = (data >> disp[offset]) & mask[offset];
660
 
661
    s->r[reg_index] = (s->r[reg_index] & (~mask[offset])) | data;
662
}
663
 
664
void mem_lwl(t_state *s, uint32_t address, uint32_t reg_index, uint32_t log){
665
    uint32_t offset, data;
666
    uint32_t disp[4] = {0,          8,          16,         24};
667
    uint32_t mask[4] = {0xffffffff, 0xffffff00, 0xffff0000, 0xff000000};
668
 
669
    if(!s->do_unaligned) return unimplemented(s, "LWL");
670
 
671
    offset = (address & 0x03);
672
    address = (address & (~0x03));
673
 
674
    data = mem_read(s, 4, address, 0);
675
    data = (data << disp[offset]) & mask[offset];
676
 
677
    s->r[reg_index] = (s->r[reg_index] & (~mask[offset])) | data;
678
}
679
 
680
 
681 2 ja_rd
/*---- Optional MMU and cache implementation ---------------------------------*/
682
 
683
/*
684
   The actual core does not have a cache so all of the original Plasma mlite.c
685
   code for cache simulation has been removed.
686
*/
687
 
688
/*---- End optional cache implementation -------------------------------------*/
689
 
690
 
691
/** Simulates MIPS-I multiplier unsigned behavior*/
692
void mult_big(unsigned int a,
693
              unsigned int b,
694
              unsigned int *hi,
695 31 ja_rd
              unsigned int *lo){
696
    unsigned int ahi, alo, bhi, blo;
697
    unsigned int c0, c1, c2;
698
    unsigned int c1_a, c1_b;
699 2 ja_rd
 
700 31 ja_rd
    ahi = a >> 16;
701
    alo = a & 0xffff;
702
    bhi = b >> 16;
703
    blo = b & 0xffff;
704 2 ja_rd
 
705 31 ja_rd
    c0 = alo * blo;
706
    c1_a = ahi * blo;
707
    c1_b = alo * bhi;
708
    c2 = ahi * bhi;
709 2 ja_rd
 
710 31 ja_rd
    c2 += (c1_a >> 16) + (c1_b >> 16);
711
    c1 = (c1_a & 0xffff) + (c1_b & 0xffff) + (c0 >> 16);
712
    c2 += (c1 >> 16);
713
    c0 = (c1 << 16) + (c0 & 0xffff);
714
    *hi = c2;
715
    *lo = c0;
716 2 ja_rd
}
717
 
718
/** Simulates MIPS-I multiplier signed behavior*/
719
void mult_big_signed(int a,
720
                     int b,
721
                     unsigned int *hi,
722 31 ja_rd
                     unsigned int *lo){
723
    int64_t xa, xb, xr, temp;
724
    int32_t rh, rl;
725 11 ja_rd
 
726 31 ja_rd
    xa = a;
727
    xb = b;
728
    xr = xa * xb;
729 11 ja_rd
 
730 31 ja_rd
    temp = (xr >> 32) & 0xffffffff;
731
    rh = temp;
732
    temp = (xr >> 0) & 0xffffffff;
733
    rl = temp;
734 11 ja_rd
 
735 31 ja_rd
    *hi = rh;
736
    *lo = rl;
737 2 ja_rd
}
738
 
739
/** Load data from memory (used to simulate load delay slots) */
740 53 ja_rd
void start_load(t_state *s, uint32_t addr, int rt, int data){
741 31 ja_rd
    /* load delay slot not simulated */
742 53 ja_rd
    log_read(s, addr, data, 1, 1);
743 31 ja_rd
    s->r[rt] = data;
744 2 ja_rd
}
745
 
746
/** Execute one cycle of the CPU (including any interlock stall cycles) */
747 31 ja_rd
void cycle(t_state *s, int show_mode){
748
    unsigned int opcode;
749
    int delay_slot = 0; /* 1 of this instruction is a branch */
750
    unsigned int op, rs, rt, rd, re, func, imm, target;
751
    int trap_cause = 0;
752
    int imm_shift, branch=0, lbranch=2, skip2=0;
753
    int *r=s->r;
754
    unsigned int *u=(unsigned int*)s->r;
755
    unsigned int ptr, epc, rSave;
756 2 ja_rd
 
757 93 ja_rd
    /* fetch and decode instruction */
758 31 ja_rd
    opcode = mem_read(s, 4, s->pc, 0);
759
    op = (opcode >> 26) & 0x3f;
760
    rs = (opcode >> 21) & 0x1f;
761
    rt = (opcode >> 16) & 0x1f;
762
    rd = (opcode >> 11) & 0x1f;
763
    re = (opcode >> 6) & 0x1f;
764
    func = opcode & 0x3f;
765
    imm = opcode & 0xffff;
766
    imm_shift = (((int)(short)imm) << 2) - 4;
767
    target = (opcode << 6) >> 4;
768
    ptr = (short)imm + r[rs];
769
    r[0] = 0;
770
 
771 93 ja_rd
    /* Trigger log if we fetch from trigger address */
772
    if(s->pc == s->t.log_trigger_address){
773
        trigger_log(s);
774
    }
775
 
776 31 ja_rd
    /* if we are priting state to console, do it now */
777
    if(show_mode){
778
        printf("%8.8x %8.8x ", s->pc, opcode);
779
        if(op == 0){
780
            printf("%8s ", special_string[func]);
781
        }
782
        else if(op == 1){
783
            printf("%8s ", regimm_string[rt]);
784
        }
785
        else{
786
            printf("%8s ", opcode_string[op]);
787
        }
788 2 ja_rd
 
789 31 ja_rd
        printf("$%2.2d $%2.2d $%2.2d $%2.2d ", rs, rt, rd, re);
790
        printf("%4.4x", imm);
791
        if(show_mode == 1){
792
            printf(" r[%2.2d]=%8.8x r[%2.2d]=%8.8x", rs, r[rs], rt, r[rt]);
793
        }
794
        printf("\n");
795
    }
796
 
797
    /* if we're just showing state to console, quit and don't run instruction */
798
    if(show_mode > 5){
799
        return;
800
    }
801
 
802
    /* epc will point to the victim instruction, i.e. THIS instruction */
803
    epc = s->pc;
804 32 ja_rd
 
805
    /* If we catch a jump instruction jumping to itself, assume we hit the
806
       and of the program and quit. */
807
    if(s->pc == s->pc_next+4){
808
        printf("\n\nEndless loop at 0x%08x\n\n", s->pc-4);
809
        s->wakeup = 1;
810 53 ja_rd
    }
811
    s->op_addr = s->pc;
812 31 ja_rd
    s->pc = s->pc_next;
813
    s->pc_next = s->pc_next + 4;
814
    if(s->skip){
815
        s->skip = 0;
816
        return;
817
    }
818
    rSave = r[rt];
819
 
820
    switch(op){
821
    case 0x00:/*SPECIAL*/
822
        switch(func){
823
        case 0x00:/*SLL*/  r[rd]=r[rt]<<re;          break;
824
        case 0x02:/*SRL*/  r[rd]=u[rt]>>re;          break;
825
        case 0x03:/*SRA*/  r[rd]=r[rt]>>re;          break;
826
        case 0x04:/*SLLV*/ r[rd]=r[rt]<<r[rs];       break;
827
        case 0x06:/*SRLV*/ r[rd]=u[rt]>>r[rs];       break;
828
        case 0x07:/*SRAV*/ r[rd]=r[rt]>>r[rs];       break;
829
        case 0x08:/*JR*/   delay_slot=1;
830
                           s->pc_next=r[rs];         break;
831
        case 0x09:/*JALR*/ delay_slot=1;
832
                           r[rd]=s->pc_next;
833
                           s->pc_next=r[rs]; break;
834
        case 0x0a:/*MOVZ*/ if(!r[rt]) r[rd]=r[rs];   break;  /*IV*/
835
        case 0x0b:/*MOVN*/ if(r[rt]) r[rd]=r[rs];    break;  /*IV*/
836 105 ja_rd
        case 0x0c:/*SYSCALL*/ //trap_cause = 8;
837
                              //s->exceptionId=1;
838
                              /*
839
                              FIXME enable when running uClinux
840
                              printf("SYSCALL (%08x)\n", s->pc);
841
                              */
842
                              break;
843
        case 0x0d:/*BREAK*/   //trap_cause = 9;
844
                              //s->exceptionId=1;
845
                              /*
846
                              FIXME enable when running uClinux
847
                              printf("BREAK (%08x)\n", s->pc);
848
                              */
849
                              break;
850 31 ja_rd
        case 0x0f:/*SYNC*/ s->wakeup=1;              break;
851
        case 0x10:/*MFHI*/ r[rd]=s->hi;              break;
852
        case 0x11:/*FTHI*/ s->hi=r[rs];              break;
853
        case 0x12:/*MFLO*/ r[rd]=s->lo;              break;
854
        case 0x13:/*MTLO*/ s->lo=r[rs];              break;
855
        case 0x18:/*MULT*/ mult_big_signed(r[rs],r[rt],&s->hi,&s->lo); break;
856
        case 0x19:/*MULTU*/ mult_big(r[rs],r[rt],&s->hi,&s->lo); break;
857
        case 0x1a:/*DIV*/  s->lo=r[rs]/r[rt]; s->hi=r[rs]%r[rt]; break;
858
        case 0x1b:/*DIVU*/ s->lo=u[rs]/u[rt]; s->hi=u[rs]%u[rt]; break;
859
        case 0x20:/*ADD*/  r[rd]=r[rs]+r[rt];        break;
860
        case 0x21:/*ADDU*/ r[rd]=r[rs]+r[rt];        break;
861
        case 0x22:/*SUB*/  r[rd]=r[rs]-r[rt];        break;
862
        case 0x23:/*SUBU*/ r[rd]=r[rs]-r[rt];        break;
863
        case 0x24:/*AND*/  r[rd]=r[rs]&r[rt];        break;
864
        case 0x25:/*OR*/   r[rd]=r[rs]|r[rt];        break;
865
        case 0x26:/*XOR*/  r[rd]=r[rs]^r[rt];        break;
866
        case 0x27:/*NOR*/  r[rd]=~(r[rs]|r[rt]);     break;
867
        case 0x2a:/*SLT*/  r[rd]=r[rs]<r[rt];        break;
868
        case 0x2b:/*SLTU*/ r[rd]=u[rs]<u[rt];        break;
869
        case 0x2d:/*DADDU*/r[rd]=r[rs]+u[rt];        break;
870
        case 0x31:/*TGEU*/ break;
871
        case 0x32:/*TLT*/  break;
872
        case 0x33:/*TLTU*/ break;
873
        case 0x34:/*TEQ*/  break;
874
        case 0x36:/*TNE*/  break;
875
        default: printf("ERROR0(*0x%x~0x%x)\n", s->pc, opcode);
876
           s->wakeup=1;
877
        }
878
        break;
879
    case 0x01:/*REGIMM*/
880
        switch(rt){
881 2 ja_rd
            case 0x10:/*BLTZAL*/ r[31]=s->pc_next;
882
            case 0x00:/*BLTZ*/   branch=r[rs]<0;    break;
883
            case 0x11:/*BGEZAL*/ r[31]=s->pc_next;
884
            case 0x01:/*BGEZ*/   branch=r[rs]>=0;   break;
885
            case 0x12:/*BLTZALL*/r[31]=s->pc_next;
886
            case 0x02:/*BLTZL*/  lbranch=r[rs]<0;   break;
887
            case 0x13:/*BGEZALL*/r[31]=s->pc_next;
888
            case 0x03:/*BGEZL*/  lbranch=r[rs]>=0;  break;
889
            default: printf("ERROR1\n"); s->wakeup=1;
890 31 ja_rd
        }
891
        break;
892
    case 0x03:/*JAL*/    r[31]=s->pc_next;
893
    case 0x02:/*J*/      delay_slot=1;
894
                       s->pc_next=(s->pc&0xf0000000)|target; break;
895
    case 0x04:/*BEQ*/    branch=r[rs]==r[rt];     break;
896
    case 0x05:/*BNE*/    branch=r[rs]!=r[rt];     break;
897
    case 0x06:/*BLEZ*/   branch=r[rs]<=0;         break;
898
    case 0x07:/*BGTZ*/   branch=r[rs]>0;          break;
899
    case 0x08:/*ADDI*/   r[rt]=r[rs]+(short)imm;  break;
900
    case 0x09:/*ADDIU*/  u[rt]=u[rs]+(short)imm;  break;
901
    case 0x0a:/*SLTI*/   r[rt]=r[rs]<(short)imm;  break;
902
    case 0x0b:/*SLTIU*/  u[rt]=u[rs]<(unsigned int)(short)imm; break;
903
    case 0x0c:/*ANDI*/   r[rt]=r[rs]&imm;         break;
904
    case 0x0d:/*ORI*/    r[rt]=r[rs]|imm;         break;
905
    case 0x0e:/*XORI*/   r[rt]=r[rs]^imm;         break;
906
    case 0x0f:/*LUI*/    r[rt]=(imm<<16);         break;
907
    case 0x10:/*COP0*/
908 105 ja_rd
        if((opcode & (1<<23)) == 0){  //move from CP0 (mfc0)
909
            switch(rd){
910
                case 12: r[rt]=s->status; break;
911
                case 13: r[rt]=s->cp0_cause; break;
912
                case 14: r[rt]=s->epc; break;
913
                case 15: r[rt]=0x00000200; break;
914
                default:
915
                    //printf("mfco [%02d]\n", rd);
916
                    break;
917 27 ja_rd
            }
918 31 ja_rd
        }
919 105 ja_rd
        else{                         //move to CP0 (mtc0)
920 2 ja_rd
            s->status=r[rt]&1;
921 31 ja_rd
            if(s->processId && (r[rt]&2)){
922
                s->userMode|=r[rt]&2;
923
                //printf("CpuStatus=%d %d %d\n", r[rt], s->status, s->userMode);
924
                //s->wakeup = 1;
925
                //printf("pc=0x%x\n", epc);
926 2 ja_rd
            }
927 31 ja_rd
        }
928
        break;
929 105 ja_rd
    case 0x11:/*COP1*/  unimplemented(s,"COP1");
930
                        break;
931 2 ja_rd
//      case 0x12:/*COP2*/ break;
932
//      case 0x13:/*COP3*/ break;
933 31 ja_rd
    case 0x14:/*BEQL*/  lbranch=r[rs]==r[rt];    break;
934
    case 0x15:/*BNEL*/  lbranch=r[rs]!=r[rt];    break;
935
    case 0x16:/*BLEZL*/ lbranch=r[rs]<=0;        break;
936
    case 0x17:/*BGTZL*/ lbranch=r[rs]>0;         break;
937 2 ja_rd
//      case 0x1c:/*MAD*/  break;   /*IV*/
938 31 ja_rd
    case 0x20:/*LB*/    //r[rt]=(signed char)mem_read(s,1,ptr,1);  break;
939 53 ja_rd
                        start_load(s, ptr, rt,(signed char)mem_read(s,1,ptr,1));
940 31 ja_rd
                        break;
941 2 ja_rd
 
942 31 ja_rd
    case 0x21:/*LH*/    //r[rt]=(signed short)mem_read(s,2,ptr,1); break;
943 53 ja_rd
                        start_load(s, ptr, rt, (signed short)mem_read(s,2,ptr,1));
944 31 ja_rd
                        break;
945 105 ja_rd
    case 0x22:/*LWL*/   mem_lwl(s, ptr, rt, 1);
946
                        //printf("LWL\n");
947 31 ja_rd
                        break;
948
    case 0x23:/*LW*/    //r[rt]=mem_read(s,4,ptr,1);   break;
949 53 ja_rd
                        start_load(s, ptr, rt, mem_read(s,4,ptr,1));
950 31 ja_rd
                        break;
951
    case 0x24:/*LBU*/   //r[rt]=(unsigned char)mem_read(s,1,ptr,1); break;
952 53 ja_rd
                        start_load(s, ptr, rt, (unsigned char)mem_read(s,1,ptr,1));
953 31 ja_rd
                        break;
954
    case 0x25:/*LHU*/   //r[rt]= (unsigned short)mem_read(s,2,ptr,1);
955 53 ja_rd
                        start_load(s, ptr, rt, (unsigned short)mem_read(s,2,ptr,1));
956 31 ja_rd
                        break;
957 105 ja_rd
    case 0x26:/*LWR*/   mem_lwr(s, ptr, rt, 1);
958
                        //printf("LWR\n");
959 31 ja_rd
                        break;
960
    case 0x28:/*SB*/    mem_write(s,1,ptr,r[rt],1);  break;
961
    case 0x29:/*SH*/    mem_write(s,2,ptr,r[rt],1);  break;
962 105 ja_rd
    case 0x2a:/*SWL*/   mem_swl(s, ptr, r[rt], 1);
963
                        //printf("SWL\n");
964
                        break;
965 31 ja_rd
    case 0x2b:/*SW*/    mem_write(s,4,ptr,r[rt],1);  break;
966 105 ja_rd
    case 0x2e:/*SWR*/   mem_swr(s, ptr, r[rt], 1);
967
                        //printf("SWR\n");
968
                        break;
969
    case 0x2f:/*CACHE*/ unimplemented(s,"CACHE");
970
                        break;
971
    case 0x30:/*LL*/    //unimplemented(s,"LL");
972 53 ja_rd
                        start_load(s, ptr, rt, mem_read(s,4,ptr,1));
973 31 ja_rd
                        break;
974 2 ja_rd
//      case 0x31:/*LWC1*/ break;
975
//      case 0x32:/*LWC2*/ break;
976
//      case 0x33:/*LWC3*/ break;
977
//      case 0x35:/*LDC1*/ break;
978
//      case 0x36:/*LDC2*/ break;
979
//      case 0x37:/*LDC3*/ break;
980
//      case 0x38:/*SC*/     *(int*)ptr=r[rt]; r[rt]=1; break;
981 31 ja_rd
    case 0x38:/*SC*/    mem_write(s,4,ptr,r[rt],1); r[rt]=1; break;
982 2 ja_rd
//      case 0x39:/*SWC1*/ break;
983
//      case 0x3a:/*SWC2*/ break;
984
//      case 0x3b:/*SWC3*/ break;
985
//      case 0x3d:/*SDC1*/ break;
986
//      case 0x3e:/*SDC2*/ break;
987
//      case 0x3f:/*SDC3*/ break;
988 31 ja_rd
    default:
989
        /* FIXME should trap unimplemented opcodes */
990
        printf("ERROR2 address=0x%x opcode=0x%x\n", s->pc, opcode);
991
        s->wakeup=1;
992
    }
993 53 ja_rd
 
994
    /* adjust next PC if this was a ajump instruction */
995 31 ja_rd
    s->pc_next += (branch || lbranch == 1) ? imm_shift : 0;
996
    s->pc_next &= ~3;
997
    s->skip = (lbranch == 0) | skip2;
998 2 ja_rd
 
999 31 ja_rd
    /* If there was trouble (failed assertions), log it */
1000
    if(s->failed_assertions!=0){
1001
        log_failed_assertions(s);
1002
        s->failed_assertions=0;
1003
    }
1004 5 ja_rd
 
1005 31 ja_rd
    /* if there's a delayed load pending, do it now: load reg with memory data*/
1006
    /* load delay slots not simulated */
1007 2 ja_rd
 
1008 31 ja_rd
    /* Handle exceptions */
1009
   if(s->exceptionId){
1010
        r[rt] = rSave;
1011
        s->cp0_cause = (s->delay_slot & 0x1) << 31 | (trap_cause & 0x1f);
1012
        /* adjust epc if we (i.e. the victim instruction) are in a delay slot */
1013
        if(s->delay_slot){
1014 27 ja_rd
        epc = epc - 4;
1015 31 ja_rd
        }
1016
        s->epc = epc;
1017 61 ja_rd
        s->pc_next = VECTOR_TRAP;
1018 31 ja_rd
        s->skip = 1;
1019
        s->exceptionId = 0;
1020
        s->userMode = 0;
1021
        //s->wakeup = 1;
1022
    }
1023 27 ja_rd
 
1024 53 ja_rd
    /* if we're NOT showing output to console, log state of CPU to file */
1025
    if(!show_mode){
1026
        log_cycle(s);
1027
    }
1028
 
1029
 
1030
 
1031 31 ja_rd
    /* if this instruction was any kind of branch that actually jumped, then
1032
       the next instruction will be in a delay slot. Remember it. */
1033
    delay_slot = ((lbranch==1) || branch || delay_slot);
1034
    s->delay_slot = delay_slot;
1035 2 ja_rd
}
1036
 
1037
/** Dump CPU state to console */
1038 31 ja_rd
void show_state(t_state *s){
1039
    int i,j;
1040
    printf("pid=%d userMode=%d, epc=0x%x\n", s->processId, s->userMode, s->epc);
1041
    printf("hi=0x%08x lo=0x%08x\n", s->hi, s->lo);
1042
    for(i = 0; i < 4; ++i){
1043
        printf("%2.2d ", i * 8);
1044
        for(j = 0; j < 8; ++j){
1045
            printf("%8.8x ", s->r[i*8+j]);
1046
        }
1047
        printf("\n");
1048
    }
1049
    //printf("%8.8lx %8.8lx %8.8lx %8.8lx\n", s->pc, s->pc_next, s->hi, s->lo);
1050
    j = s->pc;
1051
    for(i = -4; i <= 8; ++i){
1052
        printf("%c", i==0 ? '*' : ' ');
1053
        s->pc = j + i * 4;
1054
        cycle(s, 10);
1055
    }
1056
    s->pc = j;
1057 2 ja_rd
}
1058
 
1059
/** Show debug monitor prompt and execute user command */
1060 105 ja_rd
void do_debug(t_state *s, uint32_t no_prompt){
1061 31 ja_rd
    int ch;
1062 105 ja_rd
    int i, j=0, watch=0, addr;
1063
    j = s->breakpoint;
1064 31 ja_rd
    s->pc_next = s->pc + 4;
1065
    s->skip = 0;
1066 105 ja_rd
    s->wakeup = 0;
1067
 
1068
    printf("Starting simulation.\n");
1069
 
1070
    if(no_prompt){
1071
        ch = '5'; /* 'go' command */
1072
        printf("\n\n");
1073
    }
1074
    else{
1075
        show_state(s);
1076
        ch = ' ';
1077
    }
1078
 
1079 31 ja_rd
    for(;;){
1080 105 ja_rd
        if(ch != 'n' && !no_prompt){
1081 31 ja_rd
            if(watch){
1082
                printf("0x%8.8x=0x%8.8x\n", watch, mem_read(s, 4, watch,0));
1083 2 ja_rd
            }
1084 31 ja_rd
            printf("1=Debug 2=t_trace 3=Step 4=BreakPt 5=Go 6=Memory ");
1085 93 ja_rd
            printf("7=Watch 8=Jump 9=Quit A=Dump\n");
1086
            printf("L=LogTrigger > ");
1087 31 ja_rd
        }
1088 105 ja_rd
        if(ch==' ') ch = getch();
1089 31 ja_rd
        if(ch != 'n'){
1090
            printf("\n");
1091
        }
1092
        switch(ch){
1093
        case 'a': case 'A':
1094
            dump_trace_buffer(s); break;
1095
        case '1': case 'd': case ' ':
1096
            cycle(s, 0); show_state(s); break;
1097
        case 'n':
1098
            cycle(s, 1); break;
1099
        case '2': case 't':
1100
            cycle(s, 0); printf("*"); cycle(s, 10); break;
1101
        case '3': case 's':
1102
            printf("Count> ");
1103
            scanf("%d", &j);
1104
            for(i = 0; i < j; ++i){
1105
                cycle(s, 1);
1106
            }
1107
            show_state(s);
1108
            break;
1109
        case '4': case 'b':
1110
            printf("Line> ");
1111
            scanf("%x", &j);
1112
            printf("break point=0x%x\n", j);
1113
            break;
1114
        case '5': case 'g':
1115
            s->wakeup = 0;
1116 2 ja_rd
            cycle(s, 0);
1117 31 ja_rd
            while(s->wakeup == 0){
1118
                if(s->pc == j){
1119
                    printf("\n\nStop: pc = 0x%08x\n\n", j);
1120
                    break;
1121
                }
1122
                cycle(s, 0);
1123 105 ja_rd
            }
1124
            if(no_prompt) return;
1125 31 ja_rd
            show_state(s);
1126
            break;
1127
        case 'G':
1128
            s->wakeup = 0;
1129 2 ja_rd
            cycle(s, 1);
1130 31 ja_rd
            while(s->wakeup == 0){
1131
                if(s->pc == j){
1132
                    break;
1133
                }
1134
                cycle(s, 1);
1135
            }
1136
            show_state(s);
1137
            break;
1138
        case '6': case 'm':
1139
            printf("Memory> ");
1140
            scanf("%x", &j);
1141
            for(i = 0; i < 8; ++i){
1142
                printf("%8.8x ", mem_read(s, 4, j+i*4, 0));
1143
            }
1144
            printf("\n");
1145
            break;
1146
        case '7': case 'w':
1147
            printf("Watch> ");
1148
            scanf("%x", &watch);
1149
            break;
1150
        case '8': case 'j':
1151
            printf("Jump> ");
1152
            scanf("%x", &addr);
1153
            s->pc = addr;
1154
            s->pc_next = addr + 4;
1155
            show_state(s);
1156 93 ja_rd
            break;
1157
        case '9': case 'q':
1158
            return;
1159
        case 'l':
1160
            printf("Address> ");
1161
            scanf("%x", &(s->t.log_trigger_address));
1162
            printf("Log trigger address=0x%x\n", s->t.log_trigger_address);
1163 31 ja_rd
            break;
1164 105 ja_rd
        }
1165
        ch = ' ';
1166 31 ja_rd
    }
1167 2 ja_rd
}
1168
 
1169
/** Read binary code and data files */
1170 61 ja_rd
int read_binary_files(t_state *s, t_args *args){
1171 31 ja_rd
    FILE *in;
1172 105 ja_rd
    uint8_t *target;
1173
    uint32_t bytes=0, i, files_read=0;
1174 2 ja_rd
 
1175 31 ja_rd
    for(i=0;i<NUM_MEM_BLOCKS;i++){
1176 105 ja_rd
        bytes = 0;
1177 61 ja_rd
        if(args->bin_filename[i]!=NULL){
1178
 
1179
            in = fopen(args->bin_filename[i], "rb");
1180 31 ja_rd
            if(in == NULL){
1181 44 ja_rd
                free_cpu(s);
1182 61 ja_rd
                printf("Can't open file %s, quitting!\n",args->bin_filename[i]);
1183
                return(0);
1184 31 ja_rd
            }
1185 2 ja_rd
 
1186 105 ja_rd
            /* FIXME load offset 0x2000 for linux kernel hardcoded! */
1187
            //bytes = fread((s->blocks[i].mem + 0x2000), 1, s->blocks[i].size, in);
1188
            target = (uint8_t *)(s->blocks[i].mem + args->offset[i]);
1189
            while(!feof(in) &&
1190
                  ((bytes+1024+args->offset[i]) < (s->blocks[i].size))){
1191
                bytes += fread(&(target[bytes]), 1, 1024, in);
1192
                if(errno!=0){
1193
                    printf("ERROR: file load failed with code %d ('%s')\n",
1194
                        errno, strerror(errno));
1195
                    free_cpu(s);
1196
                    return 0;
1197
                }
1198
            }
1199
 
1200 31 ja_rd
            fclose(in);
1201 105 ja_rd
 
1202
            /* Now reverse the endianness of the data we just read, if it's
1203
             necessary. */
1204
             /* FIXME add cmd line param, etc. */
1205
            //reverse_endianess(target, bytes);
1206
 
1207 31 ja_rd
            files_read++;
1208
        }
1209 105 ja_rd
        printf("%-16s [size= %6dKB, start= 0x%08x] loaded %d bytes.\n",
1210
                s->blocks[i].area_name,
1211
                s->blocks[i].size/1024,
1212
                s->blocks[i].start,
1213
                bytes);
1214 31 ja_rd
    }
1215
 
1216
    if(!files_read){
1217 44 ja_rd
        free_cpu(s);
1218 31 ja_rd
        printf("No binary object files read, quitting\n");
1219 44 ja_rd
        return 0;
1220 31 ja_rd
    }
1221
 
1222 44 ja_rd
    return files_read;
1223 2 ja_rd
}
1224 105 ja_rd
 
1225
void reverse_endianess(uint8_t *data, uint32_t bytes){
1226
    uint8_t w[4];
1227
    uint32_t i, j;
1228
 
1229
    for(i=0;i<bytes;i=i+4){
1230
        for(j=0;j<4;j++){
1231
            w[3-j] = data[i+j];
1232
        }
1233
        for(j=0;j<4;j++){
1234
            data[i+j] = w[j];
1235
        }
1236
    }
1237
}
1238
 
1239 2 ja_rd
 
1240
/*----------------------------------------------------------------------------*/
1241
 
1242 31 ja_rd
int main(int argc,char *argv[]){
1243
    t_state state, *s=&state;
1244 105 ja_rd
 
1245
    /* Parse command line and pass any relevant arguments to CPU record */
1246
    if(parse_cmd_line(argc,argv, &cmd_line_args)==0){
1247
        return 0;
1248
    }
1249 2 ja_rd
 
1250 61 ja_rd
    printf("MIPS-I emulator (" __DATE__ ")\n\n");
1251 105 ja_rd
    if(!init_cpu(s, &cmd_line_args)){
1252 44 ja_rd
        printf("Trouble allocating memory, quitting!\n");
1253
        return 1;
1254
    };
1255 61 ja_rd
 
1256 93 ja_rd
    /* Read binary object files into memory*/
1257 61 ja_rd
    if(!read_binary_files(s, &cmd_line_args)){
1258 31 ja_rd
        return 2;
1259
    }
1260 61 ja_rd
    printf("\n\n");
1261 2 ja_rd
 
1262 93 ja_rd
    init_trace_buffer(s, &cmd_line_args);
1263 2 ja_rd
 
1264 31 ja_rd
    /* NOTE: Original mlite supported loading little-endian code, which this
1265 2 ja_rd
      program doesn't. The endianess-conversion code has been removed.
1266 31 ja_rd
    */
1267 2 ja_rd
 
1268 31 ja_rd
    /* Simulate a CPU reset */
1269 105 ja_rd
    reset_cpu(s);
1270
 
1271
    /* Simulate the work of the uClinux bootloader */
1272
    if(cmd_line_args.memory_map == MAP_UCLINUX){
1273
        /* FIXME this is a stub, flesh it out */
1274
        s->pc = 0x80002400;
1275
    }
1276 2 ja_rd
 
1277 31 ja_rd
    /* Enter debug command interface; will only exit clean with user command */
1278 105 ja_rd
    do_debug(s, cmd_line_args.no_prompt);
1279 2 ja_rd
 
1280 31 ja_rd
    /* Close and deallocate everything and quit */
1281
    close_trace_buffer(s);
1282
    free_cpu(s);
1283
    return(0);
1284 2 ja_rd
}
1285
 
1286
/*----------------------------------------------------------------------------*/
1287
 
1288
 
1289 93 ja_rd
void init_trace_buffer(t_state *s, t_args *args){
1290 31 ja_rd
    int i;
1291 2 ja_rd
 
1292
#if FILE_LOGGING_DISABLED
1293 31 ja_rd
    s->t.log = NULL;
1294 93 ja_rd
    s->t.log_triggered = 0;
1295 31 ja_rd
    return;
1296 2 ja_rd
#else
1297 93 ja_rd
    /* clear trace buffer */
1298 31 ja_rd
    for(i=0;i<TRACE_BUFFER_SIZE;i++){
1299
        s->t.buf[i]=0xffffffff;
1300
    }
1301
    s->t.next = 0;
1302 2 ja_rd
 
1303 31 ja_rd
    /* if file logging is enabled, open log file */
1304 93 ja_rd
    if(args->log_file_name!=NULL){
1305
        s->t.log = fopen(args->log_file_name, "w");
1306 31 ja_rd
        if(s->t.log==NULL){
1307
            printf("Error opening log file '%s', file logging disabled\n",
1308 93 ja_rd
                    args->log_file_name);
1309 31 ja_rd
        }
1310
    }
1311
    else{
1312
        s->t.log = NULL;
1313
    }
1314 93 ja_rd
 
1315
    /* Setup log trigger */
1316
    s->t.log_triggered = 0;
1317
    s->t.log_trigger_address = args->log_trigger_address;
1318 2 ja_rd
#endif
1319
}
1320
 
1321
/** Dumps last jump targets as a chunk of hex numbers (older is left top) */
1322 31 ja_rd
void dump_trace_buffer(t_state *s){
1323
    int i, col;
1324 2 ja_rd
 
1325 31 ja_rd
    for(i=0, col=0;i<TRACE_BUFFER_SIZE;i++, col++){
1326
        printf("%08x ", s->t.buf[s->t.next + i]);
1327
        if((col % 8)==7){
1328
            printf("\n");
1329
        }
1330
    }
1331 2 ja_rd
}
1332
 
1333
/** Logs last cycle's activity (changes in state and/or loads/stores) */
1334 31 ja_rd
void log_cycle(t_state *s){
1335
    static unsigned int last_pc = 0;
1336
    int i;
1337 53 ja_rd
    uint32_t log_pc;
1338 2 ja_rd
 
1339 31 ja_rd
    /* store PC in trace buffer only if there was a jump */
1340
    if(s->pc != (last_pc+4)){
1341
        s->t.buf[s->t.next] = s->pc;
1342
        s->t.next = (s->t.next + 1) % TRACE_BUFFER_SIZE;
1343
    }
1344
    last_pc = s->pc;
1345 2 ja_rd
 
1346 31 ja_rd
    /* if file logging is enabled, dump a trace log to file */
1347 93 ja_rd
    if(log_enabled(s)){
1348 53 ja_rd
        log_pc = s->op_addr;
1349
 
1350 31 ja_rd
        for(i=0;i<32;i++){
1351
            if(s->t.pr[i] != s->r[i]){
1352 53 ja_rd
                fprintf(s->t.log, "(%08X) [%02X]=%08X\n", log_pc, i, s->r[i]);
1353 31 ja_rd
            }
1354
            s->t.pr[i] = s->r[i];
1355
        }
1356
        if(s->lo != s->t.lo){
1357 53 ja_rd
            fprintf(s->t.log, "(%08X) [LO]=%08X\n", log_pc, s->lo);
1358 31 ja_rd
        }
1359
        s->t.lo = s->lo;
1360 2 ja_rd
 
1361 31 ja_rd
        if(s->hi != s->t.hi){
1362 53 ja_rd
            fprintf(s->t.log, "(%08X) [HI]=%08X\n", log_pc, s->hi);
1363 31 ja_rd
        }
1364
        s->t.hi = s->hi;
1365 2 ja_rd
 
1366 53 ja_rd
        /* */
1367
        /* FIXME epc may change by direct write too, handle case */
1368 31 ja_rd
        if(s->epc != s->t.epc){
1369 53 ja_rd
            fprintf(s->t.log, "(%08X) [EP]=%08X\n", log_pc, s->epc);
1370 31 ja_rd
        }
1371
        s->t.epc = s->epc;
1372
    }
1373 2 ja_rd
}
1374
 
1375
/** Frees debug buffers and closes log file */
1376 31 ja_rd
void close_trace_buffer(t_state *s){
1377
    if(s->t.log){
1378
        fclose(s->t.log);
1379
    }
1380 2 ja_rd
}
1381 5 ja_rd
 
1382
/** Logs a message for each failed assertion, each in a line */
1383 31 ja_rd
void log_failed_assertions(t_state *s){
1384
    unsigned bitmap = s->failed_assertions;
1385
    int i = 0;
1386 5 ja_rd
 
1387 31 ja_rd
    /* This loop will crash the program if the message table is too short...*/
1388
    if(s->t.log != NULL){
1389
        for(i=0;i<32;i++){
1390
            if(bitmap & 0x1){
1391
                fprintf(s->t.log, "ASSERTION FAILED: [%08x] %s\n",
1392
                        s->faulty_address,
1393
                        assertion_messages[i]);
1394
            }
1395
            bitmap = bitmap >> 1;
1396
        }
1397
    }
1398 5 ja_rd
}
1399 31 ja_rd
 
1400 93 ja_rd
uint32_t log_enabled(t_state *s){
1401
    return ((s->t.log != NULL) && (s->t.log_triggered!=0));
1402
}
1403
 
1404
void trigger_log(t_state *s){
1405
    uint32_t i;
1406
 
1407
    s->t.log_triggered = 1;
1408
 
1409
    for(i=0;i<32;i++){
1410
        s->t.pr[i] = s->r[i];
1411
    }
1412
 
1413
    s->t.lo = s->lo;
1414
    s->t.hi = s->hi;
1415
    s->t.epc = s->epc;
1416
}
1417
 
1418 31 ja_rd
void free_cpu(t_state *s){
1419
    int i;
1420
 
1421
    for(i=0;i<NUM_MEM_BLOCKS;i++){
1422
        free(s->blocks[i].mem);
1423
        s->blocks[i].mem = NULL;
1424
    }
1425
}
1426
 
1427
void reset_cpu(t_state *s){
1428
    s->pc = VECTOR_RESET;     /* reset start vector */
1429
    s->delay_slot = 0;
1430
    s->failed_assertions = 0; /* no failed assertions pending */
1431
}
1432 105 ja_rd
 
1433
void unimplemented(t_state *s, const char *txt){
1434
    /* FIXME unimplemented opcode trap */
1435
    printf("UNIMPLEMENTED: %s\n", txt);
1436
}
1437 31 ja_rd
 
1438 105 ja_rd
int init_cpu(t_state *s, t_args *args){
1439
    int i, j;
1440
    uint32_t k = args->memory_map;
1441 44 ja_rd
 
1442 31 ja_rd
    memset(s, 0, sizeof(t_state));
1443
    s->big_endian = 1;
1444 61 ja_rd
 
1445 105 ja_rd
    s->do_unaligned = args->do_unaligned;
1446
    s->breakpoint = args->breakpoint;
1447
 
1448 61 ja_rd
    /* Initialize memory map */
1449 31 ja_rd
    for(i=0;i<NUM_MEM_BLOCKS;i++){
1450 105 ja_rd
        s->blocks[i].start =        memory_maps[k].blocks[i].start;
1451
        s->blocks[i].size =         memory_maps[k].blocks[i].size;
1452
        s->blocks[i].area_name =    memory_maps[k].blocks[i].area_name;
1453
        s->blocks[i].mask =         memory_maps[k].blocks[i].mask;
1454
        s->blocks[i].read_only =    memory_maps[k].blocks[i].read_only;
1455 44 ja_rd
 
1456
        s->blocks[i].mem = (unsigned char*)malloc(s->blocks[i].size);
1457
 
1458
        if(s->blocks[i].mem == NULL){
1459
            for(j=0;j<i;j++){
1460
                free(s->blocks[j].mem);
1461
            }
1462
            return 0;
1463
        }
1464
        memset(s->blocks[i].mem, 0, s->blocks[i].size);
1465 105 ja_rd
    }
1466 44 ja_rd
    return NUM_MEM_BLOCKS;
1467 31 ja_rd
}
1468 61 ja_rd
 
1469
int32_t parse_cmd_line(uint32_t argc, char **argv, t_args *args){
1470
    uint32_t i;
1471
 
1472 105 ja_rd
    /* fill cmd line args with default values */
1473
    args->memory_map = MAP_DEFAULT;
1474
    args->do_unaligned = 0;
1475
    args->no_prompt = 0;
1476
    args->breakpoint = 0xffffffff;
1477
    args->log_file_name = "sw_sim_log.txt";
1478
    args->log_trigger_address = VECTOR_RESET;
1479 61 ja_rd
    for(i=0;i<NUM_MEM_BLOCKS;i++){
1480
        args->bin_filename[i] = NULL;
1481 105 ja_rd
        args->offset[i] = 0;
1482 61 ja_rd
    }
1483
 
1484
    /* parse actual cmd line args */
1485
    for(i=1;i<argc;i++){
1486
        if(strcmp(argv[i],"--plasma")==0){
1487 105 ja_rd
            /* plasma simulation not supported, error*/
1488
            printf("Error: program compiled for compatibility to MIPS-I\n");
1489
            return 0;
1490
        }
1491
        else if(strcmp(argv[i],"--uclinux")==0){
1492
            args->memory_map = MAP_UCLINUX;
1493
            /* FIXME selecting uClinux enables unaligned L/S emulation */
1494
            args->do_unaligned = 1;
1495 61 ja_rd
        }
1496 108 ja_rd
        else if(strcmp(argv[i],"--small")==0){
1497
            args->memory_map = MAP_SMALL;
1498
        }
1499 105 ja_rd
        else if(strcmp(argv[i],"--unaligned")==0){
1500
            args->do_unaligned = 1;
1501
        }
1502
        else if(strcmp(argv[i],"--noprompt")==0){
1503
            args->no_prompt = 1;
1504
        }
1505 61 ja_rd
        else if(strncmp(argv[i],"--bram=", strlen("--bram="))==0){
1506
            args->bin_filename[0] = &(argv[i][strlen("--bram=")]);
1507
        }
1508
        else if(strncmp(argv[i],"--flash=", strlen("--flash="))==0){
1509 105 ja_rd
            args->bin_filename[3] = &(argv[i][strlen("--flash=")]);
1510 61 ja_rd
        }
1511
        else if(strncmp(argv[i],"--xram=", strlen("--xram="))==0){
1512
            args->bin_filename[1] = &(argv[i][strlen("--xram=")]);
1513
        }
1514 105 ja_rd
        else if(strncmp(argv[i],"--kernel=", strlen("--kernel="))==0){
1515
            args->bin_filename[1] = &(argv[i][strlen("--kernel=")]);
1516
            /* FIXME uClinux kernel 'offset' hardcoded */
1517
            args->offset[1] = 0x2000;
1518
        }
1519 93 ja_rd
        else if(strncmp(argv[i],"--trigger=", strlen("--trigger="))==0){
1520
            sscanf(&(argv[i][strlen("--trigger=")]), "%x", &(args->log_trigger_address));
1521
        }
1522 105 ja_rd
        else if(strncmp(argv[i],"--breakpoint=", strlen("--breakpoint="))==0){
1523
            sscanf(&(argv[i][strlen("--breakpoint=")]), "%x", &(args->breakpoint));
1524
        }
1525 61 ja_rd
        else if((strcmp(argv[i],"--help")==0)||(strcmp(argv[i],"-h")==0)){
1526
            usage();
1527
            return 0;
1528
        }
1529
        else{
1530
            printf("unknown argument '%s'\n\n",argv[i]);
1531
            usage();
1532
            return 0;
1533
        }
1534
    }
1535
 
1536
    return 1;
1537
}
1538
 
1539
void usage(void){
1540
    printf("Usage:");
1541
    printf("    slite file.exe [arguments]\n");
1542
    printf("Arguments:\n");
1543
    printf("--bram=<file name>      : BRAM initialization file\n");
1544
    printf("--xram=<file name>      : XRAM initialization file\n");
1545 105 ja_rd
    printf("--kernel=<file name>    : XRAM initialization file for uClinux kernel\n");
1546
    printf("                          (loads at block offset 0x2000)\n");
1547 61 ja_rd
    printf("--flash=<file name>     : FLASH initialization file\n");
1548 93 ja_rd
    printf("--trigger=<hex number>  : Log trigger address\n");
1549 61 ja_rd
    printf("--plasma                : Simulate Plasma instead of MIPS-I\n");
1550 105 ja_rd
    printf("--uclinux               : Use memory map tailored to uClinux\n");
1551
    printf("--unaligned             : Implement unaligned load/store instructions\n");
1552
    printf("--noprompt              : Run in batch mode\n");
1553
    printf("--stop_at_zero          : Stop simulation when fetching from address 0x0\n");
1554 61 ja_rd
    printf("--help, -h              : Show this usage text\n");
1555
}
1556 105 ja_rd
 

powered by: WebSVN 2.1.0

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