diff options
26 files changed, 856 insertions, 183 deletions
diff --git a/qtmips_gui/coreview.cpp b/qtmips_gui/coreview.cpp index f5d86d9..e845184 100644 --- a/qtmips_gui/coreview.cpp +++ b/qtmips_gui/coreview.cpp @@ -1,9 +1,18 @@ #include "coreview.h" +#include <cmath> + +////////////////////////////////////////////////////////////////////////////// +/// Size of visible view area +#define SC_WIDTH 720 +#define SC_HEIGHT 540 +////////////////////////////////////////////////////////////////////////////// CoreView::CoreView(QWidget *parent) : QGraphicsView(parent) { setRenderHints(QPainter::Antialiasing | QPainter::SmoothPixmapTransform); +} - setSceneRect(0, 0, scene_width, scene_height); +void CoreView::setScene(QGraphicsScene *scene) { + QGraphicsView::setScene(scene); update_scale(); } @@ -13,9 +22,12 @@ void CoreView::resizeEvent(QResizeEvent *event) { } void CoreView::update_scale() { + if (scene() == nullptr) + return; // Skip if we have no scene + // Note: there is somehow three pixels error when viewing so we have to always compensate - const int w = scene_width + 3; - const int h = scene_height + 3; + const int w = scene()->width() + 3; + const int h = scene()->height() + 3; qreal scale = 1; if (height() > h && width() > w) { @@ -31,31 +43,107 @@ void CoreView::update_scale() { } CoreViewScene::CoreViewScene(CoreView *view, machine::QtMipsMachine *machine) : QGraphicsScene(view) { - this->machine = machine; + setSceneRect(0, 0, SC_WIDTH, SC_HEIGHT); // Identification cross (TODO remove) QPen pen; pen.setBrush(QBrush(QColor(220, 220, 220))); - addLine(400, 0, 400, 800, pen); - addLine(0, 400, 800, 400, pen); - addRect(0.5, 0.5, 799.5, 799.5, pen); + addLine(width()/2, 0, width()/2, height(), pen); + addLine(0, height()/2, width(), height()/2, pen); + addRect(0.5, 0.5, width() - 0.5, height() - 0.5, pen); // TODO remove - pc = new coreview::ProgramCounter(machine); - alu = new coreview::Alu(); - pc_multiplexer = new coreview::Multiplexer(4); - testlatch = new coreview::Latch(machine, 300); +#define NEW(TYPE, VAR, ...) do { \ + VAR = new coreview::TYPE(__VA_ARGS__);\ + addItem(VAR);\ + } while(false) +#define NEW_CON(VAR, ...) NEW(Connection, VAR, __VA_ARGS__) - pc2pc = new coreview::Connection(pc_multiplexer->connector_out(), pc->connector_in()); + NEW(ProgramCounter, pc, machine); + NEW(Latch, pc_latch, machine, 20); + NEW(Adder, pc_adder); + NEW(Constant, pc_adder_4, pc_adder->connector_in_b(), "4"); + NEW(Junction, pc_junction); + NEW(Alu, alu); + NEW(Memory, mem, machine); + NEW(Registers, regs); + NEW(Multiplexer, pc_multiplexer, 4); + NEW(Multiplexer, mem_or_reg, 2); - addItem(pc); - addItem(alu); - addItem(pc_multiplexer); - addItem(testlatch); - addItem(pc2pc); + struct coreview::Latch::ConnectorPair pc_latch_pair = pc_latch->new_connector(10); + NEW_CON(pc2pc_latch, pc->connector_out(), pc_latch_pair.in); + NEW_CON(pc_latch2pc_joint, pc_latch_pair.out, pc_junction->new_connector(0)); + NEW_CON(pc_joint2pc_adder, pc_junction->new_connector(M_PI_2), pc_adder->connector_in_a()); + NEW_CON(pc_joint2mem, pc_junction->new_connector(-M_PI_2), mem->connector_pc()); + pc_joint2mem->setAxes({CON_AXIS_X(430)}); + NEW_CON(pc_multiplexer2pc, pc_multiplexer->connector_out(), pc->connector_in()); + pc_multiplexer2pc->setAxes({CON_AXIS_Y(90), CON_AXIS_X(80)}); - pc->setPos(100,100); - alu->setPos(200, 100); + pc->setPos(2, 330); + pc_latch->setPos(50, 370); + pc_adder->setPos(100, 350); + pc_junction->setPos(80, pc_latch_pair.out->y()); + alu->setPos(470, 230); + mem->setPos(20, 510); + regs->setPos(20, 0); pc_multiplexer->setPos(60, 100); - pc_multiplexer->set(2); + mem_or_reg->setPos(570, 180); + + connect(regs, SIGNAL(open_registers()), this, SIGNAL(request_registers())); + connect(mem, SIGNAL(open_data_mem()), this, SIGNAL(request_data_memory())); + connect(mem, SIGNAL(open_program_mem()), this, SIGNAL(request_program_memory())); +} + +CoreViewScene::~CoreViewScene() { + delete pc2pc_latch; + delete pc_latch2pc_joint; + delete pc_joint2pc_adder; + delete pc_joint2mem; + delete pc_multiplexer2pc; + + delete pc; + delete pc_latch; + delete pc_adder; + delete pc_adder_4; + delete pc_junction; + delete alu; + delete pc_multiplexer; +} + +CoreViewSceneSimple::CoreViewSceneSimple(CoreView *view, machine::QtMipsMachine *machine) : CoreViewScene(view, machine) { + delay_slot_latch = new coreview::Latch(machine, 150); + + addItem(delay_slot_latch); + + delay_slot_latch->setPos(160, 50); +} + +CoreViewSceneSimple::~CoreViewSceneSimple() { + +} + +CoreViewScenePipelined::CoreViewScenePipelined(CoreView *view, machine::QtMipsMachine *machine) : CoreViewScene(view, machine) { + latch_if_id = new coreview::Latch(machine, 350); + latch_id_ex = new coreview::Latch(machine, 350); + latch_ex_mem = new coreview::Latch(machine, 350); + latch_mem_wb = new coreview::Latch(machine, 350); + + latch_if_id->setTitle("IF/ID"); + latch_id_ex->setTitle("ID/EX"); + latch_ex_mem->setTitle("EX/MEM"); + latch_mem_wb->setTitle("MEM/WB"); + + addItem(latch_if_id); + addItem(latch_id_ex); + addItem(latch_ex_mem); + addItem(latch_mem_wb); + + latch_if_id->setPos(158, 90); + latch_id_ex->setPos(392, 90); + latch_ex_mem->setPos(536, 90); + latch_mem_wb->setPos(680, 90); +} + +CoreViewScenePipelined::~CoreViewScenePipelined() { + } diff --git a/qtmips_gui/coreview.h b/qtmips_gui/coreview.h index 52b98ee..7439888 100644 --- a/qtmips_gui/coreview.h +++ b/qtmips_gui/coreview.h @@ -9,15 +9,22 @@ #include "coreview/multiplexer.h" #include "coreview/latch.h" #include "coreview/alu.h" +#include "coreview/adder.h" +#include "coreview/memory.h" +#include "coreview/registers.h" +#include "coreview/instructionview.h" +#include "coreview/junction.h" +#include "coreview/constant.h" class CoreView : public QGraphicsView { public: CoreView(QWidget *parent); + void setScene(QGraphicsScene *scene); + protected: void resizeEvent(QResizeEvent *event); private: - const int scene_width = 800, scene_height = 800; void update_scale(); }; @@ -25,20 +32,53 @@ class CoreViewScene : public QGraphicsScene { Q_OBJECT public: CoreViewScene(CoreView *view, machine::QtMipsMachine *machine); + ~CoreViewScene(); -private: - machine::QtMipsMachine *machine; +signals: + void request_registers(); + void request_data_memory(); + void request_program_memory(); +private: coreview::ProgramCounter *pc; + coreview::Latch *pc_latch; + coreview::Adder *pc_adder; + coreview::Constant *pc_adder_4; + coreview::Junction *pc_junction; coreview::Alu *alu; - coreview::Multiplexer *pc_multiplexer; - coreview::Connection *pc2pc; - coreview::Latch *testlatch; + coreview::Memory *mem; + coreview::Registers *regs; + coreview::Multiplexer *pc_multiplexer, *mem_or_reg; + + coreview::Connection *pc2pc_latch; + coreview::Connection *pc_latch2pc_joint, *pc_joint2pc_adder, *pc_joint2mem; + coreview::Connection *pc_multiplexer2pc; +}; + +class CoreViewSceneSimple : public CoreViewScene { +public: + CoreViewSceneSimple(CoreView *view, machine::QtMipsMachine *machine); + ~CoreViewSceneSimple(); + +private: + coreview::Latch *delay_slot_latch; +}; + +class CoreViewScenePipelined : public CoreViewScene { +public: + CoreViewScenePipelined(CoreView *view, machine::QtMipsMachine *machine); + ~CoreViewScenePipelined(); + +private: + coreview::Latch *latch_if_id, *latch_id_ex, *latch_ex_mem, *latch_mem_wb; + // TODO forwarding unit }; #else class CoreView; class CoreViewScene; +class CoreViewSceneSimple; +class CoreViewScenePipelined; #endif // COREVIEW_H diff --git a/qtmips_gui/coreview/adder.cpp b/qtmips_gui/coreview/adder.cpp new file mode 100644 index 0000000..cd227ab --- /dev/null +++ b/qtmips_gui/coreview/adder.cpp @@ -0,0 +1,69 @@ +#include "adder.h" +#include <cmath> + +using namespace coreview; + +////////////////////// +#define WIDTH 13 +#define HEIGHT 40 +#define DENT 3 +#define PENW 1 +////////////////////// + +Adder::Adder() : QGraphicsItem(nullptr), plus("+", this) { + QFont font; + font.setPointSize(7); + plus.setFont(font); + QRectF plus_box = plus.boundingRect(); + plus.setPos(DENT + (WIDTH-DENT)/2 - plus_box.width()/2, HEIGHT/2 - plus_box.height()/2); + + con_in_a = new Connector(0); + con_in_b = new Connector(0); + con_out = new Connector(M_PI); + + setPos(x(), y()); // set connector's position +} + +Adder::~Adder() { + delete con_in_a; + delete con_in_b; + delete con_out; +} + +QRectF Adder::boundingRect() const { + return QRectF(-PENW / 2, -PENW / 2, WIDTH + PENW, HEIGHT + PENW); +} + +void Adder::paint(QPainter *painter, const QStyleOptionGraphicsItem *option __attribute__((unused)), QWidget *widget __attribute__((unused))) { + const QPointF poly[] = { + QPointF(0, 0), + QPointF(WIDTH, WIDTH), + QPointF(WIDTH, HEIGHT - WIDTH), + QPointF(0, HEIGHT), + QPointF(0, (HEIGHT/2) + DENT), + QPointF(DENT, HEIGHT / 2), + QPointF(0, (HEIGHT / 2) - DENT) + }; + painter->drawPolygon(poly, sizeof(poly) / sizeof(QPointF)); +} + +void Adder::setPos(qreal x, qreal y) { + QGraphicsItem::setPos(x, y); + + qreal off = ((HEIGHT/2) - DENT) / 2; + con_in_a->setPos(x, y + off); + con_in_b->setPos(x, y + HEIGHT - off); + con_out->setPos(x + WIDTH, y + HEIGHT/2); +} + +const Connector *Adder::connector_in_a() const { + return con_in_a; +} + +const Connector *Adder::connector_in_b() const { + return con_in_b; +} + +const Connector *Adder::connector_out() const { + return con_out; +} diff --git a/qtmips_gui/coreview/adder.h b/qtmips_gui/coreview/adder.h new file mode 100644 index 0000000..9de81a1 --- /dev/null +++ b/qtmips_gui/coreview/adder.h @@ -0,0 +1,32 @@ +#ifndef ADDER_H +#define ADDER_H + +#include <QGraphicsItem> +#include <QPainter> +#include <QGraphicsSimpleTextItem> +#include "connection.h" + +namespace coreview { + +class Adder : public QGraphicsItem { +public: + Adder(); + ~Adder(); + + QRectF boundingRect() const; + void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget); + + void setPos(qreal x, qreal y); + const Connector *connector_in_a() const; + const Connector *connector_in_b() const; + const Connector *connector_out() const; + +private: + QGraphicsSimpleTextItem plus; + + Connector *con_in_a, *con_in_b, *con_out; +}; + +} + +#endif // ADDER_H diff --git a/qtmips_gui/coreview/alu.cpp b/qtmips_gui/coreview/alu.cpp index bb48c7e..e048578 100644 --- a/qtmips_gui/coreview/alu.cpp +++ b/qtmips_gui/coreview/alu.cpp @@ -7,9 +7,11 @@ #define PENW 1 ////////////////////// -coreview::Alu::Alu() : QGraphicsObject(nullptr), name(this) { - name.setText("ALU"); +coreview::Alu::Alu() : QGraphicsItem(nullptr), name("ALU", this) { name.setPos(3, 25); + QFont font; + font.setPointSize(7); + name.setFont(font); con_in_a = new Connector(); con_in_b = new Connector(); @@ -37,7 +39,8 @@ void coreview::Alu::paint(QPainter *painter, const QStyleOptionGraphicsItem *opt } void coreview::Alu::setPos(qreal x, qreal y) { - QGraphicsObject::setPos(x, y); + QGraphicsItem::setPos(x, y); + // TODO fix this (should be relative to x and y) qreal off = ((HEIGHT/2) - DENT) / 2; con_in_a->setPos(0, off); con_in_b->setPos(0, HEIGHT - off); diff --git a/qtmips_gui/coreview/alu.h b/qtmips_gui/coreview/alu.h index 4c9a73b..25d7351 100644 --- a/qtmips_gui/coreview/alu.h +++ b/qtmips_gui/coreview/alu.h @@ -1,14 +1,13 @@ #ifndef COREVIEW_ALU_H #define COREVIEW_ALU_H -#include <QGraphicsObject> +#include <QGraphicsItem> #include <qtmipsmachine.h> -#include "../coreview.h" #include "connection.h" namespace coreview { -class Alu : public QGraphicsObject { +class Alu : public QGraphicsItem { public: Alu(); @@ -28,10 +27,4 @@ private: } -#else - -namespace coreview { - class Alu; -} - #endif // COREVIEW_ALU_H diff --git a/qtmips_gui/coreview/connection.cpp b/qtmips_gui/coreview/connection.cpp index f2b730c..85f7a96 100644 --- a/qtmips_gui/coreview/connection.cpp +++ b/qtmips_gui/coreview/connection.cpp @@ -1,11 +1,16 @@ #include "connection.h" +#include <cmath> using namespace coreview; +Connector::Connector(qreal angle) { + ang = angle; +} + void Connector::setPos(qreal x, qreal y) { qx = x; qy = y; - emit updated(); + emit updated(QPointF(qx, qy)); } qreal Connector::x() const { @@ -16,16 +21,28 @@ qreal Connector::y() const { return qy; } +QLineF Connector::vector() const { + return QLineF(point(), QPointF(x() + cos(ang), y() + sin(ang))); +} + QPointF Connector::point() const { return QPointF(qx, qy); } +qreal Connector::angle() const { + return ang; +} + 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(); + pen_width = 1; + + ang_start = a->angle(); + ang_end = b->angle(); + + connect(a, SIGNAL(updated(QPointF)), this, SLOT(moved_start(QPointF))); + connect(b, SIGNAL(updated(QPointF)), this, SLOT(moved_end(QPointF))); + moved_start(a->point()); + moved_end(b->point()); } void Connection::setHasText(bool has) { @@ -35,7 +52,6 @@ void Connection::setHasText(bool has) { } else if (!has && value != nullptr) { delete value; } - update_pos(); } void Connection::setText(QString val) { @@ -44,36 +60,56 @@ void Connection::setText(QString val) { value->setText(val); } -void Connection::moved() { - update_pos(); +void Connection::setAxes(QVector<QLineF> axes) { + break_axes = axes; +} + +void Connection::moved_start(QPointF p) { + p_start = p; + recalc_line(); +} + +void Connection::moved_end(QPointF p) { + p_end = p; + recalc_line(); } 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 = 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)); + qreal x = points[i].x() > points[i+1].x() ? points[i].x() : points[i+1].x(); + qreal y = points[i].y() > points[i+1].y() ? points[i].y() : points[i+1].y(); + rect |= QRectF(x - pen_width/2.0, y - pen_width/2.0, fabs(points[i].x() - points[i+1].x()) + pen_width, fabs(points[i].y() - points[i+1].y()) + pen_width); } - //return rect; - return QRectF(0, 0, 300, 300); + return rect; } void Connection::paint(QPainter *painter, const QStyleOptionGraphicsItem *option __attribute__((unused)), QWidget *widget __attribute__((unused))) { - for (int i = 0; i < (points.size() - 1); i++) - painter->drawLine(points[i], points[i+1]); - // TODO meaby use QPath instead? + QPen pen; + pen.setWidth(pen_width); + // TODO color? + painter->setPen(pen); + + painter->drawPolyline(QPolygonF(points)); } -void Connection::update_pos() { +void Connection::recalc_line() { points.clear(); - points.append(a->point()); - points.append(b->point()); - // TODO more than one line - // TODO update position of value + + points.append(p_start); + + QLineF cur_l(p_start, QPointF(p_start.x() + cos(ang_start), p_start.y() + sin(ang_start))); + for (int i = 0; i < break_axes.size(); i++) { + recalc_line_add_point(cur_l, break_axes[i]); + cur_l = break_axes[i]; + } + recalc_line_add_point(cur_l, QLineF(QPoint(p_end.x() + cos(ang_end), p_end.y() + sin(ang_end)), p_end)); + + points.append(p_end); +} + +void Connection::recalc_line_add_point(const QLineF &l1, const QLineF &l2) { + QPointF intersec; + if (l1.intersect(l2, &intersec) != QLineF::NoIntersection) + points.append(intersec); } diff --git a/qtmips_gui/coreview/connection.h b/qtmips_gui/coreview/connection.h index efe3942..0ee981e 100644 --- a/qtmips_gui/coreview/connection.h +++ b/qtmips_gui/coreview/connection.h @@ -2,59 +2,67 @@ #define COREVIEW_CONNECTION_H #include <QGraphicsObject> -#include <QList> -#include <cmath> -#include "../coreview.h" +#include <QPainter> +#include <QVector> namespace coreview { class Connector : public QObject { Q_OBJECT public: + Connector(qreal angle); + void setPos(qreal x, qreal y); qreal x() const; qreal y() const; QPointF point() const; + QLineF vector() const; + + qreal angle() const; signals: - void updated(); + void updated(QPointF); private: + qreal ang; qreal qx, qy; }; class Connection : public QGraphicsObject { Q_OBJECT public: - Connection(const Connector *a, const Connector *b); + Connection(const Connector *start, const Connector *end); + + QRectF boundingRect() const; + void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget); void setHasText(bool has); void setText(QString val); + void setAxes(QVector<QLineF>); + private slots: - void moved(); + void moved_start(QPointF); + void moved_end(QPointF); private: QGraphicsSimpleTextItem *value; - QList<QPointF> points; - const Connector *a, *b; + QVector<QPointF> points; + QPointF p_start, p_end; + qreal ang_start, ang_end; + QVector<QLineF> break_axes; QString text; - QRectF boundingRect() const; - void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget); + int pen_width; // TODO line width and possibly bus width - - void update_pos(); + void recalc_line(); + void recalc_line_add_point(const QLineF &l1, const QLineF &l2); }; -} - -#else +#define CON_AXIS_X(Y) QLineF(QPointF(0, Y), QPointF(1, Y)) +#define CON_AXIS_Y(X) QLineF(QPointF(X, 0), QPointF(X, 1)) -namespace coreview { - class Connector; - class Connection; -}; +} #endif // COREVIEW_CONNECTION_H diff --git a/qtmips_gui/coreview/constant.cpp b/qtmips_gui/coreview/constant.cpp new file mode 100644 index 0000000..2f39fce --- /dev/null +++ b/qtmips_gui/coreview/constant.cpp @@ -0,0 +1,48 @@ +#include "constant.h" +#include <cmath> + +using namespace coreview; + +////////////////////// +#define OFFSET 6 +////////////////////// + +Constant::Constant(const Connector *con, const QString &text) : QGraphicsObject(nullptr), text(text, this) { + QFont font; + font.setPointSize(7); + this->text.setFont(font); + + con_our = new Connector(M_PI); + conn = new Connection(con_our, con); + connect(con, SIGNAL(updated(QPointF)), this, SLOT(ref_con_updated(QPointF))); + ref_con_updated(con->point()); // update initial connector position +} + +Constant::~Constant() { + delete conn; + delete con_our; +} + +QRectF Constant::boundingRect() const { + return conn->boundingRect(); +} + +void Constant::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget) { + conn->paint(painter, option, widget); +} + +void Constant::set_text(const QString &text) { + this->text.setText(text); + set_text_pos(); // update text positioning +} + +void Constant::ref_con_updated(QPointF p) { + con_our->setPos(p.x() - OFFSET, p.y()); + set_text_pos(); +} + +void Constant::set_text_pos() { + // We are using here our known position of con_our + QRectF box = text.boundingRect(); + text.setPos(con_our->x() - box.width() - 2, con_our->y() - box.height()/2); +} diff --git a/qtmips_gui/coreview/constant.h b/qtmips_gui/coreview/constant.h new file mode 100644 index 0000000..2d60f04 --- /dev/null +++ b/qtmips_gui/coreview/constant.h @@ -0,0 +1,35 @@ +#ifndef CONSTANT_H +#define CONSTANT_H + +#include <QGraphicsObject> +#include <QPainter> +#include <QGraphicsSimpleTextItem> +#include "connection.h" + +namespace coreview { + +class Constant : public QGraphicsObject { + Q_OBJECT +public: + Constant(const Connector *con, const QString &text); + ~Constant(); + + QRectF boundingRect() const; + void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget); + + void set_text(const QString &text); + +private slots: + void ref_con_updated(QPointF); + +private: + QGraphicsSimpleTextItem text; + Connector *con_our; + Connection *conn; + + void set_text_pos(); +}; + +} + +#endif // CONSTANT_H diff --git a/qtmips_gui/coreview/instructionview.cpp b/qtmips_gui/coreview/instructionview.cpp new file mode 100644 index 0000000..202aa3c --- /dev/null +++ b/qtmips_gui/coreview/instructionview.cpp @@ -0,0 +1,9 @@ +#include "instructionview.h" + +using namespace coreview; + +InstructionView::InstructionView() : QObject(), QGraphicsSimpleTextItem() { } + +void InstructionView::instruction_update(machine::Instruction &i) { + setText(i.to_str()); +} diff --git a/qtmips_gui/coreview/instructionview.h b/qtmips_gui/coreview/instructionview.h new file mode 100644 index 0000000..8db4756 --- /dev/null +++ b/qtmips_gui/coreview/instructionview.h @@ -0,0 +1,20 @@ +#ifndef INSTRUCTIONVIEW_H +#define INSTRUCTIONVIEW_H + +#include <QGraphicsSimpleTextItem> +#include "qtmipsmachine.h" + +namespace coreview { + +class InstructionView : public QObject, public QGraphicsSimpleTextItem { + Q_OBJECT +public: + InstructionView(); + +public slots: + void instruction_update(machine::Instruction &i); +}; + +} + +#endif // INSTRUCTIONVIEW_H diff --git a/qtmips_gui/coreview/junction.cpp b/qtmips_gui/coreview/junction.cpp new file mode 100644 index 0000000..271284c --- /dev/null +++ b/qtmips_gui/coreview/junction.cpp @@ -0,0 +1,36 @@ +#include "junction.h" + +using namespace coreview; + +////////////////////// +#define DOT_SIZE 4 +////////////////////// + +Junction::Junction() : QGraphicsItem(nullptr) { } + +Junction::~Junction() { + for (int i = 0; i < cons.size(); i++) + delete cons[i]; +} + +QRectF Junction::boundingRect() const { + return QRectF(-DOT_SIZE/2, -DOT_SIZE/2, DOT_SIZE, DOT_SIZE); +} + +void Junction::paint(QPainter *painter, const QStyleOptionGraphicsItem *option __attribute__((unused)), QWidget *widget __attribute__((unused))) { + painter->setBrush(QBrush(QColor(0, 0, 0))); + painter->drawEllipse(-DOT_SIZE/2, -DOT_SIZE/2, DOT_SIZE, DOT_SIZE); +} + +void Junction::setPos(qreal x, qreal y) { + QGraphicsItem::setPos(x, y); + foreach (Connector *con, cons) + con->setPos(x, y); +} + +Connector *Junction::new_connector(qreal angle) { + Connector*n = new Connector(angle); + cons.append(n); + setPos(x(), y()); // set connector's position + return n; +} diff --git a/qtmips_gui/coreview/junction.h b/qtmips_gui/coreview/junction.h new file mode 100644 index 0000000..1a8f5d7 --- /dev/null +++ b/qtmips_gui/coreview/junction.h @@ -0,0 +1,28 @@ +#ifndef JUNCTION_H +#define JUNCTION_H + +#include <QGraphicsItem> +#include <QPainter> +#include <QList> +#include "connection.h" + +namespace coreview { + +class Junction : public QGraphicsItem { +public: + Junction(); + ~Junction(); + + QRectF boundingRect() const; + void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget); + + void setPos(qreal x, qreal y); + Connector *new_connector(qreal angle); + +private: + QList<Connector*> cons; +}; + +} + +#endif // JUNCTION_H diff --git a/qtmips_gui/coreview/latch.cpp b/qtmips_gui/coreview/latch.cpp index 13351a2..c3bab4f 100644 --- a/qtmips_gui/coreview/latch.cpp +++ b/qtmips_gui/coreview/latch.cpp @@ -1,15 +1,21 @@ #include "latch.h" +#include <cmath> using namespace coreview; ////////////////////// -#define WIDTH 10 +#define WIDTH 7 #define PENW 1 ////////////////////// Latch::Latch(machine::QtMipsMachine *machine, qreal height) : QGraphicsObject(nullptr) { this->height = height; + title = new QGraphicsSimpleTextItem(this); + QFont font; + font.setPointSize(6); + title->setFont(font); + wedge_animation = new QPropertyAnimation(this, "wedge_clr"); wedge_animation->setDuration(100); wedge_animation->setStartValue(QColor(0, 0, 0)); @@ -20,7 +26,9 @@ Latch::Latch(machine::QtMipsMachine *machine, qreal height) : QGraphicsObject(nu } QRectF Latch::boundingRect() const { - return QRectF(-PENW / 2, -PENW / 2, WIDTH + PENW, height + PENW); + QRectF b(-PENW / 2, -PENW / 2, WIDTH + PENW, height + PENW); + b |= title->boundingRect(); + return b; } void Latch::paint(QPainter *painter, const QStyleOptionGraphicsItem *option __attribute__((unused)), QWidget *widget __attribute__((unused))) { @@ -44,6 +52,12 @@ void Latch::set_wedge_color(QColor &c) { update(); } +void Latch::setTitle(const QString &str) { + title->setText(str); + QRectF box = title->boundingRect(); + title->setPos(WIDTH/2 - box.width()/2, - box.height() - 1); +} + void Latch::setPos(qreal x, qreal y) { QGraphicsObject::setPos(x, y); for (int i = 0; i < connectors.size(); i++) { @@ -55,8 +69,8 @@ void Latch::setPos(qreal x, qreal y) { 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(); + cp.in = new Connector(0); + cp.out = new Connector(M_PI); connectors.append(cp); connectors_off.append(cy); setPos(x(), y()); // Update connectors position diff --git a/qtmips_gui/coreview/latch.h b/qtmips_gui/coreview/latch.h index 951f16a..59f4df0 100644 --- a/qtmips_gui/coreview/latch.h +++ b/qtmips_gui/coreview/latch.h @@ -2,11 +2,10 @@ #define COREVIEW_LATCH_H #include <QGraphicsObject> -#include <QList> #include <QPropertyAnimation> +#include <QVector> #include "qtmipsexception.h" #include "qtmipsmachine.h" -#include "../coreview.h" #include "connection.h" namespace coreview { @@ -23,6 +22,8 @@ public: QColor wedge_color(); void set_wedge_color(QColor &c); + void setTitle(const QString &str); + void setPos(qreal x, qreal y); struct ConnectorPair { Connector *in, *out; }; @@ -37,8 +38,10 @@ private slots: private: qreal height; - QList<ConnectorPair> connectors; - QList<qreal> connectors_off; + QVector<ConnectorPair> connectors; + QVector<qreal> connectors_off; + + QGraphicsSimpleTextItem *title; QPropertyAnimation *wedge_animation; QColor wedge_clr; @@ -46,10 +49,4 @@ private: } -#else - -namespace coreview { - class Latch; -}; - #endif // COREVIEW_LATCH_H diff --git a/qtmips_gui/coreview/memory.cpp b/qtmips_gui/coreview/memory.cpp index c732687..13355db 100644 --- a/qtmips_gui/coreview/memory.cpp +++ b/qtmips_gui/coreview/memory.cpp @@ -1,63 +1,119 @@ #include "memory.h" +#include <cmath> using namespace coreview; ////////////////////// -#define WIDTH 80 -#define HEIGHT 100 +#define WIDTH 680 +#define HEIGHT 30 #define PENW 1 ////////////////////// Memory::Memory(machine::QtMipsMachine *machine) : QGraphicsObject(nullptr) { -#define CON_INIT(X) do { \ - X.in = new Connector(); \ - X.out = new Connector(); \ - X.read = new Connector(); \ - X.write = new Connector(); \ - } while(false) - CON_INIT(con_program); - CON_INIT(con_data); -#undef CON_INIT - // TODO cache? + con_pc = new Connector(M_PI_2); + con_inst = new Connector(M_PI_2); + con_address = new Connector(M_PI_2); + con_data_in = new Connector(M_PI_2); + con_data_out = new Connector(M_PI_2); + con_req_write = new Connector(M_PI_2); + con_req_read = new Connector(M_PI_2); + + if (machine->config().cache()) { + // TODO cache? + } + + name = new QGraphicsSimpleTextItem("Memory", this); + QRectF name_box = name->boundingRect(); + name->setPos(WIDTH/2 - name_box.width()/2, HEIGHT/2 - name_box.height()/2); + + // TODO add labels for connections + + QFont font; + font.setPointSize(7); + + // TODO better placement + name_program = new QGraphicsSimpleTextItem("Program", this); + name_box = name_program->boundingRect(); + name_program->setPos(1, HEIGHT - 1 - name_box.height()); + name_program->setFont(font); + + name_data = new QGraphicsSimpleTextItem("Data", this); + name_box = name_data->boundingRect(); + name_data->setPos(WIDTH - 1 - name_box.width(), HEIGHT - 1 - name_box.height()); + name_data->setFont(font); + + setPos(x(), y()); // set connector's position +} + +Memory::~Memory() { + delete con_pc; + delete con_inst; + delete con_address; + delete con_data_out; + delete con_data_in; + delete con_req_write; + delete con_req_read; + + delete name; + delete name_program; + delete name_data; } QRectF Memory::boundingRect() const { - // TODO + return QRectF(-PENW / 2, -PENW / 2, WIDTH + PENW, HEIGHT + PENW); } void Memory::paint(QPainter *painter, const QStyleOptionGraphicsItem *option __attribute__((unused)), QWidget *widget __attribute__((unused))) { - // TODO + painter->drawRect(0, 0, WIDTH, HEIGHT); + // TODO cache } void Memory::setPos(qreal x, qreal y) { QGraphicsObject::setPos(x, y); - // TODO con + + con_pc->setPos(x + 30, y); + con_inst->setPos(x + 40, y); + + con_address->setPos(x + WIDTH - 70, y); + con_data_in->setPos(x + WIDTH - 60, y); + con_req_write->setPos(x + WIDTH- 50, y); + con_req_read->setPos(x + WIDTH - 40, y); + con_data_out->setPos(x + WIDTH - 30, y); } -const Connector *Memory::connector_in(bool program) const { - if (program) - return con_program.in; - else - return con_data.in; +const Connector *Memory::connector_pc() const { + return con_pc; } -const Connector *Memory::connector_out(bool program) const { - if (program) - return con_program.out; - else - return con_data.out; +const Connector *Memory::connector_inst() const { + return con_inst; } -const Connector *Memory::connector_read(bool program) const { - if (program) - return con_program.read; - else - return con_data.read; +const Connector *Memory::connector_address() const { + return con_address; +} + +const Connector *Memory::connector_data_out() const { + return con_data_out; +} + +const Connector *Memory::connector_data_in() const { + return con_data_in; +} + +const Connector *Memory::connector_req_write() const { + return con_req_write; } -const Connector *Memory::connector_write(bool program) const { - if (program) - return con_program.write; +const Connector *Memory::connector_req_read() const { + return con_req_read; +} + +void Memory::mouseDoubleClickEvent(QGraphicsSceneMouseEvent *event) { + QGraphicsObject::mouseDoubleClickEvent(event); + + if (event->pos().x() < WIDTH/2) + emit open_program_mem(); else - return con_data.write; + emit open_data_mem(); } diff --git a/qtmips_gui/coreview/memory.h b/qtmips_gui/coreview/memory.h index 0f0d40d..067d62f 100644 --- a/qtmips_gui/coreview/memory.h +++ b/qtmips_gui/coreview/memory.h @@ -3,39 +3,48 @@ #include <QGraphicsObject> #include <QPainter> +#include <QGraphicsSceneMouseEvent> +#include <QGraphicsSimpleTextItem> #include <qtmipsmachine.h> -#include "../coreview.h" #include "connection.h" -namespace coreview{ +namespace coreview { class Memory : public QGraphicsObject { Q_OBJECT public: Memory(machine::QtMipsMachine *machine); + ~Memory(); QRectF boundingRect() const; void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget); void setPos(qreal x, qreal y); - const Connector *connector_in(bool program) const; - const Connector *connector_out(bool program) const; - const Connector *connector_read(bool program) const; - const Connector *connector_write(bool program) const; + const Connector *connector_pc() const; + const Connector *connector_inst() const; + const Connector *connector_address() const; + const Connector *connector_data_out() const; + const Connector *connector_data_in() const; + const Connector *connector_req_write() const; + const Connector *connector_req_read() const; // TODO integrate cache -private: - struct { - Connector *in, *out, *read, *write; - } con_program, con_data; -}; +signals: + void open_data_mem(); + void open_program_mem(); -} +protected: + void mouseDoubleClickEvent(QGraphicsSceneMouseEvent *event); -#else +private: + // Connectors for instruction memory + Connector *con_pc, *con_inst; + // Connectors for data memory + Connector *con_address, *con_data_out, *con_data_in, *con_req_write, *con_req_read; + + QGraphicsSimpleTextItem *name, *name_program, *name_data; +}; -namespace coreview { - class Memory; } #endif // MEMORY_H diff --git a/qtmips_gui/coreview/multiplexer.cpp b/qtmips_gui/coreview/multiplexer.cpp index 6f6abe1..b8bab5a 100644 --- a/qtmips_gui/coreview/multiplexer.cpp +++ b/qtmips_gui/coreview/multiplexer.cpp @@ -1,9 +1,10 @@ #include "multiplexer.h" +#include <cmath> using namespace coreview; ////////////////////// -#define WIDTH 20 +#define WIDTH 10 #define HEIGHT 20 #define PENW 1 ////////////////////// @@ -12,11 +13,11 @@ Multiplexer::Multiplexer(unsigned size) { this->size = size; seton = 0; ctlfrom = false; - con_ctl = new Connector(); - con_out = new Connector(); + con_ctl = new Connector(M_PI_2); + con_out = new Connector(M_PI); con_in = new Connector*[size]; for (unsigned i = 0; i < size; i++) - con_in[i] = new Connector(); + con_in[i] = new Connector(0); setPos(x(), y()); // Set connectors possitions } @@ -33,6 +34,10 @@ QRectF Multiplexer::boundingRect() const { } void Multiplexer::paint(QPainter *painter, const QStyleOptionGraphicsItem *option __attribute__((unused)), QWidget *widget __attribute__((unused))) { + painter->setPen(QColor(200, 200, 200)); + painter->drawLine(0, (HEIGHT / 2) + (seton * HEIGHT), WIDTH, (HEIGHT * size) / 2); + + painter->setPen(QColor(0, 0, 0)); const QPointF poly[] = { QPointF(0, 0), QPointF(WIDTH, WIDTH), @@ -40,9 +45,6 @@ void Multiplexer::paint(QPainter *painter, const QStyleOptionGraphicsItem *optio QPointF(0, HEIGHT * size) }; painter->drawPolygon(poly, sizeof(poly) / sizeof(QPointF)); - - painter->setPen(QColor(200, 200, 200)); - painter->drawLine(0, (HEIGHT / 2) + (seton * HEIGHT), WIDTH, (HEIGHT * size) / 2); } void Multiplexer::setPos(qreal x, qreal y) { diff --git a/qtmips_gui/coreview/multiplexer.h b/qtmips_gui/coreview/multiplexer.h index 16378fe..2ce7dab 100644 --- a/qtmips_gui/coreview/multiplexer.h +++ b/qtmips_gui/coreview/multiplexer.h @@ -3,7 +3,6 @@ #include <QGraphicsItem> #include "qtmipsexception.h" -#include "../coreview.h" #include "connection.h" namespace coreview { @@ -32,10 +31,4 @@ private: } -#else - -namespace coreview { - class Multiplexer; -} - #endif // COREVIEW_MULTIPLEXER_H diff --git a/qtmips_gui/coreview/programcounter.cpp b/qtmips_gui/coreview/programcounter.cpp index 1f4e623..b66d7ac 100644 --- a/qtmips_gui/coreview/programcounter.cpp +++ b/qtmips_gui/coreview/programcounter.cpp @@ -1,23 +1,29 @@ #include "programcounter.h" +#include <cmath> using namespace coreview; ////////////////////// -#define WIDTH 80 -#define HEIGHT 50 +#define WIDTH 72 +#define HEIGHT 25 #define PENW 1 ////////////////////// -ProgramCounter::ProgramCounter(machine::QtMipsMachine *machine) : QGraphicsObject(nullptr), value(this), name(this) { - value.setText(QString("0x") + QString::number(machine->registers()->read_pc(), 16)); - value.setPos(1, HEIGHT/2 - value.boundingRect().height()/2); - name.setText(QString("PC")); +ProgramCounter::ProgramCounter(machine::QtMipsMachine *machine) : QGraphicsObject(nullptr), name("PC", this), value(this) { + QFont font; + + font.setPointSize(7); name.setPos(WIDTH/2 - name.boundingRect().width()/2, 0); + name.setFont(font); + font.setPointSize(8); + value.setText(QString("0x") + QString::number(machine->registers()->read_pc(), 16)); + value.setPos(1, HEIGHT - value.boundingRect().height()); + value.setFont(font); connect(machine->registers(), SIGNAL(pc_update(std::uint32_t)), this, SLOT(pc_update(std::uint32_t))); - con_in = new Connector(); - con_out = new Connector(); + con_in = new Connector(M_PI_2); + con_out = new Connector(-M_PI_2); setPos(x(), y()); // To set initial connectors positions } @@ -31,8 +37,8 @@ void ProgramCounter::paint(QPainter *painter, const QStyleOptionGraphicsItem *op 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); + con_in->setPos(x + WIDTH/2, y); + con_out->setPos(x + WIDTH/2, y + HEIGHT); } const Connector *ProgramCounter::connector_in() const { diff --git a/qtmips_gui/coreview/programcounter.h b/qtmips_gui/coreview/programcounter.h index 220b42e..c60ad36 100644 --- a/qtmips_gui/coreview/programcounter.h +++ b/qtmips_gui/coreview/programcounter.h @@ -4,7 +4,6 @@ #include <QGraphicsObject> #include <QPainter> #include "qtmipsmachine.h" -#include "../coreview.h" #include "connection.h" namespace coreview { @@ -25,18 +24,13 @@ private slots: void pc_update(std::uint32_t val); private: - QGraphicsSimpleTextItem value; QGraphicsSimpleTextItem name; + QGraphicsSimpleTextItem value; Connector *con_in, *con_out; }; } -#else - -namespace coreview { - class ProgramCounter; -}; #endif // COREVIEW_PROGRAMCOUNTER_H diff --git a/qtmips_gui/coreview/registers.cpp b/qtmips_gui/coreview/registers.cpp new file mode 100644 index 0000000..12684e8 --- /dev/null +++ b/qtmips_gui/coreview/registers.cpp @@ -0,0 +1,95 @@ +#include "registers.h" +#include <cmath> + +using namespace coreview; + +////////////////////// +#define WIDTH 680 +#define HEIGHT 30 +#define PENW 1 +////////////////////// + +Registers::Registers() : QGraphicsObject(nullptr) { + con_read1 = new Connector(-M_PI_2); + con_read1_reg = new Connector(-M_PI_2); + con_read2 = new Connector(-M_PI_2); + con_read2_reg = new Connector(-M_PI_2); + con_write = new Connector(-M_PI_2); + con_write_reg = new Connector(-M_PI_2); + con_ctl_write = new Connector(-M_PI_2); + + // TODO do we want to have any hooks on real registers? + + // TODO add labels for connections + + name = new QGraphicsSimpleTextItem("Registers", this); + QRectF name_box = name->boundingRect(); + name->setPos(WIDTH/2 - name_box.width()/2, HEIGHT/2 - name_box.height()/2); + + setPos(x(), y()); // set connector's position +} + +Registers::~Registers() { + delete con_read1; + delete con_read1_reg; + delete con_read2; + delete con_read2_reg; + delete con_write; + delete con_write_reg; + delete con_ctl_write; +} + +QRectF Registers::boundingRect() const { + return QRectF(-PENW / 2, -PENW / 2, WIDTH + PENW, HEIGHT + PENW); +} + +void Registers::paint(QPainter *painter, const QStyleOptionGraphicsItem *option __attribute((unused)), QWidget *widget __attribute((unused))) { + painter->drawRect(0, 0, WIDTH, HEIGHT); + // TODO anything else? +} + +void Registers::setPos(qreal x, qreal y) { + QGraphicsObject::setPos(x, y); + + con_read1_reg->setPos(x + 30, y + HEIGHT); + con_read2_reg->setPos(x + 40, y + HEIGHT); + con_read1->setPos(x + 60, y + HEIGHT); + con_read2->setPos(x + 70, y + HEIGHT); + + con_write_reg->setPos(x + WIDTH - 40, y + HEIGHT); + con_write->setPos(x + WIDTH - 30, y + HEIGHT); + con_ctl_write->setPos(x + WIDTH - 20, y + HEIGHT); +} + +const Connector *Registers::connector_read1() const { + return con_read1; +} + +const Connector *Registers::connector_read1_reg() const { + return con_read1_reg; +} + +const Connector *Registers::connector_read2() const { + return con_read2; +} + +const Connector *Registers::connector_read2_reg() const { + return con_read2_reg; +} + +const Connector *Registers::connector_write() const { + return con_write; +} + +const Connector *Registers::connector_write_reg() const { + return con_write_reg; +} + +const Connector *Registers::connector_ctl_write() const { + return con_ctl_write; +} + +void Registers::mouseDoubleClickEvent(QGraphicsSceneMouseEvent *event) { + QGraphicsObject::mouseDoubleClickEvent(event); + emit open_registers(); +} diff --git a/qtmips_gui/coreview/registers.h b/qtmips_gui/coreview/registers.h new file mode 100644 index 0000000..ece710d --- /dev/null +++ b/qtmips_gui/coreview/registers.h @@ -0,0 +1,44 @@ +#ifndef COREVIEW_REGISTERS_H +#define COREVIEW_REGISTERS_H + +#include <QGraphicsObject> +#include <QPainter> +#include <QGraphicsSimpleTextItem> +#include "connection.h" + +namespace coreview { + +class Registers : public QGraphicsObject { + Q_OBJECT +public: + Registers(); + ~Registers(); + + QRectF boundingRect() const; + void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget); + + void setPos(qreal x, qreal y); + const Connector *connector_read1() const; + const Connector *connector_read1_reg() const; + const Connector *connector_read2() const; + const Connector *connector_read2_reg() const; + const Connector *connector_write() const; + const Connector *connector_write_reg() const; + const Connector *connector_ctl_write() const; + +signals: + void open_registers(); + +protected: + void mouseDoubleClickEvent(QGraphicsSceneMouseEvent *event); + +private: + Connector *con_read1, *con_read1_reg, *con_read2, *con_read2_reg; + Connector *con_write, *con_write_reg, *con_ctl_write; + + QGraphicsSimpleTextItem *name; +}; + +} + +#endif // COREVIEW_REGISTERS_H diff --git a/qtmips_gui/mainwindow.cpp b/qtmips_gui/mainwindow.cpp index a476290..20cd1d9 100644 --- a/qtmips_gui/mainwindow.cpp +++ b/qtmips_gui/mainwindow.cpp @@ -87,7 +87,11 @@ void MainWindow::create_core(const machine::MachineConfig &config) { // Create machine view if (corescene != nullptr) delete corescene; - corescene = new CoreViewScene(coreview, machine); + if (config.pipelined()) { + corescene = new CoreViewScenePipelined(coreview, machine); + } else { + corescene = new CoreViewSceneSimple(coreview, machine); + } coreview->setScene(corescene); set_speed(); // Update machine speed to current settings @@ -100,6 +104,10 @@ void MainWindow::create_core(const machine::MachineConfig &config) { connect(machine, SIGNAL(status_change(machine::QtMipsMachine::Status)), this, SLOT(machine_status(machine::QtMipsMachine::Status))); connect(machine, SIGNAL(program_exit()), this, SLOT(machine_exit())); connect(machine, SIGNAL(program_trap(machine::QtMipsException&)), this, SLOT(machine_trap(machine::QtMipsException&))); + // Connect scene signals to actions + connect(corescene, SIGNAL(request_registers()), this, SLOT(show_registers())); + connect(corescene, SIGNAL(request_program_memory()), this, SLOT(show_program())); + connect(corescene, SIGNAL(request_data_memory()), this, SLOT(show_memory())); // Setup docks registers->setup(machine); diff --git a/qtmips_gui/qtmips_gui.pro b/qtmips_gui/qtmips_gui.pro index 76c5e0f..719a7b9 100644 --- a/qtmips_gui/qtmips_gui.pro +++ b/qtmips_gui/qtmips_gui.pro @@ -18,6 +18,8 @@ SOURCES += \ newdialog.cpp \ coreview.cpp \ registersdock.cpp \ + programdock.cpp \ + memorydock.cpp \ memoryview.cpp \ cachestatistics.cpp \ cachecontent.cpp \ @@ -27,14 +29,19 @@ SOURCES += \ coreview/latch.cpp \ coreview/alu.cpp \ coreview/memory.cpp \ - programdock.cpp \ - memorydock.cpp + coreview/instructionview.cpp \ + coreview/registers.cpp \ + coreview/adder.cpp \ + coreview/constant.cpp \ + coreview/junction.cpp HEADERS += \ mainwindow.h \ newdialog.h \ coreview.h \ registersdock.h \ + programdock.h \ + memorydock.h \ memoryview.h \ cachestatistics.h \ cachecontent.h \ @@ -44,8 +51,11 @@ HEADERS += \ coreview/latch.h \ coreview/alu.h \ coreview/memory.h \ - programdock.h \ - memorydock.h + coreview/instructionview.h \ + coreview/registers.h \ + coreview/adder.h \ + coreview/constant.h \ + coreview/junction.h FORMS += \ NewDialog.ui \ |