diff --git a/README.md b/README.md index a98031e..daef403 100644 --- a/README.md +++ b/README.md @@ -1,22 +1,24 @@ # RISC-V Playground -Willkommen in dem RISC-V Playground! +Willkommen im RISC-V Playground! ## Installation -*Dieser Schritt ist in der gelieferten VM bereits abgeschlossen* +*Dieser Schritt ist in der gelieferten VM bereits abgeschlossen.* + + 1. Um den RISC-V Emulator zu installieren wird Python 3 und den Python Package Manger pip benötigt. Unter Linux ist beides in den meisten Paketmanagern enthalten und sollte über die bekannten Möglichkeiten installiert werden können. + 2. Installiere den Emulator als pip-Paket (das Paket heißt `riscemu`): `pip install riscemu` + + 3. Der Emulator wird als Python-Paket installiert und kann mit `python3 -m riscemu` ausgeführt werden. Teste deine Installation mit `python3 -m riscemu --version`, es sollte mindestens Version `2.0.3` installiert sein. - 1. Um den RISC-V Emulator zu installieren brauchst du Python 3 und den Python Package Manger pip. Unter Linux ist das in dem Paketmanager deiner Distribution enthalten. - 2. Installiere den Emulator als pip Paket (das Paket heißt `riscemu`): `pip install riscemu` - 3. Teste deine Installation mit `python3 -m riscemu --version`, es sollte mindestens Version `2.0.3` installiert sein. ## RISC-V Code Ausführen -*Das folgende Beispiel findet auf der Konsole statt, der RISC-V Emulator hat nur ein Konsoleninterface. In Ubuntu kann mit hilfe des Kontextmenüs (Rechtsklick) im Dateibrowser die Eintrag "Im Terminal öffnen" ein Terminal öffnen, in dem bereits der Ordner geöffnet ist.* +*Der RISC-V Emulator hat nur ein Konsoleninterface, weswegen auch folgendes Beispiel auf der Konsole abläuft. In Ubuntu kann mithilfe des Kontextmenüs (Rechtsklick) im Dateibrowser über den Eintrag "Im Terminal öffnen" ein Terminal geöffnet werden, in dem bereits der entsprechende Ordner geöffnet ist.* -Betrachten wir das beispiel: `hello-world.asm` +Betrachten wir das Beispiel: `hello-world.asm` ``` # hello-world.asm @@ -37,7 +39,7 @@ text: .asci "Hello World\n" ecall ``` -Das Programm kann auf der konsole mit dem dem Befehl `python3 -m riscemu hello-world.asm` ausgeführt werden. Dafür solltest du in der Konsole in dem gleichen Ordner wie dein assembly program sein. Es sollte das folgende Output in deiner Konsole erscheinen: +Das Programm kann auf der Konsole mit dem dem Befehl `python3 -m riscemu hello-world.asm` ausgeführt werden. Dafür solltest du in der Konsole in dem gleichen Ordner wie dein assembly-Programm sein. Es sollte der folgende Output in deiner Konsole erscheinen: ``` > python3 -m riscemu hello-world.asm @@ -64,7 +66,7 @@ Hello World ## Debugging -Der RISC-V Standard hat einen befehl reserviert der als sogenannter "Breakpoint" agiert. Wenn der Emulator diesen befehl erkennt, wird ein interaktiver Debugger gestartet. Lass uns nun hinter den ersten `ecall` Befehl in `hello-world.asm` einen Breakpoint-Befehl einfügen: +Der RISC-V Standard hat einen Befehl reserviert, der als sogenannter "Breakpoint" agiert. Wenn der Emulator diesen Befehl ausführt, wird ein interaktiver Debugger gestartet. Lass uns nun hinter den ersten `ecall` Befehl in `hello-world.asm` einen Breakpoint-Befehl einfügen: ``` @@ -82,7 +84,7 @@ Der RISC-V Standard hat einen befehl reserviert der als sogenannter "Breakpoint" ecall ``` -Wenn das Programm nun ausgeführt wird, erscheint das folgende Output generiert: +Wenn das Programm nun ausgeführt wird, wird der folgende Output generiert: ``` Hello World @@ -92,31 +94,31 @@ Debug instruction encountered at 0x00000127 >>> ```` -Dies ist der interaktive Debugger. Hier kann der Zustand der Register, des CPUs und des Arbeitsspeichers betrachtet werden. Eine übersicht der wichtigsten Funktionen sind in der debugging.md Datei zu finden. +Dies ist der interaktive Debugger. Hier kann der Zustand der Register, der CPU und des Arbeitsspeichers betrachtet werden. Eine Übersicht der wichtigsten Funktionen sind in der debugging.md Datei zu finden. ## Installation der RISC-V Gnu Toolchain *Auch dieser Schritt ist in der VM schon erledigt.* -Für die Installatio unter Linux (Ubuntu) ist ein installationsskript beigelegt, welches die RISC-V toolchain für die Nutzung im Rahmen der Vorlesung konfiguriert und kompiliert. Ich bin mir nicht sicher ob die toolchain unter Windows kompilierbar ist, nehmt dafür am besten das [WSL](https://docs.microsoft.com/en-us/windows/wsl/install) +Für die Installation unter Linux (Ubuntu) ist ein Installationsskript beigelegt, welches die RISC-V Toolchain für die Nutzung im Rahmen der Vorlesung konfiguriert und kompiliert. Ich bin mir nicht sicher ob die toolchain unter Windows kompilierbar ist, nehmt dafür am besten das [WSL](https://docs.microsoft.com/en-us/windows/wsl/install) -Falls das Skript für eure Platform nicht funktioniert, hier noch ein paar tips: +Falls das Skript für eure Platform nicht funktioniert, hier noch ein paar Tipps: - Ihr braucht ca 8 Gigabyte Festplattenplatz um RISC-V GCC zu kompilieren. (Ein teil kann nach der Installation gelöscht werden). - - In der [GitHub Readme](https://github.com/riscv-collab/riscv-gnu-toolchain#readme) findet ihr die genauen pakete, die ihr auf eurer Distro installierne müsst. + - In der [GitHub Readme](https://github.com/riscv-collab/riscv-gnu-toolchain#readme) findet ihr die genauen Pakete, die ihr auf eurer Distribution installieren müsst. - Klont das Repository mit `git clone --depth 1 https://github.com/riscv-collab/riscv-gnu-toolchain.git` um nicht die ganze git history mit herunter zu laden. - - Konfiguriert die Installation mit dem folgenden Befehl (dafür müsst ihr in die geklonte repo rein `cd`'en): `./configure --prefix=$(pwd)/../toolchain/ --with-arch=rv32ima --disable-linux --disable-gdb --disable-multilib`. Der Zielordner muss unbedingt vorher angelegt werden! Also `mkdir $(pwd)/../toolchain/` (Legt den ordner `toolchain` im Überordner der Repo an). - - Baut den compiler mit allen verfügbaren threads: `make -j `. - - Nach der installation sollte der `toolchain/bin` Ordner zu dem `$PATH` hinzugefügt werden, hierfür gibt es mehrere Möglichkeiten. Hier ein tutorial zur `$PATH` vairable: https://www.howtogeek.com/658904/how-to-add-a-directory-to-your-path-in-linux/ + - Konfiguriert die Installation mit dem folgenden Befehl (dafür müsst ihr in die geklonte Repo rein `cd`'en): `./configure --prefix=$(pwd)/../toolchain/ --with-arch=rv32ima --disable-linux --disable-gdb --disable-multilib`. Der Zielordner muss unbedingt per Hand angelegt werden, sonst funktioniert die Kompilation nicht! Also muss `mkdir $(pwd)/../toolchain/` ausgeführt werden (Legt den ordner `toolchain` im Überordner der Repo an). + - Baut den Compiler mit allen verfügbaren Threads: `make -j `. Die Anzahl der verfügbaren Threads kann mit dem Befehl `grep -c ^processor /proc/cpuinfo` bestimmt werden. + - Nach der Installation sollte der `toolchain/bin` Ordner zur `$PATH`-Variable hinzugefügt werden, hierfür gibt es mehrere Möglichkeiten. Hier ein tutorial zur `$PATH`-Variable: https://www.howtogeek.com/658904/how-to-add-a-directory-to-your-path-in-linux/ -Nach der installation sollte es möglich sein C und RISC-V Assembly in RISC-V Objektdateien und executables zu kompilieren und den bytecode aus zu geben: +Jetzt kann mit Hilfe der Toolchain, C und RISC-V Assembly in RISC-V Objektdateien und Executables kompiliert werden: ``` -# "riscv32-unknown-elf" ist das präfix, und "as" der befehl für den Assembler: +# "riscv32-unknown-elf" ist das Präfix, und Folgendes der Befehl für den Assembler: > riscv32-unknown-elf-as hello-world.asm -o hello-world.out -# gleiches präfix, hier benutzen wir "objdump" um den compilierten Inhalt zu decodieren: +# Gleiches Präfix, hier benutzen wir objdump um den Inhalt zu decodieren: > riscv32-unknown-elf-objdump -SF hello-world.out hello-world.out: file format elf32-littleriscv @@ -135,3 +137,5 @@ Disassembly of section .text: 1c: 05d00893 li a7,93 20: 00000073 ecall ``` + +Dies wird jedoch erst im weiteren Verlauf der Vorlesung wirklich wichtig werden. Zunächst werden wir mit Klartext Assembly arbeiten. diff --git a/debugging.md b/debugging.md index afda757..52355a9 100644 --- a/debugging.md +++ b/debugging.md @@ -1,32 +1,32 @@ # Debugging mit RiscEmu -Der Debugger des Emulators kann mit dem `ebreak` Breakpint-Befehl gestartet werden. +Der Debugger des Emulators kann mit dem `ebreak` Breakpoint-Befehl gestartet werden. ## Verfügbare Objekte und Funktionen In dem interaktiven Debugger sind folgende Variablen definiert: - * `cpu` Der CPU der den `ebreak` gelesen hat + * `cpu` Die CPU, die den `ebreak` gelesen hat * `mem` und `mmu` ermöglichen Zugriff auf den Arbeisspeicher - * `regs` representiert die Register des CPUs + * `regs` repräsentiert die Register der CPU -Des weiteren sind ein paar hilfsfunktionen verfügbar: +Des weiteren sind ein paar Hilfsfunktionen verfügbar: - * `run_ins('name', 'arg1', 'arg2', 'arg3')` führt den befehl `name arg1, arg2, arg3` an der aktuellen Stelle im CPU aus. - * `step()` führt den nächte Befehl aus - * `cont()` beendet den debugger - * `dump(address)` gibt den Inhalt des Arbeitsspeichers an der Adresse `address` aus, das Verhalten der Funktion ist durch einige Parameter anpassbar, die später weiter erklärt werden. + * `run_ins('name', 'arg1', 'arg2', 'arg3')` führt den Befehl `name arg1, arg2, arg3` an der aktuellen Stelle im Programm aus. + * `step()` führt den nächsten Befehl aus + * `cont()` beendet den Debugger + * `dump(address)` gibt den Inhalt des Arbeitsspeichers an der Adresse `address` aus. Das Verhalten der Funktion ist durch einige Parameter anpassbar, die später weiter erklärt werden. ## Die `dump()` Funktion -Mit hilfe dieser Funktion kann der Arbeitsspeicher angezeigt werden. Die Signator der Funktion ist etwas komplexer: +Mit hilfe dieser Funktion kann der Inhalt des Arbeitsspeichers angezeigt werden. Die Signatur der Funktion ist etwas komplexer: `dump(start, [end], [fmt], [bytes_per_row], [rows], [group], [highlight])` -Es ist möglich einen festgelegten bereich an zu zeigen, in dem `start` und `end` angegeben werden. Es ist auch möglich nur `start` zu verwenden, dann werden `rows` (standardmäßig 10) zeilen um die adresse `start` herum ausgegeben, und die Werte an der Adresse hervorgehoben. Eine andere Stelle zum hervorheben kann mit `highlight` bestimmt werden. +Es ist möglich einen festgelegten Bereich anzuzeigen, indem `start` und `end` angegeben werden. Es ist auch möglich nur `start` zu verwenden, dann werden `rows` (standardmäßig 10) Zeilen um die Adresse `start` herum ausgegeben, und die Werte an der Adresse hervorgehoben. Eine andere Stelle zum Hervorheben kann mit `highlight` bestimmt werden. -Mit `bytes_per_row` kann angegeben werden, wie viele bytes pro zeile ausgegeben werden, und `group` gibt an, wie viele bytes zusammen zu einem Wert gruppiert werden (z.B. praktisch um 32bit Inteegers an zu schauen). +Mit `bytes_per_row` kann angegeben werden, wie viele Bytes pro Zeile ausgegeben werden, und `group` gibt an, wie viele Bytes zusammen zu einem Wert gruppiert werden (z.B. praktisch um 32bit Integers anzuschauen). -Das Ausgabeformat kann mit dem `fmt` Argument angegeben werden, standardmäßig ist das `hex`, andere möglichkeiten sind `int`, `uint` für Ganzzahlen und `char` für Ascii-Text. +Das Ausgabeformat kann mit dem `fmt` Argument angegeben werden, standardmäßig ist das `hex`. Andere Möglichkeiten sind `int`, `uint` für positive Ganzzahlen und `char` für ASCII-Text.