Reimplement StageTable for the VSRTL Processor
MODIFY
external/VSRTL
external/VSRTL
-Subproject commit bdf1fa68836222e5b660d2fb963f2a5c3a5e7286
+Subproject commit 2e981658cfb29ae9ef6cf04fbe912c7b68c9c5b1

MODIFY
src/memoryviewerwidget.h
src/memoryviewerwidget.h
@@ -12,7 +12,7 @@ class MemoryViewerWidget : public QWidget {
Q_OBJECT
public:
- explicit MemoryViewerWidget(QWidget* parent = nullptr);
+ MemoryViewerWidget(QWidget* parent = nullptr);
~MemoryViewerWidget();
void updateModel();

MODIFY
src/processortab.cpp
src/processortab.cpp
#include "processorregistry.h"
#include "processorselectiondialog.h"
#include "registermodel.h"
+#include "stagetablemodel.h"
+#include "stagetablewidget.h"
#include "VSRTL/graphics/vsrtl_widget.h"
@@ -23,6 +25,9 @@ ProcessorTab::ProcessorTab(QToolBar* toolbar, QWidget* parent) : RipesTab(toolba
// Load the default processor
ProcessorHandler::get()->loadProcessorToWidget(m_vsrtlWidget);
+ m_stageModel = new StageTableModel(this);
+ connect(this, &ProcessorTab::update, m_stageModel, &StageTableModel::processorWasClocked);
+
updateInstructionModel();
m_ui->registerWidget->updateModel();
connect(this, &ProcessorTab::update, m_ui->registerWidget, &RegisterWidget::updateView);
@@ -132,7 +137,7 @@ void ProcessorTab::setupSimulatorActions() {
const QIcon tableIcon = QIcon(":/icons/spreadsheet.svg");
m_pipelineTableAction = new QAction(tableIcon, "Show pipelining table", this);
- // connect(m_pipelineTableAction, &QAction::triggered, this, &ProcessorTab::showPipeliningTable);
+ connect(m_pipelineTableAction, &QAction::triggered, this, &ProcessorTab::showStageTable);
m_toolbar->addAction(m_pipelineTableAction);
}
@@ -225,6 +230,7 @@ void ProcessorTab::enableSimulatorControls() {
void ProcessorTab::reset() {
m_autoClockAction->setChecked(false);
m_vsrtlWidget->reset();
+ m_stageModel->reset();
emit update();
enableSimulatorControls();
@@ -263,12 +269,7 @@ void ProcessorTab::clock() {
emit update();
}
-/*
-void ProcessorTab::showPipeliningTable() {
- // Setup pipeline table window
- PipelineTable window;
- PipelineTableModel model;
- window.setModel(&model);
- window.exec();
+void ProcessorTab::showStageTable() {
+ auto w = StageTableWidget(m_stageModel, this);
+ w.exec();
}
-*/

MODIFY
src/processortab.h
src/processortab.h
#include <QWidget>
#include "defines.h"
-// #include "pipelinetable.h"
-// #include "pipelinetablemodel.h"
#include "ripestab.h"
namespace Ui {
@@ -22,6 +20,7 @@ class VSRTLWidget;
class InstructionModel;
class RegisterModel;
+class StageTableModel;
class ProcessorTab : public RipesTab {
friend class RunDialog;
@@ -50,7 +49,7 @@ public slots:
private slots:
void clock();
void setInstructionViewCenterAddr(uint32_t address);
- // void showPipeliningTable();
+ void showStageTable();
private:
void setupSimulatorActions();
@@ -60,6 +59,7 @@ private:
Ui::ProcessorTab* m_ui;
InstructionModel* m_instrModel = nullptr;
+ StageTableModel* m_stageModel = nullptr;
vsrtl::VSRTLWidget* m_vsrtlWidget = nullptr;

ADD
src/stagetablemodel.cpp
+#include "stagetablemodel.h"
+
+#include "parser.h"
+
+#include <vector>
+
+StageTableModel::StageTableModel(QObject* parent) : QAbstractTableModel(parent) {}
+
+QVariant StageTableModel::headerData(int section, Qt::Orientation orientation, int role) const {
+ if (role != Qt::DisplayRole)
+ return QVariant();
+ if (orientation == Qt::Horizontal) {
+ // Cycle number
+ return QString::number(section);
+ } else {
+ return ProcessorHandler::get()->parseInstrAt(section *
+ ProcessorHandler::get()->getProcessor()->implementsISA()->bytes());
+ }
+}
+
+int StageTableModel::rowCount(const QModelIndex&) const {
+ return ProcessorHandler::get()->getCurrentProgramSize() /
+ ProcessorHandler::get()->getProcessor()->implementsISA()->bytes();
+}
+
+int StageTableModel::columnCount(const QModelIndex&) const {
+ return m_cycleStageInfos.size();
+}
+
+void StageTableModel::processorWasClocked() {
+ beginResetModel();
+ gatherStageInfo();
+ endResetModel();
+}
+
+void StageTableModel::reset() {
+ beginResetModel();
+ m_cycleStageInfos.clear();
+ endResetModel();
+}
+
+void StageTableModel::gatherStageInfo() {
+ for (int i = 0; i < ProcessorHandler::get()->getProcessor()->stageCount(); i++) {
+ const auto& stageName = ProcessorHandler::get()->getProcessor()->stageName(i);
+ m_cycleStageInfos[ProcessorHandler::get()->getProcessor()->getCycleCount()][stageName] =
+ ProcessorHandler::get()->getProcessor()->stageInfo(i);
+ }
+}
+
+QVariant StageTableModel::data(const QModelIndex& index, int role) const {
+ if (!index.isValid())
+ return QVariant();
+
+ if (role == Qt::TextAlignmentRole) {
+ return Qt::AlignCenter;
+ }
+
+ if (role != Qt::DisplayRole)
+ return QVariant();
+
+ if (!m_cycleStageInfos.count(index.column()))
+ return QVariant();
+
+ const uint32_t addr = index.row() * ProcessorHandler::get()->getProcessor()->implementsISA()->bytes();
+ const auto& stageInfo = m_cycleStageInfos.at(index.column());
+ for (const auto& si : stageInfo) {
+ if (si.second.pc == addr && si.second.pc_valid) {
+ return si.first;
+ }
+ }
+
+ return QVariant();
+}

RENAME
src/tmp_unused/pipelinetablemodel.h
src/stagetablemodel.h
-#ifndef PIPELINETABLEMODEL_H
-#define PIPELINETABLEMODEL_H
+#pragma once
#include <QAbstractTableModel>
-class Pipeline;
-class Parser;
-class PipelineTableModel : public QAbstractTableModel {
- Q_OBJECT
+#include "processorhandler.h"
+class StageTableModel : public QAbstractTableModel {
+ Q_OBJECT
public:
- explicit PipelineTableModel(QObject* parent = nullptr);
-
- // Header:
- QVariant headerData(int section, Qt::Orientation orientation, int role = Qt::DisplayRole) const override;
+ enum Column { Breakpoint = 0, PC = 1, Stage = 2, Instruction = 3, NColumns };
+ StageTableModel(QObject* parent = nullptr);
- // Basic functionality:
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;
+
+public slots:
+ void processorWasClocked();
+ void reset();
private:
- Pipeline* m_pipelinePtr;
- Parser* m_parserPtr;
-};
+ void gatherStageInfo();
-#endif // PIPELINETABLEMODEL_H
+ std::map<unsigned, std::map<QString, Ripes::StageInfo>> m_cycleStageInfos;
+};

ADD
src/stagetablewidget.cpp
+#include "stagetablewidget.h"
+#include "ui_stagetablewidget.h"
+
+#include <QClipboard>
+#include <QHeaderView>
+
+#include "stagetablemodel.h"
+
+StageTableWidget::StageTableWidget(StageTableModel* model, QWidget* parent)
+ : QDialog(parent), m_ui(new Ui::StageTableWidget) {
+ m_ui->setupUi(this);
+
+ m_stageModel = model;
+ m_ui->stageTableView->setModel(m_stageModel);
+
+ m_ui->stageTableView->horizontalHeader()->setMinimumSectionSize(0);
+ m_ui->stageTableView->resizeColumnsToContents();
+ m_ui->copy->setIcon(QIcon(":/icons/documents.svg"));
+}
+
+StageTableWidget::~StageTableWidget() {
+ delete m_ui;
+}
+
+void StageTableWidget::on_copy_clicked() {
+ // Copy entire table to clipboard, including headers
+ Q_ASSERT(m_stageModel != nullptr);
+ QString textualRepr;
+
+ // Copy headers
+ textualRepr.append('\t');
+ for (int j = 0; j < m_stageModel->columnCount(); j++) {
+ textualRepr.append(m_stageModel->headerData(j, Qt::Horizontal).toString());
+ textualRepr.append('\t');
+ }
+ textualRepr.append('\n');
+ // Copy data
+ for (int i = 0; i < m_stageModel->rowCount(); i++) {
+ textualRepr.append(m_stageModel->headerData(i, Qt::Vertical).toString());
+ textualRepr.append('\t');
+ for (int j = 0; j < m_stageModel->columnCount(); j++) {
+ textualRepr.append(m_stageModel->data(m_stageModel->index(i, j)).toString());
+ textualRepr.append('\t');
+ }
+ textualRepr.append('\n');
+ }
+ QApplication::clipboard()->setText(textualRepr);
+}

ADD
src/stagetablewidget.h
+#pragma once
+
+#include <QDialog>
+
+namespace Ui {
+class StageTableWidget;
+}
+
+class StageTableModel;
+
+QT_FORWARD_DECLARE_CLASS(QAbstractItemModel)
+
+class StageTableWidget : public QDialog {
+ Q_OBJECT
+
+public:
+ StageTableWidget(StageTableModel* model, QWidget* parent = nullptr);
+ ~StageTableWidget() override;
+
+private slots:
+ void on_copy_clicked();
+
+private:
+ Ui::StageTableWidget* m_ui;
+ StageTableModel* m_stageModel = nullptr;
+};

RENAME
src/tmp_unused/pipelinetable.ui
src/stagetablewidget.ui
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
- <class>PipelineTable</class>
- <widget class="QDialog" name="PipelineTable">
+ <class>StageTableWidget</class>
+ <widget class="QDialog" name="StageTableWidget">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
- <width>400</width>
- <height>300</height>
+ <width>748</width>
+ <height>452</height>
</rect>
</property>
<property name="windowTitle">
- <string>Pipeline table</string>
+ <string>Stage table</string>
</property>
<property name="windowIcon">
- <iconset resource="../resources/images.qrc">
+ <iconset>
<normaloff>:/icons/logo.png</normaloff>:/icons/logo.png</iconset>
</property>
<layout class="QGridLayout" name="gridLayout">
<layout class="QVBoxLayout" name="verticalLayout">
<item>
<layout class="QHBoxLayout" name="horizontalLayout">
- <item>
- <widget class="QLabel" name="description">
- <property name="text">
- <string>description...</string>
- </property>
- <property name="textFormat">
- <enum>Qt::RichText</enum>
- </property>
- </widget>
- </item>
<item>
<widget class="QToolButton" name="copy">
<property name="toolTip">
<property name="text">
<string>...</string>
</property>
- <property name="icon">
- <iconset resource="../resources/images.qrc">
- <normaloff>:/icons/documents.svg</normaloff>:/icons/documents.svg</iconset>
- </property>
<property name="iconSize">
<size>
<width>24</width>
</layout>
</item>
<item>
- <widget class="QTableView" name="table"/>
+ <widget class="QTableView" name="stageTableView"/>
</item>
</layout>
</item>
</layout>
</widget>
- <resources>
- <include location="../resources/images.qrc"/>
- </resources>
+ <resources/>
<connections/>
</ui>

DELETE
src/tmp_unused/pipelinetable.cpp
-#include "pipelinetable.h"
-#include "ui_pipelinetable.h"
-
-#include <QClipboard>
-#include <QHeaderView>
-
-PipelineTable::PipelineTable(QWidget* parent) : QDialog(parent), ui(new Ui::PipelineTable) {
- ui->setupUi(this);
- this->setModal(true);
- ui->table->horizontalHeader()->setSectionResizeMode(QHeaderView::ResizeToContents);
-
- ui->description->setText(QString(
- "<b>Note:</b> The pipeline table can be copied as tab separated,<br>suitable for pasting into a spreadsheet"));
-}
-
-void PipelineTable::setModel(QAbstractItemModel* model) {
- ui->table->setModel(model);
- m_model = model;
-}
-
-PipelineTable::~PipelineTable() {
- delete ui;
-}
-
-void PipelineTable::on_copy_clicked() {
- // Copy entire table to clipboard, including headers
- Q_ASSERT(m_model != nullptr);
- QString textualRepr;
-
- // Copy headers
- textualRepr.append('\t');
- for (int j = 0; j < m_model->columnCount(); j++) {
- textualRepr.append(m_model->headerData(j, Qt::Horizontal).toString());
- textualRepr.append('\t');
- }
- textualRepr.append('\n');
- // Copy data
- for (int i = 0; i < m_model->rowCount(); i++) {
- textualRepr.append(m_model->headerData(i, Qt::Vertical).toString());
- textualRepr.append('\t');
- for (int j = 0; j < m_model->columnCount(); j++) {
- textualRepr.append(m_model->data(m_model->index(i, j)).toString());
- textualRepr.append('\t');
- }
- textualRepr.append('\n');
- }
- QApplication::clipboard()->setText(textualRepr);
-}

DELETE
src/tmp_unused/pipelinetable.h
-#ifndef PIPELINETABLE_H
-#define PIPELINETABLE_H
-
-#include <QDialog>
-
-namespace Ui {
-class PipelineTable;
-}
-
-QT_FORWARD_DECLARE_CLASS(QAbstractItemModel)
-
-class PipelineTable : public QDialog {
- Q_OBJECT
-
-public:
- explicit PipelineTable(QWidget* parent = nullptr);
- ~PipelineTable() override;
- void setModel(QAbstractItemModel* model);
-
-private slots:
- void on_copy_clicked();
-
-private:
- Ui::PipelineTable* ui;
- QAbstractItemModel* m_model = nullptr;
-};
-
-#endif // PIPELINETABLE_H

DELETE
src/tmp_unused/pipelinetablemodel.cpp
-#include "pipelinetablemodel.h"
-
-#include "parser.h"
-
-#include <vector>
-
-PipelineTableModel::PipelineTableModel(QObject* parent) : QAbstractTableModel(parent) {
- m_pipelinePtr = Pipeline::getPipeline();
- m_parserPtr = Parser::getParser();
-}
-
-QVariant PipelineTableModel::headerData(int section, Qt::Orientation orientation, int role) const {
- if (role != Qt::DisplayRole)
- return QVariant();
- if (orientation == Qt::Horizontal) {
- // Cycle number
- return QString::number(section);
- } else {
- return m_parserPtr->getInstructionString(section * 4);
- }
- return QVariant();
-}
-int PipelineTableModel::rowCount(const QModelIndex& parent) const {
- Q_UNUSED(parent);
- int size = m_pipelinePtr->getTextSize() / 4;
- return size;
-}
-
-int PipelineTableModel::columnCount(const QModelIndex& parent) const {
- Q_UNUSED(parent);
- int size = m_pipelinePtr->getPcsList().size();
- return size;
-}
-
-QVariant PipelineTableModel::data(const QModelIndex& index, int role) const {
- if (!index.isValid() || role != Qt::DisplayRole)
- return QVariant();
- int cycle = index.column();
- uint32_t addr = index.row() * 4;
- const StagePCS& pcs = m_pipelinePtr->getPcsList()[cycle];
- StagePCS pcsPre;
- if (cycle > 0)
- pcsPre = m_pipelinePtr->getPcsList()[cycle - 1];
-
- QString stage;
- if (pcs.IF.pc == addr && pcs.IF.initialized == true && pcs.IF.invalidReason == 0) {
- // Check if PC is duplicate in current and previous stage. If so, a stall is present, and we write a "-" in the
- // table
- if (pcs.IF.pc != pcsPre.IF.pc) {
- stage = "F";
- } else {
- stage = "-";
- }
- } else if (pcs.ID.pc == addr && pcs.ID.initialized == true && pcs.ID.invalidReason == 0) {
- if ((pcs.ID.pc != pcsPre.ID.pc) || !pcsPre.ID.initialized) {
- stage = "D";
- } else {
- stage = "-";
- }
- } else if (pcs.EX.pc == addr && pcs.EX.initialized == true && pcs.EX.invalidReason == 0) {
- stage = "E";
- } else if (pcs.MEM.pc == addr && pcs.MEM.initialized == true && pcs.MEM.invalidReason == 0) {
- stage = "M";
- } else if (pcs.WB.pc == addr && pcs.WB.initialized == true && pcs.WB.invalidReason == 0) {
- stage = "W";
- }
- return stage;
-
- return QVariant();
-}

Reimplement StageTable for the VSRTL Processor