RISC-V is an open standard instruction set architecture (ISA) based on established reduced instruction set computer (RISC) principles. The RISC-V ISA is provided under open source licenses that do not require fees to use.

More information about RISC-V can be found at:

How to build Spike emulator and Proxy Kernel (PK) on macOS.

Spike is a RISC-V ISA Simulator that is the golden reference for the ISA. It supports several ISA extensions. It is a simulator of the RISCV instruction set, which can write, compile and run RISCV programs on non-RISCV platforms to facilitate the study and research of relevant personnel. It provides full system emulation or proxied emulation (using HTIF/FESVR). It is the universal starting point to explore RISC-V targeted software.

More information about Spike: https://github.com/riscv/riscv-isa-sim.git

Proxy Kernel (PK)
RISC-V Proxy Kernel, commonly known as pk is an application execution environment that can host statically linked RISC-V ELF binaries. Besides initialization and basic system setup, pk primarily traps I/O system calls in a tethered I/O limited environment and proxies them to the host. If the RISC-V core runs tethered to an actual host over FESVR, pk send it back to the host. In the case of spike, the requests are relayed back to the OS hosting spike.

More information about Proxy Kernel (PK): https://github.com/riscv/riscv-pk.git

Operating system used
macOS Monterey

Software prerequisites

  • This tutorial is a continuation of tutorial:
    How to build the Nuclei RISC-V GNU Compiler Toolchain (riscv-gnu-toolchain) on macOS.
    Please follow that tutorial first, otherwise the steps below do not make any sense.

  • Install the Device tree compiler (A dependency for spike):
    Type: brew install dtc
    Type: brew info dtc

    dtc: stable 1.6.1 (bottled)
    Device tree compiler

  • *** Build and install spike ***
    Create directories ~/riscv_spike and ~/riscv_spike/install
    Type: cd ~
    Type: mkdir riscv_spike
    Type: cd riscv_spike
    Type: mkdir install

  • Clone riscv-isa-sim.git:
    Type: git clone https://github.com/riscv/riscv-isa-sim.git
    Type: cd riscv-isa-sim
    To show the last commit on this branch, type: git log

    commit e93b9cbbbcd3ad0a02ae298e9f1a2d98d3ac0153 (HEAD -> master, origin/master, origin/HEAD)
    Merge: d1a3a42 fc572da
    Author: Andrew Waterman <[email protected]>
    Date: Mon Jan 10 14:34:16 2022 -0800

  • Create directory ~/riscv_spike/riscv-isa-sim/build.
    Type: mkdir build

  • Create the Makefile.
    Type: export PATH=`pwd`/install/bin:$PATH
    Type: cd build
    Type: ../configure --prefix=`pwd`/../../install --with-isa=RV32IMAC

    After a few seconds a ~/riscv_spike/riscv-isa-sim/build/Makefile is generated.

    Note 1:
    I have set --with-isa=RV32IMAC
    This sets the default RISC-V ISA to RV32IMAC.
    The Sipeed Logan Nano CPU is the GigaDevice GD32VF103CBT6, based on Nuclei System Technology Bumblebee core.
    The Nuclei Bumblebee core supports the RISC-V ISA version 2.2 RV32IMAC instruction set.
    This means the GD32VF103CBT6 has no floating-point support.
    See: How to build the Nuclei RISC-V GNU Compiler Toolchain (riscv-gnu-toolchain) on macOS.

    Note 2:
    The ~/riscv_spike/riscv-isa-sim/configure tool is a shell script.
    More information about the many configure options, type: ./configure --help
    See also: configure_riscv_isa_sim_help.txt

  • Build spike, it will take approximately 3 minutes depending on your machine. There are no errors.
    Type: cd ~/riscv_spike/riscv-isa-sim/build
    Type: make -j`nproc`

  • Install spike at ~/riscv_spike/install/bin.
    Type: cd ~/riscv_spike/riscv-isa-sim/build
    Type: make install

    Spike tools

  • Update PATH in .bash_profile
    Type: cd ~
    Type: nano .bash_profile
    Type: export PATH=$PATH:/Users/robertlie/riscv_spike/install/bin

  • Show spike help.
    Type: spike --help
    See: spike_help.txt

  • *** Build and install Proxy Kernel (PK) ***
    Create directory ~/riscv_spike/install_pk
    Type: cd ~/riscv_spike
    Type: mkdir install_pk

  • Clone riscv-pk.git:
    Type: git clone https://github.com/riscv/riscv-pk.git
    Type: cd riscv-pk
    To show the last commit on this branch, type: git log

    commit 387e54a5804653c4c4a22d958f05b4f91277a552 (HEAD -> master, origin/master, origin/HEAD)
    Author: Andrew Waterman <[email protected]>
    Date: Sun Jan 9 18:58:03 2022 -0800

  • Create directory ~/riscv_spike/riscv-pk/build.
    Type: mkdir build

  • Set the RISCV environment variable.
    This variable must point to the RISC-V toolchain install directory.
    Type: export RISCV=/Users/robertlie/riscv_toolchain/install

    More information about the toolchain install directory, see:
    How to build the Nuclei RISC-V GNU Compiler Toolchain (riscv-gnu-toolchain) on macOS.

    The RISCV variable is used in ~/riscv_spike/riscv-pk/configure.ac

  • Goto RISC-V toolchain install directory and create symbolic links.
    Type: cd ~/riscv_toolchain/install
    Create shell script create_symlinks.sh
    See: create_symlinks.sh.txt
    Type: chmod 755 create_symlinks.sh
    Type: ./create_symlinks

    Toolchain create symlinks

  • Create the Makefile.
    Type: cd ~/riscv_spike/riscv-pk/build
    Type: ../configure --prefix=`pwd`/../../install_pk --host=riscv32-nuclei-elf \
    --with-arch=rv32imac --with-abi=ilp32


    checking build system type... x86_64-apple-darwin21.1.0
    checking host system type... riscv32-nuclei-elf
    checking for riscv32-nuclei-elf-gcc... riscv32-nuclei-elf-gcc
    checking whether the C compiler works... yes
    checking for C compiler default output file name... a.out
    checking for suffix of executables...
    checking whether we are cross compiling... yes
    checking for suffix of object files... o
    checking whether we are using the GNU C compiler... yes
    checking whether riscv32-nuclei-elf-gcc accepts -g... yes
    checking for riscv32-nuclei-elf-gcc option to accept ISO C89... none needed
    checking for riscv32-nuclei-elf-g++... riscv32-nuclei-elf-g++
    checking whether we are using the GNU C++ compiler... yes
    checking whether riscv32-nuclei-elf-g++ accepts -g... yes
    checking for riscv32-nuclei-elf-ar... riscv32-nuclei-elf-ar
    checking for riscv32-nuclei-elf-ranlib... riscv32-nuclei-elf-ranlib
    checking for riscv32-nuclei-elf-readelf... riscv32-nuclei-elf-readelf
    checking for riscv32-nuclei-elf-objcopy... riscv32-nuclei-elf-objcopy
    checking for a BSD-compatible install... /opt/local/bin/ginstall -c
    checking how to run the C preprocessor... riscv32-nuclei-elf-gcc -E
    checking for grep that handles long lines and -e... /opt/local/bin/ggrep
    checking for egrep... /opt/local/bin/ggrep -E
    checking for ANSI C header files... yes
    configure: configuring default subproject : pk
    configure: configuring default subproject : bbl
    configure: configuring default subproject : softfloat
    configure: configuring default subproject : dummy_payload
    configure: configuring default subproject : machine
    configure: configuring default subproject : util
    configure: creating ./config.status
    config.status: creating pk.mk
    config.status: creating bbl.mk
    config.status: creating softfloat.mk
    config.status: creating dummy_payload.mk
    config.status: creating machine.mk
    config.status: creating util.mk
    config.status: creating Makefile
    config.status: creating config.h

    After a few seconds a ~/riscv_spike/riscv-pk/build/Makefile is generated.

    Note 1:
    I have set --with-arch=rv32imac --with-abi=ilp32
    Why I have done this, see:
    How to build the Nuclei RISC-V GNU Compiler Toolchain (riscv-gnu-toolchain) on macOS.

    Note 2:
    You can set --host=riscv32-unknown-elf or --host=riscv64-unknown-elf
    Instead of "unknown" I used "nuclei", because I have changed this when creating my Nuclei RISC-V GNU Compiler Toolchain.

    The configure script will search for words "riscv32" or "riscv64", that is why I created symbolic links.

    The configure script will check if certain toolchain tools can be found, for example:

    Note 3:
    The ~/riscv_spike/riscv-pk/configure tool is a shell script.
    More information about the many configure options, type: ./configure --help
    See also: configure_riscv_pk_help.txt

  • Build pk. There should be no errors.
    Type: cd ~/riscv_spike/riscv-pk/build
    Type: make -j`nproc`

  • Install pk at ~/riscv_spike/install_pk/riscv32-nuclei-elf/bin.
    Type: cd ~/riscv_spike/riscv-pk/build
    Type: make install

    pk installed

  • Test spike and pk.
    • Open a terminal.
      Type: cd ~/riscv_toolchain

    • Write a test program.
      Create a file ~/riscv_toolchain/hello.c with the following content:

      #include <stdio.h>
      int main(void) {
         printf("Hello World\n");
         return 0;

    • Compile the test program (for arch=rv32imac and abi=ilp32) into the compatible RISC-V instruction code that can be executed on the processor.

      Type: riscv-nuclei-elf-gcc hello.c -O2 -march=rv32imac -mabi=ilp32 \
      -o hello

      If you did not specify -march=rv32imac and -mabi=ilp32 the default -march=rv64imafdc and -mabi=lp64d is used.
      See: riscv-nuclei-elf-gcc -v

      Type: file hello

      hello: ELF 32-bit LSB executable, UCB RISC-V, RVC, soft-float ABI, version 1 (SYSV), statically linked, not stripped

      Type: ./hello

      -bash: ./hello: cannot execute binary file

      The hello program has been compiled for the riscv32 platform, and thus, will not run on macOS unless it is compatible.

      You can use spike, which is a RISC-V ISA simulator which run programs in a user space as if it is on a RISC-V hardware.

      Type: spike ~/riscv_spike/install_pk/riscv32-nuclei-elf/bin/pk hello

      bbl loader
      Hello World

      You must use the full path to pk.

      Instead of the full path, modify .bash_profile and add the following line:
      Type: export PK_PATH=/Users/robertlie/riscv_spike/install_pk/riscv32-nuclei-elf/bin
      Type: spike $PK_PATH/pk hello

      This will not work:
      Type: export PATH=/Users/robertlie/riscv_spike/install_pk/riscv32-nuclei-elf/bin:$PATH
      Type: spike pk hello

      libc++abi: terminating with uncaught exception of type std::runtime_error: could not open pk (did you misspell it? If VCS, did you forget +permissive/+permissive-off?)