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

Subversion Repositories ion

[/] [ion/] [trunk/] [tools/] [slite/] [src/] [slite.c] - Diff between revs 166 and 169

Go to most recent revision | Show entire file | Details | Blame | View Log

Rev 166 Rev 169
Line 49... Line 49...
#include <assert.h>
#include <assert.h>
 
 
/** CPU identification code (contents of register CP0[15], PRId */
/** CPU identification code (contents of register CP0[15], PRId */
#define R3000_ID (0x00000200)
#define R3000_ID (0x00000200)
 
 
 
/** Number of hardware interrupt inputs (irq0 is NMI) */
 
#define NUM_HW_IRQS (8)
 
 
/** Set to !=0 to disable file logging (much faster simulation) */
/** Set to !=0 to disable file logging (much faster simulation) */
/* alternately you can just set an unreachable log trigger address */
/* alternately you can just set an unreachable log trigger address */
#define FILE_LOGGING_DISABLED (0)
#define FILE_LOGGING_DISABLED (0)
/** Define to enable cache simulation (unimplemented) */
/** Define to enable cache simulation (unimplemented) */
//#define ENABLE_CACHE
//#define ENABLE_CACHE
Line 300... Line 303...
 
 
 
 
/** Length of debugging jump target queue */
/** Length of debugging jump target queue */
#define TRACE_BUFFER_SIZE (32)
#define TRACE_BUFFER_SIZE (32)
 
 
 
/** Assorted debug & trace info */
typedef struct s_trace {
typedef struct s_trace {
   unsigned int buf[TRACE_BUFFER_SIZE];   /**< queue of last jump targets */
   unsigned int buf[TRACE_BUFFER_SIZE];   /**< queue of last jump targets */
   unsigned int next;                     /**< internal queue head pointer */
   unsigned int next;                     /**< internal queue head pointer */
   FILE *log;                             /**< text log file or NULL */
   FILE *log;                             /**< text log file or NULL */
   int log_triggered;                     /**< !=0 if log has been triggered */
   int log_triggered;                     /**< !=0 if log has been triggered */
   uint32_t log_trigger_address;          /**< */
   uint32_t log_trigger_address;          /**< */
   int pr[32];                            /**< last value of register bank */
   int pr[32];                            /**< last value of register bank */
   int hi, lo, epc, status;               /**< last value of internal regs */
   int hi, lo, epc, status;               /**< last value of internal regs */
   int disasm_ptr;                        /**< disassembly pointer */
   int disasm_ptr;                        /**< disassembly pointer */
 
   /** Cycles remaining to trigger irq[i], or -1 if irq inactive */
 
   int32_t irq_trigger_countdown[NUM_HW_IRQS];  /**< (in instructions) */
} t_trace;
} t_trace;
 
 
typedef struct s_state {
typedef struct s_state {
   unsigned failed_assertions;            /**< assertion bitmap */
   unsigned failed_assertions;            /**< assertion bitmap */
   unsigned faulty_address;               /**< addr that failed assertion */
   unsigned faulty_address;               /**< addr that failed assertion */
   uint32_t do_unaligned;                 /**< !=0 to enable unaligned L/S */
   uint32_t do_unaligned;                 /**< !=0 to enable unaligned L/S */
   uint32_t breakpoint;                   /**< BP address of 0xffffffff */
   uint32_t breakpoint;                   /**< BP address of 0xffffffff */
 
 
   int delay_slot;              /**< !=0 if prev. instruction was a branch */
   int delay_slot;              /**< !=0 if prev. instruction was a branch */
 
   uint32_t instruction_ctr;    /**< # of instructions executed since reset */
 
 
   int r[32];
   int r[32];
   int opcode;
   int opcode;
   int pc, pc_next, epc;
   int pc, pc_next, epc;
   uint32_t op_addr;            /**< address of opcode being simulated */
   uint32_t op_addr;            /**< address of opcode being simulated */
Line 436... Line 443...
void reverse_endianess(uint8_t *data, uint32_t bytes);
void reverse_endianess(uint8_t *data, uint32_t bytes);
 
 
/* Hardware simulation */
/* Hardware simulation */
int mem_read(t_state *s, int size, unsigned int address, int log);
int mem_read(t_state *s, int size, unsigned int address, int log);
void mem_write(t_state *s, int size, unsigned address, unsigned value, int log);
void mem_write(t_state *s, int size, unsigned address, unsigned value, int log);
 
void debug_reg_write(t_state *s, uint32_t address, uint32_t data);
void start_load(t_state *s, uint32_t addr, int rt, int data);
void start_load(t_state *s, uint32_t addr, int rt, int data);
 
uint32_t simulate_hw_irqs(t_state *s);
 
 
 
 
/*---- Local functions -------------------------------------------------------*/
/*---- Local functions -------------------------------------------------------*/
 
 
/*---- Call & ret tracing (EARLY DRAFT) --------------------------------------*/
/*---- Call & ret tracing (EARLY DRAFT) --------------------------------------*/
Line 614... Line 623...
 
 
    //log_read(s, full_address, value, size, log);
    //log_read(s, full_address, value, size, log);
    return(value);
    return(value);
}
}
 
 
/** Write memory */
/** Write to debug register */
 
void debug_reg_write(t_state *s, uint32_t address, uint32_t data){
 
 
 
    printf("DEBUG REG[%04x]=%08x\n", address & 0xffff, data);
 
}
 
 
 
/** Write to memory, including simulated i/o */
void mem_write(t_state *s, int size, unsigned address, unsigned value, int log){
void mem_write(t_state *s, int size, unsigned address, unsigned value, int log){
    unsigned int i, ptr, mask, dvalue, b0, b1, b2, b3;
    unsigned int i, ptr, mask, dvalue, b0, b1, b2, b3;
 
 
    if(log_enabled(s)){
    if(log_enabled(s)){
        b0 = value & 0x000000ff;
        b0 = value & 0x000000ff;
Line 666... Line 681...
                s->op_addr, address, mask, dvalue);
                s->op_addr, address, mask, dvalue);
    }
    }
 
 
    /* Print anything that's written to a debug register, otherwise ignore it */
    /* Print anything that's written to a debug register, otherwise ignore it */
    if((address&0xffff0000)==(DBG_REGS&0xffff0000)){
    if((address&0xffff0000)==(DBG_REGS&0xffff0000)){
        printf("DEBUG REG[%04x]=%08x\n", address & 0xffff, value);
        debug_reg_write(s, address, value);
        return;
        return;
    }
    }
 
 
    switch(address){
    switch(address){
    case UART_WRITE:
    case UART_WRITE:
Line 826... Line 841...
 
 
uint32_t count_leading(uint32_t lead, uint32_t src){
uint32_t count_leading(uint32_t lead, uint32_t src){
    uint32_t mask, bit_val, i;
    uint32_t mask, bit_val, i;
 
 
    mask = 0x80000000;
    mask = 0x80000000;
    bit_val = lead? mask : 0x0;
    bit_val = lead? 0xffffffff : 0x00000000;
 
 
    for(i=0;i<32;i++){
    for(i=0;i<32;i++){
        if((src & mask) != bit_val){
        if((src & mask) != (bit_val & mask)){
            return i;
            return i;
        }
        }
        mask = mask >> 1;
        mask = mask >> 1;
    }
    }
 
 
Line 935... Line 950...
    /* load delay slot not simulated */
    /* load delay slot not simulated */
    log_read(s, addr, data, 1, 1);
    log_read(s, addr, data, 1, 1);
    s->r[rt] = data;
    s->r[rt] = data;
}
}
 
 
 
void process_traps(t_state *s, uint32_t epc, uint32_t rSave, uint32_t rt){
 
    int32_t i, cause= -1;
 
 
 
    if(s->trap_cause>=0){
 
        /* If there is a software-triggered trap pending, deal with it */
 
        cause = s->trap_cause;
 
    }
 
    else{
 
        /* If there's any hardware interrupt pending, deal with it */
 
        for(i=0;i<NUM_HW_IRQS;i++){
 
            if(s->t.irq_trigger_countdown[i]==0){
 
                /* trigger interrupt i */
 
                /* FIXME handle irq mask(s) in SR */
 
                cause = 0; /* cause = hardware interrupt */
 
                s->t.irq_trigger_countdown[i]--;
 
            }
 
            else if (s->t.irq_trigger_countdown[i]>0){
 
                s->t.irq_trigger_countdown[i]--;
 
            }
 
        }
 
    }
 
 
 
    /* Now, whatever the cause was, do the trap handling */
 
    if(cause >= 0){
 
        s->trap_cause = cause;
 
        s->r[rt] = rSave; /* 'undo' current instruction (?) */
 
        /* set cause field ... */
 
        s->cp0_cause = (s->delay_slot & 0x1) << 31 | (s->trap_cause & 0x1f) << 2;
 
        /* ...save previous KU/IE flags in SR... */
 
        s->status = (s->status & 0xffffffc3) | ((s->status & 0x0f) << 2);
 
        /* ...and raise KU(EXL) kernel mode flag */
 
        s->status |= 0x02;
 
        /* adjust epc if we (i.e. the victim instruction) are in a delay slot */
 
        if(s->delay_slot){
 
            epc = epc - 4;
 
        }
 
        s->epc = epc;
 
        s->pc_next = VECTOR_TRAP;
 
        s->skip = 1;
 
        s->userMode = 0;
 
    }
 
}
 
 
/** Execute one cycle of the CPU (including any interlock stall cycles) */
/** Execute one cycle of the CPU (including any interlock stall cycles) */
void cycle(t_state *s, int show_mode){
void cycle(t_state *s, int show_mode){
    unsigned int opcode;
    unsigned int opcode;
    int delay_slot = 0; /* 1 of this instruction is a branch */
    int delay_slot = 0; /* 1 of this instruction is a branch */
    unsigned int op, rs, rt, rd, re, func, imm, target;
    unsigned int op, rs, rt, rd, re, func, imm, target;
Line 950... Line 1008...
    char format;
    char format;
    uint32_t aux;
    uint32_t aux;
    uint32_t target_offset16;
    uint32_t target_offset16;
    uint32_t target_long;
    uint32_t target_long;
 
 
 
    s->instruction_ctr++;
    s->trap_cause = -1;
    s->trap_cause = -1;
 
 
    /* fetch and decode instruction */
    /* fetch and decode instruction */
    opcode = mem_read(s, 4, s->pc, 0);
    opcode = mem_read(s, 4, s->pc, 0);
 
 
Line 1112... Line 1171...
                           log_call(s->pc_next, epc); break;
                           log_call(s->pc_next, epc); break;
        case 0x0a:/*MOVZ*/ if(!r[rt]) r[rd]=r[rs];   break;  /*IV*/
        case 0x0a:/*MOVZ*/ if(!r[rt]) r[rd]=r[rs];   break;  /*IV*/
        case 0x0b:/*MOVN*/ if(r[rt]) r[rd]=r[rs];    break;  /*IV*/
        case 0x0b:/*MOVN*/ if(r[rt]) r[rd]=r[rs];    break;  /*IV*/
        case 0x0c:/*SYSCALL*/ s->trap_cause = 8;
        case 0x0c:/*SYSCALL*/ s->trap_cause = 8;
                              /*
                              /*
                              FIXME enable when running uClinux
                              //FIXME enable when running uClinux
                              printf("SYSCALL (%08x)\n", s->pc);
                              printf("SYSCALL (%08x)\n", s->pc);
                              */
                              */
                              break;
                              break;
        case 0x0d:/*BREAK*/   s->trap_cause = 9;
        case 0x0d:/*BREAK*/   s->trap_cause = 9;
                              /*
                              /*
Line 1181... Line 1240...
    case 0x0d:/*ORI*/    r[rt]=r[rs]|imm;         break;
    case 0x0d:/*ORI*/    r[rt]=r[rs]|imm;         break;
    case 0x0e:/*XORI*/   r[rt]=r[rs]^imm;         break;
    case 0x0e:/*XORI*/   r[rt]=r[rs]^imm;         break;
    case 0x0f:/*LUI*/    r[rt]=(imm<<16);         break;
    case 0x0f:/*LUI*/    r[rt]=(imm<<16);         break;
    case 0x10:/*COP0*/
    case 0x10:/*COP0*/
        if(s->status & 0x02){ /* kernel mode? */
        if(s->status & 0x02){ /* kernel mode? */
            if((opcode & (1<<23)) == 0){  //move from CP0 (mfc0)
            if(opcode==0x42000010){  // rfe
                //printf("mfc0: [SR]=0x%08x @ [0x%08x]\n", s->status, epc);
                /* FIXME unimplemented yet */
 
            }
 
            else if((opcode & (1<<23)) == 0){  //move from CP0 (mfc0)
 
                //printf("mfc0: [%02d]=0x%08x @ [0x%08x]\n", rd, s->status, epc);
                switch(rd){
                switch(rd){
                    case 12: r[rt]=s->status & 0x0000003f; break;
                    case 12: r[rt]=s->status & 0x0000003f; break;
                    case 13: r[rt]=s->cp0_cause; break;
                    case 13: r[rt]=s->cp0_cause; break;
                    case 14: r[rt]=s->epc; break;
                    case 14: r[rt]=s->epc; break;
                    case 15: r[rt]=R3000_ID; break;
                    case 15: r[rt]=R3000_ID; break;
                    default:
                    default:
                        printf("mfc0 [%02d] @ [0x%08x]\n", rt, s->pc);
                        /* FIXME log access to unimplemented CP0 register */
 
                        printf("mfc0 [%02d]->%02d @ [0x%08x]\n", rd, rt,s->pc);
                        break;
                        break;
                }
                }
            }
            }
            else{                         //move to CP0 (mtc0)
            else{                         //move to CP0 (mtc0)
                /* FIXME check CF= reg address */
                /* FIXME check CF= reg address */
Line 1323... Line 1386...
    }
    }
 
 
    /* if there's a delayed load pending, do it now: load reg with memory data*/
    /* if there's a delayed load pending, do it now: load reg with memory data*/
    /* load delay slots not simulated */
    /* load delay slots not simulated */
 
 
    /* Handle exceptions */
    /* Handle exceptions, software and hardware */
   if(s->trap_cause>=0){
    /* Software-triggered traps have priority over HW interrupts, IIF they
        r[rt] = rSave;
       trigger in the same clock cycle. */
        /* set cause field ... */
    process_traps(s, epc, rSave, rt);
        s->cp0_cause = (s->delay_slot & 0x1) << 31 | (s->trap_cause & 0x1f) << 2;
 
        /* ...save previous KU/IE flags in SR... */
 
        s->status = (s->status & 0xffffffc3) | ((s->status & 0x0f) << 2);
 
        /* ...and raise KU(EXL) kernel mode flag */
 
        s->status |= 0x02;
 
        /* adjust epc if we (i.e. the victim instruction) are in a delay slot */
 
        if(s->delay_slot){
 
            epc = epc - 4;
 
        }
 
        s->epc = epc;
 
        s->pc_next = VECTOR_TRAP;
 
        s->skip = 1;
 
        s->userMode = 0;
 
        //s->wakeup = 1;
 
    }
 
 
 
    /* if we're NOT showing output to console, log state of CPU to file */
    /* if we're NOT showing output to console, log state of CPU to file */
    if(!show_mode){
    if(!show_mode){
        s->wakeup |= log_cycle(s);
        s->wakeup |= log_cycle(s);
    }
    }
 
 
 
 
 
 
    /* if this instruction was any kind of branch that actually jumped, then
    /* if this instruction was any kind of branch that actually jumped, then
       the next instruction will be in a delay slot. Remember it. */
       the next instruction will be in a delay slot. Remember it. */
    delay_slot = ((lbranch==1) || branch || delay_slot);
    delay_slot = ((lbranch==1) || branch || delay_slot);
    s->delay_slot = delay_slot;
    s->delay_slot = delay_slot;
}
}
Line 1914... Line 1960...
        s->blocks[i].mem = NULL;
        s->blocks[i].mem = NULL;
    }
    }
}
}
 
 
void reset_cpu(t_state *s){
void reset_cpu(t_state *s){
 
    uint32_t i;
 
 
    s->pc = cmd_line_args.start_addr; /* reset start vector or cmd line address */
    s->pc = cmd_line_args.start_addr; /* reset start vector or cmd line address */
    s->delay_slot = 0;
    s->delay_slot = 0;
    s->failed_assertions = 0; /* no failed assertions pending */
    s->failed_assertions = 0; /* no failed assertions pending */
    s->status = 0x02; /* kernel mode, interrupts disabled */
    s->status = 0x02; /* kernel mode, interrupts disabled */
 
    s->instruction_ctr = 0;
 
    for(i=0;i<NUM_HW_IRQS;i++){
 
        s->t.irq_trigger_countdown[i] = -1;
 
    }
    /* init trace struct to prevent spurious logs */
    /* init trace struct to prevent spurious logs */
    s->t.status = s->status;
    s->t.status = s->status;
}
}
 
 
/* FIXME redundant function, merge with reserved_opcode */
/* FIXME redundant function, merge with reserved_opcode */

powered by: WebSVN 2.1.0

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