diff options
Diffstat (limited to 'include/mips_mem.h')
-rw-r--r-- | include/mips_mem.h | 155 |
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 |