Clean up Parser
MODIFY
src/edittab.cpp
src/edittab.cpp
@@ -23,6 +23,7 @@ EditTab::EditTab(QToolBar* toolbar, QWidget* parent) : RipesTab(toolbar, parent)
m_ui->assemblyedit->setupSyntaxHighlighter();
m_ui->assemblyedit->setupChangedTimer();
m_ui->binaryedit->setReadOnly(true);
+
// enable breakpoint area for the translated code only
m_ui->binaryedit->enableBreakpointArea();
@@ -66,6 +67,7 @@ void EditTab::clear() {
void EditTab::emitProgramChanged() {
emit programChanged(m_assembler->getProgram());
+ setDisassemblerText();
}
void EditTab::assemble() {
@@ -96,22 +98,12 @@ void EditTab::setAssemblyText(const QString& text) {
}
void EditTab::setDisassemblerText() {
- const QString& text = m_ui->disassembledViewButton->isChecked() ? Parser::getParser()->getDisassembledRepr()
- : Parser::getParser()->getBinaryRepr();
+ const QString& text = m_ui->disassembledViewButton->isChecked()
+ ? Parser::getParser()->disassemble(m_assembler->getTextSegment())
+ : Parser::getParser()->binarize(m_assembler->getTextSegment());
m_ui->binaryedit->setPlainText(text);
}
-void EditTab::on_assemblyfile_toggled(bool checked) {
- if (!checked) {
- // Disable assembly edit when loading binary files
- m_ui->assemblyedit->setEnabled(false);
- }
- // clear both editors when switching input mode and reset the highlighter for the assembly editor
- m_ui->assemblyedit->clear();
- m_ui->assemblyedit->reset();
- m_ui->binaryedit->clear();
-}
-
void EditTab::enableEditor() {
m_ui->editorStackedWidget->setCurrentIndex(0);
}
@@ -120,8 +112,8 @@ void EditTab::disableEditor() {
m_ui->editorStackedWidget->setCurrentIndex(1);
}
-void EditTab::on_disassembledViewButton_toggled(bool checked) {
- Q_UNUSED(checked)
+void EditTab::on_disassembledViewButton_toggled() {
+ setDisassemblerText();
}
void EditTab::loadFlatBinaryFile(const LoadFileParams& params) {
@@ -132,7 +124,6 @@ void EditTab::loadFlatBinaryFile(const LoadFileParams& params) {
void EditTab::loadAssemblyFile(const LoadFileParams& params) {
// ... load file
QFile file(params.filepath);
- Parser::getParser()->clear();
clear();
if (file.open(QIODevice::ReadOnly | QIODevice::Text)) {
setAssemblyText(file.readAll());

MODIFY
src/edittab.h
src/edittab.h
@@ -43,8 +43,7 @@ public slots:
private slots:
void assemble();
- void on_assemblyfile_toggled(bool checked);
- void on_disassembledViewButton_toggled(bool checked);
+ void on_disassembledViewButton_toggled();
private:
void loadFlatBinaryFile(const LoadFileParams&);

MODIFY
src/mainwindow.cpp
src/mainwindow.cpp
@@ -115,10 +115,6 @@ void MainWindow::setupMenus() {
m_ui->menuFile->addAction(exitAction);
}
-void MainWindow::run() {
- // Function for triggering the run dialog from unit tests
-}
-
MainWindow::~MainWindow() {
delete m_ui;
}
@@ -150,13 +146,6 @@ void MainWindow::loadFileTriggered() {
m_editTab->loadFile(diag.getParams());
}
-void MainWindow::loadBinaryFile(QString filename) {
- m_processorTab->restart();
- Parser::getParser()->loadBinaryFile(filename);
- m_editTab->setDisassemblerText();
- emit update();
-}
-
void MainWindow::about() {
AboutWidget about;
about.exec();
@@ -200,26 +189,12 @@ void MainWindow::saveFilesTriggered() {
}
//}
- // if (m_ui->actionSave_Disassembled->isChecked()) {
- {
- QFile file(removeFileExt(m_currentFile) + "_dis.s");
- writeTextFile(file, Parser::getParser()->getDisassembledRepr());
- }
- //}
-
// QAction* binaryStoreAction = m_binaryStoreAction->checkedAction();
// if (binaryStoreAction == m_ui->actionSave_as_flat_binary) {
{
QFile file(removeFileExt(m_currentFile) + ".bin");
writeBinaryFile(file, m_editTab->getBinaryData());
}
- //} else if (binaryStoreAction == m_ui->actionSave_as_text) {
-
- {
- QFile file(removeFileExt(m_currentFile) + "_bin.txt");
- writeTextFile(file, Parser::getParser()->getBinaryRepr());
- }
- //}
}
void MainWindow::saveFilesAsTriggered() {

MODIFY
src/mainwindow.h
src/mainwindow.h
@@ -27,10 +27,6 @@ public:
explicit MainWindow(QWidget* parent = nullptr);
~MainWindow() override;
- void loadBinaryFile(QString fileName = QString());
-
- void run();
-
private slots:
void exit();
void about();

MODIFY
src/parser.cpp
src/parser.cpp
#include "defines.h"
#include <cassert>
+#include <functional>
#include <iostream>
#include "binutils.h"
@@ -18,78 +19,44 @@ Parser::Parser() {
m_decodeJInstr = generateWordParser(vector<int>{5, 8, 1, 10, 1});
}
-bool Parser::initBinaryFile(char* filename) {
- // Open binary file
- const string fname = string(filename);
- m_fileStream = ifstream(fname.c_str(), ios::binary);
- if (!(m_fileStream.good())) {
- return true;
- }
-
- // Create filestream iterator
- m_fileIter = istreambuf_iterator<char>(m_fileStream);
-
- // get file size
- m_fileStream.seekg(0, ios::end);
- m_fileSize = m_fileStream.tellg();
- m_fileStream.clear();
- m_fileStream.seekg(0, ios::beg);
- return false;
-}
-
Parser::~Parser() {}
-void Parser::clear() {
- m_disassembledRepr.clear();
- m_binaryRepr.clear();
+QString Parser::disassemble(const QByteArray& text) const {
+ return stringifyByteArray(text, 4, [this](const std::vector<char>& buffer, uint32_t index) {
+ // Hardcoded for RV32 for now
+ uint32_t instr = 0;
+ for (int i = 0; i < 4; i++) {
+ instr |= (buffer[i] & 0xFF) << (CHAR_BIT * i);
}
-
-const QString& Parser::loadBinaryFile(QString fileName, bool disassembled) {
- // Loads a binary file and converts it to a text string, as well as puts the binary information into the pipeline
- // memorys text segment
-
- QFile file(fileName);
- if (file.open(QIODevice::ReadOnly)) {
- m_fileByteArray = file.readAll();
- file.close();
+ return disassemble(instr, index);
+ });
}
- if (disassembled) {
- return m_disassembledRepr;
- } else {
- return m_binaryRepr;
+
+QString Parser::binarize(const QByteArray& text) const {
+ return stringifyByteArray(text, 4, [](const std::vector<char>& buffer, uint32_t) {
+ QString binaryString;
+ for (auto byte : buffer) {
+ binaryString.prepend(QString().setNum(static_cast<uint8_t>(byte), 2).rightJustified(8, '0'));
}
+ return binaryString;
+ });
}
-const QString& Parser::loadFromByteArray(QByteArray arr, bool disassembled, uint32_t baseAddress) {
- // Loads the input arr into the memory of the simulator
- // Baseaddress is default = 0 (text). Can be changed for inserting into ie. data memory
+QString Parser::stringifyByteArray(const QByteArray& data, unsigned stride,
+ std::function<QString(const std::vector<char>&, uint32_t index)> stringifier) const {
+ QString out;
+ auto dataStream = QDataStream(data);
+ std::vector<char> buffer;
+ buffer.resize(stride);
+ uint32_t byteIndex = 0;
- QString output = "";
- auto length = arr.length();
- QDataStream in(&arr, QIODevice::ReadOnly);
- char buffer[4];
- uint32_t byteIndex = baseAddress;
- for (int i = 0; i < length; i += 4) {
- in.readRawData(buffer, 4);
- QString binaryRepString;
- for (char j : buffer) {
- binaryRepString.prepend(QString().setNum((uint8_t)j, 2).rightJustified(8, '0'));
- byteIndex++;
- }
- m_binaryRepr.append(binaryRepString).append('\n');
- uint32_t instr =
- (buffer[3] & 0xff) << 24 | (buffer[2] & 0xff) << 16 | (buffer[1] & 0xff) << 8 | (buffer[0] & 0xff);
- output.append(genStringRepr(instr, byteIndex - 4));
- output.append("\n");
- }
- // Remove trailing \n character
- output.truncate(output.lastIndexOf('\n'));
-
- if (disassembled) {
- return m_disassembledRepr;
- } else {
- return m_binaryRepr;
+ for (int i = 0; i < data.length(); i += stride) {
+ dataStream.readRawData(buffer.data(), stride);
+ out += stringifier(buffer, byteIndex);
+ out += "\n";
+ byteIndex += stride;
}
+ return out;
}
decode_functor Parser::generateWordParser(std::vector<int> bitFields) {
@@ -125,7 +92,7 @@ decode_functor Parser::generateWordParser(std::vector<int> bitFields) {
return wordParser;
}
-QString Parser::genStringRepr(uint32_t instr, uint32_t address) const {
+QString Parser::disassemble(uint32_t instr, uint32_t address) const {
switch (instr & 0x7f) {
case instrType::LUI:
return generateLuiString(instr);

MODIFY
src/parser.h
src/parser.h
@@ -24,9 +24,7 @@ public:
return &parser;
}
- int getFileSize() { return m_fileSize; }
- QString genStringRepr(uint32_t instr, uint32_t address) const;
- void clear();
+ QString disassemble(uint32_t instr, uint32_t address) const;
// Const interfaces to intstruction decode lamdas
std::vector<uint32_t> decodeUInstr(uint32_t instr) const { return m_decodeUInstr(instr); }
@@ -36,25 +34,16 @@ public:
std::vector<uint32_t> decodeRInstr(uint32_t instr) const { return m_decodeRInstr(instr); }
std::vector<uint32_t> decodeBInstr(uint32_t instr) const { return m_decodeBInstr(instr); }
- const QString& loadFromByteArray(QByteArray arr, bool disassembled, uint32_t baseAddress);
- const QString& loadBinaryFile(QString fileName, bool disassembled = true);
- const QString& getBinaryRepr() { return m_binaryRepr; }
- const QString& getDisassembledRepr() { return m_disassembledRepr; }
- QByteArray getFileByteArray() { return m_fileByteArray; }
- bool initBinaryFile(char* filename);
+ QString disassemble(const QByteArray& text) const;
+ QString binarize(const QByteArray& text) const;
private:
+ QString
+ stringifyByteArray(const QByteArray& data, unsigned stride,
+ std::function<QString(const std::vector<char>& buffer, uint32_t index)> stringifier) const;
+
Parser();
~Parser();
- ifstream m_fileStream;
- istreambuf_iterator<char> m_fileIter;
- QByteArray m_fileByteArray;
- int m_fileSize;
- QString m_disassembledRepr; // disassembled representation of the currently loaded binary file in the pipeline
- QString m_binaryRepr;
-
- QMap<int, uint32_t>
- m_assembledInputFileMap; // Intermediate assembler stage used for setting labels post-translation
// Instruction decode lambda functions; runtime generated
decode_functor generateWordParser(std::vector<int> bitFields);

MODIFY
src/processorhandler.cpp
src/processorhandler.cpp
@@ -136,7 +136,7 @@ int ProcessorHandler::getCurrentProgramSize() const {
}
QString ProcessorHandler::parseInstrAt(const uint32_t addr) const {
- return Parser::getParser()->genStringRepr(m_currentProcessor->getMemory().readMem(addr), addr);
+ return Parser::getParser()->disassemble(m_currentProcessor->getMemory().readMem(addr), addr);
}
void ProcessorHandler::handleSysCall() {

Clean up Parser