Convert Figma logo to code with AI

riscv-software-src logoriscv-isa-sim

Spike, a RISC-V ISA Simulator

2,357
823
2,357
303

Top Related Projects

GNU toolchain for RISC-V, including GCC

RISC-V Tools (ISA Simulator and Tests)

RISC-V Instruction Set Manual

SonicBOOM: The Berkeley Out-of-Order Machine

1,331

Ibex is a small 32 bit RISC-V CPU core, previously known as zero-riscy.

Quick Overview

The riscv-software-src/riscv-isa-sim repository contains Spike, the official RISC-V ISA simulator. It serves as a golden reference model for RISC-V implementations and is widely used for software development, testing, and verification in the RISC-V ecosystem. Spike supports various RISC-V extensions and can be used as a functional simulator or integrated into other tools.

Pros

  • Officially supported and maintained by the RISC-V Foundation
  • Highly accurate and up-to-date with the latest RISC-V specifications
  • Supports a wide range of RISC-V extensions and configurations
  • Can be used as a standalone simulator or integrated into other tools

Cons

  • Performance may be slower compared to some other RISC-V simulators
  • Limited debugging capabilities compared to full-featured debuggers
  • May require additional setup for certain use cases (e.g., running full operating systems)
  • Learning curve for users unfamiliar with RISC-V ISA or simulator usage

Code Examples

  1. Running a simple RISC-V program:
spike pk hello_world

This command runs the "hello_world" program using Spike and the proxy kernel (pk).

  1. Debugging with Spike:
spike -d pk hello_world

This command starts Spike in debug mode, allowing step-by-step execution and examination of registers and memory.

  1. Using Spike as a library in C++:
#include "riscv/sim.h"
#include "riscv/processor.h"

int main() {
    sim_t sim(1, false);
    processor_t *proc = sim.get_core(0);
    
    // Load a program
    sim.load_elf("path/to/program.elf");
    
    // Run the simulation
    sim.run();
    
    return 0;
}

This example demonstrates how to use Spike as a library in a C++ program, creating a simulator instance and running a RISC-V program.

Getting Started

To get started with Spike:

  1. Clone the repository:

    git clone https://github.com/riscv-software-src/riscv-isa-sim.git
    cd riscv-isa-sim
    
  2. Build Spike:

    mkdir build
    cd build
    ../configure --prefix=$RISCV
    make
    make install
    
  3. Run a RISC-V program:

    spike pk path/to/your/riscv/program
    

Make sure you have the RISC-V toolchain installed and the $RISCV environment variable set to the toolchain installation directory.

Competitor Comparisons

GNU toolchain for RISC-V, including GCC

Pros of riscv-gnu-toolchain

  • Provides a complete toolchain for RISC-V development, including GCC, binutils, and GDB
  • Supports cross-compilation for various RISC-V targets
  • Regularly updated with the latest upstream changes from GNU projects

Cons of riscv-gnu-toolchain

  • Larger and more complex to build and maintain
  • May have a steeper learning curve for users new to toolchain development
  • Requires more system resources to build and run

Code Comparison

riscv-gnu-toolchain (Makefile):

build-binutils-newlib:
	$(MAKE) -C build-binutils-newlib
	$(MAKE) -C build-binutils-newlib install

riscv-isa-sim (riscv/insns/add.h):

require_extension('I');
WRITE_RD(sext_xlen(RS1 + RS2));

The riscv-gnu-toolchain repository focuses on building and installing the complete toolchain, while riscv-isa-sim (Spike) implements individual RISC-V instructions and provides a simulation environment.

riscv-gnu-toolchain is better suited for developers who need a full RISC-V development environment, while riscv-isa-sim is ideal for those focusing on instruction-level simulation and testing of RISC-V programs.

RISC-V Tools (ISA Simulator and Tests)

Pros of riscv-tools

  • Comprehensive toolchain collection for RISC-V development
  • Includes various tools like GCC, Binutils, and Newlib
  • Provides a complete ecosystem for RISC-V software development

Cons of riscv-tools

  • Larger repository size due to multiple components
  • Potentially more complex setup and maintenance
  • May include tools not needed for all use cases

Code Comparison

riscv-isa-sim (Spike):

void processor_t::set_pc(reg_t pc)
{
  state.pc = pc & ~(reg_t)1;
}

riscv-tools (example from riscv-gnu-toolchain):

#define LOAD_STORE(op, func, type)                 \
  extern type __atomic_##func##_##op(type *ptr,    \
                                     type val,     \
                                     int memorder);

Summary

riscv-isa-sim (Spike) is a RISC-V ISA simulator, while riscv-tools is a collection of various RISC-V development tools. Spike focuses on instruction set simulation, whereas riscv-tools provides a broader set of utilities for RISC-V software development. The choice between them depends on specific project requirements and development needs.

RISC-V Instruction Set Manual

Pros of riscv-isa-manual

  • Comprehensive documentation of the RISC-V instruction set architecture
  • Regularly updated to reflect the latest RISC-V specifications
  • Serves as the authoritative reference for RISC-V implementations

Cons of riscv-isa-manual

  • Lacks practical implementation examples
  • May be more challenging for beginners to understand without accompanying code
  • Does not provide a simulation environment for testing RISC-V instructions

Code Comparison

riscv-isa-manual (LaTeX example):

\chapter{RV32I Base Integer Instruction Set, Version 2.1}
\label{rv32}

This chapter describes the RV32I base integer instruction set.

riscv-isa-sim (C++ example):

void processor_t::step(size_t n)
{
  for (size_t i = 0; i < n; i++)
    step(1);
  update_histogram(n);
}

The riscv-isa-manual repository contains LaTeX source for the RISC-V specification, while riscv-isa-sim provides C++ code for a RISC-V simulator. The manual focuses on describing the architecture, whereas the simulator implements the behavior of RISC-V instructions.

SonicBOOM: The Berkeley Out-of-Order Machine

Pros of riscv-boom

  • Implements a high-performance, out-of-order RISC-V core
  • Designed for scalability and customization
  • Provides a more realistic representation of modern processor architectures

Cons of riscv-boom

  • More complex and resource-intensive to simulate
  • May be overkill for simple RISC-V software development tasks
  • Steeper learning curve for newcomers to processor design

Code Comparison

riscv-boom:

class BoomCore(implicit p: Parameters) extends BoomModule()(p)
  with HasBoomCoreParameters
  with HasL1ICacheBankedParameters
{
  val io = IO(new BoomCoreIO)
  // ... (core implementation)
}

riscv-isa-sim:

class processor_t : public abstract_device_t
{
 public:
  processor_t(const char* isa, const char* priv, const char* varch,
              simif_t* sim, uint32_t id, bool halt_on_reset,
              FILE* log_file);
  // ... (processor implementation)
};

The riscv-boom code showcases a Scala implementation of a complex out-of-order core, while riscv-isa-sim uses C++ for a more straightforward instruction set simulator. riscv-boom's approach allows for more advanced architectural exploration, while riscv-isa-sim focuses on functional correctness and ease of use for software development.

1,331

Ibex is a small 32 bit RISC-V CPU core, previously known as zero-riscy.

Pros of ibex

  • Hardware implementation of RISC-V core, suitable for FPGA or ASIC designs
  • Highly configurable and optimized for embedded systems
  • Includes advanced features like debug support and performance counters

Cons of ibex

  • Limited to RV32IMC instruction set, less comprehensive than riscv-isa-sim
  • Requires hardware synthesis tools for full utilization
  • May have a steeper learning curve for software-focused developers

Code Comparison

ibex (Verilog HDL):

module ibex_core #(
  parameter bit          PMPEnable         = 1'b0,
  parameter int unsigned PMPGranularity    = 0,
  parameter int unsigned PMPNumRegions     = 4,
  parameter int unsigned MHPMCounterNum    = 0,
  parameter int unsigned MHPMCounterWidth  = 40,
  parameter bit          RV32E             = 1'b0,
  parameter bit          RV32M             = 1'b1,
  parameter bit          RV32B             = 1'b0,
  parameter bit          BranchTargetALU   = 1'b0,
  parameter bit          WritebackStage    = 1'b0
) (
  // Clock and Reset
  input  logic        clk_i,
  input  logic        rst_ni,
  // ...
);

riscv-isa-sim (C++):

class processor_t : public abstract_device_t {
 public:
  processor_t(const char* isa, const char* priv, const char* varch,
              simif_t* sim, uint32_t id, bool halt_on_reset,
              FILE* log_file, std::ostream& sout_);
  ~processor_t();

  void set_debug(bool value);
  void set_histogram(bool value);
  void enable_log_commits();
  void reset();
  // ...
};

Convert Figma logo designs to code with AI

Visual Copilot

Introducing Visual Copilot: A new AI model to turn Figma designs to high quality code using your components.

Try Visual Copilot

README

Spike RISC-V ISA Simulator

About

Spike, the RISC-V ISA Simulator, implements a functional model of one or more RISC-V harts. It is named after the golden spike used to celebrate the completion of the US transcontinental railway.

Spike supports the following RISC-V ISA features:

  • RV32I and RV64I base ISAs, v2.1
  • RV32E and RV64E base ISAs, v1.9
  • Zifencei extension, v2.0
  • Zicsr extension, v2.0
  • Zicntr extension, v2.0
  • M extension, v2.0
  • A extension, v2.1
  • B extension, v1.0
  • F extension, v2.2
  • D extension, v2.2
  • Q extension, v2.2
  • C extension, v2.0
  • Zbkb, Zbkc, Zbkx, Zknd, Zkne, Zknh, Zksed, Zksh scalar cryptography extensions (Zk, Zkn, and Zks groups), v1.0
  • Zkr virtual entropy source emulation, v1.0
  • V extension, v1.0 (requires a 64-bit host)
  • P extension, v0.9.2
  • Zba extension, v1.0
  • Zbb extension, v1.0
  • Zbc extension, v1.0
  • Zbs extension, v1.0
  • Zfh and Zfhmin half-precision floating-point extensions, v1.0
  • Zfinx extension, v1.0
  • Zmmul integer multiplication extension, v1.0
  • Zicbom, Zicbop, Zicboz cache-block maintenance extensions, v1.0
  • Conformance to both RVWMO and RVTSO (Spike is sequentially consistent)
  • Machine, Supervisor, and User modes, v1.11
  • Hypervisor extension, v1.0
  • Svnapot extension, v1.0
  • Svpbmt extension, v1.0
  • Svinval extension, v1.0
  • Svadu extension, v1.0
  • Sdext extension, v1.0-STABLE
  • Sdtrig extension, v1.0-STABLE
  • Smepmp extension v1.0
  • Smstateen extension, v1.0
  • Smdbltrp extension, v1.0
  • Sscofpmf v0.5.2
  • Ssdbltrp extension, v1.0
  • Ssqosid extension, v1.0
  • Zaamo extension, v1.0
  • Zalrsc extension, v1.0
  • Zabha extension, v1.0
  • Zacas extension, v1.0
  • Zawrs extension, v1.0
  • Zicfiss extension, v1.0
  • Zicfilp extension, v1.0
  • Zca extension, v1.0
  • Zcb extension, v1.0
  • Zcf extension, v1.0
  • Zcd extension, v1.0
  • Zcmp extension, v1.0
  • Zcmt extension, v1.0
  • Zfbfmin extension, v0.6
  • Zvfbfmin extension, v0.6
  • Zvfbfwma extension, v0.6
  • Zvbb extension, v1.0
  • Zvbc extension, v1.0
  • Zvkg extension, v1.0
  • Zvkned extension, v1.0
  • Zvknha, Zvknhb extension, v1.0
  • Zvksed extension, v1.0
  • Zvksh extension, v1.0
  • Zvkt extension, v1.0
  • Zvkn, Zvknc, Zvkng extension, v1.0
  • Zvks, Zvksc, Zvksg extension, v1.0
  • Zicond extension, v1.0
  • Zilsd extension, v0.9.0
  • Zcmlsd extension, v0.9.0

Versioning and APIs

Projects are versioned primarily to indicate when the API has been extended or rendered incompatible. In that spirit, Spike aims to follow the SemVer versioning scheme, in which major version numbers are incremented when backwards-incompatible API changes are made; minor version numbers are incremented when new APIs are added; and patch version numbers are incremented when bugs are fixed in a backwards-compatible manner.

Spike's principal public API is the RISC-V ISA. The C++ interface to Spike's internals is not considered a public API at this time, and backwards-incompatible changes to this interface will be made without incrementing the major version number.

Build Steps

We assume that the RISCV environment variable is set to the RISC-V tools install path.

$ apt-get install device-tree-compiler libboost-regex-dev libboost-system-dev
$ mkdir build
$ cd build
$ ../configure --prefix=$RISCV
$ make
$ [sudo] make install

If your system uses the yum package manager, you can substitute yum install dtc for the first step.

Build Steps on OpenBSD

Install bash, gmake, dtc, and use clang.

$ pkg_add bash gmake dtc
$ exec bash
$ export CC=cc; export CXX=c++
$ mkdir build
$ cd build
$ ../configure --prefix=$RISCV
$ gmake
$ [doas] make install

Compiling and Running a Simple C Program

Install spike (see Build Steps), riscv-gnu-toolchain, and riscv-pk.

Write a short C program and name it hello.c. Then, compile it into a RISC-V ELF binary named hello:

$ riscv64-unknown-elf-gcc -o hello hello.c

Now you can simulate the program atop the proxy kernel:

$ spike pk hello

Simulating a New Instruction

Adding an instruction to the simulator requires two steps:

  1. Describe the instruction's functional behavior in the file riscv/insns/<new_instruction_name>.h. Examine other instructions in that directory as a starting point.

  2. Add the opcode and opcode mask to riscv/opcodes.h. Alternatively, add it to the riscv-opcodes package, and it will do so for you:

     $ cd ../riscv-opcodes
     $ vi opcodes       // add a line for the new instruction
     $ make install
    
  3. Add the instruction to riscv/riscv.mk.in. Otherwise, the instruction will not be included in the build and will be treated as an illegal instruction.

  4. Rebuild the simulator.

Interactive Debug Mode

To invoke interactive debug mode, launch spike with -d:

$ spike -d pk hello

To see the contents of an integer register (0 is for core 0):

: reg 0 a0

To see the contents of a floating point register:

: fregs 0 ft0

or:

: fregd 0 ft0

depending upon whether you wish to print the register as single- or double-precision.

To see the contents of a memory location (physical address in hex):

: mem 2020

To see the contents of memory with a virtual address (0 for core 0):

: mem 0 2020

You can advance by one instruction by pressing the enter key. You can also execute until a desired equality is reached:

: until pc 0 2020                   (stop when pc=2020)
: until reg 0 mie a                 (stop when register mie=0xa)
: until mem 2020 50a9907311096993   (stop when mem[2020]=50a9907311096993)

Alternatively, you can execute as long as an equality is true:

: while mem 2020 50a9907311096993

You can continue execution indefinitely by:

: r

At any point during execution (even without -d), you can enter the interactive debug mode with <control>-<c>.

To end the simulation from the debug prompt, press <control>-<c> or:

: q

Debugging With Gdb

An alternative to interactive debug mode is to attach using gdb. Because spike tries to be like real hardware, you also need OpenOCD to do that. OpenOCD doesn't currently know about address translation, so it's not possible to easily debug programs that are run under pk. We'll use the following test program:

$ cat rot13.c 
char text[] = "Vafgehpgvba frgf jnag gb or serr!";

// Don't use the stack, because sp isn't set up.
volatile int wait = 1;

int main()
{
    while (wait)
        ;

    // Doesn't actually go on the stack, because there are lots of GPRs.
    int i = 0;
    while (text[i]) {
        char lower = text[i] | 32;
        if (lower >= 'a' && lower <= 'm')
            text[i] += 13;
        else if (lower > 'm' && lower <= 'z')
            text[i] -= 13;
        i++;
    }

done:
    while (!wait)
        ;
}
$ cat spike.lds 
OUTPUT_ARCH( "riscv" )

SECTIONS
{
  . = 0x10110000;
  .text : { *(.text) }
  .data : { *(.data) }
}
$ riscv64-unknown-elf-gcc -g -Og -o rot13-64.o -c rot13.c
$ riscv64-unknown-elf-gcc -g -Og -T spike.lds -nostartfiles -o rot13-64 rot13-64.o

To debug this program, first run spike telling it to listen for OpenOCD:

$ spike --rbb-port=9824 -m0x10100000:0x20000 rot13-64
Listening for remote bitbang connection on port 9824.

In a separate shell run OpenOCD with the appropriate configuration file:

$ cat spike.cfg 
adapter driver remote_bitbang
remote_bitbang host localhost
remote_bitbang port 9824

set _CHIPNAME riscv
jtag newtap $_CHIPNAME cpu -irlen 5 -expected-id 0xdeadbeef

set _TARGETNAME $_CHIPNAME.cpu
target create $_TARGETNAME riscv -chain-position $_TARGETNAME

gdb_report_data_abort enable

init
halt
$ openocd -f spike.cfg
Open On-Chip Debugger 0.10.0-dev-00002-gc3b344d (2017-06-08-12:14)
...
riscv.cpu: target state: halted

In yet another shell, start your gdb debug session:

tnewsome@compy-vm:~/SiFive/spike-test$ riscv64-unknown-elf-gdb rot13-64
GNU gdb (GDB) 8.0.50.20170724-git
Copyright (C) 2017 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.  Type "show copying"
and "show warranty" for details.
This GDB was configured as "--host=x86_64-pc-linux-gnu --target=riscv64-unknown-elf".
Type "show configuration" for configuration details.
For bug reporting instructions, please see:
<http://www.gnu.org/software/gdb/bugs/>.
Find the GDB manual and other documentation resources online at:
<http://www.gnu.org/software/gdb/documentation/>.
For help, type "help".
Type "apropos word" to search for commands related to "word"...
Reading symbols from rot13-64...done.
(gdb) target remote localhost:3333
Remote debugging using localhost:3333
0x0000000010010004 in main () at rot13.c:8
8	    while (wait)
(gdb) print wait
$1 = 1
(gdb) print wait=0
$2 = 0
(gdb) print text
$3 = "Vafgehpgvba frgf jnag gb or serr!"
(gdb) b done 
Breakpoint 1 at 0x10110064: file rot13.c, line 22.
(gdb) c
Continuing.
Disabling abstract command writes to CSRs.

Breakpoint 1, main () at rot13.c:23
23	    while (!wait)
(gdb) print wait
$4 = 0
(gdb) print text
...