From 361f5aab10d72e2200dfc7985a1511044b987db8 Mon Sep 17 00:00:00 2001 From: Pavel Pisa Date: Sun, 3 Feb 2019 23:03:59 +0100 Subject: Correct memory view updates for uncached and write-through case. Signed-off-by: Pavel Pisa --- qtmips_gui/memoryview.cpp | 11 +++++++++++ qtmips_gui/memoryview.h | 4 ++++ qtmips_machine/cache.cpp | 19 ++++++++++++------- qtmips_machine/cache.h | 4 ++-- qtmips_machine/memory.cpp | 26 +++++++++++++++++--------- qtmips_machine/memory.h | 18 ++++++++++++------ qtmips_machine/qtmipsmachine.cpp | 1 + qtmips_machine/qtmipsmachine.h | 1 + 8 files changed, 60 insertions(+), 24 deletions(-) diff --git a/qtmips_gui/memoryview.cpp b/qtmips_gui/memoryview.cpp index 3f5fbc3..1ce02d7 100644 --- a/qtmips_gui/memoryview.cpp +++ b/qtmips_gui/memoryview.cpp @@ -31,6 +31,8 @@ MemoryView::MemoryView(QWidget *parent, std::uint32_t addr0) : QWidget(parent) { void MemoryView::setup(machine::QtMipsMachine *machine) { memory = (machine == nullptr) ? nullptr : machine->memory(); + if (machine != nullptr) + connect(machine, SIGNAL(post_tick()), this, SLOT(check_for_updates())); reload_content(); } @@ -58,9 +60,18 @@ void MemoryView::edit_load_focus() { go_edit->setText(QString("0x%1").arg(focus(), 8, 16, QChar('0'))); } +void MemoryView::check_for_updates() { + if (memory != nullptr) { + if (change_counter != memory->get_change_counter()) + reload_content(); + } +} + void MemoryView::reload_content() { int count = memf->widg->count(); memf->widg->clearRows(); + if (memory != nullptr) + change_counter = memory->get_change_counter(); update_content(count, 0); } diff --git a/qtmips_gui/memoryview.h b/qtmips_gui/memoryview.h index 1aeaf10..7b63d47 100644 --- a/qtmips_gui/memoryview.h +++ b/qtmips_gui/memoryview.h @@ -27,6 +27,9 @@ public: void edit_load_focus(); // Set current focus to edit field +public slots: + void check_for_updates(); + protected: const machine::Memory *memory; @@ -43,6 +46,7 @@ private slots: void go_edit_finish(); private: + std::uint32_t change_counter; unsigned count; std::uint32_t addr_0; // First address in view 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; -- cgit v1.2.3