Files
riscv-emulator/ERFAHRUNGSBERICHT.md
2025-07-10 19:14:24 +02:00

4.2 KiB

Erfahrungsbericht zu der Programmierung des RISC-V Emulators


Für mich war direkt ab Beginn des Projektes klar, dass ich das in C++ schreiben möchte. Einmal, um das frisch Gelernte aus der C+ Vorlesung mit Anwendung vertiefen zu können, als auch um Praxiserfahrung mit der reinen Theorie zu bekommen.

Da C++ objektorientierte Programmierung erlaubt, habe ich mich dafür entschieden und habe begonnen, die ersten wichtigen Komponenten eines Rechenwerks als Singleton zu implementieren. Nötig oder nicht konnte ich dabei das Konzept näher vertiefen.
So hat sich dann mit der Zeit immer mehr herauskristallisiert, welche Komponenten ich in meinem Programm brauche. Schlussendlich eben ein ProgramLoader und einen Manager, neben den Registern, dem Memory und der ALU. Und somit viel weniger, als ich Anfangs dachte zu brauchen.

Begonnen habe ich damit, die Assembly Datei zu lesen und zu interpretieren. Zeile für Zeile zu lesen, Kommentare zu ignorieren, Befehl und Argumente zu trennen. Ich habe mich dafür, diese in einem Vektor zu speichern, den ich dann an die ALU weitergeben kann. Diese kann dann simpel die benötigten Daten aus dem Vektor herauslesen.
Die Labels haben zu Beginn einer Herausforderung dargestellt, da ich ja keinen herkömmlichen program counter verwende, kann ich also nicht einfach den aktuellen pc-value in einem register speichern. Dabei lernte ich den virtuellen Lesekopf eines Dateistreams in C++ kennen. Dieser erlaubt mir, mit geeigneten Funktionen jederzeit die aktuelle Position des Kopfes auszulesen als auch manuell zu setzen.
Dadurch habe ich mich entschieden, zu Beginn jeden Programmstartes die Assembly Datei zu indexieren und nach Labeln zu suchen. Wird eins gefunden, wird dieses zusammen mit dem Stream offset in einer Map gespeichert. Somit konnte ich jederzeit an bestimmte Labels im Code springen.

Der Rest war "nur noch" die Implementierung der ALU Befehle selbst. Da bereits (fast) alle Helfermethoden und Daten zur Verfügung standen, ging dies je nach Befehl recht schnell. Die größte Herausforderung hierbei war das erkennen eines Arguments als Register, Label oder immediate Value.

Nachdem alles angeforderte Implementiert war, habe ich mithilfe der Beispielprogramme den Emulator angepasst und gefixt, bis alles wie gewünscht funktioniert hat.


Ich habe beim Programmieren auf einen sehr modularen Aufbau geachtet. Das ist mir Teils gelungen, Teils sind einige Durchführungen von Befehlen sehr unschön im Code anzusehen. Begonnen von der riesigen if/else Abfrage in der Alu. Durch noch mehr Modularität wäre das deutlich schöner. Bereits das Parsen der Argumente ist meiner Meinung nach nicht elegant noch 100% sicher.
Außerdem ist der Emulator für die aktuellen Anforderungen sicherlich genügend, für nicht unterstütze Syntax oder Angaben von immediate values anstatt von Labeln im Assembly Code aber keines Falls gewachsen. Das liegt unter anderem an der fast nicht vorhandenen Fehlerbehebung im Code. Tritt irgendwo ein z.B. parsing Fehler auf, führt das direkt zu undefiniertem Verhalten, möglich sogar direkt zu einem Absturz. Bis auf ein paar Ausnahmen ist dieser dann undokumentiert, es kann also ohne genaues debuggen im Code nicht der Fehler direkt festgestellt werden.

Auch wenn der Emulator feature complete ist, ist er nicht poliert und optimiert wie er das sein sollte, um einen reibungslosen Verlauf bei z.B. möglichen Fehlern zu gewährleisten.


Fazit

Durch das Programmieren dieses Emulators konnte ich viel in C++ selber dazu lernen. Darunter auch die Anwendung von programmier-Pattern wie etwa Singleton, dem Einlesen von Dateien und dem gestylten Ausgeben von Text in der Konsole. Durch das Projekt hat sich mein Verständnis von C++ deutlich erhöht. Nicht zuletzt konnte ich durch das Programmieren und Einlesen auch einiges über die Funktionsweise eines echten Computers verstehen, wie dieser arbeitet. Speziell natürlich in der RISC-V Architektur.


Der Emulator wurde mit Git erstellt. Das Repository ist auf meinem Privaten Git Server zu finden. Durch die einzelnen Commits und den somit sichtbaren Fortschritt soll gezeigt werden, dass der Code von mir selber geschrieben wurde und nicht von einer KI.