aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDavid Thomas <m8pple@github.com>2016-10-10 06:27:37 +0100
committerDavid Thomas <m8pple@github.com>2016-10-10 06:27:37 +0100
commit0673cc3651b60203b90eccdc1c5af5e455f4b6fb (patch)
tree6c50f8b4387ebda2c647b8e7bd66d60884d1e557
parent969874832d55c00c1c5874ef5ae1fdb82b3ded83 (diff)
downloadMipsCPU-0673cc3651b60203b90eccdc1c5af5e455f4b6fb.tar.gz
MipsCPU-0673cc3651b60203b90eccdc1c5af5e455f4b6fb.zip
Updated for 2016.
-rw-r--r--README.md153
-rw-r--r--fragments/run_addu.cpp2
-rw-r--r--fragments/run_fibonacci.cpp2
-rw-r--r--include/mips_core.h13
-rw-r--r--include/mips_cpu.h4
-rw-r--r--include/mips_mem.h54
-rw-r--r--makefile51
-rw-r--r--src/eie2ugs/mips_cpu.cpp128
-rw-r--r--src/eie2ugs/test_mips.cpp131
-rw-r--r--src/shared/mips_mem_ram.cpp19
10 files changed, 169 insertions, 388 deletions
diff --git a/README.md b/README.md
index c71ea9e..63274f5 100644
--- a/README.md
+++ b/README.md
@@ -1,5 +1,9 @@
-Architecture II 2015, Coursework 1
-==================================
+Architecture II 2016, Coursework
+================================
+
+This is a living specification. Please feel free to post
+questions as issues, or submit pull requests if you see
+a chance for improvements.
Goals of this coursework
------------------------
@@ -10,7 +14,7 @@ There are three central aims of this coursework:
processor actually functions. The overall functionality
of how a processor works is relatively easy to grasp,
but there is lots of interesting detail which gives
- you a lot of insight (both into CPUs, but also into
+ you some insight (both into CPUs, but also into
software and digital design).
- Understand the importance of having good specifications,
@@ -21,12 +25,14 @@ There are three central aims of this coursework:
- Develop your skills in coding from scratch. There is
not much scaffolding here, I am genuinely asking you
- to create your own CPU simulator from scratch.
+ to create your own CPU simulator from scratch. You
+ will also hopefully learn some important lessons about
+ reducing code repetition and automation.
Coursework Deliverables
-----------------------
-There are two C/C++ components to this coursework:
+There are two C++ [deliverables](https://en.wikipedia.org/wiki/Deliverable) for this coursework:
1. Create a MIPS software simulator
@@ -44,32 +50,38 @@ the original directory structure and files, as well as the
files that you have contributed. The two key things you will
be adding are:
- - `src/[your_login]/mips_cpu.c` or `mips_cpu.cpp`
+ - `src/[your_login]/mips_cpu.cpp`
- - `src/[your_login]/test_mips.c` or `test_mips.cpp`
+ - `src/[your_login]/test_mips.cpp`
The first part is the implementation of a mips simulator, and
-is essentially a library that implements the api found in
-include/mips_cpu.h. You can use C or C++, either is fine.
+is essentially a library that implements the api found in [`include/mips_cpu.h`](include/mips_cpu.h).
If you want to split into multiple files, then feel free to do
-so - anything which matches the pattern `src/[your_login]/mips_cpu_*.c`
-or `src/[your_login]/mips_cpu_*.cpp` will also get compiled into
-your library.
+so - anything which matches the pattern `src/[your_login]/mips_cpu_*.cpp`
+or `src/[your_login]/mips_cpu_*/*.cpp` will also get compiled into your library.
+So the three types of source file that will get compiled into your CPU are:
+
+- `src/[your_login]/mips_cpu.cpp` (must exist)
+
+- `src/[your_login]/mips_cpu_*.cpp` (if any)
+
+- `src/[your_login]/mips_cpu_*/*.cpp` (if any)
The second part is the test suite which will drive your
-simulator and make it do things. This is a C or C++ program
-(so it will have a main function), and should be either
-`src/[your_login]/test_mips.c` or `src/[your_login]/test_mips.cpp`.
-Again, if you want to split into multiple files, anything
-that matches the pattern `src/[your_login]/test_mips_*.c` or
-`src/[your_login]/test_mips_*.cpp` will get compiled into
-your program.
-
-Update: by request, I will also include c or C++ files in
-directories matching `src/[your_login]/*`. See issue #2.
-
-You can also add your own private header files (generally
-a good idea), which should be part of the submitted zip file,
+simulator and make it do things. This is a C++ program
+(so it will have a main function) in a file called `src/[your_login]/test_mips.cpp`.
+Again, your can split it into multiple files, so anything
+that matches these patterns will get compiled in:
+
+- `src/[your_login]/test_mips.cpp` (must exist)
+
+- `src/[your_login]/test_mips_*.cpp` (if any)
+
+- `src/[your_login]/test_mips_*/*.cpp` (if any)
+
+
+You can also add your own private header files (often a good idea),
+which should be part of the submitted zip file,
but they don't need to follow any specific pattern. However,
they should be completely located within the `src/[your_login]`
directory or a sub-directory of it. Note that your simulator
@@ -82,33 +94,35 @@ The directory structure should look like:
.
+-readme.md # This document
|
- +-include
+ +-include # A directory that you don't own. Don't put things here.
| |
| +-mips.h
| +-mips_*.h # Other mips headers
|
+-src
| |
- | +-shared
+ | +-shared # This is shared with everyone. Don't put things here.
| | |
| | +-mips_mem_ram.cpp
| | +-mips_test_framework.cpp
| |
- | +-[your_login] # This is your private folder
+ | +-[your_login] # This is your private folder. Do whatever you like here.
| |
- | +-mips_cpu.c or mips_cpu.cpp
- | +-mips_cpu_*.c or mips_cpu_*.cpp (if you want them)
+ | +-mips_cpu.cpp
+ | +-mips_cpu_*.cpp (if you want them)
+ | +-mips_cpu_*/*.cpp (if you want them)
| |
- | +-test_mips.c or test_mips.cpp
- | +-test_mips_*.c or test_mips_*.cpp (if you want them)
+ | +-test_mips.cpp
+ | +-test_mips_*.cpp (if you want them)
+ | +-test_mips_*/*.cpp (if you want them)
| |
| +-(anything else you want, e.g. headers, docs)
|
- +-doc
+ +-doc # Used for doxygen (if generated)
|
- +-fragments # Some very simple examples of C, assembly, and binary code
+ +-fragments # Some simple shared examples of C, assembly, and binary code
|
- +-(anything else you want, but it won't be available in the environment)
+ +-(anything else you want, but it won't be available in the test environment)
Your submitted code will need to work within the
compilation environment specified later on (another
@@ -151,9 +165,9 @@ is weighted as follows:
even if you have a small number of instructions implemented,
as long as they are tested well.
-- (10%) Bug reports: This specification will not be perfect, and
+- (at most 10%) Bug reports: This specification will not be perfect, and
I welcome bug reports. Things like spelling mistakes are
- welcome, but not especially valuable. What is important
+ welcome, but not quite as valuable. What is important
are points of genuine ambiguity, or errors of implementation
in the code spec. Bug reports should identify both the
problem, and how to reproduce it, and particularly welcome are
@@ -165,17 +179,17 @@ Except for the marks for compilation (where everyone
should really get full marks, but is down to me assessing
how much manual work I needed to put in) and bug reports
(which are subjective and more rare) the assessment is
-entirely quantitative and metric based.
+quantitative and metric based.
There are two submission deadlines, one soft, one hard:
-- Friday 23th October 22:00: deadline for formative (ungraded)
+- Friday 21st October 22:00: deadline for formative (ungraded)
assessment. If you submit a version by this deadline, it
will be put through a subset of the assessment. The
- results (but not a grade), will be returned on Monday 26th.
+ results (but not a grade), will be returned on Monday 21st.
Submission is not required, but is obviously encouraged.
-- Friday 30th October 22:00: deadline for summative (graded)
+- Friday 28th October 22:00: deadline for summative (graded)
assessment. Whether or not you submitted for the previous
deadline, everyone must submit for this deadline. This
will be the part which results in the grade for this
@@ -197,7 +211,7 @@ APIs, as no platform-specific interaction with the environment is
needed during execution. So it should work happily on both linux
and windows.
-The actual target environment is the lab Ubuntu environment,
+The actual target environment is the lab Linux environment,
and the version of gcc/g++ installed there. You can develop
in Windows, MacOS, or another linux, but you need to make sure
it works in that environment.
@@ -347,6 +361,43 @@ difficult, but testing them can be more complex. The 4s are doable,
but have some complexity in implementation and testing. Implementing
the 5s correctly is really quite challenging.
+Plagiarism
+----------
+
+Everyone is implementing the same CPU, with the same API, which
+means that there will be a certain amount of similarity. However,
+there will also be differences, and you might be surprised by
+the amount of variation that ones sees. I do actually read your
+code too, and you'd be surprised how well the human brain remembers
+patterns and oddities, even across 40 submissions (particularly
+if that brain has been programming for some years). There are
+also ways of automatically looking for similarities for further
+review by a human.
+
+This coursework is also largely unchanged since last year, and
+substantially similar to the year before. You may well be able
+to get hold of someone's solution from a previous year. But
+bear in mind that I have a copy of every solution ever submitted
+for this coursework, in an easily searchable file structure.
+
+Please note that discussion is not plagiarism, and even showing
+each other your solutions is generally fine. It is interesting
+to see how someone else has solved the same problem, and even
+having seen their solution, you will not produce the same code
+(unless you stare at it and type it in). The point where it
+becomes plagiarism is when the code is shared between students - never
+give someone a copy of your code on a USB or give them access
+to a git repo.
+
+By far the most common type of plagiarism is where one (well-meaning)
+student give's another (well-meaning) student their submission so
+that they can "have a look". The receiver may then face time
+pressure, so despite the good intentions of all they end up using
+some bits and pieces from the originator's submission.
+Unfortunately, in such cases both students will be considered to
+have plagiarised.
+
+
Getting Started
---------------
@@ -372,10 +423,10 @@ You can get the source code either by:
if you're interested in that direction.
While it is not required, I would highly recommend that you try
-option 2 (I will use this route in class). It is good to get some
-experience of how source control works, and acting as a consumer is
-a good way of understanding what is going on. There are a number
-of GUI tools available which make things easier:
+option 2 (I will use this route in class), and option 3 is even better.
+It is good to get some experience of how source control works,
+and acting as a consumer is a good way of understanding what is going on.
+There are a number of GUI tools available which make things easier:
- The github GUI is available for [Windows](https://windows.github.com/),
[Mac](https://mac.github.com/).
@@ -434,9 +485,9 @@ helps to visualise how the hardware works.
Some Questions I've recieved
----------------------------
-Note to 2015 students: I ran almost the same coursework
-last year, so these are some questions from then. And
-as you would hope and expect, I still have all of their
+Note to 2016 students: I ran almost the same coursework
+the last two years, so these are some questions from then. And
+as I mentioned, I still have all of their
submissions in a readily accessible form should I choose
to diff them against this years submissions.
@@ -475,7 +526,7 @@ kind of memory, whether each operation behaves correctly
if it appears after a jump, and so on.
So you are correct that the test_mips file should define the
-functionality, but _only_ the functionality, it should say
+functionality, but _only_ the functionality - it should say
nothing about the implementation of that functionality. If
you know the initial state of a MIPS, plus the memory it
is attached to, you should be able to predict precisely what
@@ -575,7 +626,7 @@ better idea why it might be useful.
> did in the skeleton file?
You control the internals of the cpu state,
-so on the `mips_cpu.c` side, you can totally
+so on the `mips_cpu.cpp` side, you can totally
reach into `state->pc` and read it out. Or
you can use `mips_cpu_get_pc`. Either is fine,
because you are on the implementation side
diff --git a/fragments/run_addu.cpp b/fragments/run_addu.cpp
index effa24e..460548f 100644
--- a/fragments/run_addu.cpp
+++ b/fragments/run_addu.cpp
@@ -10,7 +10,7 @@ int main(int argc, char *argv[])
srcName=argv[1];
}
- mips_mem_h m=mips_mem_create_ram(0x20000, 4);
+ mips_mem_h m=mips_mem_create_ram(0x20000);
mips_cpu_h c=mips_cpu_create(m);
FILE *src=fopen(srcName,"rb");
diff --git a/fragments/run_fibonacci.cpp b/fragments/run_fibonacci.cpp
index 041d667..6017971 100644
--- a/fragments/run_fibonacci.cpp
+++ b/fragments/run_fibonacci.cpp
@@ -10,7 +10,7 @@ int main(int argc, char *argv[])
srcName=argv[1];
}
- mips_mem_h m=mips_mem_create_ram(0x20000, 4);
+ mips_mem_h m=mips_mem_create_ram(0x20000);
mips_cpu_h c=mips_cpu_create(m);
FILE *src=fopen(srcName,"rb");
diff --git a/include/mips_core.h b/include/mips_core.h
index 0733333..a59057b 100644
--- a/include/mips_core.h
+++ b/include/mips_core.h
@@ -10,7 +10,7 @@
matching the internal types of a processor, and for managing
conversions from signed to unsigned types. The C/C++ standard has certain
(very strict) rules for conversion between types, which are different from
- the rules of any particular CPU. In an extremely legalitic interpretation, the
+ the rules of any particular CPU. In an extremely legalistic interpretation, the
integer encoding is not necessarily twos complement, but we
will mandate that all target architectures use a twos complement
representation.
@@ -46,11 +46,12 @@ typedef enum _mips_error{
//! Error or exception from the simulated processor or program.
///@{
mips_ExceptionBreak=0x2000,
- mips_ExceptionInvalidAddress=0x2001,
- mips_ExceptionInvalidAlignment=0x2002,
- mips_ExceptionAccessViolation=0x2003,
- mips_ExceptionInvalidInstruction=0x2004,
- mips_ExceptionArithmeticOverflow=0x2005,
+ mips_ExceptionInvalidLength=0x2001,
+ mips_ExceptionInvalidAddress=0x2002,
+ mips_ExceptionInvalidAlignment=0x2003,
+ mips_ExceptionAccessViolation=0x2004,
+ mips_ExceptionInvalidInstruction=0x2005,
+ mips_ExceptionArithmeticOverflow=0x2006,
///@}
/*! This is an extension point for implementations. Codes
diff --git a/include/mips_cpu.h b/include/mips_cpu.h
index 96aaefe..a0da378 100644
--- a/include/mips_cpu.h
+++ b/include/mips_cpu.h
@@ -18,7 +18,7 @@ extern "C"{
/*! Represents the state of a cpu.
- This another opaque data type, similar to \ref mips_mem_provider.
+ This an opaque data type, similar to \ref mips_mem_provider.
\struct mips_cpu_impl
*/
@@ -191,7 +191,7 @@ mips_error mips_cpu_set_debug_level(mips_cpu_h state, unsigned level, FILE *dest
\param state Either a handle to a valid simulation state, or an empty (NULL) handle.
- It is legal to pass an empty handle to mips_cpu_free. It is illegal
+ It is legal to pass an empty (NULL) handle to mips_cpu_free. It is illegal
to pass the same non-empty handle to mips_cpu_free twice, and will
result in undefined behaviour (i.e. anything could happen):
diff --git a/include/mips_mem.h b/include/mips_mem.h
index 1b78c34..a419413 100644
--- a/include/mips_mem.h
+++ b/include/mips_mem.h
@@ -90,15 +90,12 @@ mips_error mips_mem_read(
/*! Perform a write transaction on the memory
The implementation is expected to check that the transaction
- matches the alignment and block size requirements, and return an
- error if they are violated.
+ matches the alignment requirements, and return an error if they are violated.
The input pointer is a pointer to bytes, because the RAM is byte
- addressable, however the transaction size may consist of multiple
- bytes - indeed, for memories with a block size greater than one,
- all transactions must be multiple bytes. To write a larger piece
- of data, you can use pointer casting, or pass in an array. For
- example, if I want to write 0xFF001100 to address 12, I could do:
+ addressable, however the transaction size may be 1, 2, or 4 bytes.
+ To write a larger piece of data, you can use pointer casting, or pass in an array.
+ For example, if I want to write 0xFF001100 to address 12, I could do:
uint32_t xv=0xFF001100;
mips_error err=mips_mem_write(mem, 12, 4, (uint8_t*)&xv);
@@ -175,41 +172,18 @@ void mips_mem_free(mips_mem_h mem);
/*! Initialise a new RAM of the given size.
- The RAM will expect transactions to be at the granularity
- of the blockSize. This means any reads or writes must be aligned
- to the correct blockSize, and should consist of an integer number
- of blocks. For example, choosing blockSize=4 would result in a RAM
- that only supports aligned 32-bit reads and writes.
-
- You can think of the blockSize as being equivalent to the number
- of wires in the data-bus of the memory. If the only wires you
- have are readEnable, writeEnable, address, dataIn, and dataOut,
- then within one cycle you could do a write by asserting writeEnable=1,
- specifying the address, and driving the data to be written onto dataIn.
- Or you could perform a read by asserting readEnable=1, driving the
- address bus, and looking at the value that the RAM drives onto dataOut.
- If blockSize=4, then we would have 32 wires for both dataIn and dataOut,
- and any address would need to have the two least significant bits as zero.
-
- In MIPS the basic unit of transfer is 32-bits, so the granularity of the
- data bus is also 32-bits, and blockSize must be 4.
-
- "Why do we even have this blockSize if it is always 4?" : It is in
- anticipation of a future extension, and a mistake on my part (from
- a teaching point of view). I should have given it the simpler signature of:
-
- mips_mem_h mips_mem_create_ram(uint32_t cbMem);
-
- and stated that it creates a RAM of the given size with a granularity of 4.
-
- "How can MIPS do SH (store half) efficiently if this is the case?" - An
- actual MIPS implementation would have what are called "byte-enables",
- which are extra signals saying which bytes within the data bus are
- valid, but I didn't include them in the API as they complicate things.
+ The RAM will expect transactions to be aligned at the granularity
+ of the transfer, so 4-byte transfers are aligned on 4-byte addresses,
+ 2-byte transfers on 2-byte address, and single byte transfers can
+ have any address.
+
+ This interface is over-simplifying things, and ignoring
+ "byte-enables". These are what allows a CPU to indicate
+ which of the bytes within a 32-bit bus are being actively
+ written.
*/
mips_mem_h mips_mem_create_ram(
- uint32_t cbMem, //!< Total number of bytes of ram
- uint32_t blockSize //!< Granularity of transactions supported by RAM
+ uint32_t cbMem //!< Total number of bytes of ram
);
/*!
diff --git a/makefile b/makefile
index d00ca10..2f38cb0 100644
--- a/makefile
+++ b/makefile
@@ -2,34 +2,45 @@
# won't be eie2ugs...
LOGIN ?= eie2ugs
-CPPFLAGS += -W -Wall -g
+# Turn on all warnings
+CPPFLAGS += -W -Wall
+
+# Add debug information
+CPPFLAGS += -g
+
+# Pick up any headers in the ./include directories
CPPFLAGS += -I include
-CFLAGS += -std=c99
+# C++11 by default
CXXFLAGS += -std=c++11
-# Force the inclusion of C++ standard libraries
-LDLIBS += -lstdc++
-
DEFAULT_OBJECTS = \
- src/shared/mips_test_framework.o \
- src/shared/mips_mem_ram.o
+ src/shared/mips_test_framework.o \
+ src/shared/mips_mem_ram.o
USER_CPU_SRCS = \
- $(wildcard src/$(LOGIN)/mips_cpu.c) \
- $(wildcard src/$(LOGIN)/mips_cpu.cpp) \
- $(wildcard src/$(LOGIN)/mips_cpu_*.c) \
- $(wildcard src/$(LOGIN)/mips_cpu_*.cpp) \
- $(wildcard src/$(LOGIN)/*/*.c) \
- $(wildcard src/$(LOGIN)/*/*.cpp) \
- $(wildcard src/$(LOGIN)/*/*.c) \
- $(wildcard src/$(LOGIN)/*/*.cpp)
-
-USER_CPU_OBJECTS = $(patsubst %.c,%.o,$(patsubst %.cpp,%.o,$(USER_CPU_SRCS)))
-
-src/$(LOGIN)/test_mips : $(DEFAULT_OBJECTS) $(USER_CPU_OBJECTS)
+ $(wildcard src/$(LOGIN)/mips_cpu.cpp) \
+ $(wildcard src/$(LOGIN)/mips_cpu_*.cpp) \
+ $(wildcard src/$(LOGIN)/mips_cpu/*.cpp)
+
+USER_TEST_SRCS = \
+ $(wildcard src/$(LOGIN)/test_mips.cpp) \
+ $(wildcard src/$(LOGIN)/test_mips_*.cpp) \
+ $(wildcard src/$(LOGIN)/test_mips/*.cpp)
+
+USER_CPU_OBJECTS = $(patsubst %.cpp,%.o,$(USER_CPU_SRCS))
+USER_TEST_OBJECTS = $(patsubst %.cpp,%.o,$(USER_TEST_SRCS))
+
+src/$(LOGIN)/test_mips : $(DEFAULT_OBJECTS) $(USER_CPU_OBJECTS) $(USER_TEST_OBJECTS)
+ $(CXX) $(CPPFLAGS) $(CXXFLAGS) -o $@ $^ $(LFLAGS) $(LDLIBS)
+
fragments/run_fibonacci : $(DEFAULT_OBJECTS) $(USER_CPU_OBJECTS)
-
+
fragments/run_addu : $(DEFAULT_OBJECTS) $(USER_CPU_OBJECTS)
+clean :
+ -rm src/$(LOGIN)/test_mips
+ -rm $(DEFAULT_OBJECTS) $(USER_CPU_OBJECTS) $(USER_TEST_OBJECTS)
+
+all : src/$(LOGIN)/test_mips
diff --git a/src/eie2ugs/mips_cpu.cpp b/src/eie2ugs/mips_cpu.cpp
deleted file mode 100644
index 475977e..0000000
--- a/src/eie2ugs/mips_cpu.cpp
+++ /dev/null
@@ -1,128 +0,0 @@
-#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
deleted file mode 100644
index 26db856..0000000
--- a/src/eie2ugs/test_mips.cpp
+++ /dev/null
@@ -1,131 +0,0 @@
-#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;
-}
diff --git a/src/shared/mips_mem_ram.cpp b/src/shared/mips_mem_ram.cpp
index 276388b..0a01b5b 100644
--- a/src/shared/mips_mem_ram.cpp
+++ b/src/shared/mips_mem_ram.cpp
@@ -12,14 +12,16 @@
struct mips_mem_provider
{
uint32_t length;
- uint32_t blockSize;
uint8_t *data;
};
extern "C" mips_mem_h mips_mem_create_ram(
- uint32_t cbMem, //!< Total number of bytes of ram
- uint32_t blockSize //!< Granularity in bytes
+ uint32_t cbMem //!< Total number of bytes of ram
){
+ if(cbMem>0x10000000){
+ return 0; // No more than 256MB of RAM
+ }
+
uint8_t *data=(uint8_t*)malloc(cbMem);
if(data==0)
return 0;
@@ -31,7 +33,6 @@ extern "C" mips_mem_h mips_mem_create_ram(
}
mem->length=cbMem;
- mem->blockSize=blockSize;
mem->data=data;
return mem;
@@ -45,13 +46,15 @@ static mips_error mips_mem_read_write(
uint8_t *dataOut
)
{
- if(mem==0)
+ if(mem==0){
return mips_ErrorInvalidHandle;
+ }
- if(0 != (address%mem->blockSize) ){
- return mips_ExceptionInvalidAlignment;
+ if( (length!=1) && (length!=2) && (length!=4) ){
+ return mips_ExceptionInvalidLength;
}
- if(0 != ((address+length)%mem->blockSize)){
+
+ if(0 != (address % length) ){
return mips_ExceptionInvalidAlignment;
}
if((address+length) > mem->length){ // A subtle bug here, maybe?