aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--qtmips_cli/chariohandler.cpp159
-rw-r--r--qtmips_cli/chariohandler.h85
-rw-r--r--qtmips_cli/main.cpp57
-rw-r--r--qtmips_cli/qtmips_cli.pro6
4 files changed, 305 insertions, 2 deletions
diff --git a/qtmips_cli/chariohandler.cpp b/qtmips_cli/chariohandler.cpp
new file mode 100644
index 0000000..6d9c6e1
--- /dev/null
+++ b/qtmips_cli/chariohandler.cpp
@@ -0,0 +1,159 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*******************************************************************************
+ * QtMips - MIPS 32-bit Architecture Subset Simulator
+ *
+ * Implemented to support following courses:
+ *
+ * B35APO - Computer Architectures
+ * https://cw.fel.cvut.cz/wiki/courses/b35apo
+ *
+ * B4M35PAP - Advanced Computer Architectures
+ * https://cw.fel.cvut.cz/wiki/courses/b4m35pap/start
+ *
+ * Copyright (c) 2017-2019 Karel Koci<cynerd@email.cz>
+ * Copyright (c) 2019 Pavel Pisa <pisa@cmp.felk.cvut.cz>
+ *
+ * Faculty of Electrical Engineering (http://www.fel.cvut.cz)
+ * Czech Technical University (http://www.cvut.cz/)
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ ******************************************************************************/
+
+#include <chariohandler.h>
+
+CharIOHandler::CharIOHandler(QIODevice *iodev, QObject *parent) :
+ QIODevice(parent), fd_list() {
+ this->iodev = iodev;
+ if (!iodev->parent())
+ iodev->setParent(this);
+ fd_specific = false;
+ if (iodev->isOpen())
+ Super::open(iodev->openMode());
+ connect(iodev, &Super::aboutToClose, this, &CharIOHandler::aboutToClose);
+ connect(iodev, &Super::bytesWritten, this, &CharIOHandler::bytesWritten);
+ connect(iodev, &Super::channelBytesWritten, this, &CharIOHandler::channelBytesWritten);
+ connect(iodev, &Super::channelReadyRead, this, &CharIOHandler::channelReadyRead);
+ connect(iodev, &Super::readChannelFinished, this, &CharIOHandler::readChannelFinished);
+ connect(iodev, &Super::readyRead, this, &CharIOHandler::readyRead);
+}
+
+CharIOHandler::~CharIOHandler() {
+ if (iodev->parent() == this)
+ delete iodev;
+}
+
+void CharIOHandler::writeByte(unsigned int data) {
+ char ch = (char)data;
+ write(&ch, 1);
+}
+
+void CharIOHandler::writeByte(int fd, unsigned int data) {
+ if(!fd_specific || fd_list.contains(fd))
+ writeByte(data);
+}
+
+void CharIOHandler::readBytePoll(int fd, unsigned int &data, bool &available) {
+ char ch;
+ qint64 res;
+ if(!fd_specific || fd_list.contains(fd)) {
+ if (bytesAvailable() > 0) {
+ res = read(&ch, 1);
+ if (res > 0) {
+ data = ch & 0xff;
+ available = true;
+ }
+ }
+ }
+}
+
+void CharIOHandler::insertFd(const int &fd) {
+ fd_list.insert(fd);
+}
+
+void CharIOHandler::removeFd(const int &fd) {
+ fd_list.remove(fd);
+}
+
+bool CharIOHandler::isSequential() const {
+ return iodev->isSequential();
+}
+
+bool CharIOHandler::open(OpenMode mode) {
+ if (!iodev->open(mode)) {
+
+ return false;
+ }
+ Super::open(mode);
+ return true;
+}
+
+void CharIOHandler::close() {
+ Super::close();
+ iodev->close();
+}
+
+qint64 CharIOHandler::pos() const {
+ return iodev->pos();
+}
+
+qint64 CharIOHandler::size() const {
+ return iodev->size();
+}
+
+bool CharIOHandler::seek(qint64 pos) {
+ return iodev->seek(pos);
+}
+
+bool CharIOHandler::atEnd() const {
+ return iodev->atEnd();
+}
+
+bool CharIOHandler::reset() {
+ return iodev->reset();
+}
+
+qint64 CharIOHandler::bytesAvailable() const {
+ return iodev->bytesAvailable() + Super::bytesAvailable();
+}
+
+qint64 CharIOHandler::bytesToWrite() const {
+ return iodev->bytesToWrite() + Super::bytesToWrite();
+}
+
+bool CharIOHandler::canReadLine() const {
+ return iodev->canReadLine();
+}
+
+bool CharIOHandler::waitForReadyRead(int msecs) {
+ return iodev->waitForReadyRead(msecs);
+}
+
+bool CharIOHandler::waitForBytesWritten(int msecs) {
+ return iodev->waitForBytesWritten(msecs);
+}
+
+qint64 CharIOHandler::readData(char *data, qint64 maxSize) {
+ return iodev->read(data, maxSize);
+}
+
+qint64 CharIOHandler::readLineData(char *data, qint64 maxSize) {
+ return iodev->readLine(data, maxSize);
+}
+
+qint64 CharIOHandler::writeData(const char *data, qint64 maxSize) {
+ return iodev->write(data, maxSize);
+}
diff --git a/qtmips_cli/chariohandler.h b/qtmips_cli/chariohandler.h
new file mode 100644
index 0000000..a37a217
--- /dev/null
+++ b/qtmips_cli/chariohandler.h
@@ -0,0 +1,85 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*******************************************************************************
+ * QtMips - MIPS 32-bit Architecture Subset Simulator
+ *
+ * Implemented to support following courses:
+ *
+ * B35APO - Computer Architectures
+ * https://cw.fel.cvut.cz/wiki/courses/b35apo
+ *
+ * B4M35PAP - Advanced Computer Architectures
+ * https://cw.fel.cvut.cz/wiki/courses/b4m35pap/start
+ *
+ * Copyright (c) 2017-2019 Karel Koci<cynerd@email.cz>
+ * Copyright (c) 2019 Pavel Pisa <pisa@cmp.felk.cvut.cz>
+ *
+ * Faculty of Electrical Engineering (http://www.fel.cvut.cz)
+ * Czech Technical University (http://www.cvut.cz/)
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ ******************************************************************************/
+
+#ifndef CHARIOHANDLER_H
+#define CHARIOHANDLER_H
+
+#include <QObject>
+#include <QIODevice>
+#include <QSet>
+
+class CharIOHandler : public QIODevice
+{
+ Q_OBJECT
+
+ using Super = QIODevice;
+
+public:
+ explicit CharIOHandler(QIODevice *iodev, QObject *parent = nullptr);
+ virtual ~CharIOHandler() override;
+
+public slots:
+ void writeByte(unsigned int data);
+ void writeByte(int fd, unsigned int data);
+ void readBytePoll(int fd, unsigned int &data, bool &available);
+
+public:
+ void insertFd(const int &fd);
+ void removeFd(const int &fd);
+
+ virtual bool isSequential() const override;
+ virtual bool open(OpenMode mode) override;
+ virtual void close() override;
+ virtual qint64 pos() const override;
+ virtual qint64 size() const override;
+ virtual bool seek(qint64 pos) override;
+ virtual bool atEnd() const override;
+ virtual bool reset() override;
+ virtual qint64 bytesAvailable() const override;
+ virtual qint64 bytesToWrite() const override;
+ virtual bool canReadLine() const override;
+ virtual bool waitForReadyRead(int msecs) override;
+ virtual bool waitForBytesWritten(int msecs) override;
+protected:
+ virtual qint64 readData(char *data, qint64 maxSize) override;
+ virtual qint64 readLineData(char *data, qint64 maxSize) override;
+ virtual qint64 writeData(const char *data, qint64 maxSize) override;
+private:
+ QIODevice *iodev;
+ bool fd_specific;
+ QSet<int> fd_list;
+};
+
+#endif // CHARIOHANDLER_H
diff --git a/qtmips_cli/main.cpp b/qtmips_cli/main.cpp
index 2984d8c..6430695 100644
--- a/qtmips_cli/main.cpp
+++ b/qtmips_cli/main.cpp
@@ -44,6 +44,7 @@
#include "reporter.h"
#include "msgreport.h"
#include "simpleasm.h"
+#include "chariohandler.h"
using namespace machine;
using namespace std;
@@ -81,6 +82,8 @@ void create_parser(QCommandLineParser &p) {
p.addOption({"read-time", "Memory read access time (cycles).", "RTIME"});
p.addOption({"write-time", "Memory read access time (cycles).", "WTIME"});
p.addOption({"burst-time", "Memory read access time (cycles).", "BTIME"});
+ p.addOption({{"serial-in", "serin"}, "File connected to the serial port input.", "FNAME"});
+ p.addOption({{"serial-out", "serout"}, "File connected to the serial port output.", "FNAME"});
}
void configure_cache(MachineConfigCache &cacheconf, QStringList cachearg, QString which) {
@@ -284,6 +287,58 @@ void configure_reporter(QCommandLineParser &p, Reporter &r, const SymbolTable *s
// TODO
}
+void configure_serial_port(QCommandLineParser &p, SerialPort *ser_port) {
+ int siz;
+ CharIOHandler *ser_in = nullptr;
+ CharIOHandler *ser_out = nullptr;
+
+ if (!ser_port)
+ return;
+
+ siz = p.values("serial-in").size();
+ if (siz >= 1) {
+ QIODevice::OpenMode mode = QFile::ReadOnly;
+ QFile *qf = new QFile(p.values("serial-in").at(siz - 1));
+ ser_in = new CharIOHandler(qf, ser_port);
+ siz = p.values("serial-out").size();
+ if (siz) {
+ if (p.values("serial-in").at(siz - 1) == p.values("serial-out").at(siz - 1)) {
+ mode = QFile::ReadWrite;
+ ser_out = ser_in;
+ }
+ }
+ if (!ser_in->open(mode)) {
+ cout << "Serial port input file cannot be open for read." << endl;
+ exit(1);
+ }
+ }
+
+ if (!ser_out) {
+ siz = p.values("serial-out").size();
+ if (siz >= 1) {
+ QFile *qf = new QFile(p.values("serial-out").at(siz - 1));
+ ser_out = new CharIOHandler(qf, ser_port);
+ if (!ser_out->open(QFile::WriteOnly)) {
+ cout << "Serial port output file cannot be open for write." << endl;
+ exit(1);
+ }
+ }
+ }
+
+ if (ser_in) {
+ ser_port->connect(ser_in, SIGNAL(readyRead()), ser_port, SLOT(rx_queue_check()));
+ ser_port->connect(ser_port, SIGNAL(rx_byte_pool(int,unsigned int&, bool&)),
+ ser_in, SLOT(readBytePoll(int,unsigned int&, bool&)));
+ if (ser_in->bytesAvailable())
+ ser_port->rx_queue_check();
+ }
+
+ if (ser_out) {
+ ser_port->connect(ser_port, SIGNAL(tx_byte(unsigned int)),
+ ser_out, SLOT(writeByte(unsigned int)));
+ }
+}
+
void load_ranges(QtMipsMachine &machine, const QStringList &ranges) {
foreach (QString range_arg, ranges) {
std::uint32_t start;
@@ -371,6 +426,8 @@ int main(int argc, char *argv[]) {
Reporter r(&app, &machine);
configure_reporter(p, r, machine.symbol_table());
+ configure_serial_port(p, machine.serial_port());
+
if (asm_source) {
MsgReport msgrep(&app);
if (!assemble(machine, msgrep, p.positionalArguments()[0]))
diff --git a/qtmips_cli/qtmips_cli.pro b/qtmips_cli/qtmips_cli.pro
index ea692ec..eb7be14 100644
--- a/qtmips_cli/qtmips_cli.pro
+++ b/qtmips_cli/qtmips_cli.pro
@@ -34,9 +34,11 @@ SOURCES += \
main.cpp \
tracer.cpp \
reporter.cpp \
- msgreport.cpp
+ msgreport.cpp \
+ chariohandler.cpp
HEADERS += \
tracer.h \
reporter.h \
- msgreport.h
+ msgreport.h \
+ chariohandler.h