Handle ecalls during 'run' without closing the run dialog
MODIFY
src/pipeline.cpp
src/pipeline.cpp
@@ -882,6 +882,9 @@ void Pipeline::setStagePCS() {
void Pipeline::abort() {
m_abort = true; // async abort of run()
}
+void Pipeline::clearAbort() {
+ m_abort = false;
+}
int Pipeline::run() {
m_running = true;
@@ -891,6 +894,8 @@ int Pipeline::run() {
if (m_abort) {
restart();
return 1;
+ } else if (m_ecallArg != ECALL::none) {
+ return 1;
} else {
return 0;
}

MODIFY
src/pipeline.h
src/pipeline.h
@@ -25,6 +25,7 @@ public:
int step();
int run();
void abort();
+ void clearAbort();
bool isRunning() const { return m_running; }
// Pointers for GUI

MODIFY
src/processortab.cpp
src/processortab.cpp
@@ -134,17 +134,6 @@ void ProcessorTab::on_run_clicked() {
m_ui->step->setEnabled(false);
m_ui->start->setEnabled(false);
m_ui->run->setEnabled(false);
- } else {
- const auto ecall_val = pipeline->checkEcall(true);
- if (ecall_val.first != Pipeline::ECALL::none) {
- // An ECALL has been invoked during continuous running. Handle ecall and continue to run
- if (handleEcall(ecall_val)) {
- on_run_clicked();
- }
- } else {
- m_ui->table->setEnabled(true);
- emit update();
- }
}
}
}

MODIFY
src/processortab.h
src/processortab.h
@@ -17,6 +17,7 @@ class InstructionModel;
class Parser;
class ProcessorTab : public QWidget {
+ friend class RunDialog;
Q_OBJECT
public:

MODIFY
src/rundialog.cpp
src/rundialog.cpp
#include "ui_rundialog.h"
#include "pipeline.h"
+#include "processortab.h"
#include <QPushButton>
#include <QtConcurrent/QtConcurrent>
-RunDialog::RunDialog(QWidget *parent) :
- QDialog(parent),
- ui(new Ui::RunDialog)
-{
+RunDialog::RunDialog(QWidget* parent) : QDialog(parent), ui(new Ui::RunDialog) {
ui->setupUi(this);
ui->buttonBox->button(QDialogButtonBox::Ok)->setVisible(false);
ui->buttonBox->button(QDialogButtonBox::Cancel)->setText("Abort");
+ m_processorTab = static_cast<ProcessorTab*>(parent);
+
setWindowTitle("Running...");
ui->label->setText(QString("Running for 0 seconds"));
@@ -30,29 +30,35 @@ void RunDialog::updateText(){
}
}
QFuture<int> RunDialog::startSimulation() {
+ // Ensure that abort flag of pipeline is cleared before running again
+ Pipeline::getPipeline()->clearAbort();
QFuture<int> future = QtConcurrent::run(Pipeline::getPipeline(), &Pipeline::run);
return future;
}
int RunDialog::exec() {
- connect(&m_runWatcher, &QFutureWatcher<int>::finished,
- this, &RunDialog::finished);
+ connect(&m_runWatcher, &QFutureWatcher<int>::finished, this, &RunDialog::finished);
m_runWatcher.setFuture(startSimulation());
return QDialog::exec();
}
-RunDialog::~RunDialog()
-{
+RunDialog::~RunDialog() {
delete ui;
}
void RunDialog::finished() {
- m_timer.stop();
if (m_runWatcher.future().result() == 0) {
+ m_timer.stop();
accept();
} else {
- reject();
+ // Check if there was an ecall
+ const auto ecall_val = Pipeline::getPipeline()->checkEcall(true);
+ if (ecall_val.first != Pipeline::ECALL::none) {
+ // An ECALL has been invoked during continuous running. Handle ecall and continue to run
+ m_processorTab->handleEcall(ecall_val);
+ m_runWatcher.setFuture(startSimulation());
+ }
}
}

MODIFY
src/rundialog.h
src/rundialog.h
namespace Ui {
class RunDialog;
}
+class ProcessorTab;
-class RunDialog : public QDialog
-{
+class RunDialog : public QDialog {
Q_OBJECT
public:
@@ -33,6 +33,8 @@ private:
Ui::RunDialog* ui;
+ ProcessorTab* m_processorTab;
+
QFutureWatcher<int> m_runWatcher;
QTimer m_timer;
};

Handle ecalls during 'run' without closing the run dialog #30