Add settings for restoring state between executions
MODIFY
src/edittab.cpp
src/edittab.cpp
#include "parser.h"
#include "processorhandler.h"
#include "program.h"
+#include "ripessettings.h"
#include "symbolnavigator.h"
namespace Ripes {
@@ -36,7 +37,7 @@ EditTab::EditTab(QToolBar* toolbar, QWidget* parent) : RipesTab(toolbar, parent)
"always visible\nin the disassembled view.");
m_toolbar->addAction(m_followAction);
connect(m_followAction, &QAction::triggered, m_ui->programViewer, &ProgramViewer::setFollowEnabled);
- m_followAction->setChecked(true);
+ m_followAction->setChecked(RipesSettings::value(RIPES_SETTING_FOLLOW_EXEC).toBool());
m_buildAction = new QAction(this);
m_buildAction->setIcon(QIcon(":/icons/build.svg"));

MODIFY
src/mainwindow.cpp
src/mainwindow.cpp
@@ -75,6 +75,8 @@ MainWindow::MainWindow(QWidget* parent) : QMainWindow(parent), m_ui(new Ui::Main
connect(m_stackedTabs, &QStackedWidget::currentChanged, this, &MainWindow::tabChanged);
connect(m_ui->tabbar, &FancyTabBar::activeIndexChanged, m_stackedTabs, &QStackedWidget::setCurrentIndex);
connect(m_ui->tabbar, &FancyTabBar::activeIndexChanged, m_editTab, &EditTab::updateProgramViewerHighlighting);
+ connect(m_ui->tabbar, &FancyTabBar::activeIndexChanged,
+ [=](int index) { RipesSettings::setValue(RIPES_SETTING_APP_TAB, index); });
setupMenus();
@@ -109,7 +111,7 @@ MainWindow::MainWindow(QWidget* parent) : QMainWindow(parent), m_ui(new Ui::Main
connect(m_ui->actionVersion, &QAction::triggered, this, &MainWindow::version);
connect(m_ui->actionSettings, &QAction::triggered, this, &MainWindow::settingsTriggered);
- m_ui->tabbar->setActiveIndex(1);
+ m_ui->tabbar->setActiveIndex(RipesSettings::value(RIPES_SETTING_APP_TAB).toInt());
m_processorToolbar->setVisible(true);
}

MODIFY
src/processorhandler.cpp
src/processorhandler.cpp
@@ -15,6 +15,14 @@ namespace Ripes {
ProcessorHandler::ProcessorHandler() {
// Contruct the default processor
+ if (RipesSettings::value(RIPES_SETTING_PROCESSOR_ID).isNull()) {
+ m_currentID = ProcessorID::RV5S;
+ } else {
+ m_currentID = RipesSettings::value(RIPES_SETTING_PROCESSOR_ID).value<ProcessorID>();
+
+ // Some sanity checking
+ m_currentID = m_currentID >= ProcessorID::NUM_PROCESSORS ? ProcessorID::RV5S : m_currentID;
+ }
selectProcessor(m_currentID, ProcessorRegistry::getDescription(m_currentID).defaultRegisterVals);
// Connect relevant settings changes to VSRTL
@@ -140,6 +148,7 @@ void ProcessorHandler::clearBreakpoints() {
void ProcessorHandler::selectProcessor(const ProcessorID& id, RegisterInitialization setup) {
m_program = nullptr;
m_currentID = id;
+ RipesSettings::setValue(RIPES_SETTING_PROCESSOR_ID, id);
// Processor initializations
m_currentProcessor = ProcessorRegistry::constructProcessor(m_currentID);

MODIFY
src/processorhandler.h
src/processorhandler.h
@@ -172,7 +172,7 @@ private slots:
private:
ProcessorHandler();
- ProcessorID m_currentID = ProcessorID::RV5S;
+ ProcessorID m_currentID;
std::unique_ptr<vsrtl::core::RipesProcessor> m_currentProcessor;
std::unique_ptr<SyscallManager> m_syscallManager;

MODIFY
src/processorregistry.h
src/processorregistry.h
#include "processors/RISC-V/rvss/rvss.h"
namespace Ripes {
+Q_NAMESPACE
// =============================== Processors =================================
-enum class ProcessorID { RVSS, RV5S, RV5S_NO_HZ, RV5S_NO_FW_HZ };
+enum ProcessorID { RVSS, RV5S, RV5S_NO_HZ, RV5S_NO_FW_HZ, NUM_PROCESSORS };
+Q_ENUM_NS(Ripes::ProcessorID); // Register with the metaobject system
// ============================================================================
using RegisterInitialization = std::map<unsigned, uint32_t>;
@@ -30,6 +32,7 @@ struct Layout {
* Must contain an entry for each stage in the processor model.
*/
std::vector<double> stageLabelPositions;
+ bool operator==(const Layout& rhs) const { return this->name == rhs.name; }
};
struct ProcessorDescription {
@@ -56,6 +59,8 @@ public:
return std::make_unique<vsrtl::core::RVSS>();
case ProcessorID::RV5S_NO_HZ:
return std::make_unique<vsrtl::core::RV5S_NO_HZ>();
+ case ProcessorID::NUM_PROCESSORS:
+ Q_UNREACHABLE();
}
Q_UNREACHABLE();
}
@@ -122,5 +127,3 @@ private:
ProcessorMap m_descriptions;
};
} // namespace Ripes
-
-Q_DECLARE_METATYPE(Ripes::ProcessorID);

MODIFY
src/processorselectiondialog.cpp
src/processorselectiondialog.cpp
#include "processorhandler.h"
#include "radix.h"
+#include "ripessettings.h"
namespace Ripes {
@@ -45,7 +46,13 @@ ProcessorSelectionDialog::ProcessorSelectionDialog(QWidget* parent)
connect(m_ui->buttonBox, &QDialogButtonBox::rejected, this, &QDialog::reject);
if (selectedItem != nullptr) {
+ // Select the processor and layout which is currently active
m_ui->processors->setCurrentItem(selectedItem);
+ int layoutID = RipesSettings::value(RIPES_SETTING_PROCESSOR_LAYOUT_ID).toInt();
+ if (layoutID >= ProcessorRegistry::getDescription(ProcessorHandler::get()->getID()).layouts.size()) {
+ layoutID = 0;
+ }
+ m_ui->layout->setCurrentIndex(layoutID);
}
}

MODIFY
src/processortab.cpp
src/processortab.cpp
@@ -71,8 +71,13 @@ ProcessorTab::ProcessorTab(QToolBar* controlToolbar, QToolBar* additionalToolbar
m_vsrtlWidget = m_ui->vsrtlWidget;
- // Load the default constructed processor to the VSRTL widget
- loadProcessorToWidget(ProcessorRegistry::getDescription(ProcessorHandler::get()->getID()).layouts.at(0));
+ // Load the default constructed processor to the VSRTL widget. Do a bit of sanity checking to ensure that the layout
+ // stored in the settings is valid for the given processor
+ int layoutID = RipesSettings::value(RIPES_SETTING_PROCESSOR_LAYOUT_ID).toInt();
+ if (layoutID >= ProcessorRegistry::getDescription(ProcessorHandler::get()->getID()).layouts.size()) {
+ layoutID = 0;
+ }
+ loadProcessorToWidget(ProcessorRegistry::getDescription(ProcessorHandler::get()->getID()).layouts.at(layoutID));
// By default, lock the VSRTL widget
m_vsrtlWidget->setLocked(true);
@@ -311,6 +316,14 @@ void ProcessorTab::processorSelection() {
m_vsrtlWidget->clearDesign();
m_stageInstructionLabels.clear();
ProcessorHandler::get()->selectProcessor(diag.getSelectedId(), diag.getRegisterInitialization());
+
+ // Store selected layout index
+ const auto& layouts = ProcessorRegistry::getDescription(diag.getSelectedId()).layouts;
+ auto layoutIter = std::find(layouts.begin(), layouts.end(), diag.getSelectedLayout());
+ Q_ASSERT(layoutIter != layouts.end());
+ const long layoutIndex = std::distance(layouts.begin(), layoutIter);
+ RipesSettings::setValue(RIPES_SETTING_PROCESSOR_LAYOUT_ID, static_cast<int>(layoutIndex));
+
loadProcessorToWidget(diag.getSelectedLayout());
m_vsrtlWidget->reset();
updateInstructionModel();

MODIFY
src/programviewer.cpp
src/programviewer.cpp
#include "programviewer.h"
#include "defines.h"
+#include "ripessettings.h"
#include <QAction>
#include <QApplication>
@@ -84,6 +85,7 @@ void ProgramViewer::updateCenterAddressFromProcessor() {
}
void ProgramViewer::setFollowEnabled(bool enabled) {
+ RipesSettings::setValue(RIPES_SETTING_FOLLOW_EXEC, enabled);
m_following = enabled;
if (enabled) {

MODIFY
src/ripessettings.h
src/ripessettings.h
namespace Ripes {
-// Definitions of the name of all settings within Ripes
+// =========== Definitions of the name of all settings within Ripes ============
+// User-modifyable settings
#define RIPES_SETTING_REWINDSTACKSIZE ("simulator_rewindstacksize")
#define RIPES_SETTING_CCPATH ("compiler_path")
#define RIPES_SETTING_CCARGS ("compiler_args")
@@ -15,8 +16,17 @@ namespace Ripes {
#define RIPES_SETTING_CONSOLEFONTCOLOR ("console_font_color")
#define RIPES_SETTING_CONSOLEFONT ("console_font")
-// Definitions of all default settings within Ripes
+// Program state preserving settings
+#define RIPES_SETTING_APP_TAB ("app_tab")
+#define RIPES_SETTING_SETTING_TAB ("settings_tab")
+#define RIPES_SETTING_VIEW_ZOOM ("view_zoom")
+#define RIPES_SETTING_PROCESSOR_ID ("processor_id")
+#define RIPES_SETTING_PROCESSOR_LAYOUT_ID ("processor_layout_id")
+#define RIPES_SETTING_FOLLOW_EXEC ("follow_execution")
+
+// ============= Definitions of all default settings within Ripes ==============
const static std::map<QString, QVariant> s_defaultSettings = {
+ // User-modifyable settings
{RIPES_SETTING_REWINDSTACKSIZE, 100},
{RIPES_SETTING_CCPATH, ""},
{RIPES_SETTING_CCARGS, "-O0"},
@@ -24,6 +34,15 @@ const static std::map<QString, QVariant> s_defaultSettings = {
{RIPES_SETTING_CONSOLEBG, QColor(Qt::white)},
{RIPES_SETTING_CONSOLEFONTCOLOR, QColor(Qt::black)},
{RIPES_SETTING_CONSOLEFONT, QVariant() /* Let Console define its own default font */}};
+ {RIPES_SETTING_CONSOLEFONT, QColor(Qt::black)},
+
+ // Program state preserving settings
+ {RIPES_SETTING_APP_TAB, 1 /* Processor */},
+ {RIPES_SETTING_SETTING_TAB, 0},
+ {RIPES_SETTING_VIEW_ZOOM, 250},
+ {RIPES_SETTING_PROCESSOR_ID, QVariant() /* Let processorhandler define default */},
+ {RIPES_SETTING_PROCESSOR_LAYOUT_ID, 0},
+ {RIPES_SETTING_FOLLOW_EXEC, "true"}};
/**
* @brief The SettingObserver class

MODIFY
src/settingsdialog.cpp
src/settingsdialog.cpp
@@ -120,7 +120,7 @@ SettingsDialog::SettingsDialog(QWidget* parent) : QDialog(parent), m_ui(new Ui::
addPage("Simulator", createSimulatorPage());
addPage("Environment", createEnvironmentPage());
- m_ui->settingsList->setCurrentRow(0);
+ m_ui->settingsList->setCurrentRow(RipesSettings::value(RIPES_SETTING_SETTING_TAB).toInt());
}
SettingsDialog::~SettingsDialog() {
@@ -258,7 +258,9 @@ void SettingsDialog::addPage(const QString& name, QWidget* page) {
const QString name = current->text();
Q_ASSERT(m_pageIndex.count(name));
- m_ui->settingsPages->setCurrentIndex(m_pageIndex.at(name));
+ const int index = m_pageIndex.at(name);
+ m_ui->settingsPages->setCurrentIndex(index);
+ RipesSettings::setValue(RIPES_SETTING_SETTING_TAB, index);
});
}

Add settings for restoring state between executions