summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorbd <bdunaisky@umass.edu>2025-04-28 03:44:42 +0000
committerGitHub <noreply@github.com>2025-04-28 03:44:42 +0000
commit013a79547aa465872d0262b2f5c24e73f9556869 (patch)
tree28cc8f2ea6e5aa1a74f328de8594b0ad5995fa66
parent5653b2a033e7a4173d2f178b5ce52384666d3d7b (diff)
parent336faf3fd701aaf962613abd1ff0a69cbdf021ce (diff)
Merge pull request #69 from bdunahu/vector_ext
Vector ext
-rw-r--r--gui/cachewaysselector.cc58
-rw-r--r--gui/cachewaysselector.h (renamed from gui/dynamicwaysentry.h)45
-rw-r--r--gui/digitlabeldelegate.cc8
-rw-r--r--gui/dynamicwaysentry.cc99
-rw-r--r--gui/gui.cc65
-rw-r--r--gui/gui.h4
-rw-r--r--gui/gui.ui128
-rw-r--r--gui/messages.h3
-rw-r--r--gui/registerview.cc69
-rw-r--r--gui/registerview.h64
-rw-r--r--gui/resources.qrc4
-rw-r--r--gui/resources/arrow_down.pngbin0 -> 228 bytes
-rw-r--r--gui/resources/arrow_down_pressed.pngbin0 -> 234 bytes
-rw-r--r--gui/resources/arrow_up.pngbin0 -> 221 bytes
-rw-r--r--gui/resources/arrow_up_pressed.pngbin0 -> 227 bytes
-rw-r--r--gui/resources/styles.qss62
-rw-r--r--gui/storageview.cc5
-rw-r--r--gui/storageview.h14
-rw-r--r--gui/worker.cc25
-rw-r--r--gui/worker.h22
-rw-r--r--inc/controller.h6
-rw-r--r--inc/ex.h12
-rw-r--r--inc/id.h14
-rw-r--r--inc/instrDTO.h12
-rw-r--r--inc/pipe_spec.h2
-rw-r--r--inc/stage.h40
-rw-r--r--src/controller.cc9
-rw-r--r--src/ex.cc613
-rw-r--r--src/id.cc221
-rw-r--r--src/mm.cc52
-rw-r--r--src/stage.cc43
-rw-r--r--src/wb.cc13
32 files changed, 908 insertions, 804 deletions
diff --git a/gui/cachewaysselector.cc b/gui/cachewaysselector.cc
new file mode 100644
index 0000000..14dae6f
--- /dev/null
+++ b/gui/cachewaysselector.cc
@@ -0,0 +1,58 @@
+// Simulator for the RISC-V[ECTOR] mini-ISA
+// Copyright (C) 2025 Siddarth Suresh
+// Copyright (C) 2025 bdunahu
+
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License
+// along with this program. If not, see <https://www.gnu.org/licenses/>.
+
+#include "cachewaysselector.h"
+#include <QHBoxLayout>
+#include <QLabel>
+#include <QSpinBox>
+#include <QVBoxLayout>
+
+CacheWaysSelector::CacheWaysSelector(QWidget *parent) : QWidget(parent)
+{
+ QVBoxLayout *v;
+ QHBoxLayout *l;
+ QSpinBox *sb;
+ QLabel *b;
+ int i;
+
+ v = new QVBoxLayout(this);
+
+ for (i = 1; i <= 6; ++i) {
+ l = new QHBoxLayout;
+
+ b = new QLabel(QString("L%1 2^").arg(i), this);
+
+ sb = new QSpinBox;
+ sb->setRange(-1, 4);
+ sb->setValue(-1);
+
+ l->addWidget(b);
+ l->addWidget(sb);
+
+ v->addLayout(l);
+ this->sbs.append(sb);
+ }
+}
+
+QList<int> CacheWaysSelector::values() const
+{
+ QList<int> r;
+ for (const QSpinBox *sb : this->sbs) {
+ r.append(sb->value());
+ }
+ return r;
+}
diff --git a/gui/dynamicwaysentry.h b/gui/cachewaysselector.h
index 26b8b3e..4612b0c 100644
--- a/gui/dynamicwaysentry.h
+++ b/gui/cachewaysselector.h
@@ -15,37 +15,36 @@
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <https://www.gnu.org/licenses/>.
-#ifndef DYNAMICWAYSENTRY_H
-#define DYNAMICWAYSENTRY_H
+#ifndef CACHEWAYSSELECTOR_H
+#define CACHEWAYSSELECTOR_H
-
-#include <QLineEdit>
-#include <QStringList>
-#include <QVBoxLayout>
-#include <QVector>
+#include <QSpinBox>
#include <QWidget>
-class DynamicWaysEntry : public QWidget
+class CacheWaysSelector : public QWidget
{
+ Q_OBJECT
+
public:
- DynamicWaysEntry(QWidget *parent = nullptr);
- QStringList get_entries() const;
/**
- * Parses a string from this entry field, if it is valid.
- * @param a string
- * @param -1 if the string is not suitable as a way, an integer compatible
- * with the cache constructor otherwise.
+ * Constructor.
+ * This class provides a simple group of labeled spinboxs meant for
+ * selecting cache ways.
+ * @param The parent widget.
+ * @param a newly allocated CacheWaysSelector
*/
- int parse_valid_way(QString t);
- private slots:
- void on_number_enter(const QString &t);
+ explicit CacheWaysSelector(QWidget *parent = nullptr);
+
+ /**
+ * @return the values in the spinboxes.
+ */
+ QList<int> values() const;
private:
- QVBoxLayout *l;
- QVector<QLineEdit *> fields;
- QStringList entries;
- void add_field();
- void remove_last_field();
+ /**
+ * A list of spinboxes.
+ */
+ QList<QSpinBox *> sbs;
};
-#endif // DYNAMICWAYSENTRY_H
+#endif // CACHEWAYSSELECTOR_H
diff --git a/gui/digitlabeldelegate.cc b/gui/digitlabeldelegate.cc
index 430946c..7a6a1d5 100644
--- a/gui/digitlabeldelegate.cc
+++ b/gui/digitlabeldelegate.cc
@@ -37,9 +37,13 @@ void DigitLabelDelegate::paint(
QString t;
QStyleOptionViewItem o;
QStyle *s;
+ QVariant a;
+ bool e;
- v = index.data(Qt::DisplayRole).toInt();
- t = format_toggled_value(v, this->is_hex);
+ a = index.data(Qt::DisplayRole);
+ v = a.toInt();
+ e = a.isNull();
+ t = format_toggled_value(v, this->is_hex, e);
o = option;
initStyleOption(&o, index);
diff --git a/gui/dynamicwaysentry.cc b/gui/dynamicwaysentry.cc
deleted file mode 100644
index cbd5342..0000000
--- a/gui/dynamicwaysentry.cc
+++ /dev/null
@@ -1,99 +0,0 @@
-// Simulator for the RISC-V[ECTOR] mini-ISA
-// Copyright (C) 2025 Siddarth Suresh
-// Copyright (C) 2025 bdunahu
-
-// This program is free software: you can redistribute it and/or modify
-// it under the terms of the GNU General Public License as published by
-// the Free Software Foundation, either version 3 of the License, or
-// (at your option) any later version.
-
-// This program is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// GNU General Public License for more details.
-
-// You should have received a copy of the GNU General Public License
-// along with this program. If not, see <https://www.gnu.org/licenses/>.
-
-#include "dynamicwaysentry.h"
-#include <QLabel>
-#include <QLineEdit>
-#include <QStringList>
-#include <QVBoxLayout>
-#include <QVector>
-#include <QWidget>
-
-DynamicWaysEntry::DynamicWaysEntry(QWidget *parent) : QWidget(parent)
-{
- this->l = new QVBoxLayout(this);
- this->l->setAlignment(Qt::AlignTop);
- this->l->setSpacing(6);
- this->l->setContentsMargins(0, 0, 0, 0);
- this->setLayout(l);
- this->add_field();
-}
-
-QStringList DynamicWaysEntry::get_entries() const { return this->entries; }
-
-int DynamicWaysEntry::parse_valid_way(QString t)
-{
- bool s;
- int i;
- i = t.toInt(&s);
- return (s && i >= 0 && 5 > i) ? i : -1;
-}
-
-// TODO if you enter something valid and then make it invalid,
-// the next box still shows
-void DynamicWaysEntry::on_number_enter(const QString &t)
-{
- int i;
- QLineEdit *sender_field;
-
- sender_field = qobject_cast<QLineEdit *>(sender());
- i = fields.indexOf(sender_field);
- entries[i] = t;
-
- if (i == this->fields.size() - 1 && !t.isEmpty() &&
- (this->parse_valid_way(t) >= 0) && fields.size() < 4)
- add_field();
-
- // TODO, unlink, don't trash everything after
- if (t.isEmpty()) {
- while (this->fields.size() > i + 1) {
- remove_last_field();
- }
- while (entries.size() > fields.size()) {
- entries.removeLast();
- }
- }
-}
-
-void DynamicWaysEntry::add_field()
-{
- QLineEdit *f;
-
- f = new QLineEdit(this);
- f->setPlaceholderText("# ways (a power of 2)");
-
- this->l->addWidget(f);;
- this->fields.append(f);
- this->entries.append(QString());
- connect(
- f, &QLineEdit::textChanged, this, &DynamicWaysEntry::on_number_enter);
-}
-
-void DynamicWaysEntry::remove_last_field()
-{
- QLineEdit *f;
-
- if (this->fields.isEmpty())
- return;
-
- f = this->fields.takeLast();
- this->l->removeWidget(f);
- f->deleteLater();
-
- if (!this->entries.isEmpty())
- entries.removeLast();
-}
diff --git a/gui/gui.cc b/gui/gui.cc
index b4feda6..395c6e6 100644
--- a/gui/gui.cc
+++ b/gui/gui.cc
@@ -17,9 +17,10 @@
#include "gui.h"
#include "./ui_gui.h"
+#include "cachewaysselector.h"
#include "digitlabeldelegate.h"
-#include "dynamicwaysentry.h"
#include "messages.h"
+#include "registerview.h"
#include "storageview.h"
#include "util.h"
#include <QHeaderView>
@@ -72,6 +73,8 @@ GUI::GUI(QWidget *parent) : QMainWindow(parent), ui(new Ui::GUI)
connect(worker, &Worker::wb_info, this, &GUI::onWorkerWriteBackInfo);
+ connect(worker, &Worker::steps_done, this, &GUI::onWorkerStepsDone);
+
// Display cache
connect(worker, &Worker::storage, this, &GUI::onWorkerShowStorage);
@@ -109,37 +112,10 @@ GUI::~GUI()
delete ui;
}
-void displayArrayHTML(QTextEdit *textEdit, const std::array<int, GPR_NUM> &data)
-{
- textEdit->setReadOnly(false);
- QString tableText = "<table border='1' cellspacing='0' cellpadding='8' "
- "style='border-collapse: collapse; width: 100%; "
- "border: 2px solid black;'>";
-
- tableText += "<tr>";
- int index = 0;
- for (int value : data) {
- tableText += QString("<td align='center' style='border: 2px solid "
- "black; min-width: 60px; padding: 10px;'>"
- "%1 <sup style='font-size: 10px; font-weight: "
- "bold; color: black;'>%2</sup>"
- "</td>")
- .arg(QString::asprintf("%04X", value))
- .arg(index);
- index++;
- }
- tableText += "</tr>";
- tableText += "</table>";
-
- textEdit->setHtml(tableText);
- textEdit->setReadOnly(true);
-}
-
void GUI::on_worker_refresh_gui(int cycles, int pc)
{
ui->p_counter->set_value(pc);
ui->cycle_counter->set_value(cycles);
- this->set_status(get_waiting, "idle");
}
void GUI::onWorkerFetchInfo(const InstrDTO *i)
@@ -215,15 +191,20 @@ void GUI::onWorkerWriteBackInfo(const InstrDTO *i)
}
}
+void GUI::onWorkerStepsDone() { this->set_status(get_waiting, "idle"); }
+
void GUI::onWorkerShowStorage(const QVector<QVector<int>> &data, int i)
{
this->tab_boxes.at(i)->set_data(data);
}
-void GUI::onWorkerShowRegisters(const std::array<int, GPR_NUM> &data)
+void GUI::onWorkerShowRegisters(
+ const QVector<signed int> &gprs, const QVector<QVector<signed int>> &vrs)
{
- ;
- // displayArrayHTML(this->tab_boxes.at(0), data);
+ RegisterView *rv;
+
+ rv = dynamic_cast<RegisterView *>(this->tab_boxes.at(0));
+ rv->set_data(gprs, vrs);
}
void GUI::on_upload_intructions_btn_clicked()
@@ -301,21 +282,15 @@ void GUI::on_config_clicked()
{
std::vector<unsigned int> ways;
QStringList entries;
- signed int i;
- DynamicWaysEntry *dwe = ui->cache_way_selector;
+ CacheWaysSelector *cws = ui->cache_ways_selector;
- for (const QString &s : dwe->get_entries()) {
+ for (int i : cws->values()) {
- if (s.isEmpty())
+ // invalid
+ if (i == -1)
continue;
- i = dwe->parse_valid_way(s);
- if (i >= 0) {
- ways.push_back((unsigned int)i);
- } else {
- this->set_status(get_bad_cache, "angry");
- return;
- }
+ ways.push_back((unsigned int)i);
}
if (this->p.empty()) {
@@ -355,15 +330,15 @@ void GUI::make_tabs(int num)
for (i = 0; i < num; ++i) {
if (i == 0) {
n = "Registers";
- e = new StorageView(0, this);
+ e = new RegisterView(GPR_NUM + V_NUM, V_R_LIMIT, this);
} else if (i == num - 1) {
n = "DRAM";
- e = new StorageView(MEM_LINES, this);
+ e = new StorageView(MEM_LINES, LINE_SIZE, this);
} else {
n = QString("L%1").arg(i);
e = new StorageView(
(1 << cache_size_mapper(this->curr_cache_levels - 1, i - 1)),
- this);
+ LINE_SIZE, this);
}
t = new QTableView(ui->storage);
diff --git a/gui/gui.h b/gui/gui.h
index 830d852..edcde88 100644
--- a/gui/gui.h
+++ b/gui/gui.h
@@ -68,9 +68,11 @@ class GUI : public QMainWindow
void onWorkerWriteBackInfo(const InstrDTO *);
+ void onWorkerStepsDone();
+
void onWorkerShowStorage(const QVector<QVector<int>> &data, int i);
- void onWorkerShowRegisters(const std::array<int, GPR_NUM> &data);
+ void onWorkerShowRegisters(const QVector<signed int> &gprs, const QVector<QVector<signed int>> &vrs);
void on_upload_intructions_btn_clicked();
diff --git a/gui/gui.ui b/gui/gui.ui
index 67cca60..5a5a037 100644
--- a/gui/gui.ui
+++ b/gui/gui.ui
@@ -6,7 +6,7 @@
<rect>
<x>0</x>
<y>0</y>
- <width>1499</width>
+ <width>1686</width>
<height>621</height>
</rect>
</property>
@@ -18,14 +18,17 @@
<item>
<layout class="QGridLayout" name="gridLayout_2" rowstretch="0" columnstretch="0">
<item row="0" column="0">
- <layout class="QHBoxLayout" name="control_separator">
+ <layout class="QHBoxLayout" name="control_separator" stretch="6,1">
+ <property name="spacing">
+ <number>6</number>
+ </property>
<item>
<layout class="QVBoxLayout" name="storage_pipe_separator">
<item>
<widget class="QTabWidget" name="storage">
<property name="minimumSize">
<size>
- <width>700</width>
+ <width>0</width>
<height>0</height>
</size>
</property>
@@ -35,7 +38,7 @@
</widget>
</item>
<item>
- <layout class="QHBoxLayout" name="pipe_view">
+ <layout class="QHBoxLayout" name="pipe_view" stretch="1,2,2,2,2,2">
<item>
<widget class="QGroupBox" name="groupBox">
<property name="maximumSize">
@@ -45,7 +48,7 @@
</size>
</property>
<property name="title">
- <string> </string>
+ <string/>
</property>
<property name="alignment">
<set>Qt::AlignmentFlag::AlignLeading|Qt::AlignmentFlag::AlignLeft|Qt::AlignmentFlag::AlignTop</set>
@@ -93,7 +96,7 @@
<widget class="QGroupBox" name="Fetch">
<property name="minimumSize">
<size>
- <width>200</width>
+ <width>0</width>
<height>0</height>
</size>
</property>
@@ -146,7 +149,7 @@
<widget class="QGroupBox" name="Decode">
<property name="minimumSize">
<size>
- <width>200</width>
+ <width>0</width>
<height>0</height>
</size>
</property>
@@ -199,7 +202,7 @@
<widget class="QGroupBox" name="Execute">
<property name="minimumSize">
<size>
- <width>200</width>
+ <width>0</width>
<height>0</height>
</size>
</property>
@@ -255,7 +258,7 @@
<widget class="QGroupBox" name="Memory">
<property name="minimumSize">
<size>
- <width>200</width>
+ <width>0</width>
<height>0</height>
</size>
</property>
@@ -308,7 +311,7 @@
<widget class="QGroupBox" name="WriteBack">
<property name="minimumSize">
<size>
- <width>200</width>
+ <width>0</width>
<height>0</height>
</size>
</property>
@@ -376,93 +379,14 @@
</widget>
</item>
<item>
- <layout class="QHBoxLayout" name="cache_controls">
- <property name="sizeConstraint">
- <enum>QLayout::SizeConstraint::SetMinimumSize</enum>
+ <widget class="QLabel" name="label">
+ <property name="text">
+ <string>Ways Selector (powers of 2)</string>
</property>
- <item>
- <widget class="Line" name="line_8">
- <property name="orientation">
- <enum>Qt::Orientation::Vertical</enum>
- </property>
- </widget>
- </item>
- <item>
- <layout class="QVBoxLayout" name="cache_way_text">
- <property name="sizeConstraint">
- <enum>QLayout::SizeConstraint::SetMinimumSize</enum>
- </property>
- <item>
- <widget class="QLabel" name="label">
- <property name="maximumSize">
- <size>
- <width>16777215</width>
- <height>16777215</height>
- </size>
- </property>
- <property name="text">
- <string>C1 2^</string>
- </property>
- </widget>
- </item>
- <item>
- <widget class="QLabel" name="label_2">
- <property name="maximumSize">
- <size>
- <width>16777215</width>
- <height>16777215</height>
- </size>
- </property>
- <property name="text">
- <string>C2 2^</string>
- </property>
- </widget>
- </item>
- <item>
- <widget class="QLabel" name="label_3">
- <property name="minimumSize">
- <size>
- <width>0</width>
- <height>0</height>
- </size>
- </property>
- <property name="maximumSize">
- <size>
- <width>16777215</width>
- <height>16777215</height>
- </size>
- </property>
- <property name="text">
- <string>C3 2^</string>
- </property>
- </widget>
- </item>
- <item>
- <widget class="QLabel" name="label_4">
- <property name="maximumSize">
- <size>
- <width>16777215</width>
- <height>16777215</height>
- </size>
- </property>
- <property name="text">
- <string>C4 2^</string>
- </property>
- </widget>
- </item>
- </layout>
- </item>
- <item>
- <widget class="DynamicWaysEntry" name="cache_way_selector" native="true">
- <property name="minimumSize">
- <size>
- <width>0</width>
- <height>0</height>
- </size>
- </property>
- </widget>
- </item>
- </layout>
+ </widget>
+ </item>
+ <item>
+ <widget class="CacheWaysSelector" name="cache_ways_selector" native="true"/>
</item>
<item>
<widget class="QCheckBox" name="enable_pipeline_checkbox">
@@ -675,16 +599,16 @@
</widget>
<customwidgets>
<customwidget>
- <class>DynamicWaysEntry</class>
- <extends>QWidget</extends>
- <header>dynamicwaysentry.h</header>
- <container>1</container>
- </customwidget>
- <customwidget>
<class>DigitLabel</class>
<extends>QLabel</extends>
<header location="global">digitlabel.h</header>
</customwidget>
+ <customwidget>
+ <class>CacheWaysSelector</class>
+ <extends>QWidget</extends>
+ <header>cachewaysselector.h</header>
+ <container>1</container>
+ </customwidget>
</customwidgets>
<resources/>
<connections/>
diff --git a/gui/messages.h b/gui/messages.h
index 461c461..0c38751 100644
--- a/gui/messages.h
+++ b/gui/messages.h
@@ -35,8 +35,6 @@ const std::vector<std::string> load_file = {
const std::vector<std::string> no_instructions = {
"NO PROGRAM PROVIDED", "NOTHING TO DO, GIVING UP", "INSTRUCTIONS MISSING",
"404 INSTRUCTIONS NOT FOUND"};
-const std::vector<std::string> bad_cache = {
- "WAYS CANNOT BE BELOW 0 OR ABOVE 4"};
const std::vector<std::string> no_pipeline = {
"SIMULATION READY: NO PIPE", "PIPE OFF, SIMULATION READY"};
const std::vector<std::string> no_cache = {
@@ -59,7 +57,6 @@ std::string get_load_file() { return RANDOM_MESSAGE(load_file); }
* @return a friendly reminder that the simulation is not configured yet
*/
std::string get_no_instructions() { return RANDOM_MESSAGE(no_instructions); }
-std::string get_bad_cache() { return RANDOM_MESSAGE(bad_cache); }
/**
* @return unsolicited complaints for successful initialization
diff --git a/gui/registerview.cc b/gui/registerview.cc
new file mode 100644
index 0000000..b1a1333
--- /dev/null
+++ b/gui/registerview.cc
@@ -0,0 +1,69 @@
+// Simulator for the RISC-V[ECTOR] mini-ISA
+// Copyright (C) 2025 Siddarth Suresh
+// Copyright (C) 2025 bdunahu
+
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License
+// along with this program. If not, see <https://www.gnu.org/licenses/>.
+
+#include "pipe_spec.h"
+#include "registerview.h"
+#include "util.h"
+#include <QAbstractTableModel>
+#include <QVector>
+
+QVariant RegisterView::data(const QModelIndex &i, int role) const
+{
+ Qt::Alignment a;
+
+ if (role == Qt::TextAlignmentRole) {
+ a = Qt::AlignRight | Qt::AlignVCenter;
+ return QVariant(static_cast<int>(a));
+ }
+
+ if (!i.isValid() || role != Qt::DisplayRole)
+ return QVariant();
+
+ if (i.row() < 16) {
+ if (i.column() < 1)
+ return this->gprs[i.row()];
+ else
+ return QVariant();
+ }
+
+ return this->vrs[i.row() - GPR_NUM][i.column() - GPR_NUM];
+}
+
+QVariant
+RegisterView::headerData(int section, Qt::Orientation o, int role) const
+{
+ Qt::Alignment a;
+
+ if (role == Qt::TextAlignmentRole) {
+ a = Qt::AlignRight | Qt::AlignVCenter;
+ return QVariant(static_cast<int>(a));
+ }
+
+ if (role != Qt::DisplayRole)
+ return QVariant();
+
+ if (o == Qt::Vertical) {
+ return format_toggled_value(section, this->is_hex);
+ }
+ return QVariant();
+}
+
+void RegisterView::set_data(const QVector<int> &gprs, const QVector<QVector<int>> &vrs)
+{
+ this->gprs = gprs;
+ this->vrs = vrs;
+}
diff --git a/gui/registerview.h b/gui/registerview.h
new file mode 100644
index 0000000..cc5a1f8
--- /dev/null
+++ b/gui/registerview.h
@@ -0,0 +1,64 @@
+// Simulator for the RISC-V[ECTOR] mini-ISA
+// Copyright (C) 2025 Siddarth Suresh
+// Copyright (C) 2025 bdunahu
+
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License
+// along with this program. If not, see <https://www.gnu.org/licenses/>.
+
+#ifndef REGISTERVIEW_H
+#define REGISTERVIEW_H
+
+#include "storageview.h"
+#include <QAbstractTableModel>
+#include <QVector>
+
+// see https://doc.qt.io/qt-6/qabstracttablemodel.html
+class RegisterView : public StorageView
+{
+ Q_OBJECT
+ public:
+ using StorageView::StorageView;
+
+ /**
+ * Returns a properly formatted cell, including alignment.This function is
+ * specific to the implementation details of QAbstractTableModel.
+ */
+ QVariant
+ data(const QModelIndex &index, int role = Qt::DisplayRole) const override;
+
+ /**
+ * Adds custom formatting options for row and column headers.
+ */
+ QVariant headerData(
+ int section,
+ Qt::Orientation o,
+ int role = Qt::DisplayRole) const override;
+
+ /**
+ * @param field to assign to `this->gprs'.
+ * @param field to assign to `this->vrs'.
+ */
+ void set_data(const QVector<int> &gprs, const QVector<QVector<int>> &vrs);
+
+ private:
+ /**
+ * The general purpose registers.
+ */
+ QVector<int> gprs;
+ /**
+ * The vector registers.
+ */
+ QVector<QVector<int>> vrs;
+};
+
+#endif // REGISTERVIEW_H
diff --git a/gui/resources.qrc b/gui/resources.qrc
index 569cc22..66cd6e4 100644
--- a/gui/resources.qrc
+++ b/gui/resources.qrc
@@ -1,6 +1,10 @@
<!DOCTYPE RCC>
<RCC version="1.0">
<qresource>
+ <file>resources/arrow_down.png</file>
+ <file>resources/arrow_up.png</file>
+ <file>resources/arrow_down_pressed.png</file>
+ <file>resources/arrow_up_pressed.png</file>
<file>resources/styles.qss</file>
<file>resources/idle.png</file>
<file>resources/angry.png</file>
diff --git a/gui/resources/arrow_down.png b/gui/resources/arrow_down.png
new file mode 100644
index 0000000..80b1753
--- /dev/null
+++ b/gui/resources/arrow_down.png
Binary files differ
diff --git a/gui/resources/arrow_down_pressed.png b/gui/resources/arrow_down_pressed.png
new file mode 100644
index 0000000..0981cf2
--- /dev/null
+++ b/gui/resources/arrow_down_pressed.png
Binary files differ
diff --git a/gui/resources/arrow_up.png b/gui/resources/arrow_up.png
new file mode 100644
index 0000000..69b65af
--- /dev/null
+++ b/gui/resources/arrow_up.png
Binary files differ
diff --git a/gui/resources/arrow_up_pressed.png b/gui/resources/arrow_up_pressed.png
new file mode 100644
index 0000000..98d50ac
--- /dev/null
+++ b/gui/resources/arrow_up_pressed.png
Binary files differ
diff --git a/gui/resources/styles.qss b/gui/resources/styles.qss
index a61035e..c6d8daa 100644
--- a/gui/resources/styles.qss
+++ b/gui/resources/styles.qss
@@ -4,6 +4,8 @@
color: "#00cc00";
background-color: "#000200";
border: 0px solid "#000200";
+ selection-background-color: "#00cc00";
+ selection-color: "#000200";
}
QStatusBar {
@@ -50,6 +52,66 @@ QGroupBox::title {
QLabel {
}
+QSpinBox {
+ padding-right: 15px; /* make room for the arrows */
+ border: none;
+}
+
+QSpinBox::up-button {
+ color: "#000200";
+ background-color: "#00cc00";
+ subcontrol-origin: border;
+ subcontrol-position: top right; /* position at the top right corner */
+
+ width: 16px;
+ border: none;
+ subcontrol-origin: border;
+}
+
+QSpinBox::up-arrow {
+ image: url(:/resources/arrow_up.png);
+ width: 7px;
+ height: 7px;
+}
+
+QSpinBox::up-arrow:pressed {
+ image: url(:/resources/arrow_up_pressed.png);
+ width: 7px;
+ height: 7px;
+}
+
+QSpinBox::up-button:pressed {
+ color: "#00cc00";
+ background-color: "#000200";
+}
+
+QSpinBox::down-button {
+ color: "#000200";
+ background-color: "#00cc00";
+ subcontrol-origin: border;
+ subcontrol-position: bottom right; /* position at bottom right corner */
+
+ width: 16px;
+ border: none;
+}
+
+QSpinBox::down-button:pressed {
+ color: "#00cc00";
+ background-color: "#000200";
+}
+
+QSpinBox::down-arrow {
+ image: url(:/resources/arrow_down.png);
+ width: 7px;
+ height: 7px;
+}
+
+QSpinBox::down-arrow:pressed {
+ image: url(:/resources/arrow_down_pressed.png);
+ width: 7px;
+ height: 7px;
+}
+
QTableView {
border: 0px;
selection-background-color: transparent;
diff --git a/gui/storageview.cc b/gui/storageview.cc
index 2f444a9..60391f9 100644
--- a/gui/storageview.cc
+++ b/gui/storageview.cc
@@ -21,10 +21,11 @@
#include <QAbstractTableModel>
#include <QVector>
-StorageView::StorageView(int rows, QObject *parent)
+StorageView::StorageView(int rows, int columns, QObject *parent)
: QAbstractTableModel(parent)
{
this->r = rows;
+ this->c = columns;
this->d.resize(rows);
for (auto &row : this->d)
row.resize(LINE_SIZE, 0);
@@ -32,7 +33,7 @@ StorageView::StorageView(int rows, QObject *parent)
int StorageView::rowCount(const QModelIndex &) const { return this->r; }
-int StorageView::columnCount(const QModelIndex &) const { return LINE_SIZE; }
+int StorageView::columnCount(const QModelIndex &) const { return this->c; }
QVariant StorageView::data(const QModelIndex &i, int role) const
{
diff --git a/gui/storageview.h b/gui/storageview.h
index 0518d8f..a0f8dbb 100644
--- a/gui/storageview.h
+++ b/gui/storageview.h
@@ -31,7 +31,7 @@ class StorageView : public QAbstractTableModel
* `rows' rows.
* @param the number of rows
*/
- StorageView(int rows, QObject *parent = nullptr);
+ StorageView(int rows, int columns, QObject *parent = nullptr);
/**
* Returns the number of rows in this table.
@@ -51,13 +51,13 @@ class StorageView : public QAbstractTableModel
* Returns a properly formatted cell, including alignment.This function is
* specific to the implementation details of QAbstractTableModel.
*/
- QVariant
+ virtual QVariant
data(const QModelIndex &index, int role = Qt::DisplayRole) const override;
/**
* Adds custom formatting options for row and column headers.
*/
- QVariant headerData(
+ virtual QVariant headerData(
int section,
Qt::Orientation o,
int role = Qt::DisplayRole) const override;
@@ -75,15 +75,21 @@ class StorageView : public QAbstractTableModel
public slots:
void set_hex_display(bool hex);
- private:
+ protected:
/**
* The number of rows in this table.
*/
int r;
/**
+ * The number of columns in this table.
+ */
+ int c;
+ /**
* Whether or not the headers should be displayed in hex.
*/
bool is_hex = true;
+
+ private:
/**
* The data this table displays.
*/
diff --git a/gui/worker.cc b/gui/worker.cc
index 0ba364b..a48888c 100644
--- a/gui/worker.cc
+++ b/gui/worker.cc
@@ -72,14 +72,22 @@ void Worker::runSteps(int steps)
{
this->ct->run_for(steps);
this->update();
+ emit steps_done();
}
void Worker::update()
{
unsigned long i;
+ std::array<int, GPR_NUM> gprs;
+ std::array<std::array<signed int, V_R_LIMIT>, V_NUM> vrs;
this->ct_mutex.lock();
- emit register_storage(this->ct->get_gprs());
+ gprs = this->ct->get_gprs();
+ vrs = this->ct->get_vrs();
+ std::vector<std::array<signed int, V_R_LIMIT>> v(vrs.begin(), vrs.end());
+
+ emit register_storage(
+ QVector<int>(gprs.begin(), gprs.end()), this->data_to_QT(v));
for (i = 0; i < s.size(); ++i)
emit storage(this->data_to_QT(this->s.at(i)->get_data()), i + 1);
@@ -92,18 +100,3 @@ void Worker::update()
emit wb_info(this->wb_stage->get_instr());
this->ct_mutex.unlock();
}
-
-QVector<QVector<int>>
-Worker::data_to_QT(std::vector<std::array<signed int, LINE_SIZE>> data)
-{
- QVector<QVector<int>> r;
- QVector<int> tmp;
-
- r.reserve(static_cast<int>(data.size()));
-
- for (const auto &line : data) {
- tmp = QVector<int>(line.begin(), line.end());
- r.append(tmp);
- }
- return r;
-}
diff --git a/gui/worker.h b/gui/worker.h
index c62f4ed..2a362a4 100644
--- a/gui/worker.h
+++ b/gui/worker.h
@@ -64,14 +64,15 @@ class Worker : public QObject
signals:
void clock_cycles(int value, int pc);
- void
- storage(QVector<QVector<int>> data, int i);
- void register_storage(const std::array<int, GPR_NUM> data);
+ void storage(QVector<QVector<int>> data, int i);
+ void register_storage(
+ QVector<signed int> gprs, QVector<QVector<signed int>> vrs);
void if_info(const InstrDTO *);
void id_info(const InstrDTO *);
void ex_info(const InstrDTO *);
void mm_info(const InstrDTO *);
void wb_info(const InstrDTO *);
+ void steps_done();
void finished();
private:
@@ -80,8 +81,21 @@ class Worker : public QObject
* @param the original data
* @return a less universal version of the same thing
*/
+ template <size_t N>
QVector<QVector<int>>
- data_to_QT(std::vector<std::array<signed int, LINE_SIZE>> data);
+ data_to_QT(const std::vector<std::array<signed int, N>> &data)
+ {
+ QVector<QVector<int>> r;
+ QVector<int> tmp;
+
+ r.reserve(static_cast<int>(data.size()));
+
+ for (const auto &line : data) {
+ tmp = QVector<int>(line.begin(), line.end());
+ r.append(tmp);
+ }
+ return r;
+ }
/**
* Sets the GUI signals to update the storage, clock cycle, and stage
* displays.
diff --git a/inc/controller.h b/inc/controller.h
index b7fa835..cd59fc8 100644
--- a/inc/controller.h
+++ b/inc/controller.h
@@ -49,7 +49,11 @@ class Controller : public Stage
/**
* @return a copy of gprs.
*/
- std::array<int, GPR_NUM> get_gprs();
+ std::array<signed int, GPR_NUM> get_gprs();
+ /**
+ * @return a copy of vrs.
+ */
+ std::array<std::array<signed int, V_R_LIMIT>, V_NUM> get_vrs();
/**
* @return the pc.
*/
diff --git a/inc/ex.h b/inc/ex.h
index c356543..5a5c046 100644
--- a/inc/ex.h
+++ b/inc/ex.h
@@ -63,7 +63,7 @@ class EX : public Stage
* @param The next stage in the pipeline.
* @return A newly allocated EX object.
*/
- EX(Stage *next);
+ using Stage::Stage;
using Stage::advance;
private:
@@ -76,16 +76,6 @@ class EX : public Stage
* @param if the modulo operator should instead be used
*/
void handle_divide(signed int &s1, signed int s2, bool is_mod);
- /**
- * Maps each mnemonic to a function which carries out the instruction's base
- * logic.
- * All instructions store the result into s1.
- */
- std::unordered_map<
- Mnemonic,
- std::function<void(
- signed int &s1, signed int s2, signed int s3, unsigned int pc)>>
- instr_map;
};
#endif /* EX_H_INCLUDED */
diff --git a/inc/id.h b/inc/id.h
index aafe2e5..e8e9c36 100644
--- a/inc/id.h
+++ b/inc/id.h
@@ -50,6 +50,12 @@ class ID : public Stage
*/
void write_guard(signed int &r);
+ Response read_vec_guard(signed int r, std::array<signed int, V_R_LIMIT> &v);
+
+ void write_vec_guard(signed int r, std::array<signed int, V_R_LIMIT> &v);
+
+ Response set_vlen();
+
private:
/**
* Helper for `get_instr_fields`
@@ -76,10 +82,10 @@ class ID : public Stage
* @param the resulting third field, which varies per type.
* @param the resulting mnemonic.
*/
- void get_instr_fields(signed int &s1, signed int &s2, signed int &s3, Mnemonic &m);
- void decode_R_type(signed int &s1, signed int &s2, signed int &s3, Mnemonic &m);
- void decode_I_type(signed int &s1, signed int &s2, signed int &s3, Mnemonic &m);
- void decode_J_type(signed int &s1, signed int &s2, signed int &s3, Mnemonic &m);
+ void get_instr_fields(signed int &s1);
+ void decode_R_type(signed int &s1);
+ void decode_I_type(signed int &s1);
+ void decode_J_type(signed int &s1);
/**
* Helper for `get_instr_fields`.
* Given a raw instruction, returns the mnemonic and type.
diff --git a/inc/instrDTO.h b/inc/instrDTO.h
index 1402526..f3d4597 100644
--- a/inc/instrDTO.h
+++ b/inc/instrDTO.h
@@ -18,6 +18,8 @@
#ifndef INSTRDTO_H
#define INSTRDTO_H
#include "instr.h"
+#include "pipe_spec.h"
+#include<array>
struct U_INT_TYPE {
signed int slot_one;
@@ -26,6 +28,15 @@ struct U_INT_TYPE {
};
struct V_TYPE {
+ std::array<signed int, V_R_LIMIT> slot_one;
+ std::array<signed int, V_R_LIMIT> slot_two;
+ std::array<signed int, V_R_LIMIT> slot_three;
+};
+
+struct LOAD_STORE_V_TYPE{
+ signed int base_addr;
+ signed int immediate;
+ std::array<signed int, V_R_LIMIT> vector_register;
};
struct InstrDTO {
@@ -52,6 +63,7 @@ struct InstrDTO {
union {
struct U_INT_TYPE integer;
struct V_TYPE vector;
+ struct LOAD_STORE_V_TYPE load_store_vector;
} operands;
};
diff --git a/inc/pipe_spec.h b/inc/pipe_spec.h
index 7d65637..d8153af 100644
--- a/inc/pipe_spec.h
+++ b/inc/pipe_spec.h
@@ -80,6 +80,8 @@
*/
#define CACHE_DELAY 1
+#define VECTOR_MEM_DELAY 10
+
/**
* Return the N least-significant bits from integer K using a bit mask
* @param the integer to be parsed
diff --git a/inc/stage.h b/inc/stage.h
index 16f1235..4e0c252 100644
--- a/inc/stage.h
+++ b/inc/stage.h
@@ -83,6 +83,10 @@ class Stage
*/
static std::deque<signed int> checked_out;
+ bool is_vector_type(Mnemonic m);
+
+ bool is_logical(Mnemonic m);
+
protected:
/**
* The function expected to do the majority of the work.
@@ -104,13 +108,43 @@ class Stage
* @param the register number.
* @param the value to store.
*/
- void store_register(signed int v, signed int d);
+ template <typename T>
+ void store_register(signed int v, T d)
+ {
+ if constexpr (std::is_same_v<T, signed int>) {
+ if (v < 0 || v >= GPR_NUM) {
+ throw std::out_of_range("Invalid GPR index for storing scalar");
+ }
+ gprs[v] = d;
+ }
+ else if constexpr (std::is_same_v<T, std::array<signed int, V_R_LIMIT>>) {
+ if (v < GPR_NUM || v >= GPR_NUM + V_NUM) {
+ throw std::out_of_range("Invalid VR index for storing vector");
+ }
+ vrs[v % GPR_NUM] = d;
+ }
+ }
/**
* Returns the value of the register corresponding to `v`.
* @param the register number.
* @return the value in the associated register.
*/
- signed int dereference_register(signed int v);
+ template <typename T>
+ T dereference_register(signed int v)
+ {
+ if constexpr (std::is_same_v<T, signed int>) {
+ if (v < 0 || v >= GPR_NUM) {
+ throw std::out_of_range("Invalid GPR index");
+ }
+ return gprs[v];
+ }
+ else if constexpr (std::is_same_v<T, std::array<signed int, V_R_LIMIT>>) {
+ if (v < GPR_NUM || v >= GPR_NUM + V_NUM) {
+ throw std::out_of_range("Invalid vector register index");
+ }
+ return vrs[v % GPR_NUM];
+ }
+ }
/**
* The shared pool of general-purpose integer registers.
*/
@@ -118,7 +152,7 @@ class Stage
/**
* The shared pool of general-purpose vector registers.
*/
- static std::array<signed int, V_NUM> vrs;
+ static std::array<std::array<signed int, V_R_LIMIT>, V_NUM> vrs;
/**
* The address of the currently executing instruction.
*/
diff --git a/src/controller.cc b/src/controller.cc
index 8df4b97..a5c6691 100644
--- a/src/controller.cc
+++ b/src/controller.cc
@@ -15,6 +15,7 @@
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <https://www.gnu.org/licenses/>.
+#include "definitions.h"
#include "controller.h"
#include "ex.h"
#include "response.h"
@@ -30,6 +31,7 @@ Controller::Controller(Stage *stage, Storage *storage, bool is_pipelined)
this->pc = 0x0;
this->checked_out = {};
this->gprs = {0};
+ this->vrs.fill({0});
this->gprs.at(2) = MEM_WORDS; // set the stack pointer
}
@@ -47,7 +49,12 @@ void Controller::run_for(int number)
int Controller::get_clock_cycle() { return this->clock_cycle; }
-std::array<int, GPR_NUM> Controller::get_gprs() { return this->gprs; }
+std::array<signed int, GPR_NUM> Controller::get_gprs() { return this->gprs; }
+
+std::array<std::array<signed int, V_R_LIMIT>, V_NUM> Controller::get_vrs()
+{
+ return this->vrs;
+}
int Controller::get_pc() { return this->pc; }
diff --git a/src/ex.cc b/src/ex.cc
index eac24ff..286c7ba 100644
--- a/src/ex.cc
+++ b/src/ex.cc
@@ -22,415 +22,230 @@
#include "stage.h"
#include <unordered_map>
-// clang-format off
-#define INIT_INSTRUCTION(mnemonic, body) \
- {mnemonic, [this](signed int &s1, signed int s2, signed int s3, unsigned int pc) { \
- body; \
- }}
-// clang-format on
-
-EX::EX(Stage *stage) : Stage(stage)
-{
- instr_map = {
-
- /* R type instructions */
- INIT_INSTRUCTION(
- ADD,
- {
- this->set_condition(OF, ADDITION_OF_GUARD(s1, s2));
- this->set_condition(UF, ADDITION_UF_GUARD(s1, s2));
- s1 = s1 + s2;
- (void)pc;
- (void)s3;
- (void)this;
- }),
-
- INIT_INSTRUCTION(
- SUB,
- {
- this->set_condition(OF, SUBTRACTION_OF_GUARD(s1, s2));
- this->set_condition(UF, SUBTRACTION_UF_GUARD(s1, s2));
- s1 = s1 - s2;
- (void)pc;
- (void)s3;
- (void)this;
- }),
-
- INIT_INSTRUCTION(
- MUL,
- {
- this->set_condition(OF, MULTIPLICATION_OF_GUARD(s1, s2));
- this->set_condition(UF, MULTIPLICATION_UF_GUARD(s1, s2));
- s1 = s1 * s2;
- (void)pc;
- (void)s3;
- (void)this;
- }),
-
- INIT_INSTRUCTION(
- QUOT,
- {
- this->handle_divide(s1, s2, false);
- (void)pc;
- (void)s3;
- }),
-
- INIT_INSTRUCTION(
- REM,
- {
- this->handle_divide(s1, s2, true);
- (void)pc;
- (void)s3;
- (void)this;
- }),
-
- INIT_INSTRUCTION(
- SFTR,
- {
- s1 = s1 >> s2;
- (void)pc;
- (void)s3;
- (void)this;
- }),
-
- INIT_INSTRUCTION(
- SFTL,
- {
- s1 = s1 << s2;
- (void)pc;
- (void)s3;
- (void)this;
- }),
-
- INIT_INSTRUCTION(
- AND,
- {
- this->set_condition(OF, false);
- this->set_condition(UF, false);
- s1 = s1 & s2;
- (void)pc;
- (void)s3;
- (void)this;
- }),
-
- INIT_INSTRUCTION(
- OR,
- {
- this->set_condition(OF, false);
- this->set_condition(UF, false);
- s1 = s1 | s2;
- (void)pc;
- (void)s3;
- (void)this;
- }),
-
- INIT_INSTRUCTION(
- NOT,
- {
- this->set_condition(OF, false);
- this->set_condition(UF, false);
- s1 = ~s1;
- (void)pc;
- (void)s3;
- (void)s2;
- (void)this;
- }),
-
- INIT_INSTRUCTION(
- XOR,
- {
- this->set_condition(OF, false);
- this->set_condition(UF, false);
- s1 = s1 ^ s2;
- (void)pc;
- (void)s3;
- (void)this;
- }),
-
- INIT_INSTRUCTION(
- ADDV,
- {
- (void)pc;
- (void)s3;
- (void)s2;
- (void)s1;
- (void)this;
- }),
-
- INIT_INSTRUCTION(
- SUBV,
- {
- (void)pc;
- (void)s3;
- (void)s2;
- (void)s1;
- (void)this;
- }),
-
- INIT_INSTRUCTION(
- MULV,
- {
- (void)pc;
- (void)s3;
- (void)s2;
- (void)s1;
- (void)this;
- }),
-
- INIT_INSTRUCTION(
- DIVV,
- {
- (void)pc;
- (void)s3;
- (void)s2;
- (void)s1;
- (void)this;
- }),
-
- INIT_INSTRUCTION(
- CMP,
- {
- (s1 > s2) ? this->set_condition(GT, true)
- : this->set_condition(GT, false);
- (s1 == s2) ? this->set_condition(EQ, true)
- : this->set_condition(EQ, false);
- (void)pc;
- (void)s3;
- }),
-
- INIT_INSTRUCTION(
- CEV,
- {
- (void)pc;
- (void)s3;
- (void)s2;
- (void)s1;
- (void)this;
- }),
-
- /* I type instructions */
- INIT_INSTRUCTION(
- LOAD,
- {
- s1 = s1 + s3;
- (void)pc;
- (void)s2;
- (void)this;
- }),
-
- INIT_INSTRUCTION(
- LOADV,
- {
- (void)pc;
- (void)s3;
- (void)s2;
- (void)s1;
- (void)this;
- }),
-
- INIT_INSTRUCTION(
- ADDI,
- {
- this->set_condition(OF, ADDITION_OF_GUARD(s1, s3));
- this->set_condition(UF, ADDITION_UF_GUARD(s1, s3));
- s1 = s1 + s3;
- (void)pc;
- (void)s2;
- (void)this;
- }),
-
- INIT_INSTRUCTION(
- SUBI,
- {
- this->set_condition(OF, SUBTRACTION_OF_GUARD(s1, s3));
- this->set_condition(UF, SUBTRACTION_UF_GUARD(s1, s3));
- s1 = s1 - s3;
- (void)pc;
- (void)s2;
- (void)this;
- }),
-
- INIT_INSTRUCTION(
- SFTRI,
- {
- s1 = s1 >> s3;
- (void)pc;
- (void)s2;
- (void)this;
- }),
-
- INIT_INSTRUCTION(
- SFTLI,
- {
- s1 = s1 << s3;
- (void)pc;
- (void)s2;
- (void)this;
- }),
-
- INIT_INSTRUCTION(
- ANDI,
- {
- this->set_condition(OF, false);
- this->set_condition(UF, false);
- s1 = s1 & s3;
- (void)pc;
- (void)s2;
- (void)this;
- }),
-
- INIT_INSTRUCTION(
- ORI,
- {
- this->set_condition(OF, false);
- this->set_condition(UF, false);
- s1 = s1 | s3;
- (void)pc;
- (void)s2;
- (void)this;
- }),
-
- INIT_INSTRUCTION(
- XORI,
- {
- this->set_condition(OF, false);
- this->set_condition(UF, false);
- s1 = s1 ^ s3;
- (void)pc;
- (void)s2;
- (void)this;
- }),
-
- INIT_INSTRUCTION(
- STORE,
- {
- s1 = s1 + s3;
- (void)pc;
- (void)s2;
- (void)this;
- }),
-
- INIT_INSTRUCTION(
- STOREV,
- {
- (void)pc;
- (void)s3;
- (void)s2;
- (void)s1;
- (void)this;
- }),
-
- /* J type instructions */
- INIT_INSTRUCTION(
- JMP,
- {
- s1 = s1 + s2;
- (void)pc;
- (void)s3;
- (void)this;
- }),
-
- INIT_INSTRUCTION(
- JRL,
- {
- s1 = pc + s2;
- (void)s3;
- (void)this;
- }),
-
- INIT_INSTRUCTION(
- JAL,
- {
- s1 = s1 + s2;
- (void)pc;
- (void)s3;
- (void)this;
- }),
-
- INIT_INSTRUCTION(
- BEQ,
- {
- (this->get_condition(EQ)) ? s1 = pc + s2 : s1 = -1;
- (void)s3;
- }),
-
- INIT_INSTRUCTION(
- BGT,
- {
- (this->get_condition(GT)) ? s1 = pc + s2 : s1 = -1;
- (void)s3;
- }),
-
- INIT_INSTRUCTION(
- BUF,
- {
- (this->get_condition(UF)) ? s1 = pc + s2 : s1 = -1;
- (void)s3;
- }),
-
- INIT_INSTRUCTION(
- BOF,
- {
- (this->get_condition(OF)) ? s1 = pc + s2 : s1 = -1;
- (void)s3;
- }),
-
- INIT_INSTRUCTION(
- PUSH,
- {
- s1 = s1 + s3;
- (void)pc;
- (void)s2;
- (void)this;
- }),
-
- INIT_INSTRUCTION(
- POP,
- {
- s1 = s1 + s3;
- (void)pc;
- (void)s2;
- (void)this;
- }),
-
- INIT_INSTRUCTION(
- RET,
- {
- (void)pc;
- (void)s3;
- (void)s2;
- (void)s1;
- (void)this;
- }),
-
- /* NOP */
- INIT_INSTRUCTION(
- NOP,
- {
- (void)pc;
- (void)s3;
- (void)s2;
- (void)s1;
- (void)this;
- }),
- };
-}
-
+// Switch statements for each instruction
void EX::advance_helper()
{
signed int s1, s2, s3;
+ std::array<signed int, V_R_LIMIT> v1, v2, v3;
+ signed int v_len, v_immediate, v_base_addr;
unsigned int pc;
Mnemonic m;
+ s1 = 0, s2 = 0, s3 = 0;
+ v1 = {0}, v2 = {0}, v3 = {0};
+ v_len = 0, v_immediate = 0, v_base_addr = 0;
m = this->curr_instr->mnemonic;
- s1 = this->curr_instr->operands.integer.slot_one;
- s2 = this->curr_instr->operands.integer.slot_two;
- s3 = this->curr_instr->operands.integer.slot_three;
pc = this->curr_instr->slot_B;
- this->instr_map[m](s1, s2, s3, pc);
+ if (this->is_vector_type(m)) {
+ if (this->curr_instr->mnemonic != LOADV &&
+ this->curr_instr->mnemonic != STOREV) {
+ v1 = this->curr_instr->operands.vector.slot_one;
+ v2 = this->curr_instr->operands.vector.slot_two;
+ v3 = this->curr_instr->operands.vector.slot_three;
+ } else {
+ v_immediate =
+ this->curr_instr->operands.load_store_vector.immediate;
+ v_base_addr =
+ this->curr_instr->operands.load_store_vector.base_addr;
+ }
+ v_len = this->curr_instr->slot_A;
+ if (v_len == 0) {
+ // clear destination vector reg
+ v1.fill(0);
+ }
+ } else {
+ s1 = this->curr_instr->operands.integer.slot_one;
+ s2 = this->curr_instr->operands.integer.slot_two;
+ s3 = this->curr_instr->operands.integer.slot_three;
+ }
+
+ if (this->is_logical(m)) {
+ this->set_condition(OF, false);
+ this->set_condition(UF, false);
+ }
- this->curr_instr->operands.integer.slot_one = s1;
+ switch (m) {
+ case ADD:
+ this->set_condition(OF, ADDITION_OF_GUARD(s1, s2));
+ this->set_condition(UF, ADDITION_UF_GUARD(s1, s2));
+ s1 = s1 + s2;
+ break;
+
+ case SUB:
+ this->set_condition(OF, SUBTRACTION_OF_GUARD(s1, s2));
+ this->set_condition(UF, SUBTRACTION_UF_GUARD(s1, s2));
+ s1 = s1 - s2;
+ break;
+
+ case MUL:
+ this->set_condition(OF, MULTIPLICATION_OF_GUARD(s1, s2));
+ this->set_condition(UF, MULTIPLICATION_UF_GUARD(s1, s2));
+ s1 = s1 * s2;
+ break;
+
+ case QUOT:
+ this->handle_divide(s1, s2, false);
+ break;
+
+ case REM:
+ this->handle_divide(s1, s2, true);
+ break;
+
+ case SFTR:
+ s1 = s1 >> s2;
+ break;
+
+ case SFTL:
+ s1 = s1 << s2;
+ break;
+
+ case AND:
+ s1 = s1 & s2;
+ break;
+
+ case OR:
+ s1 = s1 | s2;
+ break;
+
+ case XOR:
+ s1 = s1 ^ s2;
+ break;
+
+ case NOT:
+ s1 = ~s1;
+ break;
+
+ case CMP:
+ (s1 > s2) ? this->set_condition(GT, true)
+ : this->set_condition(GT, false);
+ (s1 == s2) ? this->set_condition(EQ, true)
+ : this->set_condition(EQ, false);
+ break;
+
+ case ADDI:
+ this->set_condition(OF, ADDITION_OF_GUARD(s1, s3));
+ this->set_condition(UF, ADDITION_UF_GUARD(s1, s3));
+ s1 = s1 + s3;
+ break;
+
+ case SUBI:
+ this->set_condition(OF, SUBTRACTION_OF_GUARD(s1, s3));
+ this->set_condition(UF, SUBTRACTION_UF_GUARD(s1, s3));
+ s1 = s1 - s3;
+ break;
+
+ case SFTRI:
+ s1 = s1 >> s3;
+ break;
+
+ case SFTLI:
+ s1 = s1 << s3;
+ break;
+
+ case ANDI:
+ s1 = s1 & s3;
+ break;
+
+ case ORI:
+ s1 = s1 | s3;
+ break;
+
+ case XORI:
+ s1 = s1 ^ s3;
+ break;
+
+ case LOAD:
+ case STORE:
+ case PUSH:
+ case POP:
+ s1 = s1 + s3;
+ break;
+
+ case JMP:
+ case JAL:
+ s1 = s1 + s2;
+ break;
+
+ case JRL:
+ s1 = pc + s2;
+ break;
+
+ case BEQ:
+ (this->get_condition(EQ)) ? s1 = pc + s2 : s1 = -1;
+ break;
+
+ case BGT:
+ (this->get_condition(GT)) ? s1 = pc + s2 : s1 = -1;
+ break;
+
+ case BUF:
+ (this->get_condition(UF)) ? s1 = pc + s2 : s1 = -1;
+ break;
+
+ case BOF:
+ (this->get_condition(OF)) ? s1 = pc + s2 : s1 = -1;
+ break;
+
+ case ADDV:
+ for (int i = 0; i < v_len; i++) {
+ this->set_condition(OF, ADDITION_OF_GUARD(v1[i], v2[i]));
+ this->set_condition(UF, ADDITION_UF_GUARD(v1[i], v2[i]));
+ v1[i] = v1[i] + v2[i];
+ }
+ break;
+ case SUBV:
+ for (int i = 0; i < v_len; i++) {
+ this->set_condition(OF, SUBTRACTION_OF_GUARD(v1[i], v2[i]));
+ this->set_condition(UF, SUBTRACTION_UF_GUARD(v1[i], v2[i]));
+ v1[i] = v1[i] - v2[i];
+ }
+ break;
+ case MULV:
+ for (int i = 0; i < v_len; i++) {
+ this->set_condition(OF, MULTIPLICATION_OF_GUARD(v1[i], v2[i]));
+ this->set_condition(UF, MULTIPLICATION_UF_GUARD(v1[i], v2[i]));
+ v1[i] = v1[i] * v2[i];
+ }
+ break;
+ case DIVV:
+ for (int i = 0; i < v_len; i++) {
+ this->handle_divide(v1[i], v2[i], false);
+ }
+ break;
+ case CEV:
+ int i;
+ for (i = 0; i < v_len; i++) {
+ if (v1[i] != v2[i]) {
+ break;
+ }
+ }
+ if (i == v_len) {
+ this->set_condition(EQ, true);
+ } else {
+ this->set_condition(EQ, false);
+ }
+ break;
+ case LOADV:
+ case STOREV:
+ v_base_addr = v_base_addr + v_immediate;
+ break;
+
+ case RET:
+ case NOP:
+ break;
+ }
+ if (this->is_vector_type(m)) {
+ if (this->curr_instr->mnemonic != LOADV &&
+ this->curr_instr->mnemonic != STOREV) {
+ this->curr_instr->operands.vector.slot_one = v1;
+ } else {
+ this->curr_instr->operands.load_store_vector.base_addr =
+ v_base_addr;
+ }
+ } else {
+ this->curr_instr->operands.integer.slot_one = s1;
+ }
this->status = OK;
}
diff --git a/src/id.cc b/src/id.cc
index d2a8f02..e4790ef 100644
--- a/src/id.cc
+++ b/src/id.cc
@@ -22,30 +22,27 @@
#include "response.h"
#include "stage.h"
-void ID::split_instr(signed int &raw, unsigned int &type, Mnemonic &m)
+Response ID::read_guard(signed int &v)
{
- unsigned int opcode, opcode_size;
-
- type = GET_LS_BITS(raw, TYPE_SIZE);
- opcode_size = (type == 0b0) ? R_OPCODE_SIZE : OPCODE_SIZE;
- opcode = GET_MID_BITS(raw, TYPE_SIZE, TYPE_SIZE + opcode_size);
- try {
- m = instr::mnemonic_map.at((opcode << TYPE_SIZE) + type);
- } catch (std::out_of_range const &) {
- m = NOP;
+ Response r;
+ if (this->is_checked_out(v))
+ r = STALLED;
+ else {
+ r = OK;
+ v = this->dereference_register<signed int>(v);
}
-
- raw = (unsigned int)raw >> (TYPE_SIZE + opcode_size);
+ return r;
}
-Response ID::read_guard(signed int &v)
+Response
+ID::read_vec_guard(signed int v, std::array<signed int, V_R_LIMIT> &vrs)
{
Response r;
if (this->is_checked_out(v))
r = STALLED;
else {
r = OK;
- v = this->dereference_register(v);
+ vrs = this->dereference_register<std::array<signed int, V_R_LIMIT>>(v);
}
return r;
}
@@ -59,55 +56,95 @@ void ID::write_guard(signed int &v)
this->checked_out.push_back(v);
this->curr_instr->checked_out = v;
}
- v = this->dereference_register(v);
+ v = this->dereference_register<signed int>(v);
+}
+
+void ID::write_vec_guard(signed int v, std::array<signed int, V_R_LIMIT> &vrs)
+{
+
+ // zero register shouldn't be written.
+ if (v != 0) {
+ // keep track in the instrDTO for displaying to user and writeback
+ // keep track in checked_out so we can still access this information!
+ this->checked_out.push_back(v);
+ this->curr_instr->checked_out = v;
+ }
+ vrs = this->dereference_register<std::array<signed int, V_R_LIMIT>>(v);
}
void ID::advance_helper()
{
- signed int s1, s2, s3;
- Mnemonic m;
+ signed int s1;
- if (curr_instr->mnemonic == NOP)
+ if (this->curr_instr->mnemonic == NOP)
this->status = OK;
else {
- s1 = curr_instr->slot_A;
- get_instr_fields(s1, s2, s3, m);
- if (this->status == OK) {
- curr_instr->operands.integer.slot_one = s1;
- curr_instr->operands.integer.slot_two = s2;
- curr_instr->operands.integer.slot_three = s3;
- curr_instr->mnemonic = m;
- }
+ // instuction in bits in s1
+ s1 = this->curr_instr->slot_A;
+ get_instr_fields(s1);
}
}
-void ID::get_instr_fields(
- signed int &s1, signed int &s2, signed int &s3, Mnemonic &m)
+void ID::get_instr_fields(signed int &s1)
{
unsigned int type;
+ Mnemonic m;
this->split_instr(s1, type, m);
-
+ this->curr_instr->mnemonic = m;
switch (type) {
case 0b00:
- this->decode_R_type(s1, s2, s3, m);
+ this->decode_R_type(s1);
break;
case 0b01:
- this->decode_I_type(s1, s2, s3, m);
+ this->decode_I_type(s1);
break;
case 0b10:
- this->decode_J_type(s1, s2, s3, m);
+ this->decode_J_type(s1);
break;
case 0b11:
- m = NOP;
+ // not defined, m = NOP
this->status = OK;
}
}
-void ID::decode_R_type(
- signed int &s1, signed int &s2, signed int &s3, Mnemonic &m)
+void ID::split_instr(signed int &raw, unsigned int &type, Mnemonic &m)
+{
+ unsigned int opcode, opcode_size;
+
+ type = GET_LS_BITS(raw, TYPE_SIZE);
+ opcode_size = (type == 0b0) ? R_OPCODE_SIZE : OPCODE_SIZE;
+ opcode = GET_MID_BITS(raw, TYPE_SIZE, TYPE_SIZE + opcode_size);
+ try {
+ m = instr::mnemonic_map.at((opcode << TYPE_SIZE) + type);
+ } catch (std::out_of_range const &) {
+ m = NOP;
+ }
+
+ raw = (unsigned int)raw >> (TYPE_SIZE + opcode_size);
+}
+
+Response ID::set_vlen()
+{
+ signed int vlen_reg = 4;
+ Response r;
+ r = this->read_guard(vlen_reg);
+ vlen_reg = vlen_reg & 0xf;
+ if (r == OK) {
+ if (vlen_reg > V_R_LIMIT) {
+ this->curr_instr->slot_A = V_R_LIMIT;
+ } else {
+ this->curr_instr->slot_A = vlen_reg;
+ }
+ }
+ return r;
+}
+
+void ID::decode_R_type(signed int &s1)
{
unsigned int s0b, s1b, s2b;
+ signed int s2, s3;
Response r1, r2;
+ Response r3 = OK;
s0b = REG_SIZE;
s1b = s0b + REG_SIZE;
@@ -116,62 +153,124 @@ void ID::decode_R_type(
s2 = GET_MID_BITS(s1, s0b, s1b);
s1 = GET_LS_BITS(s1, s0b);
- r1 = this->read_guard(s1);
- r2 = this->read_guard(s2);
- this->status = (r1 == OK && r2 == OK) ? OK : STALLED;
+ if (this->is_vector_type(this->curr_instr->mnemonic)) {
+ r1 = this->read_vec_guard(
+ s1, this->curr_instr->operands.vector.slot_one);
+ r2 = this->read_vec_guard(
+ s2, this->curr_instr->operands.vector.slot_two);
+ r3 = this->set_vlen();
+ } else {
+ r1 = this->read_guard(s1);
+ this->curr_instr->operands.integer.slot_one = s1;
+ r2 = this->read_guard(s2);
+ this->curr_instr->operands.integer.slot_two = s2;
+ }
- switch (m) {
+ this->status = (r1 == OK && r2 == OK && r3 == OK) ? OK : STALLED;
+
+ switch (this->curr_instr->mnemonic) {
case CMP:
case CEV:
break;
+ case ADDV:
+ case SUBV:
+ case MULV:
+ case DIVV:
+ if (this->status == OK) {
+ this->write_vec_guard(
+ s3, this->curr_instr->operands.vector.slot_three);
+ }
+ break;
default:
- if (this->status == OK)
+ if (this->status == OK) {
this->write_guard(s3);
+ this->curr_instr->operands.integer.slot_three = s3;
+ }
}
}
-void ID::decode_I_type(
- signed int &s1, signed int &s2, signed int &s3, Mnemonic &m)
+void ID::decode_I_type(signed int &s1)
{
unsigned int s0b, s1b, s2b;
+ signed int s2, s3;
Response r1, r2;
+ Response r3 = OK;
s0b = REG_SIZE;
s1b = s0b + REG_SIZE;
s2b = WORD_SPEC - LINE_SPEC - OPCODE_SIZE;
+ // s3 is immediate
s3 = GET_BITS_SIGN_EXTEND(s1, s1b, s2b);
- switch (m) {
+ switch (this->curr_instr->mnemonic) {
case STORE:
- case STOREV:
+ this->curr_instr->operands.integer.slot_three = s3;
s2 = GET_MID_BITS(s1, s0b, s1b);
s1 = GET_LS_BITS(s1, s0b);
// both operands are read values
+ // s1 is base address
r1 = this->read_guard(s1);
+ this->curr_instr->operands.integer.slot_one = s1;
+ // s2 is value to be stored
r2 = this->read_guard(s2);
+ this->curr_instr->operands.integer.slot_two = s2;
this->status = (r1 == OK && r2 == OK) ? OK : STALLED;
return;
- case LOAD:
+ case STOREV:
+ this->curr_instr->operands.load_store_vector.immediate = s3;
+ s2 = GET_MID_BITS(s1, s0b, s1b);
+ s1 = GET_LS_BITS(s1, s0b);
+
+ // base address
+ r1 = this->read_guard(s1);
+ this->curr_instr->operands.load_store_vector.base_addr = s1;
+ // vector value to be stored
+ r2 = this->read_vec_guard(
+ s2, this->curr_instr->operands.load_store_vector.vector_register);
+ r3 = this->set_vlen();
+
+ this->status = (r1 == OK && r2 == OK && r3 == OK) ? OK : STALLED;
+ return;
case LOADV:
+ this->curr_instr->operands.load_store_vector.immediate = s3;
+ s2 = GET_LS_BITS(s1, s0b);
+ s1 = GET_MID_BITS(s1, s0b, s1b);
+ // base address
+ r1 = this->read_guard(s1);
+ this->curr_instr->operands.load_store_vector.base_addr = s1;
+ r3 = this->set_vlen();
+ if (r1 == OK && r3 == OK)
+ // vector destination
+ this->write_vec_guard(
+ s2,
+ this->curr_instr->operands.load_store_vector.vector_register);
+ this->status = (r1 == OK && r3 == OK) ? OK : STALLED;
+ return;
+ case LOAD:
+ this->curr_instr->operands.integer.slot_three = s3;
s2 = GET_LS_BITS(s1, s0b);
s1 = GET_MID_BITS(s1, s0b, s1b);
break;
default:
+ this->curr_instr->operands.integer.slot_three = s3;
s2 = GET_MID_BITS(s1, s0b, s1b);
s1 = GET_LS_BITS(s1, s0b);
}
r1 = this->read_guard(s1);
- if (r1 == OK)
+ this->curr_instr->operands.integer.slot_one = s1;
+ if (r1 == OK) {
this->write_guard(s2);
+ this->curr_instr->operands.integer.slot_two = s2;
+ }
this->status = r1;
}
-void ID::decode_J_type(
- signed int &s1, signed int &s2, signed int &s3, Mnemonic &m)
+void ID::decode_J_type(signed int &s1)
{
Response r1, r2;
+ signed int s2, s3;
unsigned int s0b, s1b;
s0b = REG_SIZE;
@@ -180,26 +279,34 @@ void ID::decode_J_type(
s2 = GET_BITS_SIGN_EXTEND(s1, s0b, s1b);
s1 = GET_LS_BITS(s1, s0b);
- switch (m) {
+ switch (this->curr_instr->mnemonic) {
case PUSH:
s2 = s1; // source
- s3 = 2; // stack pointer
+ s3 = 2; // stack pointer
s1 = -1; // increment amount
r1 = this->read_guard(s2);
- r2 = (this->is_checked_out(s3)) ? STALLED : OK; // we read the stack pointer
+ this->curr_instr->operands.integer.slot_one = s1;
+ this->curr_instr->operands.integer.slot_two = s2;
+ r2 = (this->is_checked_out(s3)) ? STALLED
+ : OK; // we read the stack pointer
if (r1 == OK && r2 == OK) {
this->write_guard(s3); // we write the stack pointer
+ this->curr_instr->operands.integer.slot_three = s3;
}
this->status = (r1 == OK && r2 == OK) ? OK : STALLED;
break;
case POP:
s2 = s1; // destination
- s3 = 2; // stack pointer
- s1 = 1; // increment amount
- r1 = (this->is_checked_out(s3)) ? STALLED : OK; // we read the stack pointer
+ s3 = 2; // stack pointer
+ s1 = 1; // increment amount
+ this->curr_instr->operands.integer.slot_one = s1;
+ r1 = (this->is_checked_out(s3)) ? STALLED
+ : OK; // we read the stack pointer
if (r1 == OK) {
this->write_guard(s2);
+ this->curr_instr->operands.integer.slot_two = s2;
this->write_guard(s3); // we write the stack pointer
+ this->curr_instr->operands.integer.slot_three = s3;
}
this->status = r1;
break;
@@ -208,6 +315,10 @@ void ID::decode_J_type(
[[fallthrough]];
default:
this->status = this->read_guard(s1);
+ if(this->status == OK){
+ this->curr_instr->operands.integer.slot_one = s1;
+ this->curr_instr->operands.integer.slot_two = s2;
+ this->curr_instr->operands.integer.slot_three = s3;
+ }
}
-
}
diff --git a/src/mm.cc b/src/mm.cc
index ac77433..8134cf5 100644
--- a/src/mm.cc
+++ b/src/mm.cc
@@ -24,6 +24,7 @@ void MM::advance_helper()
{
signed int data;
int i;
+ int vector_delay = VECTOR_MEM_DELAY;
switch (this->curr_instr->mnemonic) {
case LOAD:
@@ -35,6 +36,32 @@ void MM::advance_helper()
} else
this->status = STALLED;
break;
+ case LOADV:
+ if (vector_delay == 0){
+ signed int word_address = this->curr_instr->operands.load_store_vector.base_addr;
+ int j = 0;
+ while(j < this->curr_instr->slot_A){
+ i = this->storage->read_word(this, word_address, data);
+ this->status = i ? OK : STALLED;
+ if (this->status == OK) {
+ this->curr_instr->operands.load_store_vector.vector_register[j] = data;
+ // +1 or +4?
+ word_address += 1;
+ j++;
+ } else {
+ break;
+ }
+ }
+ if(this->status == OK){
+ // if vector is loaded, reset delay
+ vector_delay = VECTOR_MEM_DELAY;
+ } else {
+ this->status = STALLED;
+ }
+ } else {
+ vector_delay--;
+ }
+ break;
case PUSH:
case STORE:
@@ -46,6 +73,31 @@ void MM::advance_helper()
this->status = STALLED;
}
break;
+ case STOREV:
+ if (vector_delay == 0){
+ signed int word_address = this->curr_instr->operands.load_store_vector.base_addr;
+ int j = 0;
+ while(j < this->curr_instr->slot_A){
+ this->storage->write_word(
+ this, this->curr_instr->operands.load_store_vector.vector_register[j], word_address);
+ this->status = i ? OK : STALLED;
+ if (this->status != OK) {
+ break;
+ } else {
+ word_address += 1;
+ j++;
+ }
+ }
+ if(this->status == OK){
+ // if vector is stored , reset delay
+ vector_delay = VECTOR_MEM_DELAY;
+ } else {
+ this->status = STALLED;
+ }
+ } else {
+ vector_delay--;
+ }
+ break;
case POP:
i = this->storage->read_word(this, this->curr_instr->operands.integer.slot_three, data);
diff --git a/src/stage.cc b/src/stage.cc
index 4efe2fe..ac688d8 100644
--- a/src/stage.cc
+++ b/src/stage.cc
@@ -16,6 +16,7 @@
// along with this program. If not, see <https://www.gnu.org/licenses/>.
#include "stage.h"
+#include "pipe_spec.h"
#include <array>
#include <deque>
@@ -29,7 +30,7 @@ Stage::Stage(Stage *next)
Stage::~Stage() { delete this->next; };
std::array<int, GPR_NUM> Stage::gprs;
-std::array<int, V_NUM> Stage::vrs;
+std::array<std::array<signed int, V_R_LIMIT>, V_NUM> Stage::vrs;
std::deque<signed int> Stage::checked_out;
unsigned int Stage::pc;
Storage *Stage::storage;
@@ -65,40 +66,28 @@ InstrDTO *Stage::advance(Response p)
return r;
}
-InstrDTO *Stage::get_instr() { return this->curr_instr; }
-
-void Stage::set_condition(CC c, bool v)
+bool Stage::is_vector_type(Mnemonic m)
{
- if (v)
- this->gprs[3] = this->gprs[3] | 1 << c;
- else
- this->gprs[3] = this->gprs[3] & ~(1 << c);
+ return (
+ m == ADDV || m == SUBV || m == MULV || m == DIVV || m == CEV ||
+ m == LOADV || m == STOREV);
}
-signed int Stage::dereference_register(signed int v)
+bool Stage::is_logical(Mnemonic m)
{
- signed int r;
-
- if (v < 0 || v >= GPR_NUM + V_NUM) {
- throw std::out_of_range(
- "instruction tried to access register which does not exist");
- }
-
- r = (v >= GPR_NUM) ? this->vrs[v % GPR_NUM] : this->gprs[v];
- return r;
+ return (
+ m == ANDI || m == ORI || m == XORI || m == AND || m == OR || m == XOR ||
+ m == NOT);
}
-void Stage::store_register(signed int v, signed int d)
-{
- if (v < 0 || v >= GPR_NUM + V_NUM) {
- throw std::out_of_range(
- "instruction tried to access register which does not exist");
- }
+InstrDTO *Stage::get_instr() { return this->curr_instr; }
- if (v >= GPR_NUM)
- this->vrs[v % GPR_NUM] = d;
+void Stage::set_condition(CC c, bool v)
+{
+ if (v)
+ this->gprs[3] = this->gprs[3] | 1 << c;
else
- this->gprs[v] = d;
+ this->gprs[3] = this->gprs[3] & ~(1 << c);
}
bool Stage::is_checked_out(signed int r)
diff --git a/src/wb.cc b/src/wb.cc
index cd24c6a..0dae5f2 100644
--- a/src/wb.cc
+++ b/src/wb.cc
@@ -45,13 +45,22 @@ void WB::write_handler()
// POP performs a second register write
reg = this->checked_out.front();
this->checked_out.pop_front();
- this->store_register(
+ this->store_register<signed int>(
reg, this->curr_instr->operands.integer.slot_three);
}
this->checked_out.pop_front();
reg = this->curr_instr->checked_out;
- this->store_register(reg, this->curr_instr->operands.integer.slot_one);
+
+ if(this->is_vector_type(this->curr_instr->mnemonic)) {
+ if(this->curr_instr->mnemonic != STOREV && this->curr_instr->mnemonic != LOADV) {
+ this->store_register<std::array<signed int, V_R_LIMIT>>(reg, this->curr_instr->operands.vector.slot_one);
+ } else {
+ this->store_register<std::array<signed int, V_R_LIMIT>>(reg, this->curr_instr->operands.load_store_vector.vector_register);
+ }
+ } else{
+ this->store_register<signed int>(reg, this->curr_instr->operands.integer.slot_one);
+ }
}
void WB::jump_handler()