Initial commit for IOManager
MODIFY
src/io/iobase.cpp
src/io/iobase.cpp
@@ -4,6 +4,12 @@ namespace Ripes {
std::map<std::type_index, int> IOBase::s_peripheralCount;
+IOBase::IOBase(QWidget* parent) : QWidget(parent) {
+ registerPeripheral(this);
+
+ connect(this, &IOBase::scheduleUpdate, this, QOverload<>::of(&QWidget::update));
+}
+
bool IOBase::setParameter(unsigned ID, const QVariant& value) {
m_parameters.at(ID).value = value;
parameterChanged(ID);

MODIFY
src/io/iobase.h
src/io/iobase.h
@@ -35,7 +35,7 @@ class IOBase : public QWidget {
Q_OBJECT
public:
- IOBase(QWidget* parent) : QWidget(parent) { registerPeripheral(this); }
+ IOBase(QWidget* parent);
virtual ~IOBase() { deregisterPeripheral(this); };
const std::map<unsigned, IOParam>& parameters() const { return m_parameters; }
@@ -72,6 +72,13 @@ signals:
*/
void regMapChanged();
+ /**
+ * @brief scheduleUpdate
+ * Should be emitted when a peripheral requests to be repainted. We do this through signal/slot mechanisms to ensure
+ * that the actual update() is only performed on the GUI thread.
+ */
+ void scheduleUpdate();
+
protected:
virtual void parameterChanged(unsigned ID) = 0;

MODIFY
src/io/ioledmatrix.cpp
src/io/ioledmatrix.cpp
@@ -19,6 +19,14 @@ IOLedMatrix::IOLedMatrix(QWidget* parent) : IOBase(parent) {
updateLEDRegs();
}
+uint32_t IOLedMatrix::size() const {
+ const int width = m_parameters.at(WIDTH).value.toInt();
+ const int height = m_parameters.at(HEIGHT).value.toInt();
+ const int nLEDs = width * height;
+
+ return nLEDs * 4;
+}
+
QString IOLedMatrix::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 "
@@ -48,7 +56,14 @@ uint32_t IOLedMatrix::regRead(uint32_t offset) const {
void IOLedMatrix::ioWrite8(uint32_t offset, uint32_t value) {}
void IOLedMatrix::ioWrite16(uint32_t offset, uint32_t value) {}
-void IOLedMatrix::ioWrite32(uint32_t offset, uint32_t value) {}
+void IOLedMatrix::ioWrite32(uint32_t offset, uint32_t value) {
+ offset >>= 2; // word addressable
+ if (offset >= m_ledRegs.size()) {
+ Q_ASSERT(false);
+ }
+ m_ledRegs.at(offset) = value;
+ emit scheduleUpdate();
+}
inline QColor regToColor(uint32_t regVal) {
return QColor(regVal >> 16 & 0xFF, regVal >> 8 & 0xFF, regVal & 0xFF);
@@ -66,18 +81,6 @@ void IOLedMatrix::updateLEDRegs() {
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++) {
- const int r = (0xFF * x) / width;
- const int g = (0xFF * y) / height;
- const int b = (0xFF * (x + y)) / (width + height);
-
- const unsigned idx = y * width + x;
- m_ledRegs.at(idx) = r << 16 | g << 8 | b;
- }
- }
-
updateGeometry();
resize(minimumSize());
emit regMapChanged();

MODIFY
src/io/ioledmatrix.h
src/io/ioledmatrix.h
@@ -17,7 +17,7 @@ public:
IOLedMatrix(QWidget* parent);
~IOLedMatrix(){};
- virtual uint32_t size() const override { return (m_maxSideWidth * m_maxSideWidth) * 4; }
+ virtual uint32_t size() const override;
virtual QString description() const override;
virtual QString name() const override;

MODIFY
src/io/iomanager.cpp
src/io/iomanager.cpp
#include "iomanager.h"
+#include "processorhandler.h"
+#include "ripessettings.h"
+
+#include "VSRTL/core/vsrtl_sparsearray.h"
+
namespace Ripes {
-IOManager::IOManager() {}
+IOManager::IOManager() : QObject(nullptr) {
+ // Always re-register the currently active peripherals when the processor changes
+ connect(ProcessorHandler::get(), &ProcessorHandler::processorChanged, this, &IOManager::setProcessorPeripherals);
+}
IOBase* IOManager::createPeripheral(IOType type) {
auto* peripheral = IOFactories.at(type)(nullptr);
// Assign base address to peripheral
+ uint32_t base;
+ if (m_memoryMap.empty()) {
+ base = RipesSettings::value(RIPES_SETTING_PERIPHERALS_START).toUInt();
+ } else {
+ auto lastPeriph = m_memoryMap.rbegin();
+ base = lastPeriph->first + lastPeriph->second.size;
+ }
+
+ ProcessorHandler::get()->getMemory().addRegion(
+ base, peripheral->size(),
+ vsrtl::core::IOFunctors{
+ [peripheral](uint32_t offset, uint32_t value, uint32_t size) { peripheral->ioWrite32(offset, value); },
+ [peripheral](uint32_t offset, uint32_t size) { return peripheral->ioRead32(offset); }});
+
+ m_memoryMap[base] = {peripheral->size(), peripheral->name()};
return peripheral;
}
+void IOManager::setProcessorPeripherals() {}
+
} // namespace Ripes

MODIFY
src/io/iomanager.h
src/io/iomanager.h
@@ -12,13 +12,16 @@ struct MemoryMapEntry {
using MemoryMap = std::map<uint32_t, MemoryMapEntry>;
-class IOManager {
+class IOManager : public QObject {
+ Q_OBJECT
+
public:
IOManager();
IOBase* createPeripheral(IOType type);
const MemoryMap& memoryMap() const { return m_memoryMap; }
private:
+ void setProcessorPeripherals();
MemoryMap m_memoryMap;
};

MODIFY
src/processorhandler.cpp
src/processorhandler.cpp
@@ -76,7 +76,7 @@ void ProcessorHandler::writeMem(uint32_t address, uint32_t value, int size) {
m_currentProcessor->getMemory().writeMem(address, value, size);
}
-const vsrtl::core::SparseArrayMM& ProcessorHandler::getMemory() const {
+vsrtl::core::SparseArrayMM& ProcessorHandler::getMemory() {
return m_currentProcessor->getMemory();
}

MODIFY
src/processorhandler.h
src/processorhandler.h
@@ -88,7 +88,7 @@ public:
* @brief getMemory & getRegisters
* returns const-wrapped references to the current process memory elements
*/
- const vsrtl::core::SparseArrayMM& getMemory() const;
+ vsrtl::core::SparseArrayMM& getMemory();
const vsrtl::core::SparseArray& getRegisters() const;
const vsrtl::core::RVMemory<RV_REG_WIDTH, RV_REG_WIDTH>* getDataMemory() const;
const vsrtl::core::ROM<RV_REG_WIDTH, RV_INSTR_WIDTH>* getInstrMemory() const;

Initial commit for IOManager