diff --git a/docs/docker/Dockerfile.builds b/docs/docker/Dockerfile.builds new file mode 100644 index 000000000..9b16f7880 --- /dev/null +++ b/docs/docker/Dockerfile.builds @@ -0,0 +1,83 @@ +FROM wallysoc/ubuntu_wally + +# SET ENVIRONMENT VARIABLES +# assume 4 threads are available to speed up +ARG NUM_THREADS=4 +ENV RISCV=/opt/riscv + +WORKDIR /opt/riscv + +# TOOLCHAIN +RUN git clone https://github.com/riscv/riscv-gnu-toolchain && \ + cd riscv-gnu-toolchain && \ + sed -i 's/https/git/' .gitmodules && git submodule sync && \ + ./configure --prefix=${RISCV} --enable-multilib \ + --with-multilib-generator="rv32e-ilp32e--;rv32i-ilp32--;rv32im-ilp32--;rv32iac-ilp32--;rv32imac-ilp32--;rv32imafc-ilp32f--;rv32imafdc-ilp32d--;rv64i-lp64--;rv64ic-lp64--;rv64iac-lp64--;rv64imac-lp64--;rv64imafdc-lp64d--;rv64im-lp64--;" && \ + make --jobs ${NUM_THREADS} && \ + make install && cd ${RISCV} && \ + rm -rf ${RISCV}/riscv-gnu-toolchain + +# # TOOLCHAIN +# RUN git clone https://github.com/riscv/riscv-gnu-toolchain && \ +# cd riscv-gnu-toolchain && \ +# sed -i 's/https/git/' .gitmodules && git submodule sync && \ +# ./configure --prefix=${RISCV} --enable-multilib \ +# --with-multilib-generator="rv32e-ilp32e--;rv32i-ilp32--;rv32im-ilp32--;rv32iac-ilp32--;rv32imac-ilp32--;rv32imafc-ilp32f--;rv32imafdc-ilp32d--;rv64i-lp64--;rv64ic-lp64--;rv64iac-lp64--;rv64imac-lp64--;rv64imafdc-lp64d--;rv64im-lp64--;" + +# RUN cd riscv-gnu-toolchain && make --jobs ${NUM_THREADS} +# RUN cd riscv-gnu-toolchain && make install && cd ${RISCV} +# RUN cd riscv-gnu-toolchain && rm -rf ${RISCV}/riscv-gnu-toolchain + +# elf2hex +RUN git clone https://github.com/sifive/elf2hex.git && \ + cd elf2hex && \ + autoreconf -i && \ + ./configure --target=riscv64-unknown-elf --prefix=${RISCV} && \ + make && \ + make install && cd ${RISCV} && \ + rm -rf ${RISCV}/elf2hex + +# QEMU +RUN git clone --recursive https://github.com/qemu/qemu && \ + cd qemu && \ + ./configure --target-list=riscv64-softmmu --prefix=${RISCV} && \ + make --jobs ${NUM_THREADS} && \ + make install && cd ${RISCV} && \ + rm -rf ${RISCV}/qemu + +# Spike +RUN git clone https://github.com/riscv-software-src/riscv-isa-sim && \ + mkdir riscv-isa-sim/build && \ + cd riscv-isa-sim/build && \ + ../configure --prefix=$RISCV --enable-commitlog && \ + make --jobs ${NUM_THREADS} && \ + make install && cd ${RISCV} && \ + rm -rf ${RISCV}/riscv-isa-sim + +# SAIL +RUN opam init -y --disable-sandboxing && \ + opam switch create 5.1.0 && \ + opam install sail -y && \ + eval $(opam config env) && \ + git clone https://github.com/riscv/sail-riscv.git && \ + cd sail-riscv && \ + ARCH=RV32 make c_emulator/riscv_sim_RV32 && \ + ARCH=RV64 make c_emulator/riscv_sim_RV64 && \ + ln -s ${RISCV}/sail-riscv/c_emulator/riscv_sim_RV64 ${RISCV}/bin/riscv_sim_RV64 && \ + ln -s ${RISCV}/sail-riscv/c_emulator/riscv_sim_RV32 ${RISCV}/bin/riscv_sim_RV32 && \ + rm -rf ${RISCV}/sail-riscv + +# Buildroot +RUN git clone https://github.com/buildroot/buildroot.git && \ + cd buildroot && \ + git checkout 2021.05 && \ + # cp -r /opt/riscv/riscv-wally/linux/buildroot-config-src/wally ./board && \ + # cp ./board/wally/main.config .config && \ + wget https://raw.githubusercontent.com/openhwgroup/cvw/main/linux/buildroot-config-src/wally/main.config -o .config && \ + make --jobs ${NUM_THREADS} + +RUN pip3 install --no-cache-dir \ + testresources riscv_config \ + git+https://github.com/riscv/riscof.git + +USER ${USERNAME} \ No newline at end of file diff --git a/docs/docker/Dockerfile.ubuntu b/docs/docker/Dockerfile.ubuntu new file mode 100644 index 000000000..3347c6ce9 --- /dev/null +++ b/docs/docker/Dockerfile.ubuntu @@ -0,0 +1,33 @@ +FROM ubuntu:22.04@sha256:aa772c98400ef833586d1d517d3e8de670f7e712bf581ce6053165081773259d + +# Create a user group 'xyzgroup' +ARG USERNAME=cad +ARG USER_UID=1000 +ARG USER_GID=$USER_UID + +RUN apt update && \ + apt install -y \ + git gawk make texinfo bison flex build-essential python3 libz-dev libexpat-dev autoconf device-tree-compiler ninja-build libpixman-1-dev build-essential ncurses-base ncurses-bin libncurses5-dev dialog curl wget ftp libgmp-dev python3-pip pkg-config libglib2.0-dev opam z3 zlib1g-dev automake autotools-dev libmpc-dev libmpfr-dev gperf libtool patchutils verilator cpio bc vim emacs gedit nano && \ + apt-get clean + +# COPY requirements.txt /root +RUN pip3 install --no-cache-dir \ + sphinx sphinx_rtd_theme matplotlib scipy scikit-learn adjustText lief + +RUN ln -s /usr/bin/python3 /usr/bin/python + +# Create the user +RUN groupadd --gid $USER_GID ${USERNAME} \ + && useradd --uid $USER_UID --gid $USER_GID -m ${USERNAME} \ + # [Optional] Add sudo support. Omit if you don't need to install software after connecting. + && apt-get update \ + && apt-get install -y sudo \ + && echo ${USERNAME} ALL=\(root\) NOPASSWD:ALL > /etc/sudoers.d/${USERNAME} \ + && chmod 0440 /etc/sudoers.d/${USERNAME} + +# Change RISCV user +RUN chown -Rf cad:cad /opt + +# Add cad user +USER ${USERNAME} +WORKDIR /home/${USERNAME} \ No newline at end of file diff --git a/docs/docker/README.md b/docs/docker/README.md new file mode 100644 index 000000000..af9acf307 --- /dev/null +++ b/docs/docker/README.md @@ -0,0 +1,131 @@ +# Consistant Build of Toolchain for Wally + +`Dockerfile.*` contains a ~~multi-stage~~ build for all the toolchains that are required for Wally's open-source features. + +## TODOs + +- [ ] Pinning the tools version + - As for the consistent tool build, should we use specific versions of tools in order to avoid bugs at the master branch? + - And we will upgrade the versions of tool after a certain period of time to get the latest features and patches while verifying it won’t cause any problem. +- [ ] Mount the EDA Tools and Path +- [x] Enable X11 forwarding for docker + - `--network=host` for docker run + - `xhost +localhost:${USER}` for host + +## TL;DR + +Files at this folder can help you to build/fetch environment you need to run wally with the help of Docker. + +Here are some common use cases, read the following text for other configuration: + +```shell +# For HMC students, /opt/riscv is available and nothing needs to be built, skip this file + +# For those with all the toolchains installed, simply mount the toolchains +TOOLCHAINS_MOUNT= ./start + +# For those have nothing, fetching the builds are easiest thing +./start + +# For other cases, checkout start-up script for building option +``` + +## New Dockerfile Design + +There are two parts of the new docker-related design: + +- build proper image(s) +- set up start-up script + +### Problem Statement + +The following 3 problems are to be resolved: + +- remove storage of useless files with `Dockerfile` + - git build: clean up + - packages info + - apt: `apt-get clean` + - pip: `--no-cache-dir` +- reuse storage + - read-only $RISCV volume across different users with `docker image` + - local-built RISCV with `start-up script` +- use commercial EDA tools: optional environment variable configuration with `start-up script` + +### Dockerfiles + +There are two Dockerfiles: + +- `Dockerfile.ubuntu`: basic ubuntu system setup and produce `ubuntu_wally` image in docker + - corresponds to `wallysoc/ubuntu_wally` +- `Dockerfile.builds`: all the required toolchains are built + - corresponds to `wallysoc/toolchains_wally` + +Because we are going to use the whole environment of ubuntu to get both executables and python packages, we are not going to use multi-stage builds, which runs only executables. + +### Scripts + +There are two scripts: + +- `get_images.sh`: get docker image `wallysoc/ubuntu_wally` or `wallysoc/toolchains_wally` +- `start.sh`: start running the container + +#### Image Building Script + +Options (if you want to build the images): + +- UBUNTU_BUILD: value other than 0 +- TOOLCHAINS_BUILD: value other than 0 + +#### Start-up Script + +There are two settings: + +- build/fetch both ubuntu_wally and toolchains in docker image and use it +- build/fetch only ubuntu_wally and use local toolchains folder + +Options: + +- ubuntu_wally: fetch by default + - build: UBUNTU_BUILD=1 +- toolchains: fetch by default + - build: TOOLCHAINS_BUILD=1 + - use local toolchain: TOOLCHAINS_MOUNT + +### Commercial EDA Tools + +This is kind of tricky, because Docker network is a different network from the host. Therefore, it should be carefully handled in order to use the host's license server while minimizing the access of docker container. + +There are at least two ways to solve this problem: + +- use `--network=host` in docker-run to use the same network +- (NOT WORKING) use bridge in docker-run while forwarding docker network's traffic to localhost without setting `X11UseLocalhost no` + - this idea is from https://stackoverflow.com/a/64284364/10765798 + +## Old Dockerfile Analysis + +> Refer to https://github.com/openhwgroup/cvw/blob/91919150a94ccf8e750cf7c9eec1c400efaef7f5/docs/Dockerfile + +There are stages in the old Dockerfile: + +- debian-based package installtion + - apt package + - python3 package +- user and its group configuration +- clone and build toolchain with prefix=$RISCV + - riscv-gnu-toolchain + - elf2hex + - qemu + - spike + - sail + - buildroot + +## References + +- Dockerfile Docs: https://docs.docker.com/reference/dockerfile/ +- Multi-stage builds: https://docs.docker.com/build/building/multi-stage/ +- Best Practices: https://docs.docker.com/develop/develop-images/guidelines/ +- Chinese Reference: https://yeasy.gitbook.io/docker_practice/ +- Clean Cache + - apt cache: https://gist.github.com/marvell/7c812736565928e602c4 + - pip cache: https://stackoverflow.com/questions/50333650/install-python-package-in-docker-file +- Docker Network: https://docs.docker.com/network/ diff --git a/docs/docker/get_images.sh b/docs/docker/get_images.sh new file mode 100755 index 000000000..39b844a31 --- /dev/null +++ b/docs/docker/get_images.sh @@ -0,0 +1,20 @@ +UBUNTU_BUILD=${UBUNTU_BUILD:-0} +TOOLCHAINS_BUILD=${TOOLCHAINS_BUILD:-0} + +# if UBUNTU_BUILD is 0, then call function fetch_ubuntu_image +# otherwise, call function build_ubuntu_image +if [ $UBUNTU_BUILD -eq 0 ]; then + docker pull wallysoc/ubuntu_wally +else + docker build -t ubuntu_wally -f Dockerfile.ubuntu . + docker tag ubuntu_wally:latest wallysoc/ubuntu_wally:latest +fi + +# if TOOLCHAINS_BUILD is 0, then call function fetch_toolchains_image +# otherwise, call function build_toolchains_image +if [ $TOOLCHAINS_BUILD -eq 0 ]; then + docker pull wallysoc/wally_toolchains +else + docker build -t wally_toolchains -f Dockerfile.builds . + docker tag wally_toolchains:latest wallysoc/wally_toolchains:latest +fi \ No newline at end of file diff --git a/docs/docker/start.sh b/docs/docker/start.sh new file mode 100755 index 000000000..8adfe81f1 --- /dev/null +++ b/docs/docker/start.sh @@ -0,0 +1,22 @@ +UBUNTU_WALLY_HASH=$(docker images --quiet wallysoc/ubuntu_wally) +TOOLCHAINS_HASH=$(docker images --quiet wallysoc/toolchains_wally) +TOOLCHAINS_MOUNT=${TOOLCHAINS_MOUNT} + +if [ -z $UBUNTU_WALLY_HASH ]; then + echo "CANNOT FIND wallysoc/ubuntu_wally, please get the image first with \`get_image.sh\`"; + exit 1 +else + echo "Get ${UBUNTU_WALLY_HASH} for ubuntu_wally" +fi + +if [ ! -z $TOOLCHAINS_MOUNT ]; then + docker run -it --rm -v ${TOOLCHAINS_MOUNT}:/opt/riscv wallysoc/ubuntu_wally +elif [ -z $TOOLCHAINS_HASH ]; then + echo "CANNOT FIND wallysoc/toolchains_wally, please get the image first with \`get_image.sh\`"; + exit 1 +else + echo "Get ${TOOLCHAINS_HASH} for toolchains_wally" + docker run -it --rm wallysoc/toolchains_wally +fi + +echo "Successfully reach the end"