aboutsummaryrefslogtreecommitdiff
path: root/qtmips_machine
diff options
context:
space:
mode:
Diffstat (limited to 'qtmips_machine')
-rw-r--r--qtmips_machine/qtmipsmachine.cpp67
-rw-r--r--qtmips_machine/qtmipsmachine.h20
2 files changed, 67 insertions, 20 deletions
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);
};
}