From 7775c330d50d5fdd7abf7e3494a938264f5ac28c Mon Sep 17 00:00:00 2001 From: Morten Borup Petersen Date: Sat, 26 Mar 2022 13:10:19 -0400 Subject: [PATCH] Implement iterator interface for stages in ProcessorStructure #203 --- src/editor/codeeditor.cpp | 44 +++++++--------- src/instructionmodel.cpp | 58 ++++++++++----------- src/pipelinediagrammodel.cpp | 10 ++-- src/processors/interface/ripesprocessor.h | 63 ++++++++++++++++++++--- src/processortab.cpp | 46 +++++++---------- src/programviewer.cpp | 27 +++++----- 6 files changed, 136 insertions(+), 112 deletions(-) diff --git a/src/editor/codeeditor.cpp b/src/editor/codeeditor.cpp index d1562e02c..10ef67a36 100644 --- a/src/editor/codeeditor.cpp +++ b/src/editor/codeeditor.cpp @@ -445,31 +445,27 @@ void CodeEditor::updateHighlighting() { const unsigned stages = proc->structure().numStages(); auto colorGenerator = Colors::incrementalRedGenerator(stages); - for (auto laneIt : proc->structure()) { - for (unsigned stageIdx = 0; stageIdx < laneIt.second; stageIdx++) { - StageIndex sid = StageIndex{laneIt.first, stageIdx}; - const auto stageInfo = proc->stageInfo(sid); - QColor stageColor = colorGenerator(); - if (stageInfo.stage_valid) { - auto mappingIt = sourceMapping.find(stageInfo.pc); - if (mappingIt == sourceMapping.end()) { - // No source line registerred for this PC. + for (auto sid : proc->structure().stageIt()) { + const auto stageInfo = proc->stageInfo(sid); + QColor stageColor = colorGenerator(); + if (stageInfo.stage_valid) { + auto mappingIt = sourceMapping.find(stageInfo.pc); + if (mappingIt == sourceMapping.end()) { + // No source line registerred for this PC. + continue; + } + + for (auto sourceLine : mappingIt->second) { + // Find block + QTextBlock block = document()->findBlockByLineNumber(sourceLine); + if (!block.isValid()) continue; - } - - for (auto sourceLine : mappingIt->second) { - // Find block - QTextBlock block = document()->findBlockByLineNumber(sourceLine); - if (!block.isValid()) - continue; - - // Record the stage name for the highlighted block for later painting - QString stageString = - ProcessorHandler::getProcessor()->stageName(sid); - if (!stageInfo.namedState.isEmpty()) - stageString += " (" + stageInfo.namedState + ")"; - highlightBlock(block, stageColor, stageString); - } + + // Record the stage name for the highlighted block for later painting + QString stageString = ProcessorHandler::getProcessor()->stageName(sid); + if (!stageInfo.namedState.isEmpty()) + stageString += " (" + stageInfo.namedState + ")"; + highlightBlock(block, stageColor, stageString); } } } diff --git a/src/instructionmodel.cpp b/src/instructionmodel.cpp index 6e113cc2a..b45f50e00 100644 --- a/src/instructionmodel.cpp +++ b/src/instructionmodel.cpp @@ -27,12 +27,9 @@ int InstructionModel::addressToRow(AInt addr) const { InstructionModel::InstructionModel(QObject *parent) : QAbstractTableModel(parent) { - for (auto laneIt : ProcessorHandler::getProcessor()->structure()) { - for (unsigned stageIdx = 0; stageIdx < laneIt.second; stageIdx++) { - StageIndex idx = {laneIt.first, stageIdx}; - m_stageNames[idx] = ProcessorHandler::getProcessor()->stageName(idx); - m_stageInfos[idx] = ProcessorHandler::getProcessor()->stageInfo(idx); - } + for (auto idx : ProcessorHandler::getProcessor()->structure().stageIt()) { + m_stageNames[idx] = ProcessorHandler::getProcessor()->stageName(idx); + m_stageInfos[idx] = ProcessorHandler::getProcessor()->stageInfo(idx); } connect(ProcessorHandler::get(), &ProcessorHandler::procStateChangedNonRun, this, &InstructionModel::updateStageInfo); @@ -67,34 +64,31 @@ int InstructionModel::rowCount(const QModelIndex &) const { return m_rowCount; } void InstructionModel::updateStageInfo() { bool firstStageChanged = false; - for (auto laneIt : ProcessorHandler::getProcessor()->structure()) { - for (unsigned stageIdx = 0; stageIdx < laneIt.second; stageIdx++) { - StageIndex idx = {laneIt.first, stageIdx}; - auto stageInfoIt = m_stageInfos.find(idx); - if (stageInfoIt != m_stageInfos.end()) { - auto &oldStageInfo = m_stageInfos.at(idx); - if (idx == StageIndex(0, 0)) { - if (oldStageInfo.pc != - ProcessorHandler::getProcessor()->stageInfo(idx).pc) { - firstStageChanged = true; - } - } - const auto stageInfo = ProcessorHandler::getProcessor()->stageInfo(idx); - const AInt oldAddress = oldStageInfo.pc; - if (oldStageInfo != stageInfo) { - oldStageInfo = stageInfo; - 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(addressToRow(m_stageInfos.at({0, 0}).pc)); - firstStageChanged = false; + for (auto idx : ProcessorHandler::getProcessor()->structure().stageIt()) { + auto stageInfoIt = m_stageInfos.find(idx); + if (stageInfoIt != m_stageInfos.end()) { + auto &oldStageInfo = m_stageInfos.at(idx); + if (idx == StageIndex(0, 0)) { + if (oldStageInfo.pc != + ProcessorHandler::getProcessor()->stageInfo(idx).pc) { + firstStageChanged = true; } } + const auto stageInfo = ProcessorHandler::getProcessor()->stageInfo(idx); + const AInt oldAddress = oldStageInfo.pc; + if (oldStageInfo != stageInfo) { + oldStageInfo = stageInfo; + 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(addressToRow(m_stageInfos.at({0, 0}).pc)); + firstStageChanged = false; + } } } } diff --git a/src/pipelinediagrammodel.cpp b/src/pipelinediagrammodel.cpp index af7e965f8..46df90073 100644 --- a/src/pipelinediagrammodel.cpp +++ b/src/pipelinediagrammodel.cpp @@ -76,13 +76,9 @@ void PipelineDiagramModel::gatherStageInfo() { if (stageInfoForCycle == m_cycleStageInfos.end()) { return; } - for (auto laneIt : ProcessorHandler::getProcessor()->structure()) { - for (unsigned stageIdx = 0; stageIdx < laneIt.second; stageIdx++) { - StageIndex idx = {laneIt.first, stageIdx}; - stageInfoForCycle->second[idx] = - ProcessorHandler::getProcessor()->stageInfo(idx); - } - } + for (auto idx : ProcessorHandler::getProcessor()->structure().stageIt()) + stageInfoForCycle->second[idx] = + ProcessorHandler::getProcessor()->stageInfo(idx); } QVariant PipelineDiagramModel::data(const QModelIndex &index, int role) const { diff --git a/src/processors/interface/ripesprocessor.h b/src/processors/interface/ripesprocessor.h index d3466f453..32245818a 100644 --- a/src/processors/interface/ripesprocessor.h +++ b/src/processors/interface/ripesprocessor.h @@ -44,20 +44,69 @@ struct MemoryAccess { struct StageIndex : public std::pair { using std::pair::pair; - unsigned lane() const {return this->first;} - unsigned index() const {return this->second;} + unsigned lane() const { return this->first; } + unsigned index() const { return this->second; } }; - -/// Structural description of the processor model. Currently this is a map of {# of lanes, # of stages}. +/// Structural description of the processor model. Currently this is a map of {# +/// of lanes, # of stages}. /// @todo: add an iterator over all stages. struct ProcessorStructure : public std::map { using std::map::map; + struct StageIterator { + StageIterator(const ProcessorStructure &structure) + : m_structure(structure) {} + + struct Iterator { + using iterator_category = std::forward_iterator_tag; + using difference_type = std::ptrdiff_t; + using value_type = StageIndex; + using pointer = value_type *; + using reference = value_type &; + + Iterator(unsigned lane, unsigned index, + const ProcessorStructure &structure) + : m_lane(lane), m_index(index), m_structure(structure) {} + StageIndex operator*() const { return {m_lane, m_index}; } + StageIndex operator->() const { return {m_lane, m_index}; } + Iterator &operator++() { + ++m_index; + if (m_index == m_structure.at(m_lane)) { + m_index = 0; + ++m_lane; + } + return *this; + } + Iterator operator++(int) { + Iterator tmp = *this; + ++(*this); + return tmp; + } + bool operator==(const Iterator &other) const { + return m_lane == other.m_lane && m_index == other.m_index; + } + bool operator!=(const Iterator &other) const { return !(*this == other); } + + unsigned m_lane = 0; + unsigned m_index = 0; + const ProcessorStructure &m_structure; + }; + + Iterator begin() const { return Iterator(0, 0, m_structure); } + Iterator end() const { + return Iterator(m_structure.size(), 0, m_structure); + } + const ProcessorStructure &m_structure; + }; + + // Returns an iterator over all stages. + StageIterator stageIt() const { return {*this}; } + // Returns the total number of stages of this processor. unsigned numStages() const { unsigned count = 0; - for(auto it : *this) + for (auto it : *this) count += it.second; return count; } @@ -129,9 +178,7 @@ class RipesProcessor { * @brief stageCount * @return number of stages for the processor */ - virtual const ProcessorStructure& structure() const = 0; - - + virtual const ProcessorStructure &structure() const = 0; /** * @brief getPcForStage diff --git a/src/processortab.cpp b/src/processortab.cpp index 5453d47ad..a80796610 100644 --- a/src/processortab.cpp +++ b/src/processortab.cpp @@ -186,15 +186,12 @@ void ProcessorTab::loadLayout(const Layout &layout) { // Adjust stage label positions const auto &parent = m_stageInstructionLabels.at({0, 0})->parentItem(); - for (auto laneIt : ProcessorHandler::getProcessor()->structure()) { - for (unsigned stageIdx = 0; stageIdx < laneIt.second; stageIdx++) { - StageIndex sid = {laneIt.first, stageIdx}; - auto &label = m_stageInstructionLabels.at(sid); - QFontMetrics metrics(label->font()); - label->setPos(parent->boundingRect().width() * - layout.stageLabelPositions.at(sid).x(), - metrics.height() * layout.stageLabelPositions.at(sid).y()); - } + for (auto sid : ProcessorHandler::getProcessor()->structure().stageIt()) { + auto &label = m_stageInstructionLabels.at(sid); + QFontMetrics metrics(label->font()); + label->setPos(parent->boundingRect().width() * + layout.stageLabelPositions.at(sid).x(), + metrics.height() * layout.stageLabelPositions.at(sid).y()); } } @@ -473,16 +470,14 @@ void ProcessorTab::enableSimulatorControls() { void ProcessorTab::updateInstructionLabels() { const auto &proc = ProcessorHandler::getProcessor(); - for (auto laneIt : ProcessorHandler::getProcessor()->structure()) { - for (unsigned stageIdx = 0; stageIdx < laneIt.second; stageIdx++) { - StageIndex sid = {laneIt.first, stageIdx}; - if (!m_stageInstructionLabels.count(sid)) - continue; - const auto stageInfo = proc->stageInfo(sid); - auto &instrLabel = m_stageInstructionLabels.at(sid); - QString instrString; - if (stageInfo.state != StageInfo::State::None) { - /* clang-format off */ + for (auto sid : ProcessorHandler::getProcessor()->structure().stageIt()) { + if (!m_stageInstructionLabels.count(sid)) + continue; + const auto stageInfo = proc->stageInfo(sid); + auto &instrLabel = m_stageInstructionLabels.at(sid); + QString instrString; + if (stageInfo.state != StageInfo::State::None) { + /* clang-format off */ switch (stageInfo.state) { case StageInfo::State::Flushed: instrString = "nop (flush)"; break; case StageInfo::State::Stalled: instrString = "nop (stall)"; break; @@ -490,14 +485,13 @@ void ProcessorTab::updateInstructionLabels() { case StageInfo::State::Unused: instrString = "nop (unused)"; break; case StageInfo::State::None: Q_UNREACHABLE(); } - /* clang-format on */ - instrLabel->forceDefaultTextColor(Qt::red); - } else if (stageInfo.stage_valid) { - instrString = ProcessorHandler::disassembleInstr(stageInfo.pc); - instrLabel->clearForcedDefaultTextColor(); - } - instrLabel->setText(instrString); + /* clang-format on */ + instrLabel->forceDefaultTextColor(Qt::red); + } else if (stageInfo.stage_valid) { + instrString = ProcessorHandler::disassembleInstr(stageInfo.pc); + instrLabel->clearForcedDefaultTextColor(); } + instrLabel->setText(instrString); } } diff --git a/src/programviewer.cpp b/src/programviewer.cpp index c7b644df2..2810ba64c 100644 --- a/src/programviewer.cpp +++ b/src/programviewer.cpp @@ -105,21 +105,18 @@ void ProgramViewer::updateHighlightedAddresses() { ProcessorHandler::getProcessor()->structure().numStages(); auto colorGenerator = Colors::incrementalRedGenerator(stages); - for (auto laneIt : ProcessorHandler::getProcessor()->structure()) { - for (unsigned stageIdx = 0; stageIdx < laneIt.second; stageIdx++) { - StageIndex sid = {laneIt.first, stageIdx}; - const auto stageInfo = ProcessorHandler::getProcessor()->stageInfo(sid); - if (stageInfo.stage_valid) { - auto block = blockForAddress(stageInfo.pc); - if (!block.isValid()) - continue; - - // Record the stage name for the highlighted block for later painting - QString stageString = ProcessorHandler::getProcessor()->stageName(sid); - if (!stageInfo.namedState.isEmpty()) - stageString += " (" + stageInfo.namedState + ")"; - highlightBlock(block, colorGenerator(), stageString); - } + for (auto sid : ProcessorHandler::getProcessor()->structure().stageIt()) { + const auto stageInfo = ProcessorHandler::getProcessor()->stageInfo(sid); + if (stageInfo.stage_valid) { + auto block = blockForAddress(stageInfo.pc); + if (!block.isValid()) + continue; + + // Record the stage name for the highlighted block for later painting + QString stageString = ProcessorHandler::getProcessor()->stageName(sid); + if (!stageInfo.namedState.isEmpty()) + stageString += " (" + stageInfo.namedState + ")"; + highlightBlock(block, colorGenerator(), stageString); } }