diff options
-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; |