Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "triops"
version = "0.1.0"
version = "0.2.0"
edition = "2021"

[dependencies]
Expand Down
91 changes: 63 additions & 28 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,24 +22,81 @@ Triops is a genus of small c**rust**aceans. They have three eyes 👀, live up t
* Comes with an easy to use and pretty looking TUI - which is powered by [Ratatui](https://github.com/ratatui/ratatui).
* Single step or autostep through the executable.
* A minimal, simple and bare metal C project is in `test_app/` included. Build it, run it in the emulator, tinker with it and repeat!
* Interact with the running executable via an UART - emulating the peripheral of the [Hifive1b](https://www.sifive.com/boards/hifive1-rev-b).
* Can also run without the TUI, attaching the UART directly to stdio.
* Interact with the running executable via the two UARTs - emulating the peripheral of the [Hifive1b](https://www.sifive.com/boards/hifive1-rev-b).
* Can map both UARTs to any unixsocket of your choice!
* Can also run without the TUI, attaching the UART0 directly to stdio!
* Run [RIOT](https://github.com/RIOT-OS/RIOT) in TRIOPS using the included example app in `RIOT_app/`! RIOT, "the friendly Operating System for IoT", is a good example application to test for the correct behavior of TRIOPS. As an open-source microcontroller operating system, RIOT supports a huge amount of CPU architectures and development boards. Among those is the RISC-V based [Hifive1b](https://www.sifive.com/boards/hifive1-rev-b), which TRIOPS aims for.

### Limitations

There is currently no PLIC/CLIC and no interrupts. Control and status register (csr) are without effect.
There is currently no PLIC/CLIC but there is a limited interrupt support for the most essential stuff. Control and status register (csr) are without effect.
The hardware emulation of the [Hifive1b](https://www.sifive.com/boards/hifive1-rev-b) is not hardware accurate and not intended to be so.

## Requierments
On the Rust side, handled by cargo: `clap`, `anyhow`, `ratatui`, `crossterm`, `elf`.

For the `test_app`, which is in C: `riscv64-elf-gcc` and `riscv64-elf-objcopy`.
For the `test_app`, which is in C: `riscv64-unknown-elf-gcc` and `riscv64-unknown-elf-objcopy`.

For the RIOT example please refer to the RIOT documentation and the [Getting Started](https://guide.riot-os.org/getting-started/installing/) guide.

## Usage
#### Ready the emulator:
1. Clone the repository and `cd` into it.
2. Build it: `cargo build`
3. Test it: `cargo run -- --help`

```txt
Usage: triops [OPTIONS] <FILE>

Arguments:
<FILE>
Path to the file that should be executed in the emulator

Options:
--headless
If set, no TUI is started.

TRIOPS will run as fast as your machine allows.
The UART will be mapped to stdio unless a unix socket is specified, see `uart-socket`.

--uart0 <UART0>
If set, connects UART0 TX/RX to the specified unix socket.
If not set, the UART0 will be mapped to stdio.

--uart1 <UART1>
If set, connects UART1 TX/RX to the specified unix socket.
If not set, the UART1 will not be accessible.

--testing
If set, the emulation result will be checked.

TRIOPS will probe the registers according to the riscv-software-src/riscv-tests.
Their contents determine the return value. The checks are done after the emulation completed.
Mainly used for CI.

--bin
If set, the provided file is treated as pure binary

When used, the entry address and base address can also be set.

--entryaddress <ENTRYADDRESS>
The entry address, where execution is started / PC is set to.

Can be in hex or decimal.

[default: 0x20000000]

--baseaddress <BASEADDRESS>
The base address, where the bin file is loaded to. Must be in RAM or ROM.

Can be in hex or decimal.

[default: 0x20000000]

-h, --help
Print help (see a summary with '-h')
```

#### Ready a RISC-V elf binary:
1. Enter the test application: `cd test_app/`
2. Build it: `./build.sh`
Expand All @@ -55,33 +112,11 @@ For the `test_app`, which is in C: `riscv64-elf-gcc` and `riscv64-elf-objcopy`.

## Goal

The purpose of this emulator is to teach me Rust and further deepen my love to RISC-V.
The purpose of this emulator is to teach me Rust and having fun with RISC-V. Recently it also became an aid in my job as a RIOT maintainer. Turns out, having a custom emulator is really useful when tracing bugs in an embedded operating system.

## Thanks

* [Einhornwolle](https://github.com/einhornwolle) for drawing this awesome logo.
* [EdJoPaTo](https://github.com/edjopato) for so much Rust feedback.
* [Kosmas12](https://github.com/kosmas12) for implementing the Multiplication extension.
* [Chrysn](https://github.com/chrysn) for responding to every single Rust-cry, I tooted on Mastodon.

## Bonus: Running RIOT OS within TRIOPS

[RIOT](https://github.com/RIOT-OS/RIOT), "the friendly Operating System for IoT", is a good example application to test for the correct behavior of TRIOPS. As an open-source microcontroller operating system, RIOT supports a huge amount of CPU architectures and development boards. Among those is the RISC-V based [Hifive1b](https://www.sifive.com/boards/hifive1-rev-b).

1. Clone RIOT into a folder of your choice: `git clone git@github.com:RIOT-OS/RIOT.git`
2. Go into `cd RIOT/examples/hello-world`
3. Compile for the Hifive1b: `BOARD=hifive1b make all`
4. After successfull compilation, RIOT will tell you where the resulting ELF file is stored, e.g. `/tmp/RIOT/examples/hello-world/bin/hifive1b/hello-world.elf`
5. Run TRIOPS with that file as input. For best results, disable the TUI to increase the execution speed:
`cargo run -- --headless /tmp/RIOT/examples/hello-world/bin/hifive1b/hello-world.elf`
6. It should look like this:
```
Finished `dev` profile [unoptimized + debuginfo] target(s) in 0.06s
Running `target/debug/rv --headless /tmp/RIOT/examples/hello-world/bin/hifive1b/hello-world.elf`
main(): This is RIOT! (Version: 2025.01-devel-335-ga8b47)
Hello World!
You are running RIOT on a(n) hifive1b board.
This board features a(n) fe310 CPU.
```

Please note that the hello-world performs no further actions and the execution will halt. Additionally, whenever RIOT has nothing todo, it emits the `WFI` (wait for interrupt) instruction. This instruction is currently not supported by TRIOPS - unlike other unsupported instructions, which `panic!()` TRIOPS, `WFI` just hangs. This is a temporal fix to reduce the pain when playing around with RIOT.
* [Chrysn](https://github.com/chrysn) for responding to every single Rust-cry that I tooted on Mastodon.