Set Mux input coloring identifiers according to simulator state
MODIFY
src/graphics/backgrounditems.cpp
src/graphics/backgrounditems.cpp
@@ -40,9 +40,13 @@ Text::Text(QPointF pos) {
}
QRectF Text::boundingRect() const {
+ // Because text changes regularly, bounding rect is only defined by the text height, and a fixed rect width is set
QFontMetrics obj(m_font);
- auto rect = obj.boundingRect(m_text);
+ QRectF rect = obj.boundingRect(m_text);
+ rect.setWidth(200);
+ rect.setHeight(obj.height());
rect.moveTo(m_pos.toPoint());
+ rect.translate(-rect.width() / 2, -rect.height() / 2);
return rect;
}

MODIFY
src/graphics/backgrounditems.h
src/graphics/backgrounditems.h
@@ -21,7 +21,10 @@ private:
class Text : public QGraphicsItem {
public:
Text(QPointF pos);
- void setText(const QString& text) { m_text = text; }
+ void setText(const QString& text) {
+ m_text = text;
+ update();
+ }
QRectF boundingRect() const;
void paint(QPainter* painter, const QStyleOptionGraphicsItem* option, QWidget* widget);

MODIFY
src/graphics/connection.cpp
src/graphics/connection.cpp
@@ -30,6 +30,7 @@ Connection::Connection(Shape* source, QPointF* sourcePoint, QList<PointPair> des
}
QRectF Connection::boundingRect() const {
+ const static double pad = 5; // pad around each edge
double left, top, bot, right;
// Iterate through all points in the connection line to find bounding rect
for (const auto& pointVec : m_polyLines) {
@@ -40,7 +41,7 @@ QRectF Connection::boundingRect() const {
bot = point.y() > bot ? point.y() : bot;
}
}
- return QRectF(left, top, right - left, bot - top);
+ return QRectF(left - pad, top - pad, right - left + pad, bot - top + pad);
}
QPair<QPointF, QPointF> Connection::getPoints() const {
@@ -86,10 +87,17 @@ void Connection::paint(QPainter* painter, const QStyleOptionGraphicsItem*, QWidg
int xDiff = dest.x() - source.x();
if (i == 0) {
// do kink for first line
+ if (m_dir == Direction::east) {
QPointF point(source.x() + xDiff / 2 + bias, source.y());
QPointF point2(point.x(), dest.y());
sourcePoints << point << point2;
polyLine << point << point2;
+ } else {
+ QPointF point(dest.x(), source.y());
+ sourcePoints << point;
+ polyLine << point;
+ }
+
} else {
QPointF point(source.x(), dest.y());
sourcePoints << point;
@@ -100,6 +108,7 @@ void Connection::paint(QPainter* painter, const QStyleOptionGraphicsItem*, QWidg
}
} else {
// Feedback connection
+ Q_ASSERT(m_kinkBiases.length() > 0);
QList<QPointF> sourcePoints = QList<QPointF>() << sourcePoint;
for (int i = 0; i < m_dests.length(); i++) {
QVector<QPointF> polyLine;
@@ -116,14 +125,26 @@ void Connection::paint(QPainter* painter, const QStyleOptionGraphicsItem*, QWidg
// do kink for first line
QPointF point(source.x() + m_sourceStubLen, source.y());
QPointF point2(point.x(), m_kinkBiases[i] + point.y());
+ if (m_dir == Direction::east) {
QPointF point3(dest.x() - m_destStubLen, point2.y());
QPointF point4(point3.x(), dest.y());
- sourcePoints << point << point2 << point3 << point4;
+ sourcePoints << point << point2 << point3;
+ if (!m_invalidDestSourcePoints.contains(i))
+ sourcePoints << point4;
polyLine << point << point2 << point3 << point4;
+ } else {
+ QPointF point4(dest.x(), point2.y());
+ sourcePoints << point << point2;
+ if (!m_invalidDestSourcePoints.contains(i))
+ sourcePoints << point4;
+ polyLine << point << point2 << point4;
+ }
} else {
QPointF point(dest.x() - m_destStubLen, source.y());
QPointF point2(point.x(), dest.y());
- sourcePoints << point << point2;
+ sourcePoints << point;
+ if (!m_invalidDestSourcePoints.contains(i))
+ sourcePoints << point2;
polyLine << point << point2;
}
polyLine << dest;
@@ -132,18 +153,35 @@ void Connection::paint(QPainter* painter, const QStyleOptionGraphicsItem*, QWidg
}
painter->setPen(QPen(Qt::black, 1, Qt::SolidLine, Qt::RoundCap, Qt::RoundJoin));
+ painter->setBrush(Qt::black);
+ // painter->setCompositionMode(QPainter::CompositionMode_DestinationOver);
for (const auto& line : m_polyLines) {
// Draw connection polyline
painter->drawPolyline(QPolygonF(line));
- // Draw destination arrows
- qreal angle = 0;
+ // Draw destination arrows - angles are a bit strange
+ qreal angle;
+ switch (m_dir) {
+ case Direction::east:
+ angle = 0;
+ break;
+ case Direction::north:
+ angle = 2 * Pi / 4;
+ break;
+ case Direction::west:
+ angle = Pi / 2;
+ break;
+ case Direction::south:
+ angle = -2 * Pi / 4;
+ break;
+ }
+
QPointF destArrowP1 =
*(line.end() - 1) + QPointF(sin(angle - Pi / 3) * m_arrowSize, cos(angle - Pi / 3) * m_arrowSize);
QPointF destArrowP2 =
*(line.end() - 1) + QPointF(sin(angle - Pi + Pi / 3) * m_arrowSize, cos(angle - Pi + Pi / 3) * m_arrowSize);
- painter->setBrush(Qt::black);
+
painter->drawPolygon(QPolygonF() << *(line.end() - 1) << destArrowP1 << destArrowP2);
}
@@ -165,6 +203,13 @@ void Connection::paint(QPainter* painter, const QStyleOptionGraphicsItem*, QWidg
}
i++;
}
+
+ /*
+ * Debugging: draw bounding rect
+ painter->setPen(QPen(Qt::red, 1, Qt::SolidLine, Qt::RoundCap, Qt::RoundJoin));
+ painter->setBrush(Qt::transparent);
+ painter->drawRect(boundingRect());
+ */
}
void Connection::setValue(uint32_t value) {

MODIFY
src/graphics/connection.h
src/graphics/connection.h
@@ -39,6 +39,7 @@ private:
Class for drawing connections and signal values between shapes in the
pipeline view.
*/
+enum class Direction { east, west, north, south };
class Connection : public QObject, public QGraphicsItem {
Q_OBJECT
public:
@@ -61,7 +62,9 @@ public:
m_sourceStubLen = sourceStubLen;
m_destStubLen = destStubLen;
}
+ void addInvalidDestSourcePoint(int i) { m_invalidDestSourcePoints.append(i); }
void addLabelToScene();
+ void setDirection(Direction rot) { m_dir = rot; }
public slots:
void showValue(bool state) { m_label.m_showValue = state; }
@@ -83,6 +86,8 @@ private:
int m_sourceStubLen;
int m_destStubLen;
+ Direction m_dir = Direction::east; // By default, all arrows point towards east
+
// Variables related to the current value of the connection (signal value)
ValueDrawPos m_valuePos = ValueDrawPos::Source;
@@ -91,6 +96,8 @@ private:
Shape* m_source;
QPointF* m_sourcePointPtr;
QList<PointPair> m_dests;
+ QList<int> m_invalidDestSourcePoints; // used when algorithm shouldnt use created source points for a destination,
+ // when calculating connections to other destinations
Label m_label;
};

MODIFY
src/graphics/pipelinewidget.cpp
src/graphics/pipelinewidget.cpp
@@ -18,6 +18,8 @@ PipelineWidget::PipelineWidget(QWidget* parent) : QGraphicsView(parent) {
setDragMode(QGraphicsView::ScrollHandDrag);
setCursor(Qt::CrossCursor);
+ m_pipelinePtr = Pipeline::getPipeline();
+
// ------------ Create pipeline objects ---------------
// Registers memory
Graphics::Shape* registers = new Graphics::Shape(Graphics::ShapeType::Block, Graphics::Stage::ID, 10, 15);
@@ -27,14 +29,22 @@ PipelineWidget::PipelineWidget(QWidget* parent) : QGraphicsView(parent) {
<< "Write\ndata");
registers->addOutput(QStringList() << "Read\ndata 1"
<< "Read\ndata 2");
+ registers->addTopPoint("");
registers->setName("Registers");
+ registers->setSignal(Graphics::SignalPos::Top, m_pipelinePtr->r_regWrite_MEMWB.getOutput());
+ m_animatedItems.push_back(registers);
// Data memory
Graphics::Shape* data_mem = new Graphics::Shape(Graphics::ShapeType::Block, Graphics::Stage::MEM, 50, 5);
data_mem->addInput(QStringList() << "Address"
<< "Write\ndata");
data_mem->addOutput(QStringList() << "Read\ndata");
+ data_mem->addTopPoint("Write");
+ data_mem->addBotPoint("Read");
data_mem->setName("Data\nmemory");
+ data_mem->setSignal(Graphics::SignalPos::Top, m_pipelinePtr->r_MemWrite_EXMEM.getOutput());
+ data_mem->setSignal(Graphics::SignalPos::Bot, m_pipelinePtr->r_MemRead_EXMEM.getOutput());
+ m_animatedItems.push_back(data_mem);
// Instruction memory
Graphics::Shape* instr_mem = new Graphics::Shape(Graphics::ShapeType::Block, Graphics::Stage::IF, 60, 0);
@@ -55,48 +65,78 @@ PipelineWidget::PipelineWidget(QWidget* parent) : QGraphicsView(parent) {
<< ""
<< "");
mux_PCSrc->addOutput("");
- mux_PCSrc->addBotPoint("");
mux_PCSrc->setName("M\nu\nx");
+ mux_PCSrc->setSignal(Graphics::SignalPos::Left, &m_pipelinePtr->s_PCSrc);
+ m_animatedItems.push_back(mux_PCSrc);
- Graphics::Shape* mux_forwardA_EX = new Graphics::Shape(Graphics::ShapeType::MUX, Graphics::Stage::EX, 0, 0);
+ Graphics::Shape* mux_forwardA_EX = new Graphics::Shape(Graphics::ShapeType::MUX, Graphics::Stage::EX, -15, 0);
mux_forwardA_EX->addInput(QStringList() << ""
<< ""
<< "");
mux_forwardA_EX->addOutput("");
mux_forwardA_EX->setName("M\nu\nx");
+ mux_forwardA_EX->setSignal(Graphics::SignalPos::Left, &m_pipelinePtr->s_forwardA_EX);
+ m_animatedItems.push_back(mux_forwardA_EX);
- Graphics::Shape* mux_forwardB_EX = new Graphics::Shape(Graphics::ShapeType::MUX, Graphics::Stage::EX, 0, 0);
+ Graphics::Shape* mux_forwardB_EX = new Graphics::Shape(Graphics::ShapeType::MUX, Graphics::Stage::EX, -15, 0);
mux_forwardB_EX->addInput(QStringList() << ""
<< ""
<< "");
mux_forwardB_EX->addOutput("");
mux_forwardB_EX->setName("M\nu\nx");
+ mux_forwardB_EX->setSignal(Graphics::SignalPos::Left, &m_pipelinePtr->s_forwardB_EX);
+ m_animatedItems.push_back(mux_forwardB_EX);
+
+ Graphics::Shape* mux_forwardA_ID = new Graphics::Shape(Graphics::ShapeType::MUX, Graphics::Stage::EX, -15, 0);
+ mux_forwardA_ID->addInput(QStringList() << ""
+ << ""
+ << "");
+ mux_forwardA_ID->addOutput("");
+ mux_forwardA_ID->setName("M\nu\nx");
+ mux_forwardA_ID->setSignal(Graphics::SignalPos::Left, &m_pipelinePtr->s_forwardA_ID);
+ m_animatedItems.push_back(mux_forwardA_ID);
+
+ Graphics::Shape* mux_forwardB_ID = new Graphics::Shape(Graphics::ShapeType::MUX, Graphics::Stage::EX, -15, 0);
+ mux_forwardB_ID->addInput(QStringList() << ""
+ << ""
+ << "");
+ mux_forwardB_ID->addOutput("");
+ mux_forwardB_ID->setName("M\nu\nx");
+ mux_forwardB_ID->setSignal(Graphics::SignalPos::Left, &m_pipelinePtr->s_forwardB_ID);
+ m_animatedItems.push_back(mux_forwardB_ID);
Graphics::Shape* mux_ALUSrc1 = new Graphics::Shape(Graphics::ShapeType::MUX, Graphics::Stage::EX, 0, 0);
mux_ALUSrc1->addInput(QStringList() << ""
<< "");
mux_ALUSrc1->addOutput("");
mux_ALUSrc1->setName("M\nu\nx");
+ mux_ALUSrc1->setSignal(Graphics::SignalPos::Left, &m_pipelinePtr->s_ALUSrc1);
+ m_animatedItems.push_back(mux_ALUSrc1);
Graphics::Shape* mux_ALUSrc2 = new Graphics::Shape(Graphics::ShapeType::MUX, Graphics::Stage::EX, 0, 0);
mux_ALUSrc2->addInput(QStringList() << ""
<< "");
mux_ALUSrc2->addOutput("");
mux_ALUSrc2->setName("M\nu\nx");
+ mux_ALUSrc2->setSignal(Graphics::SignalPos::Left, &m_pipelinePtr->s_ALUSrc2);
+ m_animatedItems.push_back(mux_ALUSrc2);
Graphics::Shape* mux_alures_PC4_MEM = new Graphics::Shape(Graphics::ShapeType::MUX, Graphics::Stage::EX, 0, 0);
mux_alures_PC4_MEM->addInput(QStringList() << ""
<< "");
mux_alures_PC4_MEM->addOutput("");
mux_alures_PC4_MEM->setName("M\nu\nx");
+ mux_alures_PC4_MEM->setSignal(Graphics::SignalPos::Left, &m_pipelinePtr->s_alures_PC4_MEM);
+ m_animatedItems.push_back(mux_alures_PC4_MEM);
Graphics::Shape* mux_memToReg = new Graphics::Shape(Graphics::ShapeType::MUX, Graphics::Stage::WB, 0, 0);
mux_memToReg->addInput(QStringList() << ""
<< ""
<< "");
- mux_memToReg->addBotPoint("");
mux_memToReg->addOutput("");
mux_memToReg->setName("M\nu\nx");
+ mux_memToReg->setSignal(Graphics::SignalPos::Left, &m_pipelinePtr->s_memToReg);
+ m_animatedItems.push_back(mux_memToReg);
// ALUs
Graphics::Shape* alu_pc4 = new Graphics::Shape(Graphics::ShapeType::ALU, Graphics::Stage::ID, 70, 10);
@@ -153,6 +193,13 @@ PipelineWidget::PipelineWidget(QWidget* parent) : QGraphicsView(parent) {
immgen->addInput("");
immgen->addOutput("");
+ Graphics::Shape* comp = new Graphics::Shape(Graphics::ShapeType::Static, Graphics::Stage::EX, 0, 20);
+ comp->setName("=");
+ comp->addOutput("");
+ comp->setHiddenOutputs(std::set<int>{0});
+ comp->addTopPoint("");
+ comp->addBotPoint("");
+
// Add pipeline objects to graphics scene
scene->addItem(mux_PCSrc);
@@ -165,6 +212,8 @@ PipelineWidget::PipelineWidget(QWidget* parent) : QGraphicsView(parent) {
scene->addItem(data_mem);
scene->addItem(mux_forwardA_EX);
scene->addItem(mux_forwardB_EX);
+ scene->addItem(mux_forwardA_ID);
+ scene->addItem(mux_forwardB_ID);
scene->addItem(mux_ALUSrc1);
scene->addItem(mux_ALUSrc2);
scene->addItem(mux_alures_PC4_MEM);
@@ -174,9 +223,11 @@ PipelineWidget::PipelineWidget(QWidget* parent) : QGraphicsView(parent) {
scene->addItem(idex);
scene->addItem(exmem);
scene->addItem(memwb);
+ scene->addItem(comp);
// ----------- Create connections ----------------------
Graphics::Connection* connPtr;
+
// IF
createConnection(mux_PCSrc, 0, pc, 0);
createConnection(pc, 0,
@@ -193,40 +244,50 @@ PipelineWidget::PipelineWidget(QWidget* parent) : QGraphicsView(parent) {
<< ShapePair(immgen, 0) << /* To IDEX*/
ShapePair(idex, 8) << ShapePair(idex, 9) << ShapePair(idex, 10));
- connPtr = createConnection(registers, 0, idex, 5);
- connPtr->setKinkBias(-10);
- connPtr = createConnection(registers, 1, idex, 6);
- connPtr->setKinkBias(10);
- createConnection(immgen, 0, idex, 7);
+ // createConnection(registers, 0, idex, 5)->setKinkBias(-10);
+ createConnection(registers, 0, idex, 5);
+ createConnection(registers, 0, mux_forwardA_ID, 0)->setKinkBias(-10);
+ createConnection(registers, 1, idex, 6);
+ createConnection(registers, 1, mux_forwardB_ID, 0);
+
+ createConnection(immgen, 0, idex, 7)->setKinkBias(25);
connPtr = createConnection(alu_pc_target, 0, mux_PCSrc, 1);
connPtr->setFeedbackSettings(false, 10, minConnectionLen);
connPtr->setKinkBias(-150);
- createConnection(ifid, 1, alu_pc_target, 0);
- connPtr = createConnection(immgen, 0, alu_pc_target, 1);
+ createConnection(ifid, 1, QList<ShapePair>() << ShapePair(alu_pc_target, 0) << ShapePair(idex, 4))->setKinkBias(20);
+ createConnection(ifid, 0, idex, 3)->setKinkBias(-110);
+ createConnection(immgen, 0, alu_pc_target, 1)->setKinkBias(20);
+
+ createConnection(mux_forwardA_ID, comp, mux_forwardA_ID->getOutputPoint(0), comp->getTopPoint())
+ ->setDirection(Graphics::Direction::south);
+ createConnection(mux_forwardB_ID, comp, mux_forwardB_ID->getOutputPoint(0), comp->getBotPoint())
+ ->setDirection(Graphics::Direction::north);
// EX
- createConnection(idex, 4, mux_forwardA_EX, 0);
- createConnection(idex, 5, mux_forwardB_EX, 0);
- createConnection(idex, 3, mux_ALUSrc1, 1);
- createConnection(idex, 6, mux_ALUSrc2, 1);
+ createConnection(idex, 5, mux_forwardA_EX, 0);
+ createConnection(idex, 6, mux_forwardB_EX, 0);
+ createConnection(idex, 7, mux_ALUSrc2, 1)->setKinkBias(-50);
+ createConnection(idex, 3, exmem, 2)->setKinkBias(100);
+ createConnection(idex, 4, mux_ALUSrc1, 1)->setKinkBias(50);
+ createConnection(idex, 10, exmem, 5);
createConnection(mux_forwardA_EX, 0, mux_ALUSrc1, 0);
- createConnection(mux_forwardB_EX, 0, mux_ALUSrc2, 0);
+ createConnection(mux_forwardB_EX, 0, QList<ShapePair>() << ShapePair(mux_ALUSrc2, 0) << ShapePair(exmem, 4));
createConnection(mux_ALUSrc1, 0, alu_mainALU, 0);
createConnection(mux_ALUSrc2, 0, alu_mainALU, 1);
createConnection(alu_mainALU, 0, exmem, 3);
connPtr = createConnection(alu_mainALU, 0, mux_PCSrc, 2);
- connPtr->setFeedbackSettings(false, 10, minConnectionLen + 10);
- connPtr->setKinkBias(330);
+ connPtr->setFeedbackSettings(false, 10, minConnectionLen);
+ connPtr->setKinkBias(325);
// MEM
createConnection(exmem, 3, mux_alures_PC4_MEM, 0);
- createConnection(exmem, 2, mux_alures_PC4_MEM, 1);
+ createConnection(exmem, 2, mux_alures_PC4_MEM, 1)->setKinkBias(-15);
createConnection(exmem, 0, memwb, 0);
- createConnection(exmem, 2, memwb, 1);
+ createConnection(exmem, 2, memwb, 1)->setKinkBias(-80);
createConnection(exmem, 3, QList<ShapePair>() << ShapePair(data_mem, 0) << ShapePair(memwb, 3));
createConnection(exmem, 4, data_mem, 1);
createConnection(exmem, 5, memwb, 4);
@@ -234,15 +295,37 @@ PipelineWidget::PipelineWidget(QWidget* parent) : QGraphicsView(parent) {
connPtr = createConnection(mux_alures_PC4_MEM, 0,
QList<ShapePair>() << ShapePair(mux_forwardA_EX, 1) << ShapePair(mux_forwardB_EX, 1));
+
+ connPtr->setFeedbackSettings(true, 10, minConnectionLen - 10);
+ connPtr->setKinkBias(200);
+ connPtr = createConnection(mux_alures_PC4_MEM, 0,
+ QList<ShapePair>() << ShapePair(mux_forwardA_ID, 1) << ShapePair(mux_forwardB_ID, 1));
+
connPtr->setFeedbackSettings(true, 10, minConnectionLen - 10);
- connPtr->setKinkBias(150);
+ connPtr->setKinkBias(200);
// WB
- createConnection(memwb, 0, mux_memToReg, 0);
- createConnection(memwb, 1, mux_memToReg, 1);
- connPtr = createConnection(mux_memToReg, 0, registers, 3);
+ connPtr = createConnection(memwb, registers, memwb->getOutputPoint(0), registers->getTopPoint());
connPtr->setFeedbackSettings(true, minConnectionLen - 20, minConnectionLen - 10);
- connPtr->setKinkBias(430);
+ connPtr->setKinkBias(-100);
+ connPtr->setDirection(Graphics::Direction::south);
+ createConnection(memwb, 1, mux_memToReg, 0);
+ createConnection(memwb, 2, mux_memToReg, 1);
+ createConnection(memwb, 3, mux_memToReg, 2);
+
+ connPtr = createConnection(mux_memToReg, 0,
+ QList<ShapePair>() << ShapePair(mux_forwardA_EX, 2) << ShapePair(mux_forwardB_EX, 2));
+ connPtr->setFeedbackSettings(false, minConnectionLen - 20, minConnectionLen + 20);
+ connPtr->setKinkBias(320);
+
+ connPtr = createConnection(mux_memToReg, 0,
+ QList<ShapePair>() << ShapePair(mux_forwardA_ID, 2) << ShapePair(mux_forwardB_ID, 2));
+ connPtr->setFeedbackSettings(false, minConnectionLen - 20, minConnectionLen + 20);
+ connPtr->setKinkBias(320);
+
+ connPtr = createConnection(mux_memToReg, 0, registers, 3);
+ connPtr->setFeedbackSettings(false, minConnectionLen - 20, minConnectionLen - 10);
+ connPtr->setKinkBias(320);
// ------- ITEM POSITIONING ------
// Item positioning will mostly be done manually.
@@ -251,7 +334,7 @@ PipelineWidget::PipelineWidget(QWidget* parent) : QGraphicsView(parent) {
// items position relative to these
// Position state registers
- ifid->moveBy(0, 0);
+ ifid->moveBy(-spaceBetweenStateRegs * 0.2, 0);
idex->moveBy(spaceBetweenStateRegs * 1, 0);
exmem->moveBy(spaceBetweenStateRegs * 2, 0);
memwb->moveBy(spaceBetweenStateRegs * 3, 0);
@@ -264,10 +347,17 @@ PipelineWidget::PipelineWidget(QWidget* parent) : QGraphicsView(parent) {
// position ID stage
moveToIO(alu_pc_target, idex, alu_pc_target->getOutputPoint(0), idex->getInputPoint(2));
- alu_pc_target->moveBy(-50, 0);
- registers->moveBy(spaceBetweenStateRegs * 0.5, 0);
+ alu_pc_target->moveBy(-20, -30);
+ registers->moveBy(spaceBetweenStateRegs * 0.3 - 10, 20);
moveToIO(immgen, idex, immgen->getOutputPoint(0), idex->getInputPoint(7));
- immgen->moveBy(-120, 20);
+ immgen->moveBy(-120, 60);
+
+ moveToIO(mux_forwardA_ID, idex, mux_forwardA_ID->getOutputPoint(0), idex->getInputPoint(11));
+ mux_forwardA_ID->moveBy(-25, -10);
+ moveToIO(mux_forwardB_ID, idex, mux_forwardB_ID->getOutputPoint(0), idex->getInputPoint(11));
+ mux_forwardB_ID->moveBy(-25, 80);
+ moveToIO(comp, idex, comp->getOutputPoint(0), idex->getInputPoint(11));
+ comp->moveBy(15, 30);
// position EX stage
moveToIO(alu_mainALU, exmem, alu_mainALU->getOutputPoint(0), exmem->getInputPoint(3));
@@ -279,10 +369,10 @@ PipelineWidget::PipelineWidget(QWidget* parent) : QGraphicsView(parent) {
// position MEM stage
data_mem->moveBy(spaceBetweenStateRegs * 2.5, 0);
- mux_alures_PC4_MEM->moveBy(spaceBetweenStateRegs * 2.3, 120);
+ mux_alures_PC4_MEM->moveBy(spaceBetweenStateRegs * 2.4, 130);
// position WB stage
- moveToIO(mux_memToReg, memwb, mux_memToReg->getInputPoint(0), memwb->getOutputPoint(0), -minConnectionLen);
+ moveToIO(mux_memToReg, memwb, mux_memToReg->getInputPoint(0), memwb->getOutputPoint(2), -minConnectionLen);
// ----------- Create Etc. objects -----------
Graphics::DashLine* dash1 = new Graphics::DashLine(ifid);
@@ -296,8 +386,8 @@ PipelineWidget::PipelineWidget(QWidget* parent) : QGraphicsView(parent) {
scene->addItem(dash4);
int textPad = 20;
- if_instr = new Graphics::Text(QPointF(
- -dash1->sceneBoundingRect().left() + dash1->sceneBoundingRect().width() / 2 + -spaceBetweenStateRegs / 2,
+ if_instr = new Graphics::Text(
+ QPointF(-dash1->sceneBoundingRect().left() + dash1->sceneBoundingRect().width() / 2 + -spaceBetweenStateRegs,
dash1->sceneBoundingRect().top() + textPad));
id_instr = new Graphics::Text(
QPointF(dash1->sceneBoundingRect().left() + dash1->sceneBoundingRect().width() / 2 + spaceBetweenStateRegs / 2,
@@ -308,7 +398,7 @@ PipelineWidget::PipelineWidget(QWidget* parent) : QGraphicsView(parent) {
mem_instr = new Graphics::Text(
QPointF(dash3->sceneBoundingRect().left() + dash3->sceneBoundingRect().width() / 2 + spaceBetweenStateRegs / 2,
dash3->sceneBoundingRect().top() + textPad));
- wb_instr = new Graphics::Text(QPointF(dash4->sceneBoundingRect().left() + spaceBetweenStateRegs / 3,
+ wb_instr = new Graphics::Text(QPointF(dash4->sceneBoundingRect().left() + spaceBetweenStateRegs / 3 + 20,
dash4->sceneBoundingRect().top() + textPad));
scene->addItem(if_instr);
@@ -316,10 +406,17 @@ PipelineWidget::PipelineWidget(QWidget* parent) : QGraphicsView(parent) {
scene->addItem(ex_instr);
scene->addItem(mem_instr);
scene->addItem(wb_instr);
+
+ // For some reason, the boundingrect of the leftmost connections are not forcing the scene rect to change
+ // We manually adjust it a bit
+ setSceneRect(scene->itemsBoundingRect().adjusted(-40, 0, 0, 0));
}
void PipelineWidget::update() {
QWidget::update();
+ for (const auto& item : m_animatedItems) {
+ item->update();
+ }
}
void PipelineWidget::stageTextChanged(Stage stage, const QString& text) {
@@ -340,7 +437,6 @@ void PipelineWidget::stageTextChanged(Stage stage, const QString& text) {
wb_instr->setText(text);
break;
}
- scene()->update();
}
void PipelineWidget::moveToIO(Graphics::Shape* source, Graphics::Shape* dest, QPointF* sourcePoint, QPointF* destPoint,

MODIFY
src/graphics/pipelinewidget.h
src/graphics/pipelinewidget.h
#include <QPair>
#include "defines.h"
+#include "pipeline.h"
namespace Graphics {
class Connection;
@@ -21,7 +22,7 @@ public:
PipelineWidget(QWidget* parent = nullptr);
void wheelEvent(QWheelEvent* event);
- void expandToView() { fitInView(scene()->sceneRect().adjusted(-30, 0, 10, 0), Qt::KeepAspectRatio); }
+ void expandToView() { fitInView(scene()->itemsBoundingRect(), Qt::KeepAspectRatio); }
void displayAllValues(bool state);
void zoomIn();
void zoomOut();
@@ -66,6 +67,11 @@ private:
Graphics::Text* ex_instr;
Graphics::Text* mem_instr;
Graphics::Text* wb_instr;
+
+ Pipeline* m_pipelinePtr;
+
+ // Vector of Shape* where each item gets its update() function called whenever stepping the simulator.
+ std::vector<Graphics::Shape*> m_animatedItems;
};
#endif // PIPELINEWIDGET_H

MODIFY
src/graphics/shape.cpp
src/graphics/shape.cpp
@@ -166,7 +166,8 @@ QPainterPath Shape::drawALUPath(QRectF rect) const {
void Shape::paint(QPainter* painter, const QStyleOptionGraphicsItem* /*option*/, QWidget*) {
auto rect = boundingRect();
- painter->setPen(QPen(Qt::black, 1));
+ painter->setPen(QPen(Qt::black, 1.5));
+ painter->setBrush(Qt::white);
switch (m_type) {
case ShapeType::Block: {
painter->drawRect(rect);
@@ -182,6 +183,8 @@ void Shape::paint(QPainter* painter, const QStyleOptionGraphicsItem* /*option*/,
} break;
}
+ painter->setBrush(Qt::transparent);
+
// Translate text in relation to the bounding rectangle, and draw shape name
auto fontMetricsObject = QFontMetrics(m_nameFont);
QRectF textRect = fontMetricsObject.boundingRect(QRect(0, 0, 200, 200), 0, m_name);
@@ -212,13 +215,32 @@ void Shape::paint(QPainter* painter, const QStyleOptionGraphicsItem* /*option*/,
// draw IO points
if (m_drawTopPoint)
+ if (m_topSignal != nullptr && m_topSignal->getValue() > 0) {
+ painter->setBrush(Qt::green);
+ painter->drawEllipse(m_topPoint, 5, 5);
+ painter->setBrush(Qt::transparent);
+ } else {
painter->drawEllipse(m_topPoint, 5, 5);
+ }
if (m_drawBotPoint)
+ if (m_botsignal != nullptr && m_botsignal->getValue() > 0) {
+ painter->setBrush(Qt::green);
painter->drawEllipse(m_bottomPoint, 5, 5);
+ painter->setBrush(Qt::transparent);
+ } else {
+ painter->drawEllipse(m_bottomPoint, 5, 5);
+ }
for (int i = 0; i < m_inputPoints.length(); i++) {
if (m_hiddenInputPoints.find(i) == m_hiddenInputPoints.end())
+ // For multiplexers, we want to color the input that is asserted
+ if (m_leftSignal != nullptr && m_leftSignal->getValue() == i) {
+ painter->setBrush(Qt::red);
painter->drawEllipse(m_inputPoints[i], 5, 5);
+ painter->setBrush(Qt::transparent);
+ } else {
+ painter->drawEllipse(m_inputPoints[i], 5, 5);
+ }
}
for (int i = 0; i < m_outputPoints.length(); i++) {
if (m_hiddenOutputPoints.find(i) == m_hiddenOutputPoints.end())
@@ -226,6 +248,22 @@ void Shape::paint(QPainter* painter, const QStyleOptionGraphicsItem* /*option*/,
}
}
+void Shape::setSignal(SignalPos pos, SignalBase* sig) {
+ switch (pos) {
+ case SignalPos::Left:
+ m_leftSignal = sig;
+ break;
+ case SignalPos::Top:
+ m_topSignal = sig;
+ break;
+ case SignalPos::Bot:
+ m_botsignal = sig;
+ break;
+ default:
+ break;
+ }
+}
+
QPointF* Shape::getInputPoint(int index) {
Q_ASSERT(index < m_inputPoints.size());
return &m_inputPoints[index];

MODIFY
src/graphics/shape.h
src/graphics/shape.h
#include <set>
+#include "pipelineobjects.h"
+
namespace Graphics {
class Connection;
enum class ShapeType { Block, ALU, MUX, Static };
enum class Stage { IF = 1, ID = 2, EX = 3, MEM = 4, WB = 5 };
+enum class SignalPos { Left, Top, Bot };
class Shape : public QGraphicsItem {
public:
@@ -28,6 +31,8 @@ public:
void addConnection(Connection* connection) { m_connections.append(connection); }
void setFixedHeight(bool state, int height = 0) { m_isFixedHeight = state, m_fixedHeight = height; }
+ void setSignal(SignalPos pos, SignalBase* sig);
+
void setHiddenInputs(std::set<int> set) { m_hiddenInputPoints = set; }
void setHiddenOutputs(std::set<int> set) { m_hiddenOutputPoints = set; }
@@ -40,7 +45,7 @@ public:
void calculateRect();
void calculatePoints();
- void drawTopPoint(bool state) { m_drawTopPoint = state; }
+ void addTopPoint(bool state) { m_drawTopPoint = state; }
void addBotPoint(bool state) { m_drawBotPoint = state; }
static int connectionType() { return QGraphicsItem::UserType + 2; }
@@ -94,6 +99,11 @@ private:
qreal sidePadding = 7; // padding between an IO description and the side of the shape
int m_fixedHeight;
bool m_isFixedHeight = false;
+
+ // Interfacing signals to pipeline
+ SignalBase* m_leftSignal = nullptr;
+ SignalBase* m_topSignal = nullptr;
+ SignalBase* m_botsignal = nullptr;
};
} // namespace Graphics

MODIFY
src/pipeline.h
src/pipeline.h
#include <set>
class Pipeline {
+ friend class PipelineWidget;
+
public:
Pipeline();
// Utility functions

MODIFY
src/pipelineobjects.h
src/pipelineobjects.h
#define CREATE_VEC m_value = std::vector<bool>(n);
#define SETNAME m_name = name;
+class SignalBase {
+public:
+ uint32_t getValue() { return accBVec(m_value); }
+
+protected:
+ std::vector<bool> value() const { return m_value; }
+ std::vector<bool> m_value;
+ std::string m_name;
+};
+
template <int n>
-class Signal {
+class Signal : public SignalBase {
public:
// Constructors
Signal(std::string name = ""){ASSERT_SIZE CREATE_VEC SETNAME};
@@ -63,11 +73,6 @@ public:
explicit operator int() const { return signextend<int32_t, n>(accBVec(m_value)); }
explicit operator uint32_t() const { return accBVec(m_value); }
explicit operator bool() const { return m_value[0]; }
-
-private:
- std::vector<bool> value() const { return m_value; }
- std::vector<bool> m_value;
- std::string m_name;
};
// The Reg class is used for sequential signal assignment. Has a single input/output of a given signal size.

MODIFY
src/processortab.ui
src/processortab.ui
</sizepolicy>
</property>
<property name="title">
- <string>Simulation settings</string>
+ <string>Simulator settings</string>
</property>
<layout class="QGridLayout" name="gridLayout_7">
<item row="0" column="0">
</size>
</property>
<property name="toolTip">
- <string>Start simulation, stepping through the program</string>
+ <string>Automatically step through the program</string>
</property>
<property name="text">
<string>Start autostepping (F5)</string>

Set Mux input coloring identifiers according to simulator state