aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--qtmips_gui/NewDialog.ui31
-rw-r--r--qtmips_gui/NewDialogCache.ui169
-rw-r--r--qtmips_gui/newdialog.cpp190
-rw-r--r--qtmips_gui/newdialog.h15
-rw-r--r--qtmips_machine/machineconfig.cpp192
-rw-r--r--qtmips_machine/machineconfig.h50
6 files changed, 507 insertions, 140 deletions
diff --git a/qtmips_gui/NewDialog.ui b/qtmips_gui/NewDialog.ui
index a39a014..0490ca3 100644
--- a/qtmips_gui/NewDialog.ui
+++ b/qtmips_gui/NewDialog.ui
@@ -37,7 +37,7 @@
</attribute>
<layout class="QVBoxLayout" name="verticalLayout_5">
<item>
- <widget class="QGroupBox" name="groupBox_2">
+ <widget class="QGroupBox" name="preset_box">
<property name="title">
<string>Preset</string>
</property>
@@ -198,6 +198,35 @@
</widget>
</item>
<item>
+ <widget class="QGroupBox" name="groupBox">
+ <property name="title">
+ <string>Access time (in cycles)</string>
+ </property>
+ <layout class="QFormLayout" name="formLayout">
+ <item row="0" column="0">
+ <widget class="QLabel" name="label_2">
+ <property name="text">
+ <string>Read:</string>
+ </property>
+ </widget>
+ </item>
+ <item row="0" column="1">
+ <widget class="QSpinBox" name="mem_time_read"/>
+ </item>
+ <item row="1" column="0">
+ <widget class="QLabel" name="label_3">
+ <property name="text">
+ <string>Write:</string>
+ </property>
+ </widget>
+ </item>
+ <item row="1" column="1">
+ <widget class="QSpinBox" name="mem_time_write"/>
+ </item>
+ </layout>
+ </widget>
+ </item>
+ <item>
<spacer name="verticalSpacer_2">
<property name="orientation">
<enum>Qt::Vertical</enum>
diff --git a/qtmips_gui/NewDialogCache.ui b/qtmips_gui/NewDialogCache.ui
index 3c91824..04f15f7 100644
--- a/qtmips_gui/NewDialogCache.ui
+++ b/qtmips_gui/NewDialogCache.ui
@@ -6,63 +6,140 @@
<rect>
<x>0</x>
<y>0</y>
- <width>339</width>
- <height>167</height>
+ <width>435</width>
+ <height>272</height>
</rect>
</property>
<property name="windowTitle">
<string>Form</string>
</property>
- <layout class="QFormLayout" name="formLayout_2">
- <item row="0" column="0">
- <widget class="QLabel" name="label">
- <property name="text">
- <string>Capacity:</string>
+ <layout class="QVBoxLayout" name="verticalLayout">
+ <item>
+ <widget class="QGroupBox" name="enabled">
+ <property name="title">
+ <string/>
</property>
- </widget>
- </item>
- <item row="0" column="1">
- <widget class="QSpinBox" name="spinBox"/>
- </item>
- <item row="1" column="0">
- <widget class="QLabel" name="label_2">
- <property name="text">
- <string>Number of sets:</string>
+ <property name="checkable">
+ <bool>true</bool>
</property>
+ <layout class="QFormLayout" name="formLayout">
+ <item row="0" column="0">
+ <widget class="QLabel" name="label">
+ <property name="text">
+ <string>Capacity:</string>
+ </property>
+ </widget>
+ </item>
+ <item row="0" column="1">
+ <widget class="QSpinBox" name="capcity"/>
+ </item>
+ <item row="1" column="0">
+ <widget class="QLabel" name="label_2">
+ <property name="text">
+ <string>Number of sets:</string>
+ </property>
+ </widget>
+ </item>
+ <item row="1" column="1">
+ <widget class="QSpinBox" name="number_of_sets"/>
+ </item>
+ <item row="2" column="0">
+ <widget class="QLabel" name="label_3">
+ <property name="text">
+ <string>Block size:</string>
+ </property>
+ </widget>
+ </item>
+ <item row="2" column="1">
+ <widget class="QSpinBox" name="block_size"/>
+ </item>
+ <item row="3" column="0">
+ <widget class="QLabel" name="label_4">
+ <property name="text">
+ <string>Number of blocks:</string>
+ </property>
+ </widget>
+ </item>
+ <item row="3" column="1">
+ <widget class="QSpinBox" name="number_of_blocks"/>
+ </item>
+ <item row="4" column="0">
+ <widget class="QLabel" name="label_5">
+ <property name="text">
+ <string>Degree of associativity:</string>
+ </property>
+ </widget>
+ </item>
+ <item row="4" column="1">
+ <widget class="QSpinBox" name="degree_if_associativity"/>
+ </item>
+ <item row="5" column="0">
+ <widget class="QLabel" name="label_6">
+ <property name="text">
+ <string>Replacement policy:</string>
+ </property>
+ </widget>
+ </item>
+ <item row="6" column="0">
+ <widget class="QLabel" name="label_7">
+ <property name="text">
+ <string>Writeback policy:</string>
+ </property>
+ </widget>
+ </item>
+ <item row="5" column="1">
+ <widget class="QComboBox" name="comboBox">
+ <item>
+ <property name="text">
+ <string>Random</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string>Least Recently Used (LRU)</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string>Least Frequently Used (LFU)</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string>Adaptive Replacement Cache (ARC)</string>
+ </property>
+ </item>
+ </widget>
+ </item>
+ <item row="6" column="1">
+ <widget class="QComboBox" name="comboBox_2">
+ <item>
+ <property name="text">
+ <string>Write trough</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string>Write back</string>
+ </property>
+ </item>
+ </widget>
+ </item>
+ </layout>
</widget>
</item>
- <item row="2" column="0">
- <widget class="QLabel" name="label_3">
- <property name="text">
- <string>Block size:</string>
+ <item>
+ <spacer name="verticalSpacer">
+ <property name="orientation">
+ <enum>Qt::Vertical</enum>
</property>
- </widget>
- </item>
- <item row="3" column="0">
- <widget class="QLabel" name="label_4">
- <property name="text">
- <string>Number of blocks:</string>
+ <property name="sizeHint" stdset="0">
+ <size>
+ <width>20</width>
+ <height>40</height>
+ </size>
</property>
- </widget>
- </item>
- <item row="4" column="0">
- <widget class="QLabel" name="label_5">
- <property name="text">
- <string>Degree of associativity:</string>
- </property>
- </widget>
- </item>
- <item row="1" column="1">
- <widget class="QSpinBox" name="spinBox_2"/>
- </item>
- <item row="2" column="1">
- <widget class="QSpinBox" name="spinBox_3"/>
- </item>
- <item row="3" column="1">
- <widget class="QSpinBox" name="spinBox_4"/>
- </item>
- <item row="4" column="1">
- <widget class="QSpinBox" name="spinBox_5"/>
+ </spacer>
</item>
</layout>
</widget>
diff --git a/qtmips_gui/newdialog.cpp b/qtmips_gui/newdialog.cpp
index 6aec98a..033d0ce 100644
--- a/qtmips_gui/newdialog.cpp
+++ b/qtmips_gui/newdialog.cpp
@@ -5,32 +5,35 @@
NewDialog::NewDialog(QWidget *parent, QSettings *settings) : QDialog(parent) {
setWindowTitle("New machine");
+ this->settings = settings;
+ config = nullptr;
+
ui = new Ui::NewDialog();
ui->setupUi(this);
ui_cache_p = new Ui::NewDialogCache();
ui_cache_p->setupUi(ui->tab_cache_program);
ui_cache_d = new Ui::NewDialogCache();
ui_cache_d->setupUi(ui->tab_cache_data);
- // TODO setup more? settings and configuration pull
-
- this->settings = settings;
-
- QObject::connect(ui->pushButton_load, SIGNAL(clicked(bool)), this, SLOT(create()));
- QObject::connect(ui->pushButton_cancel, SIGNAL(clicked(bool)), this, SLOT(cancel()));
- // Signals on Base tab
- QObject::connect(ui->preset_no_pipeline, SIGNAL(toggled(bool)), this, SLOT(preset(bool)));
- QObject::connect(ui->preset_pipelined, SIGNAL(toggled(bool)), this, SLOT(preset(bool)));
- QObject::connect(ui->pushButton_browse, SIGNAL(clicked(bool)), this, SLOT(browse_elf()));
-#define CUSTOM_PRESET(UI) QObject::connect(UI, SIGNAL(clicked(bool)), this, SLOT(set_custom_preset()))
- // Signals on Core tab
- CUSTOM_PRESET(ui->pipelined);
- // Signals on Memory tab
- CUSTOM_PRESET(ui->mem_protec_write);
- CUSTOM_PRESET(ui->mem_protec_exec);
-#undef CUSTOM_PRESET
- // Load setting after signals are configured so that we can have correct settings
- load_settings();
+ connect(ui->pushButton_load, SIGNAL(clicked(bool)), this, SLOT(create()));
+ connect(ui->pushButton_cancel, SIGNAL(clicked(bool)), this, SLOT(cancel()));
+ connect(ui->pushButton_browse, SIGNAL(clicked(bool)), this, SLOT(browse_elf()));
+ //connect(ui->preset_box, SIGNAL(clicked(bool)), this, SLOT(set_preset()));
+ connect(ui->preset_no_pipeline, SIGNAL(toggled(bool)), this, SLOT(set_preset()));
+ connect(ui->preset_pipelined, SIGNAL(toggled(bool)), this, SLOT(set_preset()));
+
+ connect(ui->pipelined, SIGNAL(clicked(bool)), this, SLOT(pipelined_change(bool)));
+ connect(ui->delay_slot, SIGNAL(clicked(bool)), this, SLOT(delay_slot_change(bool)));
+ connect(ui->hazard_unit, SIGNAL(clicked(bool)), this, SLOT(hazard_unit_change()));
+ connect(ui->hazard_stall, SIGNAL(clicked(bool)), this, SLOT(hazard_unit_change()));
+ connect(ui->hazard_stall_forward, SIGNAL(clicked(bool)), this, SLOT(hazard_unit_change()));
+ connect(ui->mem_protec_exec, SIGNAL(clicked(bool)), this, SIGNAL(mem_protec_exec_change(bool)));
+ connect(ui->mem_protec_write, SIGNAL(clicked(bool)), this, SLOT(mem_protec_write_change(bool)));
+
+ connect(ui_cache_p->enabled, SIGNAL(clicked(bool)), this, SLOT(cache_program_change(bool)));
+ connect(ui_cache_d->enabled, SIGNAL(clicked(bool)), this, SLOT(cache_data_change(bool)));
+
+ load_settings(); // Also configures gui
}
NewDialog::~NewDialog() {
@@ -38,6 +41,7 @@ NewDialog::~NewDialog() {
delete ui_cache_p;
delete ui;
// Settings is freed by parent
+ delete config;
}
void NewDialog::closeEvent(QCloseEvent *) {
@@ -55,13 +59,8 @@ void NewDialog::cancel() {
void NewDialog::create() {
MainWindow *prnt = (MainWindow*)parent();
- machine::MachineConfig mc;
- mc.set_elf(ui->elf_file->text());
- mc.set_pipelined(ui->pipelined->isChecked());
- // TODO other settings
-
try {
- prnt->create_core(mc);
+ prnt->create_core(*config);
} catch (const machine::QtMipsExceptionInput &e) {
QMessageBox msg(this);
msg.setText(e.msg(false));
@@ -80,54 +79,119 @@ void NewDialog::create() {
void NewDialog::browse_elf() {
QFileDialog elf_dialog(this);
elf_dialog.setFileMode(QFileDialog::ExistingFile);
- if (elf_dialog.exec())
- ui->elf_file->setText(elf_dialog.selectedFiles()[0]);
+ if (elf_dialog.exec()) {
+ QString path = elf_dialog.selectedFiles()[0];
+ ui->elf_file->setText(path);
+ config->set_elf(path);
+ }
+ // Elf shouldn't have any other effect so we skip config_gui here
+}
+
+void NewDialog::set_preset() {
+ if (ui->preset_no_pipeline->isChecked())
+ config->preset(machine::CP_SINGLE);
+ else if (ui->preset_pipelined->isChecked())
+ config->preset(machine::CP_PIPE_WITH_CACHE);
+ else
+ // Skip apply configuration as we changed nothing.
+ return;
+ config_gui();
+}
+
+// Common end section of *_change slots
+#define CHANGE_COMMON do { \
+ ui->preset_custom->setChecked(true); \
+ config_gui(); \
+ } while(false)
+
+void NewDialog::pipelined_change(bool val) {
+ config->set_pipelined(val);
+ CHANGE_COMMON;
+}
+
+void NewDialog::delay_slot_change(bool val) {
+ config->set_delay_slot(val);
+ CHANGE_COMMON;
}
-void NewDialog::preset(bool value) {
- if (value) {
- bool pip = ui->preset_pipelined->isChecked();
- // Core settings
- ui->pipelined->setChecked(pip);
- // Memory settings
- ui->mem_protec_write->setChecked(true);
- ui->mem_protec_exec->setChecked(true);
- } // Else custom so do no changes
+void NewDialog::hazard_unit_change() {
+ if (ui->hazard_unit->isChecked())
+ config->set_hazard_unit(ui->hazard_stall->isChecked() ? machine::MachineConfig::HU_STALL : machine::MachineConfig::HU_STALL_FORWARD);
+ else
+ config->set_hazard_unit(machine::MachineConfig::HU_NONE);
+ CHANGE_COMMON;
}
-void NewDialog::set_custom_preset() {
- ui->preset_custom->setChecked(true);
+void NewDialog::mem_protec_exec_change(bool v) {
+ config->set_memory_execute_protection(v);
+ CHANGE_COMMON;
}
-#define LOAD_BUTTON(NAME, DEF) ui->NAME->setChecked(settings->value(#NAME, DEF).toBool())
-#define LOAD_LINE(NAME, DEF) ui->NAME->setText(settings->value(#NAME, DEF).toString())
+void NewDialog::mem_protec_write_change(bool v) {
+ config->set_memory_write_protection(v);
+ CHANGE_COMMON;
+}
-#define STORE_BUTTON(NAME) settings->setValue(#NAME, ui->NAME->isChecked())
-#define STORE_LINE(NAME) settings->setValue(#NAME, ui->NAME->text())
+void NewDialog::cache_data_change(bool v) {
+ config->access_cache_data()->set_enabled(v);
+ CHANGE_COMMON;
+}
+
+void NewDialog::cache_program_change(bool v) {
+ config->access_cache_program()->set_enabled(v);
+ CHANGE_COMMON;
+}
+
+void NewDialog::config_gui() {
+ // Set values
+ ui->elf_file->setText(config->elf());
+ ui->pipelined->setChecked(config->pipelined());
+ ui->delay_slot->setChecked(config->delay_slot());
+ ui->hazard_unit->setChecked(config->hazard_unit() != machine::MachineConfig::HU_NONE);
+ ui->hazard_stall->setChecked(config->hazard_unit() == machine::MachineConfig::HU_STALL);
+ // ui->hazard_stall_forward is configured automatically according to box exclusivity
+ ui->mem_protec_exec->setChecked(config->memory_execute_protection());
+ ui->mem_protec_write->setChecked(config->memory_write_protection());
+ ui->mem_time_read->setValue(config->memory_access_time_read());
+ ui->mem_time_write->setValue(config->memory_access_time_write());
+ ui_cache_p->enabled->setChecked(config->cache_program().enabled());
+ ui_cache_d->enabled->setChecked(config->cache_data().enabled());
+ // Disable various sections according to configuration
+ ui->delay_slot->setEnabled(!config->pipelined());
+ ui->hazard_unit->setEnabled(config->pipelined());
+}
void NewDialog::load_settings() {
- // Core tab
- LOAD_BUTTON(pipelined, false);
- // Memory tab
- LOAD_BUTTON(mem_protec_write, true);
- LOAD_BUTTON(mem_protec_exec, true);
- // Base tab
- // We are doing this last so presets can reset previous configuration to somethin valid
- LOAD_BUTTON(preset_no_pipeline, true);
- LOAD_BUTTON(preset_pipelined, false);
- LOAD_BUTTON(preset_custom, false);
- LOAD_LINE(elf_file, "");
+ if (config != nullptr)
+ delete config;
+
+ // Load config
+ config = new machine::MachineConfig(settings);
+
+ // Load preset
+ unsigned preset = settings->value("Preset", 1).toUInt();
+ if (preset != 0) {
+ enum machine::ConfigPresets p = (enum machine::ConfigPresets)(preset - 1);
+ config->preset(p);
+ switch (p) {
+ case machine::CP_SINGLE:
+ ui->preset_no_pipeline->setChecked(true);
+ break;
+ case machine::CP_PIPE_WITH_CACHE:
+ ui->preset_pipelined->setChecked(true);
+ break;
+ }
+ } else
+ ui->preset_custom->setChecked(true);
+
+ config_gui();
}
void NewDialog::store_settings() {
- // Core tab
- STORE_BUTTON(pipelined);
- // Memory tab
- STORE_BUTTON(mem_protec_write);
- STORE_BUTTON(mem_protec_exec);
- // Base tab
- STORE_BUTTON(preset_no_pipeline);
- STORE_BUTTON(preset_pipelined);
- STORE_BUTTON(preset_custom);
- STORE_LINE(elf_file);
+ config->store(settings);
+
+ if (ui->preset_custom->isChecked())
+ settings->setValue("Preset", 0);
+ else
+ settings->setValue("Preset", ui->preset_no_pipeline->isChecked() ? machine::CP_SINGLE + 1 : machine::CP_PIPE_WITH_CACHE + 1);
}
diff --git a/qtmips_gui/newdialog.h b/qtmips_gui/newdialog.h
index a088777..5b50a41 100644
--- a/qtmips_gui/newdialog.h
+++ b/qtmips_gui/newdialog.h
@@ -7,6 +7,7 @@
#include <QMessageBox>
#include "ui_NewDialog.h"
#include "ui_NewDialogCache.h"
+#include "machineconfig.h"
class NewDialog : public QDialog {
Q_OBJECT
@@ -21,14 +22,24 @@ private slots:
void cancel();
void create();
void browse_elf();
- void preset(bool);
- void set_custom_preset();
+ void set_preset();
+ void pipelined_change(bool);
+ void delay_slot_change(bool);
+ void hazard_unit_change();
+ void mem_protec_exec_change(bool);
+ void mem_protec_write_change(bool);
+
+ void cache_data_change(bool);
+ void cache_program_change(bool);
private:
Ui::NewDialog *ui;
Ui::NewDialogCache *ui_cache_p, *ui_cache_d;
QSettings *settings;
+ machine::MachineConfig *config;
+ void config_gui(); // Apply configuration to gui
+
void load_settings();
void store_settings();
};
diff --git a/qtmips_machine/machineconfig.cpp b/qtmips_machine/machineconfig.cpp
index e479d66..ab6f2a5 100644
--- a/qtmips_machine/machineconfig.cpp
+++ b/qtmips_machine/machineconfig.cpp
@@ -2,17 +2,64 @@
using namespace machine;
+//////////////////////////////////////////////////////////////////////////////
+/// Default config of MachineConfig
+#define DF_PIPELINE false
+#define DF_DELAYSLOT true
+#define DF_HUNIT HU_STALL_FORWARD
+#define DF_EXEC_PROTEC false
+#define DF_WRITE_PROTEC false
+#define DF_MEM_ACC_READ 10
+#define DF_MEM_ACC_WRITE 10
+#define DF_ELF QString("")
+//////////////////////////////////////////////////////////////////////////////
+/// Default config of MachineConfigCache
+#define DFC_EN false
+//////////////////////////////////////////////////////////////////////////////
+
MachineConfigCache::MachineConfigCache() {
- // TODO
+ en = DFC_EN;
}
MachineConfigCache::MachineConfigCache(const MachineConfigCache *cc) {
- // TODO
+ en = cc->enabled();
+}
+
+#define N(STR) (prefix + QString(STR))
+
+MachineConfigCache::MachineConfigCache(const QSettings *sts, const QString &prefix) {
+ en = sts->value(N("Enabled"), DFC_EN).toBool();
+}
+
+void MachineConfigCache::store(QSettings *sts, const QString &prefix) {
+ sts->setValue(N("Enabled"), en);
+}
+
+#undef N
+
+void MachineConfigCache::preset(enum ConfigPresets p) {
+ switch (p) {
+ case CP_SINGLE:
+ set_enabled(false);
+ break;
+ case CP_PIPE_WITH_CACHE:
+ set_enabled(false);
+ break;
+ }
+}
+
+void MachineConfigCache::set_enabled(bool v) {
+ en = v;
+}
+
+bool MachineConfigCache::enabled() const {
+ return en;
}
bool MachineConfigCache::operator==(const MachineConfigCache &c) const {
- // TODO
- return true;
+#define CMP(GETTER) (GETTER)() == (c.GETTER)()
+ return CMP(enabled);
+#undef CMP
}
bool MachineConfigCache::operator!=(const MachineConfigCache &c) const {
@@ -20,18 +67,77 @@ bool MachineConfigCache::operator!=(const MachineConfigCache &c) const {
}
MachineConfig::MachineConfig() {
- pipeline = false;
- delayslot = true;
- hunit = HU_STALL_FORWARD;
+ pipeline = DF_PIPELINE;
+ delayslot = DF_DELAYSLOT;
+ hunit = DF_HUNIT;
+ exec_protect = DF_EXEC_PROTEC;
+ write_protect = DF_WRITE_PROTEC;
+ mem_acc_read = DF_MEM_ACC_READ;
+ mem_acc_write = DF_MEM_ACC_WRITE;
+ elf_path = DF_ELF;
+ cch_program = MachineConfigCache();
+ cch_data = MachineConfigCache();
}
MachineConfig::MachineConfig(const MachineConfig *cc) {
pipeline = cc->pipelined();
delayslot = cc->delay_slot();
+ hunit = cc->hazard_unit();
+ exec_protect = cc->memory_execute_protection();
+ write_protect = cc->memory_write_protection();
+ mem_acc_read = cc->memory_access_time_read();
+ mem_acc_write = cc->memory_access_time_write();
elf_path = cc->elf();
cch_program = cc->cache_program();
cch_data = cc->cache_data();
- hunit = cc->hazard_unit();
+}
+
+#define N(STR) (prefix + QString(STR))
+
+MachineConfig::MachineConfig(const QSettings *sts, const QString &prefix) {
+ pipeline = sts->value(N("Pipelined"), DF_PIPELINE).toBool();
+ delayslot = sts->value(N("DelaySlot"), DF_DELAYSLOT).toBool();
+ hunit = (enum HazardUnit)sts->value(N("HazardUnit"), DF_HUNIT).toUInt(); // TODO probably rather save as string
+ exec_protect = sts->value(N("MemoryExecuteProtection"), DF_EXEC_PROTEC).toBool();
+ write_protect = sts->value(N("MemoryWriteProtection"), DF_WRITE_PROTEC).toBool();
+ mem_acc_read = sts->value(N("MemoryRead"), DF_MEM_ACC_READ).toUInt();
+ mem_acc_write = sts->value(N("MemoryWrite"), DF_MEM_ACC_WRITE).toUInt();
+ elf_path = sts->value(N("Elf"), DF_ELF).toString();
+ cch_program = MachineConfigCache(sts, N("ProgramCache_"));
+ cch_data = MachineConfigCache(sts, N("DataCache_"));
+}
+
+void MachineConfig::store(QSettings *sts, const QString &prefix) {
+ sts->setValue(N("Pipelined"), pipelined());
+ sts->setValue(N("DelaySlot"), delay_slot());
+ sts->setValue(N("HazardUnit"), (unsigned)hazard_unit());
+ sts->setValue(N("Elf"), elf_path);
+ cch_program.store(sts, N("ProgramCache_"));
+ cch_data.store(sts, N("DataCache_"));
+}
+
+#undef N
+
+void MachineConfig::preset(enum ConfigPresets p) {
+ // Note: we set just a minimal subset to get preset (preserving as much of hidden configuration as possible)
+ switch (p) {
+ case CP_SINGLE:
+ set_pipelined(false);
+ set_delay_slot(true);
+ break;
+ case CP_PIPE_WITH_CACHE:
+ set_pipelined(true);
+ set_hazard_unit(MachineConfig::HU_STALL_FORWARD);
+ break;
+ }
+ // Some common configurations
+ set_memory_execute_protection(DF_EXEC_PROTEC);
+ set_memory_write_protection(DF_WRITE_PROTEC);
+ set_memory_access_time_read(DF_MEM_ACC_READ);
+ set_memory_access_time_write(DF_MEM_ACC_WRITE);
+
+ access_cache_program()->preset(p);
+ access_cache_data()->preset(p);
}
void MachineConfig::set_pipelined(bool v) {
@@ -40,8 +146,26 @@ void MachineConfig::set_pipelined(bool v) {
void MachineConfig::set_delay_slot(bool v) {
delayslot = v;
- if (!delayslot)
- pipeline = false;
+}
+
+void MachineConfig::set_hazard_unit(enum MachineConfig::HazardUnit hu) {
+ hunit = hu;
+}
+
+void MachineConfig::set_memory_execute_protection(bool v) {
+ exec_protect = v;
+}
+
+void MachineConfig::set_memory_write_protection(bool v) {
+ write_protect = v;
+}
+
+void MachineConfig::set_memory_access_time_read(unsigned v) {
+ mem_acc_read = v;
+}
+
+void MachineConfig::set_memory_access_time_write(unsigned v) {
+ mem_acc_write = v;
}
void MachineConfig::set_elf(QString path) {
@@ -56,42 +180,68 @@ void MachineConfig::set_cache_data(const MachineConfigCache &c) {
cch_data = c;
}
-void MachineConfig::set_hazard_unit(enum MachineConfig::HazardUnit hu) {
- hunit = hu;
-}
-
bool MachineConfig::pipelined() const {
return pipeline;
}
bool MachineConfig::delay_slot() const {
- return delayslot;
+ // Delay slot is always on when pipeline is enabled
+ return pipeline || delayslot;
+}
+
+enum MachineConfig::HazardUnit MachineConfig::hazard_unit() const {
+ // Hazard unit is always off when there is no pipeline
+ return pipeline ? hunit : machine::MachineConfig::HU_NONE;
+}
+
+bool MachineConfig::memory_execute_protection() const {
+ return exec_protect;
+}
+
+bool MachineConfig::memory_write_protection() const {
+ return write_protect;
+}
+
+unsigned MachineConfig::memory_access_time_read() const {
+ return mem_acc_read;
+}
+
+unsigned MachineConfig::memory_access_time_write() const {
+ return mem_acc_write;
}
QString MachineConfig::elf() const {
return elf_path;
}
-MachineConfigCache MachineConfig::cache_program() const {
+const MachineConfigCache &MachineConfig::cache_program() const {
return cch_program;
}
-MachineConfigCache MachineConfig::cache_data() const {
+const MachineConfigCache &MachineConfig::cache_data() const {
return cch_data;
}
-enum MachineConfig::HazardUnit MachineConfig::hazard_unit() const {
- return hunit;
+MachineConfigCache *MachineConfig::access_cache_program() {
+ return &cch_program;
+}
+
+MachineConfigCache *MachineConfig::access_cache_data() {
+ return &cch_data;
}
bool MachineConfig::operator==(const MachineConfig &c) const {
#define CMP(GETTER) (GETTER)() == (c.GETTER)()
return CMP(pipelined) && \
CMP(delay_slot) && \
+ CMP(hazard_unit) && \
+ CMP(memory_execute_protection) && \
+ CMP(memory_write_protection) && \
+ CMP(memory_access_time_read) && \
+ CMP(memory_access_time_write) && \
CMP(elf) && \
CMP(cache_program) && \
- CMP(cache_data) && \
- CMP(hazard_unit);
+ CMP(cache_data);
#undef CMP
}
diff --git a/qtmips_machine/machineconfig.h b/qtmips_machine/machineconfig.h
index 10b8458..90c9b75 100644
--- a/qtmips_machine/machineconfig.h
+++ b/qtmips_machine/machineconfig.h
@@ -2,20 +2,35 @@
#define MACHINECONFIG_H
#include <QString>
+#include <QSettings>
namespace machine {
+enum ConfigPresets {
+ CP_SINGLE,
+ CP_PIPE_WITH_CACHE
+};
+
class MachineConfigCache {
public:
MachineConfigCache();
MachineConfigCache(const MachineConfigCache *cc);
+ MachineConfigCache(const QSettings*, const QString &prefix = "");
- // TODO
+ void store(QSettings*, const QString &prefix = "");
+
+ void preset(enum ConfigPresets);
+
+ // If cache should be used or not
+ void set_enabled(bool);
+
+ bool enabled() const;
bool operator ==(const MachineConfigCache &c) const;
bool operator !=(const MachineConfigCache &c) const;
private:
+ bool en;
// TODO
};
@@ -23,6 +38,11 @@ class MachineConfig {
public:
MachineConfig();
MachineConfig(const MachineConfig *cc);
+ MachineConfig(const QSettings*, const QString &prefix = "");
+
+ void store(QSettings*, const QString &prefix = "");
+
+ void preset(enum ConfigPresets);
enum HazardUnit {
HU_NONE,
@@ -36,29 +56,45 @@ public:
// Configure if cpu should simulate delay slot in non-pipelined core
// In default enabled. When disabled it also automatically disables pipelining.
void set_delay_slot(bool);
+ // Hazard unit
+ void set_hazard_unit(enum HazardUnit);
+ // Protect data memory from execution. Only program sections can be executed.
+ void set_memory_execute_protection(bool);
+ // Protect program memory from accidental writes.
+ void set_memory_write_protection(bool);
+ // Set memory access times. Passed value is in cycles.
+ void set_memory_access_time_read(unsigned);
+ void set_memory_access_time_write(unsigned);
// Set path to source elf file. This has to be set before core is initialized.
void set_elf(QString path);
// Configure cache
void set_cache_program(const MachineConfigCache&);
void set_cache_data(const MachineConfigCache&);
- // Hazard unit
- void set_hazard_unit(enum HazardUnit);
bool pipelined() const;
bool delay_slot() const;
- QString elf() const;
- MachineConfigCache cache_program() const;
- MachineConfigCache cache_data() const;
enum HazardUnit hazard_unit() const;
+ bool memory_execute_protection() const;
+ bool memory_write_protection() const;
+ unsigned memory_access_time_read() const;
+ unsigned memory_access_time_write() const;
+ QString elf() const;
+ const MachineConfigCache &cache_program() const;
+ const MachineConfigCache &cache_data() const;
+
+ MachineConfigCache *access_cache_program();
+ MachineConfigCache *access_cache_data();
bool operator ==(const MachineConfig &c) const;
bool operator !=(const MachineConfig &c) const;
private:
bool pipeline, delayslot;
+ enum HazardUnit hunit;
+ bool exec_protect, write_protect;
+ unsigned mem_acc_read, mem_acc_write;
QString elf_path;
MachineConfigCache cch_program, cch_data;
- enum HazardUnit hunit;
};
}