diff options
| -rw-r--r-- | gui/digitlabel.cc | 10 | ||||
| -rw-r--r-- | gui/digitlabel.h | 2 | ||||
| -rw-r--r-- | gui/digitlabeldelegate.cc (renamed from src/sim/dum.cc) | 47 | ||||
| -rw-r--r-- | gui/digitlabeldelegate.h (renamed from inc/dum.h) | 43 | ||||
| -rw-r--r-- | gui/gui.cc | 159 | ||||
| -rw-r--r-- | gui/gui.h | 27 | ||||
| -rw-r--r-- | gui/gui.ui | 2 | ||||
| -rw-r--r-- | gui/resources/styles.qss | 30 | ||||
| -rw-r--r-- | gui/storageview.cc | 88 | ||||
| -rw-r--r-- | gui/storageview.h | 93 | ||||
| -rw-r--r-- | gui/util.cc | 25 | ||||
| -rw-r--r-- | gui/util.h | 27 | ||||
| -rw-r--r-- | gui/worker.cc | 53 | ||||
| -rw-r--r-- | gui/worker.h | 31 | ||||
| -rw-r--r-- | inc/accessor.h | 35 | ||||
| -rw-r--r-- | inc/ex.h | 2 | ||||
| -rw-r--r-- | inc/id.h | 11 | ||||
| -rw-r--r-- | inc/if.h | 10 | ||||
| -rw-r--r-- | inc/instr.h | 7 | ||||
| -rw-r--r-- | inc/instrDTO.h | 133 | ||||
| -rw-r--r-- | inc/mm.h | 7 | ||||
| -rw-r--r-- | inc/pipe_spec.h | 5 | ||||
| -rw-r--r-- | inc/response.h | 3 | ||||
| -rw-r--r-- | inc/stage.h | 22 | ||||
| -rw-r--r-- | inc/wb.h | 7 | ||||
| -rw-r--r-- | src/controller.cc (renamed from src/sim/controller.cc) | 4 | ||||
| -rw-r--r-- | src/ex.cc (renamed from src/sim/ex.cc) | 16 | ||||
| -rw-r--r-- | src/id.cc (renamed from src/sim/id.cc) | 38 | ||||
| -rw-r--r-- | src/if.cc (renamed from src/sim/if.cc) | 23 | ||||
| -rw-r--r-- | src/instr.cc (renamed from src/sim/instr.cc) | 0 | ||||
| -rw-r--r-- | src/logger.cc (renamed from src/logger/logger.cc) | 0 | ||||
| -rw-r--r-- | src/mm.cc (renamed from src/sim/mm.cc) | 17 | ||||
| -rw-r--r-- | src/response.cc (renamed from src/utils/response.cc) | 2 | ||||
| -rw-r--r-- | src/sim/instrDTO.cc | 71 | ||||
| -rw-r--r-- | src/stage.cc (renamed from src/sim/stage.cc) | 31 | ||||
| -rw-r--r-- | src/utils/accessor.cc | 27 | ||||
| -rw-r--r-- | src/wb.cc (renamed from src/sim/wb.cc) | 38 | ||||
| -rw-r--r-- | tests/controller.cc | 2 | ||||
| -rw-r--r-- | tests/dum.h | 35 | ||||
| -rw-r--r-- | tests/ex.cc | 102 | ||||
| -rw-r--r-- | tests/id.cc | 52 | ||||
| -rw-r--r-- | tests/if.cc | 16 | 
42 files changed, 670 insertions, 683 deletions
diff --git a/gui/digitlabel.cc b/gui/digitlabel.cc index 8314943..f77c1fa 100644 --- a/gui/digitlabel.cc +++ b/gui/digitlabel.cc @@ -16,6 +16,7 @@  // along with this program.  If not, see <https://www.gnu.org/licenses/>.  #include "digitlabel.h" +#include "util.h"  #include "gui.h"  DigitLabel::DigitLabel(QWidget *parent) : QLabel(parent) { setText(QString()); } @@ -42,11 +43,6 @@ void DigitLabel::on_hex_toggle(bool is_hex)  void DigitLabel::update_display()  {  	QString t; -	if (this->is_cleared) { -		setText(QString()); -	} else { -		t = (this->is_hex) ? QString::number(this->v, 16).toUpper() -						   : QString::number(this->v); -		setText(t); -	} +	t = format_toggled_value(this->v, this->is_hex, this->is_cleared); +	setText(t);  } diff --git a/gui/digitlabel.h b/gui/digitlabel.h index 68b01cb..bffdd0a 100644 --- a/gui/digitlabel.h +++ b/gui/digitlabel.h @@ -59,7 +59,7 @@ class DigitLabel : public QLabel  	/**  	 * If this digit should display in hexidecinmal.  	 */ -	int is_hex; +	int is_hex = true;  	/**  	 * If this digit should not display.  	 */ diff --git a/src/sim/dum.cc b/gui/digitlabeldelegate.cc index 744c110..430946c 100644 --- a/src/sim/dum.cc +++ b/gui/digitlabeldelegate.cc @@ -15,30 +15,37 @@  // 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 "dum.h" -#include "accessor.h" -#include "instrDTO.h" -#include "response.h" -#include "stage.h" +#include "digitlabeldelegate.h" +#include "util.h" +#include <QString> -DUM::DUM(Stage *stage) : Stage(stage) { this->id = IDLE; } - -InstrDTO *DUM::advance(Response p) +void DigitLabelDelegate::set_hex_display(bool hex)  { -	InstrDTO *r = nullptr; - -	if (this->curr_instr && p == WAIT) { -		r = new InstrDTO(*this->curr_instr); -		delete this->curr_instr; -		curr_instr = nullptr; +	if (this->is_hex != hex) { +		this->is_hex = hex; +		if (auto v = qobject_cast<QAbstractItemView *>(parent())) +			v->viewport()->update();  	} - -	return r;  } -void DUM::advance_helper() {} - -void DUM::set_curr_instr(InstrDTO *d) +void DigitLabelDelegate::paint( +	QPainter *painter, +	const QStyleOptionViewItem &option, +	const QModelIndex &index) const  { -	this->curr_instr = d; +	int v; +	QString t; +	QStyleOptionViewItem o; +	QStyle *s; + +	v = index.data(Qt::DisplayRole).toInt(); +	t = format_toggled_value(v, this->is_hex); + +	o = option; +	initStyleOption(&o, index); +	o.text = t; + +	const QWidget *w = option.widget; +	s = w ? w->style() : QApplication::style(); +	s->drawControl(QStyle::CE_ItemViewItem, &o, painter, w);  } diff --git a/inc/dum.h b/gui/digitlabeldelegate.h index 4a3069a..7714d25 100644 --- a/inc/dum.h +++ b/gui/digitlabeldelegate.h @@ -15,31 +15,32 @@  // 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 DUM_H -#define DUM_H -#include "instrDTO.h" -#include "response.h" -#include "stage.h" - -/** - * Don't underestimate mocks (the DUM pipe stage). - */ -class DUM : public Stage +#ifndef DIGITLABELDELEGATE_H +#define DIGITLABELDELEGATE_H + +#include <QAbstractItemView> +#include <QApplication> +#include <QPainter> +#include <QString> +#include <QStyleOptionViewItem> +#include <QStyledItemDelegate> + +class DigitLabelDelegate : public QStyledItemDelegate  { +	Q_OBJECT    public: -	/** -	 * Constructor. -	 * @param The next stage in the pipeline. -	 * @return A newly allocated DUM object. -	 */ -	DUM(Stage *next); +	using QStyledItemDelegate::QStyledItemDelegate; -	InstrDTO *advance(Response p) override; - -	void set_curr_instr(InstrDTO *); +  public slots: +	void set_hex_display(bool hex);    private: -	void advance_helper() override; +	bool is_hex = true; + +	void paint( +		QPainter *painter, +		const QStyleOptionViewItem &option, +		const QModelIndex &index) const override;  }; -#endif /* DUM_H_INCLUDED */ +#endif // DIGITLABELDELEGATE_H @@ -17,10 +17,15 @@  #include "gui.h"  #include "./ui_gui.h" +#include "digitlabeldelegate.h"  #include "dynamicwaysentry.h"  #include "messages.h" +#include "storageview.h" +#include "util.h" +#include <QHeaderView>  #include <QPixmap>  #include <QString> +#include <QTableView>  GUI::GUI(QWidget *parent) : QMainWindow(parent), ui(new Ui::GUI)  { @@ -53,7 +58,6 @@ GUI::GUI(QWidget *parent) : QMainWindow(parent), ui(new Ui::GUI)  	for (DigitLabel *label : labels) {  		connect(this, &GUI::hex_toggled, label, &DigitLabel::on_hex_toggle);  	} -	emit this->hex_toggled(this->is_hex);  	// display clock cycles and PC  	connect(worker, &Worker::clock_cycles, this, &GUI::on_worker_refresh_gui); @@ -92,7 +96,6 @@ GUI::GUI(QWidget *parent) : QMainWindow(parent), ui(new Ui::GUI)  	});  	// Proper cleanup when worker finishes -	connect(worker, &Worker::finished, this, &GUI::onWorkerFinished);  	connect(worker, &Worker::finished, &workerThread, &QThread::quit);  	connect(&workerThread, &QThread::finished, worker, &QObject::deleteLater); @@ -132,73 +135,43 @@ void displayArrayHTML(QTextEdit *textEdit, const std::array<int, GPR_NUM> &data)  	textEdit->setReadOnly(true);  } -void displayTableHTML( -	QTextEdit *textEdit, -	const std::vector<std::array<signed int, LINE_SIZE>> &data) -{ -	textEdit->setReadOnly(false); -	QString tableText = "<table border='1' cellspacing='0' cellpadding='8' " -						"style='border-collapse: collapse; width: 100%; " -						"border: 2px solid black;'>"; - -	int index = 0; -	for (const auto &row : data) { -		tableText += "<tr>"; -		for (signed int value : row) { -			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 std::vector<int> info) +void GUI::onWorkerFetchInfo(const InstrDTO *i)  { -	if (!info.empty()) { -		ui->fetch_squashed->setText(QString::number(info[0])); -		ui->fetch_bits->set_value(info[1]); +	if (i) { +		ui->fetch_squashed->setText(QString::number(i->is_squashed)); +		ui->fetch_bits->set_value(i->slot_A);  	} else {  		ui->fetch_squashed->clear();  		ui->fetch_bits->clear();  	}  } -void GUI::onWorkerDecodeInfo(const std::vector<int> info) +void GUI::onWorkerDecodeInfo(const InstrDTO *i)  { -	if (!info.empty()) { -		ui->decode_squashed->setText(QString::number(info[0])); -		ui->decode_bits->set_value(info[1]); +	if (i) { +		ui->decode_squashed->setText(QString::number(i->is_squashed)); +		ui->decode_bits->set_value(i->slot_A);  	} else {  		ui->decode_squashed->clear();  		ui->decode_bits->clear();  	}  } -void GUI::onWorkerExecuteInfo(const std::vector<int> info) +void GUI::onWorkerExecuteInfo(const InstrDTO *i)  { -	if (!info.empty()) { -		ui->execute_mnemonic->setText(mnemonicToString((Mnemonic)info[0])); -		ui->execute_squashed->setText(QString::number(info[1])); -		ui->execute_s1->set_value(info[2]); -		ui->execute_s2->set_value(info[3]); -		ui->execute_s3->set_value(info[4]); +	if (i) { +		ui->execute_mnemonic->setText(mnemonicToString(i->mnemonic)); +		ui->execute_squashed->setText(QString::number(i->is_squashed)); +		ui->execute_s1->set_value(i->operands.integer.slot_one); +		ui->execute_s2->set_value(i->operands.integer.slot_two); +		ui->execute_s3->set_value(i->operands.integer.slot_three);  	} else {  		ui->execute_mnemonic->clear();  		ui->execute_squashed->clear(); @@ -208,15 +181,14 @@ void GUI::onWorkerExecuteInfo(const std::vector<int> info)  	}  } -void GUI::onWorkerMemoryInfo(const std::vector<int> info) +void GUI::onWorkerMemoryInfo(const InstrDTO *i)  { -	if (!info.empty()) { -		std::cout << "this " << info[3] << std::endl; -		ui->memory_mnemonic->setText(mnemonicToString((Mnemonic)info[0])); -		ui->memory_squashed->setText(QString::number(info[1])); -		ui->memory_s1->set_value(info[2]); -		ui->memory_s2->set_value(info[3]); -		ui->memory_s3->set_value(info[4]); +	if (i) { +		ui->memory_mnemonic->setText(mnemonicToString(i->mnemonic)); +		ui->memory_squashed->setText(QString::number(i->is_squashed)); +		ui->memory_s1->set_value(i->operands.integer.slot_one); +		ui->memory_s2->set_value(i->operands.integer.slot_two); +		ui->memory_s3->set_value(i->operands.integer.slot_three);  	} else {  		ui->memory_mnemonic->clear();  		ui->memory_squashed->clear(); @@ -226,14 +198,14 @@ void GUI::onWorkerMemoryInfo(const std::vector<int> info)  	}  } -void GUI::onWorkerWriteBackInfo(const std::vector<int> info) +void GUI::onWorkerWriteBackInfo(const InstrDTO *i)  { -	if (!info.empty()) { -		ui->write_mnemonic->setText(mnemonicToString((Mnemonic)info[0])); -		ui->write_squashed->setText(QString::number(info[1])); -		ui->write_s1->set_value(info[2]); -		ui->write_s2->set_value(info[3]); -		ui->write_s3->set_value(info[4]); +	if (i) { +		ui->write_mnemonic->setText(mnemonicToString(i->mnemonic)); +		ui->write_squashed->setText(QString::number(i->is_squashed)); +		ui->write_s1->set_value(i->operands.integer.slot_one); +		ui->write_s2->set_value(i->operands.integer.slot_two); +		ui->write_s3->set_value(i->operands.integer.slot_three);  	} else {  		ui->write_mnemonic->clear();  		ui->write_squashed->clear(); @@ -243,24 +215,19 @@ void GUI::onWorkerWriteBackInfo(const std::vector<int> info)  	}  } -void GUI::onWorkerShowStorage( -	const std::vector<std::array<signed int, LINE_SIZE>> data, int i) +void GUI::onWorkerShowStorage(const QVector<QVector<int>> &data, int i)  { -	std::cout << this->tab_text_boxes.size() << std::endl; -	displayTableHTML(this->tab_text_boxes.at(i), data); +	this->tab_boxes.at(i)->set_data(data);  }  void GUI::onWorkerShowRegisters(const std::array<int, GPR_NUM> &data)  { -	displayArrayHTML(this->tab_text_boxes.at(0), data); +	; +	// displayArrayHTML(this->tab_boxes.at(0), data);  } -void GUI::onWorkerFinished() { qDebug() << "Worker has finished processing."; } -  void GUI::on_upload_intructions_btn_clicked()  { -	qDebug() << "Upload intructions button clicked."; -  	// why ui->register_table, or now ui->storage  	QString filePath = QFileDialog::getOpenFileName(  		ui->storage, "Open Binary File", QDir::homePath(), @@ -312,7 +279,6 @@ void GUI::on_base_toggle_checkbox_checkStateChanged(const Qt::CheckState &state)  void GUI::on_step_btn_clicked()  { -	qDebug() << "Run step button clicked.";  	// try to configure first  	if (!this->ready)  		this->on_config_clicked(); @@ -323,7 +289,6 @@ void GUI::on_step_btn_clicked()  	this->set_status(get_running, "busy");  	int steps = step_values[ui->step_slider->value()];  	emit sendRunSteps(steps); -	this->set_status(get_waiting, "idle");  }  void GUI::on_save_program_state_btn_clicked() @@ -368,6 +333,8 @@ void GUI::on_config_clicked()  	else  		this->set_status(get_initialize, "happy"); +	this->curr_cache_levels = ways.size(); +  	emit sendConfigure(ways, this->p, is_pipelined);  	make_tabs(2 + ways.size());  } @@ -375,27 +342,43 @@ void GUI::on_config_clicked()  void GUI::make_tabs(int num)  {  	int i; -	QStringList names; -	QTextEdit *e; +	StorageView *e; +	QTableView *t;  	QString n; - -	names = {"Registers", "DRAM"}; +	DigitLabelDelegate *d;  	ui->storage->clear(); -	this->tab_text_boxes.clear(); + +	qDeleteAll(this->tab_boxes); +	this->tab_boxes.clear();  	for (i = 0; i < num; ++i) { -		e = new QTextEdit(); -		e->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding); +		if (i == 0) { +			n = "Registers"; +			e = new StorageView(0, this); +		} else if (i == num - 1) { +			n = "DRAM"; +			e = new StorageView(MEM_LINES, this); +		} else { +			n = QString("L%1").arg(i); +			e = new StorageView( +				(1 << cache_size_mapper(this->curr_cache_levels - 1, i - 1)), +				this); +		} + +		t = new QTableView(ui->storage); +		t->setModel(e); +		d = new DigitLabelDelegate(t); + +		connect(this, &GUI::hex_toggled, e, &StorageView::set_hex_display); +		connect( +			this, &GUI::hex_toggled, d, &DigitLabelDelegate::set_hex_display); -		// make the name -		if (i < names.size()) -			n = names[i]; -		else -			n = QString("Level %1").arg(i - 1); +		t->setItemDelegate(d); +		t->horizontalHeader()->setSectionResizeMode(QHeaderView::Stretch); -		ui->storage->addTab(e, n); -		this->tab_text_boxes.push_back(e); +		ui->storage->addTab(t, n); +		this->tab_boxes.push_back(e);  	}  } @@ -18,6 +18,7 @@  #ifndef GUI_H  #define GUI_H +#include "storageview.h"  #include "worker.h"  #include <QFile>  #include <QFileDialog> @@ -57,23 +58,20 @@ class GUI : public QMainWindow    private slots:  	void on_worker_refresh_gui(int value, int pc); -	void onWorkerFetchInfo(const std::vector<int> info); +	void onWorkerFetchInfo(const InstrDTO *); -	void onWorkerDecodeInfo(const std::vector<int> info); +	void onWorkerDecodeInfo(const InstrDTO *); -	void onWorkerExecuteInfo(const std::vector<int> info); +	void onWorkerExecuteInfo(const InstrDTO *); -	void onWorkerMemoryInfo(const std::vector<int> info); +	void onWorkerMemoryInfo(const InstrDTO *); -	void onWorkerWriteBackInfo(const std::vector<int> info); +	void onWorkerWriteBackInfo(const InstrDTO *); -	void onWorkerShowStorage( -		const std::vector<std::array<signed int, LINE_SIZE>> data, int i); +	void onWorkerShowStorage(const QVector<QVector<int>> &data, int i);  	void onWorkerShowRegisters(const std::array<int, GPR_NUM> &data); -	void onWorkerFinished(); -  	void on_upload_intructions_btn_clicked();  	void on_upload_program_state_btn_clicked(); @@ -101,12 +99,17 @@ class GUI : public QMainWindow  	/**  	 * Indicates if the program has been initialized.  	 */ -	bool ready; +	bool ready = false; + +	/** +	 * The current number of cache levels. +	 */ +	int curr_cache_levels = 0;  	/**  	 * The list of storage displays.  	 */ -	std::vector<QTextEdit *> tab_text_boxes; +	std::vector<StorageView *> tab_boxes;  	/**  	 * Whether or not numerical values are currently displaying in hex. @@ -135,7 +138,7 @@ class GUI : public QMainWindow  	/**  	 * The possible step slider values.  	 */ -	QVector<int> step_values = {1, 5, 20, 50, 250, 1000, 10000}; +	QVector<int> step_values = {1, 5, 20, 50, 250, 1000, 10000, 100000, 500000, 100000000};  	QThread workerThread; @@ -630,7 +630,7 @@                   <number>0</number>                  </property>                  <property name="maximum"> -                 <number>6</number> +                 <number>9</number>                  </property>                  <property name="pageStep">                   <number>1</number> diff --git a/gui/resources/styles.qss b/gui/resources/styles.qss index 76d0311..a61035e 100644 --- a/gui/resources/styles.qss +++ b/gui/resources/styles.qss @@ -50,15 +50,27 @@ QGroupBox::title {  QLabel {  } -/* text entry */ -QLineEdit { -    font-size: 18pt; -    border-radius: 0px; -    padding: 0 4px; -    selection-background-color: "#00cc00"; +QTableView { +    border: 0px; +    selection-background-color: transparent; +    selection-color: black; +    outline: none; +} + +QTableView::item { +    border: none; +    padding: 4px; +} + +QHeaderView::section { +    color: "#00cc00"; +    background-color: "#000200"; +    border: none;  } -QTextEdit, QListView { +QTableView QTableCornerButton::section { +    background-color: "#000200"; +    border: none;  }  QPushButton { @@ -71,8 +83,8 @@ QPushButton {  QPushButton:pressed {      color: "#00cc00"; -    background-color: "#000200"; -} +    background-color: "#000200";} +  QPushButton:flat {      border: none; /* no border for a flat push button */ diff --git a/gui/storageview.cc b/gui/storageview.cc new file mode 100644 index 0000000..2f444a9 --- /dev/null +++ b/gui/storageview.cc @@ -0,0 +1,88 @@ +// 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 "storageview.h" +#include "definitions.h" +#include "util.h" +#include <QAbstractTableModel> +#include <QVector> + +StorageView::StorageView(int rows, QObject *parent) +	: QAbstractTableModel(parent) +{ +	this->r = rows; +	this->d.resize(rows); +	for (auto &row : this->d) +		row.resize(LINE_SIZE, 0); +} + +int StorageView::rowCount(const QModelIndex &) const { return this->r; } + +int StorageView::columnCount(const QModelIndex &) const { return LINE_SIZE; } + +QVariant StorageView::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(); +	return this->d[i.row()][i.column()]; +} + +QVariant StorageView::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 * 4, this->is_hex); +	} +	return QVariant(); +} + +Qt::ItemFlags StorageView::flags(const QModelIndex &i) const +{ +	(void)i; +	return Qt::ItemIsEnabled; +} + +void StorageView::set_data(const QVector<QVector<int>> &data) +{ +	beginResetModel(); +	this->d = data; +	endResetModel(); +} + +void StorageView::set_hex_display(bool hex) +{ +	if (this->is_hex != hex) { +		beginResetModel(); +		this->is_hex = hex; +		endResetModel(); +	} +} diff --git a/gui/storageview.h b/gui/storageview.h new file mode 100644 index 0000000..0518d8f --- /dev/null +++ b/gui/storageview.h @@ -0,0 +1,93 @@ +// 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 STORAGEVIEW_H +#define STORAGEVIEW_H + +#include <QAbstractTableModel> +#include <QVector> + +// see https://doc.qt.io/qt-6/qabstracttablemodel.html +class StorageView : public QAbstractTableModel +{ +	Q_OBJECT +  public: +	/** +	 * Constructor. Initializes a clean StorageView object with +	 * `rows' rows. +	 * @param the number of rows +	 */ +	StorageView(int rows, QObject *parent = nullptr); + +	/** +	 * Returns the number of rows in this table. +	 * @param the parent +	 * @return the number of rows under the given parent. +	 */ +	int rowCount(const QModelIndex &) const override; +	/** +	 * Returns the number of columns in this table. +	 * @param the parent +	 * @return the number of columns under the given parent (hint: it's +	 * LINE_SIZE) +	 */ +	int columnCount(const QModelIndex &) const override; + +	/** +	 * 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; + +	/** +	 * Ensures the table is enabled, but not selectable. +	 */ +	Qt::ItemFlags flags(const QModelIndex &i) const override; + +	/** +	 * @param field to assign to `this->d' +	 */ +	void set_data(const QVector<QVector<int>> &data); + +  public slots: +	void set_hex_display(bool hex); + +  private: +	/** +	 * The number of rows in this table. +	 */ +	int r; +	/** +	 * Whether or not the headers should be displayed in hex. +	 */ +	bool is_hex = true; +	/** +	 * The data this table displays. +	 */ +	QVector<QVector<int>> d; +}; + +#endif // STORAGEVIEW_H diff --git a/gui/util.cc b/gui/util.cc new file mode 100644 index 0000000..b62ed81 --- /dev/null +++ b/gui/util.cc @@ -0,0 +1,25 @@ +#include "util.h" +#include "definitions.h" +#include <QString> + +int cache_size_mapper(int total_levels, int level) +{ +	const int y_min = 4; +	const int y_max = MEM_LINE_SPEC - 4; +	double f, r; + +	if (total_levels <= 0) +		return 7; + +	f = level / (double)total_levels; +	r = y_min + f * (y_max - y_min); + +	return r; +} + +QString format_toggled_value(int value, bool is_hex, bool is_cleared) +{ +	if (is_cleared) +		return QString(); +	return is_hex ? QString::asprintf("%X", value) : QString::number(value); +} diff --git a/gui/util.h b/gui/util.h new file mode 100644 index 0000000..8e9d308 --- /dev/null +++ b/gui/util.h @@ -0,0 +1,27 @@ +#ifndef UTIL_H +#define UTIL_H + +#include <QString> + +/** + * Given `total_levels', returns an integer between 4 and 12 which is a linear + * map of `level' onto `total_levels'. This is used for generating cache sizes + * given a number of levels. + * @param the total number of cache levels, zero-indexed. + * @param a numberedcache level, zero-indexed. + * @return an integer between 4-12, linearly scaled with level. + */ +int cache_size_mapper(int total_levels, int level); + +/** + * Contains the main formatting logic used to format integers. Uses 2's + * complement for hexadecimal numbers. + * @param the value to be formated + * @param if the value should be displayed in hex. If false, displays in + * decimal. + * @param if the value should display. + * @return a string respecting the above parameters. + */ +QString format_toggled_value(int value, bool is_hex, bool is_cleared = false); + +#endif // UTIL_H diff --git a/gui/worker.cc b/gui/worker.cc index 2652fce..0ba364b 100644 --- a/gui/worker.cc +++ b/gui/worker.cc @@ -17,14 +17,13 @@  #include "worker.h"  #include "storage.h" +#include "util.h"  Worker::Worker(QObject *parent) : QObject(parent) {}  Worker::~Worker()  {  	emit finished(); -	qDebug() << "Worker destructor called in thread:" -			 << QThread::currentThread();  	delete this->ct;  } @@ -41,10 +40,6 @@ void Worker::configure(  	this->s.clear();  	this->ct_mutex.lock(); -	if (ways.size() != 0) { -		// TODO optimal proper sizes -		this->size_inc = ((MEM_LINE_SPEC * 0.75) / ways.size()); -	}  	d = new Dram(DRAM_DELAY);  	s = static_cast<Storage *>(d); @@ -53,7 +48,8 @@ void Worker::configure(  	for (i = ways.size(); i > 0; --i) {  		s = static_cast<Storage *>(new Cache( -			s, this->size_inc * (i), ways.at(i - 1), CACHE_DELAY + i)); +			s, cache_size_mapper(ways.size() - 1, i - 1), ways.at(i - 1), +			CACHE_DELAY + i));  		this->s.push_front(s);  	} @@ -69,30 +65,45 @@ void Worker::configure(  		delete old;  	this->ct_mutex.unlock(); -	emit clock_cycles(this->ct->get_clock_cycle(), this->ct->get_pc()); +	this->update();  }  void Worker::runSteps(int steps)  { +	this->ct->run_for(steps); +	this->update(); +} + +void Worker::update() +{  	unsigned long i;  	this->ct_mutex.lock(); -	qDebug() << "Running for " << steps << "steps"; -	this->ct->run_for(steps); - -	// TODO move these to separate functions  	emit register_storage(this->ct->get_gprs()); -	emit storage(this->s.at(0)->view(0, 255), 1); - -	for (i = 1; i < s.size(); ++i) -		emit storage(this->s.at(i - 1)->view(0, 1 << this->size_inc * i), i + 1); +	for (i = 0; i < s.size(); ++i) +		emit storage(this->data_to_QT(this->s.at(i)->get_data()), i + 1);  	emit clock_cycles(this->ct->get_clock_cycle(), this->ct->get_pc()); -	emit if_info(this->if_stage->stage_info()); -	emit id_info(this->id_stage->stage_info()); -	emit ex_info(this->ex_stage->stage_info()); -	emit mm_info(this->mm_stage->stage_info()); -	emit wb_info(this->wb_stage->stage_info()); +	emit if_info(this->if_stage->get_instr()); +	emit id_info(this->id_stage->get_instr()); +	emit ex_info(this->ex_stage->get_instr()); +	emit mm_info(this->mm_stage->get_instr()); +	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 95c81d5..c62f4ed 100644 --- a/gui/worker.h +++ b/gui/worker.h @@ -50,11 +50,6 @@ class Worker : public QObject  	Controller *ct = nullptr;  	QMutex ct_mutex; -	/** -	 * The size each progressive cache level increases by. -	 */ -	unsigned int size_inc; -    public:  	explicit Worker(QObject *parent = nullptr);  	~Worker(); @@ -70,14 +65,28 @@ class Worker : public QObject    signals:  	void clock_cycles(int value, int pc);  	void -	storage(const std::vector<std::array<signed int, LINE_SIZE>> data, int i); +	storage(QVector<QVector<int>> data, int i);  	void register_storage(const std::array<int, GPR_NUM> data); -	void if_info(const std::vector<int> info); -	void id_info(const std::vector<int> info); -	void ex_info(const std::vector<int> info); -	void mm_info(const std::vector<int> info); -	void wb_info(const std::vector<int> info); +	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 finished(); + +  private: +	/** +	 * Converts a vector of arrays into a QVector of QVectors. +	 * @param the original data +	 * @return a less universal version of the same thing +	 */ +	QVector<QVector<int>> +	data_to_QT(std::vector<std::array<signed int, LINE_SIZE>> data); +	/** +	 * Sets the GUI signals to update the storage, clock cycle, and stage +	 * displays. +	 */ +	void update();  };  #endif // WORKER_H diff --git a/inc/accessor.h b/inc/accessor.h deleted file mode 100644 index 67a68b9..0000000 --- a/inc/accessor.h +++ /dev/null @@ -1,35 +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/>. - -#ifndef ACCESSOR_H -#define ACCESSOR_H -#include <iostream> - -enum Accessor { -	IDLE, -	WRITE, -	MEM, -	EXEC, -	DCDE, -	FETCH, -	L1CACHE, -	SIDE, -}; - -std::ostream &operator<<(std::ostream &os, Accessor a); - -#endif /* ACCESSOR_H_INCLUDED */ @@ -41,7 +41,7 @@  	 ((b < 0) && (a < 0) && (a < MAX_INT / b)))  #define MULTIPLICATION_UF_GUARD(a, b) \ -	(b != 0) && \ +	(b != 0) && (b != -1) && \  	(((b > 0) && (a < 0) && (a < (-(MAX_INT)-1) / b)) || \  	 ((b < 0) && (a > 0) && (a > (-(MAX_INT)-1) / b))) @@ -25,12 +25,7 @@  class ID : public Stage  {    public: -	/** -	 * Constructor. -	 * @param The next stage in the pipeline. -	 * @return A newly allocated ID object. -	 */ -	ID(Stage *next); +	using Stage::Stage;  	using Stage::advance;  	/* The following methods are made public so that they may be tested, and are @@ -55,8 +50,6 @@ class ID : public Stage  	 */  	void write_guard(signed int &r); -	std::vector<int> stage_info() override; -    private:  	/**  	 * Helper for `get_instr_fields` @@ -83,7 +76,7 @@ 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, Type &t); +	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); @@ -17,7 +17,6 @@  #ifndef IF_H  #define IF_H -#include "accessor.h"  #include "instrDTO.h"  #include "response.h"  #include "stage.h" @@ -25,17 +24,10 @@  class IF : public Stage  {    public: -	/** -	 * Constructor. -	 * @param The next stage in the pipeline. -	 * @return A newly allocated IF object. -	 */ -	IF(Stage *next); +	using Stage::Stage;  	InstrDTO *advance(Response p) override; -	std::vector<int> stage_info() override; -    private:  	void advance_helper() override;  }; diff --git a/inc/instr.h b/inc/instr.h index 62af09a..98a1f0e 100644 --- a/inc/instr.h +++ b/inc/instr.h @@ -17,7 +17,6 @@  #ifndef INSTR_H  #define INSTR_H -#include <functional>  #include <unordered_map>  enum Mnemonic { @@ -62,13 +61,9 @@ enum Mnemonic {  	NOP,  }; -enum Type { R, I, J, INV }; -  namespace instr  { -// clang-format off -	extern const std::unordered_map<unsigned int, Mnemonic> mnemonic_map; -// clang-format on +extern const std::unordered_map<unsigned int, Mnemonic> mnemonic_map;  } // namespace instr  #endif /* INSTR_H_INCLUDED */ diff --git a/inc/instrDTO.h b/inc/instrDTO.h index d4af389..1402526 100644 --- a/inc/instrDTO.h +++ b/inc/instrDTO.h @@ -17,133 +17,42 @@  #ifndef INSTRDTO_H  #define INSTRDTO_H -#include "accessor.h"  #include "instr.h" -#include <functional> -#include <string> -#include <unordered_map> -class InstrDTO -{ -  public: -	/** -	 * Constructor. -	 */ -	InstrDTO(); -	~InstrDTO() = default; - -	int get_id_cycle(); -	/** -	 * @return instr_bits -	 */ -	signed int get_instr_bits(); -	/** -	 * @return checked_out -	 */ -	signed int get_checked_out(); -	/** -	 * @return s1 -	 */ -	signed int get_s1(); -	/** -	 * @return s2 -	 */ -	signed int get_s2(); -	/** -	 * @return s3 -	 */ -	signed int get_s3(); -	/** -	 * @return the mnemonic of the instruction -	 */ -	Mnemonic get_mnemonic(); -	/** -	 * @return the type of the instruction -	 */ -	Type get_type(); -	/** -	 * @return the program counter at the time this instruction was fetched -	 */ -	unsigned int get_pc(); -	/** -	 * @return 1 if this instruction is invalid, 0 otherwise -	 */ -	int is_squashed(); - -	/** -	 * @param instr_bits -	 */ -	void set_instr_bits(signed int); -	/** -	 * @param checked_out -	 */ -	void set_checked_out(signed int); -	/** -	 * @param s1 -	 */ -	void set_s1(signed int); -	/** -	 * @param s2 -	 */ -	void set_s2(signed int); -	/** -	 * @param s3 -	 */ -	void set_s3(signed int); -	/** -	 * @param the mnemonic of the instruction -	 */ -	void set_mnemonic(Mnemonic); +struct U_INT_TYPE { +	signed int slot_one; +	signed int slot_two; +	signed int slot_three; +}; -	/** -	 * @param the type of the instruction -	 */ -	void set_type(Type); -	/** -	 * @param the program counter at the time this instruction was fetched -	 */ -	void set_pc(unsigned int pc); -	/** -	 * squashes this instruction -	 */ -	void squash(); +struct V_TYPE { +}; -  private: +struct InstrDTO {  	/** -	 * The raw bits encoding the instruction. +	 * If this instruction is squashed or not.  	 */ -	signed int instr_bits; +	unsigned int is_squashed : 1;  	/** -	 * The register, if any, this instruction has checked out. A checked out -	 * register cannot be checked out by another register. This prevents RAW -	 * conflicts. +	 * Optional slot for holding the Instruction Bits  	 */ -	signed int checked_out; +	signed int slot_A;  	/** -	 * Slots in this instruction, for storing temporary registers, immediates, -	 * or other. -	 * Some instruction types may use these differently. -	 * The `oper` function is in charge of knowing how to parse these. +	 * Optional slot for holding PC  	 */ -	signed int s1; -	signed int s2; -	signed int s3; +	signed int slot_B;  	/** -	 * The mnemonic of the operation. +	 * The mnemonic of the instruction.  	 */  	Mnemonic mnemonic;  	/** -	 * Type of the instruction -	 */ -	Type type; -	/** -	 * The PC of the instruction +	 * The register this instruction checks out.  	 */ -	unsigned int pc; -	/** -	 * If this instruction was made dead -	 */ -	unsigned int squashed; +	signed int checked_out; +	union { +		struct U_INT_TYPE integer; +		struct V_TYPE vector; +	} operands;  };  #endif /* INSTRDTO_H_INCLUDED */ @@ -24,12 +24,7 @@  class MM : public Stage  {    public: -	/** -	 * Constructor. -	 * @param The next stage in the pipeline. -	 * @return A newly allocated MM object. -	 */ -	MM(Stage *next); +	using Stage::Stage;  	using Stage::advance;    private: diff --git a/inc/pipe_spec.h b/inc/pipe_spec.h index 0433f23..7d65637 100644 --- a/inc/pipe_spec.h +++ b/inc/pipe_spec.h @@ -40,6 +40,11 @@  #define V_NUM 8  /** + * The size, in 32-bit integers, of a vector register. + */ +#define V_R_LIMIT 8 + +/**   * The number of bits to specify an instruction type   */  #define TYPE_SIZE 2 diff --git a/inc/response.h b/inc/response.h index 501923a..c1f38e7 100644 --- a/inc/response.h +++ b/inc/response.h @@ -21,8 +21,7 @@  enum Response {  	OK, -	WAIT, -	BLOCKED, +	READY,  	STALLED,  }; diff --git a/inc/stage.h b/inc/stage.h index 448c61a..16f1235 100644 --- a/inc/stage.h +++ b/inc/stage.h @@ -17,7 +17,6 @@  #ifndef STAGE_H  #define STAGE_H -#include "accessor.h"  #include "instrDTO.h"  #include "pipe_spec.h"  #include "response.h" @@ -51,11 +50,17 @@ class Stage  	 * ready to accept a new instruction object next cycle.  	 * @return a DTO object containing the next instruction to be processed.  	 * -	 * Must set the status to WAIT when the current instruction is evicted.. +	 * Must set the status to READY when the current instruction is evicted..  	 */  	virtual InstrDTO *advance(Response p); - -	virtual std::vector<int> stage_info(); +	/** +	 * @return the current instruction. +	 */ +	InstrDTO *get_instr(); +	/** +	 * Squashes the pipeline. +	 */ +	void squash();  	/* The following methods are made public so that they may be tested, and are  	 * not to be called from outside classes during standard execution. @@ -74,11 +79,6 @@ class Stage  	void set_condition(CC c, bool v);  	/** -	 * Squashes the pipeline. -	 */ -	void squash(); - -	/**  	 * The set of registers currently checked out.  	 */  	static std::deque<signed int> checked_out; @@ -112,10 +112,6 @@ class Stage  	 */  	signed int dereference_register(signed int v);  	/** -	 * The name of the pipeline stage. -	 */ -	Accessor id; -	/**  	 * The shared pool of general-purpose integer registers.  	 */  	static std::array<signed int, GPR_NUM> gprs; @@ -24,12 +24,7 @@  class WB : public Stage  {    public: -	/** -	 * Constructor. -	 * @param The next stage in the pipeline. -	 * @return A newly allocated WB object. -	 */ -	WB(Stage *next); +	using Stage::Stage;  	using Stage::advance;    private: diff --git a/src/sim/controller.cc b/src/controller.cc index 59fbbb7..8df4b97 100644 --- a/src/sim/controller.cc +++ b/src/controller.cc @@ -31,8 +31,6 @@ Controller::Controller(Stage *stage, Storage *storage, bool is_pipelined)  	this->checked_out = {};  	this->gprs = {0};  	this->gprs.at(2) = MEM_WORDS; // set the stack pointer -	// grant side-door access -	this->id = SIDE;  }  void Controller::run_for(int number) @@ -40,7 +38,7 @@ void Controller::run_for(int number)  	int i;  	for (i = 0; i < number; ++i) {  		try { -			this->advance(WAIT); +			this->advance(READY);  		} catch (HaltException &e) {  			break;  		} diff --git a/src/sim/ex.cc b/src/ex.cc index d345ecf..eac24ff 100644 --- a/src/sim/ex.cc +++ b/src/ex.cc @@ -16,7 +16,6 @@  // along with this program.  If not, see <https://www.gnu.org/licenses/>.  #include "ex.h" -#include "accessor.h"  #include "instrDTO.h"  #include "pipe_spec.h"  #include "response.h" @@ -32,7 +31,6 @@  EX::EX(Stage *stage) : Stage(stage)  { -	this->id = EXEC;  	instr_map = {  		/* R type instructions */ @@ -424,15 +422,15 @@ void EX::advance_helper()  	unsigned int pc;  	Mnemonic m; -	m = this->curr_instr->get_mnemonic(); -	s1 = this->curr_instr->get_s1(); -	s2 = this->curr_instr->get_s2(); -	s3 = this->curr_instr->get_s3(); -	pc = this->curr_instr->get_pc(); +	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); -	this->curr_instr->set_s1(s1); +	this->curr_instr->operands.integer.slot_one = s1;  	this->status = OK;  } @@ -442,7 +440,7 @@ void EX::handle_divide(signed int &s1, signed int s2, bool is_mod)  	this->set_condition(UF, false);  	if (s2 == 0) {  		// handle everything here -		this->curr_instr->set_s1(MAX_INT); +		this->curr_instr->operands.integer.slot_one = MAX_INT;  		this->status = OK;  		throw HaltException();  	} else if ((s1 == -(MAX_INT)-1) && s2 == -1) { diff --git a/src/sim/id.cc b/src/id.cc index cdbaba9..d2a8f02 100644 --- a/src/sim/id.cc +++ b/src/id.cc @@ -16,15 +16,12 @@  // along with this program.  If not, see <https://www.gnu.org/licenses/>.  #include "id.h" -#include "accessor.h"  #include "instr.h"  #include "instrDTO.h"  #include "logger.h"  #include "response.h"  #include "stage.h" -ID::ID(Stage *stage) : Stage(stage) { this->id = DCDE; } -  void ID::split_instr(signed int &raw, unsigned int &type, Mnemonic &m)  {  	unsigned int opcode, opcode_size; @@ -60,7 +57,7 @@ void ID::write_guard(signed int &v)  		// 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->set_checked_out(v); +		this->curr_instr->checked_out = v;  	}  	v = this->dereference_register(v);  } @@ -69,44 +66,39 @@ void ID::advance_helper()  {  	signed int s1, s2, s3;  	Mnemonic m; -	Type t; -	if (curr_instr->get_mnemonic() == NOP) +	if (curr_instr->mnemonic == NOP)  		this->status = OK;  	else { -		s1 = curr_instr->get_instr_bits(); -		get_instr_fields(s1, s2, s3, m, t); +		s1 = curr_instr->slot_A; +		get_instr_fields(s1, s2, s3, m);  		if (this->status == OK) { -			curr_instr->set_s1(s1); -			curr_instr->set_s2(s2); -			curr_instr->set_s3(s3); -			curr_instr->set_mnemonic(m); -			curr_instr->set_type(t); +			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;  		}  	}  }  void ID::get_instr_fields( -	signed int &s1, signed int &s2, signed int &s3, Mnemonic &m, Type &t) +	signed int &s1, signed int &s2, signed int &s3, Mnemonic &m)  {  	unsigned int type;  	this->split_instr(s1, type, m);  	switch (type) {  	case 0b00: -		t = R;  		this->decode_R_type(s1, s2, s3, m);  		break;  	case 0b01: -		t = I;  		this->decode_I_type(s1, s2, s3, m);  		break;  	case 0b10: -		t = J;  		this->decode_J_type(s1, s2, s3, m);  		break;  	case 0b11: -		t = INV; +		m = NOP;  		this->status = OK;  	}  } @@ -219,13 +211,3 @@ void ID::decode_J_type(  	}  } - -std::vector<int> ID::stage_info() -{ -	std::vector<int> info; -	if (this->curr_instr) { -		info.push_back(this->curr_instr->is_squashed()); -		info.push_back(this->curr_instr->get_instr_bits()); -	} -	return info; -} diff --git a/src/sim/if.cc b/src/if.cc index e8e7272..0f622d4 100644 --- a/src/sim/if.cc +++ b/src/if.cc @@ -16,21 +16,18 @@  // along with this program.  If not, see <https://www.gnu.org/licenses/>.  #include "if.h" -#include "accessor.h"  #include "instrDTO.h"  #include "response.h"  #include "stage.h" -IF::IF(Stage *stage) : Stage(stage) { this->id = FETCH; } -  InstrDTO *IF::advance(Response p)  {  	InstrDTO *r = nullptr;  	this->advance_helper(); -	if (this->curr_instr != nullptr && p == WAIT) { +	if (this->curr_instr != nullptr && p == READY) {  		// don't increment PC if the PC was just set by wb -		if (this->curr_instr->is_squashed() != 1) +		if (this->curr_instr->is_squashed != 1)  			++this->pc;  		r = new InstrDTO(*this->curr_instr);  		delete curr_instr; @@ -40,15 +37,6 @@ InstrDTO *IF::advance(Response p)  	return r;  } -std::vector<int> IF::stage_info() { -	std::vector<int> info; -	if(this->curr_instr){ -		info.push_back(this->curr_instr->is_squashed()); -		info.push_back(this->curr_instr->get_instr_bits()); -	} -	return info; -} -  void IF::advance_helper()  {  	Response r; @@ -60,8 +48,11 @@ void IF::advance_helper()  		r = i ? OK : STALLED;  		if (r == OK) {  			this->curr_instr = new InstrDTO(); -			this->curr_instr->set_instr_bits(bits); -			this->curr_instr->set_pc(this->pc); +			this->curr_instr->slot_A = bits; +			this->curr_instr->slot_B = this->pc; +			this->curr_instr->is_squashed = 0; +			this->curr_instr->checked_out = -1; +			this->curr_instr->mnemonic = ADD;  			this->is_empty = false;  		}  	} diff --git a/src/sim/instr.cc b/src/instr.cc index 9bd951b..9bd951b 100644 --- a/src/sim/instr.cc +++ b/src/instr.cc diff --git a/src/logger/logger.cc b/src/logger.cc index a665dcd..a665dcd 100644 --- a/src/logger/logger.cc +++ b/src/logger.cc diff --git a/src/sim/mm.cc b/src/mm.cc index e1057d5..ac77433 100644 --- a/src/sim/mm.cc +++ b/src/mm.cc @@ -16,24 +16,22 @@  // along with this program.  If not, see <https://www.gnu.org/licenses/>.  #include "mm.h" -#include "accessor.h"  #include "instrDTO.h"  #include "response.h"  #include "stage.h" -MM::MM(Stage *stage) : Stage(stage) { this->id = MEM; } -  void MM::advance_helper()  {  	signed int data;  	int i; -	switch (this->curr_instr->get_mnemonic()) { +	switch (this->curr_instr->mnemonic) {  	case LOAD: -		i = this->storage->read_word(this, this->curr_instr->get_s1(), data); +		i = this->storage->read_word( +			this, this->curr_instr->operands.integer.slot_one, data);  		this->status = i ? OK : STALLED;  		if (this->status == OK) { -			this->curr_instr->set_s1(data); +			this->curr_instr->operands.integer.slot_one = data;  		} else  			this->status = STALLED;  		break; @@ -41,7 +39,8 @@ void MM::advance_helper()  	case PUSH:  	case STORE:  		i = this->storage->write_word( -			this, this->curr_instr->get_s2(), this->curr_instr->get_s1()); +			this, this->curr_instr->operands.integer.slot_two, +			this->curr_instr->operands.integer.slot_one);  		this->status = i ? OK : STALLED;  		if (this->status != OK) {  			this->status = STALLED; @@ -49,10 +48,10 @@ void MM::advance_helper()  		break;  	case POP: -		i = this->storage->read_word(this, this->curr_instr->get_s3(), data); +		i = this->storage->read_word(this, this->curr_instr->operands.integer.slot_three, data);  		this->status = i ? OK : STALLED;  		if (this->status == OK) { -			this->curr_instr->set_s3(data); +			this->curr_instr->operands.integer.slot_three = data;  		} else  			this->status = STALLED;  		break; diff --git a/src/utils/response.cc b/src/response.cc index d56419a..7624b82 100644 --- a/src/utils/response.cc +++ b/src/response.cc @@ -20,6 +20,6 @@  std::ostream &operator<<(std::ostream &os, Response r)  { -	const std::string nameR[] = {"OK", "WAIT", "BLOCKED", "STALLED"}; +	const std::string nameR[] = {"OK", "READY", "STALLED"};  	return os << nameR[r];  } diff --git a/src/sim/instrDTO.cc b/src/sim/instrDTO.cc deleted file mode 100644 index 00b6d5f..0000000 --- a/src/sim/instrDTO.cc +++ /dev/null @@ -1,71 +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 "instrDTO.h" -#include "accessor.h" - -InstrDTO::InstrDTO() -{ -	this->instr_bits = 0; -	this->checked_out = -1; -	this->s1 = 0; -	this->s2 = 0; -	this->s3 = 0; -	this->mnemonic = ADD; -	this->type = INV; -	this->pc = 0; -	this->squashed = 0; -} - -signed int InstrDTO::get_instr_bits() { return this->instr_bits; } - -signed int InstrDTO::get_checked_out() { return this->checked_out; } - -signed int InstrDTO::get_s1() { return this->s1; } - -signed int InstrDTO::get_s2() { return this->s2; } - -signed int InstrDTO::get_s3() { return this->s3; } - -Mnemonic InstrDTO::get_mnemonic() { return this->mnemonic; } - -Type InstrDTO::get_type() { return this->type; } - -unsigned int InstrDTO::get_pc() { return this->pc; } - -int InstrDTO::is_squashed() { return this->squashed; } - -void InstrDTO::set_instr_bits(signed int instr) { this->instr_bits = instr; } - -void InstrDTO::set_checked_out(signed int checked_out) -{ -	this->checked_out = checked_out; -} - -void InstrDTO::set_s1(signed int s) { this->s1 = s; } - -void InstrDTO::set_s2(signed int s) { this->s2 = s; } - -void InstrDTO::set_s3(signed int s) { this->s3 = s; } - -void InstrDTO::set_mnemonic(Mnemonic m) { this->mnemonic = m; } - -void InstrDTO::set_type(Type t) { this->type = t; } - -void InstrDTO::set_pc(unsigned int pc) { this->pc = pc; } - -void InstrDTO::squash() { this->squashed = 1; } diff --git a/src/sim/stage.cc b/src/stage.cc index 35c6936..4efe2fe 100644 --- a/src/sim/stage.cc +++ b/src/stage.cc @@ -23,7 +23,7 @@ Stage::Stage(Stage *next)  {  	this->next = next;  	this->curr_instr = nullptr; -	this->status = WAIT; +	this->status = READY;  }  Stage::~Stage() { delete this->next; }; @@ -45,44 +45,27 @@ InstrDTO *Stage::advance(Response p)  	InstrDTO *s = nullptr;  	Response n; -	// std::cout << "advance: " << this->id << ": " << this->curr_instr << "?: " -	// << p << ": " << this->checked_out.size() << ": "; if (curr_instr) -	// 	std::cout << curr_instr->get_mnemonic(); -	// for (long unsigned int i = 0; i < this->checked_out.size(); ++i) -	// 	std::cout << this->checked_out[i] << " "; -	// std::cout << std::endl; -	if (this->curr_instr && this->curr_instr->is_squashed() == 1) +	if (this->curr_instr && this->curr_instr->is_squashed == 1)  		this->status = OK;  	if (this->curr_instr && this->status != OK) {  		this->advance_helper();  	} -	if (this->status == OK && p == WAIT && this->curr_instr) { +	if (this->status == OK && p == READY && this->curr_instr) {  		// mutual consent  		r = new InstrDTO(*this->curr_instr);  		delete curr_instr;  		curr_instr = nullptr; -		this->status = WAIT; +		this->status = READY;  	} -	n = (p != WAIT || this->status != WAIT) ? STALLED : WAIT; +	n = (p != READY || this->status != READY) ? STALLED : READY;  	s = this->next->advance(n);  	if (s)  		this->curr_instr = s;  	return r;  } -std::vector<int> Stage::stage_info() -{ -	std::vector<int> info; -	if (this->curr_instr) { -		info.push_back(this->curr_instr->get_mnemonic()); -		info.push_back(this->curr_instr->is_squashed()); -		info.push_back(this->curr_instr->get_s1()); -		info.push_back(this->curr_instr->get_s2()); -		info.push_back(this->curr_instr->get_s3()); -	} -	return info; -} +InstrDTO *Stage::get_instr() { return this->curr_instr; }  void Stage::set_condition(CC c, bool v)  { @@ -127,7 +110,7 @@ bool Stage::is_checked_out(signed int r)  void Stage::squash()  {  	if (curr_instr) { -		this->curr_instr->squash(); +		this->curr_instr->is_squashed = 1;  		this->status = OK;  	}  	if (this->next) { diff --git a/src/utils/accessor.cc b/src/utils/accessor.cc deleted file mode 100644 index c49a2b2..0000000 --- a/src/utils/accessor.cc +++ /dev/null @@ -1,27 +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 "accessor.h" -#include <iostream> - -std::ostream &operator<<(std::ostream &os, Accessor a) -{ -	const std::string nameA[] = { -		"IDLE", "WRITE", "MEM", "EXEC", "DCDE", "FETCH", "L1CACHE", "SIDE", -	}; -	return os << nameA[a]; -} diff --git a/src/sim/wb.cc b/src/wb.cc index 0348b51..cd24c6a 100644 --- a/src/sim/wb.cc +++ b/src/wb.cc @@ -16,20 +16,16 @@  // along with this program.  If not, see <https://www.gnu.org/licenses/>.  #include "wb.h" -#include "accessor.h"  #include "instrDTO.h"  #include "response.h"  #include "stage.h" -#include <array>  #include <algorithm> - -WB::WB(Stage *stage) : Stage(stage) { this->id = WRITE; } +#include <array>  void WB::advance_helper()  { -	if (this->curr_instr->get_mnemonic() != NOP && -		this->curr_instr->get_type() != INV) { -		if (this->curr_instr->get_checked_out() > 0) +	if (this->curr_instr->mnemonic != NOP) { +		if (this->curr_instr->checked_out > 0)  			this->write_handler();  		else if (this->should_jump())  			this->jump_handler(); @@ -45,34 +41,38 @@ void WB::write_handler()  		throw std::runtime_error("instruction tried to pop a register out of "  								 "an empty queue during writeback."); -	if (this->curr_instr->get_mnemonic() == POP) { +	if (this->curr_instr->mnemonic == POP) {  		// POP performs a second register write  		reg = this->checked_out.front();  		this->checked_out.pop_front(); -		this->store_register(reg, this->curr_instr->get_s3()); +		this->store_register( +			reg, this->curr_instr->operands.integer.slot_three);  	}  	this->checked_out.pop_front(); -	reg = this->curr_instr->get_checked_out(); -	this->store_register(reg, this->curr_instr->get_s1()); - +	reg = this->curr_instr->checked_out; +	this->store_register(reg, this->curr_instr->operands.integer.slot_one);  }  void WB::jump_handler()  { -	if (this->curr_instr->get_s1() > 0) { -		if (this->curr_instr->get_mnemonic() == JAL) -			this->gprs[1] = this->curr_instr->get_pc() + 1;; -		this->pc = this->curr_instr->get_s1(); +	if (this->curr_instr->operands.integer.slot_one > 0) { +		if (this->curr_instr->mnemonic == JAL) +			this->gprs[1] = this->curr_instr->slot_B + 1; +		; +		this->pc = this->curr_instr->operands.integer.slot_one;  		this->checked_out = {};  		this->next->squash();  	}  } +// TODO clean this up...  bool WB::should_jump()  { -	Type t; +	vector<Mnemonic> Js = {JMP, JRL, JAL, BEQ, BGT, BUF, BOF, PUSH, POP, RET}; -	t = this->curr_instr->get_type(); -	return t == J; +	if (find(Js.begin(), Js.end(), this->curr_instr->mnemonic) != Js.end()) +		return true; +	else +		return false;  } diff --git a/tests/controller.cc b/tests/controller.cc index 1d1ddb6..9bc71f6 100644 --- a/tests/controller.cc +++ b/tests/controller.cc @@ -37,7 +37,7 @@ class ControllerPipeFixture  		InstrDTO *i = nullptr;  		int j;  		for (j = 0; j < this->stage_num + 1; ++j) { -			i = this->ct->advance(WAIT); +			i = this->ct->advance(READY);  			REQUIRE(i == nullptr);  		}  	} diff --git a/tests/dum.h b/tests/dum.h new file mode 100644 index 0000000..e60ffad --- /dev/null +++ b/tests/dum.h @@ -0,0 +1,35 @@ +#ifndef DUM_H +#define DUM_H + +#include "instrDTO.h" +#include "response.h" +#include "stage.h" + +/** + * Don't underestimate mocks (the DUM pipe stage). + */ +class DUM : public Stage +{ +  public: +	using Stage::Stage; + +	InstrDTO *advance(Response p) override +	{ +		InstrDTO *r = nullptr; + +		if (this->curr_instr && p == READY) { +			r = new InstrDTO(*this->curr_instr); +			delete this->curr_instr; +			curr_instr = nullptr; +		} + +		return r; +	} + +	void set_curr_instr(InstrDTO *d) { this->curr_instr = d; }; + +  private: +	void advance_helper() override{}; +}; + +#endif /* DUM_H_INCLUDED */ diff --git a/tests/ex.cc b/tests/ex.cc index 400916e..5972182 100644 --- a/tests/ex.cc +++ b/tests/ex.cc @@ -27,15 +27,15 @@ class EXFixture  	execute_instr(signed int s1, signed int s2, signed int s3, Mnemonic m)  	{  		InstrDTO *i = new InstrDTO(); -		i->set_s1(s1); -		i->set_s2(s2); -		i->set_s3(s3); -		i->set_mnemonic(m); +		i->operands.integer.slot_one = s1; +		i->operands.integer.slot_two = s2; +		i->operands.integer.slot_three = s3; +		i->mnemonic = m;  		this->dum->set_curr_instr(i); -		i = this->ct->advance(WAIT); +		i = this->ct->advance(READY);  		REQUIRE(i == nullptr); -		i = this->ct->advance(WAIT); +		i = this->ct->advance(READY);  		REQUIRE(i != nullptr);  		return i; @@ -57,7 +57,7 @@ TEST_CASE_METHOD(EXFixture, "ADD within bounds", "[ex]")  	s1 = 42000, s2 = -41958, s3 = 0;  	i = execute_instr(s1, s2, s3, m); -	CHECK(i->get_s1() == 42); +	CHECK(i->operands.integer.slot_one == 42);  	CHECK(!ct->get_condition(OF));  	CHECK(!ct->get_condition(UF)); @@ -74,7 +74,7 @@ TEST_CASE_METHOD(EXFixture, "ADD overflow", "[ex]")  	s1 = MAX_INT, s2 = 1, s3 = 0;  	i = execute_instr(s1, s2, s3, m); -	CHECK(i->get_s1() == -(MAX_INT)-1); +	CHECK(i->operands.integer.slot_one == -(MAX_INT)-1);  	CHECK(ct->get_condition(OF));  	CHECK(!ct->get_condition(UF)); @@ -91,7 +91,7 @@ TEST_CASE_METHOD(EXFixture, "ADD underflow", "[ex]")  	s1 = -(MAX_INT)-1, s2 = -1, s3 = 0;  	i = execute_instr(s1, s2, s3, m); -	CHECK(i->get_s1() == MAX_INT); +	CHECK(i->operands.integer.slot_one == MAX_INT);  	CHECK(!ct->get_condition(OF));  	CHECK(ct->get_condition(UF)); @@ -108,7 +108,7 @@ TEST_CASE_METHOD(EXFixture, "SUB within bounds", "[ex]")  	s1 = 200, s2 = 131, s3 = 0;  	i = execute_instr(s1, s2, s3, m); -	CHECK(i->get_s1() == 69); +	CHECK(i->operands.integer.slot_one == 69);  	CHECK(!ct->get_condition(OF));  	CHECK(!ct->get_condition(UF)); @@ -125,7 +125,7 @@ TEST_CASE_METHOD(EXFixture, "SUB overflow", "[ex]")  	s1 = MAX_INT, s2 = -1, s3 = 0;  	i = execute_instr(s1, s2, s3, m); -	CHECK(i->get_s1() == -(MAX_INT)-1); +	CHECK(i->operands.integer.slot_one == -(MAX_INT)-1);  	CHECK(ct->get_condition(OF));  	CHECK(!ct->get_condition(UF)); @@ -142,7 +142,7 @@ TEST_CASE_METHOD(EXFixture, "SUB underflow", "[ex]")  	s1 = -(MAX_INT)-1, s2 = 1, s3 = 0;  	i = execute_instr(s1, s2, s3, m); -	CHECK(i->get_s1() == MAX_INT); +	CHECK(i->operands.integer.slot_one == MAX_INT);  	CHECK(!ct->get_condition(OF));  	CHECK(ct->get_condition(UF)); @@ -159,7 +159,7 @@ TEST_CASE_METHOD(EXFixture, "MUL within bounds", "[ex]")  	s1 = 200, s2 = 200, s3 = 0;  	i = execute_instr(s1, s2, s3, m); -	CHECK(i->get_s1() == 40000); +	CHECK(i->operands.integer.slot_one == 40000);  	CHECK(!ct->get_condition(OF));  	CHECK(!ct->get_condition(UF)); @@ -176,7 +176,7 @@ TEST_CASE_METHOD(EXFixture, "MUL overflow", "[ex]")  	s1 = MAX_INT, s2 = MAX_INT, s3 = 0;  	i = execute_instr(s1, s2, s3, m); -	CHECK(i->get_s1() == 1); +	CHECK(i->operands.integer.slot_one == 1);  	CHECK(ct->get_condition(OF));  	CHECK(!ct->get_condition(UF)); @@ -193,7 +193,7 @@ TEST_CASE_METHOD(EXFixture, "MUL underflow", "[ex]")  	s1 = MAX_INT, s2 = -MAX_INT, s3 = 0;  	i = execute_instr(s1, s2, s3, m); -	CHECK(i->get_s1() == -1); +	CHECK(i->operands.integer.slot_one == -1);  	CHECK(!ct->get_condition(OF));  	CHECK(ct->get_condition(UF)); @@ -210,7 +210,7 @@ TEST_CASE_METHOD(EXFixture, "QUOT within bounds", "[ex]")  	s1 = 2043, s2 = 40, s3 = 0;  	i = execute_instr(s1, s2, s3, m); -	CHECK(i->get_s1() == 51); +	CHECK(i->operands.integer.slot_one == 51);  	CHECK(!ct->get_condition(OF));  	CHECK(!ct->get_condition(UF)); @@ -227,7 +227,7 @@ TEST_CASE_METHOD(EXFixture, "QUOT overflow", "[ex]")  	s1 = -(MAX_INT)-1, s2 = -1, s3 = 0;  	i = execute_instr(s1, s2, s3, m); -	CHECK(i->get_s1() == -(MAX_INT)-1); +	CHECK(i->operands.integer.slot_one == -(MAX_INT)-1);  	CHECK(ct->get_condition(OF));  	CHECK(!ct->get_condition(UF)); @@ -258,7 +258,7 @@ TEST_CASE_METHOD(EXFixture, "REM within bounds", "[ex]")  	s1 = 2043, s2 = 40, s3 = 0;  	i = execute_instr(s1, s2, s3, m); -	CHECK(i->get_s1() == 3); +	CHECK(i->operands.integer.slot_one == 3);  	CHECK(!ct->get_condition(OF));  	CHECK(!ct->get_condition(UF)); @@ -289,7 +289,7 @@ TEST_CASE_METHOD(EXFixture, "SFTR within bounds", "[ex]")  	s1 = 1300, s2 = 6, s3 = 0;  	i = execute_instr(s1, s2, s3, m); -	CHECK(i->get_s1() == 20); +	CHECK(i->operands.integer.slot_one == 20);  	CHECK(!ct->get_condition(OF));  	CHECK(!ct->get_condition(UF)); @@ -314,7 +314,7 @@ TEST_CASE_METHOD(EXFixture, "SFTL within bounds", "[ex]")  	s1 = 13, s2 = 6, s3 = 0;  	i = execute_instr(s1, s2, s3, m); -	CHECK(i->get_s1() == 832); +	CHECK(i->operands.integer.slot_one == 832);  	CHECK(!ct->get_condition(OF));  	CHECK(!ct->get_condition(UF)); @@ -339,7 +339,7 @@ TEST_CASE_METHOD(EXFixture, "AND", "[ex]")  	s1 = 1234, s2 = 5678, s3 = 0;  	i = execute_instr(s1, s2, s3, m); -	CHECK(i->get_s1() == 1026); +	CHECK(i->operands.integer.slot_one == 1026);  	CHECK(!ct->get_condition(OF));  	CHECK(!ct->get_condition(UF)); @@ -356,7 +356,7 @@ TEST_CASE_METHOD(EXFixture, "OR", "[ex]")  	s1 = 1234, s2 = 5678, s3 = 0;  	i = execute_instr(s1, s2, s3, m); -	CHECK(i->get_s1() == 5886); +	CHECK(i->operands.integer.slot_one == 5886);  	CHECK(!ct->get_condition(OF));  	CHECK(!ct->get_condition(UF)); @@ -373,7 +373,7 @@ TEST_CASE_METHOD(EXFixture, "NOT", "[ex]")  	s1 = 1234, s2 = -1, s3 = 0;  	i = execute_instr(s1, s2, s3, m); -	CHECK(i->get_s1() == -1235); +	CHECK(i->operands.integer.slot_one == -1235);  	CHECK(!ct->get_condition(OF));  	CHECK(!ct->get_condition(UF)); @@ -390,7 +390,7 @@ TEST_CASE_METHOD(EXFixture, "XOR", "[ex]")  	s1 = 1234, s2 = 5678, s3 = 0;  	i = execute_instr(s1, s2, s3, m); -	CHECK(i->get_s1() == 4860); +	CHECK(i->operands.integer.slot_one == 4860);  	CHECK(!ct->get_condition(OF));  	CHECK(!ct->get_condition(UF)); @@ -456,7 +456,7 @@ TEST_CASE_METHOD(EXFixture, "CMP less", "[ex]")  	i = execute_instr(s1, s2, s3, m);  	// should not be changed -	CHECK(i->get_s1() == -1); +	CHECK(i->operands.integer.slot_one == -1);  	CHECK(!ct->get_condition(EQ));  	CHECK(!ct->get_condition(GT)); @@ -477,7 +477,7 @@ TEST_CASE_METHOD(EXFixture, "CMP equal", "[ex]")  	i = execute_instr(s1, s2, s3, m);  	// should not be changed -	CHECK(i->get_s1() == 20); +	CHECK(i->operands.integer.slot_one == 20);  	CHECK(ct->get_condition(EQ));  	CHECK(!ct->get_condition(GT)); @@ -498,7 +498,7 @@ TEST_CASE_METHOD(EXFixture, "CMP greater", "[ex]")  	i = execute_instr(s1, s2, s3, m);  	// should not be changed -	CHECK(i->get_s1() == 21); +	CHECK(i->operands.integer.slot_one == 21);  	CHECK(!ct->get_condition(EQ));  	CHECK(ct->get_condition(GT)); @@ -531,7 +531,7 @@ TEST_CASE_METHOD(EXFixture, "LOAD", "[ex]")  	s3 = -41958;  	i = execute_instr(s1, s2, s3, m); -	CHECK(i->get_s1() == 42); +	CHECK(i->operands.integer.slot_one == 42);  	CHECK(!ct->get_condition(OF));  	CHECK(!ct->get_condition(UF)); @@ -553,7 +553,7 @@ TEST_CASE_METHOD(EXFixture, "ADDI within bounds", "[ex]")  	s3 = -41958;  	i = execute_instr(s1, s2, s3, m); -	CHECK(i->get_s1() == 42); +	CHECK(i->operands.integer.slot_one == 42);  	CHECK(!ct->get_condition(OF));  	CHECK(!ct->get_condition(UF)); @@ -570,7 +570,7 @@ TEST_CASE_METHOD(EXFixture, "ADDI overflow", "[ex]")  	s1 = MAX_INT, s2 = 0, s3 = 1;  	i = execute_instr(s1, s2, s3, m); -	CHECK(i->get_s1() == -(MAX_INT)-1); +	CHECK(i->operands.integer.slot_one == -(MAX_INT)-1);  	CHECK(ct->get_condition(OF));  	CHECK(!ct->get_condition(UF)); @@ -587,7 +587,7 @@ TEST_CASE_METHOD(EXFixture, "ADDI underflow", "[ex]")  	s1 = -(MAX_INT)-1, s2 = 0, s3 = -1;  	i = execute_instr(s1, s2, s3, m); -	CHECK(i->get_s1() == MAX_INT); +	CHECK(i->operands.integer.slot_one == MAX_INT);  	CHECK(!ct->get_condition(OF));  	CHECK(ct->get_condition(UF)); @@ -604,7 +604,7 @@ TEST_CASE_METHOD(EXFixture, "SUBI within bounds", "[ex]")  	s1 = 200, s2 = 0, s3 = 131;  	i = execute_instr(s1, s2, s3, m); -	CHECK(i->get_s1() == 69); +	CHECK(i->operands.integer.slot_one == 69);  	CHECK(!ct->get_condition(OF));  	CHECK(!ct->get_condition(UF)); @@ -621,7 +621,7 @@ TEST_CASE_METHOD(EXFixture, "SUBI overflow", "[ex]")  	s1 = -(MAX_INT)-1, s2 = 0, s3 = 1;  	i = execute_instr(s1, s2, s3, m); -	CHECK(i->get_s1() == MAX_INT); +	CHECK(i->operands.integer.slot_one == MAX_INT);  	CHECK(!ct->get_condition(OF));  	CHECK(ct->get_condition(UF)); @@ -638,7 +638,7 @@ TEST_CASE_METHOD(EXFixture, "SUBI underflow", "[ex]")  	s1 = MAX_INT, s2 = 0, s3 = -1;  	i = execute_instr(s1, s2, s3, m); -	CHECK(i->get_s1() == -(MAX_INT)-1); +	CHECK(i->operands.integer.slot_one == -(MAX_INT)-1);  	CHECK(ct->get_condition(OF));  	CHECK(!ct->get_condition(UF)); @@ -655,7 +655,7 @@ TEST_CASE_METHOD(EXFixture, "SFTRI within bounds", "[ex]")  	s1 = 1300, s2 = 0, s3 = 6;  	i = execute_instr(s1, s2, s3, m); -	CHECK(i->get_s1() == 20); +	CHECK(i->operands.integer.slot_one == 20);  	CHECK(!ct->get_condition(OF));  	CHECK(!ct->get_condition(UF)); @@ -680,7 +680,7 @@ TEST_CASE_METHOD(EXFixture, "SFTLI within bounds", "[ex]")  	s1 = 13, s2 = 0, s3 = 6;  	i = execute_instr(s1, s2, s3, m); -	CHECK(i->get_s1() == 832); +	CHECK(i->operands.integer.slot_one == 832);  	CHECK(!ct->get_condition(OF));  	CHECK(!ct->get_condition(UF)); @@ -705,7 +705,7 @@ TEST_CASE_METHOD(EXFixture, "ANDI", "[ex]")  	s1 = 1234, s2 = 0, s3 = 5678;  	i = execute_instr(s1, s2, s3, m); -	CHECK(i->get_s1() == 1026); +	CHECK(i->operands.integer.slot_one == 1026);  	CHECK(!ct->get_condition(OF));  	CHECK(!ct->get_condition(UF)); @@ -722,7 +722,7 @@ TEST_CASE_METHOD(EXFixture, "ORI", "[ex]")  	s1 = 1234, s2 = 0, s3 = 5678;  	i = execute_instr(s1, s2, s3, m); -	CHECK(i->get_s1() == 5886); +	CHECK(i->operands.integer.slot_one == 5886);  	CHECK(!ct->get_condition(OF));  	CHECK(!ct->get_condition(UF)); @@ -739,7 +739,7 @@ TEST_CASE_METHOD(EXFixture, "XORI", "[ex]")  	s1 = 1234, s2 = 0, s3 = 5678;  	i = execute_instr(s1, s2, s3, m); -	CHECK(i->get_s1() == 4860); +	CHECK(i->operands.integer.slot_one == 4860);  	CHECK(!ct->get_condition(OF));  	CHECK(!ct->get_condition(UF)); @@ -756,7 +756,7 @@ TEST_CASE_METHOD(EXFixture, "STORE", "[ex]")  	s1 = 42000, s2 = 0, s3 = -41958;  	i = execute_instr(s1, s2, s3, m); -	CHECK(i->get_s1() == 42); +	CHECK(i->operands.integer.slot_one == 42);  	CHECK(!ct->get_condition(OF));  	CHECK(!ct->get_condition(UF)); @@ -777,7 +777,7 @@ TEST_CASE_METHOD(EXFixture, "JMP", "[ex]")  	s1 = 42000, s2 = -41958, s3 = 0;  	i = execute_instr(s1, s2, s3, m); -	CHECK(i->get_s1() == 42); +	CHECK(i->operands.integer.slot_one == 42);  	CHECK(!ct->get_condition(OF));  	CHECK(!ct->get_condition(UF)); @@ -794,7 +794,7 @@ TEST_CASE_METHOD(EXFixture, "JRL", "[ex]")  	s1 = 100, s2 = 69, s3 = 0;  	i = execute_instr(s1, s2, s3, m); -	CHECK(i->get_s1() == 69); +	CHECK(i->operands.integer.slot_one == 69);  	CHECK(!ct->get_condition(OF));  	CHECK(!ct->get_condition(UF)); @@ -811,7 +811,7 @@ TEST_CASE_METHOD(EXFixture, "JAL", "[ex]")  	s1 = 42000, s2 = -41958, s3 = 0;  	i = execute_instr(s1, s2, s3, m); -	CHECK(i->get_s1() == 42); +	CHECK(i->operands.integer.slot_one == 42);  	CHECK(!ct->get_condition(OF));  	CHECK(!ct->get_condition(UF)); @@ -828,7 +828,7 @@ TEST_CASE_METHOD(EXFixture, "BEQ no cond", "[ex]")  	s1 = 100, s2 = 50, s3 = 0;  	i = execute_instr(s1, s2, s3, m); -	CHECK(i->get_s1() == -1); +	CHECK(i->operands.integer.slot_one == -1);  	delete i;  } @@ -844,7 +844,7 @@ TEST_CASE_METHOD(EXFixture, "BEQ", "[ex]")  	this->ct->set_condition(EQ, true);  	i = execute_instr(s1, s2, s3, m); -	CHECK(i->get_s1() == 50); +	CHECK(i->operands.integer.slot_one == 50);  	delete i;  } @@ -859,7 +859,7 @@ TEST_CASE_METHOD(EXFixture, "BGT no cond", "[ex]")  	s1 = 100, s2 = 50, s3 = 0;  	i = execute_instr(s1, s2, s3, m); -	CHECK(i->get_s1() == -1); +	CHECK(i->operands.integer.slot_one == -1);  	delete i;  } @@ -875,7 +875,7 @@ TEST_CASE_METHOD(EXFixture, "BGT", "[ex]")  	this->ct->set_condition(GT, true);  	i = execute_instr(s1, s2, s3, m); -	CHECK(i->get_s1() == 50); +	CHECK(i->operands.integer.slot_one == 50);  	delete i;  } @@ -890,7 +890,7 @@ TEST_CASE_METHOD(EXFixture, "BUF no cond", "[ex]")  	s1 = 100, s2 = -42027, s3 = 0;  	i = execute_instr(s1, s2, s3, m); -	CHECK(i->get_s1() == -1); +	CHECK(i->operands.integer.slot_one == -1);  	delete i;  } @@ -906,7 +906,7 @@ TEST_CASE_METHOD(EXFixture, "BUF", "[ex]")  	this->ct->set_condition(UF, true);  	i = execute_instr(s1, s2, s3, m); -	CHECK(i->get_s1() == 50); +	CHECK(i->operands.integer.slot_one == 50);  	delete i;  } @@ -921,7 +921,7 @@ TEST_CASE_METHOD(EXFixture, "BOF no cond", "[ex]")  	s1 = 100, s2 = -42027, s3 = 0;  	i = execute_instr(s1, s2, s3, m); -	CHECK(i->get_s1() == -1); +	CHECK(i->operands.integer.slot_one == -1);  	delete i;  } @@ -937,7 +937,7 @@ TEST_CASE_METHOD(EXFixture, "BOF", "[ex]")  	this->ct->set_condition(OF, true);  	i = execute_instr(s1, s2, s3, m); -	CHECK(i->get_s1() == 50); +	CHECK(i->operands.integer.slot_one == 50);  	delete i;  } diff --git a/tests/id.cc b/tests/id.cc index 321c013..a81e967 100644 --- a/tests/id.cc +++ b/tests/id.cc @@ -26,12 +26,12 @@ class IDFixture  	InstrDTO *decode_bits(signed int raw)  	{  		InstrDTO *i = new InstrDTO(); -		i->set_instr_bits(raw); +		i->slot_A = raw;  		this->dum->set_curr_instr(i); -		i = this->ct->advance(WAIT); +		i = this->ct->advance(READY);  		REQUIRE(i == nullptr); -		i = this->ct->advance(WAIT); +		i = this->ct->advance(READY);  		REQUIRE(i != nullptr);  		return i; @@ -92,7 +92,7 @@ TEST_CASE_METHOD(IDFixture, "Parse invalid type", "[id]")  	t = this->encode_R_type(0b0, 0b1, 0b10, 0b11, 0b11);  	i = this->decode_bits(t); -	CHECK(i->get_mnemonic() == NOP); +	CHECK(i->mnemonic == NOP);  	delete i;  } @@ -105,10 +105,10 @@ TEST_CASE_METHOD(IDFixture, "Parse arbitrary r-type # one", "[id]")  	t = this->encode_R_type(0b101, 0b110, 0b111, 0b11, 0b0);  	i = this->decode_bits(t); -	CHECK(i->get_s1() == 0x00000000); // registers are empty -	CHECK(i->get_s2() == 0x00000000); -	CHECK(i->get_s3() == 0x00000000); -	CHECK(i->get_mnemonic() == MUL); +	CHECK(i->operands.integer.slot_one == 0x00000000); // registers are empty +	CHECK(i->operands.integer.slot_two == 0x00000000); +	CHECK(i->operands.integer.slot_three == 0x00000000); +	CHECK(i->mnemonic == MUL);  	delete i;  } @@ -121,10 +121,10 @@ TEST_CASE_METHOD(IDFixture, "Parse arbitrary r-type # two", "[id]")  	t = this->encode_R_type(0b10000, 0b01000, 0b00100, 0b10, 0b0);  	i = this->decode_bits(t); -	CHECK(i->get_s1() == 0x00000000); // registers are empty -	CHECK(i->get_s2() == 0x00000000); -	CHECK(i->get_s3() == 0x00000000); -	CHECK(i->get_mnemonic() == SUB); +	CHECK(i->operands.integer.slot_one == 0x00000000); // registers are empty +	CHECK(i->operands.integer.slot_two == 0x00000000); +	CHECK(i->operands.integer.slot_three == 0x00000000); +	CHECK(i->mnemonic == SUB);  	delete i;  } @@ -137,10 +137,10 @@ TEST_CASE_METHOD(IDFixture, "Parse arbitrary i-type # one", "[id]")  	t = this->encode_I_type(0xF, 0b101, 0b110, 0b0111, 0b1);  	i = this->decode_bits(t); -	CHECK(i->get_s1() == 0x00000000); // registers are empty -	CHECK(i->get_s2() == 0x00000000); -	CHECK(i->get_s3() == 0xF); -	CHECK(i->get_mnemonic() == ANDI); +	CHECK(i->operands.integer.slot_one == 0x00000000); // registers are empty +	CHECK(i->operands.integer.slot_two == 0x00000000); +	CHECK(i->operands.integer.slot_three == 0xF); +	CHECK(i->mnemonic == ANDI);  	delete i;  } @@ -153,10 +153,10 @@ TEST_CASE_METHOD(IDFixture, "Parse arbitrary i-type # two", "[id]")  	t = this->encode_I_type(0xCC, 0b101, 0b110, 0b1011, 0b1);  	i = this->decode_bits(t); -	CHECK(i->get_s1() == 0x00000000); // registers are empty -	CHECK(i->get_s2() == 0x00000000); -	CHECK(i->get_s3() == 0xCC); -	CHECK(i->get_mnemonic() == STOREV); +	CHECK(i->operands.integer.slot_one == 0x00000000); // registers are empty +	CHECK(i->operands.integer.slot_two == 0x00000000); +	CHECK(i->operands.integer.slot_three == 0xCC); +	CHECK(i->mnemonic == STOREV);  	delete i;  } @@ -169,9 +169,9 @@ TEST_CASE_METHOD(IDFixture, "Parse arbitrary j-type # one", "[id]")  	t = this->encode_J_type(0x3456, 0b10101, 0b0111, 0b10);  	i = this->decode_bits(t); -	CHECK(i->get_s1() == 0x00000000); // registers are empty -	CHECK(i->get_s2() == 0x3456); -	CHECK(i->get_mnemonic() == BOF); +	CHECK(i->operands.integer.slot_one == 0x00000000); // registers are empty +	CHECK(i->operands.integer.slot_two == 0x3456); +	CHECK(i->mnemonic == BOF);  	delete i;  } @@ -185,9 +185,9 @@ TEST_CASE_METHOD(IDFixture, "Parse arbitrary j-type # two", "[id]")  	i = this->decode_bits(t);  	t = 0xFFFBBCCF; -	CHECK(i->get_s1() == 0x00000000); // registers are empty -	CHECK(i->get_s2() == t); -	CHECK(i->get_mnemonic() == JAL); +	CHECK(i->operands.integer.slot_one == 0x00000000); // registers are empty +	CHECK(i->operands.integer.slot_two == t); +	CHECK(i->mnemonic == JAL);  	delete i;  } diff --git a/tests/if.cc b/tests/if.cc index 8b30d0e..e2a7dbe 100644 --- a/tests/if.cc +++ b/tests/if.cc @@ -36,7 +36,7 @@ class IFFixture  		int i;  		for (i = 0; i < this->m_delay + 1; ++i) { -			r = this->ct->advance(WAIT); +			r = this->ct->advance(READY);  			// check response  			CHECK(r == nullptr);  		} @@ -52,11 +52,11 @@ class IFFixture  		int i;  		for (i = 0; i < this->c_delay; ++i) { -			r = this->ct->advance(WAIT); +			r = this->ct->advance(READY);  			// check response  			REQUIRE(r == nullptr);  		} -		r = this->ct->advance(WAIT); +		r = this->ct->advance(READY);  		// check response  		REQUIRE(r != nullptr);  		return r; @@ -75,7 +75,7 @@ TEST_CASE_METHOD(IFFixture, "fetch returns single instuction", "[if_pipe]")  	InstrDTO *i;  	i = this->fetch_through(); -	REQUIRE(i->get_instr_bits() == this->p[0]); +	REQUIRE(i->slot_A == this->p[0]);  	delete i;  } @@ -88,13 +88,13 @@ TEST_CASE_METHOD(IFFixture, "fetch returns two instuctions", "[if_pipe]")  	expected_cycles = this->m_delay + this->c_delay + 2;  	i = this->fetch_through(); -	REQUIRE(i->get_instr_bits() == this->p[0]); +	REQUIRE(i->slot_A == this->p[0]);  	delete i;  	expected_cycles += this->c_delay + 1;  	i = this->fetch_cache(); -	REQUIRE(i->get_instr_bits() == this->p[1]); +	REQUIRE(i->slot_A == this->p[1]);  	delete i;  } @@ -122,9 +122,9 @@ TEST_CASE_METHOD(IFFixture, "fetch waits with old instruction", "[if_pipe]")  		REQUIRE(i != nullptr);  	} -	i = this->ct->advance(WAIT); +	i = this->ct->advance(READY);  	REQUIRE(i != nullptr); -	REQUIRE(i->get_instr_bits() == this->p[0]); +	REQUIRE(i->slot_A == this->p[0]);  	delete i;  }  | 
