Skip to content

Teufelchen1/TRIOPS

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

The TRIOPS logo. Showing a hand-drawn triops, brown colored with black lining (or white lining in dark mode).

Clippy & co


TRIOPS

A RISC-V emulator written in Rust. 🦀

The TRIOPS logo. Showing a hand-drawn triops, brown colored with black lining (or white lining in dark mode).

Triops is a genus of small crustaceans. They have three eyes 👀, live up to 90 days and their eggs can stay dormant for years.

Features

  • RV32IMAC ISA - Implementing Multiplication, Compressed Instructions and Atomics extension.
  • Loads ELF and BIN files.
  • Comes with an easy to use and pretty looking TUI - which is powered by 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 the two UARTs - emulating the peripheral of the Hifive1b.
  • Can map both UARTs to any unixsocket of your choice!
  • Can also run without the TUI, attaching the UART0 directly to stdio!
  • Run 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, which TRIOPS aims for.

Limitations

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. Most peripherals are not yet implemented. Most noteworthy the timer (wip). The hardware emulation of the Hifive1b 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-unknown-elf-gcc and riscv64-unknown-elf-objcopy. (For MacOS users I recommend: brew install riscv-software-src/riscv/riscv-gnu-toolchain)

For the RIOT example please refer to the RIOT documentation and the Getting Started guide.

Usage

Ready the emulator:

  1. Clone the repository and cd into it.
  2. Build it: cargo build
  3. Test it: cargo run -- --help
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
  3. Results in test.elf and test.bin

Run the emulator:

  1. cd .. back into the root directory.
  2. cargo run -- test_app/test.elf

hello_world.mp4

Goal

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 for drawing this awesome logo.
  • EdJoPaTo for so much Rust feedback.
  • Kosmas12 for implementing the Multiplication extension.
  • Chrysn for responding to every single Rust-cry that I tooted on Mastodon.

Bonus exercise: Using Jelly with TRIOPS

You can easily use Jelly with TRIOPS.

  1. Build RIOT for Hifive1b with slipdev and slipdev_stdio enabled (optional: slipdev_config)
  2. Start the emulator, preferred in headless mode with --headless, mapping the first uart to a socket --uart0 uart0socket
  3. Run Jelly and attach it to the unixsocket: jelly /path/to/uart0socket
  4. Done! Enjoy slipmux!

Exercise left for the curious: You can also configure RIOT to use slipdev on both uarts! And since TRIOPS can map both uarts to unixsockets, you can attach two Jellys to the same RIOT simultaneously. Why would you do that? Well, Jelly can open a tun network interface and pass packets to RIOT.

Easy: Can you ping RIOT via both tun interfaces? Pro: Can you make it so that a ping passes into RIOT via the first tun interface, is forwarded by RIOT and reaches your host again via the second tun?

About

A RISC-V emulator written in Rust

Resources

Stars

Watchers

Forks

Contributors 2

  •  
  •  

Languages