aboutsummaryrefslogtreecommitdiff
path: root/qtmips_machine
diff options
context:
space:
mode:
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;