From 95956a7457a1237385a314212c4e106bed88f05d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Karel=20Ko=C4=8D=C3=AD?= Date: Tue, 17 Apr 2018 12:44:44 +0200 Subject: Initial implementation of cache view It needs some more work to look nice but it already works. --- qtmips_gui/cachedock.cpp | 17 +++++-- qtmips_gui/cachedock.h | 4 ++ qtmips_gui/cacheview.cpp | 118 ++++++++++++++++++++++++++++++++++++++++++++++ qtmips_gui/cacheview.h | 39 +++++++++++++++ qtmips_gui/mainwindow.cpp | 4 +- qtmips_gui/qtmips_gui.pro | 2 + 6 files changed, 178 insertions(+), 6 deletions(-) create mode 100644 qtmips_gui/cacheview.cpp create mode 100644 qtmips_gui/cacheview.h (limited to 'qtmips_gui') diff --git a/qtmips_gui/cachedock.cpp b/qtmips_gui/cachedock.cpp index eb96e06..79097b3 100644 --- a/qtmips_gui/cachedock.cpp +++ b/qtmips_gui/cachedock.cpp @@ -18,7 +18,10 @@ CacheDock::CacheDock(QWidget *parent, const QString &type) : QDockWidget(parent) l_miss = new QLabel("0", top_form); layout_top_form->addRow("Miss:", l_miss); - // TODO cache view + graphicsview = new GraphicsView(top_widget); + graphicsview->setVisible(false); + layout_box->addWidget(graphicsview); + cachescene = nullptr; setObjectName(type + "Cache"); setWindowTitle(type + " Cache"); @@ -27,12 +30,18 @@ CacheDock::CacheDock(QWidget *parent, const QString &type) : QDockWidget(parent) void CacheDock::setup(const machine::Cache *cache) { l_hit->setText("0"); l_miss->setText("0"); - if (cache) { + 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))); } - top_form->setVisible((bool)cache); - no_cache->setVisible(!(bool)cache); + top_form->setVisible(cache->config().enabled()); + no_cache->setVisible(!cache->config().enabled()); + + if (cachescene) + delete cachescene; + cachescene = new CacheViewScene(cache); + graphicsview->setScene(cachescene); + graphicsview->setVisible(cache->config().enabled()); } void CacheDock::hit_update(unsigned val) { diff --git a/qtmips_gui/cachedock.h b/qtmips_gui/cachedock.h index a13cd08..598a9c7 100644 --- a/qtmips_gui/cachedock.h +++ b/qtmips_gui/cachedock.h @@ -4,6 +4,8 @@ #include #include #include +#include "cacheview.h" +#include "graphicsview.h" #include "qtmipsmachine.h" class CacheDock : public QDockWidget { @@ -22,6 +24,8 @@ private: QWidget *top_widget, *top_form; QFormLayout *layout_top_form; QLabel *l_hit, *l_miss, *no_cache; + GraphicsView *graphicsview; + CacheViewScene *cachescene; }; #endif // CACHEDOCK_H diff --git a/qtmips_gui/cacheview.cpp b/qtmips_gui/cacheview.cpp new file mode 100644 index 0000000..8582e63 --- /dev/null +++ b/qtmips_gui/cacheview.cpp @@ -0,0 +1,118 @@ +#include "cacheview.h" + +////////////////////// +#define ROW_HEIGHT 14 +#define VD_WIDTH 10 +#define DATA_WIDTH 72 +#define PENW 1 +////////////////////// + +CacheViewBlock::CacheViewBlock(const machine::Cache *cache, unsigned block) : QGraphicsObject(nullptr) { + this->block = block; + rows = cache->config().sets(); + columns = cache->config().blocks(); + + QFont font; + font.setPointSize(7); + + validity = new QGraphicsSimpleTextItem*[rows]; + if (cache->config().write_policy() == machine::MachineConfigCache::WP_BACK) + dirty = new QGraphicsSimpleTextItem*[rows]; + else + dirty = nullptr; + tag = new QGraphicsSimpleTextItem*[rows]; + data = new QGraphicsSimpleTextItem**[rows]; + int row_y = 1; + for (unsigned i = 0; i < rows; i++) { + int row_x = 2; + validity[i] = new QGraphicsSimpleTextItem("0", this); + validity[i]->setPos(row_x, row_y); + validity[i]->setFont(font); + row_x += VD_WIDTH; + if (dirty) { + dirty[i] = new QGraphicsSimpleTextItem(this); + dirty[i]->setPos(row_x, row_y); + dirty[i]->setFont(font); + row_x += VD_WIDTH; + } + tag[i] = new QGraphicsSimpleTextItem(this); + tag[i]->setPos(row_x, row_y); + tag[i]->setFont(font); + row_x += DATA_WIDTH; + + data[i] = new QGraphicsSimpleTextItem*[columns]; + for (unsigned y = 0; y < columns; y++) { + data[i][y] = new QGraphicsSimpleTextItem(this); + data[i][y]->setPos(row_x, row_y); + data[i][y]->setFont(font); + row_x += DATA_WIDTH; + } + + row_y += ROW_HEIGHT; + } + + connect(cache, SIGNAL(cache_update(uint,uint,bool,bool,std::uint32_t,const std::uint32_t*)), this, SLOT(cache_update(uint,uint,bool,bool,std::uint32_t,const std::uint32_t*))); +} + +CacheViewBlock::~CacheViewBlock() { + delete validity; + delete dirty; + delete tag; + for (unsigned y = 0; y < rows; y++) + delete data[y]; + delete data; +} + +QRectF CacheViewBlock::boundingRect() const { + return QRectF( + -PENW / 2, + -PENW / 2, + VD_WIDTH + (dirty ? VD_WIDTH : 0) + DATA_WIDTH*(columns+1) + PENW, + ROW_HEIGHT*rows + PENW + ); +} + +void CacheViewBlock::paint(QPainter *painter, const QStyleOptionGraphicsItem *option __attribute__((unused)), QWidget *widget __attribute__((unused))) { + // Draw horizontal lines + for (unsigned i = 0; i <= rows; i++) + painter->drawLine(0, i * ROW_HEIGHT, VD_WIDTH + (dirty ? VD_WIDTH : 0) + DATA_WIDTH*(columns + 1), i * ROW_HEIGHT); + // Draw vertical lines + painter->drawLine(0, 0, 0, rows*ROW_HEIGHT); + int c_width = VD_WIDTH; + painter->drawLine(c_width, 0, c_width, rows*ROW_HEIGHT); + if (dirty) { + c_width += VD_WIDTH; + painter->drawLine(c_width, 0, c_width, rows*ROW_HEIGHT); + } + c_width += DATA_WIDTH; + painter->drawLine(c_width, 0, c_width, rows*ROW_HEIGHT); + for (unsigned i = 0; i <= columns; i++) { + c_width += DATA_WIDTH; + painter->drawLine(c_width, 0, c_width, rows*ROW_HEIGHT); + } +} + +void CacheViewBlock::cache_update(unsigned associat, unsigned set, bool valid, bool dirty, std::uint32_t tag, const std::uint32_t *data) { + if (associat != block) + return; // Ignore blocks that are not us + validity[set]->setText(valid ? "1" : "0"); + if (this->dirty) + this->dirty[set]->setText(valid ? (dirty ? "1" : "0") : ""); + // TODO calculate correct size of tag + this->tag[set]->setText(valid ? QString("0x") + QString("%1").arg(tag, 8, 16, QChar('0')).toUpper() : ""); + for (unsigned i = 0; i < columns; i++) + this->data[set][i]->setText(valid ? QString("0x") + QString("%1").arg(data[i], 8, 16, QChar('0')).toUpper() : ""); +} + + +CacheViewScene::CacheViewScene(const machine::Cache *cache) { + associativity = cache->config().associativity(); + block = new CacheViewBlock*[associativity]; + int offset = 0; + for (unsigned i = 0; i < associativity; i++) { + block[i] = new CacheViewBlock(cache, i); + addItem(block[i]); + block[i]->setPos(1, offset); + offset += block[i]->boundingRect().height() + 3; + } +} diff --git a/qtmips_gui/cacheview.h b/qtmips_gui/cacheview.h new file mode 100644 index 0000000..1fb224f --- /dev/null +++ b/qtmips_gui/cacheview.h @@ -0,0 +1,39 @@ +#ifndef CACHEVIEW_H +#define CACHEVIEW_H + +#include +#include +#include +#include "graphicsview.h" +#include "qtmipsmachine.h" + +class CacheViewBlock : public QGraphicsObject { + Q_OBJECT +public: + CacheViewBlock(const machine::Cache *cache, unsigned block); + ~CacheViewBlock(); + + QRectF boundingRect() const; + + void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget); + +private slots: + void cache_update(unsigned associat, unsigned set, bool valid, bool dirty, std::uint32_t tag, const std::uint32_t *data); + +private: + unsigned block; + unsigned rows, columns; + QGraphicsSimpleTextItem **validity, **dirty, **tag, ***data; +}; + +class CacheViewScene : public QGraphicsScene { + Q_OBJECT +public: + CacheViewScene(const machine::Cache *cache); + +private: + unsigned associativity; + CacheViewBlock **block; +}; + +#endif // CACHEVIEW_H diff --git a/qtmips_gui/mainwindow.cpp b/qtmips_gui/mainwindow.cpp index d3434bc..4fb9cbf 100644 --- a/qtmips_gui/mainwindow.cpp +++ b/qtmips_gui/mainwindow.cpp @@ -118,8 +118,8 @@ void MainWindow::create_core(const machine::MachineConfig &config) { registers->setup(machine); program->setup(machine); memory->setup(machine); - cache_program->setup(machine->config().cache_program().enabled() ? machine->cache_program() : nullptr); - cache_data->setup(machine->config().cache_data().enabled() ? machine->cache_data() : nullptr); + cache_program->setup(machine->cache_program()); + cache_data->setup(machine->cache_data()); // Set status to ready machine_status(machine::QtMipsMachine::ST_READY); } diff --git a/qtmips_gui/qtmips_gui.pro b/qtmips_gui/qtmips_gui.pro index e12eaef..eb5f392 100644 --- a/qtmips_gui/qtmips_gui.pro +++ b/qtmips_gui/qtmips_gui.pro @@ -36,6 +36,7 @@ SOURCES += \ coreview/logicblock.cpp \ coreview/and.cpp \ statictable.cpp \ + cacheview.cpp \ cachedock.cpp \ graphicsview.cpp @@ -61,6 +62,7 @@ HEADERS += \ coreview/logicblock.h \ coreview/and.h \ statictable.h \ + cacheview.h \ cachedock.h \ graphicsview.h -- cgit v1.2.3