aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--qtmips_gui/coreview.cpp36
-rw-r--r--qtmips_gui/coreview.h13
-rw-r--r--qtmips_gui/mainwindow.cpp83
-rw-r--r--qtmips_gui/mainwindow.h11
-rw-r--r--qtmips_gui/registersdock.cpp11
-rw-r--r--qtmips_gui/registersdock.h3
-rw-r--r--qtmips_machine/qtmipsmachine.cpp67
-rw-r--r--qtmips_machine/qtmipsmachine.h20
8 files changed, 188 insertions, 56 deletions
diff --git a/qtmips_gui/coreview.cpp b/qtmips_gui/coreview.cpp
index b7c17fc..f7cc416 100644
--- a/qtmips_gui/coreview.cpp
+++ b/qtmips_gui/coreview.cpp
@@ -1,14 +1,23 @@
#include "coreview.h"
-CoreView::CoreView(QWidget *parent, machine::QtMipsMachine *machine) : QGraphicsView(parent) {
+CoreView::CoreView(QWidget *parent) : QGraphicsView(parent) {
setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
setRenderHints(QPainter::Antialiasing | QPainter::SmoothPixmapTransform);
+ // TODO fitInView doesn't work as I want so reimplement or do something with it
+ //fitInView(0, 0, 201, 201, Qt::KeepAspectRatioByExpanding);
+}
+
+void CoreView::resizeEvent(QResizeEvent *event) {
+ // fitInView(0, 0, 201, 201, Qt::KeepAspectRatioByExpanding);
+}
+
+CoreViewScene::CoreViewScene(CoreView *view, machine::QtMipsMachine *machine) : QGraphicsScene(view) {
this->machine = machine;
// Identification cross
- scene.addLine(400, 0, 400, 800);
- scene.addLine(0, 400, 800, 400);
+ addLine(400, 0, 400, 800);
+ addLine(0, 400, 800, 400);
pc = new coreview::ProgramCounter(machine);
alu = new coreview::Alu();
@@ -17,22 +26,19 @@ CoreView::CoreView(QWidget *parent, machine::QtMipsMachine *machine) : QGraphics
pc2pc = new coreview::Connection(pc_multiplexer->connector_out(), pc->connector_in());
- scene.addItem(pc);
- scene.addItem(alu);
- scene.addItem(pc_multiplexer);
- scene.addItem(testlatch);
- scene.addItem(pc2pc);
+ addItem(pc);
+ addItem(alu);
+ addItem(pc_multiplexer);
+ addItem(testlatch);
+ addItem(pc2pc);
pc->setPos(100,100);
alu->setPos(200, 100);
pc_multiplexer->setPos(60, 100);
pc_multiplexer->set(2);
- setScene(&scene);
- // TODO fitInView doesn't work as I want so reimplement or do something with it
- //fitInView(0, 0, 201, 201, Qt::KeepAspectRatioByExpanding);
-}
-
-void CoreView::resizeEvent(QResizeEvent *event) {
- // fitInView(0, 0, 201, 201, Qt::KeepAspectRatioByExpanding);
+ QGraphicsScene *old_scene = view->scene();
+ view->setScene(this);
+ if (old_scene != nullptr)
+ delete old_scene;
}
diff --git a/qtmips_gui/coreview.h b/qtmips_gui/coreview.h
index 8c0701e..fddcafe 100644
--- a/qtmips_gui/coreview.h
+++ b/qtmips_gui/coreview.h
@@ -11,14 +11,19 @@
#include "coreview/alu.h"
class CoreView : public QGraphicsView {
- Q_OBJECT
public:
- CoreView(QWidget *parent, machine::QtMipsMachine *machine);
+ CoreView(QWidget *parent);
private:
void resizeEvent(QResizeEvent *event);
+};
+
+class CoreViewScene : public QGraphicsScene {
+ Q_OBJECT
+public:
+ CoreViewScene(CoreView *view, machine::QtMipsMachine *machine);
- QGraphicsScene scene;
+private:
machine::QtMipsMachine *machine;
coreview::ProgramCounter *pc;
@@ -31,6 +36,6 @@ private:
#else
class CoreView;
-class CoreViewBlock;
+class CoreViewScene;
#endif // COREVIEW_H
diff --git a/qtmips_gui/mainwindow.cpp b/qtmips_gui/mainwindow.cpp
index 6a507fa..9e1902a 100644
--- a/qtmips_gui/mainwindow.cpp
+++ b/qtmips_gui/mainwindow.cpp
@@ -1,13 +1,17 @@
#include "mainwindow.h"
MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent) {
+ machine = nullptr;
+ corescene = nullptr;
settings = new QSettings("CTU", "QtMips");
- coreview = nullptr;
ui = new Ui::MainWindow();
ui->setupUi(this);
setWindowTitle("QtMips");
+ // Prepare empty core view
+ coreview = new CoreView(this);
+ this->setCentralWidget(coreview);
// Create/prepare other widgets
ndialog = new NewDialog(this, settings);
cache_content = new CacheContentDock(this);
@@ -32,6 +36,8 @@ MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent) {
MainWindow::~MainWindow() {
settings->sync();
delete settings;
+ if (corescene != nullptr)
+ delete corescene;
if (coreview != nullptr)
delete coreview;
delete ndialog;
@@ -49,22 +55,34 @@ void MainWindow::start() {
}
void MainWindow::create_core(machine::MachineConfig *config) {
+ // Remove old machine
+ if (machine != nullptr)
+ delete machine;
// Create machine
machine = new machine::QtMipsMachine(config);
// Create machine view
- coreview = new CoreView(this, machine);
- this->setCentralWidget(coreview);
+ corescene = new CoreViewScene(coreview, machine);
- machine->set_speed(1000); // Set default speed to 1 sec
+ //machine->set_speed(1000); // Set default speed to 1 sec
+ machine->set_speed(0);
- // Connect machine signals
+ // Connect machine signals and slots
connect(ui->actionRun, SIGNAL(triggered(bool)), machine, SLOT(play()));
connect(ui->actionPause, SIGNAL(triggered(bool)), machine, SLOT(pause()));
connect(ui->actionStep, SIGNAL(triggered(bool)), machine, SLOT(step()));
connect(ui->actionRestart, SIGNAL(triggered(bool)), machine, SLOT(restart()));
+ connect(machine, SIGNAL(status_change(machine::QtMipsMachine::Status)), this, SLOT(machine_status(machine::QtMipsMachine::Status)));
+ connect(machine, SIGNAL(program_exit()), this, SLOT(machine_exit()));
+ connect(machine, SIGNAL(program_trap(machine::QtMipsException&)), this, SLOT(machine_trap(machine::QtMipsException&)));
// Setup docks
registers->setup(machine);
+ // Set status to ready
+ machine_status(machine::QtMipsMachine::ST_READY);
+}
+
+bool MainWindow::configured() {
+ return (machine != nullptr);
}
void MainWindow::new_machine() {
@@ -83,15 +101,10 @@ void MainWindow::show_registers() {
show_dockwidget(registers);
}
-bool MainWindow::configured() {
- return (machine != nullptr);
-}
-
void MainWindow::closeEvent(QCloseEvent *event) {
settings->setValue("windowGeometry", saveGeometry());
settings->setValue("windowState", saveState());
settings->sync();
- QMainWindow::closeEvent(event);
}
void MainWindow::show_dockwidget(QDockWidget *dw) {
@@ -103,3 +116,53 @@ void MainWindow::show_dockwidget(QDockWidget *dw) {
dw->setFocus();
}
}
+
+void MainWindow::machine_status(enum machine::QtMipsMachine::Status st) {
+ QString status;
+ switch (st) {
+ case machine::QtMipsMachine::ST_READY:
+ ui->actionPause->setEnabled(false);
+ ui->actionRun->setEnabled(true);
+ ui->actionStep->setEnabled(true);
+ status = "Ready";
+ break;
+ case machine::QtMipsMachine::ST_RUNNING:
+ ui->actionPause->setEnabled(true);
+ ui->actionRun->setEnabled(false);
+ ui->actionStep->setEnabled(false);
+ status = "Running";
+ break;
+ case machine::QtMipsMachine::ST_BUSY:
+ // Busy is not interesting (in such case we should just be running
+ return;
+ case machine::QtMipsMachine::ST_EXIT:
+ // machine_exit is called so we disable controls in that
+ status = "Exited";
+ break;
+ case machine::QtMipsMachine::ST_TRAPPED:
+ // machine_trap is called so we disable controls in that
+ status = "Trapped";
+ break;
+ default:
+ status = "Unknown";
+ break;
+ }
+ ui->statusBar->showMessage(status);
+}
+
+void MainWindow::machine_exit() {
+ ui->actionPause->setEnabled(false);
+ ui->actionRun->setEnabled(false);
+ ui->actionStep->setEnabled(false);
+}
+
+void MainWindow::machine_trap(machine::QtMipsException &e) {
+ machine_exit();
+
+ QMessageBox msg(this);
+ msg.setText(e.msg(false));
+ msg.setIcon(QMessageBox::Critical);
+ msg.setDetailedText(e.msg(true));
+ msg.setWindowTitle("Machine trapped");
+ msg.exec();
+}
diff --git a/qtmips_gui/mainwindow.h b/qtmips_gui/mainwindow.h
index 8b9e3e7..6f588ac 100644
--- a/qtmips_gui/mainwindow.h
+++ b/qtmips_gui/mainwindow.h
@@ -23,14 +23,18 @@ public:
void start();
void create_core(machine::MachineConfig *config);
+ bool configured();
+
public slots:
+ // Actions signals
void new_machine();
-
void show_cache_content();
void show_cache_statictics();
void show_registers();
-
- bool configured();
+ // Machine signals
+ void machine_status(enum machine::QtMipsMachine::Status st);
+ void machine_exit();
+ void machine_trap(machine::QtMipsException &e);
protected:
void closeEvent(QCloseEvent *event);
@@ -41,6 +45,7 @@ private:
NewDialog *ndialog;
CoreView *coreview;
+ CoreViewScene *corescene;
CacheContentDock *cache_content;
CacheStatisticsDock *cache_statictics;
diff --git a/qtmips_gui/registersdock.cpp b/qtmips_gui/registersdock.cpp
index 20eb9e4..5d965ca 100644
--- a/qtmips_gui/registersdock.cpp
+++ b/qtmips_gui/registersdock.cpp
@@ -3,8 +3,10 @@
RegistersDock::RegistersDock(QWidget *parent) : QDockWidget(parent) {
regs = nullptr;
- widg = new QScrollArea(this);
+ scrollarea = new QScrollArea(this);
+ widg = new QWidget(scrollarea);
layout = new QFormLayout(widg);
+ layout->setSizeConstraint(QLayout::SetMinAndMaxSize);
#define INIT(X, LABEL) do{ \
X = new QLabel(widg); \
@@ -17,10 +19,13 @@ RegistersDock::RegistersDock(QWidget *parent) : QDockWidget(parent) {
INIT(gp[i], QString("GP") + QString::number(i) + QString(" ($") + QString::number(i) + QString("):"));
INIT(lo, "LO:");
INIT(hi, "HI:");
-
#undef INIT
+ widg->setLayout(layout);
+ scrollarea->setWidget(widg);
- setWidget(widg);
+ setWidget(scrollarea);
+ setObjectName("Registers");
+ setWindowTitle("Registers");
}
RegistersDock::~RegistersDock() {
diff --git a/qtmips_gui/registersdock.h b/qtmips_gui/registersdock.h
index 654983e..3504608 100644
--- a/qtmips_gui/registersdock.h
+++ b/qtmips_gui/registersdock.h
@@ -24,7 +24,8 @@ private slots:
private:
const machine::Registers *regs;
- QScrollArea *widg;
+ QWidget *widg;
+ QScrollArea *scrollarea;
QFormLayout *layout;
QLabel *pc;
diff --git a/qtmips_machine/qtmipsmachine.cpp b/qtmips_machine/qtmipsmachine.cpp
index 8d1a46a..102dff0 100644
--- a/qtmips_machine/qtmipsmachine.cpp
+++ b/qtmips_machine/qtmipsmachine.cpp
@@ -4,14 +4,15 @@
using namespace machine;
QtMipsMachine::QtMipsMachine(const MachineConfig &cc) {
+ stat = ST_READY;
+
ProgramLoader program(cc.elf());
+ mem_program_only = new Memory();
+ program.to_memory(mem_program_only);
+ program_end = program.end();
regs = new Registers();
- mem = new Memory();
-
- program.to_memory(mem);
- program_end = program.end();
- program_ended = false;
+ mem = new Memory(*mem_program_only);
MemoryAccess *coremem;
switch (cc.cache()) {
@@ -28,8 +29,11 @@ QtMipsMachine::QtMipsMachine(const MachineConfig &cc) {
throw QTMIPS_EXCEPTION(Sanity, "Trying to configure unknown cache type", "");
}
- // TODO pipelined
- cr = new CoreSingle(regs, coremem);
+ cr_pipelined = cc.pipelined();
+ if (cc.pipelined())
+ cr = new CorePipelined(regs, coremem);
+ else
+ cr = new CoreSingle(regs, coremem);
run_speed = 1;
run_t = new QTimer(this);
@@ -58,32 +62,59 @@ const Core *QtMipsMachine::core() {
return cr;
}
+enum QtMipsMachine::Status QtMipsMachine::status() {
+ return stat;
+}
+
+bool QtMipsMachine::exited() {
+ return stat == ST_EXIT || stat == ST_TRAPPED;
+}
+
+// We don't allow to call control methods when machine exited or if it's busy
+// We rather silently fail.
+// TODO wouldn't be error better?
+#define CTL_GUARD do { if (exited() || stat == ST_BUSY) return; } while(false)
+
void QtMipsMachine::play() {
- if (program_ended)
- return;
+ CTL_GUARD;
+ set_status(ST_RUNNING);
run_t->start(run_speed);
}
void QtMipsMachine::pause() {
- if (program_ended)
- return;
+ CTL_GUARD;
+ set_status(ST_READY);
run_t->stop();
}
void QtMipsMachine::step() {
- if (program_ended) // Ignore if program ended
- return;
+ CTL_GUARD;
+ enum Status stat_prev = stat;
+ set_status(ST_BUSY);
emit tick();
- cr->step();
+ try {
+ cr->step();
+ } catch (QtMipsException e) {
+ run_t->stop();
+ set_status(ST_TRAPPED);
+ emit program_trap(e);
+ return;
+ }
if (regs->read_pc() >= program_end) {
- program_ended = true;
run_t->stop();
+ set_status(ST_EXIT);
emit program_exit();
- }
+ } else
+ set_status(stat_prev);
}
void QtMipsMachine::restart() {
- if (!program_ended)
- run_t->stop(); // Stop timer if program is still running
// TODO
}
+
+void QtMipsMachine::set_status(enum Status st) {
+ bool change = st != stat;
+ stat = st;
+ if (change)
+ emit status_change(st);
+}
diff --git a/qtmips_machine/qtmipsmachine.h b/qtmips_machine/qtmipsmachine.h
index 28abfa6..d2e60de 100644
--- a/qtmips_machine/qtmipsmachine.h
+++ b/qtmips_machine/qtmipsmachine.h
@@ -25,6 +25,16 @@ public:
const Cache *cache();
const Core *core();
+ enum Status {
+ ST_READY, // Machine is ready to be started or step to be called
+ ST_RUNNING, // Machine is running
+ ST_BUSY, // Machine is calculating step
+ ST_EXIT, // Machine exited
+ ST_TRAPPED // Machine exited with failure
+ };
+ enum Status status();
+ bool exited();
+
public slots:
// TODO handle speed
void play();
@@ -34,19 +44,25 @@ public slots:
signals:
void program_exit();
+ void program_trap(machine::QtMipsException &e);
+ void status_change(enum machine::QtMipsMachine::Status st);
void tick(); // Time tick
private:
Registers *regs;
- Memory *mem;
+ Memory *mem, *mem_program_only;
Cache *cch;
Core *cr;
+ bool cr_pipelined;
+
unsigned run_speed;
QTimer *run_t;
std::uint32_t program_end;
- bool program_ended;
+ enum Status stat;
+
+ void set_status(enum Status st);
};
}