changed "///" to "//" in comments
This commit is contained in:
@@ -13,24 +13,24 @@
|
|||||||
#include "../ProgramLoader.h"
|
#include "../ProgramLoader.h"
|
||||||
|
|
||||||
void Alu::calculate(const std::vector<std::string> &commandVector) {
|
void Alu::calculate(const std::vector<std::string> &commandVector) {
|
||||||
/// Falls die aktuelle Zeile ein Label ist, return
|
// Falls die aktuelle Zeile ein Label ist, return
|
||||||
if (const auto length = commandVector.at(0).size(); commandVector.at(0).at(length - 1) == ':') {
|
if (const auto length = commandVector.at(0).size(); commandVector.at(0).at(length - 1) == ':') {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Extrahiere den eigentlichen RISC-V Befehl für die ALU
|
// Extrahiere den eigentlichen RISC-V Befehl für die ALU
|
||||||
const std::string &command = commandVector.at(0);
|
const std::string &command = commandVector.at(0);
|
||||||
|
|
||||||
/// Extrahiere die Argumente des Befehls
|
// Extrahiere die Argumente des Befehls
|
||||||
const auto arg1 = parseArgument(commandVector.at(1));
|
const auto arg1 = parseArgument(commandVector.at(1));
|
||||||
/// Wandle Vektor[2] (das zweite Argument) nur um, falls es kein SW/LW Argument ist
|
// Wandle Vektor[2] (das zweite Argument) nur um, falls es kein SW/LW Argument ist
|
||||||
int arg2 = 0;
|
int arg2 = 0;
|
||||||
if (commandVector.at(2).find('(') != std::string::npos) {
|
if (commandVector.at(2).find('(') != std::string::npos) {
|
||||||
arg2 = parseAddress(commandVector.at(2));
|
arg2 = parseAddress(commandVector.at(2));
|
||||||
} else {
|
} else {
|
||||||
arg2 = parseArgument(commandVector.at(2));
|
arg2 = parseArgument(commandVector.at(2));
|
||||||
}
|
}
|
||||||
/// Wandle Vektor[3] (das dritte Argument) nur um, falls dieser existiert und kein immediate Wert ist
|
// Wandle Vektor[3] (das dritte Argument) nur um, falls dieser existiert und kein immediate Wert ist
|
||||||
int arg3 = 0;
|
int arg3 = 0;
|
||||||
if (commandVector.size() > 3) {
|
if (commandVector.size() > 3) {
|
||||||
if (const std::string &arg = commandVector.at(3); isRegister(arg) || isImmediate(arg)) {
|
if (const std::string &arg = commandVector.at(3); isRegister(arg) || isImmediate(arg)) {
|
||||||
@@ -39,82 +39,82 @@ void Alu::calculate(const std::vector<std::string> &commandVector) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (command == "add") {
|
if (command == "add") {
|
||||||
/// Addition Befehl
|
// Addition Befehl
|
||||||
/// Hole die Werte beider angegebener Register
|
// Hole die Werte beider angegebener Register
|
||||||
const auto register1 = Register::getInstance().getRegister(arg2);
|
const auto register1 = Register::getInstance().getRegister(arg2);
|
||||||
const auto register2 = Register::getInstance().getRegister(arg3);
|
const auto register2 = Register::getInstance().getRegister(arg3);
|
||||||
/// Addiere die beiden Werte und schreibe das Ergebnis ins angegebene Register zurück
|
// Addiere die beiden Werte und schreibe das Ergebnis ins angegebene Register zurück
|
||||||
const auto result = register1 + register2;
|
const auto result = register1 + register2;
|
||||||
Register::getInstance().setRegister(arg1, result);
|
Register::getInstance().setRegister(arg1, result);
|
||||||
} else if (command == "sub") {
|
} else if (command == "sub") {
|
||||||
/// Subtraktion Befehl
|
// Subtraktion Befehl
|
||||||
/// Hole die Werte beider angegebener Register
|
// Hole die Werte beider angegebener Register
|
||||||
const auto register1 = Register::getInstance().getRegister(arg2);
|
const auto register1 = Register::getInstance().getRegister(arg2);
|
||||||
const auto register2 = Register::getInstance().getRegister(arg3);
|
const auto register2 = Register::getInstance().getRegister(arg3);
|
||||||
/// Subtrahiere die beiden Werte und schreibe das Ergebnis ins angegebene Register zurück
|
// Subtrahiere die beiden Werte und schreibe das Ergebnis ins angegebene Register zurück
|
||||||
const auto result = register1 - register2;
|
const auto result = register1 - register2;
|
||||||
Register::getInstance().setRegister(arg1, result);
|
Register::getInstance().setRegister(arg1, result);
|
||||||
} else if (command == "and") {
|
} else if (command == "and") {
|
||||||
/// Binärer und Befehl
|
// Binärer und Befehl
|
||||||
/// Hole die Werte beider angegebener Register
|
// Hole die Werte beider angegebener Register
|
||||||
const auto register1 = Register::getInstance().getRegister(arg2);
|
const auto register1 = Register::getInstance().getRegister(arg2);
|
||||||
const auto register2 = Register::getInstance().getRegister(arg3);
|
const auto register2 = Register::getInstance().getRegister(arg3);
|
||||||
/// Verknüpfe die beiden Werte binär und schreibe das Ergebnis ins angegebene Register zurück
|
// Verknüpfe die beiden Werte binär und schreibe das Ergebnis ins angegebene Register zurück
|
||||||
const auto result = register1 & register2;
|
const auto result = register1 & register2;
|
||||||
Register::getInstance().setRegister(arg1, result);
|
Register::getInstance().setRegister(arg1, result);
|
||||||
} else if (command == "or") {
|
} else if (command == "or") {
|
||||||
/// Binärer oder Befehl
|
// Binärer oder Befehl
|
||||||
/// Hole die Werte beider angegebener Register
|
// Hole die Werte beider angegebener Register
|
||||||
const auto register1 = Register::getInstance().getRegister(arg2);
|
const auto register1 = Register::getInstance().getRegister(arg2);
|
||||||
const auto register2 = Register::getInstance().getRegister(arg3);
|
const auto register2 = Register::getInstance().getRegister(arg3);
|
||||||
/// Unterscheide die beiden Werte binär und schreibe das Ergebnis ins angegebene Register zurück
|
// Unterscheide die beiden Werte binär und schreibe das Ergebnis ins angegebene Register zurück
|
||||||
const auto result = register1 | register2;
|
const auto result = register1 | register2;
|
||||||
Register::getInstance().setRegister(arg1, result);
|
Register::getInstance().setRegister(arg1, result);
|
||||||
} else if (command == "xor") {
|
} else if (command == "xor") {
|
||||||
/// Binärer exklusiver oder Befehl
|
// Binärer exklusiver oder Befehl
|
||||||
/// Hole die Werte beider angegebener Register
|
// Hole die Werte beider angegebener Register
|
||||||
const auto register1 = Register::getInstance().getRegister(arg2);
|
const auto register1 = Register::getInstance().getRegister(arg2);
|
||||||
const auto register2 = Register::getInstance().getRegister(arg3);
|
const auto register2 = Register::getInstance().getRegister(arg3);
|
||||||
/// Unterscheide die beiden Werte binär exklusiv und schreibe das Ergebnis ins angegebene Register zurück
|
// Unterscheide die beiden Werte binär exklusiv und schreibe das Ergebnis ins angegebene Register zurück
|
||||||
const auto result = register1 ^ register2;
|
const auto result = register1 ^ register2;
|
||||||
Register::getInstance().setRegister(arg1, result);
|
Register::getInstance().setRegister(arg1, result);
|
||||||
} else if (command == "addi") {
|
} else if (command == "addi") {
|
||||||
/// Immediate und Befehl
|
// Immediate und Befehl
|
||||||
/// Hole Wert1 aus dem angegebenen Register und Wert2 aus dem Befehlsargument
|
// Hole Wert1 aus dem angegebenen Register und Wert2 aus dem Befehlsargument
|
||||||
const auto register1 = Register::getInstance().getRegister(arg2);
|
const auto register1 = Register::getInstance().getRegister(arg2);
|
||||||
const auto immediate = arg3;
|
const auto immediate = arg3;
|
||||||
/// Addiere die beiden Werte und schreibe das Ergebnis ins angegebene Register zurück
|
// Addiere die beiden Werte und schreibe das Ergebnis ins angegebene Register zurück
|
||||||
const auto result = register1 + immediate;
|
const auto result = register1 + immediate;
|
||||||
Register::getInstance().setRegister(arg1, result);
|
Register::getInstance().setRegister(arg1, result);
|
||||||
} else if (command == "andi") {
|
} else if (command == "andi") {
|
||||||
/// Binärer immediate und Befehl
|
// Binärer immediate und Befehl
|
||||||
/// Hole Wert1 aus dem angegebnen Register und Wert2 aus dem Befehlsargument
|
// Hole Wert1 aus dem angegebnen Register und Wert2 aus dem Befehlsargument
|
||||||
const auto register1 = Register::getInstance().getRegister(arg2);
|
const auto register1 = Register::getInstance().getRegister(arg2);
|
||||||
const auto immediate = arg3;
|
const auto immediate = arg3;
|
||||||
/// Addiere die beiden Werte und schreibe das Ergebnis ins angegebene Register zurück
|
// Addiere die beiden Werte und schreibe das Ergebnis ins angegebene Register zurück
|
||||||
const auto result = register1 & immediate;
|
const auto result = register1 & immediate;
|
||||||
Register::getInstance().setRegister(arg1, result);
|
Register::getInstance().setRegister(arg1, result);
|
||||||
} else if (command == "ori") {
|
} else if (command == "ori") {
|
||||||
/// Binärer immediate oder Befehl
|
// Binärer immediate oder Befehl
|
||||||
/// Hole Wert1 aus dem angegebenen Register und Wert2 aus dem Befehlsargument
|
// Hole Wert1 aus dem angegebenen Register und Wert2 aus dem Befehlsargument
|
||||||
const auto register1 = Register::getInstance().getRegister(arg2);
|
const auto register1 = Register::getInstance().getRegister(arg2);
|
||||||
const auto immediate = arg3;
|
const auto immediate = arg3;
|
||||||
/// Unterscheide beide Werte binär und schreibe das Ergebnis ins angegebene Register zurück
|
// Unterscheide beide Werte binär und schreibe das Ergebnis ins angegebene Register zurück
|
||||||
const auto result = register1 | immediate;
|
const auto result = register1 | immediate;
|
||||||
Register::getInstance().setRegister(arg1, result);
|
Register::getInstance().setRegister(arg1, result);
|
||||||
} else if (command == "lw") {
|
} else if (command == "lw") {
|
||||||
/// Loadword Befehl
|
// Loadword Befehl
|
||||||
/// Hole die Adresse aus dem Befehlsargument und die dazugehörigen Daten aus dem RAM
|
// Hole die Adresse aus dem Befehlsargument und die dazugehörigen Daten aus dem RAM
|
||||||
const auto address = arg2;
|
const auto address = arg2;
|
||||||
const auto data = Memory::getInstance()->load(address);
|
const auto data = Memory::getInstance()->load(address);
|
||||||
/// Speichere die Daten im angegeben Register
|
// Speichere die Daten im angegeben Register
|
||||||
Register::getInstance().setRegister(arg1, data);
|
Register::getInstance().setRegister(arg1, data);
|
||||||
} else if (command == "sw") {
|
} else if (command == "sw") {
|
||||||
/// Storeword Befehl
|
// Storeword Befehl
|
||||||
/// Hole die Adresse aus dem Befehlsargument und die dazugehörigen Daten aus dem Register
|
// Hole die Adresse aus dem Befehlsargument und die dazugehörigen Daten aus dem Register
|
||||||
const auto address = arg2;
|
const auto address = arg2;
|
||||||
const auto data = Register::getInstance().getRegister(arg1);
|
const auto data = Register::getInstance().getRegister(arg1);
|
||||||
/// Speichere die Daten im angegeben RAM slot
|
// Speichere die Daten im angegeben RAM slot
|
||||||
Memory::getInstance()->store(address, data);
|
Memory::getInstance()->store(address, data);
|
||||||
} else if (command == "beq") {
|
} else if (command == "beq") {
|
||||||
const auto register1 = Register::getInstance().getRegister(arg1);
|
const auto register1 = Register::getInstance().getRegister(arg1);
|
||||||
@@ -133,23 +133,28 @@ void Alu::calculate(const std::vector<std::string> &commandVector) {
|
|||||||
Manager::getInstance()->setStreamPosition(streamPos);
|
Manager::getInstance()->setStreamPosition(streamPos);
|
||||||
}
|
}
|
||||||
} else if (command == "jal") {
|
} else if (command == "jal") {
|
||||||
/// Jump and link Befehl
|
// Jump and link Befehl
|
||||||
/// !!! Aufgrund des casts des stream offsets zu int funktioniert das nicht bei großen Quellcode Dateien
|
// !!! Aufgrund des casts des stream offsets zu int funktioniert das nicht bei großen Quellcode Dateien
|
||||||
/// und führt zu undefiniertem Verhalten !!!
|
// und führt zu undefiniertem Verhalten !!!
|
||||||
|
// Speichert die Position des nächsten Befehls im angegebenen Register
|
||||||
const auto pos = static_cast<int>(Manager::getInstance()->getNextStreamLineOffset().operator std::streamoff());
|
const auto pos = static_cast<int>(Manager::getInstance()->getNextStreamLineOffset().operator std::streamoff());
|
||||||
|
Register::getInstance().setRegister(arg1, pos);
|
||||||
|
// Holt sich die Position des angegebenen labels und die stream Position auf diese
|
||||||
const auto &label = commandVector.at(2);
|
const auto &label = commandVector.at(2);
|
||||||
const auto streamPos = ProgramLoader::getInstance()->getStreamPosition(label);
|
const auto streamPos = ProgramLoader::getInstance()->getStreamPosition(label);
|
||||||
Register::getInstance().setRegister(arg1, pos);
|
|
||||||
Manager::getInstance()->setStreamPosition(streamPos);
|
Manager::getInstance()->setStreamPosition(streamPos);
|
||||||
} else if (command == "jalr") {
|
} else if (command == "jalr") {
|
||||||
/// Jump and link register Befehl
|
// Jump and link register Befehl
|
||||||
/// !!! Aufgrund des casts des stream offsets zu int funktioniert das nicht bei großen Quellcode Dateien
|
// !!! Aufgrund des casts des stream offsets zu int funktioniert das nicht bei großen Quellcode Dateien
|
||||||
/// und führt zu undefiniertem Verhalten !!!
|
// und führt zu undefiniertem Verhalten !!!
|
||||||
|
// Speichert die Position des nächsten Befehls im angegebenen Register
|
||||||
const auto pos = static_cast<int>(Manager::getInstance()->getNextStreamLineOffset().operator std::streamoff());
|
const auto pos = static_cast<int>(Manager::getInstance()->getNextStreamLineOffset().operator std::streamoff());
|
||||||
|
Register::getInstance().setRegister(arg1, pos);
|
||||||
|
// Holt sich die Position des angegebenen labels und das Offset aus dem angegebenen Register
|
||||||
const auto &label = commandVector.at(3);
|
const auto &label = commandVector.at(3);
|
||||||
const auto streamPosLabel = ProgramLoader::getInstance()->getStreamPosition(label);
|
const auto streamPosLabel = ProgramLoader::getInstance()->getStreamPosition(label);
|
||||||
const auto posOffset = Register::getInstance().getRegister(arg2);
|
const auto posOffset = Register::getInstance().getRegister(arg2);
|
||||||
Register::getInstance().setRegister(arg1, pos);
|
// Setzt die stream Position auf den gegebenen Wert & erhöht sie um den angegebenen Offset
|
||||||
Manager::getInstance()->setStreamPosition(streamPosLabel);
|
Manager::getInstance()->setStreamPosition(streamPosLabel);
|
||||||
for (int i = 0; i < posOffset; ++i) {
|
for (int i = 0; i < posOffset; ++i) {
|
||||||
Manager::getInstance()->gotoNextStreamLine();
|
Manager::getInstance()->gotoNextStreamLine();
|
||||||
@@ -158,16 +163,16 @@ void Alu::calculate(const std::vector<std::string> &commandVector) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
int Alu::parseArgument(std::string argument) {
|
int Alu::parseArgument(std::string argument) {
|
||||||
/// Falls das erste Argument ein Register ist, entferne das führende "x"
|
// Falls das erste Argument ein Register ist, entferne das führende "x"
|
||||||
if (argument.at(0) == 'x') argument = argument.substr(1);
|
if (argument.at(0) == 'x') argument = argument.substr(1);
|
||||||
/// Da das Argument noch als String vorliegt, muss es in ein int umgewandelt werden
|
// Da das Argument noch als String vorliegt, muss es in ein int umgewandelt werden
|
||||||
return std::stoi(argument);
|
return std::stoi(argument);
|
||||||
}
|
}
|
||||||
|
|
||||||
int Alu::parseAddress(const std::string &argument) {
|
int Alu::parseAddress(const std::string &argument) {
|
||||||
/// Finde die Position von '(', trenne die den String dort und
|
// Finde die Position von '(', trenne die den String dort und
|
||||||
/// addiere die umgewandelten Integer zur Adresse
|
// addiere die umgewandelten Integer zur Adresse
|
||||||
/// Bsp: 0(x1)
|
// Bsp: 0(x1)
|
||||||
if (const size_t pos = argument.find('('); pos != std::string::npos) {
|
if (const size_t pos = argument.find('('); pos != std::string::npos) {
|
||||||
const auto immediate = std::stoi(argument.substr(0, pos + 1));
|
const auto immediate = std::stoi(argument.substr(0, pos + 1));
|
||||||
const auto register1 = std::stoi(argument.substr(pos + 2));
|
const auto register1 = std::stoi(argument.substr(pos + 2));
|
||||||
@@ -178,16 +183,16 @@ int Alu::parseAddress(const std::string &argument) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool Alu::isRegister(const std::string &argument) {
|
bool Alu::isRegister(const std::string &argument) {
|
||||||
/// Überprüfe, ob das nichtleere Argument mit 'x' startet
|
// Überprüfe, ob das nichtleere Argument mit 'x' startet
|
||||||
if (argument.empty() || argument.at(0) != 'x') return false;
|
if (argument.empty() || argument.at(0) != 'x') return false;
|
||||||
/// Entfernt das voranstehende 'x' und checkt, ob darauf etwas folgt
|
// Entfernt das voranstehende 'x' und checkt, ob darauf etwas folgt
|
||||||
const std::string numberPart = argument.substr(1);
|
const std::string numberPart = argument.substr(1);
|
||||||
if (numberPart.empty()) return false;
|
if (numberPart.empty()) return false;
|
||||||
/// Überprüfe, ob alle Zeichen im restlichen Argument Nummern sind
|
// Überprüfe, ob alle Zeichen im restlichen Argument Nummern sind
|
||||||
for (const char c: numberPart) {
|
for (const char c: numberPart) {
|
||||||
if (!std::isdigit(c)) return false;
|
if (!std::isdigit(c)) return false;
|
||||||
}
|
}
|
||||||
/// Konvertiere zu int und überprüfe, ob es ein Register zwischen inklusive x0 und x32 ist
|
// Konvertiere zu int und überprüfe, ob es ein Register zwischen inklusive x0 und x32 ist
|
||||||
const int regNum = std::stoi(numberPart);
|
const int regNum = std::stoi(numberPart);
|
||||||
return regNum >= 0 && regNum <= 32;
|
return regNum >= 0 && regNum <= 32;
|
||||||
}
|
}
|
||||||
@@ -195,7 +200,7 @@ bool Alu::isRegister(const std::string &argument) {
|
|||||||
bool Alu::isImmediate(const std::string &argument) {
|
bool Alu::isImmediate(const std::string &argument) {
|
||||||
if (argument.empty()) return false;
|
if (argument.empty()) return false;
|
||||||
constexpr size_t start = 0;
|
constexpr size_t start = 0;
|
||||||
/// Überprüfe, ob jedes Zeichen im Argument eine Nummer ista
|
// Überprüfe, ob jedes Zeichen im Argument eine Nummer ista
|
||||||
for (size_t i = start; i < argument.size(); ++i) {
|
for (size_t i = start; i < argument.size(); ++i) {
|
||||||
if (!std::isdigit(argument.at(i))) return false;
|
if (!std::isdigit(argument.at(i))) return false;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,21 +6,21 @@
|
|||||||
#define MEMORY_H
|
#define MEMORY_H
|
||||||
#include <array>
|
#include <array>
|
||||||
|
|
||||||
/// Eine Hauptspeicherklasse als Singleton implementiert.
|
// Eine Hauptspeicherklasse als Singleton implementiert.
|
||||||
/// Als Hauptspeicher wird ein Array genutzt.
|
// Als Hauptspeicher wird ein Array genutzt.
|
||||||
|
|
||||||
|
|
||||||
class Memory {
|
class Memory {
|
||||||
private:
|
private:
|
||||||
Memory();
|
Memory();
|
||||||
|
|
||||||
/// Singleton instance
|
// Singleton instance
|
||||||
static Memory *m_instance;
|
static Memory *m_instance;
|
||||||
/// Hauptspeicher (hier 32 kB groß)
|
// Hauptspeicher (hier 32 kB groß)
|
||||||
std::array<int, 8192> m_memory{};
|
std::array<int, 8192> m_memory{};
|
||||||
|
|
||||||
public:
|
public:
|
||||||
/// Singleton Logik
|
// Singleton Logik
|
||||||
Memory(const Memory &) = delete;
|
Memory(const Memory &) = delete;
|
||||||
|
|
||||||
Memory(const Memory &&) = delete;
|
Memory(const Memory &&) = delete;
|
||||||
|
|||||||
@@ -6,21 +6,21 @@
|
|||||||
#define REGISTER_H
|
#define REGISTER_H
|
||||||
#include <array>
|
#include <array>
|
||||||
|
|
||||||
/// Eine Registerklasse als Singleton implementiert.
|
// Eine Registerklasse als Singleton implementiert.
|
||||||
/// Als Speicher (Registers) wird ein int Array genutzt.
|
// Als Speicher (Registers) wird ein int Array genutzt.
|
||||||
|
|
||||||
|
|
||||||
class Register {
|
class Register {
|
||||||
private:
|
private:
|
||||||
Register();
|
Register();
|
||||||
|
|
||||||
/// Singleton instance
|
// Singleton instance
|
||||||
static Register *m_instance;
|
static Register *m_instance;
|
||||||
/// "Echter" Register Speicher
|
// "Echter" Register Speicher
|
||||||
std::array<int, 32> m_registers{};
|
std::array<int, 32> m_registers{};
|
||||||
|
|
||||||
public:
|
public:
|
||||||
/// Singleton Logik
|
// Singleton Logik
|
||||||
Register(const Register &) = delete;
|
Register(const Register &) = delete;
|
||||||
|
|
||||||
Register(const Register &&) = delete;
|
Register(const Register &&) = delete;
|
||||||
|
|||||||
Reference in New Issue
Block a user