aboutsummaryrefslogtreecommitdiffstats
path: root/include/mips_mem.h
diff options
context:
space:
mode:
Diffstat (limited to 'include/mips_mem.h')
-rw-r--r--include/mips_mem.h155
1 files changed, 155 insertions, 0 deletions
diff --git a/include/mips_mem.h b/include/mips_mem.h
new file mode 100644
index 0000000..97724ff
--- /dev/null
+++ b/include/mips_mem.h
@@ -0,0 +1,155 @@
+/*! \file mips_mem.h
+ Defines the functions used to interact with simulated memory.
+
+ Note that the notions of "memory/address space" and "RAM" are actually
+ two related but distinct things (we will explore this more later).
+ A memory space is some kind of addressable space that the CPU can
+ read and write to, where addressable locations are identified by
+ integers. For the moment we will only deal with one address space,
+ but later on we'll see others. In this API, abstract memory spaces
+ are accessed using the functions in \ref mips_mem_core, but they
+ must be intially created using a device specific API from \ref mips_mem_devices.
+
+ RAM is a particular kind of memory device, which maps reads and
+ writes transactions at particular addresses to corresponding
+ storage locations. ROM is another kind of memory device that you
+ saw earlier. It is extremely common for multiple types of memory
+ device to exist in one address space, but for now we will stick
+ with the simple idea of having one RAM, which is created using mips_mem_create_ram.
+*/
+#ifndef mips_mem_header
+#define mips_mem_header
+
+#include "mips_core.h"
+
+/* This allows the header to be used from both C and C++, so
+programs can be written in either (or both) languages. */
+#ifdef __cplusplus
+extern "C"{
+#endif
+
+/*! \defgroup mips_mem Memory
+ \addtogroup mips_mem
+ @{
+
+ \defgroup mips_mem_core Abstract Memory Interface
+ \addtogroup mips_mem_core
+ @{
+*/
+
+/*! Represents some sort of memory, but without saying
+anything about how it is represented. See \ref mips_mem_h.
+
+\struct mips_mem_provider
+*/
+struct mips_mem_provider;
+
+/*! An opaque handle to a memory space.
+
+ We can pass this around without knowing who or what provides the
+ memory. This is an example of an "opaque data type" http://en.wikipedia.org/wiki/Opaque_data_type
+ and is commonly used in embedded systems and operating
+ systems. An example you might have come across includes the
+ FILE data-type used by fopen and fprintf in the C standard
+ library.
+
+ Because this is a pointer, we can safely give it the
+ known value of 0 or NULL in order to get a known empty
+ state. For example:
+
+ mips_mem_h myMem=0; // Declare an empty handle
+
+ if(some_condition)
+ myMem=get_a_handle();
+
+ if(myMem)
+ do_something_with mem(myMem);
+
+ So even without knowing what the data-structure is, we can still
+ tell whether or not a handle is currently pointing at a
+ data-structure.
+*/
+typedef struct mips_mem_provider *mips_mem_h;
+
+
+/*! Perform a read 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.
+*/
+mips_error mips_mem_read(
+ mips_mem_h mem, //!< Handle to target memory
+ uint32_t address, //!< Byte address to start transaction at
+ uint32_t length, //!< Number of bytes to transfer
+ uint8_t *dataOut //!< Receives the target bytes
+);
+
+/*! 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.
+*/
+mips_error mips_mem_write(
+ mips_mem_h mem, //!< Handle to target memory
+ uint32_t address, //!< Byte address to start transaction at
+ uint32_t length, //!< Number of bytes to transfer
+ const uint8_t *dataIn //!< Receives the target bytes
+);
+
+
+/*! Release all resources associated with memory. The caller doesn't
+ really know what is being released (it could be memory, it could
+ be file handles), and shouldn't care. Calling mips_mem_free on an
+ empty (zero) handle is legal. Calling mips_mem_free twice on the
+ same handle is illegal, and the resulting behaviour is undefined
+ (most likely a crash).
+
+ A pattern that can be useful is:
+
+ mips_mem_h h=0; // Initialise it to empty
+ ...
+ h=some_creator_function(...);
+ ...
+ use_memory_somehow(h);
+ ...
+ if(h){
+ mips_mem_free(h);
+ h=0; // Make sure it is never freed again
+ }
+*/
+void mips_mem_free(mips_mem_h mem);
+
+/*! @} */
+
+
+/*! \defgroup mips_mem_devices Concrete Memory Devices
+ \ingroup mips_mem_devices
+ @{
+*/
+
+/*! 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.
+*/
+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
+);
+
+/*!
+ @}
+ @}
+*/
+
+
+#ifdef __cplusplus
+};
+#endif
+
+#endif