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

Subversion Repositories ion

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

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

powered by: WebSVN 2.1.0

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