Create validators for displaying and editing register content
MODIFY
src/mainwindow.cpp
src/mainwindow.cpp
@@ -17,6 +17,10 @@ MainWindow::MainWindow(Runner *runnerPtr, Parser *parserPtr, QWidget *parent)
// Setup tab pointers
m_ui->cachetab->setRunnerCachePtr(m_runnerPtr->getRunnerCachePtr());
+ m_ui->memorytab->setMemoryPtr(m_runnerPtr->getMemoryPtr());
+ m_ui->memorytab->setRegPtr(m_runnerPtr->getRegPtr());
+
+ m_ui->memorytab->init();
// setup example projects
setupExamples();

MODIFY
src/memorytab.cpp
src/memorytab.cpp
MemoryTab::MemoryTab(QWidget *parent)
: QWidget(parent), m_ui(new Ui::MemoryTab) {
m_ui->setupUi(this);
+}
+
+void MemoryTab::init() {
+ // !! m_memoryPtr and m_regPtr must be set before initializing
// Initialize register ABInames
QStringList ABInames = QStringList() << "zero"
@@ -77,15 +81,23 @@ MemoryTab::MemoryTab(QWidget *parent)
// Initialize 32 register widgets
for (int i = 0; i < 32; i++) {
auto reg = new RegisterWidget(this);
+ m_regWidgetPtrs.push_back(reg);
+ reg->setRegPtr(&(*m_regPtr)[i]);
reg->setAlias(ABInames[i]);
reg->setNumber(i);
reg->setToolTip(descriptions[i]);
reg->setDisplayType(m_ui->registerdisplaytype->currentText());
- reg->setRegPtr(&(*m_regPtr)[i]);
connect(m_ui->registerdisplaytype, &QComboBox::currentTextChanged,
[=](const QString &text) { reg->setDisplayType(text); });
m_ui->registerLayout->addWidget(reg);
}
+ m_regWidgetPtrs[0]->setEnabled(false);
+}
+
+void MemoryTab::updateRegisterWidget(int n) {
+ // Invoked when runner edits an internal register, requiring an update of the
+ // widget
+ m_regWidgetPtrs[n]->setText();
}
MemoryTab::~MemoryTab() { delete m_ui; }

MODIFY
src/memorytab.h
src/memorytab.h
@@ -7,6 +7,8 @@ namespace Ui {
class MemoryTab;
}
+class RegisterWidget;
+
class MemoryTab : public QWidget {
Q_OBJECT
@@ -14,14 +16,20 @@ public:
explicit MemoryTab(QWidget *parent = 0);
~MemoryTab();
- void setMemoryPtr(uint32_t *ptr) { m_memoryPtr = ptr; }
+ void setMemoryPtr(std::vector<uint8_t> *ptr) { m_memoryPtr = ptr; }
void setRegPtr(std::vector<uint32_t> *ptr) { m_regPtr = ptr; }
+ void init();
+
+public slots:
+ void updateRegisterWidget(int n);
private:
Ui::MemoryTab *m_ui;
- uint32_t *m_memoryPtr;
+ std::vector<uint8_t> *m_memoryPtr;
std::vector<uint32_t> *m_regPtr;
+
+ std::vector<RegisterWidget *> m_regWidgetPtrs;
};
#endif // MEMORYTAB_H

MODIFY
src/registerwidget.cpp
src/registerwidget.cpp
RegisterWidget::RegisterWidget(QWidget *parent)
: QWidget(parent), m_ui(new Ui::RegisterWidget) {
m_ui->setupUi(this);
- m_ui->value->setValidator(&m_validator);
+ // m_ui->value->setValidator(&m_validator);
+
+ connect(m_ui->value, &QLineEdit::editingFinished, this,
+ &RegisterWidget::validateInput);
}
RegisterWidget::~RegisterWidget() { delete m_ui; }
void RegisterWidget::setAlias(QString text) { m_ui->alias->setText(text); }
+void RegisterWidget::validateInput() {
+ // Instead of subclassing QValidator for ie. hex, we do some simple input
+ // validation here
+ const QString input = m_ui->value->text();
+
+ bool ok;
+ auto value = input.toLongLong(&ok, m_displayBase);
+ if (ok && value >= m_range.first &&
+ value <= m_range.second) { // verify "ok" and that value is within current
+ // accepted range of the display type
+ *m_regPtr = value;
+ } else {
+ // revert lineedit to the current register value
+ setText();
+ }
+}
+
+void RegisterWidget::setText() {
+ // Sets line edit text based on current display type and register value
+ if (m_displayType == displayTypes[0]) {
+ // hex
+ m_ui->value->setText(
+ QString()
+ .setNum(*m_regPtr, 16)
+ .rightJustified(8, '0')); // zero padding on hex numbers
+ } else if (m_displayType == displayTypes[1]) {
+ // binary
+ m_ui->value->setText(QString().setNum(*m_regPtr, 2));
+ } else if (m_displayType == displayTypes[2]) {
+ // Decimal
+ m_ui->value->setText(QString().setNum(*(int32_t *)m_regPtr, 10));
+ } else if (m_displayType == displayTypes[3]) {
+ // Unsigned
+ m_ui->value->setText(QString().setNum(*m_regPtr, 10));
+ } else if (m_displayType == displayTypes[4]) {
+ // ASCII - valid ascii characters will not be able to fill the 32-bit range
+ m_ui->value->setInputMask("nnnn");
+ } else if (m_displayType == displayTypes[5]) {
+ // float
+ m_ui->value->setInputMask("B");
+ }
+}
+
void RegisterWidget::setNumber(int number) {
m_ui->number->setText(QString("x(%1)").arg(number));
}
void RegisterWidget::setDisplayType(QString type) {
+ // Given a display type "type", sets validators for the input.
+
+ m_displayType = type;
if (type == displayTypes[0]) {
// hex
- m_ui->value->setInputMask("HHHHHHHH");
- m_ui->value->setText(QString().setNum(*m_regPtr, 16));
- // m_validator.setRange(0, 4294967295);
+ m_displayBase = 16;
+ m_ui->value->setInputMask("hhhhhhhh");
+ m_range = rangePair(0, (long long)4294967295);
+ setText();
} else if (type == displayTypes[1]) {
// binary
- m_ui->value->setInputMask("BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB");
- m_ui->value->setText(QString().setNum(*m_regPtr, 2));
- // m_validator.setRange(0, 4294967295);
+ m_displayBase = 2;
+ m_ui->value->setInputMask("bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb");
+ setText();
+ m_range = rangePair(0, (long long)4294967295);
} else if (type == displayTypes[2]) {
// Decimal
- m_ui->value->setInputMask("#9999999999");
- m_ui->value->setText(QString().setNum((int32_t)*m_regPtr, 10));
- // m_validator.setRange(-2147483648, 2147483647);
+ m_displayBase = 10;
+ m_ui->value->setInputMask("#0000000000");
+ setText();
+ m_range = rangePair(-(long long)2147483648, (long long)2147483647);
} else if (type == displayTypes[3]) {
// Unsigned
- m_ui->value->setInputMask("9999999999");
- m_ui->value->setText(QString().setNum(*m_regPtr, 10));
- // m_validator.setRange(0, 4294967295);
+ m_displayBase = 10;
+ m_ui->value->setInputMask("0000000000");
+ setText();
+ m_range = rangePair(0, (long long)4294967295);
} else if (type == displayTypes[4]) {
// ASCII - valid ascii characters will not be able to fill the 32-bit range
- m_ui->value->setInputMask("NNNN");
- // m_validator.setRange(0, 4294967295);
+ m_ui->value->setInputMask("nnnn");
+ m_range = rangePair(0, (long long)4294967295);
} else if (type == displayTypes[5]) {
// float
m_ui->value->setInputMask("B");
- // m_validator.setRange(0, 4294967295);
+ m_range = {0, (long)4294967295};
}
}
+
+void RegisterWidget::enableInput(bool state) {
+ // permanently called on reg[0], and on all registers when running simulation,
+ // to disable memory editing while running
+ m_ui->value->setEnabled(state);
+}

MODIFY
src/registerwidget.h
src/registerwidget.h
@@ -15,6 +15,14 @@ namespace Ui {
class RegisterWidget;
}
+namespace {
+typedef QPair<long long, long long> rangePair;
+}
+
+/*
+ * Widget for representing register contents
+*/
+
class RegisterWidget : public QWidget {
Q_OBJECT
@@ -26,12 +34,22 @@ public:
void setNumber(int number);
void setDisplayType(QString type);
void setRegPtr(uint32_t *ptr) { m_regPtr = ptr; }
+ void enableInput(bool state);
+
+public slots:
+ void setText();
+
+private slots:
+ void validateInput();
private:
Ui::RegisterWidget *m_ui;
QIntValidator m_validator;
-
+ QString m_displayType;
+ int m_displayBase = 10;
uint32_t *m_regPtr;
+
+ rangePair m_range;
};
#endif // REGISTERWIDGET_H

MODIFY
src/registerwidget.ui
src/registerwidget.ui
</spacer>
</item>
<item>
- <widget class="QLineEdit" name="lineEdit">
+ <widget class="QLineEdit" name="value">
<property name="sizePolicy">
<sizepolicy hsizetype="Minimum" vsizetype="Fixed">
<horstretch>0</horstretch>

MODIFY
src/runner.h
src/runner.h
@@ -20,6 +20,8 @@ public:
int exec();
RunnerCache *getRunnerCachePtr() { return &m_cache; }
+ std::vector<uint8_t> *getMemoryPtr() { return &m_text; }
+ std::vector<uint32_t> *getRegPtr() { return &m_reg; }
private:
instrState execInstruction(Instruction instr);
@@ -47,6 +49,8 @@ private:
int m_memsize;
Parser *m_parser;
+ bool m_running =
+ false; // flag for disabling UI update signals when running simulator
bool getInstruction(int pc);
Instruction m_currentInstruction;

Create validators for displaying and editing register content