aboutsummaryrefslogtreecommitdiff
path: root/qtmips_machine/memory.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'qtmips_machine/memory.cpp')
-rw-r--r--qtmips_machine/memory.cpp123
1 files changed, 106 insertions, 17 deletions
diff --git a/qtmips_machine/memory.cpp b/qtmips_machine/memory.cpp
index 21ca03f..a9cc055 100644
--- a/qtmips_machine/memory.cpp
+++ b/qtmips_machine/memory.cpp
@@ -56,28 +56,47 @@ std::uint32_t MemoryAccess::read_word(std::uint32_t offset) {
}
MemorySection::MemorySection(std::uint32_t length) {
- this->length = length;
+ this->len = length;
this->dt = new std::uint8_t[length];
+ memset(this->dt, 0, sizeof *this->dt * length);
+}
+
+MemorySection::MemorySection(const MemorySection &ms) : MemorySection(ms.length()) {
+ memcpy(this->dt, ms.data(), sizeof *this->dt * this->len);
}
MemorySection::~MemorySection() {
delete this->dt;
}
-using namespace std;
-
void MemorySection::write_byte(std::uint32_t offset, std::uint8_t value) {
- if (offset >= this->length)
+ if (offset >= this->len)
throw QTMIPS_EXCEPTION(OutOfMemoryAccess, "Trying to write outside of the memory section", QString("Accessing using offset: ") + QString(offset));
this->dt[offset] = value;
}
-std::uint8_t MemorySection::read_byte(std::uint32_t offset) {
- if (offset >= this->length)
+std::uint8_t MemorySection::read_byte(std::uint32_t offset) const {
+ if (offset >= this->len)
throw QTMIPS_EXCEPTION(OutOfMemoryAccess, "Trying to read outside of the memory section", QString("Accessing using offset: ") + QString(offset));
return this->dt[offset];
}
+std::uint32_t MemorySection::length() const {
+ return len;
+}
+
+const std::uint8_t* MemorySection::data() const {
+ return this->dt;
+}
+
+bool MemorySection::operator==(const MemorySection &ms) const {
+ return ! memcmp(this->dt, ms.data(), sizeof *this->dt * this->len);
+}
+
+bool MemorySection::operator!=(const MemorySection &ms) const {
+ return ! this->operator ==(ms);
+}
+
// Number of bites per row on lookup tree
#define MEMORY_TREE_ROW ((32 - MEMORY_SECTION_BITS) / MEMORY_TREE_H)
// Size of row in memory lookup tree
@@ -102,17 +121,12 @@ Memory::Memory() {
this->mt_root = allocate_section_tree();
}
-Memory::~Memory() {
- // Free up memory tree
- // TODO
+Memory::Memory(const Memory &m) {
+ this->mt_root = copy_section_tree(m.get_memorytree_root(), 0);
}
-union MemoryTree *Memory::allocate_section_tree() {
- union MemoryTree *mt = new union MemoryTree[MEMORY_TREE_LEN];
- for (size_t i = 0; i < MEMORY_TREE_LEN; i++)
- // Note that this also nulls sec pointer as those are both pointers and so they have same size
- mt[i].mt = nullptr;
- return mt;
+Memory::~Memory() {
+ free_section_tree(this->mt_root, 0);
}
// Create address mask with section length
@@ -123,7 +137,7 @@ union MemoryTree *Memory::allocate_section_tree() {
#define ADDRESS_TREE_INDEX(DEPTH, ADDR) ((ADDR >> (DEPTH * MEMORY_TREE_ROW)) & ADDRESS_MASK(MEMORY_TREE_ROW))
-MemorySection *Memory::get_section(std::uint32_t address, bool create) {
+MemorySection *Memory::get_section(std::uint32_t address, bool create) const {
std::uint32_t addr = address >> MEMORY_SECTION_BITS; // drop all bits for addressing inside of the section
union MemoryTree *w = this->mt_root;
size_t ii;
@@ -155,10 +169,85 @@ void Memory::write_byte(std::uint32_t address, std::uint8_t value) {
section->write_byte(SECTION_ADDRESS(address), value);
}
-std::uint8_t Memory::read_byte(std::uint32_t address) {
+std::uint8_t Memory::read_byte(std::uint32_t address) const {
MemorySection *section = this->get_section(address, true);
if (section == nullptr)
return 0;
else
return section->read_byte(SECTION_ADDRESS(address));
}
+
+bool Memory::operator==(const Memory&m) const {
+ return compare_section_tree(this->mt_root, m.get_memorytree_root(), 0);
+}
+
+bool Memory::operator!=(const Memory&m) const {
+ return ! this->operator ==(m);
+}
+
+const union MemoryTree *Memory::get_memorytree_root() const {
+ return this->mt_root;
+}
+
+union MemoryTree *Memory::allocate_section_tree() {
+ union MemoryTree *mt = new union MemoryTree[MEMORY_TREE_LEN];
+ for (size_t i = 0; i < MEMORY_TREE_LEN; i++)
+ // Note that this also nulls sec pointer as those are both pointers and so they have same size
+ mt[i].mt = nullptr;
+ return mt;
+}
+
+void Memory::free_section_tree(union MemoryTree *mt, size_t depth) {
+ if (depth < (MEMORY_TREE_H - 1)) { // Following level is memory tree
+ for (int i = 0; i < MEMORY_TREE_LEN; i++) {
+ if (mt[i].mt != nullptr)
+ free_section_tree(mt[i].mt, depth + 1);
+ }
+ } else { // Following level is memory section
+ for (int i = 0; i < MEMORY_TREE_LEN; i++) {
+ if (mt[i].sec != nullptr)
+ delete mt[i].sec;
+ }
+ }
+}
+
+bool Memory::compare_section_tree(const union MemoryTree *mt1, const union MemoryTree *mt2, size_t depth) {
+ if (depth < (MEMORY_TREE_H - 1)) { // Following level is memory tree
+ for (int i = 0; i < MEMORY_TREE_LEN; i++) {
+ if (
+ ((mt1[i].mt == nullptr || mt2[i].mt == nullptr) && mt1[i].mt != mt2[i].mt)
+ ||
+ (mt1[i].mt != nullptr && mt2[i].mt != nullptr && !compare_section_tree(mt1[i].mt, mt2[i].mt, depth + 1))
+ ) {
+ return false;
+ }
+ }
+ } else { // Following level is memory section
+ for (int i = 0; i < MEMORY_TREE_LEN; i++) {
+ if (
+ ((mt1[i].sec == nullptr || mt2[i].sec == nullptr) && mt1[i].sec != mt2[i].sec)
+ ||
+ (mt1[i].sec != nullptr && mt2[i].sec != nullptr && *mt1[i].sec != *mt2[i].sec)
+ ) {
+ return false;
+ }
+ }
+ }
+ return true;
+}
+
+union MemoryTree *Memory::copy_section_tree(const union MemoryTree *mt, size_t depth) {
+ union MemoryTree *nmt = allocate_section_tree();
+ if (depth < (MEMORY_TREE_H - 1)) { // Following level is memory tree
+ for (int i = 0; i < MEMORY_TREE_LEN; i++) {
+ if (mt[i].mt != nullptr)
+ nmt[i].mt = copy_section_tree(mt[i].mt, depth + 1);
+ }
+ } else { // Following level is memory section
+ for (int i = 0; i < MEMORY_TREE_LEN; i++) {
+ if (mt[i].sec != nullptr)
+ nmt[i].sec = new MemorySection(*mt[i].sec);
+ }
+ }
+ return nmt;
+}