diff options
author | Pavel Pisa <pisa@cmp.felk.cvut.cz> | 2019-06-30 18:22:27 +0200 |
---|---|---|
committer | Pavel Pisa <pisa@cmp.felk.cvut.cz> | 2019-06-30 18:22:27 +0200 |
commit | 9dc519887f61ae33ff82bb125fb69398503f91f6 (patch) | |
tree | c0074870df060adc0f546715e39169cacc8d5667 | |
parent | c86a491e26800f620b51ced800b612e73da1cced (diff) | |
download | qtmips-9dc519887f61ae33ff82bb125fb69398503f91f6.tar.gz qtmips-9dc519887f61ae33ff82bb125fb69398503f91f6.tar.bz2 qtmips-9dc519887f61ae33ff82bb125fb69398503f91f6.zip |
Memory change counter moved to MemoryAccess and external changes notification added.
This change together with use of PhysAddrSpace as the memory
content source for memory and program view allows to access
and monitor contents of peripheral registers and frame-buffer
memory from graphic user interface.
Signed-off-by: Pavel Pisa <pisa@cmp.felk.cvut.cz>
-rw-r--r-- | qtmips_gui/memorymodel.cpp | 39 | ||||
-rw-r--r-- | qtmips_gui/memorymodel.h | 2 | ||||
-rw-r--r-- | qtmips_gui/programmodel.cpp | 41 | ||||
-rw-r--r-- | qtmips_gui/programmodel.h | 2 | ||||
-rw-r--r-- | qtmips_machine/cache.cpp | 4 | ||||
-rw-r--r-- | qtmips_machine/cache.h | 4 | ||||
-rw-r--r-- | qtmips_machine/lcddisplay.cpp | 9 | ||||
-rw-r--r-- | qtmips_machine/lcddisplay.h | 2 | ||||
-rw-r--r-- | qtmips_machine/memory.cpp | 8 | ||||
-rw-r--r-- | qtmips_machine/memory.h | 11 | ||||
-rw-r--r-- | qtmips_machine/peripspiled.cpp | 50 | ||||
-rw-r--r-- | qtmips_machine/peripspiled.h | 4 | ||||
-rw-r--r-- | qtmips_machine/physaddrspace.cpp | 31 | ||||
-rw-r--r-- | qtmips_machine/physaddrspace.h | 5 | ||||
-rw-r--r-- | qtmips_machine/qtmipsmachine.cpp | 8 | ||||
-rw-r--r-- | qtmips_machine/qtmipsmachine.h | 2 | ||||
-rw-r--r-- | qtmips_machine/serialport.cpp | 33 | ||||
-rw-r--r-- | qtmips_machine/serialport.h | 3 |
18 files changed, 204 insertions, 54 deletions
diff --git a/qtmips_gui/memorymodel.cpp b/qtmips_gui/memorymodel.cpp index 329891e..2927279 100644 --- a/qtmips_gui/memorymodel.cpp +++ b/qtmips_gui/memorymodel.cpp @@ -49,6 +49,22 @@ MemoryModel::MemoryModel(QObject *parent) access_through_cache = 0; } +const machine::MemoryAccess *MemoryModel::mem_access() const { + if (machine == nullptr) + return nullptr; + if (machine->physical_address_space() != nullptr) + return machine->physical_address_space(); + return machine->memory(); +} + +machine::MemoryAccess *MemoryModel::mem_access_rw() const { + if (machine == nullptr) + return nullptr; + if (machine->physical_address_space_rw() != nullptr) + return machine->physical_address_space_rw(); + return machine->memory_rw(); +} + int MemoryModel::rowCount(const QModelIndex & /*parent*/) const { // std::uint64_t rows = (0x2000 + cells_per_row - 1) / cells_per_row; return 750; @@ -91,7 +107,7 @@ QVariant MemoryModel::data(const QModelIndex &index, int role) const { } if (machine == nullptr) return QString(""); - mem = machine->memory(); + mem = mem_access(); if (mem == nullptr) return QString(""); if ((access_through_cache > 0) && (machine->cache_data() != nullptr)) @@ -155,6 +171,9 @@ void MemoryModel::setup(machine::QtMipsMachine *machine) { this->machine = machine; if (machine != nullptr) connect(machine, SIGNAL(post_tick()), this, SLOT(check_for_updates())); + if (mem_access() != nullptr) + connect(mem_access(), SIGNAL(external_change_notify(const MemoryAccess*,std::uint32_t,std::uint32_t,bool)), + this, SLOT(check_for_updates())); emit update_all(); emit setup_done(); } @@ -174,8 +193,10 @@ void MemoryModel::set_cell_size(int index) { } void MemoryModel::update_all() { - if (machine != nullptr && machine->memory() != nullptr) { - memory_change_counter = machine->memory()->get_change_counter(); + const machine::MemoryAccess *mem; + mem = mem_access(); + if (mem != nullptr) { + memory_change_counter = mem->get_change_counter(); if (machine->cache_data() != nullptr) cache_data_change_counter = machine->cache_data()->get_change_counter(); } @@ -184,12 +205,12 @@ void MemoryModel::update_all() { void MemoryModel::check_for_updates() { bool need_update = false; - if (machine == nullptr) - return; - if (machine->memory() == nullptr) + const machine::MemoryAccess *mem; + mem = mem_access(); + if (mem == nullptr) return; - if (memory_change_counter != machine->memory()->get_change_counter()) + if (memory_change_counter != mem->get_change_counter()) need_update = true; if (machine->cache_data() != nullptr) { if (cache_data_change_counter != machine->cache_data()->get_change_counter()) @@ -235,15 +256,15 @@ bool MemoryModel::setData(const QModelIndex & index, const QVariant & value, int { bool ok; std::uint32_t address; + machine::MemoryAccess *mem; std::uint32_t data = value.toString().toULong(&ok, 16); if (!ok) return false; - machine::MemoryAccess *mem; if (!get_row_address(address, index.row())) return false; if (index.column() == 0 || machine == nullptr) return false; - mem = machine->memory_rw(); + mem = mem_access_rw(); if (mem == nullptr) return false; if ((access_through_cache > 0) && (machine->cache_data_rw() != nullptr)) diff --git a/qtmips_gui/memorymodel.h b/qtmips_gui/memorymodel.h index bab07fa..353757a 100644 --- a/qtmips_gui/memorymodel.h +++ b/qtmips_gui/memorymodel.h @@ -115,6 +115,8 @@ signals: void setup_done(); private: + const machine::MemoryAccess *mem_access() const; + machine::MemoryAccess *mem_access_rw() const; enum MemoryCellSize cell_size; unsigned int cells_per_row; std::uint32_t index0_offset; diff --git a/qtmips_gui/programmodel.cpp b/qtmips_gui/programmodel.cpp index 90e161b..9098ab1 100644 --- a/qtmips_gui/programmodel.cpp +++ b/qtmips_gui/programmodel.cpp @@ -49,6 +49,22 @@ ProgramModel::ProgramModel(QObject *parent) stages_need_update = false; } +const machine::MemoryAccess *ProgramModel::mem_access() const { + if (machine == nullptr) + return nullptr; + if (machine->physical_address_space() != nullptr) + return machine->physical_address_space(); + return machine->memory(); +} + +machine::MemoryAccess *ProgramModel::mem_access_rw() const { + if (machine == nullptr) + return nullptr; + if (machine->physical_address_space_rw() != nullptr) + return machine->physical_address_space_rw(); + return machine->memory_rw(); +} + int ProgramModel::rowCount(const QModelIndex & /*parent*/) const { return 750; } @@ -79,6 +95,8 @@ QVariant ProgramModel::headerData(int section, Qt::Orientation orientation, int } QVariant ProgramModel::data(const QModelIndex &index, int role) const { + const machine::MemoryAccess *mem; + if (role == Qt::DisplayRole || role == Qt::EditRole) { QString s, t; @@ -92,12 +110,11 @@ QVariant ProgramModel::data(const QModelIndex &index, int role) const { return "0x" + s + t.toUpper(); } - if (machine == nullptr) - return QString(" "); - if (machine->memory() == nullptr) + mem = mem_access(); + if (mem == nullptr) return QString(" "); - machine::Instruction inst(machine->memory()->read_word(address)); + machine::Instruction inst(mem->read_word(address)); switch (index.column()) { case 0: @@ -163,8 +180,10 @@ void ProgramModel::setup(machine::QtMipsMachine *machine) { } void ProgramModel::update_all() { - if (machine != nullptr && machine->memory() != nullptr) { - memory_change_counter = machine->memory()->get_change_counter(); + const machine::MemoryAccess *mem; + mem = mem_access(); + if (mem != nullptr) { + memory_change_counter = mem->get_change_counter(); if (machine->cache_program() != nullptr) cache_program_change_counter = machine->cache_program()->get_change_counter(); } @@ -174,12 +193,12 @@ void ProgramModel::update_all() { void ProgramModel::check_for_updates() { bool need_update = stages_need_update; - if (machine == nullptr) - return; - if (machine->memory() == nullptr) + const machine::MemoryAccess *mem; + mem = mem_access(); + if (mem == nullptr) return; - if (memory_change_counter != machine->memory()->get_change_counter()) + if (memory_change_counter != mem->get_change_counter()) need_update = true; if (machine->cache_data() != nullptr) { if (cache_program_change_counter != machine->cache_program()->get_change_counter()) @@ -241,7 +260,7 @@ bool ProgramModel::setData(const QModelIndex & index, const QVariant & value, in return false; if (index.column() == 0 || machine == nullptr) return false; - mem = machine->memory_rw(); + mem = mem_access_rw(); if (mem == nullptr) return false; switch (index.column()) { diff --git a/qtmips_gui/programmodel.h b/qtmips_gui/programmodel.h index a7c1699..d458eef 100644 --- a/qtmips_gui/programmodel.h +++ b/qtmips_gui/programmodel.h @@ -100,6 +100,8 @@ public slots: void update_stage_addr(uint stage, std::uint32_t addr); private: + const machine::MemoryAccess *mem_access() const; + machine::MemoryAccess *mem_access_rw() const; std::uint32_t index0_offset; QFont data_font; machine::QtMipsMachine *machine; diff --git a/qtmips_machine/cache.cpp b/qtmips_machine/cache.cpp index b3afbeb..be3d323 100644 --- a/qtmips_machine/cache.cpp +++ b/qtmips_machine/cache.cpp @@ -171,6 +171,10 @@ std::uint32_t Cache::rword(std::uint32_t address, bool debug_access) const { return data; } +std::uint32_t Cache::get_change_counter() const { + return change_counter; +} + void Cache::flush() { if (!cnf.enabled()) return; diff --git a/qtmips_machine/cache.h b/qtmips_machine/cache.h index 324d55a..1c455f7 100644 --- a/qtmips_machine/cache.h +++ b/qtmips_machine/cache.h @@ -52,6 +52,7 @@ public: bool wword(std::uint32_t address, std::uint32_t value); std::uint32_t rword(std::uint32_t address, bool debug_access = false) const; + virtual std::uint32_t get_change_counter() const override; void flush(); // flush cache void sync(); // Same as flush @@ -69,9 +70,6 @@ public: const MachineConfigCache &config() const; enum LocationStatus location_status(std::uint32_t address) const; - inline std::uint32_t get_change_counter() const { - return change_counter; - } signals: void hit_update(unsigned) const; void miss_update(unsigned) const; diff --git a/qtmips_machine/lcddisplay.cpp b/qtmips_machine/lcddisplay.cpp index 1d96b9d..bd12b1c 100644 --- a/qtmips_machine/lcddisplay.cpp +++ b/qtmips_machine/lcddisplay.cpp @@ -38,6 +38,7 @@ using namespace machine; LcdDisplay::LcdDisplay() { + change_counter = 0; size_t need_bytes; fb_size = 0x4b000; fb_bpp = 16; @@ -88,12 +89,16 @@ bool LcdDisplay::wword(std::uint32_t address, std::uint32_t value) { printf("LcdDisplay::wword address 0x%08lx data 0x%08lx\n", (unsigned long)address, (unsigned long)value); #endif + if (value == rword(address, true)) + return false; fb_data[address + 0] = (value >> 24) & 0xff; fb_data[address + 1] = (value >> 16) & 0xff; fb_data[address + 2] = (value >> 8) & 0xff; fb_data[address + 3] = (value >> 0) & 0xff; + change_counter++; + y = address / fb_linesize; if (fb_bpp > 12) x = (address - y * fb_linesize) / ((fb_bpp + 7) >> 3); @@ -143,3 +148,7 @@ std::uint32_t LcdDisplay::rword(std::uint32_t address, bool debug_access) const return value; } + +std::uint32_t LcdDisplay::get_change_counter() const { + return change_counter; +} diff --git a/qtmips_machine/lcddisplay.h b/qtmips_machine/lcddisplay.h index 15a1e80..4821401 100644 --- a/qtmips_machine/lcddisplay.h +++ b/qtmips_machine/lcddisplay.h @@ -59,6 +59,7 @@ signals: public: bool wword(std::uint32_t address, std::uint32_t value); std::uint32_t rword(std::uint32_t address, bool debug_access = false) const; + virtual std::uint32_t get_change_counter() const override; inline uint width() { return fb_width; @@ -69,6 +70,7 @@ public: } private: + mutable std::uint32_t change_counter; std::uint32_t pixel_address(uint x, uint y); uchar *fb_data; size_t fb_size; diff --git a/qtmips_machine/memory.cpp b/qtmips_machine/memory.cpp index f7fdff9..1e959ae 100644 --- a/qtmips_machine/memory.cpp +++ b/qtmips_machine/memory.cpp @@ -159,6 +159,10 @@ std::uint32_t MemorySection::rword(std::uint32_t offset, bool debug_access) cons return this->dt[offset]; } +std::uint32_t MemorySection::get_change_counter() const { + return 0; +} + std::uint32_t MemorySection::length() const { return len; } @@ -272,6 +276,10 @@ std::uint32_t Memory::rword(std::uint32_t address, bool debug_access) const { return section->read_word(SECTION_OFFSET_MASK(address), debug_access); } +std::uint32_t Memory::get_change_counter() const { + return change_counter; +} + bool Memory::operator==(const Memory&m) const { return compare_section_tree(this->mt_root, m.get_memorytree_root(), 0); } diff --git a/qtmips_machine/memory.h b/qtmips_machine/memory.h index 49ae04e..2b20366 100644 --- a/qtmips_machine/memory.h +++ b/qtmips_machine/memory.h @@ -61,6 +61,11 @@ public: virtual void sync(); virtual enum LocationStatus location_status(std::uint32_t offset) const; + virtual std::uint32_t get_change_counter() const = 0; + +signals: + void external_change_notify(const MemoryAccess *mem_access, std::uint32_t start_addr, + std::uint32_t last_addr, bool external) const; protected: virtual bool wword(std::uint32_t offset, std::uint32_t value) = 0; @@ -78,6 +83,7 @@ public: bool wword(std::uint32_t offset, std::uint32_t value); std::uint32_t rword(std::uint32_t offsetbool, bool debug_access = false) const; + virtual std::uint32_t get_change_counter() const override; void merge(MemorySection&); std::uint32_t length() const; @@ -108,16 +114,13 @@ public: MemorySection *get_section(std::uint32_t address, bool create) const; // returns section containing given address bool wword(std::uint32_t address, std::uint32_t value); std::uint32_t rword(std::uint32_t address, bool debug_access = false) const; + virtual std::uint32_t get_change_counter() const override; bool operator==(const Memory&) const; bool operator!=(const Memory&) const; 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; diff --git a/qtmips_machine/peripspiled.cpp b/qtmips_machine/peripspiled.cpp index d016f90..9387ace 100644 --- a/qtmips_machine/peripspiled.cpp +++ b/qtmips_machine/peripspiled.cpp @@ -46,6 +46,8 @@ using namespace machine; #define SPILED_REG_KNOBS_8BIT_o 0x024 PeripSpiLed::PeripSpiLed() { + change_counter = 0; + spiled_reg_led_line = 0; spiled_reg_led_rgb1 = 0; spiled_reg_led_rgb2 = 0; @@ -60,20 +62,27 @@ PeripSpiLed::~PeripSpiLed() { } bool PeripSpiLed::wword(std::uint32_t address, std::uint32_t value) { + bool changed = false; #if 0 printf("PeripSpiLed::wword address 0x%08lx data 0x%08lx\n", (unsigned long)address, (unsigned long)value); #endif switch (address & ~3) { case SPILED_REG_LED_LINE_o: + if (spiled_reg_led_line == value) + break; spiled_reg_led_line = value; emit led_line_changed(value); break; case SPILED_REG_LED_RGB1_o: + if (spiled_reg_led_rgb1 == value) + break; spiled_reg_led_rgb1 = value; emit led_rgb1_changed(value); break; case SPILED_REG_LED_RGB2_o: + if (spiled_reg_led_rgb2 == value) + break; spiled_reg_led_rgb2 = value; emit led_rgb2_changed(value); break; @@ -83,7 +92,9 @@ bool PeripSpiLed::wword(std::uint32_t address, std::uint32_t value) { emit write_notification(address, value); - return true; + if (changed) + change_counter++; + return changed; } std::uint32_t PeripSpiLed::rword(std::uint32_t address, bool debug_access) const { @@ -123,35 +134,42 @@ std::uint32_t PeripSpiLed::rword(std::uint32_t address, bool debug_access) const return value; } +std::uint32_t PeripSpiLed::get_change_counter() const { + return change_counter; +} + +void PeripSpiLed::knob_update_notify(std::uint32_t val, std::uint32_t mask, int shift) { + mask <<= shift; + val <<= shift; + if (!((spiled_reg_knobs_8bit ^ val) & mask)) + return; + spiled_reg_knobs_8bit &= ~mask; + spiled_reg_knobs_8bit |= val; + change_counter++; + emit external_change_notify(this, SPILED_REG_KNOBS_8BIT_o, + SPILED_REG_KNOBS_8BIT_o + 3, true); +} + void PeripSpiLed::red_knob_update(int val) { - spiled_reg_knobs_8bit &= ~(0xff << 16); - spiled_reg_knobs_8bit |= (val & 0xff) << 16; + knob_update_notify(val, 0xff, 16); } void PeripSpiLed::green_knob_update(int val) { - spiled_reg_knobs_8bit &= ~(0xff << 8); - spiled_reg_knobs_8bit |= (val & 0xff) << 8; + knob_update_notify(val, 0xff, 8); } void PeripSpiLed::blue_knob_update(int val) { - spiled_reg_knobs_8bit &= ~(0xff << 0); - spiled_reg_knobs_8bit |= (val & 0xff) << 0; + knob_update_notify(val, 0xff, 0); } void PeripSpiLed::red_knob_push(bool state) { - spiled_reg_knobs_8bit &= ~(1 << 26); - if (state) - spiled_reg_knobs_8bit |= 1 << 26; + knob_update_notify(state? 1: 0, 1, 26); } void PeripSpiLed::green_knob_push(bool state) { - spiled_reg_knobs_8bit &= ~(1 << 25); - if (state) - spiled_reg_knobs_8bit |= 1 << 25; + knob_update_notify(state? 1: 0, 1, 25); } void PeripSpiLed::blue_knob_push(bool state) { - spiled_reg_knobs_8bit &= ~(1 << 24); - if (state) - spiled_reg_knobs_8bit |= 1 << 24; + knob_update_notify(state? 1: 0, 1, 24); } diff --git a/qtmips_machine/peripspiled.h b/qtmips_machine/peripspiled.h index 8c884e3..70c8019 100644 --- a/qtmips_machine/peripspiled.h +++ b/qtmips_machine/peripspiled.h @@ -69,7 +69,11 @@ public slots: public: bool wword(std::uint32_t address, std::uint32_t value); std::uint32_t rword(std::uint32_t address, bool debug_access = false) const; + virtual std::uint32_t get_change_counter() const override; private: + void knob_update_notify(std::uint32_t val, std::uint32_t mask, int shift); + + mutable std::uint32_t change_counter; std::uint32_t spiled_reg_led_line; std::uint32_t spiled_reg_led_rgb1; std::uint32_t spiled_reg_led_rgb2; diff --git a/qtmips_machine/physaddrspace.cpp b/qtmips_machine/physaddrspace.cpp index 4d0045c..22ae036 100644 --- a/qtmips_machine/physaddrspace.cpp +++ b/qtmips_machine/physaddrspace.cpp @@ -38,12 +38,12 @@ using namespace machine; PhysAddrSpace::PhysAddrSpace() { - + change_counter = 0; } PhysAddrSpace::~PhysAddrSpace() { while (!ranges_by_access.isEmpty()) { - RangeDesc *p_range = ranges_by_access.first(); + RangeDesc *p_range = ranges_by_addr.first(); ranges_by_addr.remove(p_range->last_addr); ranges_by_access.remove(p_range->mem_acces); if (p_range->owned) @@ -53,10 +53,14 @@ PhysAddrSpace::~PhysAddrSpace() { } bool PhysAddrSpace::wword(std::uint32_t address, std::uint32_t value) { + bool changed; RangeDesc *p_range = find_range(address); if (p_range == nullptr) return false; - return p_range->mem_acces->write_word(address - p_range->start_addr, value); + changed = p_range->mem_acces->write_word(address - p_range->start_addr, value); + if (changed) + change_counter++; + return changed; } std::uint32_t PhysAddrSpace::rword(std::uint32_t address, bool debug_access) const { @@ -66,6 +70,10 @@ std::uint32_t PhysAddrSpace::rword(std::uint32_t address, bool debug_access) con return p_range->mem_acces->read_word(address - p_range->start_addr, debug_access); } +std::uint32_t PhysAddrSpace::get_change_counter() const { + return change_counter; +} + enum LocationStatus PhysAddrSpace::location_status(std::uint32_t address) const { const RangeDesc *p_range = find_range(address); if (p_range == nullptr) @@ -92,7 +100,9 @@ bool PhysAddrSpace::insert_range(MemoryAccess *mem_acces, std::uint32_t start_ad return false; } ranges_by_addr.insert(last_addr, p_range); - ranges_by_access.insert(mem_acces, p_range); + ranges_by_access.insertMulti(mem_acces, p_range); + connect(mem_acces, SIGNAL(external_change_notify(const MemoryAccess*,std::uint32_t,std::uint32_t,bool)), + this, SLOT(range_external_change(const MemoryAccess*,std::uint32_t,std::uint32_t,bool))); return true; } @@ -119,6 +129,19 @@ void PhysAddrSpace::clean_range(std::uint32_t start_addr, std::uint32_t last_add } } +void PhysAddrSpace::range_external_change(const MemoryAccess *mem_access, std::uint32_t start_addr, + std::uint32_t last_addr, bool external) { + if (external) + change_counter++; + auto i = ranges_by_access.find(const_cast<MemoryAccess *>(mem_access)); + while (i != ranges_by_access.end() && i.key() == mem_access) { + RangeDesc *p_range = i.value(); + ++i; + emit external_change_notify(this, start_addr + p_range->start_addr, + last_addr + p_range->start_addr, external); + } +} + PhysAddrSpace::RangeDesc::RangeDesc(MemoryAccess *mem_acces, std::uint32_t start_addr, std::uint32_t last_addr, bool owned) { this->mem_acces = mem_acces; this->start_addr = start_addr; diff --git a/qtmips_machine/physaddrspace.h b/qtmips_machine/physaddrspace.h index 9c13e07..7bc126b 100644 --- a/qtmips_machine/physaddrspace.h +++ b/qtmips_machine/physaddrspace.h @@ -53,11 +53,15 @@ public: bool wword(std::uint32_t address, std::uint32_t value); std::uint32_t rword(std::uint32_t address, bool debug_access = false) const; + virtual std::uint32_t get_change_counter() const override; bool insert_range(MemoryAccess *mem_acces, std::uint32_t start_addr, std::uint32_t last_addr, bool move_ownership); bool remove_range(MemoryAccess *mem_acces); void clean_range(std::uint32_t start_addr, std::uint32_t last_addr); enum LocationStatus location_status(std::uint32_t offset) const; +private slots: + void range_external_change(const MemoryAccess *mem_access, std::uint32_t start_addr, + std::uint32_t last_addr, bool external); private: class RangeDesc { public: @@ -70,6 +74,7 @@ private: QMap<std::uint32_t, RangeDesc *> ranges_by_addr; QMap<MemoryAccess *, RangeDesc *> ranges_by_access; RangeDesc *find_range(std::uint32_t address) const; + mutable std::uint32_t change_counter; }; } diff --git a/qtmips_machine/qtmipsmachine.cpp b/qtmips_machine/qtmipsmachine.cpp index 982e581..8299ddf 100644 --- a/qtmips_machine/qtmipsmachine.cpp +++ b/qtmips_machine/qtmipsmachine.cpp @@ -186,6 +186,14 @@ Cache *QtMipsMachine::cache_data_rw() { return cch_data; } +const PhysAddrSpace *QtMipsMachine::physical_address_space() { + return physaddrspace; +} + +PhysAddrSpace *QtMipsMachine::physical_address_space_rw() { + return physaddrspace; +} + SerialPort *QtMipsMachine::serial_port() { return ser_port; } diff --git a/qtmips_machine/qtmipsmachine.h b/qtmips_machine/qtmipsmachine.h index 0d9875a..03cdad9 100644 --- a/qtmips_machine/qtmipsmachine.h +++ b/qtmips_machine/qtmipsmachine.h @@ -70,6 +70,8 @@ public: const Cache *cache_program(); const Cache *cache_data(); Cache *cache_data_rw(); + const PhysAddrSpace *physical_address_space(); + PhysAddrSpace *physical_address_space_rw(); SerialPort *serial_port(); PeripSpiLed *peripheral_spi_led(); LcdDisplay *peripheral_lcd_display(); diff --git a/qtmips_machine/serialport.cpp b/qtmips_machine/serialport.cpp index f1cb620..135d9ea 100644 --- a/qtmips_machine/serialport.cpp +++ b/qtmips_machine/serialport.cpp @@ -50,6 +50,7 @@ using namespace machine; SerialPort::SerialPort() { + change_counter = 0; rx_st_reg = 0; rx_data_reg = 0; tx_st_reg = 0; @@ -69,10 +70,12 @@ void SerialPort::pool_rx_byte() const { if (!(rx_st_reg & SERP_RX_ST_REG_READY_m)) { rx_st_reg |= SERP_RX_ST_REG_READY_m; emit rx_byte_pool(0, byte, available); - if (available) + if (available) { + change_counter++; rx_data_reg = byte; - else + } else { rx_st_reg &= ~SERP_RX_ST_REG_READY_m; + } } } @@ -87,7 +90,7 @@ bool SerialPort::wword(std::uint32_t address, std::uint32_t value) { case SERP_RX_ST_REG_o: rx_st_reg &= ~SERP_RX_ST_REG_IE_m; rx_st_reg |= value & SERP_RX_ST_REG_IE_m; - rx_queue_check(); + rx_queue_check_internal(); update_rx_irq(); break; case SERP_TX_ST_REG_o: @@ -119,12 +122,16 @@ std::uint32_t SerialPort::rword(std::uint32_t address, bool debug_access) const pool_rx_byte(); if (rx_st_reg & SERP_RX_ST_REG_READY_m) { value = rx_data_reg; - rx_st_reg &= ~SERP_RX_ST_REG_READY_m; - update_rx_irq(); + if (!debug_access) { + rx_st_reg &= ~SERP_RX_ST_REG_READY_m; + update_rx_irq(); + emit external_change_notify(this, SERP_RX_ST_REG_o, + SERP_RX_DATA_REG_o + 3, true); + } } else { value = 0; } - rx_queue_check(); + rx_queue_check_internal(); break; case SERP_TX_ST_REG_o: value = tx_st_reg | SERP_TX_ST_REG_READY_m; @@ -136,11 +143,16 @@ std::uint32_t SerialPort::rword(std::uint32_t address, bool debug_access) const return value; } +std::uint32_t SerialPort::get_change_counter() const { + return change_counter; +} + void SerialPort::update_rx_irq() const { bool active = !!(rx_st_reg & SERP_RX_ST_REG_IE_m); active &= !!(rx_st_reg & SERP_RX_ST_REG_READY_m); if (active != rx_irq_active) { rx_irq_active = active; + change_counter++; emit signal_interrupt(rx_irq_level, active); } } @@ -150,12 +162,19 @@ void SerialPort::update_tx_irq() const { active &= !!(tx_st_reg & SERP_TX_ST_REG_READY_m); if (active != tx_irq_active) { tx_irq_active = active; + change_counter++; emit signal_interrupt(tx_irq_level, active); } } -void SerialPort::rx_queue_check() const { +void SerialPort::rx_queue_check_internal() const { if (rx_st_reg & SERP_RX_ST_REG_IE_m) pool_rx_byte(); update_rx_irq(); } + +void SerialPort::rx_queue_check() const { + rx_queue_check_internal(); + emit external_change_notify(this, SERP_RX_ST_REG_o, + SERP_RX_DATA_REG_o + 3, true); +} diff --git a/qtmips_machine/serialport.h b/qtmips_machine/serialport.h index 0f469b7..095c06e 100644 --- a/qtmips_machine/serialport.h +++ b/qtmips_machine/serialport.h @@ -63,7 +63,10 @@ public slots: public: bool wword(std::uint32_t address, std::uint32_t value); std::uint32_t rword(std::uint32_t address, bool debug_access = false) const; + virtual std::uint32_t get_change_counter() const override; private: + void rx_queue_check_internal() const; + mutable std::uint32_t change_counter; void pool_rx_byte() const; void update_rx_irq() const; void update_tx_irq() const; |