├── examples
├── build-rust
│ ├── .gitignore
│ ├── README.md
│ ├── Makefile
│ └── test.rs
├── build-c
│ ├── test.c
│ ├── .gitignore
│ ├── README.md
│ └── Makefile
├── test-code-c
│ ├── README.md
│ ├── Makefile
│ ├── .devcontainer
│ │ └── devcontainer.json
│ ├── CMakePresets.json
│ ├── timer.h
│ ├── CMakeLists.txt
│ ├── main.c
│ ├── timer.c
│ ├── riscv-interrupts.h
│ ├── startup.c
│ ├── riscv.cmake
│ └── linker.lds
├── build-run-sim
│ ├── README.md
│ ├── test-decode.sh
│ ├── test.gtkw
│ └── Makefile
├── Makefile
└── README.md
├── docker
├── riscv-spike-debug-sim
│ ├── .gitignore
│ ├── Makefile
│ ├── riscv_spike.cfg
│ ├── Makefile.vcd_spike
│ ├── Dockerfile
│ ├── README.md
│ ├── sim_helpers.sh
│ └── sim_entrypoint.sh
├── riscv-spike-debug-gdb
│ ├── .gitignore
│ ├── Makefile
│ ├── Makefile.vcd_spike
│ ├── README.md
│ ├── Dockerfile
│ └── entrypoint_gdb.sh
├── riscv-tool-build
│ ├── Makefile
│ ├── README.md
│ └── Dockerfile
├── riscv-rust
│ ├── Makefile
│ ├── README.md
│ └── Dockerfile
├── riscv-openocd
│ ├── Makefile
│ ├── riscv_spike.cfg
│ ├── compose.yaml
│ ├── README.md
│ └── Dockerfile
├── riscv-spike
│ ├── Makefile
│ ├── Makefile.vcd_spike
│ ├── README.md
│ └── Dockerfile
├── riscv-gnu-toolchain
│ ├── Makefile
│ ├── README.md
│ └── Dockerfile
├── riscv-xpack-gcc
│ ├── Makefile
│ ├── README.md
│ └── Dockerfile
├── Makefile
├── riscv-gtkwave
│ ├── Makefile
│ ├── README.md
│ └── Dockerfile
├── README.md
├── riscv-gnu-toolchain-2
│ ├── README.md
│ ├── compose.yaml
│ ├── docker_build
│ │ └── Dockerfile
│ └── Makefile
├── common.mak
└── targets.mak
├── .gitmodules
├── .gitignore
├── LICENSE
└── README.md
/examples/build-rust/.gitignore:
--------------------------------------------------------------------------------
1 | test.elf
2 |
--------------------------------------------------------------------------------
/docker/riscv-spike-debug-sim/.gitignore:
--------------------------------------------------------------------------------
1 | riscv_spike.cfg
2 |
--------------------------------------------------------------------------------
/examples/build-c/test.c:
--------------------------------------------------------------------------------
1 | int main() {
2 | return 0;
3 | }
4 |
--------------------------------------------------------------------------------
/examples/build-c/.gitignore:
--------------------------------------------------------------------------------
1 | host_out
2 | riscv-none-embed_out
3 |
--------------------------------------------------------------------------------
/examples/test-code-c/README.md:
--------------------------------------------------------------------------------
1 | Example code for ../build-run-sim.
2 |
--------------------------------------------------------------------------------
/examples/test-code-c/Makefile:
--------------------------------------------------------------------------------
1 | all :
2 |
3 | clean :
4 | rm -rf build
5 |
--------------------------------------------------------------------------------
/docker/riscv-spike-debug-gdb/.gitignore:
--------------------------------------------------------------------------------
1 | riscv_spike.cfg
2 | sim_helpers.sh
3 |
4 |
--------------------------------------------------------------------------------
/examples/build-run-sim/README.md:
--------------------------------------------------------------------------------
1 | Build a complete program and ensure it can run in spike.
2 |
--------------------------------------------------------------------------------
/examples/build-rust/README.md:
--------------------------------------------------------------------------------
1 | Build a baremetal rust program for riscv32imac using fiveembeddev/riscv_rustup_dev_env docker container.
2 |
--------------------------------------------------------------------------------
/.gitmodules:
--------------------------------------------------------------------------------
1 | [submodule "_export/build-and-verify"]
2 | path = _export/build-and-verify
3 | url = git@github.com:five-embeddev/build-and-verify.git
4 |
--------------------------------------------------------------------------------
/docker/riscv-tool-build/Makefile:
--------------------------------------------------------------------------------
1 | include ../common.mak
2 | IMAGE_NAME=build_env
3 |
4 | all : docker-build-build_env
5 |
6 | include ../targets.mak
7 |
8 |
--------------------------------------------------------------------------------
/examples/build-c/README.md:
--------------------------------------------------------------------------------
1 | Examples on building for the host and target via docker.
2 |
3 | Depends on the docker images build in the
4 | ../../docker directory. Those should be built first.
5 |
--------------------------------------------------------------------------------
/docker/riscv-rust/Makefile:
--------------------------------------------------------------------------------
1 | include ../common.mak
2 |
3 | IMAGE_NAME=riscv_rustup_dev_env
4 | COMPOSE_TARGET=build_env
5 | RELEASE_TAG:=${RELEASE_TAG}
6 |
7 | all : docker-build-${IMAGE_NAME}
8 |
9 | include ../targets.mak
10 |
--------------------------------------------------------------------------------
/examples/test-code-c/.devcontainer/devcontainer.json:
--------------------------------------------------------------------------------
1 | {
2 | "name" : "RISC-V Dev",
3 | "image": "fiveembeddev/riscv_xpack_gcc_dev_env:latest",
4 | "customizations": {
5 | "vscode": {
6 | "extensions": ["cmake"]
7 | }
8 | },
9 | }
10 |
--------------------------------------------------------------------------------
/examples/Makefile:
--------------------------------------------------------------------------------
1 | DIRS=\
2 | build-c \
3 | build-rust \
4 | test-code-c \
5 | build-run-sim
6 |
7 | build : ${DIRS:%=build.%}
8 | echo ${DIRS}
9 |
10 | build.% :
11 | ${MAKE} -C ${*} all
12 |
13 | clean : ${DIRS:%=clean.%}
14 | echo ${DIRS}
15 |
16 | clean.% :
17 | ${MAKE} -C ${*} clean
18 |
--------------------------------------------------------------------------------
/examples/build-run-sim/test-decode.sh:
--------------------------------------------------------------------------------
1 | #! /bin/bash
2 |
3 | echo "DECODE_ELF=${DECODE_ELF}"
4 | grep 0x build/main.map | \
5 | perl -p -e 's/^.*(0x[0-9A-Fa-f]{8,16}).*$/$1/' | \
6 | cut -f1 -d' ' | \
7 | sort -u > test.addr
8 | cat test.addr
9 | /opt/riscv-gtkwave/bin/decode_addr < test.addr
10 |
--------------------------------------------------------------------------------
/docker/riscv-spike-debug-sim/Makefile:
--------------------------------------------------------------------------------
1 | include ../common.mak
2 |
3 | IMAGE_NAME=riscv_spike_debug_sim
4 | RELEASE_TAG:=${RELEASE_TAG}_spike_${SPIKE_TAG}
5 |
6 | all : docker-build-${IMAGE_NAME}
7 |
8 | docker-build-${IMAGE_NAME} : riscv-spike riscv-openocd riscv_spike.cfg
9 |
10 | include ../targets.mak
11 |
12 |
13 |
--------------------------------------------------------------------------------
/examples/test-code-c/CMakePresets.json:
--------------------------------------------------------------------------------
1 | {
2 | "configurePresets": [
3 | {
4 | "name": "RISC-V Build",
5 | "displayName": "RISC-V Build Preset",
6 | "binaryDir": "${sourceDir}/build/default",
7 | "generator": "Makefile",
8 | "toolchainFile": "riscv.cmake"
9 | }
10 | ]
11 | }
--------------------------------------------------------------------------------
/examples/build-rust/Makefile:
--------------------------------------------------------------------------------
1 | all : test.elf
2 |
3 | test.elf : test.rs
4 | docker run \
5 | --rm \
6 | -v .:/project \
7 | fiveembeddev/riscv_rustup_dev_env:latest \
8 | rustc \
9 | --target riscv32imac-unknown-none-elf \
10 | /project/test.rs \
11 | -o test.elf
12 |
13 |
14 | clean :
15 | rm -f test.elf
16 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | docker/riscv-gnu-toolchain-2/docker_build/install_dir/
2 | examples/build-run-sim/build/
3 | CMakeLists.txt.user
4 | CMakeCache.txt
5 | CMakeFiles
6 | CMakeScripts
7 | Testing
8 | cmake_install.cmake
9 | install_manifest.txt
10 | compile_commands.json
11 | CTestTestfile.cmake
12 | _deps
13 |
14 | *~
15 |
16 | **/build/*
17 | *.log
18 | *#
19 | .#*
20 |
--------------------------------------------------------------------------------
/docker/riscv-openocd/Makefile:
--------------------------------------------------------------------------------
1 | include ../common.mak
2 |
3 | IMAGE_NAME=riscv_openocd_base
4 |
5 | # Override to choose spike fork
6 | RELEASE_TAG:=${RELEASE_TAG}_openocd_${OPENOCD_TAG}
7 |
8 | DOCKER_BUILD_ARGS += \
9 | OPENOCD_TAG=${OPENOCD_TAG} \
10 |
11 | all : docker-build-${IMAGE_NAME}
12 |
13 | docker-build-${IMAGE_NAME} : riscv-tool-build
14 |
15 | include ../targets.mak
16 |
--------------------------------------------------------------------------------
/docker/riscv-openocd/riscv_spike.cfg:
--------------------------------------------------------------------------------
1 | adapter driver remote_bitbang
2 | remote_bitbang host localhost
3 | remote_bitbang port 9824
4 |
5 | set _CHIPNAME riscv
6 | jtag newtap $_CHIPNAME cpu -irlen 5 -expected-id 0x10e31913
7 |
8 | set _TARGETNAME $_CHIPNAME.cpu
9 | target create $_TARGETNAME riscv -chain-position $_TARGETNAME
10 |
11 | gdb_report_data_abort enable
12 |
13 | bindto 0.0.0.0
14 |
15 | init
16 | halt
17 |
18 |
--------------------------------------------------------------------------------
/docker/riscv-spike-debug-gdb/Makefile:
--------------------------------------------------------------------------------
1 | include ../common.mak
2 |
3 | IMAGE_NAME=riscv_spike_debug_gdb
4 | RELEASE_TAG:=${RELEASE_TAG}_spike_${SPIKE_TAG}
5 |
6 | all : docker-build-${IMAGE_NAME}
7 |
8 | .PHONY: docker-build-${IMAGE_NAME}
9 | docker-build-${IMAGE_NAME} : \
10 | riscv_spike.cfg \
11 | sim_helpers.sh \
12 | riscv-spike \
13 | riscv-openocd \
14 | riscv-xpack-gcc
15 |
16 | include ../targets.mak
17 |
18 |
19 |
--------------------------------------------------------------------------------
/docker/riscv-spike-debug-sim/riscv_spike.cfg:
--------------------------------------------------------------------------------
1 | adapter driver remote_bitbang
2 | remote_bitbang host localhost
3 | remote_bitbang port 9824
4 |
5 | set _CHIPNAME riscv
6 | jtag newtap $_CHIPNAME cpu -irlen 5 -expected-id 0x10e31913
7 |
8 | set _TARGETNAME $_CHIPNAME.cpu
9 | target create $_TARGETNAME riscv -chain-position $_TARGETNAME
10 |
11 | gdb_report_data_abort enable
12 |
13 | bindto 0.0.0.0
14 |
15 | init
16 | halt
17 |
18 |
--------------------------------------------------------------------------------
/examples/README.md:
--------------------------------------------------------------------------------
1 | # Examples of using docker
2 |
3 | | Example | Description |
4 | |-----------------------|-------------|
5 | | build-c/ | Build a simple C test program for host and target |
6 | | build-rust/ | Build a small rust program |
7 | | build-run-sim/ | Build a full baremetal example and simulate with Spike, debug with GDB |
8 | | test-code-c/ | Small example program |
9 |
10 |
--------------------------------------------------------------------------------
/docker/riscv-spike/Makefile:
--------------------------------------------------------------------------------
1 | # -*- Makefile -*-
2 | include ../common.mak
3 |
4 | IMAGE_NAME=riscv_spike_dev_env
5 | COMPOSE_TARGET=riscv_spike
6 |
7 | # Override to choose spike fork
8 | RELEASE_TAG:=${RELEASE_TAG}_spike_${SPIKE_TAG}
9 |
10 | DOCKER_BUILD_ARGS += \
11 | SPIKE_TAG=${SPIKE_TAG} \
12 | SPIKE_URL=${SPIKE_URL}
13 |
14 | all : docker-build-${IMAGE_NAME}
15 |
16 | docker-build-${IMAGE_NAME} : riscv-tool-build
17 |
18 | include ../targets.mak
19 |
20 |
--------------------------------------------------------------------------------
/docker/riscv-spike-debug-sim/Makefile.vcd_spike:
--------------------------------------------------------------------------------
1 | # -*- Makefile -*-
2 | include ../common.mak
3 |
4 | SPIKE_IMAGE_NAME=forked_riscv_spike_dev_env
5 | IMAGE_NAME=forked_riscv_spike_debug_sim
6 | RELEASE_TAG:=${RELEASE_TAG}_spike_${SPIKE_TAG}
7 |
8 | DOCKER_BUILD_ARGS += \
9 | SPIKE_IMAGE_NAME=${SPIKE_IMAGE_NAME}
10 |
11 | all : docker-build-${IMAGE_NAME}
12 |
13 | docker-build-${IMAGE_NAME} : riscv-spike-vcd riscv-openocd riscv_spike.cfg
14 |
15 | include ../targets.mak
16 |
17 |
18 |
--------------------------------------------------------------------------------
/docker/riscv-gnu-toolchain/Makefile:
--------------------------------------------------------------------------------
1 | include ../common.mak
2 |
3 | IMAGE_NAME=riscv_gnu_toolchain_dev_env
4 |
5 | # Override to choose spike fork
6 | RELEASE_TAG:=${RELEASE_TAG}_gcc_${GCC_TAG}
7 |
8 | DOCKER_BUILD_ARGS += \
9 | GNU_TOOLCHAIN_TAG=${GNU_TOOLCHAIN_TAG} \
10 | GCC_TAG=${GCC_TAG} \
11 | RISCV_MARCH=${RISCV_MARCH} \
12 | RISCV_ABI=${RISCV_ABI}
13 |
14 | all : docker-build-${IMAGE_NAME}
15 |
16 | docker-build-${IMAGE_NAME} : riscv-tool-build
17 |
18 | include ../targets.mak
19 |
--------------------------------------------------------------------------------
/docker/riscv-openocd/compose.yaml:
--------------------------------------------------------------------------------
1 | services:
2 | riscv_openocd:
3 | build:
4 | context : .
5 | target: riscv_openocd_base
6 | image: fiveembeddev/riscv_openocd
7 | ports:
8 | - "9824:9824"
9 | - "4000:4000"
10 | - "6000:6000"
11 | - "3000:3000"
12 | command: ["openocd", "--version"]
13 |
14 | riscv_openocd_shell:
15 | image: fiveembeddev/riscv_openocd
16 | command: bash
17 | tty: true
18 | stdin_open: true
19 |
--------------------------------------------------------------------------------
/docker/riscv-xpack-gcc/Makefile:
--------------------------------------------------------------------------------
1 | include ../common.mak
2 |
3 | IMAGE_NAME=riscv_xpack_gcc_dev_env
4 | COMPOSE_TARGET=build_env
5 |
6 | #XPACK_GCC_VERSION=10.1.0-1.1.1
7 | XPACK_GCC_VERSION=12.2.0-3.1
8 | NODE_VERSION=16.16.0
9 | NVM_VERSION=v0.38.0
10 |
11 | RELEASE_TAG:=${RELEASE_TAG}_gcc_${XPACK_GCC_VERSION}
12 |
13 | DOCKER_BUILD_ARGS += \
14 | XPACK_GCC_VERSION=${XPACK_GCC_VERSION} \
15 | NODE_VERSION=${NODE_VERSION} \
16 | NVM_VERSION=${NVM_VERSION}
17 |
18 | all : docker-build-${IMAGE_NAME}
19 |
20 | include ../targets.mak
21 |
--------------------------------------------------------------------------------
/examples/build-rust/test.rs:
--------------------------------------------------------------------------------
1 | #![no_std]
2 | #![no_main]
3 |
4 | use core::panic::PanicInfo;
5 |
6 | //fn main() {
7 | // // Statements here are executed when the compiled binary is called
8 | //
9 | // // Print text to the console
10 | // // println!("Hello World!");
11 | //}
12 |
13 | // error: `#[panic_handler]` function required, but not found
14 | #[panic_handler]
15 | fn panic(_info: &PanicInfo) -> ! {
16 |
17 | loop {}
18 | }
19 |
20 | #[no_mangle]
21 | pub extern "C" fn _start() -> ! {
22 | loop {}
23 | }
24 |
--------------------------------------------------------------------------------
/docker/riscv-spike-debug-gdb/Makefile.vcd_spike:
--------------------------------------------------------------------------------
1 | include ../common.mak
2 |
3 | SPIKE_IMAGE_NAME=forked_riscv_spike_dev_env
4 | IMAGE_NAME=forked_riscv_spike_debug_gdb
5 | RELEASE_TAG:=${RELEASE_TAG}_spike_${SPIKE_TAG}
6 |
7 | DOCKER_BUILD_ARGS += \
8 | SPIKE_IMAGE_NAME=${SPIKE_IMAGE_NAME}
9 |
10 | all : docker-build-${IMAGE_NAME}
11 |
12 | .PHONY: docker-build-${IMAGE_NAME}
13 | docker-build-${IMAGE_NAME} : \
14 | riscv_spike.cfg \
15 | sim_helpers.sh \
16 | riscv-spike-vcd \
17 | riscv-openocd \
18 | riscv-xpack-gcc
19 |
20 | include ../targets.mak
21 |
22 |
23 |
--------------------------------------------------------------------------------
/docker/riscv-spike/Makefile.vcd_spike:
--------------------------------------------------------------------------------
1 | # -*- Makefile -*-
2 | include ../common.mak
3 |
4 | IMAGE_NAME=forked_riscv_spike_dev_env
5 | COMPOSE_TARGET=riscv_spike
6 |
7 | # Override to choose spike fork
8 | SPIKE_TAG=vcd_trace_20241109
9 | SPIKE_URL=https://github.com/five-embeddev/riscv-isa-sim.git
10 | RELEASE_TAG:=${RELEASE_TAG}_spike_${SPIKE_TAG}
11 |
12 | DOCKER_BUILD_ARGS += \
13 | SPIKE_TAG=${SPIKE_TAG} \
14 | SPIKE_URL=${SPIKE_URL}
15 |
16 | all : docker-build-${IMAGE_NAME}
17 |
18 | docker-build-${IMAGE_NAME} : riscv-tool-build
19 |
20 | include ../targets.mak
21 |
22 |
--------------------------------------------------------------------------------
/docker/Makefile:
--------------------------------------------------------------------------------
1 |
2 | .PHONY: build push
3 | build push :
4 | ${MAKE} -C riscv-tool-build/ $@
5 | ${MAKE} -C riscv-spike/ $@
6 | ${MAKE} -C riscv-spike/ -f Makefile.vcd_spike $@
7 | ${MAKE} -C riscv-openocd/ $@
8 | ${MAKE} -C riscv-xpack-gcc/ $@
9 | ${MAKE} -C riscv-spike-debug-sim/ $@
10 | ${MAKE} -C riscv-spike-debug-sim/ -f Makefile.vcd_spike $@
11 | ${MAKE} -C riscv-spike-debug-gdb/ $@
12 | ${MAKE} -C riscv-spike-debug-gdb/ -f Makefile.vcd_spike $@
13 | ${MAKE} -C riscv-rust/ $@
14 |
15 | .PHONY: login
16 | login :
17 | docker login \
18 | -u fiveembeddev
19 |
20 |
21 |
--------------------------------------------------------------------------------
/docker/riscv-gtkwave/Makefile:
--------------------------------------------------------------------------------
1 | include ../common.mak
2 |
3 | IMAGE_NAME=riscv_gtkwave_base
4 |
5 | RISCV_GTKWAVE_TAG=docker_build_9da3e8c8a6
6 | RISCV_GTKWAVE_URL=https://github.com/five-embeddev/riscv-gtkwave.git
7 |
8 | # Override to choose spike fork
9 | RELEASE_TAG:=${RELEASE_TAG}_decoders_${RISCV_GTKWAVE_TAG}
10 |
11 | DOCKER_BUILD_ARGS += \
12 | RISCV_GTKWAVE_TAG=${RISCV_GTKWAVE_TAG} \
13 | RISCV_GTKWAVE_URL=${RISCV_GTKWAVE_URL}
14 |
15 | DOCKER_RUN_ARGS += \
16 | -v /tmp/.X11-unix:/tmp/.X11-unix \
17 | -e DISPLAY=${DISPLAY}
18 |
19 | DOCKER_RUN_SHELL=gtkwave
20 |
21 | all : docker-build-${IMAGE_NAME}
22 |
23 | docker-build-${IMAGE_NAME} : riscv-tool-build
24 |
25 | include ../targets.mak
26 |
--------------------------------------------------------------------------------
/docker/riscv-spike-debug-sim/Dockerfile:
--------------------------------------------------------------------------------
1 | ARG SPIKE_IMAGE_NAME=riscv_spike_dev_env
2 | FROM fiveembeddev/${SPIKE_IMAGE_NAME}:latest AS riscv_spike_debug_sim
3 |
4 | WORKDIR /project/
5 |
6 | # Merge in openocd
7 | COPY --from=fiveembeddev/riscv_openocd_base:latest \
8 | /opt/riscv-openocd/ \
9 | /opt/riscv-openocd/
10 |
11 | RUN sudo apt-get update -qq && sudo apt-get install -y ncat
12 | ENV PATH=/opt/riscv-openocd/bin:/opt/riscv-isa-sim/bin:/bin:/usr/bin:/usr/local/bin
13 |
14 | COPY riscv_spike.cfg /opt/
15 | COPY sim_helpers.sh /opt/
16 | COPY sim_entrypoint.sh /opt/
17 | RUN sudo chmod +x /opt/sim_entrypoint.sh
18 |
19 | ENV RISCV_ISA=rv32imac
20 | ENV RISCV_PRIV=m
21 | ENV BOARD_MEM=0x8000000:0x2000,0x80000000:0x4000,0x20010000:0x6a120
22 | ENV START_PC=0x20010000
23 |
24 | ENTRYPOINT ["/opt/sim_entrypoint.sh"]
25 |
--------------------------------------------------------------------------------
/docker/README.md:
--------------------------------------------------------------------------------
1 | # Docker for emebdded RISC-V development.
2 |
3 | | Target | Description |
4 | |-----------------------|-------------|
5 | | riscv-tool-build | Base image for compiling tools|
6 | | riscv-spike | RISC-V ISA Simulator. |
7 | | riscv-openocd | OpenOCD JTAG debugger interface|
8 | | riscv-xpack-gcc | X-PACK packaged GCC |
9 | | riscv-spike-debug-sim | RISC-V Spike ISA configured to run with OpenOCD|
10 | | riscv-spike-debug-gdb | RISC-V Spike ISA configured to run with OpenOCD & GDB|
11 | | riscv-rust | Rust for RISC-V |
12 | | riscv-gnu-toolchain | Build GCC for RISC-V |
13 | | riscv-gnu-toolchain-2 | Build GCC for RISC-V (using docker compose to conserve resources) |
14 |
15 | Each Docker environment is configured to run with a `docker_user` account and user `/project/` as the working directory.
16 |
17 |
18 |
--------------------------------------------------------------------------------
/docker/riscv-gnu-toolchain-2/README.md:
--------------------------------------------------------------------------------
1 | # GNU Toolchain compiled from source
2 |
3 | | | |
4 | |-------|-----------------------------------------|
5 | |*Image*| `fiveembeddev/riscv_gnu_toolchain_dev_env2:latest`|
6 | |*User* | `docker_user`|
7 | |*Home Dir*| `/home/docker_user`|
8 | |*Workdir*| `/project`|
9 | |*Tool Path*| `/opt/riscv-toolchain/`|
10 |
11 |
12 | Clone the https://github.com/riscv-collab/riscv-gnu-toolchain repo and
13 | build the toolchain in this folder. The build files will be copied
14 | into a docker container.
15 |
16 | NOTE - The Makefile in this directory is not for convinence, it must
17 | be used to build the image.
18 |
19 | The final `fiveembeddev/riscv_gnu_toolchain_dev_env2` image will have
20 | the `riscv32-unknown-elf-` toolchain on the path.
21 |
22 | NOTE - The tool build requires 5GB+ of disk space.
23 |
24 |
--------------------------------------------------------------------------------
/docker/riscv-gnu-toolchain-2/compose.yaml:
--------------------------------------------------------------------------------
1 | version: "3"
2 | services:
3 |
4 | build_env:
5 | build:
6 | context: ../riscv-tool-build/
7 | dockerfile: Dockerfile
8 | target: riscv_tools_build_env
9 | image: fiveembeddev/build_env
10 | volumes:
11 | - ./build_dir:/project/build_dir
12 | - ./docker_build/install_dir:/opt/riscv-gnu-toolchain
13 |
14 | dev_env:
15 | build:
16 | context: docker_build/
17 | dockerfile: Dockerfile
18 | target: riscv_gnu_toolchain_dev_env2
19 | args:
20 | DOCKER_USER_UID: 1000
21 | image: fiveembeddev/riscv_gnu_toolchain_dev_env2
22 | command: ["riscv32-unknown-elf-gcc", "--version"]
23 |
24 | shell:
25 | image: fiveembeddev/riscv_gnu_toolchain_dev_env2
26 | stdin_open: true # docker run -i
27 | tty: true # docker run -t
28 | command: ["bash"]
29 |
30 |
--------------------------------------------------------------------------------
/examples/build-c/Makefile:
--------------------------------------------------------------------------------
1 | DOCKER_CMD= docker run \
2 | --rm \
3 | -v .:/project \
4 |
5 |
6 | all : host_out riscv-none-embed_out riscv32-unknown-elf_out
7 |
8 | host : host_out
9 |
10 | gnu_toolchain : riscv32-unknown-elf_out
11 |
12 | xpack : riscv-none-embed_out
13 |
14 | host_out : test.c
15 | ${DOCKER_CMD} \
16 | fiveembeddev/build_env \
17 | gcc test.c -o host_out \
18 |
19 | riscv-none-embed_out : test.c
20 | ${DOCKER_CMD} \
21 | fiveembeddev/riscv_xpack_gcc_dev_env:latest \
22 | riscv-none-elf-gcc \
23 | test.c \
24 | -nostartfiles \
25 | -o riscv-none-embed_out
26 |
27 |
28 | riscv32-unknown-elf_out : test.c
29 | ${DOCKER_CMD} \
30 | fiveembeddev/riscv_gnu_toolchain_dev_env2:latest \
31 | riscv32-unknown-elf-gcc \
32 | test.c \
33 | -o riscv32-unknown-elf_out
34 |
35 | clean :
36 | rm -f riscv32-unknown-elf_out riscv-none-embed_out
37 |
--------------------------------------------------------------------------------
/docker/riscv-rust/README.md:
--------------------------------------------------------------------------------
1 | # Docker environment for running Rust for cross compilation for RISC-V.
2 |
3 | | | |
4 | |-------|-----------------------------------------|
5 | |*Image*| `fiveembeddev/riscv_rustup_dev_env:latest`|
6 | |*User*| `docker_user`|
7 | |*Home Dir*| `/home/docker_user`|
8 | |*Workdir*| `/project`|
9 | |*Tool Path*| `/home/docker_user/.cargo`|
10 |
11 |
12 | The compile is installed using rustup
13 |
14 | RISC-V was a tier-2 platform when this was `Dockerfile` developed. ()
15 |
16 | More info about rust for embedded targets .
17 |
18 | ```bash
19 | docker run \
20 | --tty \
21 | --interactive \
22 | --rm \
23 | -v .:/project \
24 | fiveembeddev/riscv_rustup_dev_env:latest \
25 | rustc --version
26 | ```
27 |
--------------------------------------------------------------------------------
/docker/common.mak:
--------------------------------------------------------------------------------
1 | DOCKER=docker
2 | DOCKER_COMPOSE=${DOCKER} compose
3 | DOCKER_USER_UID:=$(shell id -u)
4 | DOCKER_USER_GID:=$(shell id -g)
5 |
6 | BASE_IMAGE=ubuntu:jammy
7 |
8 | DOCKER_REPO=
9 | DOCKER_USER=fiveembeddev
10 |
11 | RELEASE_VERSION=0.2.0
12 | RELEASE_LABEL=env_${RELEASE_VERSION}
13 | BUILD_TAG=${DOCKER_USER}/${IMAGE_NAME}:latest
14 | RELEASE_TAG=${DOCKER_USER}/${IMAGE_NAME}:${RELEASE_LABEL}
15 |
16 | DOCKER_BUILD_ARGS=\
17 | DOCKER_USER_UID=${DOCKER_USER_UID} \
18 | BASE_IMAGE=${BASE_IMAGE}
19 |
20 | #NO_CACHE=--no-cache
21 | NO_CACHE=
22 | # Show cache
23 | #export DOCKER_BUILDKIT=0
24 |
25 | # Versions
26 | SPIKE_TAG=v1.1.0
27 | SPIKE_URL=https://github.com/riscv-software-src/riscv-isa-sim.git
28 | #GNU_TOOLCHAIN_TAG=2022.03.09
29 | GNU_TOOLCHAIN_TAG=2025.05.30
30 | GCC_TAG=riscv-gcc-10.2.0
31 |
32 | # Default arch
33 | RISCV_MARCH=rv32imac
34 | RISCV_ABI=ilp32
35 |
36 | OPENOCD_TAG=riscv
37 |
38 | DOCKER_RUN_SHELL=/bin/bash
39 |
--------------------------------------------------------------------------------
/docker/riscv-gnu-toolchain-2/docker_build/Dockerfile:
--------------------------------------------------------------------------------
1 | ARG DOCKER_USER_UID=1000
2 |
3 | # ------------------------------------------------------------------------
4 | # Lightwieght container with only tools, no source
5 | ARG BASE_IMAGE=ubuntu:jammy
6 | FROM ${BASE_IMAGE} AS riscv_gnu_toolchain_dev_env2
7 |
8 | ARG DOCKER_USER_UID
9 | ARG TZ
10 |
11 | ENV INSTALL_PATH=/opt/riscv-toolchain/
12 |
13 | # Basic OS update
14 | RUN apt-get update -qq
15 | RUN apt-get install -y sudo
16 |
17 | # Setup user
18 | RUN useradd \
19 | -u ${DOCKER_USER_UID} \
20 | -m \
21 | -r \
22 | -G sudo -s /sbin/nologin \
23 | -c "Docker image user" \
24 | docker_user
25 | RUN echo '%sudo ALL=(ALL) NOPASSWD:ALL' >> /etc/sudoers
26 | USER docker_user
27 |
28 | COPY install_dir ${INSTALL_PATH}
29 |
30 | RUN sudo apt-get install -y libmpc3
31 |
32 | ENV PATH=${INSTALL_PATH}bin:/bin:/usr/bin:/usr/local/bin
33 |
34 | RUN sudo mkdir /project && sudo chown docker_user /project
35 | WORKDIR /project
36 |
--------------------------------------------------------------------------------
/examples/build-run-sim/test.gtkw:
--------------------------------------------------------------------------------
1 | [*]
2 | [*] GTKWave Analyzer v3.3.103 (w)1999-2019 BSI
3 | [*] Sat Jun 15 14:41:00 2024
4 | [*]
5 | [dumpfile] "/project/test.vcd"
6 | [dumpfile_mtime] "Sat Jun 15 14:22:49 2024"
7 | [dumpfile_size] 6360
8 | [savefile] "/project/test.gtkw"
9 | [timestart] 1023
10 | [size] 1182 591
11 | [pos] -1 -1
12 | *0.000000 2 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1
13 | [treeopen] riscv_isa_sim.
14 | [treeopen] riscv_isa_sim.core0.
15 | [sst_width] 214
16 | [signals_width] 134
17 | [sst_expanded] 1
18 | [sst_vpaned_height] 149
19 | @4022
20 | ^>1 /opt/riscv-gtkwave/bin/decode_inst
21 | riscv_isa_sim.core0.processor.insn[63:0]
22 | @22
23 | riscv_isa_sim.core0.processor.jump_pc[63:0]
24 | riscv_isa_sim.core0.processor.pc[63:0]
25 | @4022
26 | ^>2 /opt/riscv-gtkwave/bin/decode_addr
27 | riscv_isa_sim.core0.processor.jump_pc[63:0]
28 | @4023
29 | ^>2 /opt/riscv-gtkwave/bin/decode_addr
30 | riscv_isa_sim.core0.processor.pc[63:0]
31 | [pattern_trace] 1
32 | [pattern_trace] 0
33 |
--------------------------------------------------------------------------------
/docker/riscv-xpack-gcc/README.md:
--------------------------------------------------------------------------------
1 | # XPack RISC-V GCC package
2 |
3 | | | |
4 | |-------|-----------------------------------------|
5 | |*Image*| `fiveembeddev/riscv_xpack_gcc_dev_env:latest`|
6 | |*User* | `docker_user`|
7 | |*Home Dir*| `/home/docker_user`|
8 | |*Workdir*| `/project`|
9 | |*Tool Path*| `/home/docker_user/.xpack/repos/@xpack-dev-tools/`|
10 | |*Tool Path*| `/opt/riscv-none-embed` |
11 |
12 | Docker environment for running the xpack riscv-none-elf-gcc release.
13 |
14 | https://github.com/xpack-dev-tools/riscv-none-elf-gcc-xpack/releases
15 |
16 | ```bash
17 | docker run \
18 | --tty \
19 | --interactive \
20 | --rm \
21 | -v .:/project \
22 | fiveembeddev/riscv_xpack_gcc_dev_env:latest \
23 | riscv-none-elf-gcc --version
24 | ```
25 |
26 | ```
27 | riscv-none-elf-gcc (xPack GNU RISC-V Embedded GCC x86_64) 12.2.0
28 | Copyright (C) 2022 Free Software Foundation, Inc.
29 | This is free software; see the source for copying conditions. There is NO
30 | warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
31 | ```
32 |
--------------------------------------------------------------------------------
/docker/riscv-gnu-toolchain/README.md:
--------------------------------------------------------------------------------
1 | # GNU Toolchain compiled from source
2 |
3 | | | |
4 | |-------|-----------------------------------------|
5 | |*Image*| `fiveembeddev/riscv_gnu_toolchain_dev_env:latest`|
6 | |*User* | `docker_user`|
7 | |*Home Dir*| `/home/docker_user`|
8 | |*Workdir*| `/project`|
9 | |*Tool Path*| `/opt/riscv-toolchain/`|
10 |
11 |
12 | Clone the https://github.com/riscv-collab/riscv-gnu-toolchain repo and
13 | build the toolchain within Docker. A multistage docker file is used to
14 | reduce the size of the final image.
15 |
16 | The final `fiveembeddev/riscv_gnu_toolchain_dev_env` image will have
17 | the `riscv32-unknown-elf-` toolchain on the path.
18 |
19 |
20 | *NOTE*: The tool build requires 5GB+ of disk space, and building within
21 | docker requires a lot of system resources. An alternate build is in
22 | `../riscv-gnu-toolchain-2/`.
23 |
24 | ```bash
25 | docker run \
26 | --tty \
27 | --interactive \
28 | --rm \
29 | -v .:/project \
30 | fiveembeddev/riscv_gnu_toolchain_dev_env:latest \
31 | riscv32-unknown-elf-gcc --version
32 | ```
33 |
34 |
--------------------------------------------------------------------------------
/docker/riscv-openocd/README.md:
--------------------------------------------------------------------------------
1 | # OpenOCD for RISC-V
2 |
3 | | | |
4 | |-------|-----------------------------------------|
5 | |*Image*| `fiveembeddev/riscv_openocd_base:latest`|
6 | |*User*| `docker_user`|
7 | |*Home Dir*| `/home/docker_user`|
8 | |*Workdir*| `/project`|
9 | |*Tool Path*| `/opt/riscv-openocd/`|
10 |
11 |
12 | Clone and build the RISC-V port of openocd from
13 | https://github.com/riscv-collab/riscv-openocd. The tools will be built inside
14 | of the docker image. A multistage docker file is used so the source is
15 | not included in the final image.
16 |
17 | An example configuration file is copied into the docker image for
18 | running with the spike ISA simulator.
19 |
20 | ```bash
21 | docker run \
22 | --tty \
23 | --interactive \
24 | --rm \
25 | -v .:/project \
26 | -p "9824:9824" \
27 | -p "4000:4000" \
28 | -p "6000:6000" \
29 | -p "3000:3000" \
30 | fiveembeddev/riscv_openocd_base:latest \
31 | /opt/riscv-openocd/bin/openocd \
32 | -f /opt/riscv-openocd/riscv_spike.cfg
33 | ```
34 |
35 | (Note: command requires a target to connect to on 9824, such as riscv-spike)
36 |
--------------------------------------------------------------------------------
/examples/test-code-c/timer.h:
--------------------------------------------------------------------------------
1 | /*
2 | Simple machine mode timer driver for RISC-V standard timer.
3 | SPDX-License-Identifier: Unlicense
4 |
5 | (https://five-embeddev.com/)
6 |
7 | */
8 |
9 | #ifndef TIMER_H
10 | #define TIMER_H
11 |
12 | #include
13 |
14 | #define RISCV_MTIMECMP_ADDR (0x2000000 + 0x4000)
15 | #define RISCV_MTIME_ADDR (0x2000000 + 0xBFF8)
16 |
17 | #define MTIME_FREQ_HZ 32768
18 |
19 | #define MTIMER_SECONDS_TO_CLOCKS(SEC) \
20 | ((uint64_t)(((SEC)*(MTIME_FREQ_HZ))))
21 |
22 | /** Set the raw time compare point in system timer clocks.
23 | * @param clock_offset Time relative to current mtime when
24 | * @note The time range of the 64 bit timer is large enough not to consider a wrap around of mtime.
25 | * An interrupt will be generated at mtime + clock_offset.
26 | * See http://five-embeddev.com/riscv-isa-manual/latest/machine.html#machine-timer-registers-mtime-and-mtimecmp
27 | */
28 | void mtimer_set_raw_time_cmp(uint64_t clock_offset);
29 |
30 | /** Read the raw time of the system timer in system timer clocks
31 | */
32 | uint64_t mtimer_get_raw_time(void);
33 |
34 |
35 | #endif // #ifdef TIMER_H
36 |
37 |
--------------------------------------------------------------------------------
/docker/riscv-spike-debug-sim/README.md:
--------------------------------------------------------------------------------
1 | # Debug Server With RISC-V Spike
2 |
3 | | | |
4 | |-------|-----------------------------------------|
5 | |*Image*| `fiveembeddev/riscv_spike_debug_sim:latest`|
6 | |*Image*|`fiveembeddev/forked_riscv_spike_debug_sim:latest`|
7 | |*User*| `docker_user`|
8 | |*Home Dir*| `/home/docker_user`|
9 | |*Workdir*| `/project`|
10 | |*Tool Path*| `/opt/riscv-isa-sim/`|
11 | |*Tool Path*| `/opt/riscv-openocd/`|
12 | |*GDB Port*| 3333 |
13 | |*OpenOCD TCL Port*| 6666 |
14 | |*OpenOCD CMD Port*| 4444 |
15 |
16 | Docker environment for running spike with openocd for exposing a GDB
17 | port for debugging RISC-V applications.
18 |
19 | ## Standard Version
20 |
21 | Expose a server for GDB.
22 |
23 | ~~~
24 | docker run \
25 | -it \
26 | -p 3333:3333
27 | --rm \
28 | -v .:/project \
29 | fiveembeddev/riscv_spike_debug_sim:latest \
30 | build_target/src/main.elf
31 | ~~~
32 |
33 |
34 | ## VCD Version
35 |
36 | VCD Trace can saved to inspect a run.
37 |
38 | ~~~
39 | docker run \
40 | -it \
41 | --rm \
42 | -v .:/project \
43 | fiveembeddev/forked_riscv_spike_debug_sim:latest \
44 | --vcd-log=test.vcd \
45 | --max-cycles=10000 \
46 | build_target/src/main.elf
47 | ~~~
48 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | This is free and unencumbered software released into the public domain.
2 |
3 | Anyone is free to copy, modify, publish, use, compile, sell, or
4 | distribute this software, either in source code form or as a compiled
5 | binary, for any purpose, commercial or non-commercial, and by any
6 | means.
7 |
8 | In jurisdictions that recognize copyright laws, the author or authors
9 | of this software dedicate any and all copyright interest in the
10 | software to the public domain. We make this dedication for the benefit
11 | of the public at large and to the detriment of our heirs and
12 | successors. We intend this dedication to be an overt act of
13 | relinquishment in perpetuity of all present and future rights to this
14 | software under copyright law.
15 |
16 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
19 | IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR
20 | OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
21 | ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
22 | OTHER DEALINGS IN THE SOFTWARE.
23 |
24 | For more information, please refer to
25 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | Docker and docker-compose files for building and simulating RISC-V target code.
2 |
3 | See for more info.
4 |
5 | ## Dockerfiles
6 |
7 | Each directory in `docker/` folder includes at least `Dockerfile` and `Makefile`. The docker `Dockerfile` will build an
8 | image, either from source or using the OS package and tools
9 | manager. The `Makefile` is used to define the image
10 | tags and run some commands or open a shell to check the build. The
11 | `Makefile` is generally for convinience, the build steps are in the
12 | `Dockerfile` and `targets.mak` file. NOTE - `riscv-gnu-toolchain-2`
13 | relies on the `compose.yaml` to build the image, as the build files are stored
14 | outside of docker.
15 |
16 | The docker images are designed to run tools using a user account with
17 | user ID, `DOCKER_USER_UID`. The `Makefile` will set that to the uid of
18 | the user building the docker images.
19 |
20 | The docker images set the workdir to `/project`. The input and output
21 | files can be mounted to this volume.
22 |
23 | ## Examples
24 |
25 | The directories in `example/` will compile or simulate some target code.
26 |
27 | The `Makefile` files generally include the commands, the
28 | `compose.yaml` are provided for convinience if needed. These all
29 | assume the required images in `docker/` have been built.
30 |
31 |
32 |
33 |
--------------------------------------------------------------------------------
/docker/riscv-spike-debug-sim/sim_helpers.sh:
--------------------------------------------------------------------------------
1 | BITBANG_PORT=9824
2 | GDB_PORT=3333
3 | TCL_PORT=6666
4 | CMD_PORT=4444
5 |
6 | SPIKE_PID=-1
7 | OPENOCD_PID=-1
8 |
9 | LOG_DIR=/project
10 | PID_DIR=/tmp
11 |
12 | ELF_FILE=
13 |
14 | # ------------------------------------------
15 | # Functions
16 |
17 | print_log(){
18 | if [ -f $2 ]; then
19 | echo "$1: BEGIN"
20 | cat $2
21 | echo "$1: END"
22 | else
23 | echo "$1 LOG: NOT FOUND..."
24 | fi
25 | }
26 |
27 | clean_up_pid() {
28 | if [ $2 > 0 ] ; then
29 | if ps -p $2 > /dev/null 2>&1 ; then
30 | echo "$1 EXIT: KILL ($2)"
31 | kill $2;
32 | else
33 | echo "$1 EXIT: ALREADY DEAD"
34 | fi
35 | fi
36 | }
37 |
38 | clean_up() {
39 | print_log "SPIKE" ${LOG_DIR}/spike.log
40 | print_log "OPENOCD" ${LOG_DIR}/openocd.log
41 | clean_up_pid "SPIKE" $SPIKE_PID
42 | clean_up_pid "OPENOCD" $OPENOCD_PID
43 | exit $1
44 | }
45 |
46 | test_alive() {
47 | if ! ps -p $2 > /dev/null 2>&1 ; then
48 | echo "$1: PROCESS DIED"
49 | clean_up 1
50 | fi
51 | }
52 |
53 | waitport() {
54 | while ! nc -z localhost $3 ; do
55 | sleep 0.1 ;
56 | test_alive $1 $2
57 | done
58 | }
59 |
60 |
61 |
62 | find_elf_args() {
63 | for arg in $@; do
64 | if [[ "$arg" != "-"* ]] ; then
65 | if [ -f $arg ] ; then
66 | echo "$arg"
67 | fi
68 | fi
69 | done
70 | }
71 |
--------------------------------------------------------------------------------
/docker/riscv-spike-debug-gdb/README.md:
--------------------------------------------------------------------------------
1 | # Debug Server With RISC-V Spike
2 |
3 | | | |
4 | |-------|-----------------------------------------|
5 | |*Image*| `fiveembeddev/riscv_spike_debug_gdb:latest`|
6 | |*User*| `docker_user`|
7 | |*Home Dir*| `/home/docker_user`|
8 | |*Workdir*| `/project`|
9 | |*Tool Path*| `/opt/riscv-isa-sim/`|
10 | |*Tool Path*| `/opt/riscv-openocd/`|
11 | |*Tool Path*| `/opt/riscv-none-embed/`|
12 |
13 | Docker environment for running spike with openocd & GDB to allow direct debugging RISC-V applications.
14 |
15 | ~~~
16 | docker run \
17 | -it \
18 | --rm \
19 | -v .:/project \
20 | fiveembeddev/riscv_spike_debug_gdb:latest \
21 | build/main.elf
22 | ~~~
23 |
24 | output:
25 |
26 | ~~~
27 | SPIKE: STARTING with ARGS: build/main.elf
28 | FOUND ELF: build/main.elf
29 | SPIKE: WAIT FOR PORT 9824
30 | SPIKE: READY
31 | OPENOCD: STARTING
32 | OPENOCD: READY
33 | GDB: LOAD: build/main.elf
34 | GNU gdb (xPack GNU RISC-V Embedded GCC x86_64) 12.1
35 |
36 | For help, type "help".
37 | Type "apropos word" to search for commands related to "word"...
38 | Reading symbols from build/main.elf...
39 | Remote debugging using 127.0.0.1:3333
40 | 0x00001000 in ?? ()
41 | (gdb) tui enable
42 | Detaching from program: /project/build/main.elf, Remote target
43 | Ending remote debugging.
44 | [Inferior 1 (Remote target) detached]
45 | ~~~
46 |
--------------------------------------------------------------------------------
/docker/riscv-spike-debug-gdb/Dockerfile:
--------------------------------------------------------------------------------
1 | ARG SPIKE_IMAGE_NAME=riscv_spike_dev_env
2 | FROM fiveembeddev/${SPIKE_IMAGE_NAME}:latest AS riscv_spike_debug_gdb
3 |
4 | WORKDIR /project/
5 |
6 | # Merge in openocd
7 | COPY --from=fiveembeddev/riscv_openocd_base:latest \
8 | /opt/riscv-openocd/ \
9 | /opt/riscv-openocd/
10 |
11 | RUN sudo mkdir -p /opt/riscv-none-embed/bin
12 |
13 | COPY --from=fiveembeddev/riscv_xpack_gcc_dev_env:latest \
14 | /opt/riscv-none-embed/bin/riscv-none-elf-gdb \
15 | /opt/riscv-none-embed/bin/
16 | COPY --from=fiveembeddev/riscv_xpack_gcc_dev_env:latest \
17 | /opt/riscv-none-embed/libexec \
18 | /opt/riscv-none-embed/libexec
19 |
20 | COPY --from=fiveembeddev/riscv_xpack_gcc_dev_env:latest \
21 | /opt/riscv-none-embed/include \
22 | /opt/riscv-none-embed/include
23 |
24 | ENV PATH=/opt/riscv-none-embed/bin:${PATH}
25 | RUN /opt/riscv-none-embed/bin/riscv-none-elf-gdb --version
26 |
27 | RUN sudo apt-get update -qq && sudo apt-get install -y ncat
28 | ENV PATH=/opt/riscv-openocd/bin:/opt/riscv-isa-sim/bin:/bin:/usr/bin:/usr/local/bin:/opt/riscv-none-embed/bin/
29 |
30 | COPY riscv_spike.cfg /opt/
31 | COPY sim_helpers.sh /opt/
32 | COPY entrypoint_gdb.sh /opt/
33 | RUN sudo chmod +x /opt/entrypoint_gdb.sh
34 |
35 | ENV RISCV_ISA=rv32imac
36 | ENV RISCV_PRIV=m
37 | ENV BOARD_MEM=0x8000000:0x2000,0x80000000:0x4000,0x20010000:0x6a120
38 | ENV START_PC=0x20010000
39 |
40 | ENTRYPOINT ["/opt/entrypoint_gdb.sh"]
41 |
--------------------------------------------------------------------------------
/docker/riscv-gtkwave/README.md:
--------------------------------------------------------------------------------
1 | # Container for running GTKWave with decoders.
2 |
3 | | | |
4 | |-------|-----------------------------------------|
5 | |*Image*| `fiveembeddev/riscv_gtkwave_base:latest`|
6 | |*User*| `docker_user`|
7 | |*Home Dir*| `/home/docker_user`|
8 | |*Workdir*| `/project`|
9 | |*Tool Path*| `/opt/riscv-gtkwave/`|
10 |
11 | Following tools installed:
12 | - [GTKWave](https://gtkwave.sourceforge.net/)
13 | - [RISC-V GTKWave Decoders](https://github.com/five-embeddev/riscv-gtkwave)
14 |
15 | GTKWave is an x11 app, expose X11 env.
16 |
17 | ```bash
18 | docker run \
19 | --tty \
20 | --interactive \
21 | --rm \
22 | -v .:/project \
23 | -v /tmp/.X11-unix:/tmp/.X11-unix \
24 | -e DISPLAY=:0 \
25 | fiveembeddev/riscv_gtkwave_base:latest \
26 | gtkwave vcd-trace.vcd config.gtkw
27 | ```
28 |
29 | Decode elf address:
30 |
31 | ``` bash
32 | docker run \
33 | --tty \
34 | --interactive \
35 | --rm \
36 | -v .:/project \
37 | -eDECODE_ELF=build_target/src/main.elf \
38 | fiveembeddev/riscv_gtkwave_base:latest
39 | /opt/riscv_gtkwave/bin/decode_addr
40 | 0x21000000
41 | __clz_tab+0xfeffec
42 | ```
43 |
44 |
45 | Decode risc-v opcode:
46 |
47 | ``` bash
48 | docker run \
49 | --tty \
50 | --interactive \
51 | --rm \
52 | fiveembeddev/riscv_gtkwave_base:latest
53 | /opt/riscv_gtkwave/bin/decode_inst-rv32imac
54 | 0
55 | c.unimp
56 | ```
57 |
58 |
--------------------------------------------------------------------------------
/docker/targets.mak:
--------------------------------------------------------------------------------
1 |
2 | .PHONY:
3 | build: docker-build-${IMAGE_NAME}
4 |
5 |
6 | .PHONY: compose-build-${IMAGE_NAME}
7 | compose-build-${IMAGE_NAME} :
8 | ${DOCKER_COMPOSE} build \
9 | ${DOCKER_BUILD_ARGS:%=--build-arg %} \
10 | ${IMAGE_NAME}
11 |
12 | .PHONY: docker-build-${IMAGE_NAME}
13 | docker-build-${IMAGE_NAME} :
14 | ${DOCKER} build ${NO_CACHE} \
15 | ${DOCKER_BUILD_ARGS:%=--build-arg %} \
16 | --tag ${BUILD_TAG} \
17 | .
18 |
19 | # --progress=plain \
20 |
21 | .PHONY: shell
22 | shell :
23 | ${DOCKER} run \
24 | --tty \
25 | --interactive \
26 | --rm \
27 | --user ${DOCKER_USER_UID}:${DOCKER_USER_GID} \
28 | -v .:/project \
29 | ${DOCKER_RUN_ARGS} \
30 | --entrypoint ${DOCKER_RUN_SHELL} \
31 | ${BUILD_TAG}
32 |
33 |
34 | .PHONY: push
35 | push :
36 | ${DOCKER} push ${BUILD_TAG}
37 | docker tag ${BUILD_TAG} ${RELEASE_TAG}
38 | ${DOCKER} push ${RELEASE_TAG}
39 |
40 | COMPILE_DIRS=\
41 | riscv-gnu-toolchain \
42 | riscv-gnu-toolchain-2 \
43 | riscv-openocd \
44 | riscv-rust \
45 | riscv-spike \
46 | riscv-spike-debug-sim \
47 | riscv-tool-build \
48 | riscv-xpack-gcc
49 |
50 | .PHONY: ${COMPILE_DIRS}
51 | ${COMPILE_DIRS} :
52 | ${MAKE} -C ../$@
53 |
54 | .PHONY: riscv-spike-vcd
55 | riscv-spike-vcd :
56 | ${MAKE} -C ../riscv-spike -f Makefile.vcd_spike
57 |
58 |
59 |
60 | riscv_spike.cfg : ../riscv-openocd/riscv_spike.cfg
61 | cp $< $@
62 |
63 | sim_helpers.sh : ../riscv-spike-debug-sim/sim_helpers.sh
64 | cp $< $@
65 |
--------------------------------------------------------------------------------
/docker/riscv-tool-build/README.md:
--------------------------------------------------------------------------------
1 | # Docker environment for building RISC-V tools.
2 |
3 | | | |
4 | |-------|-----------------------------------------|
5 | |*Image*| `fiveembeddev/build_env:latest`|
6 | |*User*| `docker_user`|
7 | |*Home Dir*| `/home/docker_user`|
8 | |*Workdir*| `/project`|
9 | |*Tool Path*| `/opt/riscv-gtkwave/`|
10 |
11 | Build tools (g++, autoconf, etc) and libraries for building development tools.
12 |
13 | Non-root user environment and workdir.
14 |
15 | ```bash
16 | docker run \
17 | --tty \
18 | --interactive \
19 | --rm \
20 | -v .:/project \
21 | fiveembeddev/build_env:latest
22 | ```
23 |
24 | ```bash
25 | docker_user@4b308be4da67:/project$ gcc --version
26 | gcc (Ubuntu 9.4.0-1ubuntu1~20.04.2) 9.4.0
27 | Copyright (C) 2019 Free Software Foundation, Inc.
28 | This is free software; see the source for copying conditions. There is NO
29 | warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
30 |
31 | docker_user@4b308be4da67:/project$ autoconf --version
32 | autoconf (GNU Autoconf) 2.69
33 | Copyright (C) 2012 Free Software Foundation, Inc.
34 | License GPLv3+/Autoconf: GNU GPL version 3 or later
35 | ,
36 | This is free software: you are free to change and redistribute it.
37 | There is NO WARRANTY, to the extent permitted by law.
38 |
39 | Written by David J. MacKenzie and Akim Demaille.
40 | docker_user@4b308be4da67:/project$
41 | ```
42 |
--------------------------------------------------------------------------------
/docker/riscv-spike/README.md:
--------------------------------------------------------------------------------
1 | # Docker container for running the RISC-V spike ISA simulator.
2 |
3 | The source will be downloaded and compiled within the docker container.
4 |
5 | ## Standard Version
6 |
7 | | | |
8 | |-------|-----------------------------------------|
9 | |*Image*| `fiveembeddev/riscv_spike_dev_env:latest`|
10 | |*User*| `docker_user`|
11 | |*Home Dir*| `/home/docker_user`|
12 | |*Workdir*| `/project`|
13 | |*Tool Path*| `/opt/riscv-isa-sim/`|
14 |
15 | RISC-V reference ISA simulator, Spike.
16 |
17 | ```bash
18 | docker run \
19 | --tty \
20 | --interactive \
21 | --rm \
22 | -v .:/project \
23 | fiveembeddev/riscv_spike_dev_env:latest \
24 | spike --help
25 | ```
26 |
27 | ## Forked Version with VCD Tracing and command file extensions
28 |
29 | Compiled from my fork with VCD tracing https://github.com/five-embeddev/riscv-isa-sim/tree/vcd_trace
30 |
31 | | | |
32 | |-------|-----------------------------------------|
33 | |*Image*| `fiveembeddev/forked_riscv_spike_dev_env:latest`|
34 | |*User*| `docker_user`|
35 | |*Home Dir*| `/home/docker_user`|
36 | |*Workdir*| `/project`|
37 | |*Tool Path*| `/opt/riscv-isa-sim/`|
38 |
39 | ```bash
40 | docker run \
41 | --tty \
42 | --interactive \
43 | --rm \
44 | -v .:/project \
45 | fiveembeddev/forked_riscv_spike_dev_env:latest \
46 | spike --help
47 | ```
48 |
49 | Note the new options
50 |
51 | ```
52 | --vcd-log= Log VCD to this file.
53 | --max-cycles= Limit simulation to this number of cycles.
54 | ```
55 |
--------------------------------------------------------------------------------
/docker/riscv-spike-debug-gdb/entrypoint_gdb.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 | # USAGE: ./entrypoint.sh
3 |
4 | source /opt/sim_helpers.sh
5 |
6 | # ------------------------------------------
7 | # Setup
8 |
9 | trap clean_up SIGHUP SIGINT SIGTERM
10 |
11 | # ------------------------------------------
12 | # Print args
13 |
14 | echo "SPIKE: STARTING with ARGS: $@"
15 |
16 | ELF_FILE=$(find_elf_args $@)
17 | echo "FOUND ELF: ${ELF_FILE}"
18 | echo "OTHER ARGS: ${@}"
19 |
20 |
21 | # ------------------------------------------
22 | # Start sim
23 |
24 | nohup \
25 | /opt/riscv-isa-sim/bin/spike \
26 | --rbb-port=${BITBANG_PORT} \
27 | -H \
28 | --isa=${RISCV_ISA} \
29 | --priv=${RISCV_PRIV} \
30 | -m${BOARD_MEM} \
31 | --pc=${START_PC} \
32 | $@ \
33 | > ${LOG_DIR}/spike.log 2>&1 & echo $! > ${PID_DIR}/spike.pid
34 |
35 | if [ -f ${PID_DIR}/spike.pid ] ; then
36 | SPIKE_PID=`cat ${PID_DIR}/spike.pid`
37 | fi
38 |
39 | echo "SPIKE: WAIT FOR PORT ${BITBANG_PORT}"
40 |
41 | waitport "SPIKE" ${SPIKE_PID} ${BITBANG_PORT}
42 |
43 | echo "SPIKE: READY"
44 |
45 | # ------------------------------------------
46 | # Start openocd
47 |
48 | echo "OPENOCD: STARTING"
49 |
50 | nohup \
51 | /opt/riscv-openocd/bin/openocd \
52 | -f /opt/riscv_spike.cfg \
53 | > ${LOG_DIR}/openocd.log 2>&1 & echo $! > ${PID_DIR}/openocd.pid
54 |
55 | if [ -f ${PID_DIR}/openocd.pid ] ; then
56 | OPENOCD_PID=`cat ${PID_DIR}/openocd.pid`
57 | fi
58 |
59 | waitport "OPENOCD" ${OPENOCD_PID} ${CMD_PORT}
60 |
61 | # ------------------------------------------
62 | # Wait for exit
63 |
64 | echo "OPENOCD: READY"
65 | echo "GDB: LOAD: ${ELF_FILE}"
66 |
67 | riscv-none-elf-gdb \
68 | -ex 'target remote 127.0.0.1:3333' \
69 | ${ELF_FILE}
70 |
71 |
--------------------------------------------------------------------------------
/examples/test-code-c/CMakeLists.txt:
--------------------------------------------------------------------------------
1 |
2 | cmake_minimum_required(VERSION 3.10)
3 |
4 | # set the project name
5 | project(baremetal_startup_c C)
6 |
7 | # specify the C standard
8 | set(CMAKE_C_FLAGS "\
9 | -march=${CMAKE_SYSTEM_PROCESSOR} \
10 | -std=c99 \
11 | -Os \
12 | -g \
13 | -Wall \
14 | -ffunction-sections \
15 | ")
16 | set ( STACK_SIZE 0xf00 )
17 | set ( TARGET main )
18 |
19 | # add the executable
20 |
21 | add_executable(${TARGET}.elf ${TARGET}.c startup.c timer.c)
22 | SET(LINKER_SCRIPT "${CMAKE_CURRENT_SOURCE_DIR}/linker.lds")
23 |
24 | set_target_properties(${TARGET}.elf PROPERTIES LINK_DEPENDS "${LINKER_SCRIPT}")
25 | target_include_directories(${TARGET}.elf PRIVATE ../include/ )
26 |
27 | # Linker control
28 | SET(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -nostartfiles -Xlinker --defsym=__stack_size=${STACK_SIZE} -T ${LINKER_SCRIPT} -Wl,-Map=${TARGET}.map")
29 |
30 | # Post processing command to create a disassembly file
31 | add_custom_command(TARGET ${TARGET}.elf POST_BUILD
32 | COMMAND ${CMAKE_OBJDUMP} -S ${TARGET}.elf > ${TARGET}.disasm
33 | COMMENT "Invoking: Disassemble")
34 |
35 | # Post processing command to create a hex file
36 | add_custom_command(TARGET ${TARGET}.elf POST_BUILD
37 | COMMAND ${CMAKE_OBJCOPY} -O ihex ${TARGET}.elf ${TARGET}.hex
38 | COMMENT "Invoking: Hexdump")
39 |
40 | # Pre-processing command to create disassembly for each source file
41 | foreach (SRC_MODULE main startup)
42 | add_custom_command(TARGET ${TARGET}.elf
43 | PRE_LINK
44 | COMMAND ${CMAKE_OBJDUMP} -S CMakeFiles/${TARGET}.elf.dir/${SRC_MODULE}.c.obj > ${SRC_MODULE}.s
45 | COMMENT "Invoking: Disassemble ( CMakeFiles/${TARGET}.elf.dir/${SRC_MODULE}.c.obj)")
46 | endforeach()
47 |
48 | SET(DCMAKE_EXPORT_COMPILE_COMMANDS ON)
49 |
--------------------------------------------------------------------------------
/docker/riscv-spike-debug-sim/sim_entrypoint.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 | # USAGE: ./entrypoint.sh
3 |
4 | source /opt/sim_helpers.sh
5 |
6 | # ------------------------------------------
7 | # Setup
8 |
9 | trap clean_up SIGHUP SIGINT SIGTERM
10 |
11 | # ------------------------------------------
12 | # Print args
13 |
14 | echo "SPIKE: STARTING with ARGS: $@"
15 | ELF=$(find_elf_args $@)
16 | echo "FOUND ELF: ${ELF}"
17 |
18 | if [ "${ELF}" == "" ] ; then
19 | echo "NO ELF FILE FOUND: ${ELF}"
20 | fi
21 |
22 | # ------------------------------------------
23 | # Start sim
24 |
25 | nohup \
26 | /opt/riscv-isa-sim/bin/spike \
27 | --rbb-port=${BITBANG_PORT} \
28 | -H \
29 | --isa=${RISCV_ISA} \
30 | --priv=${RISCV_PRIV} \
31 | -m${BOARD_MEM} \
32 | --pc=${START_PC} \
33 | "$@" \
34 | > ${LOG_DIR}/spike.log 2>&1 & echo $! > ${PID_DIR}/spike.pid
35 |
36 | if [ -f ${PID_DIR}/spike.pid ] ; then
37 | SPIKE_PID=`cat ${PID_DIR}/spike.pid`
38 | fi
39 |
40 | echo "SPIKE: WAIT FOR PORT ${BITBANG_PORT}"
41 |
42 | waitport "SPIKE" ${SPIKE_PID} ${BITBANG_PORT}
43 |
44 | echo "SPIKE: READY"
45 |
46 | # ------------------------------------------
47 | # Start openocd
48 |
49 | echo "OPENOCD: STARTING"
50 |
51 | nohup \
52 | /opt/riscv-openocd/bin/openocd \
53 | -f /opt/riscv_spike.cfg \
54 | > ${LOG_DIR}/openocd.log 2>&1 & echo $! > ${PID_DIR}/openocd.pid
55 |
56 | if [ -f ${PID_DIR}/openocd.pid ] ; then
57 | OPENOCD_PID=`cat ${PID_DIR}/openocd.pid`
58 | fi
59 |
60 | waitport "OPENOCD" ${OPENOCD_PID} ${CMD_PORT}
61 |
62 | # ------------------------------------------
63 | # Wait for exit
64 |
65 | echo "OPENOCD: READY, GDB: ${GDB_PORT}, COMMAND: ${CMD_PORT}"
66 |
67 | while [ 1 ] ; do
68 | sleep 0.1 ;
69 | test_alive "SPIKE" $SPIKE_PID
70 | test_alive "OPENOCD" $OPENOCD_PID
71 | done
72 |
73 |
74 | # will not reach here.
75 |
--------------------------------------------------------------------------------
/docker/riscv-rust/Dockerfile:
--------------------------------------------------------------------------------
1 | ARG DOCKER_USER_UID=1000
2 | ARG TZ=UTC
3 |
4 | # ------------------------------------------------------------------------
5 | # Just the RUST installer
6 |
7 | ARG BASE_IMAGE=ubuntu:jammy
8 | FROM ${BASE_IMAGE} AS riscv_rustup_env
9 |
10 | ARG DOCKER_USER_UID
11 | ARG TZ
12 |
13 | # Basic OS update
14 | RUN apt-get update -qq
15 | RUN apt-get install -y sudo
16 |
17 | # Setup user
18 | RUN useradd \
19 | -u ${DOCKER_USER_UID} \
20 | -m \
21 | -r \
22 | -G sudo -s /sbin/nologin \
23 | -c "Docker image user" \
24 | docker_user
25 | RUN echo '%sudo ALL=(ALL) NOPASSWD:ALL' >> /etc/sudoers
26 | USER docker_user
27 |
28 | WORKDIR /home/docker_user
29 |
30 | # Basic OS Tools
31 | RUN DEBIAN_FRONTEND="noninteractive" sudo apt-get -y install tzdata
32 | RUN sudo apt-get install -y curl
33 |
34 | RUN curl \
35 | --proto '=https' \
36 | --tlsv1.2 \
37 | -sSf \
38 | https://sh.rustup.rs \
39 | -o setup.rustup.sh
40 |
41 | RUN sh ./setup.rustup.sh \
42 | -y \
43 | --no-modify-path \
44 | --profile minimal \
45 | --default-toolchain stable
46 |
47 | ENV PATH=/home/docker_user/.cargo/bin:/bin/:/usr/bin
48 |
49 | RUN sudo mkdir /project && sudo chown docker_user /project
50 | WORKDIR /project
51 |
52 | # ------------------------------------------------------------------------
53 | # Add the RISC-V target
54 |
55 | FROM riscv_rustup_env AS riscv_rustup_dev_env
56 |
57 | RUN rustup target add riscv32imac-unknown-none-elf
58 | RUN rustup target add riscv32i-unknown-none-elf
59 | RUN rustup target add riscv32imac-unknown-none-elf
60 | RUN rustup target add riscv32imc-unknown-none-elf
61 | RUN rustup target add riscv64gc-unknown-none-elf
62 | RUN rustup target add riscv64imac-unknown-none-elf
63 |
64 | RUN sudo apt-get install -y build-essential
65 |
66 | # For cargo objdump etc
67 | RUN cargo install cargo-binutils
68 | RUN rustup component add llvm-tools-preview
69 |
--------------------------------------------------------------------------------
/docker/riscv-openocd/Dockerfile:
--------------------------------------------------------------------------------
1 | ARG OPENOCD_TAG=riscv
2 | ARG DOCKER_USER_UID=1000
3 | ARG BASE_IMAGE=ubuntu:jammy
4 |
5 | FROM fiveembeddev/build_env:latest AS riscv_openocd_build_config
6 |
7 | ARG OPENOCD_TAG
8 | ENV INSTALL_PATH=/opt/riscv-openocd/
9 |
10 | # Clone git repos
11 | RUN sudo apt-get update && sudo apt-get install -y ca-certificates pkg-config
12 |
13 | RUN sudo mkdir -p /work/git && sudo chown -R docker_user /work/
14 | WORKDIR /work/git
15 | RUN git clone \
16 | --depth 1 \
17 | --branch ${OPENOCD_TAG} \
18 | https://github.com/riscv/riscv-openocd.git
19 |
20 | WORKDIR /work/git/riscv-openocd
21 | RUN ls
22 | RUN git submodule update \
23 | --init \
24 | --recommend-shallow \
25 | jimtcl
26 |
27 | RUN git submodule update \
28 | --init \
29 | --recommend-shallow \
30 | src/jtag/drivers/libjaylink
31 |
32 | RUN sudo apt-get update && sudo apt-get install -y libjim-dev
33 |
34 | # Configure
35 | RUN ./bootstrap
36 | RUN ./configure \
37 | --enable-dummy \
38 | --enable-remote-bitbang \
39 | --prefix=${INSTALL_PATH}
40 |
41 | # Build and install
42 | RUN make
43 | RUN sudo make install
44 |
45 | # Lightwieght container with only tools, no source
46 | ARG BASE_IMAGE
47 | FROM ${BASE_IMAGE} AS riscv_openocd_base
48 |
49 | ARG DOCKER_USER_UID
50 | ARG TZ
51 |
52 | ENV INSTALL_PATH=/opt/riscv-openocd/
53 |
54 | # Basic OS update
55 | RUN apt-get update -qq
56 | RUN apt-get install -y sudo
57 |
58 | # Setup user
59 | RUN useradd \
60 | -u ${DOCKER_USER_UID} \
61 | -m \
62 | -r \
63 | -G sudo -s /sbin/nologin \
64 | -c "Docker image user" \
65 | docker_user
66 | RUN echo '%sudo ALL=(ALL) NOPASSWD:ALL' >> /etc/sudoers
67 | USER docker_user
68 |
69 | COPY --from=riscv_openocd_build_config ${INSTALL_PATH} ${INSTALL_PATH}
70 |
71 | ENV PATH=${INSTALL_PATH}/bin:/bin:/usr/bin:/usr/local/bin
72 |
73 | COPY riscv_spike.cfg /opt/riscv-openocd/
74 |
75 | RUN sudo mkdir /project && sudo chown docker_user /project
76 | WORKDIR /project
77 |
78 |
--------------------------------------------------------------------------------
/examples/test-code-c/main.c:
--------------------------------------------------------------------------------
1 | /*
2 | Baremetal main program with timer interrupt.
3 | SPDX-License-Identifier: Unlicense
4 |
5 | https://five-embeddev.com/
6 |
7 | Tested with sifive-hifive-revb, but should not have any
8 | dependencies to any particular implementation.
9 |
10 | */
11 | // RISC-V CSR definitions and access classes
12 | #include "riscv-csr.h"
13 | #include "riscv-interrupts.h"
14 | #include "timer.h"
15 |
16 | // Machine mode interrupt service routine
17 | static void irq_entry(void) __attribute__ ((interrupt ("machine")));
18 |
19 | // Global to hold current timestamp
20 | static volatile uint64_t timestamp = 0;
21 |
22 | int main(void) {
23 | // Global interrupt disable
24 | csr_clr_bits_mstatus(MSTATUS_MIE_BIT_MASK);
25 | csr_write_mie(0);
26 |
27 | // Setup timer for 1 second interval
28 | timestamp = mtimer_get_raw_time();
29 | mtimer_set_raw_time_cmp(MTIMER_SECONDS_TO_CLOCKS(1));
30 |
31 | // Setup the IRQ handler entry point
32 | csr_write_mtvec((uint_xlen_t) irq_entry);
33 |
34 | // Enable MIE.MTI
35 | csr_set_bits_mie(MIE_MTI_BIT_MASK);
36 |
37 | // Global interrupt enable
38 | csr_set_bits_mstatus(MSTATUS_MIE_BIT_MASK);
39 |
40 | // Busy loop
41 | do {
42 | __asm__ volatile ("wfi");
43 | } while (1);
44 |
45 | return 0;
46 |
47 | }
48 |
49 | #pragma GCC push_options
50 | // Force the alignment for mtvec.BASE. A 'C' extension program could be aligned to to bytes.
51 | #pragma GCC optimize ("align-functions=4")
52 | static void irq_entry(void) {
53 | uint_xlen_t this_cause = csr_read_mcause();
54 | if (this_cause & MCAUSE_INTERRUPT_BIT_MASK) {
55 | this_cause &= 0xFF;
56 | // Known exceptions
57 | switch (this_cause) {
58 | case RISCV_INT_MASK_MTI :
59 | // Timer exception, keep up the one second tick.
60 | mtimer_set_raw_time_cmp(MTIMER_SECONDS_TO_CLOCKS(1));
61 | timestamp = mtimer_get_raw_time();
62 | break;
63 | }
64 | }
65 | }
66 | #pragma GCC pop_options
67 |
--------------------------------------------------------------------------------
/docker/riscv-gtkwave/Dockerfile:
--------------------------------------------------------------------------------
1 | ARG OPENOCD_TAG=riscv
2 | ARG DOCKER_USER_UID=1000
3 | ARG BASE_IMAGE=ubuntu:jammy
4 | ARG RISCV_GTKWAVE_TAG=main
5 | ARG RISCV_GTKWAVE_URL=https://github.com/five-embeddev/riscv-gtkwave.git
6 | ARG INSTALL_PATH=/opt/riscv_gtkwave/
7 |
8 | # ------------------------------------------------------------------------
9 | FROM fiveembeddev/build_env:latest AS riscv_gtkwave_build
10 |
11 | ARG INSTALL_PATH
12 | ARG RISCV_GTKWAVE_TAG
13 | ARG RISCV_GTKWAVE_URL
14 |
15 | RUN sudo mkdir -p /work/git && sudo chown -R docker_user /work/
16 | RUN sudo mkdir -p /opt/riscv_gtkwave && sudo chown -R docker_user /work/
17 | WORKDIR /work/git/
18 |
19 | RUN git clone \
20 | --depth 1\
21 | --recursive \
22 | --branch ${RISCV_GTKWAVE_TAG} \
23 | ${RISCV_GTKWAVE_URL}
24 |
25 | RUN sudo apt-get update && sudo apt-get install -y \
26 | python3-pip \
27 | device-tree-compiler \
28 | libboost-all-dev \
29 | libboost-regex-dev
30 |
31 |
32 | WORKDIR /work/git/riscv-gtkwave/
33 | RUN pip3 install -r requirements.txt
34 | RUN cd extern/riscv-isa-sim/ && ./configure
35 | RUN make -C extern/riscv-isa-sim/ -j8
36 | RUN make csrs
37 | RUN make -C src
38 | RUN sudo mkdir -p ${INSTALL_PATH}
39 | RUN sudo make install PREFIX_DIR=${INSTALL_PATH}
40 |
41 | # ------------------------------------------------------------------------
42 | ARG BASE_IMAGE
43 | FROM ${BASE_IMAGE} AS riscv_gtkwave_base
44 |
45 | ARG INSTALL_PATH
46 | ARG DOCKER_USER_UID
47 |
48 | # Basic OS update
49 | RUN apt-get update -qq
50 | RUN apt-get install -y sudo
51 |
52 | # Setup user
53 | RUN useradd \
54 | -u ${DOCKER_USER_UID} \
55 | -m \
56 | -r \
57 | -G sudo -s /sbin/nologin \
58 | -c "Docker image user" \
59 | docker_user
60 | RUN echo '%sudo ALL=(ALL) NOPASSWD:ALL' >> /etc/sudoers
61 | USER docker_user
62 |
63 | COPY --from=riscv_gtkwave_build ${INSTALL_PATH} ${INSTALL_PATH}
64 |
65 | RUN sudo apt-get update && sudo apt-get install -y \
66 | libboost-regex1.71.0 \
67 | gtkwave
68 |
69 | RUN sudo mkdir /project && sudo chown docker_user /project
70 | WORKDIR /project
71 |
--------------------------------------------------------------------------------
/docker/riscv-tool-build/Dockerfile:
--------------------------------------------------------------------------------
1 | ARG BASE_IMAGE=ubuntu:jammy
2 | FROM ${BASE_IMAGE} AS riscv_tools_build_env
3 |
4 | ARG DOCKER_USER_UID=1000
5 | ARG TZ=UTC
6 |
7 | # Basic OS update
8 | RUN apt-get update -qq
9 | RUN apt-get install -y sudo
10 |
11 | # Setup user
12 | RUN useradd \
13 | -u ${DOCKER_USER_UID} \
14 | -r \
15 | -G sudo -s /sbin/nologin \
16 | -c "Docker image user" \
17 | --create-home \
18 | docker_user
19 | RUN echo '%sudo ALL=(ALL) NOPASSWD:ALL' >> /etc/sudoers
20 | USER docker_user
21 |
22 | # Basic OS update
23 | RUN DEBIAN_FRONTEND="noninteractive" sudo apt-get update && sudo apt-get -y install tzdata
24 | RUN sudo apt-get update && sudo apt-get install -y git
25 | RUN sudo apt-get update && sudo apt-get install -y \
26 | bison \
27 | build-essential \
28 | flex
29 |
30 | RUN sudo apt-get update && sudo apt-get install -y \
31 | autoconf \
32 | automake \
33 | autotools-dev
34 |
35 | RUN sudo apt-get update && sudo apt-get install -y \
36 | bc \
37 | curl \
38 | gawk \
39 | gperf \
40 | libtool \
41 | patchutils \
42 | python3 \
43 | texinfo
44 |
45 | RUN sudo apt-get update && sudo apt-get install -y \
46 | libexpat-dev \
47 | libgmp-dev \
48 | libmpc-dev \
49 | libmpfr-dev \
50 | zlib1g-dev
51 |
52 | # HTTP Git clone is unreliable for gcc etc
53 | # gh cli may resolve this, but need to setup token.
54 | # RUN sudo apt-get update && sudo apt-get install -y \
55 | # gpg
56 | # RUN curl -fsSL https://cli.github.com/packages/githubcli-archive-keyring.gpg \
57 | # | sudo gpg --dearmor -o /usr/share/keyrings/githubcli-archive-keyring.gpg
58 | # RUN echo "deb [arch=$(dpkg --print-architecture) signed-by=/usr/share/keyrings/githubcli-archive-keyring.gpg] https://cli.github.com/packages stable main" \
59 | # | sudo tee /etc/apt/sources.list.d/github-cli.list > /dev/null;
60 | # RUN sudo apt-get update && sudo apt-get install -y \
61 | # gh
62 |
63 |
64 | RUN sudo mkdir /project && sudo chown docker_user /project
65 | RUN sudo chown docker_user /opt
66 | WORKDIR /project
67 |
68 |
--------------------------------------------------------------------------------
/examples/test-code-c/timer.c:
--------------------------------------------------------------------------------
1 | /*
2 | Simple machine mode timer driver for RISC-V standard timer.
3 | SPDX-License-Identifier: Unlicense
4 |
5 | (https://five-embeddev.com/)
6 |
7 | */
8 |
9 | #include "timer.h"
10 |
11 | void mtimer_set_raw_time_cmp(uint64_t clock_offset) {
12 | // First of all set
13 | uint64_t new_mtimecmp = mtimer_get_raw_time() + clock_offset;
14 | #if (__riscv_xlen == 64)
15 | // Single bus access
16 | volatile uint64_t *mtimecmp = (volatile uint64_t*)(RISCV_MTIMECMP_ADDR);
17 | *mtimecmp = new_mtimecmp;
18 | #else
19 | volatile uint32_t *mtimecmpl = (volatile uint32_t *)(RISCV_MTIMECMP_ADDR);
20 | volatile uint32_t *mtimecmph = (volatile uint32_t *)(RISCV_MTIMECMP_ADDR+4);
21 | // AS we are doing 32 bit writes, an intermediate mtimecmp value may cause spurious interrupts.
22 | // Prevent that by first setting the dummy MSB to an unacheivable value
23 | *mtimecmph = 0xFFFFFFFF; // cppcheck-suppress redundantAssignment
24 | // set the LSB
25 | *mtimecmpl = (uint32_t)(new_mtimecmp & 0x0FFFFFFFFUL);
26 | // Set the correct MSB
27 | *mtimecmph = (uint32_t)(new_mtimecmp >> 32); // cppcheck-suppress redundantAssignment
28 | #endif
29 | }
30 |
31 | /** Read the raw time of the system timer in system timer clocks
32 | */
33 | uint64_t mtimer_get_raw_time(void) {
34 | #if ( __riscv_xlen == 64)
35 | // Directly read 64 bit value
36 | volatile uint64_t *mtime = (volatile uint64_t *)(RISCV_MTIME_ADDR);
37 | return *mtime;
38 | #else
39 | volatile uint32_t * mtimel = (volatile uint32_t *)(RISCV_MTIME_ADDR);
40 | volatile uint32_t * mtimeh = (volatile uint32_t *)(RISCV_MTIME_ADDR+4);
41 | uint32_t mtimeh_val;
42 | uint32_t mtimel_val;
43 | do {
44 | // There is a small risk the mtimeh will tick over after reading mtimel
45 | mtimeh_val = *mtimeh;
46 | mtimel_val = *mtimel;
47 | // Poll mtimeh to ensure it's consistent after reading mtimel
48 | // The frequency of mtimeh ticking over is low
49 | } while (mtimeh_val != *mtimeh);
50 | return (uint64_t) ( ( ((uint64_t)mtimeh_val)<<32) | mtimel_val);
51 | #endif
52 | }
53 |
--------------------------------------------------------------------------------
/docker/riscv-gnu-toolchain-2/Makefile:
--------------------------------------------------------------------------------
1 | # -*- Makefile -*-
2 | #
3 | IMAGE_NAME=riscv_gnu_toolchain_dev_env2
4 |
5 | include ../common.mak
6 |
7 | RELEASE_TAG:=${RELEASE_TAG}_gcc_${GCC_TAG}
8 |
9 | MOUNT_BUILD_PATH=/project/build_dir
10 | MOUNT_INSTALL_PATH=/opt/riscv-gnu-toolchain
11 | COMPOSE_RUN_BUILD_DIR=${DOCKER_COMPOSE} run -w ${MOUNT_BUILD_PATH} build_env
12 | COMPOSE_RUN_SRC_DIR=${DOCKER_COMPOSE} run -w ${MOUNT_BUILD_PATH}/riscv-gnu-toolchain build_env
13 | #BASE_REPO=https://github.com/riscv-collab/riscv-gnu-toolchain.git
14 | BASE_REPO=git@github.com:riscv-collab/riscv-gnu-toolchain.git
15 |
16 | # Https clone in docker is unreliable
17 | #GIT_RUN_BUILD_DIR=${COMPOSE_RUN_BUILD_DIR}
18 | #GIT_RUN_SRC_DIR=${COMPOSE_RUN_SRC_DIR}
19 | # Do git operations in host
20 | GIT_RUN_BUILD_DIR=cd build_dir &&
21 | GIT_RUN_SRC_DIR=cd build_dir/riscv-gnu-toolchain &&
22 |
23 |
24 |
25 | all : dev_env
26 |
27 | tools : docker_build/install_dir/bin/riscv32-unknown-elf-gcc
28 |
29 | docker_build/install_dir/bin/riscv32-unknown-elf-gcc :
30 | if [ ! -d docker_build/install_dir ] ; then mkdir docker_build/install_dir; fi
31 | if [ ! -d build_dir ] ; then mkdir build_dir; fi
32 | ${DOCKER_COMPOSE} build \
33 | --build-arg DOCKER_USER_UID=${DOCKER_USER_UID} \
34 | build_env
35 | ${COMPOSE_RUN_BUILD_DIR} rm -rf riscv-gnu-toolchain
36 | ${GIT_RUN_BUILD_DIR} git clone \
37 | --depth 1 \
38 | --branch ${GNU_TOOLCHAIN_TAG} \
39 | ${BASE_REPO}
40 | ${GIT_RUN_SRC_DIR} git submodule set-branch --branch ${GCC_TAG} gcc
41 | ${GIT_RUN_SRC_DIR} git submodule update \
42 | --init \
43 | --recursive \
44 | --recommend-shallow \
45 | binutils dejagnu gdb glibc newlib gcc
46 | ${COMPOSE_RUN_SRC_DIR} ./configure \
47 | --prefix=${MOUNT_INSTALL_PATH} \
48 | --with-tune=size \
49 | --with-arch=${RISCV_MARCH} \
50 | --with-abi=${RISCV_ABI}
51 | ${COMPOSE_RUN_SRC_DIR} make
52 |
53 | dev_env : docker_build/install_dir/bin/riscv32-unknown-elf-gcc
54 | ${DOCKER_COMPOSE} build \
55 | --build-arg DOCKER_USER_UID=${DOCKER_USER_UID} \
56 | dev_env
57 |
58 | distclean:
59 | rm -rf docker_build/install_dir
60 | rm -rf build_dir
61 |
62 | include ../targets.mak
63 |
64 |
--------------------------------------------------------------------------------
/docker/riscv-spike/Dockerfile:
--------------------------------------------------------------------------------
1 | ARG DOCKER_USER_UID=1000
2 | ARG TZ=UTC
3 | ARG SPIKE_TAG=master
4 | ARG SPIKE_URL=https://github.com/riscv-software-src/riscv-isa-sim.git
5 | ARG BASE_IMAGE=ubuntu:jammy
6 |
7 | # ------------------------------------------------------------------------
8 | FROM fiveembeddev/build_env:latest AS riscv_spike_build_config
9 |
10 | ARG SPIKE_TAG
11 | ARG SPIKE_URL
12 | ENV INSTALL_PATH=/opt/riscv-isa-sim/
13 |
14 | RUN sudo apt-get update -qq && sudo apt-get install -y device-tree-compiler
15 |
16 |
17 | RUN sudo mkdir -p /work/git && sudo chown -R docker_user /work/
18 | WORKDIR /work/git/
19 |
20 | RUN git clone \
21 | --depth 1\
22 | --recursive \
23 | --branch ${SPIKE_TAG} \
24 | ${SPIKE_URL}
25 |
26 | WORKDIR /work/git/riscv-isa-sim
27 | RUN git submodule update \
28 | --init \
29 | --recursive \
30 | --recommend-shallow
31 |
32 | RUN sudo apt-get install -y libasio-dev libboost-regex-dev libboost-system-dev libboost-thread-dev
33 | # Configure
34 | RUN mkdir build/
35 | WORKDIR /work/git/riscv-isa-sim/build
36 | RUN ../configure \
37 | --enable-histogram \
38 | --prefix=${INSTALL_PATH}
39 |
40 | # Build and install
41 | RUN make
42 | RUN sudo make install
43 |
44 | # ------------------------------------------------------------------------
45 | # Lightwieght container with only tools, no source
46 | ARG BASE_IMAGE
47 | FROM ${BASE_IMAGE} AS riscv_spike_dev_env
48 |
49 | ARG DOCKER_USER_UID
50 |
51 | RUN apt-get update -qq && apt-get install -y device-tree-compiler
52 |
53 | ENV INSTALL_PATH=/opt/riscv-isa-sim
54 |
55 | RUN apt-get install -y sudo
56 |
57 | # Setup user
58 | RUN useradd \
59 | -u ${DOCKER_USER_UID} \
60 | -m \
61 | -r \
62 | -G sudo -s /sbin/nologin \
63 | -c "Docker image user" \
64 | docker_user
65 | RUN echo '%sudo ALL=(ALL) NOPASSWD:ALL' >> /etc/sudoers
66 |
67 | COPY --from=riscv_spike_build_config ${INSTALL_PATH} ${INSTALL_PATH}
68 |
69 | RUN sudo apt-get install -y libboost-regex1.74.0
70 |
71 | USER docker_user
72 | ENV PATH=${INSTALL_PATH}/bin:/bin:/usr/bin:/usr/local/bin
73 |
74 | RUN sudo mkdir /project && sudo chown docker_user /project
75 | WORKDIR /project
76 |
77 |
--------------------------------------------------------------------------------
/examples/build-run-sim/Makefile:
--------------------------------------------------------------------------------
1 | RISCV_ISA=rv32imac
2 | RISCV_PRIV=m
3 | # See test_code/linker.lds
4 | BOARD_MEM=0x8000000:0x2000,0x80000000:0x4000,0x20010000:0x6a120
5 | BITBANG_PORT=9824
6 | ELF_FILE=/project/build/main.elf
7 |
8 | DOCKER_CMD= docker run \
9 | --rm \
10 | -v .:/project \
11 | -v ${CURDIR}/../test-code-c:/project/test_code
12 |
13 | all : build
14 |
15 | build:
16 | ${DOCKER_CMD} \
17 | fiveembeddev/riscv_xpack_gcc_dev_env:latest \
18 | cmake \
19 | -S test_code \
20 | -B build \
21 | -G "Unix Makefiles" \
22 | -DCMAKE_TOOLCHAIN_FILE=../test_code/riscv.cmake
23 | ${DOCKER_CMD} \
24 | fiveembeddev/riscv_xpack_gcc_dev_env:latest \
25 | make \
26 | VERBOSE=1 \
27 | -C build
28 |
29 |
30 | sim:
31 | ${DOCKER_CMD} \
32 | fiveembeddev/riscv_spike_dev_env:latest \
33 | /opt/riscv-isa-sim/bin/spike \
34 | -l \
35 | -d \
36 | --isa=${RISCV_ISA} \
37 | --priv=${RISCV_PRIV} \
38 | -m${BOARD_MEM} \
39 | --pc=0x20010000 \
40 | ${ELF_FILE}
41 |
42 | gdb:
43 | ${DOCKER_CMD} \
44 | --tty \
45 | --interactive \
46 | fiveembeddev/riscv_spike_debug_gdb:latest \
47 | --isa=${RISCV_ISA} \
48 | --priv=${RISCV_PRIV} \
49 | -m${BOARD_MEM} \
50 | --pc=0x20010000 \
51 | ${ELF_FILE}
52 |
53 | trace:
54 | ${DOCKER_CMD} \
55 | fiveembeddev/forked_riscv_spike_debug_sim:latest \
56 | --isa=${RISCV_ISA} \
57 | --priv=${RISCV_PRIV} \
58 | -m${BOARD_MEM} \
59 | --pc=0x20010000 \
60 | --vcd-log=test.vcd \
61 | --max-cycles=10000 \
62 | ${ELF_FILE}
63 |
64 | gtkwave:
65 | ${DOCKER_CMD} \
66 | --tty \
67 | --interactive \
68 | -v /tmp/.X11-unix:/tmp/.X11-unix \
69 | -e DISPLAY=:0 \
70 | -e DECODE_ELF=${ELF_FILE} \
71 | fiveembeddev/riscv_gtkwave_base:latest \
72 | gtkwave test.vcd test.gtkw
73 |
74 | decode-test:
75 | ${DOCKER_CMD} \
76 | --tty \
77 | --interactive \
78 | -e DECODE_ELF=${ELF_FILE} \
79 | fiveembeddev/riscv_gtkwave_base:latest \
80 | ./test-decode.sh
81 |
82 |
83 | sim_help:
84 | docker-compose run sim_test_code \
85 | /opt/riscv-isa-sim/bin/spike \
86 | --help
87 |
88 | clean :
89 | rm -rf test.vcd build/
90 |
91 | .PHONY : build sim clean
92 |
--------------------------------------------------------------------------------
/examples/test-code-c/riscv-interrupts.h:
--------------------------------------------------------------------------------
1 | /*
2 | RISC-V machine interrupts.
3 | SPDX-License-Identifier: Unlicense
4 |
5 | https://five-embeddev.com/
6 |
7 | */
8 |
9 | #ifndef RISCV_INTERRUPTS_H
10 | #define RISCV_INTERRUPTS_H
11 |
12 | enum {
13 | RISCV_INT_POS_MSI = 3,
14 | RISCV_INT_POS_MTI = 7,
15 | RISCV_INT_POS_MEI = 11,
16 | RISCV_INT_POS_SSI = 1,
17 | RISCV_INT_POS_STI = 5,
18 | RISCV_INT_POS_SEI = 9,
19 | RISCV_INT_POS_USI = 0,
20 | RISCV_INT_POS_UTI = 4,
21 | RISCV_INT_POS_UEI = 8,
22 | };
23 |
24 | enum {
25 | RISCV_INT_MASK_MSI = (1UL<> /etc/sudoers
70 | USER docker_user
71 |
72 | COPY --from=riscv_gnu_toolchain_build_config ${INSTALL_PATH} ${INSTALL_PATH}
73 |
74 | ENV PATH=${INSTALL_PATH}/bin:/bin:/usr/bin:/usr/local/bin
75 |
76 | RUN sudo mkdir /project && sudo chown docker_user /project
77 | WORKDIR /project
78 |
--------------------------------------------------------------------------------
/docker/riscv-xpack-gcc/Dockerfile:
--------------------------------------------------------------------------------
1 | ARG XPACK_GCC_VERSION=12.2.0-3.1
2 | #ARG XPACK_GCC_VERSION=10.1.0-1.1.1
3 | ARG PACKAGE=riscv-none-elf-gcc
4 | ARG NODE_VERSION=16.16.0
5 | ARG NVM_VERSION=v0.38.0
6 | ARG DOCKER_USER_UID=1000
7 | ARG TZ=UTC
8 | ARG BASE_IMAGE=ubuntu:jammy
9 |
10 | FROM ${BASE_IMAGE} AS riscv_xpack_gcc_base_env
11 |
12 | ARG DOCKER_USER_UID
13 | ARG TZ
14 |
15 | # Basic OS update
16 | RUN apt-get update -qq
17 | RUN apt-get install -y sudo
18 |
19 | # Setup user
20 | RUN useradd \
21 | -u ${DOCKER_USER_UID} \
22 | -m \
23 | -r \
24 | -G sudo -s /sbin/nologin \
25 | -c "Docker image user" \
26 | docker_user
27 | RUN echo '%sudo ALL=(ALL) NOPASSWD:ALL' >> /etc/sudoers
28 | USER docker_user
29 |
30 | # Basic OS Tools
31 | RUN DEBIAN_FRONTEND="noninteractive" sudo apt-get -y install tzdata
32 | RUN sudo apt-get update && sudo apt-get install -y cmake
33 | RUN sudo apt-get update && sudo apt-get install -y curl
34 |
35 | # ------------------------------------------------------------------------
36 | # Node install
37 | FROM riscv_xpack_gcc_base_env AS riscv_xpack_gcc_node_env
38 |
39 | ARG NODE_VERSION
40 | ARG NVM_VERSION
41 |
42 | # Node is used to install xpack
43 | ENV NVM_DIR=/home/docker_user/.nvm
44 | RUN curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/${NVM_VERSION}/install.sh | bash
45 |
46 | RUN . "$NVM_DIR/nvm.sh" && nvm install ${NODE_VERSION}
47 | RUN . "$NVM_DIR/nvm.sh" && nvm use v${NODE_VERSION}
48 | RUN . "$NVM_DIR/nvm.sh" && nvm alias default v${NODE_VERSION}
49 |
50 | # Check it works
51 | ENV PATH="/home/docker_user/.nvm/versions/node/v${NODE_VERSION}/bin/:${PATH}"
52 | RUN node --version
53 | RUN npm --version
54 |
55 | # ------------------------------------------------------------------------
56 | # XPM install
57 | FROM riscv_xpack_gcc_node_env AS riscv_xpack_gcc_xpm_env
58 |
59 | ARG XPACK_GCC_VERSION
60 | ARG PACKAGE
61 |
62 | ENV XPACKS_REPO_FOLDER=/home/docker_user/.xpack/repos
63 | ENV XPACKS_SYSTEM_FOLDER=/home/docker_user/.xpack/system
64 |
65 | RUN npm install --global xpm@latest
66 | RUN xpm install --global --verbose @xpack-dev-tools/${PACKAGE}@${XPACK_GCC_VERSION}
67 | # ------------------------------------------------------------------------
68 | # Just the embedded dev tools - no node or xpm
69 |
70 | FROM riscv_xpack_gcc_base_env AS riscv_xpack_gcc_dev_env
71 |
72 | ARG XPACK_GCC_VERSION
73 | ARG PACKAGE
74 |
75 | COPY --from=riscv_xpack_gcc_xpm_env /home/docker_user/.xpack/ /home/docker_user/.xpack/
76 |
77 | ENV PATH=/home/docker_user/.xpack/repos/@xpack-dev-tools/${PACKAGE}/${XPACK_GCC_VERSION}/.content/bin:/bin/:/usr/bin
78 |
79 | RUN sudo ln -s /home/docker_user/.xpack/repos/@xpack-dev-tools/${PACKAGE}/${XPACK_GCC_VERSION}/.content /opt/riscv-none-embed
80 |
81 | RUN sudo mkdir /project && sudo chown docker_user /project
82 | WORKDIR /project
83 |
--------------------------------------------------------------------------------
/examples/test-code-c/startup.c:
--------------------------------------------------------------------------------
1 | /*
2 | Simple C++ startup routine to setup CRT
3 | SPDX-License-Identifier: Unlicense
4 |
5 | (https://five-embeddev.com/ | http://www.shincbm.com/)
6 |
7 | */
8 |
9 | #include
10 | #include
11 |
12 | // Generic C function pointer.
13 | typedef void (*function_t)();
14 |
15 | // These symbols are defined by the linker script.
16 | // See linker.lds
17 | extern void *metal_segment_bss_target_start;
18 | extern void *metal_segment_bss_target_end;
19 | extern const void *metal_segment_data_source_start;
20 | extern void *metal_segment_data_target_start;
21 | extern void *metal_segment_data_target_end;
22 | extern const void *metal_segment_itim_source_start;
23 | extern void *metal_segment_itim_target_start;
24 | extern void *metal_segment_itim_target_end;
25 |
26 | extern function_t __init_array_start[];
27 | extern function_t __init_array_end[];
28 |
29 |
30 | // This function will be placed by the linker script according to the section
31 | // Raw function 'called' by the CPU with no runtime.
32 | extern void _enter(void) __attribute__ ((naked, section(".text.metal.init.enter")));
33 |
34 | // Entry and exit points as C functions.
35 | extern void _start(void) __attribute__ ((noreturn));
36 | void _Exit(int exit_code) __attribute__ ((noreturn));
37 |
38 | // Standard entry point, no arguments.
39 | extern int main(void);
40 |
41 |
42 | // The linker script will place this in the reset entry point.
43 | // It will be 'called' with no stack or C runtime configuration.
44 | // NOTE - this only supports a single hart.
45 | // tp will not be initialized
46 | void _enter(void) {
47 | // Setup SP and GP
48 | // The locations are defined in the linker script
49 | __asm__ volatile (
50 | ".option push;"
51 | // The 'norelax' option is critical here.
52 | // Without 'norelax' the global pointer will
53 | // be loaded relative to the global pointer!
54 | ".option norelax;"
55 | "la gp, __global_pointer$;"
56 | ".option pop;"
57 | "la sp, _sp;"
58 | "jal zero, _start;"
59 | : /* output: none %0 */
60 | : /* input: none */
61 | : "gp"/* clobbers: none */);
62 | // This point will not be executed, _start() will be called with no return.
63 | }
64 |
65 | // At this point we have a stack and global poiner, but no access to global variables.
66 | void _start(void) {
67 |
68 | // Init memory regions
69 | // Clear the .bss section (global variables with no initial values)
70 | memset(metal_segment_bss_target_start,
71 | 0,
72 | (metal_segment_bss_target_end - metal_segment_bss_target_start));
73 |
74 | // Initialize the .data section (global variables with initial values)
75 | memcpy(metal_segment_data_target_start,
76 | metal_segment_data_source_start,
77 | (metal_segment_data_target_end-metal_segment_data_target_start));
78 |
79 | // Initialize the .itim section (code moved from flash to SRAM to improve performance)
80 | memcpy(metal_segment_itim_target_start,
81 | metal_segment_itim_source_start,
82 | (metal_segment_itim_target_start-metal_segment_itim_target_end));
83 |
84 | // Call constructors
85 | for (unsigned int i=0; i< (__init_array_start-__init_array_end)/sizeof(function_t); i++) {
86 | __init_array_start[i]();
87 | }
88 |
89 | _Exit(main());
90 | }
91 |
92 | // This should never be called. Busy loop with the CPU in idle state.
93 | void _Exit(int exit_code) {
94 | // Halt
95 | while (1) {
96 | __asm__ volatile ("wfi");
97 | }
98 | }
99 |
--------------------------------------------------------------------------------
/examples/test-code-c/riscv.cmake:
--------------------------------------------------------------------------------
1 | #include(CMakeForceCompiler)
2 |
3 | # usage
4 | # cmake -DCMAKE_TOOLCHAIN_FILE=../cmake/rv32imac.cmake ../
5 |
6 | # Look for GCC in path
7 | # https://xpack.github.io/riscv-none-embed-gcc/
8 | FIND_FILE( RISCV_XPACK_GCC_COMPILER_EXE "riscv-none-elf-gcc.exe" PATHS ENV INCLUDE)
9 | FIND_FILE( RISCV_XPACK_GCC_COMPILER "riscv-none-elf-gcc" PATHS ENV INCLUDE)
10 |
11 | # Look for RISC-V github GCC
12 | # https://github.com/riscv/riscv-gnu-toolchain
13 | FIND_FILE( RISCV_XPACK_GCC_COMPILER_EXT "riscv32-unknown-elf-gcc.exe" PATHS ENV INCLUDE)
14 | FIND_FILE( RISCV_XPACK_GCC_COMPILER "riscv32-unknown-elf-gcc" PATHS ENV INCLUDE)
15 |
16 | # Select which is found
17 | if (EXISTS ${RISCV_XPACK_GCC_COMPILER})
18 | set( RISCV_GCC_COMPILER ${RISCV_XPACK_GCC_COMPILER})
19 | elseif (EXISTS ${RISCV_XPACK_GCC_COMPILER_EXE})
20 | set( RISCV_GCC_COMPILER ${RISCV_XPACK_GCC_COMPILER_EXE})
21 | elseif (EXISTS ${RISCV_GITHUB_GCC_COMPILER})
22 | set( RISCV_GCC_COMPILER ${RISCV_GITHUB_GCC_COMPILER})
23 | elseif (EXISTS ${RISCV_GITHUB_GCC_COMPILER_EXE})
24 | set( RISCV_GCC_COMPILER ${RISCV_GITHUB_GCC_COMPILER_EXE})
25 | else()
26 | message(FATAL_ERROR "RISC-V GCC not found. ${RISCV_GITHUB_GCC_COMPILER} ${RISCV_XPACK_GCC_COMPILER} ${RISCV_GITHUB_GCC_COMPILER_EXE} ${RISCV_XPACK_GCC_COMPILER_EXE}")
27 | endif()
28 |
29 | message( "RISC-V GCC found: ${RISCV_GCC_COMPILER}")
30 |
31 | get_filename_component(RISCV_TOOLCHAIN_BIN_PATH ${RISCV_GCC_COMPILER} DIRECTORY)
32 | get_filename_component(RISCV_TOOLCHAIN_BIN_GCC ${RISCV_GCC_COMPILER} NAME_WE)
33 | get_filename_component(RISCV_TOOLCHAIN_BIN_EXT ${RISCV_GCC_COMPILER} EXT)
34 |
35 | message( "RISC-V GCC Path: ${RISCV_TOOLCHAIN_BIN_PATH}" )
36 |
37 | STRING(REGEX REPLACE "\-gcc" "-" CROSS_COMPILE ${RISCV_TOOLCHAIN_BIN_GCC})
38 | message( "RISC-V Cross Compile: ${CROSS_COMPILE}" )
39 |
40 | # The Generic system name is used for embedded targets (targets without OS) in
41 | # CMake
42 | set( CMAKE_SYSTEM_NAME Generic )
43 | set( CMAKE_SYSTEM_PROCESSOR rv32imac_zicsr )
44 | set( CMAKE_EXECUTABLE_SUFFIX ".elf")
45 |
46 | # specify the cross compiler. We force the compiler so that CMake doesn't
47 | # attempt to build a simple test program as this will fail without us using
48 | # the -nostartfiles option on the command line
49 | #CMAKE_FORCE_C_COMPILER( "${RISCV_TOOLCHAIN_BIN_PATH}/${CROSS_COMPILE}gcc${RISCV_TOOLCHAIN_BIN_EXT}" GNU )
50 | #CMAKE_FORCE_CXX_COMPILER( "${RISCV_TOOLCHAIN_BIN_PATH}/${CROSS_COMPILE}g++${RISCV_TOOLCHAIN_BIN_EXT}" GNU )
51 | set(CMAKE_ASM_COMPILER {CROSS_COMPILE}gcc )
52 | set(CMAKE_AR ${CROSS_COMPILE}ar)
53 | set(CMAKE_ASM_COMPILER ${CROSS_COMPILE}gcc)
54 | set(CMAKE_C_COMPILER ${CROSS_COMPILE}gcc)
55 | set(CMAKE_CXX_COMPILER ${CROSS_COMPILE}g++)
56 |
57 | # We must set the OBJCOPY setting into cache so that it's available to the
58 | # whole project. Otherwise, this does not get set into the CACHE and therefore
59 | # the build doesn't know what the OBJCOPY filepath is
60 | set( CMAKE_OBJCOPY ${RISCV_TOOLCHAIN_BIN_PATH}/${CROSS_COMPILE}objcopy
61 | CACHE FILEPATH "The toolchain objcopy command " FORCE )
62 |
63 | set( CMAKE_OBJDUMP ${RISCV_TOOLCHAIN_BIN_PATH}/${CROSS_COMPILE}objdump
64 | CACHE FILEPATH "The toolchain objdump command " FORCE )
65 |
66 | # Set the common build flags
67 |
68 | # Set the CMAKE C flags (which should also be used by the assembler!
69 | set( CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -g" )
70 | set( CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -march=${CMAKE_SYSTEM_PROCESSOR}" )
71 |
72 | set( CMAKE_C_FLAGS "${CMAKE_C_FLAGS}" CACHE STRING "" )
73 | set( CMAKE_CXX_FLAGS "${CMAKE_C_FLAGS}" CACHE STRING "" )
74 | set( CMAKE_ASM_FLAGS "${CMAKE_C_FLAGS}" CACHE STRING "" )
75 | set( CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -march=${CMAKE_SYSTEM_PROCESSOR} -nostartfiles " )
76 |
77 |
--------------------------------------------------------------------------------
/examples/test-code-c/linker.lds:
--------------------------------------------------------------------------------
1 | /* Copyright (c) 2020 SiFive Inc. */
2 | /* SPDX-License-Identifier: Apache-2.0 */
3 | OUTPUT_ARCH("riscv")
4 |
5 | /* Default Linker Script
6 | *
7 | * This is the default linker script for all Freedom Metal applications.
8 | */
9 |
10 | ENTRY(_enter)
11 |
12 | MEMORY
13 | {
14 | itim (airwx) : ORIGIN = 0x8000000, LENGTH = 0x2000
15 | ram (arw!xi) : ORIGIN = 0x80000000, LENGTH = 0x4000
16 | rom (irx!wa) : ORIGIN = 0x20010000, LENGTH = 0x6a120
17 | }
18 |
19 | PHDRS
20 | {
21 | rom PT_LOAD;
22 | ram_init PT_LOAD;
23 | tls PT_TLS;
24 | ram PT_LOAD;
25 | itim_init PT_LOAD;
26 | text PT_LOAD;
27 | lim_init PT_LOAD;
28 | }
29 |
30 | SECTIONS
31 | {
32 | /* Each hart is allocated its own stack of size __stack_size. This value
33 | * can be overriden at build-time by adding the following to CFLAGS:
34 | *
35 | * -Xlinker --defsym=__stack_size=0xf00
36 | *
37 | * where 0xf00 can be replaced with a multiple of 16 of your choice.
38 | *
39 | * __stack_size is PROVIDE-ed as a symbol so that initialization code
40 | * initializes the stack pointers for each hart at the right offset from
41 | * the _sp symbol.
42 | */
43 | __stack_size = DEFINED(__stack_size) ? __stack_size : 0x400;
44 | PROVIDE(__stack_size = __stack_size);
45 |
46 | /* The size of the heap can be overriden at build-time by adding the
47 | * following to CFLAGS:
48 | *
49 | * -Xlinker --defsym=__heap_size=0xf00
50 | *
51 | * where 0xf00 can be replaced with the value of your choice.
52 | *
53 | * Altertatively, the heap can be grown to fill the entire remaining region
54 | * of RAM by adding the following to CFLAGS:
55 | *
56 | * -Xlinker --defsym=__heap_max=1
57 | *
58 | * Note that depending on the memory layout, the bitness (32/64bit) of the
59 | * target, and the code model in use, this might cause a relocation error.
60 | */
61 | __heap_size = DEFINED(__heap_size) ? __heap_size : 0x800;
62 |
63 | /* The boot hart sets which hart runs the pre-main initialization routines,
64 | * including copying .data into RAM, zeroing the BSS region, running
65 | * constructors, etc. After initialization, the boot hart is also the only
66 | * hart which runs application code unless the application overrides the
67 | * secondary_main() function to start execution on secondary harts.
68 | */
69 | PROVIDE(__metal_boot_hart = 0);
70 |
71 | /* The chicken bit is used by pre-main initialization to enable/disable
72 | * certain core features */
73 | PROVIDE(__metal_chicken_bit = 1);
74 |
75 | /* The memory_ecc_scrub bit is used by _entry code to enable/disable
76 | * memories scrubbing to zero */
77 | PROVIDE(__metal_eccscrub_bit = 0);
78 |
79 | /* The RAM memories map for ECC scrubbing */
80 | PROVIDE( metal_dtim_0_memory_start = 0x80000000 );
81 | PROVIDE( metal_dtim_0_memory_end = 0x80000000 + 0x4000 );
82 | PROVIDE( metal_itim_0_memory_start = 0x8000000 );
83 | PROVIDE( metal_itim_0_memory_end = 0x8000000 + 0x2000 );
84 |
85 | /* ROM SECTION
86 | *
87 | * The following sections contain data which lives in read-only memory, if
88 | * such memory is present in the design, for the entire duration of program
89 | * execution.
90 | */
91 |
92 | .init : {
93 | /* The _enter symbol is placed in the .text.metal.init.enter section
94 | * and must be placed at the beginning of the program */
95 | KEEP (*(.text.metal.init.enter))
96 | KEEP (*(.text.metal.init.*))
97 | KEEP (*(SORT_NONE(.init)))
98 | KEEP (*(.text.libgloss.start))
99 | } >rom :rom
100 |
101 | .fini : {
102 | KEEP (*(SORT_NONE(.fini)))
103 | } >rom :rom
104 |
105 | .preinit_array : ALIGN(8) {
106 | PROVIDE_HIDDEN (__preinit_array_start = .);
107 | KEEP (*(.preinit_array))
108 | PROVIDE_HIDDEN (__preinit_array_end = .);
109 | } >rom :rom
110 |
111 | .init_array : ALIGN(8) {
112 | PROVIDE_HIDDEN (__init_array_start = .);
113 | KEEP (*(SORT_BY_INIT_PRIORITY(.init_array.*) SORT_BY_INIT_PRIORITY(.ctors.*)))
114 | KEEP (*(.init_array EXCLUDE_FILE (*crtbegin.o *crtbegin?.o *crtend.o *crtend?.o ) .ctors))
115 | PROVIDE_HIDDEN (__init_array_end = .);
116 | PROVIDE_HIDDEN ( metal_constructors_start = .);
117 | KEEP (*(SORT_BY_INIT_PRIORITY(.metal.init_array.*)));
118 | KEEP (*(.metal.init_array));
119 | PROVIDE_HIDDEN ( metal_constructors_end = .);
120 | } >rom :rom
121 |
122 | .fini_array : ALIGN(8) {
123 | PROVIDE_HIDDEN (__fini_array_start = .);
124 | KEEP (*(SORT_BY_INIT_PRIORITY(.fini_array.*) SORT_BY_INIT_PRIORITY(.dtors.*)))
125 | KEEP (*(.fini_array EXCLUDE_FILE (*crtbegin.o *crtbegin?.o *crtend.o *crtend?.o ) .dtors))
126 | PROVIDE_HIDDEN (__fini_array_end = .);
127 | PROVIDE_HIDDEN ( metal_destructors_start = .);
128 | KEEP (*(SORT_BY_INIT_PRIORITY(.metal.fini_array.*)));
129 | KEEP (*(.metal.fini_array));
130 | PROVIDE_HIDDEN ( metal_destructors_end = .);
131 | } >rom :rom
132 |
133 |
134 |
135 | .ctors : {
136 | KEEP (*crtbegin.o(.ctors))
137 | KEEP (*crtbegin?.o(.ctors))
138 | KEEP (*(EXCLUDE_FILE (*crtend.o *crtend?.o ) .ctors))
139 | KEEP (*(SORT(.ctors.*)))
140 | KEEP (*(.ctors))
141 | KEEP (*(.metal.ctors .metal.ctors.*))
142 | } >rom :rom
143 |
144 | .dtors : {
145 | KEEP (*crtbegin.o(.dtors))
146 | KEEP (*crtbegin?.o(.dtors))
147 | KEEP (*(EXCLUDE_FILE (*crtend.o *crtend?.o ) .dtors))
148 | KEEP (*(SORT(.dtors.*)))
149 | KEEP (*(.dtors))
150 | KEEP (*(.metal.dtors .metal.dtors.*))
151 | } >rom : rom
152 |
153 | .rodata : {
154 | *(.rdata)
155 | *(.rodata .rodata.*)
156 | *(.gnu.linkonce.r.*)
157 | . = ALIGN(8);
158 | *(.srodata.cst16)
159 | *(.srodata.cst8)
160 | *(.srodata.cst4)
161 | *(.srodata.cst2)
162 | *(.srodata .srodata.*)
163 | } >rom :rom
164 |
165 | /* ITIM SECTION
166 | *
167 | * The following sections contain data which is copied from read-only
168 | * memory into an instruction tightly-integrated memory (ITIM), if one
169 | * is present in the design, during pre-main program initialization.
170 | *
171 | * Generally, the data copied into the ITIM should be performance-critical
172 | * functions which benefit from low instruction-fetch latency.
173 | */
174 |
175 | .itim : ALIGN(8) {
176 | *(.itim .itim.*)
177 | } >itim AT>rom :itim_init
178 |
179 | PROVIDE( metal_segment_itim_source_start = LOADADDR(.itim) );
180 | PROVIDE( metal_segment_itim_target_start = ADDR(.itim) );
181 | PROVIDE( metal_segment_itim_target_end = ADDR(.itim) + SIZEOF(.itim) );
182 |
183 | /* LIM SECTION
184 | *
185 | * The following sections contain data which is copied from read-only
186 | * memory into a loosely integrated memory (LIM), which is shared with L2
187 | * cache, during pre-main program initialization.
188 | *
189 | * Generally, the data copied into the LIM should be performance-critical
190 | * functions which benefit from low instruction-fetch latency.
191 | */
192 |
193 | .lim : ALIGN(8) {
194 | *(.lim .lim.*)
195 | } >ram AT>rom :lim_init
196 |
197 | PROVIDE( metal_segment_lim_source_start = LOADADDR(.lim) );
198 | PROVIDE( metal_segment_lim_target_start = ADDR(.lim) );
199 | PROVIDE( metal_segment_lim_target_end = ADDR(.lim) + SIZEOF(.lim) );
200 |
201 | /* TEXT SECTION
202 | *
203 | * The following section contains the code of the program, excluding
204 | * everything that's been allocated into the ITIM/LIM already
205 | */
206 |
207 | .text : {
208 | *(.text.unlikely .text.unlikely.*)
209 | *(.text.startup .text.startup.*)
210 | *(.text .text.*)
211 | *(.gnu.linkonce.t.*)
212 | } >rom :text
213 |
214 | /* RAM SECTION
215 | *
216 | * The following sections contain data which is copied from read-only
217 | * memory into a read-write-capable memory such as data tightly-integrated
218 | * memory (DTIM) or another main memory, as well as the BSS, stack, and
219 | * heap.
220 | *
221 | * You might notice that .data, .tdata, .tbss, .tbss_space, and .bss all
222 | * have an apparently unnecessary ALIGN at their top. This is because
223 | * the implementation of _start in Freedom Metal libgloss depends on the
224 | * ADDR and LOADADDR being 8-byte aligned.
225 | */
226 |
227 | .data : ALIGN(8) {
228 | *(.data .data.*)
229 | *(.gnu.linkonce.d.*)
230 | . = ALIGN(8);
231 | PROVIDE( __global_pointer$ = . + 0x800 );
232 | *(.sdata .sdata.* .sdata2.*)
233 | *(.gnu.linkonce.s.*)
234 | } >ram AT>rom :ram_init
235 |
236 | .tdata : ALIGN(8) {
237 | PROVIDE( __tls_base = . );
238 | *(.tdata .tdata.* .gnu.linkonce.td.*)
239 | } >ram AT>rom :tls :ram_init
240 |
241 | PROVIDE( __tdata_source = LOADADDR(.tdata) );
242 | PROVIDE( __tdata_size = SIZEOF(.tdata) );
243 |
244 | PROVIDE( metal_segment_data_source_start = LOADADDR(.data) );
245 | PROVIDE( metal_segment_data_target_start = ADDR(.data) );
246 | PROVIDE( metal_segment_data_target_end = ADDR(.tdata) + SIZEOF(.tdata) );
247 |
248 | .tbss : ALIGN(8) {
249 | *(.tbss .tbss.* .gnu.linkonce.tb.*)
250 | *(.tcommon .tcommon.*)
251 | PROVIDE( __tls_end = . );
252 | } >ram AT>ram :tls :ram
253 | PROVIDE( __tbss_size = SIZEOF(.tbss) );
254 | PROVIDE( __tls_size = __tls_end - __tls_base );
255 |
256 | .tbss_space : ALIGN(8) {
257 | . = . + __tbss_size;
258 | } >ram :ram
259 |
260 | .bss (NOLOAD): ALIGN(8) {
261 | *(.sbss*)
262 | *(.gnu.linkonce.sb.*)
263 | *(.bss .bss.*)
264 | *(.gnu.linkonce.b.*)
265 | *(COMMON)
266 | } >ram :ram
267 |
268 | PROVIDE( metal_segment_bss_source_start = LOADADDR(.tbss) );
269 | PROVIDE( metal_segment_bss_target_start = ADDR(.tbss) );
270 | PROVIDE( metal_segment_bss_target_end = ADDR(.bss) + SIZEOF(.bss) );
271 |
272 |
273 |
274 | .stack (NOLOAD) : ALIGN(16) {
275 | PROVIDE(metal_segment_stack_begin = .);
276 | . += __stack_size; /* Hart 0 */
277 | PROVIDE( _sp = . );
278 | PROVIDE(metal_segment_stack_end = .);
279 | } >ram :ram
280 |
281 | .heap (NOLOAD) : ALIGN(8) {
282 | PROVIDE( __end = . );
283 | PROVIDE( __heap_start = . );
284 | PROVIDE( metal_segment_heap_target_start = . );
285 | /* If __heap_max is defined, grow the heap to use the rest of RAM,
286 | * otherwise set the heap size to __heap_size */
287 | . = DEFINED(__heap_max) ? MIN( LENGTH(ram) - ( . - ORIGIN(ram)) , 0x10000000) : __heap_size;
288 | PROVIDE( metal_segment_heap_target_end = . );
289 | PROVIDE( _heap_end = . );
290 | PROVIDE( __heap_end = . );
291 | } >ram :ram
292 |
293 | /* C++ exception handling information is
294 | * not useful with our current runtime environment,
295 | * and it consumes flash space. Discard it until
296 | * we have something that can use it
297 | */
298 | /DISCARD/ : {
299 | *(.eh_frame .eh_frame.*)
300 | }
301 | }
302 |
--------------------------------------------------------------------------------