From 974e8c2f125e57558dd273753d0c3095affcc847 Mon Sep 17 00:00:00 2001 From: m8pple Date: Mon, 19 Oct 2015 16:11:51 +0100 Subject: Adding example eie2ugs code from live tutorial + recorded tutorial: https://panopto.imperial.ac.uk/Panopto/Pages/Viewer.aspx?id=653bf926-6acd-450f-991a-9cdbdf270852 https://panopto.imperial.ac.uk/Panopto/Pages/Viewer.aspx?id=fefdb6bc-4205-4113-bf3b-76ecefc201f2 https://panopto.imperial.ac.uk/Panopto/Pages/Viewer.aspx?id=c4966c37-effd-48f7-b5b9-ebdc5a30b2de --- src/eie2ugs/mips_cpu.cpp | 128 ++++++++++++++++++++++++++++++++++++++++++++ src/eie2ugs/test_mips.cpp | 131 ++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 259 insertions(+) create mode 100644 src/eie2ugs/mips_cpu.cpp create mode 100644 src/eie2ugs/test_mips.cpp diff --git a/src/eie2ugs/mips_cpu.cpp b/src/eie2ugs/mips_cpu.cpp new file mode 100644 index 0000000..475977e --- /dev/null +++ b/src/eie2ugs/mips_cpu.cpp @@ -0,0 +1,128 @@ +#include "mips.h" + +struct mips_cpu_impl +{ + uint32_t pc; + uint32_t pcNext; + + uint32_t regs[32]; + + mips_mem_h mem; + + unsigned logLevel; + FILE *logDst; +}; + + +mips_error mips_cpu_get_register( + mips_cpu_h state, //!< Valid (non-empty) handle to a CPU + unsigned index, //!< Index from 0 to 31 + uint32_t *value //!< Where to write the value to +) +{ + // TODO : error handling + *value = state->regs[index]; + return mips_Success; +} + +/*! Modifies one of the 32 general purpose MIPS registers. */ +mips_error mips_cpu_set_register( + mips_cpu_h state, //!< Valid (non-empty) handle to a CPU + unsigned index, //!< Index from 0 to 31 + uint32_t value //!< New value to write into register file +) +{ + // TODO : error handling + state->regs[index] = value; + return mips_Success; +} + +mips_error mips_cpu_set_debug_level(mips_cpu_h state, unsigned level, FILE *dest) +{ + state->logLevel = level; + state->logDst = dest; + return mips_Success; +} + +mips_cpu_h mips_cpu_create(mips_mem_h mem) +{ + mips_cpu_impl *cpu=new mips_cpu_impl; + + cpu->pc=0; + for(int i=0;i<32;i++){ + cpu->regs[i]=0; + } + cpu->mem=mem; + + return cpu; +} + +/*! \param pData Array of 4 bytes + \retval The big-endian equivlent +*/ +uint32_t to_big(const uint8_t *pData) +{ + return + (((uint32_t)pData[0])<<24) + | + (((uint32_t)pData[1])<<16) + | + (((uint32_t)pData[2])<<8) + | + (((uint32_t)pData[3])<<0); +} + +mips_error mips_cpu_step( + mips_cpu_h state //! Valid (non-empty) handle to a CPU +) +{ + uint8_t buffer[4]; + + mips_error err=mips_mem_read( + state->mem, //!< Handle to target memory + state->pc, //!< Byte address to start transaction at + 4, //!< Number of bytes to transfer + buffer //!< Receives the target bytes + ); + + if(err!=0){ + return err; + } + + uint32_t instruction= to_big(buffer); + + uint32_t opcode = (instruction>>26) & 0x3F; + uint32_t src1 = (instruction>> 21 ) & 0x1F; + uint32_t src2 = (instruction>> 16 ) & 0x1F; + uint32_t dst = (instruction>> 11 ) & 0x1F; + uint32_t shift = (instruction>> 6 ) & 0x1F ; + uint32_t function = (instruction>> 0 ) & 0x3F ; + + if(opcode == 0){ + // This is R-type + if(state->logLevel >= 2){ + fprintf(state->logDst, "R-Type : dst=%u, src1=%u, src2=%u, shift=%u, function=%u.\n instr=%08x\n", + dst, src1, src2, shift, function, instruction + ); + } + + if(function == 0x21){ + if(state->logLevel >= 1){ + fprintf(state->logDst, "addu %u, %u, %u.\n", dst, src1, src2); + } + uint32_t va=state->regs[src1]; + uint32_t vb=state->regs[src2]; + + uint32_t res=va+vb; + + state->regs[dst] = res; // NOTE: what about zero reg? + + // NOTE : What about updating the program counter + return mips_Success; + }else{ + return mips_ErrorNotImplemented; + } + }else{ + return mips_ErrorNotImplemented; + } +} diff --git a/src/eie2ugs/test_mips.cpp b/src/eie2ugs/test_mips.cpp new file mode 100644 index 0000000..26db856 --- /dev/null +++ b/src/eie2ugs/test_mips.cpp @@ -0,0 +1,131 @@ +#include "mips.h" + +int main() +{ + mips_mem_h mem=mips_mem_create_ram(4096, 4); + + mips_cpu_h cpu=mips_cpu_create(mem); + + mips_error e=mips_cpu_set_debug_level(cpu, 4, stderr); + if(e!=mips_Success){ + fprintf(stderr, "mips_cpu_set_debug_level : failed.\n"); + exit(1); + } + + + mips_test_begin_suite(); + + + int testId = mips_test_begin_test("addu"); + + // 1 - Setup an instruction in ram + // addu r3, r4, r5 + uint32_t instr = + (0ul << 26) // opcode = 0 + | + (4ul << 21) // srca = r4 + | + (5ul << 16) // srcb = r5 + | + (3ul << 11) // dst = r3 + | + (0ul << 6) // shift = 0 + | + (0x21 << 0); + + uint8_t buffer[4]; + buffer[0]=(instr>>24)&0xFF; + buffer[1]=(instr>>16)&0xFF; + buffer[2]=(instr>>8)&0xFF; + buffer[3]=(instr>>0)&0xFF; + + e=mips_mem_write( + mem, //!< Handle to target memory + 0, //!< Byte address to start transaction at + 4, //!< Number of bytes to transfer + buffer //!< Receives the target bytes + ); + if(e!=mips_Success){ + fprintf(stderr, "mips_mem_write : failed.\n"); + exit(1); + } + + // 2 - put register values in cpu + e=mips_cpu_set_register(cpu, 4, 40); + e=mips_cpu_set_register(cpu, 5, 50); + + // 3 - step CPU + e=mips_cpu_step(cpu); + if(e!=mips_Success){ + fprintf(stderr, "mips_cpu_step : failed.\n"); + exit(1); + } + + // 4 -Check the result + uint32_t got; + e=mips_cpu_get_register(cpu, 3, &got); + + + int passed = got == 40+50; + + mips_test_end_test(testId, passed, "50 + 50 != 90"); + + + testId = mips_test_begin_test("addu"); + + // 1 - Setup an instruction in ram + // addu r3, r4, r5 + instr = + (0ul << 26) // opcode = 0 + | + (4ul << 21) // srca = r4 + | + (5ul << 16) // srcb = r5 + | + (0ul << 11) // dst = r0 + | + (0ul << 6) // shift = 0 + | + (0x21 << 0); + + buffer[0]=(instr>>24)&0xFF; + buffer[1]=(instr>>16)&0xFF; + buffer[2]=(instr>>8)&0xFF; + buffer[3]=(instr>>0)&0xFF; + + e=mips_mem_write( + mem, //!< Handle to target memory + 0, //!< Byte address to start transaction at + 4, //!< Number of bytes to transfer + buffer //!< Receives the target bytes + ); + if(e!=mips_Success){ + fprintf(stderr, "mips_mem_write : failed.\n"); + exit(1); + } + + // 2 - put register values in cpu + e=mips_cpu_set_register(cpu, 4, 40); + e=mips_cpu_set_register(cpu, 5, 50); + + // 3 - step CPU + e=mips_cpu_step(cpu); + if(e!=mips_Success){ + fprintf(stderr, "mips_cpu_step : failed.\n"); + exit(1); + } + + // 4 -Check the result + e=mips_cpu_get_register(cpu, 0, &got); + + + passed = got == 0; + + mips_test_end_test(testId, passed, "r0 <> 0"); + + + + mips_test_end_suite(); + + return 0; +} -- cgit