aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKarel Kočí <cynerd@email.cz>2018-05-23 20:23:10 +0200
committerKarel Kočí <cynerd@email.cz>2018-05-23 20:23:10 +0200
commitddde26b916c99078421992100849101455756415 (patch)
tree25a8dee1fb6ae3a78d5a46e2aabd5aa4f8bb7fb3
parentf1fc0fc1ad628d19382fe2a026a767af6f6ba12f (diff)
downloadqtmips-ddde26b916c99078421992100849101455756415.tar.gz
qtmips-ddde26b916c99078421992100849101455756415.tar.bz2
qtmips-ddde26b916c99078421992100849101455756415.zip
Add cache statistics
-rw-r--r--qtmips_gui/NewDialog.ui20
-rw-r--r--qtmips_gui/cachedock.cpp16
-rw-r--r--qtmips_gui/cachedock.h3
-rw-r--r--qtmips_machine/cache.cpp65
-rw-r--r--qtmips_machine/cache.h10
-rw-r--r--qtmips_machine/machineconfig.cpp4
-rw-r--r--qtmips_machine/qtmipsmachine.cpp4
7 files changed, 99 insertions, 23 deletions
diff --git a/qtmips_gui/NewDialog.ui b/qtmips_gui/NewDialog.ui
index 135ac83..6e6a3ec 100644
--- a/qtmips_gui/NewDialog.ui
+++ b/qtmips_gui/NewDialog.ui
@@ -29,7 +29,7 @@
<item>
<widget class="QTabWidget" name="tabWidget">
<property name="currentIndex">
- <number>0</number>
+ <number>2</number>
</property>
<widget class="QWidget" name="tab">
<attribute name="title">
@@ -225,7 +225,14 @@
</widget>
</item>
<item row="0" column="1">
- <widget class="QSpinBox" name="mem_time_read"/>
+ <widget class="QSpinBox" name="mem_time_read">
+ <property name="minimum">
+ <number>1</number>
+ </property>
+ <property name="maximum">
+ <number>999999999</number>
+ </property>
+ </widget>
</item>
<item row="1" column="0">
<widget class="QLabel" name="label_3">
@@ -235,7 +242,14 @@
</widget>
</item>
<item row="1" column="1">
- <widget class="QSpinBox" name="mem_time_write"/>
+ <widget class="QSpinBox" name="mem_time_write">
+ <property name="minimum">
+ <number>1</number>
+ </property>
+ <property name="maximum">
+ <number>999999999</number>
+ </property>
+ </widget>
</item>
</layout>
</widget>
diff --git a/qtmips_gui/cachedock.cpp b/qtmips_gui/cachedock.cpp
index 79097b3..8e63565 100644
--- a/qtmips_gui/cachedock.cpp
+++ b/qtmips_gui/cachedock.cpp
@@ -17,6 +17,12 @@ CacheDock::CacheDock(QWidget *parent, const QString &type) : QDockWidget(parent)
layout_top_form->addRow("Hit:", l_hit);
l_miss = new QLabel("0", top_form);
layout_top_form->addRow("Miss:", l_miss);
+ l_stalled = new QLabel("0", top_form);
+ layout_top_form->addRow("Memory stall cycles:", l_stalled);
+ l_usage = new QLabel("0.000%", top_form);
+ layout_top_form->addRow("Usage effectiveness:", l_usage);
+ l_speed = new QLabel("100%", top_form);
+ layout_top_form->addRow("Speed improvement:", l_speed);
graphicsview = new GraphicsView(top_widget);
graphicsview->setVisible(false);
@@ -30,9 +36,13 @@ CacheDock::CacheDock(QWidget *parent, const QString &type) : QDockWidget(parent)
void CacheDock::setup(const machine::Cache *cache) {
l_hit->setText("0");
l_miss->setText("0");
+ l_stalled->setText("0");
+ l_usage->setText("0.000%");
+ l_speed->setText("100%");
if (cache->config().enabled()) {
connect(cache, SIGNAL(hit_update(uint)), this, SLOT(hit_update(uint)));
connect(cache, SIGNAL(miss_update(uint)), this, SLOT(miss_update(uint)));
+ connect(cache, SIGNAL(statistics_update(uint,double,double)), this, SLOT(statistics_update(uint,double,double)));
}
top_form->setVisible(cache->config().enabled());
no_cache->setVisible(!cache->config().enabled());
@@ -51,3 +61,9 @@ void CacheDock::hit_update(unsigned val) {
void CacheDock::miss_update(unsigned val) {
l_miss->setText(QString::number(val));
}
+
+void CacheDock::statistics_update(unsigned stalled_cycles, double speed_improv, double usage_effic) {
+ l_stalled->setText(QString::number(stalled_cycles));
+ l_usage->setText(QString::number(usage_effic, 'f', 3) + QString("%"));
+ l_speed->setText(QString::number(speed_improv, 'f', 0) + QString("%"));
+}
diff --git a/qtmips_gui/cachedock.h b/qtmips_gui/cachedock.h
index 598a9c7..7e5ac44 100644
--- a/qtmips_gui/cachedock.h
+++ b/qtmips_gui/cachedock.h
@@ -18,12 +18,13 @@ public:
private slots:
void hit_update(unsigned);
void miss_update(unsigned);
+ void statistics_update(unsigned stalled_cycles, double speed_improv, double usage_effic);
private:
QVBoxLayout *layout_box;
QWidget *top_widget, *top_form;
QFormLayout *layout_top_form;
- QLabel *l_hit, *l_miss, *no_cache;
+ QLabel *l_hit, *l_miss, *l_stalled, *l_speed, *l_usage, *no_cache;
GraphicsView *graphicsview;
CacheViewScene *cachescene;
};
diff --git a/qtmips_machine/cache.cpp b/qtmips_machine/cache.cpp
index 753027a..acc48b1 100644
--- a/qtmips_machine/cache.cpp
+++ b/qtmips_machine/cache.cpp
@@ -2,11 +2,15 @@
using namespace machine;
-Cache::Cache(Memory *m, const MachineConfigCache *cc) : cnf(cc) {
+Cache::Cache(Memory *m, const MachineConfigCache *cc, unsigned memory_access_penalty_r, unsigned memory_access_penalty_w) : cnf(cc) {
mem = m;
+ access_pen_r = memory_access_penalty_r;
+ access_pen_w = memory_access_penalty_w;
// Zero hit and miss rate
- hitc = 0;
- missc = 0;
+ hit_read = 0;
+ hit_write = 0;
+ miss_read = 0;
+ miss_write = 0;
// Skip any other initialization if cache is disabled
if (!cc->enabled())
return;
@@ -73,11 +77,31 @@ void Cache::sync() {
}
unsigned Cache::hit() const {
- return hitc;
+ return hit_read + hit_write;
}
unsigned Cache::miss() const {
- return missc;
+ return miss_read + miss_write;
+}
+
+unsigned Cache::stalled_cycles() const {
+ return miss_read * (access_pen_r - 1) + miss_write * (access_pen_w - 1);
+}
+
+double Cache::speed_improvement() const {
+ unsigned comp = hit_read + hit_write + miss_read + miss_write;
+ if (comp == 0)
+ return 100.0;
+ return (double)((miss_read + hit_read) * access_pen_r + (miss_write + hit_write) * access_pen_w) \
+ / (double)(hit_write + hit_read + miss_read * access_pen_r + miss_write * access_pen_w) \
+ * 100;
+}
+
+double Cache::usage_efficiency() const {
+ unsigned comp = hit_read + hit_write + miss_read + miss_write;
+ if (comp == 0)
+ return 0.0;
+ return (double)(hit_read + hit_write) / (double)comp * 100.0;
}
void Cache::reset() {
@@ -90,11 +114,14 @@ void Cache::reset() {
dt[as][st].valid = false;
// Note: we don't have to zero replacement policy data as those are zeroed when first used on invalid cell
// Zero hit and miss rate
- hitc = 0;
- missc = 0;
+ hit_read = 0;
+ hit_write = 0;
+ miss_read = 0;
+ miss_write = 0;
// Trigger signals
- emit hit_update(hitc);
- emit miss_update(missc);
+ emit hit_update(hit());
+ emit miss_update(miss());
+ update_statistics();
for (unsigned as = 0; as < cnf.associativity(); as++)
for (unsigned st = 0; st < cnf.sets(); st++)
emit cache_update(as, st, false, false, 0, 0);
@@ -157,11 +184,19 @@ void Cache::access(std::uint32_t address, std::uint32_t *data, bool write, std::
// Update statistics and otherwise read from memory
if (cd.valid) {
- hitc++;
- emit hit_update(hitc);
+ if (write)
+ hit_write++;
+ else
+ hit_read++;
+ emit hit_update(hit());
+ update_statistics();
} else {
- missc++;
- emit miss_update(missc);
+ if (write)
+ miss_write++;
+ else
+ miss_read++;
+ emit miss_update(miss());
+ update_statistics();
for (unsigned i = 0; i < cnf.blocks(); i++)
cd.data[i] = mem->rword(base_address(tag, row) + (4*i));
}
@@ -209,3 +244,7 @@ void Cache::kick(unsigned associat_indx, unsigned row) const {
std::uint32_t Cache::base_address(std::uint32_t tag, unsigned row) const {
return ((tag * cnf.blocks() * cnf.sets()) + (row * cnf.blocks())) << 2;
}
+
+void Cache::update_statistics() const {
+ emit statistics_update(stalled_cycles(), speed_improvement(), usage_efficiency());
+}
diff --git a/qtmips_machine/cache.h b/qtmips_machine/cache.h
index d7bd967..6cf3a2c 100644
--- a/qtmips_machine/cache.h
+++ b/qtmips_machine/cache.h
@@ -11,7 +11,7 @@ namespace machine {
class Cache : public MemoryAccess {
Q_OBJECT
public:
- Cache(Memory *m, const MachineConfigCache *c);
+ Cache(Memory *m, const MachineConfigCache *c, unsigned memory_access_penalty_r = 1, unsigned memory_access_penalty_w = 1);
void wword(std::uint32_t address, std::uint32_t value);
std::uint32_t rword(std::uint32_t address) const;
@@ -21,6 +21,9 @@ public:
unsigned hit() const; // Number of recorded hits
unsigned miss() const; // Number of recorded misses
+ unsigned stalled_cycles() const; // Number of wasted cycles in memory waitin statistic
+ double speed_improvement() const; // Speed improvement in percents in comare with no used cache
+ double usage_efficiency() const; // Usage efficiency in percents
void reset(); // Reset whole state of cache
@@ -29,11 +32,13 @@ public:
signals:
void hit_update(unsigned) const;
void miss_update(unsigned) const;
+ void statistics_update(unsigned stalled_cycles, double speed_improv, double usage_effic) const;
void cache_update(unsigned associat, unsigned set, bool valid, bool dirty, std::uint32_t tag, const std::uint32_t *data) const;
private:
MachineConfigCache cnf;
Memory *mem;
+ unsigned access_pen_r, access_pen_w;
struct cache_data {
bool valid, dirty;
@@ -47,11 +52,12 @@ private:
unsigned **lfu; // Access count
} replc; // Data used for replacement policy
- mutable unsigned hitc, missc; // Hit and miss counters
+ mutable unsigned hit_read, miss_read, hit_write, miss_write; // Hit and miss counters
void access(std::uint32_t address, std::uint32_t *data, bool write, std::uint32_t value = 0) const;
void kick(unsigned associat_indx, unsigned row) const;
std::uint32_t base_address(std::uint32_t tag, unsigned row) const;
+ void update_statistics() const;
};
}
diff --git a/qtmips_machine/machineconfig.cpp b/qtmips_machine/machineconfig.cpp
index 13a1ff2..9329795 100644
--- a/qtmips_machine/machineconfig.cpp
+++ b/qtmips_machine/machineconfig.cpp
@@ -284,11 +284,11 @@ bool MachineConfig::memory_write_protection() const {
}
unsigned MachineConfig::memory_access_time_read() const {
- return mem_acc_read;
+ return mem_acc_read > 1 ? mem_acc_read : 1;
}
unsigned MachineConfig::memory_access_time_write() const {
- return mem_acc_write;
+ return mem_acc_write > 1 ? mem_acc_write : 1;
}
QString MachineConfig::elf() const {
diff --git a/qtmips_machine/qtmipsmachine.cpp b/qtmips_machine/qtmipsmachine.cpp
index 4a2b0f2..da4516a 100644
--- a/qtmips_machine/qtmipsmachine.cpp
+++ b/qtmips_machine/qtmipsmachine.cpp
@@ -13,8 +13,8 @@ QtMipsMachine::QtMipsMachine(const MachineConfig &cc) : QObject(), mcnf(&cc) {
regs = new Registers();
mem = new Memory(*mem_program_only);
- cch_program = new Cache(mem, &cc.cache_program());
- cch_data = new Cache(mem, &cc.cache_data());
+ cch_program = new Cache(mem, &cc.cache_program(), cc.memory_access_time_read(), cc.memory_access_time_write());
+ cch_data = new Cache(mem, &cc.cache_data(), cc.memory_access_time_read(), cc.memory_access_time_write());
if (cc.pipelined())
cr = new CorePipelined(regs, cch_program, cch_data, cc.hazard_unit());