diff options
-rw-r--r-- | qtmips_gui/NewDialog.ui | 31 | ||||
-rw-r--r-- | qtmips_gui/NewDialogCache.ui | 169 | ||||
-rw-r--r-- | qtmips_gui/newdialog.cpp | 190 | ||||
-rw-r--r-- | qtmips_gui/newdialog.h | 15 | ||||
-rw-r--r-- | qtmips_machine/machineconfig.cpp | 192 | ||||
-rw-r--r-- | qtmips_machine/machineconfig.h | 50 |
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; }; } |