diff --git a/util.c b/util.c new file mode 100644 index 0000000000000000000000000000000000000000..d74c9af870c061bb6e17edb605fee1d79eb5be46 --- /dev/null +++ b/util.c @@ -0,0 +1,292 @@ +/***************************************************************/ +/* */ +/* MIPS-32 Instruction Level Simulator */ +/* */ +/* SCE212 Ajou University */ +/* util.c */ +/* Adapted from CS311@KAIST */ +/* */ +/***************************************************************/ + +/* !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! */ +/* DO NOT MODIFY THIS FILE! */ +/* You should only the parse.c and run.c files! */ +/* !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! */ + +#include "util.h" + +/***************************************************************/ +/* Main memory. */ +/***************************************************************/ + +/* memory will be dynamically allocated at initialization */ +mem_region_t MEM_REGIONS[] = { + { MEM_TEXT_START, MEM_TEXT_SIZE, NULL }, + { MEM_DATA_START, MEM_DATA_SIZE, NULL }, +}; + +#define MEM_NREGIONS (sizeof(MEM_REGIONS)/sizeof(mem_region_t)) + +/***************************************************************/ +/* CPU State info. */ +/***************************************************************/ +CPU_State CURRENT_STATE; +int RUN_BIT; /* run bit */ +int INSTRUCTION_COUNT; + +/***************************************************************/ +/* CPU State info. */ +/***************************************************************/ +instruction *INST_INFO; +int NUM_INST; + +/***************************************************************/ +/* */ +/* Procedure: str_split */ +/* */ +/* Purpose: To parse main function argument */ +/* */ +/***************************************************************/ +char** str_split(char *a_str, const char a_delim) +{ + char** result = 0; + size_t count = 0; + char* tmp = a_str; + char* last_comma = 0; + char delim[2]; + delim[0] = a_delim; + delim[1] = 0; + + /* Count how many elements will be extracted. */ + while (*tmp) { + if (a_delim == *tmp) { + count++; + last_comma = tmp; + } + tmp++; + } + + /* Add space for trailing token. */ + count += last_comma < (a_str + strlen(a_str) - 1); + + /* Add space for terminating null string so caller + * knows where the list of returned strings ends. */ + count++; + + result = malloc(sizeof(char*) * count); + + if (result) { + size_t idx = 0; + char* token = strtok(a_str, delim); + + while (token) { + assert(idx < count); + *(result + idx++) = strdup(token); + token = strtok(0, delim); + } + assert(idx == count - 1); + *(result + idx) = 0; + } + + return result; +} + +/***************************************************************/ +/* */ +/* Procedure: fromBinary */ +/* */ +/* Purpose: From binary to integer */ +/* */ +/***************************************************************/ +int fromBinary(char *s) +{ + return (int) strtol(s, NULL, 2); +} + +/***************************************************************/ +/* */ +/* Procedure: mem_read_32 */ +/* */ +/* Purpose: Read a 32-bit word from memory */ +/* */ +/***************************************************************/ +uint32_t mem_read_32(uint32_t address) +{ + int i; + for (i = 0; i < MEM_NREGIONS; i++) { + if (address >= MEM_REGIONS[i].start && + address < (MEM_REGIONS[i].start + MEM_REGIONS[i].size)) { + uint32_t offset = address - MEM_REGIONS[i].start; + + return + (MEM_REGIONS[i].mem[offset+3] << 24) | + (MEM_REGIONS[i].mem[offset+2] << 16) | + (MEM_REGIONS[i].mem[offset+1] << 8) | + (MEM_REGIONS[i].mem[offset+0] << 0); + } + } + + return 0; +} + +/***************************************************************/ +/* */ +/* Procedure: mem_write_32 */ +/* */ +/* Purpose: Write a 32-bit word to memory */ +/* */ +/***************************************************************/ +void mem_write_32(uint32_t address, uint32_t value) +{ + int i; + for (i = 0; i < MEM_NREGIONS; i++) { + if (address >= MEM_REGIONS[i].start && + address < (MEM_REGIONS[i].start + MEM_REGIONS[i].size)) { + uint32_t offset = address - MEM_REGIONS[i].start; + + MEM_REGIONS[i].mem[offset+3] = (value >> 24) & 0xFF; + MEM_REGIONS[i].mem[offset+2] = (value >> 16) & 0xFF; + MEM_REGIONS[i].mem[offset+1] = (value >> 8) & 0xFF; + MEM_REGIONS[i].mem[offset+0] = (value >> 0) & 0xFF; + return; + } + } +} + +/***************************************************************/ +/* */ +/* Procedure : cycle */ +/* */ +/* Purpose : Execute a cycle */ +/* */ +/***************************************************************/ +void cycle() { + + process_instruction(); + INSTRUCTION_COUNT++; + + //for debug + //printf("%2d - Current PC: %x\n", INSTRUCTION_COUNT, CURRENT_STATE.PC); +} + +/***************************************************************/ +/* */ +/* Procedure : run n */ +/* */ +/* Purpose : Simulate MIPS for n cycles */ +/* */ +/***************************************************************/ +void run(int num_cycles) { + int i; + + if (RUN_BIT == FALSE) { + printf("Can't simulate, Simulator is halted\n\n"); + return; + } + + printf("Simulating for %d cycles...\n\n", num_cycles); + for (i = 0; i < num_cycles; i++) { + if (RUN_BIT == FALSE) { + printf("Simulator halted\n\n"); + break; + } + cycle(); + } +} + +/***************************************************************/ +/* */ +/* Procedure : go */ +/* */ +/* Purpose : Simulate MIPS until HALTed */ +/* */ +/***************************************************************/ +void go() { + if (RUN_BIT == FALSE) { + printf("Can't simulate, Simulator is halted\n\n"); + return; + } + + printf("Simulating...\n\n"); + while (RUN_BIT) + cycle(); + printf("Simulator halted\n\n"); +} + +/***************************************************************/ +/* */ +/* Procedure : mdump */ +/* */ +/* Purpose : Dump a word-aligned region of memory to the */ +/* output file. */ +/* */ +/***************************************************************/ +void mdump(int start, int stop) { + int address; + + printf("Memory content [0x%08x..0x%08x] :\n", start, stop); + printf("-------------------------------------\n"); + for (address = start; address <= stop; address += 4) + printf("0x%08x: 0x%08x\n", address, mem_read_32(address)); + printf("\n"); +} + +/***************************************************************/ +/* */ +/* Procedure : rdump */ +/* */ +/* Purpose : Dump current register and bus values to the */ +/* output file. */ +/* */ +/***************************************************************/ +void rdump() { + int k; + + printf("Current register values :\n"); + printf("-------------------------------------\n"); + printf("PC: 0x%08x\n", CURRENT_STATE.PC); + printf("Registers:\n"); + for (k = 0; k < MIPS_REGS; k++) + printf("R%d: 0x%08x\n", k, CURRENT_STATE.REGS[k]); + printf("\n"); +} + +/***************************************************************/ +/* */ +/* Procedure : init_memory */ +/* */ +/* Purpose : Allocate and zero memory */ +/* */ +/***************************************************************/ +void init_memory() { + int i; + for (i = 0; i < MEM_NREGIONS; i++) { + MEM_REGIONS[i].mem = malloc(MEM_REGIONS[i].size); + memset(MEM_REGIONS[i].mem, 0, MEM_REGIONS[i].size); + } +} + +/***************************************************************/ +/* */ +/* Procedure : init_inst_info */ +/* */ +/* Purpose : Initialize instruction info */ +/* */ +/***************************************************************/ +void init_inst_info() +{ + int i; + + for(i = 0; i < NUM_INST; i++) + { + INST_INFO[i].value = 0; + INST_INFO[i].opcode = 0; + INST_INFO[i].func_code = 0; + INST_INFO[i].r_t.r_i.rs = 0; + INST_INFO[i].r_t.r_i.rt = 0; + INST_INFO[i].r_t.r_i.r_i.r.rd = 0; + INST_INFO[i].r_t.r_i.r_i.imm = 0; + INST_INFO[i].r_t.r_i.r_i.r.shamt = 0; + INST_INFO[i].r_t.target = 0; + } +}