aboutsummaryrefslogtreecommitdiff
path: root/qtmips_machine
diff options
context:
space:
mode:
authorPavel Pisa <pisa@cmp.felk.cvut.cz>2019-02-03 23:03:59 +0100
committerPavel Pisa <pisa@cmp.felk.cvut.cz>2019-02-03 23:03:59 +0100
commit361f5aab10d72e2200dfc7985a1511044b987db8 (patch)
tree02688761a1dc29731c0fc069a2d89205a867a8ef /qtmips_machine
parent55e1bc746a45118e14554c957b4ee4663039d9af (diff)
downloadqtmips-361f5aab10d72e2200dfc7985a1511044b987db8.tar.gz
qtmips-361f5aab10d72e2200dfc7985a1511044b987db8.tar.bz2
qtmips-361f5aab10d72e2200dfc7985a1511044b987db8.zip
Correct memory view updates for uncached and write-through case.
Signed-off-by: Pavel Pisa <pisa@cmp.felk.cvut.cz>
Diffstat (limited to 'qtmips_machine')
-rw-r--r--qtmips_machine/cache.cpp19
-rw-r--r--qtmips_machine/cache.h4
-rw-r--r--qtmips_machine/memory.cpp26
-rw-r--r--qtmips_machine/memory.h18
-rw-r--r--qtmips_machine/qtmipsmachine.cpp1
-rw-r--r--qtmips_machine/qtmipsmachine.h1
6 files changed, 45 insertions, 24 deletions
diff --git a/qtmips_machine/cache.cpp b/qtmips_machine/cache.cpp
index acc48b1..9f4bfb0 100644
--- a/qtmips_machine/cache.cpp
+++ b/qtmips_machine/cache.cpp
@@ -40,17 +40,18 @@ Cache::Cache(Memory *m, const MachineConfigCache *cc, unsigned memory_access_pen
}
}
-void Cache::wword(std::uint32_t address, std::uint32_t value) {
+bool Cache::wword(std::uint32_t address, std::uint32_t value) {
+ bool changed;
if (!cnf.enabled()) {
- mem->write_word(address, value);
- return;
+ return mem->write_word(address, value);
}
std::uint32_t data;
- access(address, &data, true, value);
+ changed = access(address, &data, true, value);
if (cnf.write_policy() == MachineConfigCache::WP_TROUGH)
- mem->wword(address, value);
+ return mem->wword(address, value);
+ return changed;
}
std::uint32_t Cache::rword(std::uint32_t address) const {
@@ -131,7 +132,8 @@ const MachineConfigCache &Cache::config() const {
return cnf;
}
-void Cache::access(std::uint32_t address, std::uint32_t *data, bool write, std::uint32_t value) const {
+bool Cache::access(std::uint32_t address, std::uint32_t *data, bool write, std::uint32_t value) const {
+ bool changed = false;
address = address >> 2;
unsigned ssize = cnf.blocks() * cnf.sets();
std::uint32_t tag = address / ssize;
@@ -218,10 +220,13 @@ void Cache::access(std::uint32_t address, std::uint32_t *data, bool write, std::
cd.tag = tag;
*data = cd.data[col];
- if (write)
+ if (write) {
+ changed = cd.data[col] != value;
cd.data[col] = value;
+ }
emit cache_update(indx, row, cd.valid, cd.dirty, cd.tag, cd.data);
+ return changed;
}
void Cache::kick(unsigned associat_indx, unsigned row) const {
diff --git a/qtmips_machine/cache.h b/qtmips_machine/cache.h
index 6cf3a2c..1c356c7 100644
--- a/qtmips_machine/cache.h
+++ b/qtmips_machine/cache.h
@@ -13,7 +13,7 @@ class Cache : public MemoryAccess {
public:
Cache(Memory *m, const MachineConfigCache *c, unsigned memory_access_penalty_r = 1, unsigned memory_access_penalty_w = 1);
- void wword(std::uint32_t address, std::uint32_t value);
+ bool wword(std::uint32_t address, std::uint32_t value);
std::uint32_t rword(std::uint32_t address) const;
void flush(); // flush cache
@@ -54,7 +54,7 @@ private:
mutable unsigned hit_read, miss_read, hit_write, miss_write; // Hit and miss counters
- void access(std::uint32_t address, std::uint32_t *data, bool write, std::uint32_t value = 0) const;
+ bool access(std::uint32_t address, std::uint32_t *data, bool write, std::uint32_t value = 0) const;
void kick(unsigned associat_indx, unsigned row) const;
std::uint32_t base_address(std::uint32_t tag, unsigned row) const;
void update_statistics() const;
diff --git a/qtmips_machine/memory.cpp b/qtmips_machine/memory.cpp
index 3b47ca7..77f2909 100644
--- a/qtmips_machine/memory.cpp
+++ b/qtmips_machine/memory.cpp
@@ -10,20 +10,20 @@ using namespace machine;
#define SH_NTH_16(OFFSET) (((OFFSET) & 0b10) * 16)
#endif
-void MemoryAccess::write_byte(std::uint32_t offset, std::uint8_t value) {
+bool MemoryAccess::write_byte(std::uint32_t offset, std::uint8_t value) {
int nth = SH_NTH_8(offset);
std::uint32_t mask = 0xff << nth; // Mask for n-th byte
- wword(offset, (rword(offset) & ~mask) | (((std::uint32_t)value << nth) & mask));
+ return wword(offset, (rword(offset) & ~mask) | (((std::uint32_t)value << nth) & mask));
}
-void MemoryAccess::write_hword(std::uint32_t offset, std::uint16_t value) {
+bool MemoryAccess::write_hword(std::uint32_t offset, std::uint16_t value) {
int nth = SH_NTH_16(offset);
std::uint32_t mask = 0xffff << nth; // Mask for n-th half-word
- wword(offset, (rword(offset) & ~mask) | (((std::uint32_t)value << nth) & mask));
+ return wword(offset, (rword(offset) & ~mask) | (((std::uint32_t)value << nth) & mask));
}
-void MemoryAccess::write_word(std::uint32_t offset, std::uint32_t value) {
- wword(offset, value);
+bool MemoryAccess::write_word(std::uint32_t offset, std::uint32_t value) {
+ return wword(offset, value);
}
std::uint8_t MemoryAccess::read_byte(std::uint32_t offset) const {
@@ -101,11 +101,14 @@ MemorySection::~MemorySection() {
delete this->dt;
}
-void MemorySection::wword(std::uint32_t offset, std::uint32_t value) {
+bool MemorySection::wword(std::uint32_t offset, std::uint32_t value) {
+ bool changed;
offset = offset >> 2;
if (offset >= this->len)
throw QTMIPS_EXCEPTION(OutOfMemoryAccess, "Trying to write outside of the memory section", QString("Accessing using offset: ") + QString(offset));
+ changed = this->dt[offset] != value;
this->dt[offset] = value;
+ return changed;
}
std::uint32_t MemorySection::rword(std::uint32_t offset) const {
@@ -206,9 +209,14 @@ MemorySection *Memory::get_section(std::uint32_t address, bool create) const {
#define SECTION_OFFSET_MASK(ADDR) (ADDR & GENMASK(MEMORY_SECTION_BITS, 2))
-void Memory::wword(std::uint32_t address, std::uint32_t value) {
+bool Memory::wword(std::uint32_t address, std::uint32_t value) {
+ bool changed;
MemorySection *section = this->get_section(address, true);
- section->write_word(SECTION_OFFSET_MASK(address), value);
+ changed = section->write_word(SECTION_OFFSET_MASK(address), value);
+ write_counter++;
+ if (changed)
+ change_counter++;
+ return changed;
}
std::uint32_t Memory::rword(std::uint32_t address) const {
diff --git a/qtmips_machine/memory.h b/qtmips_machine/memory.h
index e4777b3..4b40243 100644
--- a/qtmips_machine/memory.h
+++ b/qtmips_machine/memory.h
@@ -12,9 +12,9 @@ class MemoryAccess : public QObject {
Q_OBJECT
public:
// Note: hword and word methods are throwing away lowest bits so unaligned access is ignored without error.
- void write_byte(std::uint32_t offset, std::uint8_t value);
- void write_hword(std::uint32_t offset, std::uint16_t value);
- void write_word(std::uint32_t offset, std::uint32_t value);
+ bool write_byte(std::uint32_t offset, std::uint8_t value);
+ bool write_hword(std::uint32_t offset, std::uint16_t value);
+ bool write_word(std::uint32_t offset, std::uint32_t value);
std::uint8_t read_byte(std::uint32_t offset) const;
std::uint16_t read_hword(std::uint32_t offset) const;
@@ -34,7 +34,7 @@ public:
virtual void sync();
protected:
- virtual void wword(std::uint32_t offset, std::uint32_t value) = 0;
+ virtual bool wword(std::uint32_t offset, std::uint32_t value) = 0;
virtual std::uint32_t rword(std::uint32_t offset) const = 0;
private:
@@ -47,7 +47,7 @@ public:
MemorySection(const MemorySection&);
~MemorySection();
- void wword(std::uint32_t offset, std::uint32_t value);
+ bool wword(std::uint32_t offset, std::uint32_t value);
std::uint32_t rword(std::uint32_t offset) const;
void merge(MemorySection&);
@@ -77,7 +77,7 @@ public:
void reset(const Memory&);
MemorySection *get_section(std::uint32_t address, bool create) const; // returns section containing given address
- void wword(std::uint32_t address, std::uint32_t value);
+ bool wword(std::uint32_t address, std::uint32_t value);
std::uint32_t rword(std::uint32_t address) const;
bool operator==(const Memory&) const;
@@ -85,8 +85,14 @@ public:
const union MemoryTree *get_memorytree_root() const;
+ inline std::uint32_t get_change_counter() const {
+ return change_counter;
+ }
+
private:
union MemoryTree *mt_root;
+ std::uint32_t change_counter;
+ std::uint32_t write_counter;
static union MemoryTree *allocate_section_tree();
static void free_section_tree(union MemoryTree*, size_t depth);
static bool compare_section_tree(const union MemoryTree*, const union MemoryTree*, size_t depth);
diff --git a/qtmips_machine/qtmipsmachine.cpp b/qtmips_machine/qtmipsmachine.cpp
index 75d8b8e..9f769c7 100644
--- a/qtmips_machine/qtmipsmachine.cpp
+++ b/qtmips_machine/qtmipsmachine.cpp
@@ -108,6 +108,7 @@ void QtMipsMachine::step() {
if (stat == ST_BUSY)
set_status(stat_prev);
}
+ emit post_tick();
}
void QtMipsMachine::restart() {
diff --git a/qtmips_machine/qtmipsmachine.h b/qtmips_machine/qtmipsmachine.h
index 46405e5..b7f229d 100644
--- a/qtmips_machine/qtmipsmachine.h
+++ b/qtmips_machine/qtmipsmachine.h
@@ -50,6 +50,7 @@ signals:
void program_trap(machine::QtMipsException &e);
void status_change(enum machine::QtMipsMachine::Status st);
void tick(); // Time tick
+ void post_tick(); // Emitted after tick to allow updates
private:
MachineConfig mcnf;