Stop simulator after failed syscall handling
This will both stop any current running of the simulator as well as
if the simulator is being autostepped.
MODIFY
external/VSRTL
external/VSRTL
-Subproject commit 8d51b2bfd65df07316d2ff9b1cd493893179361d
+Subproject commit 08bb8d2f1a47ca8b2461923fd09bf40dbbc802bb

MODIFY
src/mainwindow.cpp
src/mainwindow.cpp
@@ -101,6 +101,8 @@ MainWindow::MainWindow(QWidget* parent) : QMainWindow(parent), m_ui(new Ui::Main
connect(m_memoryTab, &MemoryTab::reqProcessorReset, m_processorTab, &ProcessorTab::reset);
connect(ProcessorHandler::get(), &ProcessorHandler::reqProcessorReset, m_processorTab, &ProcessorTab::reset);
connect(ProcessorHandler::get(), &ProcessorHandler::reqReloadProgram, m_editTab, &EditTab::emitProgramChanged);
+ connect(ProcessorHandler::get(), &ProcessorHandler::stopping, m_processorTab, &ProcessorTab::pause);
+
connect(m_processorTab, &ProcessorTab::processorWasReset, [=] { SystemIO::reset(); });
connect(m_ui->actionSystem_calls, &QAction::triggered, [=] {

MODIFY
src/processorhandler.cpp
src/processorhandler.cpp
@@ -36,7 +36,7 @@ ProcessorHandler::ProcessorHandler() {
void ProcessorHandler::loadProgram(std::shared_ptr<Program> p) {
// Stop any currently executing simulation
- stop();
+ stopRun();
auto* textSection = p->getSection(TEXT_SECTION_NAME);
if (!textSection)
@@ -208,12 +208,17 @@ QString ProcessorHandler::parseInstrAt(const uint32_t addr) const {
}
void ProcessorHandler::asyncTrap() {
- QtConcurrent::run([=] {
+ auto futureWatcher = QFutureWatcher<bool>();
+ futureWatcher.setFuture(QtConcurrent::run([=] {
const unsigned int function = m_currentProcessor->getRegister(currentISA()->syscallReg());
- m_syscallManager->execute(function);
- m_sem.release();
- });
- m_sem.acquire();
+ return m_syscallManager->execute(function);
+ }));
+
+ futureWatcher.waitForFinished();
+ if (!futureWatcher.result()) {
+ // Syscall handling failed, stop running processor
+ setStopRunFlag();
+ }
}
void ProcessorHandler::checkProcessorFinished() {
@@ -221,12 +226,17 @@ void ProcessorHandler::checkProcessorFinished() {
emit exit();
}
-void ProcessorHandler::stop() {
+void ProcessorHandler::setStopRunFlag() {
+ emit stopping();
if (m_runWatcher.isRunning()) {
m_stopRunningFlag = true;
// We might be currently trapping for user I/O. Signal to abort the trap, in this avoiding a deadlock.
SystemIO::abortSyscall(true);
}
+}
+
+void ProcessorHandler::stopRun() {
+ setStopRunFlag();
m_runWatcher.waitForFinished();
m_stopRunningFlag = false;
SystemIO::abortSyscall(false);

MODIFY
src/processorhandler.h
src/processorhandler.h
@@ -124,10 +124,10 @@ public:
void run();
/**
- * @brief stop
+ * @brief stopRun
* Sets the m_stopRunningFlag, and waits for any currently running asynchronous run execution to finish.
*/
- void stop();
+ void stopRun();
signals:
/**
@@ -150,6 +150,12 @@ signals:
*/
void exit();
+ /**
+ * @brief stopping
+ * Processor has been requested to stop
+ */
+ void stopping();
+
/**
* @brief runStarted/runFinished
* Signals indiacting whether the processor is being started/stopped in asynchronously running without any GUI
@@ -170,6 +176,8 @@ private slots:
void asyncTrap();
private:
+ void setStopRunFlag();
+
ProcessorHandler();
ProcessorID m_currentID;

MODIFY
src/processortab.cpp
src/processortab.cpp
@@ -459,7 +459,7 @@ void ProcessorTab::run(bool state) {
ProcessorHandler::get()->run();
m_statUpdateTimer->start();
} else {
- ProcessorHandler::get()->stop();
+ ProcessorHandler::get()->stopRun();
m_statUpdateTimer->stop();
}

MODIFY
src/syscall/ripes_syscall.h
src/syscall/ripes_syscall.h
@@ -77,19 +77,21 @@ public:
* @brief execute
* Executes the syscall identified by id. Throws out of range exception if syscall @p id is unknown.
*/
- void execute(int id) {
+ bool execute(int id) {
if (m_syscalls.count(id) == 0) {
postToGUIThread([=] {
QMessageBox::warning(nullptr, "Error",
"Unknown system call: " + QString::number(id) +
"\nRefer to \"Help->System calls\" for a list of support system calls.");
});
+ return false;
} else {
const auto& syscall = m_syscalls.at(id);
SyscallStatusManager::setStatus("Handling system call: " + syscall->name() + " (" + QString::number(id) +
")");
syscall->execute();
SyscallStatusManager::clearStatus();
+ return true;
}
}
@@ -102,7 +104,7 @@ protected:
* @param connection type.
*/
template <typename F>
- static void postToGUIThread(F&& fun, Qt::ConnectionType type = Qt::BlockingQueuedConnection) {
+ static void postToGUIThread(F&& fun, Qt::ConnectionType type = Qt::QueuedConnection) {
auto* obj = QAbstractEventDispatcher::instance(qApp->thread());
Q_ASSERT(obj);
QMetaObject::invokeMethod(obj, std::forward<F>(fun), type);

Stop simulator after failed syscall handling

This will both stop any current running of the simulator as well as
if the simulator is being autostepped.