Line 56... |
Line 56... |
#define VECTOR_TRAP (0x0000003c)
|
#define VECTOR_TRAP (0x0000003c)
|
|
|
typedef struct s_block {
|
typedef struct s_block {
|
uint32_t start;
|
uint32_t start;
|
uint32_t size;
|
uint32_t size;
|
|
uint32_t mask;
|
uint8_t *mem;
|
uint8_t *mem;
|
char *name;
|
char *name;
|
} t_block;
|
} t_block;
|
|
|
|
|
/* Here's where we define the memory areas (blocks) of the system */
|
/* Here's where we define the memory areas (blocks) of the system.
|
/* (make sure they don't overlap or the simulated program will crash) */
|
Memory decoding is done in the order the blocks are defined; the address
|
|
is anded with field .mask and then compared to field .start. If they match
|
|
the address modulo the field .size is used to index the memory block, giving
|
|
a 'mirror' effect. All of this simulates the behavior of the actual hardware.
|
|
Make sure the blocks don't overlap or the scheme will fail.
|
|
*/
|
|
|
#define NUM_MEM_BLOCKS (2)
|
#define NUM_MEM_BLOCKS (2)
|
|
|
t_block default_blocks[NUM_MEM_BLOCKS] = {
|
t_block default_blocks[NUM_MEM_BLOCKS] = {
|
/* meant as bootstrap block, though it's read/write */
|
/* meant as bootstrap block, though it's read/write */
|
{VECTOR_RESET, 0x00010000, NULL, "ROM"},
|
{VECTOR_RESET, 0x00010000, 0xf0000000, NULL, "Boot"},
|
/* main ram block */
|
/* main ram block */
|
{0x80000000, 0x00010000, NULL, "Data"}
|
{0x80000000, 0x00001000, 0xf0000000, NULL, "Data"}
|
};
|
};
|
|
|
|
|
#define ntohs(A) ( ((A)>>8) | (((A)&0xff)<<8) )
|
#define ntohs(A) ( ((A)>>8) | (((A)&0xff)<<8) )
|
#define htons(A) ntohs(A)
|
#define htons(A) ntohs(A)
|
Line 250... |
Line 256... |
void log_read(t_state *s, int full_address, int word_value, int size, int log);
|
void log_read(t_state *s, int full_address, int word_value, int size, int log);
|
void log_failed_assertions(t_state *s);
|
void log_failed_assertions(t_state *s);
|
|
|
/* CPU model */
|
/* CPU model */
|
void free_cpu(t_state *s);
|
void free_cpu(t_state *s);
|
void init_cpu(t_state *s);
|
int init_cpu(t_state *s);
|
void reset_cpu(t_state *s);
|
void reset_cpu(t_state *s);
|
|
|
/* 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);
|
Line 314... |
Line 320... |
}
|
}
|
|
|
/* point ptr to the byte in the block, or NULL is the address is unmapped */
|
/* point ptr to the byte in the block, or NULL is the address is unmapped */
|
ptr = 0;
|
ptr = 0;
|
for(i=0;i<NUM_MEM_BLOCKS;i++){
|
for(i=0;i<NUM_MEM_BLOCKS;i++){
|
if(address >= s->blocks[i].start &&
|
if((address & s->blocks[i].mask) == s->blocks[i].start){
|
address < s->blocks[i].start + s->blocks[i].size){
|
ptr = (unsigned)(s->blocks[i].mem) +
|
ptr = (unsigned)(s->blocks[i].mem) + address - s->blocks[i].start;
|
((address - s->blocks[i].start) % s->blocks[i].size);
|
break;
|
break;
|
}
|
}
|
}
|
}
|
if(!ptr){
|
if(!ptr){
|
/* address out of mapped blocks: log and return zero */
|
/* address out of mapped blocks: log and return zero */
|
Line 450... |
Line 456... |
if(address >= 0x80000000){
|
if(address >= 0x80000000){
|
ptr = 1;
|
ptr = 1;
|
}
|
}
|
ptr = 0;
|
ptr = 0;
|
for(i=0;i<NUM_MEM_BLOCKS;i++){
|
for(i=0;i<NUM_MEM_BLOCKS;i++){
|
if(address >= s->blocks[i].start &&
|
if((address & s->blocks[i].mask) == s->blocks[i].start){
|
address < s->blocks[i].start + s->blocks[i].size){
|
ptr = (unsigned)(s->blocks[i].mem) +
|
ptr = (unsigned)(s->blocks[i].mem) + address - s->blocks[i].start;
|
((address - s->blocks[i].start) % s->blocks[i].size);
|
break;
|
break;
|
}
|
}
|
}
|
}
|
if(!ptr){
|
if(!ptr){
|
/* address out of mapped blocks: log and return zero */
|
/* address out of mapped blocks: log and return zero */
|
Line 948... |
Line 954... |
}
|
}
|
|
|
/** Read binary code and data files */
|
/** Read binary code and data files */
|
int read_program(t_state *s, uint32_t num_files, char **file_names){
|
int read_program(t_state *s, uint32_t num_files, char **file_names){
|
FILE *in;
|
FILE *in;
|
uint32_t bytes, i, j, files_read=0;
|
uint32_t bytes, i, files_read=0;
|
|
|
for(i=0;i<NUM_MEM_BLOCKS;i++){
|
for(i=0;i<NUM_MEM_BLOCKS;i++){
|
if(i<num_files){
|
if(i<num_files){
|
in = fopen(file_names[i], "rb");
|
in = fopen(file_names[i], "rb");
|
if(in == NULL){
|
if(in == NULL){
|
for(j=0;j<i;j++){
|
free_cpu(s);
|
free(s->blocks[j].mem);
|
|
}
|
|
printf("Can't open file %s, quitting!\n",file_names[i]);
|
printf("Can't open file %s, quitting!\n",file_names[i]);
|
getch();
|
getch();
|
return(2);
|
return(2);
|
}
|
}
|
|
|
s->blocks[i].mem = (unsigned char*)malloc(s->blocks[i].size);
|
|
|
|
if(s->blocks[i].mem == NULL){
|
|
for(j=0;j<i;j++){
|
|
free(s->blocks[j].mem);
|
|
}
|
|
printf("Can't allocate %d bytes, quitting!\n",
|
|
s->blocks[i].size);
|
|
getch();
|
|
return(2);
|
|
}
|
|
|
|
memset(s->blocks[i].mem, 0, s->blocks[i].size);
|
|
|
|
bytes = fread(s->blocks[i].mem, 1, s->blocks[i].size, in);
|
bytes = fread(s->blocks[i].mem, 1, s->blocks[i].size, in);
|
fclose(in);
|
fclose(in);
|
printf("%-16s [size= %6d, start= 0x%08x]\n",
|
printf("%-16s [size= %6d, start= 0x%08x]\n",
|
s->blocks[i].name,
|
s->blocks[i].name,
|
bytes,
|
bytes,
|
Line 990... |
Line 980... |
break;
|
break;
|
}
|
}
|
}
|
}
|
|
|
if(!files_read){
|
if(!files_read){
|
|
free_cpu(s);
|
printf("No binary object files read, quitting\n");
|
printf("No binary object files read, quitting\n");
|
}
|
return 0;
|
else{
|
|
for(i=files_read;i<NUM_MEM_BLOCKS;i++){
|
|
s->blocks[i].mem = (unsigned char*)malloc(s->blocks[i].size);
|
|
|
|
if(s->blocks[i].mem == NULL){
|
|
for(j=0;j<i;j++){
|
|
free(s->blocks[j].mem);
|
|
}
|
|
printf("Can't allocate %d bytes, quitting!\n",
|
|
s->blocks[i].size);
|
|
getch();
|
|
return(2);
|
|
}
|
|
}
|
|
}
|
}
|
|
|
return 0;
|
return files_read;
|
}
|
}
|
|
|
/*----------------------------------------------------------------------------*/
|
/*----------------------------------------------------------------------------*/
|
|
|
int main(int argc,char *argv[]){
|
int main(int argc,char *argv[]){
|
t_state state, *s=&state;
|
t_state state, *s=&state;
|
|
|
printf("MIPS-I emulator\n");
|
printf("MIPS-I emulator\n");
|
init_cpu(s);
|
if(!init_cpu(s)){
|
|
printf("Trouble allocating memory, quitting!\n");
|
|
getch();
|
|
return 1;
|
|
};
|
|
|
/* do a minimal check on args */
|
/* do a minimal check on args */
|
if(argc==3 || argc==2){
|
if(argc==3 || argc==2){
|
/* */
|
/* */
|
}
|
}
|
Line 1029... |
Line 1010... |
printf("Usage:");
|
printf("Usage:");
|
printf(" slite file.exe <bin code file> [<bin data file>]\n");
|
printf(" slite file.exe <bin code file> [<bin data file>]\n");
|
return 0;
|
return 0;
|
}
|
}
|
|
|
if(read_program(s, argc-1, &(argv[1]))){
|
if(!read_program(s, argc-1, &(argv[1]))){
|
return 2;
|
return 2;
|
}
|
}
|
|
|
init_trace_buffer(s, "sw_sim_log.txt");
|
init_trace_buffer(s, "sw_sim_log.txt");
|
|
|
Line 1170... |
Line 1151... |
s->pc = VECTOR_RESET; /* reset start vector */
|
s->pc = VECTOR_RESET; /* reset start vector */
|
s->delay_slot = 0;
|
s->delay_slot = 0;
|
s->failed_assertions = 0; /* no failed assertions pending */
|
s->failed_assertions = 0; /* no failed assertions pending */
|
}
|
}
|
|
|
void init_cpu(t_state *s){
|
int init_cpu(t_state *s){
|
int i;
|
int i, j;
|
|
|
memset(s, 0, sizeof(t_state));
|
memset(s, 0, sizeof(t_state));
|
s->big_endian = 1;
|
s->big_endian = 1;
|
for(i=0;i<NUM_MEM_BLOCKS;i++){
|
for(i=0;i<NUM_MEM_BLOCKS;i++){
|
s->blocks[i].start = default_blocks[i].start;
|
s->blocks[i].start = default_blocks[i].start;
|
s->blocks[i].size = default_blocks[i].size;
|
s->blocks[i].size = default_blocks[i].size;
|
s->blocks[i].name = default_blocks[i].name;
|
s->blocks[i].name = default_blocks[i].name;
|
s->blocks[i].mem = NULL;
|
s->blocks[i].mask = default_blocks[i].mask;
|
|
|
|
s->blocks[i].mem = (unsigned char*)malloc(s->blocks[i].size);
|
|
|
|
if(s->blocks[i].mem == NULL){
|
|
for(j=0;j<i;j++){
|
|
free(s->blocks[j].mem);
|
|
}
|
|
return 0;
|
|
}
|
|
memset(s->blocks[i].mem, 0, s->blocks[i].size);
|
}
|
}
|
|
return NUM_MEM_BLOCKS;
|
}
|
}
|
|
|
No newline at end of file
|
No newline at end of file
|