aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKarel Kočí <cynerd@email.cz>2018-01-21 18:22:07 +0100
committerKarel Kočí <cynerd@email.cz>2018-01-21 18:22:07 +0100
commit74ff0f2d5282adf5ce36c9faeb2a5e85c358bf23 (patch)
tree4d31bff7ddb830c2d6b14cd9df4abe6c13e27878
parent16b1544fff7e9ca11deb3ae1b891c79eac7ec50e (diff)
downloadqtmips-74ff0f2d5282adf5ce36c9faeb2a5e85c358bf23.tar.gz
qtmips-74ff0f2d5282adf5ce36c9faeb2a5e85c358bf23.tar.bz2
qtmips-74ff0f2d5282adf5ce36c9faeb2a5e85c358bf23.zip
Implement even more parts of the schema
-rw-r--r--qtmips_gui/coreview.cpp129
-rw-r--r--qtmips_gui/coreview.h14
-rw-r--r--qtmips_gui/coreview/connection.cpp52
-rw-r--r--qtmips_gui/coreview/connection.h12
-rw-r--r--qtmips_gui/coreview/logicblock.cpp8
-rw-r--r--qtmips_gui/coreview/registers.cpp26
6 files changed, 180 insertions, 61 deletions
diff --git a/qtmips_gui/coreview.cpp b/qtmips_gui/coreview.cpp
index 6b85cfe..0fb5e76 100644
--- a/qtmips_gui/coreview.cpp
+++ b/qtmips_gui/coreview.cpp
@@ -59,18 +59,21 @@ CoreViewScene::CoreViewScene(CoreView *view, machine::QtMipsMachine *machine) :
setSceneRect(0, 0, SC_WIDTH, SC_HEIGHT);
// Identification cross (TODO remove)
+ /*
QPen pen;
pen.setBrush(QBrush(QColor(220, 220, 220)));
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
// Elements //
// Primary points
NEW(ProgramMemory, mem_program, 90, 240, machine);
- NEW(DataMemory, mem_data, 600, 300, machine);
- NEW(Registers, regs, 210, 240);
+ NEW(DataMemory, mem_data, 580, 265, machine);
+ NEW(Registers, regs, 230, 240);
+ NEW(Alu, alu, 470, 225);
// Fetch stage
NEW(ProgramCounter, ft.pc, 2, 280, machine);
NEW(Latch, ft.latch, 55, 250, machine, 20);
@@ -83,20 +86,23 @@ CoreViewScene::CoreViewScene(CoreView *view, machine::QtMipsMachine *machine) :
// Decode stage
NEW(LogicBlock, dc.ctl_block, 230, 90, {"Control", "unit"});
dc.ctl_block->setSize(35, 70);
- NEW(LogicBlock, dc.sign_ext, 230, 360, {"Sign", "extension"});
- NEW(LogicBlock, dc.shift2, 290, 390, "<<2");
- NEW(Adder, dc.add, 320, 390);
+ NEW(LogicBlock, dc.sign_ext, 250, 400, {"Sign", "extension"});
+ NEW(LogicBlock, dc.shift2, 310, 428, "<<2");
+ NEW(Adder, dc.add, 340, 428);
const coreview::Connector *dc_con_sign_ext = dc.sign_ext->new_connector(1, 0);
- NEW(Junction, dc.j_sign_ext, 270, dc_con_sign_ext->y());
+ NEW(Junction, dc.j_sign_ext, 290, dc_con_sign_ext->y());
NEW(LogicBlock, dc.cmp, 320, 200, "=");
NEW(And, dc.and_branch, 350, 190);
dc.cmp->setSize(24, 12);
- NEW(Junction, dc.j_inst_up, 180, 126);
- NEW(Junction, dc.j_inst_down, 180, dc_con_sign_ext->y());
+ NEW(Junction, dc.j_inst_up, 190, 126);
+ NEW(Junction, dc.j_inst_down, 190, dc_con_sign_ext->y());
// Execute stage
- NEW(Alu, alu, 470, 230);
- // Memory stage
- NEW(Multiplexer, mem_or_reg, 570, 180, 2);
+ NEW(Junction, ex.j_mux, 420, 316);
+ NEW(Multiplexer, ex.mux_imm, 450, 306, 2);
+ // Memory
+ NEW(Junction, mm.j_addr, 570, mem_data->connector_address()->y());
+ // WriteBack stage
+ NEW(Multiplexer, wb.mem_or_reg, 690, 252, 2);
// Connections //
coreview::Connection *con;
@@ -120,11 +126,21 @@ CoreViewScene::CoreViewScene(CoreView *view, machine::QtMipsMachine *machine) :
dc.instr_bus = new_bus(dc.j_inst_up->new_connector(coreview::Connector::AX_Y), dc.j_inst_down->new_connector(coreview::Connector::AX_Y));
new_bus(dc.j_inst_up->new_connector(coreview::Connector::AX_X), dc.ctl_block->new_connector(-1, 0), 2);
new_bus(dc.j_inst_down->new_connector(coreview::Connector::AX_X), dc.sign_ext->new_connector(-1, 0), 2);
+ new_bus(dc.instr_bus->new_connector(regs->connector_read1_reg()->point()), regs->connector_read1_reg(), 2);
+ new_bus(dc.instr_bus->new_connector(regs->connector_read2_reg()->point()), regs->connector_read2_reg(), 2);
+ // Execute stage
+ new_bus(ex.j_mux->new_connector(CON_AX_X), ex.mux_imm->connector_in(0));
+ new_bus(ex.mux_imm->connector_out(), alu->connector_in_b());
+ // Memory stage
+ new_bus(mm.j_addr->new_connector(CON_AX_X), mem_data->connector_address());
// From decode stage to fetch stage
con = new_signal(dc.and_branch->connector_out(), ft.multiplex->connector_ctl());
con->setAxes({CON_AXIS_Y(365), CON_AXIS_X(490)});
con = new_bus(dc.add->connector_out(), ft.multiplex->connector_in(1));
- con->setAxes({CON_AXIS_Y(340), CON_AXIS_X(480), CON_AXIS_Y(10)});
+ con->setAxes({CON_AXIS_Y(360), CON_AXIS_X(480), CON_AXIS_Y(10)});
+ // From write back stage to decode stage
+ con = new_bus(wb.mem_or_reg->connector_out(), regs->connector_write());
+ con->setAxes({CON_AXIS_Y(710), CON_AXIS_X(510), CON_AXIS_Y(172)});
connect(regs, SIGNAL(open_registers()), this, SIGNAL(request_registers()));
connect(mem_program, SIGNAL(open_mem()), this, SIGNAL(request_program_memory()));
@@ -132,54 +148,55 @@ CoreViewScene::CoreViewScene(CoreView *view, machine::QtMipsMachine *machine) :
}
CoreViewScene::~CoreViewScene() {
- for (int i = 0; i < connections.size(); i++)
- delete connections[i];
-
- delete ft.pc;
- delete ft.latch;
- delete ft.adder;
- delete ft.adder_4;
- delete ft.junc_pc;
- delete ft.junc_pc_4;
- delete ft.multiplex;
- delete dc.ctl_block;
- delete dc.sign_ext;
- delete dc.shift2;
- delete dc.cmp;
- delete dc.add;
- delete dc.j_sign_ext;
- delete dc.and_branch;
- delete alu;
- delete mem_program;
- delete mem_data;
- delete regs;
- delete mem_or_reg;
+ // We add all items to scene and they are removed in QGraphicsScene descructor so we don't have to care about them here
}
coreview::Connection *CoreViewScene::new_connection(const coreview::Connector *a, const coreview::Connector *b) {
coreview::Connection *c = new coreview::Connection(a, b);
- connections.append(c);
addItem(c);
+ c->setZValue(-1); // hide connections under neath the items
return c;
}
coreview::Bus *CoreViewScene::new_bus(const coreview::Connector *a, const coreview::Connector *b, unsigned width) {
coreview::Bus *c = new coreview::Bus(a, b, width);
- connections.append(c);
addItem(c);
+ c->setZValue(-2); // hide connections under neath the items
return c;
}
coreview::Signal *CoreViewScene::new_signal(const coreview::Connector *a, const coreview::Connector *b) {
coreview::Signal *c = new coreview::Signal(a, b);
- connections.append(c);
addItem(c);
- c->setZValue(-1); // hide connections under neath the items
+ c->setZValue(-3); // hide connections under neath the items
return c;
}
CoreViewSceneSimple::CoreViewSceneSimple(CoreView *view, machine::QtMipsMachine *machine) : CoreViewScene(view, machine) {
- NEW(Latch, delay_slot_latch, 160, 50, machine, 150);
+ NEW(Latch, delay_slot_latch, 55, 460, machine, 50);
+
+ coreview::Connection *con;
+ // Fetch stage
+ new_bus(mem_program->connector_instruction(), dc.instr_bus->new_connector(mem_program->connector_instruction()->point()));
+ con = new_bus(ft.junc_pc_4->new_connector(coreview::Connector::AX_Y), dc.add->connector_in_b());
+ con->setAxes({CON_AXIS_Y(270)});
+ // Decode stage
+ con = new_bus(regs->connector_read1(), alu->connector_in_a());
+ con->setAxes({CON_AXIS_Y(445)});
+ con = new_bus(regs->connector_read2(), ex.mux_imm->connector_in(0));
+ con->setAxes({CON_AXIS_Y(420)});
+ con = new_bus(dc.j_sign_ext->new_connector(coreview::Connector::AX_X), ex.mux_imm->connector_in(1));
+ con->setAxes({CON_AXIS_Y(440)});
+ // Execute
+ new_bus(alu->connector_out(), mm.j_addr->new_connector(CON_AX_X));
+ con = new_bus(ex.j_mux->new_connector(CON_AX_Y), mem_data->connector_data_in());
+ con->setAxes({CON_AXIS_X(360), CON_AXIS_Y(560)});
+ // Memory
+ con = new_bus(mm.j_addr->new_connector(CON_AX_Y), wb.mem_or_reg->connector_in(0));
+ con->setAxes({CON_AXIS_X(250), CON_AXIS_Y(678)});
+ con = new_bus(mem_data->connector_data_out(), wb.mem_or_reg->connector_in(1));
+ con->setAxes({CON_AXIS_Y(678)});
+ // WriteBack
}
CoreViewSceneSimple::~CoreViewSceneSimple() {
@@ -193,7 +210,7 @@ CoreViewScenePipelined::CoreViewScenePipelined(CoreView *view, machine::QtMipsMa
latch_id_ex->setTitle("ID/EX");
NEW(Latch, latch_ex_mem, 536, 90, machine, 380);
latch_ex_mem->setTitle("EX/MEM");
- NEW(Latch, latch_mem_wb, 680, 90, machine, 380);
+ NEW(Latch, latch_mem_wb, 660, 90, machine, 380);
latch_mem_wb->setTitle("MEM/WB");
NEW_I(inst_fetch, 100, 2, instruction_fetched(const machine::Instruction&));
@@ -214,9 +231,39 @@ CoreViewScenePipelined::CoreViewScenePipelined(CoreView *view, machine::QtMipsMa
struct coreview::Latch::ConnectorPair lp_ft_pc = latch_if_id->new_connector(370);
new_bus(ft.junc_pc_4->new_connector(coreview::Connector::AX_Y), lp_ft_pc.in);
// Decode stage
- //new_bus(lp_ft_inst.out, dc.instr_bus->new_connector(lp_ft_inst.out->point()));
+ new_bus(lp_ft_inst.out, dc.instr_bus->new_connector(lp_ft_inst.out->point()));
con = new_bus(lp_ft_pc.out, dc.add->connector_in_b());
con->setAxes({CON_AXIS_Y(270)});
+ struct coreview::Latch::ConnectorPair lp_dc_rs = latch_id_ex->new_connector(regs->connector_read1()->y() - latch_id_ex->y());
+ struct coreview::Latch::ConnectorPair lp_dc_rt = latch_id_ex->new_connector(regs->connector_read2()->y() - latch_id_ex->y());
+ new_bus(regs->connector_read1(), lp_dc_rs.in);
+ new_bus(regs->connector_read2(), lp_dc_rt.in);
+ struct coreview::Latch::ConnectorPair lp_dc_immed = latch_id_ex->new_connector(dc.j_sign_ext->y() - latch_id_ex->y());
+ new_bus(dc.j_sign_ext->new_connector(coreview::Connector::AX_X), lp_dc_immed.in);
+ // Execute
+ con = new_bus(lp_dc_rs.out, alu->connector_in_a());
+ con->setAxes({CON_AXIS_Y(445)});
+ con = new_bus(lp_dc_rt.out, ex.mux_imm->connector_in(0));
+ con->setAxes({CON_AXIS_Y(420)});
+ con = new_bus(lp_dc_immed.out, ex.mux_imm->connector_in(1));
+ con->setAxes({CON_AXIS_Y(440)});
+ struct coreview::Latch::ConnectorPair lp_ex_alu = latch_ex_mem->new_connector(alu->connector_out()->y() - latch_ex_mem->y());
+ struct coreview::Latch::ConnectorPair lp_ex_dt = latch_ex_mem->new_connector(270);
+ new_bus(alu->connector_out(), lp_ex_alu.in);
+ new_bus(ex.j_mux->new_connector(CON_AX_Y), lp_ex_dt.in);
+ // Memory
+ new_bus(lp_ex_alu.out, mm.j_addr->new_connector(CON_AX_X));
+ con = new_bus(lp_ex_dt.out, mem_data->connector_data_in());
+ con->setAxes({CON_AXIS_Y(560)});
+ struct coreview::Latch::ConnectorPair lp_mem_alu = latch_mem_wb->new_connector(160);
+ struct coreview::Latch::ConnectorPair lp_mem_mem = latch_mem_wb->new_connector(mem_data->connector_data_out()->y() - latch_mem_wb->y());
+ new_bus(mm.j_addr->new_connector(CON_AX_Y), lp_mem_alu.in);
+ new_bus(mem_data->connector_data_out(), lp_mem_mem.in);
+ // WriteBack
+ con = new_bus(lp_mem_alu.out, wb.mem_or_reg->connector_in(0));
+ con->setAxes({CON_AXIS_Y(678)});
+ con = new_bus(lp_mem_mem.out, wb.mem_or_reg->connector_in(1));
+ con->setAxes({CON_AXIS_Y(678)});
}
CoreViewScenePipelined::~CoreViewScenePipelined() {
diff --git a/qtmips_gui/coreview.h b/qtmips_gui/coreview.h
index edc970c..ed8a8ad 100644
--- a/qtmips_gui/coreview.h
+++ b/qtmips_gui/coreview.h
@@ -45,6 +45,7 @@ protected:
coreview::ProgramMemory *mem_program;
coreview::DataMemory *mem_data;
coreview::Registers *regs;
+ coreview::Alu *alu;
struct {
coreview::ProgramCounter *pc;
coreview::Latch *latch;
@@ -61,10 +62,17 @@ protected:
coreview::Junction *j_inst_up, *j_inst_down;
coreview::Bus *instr_bus;
} dc;
- coreview::Alu *alu;
- coreview::Multiplexer *mem_or_reg;
+ struct {
+ coreview::Junction *j_mux;
+ coreview::Multiplexer *mux_imm;
+ } ex;
+ struct {
+ coreview::Junction *j_addr;
+ } mm;
+ struct {
+ coreview::Multiplexer *mem_or_reg;
+ } wb;
- QVector<coreview::Connection*> connections;
coreview::Connection *new_connection(const coreview::Connector*, const coreview::Connector*);
coreview::Bus *new_bus(const coreview::Connector*, const coreview::Connector*, unsigned width = 4);
coreview::Signal *new_signal(const coreview::Connector*, const coreview::Connector*);
diff --git a/qtmips_gui/coreview/connection.cpp b/qtmips_gui/coreview/connection.cpp
index 3355eed..31d93e5 100644
--- a/qtmips_gui/coreview/connection.cpp
+++ b/qtmips_gui/coreview/connection.cpp
@@ -1,4 +1,5 @@
#include "connection.h"
+#include <qtmipsexception.h>
#include <cmath>
using namespace coreview;
@@ -14,6 +15,10 @@ void Connector::setPos(qreal x, qreal y) {
emit updated(vector());
}
+void Connector::setPos(const QPointF &p) {
+ setPos(p.x(), p.y());
+}
+
enum Connector::Axis Connector::axis() const {
return ax;
}
@@ -42,6 +47,7 @@ QLineF Connector::vector() const {
case AX_MXY:
return QLineF(p, p + QPoint(1, -1));
}
+ throw QTMIPS_EXCEPTION(Sanity, "Connection::vector() unknown axes set", QString::number(ax));
}
Connection::Connection(const Connector *a, const Connector *b) : QGraphicsObject(nullptr) {
@@ -134,13 +140,23 @@ Bus::Bus(const Connector *start, const Connector *end, unsigned width) : Connect
pen_width = width;
}
+Bus::~Bus() {
+ for (int i = 0; i < conns.size(); i++)
+ delete conns[i].c;
+}
+
+void Bus::setAxes(QVector<QLineF> axes) {
+ Connection::setAxes(axes);
+ conns_update();
+}
+
const Connector *Bus::new_connector(qreal x, qreal y, enum Connector::Axis axis) {
Connector *c = new Connector(axis);
conns.append({
.c = c,
.p = QPoint(x, y)
});
- // TODO update positions
+ conns_update();
return c;
}
@@ -148,6 +164,40 @@ const Connector *Bus::new_connector(const QPointF &p, enum Connector::Axis axis)
return new_connector(p.x(), p.y(), axis);
}
+// Calculate closes point to given line. We do it by calculating rectangular intersection between given line and imaginary line crossing given point.
+static qreal cu_closest(const QLineF &l, const QPointF &p, QPointF *intersec) {
+ // Closest point is on normal vector
+ QLineF normal = l.normalVector();
+ // Now move normal vector to 0,0 and then to p
+ QLineF nline = normal.translated(-normal.p1()).translated(p);
+ // And now found intersection
+ SANITY_ASSERT(l.intersect(nline, intersec) != QLineF::NoIntersection, "We are calculating intersection with normal vector and that should always have intersection");
+ // Now check if that point belongs to given line
+ // We know that this is intersection so just check if we are not outside of line limits
+ // TODO replace intersec if it's outside of given line with one of corner points
+
+ return (p - *intersec).manhattanLength(); // return length from each other
+}
+
+void Bus::conns_update() {
+ for (int i = 0; i < conns.size(); i++) {
+ QPointF closest;
+ qreal closest_range = 0; // Just to suppress warning. On first check the closest is null so we set it later on
+
+ QPointF inter;
+ qreal range;
+ for (int y = 0; y < (points.size() - 1); y++) {
+ range = cu_closest(QLineF(points[y], points[y+1]), QPointF(conns[i].p), &inter);
+ if (closest.isNull() || closest_range > range) {
+ closest = inter;
+ closest_range = range;
+ }
+ }
+
+ conns[i].c->setPos(closest);
+ }
+}
+
Signal::Signal(const Connector *start, const Connector *end) : Connection(start, end) {
color = QColor(0, 0, 255);
}
diff --git a/qtmips_gui/coreview/connection.h b/qtmips_gui/coreview/connection.h
index 88ad1da..fa40d95 100644
--- a/qtmips_gui/coreview/connection.h
+++ b/qtmips_gui/coreview/connection.h
@@ -20,6 +20,7 @@ public:
Connector(enum Axis axis = AX_X);
void setPos(qreal x, qreal y);
+ void setPos(const QPointF&);
enum Axis axis() const;
qreal x() const;
@@ -48,7 +49,7 @@ public:
void setHasText(bool has);
void setText(QString val);
- void setAxes(QVector<QLineF>);
+ virtual void setAxes(QVector<QLineF>);
private slots:
void moved_start(QLineF);
@@ -71,6 +72,9 @@ protected:
class Bus : public Connection {
public:
Bus(const Connector *start, const Connector *end, unsigned width = 4);
+ ~Bus();
+
+ void setAxes(QVector<QLineF>);
// This creates connector snapped to closes point to x,y that is on bus
const Connector *new_connector(qreal x, qreal y, enum Connector::Axis = Connector::AX_X);
@@ -82,6 +86,7 @@ protected:
QPointF p;
};
QVector<struct con_pos> conns;
+ void conns_update();
// TODO because of this we have to overload setAxis function and update that in there
};
@@ -90,6 +95,11 @@ public:
Signal(const Connector *start, const Connector *end);
};
+#define CON_AX_X (coreview::Connector::AX_X)
+#define CON_AX_Y (coreview::Connector::AX_Y)
+#define CON_AX_XY (coreview::Connector::AX_XY)
+#define CON_AX_MXY (coreview::Connector::AX_MXY)
+
#define CON_AXIS_X(Y) QLineF(QPointF(0, Y), QPointF(1, Y))
#define CON_AXIS_Y(X) QLineF(QPointF(X, 0), QPointF(X, 1))
diff --git a/qtmips_gui/coreview/logicblock.cpp b/qtmips_gui/coreview/logicblock.cpp
index 2e74a77..35ff0c4 100644
--- a/qtmips_gui/coreview/logicblock.cpp
+++ b/qtmips_gui/coreview/logicblock.cpp
@@ -91,7 +91,11 @@ const Connector *LogicBlock::new_connector(qreal x, qreal y) {
QPointF LogicBlock::con_pos(qreal x, qreal y) {
qreal px, py;
- px = (box.right() - GAP) * x + (GAP * sign(x));
- py = (box.bottom()/2 - GAP) * (y + 1) + (GAP * sign(y));
+ px = (box.right() - GAP) * x;
+ py = (box.bottom()/2 - GAP) * (y + 1) + GAP;
+ if (fabs(x) == 1)
+ px += GAP * sign(x);
+ if (fabs(y) == 1)
+ py += GAP * sign(y);
return QPointF(px, py);
}
diff --git a/qtmips_gui/coreview/registers.cpp b/qtmips_gui/coreview/registers.cpp
index 9a4fcff..2b1c1b5 100644
--- a/qtmips_gui/coreview/registers.cpp
+++ b/qtmips_gui/coreview/registers.cpp
@@ -10,12 +10,12 @@ using namespace coreview;
//////////////////////
Registers::Registers() : QGraphicsObject(nullptr), name("Registers", this) {
- con_read1 = new Connector(Connector::AX_Y);
- con_read1_reg = new Connector(Connector::AX_Y);
- con_read2 = new Connector(Connector::AX_Y);
- con_read2_reg = new Connector(Connector::AX_Y);
- con_write = new Connector(Connector::AX_Y);
- con_write_reg = new Connector(Connector::AX_Y);
+ con_read1 = new Connector(Connector::AX_X);
+ con_read1_reg = new Connector(Connector::AX_X);
+ con_read2 = new Connector(Connector::AX_X);
+ con_read2_reg = new Connector(Connector::AX_X);
+ con_write = new Connector(Connector::AX_X);
+ con_write_reg = new Connector(Connector::AX_X);
con_ctl_write = new Connector(Connector::AX_Y);
// TODO do we want to have any hooks on real registers?
@@ -52,14 +52,14 @@ void Registers::paint(QPainter *painter, const QStyleOptionGraphicsItem *option
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_read1_reg->setPos(x, y + 10);
+ con_read2_reg->setPos(x, y + 30);
+ con_read1->setPos(x + WIDTH, y + 10);
+ con_read2->setPos(x + WIDTH, y + 30);
- 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);
+ con_write_reg->setPos(x + WIDTH/2, y);
+ con_write->setPos(x, y + HEIGHT - 10);
+ con_ctl_write->setPos(x, y + HEIGHT - 20);
}
const Connector *Registers::connector_read1() const {