Link Search Menu Expand Document

CS6640 Lab1: Setup and hello world

Lab1 comprises two parts:

The first part guides you to install the required tools and setup the lab environment. The second part serves as a warming-up to familiarize yourself with egos-2k+. There is a lot to read, but just few lines of code to write.

Quote from the Labs page, “if a lab is at first confusing even in its instructions, please don’t be discouraged; understanding the instructions is part of the work of the labs!”

Part 1: Setup and tools

We are going to use git, qemu, and Linux or MacOS for our labs.

Section 0: GitHub

If you don’t have a GitHub account, sign up for one here. You only need a Free plan for the labs.

Section 1: Prepare your host OS: Linux or MacOS

In this course, you will run egos-2k+ on qemu (an emulator), which further runs on either Linux or MacOS.

If you’re using:

  • Windows 10/11: you can do our labs with the Windows Subsystem for Linux (WSL). If you have WSL, you’re good to go to section 2.
    • Note: how to install WSL is here.
  • Linux: you’re good to go to section 2.
    • Note: we’ve only tested labs on Ubuntu. But, in principle, you should be able to use other Linux distributions as well.
  • MacOS: you’re good to go to section 2.
    • Note: you may face a permission problem when running labs for the first time. Please give permissions to all tools the labs use. See HowTo here.
  • Virtual machine: For whoever wants to use virtual machine, we recommend VirtualBox, which runs on Windows and MacOS with x86 CPUs, and has been successfully used in other classes for many years. And CS6640 staff has prepared a ready-to-use VM image for you.
    • Here are the steps to install VirtualBox and VM:
      1. download and install VirtualBox: be sure to download the package that is appropriate for your system. Once it has downloaded, install it by double clicking on the installer and following the prompts. The default settings for installation are generally the right ones.
      2. download the pre-built VM image. The link and instructions are on Canvas homepage. This is a zipped file. You need to unzip before use.
      3. run the VM by double clicking the image file or importing the image in the VirtualBox.
      4. Note: you can find VM’s sudo password on Canvas homepage.

Section 2: Cloning CS6640 environment

We assume you know the basics of git. If not, please read what is git? in appendix.

We assume you have an ssh-key on your working machine that can git clone/push/pull your GitHub repos. If not, please read Teaching GitHub about your identity in appendix. If you don’t know, use $ ssh git@github.com to confirm if your ssh-key is ready.

Now, git clone cs6640 environment:

  1. Open a terminal
  2. Clone your cs6640 environment repo:
     $ cd ~
     $ git clone git@github.com:NEU-CS6640-labs/cs6640.git cs6640
    
  3. Check the repo:
     $ cd ~/cs6640/
     $ ls
       <You should see:>
       env.sh
    

Section 3: Preparing build environment

To run the labs, you will need (1) a cross compiler to compile C code to RISC-V machine code, and (2) a qemu that emulates RISC-V CPUs running on your host OS with x86 or ARM CPUs.

Exercise 1 download compiler, qemu, and setup environment

  1. download compiler and compiling tools:
    • for Ubuntu and WSL, download this.
    • for MacOS, dowload this.
    • if you’re using other OSes, you’re on your own; here is the tooling page for all supported OSes.
  2. download RISC-V qemu:
    • for Linux and WSL, download this.
    • for MacOS, dowload this.
  3. move the two downloaded files (named riscv64-unknown-....tar.gz and riscv-qemu-....tar.gz) to the cs6640 folder (~/cs6640)
  4. unzip the downloaded files in ~/cs6640
     $ cd ~/cs6640/
     $ tar -zxvf riscv64-unknown-....tar.gz
     $ tar -zxvf riscv-qemu-....tar.gz
    

    Now, you should see two new folders in ~\cs6640 with the same name of the downloaded files.

  5. update the environment file:
    • open ~/cs6640/env.sh with your favorite text editor.
    • uncomment the two lines that matches your OS (Ubuntu/WSL or MacOS)
    • double-check whether the two lines matches the newly created folder names
  6. load environment variables
     $ source ./env.sh
    

    This command loads egos-2k+ variables to your current shell/terminal. Note:

    • You need to run this when you open a new shell/terminal.
    • You should run this only under ~/cs6640 because the script defines home folder based on current working directory.
  7. confirm the environment variables are ready
     $ echo $EGOS
    <you should see the full path of "cs6640" folder>
     $ echo $PATH
    <you should the two newly created folders:
     "riscv64-unknown-..." and "riscv-qemu" in the PATH>
    
  8. confirm gcc and qemu are installed
    $ riscv64-unknown-elf-gcc --version
      <you should see version information of gcc>
    
    $ qemu-system-riscv32 --version
      <you should see version information of qemu>
    

    Note: for MacOS users, if you see permission warnings, you need to grant the permission. See HowTo here.

This completes the part 1.

Part 2: Hello world in egos-2k+

Git clone the egos-2k+ repository

Please click the “egos-2k+” link on Canvas homepage to create your own private clone of the egos-2k+ repository; this clone lives on (is hosted by) GitHub. Once that clone exists, you will perform a further clone to get that private repository onto your working environment (your machine). You’ll do your work on your machine, and then push your work to the GitHub-hosted private repository for us to grade.

Here’s how it should work.

  1. click the “egos-2k+” link on canvas homepage to create your clone on github.
  2. log in to your github.
  3. provide a name.
  4. the link should automatically clone the repository. for instance, if your username name was foobar, you should now have a repository on your github called neu-cs6640-labs/egos-foobar.

creating a local clone

exercise 2 clone and build egos-2k+

  1. open a terminal
  2. clone your egos-2k+ to cs6640 folder:
     $ cd ~/cs6640
     $ git clone git@github.com:NEU-CS6640-labs/egos-<Your-GitHub-Username>.git egos
    

    Note that the git@github.com:... can be obtained on GitHub by clicking the “Clone or download” button. You want to clone using SSH, not HTTPS, so you might need to click “Use SSH”.

  3. Check the repo:
     $ cd ~/cs6640/egos/
     $ ls
    
       <You should see:>
       LICENSE                 earth                   library
       Makefile                egos2000_repo.txt       slack
       apps                    grass                   tools
    
  4. Setup stream remote reporsitory
     $ git remote add upstream git@github.com:NEU-CS6640-labs/egos-upstream.git
       // [a fix on 09/13/2023]
       // due to the complication of GitHub Classroom, we have to use a new
       // upstream repo for future labs.
       // The cmd was:
       //   $ git remote add upstream git@github.com:NEU-CS6640-labs/egos.git
    

    update 09/13 the upstream repo has changed. Please see above.
    Note: your will have two remote repos—(1) origin points to your private GitHub repo where you should submit your work (this is also where we pull and grade your labs); (2) upstream points to a repo where we publish labs (this is where you should fetch the code in the beginning of each lab, starting from lab2). You can confirm this by $ git remote -v.

  5. Build egos-2k+
     <in ~/cs6640/egos/ and have executed "source ./env.sh">
    
     $ make
     -------- Compile the Apps Layer --------
     ...
     ...
     [INFO] Finish making the disk image (tools/disk.img)
    
  6. Run egos-2k+
     $ make qemu
     -------- Simulate on QEMU-RISCV --------
     ...
     [CRITICAL] Welcome to the egos-2k+ shell!
     ➜ /home/cs6640
    
     <you can try "echo README" and "ls" in egos>
    

    Note: to quit, press Ctrl-a x; that is, press and hold “Ctrl” and press “a”, release both, and press ‘x’.

Now, you can run egos-2k+ on qemu (which simulate a SiFive FE310 CPU; see Reference page for more information). Next, let’s write your first line of code.

Exercise 3 Hello world in egos-2k+

  1. open apps/user/helloworld.c
  2. in main(), write printf("Hello world!\n")
  3. recompile, run qemu, and run helloworld:
     <in ~/cs6640/egos/>
    
     $ make && make qemu
     ...
     ...
     [CRITICAL] Welcome to the egos-2k+ shell!
    
     <type in "helloworld" in egos-2k+ shell>
     ➜ /home/cs6640 helloworld
    
     <you should see:>
     Hello world!
    

    Note: your need to rebuild the OS (namely, make) for any of your modification to take effect.

Understanding memory, C pointers, and CPU instructions

Below are three excercises that help you better understand basics of OSes:

  • Exercise 4: we’re using qemu to emulate a specific CPU named SiFive FE310. In this exercise, you will use a simple tool to explore this CPU’s valid memory.
  • Exercise 5: “C pointers are memory addresses”. Is this true? You will confirm this claim in the exercise.
  • Exercise 6: you will see what “instructions” are—they are 0s and 1s.

Exercise 4 Explore valid memory

  1. read apps/user/memloop.c and understand its behavior
  2. run memloop with 0x02000000 in egos-2k+:
     ➜ /home/cs6640 memloop 0x02000000
    
     <you should see:>
     input addr[0x02000000] => 2000000
     touch memory start: 2000000
     - touched page(1) [2000000, 2001000)
     qemu-system-riscv32: clint: invalid read: 00001000
     ...
    
     - touched page(15) [200e000, 200f000)
     qemu-system-riscv32: clint: invalid read: 0000f000
     - touched page(16) [200f000, 2010000)
     [FATAL] excp_entry: kernel got exception 13
    

    Note: kernel will panic and hang in the end because memloop touches a non-existent memory (0x20100000x200f000). You need to quit qemu by Ctrl-a x (holding “Ctrl” and pressing “a”, releasing both, then pressing ‘x’).
    Ignore the message “qemu-system-riscv32:” for now. You will know what that is later in the course.

  3. use memloop to explore the following addresses, and fill in the (FILL-IN) in slack/lab1.txt.
    [0x02000000, 0x2010000)
      // was [0x02000000, 0x200f000), a typo
    [0x08000000, (FILL-IN) )
    [0x10013000, (FILL-IN) )
    [0x20400000, (FILL-IN) )
    [0x80000000, (FILL-IN) )
    

    update 09/08: there were two 0x200f000 above which should have been 0x2010000.

Exercise 5 C pointers are memory addresses

  1. read ptr_is_address in user/apps/helloworld.c
  2. use the valid memory address you found in Exercise 4 to convince yourself that pointers are addresses.
    Remember to call ptr_is_address in main and rebuild (make).
  3. You may see warning messages, weird behaviors, or instant crashing of the kernel when you randomly read/write memory. This is expected, as you may sabotage memory that is important.
  4. find one address that contains 0.
    (We expect to see that ptr_is_address prints:
    ptr:<picked-address> before:0 after:1)

Exercise 6 instructions are 0s and 1s

  1. read ins_is_zero_one in user/apps/helloworld.c
  2. call ins_is_zero_one in main, and run helloworld
     ➜ /home/cs6640 helloworld
    
     <you should see:>
     Enter ins_is_zero_one()
    

    Now, you’re stuck here because there is an infinite loop in ins_is_zero_one. Use Ctrl-c (press-and-hold “Ctrl” and press “c”) to kill the process.

  3. Next, you will need to replace the instruction at memory 0x8200000c—the instruction that runs when pressing Ctrl-c—so that, instead of exit, you will re-enter main function.
  4. Most of the work has been done by skeleton code. You need to do one thing: assign call_main with the binary (it will be 4B) of call main (this is an RISC-V assembly instruction).
    How to find the binary form of this instruction? Search call main in build/debug/helloworld.lst.
  5. If succeeded, you should see:
     ➜ /home/cs6640 helloworld
     Enter ins_is_zero_one()
     <press Ctrl-c>
     Enter ins_is_zero_one()
     <press Ctrl-c>
    

    Pressing “Ctrl-c” will not kill the process because the code will jump to call main again. (Now, use Ctrl-a x to quit qemu.)

This completes the part 2.

Finally, submit your work

Submitting consists of three steps:

  1. Executing this checklist:
    • Fill in ~/cs6640/egos/slack/lab1.txt with (1) your name, (2) your NUID, (3) GitHub id, and (4) slack hours you used.
    • Make sure that your code build with no warnings.
  2. Push your code to GitHub:

     $ cd ~/cs6640/egos/
     $ git commit -am 'submit lab1'
     $ git push origin
    
     Counting objects: ...
      ....
      To ssh://github.com/NEU-CS6640-labs/egos-<username>.git
       7337116..ceed758  main -> main
    
  3. Actually commit your lab (with timestamp and git commit id):

    1. Get the git commit id of your work. A commit id is a 40-character hexadecimal string. You can obtain the commit id for the last commit by running the command git log -1 --format=oneline.

    2. Submit a file named git.txt to Canvas. (there will be an assignment for this lab on Canvas.) The file git.txt contains two lines: the first line is your github repo url; the second line is the git commit id that you want us to grade. Here is an example:
       git@github.com:NEU-CS6640-labs/egos-<username>.git
       29dfdadeadbeefe33421f242b5dd8312732fd3c9
      

      Notice: the repo address must start with git@github.com:... (not https://...). You can get your repo address on GitHub repo page by clicking the green “Code” button, then choose “SSH”.

    3. Note: You can submit as many times as you want; we will grade the last commit id submitted to Canvas. Also, you can submit any commit id in your pushed git history; again, we will grade the commit id submitted to Canvas.
      Notice: if you submit multiple times, the file name (git.txt) changes to git-N.txt where N is an integer and represents how many times you’ve submitted. We will grade the file with the largest N.

NOTE: Ground truth is what and when you submitted to Canvas.

  • A non-existent repo address or a non-existent commit id in Canvas means that you have not submitted the lab, regardless of what you have pushed to GitHub—we will not grade it. So, please double check your submitted repo and commit id!

  • The time of your submission for the purposes of tracking lateness is the timestamp on Canvas, not the timestamp on GitHub.

This completes the lab.

Acknowledgments

Some instructions in Part1 are copied from CS5600, which are further borrowed from from Mike Walfish’s CS202, with materials from Harvard’s CS61, Jinyang Li’s CS201, and Aurojit Panda’s 3033. Some shell commands are borrowed from Yunhao Zhang’s egos-2000 USAGE page.

Appendix

What is git?

Git was developed by Linus Torvalds for development of the Linux kernel. It’s is a distributed version control system, which means it supports many local repositories which each track changes and can synchronize with each other in a peer-to-peer fashion. It’s the best widely-available version control system, and certainly the most widely used. For information on how to use git, see:

For the workflow in GitHub:

Teaching GitHub about your identity

The easiest way to access GitHub repositories is using an SSH key, a secret key stored on your machine that defines your identity. Follow the steps below to create a key for your machine.

  1. Open Terminal.

  2. Run $ ssh-keygen -t rsa -b 2048 (don’t copy the $ sign) and follow the instructions.

    • Press enter to use the default file path and key name (should be ~/.ssh/id_rsa).
    • Choose a password or leave it empty.

    This creates your ssh keys, which live in the directory ~/.ssh. Your public key is in the file ~/.ssh/id_rsa.pub.

  3. Run cat .ssh/id_rsa.pub to display your public key.

  4. Copy your public key (that is, select the text on the screen, and copy it to the clipboard).

  5. In GitHub, go to your profile settings page (accessible via the upper-rightmost link–this looks like a bunch of pixels for new accounts). Select “SSH and GPG keys” and hit the “New SSH key” button. Then copy and paste the contents of your ~/.ssh/id_rsa.pub (from your machine) into the “Key” section. Give the key a sensible title, hit the “Add SSH key” button, and you’re good to go.

  6. (if you haven’t) configure your git “identity”:

     $ git config --global user.name "FIRST_NAME LAST_NAME"
     $ git config --global user.email "YOUR_@COLLEGE_EMAIL"