Add MVC model for peripheral register maps
MODIFY
src/io/iobase.h
src/io/iobase.h
@@ -23,6 +23,14 @@ struct IOParam {
QVariant max;
};
+struct RegDesc {
+ enum class RW { R, W, RW };
+ QString name;
+ RW rw;
+ unsigned bitWidth;
+ uint32_t address;
+};
+
class IOBase : public QWidget {
Q_OBJECT
@@ -34,6 +42,12 @@ public:
virtual QString description() const = 0;
virtual QString name() const = 0;
+ /**
+ * @brief registers
+ * @return a description of the programmable interface of this peripheral
+ */
+ virtual const std::vector<RegDesc>& registers() const = 0;
+
/**
* @brief setParameter
* Attempt to set the parameter @p ID to @p value. Returns the value that the parameter was set to (use this to

MODIFY
src/io/ioledmatrix.cpp
src/io/ioledmatrix.cpp
@@ -63,6 +63,12 @@ void IOLedMatrix::updateLEDRegs() {
const int height = m_parameters[HEIGHT].value.toInt();
m_ledRegs.resize(width * width);
+ m_regDescs.clear();
+ m_regDescs.resize(width * height);
+ for (unsigned i = 0; i < m_regDescs.size(); i++) {
+ m_regDescs.at(i) = RegDesc{"LED_" + QString::number(i), RegDesc::RW::RW, 24, i * 4};
+ }
+
// DEBUG: test pattern
for (int y = 0; y < height; y++) {
for (int x = 0; x < width; x++) {

MODIFY
src/io/ioledmatrix.h
src/io/ioledmatrix.h
@@ -24,6 +24,7 @@ public:
virtual QString name() const override;
virtual const QVariant& setParameter(unsigned ID, const QVariant& value) override;
+ virtual const std::vector<RegDesc>& registers() const override { return m_regDescs; };
/**
* Hardware read/write functions
@@ -48,6 +49,7 @@ private:
unsigned m_maxSideWidth = 256;
std::vector<uint32_t> m_ledRegs;
+ std::vector<RegDesc> m_regDescs;
QPen m_pen;
};

MODIFY
src/io/ioswitches.cpp
src/io/ioswitches.cpp
@@ -149,10 +149,8 @@ IOSwitches::IOSwitches(QWidget* parent, uint32_t startAddr) : IOBase(parent, sta
QString IOSwitches::description() const {
QStringList desc;
- desc << "Each LED maps to a 24-bit register storing an RGB color value, with B stored in the least significant "
- "byte.";
- desc << "The byte offset of the LED at coordinates (x, y) is:";
- desc << " offset = (y + x*N_LEDS_ROW) * 4";
+ desc << "Each switch maps to a bit in the memory-mapped register of the peripheral.";
+ desc << "switch n = bit n";
return desc.join('\n');
}
@@ -170,7 +168,7 @@ const QVariant& IOSwitches::setParameter(unsigned ID, const QVariant& value) {
}
void IOSwitches::updateSwitches() {
- const int nSwitches = m_parameters.at(SWITCHES).value.toInt();
+ const unsigned nSwitches = m_parameters.at(SWITCHES).value.toInt();
for (int i = 0; i < nSwitches; i++) {
if (m_switches.size() <= i) {
auto* sw = new ToggleButton(10, 8, true, this);
@@ -188,6 +186,8 @@ void IOSwitches::updateSwitches() {
m_switches.erase(i);
}
+
+ m_regDescs = {RegDesc{"Switches", RegDesc::RW::R, nSwitches, 0}};
}
uint32_t IOSwitches::ioRead8(uint32_t offset) {

MODIFY
src/io/ioswitches.h
src/io/ioswitches.h
@@ -70,6 +70,7 @@ public:
virtual QString name() const override;
virtual const QVariant& setParameter(unsigned ID, const QVariant& value) override;
+ virtual const std::vector<RegDesc>& registers() const override { return m_regDescs; };
/**
* Hardware read/write functions
@@ -88,5 +89,6 @@ private:
uint32_t m_values;
std::map<int, std::pair<QLabel*, ToggleButton*>> m_switches;
QGridLayout* m_switchLayout;
+ std::vector<RegDesc> m_regDescs;
};
} // namespace Ripes

ADD
src/io/registermapmodel.cpp
+#include "registermapmodel.h"
+
+#include <QHeaderView>
+
+#include "iobase.h"
+#include "processorhandler.h"
+
+namespace Ripes {
+
+RegisterMapModel::RegisterMapModel(IOBase* peripheral, QObject* parent)
+ : QAbstractTableModel(parent), m_peripheral(peripheral) {}
+
+int RegisterMapModel::columnCount(const QModelIndex&) const {
+ return NColumns;
+}
+
+int RegisterMapModel::rowCount(const QModelIndex&) const {
+ return m_peripheral->registers().size();
+}
+
+QVariant RegisterMapModel::headerData(int section, Qt::Orientation orientation, int role) const {
+ if (orientation == Qt::Horizontal && role == Qt::DisplayRole) {
+ switch (section) {
+ case Column::Name:
+ return "Name";
+ case Column::Address:
+ return "Address";
+ case Column::RW:
+ return "R/W?";
+ case Column::BitWidth:
+ return "Size";
+ default:
+ return QVariant();
+ }
+ }
+ return QVariant();
+}
+
+QVariant RegisterMapModel::data(const QModelIndex& index, int role) const {
+ if (!index.isValid()) {
+ return QVariant();
+ }
+
+ const unsigned idx = index.row();
+ switch (index.column()) {
+ case Column::Name: {
+ if (role == Qt::DisplayRole) {
+ return m_peripheral->registers().at(idx).name;
+ }
+ break;
+ }
+ case Column::Address: {
+ switch (role) {
+ case Qt::DisplayRole:
+ return "0x" + QString::number(m_peripheral->registers().at(idx).address, 16);
+ case Qt::FontRole:
+ return QFont("Inconsolata", 11);
+ case Qt::TextAlignmentRole:
+ return Qt::AlignCenter;
+ }
+ break;
+ }
+ case Column::RW: {
+ switch (role) {
+ case Qt::DisplayRole: {
+ switch (m_peripheral->registers().at(idx).rw) {
+ case RegDesc::RW::R:
+ return "R";
+ case RegDesc::RW::W:
+ return "W";
+ case RegDesc::RW::RW:
+ return "R/W";
+ }
+ }
+ case Qt::TextAlignmentRole:
+ return Qt::AlignCenter;
+ }
+ break;
+ }
+
+ case Column::BitWidth: {
+ switch (role) {
+ case Qt::DisplayRole:
+ return QString::number(m_peripheral->registers().at(idx).bitWidth);
+ case Qt::TextAlignmentRole:
+ return Qt::AlignCenter;
+ }
+ break;
+ }
+ default:
+ return QVariant();
+ }
+ return QVariant();
+}
+
+Qt::ItemFlags RegisterMapModel::flags(const QModelIndex&) const {
+ return Qt::ItemIsEnabled;
+}
+} // namespace Ripes

ADD
src/io/registermapmodel.h
+#pragma once
+
+#include <QColor>
+#include <set>
+#include "defines.h"
+#include "mainmemory.h"
+
+#include "isa/isainfo.h"
+#include "radix.h"
+
+#include <QAbstractTableModel>
+
+namespace Ripes {
+class IOBase;
+
+class RegisterMapModel : public QAbstractTableModel {
+ Q_OBJECT
+public:
+ enum Column { Name, Address, RW, BitWidth, NColumns };
+ RegisterMapModel(IOBase* peripheral, QObject* parent = nullptr);
+
+ int rowCount(const QModelIndex& parent = QModelIndex()) const override;
+ int columnCount(const QModelIndex& parent = QModelIndex()) const override;
+
+ QVariant data(const QModelIndex& index, int role = Qt::DisplayRole) const override;
+ QVariant headerData(int section, Qt::Orientation orientation, int role = Qt::DisplayRole) const override;
+
+ Qt::ItemFlags flags(const QModelIndex& index) const override;
+
+private:
+ IOBase* m_peripheral = nullptr;
+};
+} // namespace Ripes

MODIFY
src/ioperipheraltab.cpp
src/ioperipheraltab.cpp
#include "ui_ioperipheraltab.h"
#include "io/iobase.h"
+#include "io/registermapmodel.h"
namespace Ripes {
@@ -10,6 +11,9 @@ IOPeripheralTab::IOPeripheralTab(QWidget* parent, IOBase* peripheral)
m_ui->setupUi(this);
m_ui->description->setText(m_peripheral->description());
+ m_ui->registerMapView->setModel(new RegisterMapModel(peripheral, this));
+ m_ui->registerMapView->horizontalHeader()->setStretchLastSection(true);
+ m_ui->registerMapView->resizeColumnsToContents();
}
IOPeripheralTab::~IOPeripheralTab() {

MODIFY
src/ioperipheraltab.ui
src/ioperipheraltab.ui
<x>0</x>
<y>0</y>
<width>400</width>
- <height>329</height>
+ <height>397</height>
</rect>
</property>
<property name="windowTitle">
<string>Parameters</string>
</property>
<layout class="QGridLayout" name="gridLayout_4">
+ <property name="leftMargin">
+ <number>0</number>
+ </property>
+ <property name="topMargin">
+ <number>0</number>
+ </property>
+ <property name="rightMargin">
+ <number>0</number>
+ </property>
+ <property name="bottomMargin">
+ <number>0</number>
+ </property>
<item row="0" column="0">
<widget class="QTableView" name="parameterView"/>
</item>
<string>Register map</string>
</property>
<layout class="QGridLayout" name="gridLayout_2">
+ <property name="leftMargin">
+ <number>0</number>
+ </property>
+ <property name="topMargin">
+ <number>0</number>
+ </property>
+ <property name="rightMargin">
+ <number>0</number>
+ </property>
+ <property name="bottomMargin">
+ <number>0</number>
+ </property>
<item row="0" column="0">
<widget class="QTableView" name="registerMapView"/>
</item>
<string>Code example</string>
</property>
<layout class="QGridLayout" name="gridLayout_3">
+ <property name="leftMargin">
+ <number>0</number>
+ </property>
+ <property name="topMargin">
+ <number>0</number>
+ </property>
+ <property name="rightMargin">
+ <number>0</number>
+ </property>
+ <property name="bottomMargin">
+ <number>0</number>
+ </property>
<item row="0" column="0">
<widget class="QPlainTextEdit" name="codeExample">
<property name="readOnly">

MODIFY
src/mainmemory.h
src/mainmemory.h
namespace Ripes {
// RVAccess struct - used for keeping track of read and write access to memory, for displaying in GUI
-enum class RW { Read, Write };
+enum class RW { Read, Write, ReadWrite };
typedef struct {
uint32_t pc; // GUI converts pc value to an instruction
RW rw;

Add MVC model for peripheral register maps