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

Subversion Repositories ion

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

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

powered by: WebSVN 2.1.0

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