initial commit
commit
fdaf29f235
@ -0,0 +1 @@
|
|||||||
|
venv
|
@ -0,0 +1,3 @@
|
|||||||
|
[submodule "EMBARK"]
|
||||||
|
path = EMBARK
|
||||||
|
url = https://github.com/AntonLydike/EMBARK
|
@ -0,0 +1 @@
|
|||||||
|
Subproject commit a3cc3cccbd1c804f3240f1adf6b2249dde9dab81
|
@ -0,0 +1,134 @@
|
|||||||
|
# RISC-V Playground
|
||||||
|
|
||||||
|
Willkommen in dem RISC-V Playground!
|
||||||
|
|
||||||
|
|
||||||
|
## Installation
|
||||||
|
|
||||||
|
*Dieser Schritt ist in der gelieferten VM bereits abgeschlossen*
|
||||||
|
|
||||||
|
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.*
|
||||||
|
|
||||||
|
Betrachten wir das beispiel: `hello-world.asm`
|
||||||
|
|
||||||
|
```
|
||||||
|
# hello-world.asm
|
||||||
|
# print "hello world" to stdout and exit
|
||||||
|
.data
|
||||||
|
|
||||||
|
text: .asci "Hello World\n"
|
||||||
|
|
||||||
|
.text
|
||||||
|
li a0, 1
|
||||||
|
la a1, text
|
||||||
|
li a2, 12
|
||||||
|
li a7, 64
|
||||||
|
ecall
|
||||||
|
|
||||||
|
li a0, 0
|
||||||
|
li a7, 93
|
||||||
|
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:
|
||||||
|
|
||||||
|
```
|
||||||
|
> python3 -m riscemu hello-world.asm
|
||||||
|
Hello World
|
||||||
|
```
|
||||||
|
|
||||||
|
Der emulator kann mit verschiedenen Parametern gestartet werden, z.B. kann mit `-v` die `verbosity` (die menge an Informationen die ausgegeben werden) erhöht werden. Das wiederholen der "v"s erhöht das level weiter. So wird z.B. mit dem ersten `-v` bei jedem Sprung das Sprungziel ausgegeben sowie mehr informationen über den Start und Stopp. Ab `-vv` wird jeder ausgeführte assembly Befehl ausgegeben:
|
||||||
|
|
||||||
|
```
|
||||||
|
> python3 -m riscemu -vv hello-world.asm
|
||||||
|
Running 0x00000110: li a0, 1
|
||||||
|
Running 0x00000114: la a1, text
|
||||||
|
Running 0x00000118: li a2, 12
|
||||||
|
Running 0x0000011C: li a7, 64
|
||||||
|
Running 0x00000120: ecall
|
||||||
|
Hello World
|
||||||
|
Running 0x00000124: li a0, 0
|
||||||
|
Running 0x00000128: li a7, 93
|
||||||
|
Running 0x0000012C: ecall
|
||||||
|
[CPU] Program exited with code 0
|
||||||
|
```
|
||||||
|
|
||||||
|
## 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:
|
||||||
|
|
||||||
|
|
||||||
|
```
|
||||||
|
# ...
|
||||||
|
.text
|
||||||
|
li a0, 1
|
||||||
|
la a1, text
|
||||||
|
li a2, 12
|
||||||
|
li a7, 64
|
||||||
|
ecall
|
||||||
|
ebreak # Breakpoint um den Debugger zu starten
|
||||||
|
|
||||||
|
li a0, 0
|
||||||
|
li a7, 93
|
||||||
|
ecall
|
||||||
|
```
|
||||||
|
|
||||||
|
Wenn das Programm nun ausgeführt wird, erscheint das folgende Output generiert:
|
||||||
|
|
||||||
|
```
|
||||||
|
Hello World
|
||||||
|
Debug instruction encountered at 0x00000127
|
||||||
|
[CPU] Debugger launch requested!
|
||||||
|
|
||||||
|
>>>
|
||||||
|
````
|
||||||
|
|
||||||
|
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.
|
||||||
|
|
||||||
|
|
||||||
|
## 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)
|
||||||
|
|
||||||
|
Falls das Skript für eure Platform nicht funktioniert, hier noch ein paar tips:
|
||||||
|
|
||||||
|
|
||||||
|
- 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.
|
||||||
|
- 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 <anzahl der threads eures CPU>`.
|
||||||
|
|
||||||
|
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:
|
||||||
|
|
||||||
|
```
|
||||||
|
# "riscv32-unknown-elf" ist das präfix, und as 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 Inhalt zu decodieren:
|
||||||
|
> riscv32-unknown-elf-objdump -SF hello-world.out
|
||||||
|
|
||||||
|
hello-world.out: file format elf32-littleriscv
|
||||||
|
|
||||||
|
|
||||||
|
Disassembly of section .text:
|
||||||
|
|
||||||
|
00000000 <.text> (File Offset: 0x34):
|
||||||
|
0: 00100513 li a0,1
|
||||||
|
4: 00000597 auipc a1,0x0
|
||||||
|
8: 00058593 mv a1,a1
|
||||||
|
c: 00c00613 li a2,12
|
||||||
|
10: 04000893 li a7,64
|
||||||
|
14: 00000073 ecall
|
||||||
|
18: 00000513 li a0,0
|
||||||
|
1c: 05d00893 li a7,93
|
||||||
|
20: 00000073 ecall
|
||||||
|
```
|
@ -0,0 +1,32 @@
|
|||||||
|
# Debugging mit RiscEmu
|
||||||
|
|
||||||
|
Der Debugger des Emulators kann mit dem `ebreak` Breakpint-Befehl gestartet werden.
|
||||||
|
|
||||||
|
## Verfügbare Objekte und Funktionen
|
||||||
|
|
||||||
|
In dem interaktiven Debugger sind folgende Variablen definiert:
|
||||||
|
|
||||||
|
* `cpu` Der CPU der den `ebreak` gelesen hat
|
||||||
|
* `mem` und `mmu` ermöglichen Zugriff auf den Arbeisspeicher
|
||||||
|
* `regs` representiert die Register des CPUs
|
||||||
|
|
||||||
|
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.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
## Die `dump()` Funktion
|
||||||
|
|
||||||
|
Mit hilfe dieser Funktion kann der Arbeitsspeicher angezeigt werden. Die Signator 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.
|
||||||
|
|
||||||
|
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).
|
||||||
|
|
||||||
|
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.
|
@ -0,0 +1,18 @@
|
|||||||
|
# hello-world.asm
|
||||||
|
# print "hello world" to stdout and exit
|
||||||
|
.data
|
||||||
|
|
||||||
|
text: .ascii "Hello World\n"
|
||||||
|
|
||||||
|
.text
|
||||||
|
li a0, 1
|
||||||
|
la a1, text
|
||||||
|
li a2, 12
|
||||||
|
li a7, 64
|
||||||
|
ecall
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
li a0, 0
|
||||||
|
li a7, 93
|
||||||
|
ecall
|
@ -0,0 +1,41 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
# this script installs https://github.com/riscv-collab/riscv-gnu-toolchain
|
||||||
|
|
||||||
|
set -eu
|
||||||
|
|
||||||
|
if ! command -v apt &> /dev/null
|
||||||
|
then
|
||||||
|
echo "This script was written for Debian based Linux Systems. It seems like \
|
||||||
|
you are using something else. Please change this script to work with your OS."
|
||||||
|
echo "You can find further infos at https://github.com/riscv-collab/riscv-gnu-toolchain"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
function print_step {
|
||||||
|
echo "==========="
|
||||||
|
echo -e ">>> \033[0;36m $@\033[0m"
|
||||||
|
echo "==========="
|
||||||
|
}
|
||||||
|
|
||||||
|
if test -d riscv-gnu-toolchain; then
|
||||||
|
echo "Skipping steps 1..3"
|
||||||
|
cd riscv-gnu-toolchain
|
||||||
|
else
|
||||||
|
|
||||||
|
print_step "[1] Installing dependencies"
|
||||||
|
sudo apt-get install -y autoconf automake autotools-dev curl python3 libmpc-dev libmpfr-dev libgmp-dev gawk build-essential bison flex texinfo gperf libtool patchutils bc zlib1g-dev libexpat-dev git
|
||||||
|
|
||||||
|
|
||||||
|
print_step "[2] Cloning repository"
|
||||||
|
|
||||||
|
git clone --depth 1 https://github.com/riscv-collab/riscv-gnu-toolchain
|
||||||
|
|
||||||
|
print_step "[3] Configuring build"
|
||||||
|
cd riscv-gnu-toolchain
|
||||||
|
./configure --prefix=$(pwd)/../toolchain/ --with-arch=rv32ima --disable-linux --disable-gdb --disable-multilib
|
||||||
|
fi
|
||||||
|
|
||||||
|
print_step "[4] Compiling"
|
||||||
|
echo "This might take up to an hour! Be patient!"
|
||||||
|
# call make with as many threads as the system has available
|
||||||
|
make -j $(grep -c ^processor /proc/cpuinfo)
|
@ -0,0 +1,21 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
# this script sets up a python virtual environment
|
||||||
|
|
||||||
|
if ! command -v apt &> /dev/null
|
||||||
|
then
|
||||||
|
echo "This script was written for Debian based Linux Systems. It seems like \
|
||||||
|
you are using something else. Please change these scripts to work with your OS."
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
|
||||||
|
sudo apt install -y python3 python3-venv python3-pip
|
||||||
|
|
||||||
|
if [ ! -d venv ]; then
|
||||||
|
python3 -m venv venv
|
||||||
|
fi
|
||||||
|
|
||||||
|
source venv/bin/activate
|
||||||
|
|
||||||
|
pip install --upgrade riscemu
|
||||||
|
|
Loading…
Reference in New Issue