From e6ca4b4568e311b47239bfe83de15ed9e91c57b9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Karel=20Ko=C4=8D=C3=AD?= Date: Fri, 15 Dec 2017 22:45:28 +0100 Subject: Implement few initial graphic elements --- qtmips_gui/coreview/connection.cpp | 79 ++++++++++++++++++++++++++++++++++ qtmips_gui/coreview/connection.h | 60 ++++++++++++++++++++++++++ qtmips_gui/coreview/latch.cpp | 51 ++++++++++++++++++++++ qtmips_gui/coreview/latch.h | 45 +++++++++++++++++++ qtmips_gui/coreview/multiplexer.cpp | 79 ++++++++++++++++++++++++++++++++++ qtmips_gui/coreview/multiplexer.h | 41 ++++++++++++++++++ qtmips_gui/coreview/programcounter.cpp | 48 +++++++++++++++++++++ qtmips_gui/coreview/programcounter.h | 42 ++++++++++++++++++ 8 files changed, 445 insertions(+) create mode 100644 qtmips_gui/coreview/connection.cpp create mode 100644 qtmips_gui/coreview/connection.h create mode 100644 qtmips_gui/coreview/latch.cpp create mode 100644 qtmips_gui/coreview/latch.h create mode 100644 qtmips_gui/coreview/multiplexer.cpp create mode 100644 qtmips_gui/coreview/multiplexer.h create mode 100644 qtmips_gui/coreview/programcounter.cpp create mode 100644 qtmips_gui/coreview/programcounter.h (limited to 'qtmips_gui/coreview') 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 +#include +#include +#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 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 +#include +#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 connectors; + QList 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 +#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 +#include +#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 -- cgit v1.2.3