Rust library for emulating RISC-V rv32imac

Overview

lib-rv32

Rust library for emulating 32-bit RISC-V

build tests

Documentation on docs.rs

Packaged on crates.io


Libray

This library can execute instructions against any memory and register file that implements the required primitives in the traits lib_rv32::traits::{Memory, RegisterFile}. This is to encourage usage with whatever frontend you desire.

However, reference implementations are provided in lib_rv32::mcu. The library provides functions to read from the memory, registers, and step a single instruction. Since, the user decides when to call these functions, these will probably fit most use-cases.

Example

my_app.rs:

use std::path::Path;

use lib_rv32::mcu::*;
use lib_rv32::exec_one;

fn main() {
    let mut mcu: Mcu = Mcu::new(1024 * 64);

    mcu.mem
        .program_from_file(&Path::from("./prog.bin"))
        .expect("Could not program MCU.");

    loop {
        exec_one(&mut mcu.pc, &mut mcu.mem, &mut mcu.rf).unwrap();
    }
}

CLI

Usage

The CLI is one example of how the core library can be used in an application. The primary use of the CLI is tracing execution of RISC-V programs and making assertions about their behavior. It currently only supports simple binary memory images (not ELF binaries).

USAGE:
    lrv-cli [FLAGS] [OPTIONS] 

FLAGS:
    -h, --help       Prints help information
    -V, --version    Prints version information
    -v, --verbose    Enable verbose logging

OPTIONS:
    -a, --assertions     A JSON formatted set of assertions.
    -m, --mem              Set the size of the MCU memory (default 64 KB).
    -s, --stop              Set the program counter at which to stop emulation.

ARGS:
        RISC-V binary to execute

Example

Enter assertions into a JSON file (note: all numbers are strings to allow for hex or decimal radices).

assert.json:

{
    "registers": {
        "x0": "0x0",
        "a0": "20"
    },
    "memory": {
        "0x0000": "0x00010117"
    }
}

Then run:

lrv-cli -v ./prog.bin -s 24 -a assert.json

This will execute prog.bin, stop at the PC value 0x24, and then make the assertions from assert.json.

The program will trace the execution instruction-by-instruction:

[0000]  00010117  |  auipc  sp, 0x10           |  sp <- 0x10000 (65536);
[0004]  fe010113  |  addi   sp, sp, -32        |  sp <- 0xffe0 (65504);
[0008]  00400513  |  addi   a0, zero, 4        |  a0 <- 0x4 (4);
[000c]  00500593  |  addi   a1, zero, 5        |  a1 <- 0x5 (5);
[0010]  00000097  |  auipc  ra, 0x0            |  ra <- 0x10 (16);
[0014]  018080e7  |  jalr   ra, (24)ra         |  ra <- 0x18 (24); pc <- 0x28;
...

When complete, it will summarize results:

...
[001c]  f0028293  |  addi   t0, t0, -256       |  t0 <- 0xf00 (3840);
[0020]  00a2a023  |  sw     a0, 0(t0)          |  (word *)0x00000f00 <- 0x14 (20);

Reached stop-PC.

a0 == 20
*0x00000000 == 65815

Testing

This project has a very flexible testing system.

Unit-tests are provided wherever appropriate.

Additionally, to test the whole system, test programs can be added to tests/programs. A test is simply a directory containing .c and .s source files and a test_case.json consisting of assertions about the state of the MCU after the program is complete.

During testing, Cargo will for each test:

  1. Compile it for RISC-V
  2. Spin up a new MCU
  3. Program it with the generated binary
  4. Run the test program for some number of cycles
  5. Make assertions
  6. Report succes or failure

If a test fails, it will describe the error that caused the crash or the assertion that failed and print an object dump of the compiled test binary:

...
[001c]  f0028293  |  addi   t0, t0, -256       |  t0 <- 0xf00 (3840);
[0020]  00a2a023  |  sw     a0, 0(t0)          |  (word *)0x00000f00 <- 0x14 (20);
Stopping because the stop PC 0x24 was reached.


Failed test: tests/programs/mul@0x00000024: Register assertion failed: (x10=0x00000014) != 0x00000018.

prog.elf:     file format elf32-littleriscv


Disassembly of section .text.init:

00000000 :
   0:   00010117                auipc   sp,0x10
   4:   fe010113                addi    sp,sp,-32 # ffe0 <__global_pointer$+0xf75c>
   8:   00400513                li      a0,4
   c:   00500593                li      a1,5
...

Tests are run in CI, but can be run locally provided your system has riscv(32|64)-unknown-elf-gcc.

TODO

  • Base/integer ISA (i)
    • Basic support
    • CSR/interrupt instructions
  • Multiply (m)
  • Atomics (a)
  • Compressed (c)
  • Support ELF binaries
You might also like...
An asynchronous Rust client library for the Hashicorp Vault API

vaultrs An asynchronous Rust client library for the Hashicorp Vault API The following features are currently supported: Auth AppRole JWT/OIDC Token Us

Culture ship names in a rust library.

General Systems Vehicles Culture Ships In case you ever needed Iain M. Banks's Culture ship names as a service. Names sourced from the pleasingly exte

Modrinth API is a simple library for using, you guessed it, the Modrinth API in Rust projects

Modrinth API is a simple library for using, you guessed it, the Modrinth API in Rust projects. It uses reqwest as its HTTP(S) client and deserialises responses to typed structs using serde.

Wrapper library for utilizing DigitalOcean API v2 in Rust

doapi-rs Wrapper library for utilizing DigitalOcean API v2 in Rust Disclaimer This library is in alpha - it may do anything up to, and including, eati

Rust LZ4 bindins library

lz4 This repository contains binding for lz4 compression library (https://github.com/Cyan4973/lz4). LZ4 is a very fast lossless compression algorithm,

Noto-sans-mono-bitmap (Rust library)
Noto-sans-mono-bitmap (Rust library)

noto-sans-mono-bitmap (Rust library) Pre-rasterized bitmap font from "Noto Sans Mono", an open font from Google. Original font files taken from: https

Serenity is a Rust library for the Discord API
Serenity is a Rust library for the Discord API

serenity Serenity is a Rust library for the Discord API. View the examples on how to make and structure a bot. Serenity supports bot login via the use

Deser: an experimental serialization and deserialization library for Rust

deser: an experimental serialization and deserialization library for Rust Deser is an experimental serialization system for Rust. It wants to explore

An (unofficial) Rust library for querying db-ip.com data

db_ip An (unofficial) library for querying db-ip.com CSV databases in safe Rust. This library is not affiliated with or endorsed by db-ip.com. Be advi

Comments
  • Fix assembling programs with labels that reference forward points of the program

    Fix assembling programs with labels that reference forward points of the program

    Forward labels will now be parsed correctly. Two passes are made when assembling: first parse the labels into a hash-map, second assemble the program replacing labels with immediates.

    opened by trmckay 0
  • ref: Refactor source-base into multiple crates

    ref: Refactor source-base into multiple crates

    This aims to split the project into four main components:

    • A common library of constants and utilities
    • An ISA simulator
    • An assembler
    • A CLI application

    The added modularity should allow for users to pick and choose the pieces they need. A secondary goal of this refactor is set the groundwork for porting to WASM by quarantining the pieces for which this will be impossible.

    TODO

    • [x] Initial refactor
    • [x] Pass unit tests
    • [x] Pull up integration tests
    • [x] Clean up code
    • [x] Update README
    • [x] Update docs
    opened by trmckay 0
  •  new: Add experimental built-in assembler

    new: Add experimental built-in assembler

    This assembler should take a single instructions or a reader object and assemble it down to a vector of u32s. It should support the base instructions with offset formatting and labels.

    opened by trmckay 0
  • new: Add basic functionality for a built-in assembler

    new: Add basic functionality for a built-in assembler

    This assembler should take a single instructions or a reader object and assemble it down to a vector of u32s. It should support the base instructions with offset formatting and labels.

    opened by trmckay 0
Releases(v0.2.0)
Owner
Trevor McKay
Cal Poly, SLO - Computer Engineering | RISC-V, Linux, math, systems programming
Trevor McKay
RISC-V instruction decoder written in Rust.

raki RISC-V instruction decoder written in Rust. Both 32/64bit support. Support rv32/64imac, Zicsr, Zifencei extensions. Implement Display trait for f

Norimasa Takana 5 Oct 18, 2023
A highly modular Bitcoin Lightning library written in Rust. Its Rust-Lightning, not Rusty's Lightning!

Rust-Lightning is a Bitcoin Lightning library written in Rust. The main crate, lightning, does not handle networking, persistence, or any other I/O. Thus, it is runtime-agnostic, but users must implement basic networking logic, chain interactions, and disk storage. More information is available in the About section.

Lightning Dev Kit 850 Jan 3, 2023
Rust library that can be reset if you think it's slow

GoodbyeKT Rust library that can be reset if you think it's slow

null 39 Jun 16, 2022
Notion Offical API client library for rust

Notion API client library for rust.

Jake Swenson 65 Dec 26, 2022
Rust library for program synthesis of string transformations from input-output examples 🔮

Synox implements program synthesis of string transformations from input-output examples. Perhaps the most well-known use of string program synthesis in end-user programs is the Flash Fill feature in Excel. These string transformations are learned from input-output examples.

Anish Athalye 21 Apr 27, 2022
SE3 Rust library for Robotics

Algebraic Robots A small Rust Library for SE3 Supported: Twist Screw SE3 Group se3 algebra Adjoint SE3 Twist Chains Wrenches Future plans: Jacobians V

Pau Carré Cardona 4 Jul 18, 2021
Yet another ROS2 client library written in Rust

RclRust Target CI Status Document Foxy (Ubuntu 20.04) Introduction This is yet another ROS2 client library written in Rust. I have implemented it inde

rclrust 42 Dec 1, 2022
A boiler plate code to create dynamic link library in rust.

?? rust-dll-bp This is a boiler plate code that will be generated as a dll binary. I personally cache this here for me but if you're intend to create

s3pt3mb3r 9 Nov 7, 2022
Rust telegram bot library for many runtimes

Telbot Telbot provides telegram bot types and api wrappers. Specifically, telbot now supports: telbot-types: basic telegram types / requests / respons

kiwiyou 17 Dec 3, 2022
Strongly typed Gura library for Rust

Serde Gura This crate is a Rust library for using the Serde serialization framework with data in Gura file format. This library does not re-implement

Gura Config Lang 12 Nov 14, 2022