Zoadian преди 10 години
родител
ревизия
d1119ad649
променени са 11 файла, в които са добавени 358 реда и са изтрити 74 реда
  1. 8 3
      csim.pro
  2. 3 3
      csim.pro.user
  3. 14 0
      debugwidget.cpp
  4. 22 0
      debugwidget.h
  5. 84 0
      debugwidget.ui
  6. 38 53
      mainwindow.cpp
  7. 9 1
      mainwindow.h
  8. 47 11
      mainwindow.ui
  9. 81 0
      playfield.cpp
  10. 20 0
      playfield.h
  11. 32 3
      simulator.h

+ 8 - 3
csim.pro

@@ -13,9 +13,14 @@ TARGET = csim
 TEMPLATE = app
 
 SOURCES += main.cpp\
-        mainwindow.cpp
+        mainwindow.cpp \
+    playfield.cpp \
+    debugwidget.cpp
 
 HEADERS  += mainwindow.h \
-    simulator.h
+    simulator.h \
+    playfield.h \
+    debugwidget.h
 
-FORMS    += mainwindow.ui
+FORMS    += mainwindow.ui \
+    debugwidget.ui

+ 3 - 3
csim.pro.user

@@ -1,6 +1,6 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <!DOCTYPE QtCreatorProject>
-<!-- Written by QtCreator 3.6.0, 2016-01-17T14:26:03. -->
+<!-- Written by QtCreator 3.6.0, 2016-01-18T00:59:28. -->
 <qtcreator>
  <data>
   <variable>EnvironmentId</variable>
@@ -283,8 +283,8 @@
     <value type="int" key="PE.EnvironmentAspect.Base">2</value>
     <valuelist type="QVariantList" key="PE.EnvironmentAspect.Changes"/>
     <value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">csim</value>
-    <value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName"></value>
-    <value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">Qt4ProjectManager.Qt4RunConfiguration:C:/Users/zoadian/Documents/csim/csim.pro</value>
+    <value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName">csim2</value>
+    <value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">Qt4ProjectManager.Qt4RunConfiguration:C:/projects/csim/csim.pro</value>
     <value type="bool" key="QmakeProjectManager.QmakeRunConfiguration.UseLibrarySearchPath">true</value>
     <value type="QString" key="Qt4ProjectManager.Qt4RunConfiguration.CommandLineArguments"></value>
     <value type="QString" key="Qt4ProjectManager.Qt4RunConfiguration.ProFile">csim.pro</value>

+ 14 - 0
debugwidget.cpp

@@ -0,0 +1,14 @@
+#include "debugwidget.h"
+#include "ui_debugwidget.h"
+
+DebugWidget::DebugWidget(QWidget *parent)
+    : QWidget(parent)
+    , ui(new Ui::DebugWidget)
+{
+    ui->setupUi(this);
+}
+
+DebugWidget::~DebugWidget()
+{
+    delete ui;
+}

+ 22 - 0
debugwidget.h

@@ -0,0 +1,22 @@
+#ifndef DEBUGWIDGET_H
+#define DEBUGWIDGET_H
+
+#include <QWidget>
+
+namespace Ui {
+class DebugWidget;
+}
+
+class DebugWidget : public QWidget
+{
+    Q_OBJECT
+
+public:
+    explicit DebugWidget(QWidget *parent = 0);
+    ~DebugWidget();
+
+private:
+    Ui::DebugWidget *ui;
+};
+
+#endif // DEBUGWIDGET_H

+ 84 - 0
debugwidget.ui

@@ -0,0 +1,84 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ui version="4.0">
+ <class>DebugWidget</class>
+ <widget class="QWidget" name="DebugWidget">
+  <property name="geometry">
+   <rect>
+    <x>0</x>
+    <y>0</y>
+    <width>307</width>
+    <height>673</height>
+   </rect>
+  </property>
+  <property name="windowTitle">
+   <string>Form</string>
+  </property>
+  <layout class="QVBoxLayout" name="verticalLayout_2">
+   <item>
+    <layout class="QFormLayout" name="formLayout">
+     <item row="0" column="0">
+      <widget class="QLabel" name="label">
+       <property name="text">
+        <string>InstSet:</string>
+       </property>
+      </widget>
+     </item>
+     <item row="1" column="0">
+      <widget class="QLabel" name="label_2">
+       <property name="text">
+        <string>Mobile</string>
+       </property>
+      </widget>
+     </item>
+     <item row="2" column="0">
+      <widget class="QLabel" name="label_5">
+       <property name="text">
+        <string>Gen:</string>
+       </property>
+      </widget>
+     </item>
+     <item row="0" column="1">
+      <widget class="QLabel" name="lblInstSet">
+       <property name="text">
+        <string>-</string>
+       </property>
+      </widget>
+     </item>
+     <item row="1" column="1">
+      <widget class="QLabel" name="lblMobile">
+       <property name="text">
+        <string>-</string>
+       </property>
+      </widget>
+     </item>
+     <item row="2" column="1">
+      <widget class="QLabel" name="lblGeneration">
+       <property name="text">
+        <string>-</string>
+       </property>
+      </widget>
+     </item>
+    </layout>
+   </item>
+   <item>
+    <layout class="QHBoxLayout" name="horizontalLayout_2">
+     <item>
+      <layout class="QVBoxLayout" name="verticalLayout">
+       <item>
+        <widget class="QTableWidget" name="tblBanks"/>
+       </item>
+       <item>
+        <widget class="QTableWidget" name="tblInstructions"/>
+       </item>
+      </layout>
+     </item>
+     <item>
+      <widget class="QTableWidget" name="tblVars"/>
+     </item>
+    </layout>
+   </item>
+  </layout>
+ </widget>
+ <resources/>
+ <connections/>
+</ui>

+ 38 - 53
mainwindow.cpp

@@ -1,26 +1,53 @@
 #include "mainwindow.h"
 #include "ui_mainwindow.h"
 
-#include <QPainter>
-#include <QTimer>
+#include "playfield.h"
+
 
 MainWindow::MainWindow(QWidget *parent)
     : QMainWindow(parent)
     , ui(new Ui::MainWindow)
 {
     ui->setupUi(this);
+    lblCycles = new QLabel(ui->statusBar);
+    ui->statusBar->addWidget(lblCycles);
 
 //    setMinimumSize(simulator.size * 40, simulator.size * 40);
 
     simulator.loadProgram(Qt::red, 10, 10);
     simulator.loadProgram(Qt::blue, 15, 15);
 
-    QTimer* timer = new QTimer(this);
-    connect(timer, &QTimer::timeout, this, [this](){
-        simulator.simulate();
+    ui->centralWidget->layout()->addWidget(new Playfield(simulator, ui->centralWidget));
+
+    auto timerRepaint = new QTimer(this);
+    connect(timerRepaint, &QTimer::timeout, this, [this](){
+        mutex.lock();
         repaint();
+        lblCycles->setText(QString(tr("Cycles: %1")).arg(simulator.cycle));
+        mutex.unlock();
+    });
+    timerRepaint->start(200);
+
+    connect(timer, &QTimer::timeout, this, [this](){
+        simulate();
+    });
+
+
+    connect(ui->actionStart, &QAction::triggered, this, [this](){
+        timer->start(1);
     });
-    timer->start(50);
+
+    connect(ui->actionPause, &QAction::triggered, this, [this](){
+        timer->stop();
+    });
+
+    connect(ui->actionSingleStep, &QAction::triggered, this, [this](){
+        timer->stop();
+        simulate();
+    });
+
+
+
 }
 
 MainWindow::~MainWindow()
@@ -28,51 +55,9 @@ MainWindow::~MainWindow()
     delete ui;
 }
 
-void MainWindow::paintEvent(QPaintEvent* event) {
-    QPainter painter(this);
-
-    int w = qMin(width(), height()) / simulator.size;
-    int h = qMin(width(), height()) / simulator.size;
-
-    for(int y = 0; y < simulator.size; ++y) {
-        for(int x = 0; x < simulator.size; ++x) {
-            int xx = x * w;
-            int yy = y * w;
-            painter.setPen(Qt::black);
-            painter.setBrush(Qt::gray);
-            painter.drawRect(QRect(xx, yy,w, h));
-        }
-    }
-
-
-    for (auto& program : simulator.programs) {
-        int xx = program.position.x * w;
-        int yy = program.position.y * w;
-        painter.setPen(Qt::black);
-        painter.setBrush(program.color);
-        QRect rect(xx, yy,w, h);
-        painter.drawRect(rect);
-
-        auto& taskIndex = program.taskIndex;
-
-        if(program.tasks.empty()) {
-            continue;
-        }
-
-        taskIndex += 1;
-        taskIndex %= program.tasks.size();
-
-        if (taskIndex < program.tasks.size()) {
-            auto& task = program.tasks[taskIndex];
-
-            switch(task.direction) {
-            case Right: painter.drawLine(rect.center(), QPoint(rect.right(), rect.center().y())); break;
-            case Down: painter.drawLine(rect.center(), QPoint(rect.center().x(), rect.bottom())); break;
-            case Left: painter.drawLine(rect.center(), QPoint(rect.left(), rect.center().y())); break;
-            case Up: painter.drawLine(rect.center(), QPoint(rect.center().x(), rect.top())); break;
-            }
-            painter.drawText(rect, QString("%1:%2:%3").arg(program.banks.size()).arg(task.bankIndex).arg(task.instIndex));
-        }
-
-    }
+void MainWindow::simulate()
+{
+    mutex.lock();
+    simulator.simulate();
+    mutex.unlock();
 }

+ 9 - 1
mainwindow.h

@@ -2,6 +2,9 @@
 #define MAINWINDOW_H
 
 #include <QMainWindow>
+#include <QTimer>
+#include <QLabel>
+#include <QMutex>
 #include <simulator.h>
 
 namespace Ui {
@@ -15,11 +18,16 @@ class MainWindow : public QMainWindow
 public:
     explicit MainWindow(QWidget* parent = 0);
     ~MainWindow();
-    virtual void paintEvent(QPaintEvent* event) override;
 
 private:
     Ui::MainWindow *ui;
     Simulator simulator;
+    QTimer* timer = new QTimer(this);
+    QLabel* lblCycles;
+    QMutex mutex;
+
+public slots:
+    void simulate();
 };
 
 #endif // MAINWINDOW_H

+ 47 - 11
mainwindow.ui

@@ -1,24 +1,60 @@
+<?xml version="1.0" encoding="UTF-8"?>
 <ui version="4.0">
  <class>MainWindow</class>
- <widget class="QMainWindow" name="MainWindow" >
-  <property name="geometry" >
+ <widget class="QMainWindow" name="MainWindow">
+  <property name="geometry">
    <rect>
     <x>0</x>
     <y>0</y>
-    <width>400</width>
-    <height>300</height>
+    <width>820</width>
+    <height>601</height>
    </rect>
   </property>
-  <property name="windowTitle" >
+  <property name="windowTitle">
    <string>MainWindow</string>
   </property>
-  <widget class="QMenuBar" name="menuBar" />
-  <widget class="QToolBar" name="mainToolBar" />
-  <widget class="QWidget" name="centralWidget" />
-  <widget class="QStatusBar" name="statusBar" />
+  <widget class="QWidget" name="centralWidget">
+   <layout class="QHBoxLayout" name="horizontalLayout"/>
+  </widget>
+  <widget class="QMenuBar" name="menuBar">
+   <property name="geometry">
+    <rect>
+     <x>0</x>
+     <y>0</y>
+     <width>820</width>
+     <height>21</height>
+    </rect>
+   </property>
+  </widget>
+  <widget class="QToolBar" name="mainToolBar">
+   <attribute name="toolBarArea">
+    <enum>TopToolBarArea</enum>
+   </attribute>
+   <attribute name="toolBarBreak">
+    <bool>false</bool>
+   </attribute>
+   <addaction name="actionStart"/>
+   <addaction name="actionPause"/>
+   <addaction name="actionSingleStep"/>
+  </widget>
+  <widget class="QStatusBar" name="statusBar"/>
+  <action name="actionStart">
+   <property name="text">
+    <string>Start</string>
+   </property>
+  </action>
+  <action name="actionPause">
+   <property name="text">
+    <string>Pause</string>
+   </property>
+  </action>
+  <action name="actionSingleStep">
+   <property name="text">
+    <string>SingleStep</string>
+   </property>
+  </action>
  </widget>
- <layoutDefault spacing="6" margin="11" />
- <pixmapfunction></pixmapfunction>
+ <layoutdefault spacing="6" margin="11"/>
  <resources/>
  <connections/>
 </ui>

+ 81 - 0
playfield.cpp

@@ -0,0 +1,81 @@
+#include "playfield.h"
+
+#include <QPainter>
+
+
+inline QString errorStr(Error error) {
+    switch(error) {
+    case NoError: return QObject::tr("-");
+    case EliminationTrigger: return QObject::tr("Elimination Trigger released");
+    case DataHunger: return QObject::tr("Data Hunger (Bank 1 empty and executed)");
+    case DivisionByZero: return QObject::tr("Division by zero");
+    case InvalidBankNumber: return QObject::tr("Invalid bank number (e.g. in TRANS or BJUMP)");
+    case HigherInstructionSetRequired: return QObject::tr("Higher Instruction Set required");
+    case MobilityRequired: return QObject::tr("Mobility required");
+    case DieExecuted: return QObject::tr("DIE executed");
+    case InvalidParameter: return QObject::tr("Invalid parameter (e.g. CREATE x, -1, x)");
+    case Unemployment: return QObject::tr("No more tasks left in a robot (Unemployment)");
+    case InstructionDurationTooHigh: return QObject::tr("Instruction duration too high (i.e. > MaxInstrDur)");
+    }
+}
+
+Playfield::Playfield(Simulator& simulator, QWidget *parent)
+    : QWidget(parent)
+    , simulator(simulator)
+{
+
+}
+
+
+void Playfield::paintEvent(QPaintEvent* event) {
+    QPainter painter(this);
+
+    int w = qMin(width(), height()) / simulator.size;
+    int h = qMin(width(), height()) / simulator.size;
+
+    for(int y = 0; y < simulator.size; ++y) {
+        for(int x = 0; x < simulator.size; ++x) {
+            int xx = x * w;
+            int yy = y * w;
+            painter.setPen(Qt::black);
+            painter.setBrush(Qt::gray);
+            painter.drawRect(QRect(xx, yy,w, h));
+        }
+    }
+
+
+    for (auto& program : simulator.programs) {
+        if(program.error != NoError) {
+            continue;
+        }
+
+        int xx = program.position.x * w;
+        int yy = program.position.y * w;
+        painter.setPen(QPen(program.color, 3));
+        painter.setBrush(Qt::NoBrush);
+        QRect rect(xx, yy,w+1, h+1);
+        painter.drawEllipse(rect.center(), w/2.3, h/2.3);
+
+        auto& taskIndex = program.taskIndex;
+
+        if(program.tasks.empty()) {
+            continue;
+        }
+
+        taskIndex += 1;
+        taskIndex %= program.tasks.size();
+
+        if (taskIndex < program.tasks.size()) {
+            auto& task = program.tasks[taskIndex];
+
+            switch(task.direction) {
+            case Right: painter.drawLine(rect.center(), QPoint(rect.right(), rect.center().y())); break;
+            case Down: painter.drawLine(rect.center(), QPoint(rect.center().x(), rect.bottom())); break;
+            case Left: painter.drawLine(rect.center(), QPoint(rect.left(), rect.center().y())); break;
+            case Up: painter.drawLine(rect.center(), QPoint(rect.center().x(), rect.top())); break;
+            }
+//            painter.drawText(rect, QString("%1:%2:%3").arg(program.banks.size()).arg(task.bankIndex).arg(task.instIndex));
+        }
+
+    }
+}

+ 20 - 0
playfield.h

@@ -0,0 +1,20 @@
+#ifndef PLAYFIELD_H
+#define PLAYFIELD_H
+
+#include <QWidget>
+#include <simulator.h>
+
+class Playfield : public QWidget
+{
+    Q_OBJECT
+    Simulator& simulator;
+public:
+    explicit Playfield(Simulator& simulator, QWidget *parent = 0);
+    virtual void paintEvent(QPaintEvent* event) override;
+
+//signals:
+
+public slots:
+};
+
+#endif // PLAYFIELD_H

+ 32 - 3
simulator.h

@@ -95,6 +95,21 @@ enum Params : uint16_t {
     VV = VVV,
 };
 
+enum Error {
+    NoError, // No error
+    EliminationTrigger, // Elimination Trigger released
+    DataHunger, // Data Hunger (Bank 1 empty and executed)
+    DivisionByZero, // Division by zero
+    InvalidBankNumber, // Invalid bank number (e.g. in TRANS or BJUMP)
+    HigherInstructionSetRequired, // Higher Instruction Set required
+    MobilityRequired, // Mobility required
+    DieExecuted, // DIE executed
+    InvalidParameter , // Invalid parameter (e.g. CREATE x, -1, x)
+    Unemployment, // No more tasks left in a robot (Unemployment)
+    InstructionDurationTooHigh, // Instruction duration too high (i.e. > MaxInstrDur)
+};
+
+
 using Parameter = int32_t;
 
 struct Instruction {
@@ -128,6 +143,7 @@ struct Task {
 };
 
 struct Program {
+    Error error = NoError;
     QColor color;
     Position position;
     vector<Task> tasks;
@@ -148,7 +164,7 @@ struct Field {
 };
 
 struct Simulator {
-    size_t cylcle = 0;
+    size_t cycle = 0;
     vector<Program> programs;
     size_t size = 0;
 
@@ -186,6 +202,9 @@ struct Simulator {
             bank->push_back(Instruction(TRANS, LL, 1, 1));
             bank->push_back(Instruction(RANDOM, VLL, 5, -5, 5));
             bank->push_back(Instruction(TURN, V, 5));
+            bank->push_back(Instruction(ADD, VL, 6, 1));
+//            bank->push_back(Instruction(IFG, VL, 6, 5));
+//            bank->push_back(Instruction(DIE));
             bank->push_back(Instruction(AJUMP, L, 0));
             programs.back().banks[1] = bank;
         }
@@ -193,7 +212,7 @@ struct Simulator {
 
     Program* findProgram(Position position) {
         for(auto& program : programs) {
-            if(program.position.x == position.x && program.position.y == position.y) {
+            if(program.position.x == position.x && program.position.y == position.y && program.error == NoError) {
                 return &program;
             }
         }
@@ -204,6 +223,10 @@ struct Simulator {
         for (auto& program : programs) {
             auto& taskIndex = program.taskIndex;
 
+            if(program.error != NoError) {
+                continue;
+            }
+
             if(program.tasks.empty()) {
                 continue;
             }
@@ -280,6 +303,12 @@ struct Simulator {
                     break;
                 }
 
+                case DIE: {
+                    program.error = DieExecuted;
+                    task.instIndex += 1;
+                    break;
+                }
+
                 case TRANS: {
                     auto remotePosition = calcPosition(program.position, task.direction, 1);
                     auto remoteProgram = findProgram(remotePosition);
@@ -433,7 +462,7 @@ struct Simulator {
                 }
             }
         }
-        ++cylcle;
+        ++cycle;
     }
 };