aboutsummaryrefslogtreecommitdiff
path: root/qtmips_machine
diff options
context:
space:
mode:
authorPavel Pisa <pisa@cmp.felk.cvut.cz>2019-06-30 18:22:27 +0200
committerPavel Pisa <pisa@cmp.felk.cvut.cz>2019-06-30 18:22:27 +0200
commit9dc519887f61ae33ff82bb125fb69398503f91f6 (patch)
treec0074870df060adc0f546715e39169cacc8d5667 /qtmips_machine
parentc86a491e26800f620b51ced800b612e73da1cced (diff)
downloadqtmips-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>
Diffstat (limited to 'qtmips_machine')
-rw-r--r--qtmips_machine/cache.cpp4
-rw-r--r--qtmips_machine/cache.h4
-rw-r--r--qtmips_machine/lcddisplay.cpp9
-rw-r--r--qtmips_machine/lcddisplay.h2
-rw-r--r--qtmips_machine/memory.cpp8
-rw-r--r--qtmips_machine/memory.h11
-rw-r--r--qtmips_machine/peripspiled.cpp50
-rw-r--r--qtmips_machine/peripspiled.h4
-rw-r--r--qtmips_machine/physaddrspace.cpp31
-rw-r--r--qtmips_machine/physaddrspace.h5
-rw-r--r--qtmips_machine/qtmipsmachine.cpp8
-rw-r--r--qtmips_machine/qtmipsmachine.h2
-rw-r--r--qtmips_machine/serialport.cpp33
-rw-r--r--qtmips_machine/serialport.h3
14 files changed, 140 insertions, 34 deletions
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;