diff options
author | Karel Kočí <cynerd@email.cz> | 2017-12-15 22:45:28 +0100 |
---|---|---|
committer | Karel Kočí <cynerd@email.cz> | 2017-12-15 22:45:28 +0100 |
commit | e6ca4b4568e311b47239bfe83de15ed9e91c57b9 (patch) | |
tree | 3da2f72faf360058bae02c35b0c724233bd64d61 /qtmips_gui | |
parent | bbea996112eb7ac81ec50d2af08f4bd681d0e50d (diff) | |
download | qtmips-e6ca4b4568e311b47239bfe83de15ed9e91c57b9.tar.gz qtmips-e6ca4b4568e311b47239bfe83de15ed9e91c57b9.tar.bz2 qtmips-e6ca4b4568e311b47239bfe83de15ed9e91c57b9.zip |
Implement few initial graphic elements
Diffstat (limited to 'qtmips_gui')
-rw-r--r-- | qtmips_gui/coreview.cpp | 48 | ||||
-rw-r--r-- | qtmips_gui/coreview.h | 46 | ||||
-rw-r--r-- | qtmips_gui/coreview/connection.cpp | 79 | ||||
-rw-r--r-- | qtmips_gui/coreview/connection.h | 60 | ||||
-rw-r--r-- | qtmips_gui/coreview/latch.cpp | 51 | ||||
-rw-r--r-- | qtmips_gui/coreview/latch.h | 45 | ||||
-rw-r--r-- | qtmips_gui/coreview/multiplexer.cpp | 79 | ||||
-rw-r--r-- | qtmips_gui/coreview/multiplexer.h | 41 | ||||
-rw-r--r-- | qtmips_gui/coreview/programcounter.cpp | 48 | ||||
-rw-r--r-- | qtmips_gui/coreview/programcounter.h | 42 | ||||
-rw-r--r-- | qtmips_gui/mainwindow.cpp | 26 | ||||
-rw-r--r-- | qtmips_gui/qtmips_gui.pro | 12 |
12 files changed, 515 insertions, 62 deletions
diff --git a/qtmips_gui/coreview.cpp b/qtmips_gui/coreview.cpp index 4d23bd8..660f78d 100644 --- a/qtmips_gui/coreview.cpp +++ b/qtmips_gui/coreview.cpp @@ -1,35 +1,35 @@ #include "coreview.h" -CoreView::CoreView(QWidget *parent) : QGraphicsView(parent) { +CoreView::CoreView(QWidget *parent, QtMipsMachine *machine) : QGraphicsView(parent) { + setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff); + setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff); + setRenderHints(QPainter::Antialiasing | QPainter::SmoothPixmapTransform); -} - -/* -CoreViewBlock::CoreViewBlock() { -} - -CoreViewLine::CoreViewLine() { - -} - -CoreViewLine::CoreViewLine(struct point start, struct point end, QList<struct point> axis) { + this->machine = machine; + // Identification cross + scene.addLine(400, 0, 400, 800); + scene.addLine(0, 400, 800, 400); -} + pc = new coreview::ProgramCounter(machine); + pc_multiplexer = new coreview::Multiplexer(4); + testlatch = new coreview::Latch(machine, 300); -CoreViewLine::~CoreViewLine() { + pc2pc = new coreview::Connection(pc_multiplexer->connector_out(), pc->connector_in()); -} + scene.addItem(pc); + scene.addItem(pc_multiplexer); + scene.addItem(testlatch); + scene.addItem(pc2pc); -void CoreViewLine::set_start(struct point p) { + pc->setPos(100,100); + pc_multiplexer->setPos(60, 100); + pc_multiplexer->set(2); + setScene(&scene); + // TODO fitInView doesn't work as I want so reimplement or do something with it + //fitInView(0, 0, 201, 201, Qt::KeepAspectRatioByExpanding); } -void CoreViewLine::set_end(struct point p) { - +void CoreView::resizeEvent(QResizeEvent *event) { + // fitInView(0, 0, 201, 201, Qt::KeepAspectRatioByExpanding); } - -void CoreViewLine::set_axis(QList<struct point> axs) { - -} - -*/ diff --git a/qtmips_gui/coreview.h b/qtmips_gui/coreview.h index a2772fb..fc69861 100644 --- a/qtmips_gui/coreview.h +++ b/qtmips_gui/coreview.h @@ -2,45 +2,33 @@ #define COREVIEW_H #include <QGraphicsView> -#include <QGraphicsItem> -#include <QList> -#include "machineconfig.h" +#include <QGraphicsScene> +#include "qtmipsmachine.h" +#include "coreview/connection.h" +#include "coreview/programcounter.h" +#include "coreview/multiplexer.h" +#include "coreview/latch.h" class CoreView : public QGraphicsView { Q_OBJECT public: - CoreView(QWidget *parent); + CoreView(QWidget *parent, QtMipsMachine *machine); private: + void resizeEvent(QResizeEvent *event); -}; + QGraphicsScene scene; + QtMipsMachine *machine; -/* -class CoreViewBlock : public QGraphicsItem { - Q_OBJECT -public: - CoreViewBlock(); + coreview::ProgramCounter *pc; + coreview::Multiplexer *pc_multiplexer; + coreview::Connection *pc2pc; + coreview::Latch *testlatch; }; -class CoreViewLine : public QGraphicsItem { - Q_OBJECT -public: - struct point { - int x1, y1, x2, y2; - }; - - CoreViewLine(); - CoreViewLine(struct point start, struct point end, QList<struct point> axis); - ~CoreViewLine(); +#else - void set_start(struct point); - void set_end(struct point); - void set_axis(QList<struct point>); - -protected: - struct point start, end; - QList<struct point> axis; -}; -*/ +class CoreView; +class CoreViewBlock; #endif // COREVIEW_H diff --git a/qtmips_gui/coreview/connection.cpp b/qtmips_gui/coreview/connection.cpp new file mode 100644 index 0000000..ebca519 --- /dev/null +++ b/qtmips_gui/coreview/connection.cpp @@ -0,0 +1,79 @@ +#include "connection.h" + +using namespace coreview; + +void Connector::setPos(qreal x, qreal y) { + qx = x; + qy = y; + emit updated(); +} + +qreal Connector::x() const { + return qx; +} + +qreal Connector::y() const { + return qy; +} + +QPointF Connector::point() const { + return QPointF(qx, qy); +} + +Connection::Connection(const Connector *a, const Connector *b) : QGraphicsObject(nullptr) { + connect(a, SIGNAL(updated()), this, SLOT(moved())); + connect(b, SIGNAL(updated()), this, SLOT(moved())); + this->a = a; + this->b = b; + update_pos(); +} + +void Connection::setHasText(bool has) { + if (has && value == nullptr) { + value = new QGraphicsSimpleTextItem(this); + value->setText(text); + } else if (!has && value != nullptr) { + delete value; + } + update_pos(); +} + +void Connection::setText(QString val) { + text = val; + if (value != nullptr) + value->setText(val); +} + +void Connection::moved() { + update_pos(); +} + +QRectF Connection::boundingRect() const { + QRectF rect; + for (int i = 0; i < (points.size() - 1); i++) { + qreal x = points[i].x(); + if (x > points[i+1].x()) + x = points[i+1].x(); + qreal y = points[i].y(); + if (y > points[i+1].y()) + y = points[i+1].y(); + // TODO pen width + rect.united(QRectF(x - 0.5, y - 0.5, fabs(points[i].x() - points[i+1].x()) + 1, fabs(points[i].y() - points[i+1].y()) + 1)); + } + //return rect; + return QRectF(0, 0, 300, 300); +} + +void Connection::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget) { + for (int i = 0; i < (points.size() - 1); i++) + painter->drawLine(points[i], points[i+1]); + // TODO meaby use QPath instead? +} + +void Connection::update_pos() { + points.clear(); + points.append(a->point()); + points.append(b->point()); + // TODO more than one line + // TODO update position of value +} diff --git a/qtmips_gui/coreview/connection.h b/qtmips_gui/coreview/connection.h new file mode 100644 index 0000000..eda6afe --- /dev/null +++ b/qtmips_gui/coreview/connection.h @@ -0,0 +1,60 @@ +#ifndef CONNECTION_H +#define CONNECTION_H + +#include <QGraphicsObject> +#include <QList> +#include <cmath> +#include "../coreview.h" + +namespace coreview { + +class Connector : public QObject { + Q_OBJECT +public: + void setPos(qreal x, qreal y); + qreal x() const; + qreal y() const; + QPointF point() const; + +signals: + void updated(); + +private: + qreal qx, qy; +}; + +class Connection : public QGraphicsObject { + Q_OBJECT +public: + Connection(const Connector *a, const Connector *b); + + void setHasText(bool has); + void setText(QString val); + +private slots: + void moved(); + +private: + QGraphicsSimpleTextItem *value; + QList<QPointF> points; + const Connector *a, *b; + QString text; + + QRectF boundingRect() const; + void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget); + + // TODO line width and possibly bus width + + void update_pos(); +}; + +} + +#else + +namespace coreview { + class Connector; + class Connection; +}; + +#endif // CONNECTION_H diff --git a/qtmips_gui/coreview/latch.cpp b/qtmips_gui/coreview/latch.cpp new file mode 100644 index 0000000..77bb317 --- /dev/null +++ b/qtmips_gui/coreview/latch.cpp @@ -0,0 +1,51 @@ +#include "latch.h" + +using namespace coreview; + +////////////////////// +#define WIDTH 10 +#define PENW 1 +////////////////////// + +Latch::Latch(QtMipsMachine *machine, qreal height) { + this->height = height; + connect(machine, SIGNAL(tick()), this, SLOT(tick())); +} + +QRectF Latch::boundingRect() const { + return QRectF(-PENW / 2, -PENW / 2, WIDTH + PENW, height + PENW); +} + +void Latch::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget) { + painter->drawRect(0, 0, WIDTH, height); + // Now tick rectangle + const QPointF tickPolygon[] = { + QPointF(0, 0), + QPointF(WIDTH/2, WIDTH/2), + QPointF(WIDTH, 0) + }; + painter->drawPolygon(tickPolygon, 3); +} + +void Latch::setPos(qreal x, qreal y) { + QGraphicsObject::setPos(x, y); + for (unsigned i = 0; i < connectors.size(); i++) { + connectors[i].in->setPos(x, y + connectors_off[i]); + connectors[i].out->setPos(x + WIDTH, y + connectors_off[i]); + } +} + +struct Latch::ConnectorPair Latch::new_connector(qreal cy) { + SANITY_ASSERT(cy < height, "Latch: Trying to create connector outside of latch height"); + ConnectorPair cp; + cp.in = new Connector(); + cp.out = new Connector(); + connectors.append(cp); + connectors_off.append(cy); + setPos(x(), y()); // Update connectors position + return cp; +} + +void Latch::tick() { + // TODO animate +} diff --git a/qtmips_gui/coreview/latch.h b/qtmips_gui/coreview/latch.h new file mode 100644 index 0000000..a8738b3 --- /dev/null +++ b/qtmips_gui/coreview/latch.h @@ -0,0 +1,45 @@ +#ifndef LATCH_H +#define LATCH_H + +#include <QGraphicsObject> +#include <QList> +#include "qtmipsexception.h" +#include "qtmipsmachine.h" +#include "../coreview.h" +#include "connection.h" + +namespace coreview { + +class Latch : public QGraphicsObject { + Q_OBJECT +public: + Latch(QtMipsMachine *machine, qreal height); + + QRectF boundingRect() const; + void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget); + + void setPos(qreal x, qreal y); + + struct ConnectorPair { Connector *in, *out; }; + + struct ConnectorPair new_connector(qreal y); // Create new connectors pair that is given y from top of latch + +private slots: + void tick(); + +private: + qreal height; + QList<ConnectorPair> connectors; + QList<qreal> connectors_off; + +}; + +} + +#else + +namespace coreview { + class Latch; +}; + +#endif // LATCH_H diff --git a/qtmips_gui/coreview/multiplexer.cpp b/qtmips_gui/coreview/multiplexer.cpp new file mode 100644 index 0000000..57fa443 --- /dev/null +++ b/qtmips_gui/coreview/multiplexer.cpp @@ -0,0 +1,79 @@ +#include "multiplexer.h" + +using namespace coreview; + +////////////////////// +#define WIDTH 20 +#define HEIGHT 20 +#define PENW 1 +////////////////////// + +Multiplexer::Multiplexer(unsigned size) { + this->size = size; + seton = 0; + ctlfrom = false; + con_ctl = new Connector(); + con_out = new Connector(); + con_in = new Connector*[size]; + for (unsigned i = 0; i < size; i++) + con_in[i] = new Connector(); + setPos(x(), y()); // Set connectors possitions +} + +Multiplexer::~Multiplexer() { + delete con_ctl; + delete con_out; + for (unsigned i = 0; i < size; i++) + delete con_in[i]; + delete con_in; +} + +QRectF Multiplexer::boundingRect() const { + return QRectF(-PENW / 2, -PENW / 2, WIDTH + PENW, (HEIGHT * size) + PENW); +} + +void Multiplexer::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget) { + // Draw pointing line first so it isn't over the border lines + painter->setPen(QColor(200, 200, 200)); + painter->drawLine(0, (HEIGHT / 2) + (seton * HEIGHT), WIDTH, (HEIGHT * size) / 2); + + painter->setPen(QColor()); + painter->drawLine(0, 0, 0, (HEIGHT * size)); // (|) + painter->drawLine(0, 0, WIDTH, WIDTH); // (\) + painter->drawLine(0, (HEIGHT * size), WIDTH, (HEIGHT * size) - WIDTH); // (/) + painter->drawLine(WIDTH, WIDTH, WIDTH, (HEIGHT * size) - WIDTH); // (|) +} + +void Multiplexer::setPos(qreal x, qreal y) { + QGraphicsItem::setPos(x, y); + if (ctlfrom) + con_ctl->setPos(x + (WIDTH / 2), y + (WIDTH / 2)); + else + con_ctl->setPos(x + (WIDTH / 2), y + (HEIGHT * size) - (WIDTH / 2)); + con_out->setPos(x + WIDTH, y + ((HEIGHT *size) / 2)); + for (unsigned i = 0; i < size; i++) + con_in[i]->setPos(x, y + (HEIGHT / 2) + (i * HEIGHT)); +} + +const Connector *Multiplexer::connector_ctl() const { + return con_ctl; +} + +const Connector *Multiplexer::connector_out() const { + return con_out; +} + +const Connector *Multiplexer::connector_in(unsigned i) const { + SANITY_ASSERT(i < size, "Multiplexer: requested out of range input connector"); + return con_in[i]; +} + +void Multiplexer::set(unsigned i) { + seton = i; + update(boundingRect()); +} + +void Multiplexer::setCtl(bool up) { + ctlfrom = up; + setPos(x(), y()); // Update connectors +} diff --git a/qtmips_gui/coreview/multiplexer.h b/qtmips_gui/coreview/multiplexer.h new file mode 100644 index 0000000..6aa11a6 --- /dev/null +++ b/qtmips_gui/coreview/multiplexer.h @@ -0,0 +1,41 @@ +#ifndef MULTIPLEXER_H +#define MULTIPLEXER_H + +#include <QGraphicsItem> +#include "qtmipsexception.h" +#include "../coreview.h" +#include "connection.h" + +namespace coreview { + +class Multiplexer : public QGraphicsItem { +public: + Multiplexer(unsigned size); + ~Multiplexer(); + + QRectF boundingRect() const; + void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget); + + void setPos(qreal x, qreal y); + const Connector *connector_ctl() const; // Control input + const Connector *connector_out() const; // Output + const Connector *connector_in(unsigned i) const; // Inputs + + void set(unsigned i); // Set what value should be set as connected + void setCtl(bool up); // Set if control signal is from up or down (in default down) + +private: + bool ctlfrom; + unsigned size, seton; + Connector *con_ctl, *con_out, **con_in; +}; + +} + +#else + +namespace coreview { + class Multiplexer; +} + +#endif // MULTIPLEXER_H diff --git a/qtmips_gui/coreview/programcounter.cpp b/qtmips_gui/coreview/programcounter.cpp new file mode 100644 index 0000000..32c907c --- /dev/null +++ b/qtmips_gui/coreview/programcounter.cpp @@ -0,0 +1,48 @@ +#include "programcounter.h" + +using namespace coreview; + +////////////////////// +#define WIDTH 80 +#define HEIGHT 100 +#define PENW 1 +////////////////////// + +ProgramCounter::ProgramCounter(QtMipsMachine *machine) : QGraphicsObject(nullptr), value(this), name(this) { + value.setText(QString("0x") + QString::number(machine->registers()->read_pc(), 16)); + value.setPos(0, HEIGHT/2 - value.boundingRect().height()/2); + name.setText(QString("PC")); + name.setPos(WIDTH/2 - name.boundingRect().width()/2, 0); + + connect(machine->registers(), SIGNAL(pc_update(std::uint32_t)), this, SLOT(pc_update(std::uint32_t))); + + con_in = new Connector(); + con_out = new Connector(); + setPos(x(), y()); // To set initial connectors positions +} + +QRectF ProgramCounter::boundingRect() const { + return QRectF(-PENW / 2, -PENW / 2, WIDTH + PENW, HEIGHT + PENW); +} + +void ProgramCounter::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget) { + painter->drawRect(0, 0, WIDTH, HEIGHT); +} + +void ProgramCounter::setPos(qreal x, qreal y) { + QGraphicsObject::setPos(x, y); + con_in->setPos(x, y + HEIGHT/2); + con_out->setPos(x + WIDTH, y + HEIGHT/2); +} + +const Connector *ProgramCounter::connector_in() const { + return con_in; +} + +const Connector *ProgramCounter::connector_out() const { + return con_out; +} + +void ProgramCounter::pc_update(std::uint32_t val) { + value.setText(QString("0x") + QString::number(val, 16)); +} diff --git a/qtmips_gui/coreview/programcounter.h b/qtmips_gui/coreview/programcounter.h new file mode 100644 index 0000000..98b161d --- /dev/null +++ b/qtmips_gui/coreview/programcounter.h @@ -0,0 +1,42 @@ +#ifndef PROGRAMCOUNTER_H +#define PROGRAMCOUNTER_H + +#include <QGraphicsObject> +#include <QPainter> +#include "qtmipsmachine.h" +#include "../coreview.h" +#include "connection.h" + +namespace coreview { + +class ProgramCounter : public QGraphicsObject { + Q_OBJECT +public: + ProgramCounter(QtMipsMachine *machine); + + QRectF boundingRect() const; + void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget); + + void setPos(qreal x, qreal y); + const Connector *connector_in() const; + const Connector *connector_out() const; + +private slots: + void pc_update(std::uint32_t val); + +private: + QGraphicsSimpleTextItem value; + QGraphicsSimpleTextItem name; + + Connector *con_in, *con_out; +}; + +} + +#else + +namespace coreview { + class ProgramCounter; +}; + +#endif // PROGRAMCOUNTER_H diff --git a/qtmips_gui/mainwindow.cpp b/qtmips_gui/mainwindow.cpp index ea48736..157baf4 100644 --- a/qtmips_gui/mainwindow.cpp +++ b/qtmips_gui/mainwindow.cpp @@ -18,11 +18,11 @@ MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent) { registers->hide(); // Connect signals from menu - QObject::connect(ui->actionExit, SIGNAL(triggered(bool)), this, SLOT(close())); - QObject::connect(ui->actionNew, SIGNAL(triggered(bool)), this, SLOT(new_machine())); - QObject::connect(ui->actionCache, SIGNAL(triggered(bool)), this, SLOT(show_cache_content())); - QObject::connect(ui->actionCache_statistics, SIGNAL(triggered(bool)), this, SLOT(show_cache_statictics())); - QObject::connect(ui->actionRegisters, SIGNAL(triggered(bool)), this, SLOT(show_registers())); + connect(ui->actionExit, SIGNAL(triggered(bool)), this, SLOT(close())); + connect(ui->actionNew, SIGNAL(triggered(bool)), this, SLOT(new_machine())); + connect(ui->actionCache, SIGNAL(triggered(bool)), this, SLOT(show_cache_content())); + connect(ui->actionCache_statistics, SIGNAL(triggered(bool)), this, SLOT(show_cache_statictics())); + connect(ui->actionRegisters, SIGNAL(triggered(bool)), this, SLOT(show_registers())); // Restore application state from settings restoreState(settings->value("windowState").toByteArray()); @@ -39,6 +39,8 @@ MainWindow::~MainWindow() { delete cache_statictics; delete registers; delete ui; + if (machine != nullptr) + delete machine; } void MainWindow::start() { @@ -50,9 +52,19 @@ void MainWindow::create_core(MachineConfig *config) { // Create machine machine = new QtMipsMachine(config); // Create machine view - coreview = new CoreView(this); + coreview = new CoreView(this, machine); this->setCentralWidget(coreview); - // TODO connect signals + + machine->set_speed(1000); // Set default speed to 1 sec + + // Connect machine signals + connect(ui->actionRun, SIGNAL(triggered(bool)), machine, SLOT(play())); + connect(ui->actionPause, SIGNAL(triggered(bool)), machine, SLOT(pause())); + connect(ui->actionStep, SIGNAL(triggered(bool)), machine, SLOT(step())); + connect(ui->actionRestart, SIGNAL(triggered(bool)), machine, SLOT(restart())); + + // Setup docks + registers->setup(machine); } void MainWindow::new_machine() { diff --git a/qtmips_gui/qtmips_gui.pro b/qtmips_gui/qtmips_gui.pro index ee2bd6e..da91449 100644 --- a/qtmips_gui/qtmips_gui.pro +++ b/qtmips_gui/qtmips_gui.pro @@ -19,7 +19,11 @@ SOURCES += \ coreview.cpp \ registersdock.cpp \ cachestatistics.cpp \ - cachecontent.cpp + cachecontent.cpp \ + coreview/programcounter.cpp \ + coreview/multiplexer.cpp \ + coreview/connection.cpp \ + coreview/latch.cpp HEADERS += \ mainwindow.h \ @@ -27,7 +31,11 @@ HEADERS += \ coreview.h \ registersdock.h \ cachestatistics.h \ - cachecontent.h + cachecontent.h \ + coreview/programcounter.h \ + coreview/multiplexer.h \ + coreview/connection.h \ + coreview/latch.h FORMS += \ NewDialog.ui \ |