Using the CS 3410 Infrastructure
The coursework for CS 3410 mainly consists of writing and testing programs in C and RISC-V assembly. You will need to use the course’s provided infrastructure to compile and run these programs.
Course Setup Video
We have provided a video tutorial detailing how to get started with the course infrastructure. Feel free to read the instructions below instead—they are identical to what the video describes.
Setting Up with Docker
This semester, you will use a Docker container that comes with all of the infrastructure you will need to run your programs.
The first step is to install Docker. Docker has instructions for installing it on Windows, macOS, and on various Linux distributions. Follow the instructions on those pages to get Docker up and running.
For Windows users: to type the commands in these pages, you can choose to use either the Windows Subsystem for Linux (WSL) or PowerShell. PowerShell comes built in, but you have to install WSL yourself. On the other hand, WSL lets your computer emulate a Unix environment, so you can use more commands as written. If you don’t have a preference, we recommend WSL.
Check your installation by opening your terminal and entering:
docker --version
Now, you’ll want to download the container we’ve set up. Enter this command:
docker pull ghcr.io/sampsyo/cs3410-infra
If you get an error like this: “Cannot connect to the Docker daemon at [path]. Is the docker daemon running?”, you need to ensure that the Docker desktop application is actively running on your machine. Start the application and leave it running in the background before proceeding.
This command will take a while. When it’s done, let’s make sure it works! First, create the world’s tiniest C program by copying and pasting this command into your terminal:
printf '#include <stdio.h>\nint main() { printf("hi!\\n"); }\n' > hi.c
(Or, you can just use a text editor and write a little C program yourself.)
Now, here are two commands that use the Docker container to compile and run your program.
docker run -i --rm -v ${PWD}:/root ghcr.io/sampsyo/cs3410-infra gcc hi.c
docker run -i --rm -v ${PWD}:/root ghcr.io/sampsyo/cs3410-infra qemu a.out
If your terminal prints “hi!” then you’re good to go!
You won’t need to learn Docker to do your work in this course. But to explain what’s going on here:
docker run [OPTIONS] ghcr.io/sampsyo/cs3410-infra [COMMAND]
tells Docker to run a given command in the CS 3410 infrastructure container.- Docker’s
-i
option makes sure that the command is interactive, in case you need to interact with whatever’s going on inside the container, and--rm
tells it not to keep around an “image” of the container after the command finishes (which we definitely don’t need). -v ${PWD}:/root
uses a Docker volume to give the container access to your files, likehi.c
.
After all that, the important part is the actual command we’re running.
gcc hi.c
compiles the C program (using GCC) to a RISC-V executable called a.out
.
Then, qemu a.out
runs that program (using QEMU).
Make an rv
Alias
The Docker command above is a lot to type every time! To make this easier, we can use a shell alias.
On macOS, Linux, and WSL
Try copying and pasting this command:
alias rv='docker run -i --rm -v "$PWD":/root ghcr.io/sampsyo/cs3410-infra'
Now you can use much shorter commands to compile and run code.
Just put rv
before the command you want to run, like this:
rv gcc hi.c
rv qemu a.out
Unfortunately, this alias will only last for your current terminal session.
To make it stick around when you open a new terminal window, you will need to add the alias rv=...
command to your shell’s configuration file.
First type this command to find out which shell you’re using:
echo $SHELL
It’s probably bash or zsh, in which case you need to edit .bashrc
or .zshrc
in your home directory.
Here is a command you can copy and paste, but fill in the appropriate file according to your shell:
echo "alias rv='docker run -i --rm -v \"\$PWD\":/root ghcr.io/sampsyo/cs3410-infra'" >> ~/.bashrc
Change that ~/.bashrc
at the end to ~/.zshrc
if your shell is zsh.
On Windows with PowerShell (Not WSL)
(Remember, if you’re using WSL on Windows, please use the previous section.)
In PowerShell, we will create a shell function instead of an alias.
We assume that you have created a cs3410
directory on your computer where you’ll be storing all your code files.
First, open Windows PowerShell ISE (not the plain PowerShell) by typing it into the Windows search bar.
There will be an editor component at the top, right under Untitled1.ps1
.
There, paste the following:
Function rv_d { docker run -i --rm -v ${PWD}:/root ghcr.io/sampsyo/cs3410-infra $args[0] $args[1] }
This will create a function called rv_d
that takes two arguments (we’ll see what those are in a bit). We’re naming it rv_d
and not just rv
(as done in the next section) because PowerShell already has a definition for rv
. The “d” stands for Docker.
Then, in the top left corner, click “File → Save As” and name your creation. Here, we’ll use function_rv_d
. Finally, navigate to the cs3410
folder that stores all your work and once you’re there, hit “Save.”
Assuming you don’t delete it, that file will forever be there. This is how we put it to work:
Every time you’d like to run those long docker commands, open PowerShell (the plain one, not the ISE) and navigate to your cs3410
folder. Then, enter the following command:
. .\function_rv_d.ps1
This will run the code in that script file, therefore defining the rv_d
function in your current PowerShell session. Then, navigate to wherever the .c
file you’re working on is located (we assume it’s called file.c
) and to compile it, simply type rv_d gcc file.c
. Finally, to run the compiled code, enter rv_d qemu a.out
. Try it out with your hi.c
file.
Debugging C Code
GDB is an incredibly useful tool for debugging C code. It allows you to see where errors happen and step through your code one line at a time, with the ability to see values of variables along the way. Learning how to use GDB effectively will be very important to you in this course.
Entering GDB Commandline Mode
First, make sure to compile your source files with the -g
flag. This flag will add debugging symbols to the executable that will allow GDB to debug much more effectively. For example, running:
rv gcc -g -Wall -Wextra -Wpedantic -Wshadow -Wformat=2 -std=c17 hi.c
In order to use gdb
in the 3410 container, you need to open two terminals: one for running qemu
with the debug mode in the background; and the other for invoking gdb
and iteract with it.
- First, open a new terminal, and type the following commands:
docker run -i --rm -v `pwd`:/root --name cs3410 ghcr.io/sampsyo/cs3410-infra:latest
. Feel free the change the “name” fromcs3410
to any name you prefer.rv gcc -g -Wall ... (more flags) EXECUTABLE SOURCE.c
. Once you have entered the container, compile your source file with the-g
flag and any other recommended commands.qemu -g 1234 EXECUTABLE ARG1 ... (more arguments)
. Now you can start executingqemu
with the debug mode and invoke the executable fileEXECUTABLE
with any arguments you need to pass in.
- Then, open another terminal, and type the following commands:
docker exec -i cs3410 /bin/bash
, wherecs3410
is the placeholder for the name of the container you are running in the background via the first terminal.gdb --args EXECUTABLE ARG1 ... (more arguments)
to start executing the GDB.target remote localhost:1234
: execute this inside the GDB. It instructs GDB to perform remote debugging by connecting it to listen to the specified port.- Start debugging!
- Once you
quit
a GDB session, you need to go back to the first terminal to spin up theqemu
again (Step 1.3) and then invoke GDB again (Step 2.2 and onwards).
Checking for Common C Errors
Here are some important limitations of this method:
- You’ll have to run that script file every time you open a new PowerShell session.
- This function assumes you’ll only be using it to execute
rv_d gcc file.c
andrv_d qemu a.out
(wherefile.c
anda.out
are the.c
file and corresponding executable in question). For anything else, thisrv_d
function doesn’t work. For those, you’d have to type in the entire Docker command and then whatever else after. Another incentive to go the WSL route.
Set Up Visual Studio Code
You can use any text editor you like in CS 3410. If you don’t know what to pick, many students like Visual Studio Code, which is affectionately known as VSCode.
It’s completely optional, but you might want to use VSCode’s code completion and diagnostics. Here are some suggestions:
- Install VSCode’s C/C++ extension. There is a guide to installing it in the docs.
- Configure VSCode to use the container. Put the contents of this file in
.devcontainer/devcontainer.json
inside the directory where you’re doing your work for a given assignment. - Tell VSCode to use the RISC-V setup. Put the contents of this file in
.vscode/c_cpp_properties.json
in your work directory.