Fix massive slowdown from resetting InstructionModel on each step
MODIFY
src/instructionmodel.cpp
src/instructionmodel.cpp
@@ -10,34 +10,52 @@ InstructionModel::InstructionModel(QObject* parent) : QAbstractTableModel(parent
m_stageInfos[i];
}
connect(ProcessorHandler::get(), &ProcessorHandler::procStateChangedNonRun, this,
- &InstructionModel::processorWasClocked);
+ &InstructionModel::updateStageInfo);
+ connect(ProcessorHandler::get(), &ProcessorHandler::processorReset, this, &InstructionModel::onProcessorReset);
+ onProcessorReset();
+}
+
+void InstructionModel::onProcessorReset() {
+ updateRowCount();
+ beginResetModel();
+ endResetModel();
+ updateStageInfo();
}
int InstructionModel::columnCount(const QModelIndex&) const {
return NColumns;
}
-int InstructionModel::rowCount(const QModelIndex&) const {
- return ProcessorHandler::getCurrentProgramSize() / ProcessorHandler::currentISA()->bytes();
+void InstructionModel::updateRowCount() {
+ m_rowCount = ProcessorHandler::getCurrentProgramSize() / ProcessorHandler::currentISA()->bytes();
}
-void InstructionModel::processorWasClocked() {
- // Reload model
- beginResetModel();
- gatherStageInfo();
- endResetModel();
+int InstructionModel::rowCount(const QModelIndex&) const {
+ return m_rowCount;
}
-void InstructionModel::gatherStageInfo() {
+void InstructionModel::updateStageInfo() {
bool firstStageChanged = false;
for (unsigned i = 0; i < ProcessorHandler::getProcessor()->stageCount(); i++) {
+ if (static_cast<unsigned>(m_stageInfos.size()) > i) {
+ auto& oldStageInfo = m_stageInfos.at(i);
if (i == 0) {
- if (m_stageInfos[i].pc != ProcessorHandler::getProcessor()->stageInfo(i).pc) {
+ if (oldStageInfo.pc != ProcessorHandler::getProcessor()->stageInfo(i).pc) {
firstStageChanged = true;
}
}
- if (static_cast<unsigned>(m_stageNames.size()) > i) {
- m_stageInfos[i] = ProcessorHandler::getProcessor()->stageInfo(i);
+ const auto stageInfo = ProcessorHandler::getProcessor()->stageInfo(i);
+ const uint32_t oldAddress = oldStageInfo.pc;
+ const bool stageInfoChanged = oldStageInfo != stageInfo;
+ oldStageInfo = stageInfo;
+ if (stageInfoChanged) {
+ const int oldRow = addressToRow(oldAddress);
+ const int newRow = addressToRow(stageInfo.pc);
+ const QModelIndex oldIdx = index(oldRow, Stage);
+ const QModelIndex newIdx = index(newRow, Stage);
+ emit dataChanged(oldIdx, oldIdx, {Qt::DisplayRole});
+ emit dataChanged(newIdx, newIdx, {Qt::DisplayRole});
+ }
if (firstStageChanged) {
emit firstStageInstrChanged(m_stageInfos.at(0).pc);
firstStageChanged = false;

MODIFY
src/instructionmodel.h
src/instructionmodel.h
@@ -20,7 +20,7 @@ static inline uint32_t indexToAddress(const QModelIndex& index) {
return 0;
}
-static inline int addressToIndex(uint32_t addr) {
+static inline int addressToRow(uint32_t addr) {
if (auto prog_spt = ProcessorHandler::getProgram()) {
if (prog_spt->getSection(TEXT_SECTION_NAME) != nullptr) {
return (addr - prog_spt->getSection(TEXT_SECTION_NAME)->address) / 4;
@@ -44,9 +44,6 @@ public:
bool setData(const QModelIndex& index, const QVariant& value, int role) override;
Qt::ItemFlags flags(const QModelIndex& index) const override;
-public slots:
- void processorWasClocked();
-
signals:
/**
* @brief firstStageInstrChanged
@@ -56,15 +53,18 @@ signals:
void firstStageInstrChanged(uint32_t);
private:
- void gatherStageInfo();
+ void updateStageInfo();
QVariant BPData(uint32_t addr) const;
QVariant PCData(uint32_t addr) const;
QVariant stageData(uint32_t addr) const;
QVariant instructionData(uint32_t addr) const;
+ void updateRowCount();
+ void onProcessorReset();
QStringList m_stageNames;
using StageID = unsigned;
std::map<StageID, StageInfo> m_stageInfos;
+ int m_rowCount = 0;
};
} // namespace Ripes

MODIFY
src/processors/ripesprocessor.h
src/processors/ripesprocessor.h
@@ -20,6 +20,10 @@ struct StageInfo {
unsigned int pc = 0;
bool stage_valid = false;
State state;
+ bool operator==(const StageInfo& other) const {
+ return this->pc == other.pc && this->stage_valid == other.stage_valid && this->state == other.state;
+ }
+ bool operator!=(const StageInfo& other) const { return !(*this == other); }
};
/**

MODIFY
src/processortab.cpp
src/processortab.cpp
@@ -371,12 +371,18 @@ void ProcessorTab::updateInstructionModel() {
QHeaderView::ResizeToContents);
m_ui->instructionView->horizontalHeader()->setSectionResizeMode(InstructionModel::PC,
QHeaderView::ResizeToContents);
- m_ui->instructionView->horizontalHeader()->setSectionResizeMode(InstructionModel::Stage,
- QHeaderView::ResizeToContents);
+ // The "stage" section is _NOT_ resized to contents. Resize to contents is very slow if # of items in the model is
+ // large and the contents of the rows change frequently.
+ m_ui->instructionView->horizontalHeader()->setSectionResizeMode(InstructionModel::Stage, QHeaderView::Interactive);
+ auto ivfm = QFontMetrics(m_ui->instructionView->font());
+ m_ui->instructionView->horizontalHeader()->resizeSection(
+ InstructionModel::Stage,
+ ivfm.horizontalAdvance(
+ m_instrModel->headerData(InstructionModel::Stage, Qt::Horizontal, Qt::DisplayRole).toString()) *
+ 1.25);
m_ui->instructionView->horizontalHeader()->setSectionResizeMode(InstructionModel::Instruction,
QHeaderView::Stretch);
-
- // Make the instruction view follow the instruction which is currently present in the first stage of the processor
+ // Make the instruction view follow the instruction which is currently present in the first stage of the
connect(m_instrModel, &InstructionModel::firstStageInstrChanged, this, &ProcessorTab::setInstructionViewCenterAddr);
if (oldModel) {
@@ -449,7 +455,7 @@ void ProcessorTab::reset() {
}
void ProcessorTab::setInstructionViewCenterAddr(uint32_t address) {
- const auto index = addressToIndex(address);
+ const auto index = addressToRow(address);
const auto view = m_ui->instructionView;
const auto rect = view->rect();
int indexTop = view->indexAt(rect.topLeft()).row();

Fix massive slowdown from resetting InstructionModel on each step