Setup
Development Environment Guide
This guide is based on the cs300 lab for setting up your development environment.
If you would like to try out a possibly faster setup by running natively, jump to the Advanced section at the bottom of the page.
Setting up the devenv
You’ll need to install some pre-requisite programs (Docker and X) and then run our setup scripts.
Installing Docker
Docker is a convenient way to manage virtual environments as “containers.” We will be using it to run Ubuntu 22.04 (jammy), a Linux-based operating system. If you’ve taken CS 300, the container setup will be very similar with a few extra tools preinstalled. X will allow a Docker container to run graphical applications that appear on your host computer.
Download Docker here. On Linux machines, follow the instructions here.
After downloading Docker, follow Docker’s instructions to install it on your OS. Accept if Docker asks for privileged access.
On Windows or Mac OS, open the Docker Desktop application after it has been installed. You may see a message similar to “Docker Desktop is Starting…”. Once this message goes away, your Docker has started successfully!
Verify Docker is installed by executing the following command in a terminal:
$ docker --version
A Docker version number should be printed.
After installing Docker, a Docker process (the Docker daemon) will run in the background. Run the following command to verify:
$ docker info
This should print some information about your Docker installation.
If you see the following error:
ERROR: Cannot connect to the Docker daemon at unix:///var/run/docker.sock. Is the docker daemon running?
it means Docker hasn’t started running yet. On Windows or Mac OS, ensure your Docker Desktop is running. On Linux, try the command sudo systemctl docker restart in a terminal.
Once Docker Desktop is running, modify the default docker resource settings. Open up Docker Desktop and click on the setting symbol in the top right. Go to the ‘Resources’ tab and set the CPU limit to at least 8, the memory limit to at least 8 GB, the swap to the maximum available, and the virtual disk limit to at least 64 GB.
Windows only: To change the resource settings, make a file called .wslconfig in your home directory in Windows, with the following contents:
[wsl2]
swap=4GB
(Windows only) Installing an Ubuntu distro on WSL
To run scripts for this class, you will need to set up Windows Subsystem for Linux (WSL). WSL should already be enabled after you install Docker, but you may still need to install a Linux distribution. This will run in an actual Linux VM, and you will run your Docker container within that VM.
1. Do I have a Linux distribution (Linux distro) installed?
- Run
wsl -l -vin the Command Prompt or Powershell. If there is only “Docker Desktop” and “Docker Desktop Data”, you do not have a Linux distribution installed. Proceed to step 2. Otherwise, you have a Linux distro installed. Proceed to step 3. 2. Install a Linux Distribution. - Run
wsl --set-default-version 2to ensure Ubuntu will be installed under WSL 2. - Install “Ubuntu 20.04” from Microsoft Store. (link here) -Click “Open” after Ubuntu is downloaded. A terminal will open and guide you through the installation process. 3. Ensure your Linux Distribution runs on WSL 2.
- From the output of
wsl -l -v, find out if your LinWux distro is using WSL 1 or WSL 2. - If it’s WSL1: run
wsl --set-version <distro name> 2to update your distro to use WSL 2. 4. Set your default Linux distro - Run
wsl --setdefault <distro-name>to configure your default Linux distro.should be “Ubuntu-20.04” if you installed using step 2.
Run wsl in your Command Prompt or Powershell, and you’ll enter into your WSL! You will also need to connect Docker with WSL. To do so, open your Docker Desktop’s settings (on its top right corner), click “Resources”, “WSL integration”, then enable integration with your Linux distro. Then, click “Apply and Restart”.
**Make sure to run the docker commands below (in “Setting up the dev environment”) from WSL, instead of from PS/cmd/git bash!! **
Installing X Server
X11, or X Window Subsystem is a framework that powers most GUI applications in Linux. Ripes requires a GUI interface, so in order to run it within a Docker container, we need to connect to a program on the host (the X server) that can draw its window.
Instructions for MacOS
Download and install XQuartz here. Run the installer and allow the app to make changes to your computer when prompted. During installation, you may be asked to log out and log back into your computer in order to update your system environment.
Once XQuartz is installed, open it from the applications menu. After it opens, navigate to the menu bar at the top of your screen and select XQuartz > Preferences. Go to the Security tab and check the box labeled "Allow connections from network clients". This will allow the container to connect to your X server.
Quit XQuartz by selecting XQuartz > Quit from the menu bar. XQuartz should reopen automatically when you start the container later.
Instructions for Windows
Download and install VcXsrv here. Run the installer (the default options should be fine), and allow the app to make changes to your computer when prompted.
After installing VcXsrv, run it from the start menu. If presented with any questions, accept the defaults. Once VcXsrv has finished starting, you should see it running in your system tray (bottom right corner of the screen).
NOTE: Each time you restart your computer, you will need to start VcXsrv whenever you need to run the container.
Instructions for Linux
Linux most likely has an X server already installed so you shouldn't have to do much here!
Check if you have xhost by running which xhost.
If xhost is not found, you will need to install it on your system. On Ubuntu or Debian, you can
do this by running sudo apt-get install x11-xserver-utils. On other distributions, you will
need to install a similar package (the name may be different though).
Once you have installed xhost, which xhost should print something similar to /usr/bin/xhost.
Getting the devenv
In Docker, an environment is defined as a Docker image. An image specifies the operating system environment that a container provides. An image can also contain additional software dependencies and configurations. These instructions are specified in a file, the so-called Dockerfile. We’ve pre-built the Docker image you need for the course, which the scripts below will pull and run.
You will now download the course’s setup code and create the CS 1952Y Docker image!
Mac OS only: Install Apple development tools
If you're running on Mac OS, you will need to install a set of Apple-recommended command-line tools via the following command:
xcode-select --install
This ensures that your computer has installed git, a program we'll use later. Alternatively,
you may also download and install git directly, following instructions from here.
Do the following to set up your development environment. On Windows, remember that you are running your commands from WSL!
-
Enter the directory on your computer where you want to do your coursework. We suggest making a
cs1952ydirectory or similar. Note: For Windows users, change to a drive on the linux mount to make file permissions and speed of file transfer work better (simply runningcdorcd ~, OR runningwsl ~to start WSL will get you into the linux mount’s home directory). Try not to store things on Windows drives (e.g./mnt/cas the C:/ drive appears on WSL) when working in WSL. -
Run
git clone git@github.com:browncs1952y/devenv-s26.gitto clone our development environment -
Run
cd devenv-s26 -
Inside this folder, run
./setup_docker.sh. This will attempt to pull our Docker image that has been prebuilt and copy over the gem5 and Ripes directories to the parent folder (that is, the directory you created in step 1 will contain three subdirectories:Ripes,gem5, anddevenv-s26). If you’re curious about the message at the end about using your own git repository, we address that lower down in this document. -
If this succeeds, you can enter the dev environment using
./run_docker.sh. You can now interact with the shell of the container. You can useCtrl-Dto exit.
Using the devenv
Confirming that the devenv works
To confirm that the dev environment is set up correctly, you can check whether the Ripes GUI is working. From the docker container, run each of these commands:
cd ~/Ripes
make -j8
./Ripes
the second command shouldn’t take long because the Docker image comes with Ripes precompiled (let the course staff know if this is not the case!). After the last command, a GUI screen called Ripes should pop up. Let the course staff know if it doesn’t.
To confirm that gem5 builds, from the docker container, run
cd ~/gem5
build-gem5
Again, if the last command takes a very long time, please let the course staff know.
Pulling updates to the container
Do the following to pull updates to the container (note that this will solely update your local Docker image, not the Dockerfile itself) If your top-level directory from step 1 above is CS1952y-DIR:
-
Move the
CS1952y-DIR/gem5andCS1952y-DIR/Ripesdirectories to a safe backup location and then delete the originals (the setup script won’t run if these directories exist). -
From
CS1952y-DIR/devenv-s26, rerunsetup_docker.sh -
Remove the existing container and restart it using
run_docker.sh --clean
If you also want to pull all updates to the Dockerfiles and scripts within the dev environment repo, you can run git pull from CS1952y-DIR/devenv-s26.
Editing files
You might notice that CS1952y-DIR/gem5 and CS1952y-DIR/Ripes persist on your computer even when the container is stopped. This is by design. Don’t move these folders unless you’re re-running the setup step!
You can edit your source code inside the course container, or on your normal operating system. When the container runs, it uses a mount of your local gem5 and Ripes directories. This means that you can install any editor or IDE of your choice on your local machine, edit your files and work on your assignments locally, and all of your changes will be reflected in your container! You can then compile, build, and run your assignments inside your container. You can use whatever editor you want.
If you’re using VSCode, these instructions from CS 300 have a nice way to integrate VSCode with Docker.
Integrating with git
You might have seen this message after running setup_docker.sh:
Your work will now be saved locally in the ../Ripes and ../gem5 directories.
We recommend configuring the git URLs of these directories to your own copy, e.g.
cd ../Ripes
git remote set-url origin NEW_URL
where NEW_URL is the URL of your personal Ripes repository
In homework 1 (the first homework to use Ripes) and homework 3 (the first homework to use gem5), we’ll provide github classroom links that will automatically create a fork of our Ripes and gem5 repositories. You can use the command above in the Ripes (and gem5) folders to use git with the devenv. We highly recommend that you do this, as this will allow you to use the repository as backup for your work (as long as you commit and push regularly!) and it will also allow the course staff easy access to your code for debugging help.
Building RISCV programs
The image comes with the gnu-riscv-toolchain installed in /opt/riscv. The directory has been added to PATH, meaning that you can acccess all of the riscv64-unknown-elf-* tools (such as riscv64-unknown-elf-gcc and riscv64-unknown-elf-objdump) just by typing the relevant command. You can see all of the commands by typing riscv64 and pressing tab.
Using gcc for various extensions of RISCV: we built the toolchain with multilib enabled, which means that gcc will take march and mabi flags and build to different versions of RISCV. Here are some examples on a file called prog.c compiled to the output prog.o (note that the command always starts with riscv64, even when building a 32-bit binary). If you want to use the resulting binaries with Ripes (not something this course requires), this requires a little extra finagling and doesn’t always work as expected. The static flag is recommended to build a standalone binary, and -lm links in the math libraries.
riscv64-unknown-elf-gcc -march=rv32i -mabi=ilp32 prog.c -o prog.o -static -lm # 32-bit base instruction set
riscv64-unknown-elf-gcc -march=rv32imc -mabi=ilp32 prog.c -o prog.o -static -lm # 32-bit instruction set + M and C extensions
riscv64-unknown-elf-gcc -march=rv64i -mabi=lp64 prog.c -o prog.o -static -lm # 64-bit base instruction set
For more options, see the riscv-gnu-toolchain documentation.
Objdump (getting assembly from compiled binary): The command riscv64-unknown-elf-objdump -d prog.o (or whatever your binary is) will give you a disassembled version of your program.
Advanced: installing natively
We’ll be modifying and re-building both Ripes and gem5, which, depending on your host computer, can be slow inside of a Docker container. If you would like to run natively in a Unix environment (including WSL without Docker) to speed this process up, here are the commands that we used to install Ripes, gem5, and their pre-requisites. Note that your computer might be different, so it might take some troubleshooting and searching the web to try to get this setup done. If all else fails, please use the Docker instructions above!
*Note: these instructions do not include gnu-riscv-toolchain. To build that, follow the instructions provided by that tool. Remember to run configure with --enable-multilib in order to get multilib support.
Ripes
Make sure that the start of CMAKE_PREFIX_PATH goes to the Qt.6.8.0 directory you created in the first step. If you run these lines from your home directory, the path will be correct.
sudo apt install cmake python3 ninja-build
sudo apt install libegl1-mesa-dev '^libxcb.*-dev' libx11-xcb-dev libglu1-mesa-dev libxrender-dev libxi-dev libxkbcommon-dev libxkbcommon-x11-dev
mkdir Qt6.8.0 # or wherever you want to install Qt
cd Qt6.8.0
# the following is one command (no newlines)
wget https://download.qt.io/official_releases/qt/6.8/6.8.0/submodules/qtbase-everywhere-src-6.8.0.tar.xz https://download.qt.io/official_releases/qt/6.8/6.8.0/submodules/qtcharts-everywhere-src-6.8.0.tar.xz https://download.qt.io/official_releases/qt/6.8/6.8.0/submodules/qtsvg-everywhere-src-6.8.0.tar.xz
for f in *.tar.xz; do tar xvf "$f"; done
rm *.tar.xz
mkdir install
cd qtbase-everywhere-src-6.8.0
./configure -prefix $(pwd)/../install # might take a while
cmake --build . --parallel # *will* take a while
cmake --install .
# UPDATE IF NEEDED to wherever the Qt6.8.0/install folder is
export CMAKE_PREFIX_PATH=$HOME/Qt6.8.0/install
cd ../qtcharts-everywhere-src-6.8.0
$CMAKE_PREFIX_PATH/bin/qt-configure-module .
cmake --build . --parallel
cmake --install .
cd ../qtsvg-everywhere-src-6.8.0
$CMAKE_PREFIX_PATH/bin/qt-configure-module .
cmake --build . --parallel
cmake --install .
cd # go back to home directory
git clone --recursive https://github.com/browncs1952y/Ripes-1952y.git Ripes
cd Ripes
cmake .
make -j8
Test that Ripes runs using the following command (you can also open the Ripes GUI by simply running ./Ripes):
./Ripes --mode cli --src examples/assembly/complexMul.s -t asm --proc RV32_SS --isaexts M
To make it easier to rebuild Ripes, add the line export CMAKE_PREFIX_PATH=$HOME/Qt6.8.0/install to the bottom of your .bashrc file (this file is found in your home directory. You can edit it with any text editor). Then, to rebuild Ripes, simply change to the top-level Ripes directory and run make -j8. There is usually no need to rerun the cmake command unless you are starting from scratch.
gem5
Warning: the gem5 build (final command) will take a while
apt install build-essential git m4 scons zlib1g zlib1g-dev libprotobuf-dev protobuf-compiler libprotoc-dev libgoogle-perftools-dev -y
# Install the mold linker (fastest for gem5)
mkdir mold && cd mold # or wherever you want to install mold
git clone --branch stable https://github.com/rui314/mold.git
sudo ./install-build-deps.sh
cmake -DCMAKE_BUILD_TYPE=Release -DCMAKE_CXX_COMPILER=c++ -B build
cmake --build build -j8
sudo cmake --build build --target install
cd # home directory (or wherever you want to be)
# set up gem5 build command
echo "alias build-gem5=\"scons build/RISCV/gem5.debug -j 8 --linker=mold\"" >> ~/.bashrc
source ~/.bashrc
# install gem5
git clone --recursive https://github.com/browncs1952y/gem5-assignments-stencil gem5
cd gem5
build-gem5
Test that gem5 runs with the following command (note that the first part will replace the /gem5_build/gem5.debug path from the assignment instructions)
./build/RISCV/gem5.debug configs/learning_gem5/part1/simple-riscv.py