aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorm8pple <dt10@imperial.ac.uk>2015-10-19 16:11:51 +0100
committerm8pple <dt10@imperial.ac.uk>2015-10-19 16:11:51 +0100
commit974e8c2f125e57558dd273753d0c3095affcc847 (patch)
treec6a44e5511532fcf1d909cb87d7d625106dd06f9
parent0ae060da3961c3ec49a2648103c3799f5c4046a7 (diff)
downloadMipsCPU-974e8c2f125e57558dd273753d0c3095affcc847.tar.gz
MipsCPU-974e8c2f125e57558dd273753d0c3095affcc847.zip
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
-rw-r--r--src/eie2ugs/mips_cpu.cpp128
-rw-r--r--src/eie2ugs/test_mips.cpp131
2 files changed, 259 insertions, 0 deletions
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;
+}