Display cycle count and # Instructions executed
MODIFY
src/pipeline.cpp
src/pipeline.cpp
@@ -584,13 +584,14 @@ void Pipeline::hazardControlGen() {
// Branch/ecall hazard: Result from EX stage is needed, or value from memory is needed.
// This is BOTH for Branch and Ecall instructions, since these instructions work on operands forwarded
// to the ID stage
- bool branchEcallHazardFromMem = ((r1 == (uint32_t)r_writeReg_EXMEM) || (r2 == (uint32_t)r_writeReg_EXMEM))
- && ((uint32_t)r_regWrite_EXMEM & 0b1)
- && (((uint32_t)r_instr_IFID & 0b1111111) == 0b1100011 || ((uint32_t)r_instr_IFID & 0b1111111) == 0b1110011);
+ bool branchEcallHazardFromMem =
+ ((r1 == (uint32_t)r_writeReg_EXMEM) || (r2 == (uint32_t)r_writeReg_EXMEM)) &&
+ ((uint32_t)r_regWrite_EXMEM & 0b1) &&
+ (((uint32_t)r_instr_IFID & 0b1111111) == 0b1100011 || ((uint32_t)r_instr_IFID & 0b1111111) == 0b1110011);
- bool branchEcallHazardFromEx = (r1 == (uint32_t)r_writeReg_IDEX || r2 == (uint32_t)r_writeReg_IDEX)
- && ((uint32_t)r_regWrite_IDEX & 0b1)
- && (((uint32_t)r_instr_IFID & 0b1111111) == 0b1100011 || ((uint32_t)r_instr_IFID & 0b1111111) == 0b1110011);
+ bool branchEcallHazardFromEx =
+ (r1 == (uint32_t)r_writeReg_IDEX || r2 == (uint32_t)r_writeReg_IDEX) && ((uint32_t)r_regWrite_IDEX & 0b1) &&
+ (((uint32_t)r_instr_IFID & 0b1111111) == 0b1100011 || ((uint32_t)r_instr_IFID & 0b1111111) == 0b1110011);
bool branchHazard = branchEcallHazardFromMem || branchEcallHazardFromEx;
@@ -758,8 +759,8 @@ void Pipeline::propagateCombinational() {
}
void Pipeline::handleEcall() {
- if (((uint32_t)r_instr_IFID & 0b1111111) == 0b1110011
- && static_cast<bool>(s_IFID_write) // For checking load-use hazard
+ if (((uint32_t)r_instr_IFID & 0b1111111) == 0b1110011 &&
+ static_cast<bool>(s_IFID_write) // For checking load-use hazard
) {
// ecall in EX stage
uint32_t a0 = (uint32_t)mux_forwardA_ID;
@@ -772,7 +773,6 @@ void Pipeline::handleEcall() {
m_finishing = true;
}
}
-
}
std::pair<Pipeline::ECALL, int32_t> Pipeline::checkEcall(bool reset) {
@@ -788,6 +788,13 @@ int Pipeline::step() {
// propagates the signals throgh the combinational logic and clocks the
// sequential logic afterwards - similar to clocking a circuit
+ m_cycleCount++;
+
+ // We define an instruction as being executed if the IDEX stage clocks in a new instruction
+ if (s_IFID_write) {
+ m_instructionsExecuted++;
+ }
+
// Clock inter-stage registers
m_reg.clock();
if (r_MemWrite_EXMEM) {
@@ -902,6 +909,8 @@ void Pipeline::restart() {
m_finishing = false;
m_abort = false;
m_finishingCnt = 0;
+ m_instructionsExecuted = 0;
+ m_cycleCount = 0;
m_pcsCycles.clear();
m_RVAccesses.clear();

MODIFY
src/pipeline.h
src/pipeline.h
@@ -39,6 +39,8 @@ public:
bool isReady() const { return m_ready; }
bool isFinished() const { return m_finished; }
const std::vector<StagePCS>& getPcsList() { return m_pcsCycles; }
+ int getCycleCount() const { return m_cycleCount; }
+ int getInstructionsExecuted() const { return m_instructionsExecuted; }
static Pipeline* getPipeline() {
static Pipeline pipeline;
@@ -62,6 +64,9 @@ private:
ECALL m_ecallArg;
int32_t m_ecallVal;
+ unsigned int m_instructionsExecuted = 0;
+ unsigned int m_cycleCount = 0;
+
// Program counters for each stage
void setStagePCS();
StagePCS m_pcs;

MODIFY
src/processortab.cpp
src/processortab.cpp
@@ -32,14 +32,13 @@ ProcessorTab::ProcessorTab(QWidget* parent) : QWidget(parent), m_ui(new Ui::Proc
// Setup updating signals
connect(this, &ProcessorTab::update, m_ui->registerContainer, &RegisterContainerWidget::update);
connect(this, &ProcessorTab::update, m_ui->pipelineWidget, &PipelineWidget::update);
-
+ connect(this, &ProcessorTab::update, this, &ProcessorTab::updateMetrics);
// Connect ECALL functionality to application output log and scroll to bottom
- connect(this, &ProcessorTab::appendToLog,
- [this](QString string) { m_ui->console->insertPlainText(string);
- m_ui->console->verticalScrollBar()->setValue(
- m_ui->console->verticalScrollBar()->maximum());});
-
+ connect(this, &ProcessorTab::appendToLog, [this](QString string) {
+ m_ui->console->insertPlainText(string);
+ m_ui->console->verticalScrollBar()->setValue(m_ui->console->verticalScrollBar()->maximum());
+ });
// Setup splitter such that consoles are always as small as possible
m_ui->pipelinesplitter->setStretchFactor(0, 2);
@@ -49,7 +48,6 @@ ProcessorTab::ProcessorTab(QWidget* parent) : QWidget(parent), m_ui(new Ui::Proc
<< (m_ui->consolesTab->minimumHeight() + 1));
m_ui->consolesTab->removeTab(1);
-
// Initially, no file is loaded, disable run, step and reset buttons
m_ui->reset->setEnabled(false);
m_ui->step->setEnabled(false);
@@ -91,6 +89,11 @@ void ProcessorTab::initRegWidget() {
m_ui->registerContainer->init();
}
+void ProcessorTab::updateMetrics() {
+ m_ui->cycleCount->setText(QString::number(Pipeline::getPipeline()->getCycleCount()));
+ m_ui->nInstrExecuted->setText(QString::number(Pipeline::getPipeline()->getInstructionsExecuted()));
+}
+
void ProcessorTab::initInstructionView() {
// Setup instruction view
m_instrModel = new InstructionModel(Pipeline::getPipeline()->getStagePCS(),

MODIFY
src/processortab.h
src/processortab.h
@@ -43,6 +43,8 @@ private slots:
void on_table_clicked();
+ void updateMetrics();
+
private:
bool handleEcall(const std::pair<Pipeline::ECALL, int32_t>& ecallValue);

MODIFY
src/processortab.ui
src/processortab.ui
</layout>
</widget>
<widget class="QWidget" name="verticalLayoutWidget">
- <layout class="QVBoxLayout" name="verticalLayout_4" stretch="1,1">
+ <layout class="QVBoxLayout" name="verticalLayout_4" stretch="1,1,0,0">
<item>
<widget class="RegisterContainerWidget" name="registerContainer" native="true">
<property name="minimumSize">
</layout>
</widget>
</item>
+ <item>
+ <layout class="QHBoxLayout" name="horizontalLayout_4">
+ <item>
+ <widget class="QLabel" name="label_3">
+ <property name="text">
+ <string>Cycle count:</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QLineEdit" name="cycleCount">
+ <property name="readOnly">
+ <bool>true</bool>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </item>
+ <item>
+ <layout class="QHBoxLayout" name="horizontalLayout_3">
+ <item>
+ <widget class="QLabel" name="nInstrExecutedLabel">
+ <property name="text">
+ <string># instructions executed:</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QLineEdit" name="nInstrExecuted">
+ <property name="readOnly">
+ <bool>true</bool>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </item>
</layout>
</widget>
</widget>

Display cycle count and # Instructions executed