Skip to content

Commit

Permalink
GUI: Coreview optimize updates
Browse files Browse the repository at this point in the history
  • Loading branch information
jdupak committed Dec 31, 2024
1 parent 5bedaac commit 5061a99
Show file tree
Hide file tree
Showing 2 changed files with 125 additions and 22 deletions.
77 changes: 70 additions & 7 deletions src/gui/windows/coreview/components/value_handlers.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,9 @@

using svgscene::SimpleTextItem;

const QString BoolValue::TRUE_STRING = QStringLiteral("1");
const QString BoolValue::FALSE_STRING = QStringLiteral("0");

const QString BoolValue::COMPONENT_NAME = QStringLiteral("bool-value");
const QString PCValue::COMPONENT_NAME = QStringLiteral("pc-value");
const QString RegValue::COMPONENT_NAME = QStringLiteral("reg-value");
Expand All @@ -12,12 +15,55 @@ const QString DebugValue::COMPONENT_NAME = QStringLiteral("debug-value");
const QString MultiTextValue::COMPONENT_NAME = QStringLiteral("multi-text-value");
const QString InstructionValue::COMPONENT_NAME = QStringLiteral("instruction-value");

constexpr QChar to_hex_digit(unsigned int value) {
constexpr QChar digits[16]
= { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f' };
return digits[value];
}

constexpr char16_t to_dec_digit(unsigned int value) {
constexpr char16_t digits[10] = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9' };
return digits[value];
}

template<size_t PrefixLen>
void set_hex_string(QString &buffer, uint32_t value) {
auto it = buffer.begin() + PrefixLen;
for (size_t i = 0; i < 8; ++i) {
*it++ = to_hex_digit((value >> 28) & 0xf);
value <<= 4;
}
}

void set_dec_value(QString &buffer, uint32_t value, QChar fill_char = ' ') {
if (value < 10) {
buffer.resize(2, fill_char);
buffer[0] = to_dec_digit(value);
return;
}

auto len = (size_t)ceil(log10(value) + 1);
buffer.resize(len, fill_char);
auto buffer_data = buffer.data_ptr();
auto it = buffer_data.begin() + len;
while (value > 0 && it != buffer_data.begin()) {
*--it = to_dec_digit(value % 10);
value /= 10;
}
}

BoolValue::BoolValue(SimpleTextItem *const element, const bool &data)
: element(element)
, data(data) {}

void BoolValue::update() {
element->setText(data ? QStringLiteral("1") : QStringLiteral("0"));
if (data.fetch_and_compare()) {
if (data.get()) {
element->setText(TRUE_STRING);
} else {
element->setText(FALSE_STRING);
}
}
}

PCValue::PCValue(SimpleTextItem *element, const machine::Address &data)
Expand All @@ -30,35 +76,47 @@ PCValue::PCValue(const PCValue &other)
, data(other.data) {}

void PCValue::clicked() {
emit jump_to_pc(data);
emit jump_to_pc(data.get_direct());
}

void PCValue::update() {
element->setText(QString("0x%1").arg(data.get_raw(), 8, 16, QChar('0')));
if (data.fetch_and_compare()) {
set_hex_string<2>(buffer, data.get().get_raw());
element->setText(buffer);
}
}

RegValue::RegValue(SimpleTextItem *element, const machine::RegisterValue &data)
: element(element)
, data(data) {}

void RegValue::update() {
element->setText(QString("%1").arg(data.as_u32(), 8, 16, QChar('0')));
if (data.fetch_and_compare()) {
set_hex_string<0>(buffer, data.get().as_u32());
element->setText(buffer);
}
}

RegIdValue::RegIdValue(svgscene::SimpleTextItem *element, const machine::RegisterId &data)
: element(element)
, data(data) {}

void RegIdValue::update() {
element->setText(QString("%1").arg(data, 2, 10, QChar('0')));
if (data.fetch_and_compare()) {
set_dec_value(buffer, data.get(), '0');
element->setText(buffer);
}
}

DebugValue::DebugValue(SimpleTextItem *element, const unsigned int &data)
: element(element)
, data(data) {}

void DebugValue::update() {
element->setText(QString("%1").arg(data, 0, 10, QChar(' ')));
if (data.fetch_and_compare()) {
set_dec_value(buffer, data.get());
element->setText(buffer);
}
}
MultiTextValue::MultiTextValue(SimpleTextItem *const element, Data data)
: element(element)
Expand All @@ -82,5 +140,10 @@ InstructionValue::InstructionValue(SimpleTextItem *const element, Data data)
, address_data(data.second) {}

void InstructionValue::update() {
element->setText(instruction_data.to_str(address_data));
bool inst_changed = instruction_data.fetch_and_compare();
bool addr_changed = address_data.fetch_and_compare();
// Both must be updated.
if (inst_changed || addr_changed) {
element->setText(instruction_data.get().to_str(address_data.get()));
}
}
70 changes: 55 additions & 15 deletions src/gui/windows/coreview/components/value_handlers.h
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,40 @@
#include <utility>
#include <vector>

/**
* Proxy for a value that can be fetched from a reference and compared to previous value.
*/
template<typename T>
class ValueProxy {
public:
ValueProxy(const T &data) : data(data), last_value(data) {}

/**
* Fetch new value and return true if it changed from last time this function was called.
*/
bool fetch_and_compare() {
if (data != last_value) {
last_value = data;
return true;
}
return false;
}

/**
* Get the last fetched value.
*/
const T &get() const { return last_value; }

/**
* Get remote value directly.
*/
const T &get_direct() const { return data; }

private:
const T &data;
T last_value;
};

class BoolValue {
public:
BoolValue(svgscene::SimpleTextItem *element, const bool &data);
Expand All @@ -28,7 +62,10 @@ class BoolValue {

private:
BORROWED svgscene::SimpleTextItem *const element;
const bool &data;
ValueProxy<bool> data;

static const QString TRUE_STRING;
static const QString FALSE_STRING;
};

class PCValue : public QObject {
Expand All @@ -47,7 +84,8 @@ public slots:

private:
BORROWED svgscene::SimpleTextItem *const element;
const machine::Address &data;
ValueProxy<machine::Address> data;
QString buffer { "0x00000000" };
};

class RegValue {
Expand All @@ -58,18 +96,20 @@ class RegValue {

private:
BORROWED svgscene::SimpleTextItem *const element;
const machine::RegisterValue &data;
ValueProxy<machine::RegisterValue> data;
QString buffer { "00000000" };
};

class RegIdValue {
public:
RegIdValue(svgscene::SimpleTextItem *element, const machine::RegisterId &data);
void update();
static const QString COMPONENT_NAME;
QString buffer { "00" };

private:
BORROWED svgscene::SimpleTextItem *const element;
const machine::RegisterId &data;
ValueProxy<machine::RegisterId> data;
};

class DebugValue {
Expand All @@ -80,7 +120,8 @@ class DebugValue {

private:
BORROWED svgscene::SimpleTextItem *const element;
const unsigned &data;
ValueProxy<unsigned> data;
QString buffer { "0" };
};

class MultiTextValue {
Expand All @@ -95,6 +136,7 @@ class MultiTextValue {
private:
BORROWED svgscene::SimpleTextItem *const element;
const unsigned &current_text_index;
unsigned last_text_index;
Source &text_table;
QBrush originalBrush;
};
Expand All @@ -109,8 +151,8 @@ class InstructionValue {

private:
BORROWED svgscene::SimpleTextItem *const element;
const machine::Instruction &instruction_data;
const machine::Address &address_data;
ValueProxy<machine::Instruction> instruction_data;
ValueProxy<machine::Address> address_data;
};

template<typename SOURCE>
Expand All @@ -120,25 +162,23 @@ class Multiplexer {
std::vector<BORROWED QGraphicsPathItem *> connections,
const SOURCE &active_connection)
: connections(std::move(connections))
, active_connection(active_connection)
, current_active_connection(0) {
, active_connection(active_connection) {
// Hide all but first
for (size_t i = 1; i < this->connections.size(); ++i) {
this->connections.at(i)->hide();
}
}
void update() {
if (current_active_connection != active_connection) {
connections.at(static_cast<unsigned>(current_active_connection))->hide();
connections.at(static_cast<unsigned>(active_connection))->show();
current_active_connection = active_connection;
auto old_connection = active_connection.get();
if (active_connection.fetch_and_compare()) {
connections.at(static_cast<unsigned>(old_connection))->hide();
connections.at(static_cast<unsigned>(active_connection.get()))->show();
}
}

private:
const std::vector<BORROWED QGraphicsPathItem *> connections;
const SOURCE &active_connection;
SOURCE current_active_connection;
ValueProxy<SOURCE> active_connection;
};

#endif // QTRVSIM_VALUE_HANDLERS_H

0 comments on commit 5061a99

Please sign in to comment.