diff --git a/.circleci/README.md b/.circleci/README.md index 50ede340..83fd3264 100644 --- a/.circleci/README.md +++ b/.circleci/README.md @@ -1,7 +1,7 @@ -REBAR CI -======== +Chipyard CI +=========== -Website: https://circleci.com/gh/ucb-bar/project-template +Website: https://circleci.com/gh/ucb-bar/chipyard CircleCI Brief Explanation --------------------------- @@ -32,17 +32,18 @@ Here the key is built from a string where the `checksum` portion converts the fi .circleci directory ------------------- -This directory contains all the collateral for the REBAR CI to work. +This directory contains all the collateral for the Chipyard CI to work. The following is included: - - build-toolchains.sh # build either riscv-tools or esp-tools - build-verilator.sh # build verilator - create-hash.sh # create hashes of riscv-tools/esp-tools so circleci caching can work - do-rtl-build.sh # use verilator to build a sim executable - config.yml # main circleci config script to enumerate jobs/workflows -How things are setup for REBAR ------------------------------- + `build-toolchains.sh` # build either riscv-tools or esp-tools + `build-verilator.sh` # build verilator (remotely) + `create-hash.sh` # create hashes of riscv-tools/esp-tools so circleci caching can work + `do-rtl-build.sh` # use verilator to build a sim executable (remotely) + `config.yml` # main circleci config script to enumerate jobs/workflows + `defaults.sh` # default variables used + +How things are setup for Chipyard +--------------------------------- The steps for CI to run are as follows. 1st, build the toolchains in parallel (note: `esp-tools` is currently not used in the run). @@ -52,3 +53,18 @@ The docker image sets up the `PATH` and `RISCV` variable so that `riscv-tools` i This requires the `riscv-tools` for `fesvr` and `verilator` to be able to build the binary. This stores all collateral for the tests (srcs, generated-srcs, sim binary, etc) to run "out of the gate" in the next job (make needs everything or else it will run again). 4th, finally run the tests that were wanted. + +Other CI Setup +-------------- + +To get the CI to work correctly you need to setup CircleCI environment variables to point to the remote directory to build files and the server user/ip. +In the project settings, you can find this under "Build Settings" "Environment Variables". +You need to add two variables like the following: + +CI\_DIR = /path/to/where/you/want/to/store/remote/files +SERVER = username@myserver.coolmachine.berkeley.edu + +Additionally, you need to add under the "PERMISSIONS" "SSH Permissions" section a private key that is on the build server that you are using. +After adding a private key, it will show a fingerprint that should be added under the jobs that need to be run. + +Note: On the remote server you need to have the `*.pub` key file added to the `authorized_keys` file. diff --git a/.circleci/build-toolchains.sh b/.circleci/build-toolchains.sh index 28b87caa..63f47505 100755 --- a/.circleci/build-toolchains.sh +++ b/.circleci/build-toolchains.sh @@ -6,10 +6,13 @@ # turn echo on and error on earliest command set -ex -if [ ! -d "$HOME/$1-install" ]; then +# get shared variables +SCRIPT_DIR="$( cd "$( dirname "$0" )" && pwd )" +source $SCRIPT_DIR/defaults.sh - cd $HOME/ +if [ ! -d "$HOME/$1-install" ]; then + cd $HOME # init all submodules including the tools - REBAR_DIR=$HOME/project ./project/scripts/build-toolchains.sh $1 + CHIPYARD_DIR=$LOCAL_CHIPYARD_DIR $LOCAL_CHIPYARD_DIR/scripts/build-toolchains.sh $1 fi diff --git a/.circleci/build-verilator.sh b/.circleci/build-verilator.sh index 00cd7217..acd038fb 100755 --- a/.circleci/build-verilator.sh +++ b/.circleci/build-verilator.sh @@ -5,11 +5,31 @@ # turn echo on and error on earliest command set -ex -cd $HOME/project +# get shared variables +SCRIPT_DIR="$( cd "$( dirname "$0" )" && pwd )" +source $SCRIPT_DIR/defaults.sh -cd sims/verisim +# call clean on exit +trap clean EXIT -if [ ! -d "$HOME/project/sims/verisim/verilator" ]; then - # make verilator - make verilator_install +run_script $LOCAL_CHIPYARD_DIR/.circleci/clean-old-files.sh $CI_DIR + +if [ ! -d "$LOCAL_VERILATOR_DIR" ]; then + # set stricthostkeychecking to no (must happen before rsync) + run "echo \"Ping $SERVER\"" + + clean + + run "mkdir -p $REMOTE_CHIPYARD_DIR" + copy $LOCAL_CHIPYARD_DIR/ $SERVER:$REMOTE_CHIPYARD_DIR + + run "make -C $REMOTE_SIM_DIR VERILATOR_INSTALL_DIR=$REMOTE_VERILATOR_DIR verilator_install" + + # copy so that circleci can cache + mkdir -p $LOCAL_CHIPYARD_DIR + mkdir -p $LOCAL_VERILATOR_DIR + copy $SERVER:$REMOTE_CHIPYARD_DIR/ $LOCAL_CHIPYARD_DIR + copy $SERVER:$REMOTE_VERILATOR_DIR/ $LOCAL_VERILATOR_DIR + + cp -r $LOCAL_VERILATOR_DIR/install/bin/* $LOCAL_VERILATOR_DIR/install/share/verilator/bin/. fi diff --git a/.circleci/check-commit.sh b/.circleci/check-commit.sh new file mode 100755 index 00000000..a282ebfd --- /dev/null +++ b/.circleci/check-commit.sh @@ -0,0 +1,45 @@ +#!/bin/bash + +# check to see that submodule commits are present on the master branch + +# turn echo on and error on earliest command +set -ex + +# get shared variables +SCRIPT_DIR="$( cd "$( dirname "$0" )" && pwd )" +source $SCRIPT_DIR/defaults.sh + +# enter bhd repo +cd $LOCAL_CHIPYARD_DIR + +# initialize submodules and get the hashes +git config submodule.vlsi/hammer-cad-plugins.update none +git submodule update --init +status=$(git submodule status) + +search () { + for submodule in "${submodules[@]}" + do + echo "Running check on submodule $submodule in $dir" + hash=$(echo "$status" | grep $submodule | awk '{print$1}' | grep -o "[[:alnum:]]*") + echo "Searching for $hash in origin/master of $submodule" + git -C $dir/$submodule branch -r --contains "$hash" | grep "origin/master" # needs init'ed submodules + done +} + +submodules=("boom" "hwacha" "icenet" "rocket-chip" "sifive-blocks" "sifive-cache" "testchipip") +dir="generators" + +search + +submodules=("esp-tools" "riscv-tools") +dir="toolchains" + +search + +submodules=("barstools" "chisel3" "firrtl" "torture") +dir="tools" + +search + +echo "Done checking all submodules" diff --git a/.circleci/clean-old-files.sh b/.circleci/clean-old-files.sh new file mode 100755 index 00000000..96fcf8d7 --- /dev/null +++ b/.circleci/clean-old-files.sh @@ -0,0 +1,29 @@ +#!/bin/bash + +# clean directories that are older than 30 days +# argument is used as the directory to look in + +age () { + local AGE_SEC + local CUR_SEC + local DIFF_SEC + local SEC_PER_DAY + + SEC_PER_DAY=86400 + + CUR_SEC=$(date +%s) + AGE_SEC=$(stat -c %Y -- "$1") + DIFF_SEC=$(expr $CUR_SEC - $AGE_SEC) + + echo $(expr $DIFF_SEC / $SEC_PER_DAY) +} + +for d in $1/*/ ; do + DIR_AGE="$(age $d)" + if [ $DIR_AGE -ge 30 ]; then + echo "Deleting $d since is it $DIR_AGE old" + rm -rf $d + else + echo "Keep $d since it is $DIR_AGE old" + fi +done diff --git a/.circleci/config.yml b/.circleci/config.yml index d2354fde..1ae4a000 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -5,471 +5,455 @@ version: 2 # set of jobs to run jobs: - install-riscv-toolchain: + commit-on-master-check: docker: - - image: riscvboom/riscvboom-images:0.0.5 + - image: riscvboom/riscvboom-images:0.0.10 + environment: + JVM_OPTS: -Xmx3200m # Customize the JVM maximum heap limit + TERM: dumb + steps: + - checkout + - run: + name: Check commits of each submodule + command: | + .circleci/check-commit.sh + install-riscv-toolchain: + docker: + - image: riscvboom/riscvboom-images:0.0.10 environment: JVM_OPTS: -Xmx3200m # Customize the JVM maximum heap limit TERM: dumb - steps: - # Checkout the code - checkout - - run: name: Create hash of toolchains command: | .circleci/create-hash.sh - - restore_cache: keys: - riscv-tools-installed-v1-{{ checksum "../riscv-tools.hash" }} - - run: name: Building riscv-tools toolchain command: | .circleci/build-toolchains.sh riscv-tools no_output_timeout: 120m - - save_cache: key: riscv-tools-installed-v1-{{ checksum "../riscv-tools.hash" }} paths: - "/home/riscvuser/riscv-tools-install" - install-esp-toolchain: docker: - - image: riscvboom/riscvboom-images:0.0.5 + - image: riscvboom/riscvboom-images:0.0.10 environment: JVM_OPTS: -Xmx3200m # Customize the JVM maximum heap limit TERM: dumb - steps: - # Checkout the code - checkout - - run: name: Create hash of toolchains command: | .circleci/create-hash.sh - - restore_cache: keys: - esp-tools-installed-v1-{{ checksum "../esp-tools.hash" }} - - run: name: Building esp-tools toolchain command: | .circleci/build-toolchains.sh esp-tools no_output_timeout: 120m - - save_cache: key: esp-tools-installed-v1-{{ checksum "../esp-tools.hash" }} paths: - "/home/riscvuser/esp-tools-install" - install-verilator: docker: - - image: riscvboom/riscvboom-images:0.0.5 + - image: riscvboom/riscvboom-images:0.0.10 environment: JVM_OPTS: -Xmx3200m # Customize the JVM maximum heap limit TERM: dumb - steps: - # Checkout the code + - add_ssh_keys: + fingerprints: + - "3e:c3:02:5b:ed:64:8c:b7:b0:04:43:bc:83:43:73:1e" - checkout - - restore_cache: keys: - - verilator-installed-v1-{{ checksum "sims/verisim/verilator.mk" }} - + - verilator-installed-v3-{{ checksum "sims/verilator/verilator.mk" }} - run: name: Build Verilator command: | .circleci/build-verilator.sh no_output_timeout: 120m - - save_cache: - key: verilator-installed-v1-{{ checksum "sims/verisim/verilator.mk" }} + key: verilator-installed-v3-{{ checksum "sims/verilator/verilator.mk" }} paths: - - "/home/riscvuser/project/sims/verisim/verilator" - + - "/home/riscvuser/verilator" prepare-example: docker: - - image: riscvboom/riscvboom-images:0.0.5 + - image: riscvboom/riscvboom-images:0.0.10 environment: JVM_OPTS: -Xmx3200m # Customize the JVM maximum heap limit TERM: dumb - steps: - # Checkout the code + - add_ssh_keys: + fingerprints: + - "3e:c3:02:5b:ed:64:8c:b7:b0:04:43:bc:83:43:73:1e" - checkout - - run: name: Create hash of toolchains command: | .circleci/create-hash.sh - - restore_cache: keys: - riscv-tools-installed-v1-{{ checksum "../riscv-tools.hash" }} - - restore_cache: keys: - - verilator-installed-v1-{{ checksum "sims/verisim/verilator.mk" }} - + - verilator-installed-v3-{{ checksum "sims/verilator/verilator.mk" }} - run: name: Building the example subproject using Verilator - command: .circleci/do-rtl-build.sh SUB_PROJECT=example + command: .circleci/do-rtl-build.sh example no_output_timeout: 120m - - save_cache: key: example-{{ .Branch }}-{{ .Revision }} paths: - "/home/riscvuser/project" - prepare-boomexample: docker: - - image: riscvboom/riscvboom-images:0.0.5 + - image: riscvboom/riscvboom-images:0.0.10 environment: JVM_OPTS: -Xmx3200m # Customize the JVM maximum heap limit TERM: dumb - steps: - # Checkout the code + - add_ssh_keys: + fingerprints: + - "3e:c3:02:5b:ed:64:8c:b7:b0:04:43:bc:83:43:73:1e" - checkout - - run: name: Create hash of toolchains command: | .circleci/create-hash.sh - - restore_cache: keys: - riscv-tools-installed-v1-{{ checksum "../riscv-tools.hash" }} - - restore_cache: keys: - - verilator-installed-v1-{{ checksum "sims/verisim/verilator.mk" }} - + - verilator-installed-v3-{{ checksum "sims/verilator/verilator.mk" }} - run: name: Building the boomexample subproject using Verilator - command: .circleci/do-rtl-build.sh SUB_PROJECT=example CONFIG=SmallDefaultBoomConfig + command: .circleci/do-rtl-build.sh boomexample no_output_timeout: 120m - - save_cache: key: boomexample-{{ .Branch }}-{{ .Revision }} paths: - "/home/riscvuser/project" - prepare-boomrocketexample: docker: - - image: riscvboom/riscvboom-images:0.0.5 + - image: riscvboom/riscvboom-images:0.0.10 environment: JVM_OPTS: -Xmx3200m # Customize the JVM maximum heap limit TERM: dumb - steps: - # Checkout the code + - add_ssh_keys: + fingerprints: + - "3e:c3:02:5b:ed:64:8c:b7:b0:04:43:bc:83:43:73:1e" - checkout - - run: name: Create hash of toolchains command: | .circleci/create-hash.sh - - restore_cache: keys: - riscv-tools-installed-v1-{{ checksum "../riscv-tools.hash" }} - - restore_cache: keys: - - verilator-installed-v1-{{ checksum "sims/verisim/verilator.mk" }} - + - verilator-installed-v3-{{ checksum "sims/verilator/verilator.mk" }} - run: name: Building the boomrocketexample subproject using Verilator - command: .circleci/do-rtl-build.sh SUB_PROJECT=example CONFIG=SmallDefaultBoomAndRocketConfig + command: .circleci/do-rtl-build.sh boomrocketexample no_output_timeout: 120m - - save_cache: key: boomrocketexample-{{ .Branch }}-{{ .Revision }} paths: - "/home/riscvuser/project" - prepare-boom: docker: - - image: riscvboom/riscvboom-images:0.0.5 + - image: riscvboom/riscvboom-images:0.0.10 environment: JVM_OPTS: -Xmx3200m # Customize the JVM maximum heap limit TERM: dumb - steps: - # Checkout the code + - add_ssh_keys: + fingerprints: + - "3e:c3:02:5b:ed:64:8c:b7:b0:04:43:bc:83:43:73:1e" - checkout - - run: name: Create hash of toolchains command: | .circleci/create-hash.sh - - restore_cache: keys: - riscv-tools-installed-v1-{{ checksum "../riscv-tools.hash" }} - - restore_cache: keys: - - verilator-installed-v1-{{ checksum "sims/verisim/verilator.mk" }} - + - verilator-installed-v3-{{ checksum "sims/verilator/verilator.mk" }} - run: name: Building the boom subproject using Verilator - command: .circleci/do-rtl-build.sh SUB_PROJECT=boom + command: .circleci/do-rtl-build.sh boom no_output_timeout: 120m - - save_cache: key: boom-{{ .Branch }}-{{ .Revision }} paths: - "/home/riscvuser/project" - prepare-rocketchip: docker: - - image: riscvboom/riscvboom-images:0.0.5 + - image: riscvboom/riscvboom-images:0.0.10 environment: JVM_OPTS: -Xmx3200m # Customize the JVM maximum heap limit TERM: dumb - steps: - # Checkout the code + - add_ssh_keys: + fingerprints: + - "3e:c3:02:5b:ed:64:8c:b7:b0:04:43:bc:83:43:73:1e" - checkout - - run: name: Create hash of toolchains command: | .circleci/create-hash.sh - - restore_cache: keys: - riscv-tools-installed-v1-{{ checksum "../riscv-tools.hash" }} - - restore_cache: keys: - - verilator-installed-v1-{{ checksum "sims/verisim/verilator.mk" }} - + - verilator-installed-v3-{{ checksum "sims/verilator/verilator.mk" }} - run: name: Building the rocketchip subproject using Verilator - command: .circleci/do-rtl-build.sh SUB_PROJECT=rocketchip + command: .circleci/do-rtl-build.sh rocketchip no_output_timeout: 120m - - save_cache: key: rocketchip-{{ .Branch }}-{{ .Revision }} paths: - "/home/riscvuser/project" - - prepare-hwacha-verilog-only: + prepare-blockdevrocketchip: docker: - - image: riscvboom/riscvboom-images:0.0.5 + - image: riscvboom/riscvboom-images:0.0.10 environment: JVM_OPTS: -Xmx3200m # Customize the JVM maximum heap limit TERM: dumb - steps: - # Checkout the code + - add_ssh_keys: + fingerprints: + - "3e:c3:02:5b:ed:64:8c:b7:b0:04:43:bc:83:43:73:1e" - checkout - - run: name: Create hash of toolchains command: | .circleci/create-hash.sh - - restore_cache: keys: - riscv-tools-installed-v1-{{ checksum "../riscv-tools.hash" }} - - restore_cache: keys: - - verilator-installed-v1-{{ checksum "sims/verisim/verilator.mk" }} - + - verilator-installed-v3-{{ checksum "sims/verilator/verilator.mk" }} + - run: + name: Building the blockdevrocketchip subproject using Verilator + command: .circleci/do-rtl-build.sh blockdevrocketchip + no_output_timeout: 120m + - save_cache: + key: blockdevrocketchip-{{ .Branch }}-{{ .Revision }} + paths: + - "/home/riscvuser/project" + prepare-hwacha: + docker: + - image: riscvboom/riscvboom-images:0.0.10 + environment: + JVM_OPTS: -Xmx3200m # Customize the JVM maximum heap limit + TERM: dumb + steps: + - add_ssh_keys: + fingerprints: + - "3e:c3:02:5b:ed:64:8c:b7:b0:04:43:bc:83:43:73:1e" + - checkout + - run: + name: Create hash of toolchains + command: | + .circleci/create-hash.sh + - restore_cache: + keys: + - esp-tools-installed-v1-{{ checksum "../esp-tools.hash" }} + - restore_cache: + keys: + - verilator-installed-v3-{{ checksum "sims/verilator/verilator.mk" }} - run: name: Building the hwacha subproject using Verilator - command: .circleci/do-rtl-build.sh SUB_PROJECT=hwacha verilog + command: .circleci/do-rtl-build.sh hwacha no_output_timeout: 120m - - save_cache: key: hwacha-{{ .Branch }}-{{ .Revision }} paths: - "/home/riscvuser/project" - - example-run-benchmark-tests: + example-run-tests: docker: - - image: riscvboom/riscvboom-images:0.0.5 + - image: riscvboom/riscvboom-images:0.0.10 environment: JVM_OPTS: -Xmx3200m # Customize the JVM maximum heap limit TERM: dumb - steps: - # Checkout the code - checkout - - run: name: Create hash of toolchains command: | .circleci/create-hash.sh - - restore_cache: keys: - riscv-tools-installed-v1-{{ checksum "../riscv-tools.hash" }} - - restore_cache: keys: - example-{{ .Branch }}-{{ .Revision }} - + - restore_cache: + keys: + - verilator-installed-v3-{{ checksum "sims/verilator/verilator.mk" }} - run: - name: Run example benchmark tests - command: make run-bmark-tests -C sims/verisim SUB_PROJECT=example - - boomexample-run-benchmark-tests: + name: Run example tests + command: .circleci/run-tests.sh example + boomexample-run-tests: docker: - - image: riscvboom/riscvboom-images:0.0.5 + - image: riscvboom/riscvboom-images:0.0.10 environment: JVM_OPTS: -Xmx3200m # Customize the JVM maximum heap limit TERM: dumb - steps: - # Checkout the code - checkout - - run: name: Create hash of toolchains command: | .circleci/create-hash.sh - - restore_cache: keys: - riscv-tools-installed-v1-{{ checksum "../riscv-tools.hash" }} - - restore_cache: keys: - boomexample-{{ .Branch }}-{{ .Revision }} - + - restore_cache: + keys: + - verilator-installed-v3-{{ checksum "sims/verilator/verilator.mk" }} - run: - name: Run boomexample benchmark tests - command: make run-bmark-tests -C sims/verisim SUB_PROJECT=example CONFIG=SmallDefaultBoomConfig - - boomrocketexample-run-benchmark-tests: + name: Run boomexample tests + command: .circleci/run-tests.sh boomexample + boomrocketexample-run-tests: docker: - - image: riscvboom/riscvboom-images:0.0.5 + - image: riscvboom/riscvboom-images:0.0.10 environment: JVM_OPTS: -Xmx3200m # Customize the JVM maximum heap limit TERM: dumb - steps: - # Checkout the code - checkout - - run: name: Create hash of toolchains command: | .circleci/create-hash.sh - - restore_cache: keys: - riscv-tools-installed-v1-{{ checksum "../riscv-tools.hash" }} - - restore_cache: keys: - boomrocketexample-{{ .Branch }}-{{ .Revision }} - + - restore_cache: + keys: + - verilator-installed-v3-{{ checksum "sims/verilator/verilator.mk" }} - run: - name: Run boomrocketexample benchmark tests - command: make run-bmark-tests -C sims/verisim SUB_PROJECT=example CONFIG=SmallDefaultBoomAndRocketConfig - - boom-run-benchmark-tests: + name: Run boomrocketexample tests + command: .circleci/run-tests.sh boomrocketexample + boom-run-tests: docker: - - image: riscvboom/riscvboom-images:0.0.5 + - image: riscvboom/riscvboom-images:0.0.10 environment: JVM_OPTS: -Xmx3200m # Customize the JVM maximum heap limit TERM: dumb - steps: - # Checkout the code - checkout - - run: name: Create hash of toolchains command: | .circleci/create-hash.sh - - restore_cache: keys: - riscv-tools-installed-v1-{{ checksum "../riscv-tools.hash" }} - - restore_cache: keys: - boom-{{ .Branch }}-{{ .Revision }} - + - restore_cache: + keys: + - verilator-installed-v3-{{ checksum "sims/verilator/verilator.mk" }} - run: - name: Run boom benchmark tests - command: make run-bmark-tests -C sims/verisim SUB_PROJECT=boom - - rocketchip-run-benchmark-tests: + name: Run boom tests + command: .circleci/run-tests.sh boom + rocketchip-run-tests: docker: - - image: riscvboom/riscvboom-images:0.0.5 + - image: riscvboom/riscvboom-images:0.0.10 environment: JVM_OPTS: -Xmx3200m # Customize the JVM maximum heap limit TERM: dumb - steps: - # Checkout the code - checkout - - run: name: Create hash of toolchains command: | .circleci/create-hash.sh - - restore_cache: keys: - riscv-tools-installed-v1-{{ checksum "../riscv-tools.hash" }} - - restore_cache: keys: - rocketchip-{{ .Branch }}-{{ .Revision }} - + - restore_cache: + keys: + - verilator-installed-v3-{{ checksum "sims/verilator/verilator.mk" }} - run: - name: Run rocketchip benchmark tests - command: make run-bmark-tests -C sims/verisim SUB_PROJECT=rocketchip - -# hwacha-run-benchmark-tests: -# docker: -# - image: riscvboom/riscvboom-images:0.0.5 -# environment: -# JVM_OPTS: -Xmx3200m # Customize the JVM maximum heap limit -# TERM: dumb -# -# steps: -# # Checkout the code -# - checkout -# -# - run: -# name: Create hash of toolchains -# command: | -# .circleci/create-hash.sh -# -# - restore_cache: -# keys: -# - riscv-tools-installed-v1-{{ checksum "../riscv-tools.hash" }} -# -# - restore_cache: -# keys: -# - hwacha-{{ .Branch }}-{{ .Revision }} -# -# - run: -# name: Run hwacha benchmark tests -# command: make run-bmark-tests -C sims/verisim SUB_PROJECT=hwacha + name: Run rocketchip tests + command: .circleci/run-tests.sh rocketchip + hwacha-run-tests: + docker: + - image: riscvboom/riscvboom-images:0.0.10 + environment: + JVM_OPTS: -Xmx3200m # Customize the JVM maximum heap limit + TERM: dumb + steps: + - checkout + - run: + name: Create hash of toolchains + command: | + .circleci/create-hash.sh + - restore_cache: + keys: + - esp-tools-installed-v1-{{ checksum "../esp-tools.hash" }} + - restore_cache: + keys: + - hwacha-{{ .Branch }}-{{ .Revision }} + - restore_cache: + keys: + - verilator-installed-v3-{{ checksum "sims/verilator/verilator.mk" }} + - run: + name: Run hwacha tests + command: .circleci/run-tests.sh hwacha # Order and dependencies of jobs to run workflows: version: 2 - build-and-test-rebar-integration: + submodules-on-master: jobs: + # Check to make sure submodule commits are on master branches + - commit-on-master-check + triggers: + - schedule: + cron: "0 0 * * *" + filters: + branches: + only: + - master + + build-and-test-chipyard-integration: + jobs: + # Make the toolchains - install-riscv-toolchain @@ -504,42 +488,39 @@ workflows: - install-riscv-toolchain - install-verilator - - prepare-hwacha-verilog-only: + - prepare-blockdevrocketchip: + requires: + - install-riscv-toolchain + - install-verilator + + - prepare-hwacha: requires: - - install-riscv-toolchain # TODO: Remove when esp-tools is used - install-esp-toolchain - install-verilator # Run the respective tests # Run the example tests - - example-run-benchmark-tests: + - example-run-tests: requires: - - install-riscv-toolchain - prepare-example - - boomexample-run-benchmark-tests: + - boomexample-run-tests: requires: - - install-riscv-toolchain - prepare-boomexample - - boomrocketexample-run-benchmark-tests: + - boomrocketexample-run-tests: requires: - - install-riscv-toolchain - prepare-boomrocketexample - - boom-run-benchmark-tests: + - boom-run-tests: requires: - - install-riscv-toolchain - prepare-boom - - rocketchip-run-benchmark-tests: + - rocketchip-run-tests: requires: - - install-riscv-toolchain - prepare-rocketchip -# - hwacha-run-benchmark-tests: -# requires: -# - install-riscv-toolchain # TODO: Remove when esp-tools is used -# - install-esp-toolchain -# - prepare-hwacha + - hwacha-run-tests: + requires: + - prepare-hwacha diff --git a/.circleci/create-hash.sh b/.circleci/create-hash.sh index 2aff9727..84a75244 100755 --- a/.circleci/create-hash.sh +++ b/.circleci/create-hash.sh @@ -5,8 +5,12 @@ # turn echo on and error on earliest command set -ex +# get shared variables +SCRIPT_DIR="$( cd "$( dirname "$0" )" && pwd )" +source $SCRIPT_DIR/defaults.sh + # enter bhd repo -cd $HOME/project +cd $LOCAL_CHIPYARD_DIR # get the version of riscv-tools from the git submodule hash git submodule status | grep "riscv-tools" | awk '{print$1}' | grep -o "[[:alnum:]]*" >> $HOME/riscv-tools.hash diff --git a/.circleci/defaults.sh b/.circleci/defaults.sh new file mode 100755 index 00000000..cdccc3ba --- /dev/null +++ b/.circleci/defaults.sh @@ -0,0 +1,44 @@ +#!/bin/bash + +copy () { + rsync -avzp -e 'ssh' $1 $2 +} + +run () { + ssh -o "StrictHostKeyChecking no" -t $SERVER $@ +} + +run_script () { + ssh -o "StrictHostKeyChecking no" -t $SERVER 'bash -s' < $1 "$2" +} + +clean () { + # remove remote work dir + run "rm -rf $REMOTE_WORK_DIR" +} + +# remote variables +REMOTE_WORK_DIR=$CI_DIR/$CIRCLE_PROJECT_REPONAME-$CIRCLE_BRANCH-$CIRCLE_SHA1-$CIRCLE_JOB +REMOTE_RISCV_DIR=$REMOTE_WORK_DIR/riscv-tools-install +REMOTE_ESP_DIR=$REMOTE_WORK_DIR/esp-tools-install +REMOTE_CHIPYARD_DIR=$REMOTE_WORK_DIR/chipyard +REMOTE_VERILATOR_DIR=$REMOTE_WORK_DIR/verilator +REMOTE_SIM_DIR=$REMOTE_CHIPYARD_DIR/sims/verilator + +# local variables (aka within the docker container) +LOCAL_CHECKOUT_DIR=$HOME/project +LOCAL_RISCV_DIR=$HOME/riscv-tools-install +LOCAL_ESP_DIR=$HOME/esp-tools-install +LOCAL_CHIPYARD_DIR=$LOCAL_CHECKOUT_DIR +LOCAL_VERILATOR_DIR=$HOME/verilator +LOCAL_SIM_DIR=$LOCAL_CHIPYARD_DIR/sims/verilator + +# key value store to get the build strings +declare -A mapping +mapping["example"]="SUB_PROJECT=example" +mapping["boomexample"]="SUB_PROJECT=example CONFIG=DefaultBoomConfig" +mapping["boomrocketexample"]="SUB_PROJECT=example CONFIG=DefaultBoomAndRocketConfig" +mapping["boom"]="SUB_PROJECT=example CONFIG=SmallBoomConfig" +mapping["rocketchip"]="SUB_PROJECT=rocketchip" +mapping["blockdevrocketchip"]="SUB_PROJECT=example CONFIG=BlockDeviceModelRocketConfig TOP=BoomRocketTopWithBlockDevice" +mapping["hwacha"]="SUB_PROJECT=example CONFIG=HwachaL2Config GENERATOR_PACKAGE=hwacha" diff --git a/.circleci/do-rtl-build.sh b/.circleci/do-rtl-build.sh index 51ad760b..00dc7290 100755 --- a/.circleci/do-rtl-build.sh +++ b/.circleci/do-rtl-build.sh @@ -6,15 +6,44 @@ # turn echo on and error on earliest command set -ex -# init all submodules -cd $HOME/project +# get shared variables +SCRIPT_DIR="$( cd "$( dirname "$0" )" && pwd )" +source $SCRIPT_DIR/defaults.sh + +# call clean on exit +trap clean EXIT + +cd $LOCAL_CHIPYARD_DIR ./scripts/init-submodules-no-riscv-tools.sh -# enter the verisim directory and build the specific config -cd sims/verisim -make clean +# set stricthostkeychecking to no (must happen before rsync) +run "echo \"Ping $SERVER\"" -# run the particular build command -make JAVA_ARGS="-Xmx2G -Xss8M" $@ +clean -rm -rf ../../project +# copy over riscv/esp-tools, verilator, and chipyard to remote +run "mkdir -p $REMOTE_CHIPYARD_DIR" +run "mkdir -p $REMOTE_VERILATOR_DIR" +copy $LOCAL_CHIPYARD_DIR/ $SERVER:$REMOTE_CHIPYARD_DIR +copy $LOCAL_VERILATOR_DIR/ $SERVER:$REMOTE_VERILATOR_DIR + +TOOLS_DIR=$REMOTE_RISCV_DIR +LD_LIB_DIR=$REMOTE_RISCV_DIR/lib +if [ $1 = "hwacha" ]; then + TOOLS_DIR=$REMOTE_ESP_DIR + LD_LIB_DIR=$REMOTE_ESP_DIR/lib + run "mkdir -p $REMOTE_ESP_DIR" + copy $LOCAL_ESP_DIR/ $SERVER:$REMOTE_ESP_DIR +else + run "mkdir -p $REMOTE_RISCV_DIR" + copy $LOCAL_RISCV_DIR/ $SERVER:$REMOTE_RISCV_DIR +fi + +# enter the verilator directory and build the specific config on remote server +run "make -C $REMOTE_SIM_DIR clean" +run "export RISCV=\"$TOOLS_DIR\"; export LD_LIBRARY_PATH=\"$LD_LIB_DIR\"; export VERILATOR_ROOT=$REMOTE_VERILATOR_DIR/install/share/verilator; make -C $REMOTE_SIM_DIR VERILATOR_INSTALL_DIR=$REMOTE_VERILATOR_DIR JAVA_ARGS=\"-Xmx8G -Xss8M\" ${mapping[$1]}" +run "rm -rf $REMOTE_CHIPYARD_DIR/project" + +# copy back the final build +mkdir -p $LOCAL_CHIPYARD_DIR +copy $SERVER:$REMOTE_CHIPYARD_DIR/ $LOCAL_CHIPYARD_DIR diff --git a/.circleci/run-tests.sh b/.circleci/run-tests.sh new file mode 100755 index 00000000..99fd42dd --- /dev/null +++ b/.circleci/run-tests.sh @@ -0,0 +1,53 @@ +#!/bin/bash + +# run the different tests + +# turn echo on and error on earliest command +set -ex + +# get remote exec variables +SCRIPT_DIR="$( cd "$( dirname "$0" )" && pwd )" +source $SCRIPT_DIR/defaults.sh + +export VERILATOR_ROOT=$LOCAL_VERILATOR_DIR/install/share/verilator + +run_bmark () { + make run-bmark-tests-fast -C $LOCAL_SIM_DIR VERILATOR_INSTALL_DIR=$LOCAL_VERILATOR_DIR $@ +} + +run_asm () { + make run-asm-tests-fast -C $LOCAL_SIM_DIR VERILATOR_INSTALL_DIR=$LOCAL_VERILATOR_DIR $@ +} + +run_both () { + run_bmark $@ + run_asm $@ +} + +case $1 in + example) + run_bmark ${mapping[$1]} + ;; + boomexample) + run_bmark ${mapping[$1]} + ;; + boomrocketexample) + run_bmark ${mapping[$1]} + ;; + boom) + run_bmark ${mapping[$1]} + ;; + rocketchip) + run_bmark ${mapping[$1]} + ;; + hwacha) + export RISCV=$LOCAL_ESP_DIR + export LD_LIBRARY_PATH=$LOCAL_ESP_DIR/lib + export PATH=$RISCV/bin:$PATH + make run-rv64uv-p-asm-tests -C $LOCAL_SIM_DIR VERILATOR_INSTALL_DIR=$LOCAL_VERILATOR_DIR ${mapping[$1]} + ;; + *) + echo "No set of tests for $1. Did you spell it right?" + exit 1 + ;; +esac diff --git a/.gitignore b/.gitignore index 8450e9b8..b59a80fc 100644 --- a/.gitignore +++ b/.gitignore @@ -5,8 +5,11 @@ target *.stamp *.vcd *.swp +*# +*~ .idea .DS_Store env.sh riscv-tools-install tags +*~ \ No newline at end of file diff --git a/.gitmodules b/.gitmodules index 22b438a6..5bbbedd0 100644 --- a/.gitmodules +++ b/.gitmodules @@ -13,12 +13,6 @@ [submodule "tools/firrtl"] path = tools/firrtl url = https://github.com/freechipsproject/firrtl -[submodule "riscv-tools"] - path = toolchains/riscv-tools - url = https://github.com/riscv/riscv-tools.git -[submodule "esp-tools"] - path = toolchains/esp-tools - url = https://github.com/ucb-bar/esp-tools.git [submodule "tools/torture"] path = tools/torture url = https://github.com/ucb-bar/riscv-torture.git @@ -31,3 +25,24 @@ [submodule "generators/hwacha"] path = generators/hwacha url = https://github.com/ucb-bar/hwacha.git +[submodule "sims/firesim"] + path = sims/firesim + url = https://github.com/firesim/firesim.git +[submodule "generators/icenet"] + path = generators/icenet + url = https://github.com/firesim/icenet.git +[submodule "generators/block-inclusivecache-sifive"] + path = generators/sifive-cache + url = https://github.com/sifive/block-inclusivecache-sifive.git +[submodule "toolchains/riscv-tools"] + path = toolchains/riscv-tools + url = https://github.com/freechipsproject/rocket-tools.git +[submodule "toolchains/esp-tools"] + path = toolchains/esp-tools + url = https://github.com/ucb-bar/esp-tools.git +[submodule "vlsi/hammer"] + path = vlsi/hammer + url = https://github.com/ucb-bar/hammer.git +[submodule "vlsi/hammer-cad-plugins"] + path = vlsi/hammer-cad-plugins + url = https://github.com/ucb-bar/hammer-cad-plugins.git diff --git a/README.md b/README.md index 2bf6a212..fd6e723f 100644 --- a/README.md +++ b/README.md @@ -1,20 +1,20 @@ -# REBAR Framework [![CircleCI](https://circleci.com/gh/ucb-bar/project-template/tree/master.svg?style=svg)](https://circleci.com/gh/ucb-bar/project-template/tree/master) +# Chipyard Framework [![CircleCI](https://circleci.com/gh/ucb-bar/chipyard/tree/master.svg?style=svg)](https://circleci.com/gh/ucb-bar/chipyard/tree/master) -## Using REBAR +## Using Chipyard -To get started using REBAR, see the documentation on the REBAR documentation site: https://bar-project-template.readthedocs.io/en/latest/ +To get started using Chipyard, see the documentation on the Chipyard documentation site: https://chipyard.readthedocs.io/en/latest/ -## What is REBAR +## What is Chipyard -REBAR is an open source starter template for your custom Chisel project. +Chipyard is an open source starter template for your custom Chisel project. It will allow you to leverage the Chisel HDL, Rocket Chip SoC generator, and other [Berkeley][berkeley] projects to produce a [RISC-V][riscv] SoC with everything from MMIO-mapped peripherals to custom accelerators. It contains processor cores ([Rocket][rocket-chip], [BOOM][boom]), accelerators ([Hwacha][hwacha]), FPGA simulation tools ([FireSim][firesim]), ASIC tools ([HAMMER][hammer]) and other tooling to help create a full featured SoC. -REBAR is actively developed in the [Berkeley Architecture Research Group][ucb-bar] in the [Electrical Engineering and Computer Sciences Department][eecs] at the [University of California, Berkeley][berkeley]. +Chipyard is actively developed in the [Berkeley Architecture Research Group][ucb-bar] in the [Electrical Engineering and Computer Sciences Department][eecs] at the [University of California, Berkeley][berkeley]. ## Resources -* REBAR Website: ...TBD at a later date... -* REBAR Documentation: https://bar-project-template.readthedocs.io/ +* Chipyard Website: ...TBD at a later date... +* Chipyard Documentation: https://chipyard.readthedocs.io/ [hwacha]:http://hwacha.org [hammer]:https://github.com/ucb-bar/hammer diff --git a/build.sbt b/build.sbt index 6a06fcba..cb3a0b69 100644 --- a/build.sbt +++ b/build.sbt @@ -1,3 +1,5 @@ +import Tests._ + lazy val commonSettings = Seq( organization := "edu.berkeley.cs", version := "1.0", @@ -9,7 +11,7 @@ lazy val commonSettings = Seq( case _ => MergeStrategy.first}}, scalacOptions ++= Seq("-deprecation","-unchecked","-Xsource:2.11"), libraryDependencies += "org.scalatest" %% "scalatest" % "3.0.5" % "test", - libraryDependencies += "org.json4s" %% "json4s-native" % "3.6.1", + libraryDependencies += "org.json4s" %% "json4s-jackson" % "3.6.1", libraryDependencies += "org.scala-lang" % "scala-reflect" % scalaVersion.value, libraryDependencies += "edu.berkeley.cs" %% "firrtl-interpreter" % "1.2-SNAPSHOT", libraryDependencies += "com.github.scopt" %% "scopt" % "3.7.0", @@ -19,18 +21,14 @@ lazy val commonSettings = Seq( Resolver.sonatypeRepo("releases"), Resolver.mavenLocal)) -lazy val rebarFirrtl = (project in file("tools/firrtl")) - .settings(commonSettings) +val rocketChipDir = file("generators/rocket-chip") -lazy val rocketchip = RootProject(file("generators/rocket-chip")) - -lazy val rebarrocketchip = project - .dependsOn(rocketchip) - .settings(commonSettings) - -lazy val testchipip = (project in file("generators/testchipip")) - .dependsOn(rebarrocketchip) - .settings(commonSettings) +lazy val firesimAsLibrary = sys.env.get("FIRESIM_STANDALONE") == None +lazy val firesimDir = if (firesimAsLibrary) { + file("sims/firesim/sim/") +} else { + file("../../") +} // Checks for -DROCKET_USE_MAVEN. // If it's there, use a maven dependency. @@ -45,33 +43,90 @@ def conditionalDependsOn(prj: Project): Project = { } } +// Fork each scala test for now, to work around persistent mutable state +// in Rocket-Chip based generators +def isolateAllTests(tests: Seq[TestDefinition]) = tests map { test => + val options = ForkOptions() + new Group(test.name, Seq(test), SubProcess(options)) + } toSeq + +// Subproject definitions begin + +// NB: FIRRTL dependency is unmanaged (and dropped in sim/lib) +lazy val chisel = (project in rocketChipDir / "chisel3") + + // Contains annotations & firrtl passes you may wish to use in rocket-chip without +// introducing a circular dependency between RC and MIDAS +lazy val midasTargetUtils = ProjectRef(firesimDir, "targetutils") + + // Rocket-chip dependencies (subsumes making RC a RootProject) +lazy val hardfloat = (project in rocketChipDir / "hardfloat") + .settings(commonSettings).dependsOn(midasTargetUtils) + +lazy val rocketMacros = (project in rocketChipDir / "macros") + .settings(commonSettings) + +// HACK: I'm strugging to override settings in rocket-chip's build.sbt (i want +// the subproject to register a new library dependendency on midas's targetutils library) +// So instead, avoid the existing build.sbt altogether and specify the project's root at src/ +lazy val rocketchip = (project in rocketChipDir / "src") + .settings( + commonSettings, + scalaSource in Compile := baseDirectory.value / "main" / "scala", + resourceDirectory in Compile := baseDirectory.value / "main" / "resources") + .dependsOn(chisel, hardfloat, rocketMacros) + +lazy val testchipip = (project in file("generators/testchipip")) + .dependsOn(rocketchip) + .settings(commonSettings) + lazy val example = conditionalDependsOn(project in file("generators/example")) - .dependsOn(boom, hwacha, sifive_blocks) + .dependsOn(boom, hwacha, sifive_blocks, sifive_cache) .settings(commonSettings) lazy val utilities = conditionalDependsOn(project in file("generators/utilities")) .settings(commonSettings) -lazy val hwacha = (project in file ("generators/hwacha")) - .dependsOn(rebarrocketchip) +lazy val icenet = (project in file("generators/icenet")) + .dependsOn(rocketchip, testchipip) + .settings(commonSettings) + +lazy val hwacha = (project in file("generators/hwacha")) + .dependsOn(rocketchip) .settings(commonSettings) lazy val boom = (project in file("generators/boom")) - .dependsOn(rebarrocketchip) + .dependsOn(rocketchip) .settings(commonSettings) lazy val tapeout = conditionalDependsOn(project in file("./tools/barstools/tapeout/")) - .dependsOn(rebarFirrtl) .settings(commonSettings) lazy val mdf = (project in file("./tools/barstools/mdf/scalalib/")) .settings(commonSettings) -lazy val `barstools-macros` = (project in file("./tools/barstools/macros/")) - .dependsOn(mdf, rebarrocketchip, rebarFirrtl) +lazy val barstoolsMacros = (project in file("./tools/barstools/macros/")) + .dependsOn(mdf, rocketchip) .enablePlugins(sbtassembly.AssemblyPlugin) .settings(commonSettings) lazy val sifive_blocks = (project in file("generators/sifive-blocks")) - .dependsOn(rebarrocketchip) + .dependsOn(rocketchip) .settings(commonSettings) + +lazy val sifive_cache = (project in file("generators/sifive-cache")).settings( + commonSettings, + scalaSource in Compile := baseDirectory.value / "craft" + ).dependsOn(rocketchip) + +// Library components of FireSim +lazy val midas = ProjectRef(firesimDir, "midas") +lazy val firesimLib = ProjectRef(firesimDir, "firesimLib") + +lazy val firechip = (project in file("generators/firechip")) + .dependsOn(boom, icenet, testchipip, sifive_blocks, sifive_cache, midasTargetUtils, midas, firesimLib % "test->test;compile->compile") + .settings( + commonSettings, + testGrouping in Test := isolateAllTests( (definedTests in Test).value ) + ) + diff --git a/common.mk b/common.mk index f7e46608..2be99ffe 100644 --- a/common.mk +++ b/common.mk @@ -8,63 +8,67 @@ SHELL=/bin/bash ######################################################################################### lookup_scala_srcs = $(shell find -L $(1)/ -iname "*.scala" 2> /dev/null) -PACKAGES=rocket-chip testchipip boom hwacha sifive-blocks example -SCALA_SOURCES=$(foreach pkg,$(PACKAGES),$(call lookup_scala_srcs,$(base_dir)/generators/$(pkg)/src/main/scala)) +PACKAGES=$(addprefix generators/, rocket-chip testchipip boom hwacha sifive-blocks sifive-cache example) \ + $(addprefix sims/firesim/sim/, . firesim-lib midas midas/targetutils) +SCALA_SOURCES=$(foreach pkg,$(PACKAGES),$(call lookup_scala_srcs,$(base_dir)/$(pkg)/src/main/scala)) ######################################################################################### # rocket and testchipip classes ######################################################################################### -ROCKET_CLASSES ?= "$(ROCKETCHIP_DIR)/target/scala-$(SCALA_VERSION_MAJOR)/classes:$(ROCKETCHIP_DIR)/chisel3/target/scala-$(SCALA_VERSION_MAJOR)/*" +# NB: target/ lives under source ----V , due to how we're handling midas dependency injection +ROCKET_CLASSES ?= "$(ROCKETCHIP_DIR)/src/target/scala-$(SCALA_VERSION_MAJOR)/classes:$(ROCKETCHIP_DIR)/chisel3/target/scala-$(SCALA_VERSION_MAJOR)/*" TESTCHIPIP_CLASSES ?= "$(TESTCHIP_DIR)/target/scala-$(SCALA_VERSION_MAJOR)/classes" ######################################################################################### # jar creation variables and rules ######################################################################################### -FIRRTL_JAR ?= $(ROCKETCHIP_DIR)/lib/firrtl.jar +FIRRTL_JAR := $(base_dir)/lib/firrtl.jar -$(FIRRTL_JAR): $(call lookup_scala_srcs, $(REBAR_FIRRTL_DIR)/src/main/scala) - $(MAKE) -C $(REBAR_FIRRTL_DIR) SBT="$(SBT)" root_dir=$(REBAR_FIRRTL_DIR) build-scala - mkdir -p $(dir $@) - cp -p $(REBAR_FIRRTL_DIR)/utils/bin/firrtl.jar $@ +$(FIRRTL_JAR): $(call lookup_scala_srcs, $(CHIPYARD_FIRRTL_DIR)/src/main/scala) + $(MAKE) -C $(CHIPYARD_FIRRTL_DIR) SBT="$(SBT)" root_dir=$(CHIPYARD_FIRRTL_DIR) build-scala + mkdir -p $(@D) + cp -p $(CHIPYARD_FIRRTL_DIR)/utils/bin/firrtl.jar $@ touch $@ ######################################################################################### # create simulation args file rule ######################################################################################### -$(sim_dotf): $(call lookup_scala_srcs,$(base_dir)/generators/utilities/src/main/scala) $(FIRRTL_JAR) +$(sim_files): $(call lookup_scala_srcs,$(base_dir)/generators/utilities/src/main/scala) $(FIRRTL_JAR) cd $(base_dir) && $(SBT) "project utilities" "runMain utilities.GenerateSimFiles -td $(build_dir) -sim $(sim_name)" ######################################################################################### # create firrtl file rule and variables ######################################################################################### -CHISEL_ARGS ?= - -$(FIRRTL_FILE) $(ANNO_FILE): $(SCALA_SOURCES) $(sim_dotf) +$(FIRRTL_FILE) $(ANNO_FILE): $(SCALA_SOURCES) $(sim_files) mkdir -p $(build_dir) - cd $(base_dir) && $(SBT) "project $(SBT_PROJECT)" "runMain $(GENERATOR_PACKAGE).Generator $(CHISEL_ARGS) $(build_dir) $(MODEL_PACKAGE) $(MODEL) $(CONFIG_PACKAGE) $(CONFIG)" + cd $(base_dir) && $(SBT) "project $(SBT_PROJECT)" "runMain $(GENERATOR_PACKAGE).Generator $(build_dir) $(MODEL_PACKAGE) $(MODEL) $(CONFIG_PACKAGE) $(CONFIG)" ######################################################################################### # create verilog files rules and variables ######################################################################################### -REPL_SEQ_MEM = --infer-rw --repl-seq-mem -c:$(MODEL):-o:$(SMEMS_CONF) -HARNESS_REPL_SEQ_MEM = --infer-rw --repl-seq-mem -c:$(MODEL):-o:$(HARNESS_SMEMS_CONF) +REPL_SEQ_MEM = --infer-rw --repl-seq-mem -c:$(MODEL):-o:$(TOP_SMEMS_CONF) +HARNESS_CONF_FLAGS = -thconf $(HARNESS_SMEMS_CONF) -$(VERILOG_FILE) $(SMEMS_CONF) $(TOP_ANNO) $(TOP_FIR) $(sim_top_blackboxes): $(FIRRTL_FILE) $(ANNO_FILE) - cd $(base_dir) && $(SBT) "project tapeout" "runMain barstools.tapeout.transforms.GenerateTop -o $(VERILOG_FILE) -i $(FIRRTL_FILE) --syn-top $(TOP) --harness-top $(MODEL) -faf $(ANNO_FILE) -tsaof $(TOP_ANNO) -tsf $(TOP_FIR) $(REPL_SEQ_MEM) -td $(build_dir)" - cp $(build_dir)/firrtl_black_box_resource_files.f $(sim_top_blackboxes) +TOP_TARGETS = $(TOP_FILE) $(TOP_SMEMS_CONF) $(TOP_ANNO) $(TOP_FIR) $(sim_top_blackboxes) +HARNESS_TARGETS = $(HARNESS_FILE) $(HARNESS_SMEMS_CONF) $(HARNESS_ANNO) $(HARNESS_FIR) $(sim_harness_blackboxes) -$(HARNESS_FILE) $(HARNESS_ANNO) $(HARNESS_FIR) $(sim_harness_blackboxes): $(FIRRTL_FILE) $(ANNO_FILE) $(sim_top_blackboxes) - cd $(base_dir) && $(SBT) "project tapeout" "runMain barstools.tapeout.transforms.GenerateHarness -o $(HARNESS_FILE) -i $(FIRRTL_FILE) --syn-top $(TOP) --harness-top $(VLOG_MODEL) -faf $(ANNO_FILE) -thaof $(HARNESS_ANNO) -thf $(HARNESS_FIR) $(HARNESS_REPL_SEQ_MEM) -td $(build_dir)" - grep -v "SimSerial.cc\|SimDTM.cc\|SimJTAG.cc" $(build_dir)/firrtl_black_box_resource_files.f > $(sim_harness_blackboxes) +$(TOP_TARGETS) $(HARNESS_TARGETS): $(FIRRTL_FILE) $(ANNO_FILE) + cd $(base_dir) && $(SBT) "project tapeout" "runMain barstools.tapeout.transforms.GenerateTopAndHarness -o $(TOP_FILE) -tho $(HARNESS_FILE) -i $(FIRRTL_FILE) --syn-top $(TOP) --harness-top $(VLOG_MODEL) -faf $(ANNO_FILE) -tsaof $(TOP_ANNO) -tdf $(sim_top_blackboxes) -tsf $(TOP_FIR) -thaof $(HARNESS_ANNO) -hdf $(sim_harness_blackboxes) -thf $(HARNESS_FIR) $(REPL_SEQ_MEM) $(HARNESS_CONF_FLAGS) -td $(build_dir)" # This file is for simulation only. VLSI flows should replace this file with one containing hard SRAMs MACROCOMPILER_MODE ?= --mode synflops -$(SMEMS_FILE) $(SMEMS_FIR): $(SMEMS_CONF) - cd $(base_dir) && $(SBT) "project barstools-macros" "runMain barstools.macros.MacroCompiler -n $(SMEMS_CONF) -v $(SMEMS_FILE) -f $(SMEMS_FIR) $(MACROCOMPILER_MODE)" +$(TOP_SMEMS_FILE) $(TOP_SMEMS_FIR): $(TOP_SMEMS_CONF) + cd $(base_dir) && $(SBT) "project barstoolsMacros" "runMain barstools.macros.MacroCompiler -n $(TOP_SMEMS_CONF) -v $(TOP_SMEMS_FILE) -f $(TOP_SMEMS_FIR) $(MACROCOMPILER_MODE)" HARNESS_MACROCOMPILER_MODE = --mode synflops $(HARNESS_SMEMS_FILE) $(HARNESS_SMEMS_FIR): $(HARNESS_SMEMS_CONF) - cd $(base_dir) && $(SBT) "project barstools-macros" "runMain barstools.macros.MacroCompiler -n $(HARNESS_SMEMS_CONF) -v $(HARNESS_SMEMS_FILE) -f $(HARNESS_SMEMS_FIR) $(HARNESS_MACROCOMPILER_MODE)" + cd $(base_dir) && $(SBT) "project barstoolsMacros" "runMain barstools.macros.MacroCompiler -n $(HARNESS_SMEMS_CONF) -v $(HARNESS_SMEMS_FILE) -f $(HARNESS_SMEMS_FIR) $(HARNESS_MACROCOMPILER_MODE)" + +######################################################################################## +# remove duplicate files in blackbox/simfiles +######################################################################################## +$(sim_common_files): $(sim_files) $(sim_top_blackboxes) $(sim_harness_blackboxes) + awk '{print $1;}' $^ | sort -u > $@ ######################################################################################### # helper rule to just make verilog files @@ -73,10 +77,25 @@ $(HARNESS_SMEMS_FILE) $(HARNESS_SMEMS_FIR): $(HARNESS_SMEMS_CONF) verilog: $(sim_vsrcs) ######################################################################################### -# helper rules to run simulator +# helper rules to run simulations ######################################################################################### +.PHONY: run-binary run-binary-fast run-binary-debug run-fast run-binary: $(sim) - $(sim) $(PERMISSIVE_ON) $(SIM_FLAGS) $(PERMISSIVE_OFF) $(BINARY) 3>&1 1>&2 2>&3 | spike-dasm > $(sim_out_name).out + (set -o pipefail && $(sim) $(PERMISSIVE_ON) +max-cycles=$(timeout_cycles) $(SIM_FLAGS) $(VERBOSE_FLAGS) $(PERMISSIVE_OFF) $(BINARY) 3>&1 1>&2 2>&3 | spike-dasm > $(sim_out_name).out) + +######################################################################################### +# helper rules to run simulator as fast as possible +######################################################################################### +run-binary-fast: $(sim) + (set -o pipefail && $(sim) $(PERMISSIVE_ON) +max-cycles=$(timeout_cycles) $(SIM_FLAGS) $(PERMISSIVE_OFF) $(BINARY) 3>&1 1>&2 2>&3 | spike-dasm > $(sim_out_name).out) + +######################################################################################### +# helper rules to run simulator with as much debug info as possible +######################################################################################### +run-binary-debug: $(sim_debug) + (set -o pipefail && $(sim_debug) $(PERMISSIVE_ON) +max-cycles=$(timeout_cycles) $(SIM_FLAGS) $(VERBOSE_FLAG) $(WAVEFORM_FLAG) $(PERMISSIVE_OFF) $(BINARY) 3>&1 1>&2 2>&3 | spike-dasm > $(sim_out_name).out) + +run-fast: run-asm-tests-fast run-bmark-tests-fast ######################################################################################### # run assembly/benchmarks rules @@ -86,10 +105,10 @@ $(output_dir)/%: $(RISCV)/riscv64-unknown-elf/share/riscv-tests/isa/% ln -sf $< $@ $(output_dir)/%.run: $(output_dir)/% $(sim) - $(sim) $(PERMISSIVE_ON) +max-cycles=$(timeout_cycles) $(PERMISSIVE_OFF) $< && touch $@ + $(sim) $(PERMISSIVE_ON) +max-cycles=$(timeout_cycles) $(SIM_FLAGS) $(PERMISSIVE_OFF) $< && touch $@ $(output_dir)/%.out: $(output_dir)/% $(sim) - $(sim) $(PERMISSIVE_ON) +verbose +max-cycles=$(timeout_cycles) $(PERMISSIVE_OFF) $< 3>&1 1>&2 2>&3 | spike-dasm > $@ + (set -o pipefail && $(sim) $(PERMISSIVE_ON) +max-cycles=$(timeout_cycles) $(VERBOSE_FLAGS) $(PERMISSIVE_OFF) $< 3>&1 1>&2 2>&3 | spike-dasm > $@) ######################################################################################### # include build/project specific makefrags made from the generator diff --git a/docs/Advanced-Usage/DTM-Debugging.rst b/docs/Advanced-Usage/DTM-Debugging.rst new file mode 100644 index 00000000..bf033fec --- /dev/null +++ b/docs/Advanced-Usage/DTM-Debugging.rst @@ -0,0 +1,50 @@ +Debugging with DTM/JTAG +=============================== + +By default, Chipyard is not setup to use the Debug Test Module (DTM) to bringup the core. +Instead, Chipyard uses TSI commands to bringup the core (which normally results in a faster simulation). +TSI simulations use the SimSerial interface to directly write the test binary into memory, while the DTM +executes a small loop of code to write the test binary byte-wise into memory. +However, if you want to use JTAG, you must do the following steps to setup a DTM enabled system. + +Creating a DTM/JTAG Config +------------------------------------------- + +First, a DTM config must be created for the system that you want to create. +This involves specifying the SoC top-level to add a DTM as well as configuring that DTM to use JTAG. + +.. code-block:: scala + + class DTMBoomConfig extends Config( + new WithDTMBoomRocketTop ++ + new WithBootROM ++ + new WithJtagDTM ++ + new boom.common.SmallBoomConfig) + +In this example, the ``WithDTMBoomRocketTop`` mixin specifies that the top-level SoC will instantiate a DTM. +The ``WithJtagDTM`` will configure that instantiated DTM to use JTAG as the bringup method (note: this can be removed if you want a DTM-only bringup). +The rest of the mixins specify the rest of the system (cores, accelerators, etc). + +Starting the DTM Simulation +------------------------------------------- + +After creating the config, call the ``make`` command like the following: + +.. code-block:: bash + + cd sims/verilator + # or + cd sims/vcs + + make CONFIG=DTMBoomConfig TOP=BoomRocketTopWithDTM MODEL=TestHarnessWithDTM + +In this example, this will use the config that you previously specified, as well as set the other parameters that are needed to satisfy the build system. +After that point, you should have a JTAG enabled simulation that you can attach to using OpenOCD and GDB! + +Debugging with JTAG +------------------------------------------------------- + +Please refer to the following resources on how to debug with JTAG. + +* https://github.com/chipsalliance/rocket-chip#-debugging-with-gdb +* https://github.com/riscv/riscv-isa-sim#debugging-with-gdb diff --git a/docs/Advanced-Usage/Resources.rst b/docs/Advanced-Usage/Resources.rst new file mode 100644 index 00000000..538c43b0 --- /dev/null +++ b/docs/Advanced-Usage/Resources.rst @@ -0,0 +1,38 @@ +Accessing Scala Resources +=============================== + +A simple way to copy over a source file to the build directory to be used for a simulation compile or VLSI flow is to use the ``setResource`` or ``addResource`` functions given by FIRRTL. +They can be used in the following way: + +.. code-block:: scala + + class SimSerial(w: Int) extends BlackBox with HasBlackBoxResource { + val io = IO(new Bundle { + val clock = Input(Clock()) + val reset = Input(Bool()) + val serial = Flipped(new SerialIO(w)) + val exit = Output(Bool()) + }) + + setResource("/testchipip/vsrc/SimSerial.v") + setResource("/testchipip/csrc/SimSerial.cc") + } + +In this example, the ``SimSerial`` files will be copied from a specific folder (in this case the ``path/to/testchipip/src/main/resources/testchipip/...``) to the build folder. +The ``set/addResource`` path retrieves resources from the ``src/main/resources`` directory. +So to get an item at ``src/main/resources/fileA.v`` you can use ``setResource("/fileA.v")``. +However, one caveat of this approach is that to retrieve the file during the FIRRTL compile, you must have that project in the FIRRTL compiler's classpath. +Thus, you need to add the SBT project as a dependency to the FIRRTL compiler in the Chipyard ``build.sbt``, which in Chipyards case is the ``tapeout`` project. +For example, you added a new project called ``myAwesomeAccel`` in the Chipyard ``build.sbt``. +Then you can add it as a ``dependsOn`` dependency to the ``tapeout`` project. +For example: + +.. code-block:: scala + + lazy val myAwesomeAccel = (project in file("generators/myAwesomeAccelFolder")) + .dependsOn(rocketchip) + .settings(commonSettings) + + lazy val tapeout = conditionalDependsOn(project in file("./tools/barstools/tapeout/")) + .dependsOn(myAwesomeAccel) + .settings(commonSettings) diff --git a/docs/Advanced-Usage/index.rst b/docs/Advanced-Usage/index.rst new file mode 100644 index 00000000..2a8824b2 --- /dev/null +++ b/docs/Advanced-Usage/index.rst @@ -0,0 +1,12 @@ +Advanced Usage +================================ + +The following sections are advanced topics about how to use Chipyard and special features of the framework. +They expect you to know about Chisel, Parameters, Configs, etc. + +.. toctree:: + :maxdepth: 2 + :caption: Advanced Usage: + + DTM-Debugging + Resources diff --git a/docs/Chipyard-Basics/Building-A-Chip.rst b/docs/Chipyard-Basics/Building-A-Chip.rst new file mode 100644 index 00000000..3fbbd9ea --- /dev/null +++ b/docs/Chipyard-Basics/Building-A-Chip.rst @@ -0,0 +1,6 @@ +.. _build-a-chip: + +Building A Chip +============================== + +TODO diff --git a/docs/Getting-Started/REBAR-Basics.rst b/docs/Chipyard-Basics/Chipyard-Components.rst similarity index 88% rename from docs/Getting-Started/REBAR-Basics.rst rename to docs/Chipyard-Basics/Chipyard-Components.rst index 5dcac5d7..49aff86a 100644 --- a/docs/Getting-Started/REBAR-Basics.rst +++ b/docs/Chipyard-Basics/Chipyard-Components.rst @@ -1,10 +1,12 @@ -REBAR Basics +.. _chipyard-components: + +Chipyard Components =============================== Generators ------------------------------------------- -The REBAR Framework currently consists of the following RTL generators: +The Chipyard Framework currently consists of the following RTL generators: Processor Cores ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -72,7 +74,7 @@ Toolchains A collection of software toolchains used to develop and execute software on the RISC-V ISA. The include compiler and assembler toolchains, functional ISA simulator (spike), the Berkeley Boot Loader (BBL) and proxy kernel. The riscv-tools repository was previously required to run any RISC-V software, however, many of the riscv-tools components have since been upstreamed to their respective open-source projects (Linux, GNU, etc.). - Nevertheless, for consistent versioning, as well as software design flexibility for custom hardware, we include the riscv-tools repository and installation in the REBAR framework. + Nevertheless, for consistent versioning, as well as software design flexibility for custom hardware, we include the riscv-tools repository and installation in the Chipyard framework. **esp-tools** A fork of riscv-tools, designed to work with the Hwacha non-standard RISC-V extension. @@ -81,14 +83,14 @@ Toolchains Sims ------------------------------------------- -**verisim (Verilator wrapper)** +**verilator (Verilator wrapper)** Verilator is an open source Verilog simulator. - The ``verisim`` directory provides wrappers which construct Verilator-based simulators from relevant generated RTL, allowing for execution of test RISC-V programs on the simulator (including vcd waveform files). + The ``verilator`` directory provides wrappers which construct Verilator-based simulators from relevant generated RTL, allowing for execution of test RISC-V programs on the simulator (including vcd waveform files). See :ref:`Verilator` for more information. -**vsim (VCS wrapper)** +**vcs (VCS wrapper)** VCS is a proprietary Verilog simulator. - Assuming the user has valid VCS licenses and installations, the ``vsim`` directory provides wrappers which construct VCS-based simulators from relevant generated RTL, allowing for execution of test RISC-V programs on the simulator (including vcd/vpd waveform files). + Assuming the user has valid VCS licenses and installations, the ``vcs`` directory provides wrappers which construct VCS-based simulators from relevant generated RTL, allowing for execution of test RISC-V programs on the simulator (including vcd/vpd waveform files). See :ref:`VCS` for more information. **FireSim** diff --git a/docs/Getting-Started/rebar-generator-mixins.rst b/docs/Chipyard-Basics/Chipyard-Generator-Mixins.rst similarity index 100% rename from docs/Getting-Started/rebar-generator-mixins.rst rename to docs/Chipyard-Basics/Chipyard-Generator-Mixins.rst diff --git a/docs/Getting-Started/Configs-Parameters-Mixins.rst b/docs/Chipyard-Basics/Configs-Parameters-Mixins.rst similarity index 94% rename from docs/Getting-Started/Configs-Parameters-Mixins.rst rename to docs/Chipyard-Basics/Configs-Parameters-Mixins.rst index 852f85af..d9becfdf 100644 --- a/docs/Getting-Started/Configs-Parameters-Mixins.rst +++ b/docs/Chipyard-Basics/Configs-Parameters-Mixins.rst @@ -1,7 +1,7 @@ Configs, Parameters, Mix-ins, and Everything In Between ======================================================== -A significant portion of generators in the REBAR framework use the Rocket Chip parameter system. +A significant portion of generators in the Chipyard framework use the Rocket Chip parameter system. This parameter system enables for the flexible configuration of the SoC without invasive RTL changes. In order to use the parameter system correctly, we will use several terms and conventions: @@ -69,7 +69,7 @@ Cake Pattern ------------------------- A cake pattern is a Scala programming pattern, which enable "mixing" of multiple traits or interface definitions (sometimes referred to as dependency injection). -It is used in the Rocket Chip SoC library and REBAR framework in merging multiple system components and IO interfaces into a large system component. +It is used in the Rocket Chip SoC library and Chipyard framework in merging multiple system components and IO interfaces into a large system component. :numref:`cake-example` shows a Rocket Chip based SoC that merges multiple system components (BootROM, UART, etc) into a single top-level design. diff --git a/docs/Getting-Started/Development-Ecosystem.rst b/docs/Chipyard-Basics/Development-Ecosystem.rst similarity index 80% rename from docs/Getting-Started/Development-Ecosystem.rst rename to docs/Chipyard-Basics/Development-Ecosystem.rst index fa407194..7755a7f3 100644 --- a/docs/Getting-Started/Development-Ecosystem.rst +++ b/docs/Chipyard-Basics/Development-Ecosystem.rst @@ -1,12 +1,12 @@ Development Ecosystem =============================== -REBAR Approach +Chipyard Approach ------------------------------------------- The trend towards agile hardware design and evaluation provides an ecosystem of debugging and implementation tools, that make it easier for computer architecture researchers to develop novel concepts. -REBAR hopes to build on this prior work in order to create a singular location to which multiple projects within the `Berkeley Architecture Research `__ can coexist and be used together. -REBAR aims to be the "one-stop shop" for creating and testing your own unique System on a Chip (SoC). +Chipyard hopes to build on this prior work in order to create a singular location to which multiple projects within the `Berkeley Architecture Research `__ can coexist and be used together. +Chipyard aims to be the "one-stop shop" for creating and testing your own unique System on a Chip (SoC). Chisel/FIRRTL ------------------------------------------- diff --git a/docs/Getting-Started/Initial-Repo-Setup.rst b/docs/Chipyard-Basics/Initial-Repo-Setup.rst similarity index 88% rename from docs/Getting-Started/Initial-Repo-Setup.rst rename to docs/Chipyard-Basics/Initial-Repo-Setup.rst index 58a40d56..7b7042ee 100644 --- a/docs/Getting-Started/Initial-Repo-Setup.rst +++ b/docs/Chipyard-Basics/Initial-Repo-Setup.rst @@ -8,8 +8,8 @@ After cloning this repo, you will need to initialize all of the submodules. .. code-block:: shell - git clone https://github.com/ucb-bar/project-template.git - cd project-template + git clone https://github.com/ucb-bar/chipyard.git + cd chipyard ./scripts/init-submodules-no-riscv-tools.sh Building a Toolchain @@ -26,7 +26,7 @@ But to get a basic installation, just the following steps are necessary. # OR - ./scripts/build-toolchains.sh hwacha # for a hwacha modified risc-v toolchain + ./scripts/build-toolchains.sh esp-tools # for a modified risc-v toolchain with Hwacha vector instructions Once the script is run, a ``env.sh`` file is emitted at sets the ``PATH``, ``RISCV``, and ``LD_LIBRARY_PATH`` environment variables. You can put this in your ``.bashrc`` or equivalent environment setup file to get the proper variables. diff --git a/docs/Getting-Started/Running-A-Simulation.rst b/docs/Chipyard-Basics/Running-A-Simulation.rst similarity index 89% rename from docs/Getting-Started/Running-A-Simulation.rst rename to docs/Chipyard-Basics/Running-A-Simulation.rst index 673bf0ae..39128f30 100644 --- a/docs/Getting-Started/Running-A-Simulation.rst +++ b/docs/Chipyard-Basics/Running-A-Simulation.rst @@ -1,13 +1,13 @@ Running A Simulation ======================================================== -REBAR provides support and integration for multiple simulation flows, for various user levels and requirements. +Chipyard provides support and integration for multiple simulation flows, for various user levels and requirements. In the majority of cases during a digital design development process, simple software RTL simulation is needed. When more advanced full-system evaluation is required, with long running workloads, FPGA-accelerated simulation will then become a preferable solution. Software RTL Simulation ------------------------ -The REBAR framework provides wrappers for two common software RTL simulators: +The Chipyard framework provides wrappers for two common software RTL simulators: the open-source Verilator simulator and the proprietary VCS simulator. For more information on either of these simulators, please refer to :ref:`Verilator` or :ref:`VCS`. The following instructions assume at least one of these simulators is installed. @@ -15,9 +15,9 @@ The following instructions assume at least one of these simulators is installed. Verilator/VCS Flows ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Verilator is an open-source RTL simulator. -We run Verilator simulations from within the ``sims/verisim`` directory which provides the necessary ``Makefile`` to both install and run Verilator simulations. +We run Verilator simulations from within the ``sims/verilator`` directory which provides the necessary ``Makefile`` to both install and run Verilator simulations. On the other hand, VCS is a proprietary RTL simulator. -We run VCS simulations from within the ``sims/vsim`` directory. +We run VCS simulations from within the ``sims/vcs`` directory. Assuming VCS is already installed on the machine running simulations (and is found on our ``PATH``), then this guide is the same for both Verilator and VCS. First, we will start by entering the Verilator or VCS directory: @@ -25,12 +25,12 @@ First, we will start by entering the Verilator or VCS directory: .. code-block:: shell # Enter Verilator directory - cd sims/verisim + cd sims/verilator # OR # Enter VCS directory - cd sims/vsim + cd sims/vcs In order to construct the simulator with our custom design, we run the following command within the simulator directory: @@ -97,7 +97,7 @@ FireSim enables simulations at 1000x-100000x the speed of standard software simu This is enabled using FPGA-acceleration on F1 instances of the AWS (Amazon Web Services) public cloud. Therefore FireSim simulation requires to be set-up on the AWS public cloud rather than on our local development machine. -To run an FPGA-accelerated simulation using FireSim, a we need to clone the REBAR repository (or our fork of the REBAR repository) to an AWS EC2, and follow the setup instructions specified in the FireSim Initial Setup documentation page. +To run an FPGA-accelerated simulation using FireSim, a we need to clone the Chipyard repository (or our fork of the Chipyard repository) to an AWS EC2, and follow the setup instructions specified in the FireSim Initial Setup documentation page. After setting up the FireSim environment, we now need to generate a FireSim simulation around our selected digital design. We will work from within the ``sims/firesim`` directory. diff --git a/docs/Chipyard-Basics/index.rst b/docs/Chipyard-Basics/index.rst new file mode 100644 index 00000000..be46c627 --- /dev/null +++ b/docs/Chipyard-Basics/index.rst @@ -0,0 +1,24 @@ +Chipyard Basics +================================ + +These guides will walk you through the basics of the Chipyard framework: + +- First, we will go over the components of the framework. + +- Next, we will go over the different configurations available. + +- Then, we will go over initial framework setup. + +- Finally, we will briefly walk through what you can do with the Chipyard tools. + +Hit next to get started! + +.. toctree:: + :maxdepth: 2 + :caption: Chipyard Basics: + + Chipyard-Components + Configs-Parameters-Mixins + Initial-Repo-Setup + Running-A-Simulation + Building-A-Chip diff --git a/docs/Getting-Started/Adding-An-Accelerator-Tutorial.rst b/docs/Customization/Adding-An-Accelerator.rst similarity index 95% rename from docs/Getting-Started/Adding-An-Accelerator-Tutorial.rst rename to docs/Customization/Adding-An-Accelerator.rst index bad5ceef..0b688ea6 100644 --- a/docs/Getting-Started/Adding-An-Accelerator-Tutorial.rst +++ b/docs/Customization/Adding-An-Accelerator.rst @@ -1,3 +1,5 @@ +.. _adding-an-accelerator: + Adding An Accelerator/Device =============================== @@ -28,7 +30,7 @@ Integrating into the Generator Build System ------------------------------------------- While developing, you want to include Chisel code in a submodule so that it can be shared by different projects. -To add a submodule to the REBAR framework, make sure that your project is organized as follows. +To add a submodule to the Chipyard framework, make sure that your project is organized as follows. .. code-block:: none @@ -45,11 +47,11 @@ Then add it as a submodule to under the following directory hierarchy: ``generat cd generators/ git submodule add https://git-repository.com/yourproject.git -Then add ``yourproject`` to the REBAR top-level build.sbt file. +Then add ``yourproject`` to the Chipyard top-level build.sbt file. .. code-block:: scala - lazy val yourproject = project.settings(commonSettings).dependsOn(rocketchip) + lazy val yourproject = (project in file("generators/yourproject")).settings(commonSettings).dependsOn(rocketchip) You can then import the classes defined in the submodule in a new project if you add it as a dependency. For instance, if you want to use this code in @@ -59,9 +61,15 @@ the ``example`` project, change the final line in build.sbt to the following. lazy val example = (project in file(".")).settings(commonSettings).dependsOn(testchipip, yourproject) -Finally, add ``yourproject`` to the ``PACKAGES`` variable in the ``common.mk`` file in the REBAR top level. +Finally, add ``yourproject`` to the ``PACKAGES`` variable in the ``common.mk`` file in the Chipyard top level. This will allow make to detect that your source files have changed when building the Verilog/FIRRTL files. +.. code-block:: shell + + PACKAGES=$(addprefix generators/, rocket-chip testchipip boom hwacha sifive-blocks sifive-cache example yourproject) \ + $(addprefix sims/firesim/sim/, . firesim-lib midas midas/targetutils) + + MMIO Peripheral ------------------ @@ -227,7 +235,7 @@ Now with all of that done, we can go ahead and run our simulation. .. code-block:: shell - cd verisim + cd verilator make CONFIG=PWMConfig ./simulator-example-PWMConfig ../tests/pwm.riscv diff --git a/docs/Customization/Heterogeneous-SoCs.rst b/docs/Customization/Heterogeneous-SoCs.rst new file mode 100644 index 00000000..96a7e40e --- /dev/null +++ b/docs/Customization/Heterogeneous-SoCs.rst @@ -0,0 +1,126 @@ +Heterogeneous SoCs +=============================== + +The Chipyard framework involves multiple cores and accelerators that can be composed in arbitrary ways. +This discussion will focus on how you combine Rocket, BOOM and Hwacha in particular ways to create a unique SoC. + +Creating a Rocket and BOOM System +------------------------------------------- + +Instantiating an SoC with Rocket and BOOM cores is all done with the configuration system and two specific mixins. +Both BOOM and Rocket have mixins labelled ``WithNBoomCores(X)`` and ``WithNBigCores(X)`` that automatically create ``X`` copies of the core. +When used together you can create a heterogeneous system. +The following example shows a dual core BOOM with a single core Rocket. + +.. code-block:: scala + + class DualBoomAndOneRocketConfig extends Config( + new WithNormalBoomRocketTop ++ + new WithBootROM ++ + new boom.system.WithRenumberHarts ++ + new boom.common.WithRVC ++ + new boom.common.DefaultBoomConfig ++ + new boom.system.WithNBoomCores(2) ++ + new freechips.rocketchip.subsystem.WithoutTLMonitors ++ + new freechips.rocketchip.subsystem.WithNBigCores(1) ++ + new freechips.rocketchip.system.BaseConfig) + +In this example, the ``WithNBoomCores`` and ``WithNBigCores`` mixins set up the default parameters for the multiple BOOM and Rocket cores, respectively. +However, for BOOM, an extra mixin called ``DefaultBoomConfig`` is added to override the default parameters with a different set of more common default parameters. +This mixin applies to all BOOM cores in the system and changes the parameters for each. + +Great! Now you have a heterogeneous setup with BOOMs and Rockets. +The final thing you need to make this system work is to renumber the ``hartId``'s of the cores so that each core has a unique ``hartId`` (a ``hartId`` is the hardware thread id of the core). +This is done with ``WithRenumberHarts`` (which can label the Rocket cores first or the BOOM cores first). +The reason this is needed is because by default the ``WithN...Cores(X)`` mixin assumes that there are only BOOM or only Rocket cores in the system. +Thus, without the ``WithRenumberHarts`` mixin, each set of cores is labeled starting from zero causing multiple cores to be assigned the same ``hartId``. + +Another alternative option to create a multi heterogeneous core system is to override the parameters yourself so you can specify the core parameters per core. +The mixin to add to your system would look something like the following. + +.. code-block:: scala + + // create 6 cores (4 boom and 2 rocket) + class WithHeterCoresSetup extends Config((site, here, up) => { + case BoomTilesKey => { + val boomTile0 = BoomTileParams(...) // params for boom core 0 + val boomTile1 = BoomTileParams(...) // params for boom core 1 + val boomTile2 = BoomTileParams(...) // params for boom core 2 + val boomTile3 = BoomTileParams(...) // params for boom core 3 + boomTile0 ++ boomTile1 ++ boomTile2 ++ boomTile3 + } + + case RocketTilesKey => { + val rocketTile0 = RocketTileParams(...) // params for rocket core 0 + val rocketTile1 = RocketTileParams(...) // params for rocket core 1 + rocketTile0 ++ rocketTile1 + } + }) + +Then you could use this new mixin like the following. + +.. code-block:: scala + + class SixCoreConfig extends Config( + new WithNormalBoomRocketTop ++ + new WithBootROM ++ + new WithHeterCoresSetup ++ + new freechips.rocketchip.system.BaseConfig) + +Note, in this setup you need to specify the ``hartId`` of each core in the "TileParams", where each ``hartId`` is unique. + +Adding Hwachas +------------------------------------------- + +Adding a Hwacha accelerator is as easy as adding the ``DefaultHwachaConfig`` so that it can setup the Hwacha parameters and add itself to the ``BuildRoCC`` parameter. +An example of adding a Hwacha to all tiles in the system is below. + +.. code-block:: scala + + class DualBoomAndRocketWithHwachasConfig extends Config( + new WithNormalBoomRocketTop ++ + new WithBootROM ++ + new hwacha.DefaultHwachaConfig ++ + new boom.system.WithRenumberHarts ++ + new boom.common.WithRVC ++ + new boom.common.DefaultBoomConfig ++ + new boom.system.WithNBoomCores(2) ++ + new freechips.rocketchip.subsystem.WithoutTLMonitors ++ + new freechips.rocketchip.subsystem.WithNBigCores(1) ++ + new freechips.rocketchip.system.BaseConfig) + +In this example, Hwachas are added to both BOOM tiles and to the Rocket tile. +All with the same Hwacha parameters. + +Assigning Accelerators to Specific Tiles with MultiRoCC +------------------------------------------------------- + +Located in ``generators/example/src/main/scala/ConfigMixins.scala`` is a mixin that provides support for adding RoCC accelerators to specific tiles in your SoC. +Named ``MultiRoCCKey``, this key allows you to attach RoCC accelerators based on the ``hartId`` of the tile. +For example, using this allows you to create a 8 tile system with a RoCC accelerator on only a subset of the tiles. +An example is shown below with two BOOM cores, and one Rocket tile with a RoCC accelerator (Hwacha) attached. + +.. code-block:: scala + + class DualBoomAndOneHwachaRocketConfig extends Config( + new WithNormalBoomRocketTop ++ + new WithBootROM ++ + new WithMultiRoCC ++ + new WithMultiRoCCHwacha(0) ++ // put Hwacha just on hart0 which was renumbered to Rocket + new boom.system.WithRenumberHarts(rocketFirst = true) ++ + new hwacha.DefaultHwachaConfig ++ + new boom.common.WithRVC ++ + new boom.common.DefaultBoomConfig ++ + new boom.system.WithNBoomCores(2) ++ + new freechips.rocketchip.subsystem.WithoutTLMonitors ++ + new freechips.rocketchip.subsystem.WithNBigCores(1) ++ + new freechips.rocketchip.system.BaseConfig) + +In this example, the ``WithRenumberHarts`` relabels the ``hartId``'s of all the BOOM/Rocket cores. +Then after that is applied to the parameters, the ``WithMultiRoCCHwacha(0)`` is used to assign to ``hartId`` zero a Hwacha (in this case ``hartId`` zero is Rocket). +Finally, the ``WithMultiRoCC`` mixin is called. +This mixin sets the ``BuildRoCC`` key to use the ``MultiRoCCKey`` instead of the default. +This must be used after all the RoCC parameters are set because it needs to override the ``BuildRoCC`` parameter. +If this is used earlier in the configuration sequence, then MultiRoCC does not work. + +This mixin can be changed to put more accelerators on more cores by changing the arguments to cover more ``hartId``'s (i.e. ``WithMultiRoCCHwacha(0,1,3,6,...)``). diff --git a/docs/Customization/Memory-Hierarchy.rst b/docs/Customization/Memory-Hierarchy.rst new file mode 100644 index 00000000..fc9792c4 --- /dev/null +++ b/docs/Customization/Memory-Hierarchy.rst @@ -0,0 +1,4 @@ +Memory Hierarchy +=============================== +TODO: Talk about SiFive Cache, and integration with L1 and backing main memory models +(maybe even Tilelink) diff --git a/docs/Customization/index.rst b/docs/Customization/index.rst new file mode 100644 index 00000000..8d61801e --- /dev/null +++ b/docs/Customization/index.rst @@ -0,0 +1,18 @@ +Customization +================================ + +These guides will walk you through customization of your system-on-chip: + +- Contructing heterogenous systems-on-chip using the Chipyard generators and configuration system. + +- Adding custom accelerators to your system-on-chip. + +Hit next to get started! + +.. toctree:: + :maxdepth: 2 + :caption: Customization: + + Heterogeneous-SoCs + Adding-An-Accelerator + Memory-Hierarchy diff --git a/docs/Generators/index.rst b/docs/Generators/index.rst index 765b2549..a01b5adc 100644 --- a/docs/Generators/index.rst +++ b/docs/Generators/index.rst @@ -5,7 +5,7 @@ Generator can be thought of as a generalized RTL design, written using a mix of This type of meta-programming is enabled by the Chisel hardware description language (see :ref:`Chisel`). A standard RTL design is essentially just a single instance of a design coming from a generator. However, by using meta-programming and parameter systems, generators can allow for integration of complex hardware designs in automated ways. -The following pages introduce the generators integrated with the REBAR framework. +The following pages introduce the generators integrated with the Chipyard framework. .. toctree:: :maxdepth: 2 diff --git a/docs/Getting-Started/index.rst b/docs/Getting-Started/index.rst deleted file mode 100644 index be6aa1e3..00000000 --- a/docs/Getting-Started/index.rst +++ /dev/null @@ -1,21 +0,0 @@ -Getting Started -================================ - -These guides will walk you through the basics of the REBAR framework: - -- First, we will go over the different configurations available. - -- Then, we will walk through adding a custom accelerator. - -Hit next to get started! - -.. toctree:: - :maxdepth: 2 - :caption: Getting Started: - - REBAR-Basics - Configs-Parameters-Mixins - Adding-An-Accelerator-Tutorial - Initial-Repo-Setup - Running-A-Simulation - rebar-generator-mixins diff --git a/docs/Makefile b/docs/Makefile index b3492e6c..adea9f26 100644 --- a/docs/Makefile +++ b/docs/Makefile @@ -4,7 +4,7 @@ # You can set these variables from the command line. SPHINXOPTS = SPHINXBUILD = python -msphinx -SPHINXPROJ = REBAR +SPHINXPROJ = Chipyard SOURCEDIR = . BUILDDIR = _build diff --git a/docs/Quick-Start.rst b/docs/Quick-Start.rst new file mode 100644 index 00000000..936597e6 --- /dev/null +++ b/docs/Quick-Start.rst @@ -0,0 +1,49 @@ +Quick Start +=============================== + +Setting up the Chipyard Repo +------------------------------------------- + +Start by fetching Chipyard's sources. Run: + +.. code-block:: shell + + git clone https://github.com/ucb-bar/chipyard.git + cd chipyard + ./scripts/init-submodules-no-riscv-tools.sh + +This will have initialized the git submodules. + +Installing the RISC-V Tools +------------------------------------------- + +We need to install the RISC-V toolchain in order to be able to run RISC-V programs using the Chipyard infrastructure. +This will take about 20-30 minutes. You can expedite the process by setting a ``make`` environment variable to use parallel cores: ``export MAKEFLAGS=-j8``. +To build the toolchains, you should run: + +.. code-block:: shell + + ./scripts/build-toolchains.sh + +.. Note:: If you are planning to use the Hwacha vector unit, or other RoCC-based accelerators, you should build the esp-tools toolchains by adding the ``esp-tools`` argument to the script above. + If you are running on an Amazon Web Services EC2 instance, intending to use FireSim, you can also use the ``--ec2fast`` flag for an expedited installation of a pre-compiled toolchain. + + +What's Next? +------------------------------------------- + +This depends on what you are planning to do with Chipyard. + +* If you want to learn about the structure of Chipyard, go to :ref:`chipyard-components`. + +* If you intend to build one of the vanilla Chipyard examples, go to :ref:`build-a-chip` and follow the instructions. + +* If you intend to add a new accelerator, go to :ref:`adding-an-accelerator` and follow the instructions. + +* If you intend to run a simulation of one of the vanilla Chipyard examples, go to :ref:`sw-rtl-sim-intro` and follow the instructions. + +* If you intend to run a simulation of a custom Chipyard SoC Configuration, go to <> and follow the instructions. + +* If you intend to run a full-system FireSim simulation, go to :ref:`firesim-sim-intro` and follow the instructions. + +* If you intend to run a VLSI flow using one of the vanilla Chipyard examples, go to <> and follow the instructions. diff --git a/docs/Simulation/Commercial-Simulators.rst b/docs/Simulation/Commercial-Simulators.rst deleted file mode 100644 index 8c1c34d7..00000000 --- a/docs/Simulation/Commercial-Simulators.rst +++ /dev/null @@ -1,39 +0,0 @@ -Commercial Software RTL Simulators -============================== - -VCS ------------------------ - -`VCS `__ is a commercial RTL simulator developed by Synopsys. -It requires commercial licenses. -The REBAR framework can compile and execute simulations using VCS. -VCS simulation will generally compile faster than Verilator simulations. - -To run a simulation using VCS, perform the following steps: - -Make sure that the VCS simulator is on your ``PATH``. - -To compile the example design, run make in the ``sims/vsim`` directory. -This will elaborate the ``DefaultRocketConfig`` in the example project. - -An executable called ``simulator-example-DefaultRocketConfig`` will be produced. -This executable is a simulator that has been compiled based on the design that was built. -You can then use this executable to run any compatible RV64 code. -For instance, to run one of the riscv-tools assembly tests. - -.. code-block:: shell - - ./simulator-example-DefaultRocketConfig $RISCV/riscv64-unknown-elf/share/riscv-tests/isa/rv64ui-p-simple - -If you later create your own project, you can use environment variables to build an alternate configuration. - -.. code-block:: shell - - make SUB_PROJECT=yourproject - ./simulator-- ... - -If you would like to extract waveforms from the simulation, run the command ``make debug`` instead of just ``make``. -This will generate a vpd file (this is a proprietary waveform representation format used by Synopsys) that can be loaded to vpd-supported waveform viewers. -If you have Synopsys licenses, we recommend using the DVE waveform viewer. - -Please refer to :ref:`Running A Simulation` for a step by step tutorial on how to get a simulator up and running. diff --git a/docs/Simulation/FPGA-Accelerated-Simulators.rst b/docs/Simulation/FPGA-Accelerated-Simulators.rst new file mode 100644 index 00000000..29f42880 --- /dev/null +++ b/docs/Simulation/FPGA-Accelerated-Simulators.rst @@ -0,0 +1,90 @@ +.. _firesim-sim-intro: + +FPGA-Accelerated Simulators +============================== + +FireSim +----------------------- + +`FireSim `__ is an open-source cycle-accurate FPGA-accelerated full-system hardware simulation platform that runs on cloud FPGAs (Amazon EC2 F1). +FireSim allows RTL-level simulation at orders-of-magnitude faster speeds than software RTL simulators. +FireSim also provides additional device models to allow full-system simulation, including memory models and network models. + +FireSim currently supports running only on Amazon EC2 F1 FPGA-enabled virtual instances. +In order to simulate your Chipyard design using FireSim, if you have not +already, follow the initial EC2 setup instructions as detailed in the `FireSim +documentation `__. +Then clone Chipyard onto your FireSim manager +instance, and setup your Chipyard repository as you would normally. + +Next, initalize FireSim as library in Chipyard by running: + +.. code-block:: shell + + # At the root of your chipyard repo + ./scripts/firesim-setup.sh --fast + +``firesim-setup.sh`` initializes additional submodules and then invokes +firesim's ``build-setup.sh`` script adding ``--library`` to properly +initialize FireSim as a library submodule in chipyard. You may run +``./sims/firesim/build-setup.sh --help`` to see more options. + +Finally, source the following environment at the root of the firesim directory: + +.. code-block:: shell + + cd sims/firesim + # (Recommended) The default manager environment (includes env.sh) + source sourceme-f1-manager.sh + +`Every time you want to use FireSim with a fresh shell, you must source this sourceme.sh` + +At this point you're ready to use FireSim with Chipyard. If you're not already +familiar with FireSim, please return to the `FireSim Docs +`__, +and proceed with the rest of the tutorial. + +Current Limitations: +++++++++++++++++++++ + +FireSim integration in Chipyard is still a work in progress. Presently, you +cannot build a FireSim simulator from any generator project in Chipyard except ``firechip``, +which properly invokes MIDAS on the target RTL. + +In the interim, workaround this limitation by importing Config and Module +classes from other generator projects into FireChip. For example, assuming you Chipyard +config looks as following: + +.. code-block:: scala + + class CustomConfig extends Config( + new WithInclusiveCache ++ + new myproject.MyCustomConfig ++ + new DefaultRocketConfig + ) + +Then the equivalent FireChip config (in `generators/firechip/src/main/scala/TargetConfigs.scala`) based on `FireSimRocketChipConfig` +will look as follows: + +.. code-block:: scala + + class FireSimCustomConfig extends Config( + new WithBootROM ++ + new WithPeripheryBusFrequency(BigInt(3200000000L)) ++ + new WithExtMemSize(0x400000000L) ++ // 16GB + new WithoutTLMonitors ++ + new WithUARTKey ++ + new WithNICKey ++ + new WithBlockDevice ++ + new WithRocketL2TLBs(1024) ++ + new WithPerfCounters ++ + new WithoutClockGating ++ + new WithInclusiveCache ++ + new myproject.MyCustomConfig ++ + new freechips.rocketchip.system.DefaultConfig) + + +You should then be able to refer to those classes or an alias of them in your ``DESIGN`` or ``TARGET_CONFIG`` +variables. Note that if your target machine has I/O not provided in the default +FireChip targets (see ``generators/firechip/src/main/scala/Targets.scala``) you may need +to write a custom endpoint. diff --git a/docs/Simulation/FPGA-Based-Simulators.rst b/docs/Simulation/FPGA-Based-Simulators.rst deleted file mode 100644 index 9ef19d49..00000000 --- a/docs/Simulation/FPGA-Based-Simulators.rst +++ /dev/null @@ -1,17 +0,0 @@ -FPGA-Based Simulators -============================== - -FireSim ------------------------ - -`FireSim `__ is an open-source cycle-accurate FPGA-accelerated full-system hardware simulation platform that runs on cloud FPGAs (Amazon EC2 F1). -FireSim allows RTL-level simulation at orders-of-magnitude faster speeds than software RTL simulators. -FireSim also provides additional device models to allow full-system simulation, including memory models and network models. - -FireSim currently supports running only on Amazon EC2 F1 FPGA-enabled virtual instances on the public cloud. -In order to simulate your REBAR design using FireSim, you should follow the following steps: - -Follow the initial EC2 setup instructions as detailed in the `FireSim documentation `__. -Then clone your full REBAR repository onto your Amazon EC2 FireSim manager instance. - -Enter the ``sims/FireSim`` directory, and follow the FireSim instructions for `running a simulation `__. diff --git a/docs/Simulation/Open-Source-Simulators.rst b/docs/Simulation/Open-Source-Simulators.rst deleted file mode 100644 index 11d8d696..00000000 --- a/docs/Simulation/Open-Source-Simulators.rst +++ /dev/null @@ -1,35 +0,0 @@ -Open Source Software RTL Simulators -============================== - -Verilator ------------------------ - -`Verilator `__ is an open-source LGPL-Licensed simulator maintained by `Veripool `__. -The REBAR framework can download, build, and execute simulations using Verilator. - -To run a simulation using Verilator, perform the following steps: - -To compile the example design, run ``make`` in the ``sims/verisim`` directory. -This will elaborate the ``DefaultRocketConfig`` in the example project. - -An executable called ``simulator-example-DefaultRocketConfig`` will be produced. -This executable is a simulator that has been compiled based on the design that was built. -You can then use this executable to run any compatible RV64 code. -For instance, to run one of the riscv-tools assembly tests. - -.. code-block:: shell - - ./simulator-example-DefaultRocketConfig $RISCV/riscv64-unknown-elf/share/riscv-tests/isa/rv64ui-p-simple - -If you later create your own project, you can use environment variables to build an alternate configuration. - -.. code-block:: shell - - make SUB_PROJECT=yourproject - ./simulator-- ... - -If you would like to extract waveforms from the simulation, run the command ``make debug`` instead of just ``make``. -This will generate a vcd file (vcd is a standard waveform representation file format) that can be loaded to any common waveform viewer. -An open-source vcd-capable waveform viewer is `GTKWave `__. - -Please refer to :ref:`Running A Simulation` for a step by step tutorial on how to get a simulator up and running. diff --git a/docs/Simulation/Software-RTL-Simulators.rst b/docs/Simulation/Software-RTL-Simulators.rst new file mode 100644 index 00000000..89bd337c --- /dev/null +++ b/docs/Simulation/Software-RTL-Simulators.rst @@ -0,0 +1,75 @@ +.. _sw-rtl-sim-intro: + +Software RTL Simulators +=================================== + +Verilator (Open-Source) +----------------------- + +`Verilator `__ is an open-source LGPL-Licensed simulator maintained by `Veripool `__. +The Chipyard framework can download, build, and execute simulations using Verilator. + +To run a simulation using Verilator, perform the following steps: + +To compile the example design, run ``make`` in the ``sims/verilator`` directory. +This will elaborate the ``DefaultRocketConfig`` in the example project. + +An executable called ``simulator-example-DefaultRocketConfig`` will be produced. +This executable is a simulator that has been compiled based on the design that was built. +You can then use this executable to run any compatible RV64 code. +For instance, to run one of the riscv-tools assembly tests. + +.. code-block:: shell + + ./simulator-example-DefaultRocketConfig $RISCV/riscv64-unknown-elf/share/riscv-tests/isa/rv64ui-p-simple + +If you later create your own project, you can use environment variables to build an alternate configuration. + +.. code-block:: shell + + make SUB_PROJECT=yourproject + ./simulator-- ... + +If you would like to extract waveforms from the simulation, run the command ``make debug`` instead of just ``make``. +This will generate a vcd file (vcd is a standard waveform representation file format) that can be loaded to any common waveform viewer. +An open-source vcd-capable waveform viewer is `GTKWave `__. + +Please refer to :ref:`Running A Simulation` for a step by step tutorial on how to get a simulator up and running. +Commercial Software RTL Simulators + +Synopsys VCS (License Required) +-------------------------------- + +`VCS `__ is a commercial RTL simulator developed by Synopsys. +It requires commercial licenses. +The Chipyard framework can compile and execute simulations using VCS. +VCS simulation will generally compile faster than Verilator simulations. + +To run a simulation using VCS, perform the following steps: + +Make sure that the VCS simulator is on your ``PATH``. + +To compile the example design, run make in the ``sims/vcs`` directory. +This will elaborate the ``DefaultRocketConfig`` in the example project. + +An executable called ``simulator-example-DefaultRocketConfig`` will be produced. +This executable is a simulator that has been compiled based on the design that was built. +You can then use this executable to run any compatible RV64 code. +For instance, to run one of the riscv-tools assembly tests. + +.. code-block:: shell + + ./simulator-example-DefaultRocketConfig $RISCV/riscv64-unknown-elf/share/riscv-tests/isa/rv64ui-p-simple + +If you later create your own project, you can use environment variables to build an alternate configuration. + +.. code-block:: shell + + make SUB_PROJECT=yourproject + ./simulator-- ... + +If you would like to extract waveforms from the simulation, run the command ``make debug`` instead of just ``make``. +This will generate a vpd file (this is a proprietary waveform representation format used by Synopsys) that can be loaded to vpd-supported waveform viewers. +If you have Synopsys licenses, we recommend using the DVE waveform viewer. + +Please refer to :ref:`Running A Simulation` for a step by step tutorial on how to get a simulator up and running. diff --git a/docs/Simulation/index.rst b/docs/Simulation/index.rst index d61b5ed7..50dbb57e 100644 --- a/docs/Simulation/index.rst +++ b/docs/Simulation/index.rst @@ -1,15 +1,20 @@ Simulators ======================= -REBAR provides support and integration for multiple simulation flows, for various user levels and requirements. -In the majority of cases during a digital design development process, a simple software RTL simulation will do. -When more advanced full-system evaluation is required, with long running workloads, FPGA-accelerated simulation will then become a preferable solution. -The following pages provide detailed information about the simulation possibilities within the REBAR framework. +Chipyard supports two classes of simulation: + +#. Software RTL simulation using commercial or open-source (Verilator) RTL simulators +#. FPGA-accelerated full-system simulation using FireSim + +Software RTL simulators of Chipyard designs run at O(1 KHz), but compile +quickly and provide full waveforms. Conversly, FPGA-accelerated simulators run +at O(100 MHz), making them appropriate for booting an operating system and +running a complete workload, but have multi-hour compile times and poorer debug +visability. .. toctree:: :maxdepth: 2 :caption: Simulators: - Open-Source-Simulators - Commercial-Simulators - FPGA-Based-Simulators + Software-RTL-Simulators + FPGA-Accelerated-Simulators diff --git a/docs/Tools/index.rst b/docs/Tools/index.rst index 37e0d76e..d73d4072 100644 --- a/docs/Tools/index.rst +++ b/docs/Tools/index.rst @@ -1,7 +1,7 @@ Tools ============================== -The REBAR framework relays heavily on a set of Scala-based tools. +The Chipyard framework relays heavily on a set of Scala-based tools. The following pages will introduce them, and how we can use them in order to generate flexible designs. .. toctree:: diff --git a/docs/VLSI/HAMMER.rst b/docs/VLSI/HAMMER.rst index a206fe93..c0c77824 100644 --- a/docs/VLSI/HAMMER.rst +++ b/docs/VLSI/HAMMER.rst @@ -1,7 +1,58 @@ -HAMMER +Core HAMMER ================================ `HAMMER `__ is a physical design generator that wraps around vendor specific technologies and tools to provide a single API to create ASICs. HAMMER allows for reusability in ASIC design while still providing the designers leeway to make their own modifications. For more information, read the `HAMMER paper `__ and see the `GitHub repository `__. + +Actions +------- + +Actions are the top-level tasks Hammer is capable of executing (e.g. synthesis, place-and-route, etc.) + +Steps +------- + +Steps are the sub-components of actions that individually addressable in Hammer (e.g. placement in the place-and-route action). + +Hooks +------- + +Hooks are modifications to steps or actions that are programmatically defined in a Hammer configuration. + +Tool Plugins +============ + +Hammer supports separately managed plugins for different CAD tool vendors. +The types of tools (in there hammer names) supported currently include: + +* synthesis +* par +* drc +* lvs +* sram_generator +* pcb + +In order to configure your tool plugin of choice, you will need to set several configuration variables. +First, you should select which specific tool you want to use by setting ``vlsi.core._tool`` to the name of your tool. +For example ``vlsi.core.par_tool: "innovus"``. +You will also need to point hammer to the folder that contains your tool plugin by setting ``vlsi.core._tool_path``. +This directory should include a folder with the name of the tool as specified previously, which itself includes a python file ``__init__.py`` and a yaml file ``defaults.yml`` specifying the default values for any tool specific variables. +In addition you can also customize the version of the tools you use by setting ``..version`` to a tool specific string. +Looking at the tools ``defaults.yml`` will inform you if there are other variables you would like to set for your use of this tool. + +The ``__init__.py`` file should contain a variable, ``tool``, that points to the class implementing this tools Hammer support. +This class should be a subclass of ``HammerTool``, which will be a subclass of ``HammerTool``. + +Technology Plugins +================== + +Hammer supports separately managed plugins for different technologies. + +Configuration +============= + +To configure a hammer flow the user needs to supply a yaml or json configuration file the chooses the tool and technology plugins and versions as well as any design specific configuration APIs. + +You can see the current set of all available Hammer APIs `here `__. diff --git a/docs/VLSI/index.rst b/docs/VLSI/index.rst index 448fadd7..f8bdb7a8 100644 --- a/docs/VLSI/index.rst +++ b/docs/VLSI/index.rst @@ -1,11 +1,11 @@ -VLSI Production +VLSI Flow ================================ -The REBAR framework aim to provide wrappers to a general VLSI flow. -In particular, we aim to support the HAMMER flow. +The Chipyard framework aims to provide wrappers for a general VLSI flow. +In particular, we aim to support the HAMMER physical design generator flow. .. toctree:: :maxdepth: 2 - :caption: VLSI Production: + :caption: VLSI Flow: HAMMER diff --git a/docs/conf.py b/docs/conf.py index 9b7bbe43..200e0c1e 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -1,6 +1,6 @@ # -*- coding: utf-8 -*- # -# REBAR documentation build configuration file, created by +# Chipyard documentation build configuration file, created by # sphinx-quickstart on Fri Mar 8 11:46:38 2019. # # This file is execfile()d with the current directory set to its @@ -52,7 +52,7 @@ source_suffix = '.rst' master_doc = 'index' # General information about the project. -project = u'REBAR' +project = u'Chipyard' copyright = u'2019, Berkeley Architecture Research' author = u'Berkeley Architecture Research' @@ -125,7 +125,7 @@ html_sidebars = { # -- Options for HTMLHelp output ------------------------------------------ # Output file base name for HTML help builder. -htmlhelp_basename = 'REBARdoc' +htmlhelp_basename = 'Chipyarddoc' # -- Options for LaTeX output --------------------------------------------- @@ -152,7 +152,7 @@ latex_elements = { # (source start file, target name, title, # author, documentclass [howto, manual, or own class]). latex_documents = [ - (master_doc, 'REBAR.tex', u'REBAR Documentation', + (master_doc, 'Chipyard.tex', u'Chipyard Documentation', u'Berkeley Architecture Research', 'manual'), ] @@ -162,7 +162,7 @@ latex_documents = [ # One entry per manual page. List of tuples # (source start file, name, description, authors, manual section). man_pages = [ - (master_doc, 'rebar', u'REBAR Documentation', + (master_doc, 'chipyard', u'Chipyard Documentation', [author], 1) ] @@ -173,8 +173,8 @@ man_pages = [ # (source start file, target name, title, author, # dir menu entry, description, category) texinfo_documents = [ - (master_doc, 'REBAR', u'REBAR Documentation', - author, 'REBAR', 'One line description of project.', + (master_doc, 'Chipyard', u'Chipyard Documentation', + author, 'Chipyard', 'One line description of project.', 'Miscellaneous'), ] diff --git a/docs/index.rst b/docs/index.rst index 68598e7a..1f41b4ed 100644 --- a/docs/index.rst +++ b/docs/index.rst @@ -1,21 +1,23 @@ -.. REBAR documentation master file, created by +.. Chipyard documentation master file, created by sphinx-quickstart on Fri Mar 8 11:46:38 2019. You can adapt this file completely to your liking, but it should at least contain the root `toctree` directive. -Welcome to REBAR's documentation! -================================= +Welcome to Chipyard's documentation! +==================================== -REBAR is a a framework for designing and evaluating full-system hardware using agile teams. +Chipyard is a a framework for designing and evaluating full-system hardware using agile teams. It is composed of a collection of tools and libraries designed to provide an intergration between open-source and commercial tools for the development of systems-on-chip. -New to REBAR? Jump to the :ref:`Getting Started` page for more info. +New to Chipyard? Jump to the :ref:`Chipyard Basics` page for more info. + +.. include:: Quick-Start.rst .. toctree:: :maxdepth: 3 :caption: Contents: :numbered: - Getting-Started/index + Chipyard-Basics/index :maxdepth: 3 :caption: Simulation: @@ -37,6 +39,17 @@ New to REBAR? Jump to the :ref:`Getting Started` page for more info. :numbered: VLSI/index + :maxdepth: 3 + :caption: Customization: + :numbered: + Customization/index + + :maxdepth: 3 + :caption: Advanced Usage: + :numbered: + Advanced-Usage/index + + Indices and tables ================== diff --git a/generators/boom b/generators/boom index 2f8c419f..4e9d496d 160000 --- a/generators/boom +++ b/generators/boom @@ -1 +1 @@ -Subproject commit 2f8c419ff8fa7d848d0d92d4977885cb1e1fa5b3 +Subproject commit 4e9d496d3678cc5ae005669a448ae9e89f8ae847 diff --git a/generators/example/src/main/scala/BoomConfigs.scala b/generators/example/src/main/scala/BoomConfigs.scala new file mode 100644 index 00000000..f328b902 --- /dev/null +++ b/generators/example/src/main/scala/BoomConfigs.scala @@ -0,0 +1,90 @@ +package example + +import chisel3._ + +import freechips.rocketchip.config.{Config} +import freechips.rocketchip.subsystem.{WithJtagDTM} + +import boom.common._ + +// --------------------- +// BOOM Configs +// --------------------- + +class SmallBoomConfig extends Config( + new WithNormalBoomRocketTop ++ + new WithBootROM ++ + new boom.common.SmallBoomConfig) + +class MediumBoomConfig extends Config( + new WithNormalBoomRocketTop ++ + new WithBootROM ++ + new boom.common.MediumBoomConfig) + +class LargeBoomConfig extends Config( + new WithNormalBoomRocketTop ++ + new WithBootROM ++ + new boom.common.LargeBoomConfig) + +class MegaBoomConfig extends Config( + new WithNormalBoomRocketTop ++ + new WithBootROM ++ + new boom.common.MegaBoomConfig) + +class jtagSmallBoomConfig extends Config( + new WithDTMBoomRocketTop ++ + new WithBootROM ++ + new WithJtagDTM ++ + new boom.common.SmallBoomConfig) + +class jtagMediumBoomConfig extends Config( + new WithDTMBoomRocketTop ++ + new WithBootROM ++ + new WithJtagDTM ++ + new boom.common.MediumBoomConfig) + +class jtagLargeBoomConfig extends Config( + new WithDTMBoomRocketTop ++ + new WithBootROM ++ + new WithJtagDTM ++ + new boom.common.LargeBoomConfig) + +class jtagMegaBoomConfig extends Config( + new WithDTMBoomRocketTop ++ + new WithBootROM ++ + new WithJtagDTM ++ + new boom.common.MegaBoomConfig) + +class SmallDualBoomConfig extends Config( + new WithNormalBoomRocketTop ++ + new WithBootROM ++ + new boom.common.SmallDualBoomConfig) + +class TracedSmallBoomConfig extends Config( + new WithNormalBoomRocketTop ++ + new WithBootROM ++ + new boom.common.TracedSmallBoomConfig) + +class SmallRV32UnifiedBoomConfig extends Config( + new WithNormalBoomRocketTop ++ + new WithBootROM ++ + new boom.common.SmallRV32UnifiedBoomConfig) + +// -------------------------- +// BOOM + Rocket Configs +// -------------------------- + +class SmallBoomAndRocketConfig extends Config( + new WithNormalBoomRocketTop ++ + new WithBootROM ++ + new boom.common.SmallBoomAndRocketConfig) + +class MediumBoomAndRocketConfig extends Config( + new WithNormalBoomRocketTop ++ + new WithBootROM ++ + new boom.common.MediumBoomAndRocketConfig) + +class DualMediumBoomAndDualRocketConfig extends Config( + new WithNormalBoomRocketTop ++ + new WithBootROM ++ + new boom.common.DualMediumBoomAndDualRocketConfig) diff --git a/generators/example/src/main/scala/ConfigMixins.scala b/generators/example/src/main/scala/ConfigMixins.scala index 895fa86a..17fac94d 100644 --- a/generators/example/src/main/scala/ConfigMixins.scala +++ b/generators/example/src/main/scala/ConfigMixins.scala @@ -58,6 +58,15 @@ class WithNormalBoomRocketTop extends Config((site, here, up) => { } }) +/** + * Class to specify a top level BOOM and/or Rocket system with DTM + */ +class WithDTMBoomRocketTop extends Config((site, here, up) => { + case BuildBoomRocketTopWithDTM => (clock: Clock, reset: Bool, p: Parameters) => { + Module(LazyModule(new BoomRocketTopWithDTM()(p)).module) + } +}) + /** * Class to specify a top level BOOM and/or Rocket system with PWM */ diff --git a/generators/example/src/main/scala/Configs.scala b/generators/example/src/main/scala/Configs.scala index d6ff3432..c7e70dd2 100644 --- a/generators/example/src/main/scala/Configs.scala +++ b/generators/example/src/main/scala/Configs.scala @@ -3,7 +3,7 @@ package example import chisel3._ import freechips.rocketchip.config.{Config} -import freechips.rocketchip.subsystem.{WithRoccExample, WithNMemoryChannels, WithNBigCores, WithRV32, WithExtMemSize, WithNBanks} +import freechips.rocketchip.subsystem.{WithRoccExample, WithNMemoryChannels, WithNBigCores, WithRV32, WithExtMemSize, WithNBanks, WithInclusiveCache} import testchipip._ @@ -62,17 +62,26 @@ class GB1MemoryConfig extends Config( new WithExtMemSize((1<<30) * 1L) ++ new DefaultRocketConfig) +class RocketL2Config extends Config( + new WithInclusiveCache ++ + new DefaultRocketConfig) + +class HwachaL2Config extends Config( + new hwacha.DefaultHwachaConfig ++ + new WithInclusiveCache ++ + new DefaultRocketConfig) + // ------------ // BOOM Configs // ------------ class BaseBoomConfig extends Config( new WithBootROM ++ - new boom.system.BoomConfig) + new boom.common.LargeBoomConfig) class SmallBaseBoomConfig extends Config( new WithBootROM ++ - new boom.system.SmallBoomConfig) + new boom.common.SmallBoomConfig) class DefaultBoomConfig extends Config( new WithNormalBoomRocketTop ++ @@ -121,8 +130,9 @@ class DualCoreBoomConfig extends Config( new WithNormalBoomRocketTop ++ new WithBootROM ++ new boom.common.WithRVC ++ - new boom.common.DefaultBoomConfig ++ - new boom.system.WithNBoomCores(2) ++ + new boom.common.WithLargeBooms ++ + new boom.common.BaseBoomConfig ++ + new boom.common.WithNBoomCores(2) ++ new freechips.rocketchip.subsystem.WithoutTLMonitors ++ new freechips.rocketchip.system.BaseConfig) @@ -131,15 +141,19 @@ class DualCoreSmallBoomConfig extends Config( new WithBootROM ++ new boom.common.WithRVC ++ new boom.common.WithSmallBooms ++ - new boom.common.DefaultBoomConfig ++ - new boom.system.WithNBoomCores(2) ++ + new boom.common.BaseBoomConfig ++ + new boom.common.WithNBoomCores(2) ++ new freechips.rocketchip.subsystem.WithoutTLMonitors ++ new freechips.rocketchip.system.BaseConfig) class RV32UnifiedBoomConfig extends Config( new WithNormalBoomRocketTop ++ new WithBootROM ++ - new boom.system.SmallRV32UnifiedBoomConfig) + new boom.common.SmallRV32UnifiedBoomConfig) + +class BoomL2Config extends Config( + new WithInclusiveCache ++ + new SmallDefaultBoomConfig) // --------------------- // BOOM and Rocket Configs @@ -147,21 +161,22 @@ class RV32UnifiedBoomConfig extends Config( class BaseBoomAndRocketConfig extends Config( new WithBootROM ++ - new boom.system.WithRenumberHarts ++ + new boom.common.WithRenumberHarts ++ new boom.common.WithRVC ++ - new boom.common.DefaultBoomConfig ++ - new boom.system.WithNBoomCores(1) ++ + new boom.common.WithLargeBooms ++ + new boom.common.BaseBoomConfig ++ + new boom.common.WithNBoomCores(1) ++ new freechips.rocketchip.subsystem.WithoutTLMonitors ++ new freechips.rocketchip.subsystem.WithNBigCores(1) ++ new freechips.rocketchip.system.BaseConfig) class SmallBaseBoomAndRocketConfig extends Config( new WithBootROM ++ - new boom.system.WithRenumberHarts ++ + new boom.common.WithRenumberHarts ++ new boom.common.WithRVC ++ new boom.common.WithSmallBooms ++ - new boom.common.DefaultBoomConfig ++ - new boom.system.WithNBoomCores(1) ++ + new boom.common.BaseBoomConfig ++ + new boom.common.WithNBoomCores(1) ++ new freechips.rocketchip.subsystem.WithoutTLMonitors ++ new freechips.rocketchip.subsystem.WithNBigCores(1) ++ new freechips.rocketchip.system.BaseConfig) @@ -208,24 +223,26 @@ class GPIOBoomAndRocketConfig extends Config( class DualCoreBoomAndOneRocketConfig extends Config( new WithNormalBoomRocketTop ++ new WithBootROM ++ - new boom.system.WithRenumberHarts ++ + new boom.common.WithRenumberHarts ++ new boom.common.WithRVC ++ - new boom.common.DefaultBoomConfig ++ - new boom.system.WithNBoomCores(2) ++ + new boom.common.WithLargeBooms ++ + new boom.common.BaseBoomConfig ++ + new boom.common.WithNBoomCores(2) ++ new freechips.rocketchip.subsystem.WithoutTLMonitors ++ new freechips.rocketchip.subsystem.WithNBigCores(1) ++ new freechips.rocketchip.system.BaseConfig) -class DualCoreBoomAndOneHwachaRocketConfig extends Config( +class DualBoomAndOneHwachaRocketConfig extends Config( new WithNormalBoomRocketTop ++ new WithBootROM ++ new WithMultiRoCC ++ new WithMultiRoCCHwacha(0) ++ // put Hwacha just on hart0 which was renumbered to Rocket - new boom.system.WithRenumberHarts ++ + new boom.common.WithRenumberHarts(rocketFirst = true) ++ new hwacha.DefaultHwachaConfig ++ new boom.common.WithRVC ++ - new boom.common.DefaultBoomConfig ++ - new boom.system.WithNBoomCores(2) ++ + new boom.common.WithLargeBooms ++ + new boom.common.BaseBoomConfig ++ + new boom.common.WithNBoomCores(2) ++ new freechips.rocketchip.subsystem.WithoutTLMonitors ++ new freechips.rocketchip.subsystem.WithNBigCores(1) ++ new freechips.rocketchip.system.BaseConfig) @@ -233,12 +250,17 @@ class DualCoreBoomAndOneHwachaRocketConfig extends Config( class RV32BoomAndRocketConfig extends Config( new WithNormalBoomRocketTop ++ new WithBootROM ++ - new boom.system.WithRenumberHarts ++ + new boom.common.WithRenumberHarts ++ new boom.common.WithBoomRV32 ++ new boom.common.WithRVC ++ - new boom.common.DefaultBoomConfig ++ - new boom.system.WithNBoomCores(1) ++ + new boom.common.WithLargeBooms ++ + new boom.common.BaseBoomConfig ++ + new boom.common.WithNBoomCores(1) ++ new freechips.rocketchip.subsystem.WithoutTLMonitors ++ - new WithRV32 ++ + new freechips.rocketchip.subsystem.WithRV32 ++ new freechips.rocketchip.subsystem.WithNBigCores(1) ++ new freechips.rocketchip.system.BaseConfig) + +class DualCoreRocketL2Config extends Config( + new WithInclusiveCache ++ + new DualCoreRocketConfig) diff --git a/generators/example/src/main/scala/Generator.scala b/generators/example/src/main/scala/Generator.scala index c5df8cb1..34f16e4e 100644 --- a/generators/example/src/main/scala/Generator.scala +++ b/generators/example/src/main/scala/Generator.scala @@ -1,140 +1,22 @@ package example -import scala.collection.mutable.LinkedHashSet - import chisel3._ -import chisel3.experimental._ -import firrtl.transforms.{BlackBoxResourceAnno, BlackBoxSourceHelper} - -import freechips.rocketchip.subsystem.{RocketTilesKey} -import freechips.rocketchip.diplomacy.{LazyModule} -import freechips.rocketchip.config.{Field, Parameters} +import freechips.rocketchip.config.{Parameters} import freechips.rocketchip.util.{GeneratorApp} -import freechips.rocketchip.tile.{XLen} -import freechips.rocketchip.system.{TestGeneration, RegressionTestSuite} - -import boom.system.{BoomTilesKey, BoomTestSuites} object Generator extends GeneratorApp { - val rv64RegrTestNames = LinkedHashSet( - "rv64ud-v-fcvt", - "rv64ud-p-fdiv", - "rv64ud-v-fadd", - "rv64uf-v-fadd", - "rv64um-v-mul", - "rv64mi-p-breakpoint", - "rv64uc-v-rvc", - "rv64ud-v-structural", - "rv64si-p-wfi", - "rv64um-v-divw", - "rv64ua-v-lrsc", - "rv64ui-v-fence_i", - "rv64ud-v-fcvt_w", - "rv64uf-v-fmin", - "rv64ui-v-sb", - "rv64ua-v-amomax_d", - "rv64ud-v-move", - "rv64ud-v-fclass", - "rv64ua-v-amoand_d", - "rv64ua-v-amoxor_d", - "rv64si-p-sbreak", - "rv64ud-v-fmadd", - "rv64uf-v-ldst", - "rv64um-v-mulh", - "rv64si-p-dirty") - - val rv32RegrTestNames = LinkedHashSet( - "rv32mi-p-ma_addr", - "rv32mi-p-csr", - "rv32ui-p-sh", - "rv32ui-p-lh", - "rv32uc-p-rvc", - "rv32mi-p-sbreak", - "rv32ui-p-sll") - + // add unique test suites override def addTestSuites { - import freechips.rocketchip.system.DefaultTestSuites._ - val xlen = params(XLen) - - // TODO: for now only generate tests for the first rocket/boom tile in the subsystem - // TODO: support heterogenous systems? - - // rocket specific tests - params(RocketTilesKey).headOption.map { tileParams => - val coreParams = tileParams.core - val vm = coreParams.useVM - val env = if (vm) List("p","v") else List("p") - coreParams.fpu foreach { case cfg => - if (xlen == 32) { - TestGeneration.addSuites(env.map(rv32uf)) - if (cfg.fLen >= 64) - TestGeneration.addSuites(env.map(rv32ud)) - } else { - TestGeneration.addSuite(rv32udBenchmarks) - TestGeneration.addSuites(env.map(rv64uf)) - if (cfg.fLen >= 64) - TestGeneration.addSuites(env.map(rv64ud)) - } - } - if (coreParams.useAtomics) { - if (tileParams.dcache.flatMap(_.scratch).isEmpty) - TestGeneration.addSuites(env.map(if (xlen == 64) rv64ua else rv32ua)) - else - TestGeneration.addSuites(env.map(if (xlen == 64) rv64uaSansLRSC else rv32uaSansLRSC)) - } - if (coreParams.useCompressed) TestGeneration.addSuites(env.map(if (xlen == 64) rv64uc else rv32uc)) - val (rvi, rvu) = - if (xlen == 64) ((if (vm) rv64i else rv64pi), rv64u) - else ((if (vm) rv32i else rv32pi), rv32u) - - TestGeneration.addSuites(rvi.map(_("p"))) - TestGeneration.addSuites((if (vm) List("v") else List()).flatMap(env => rvu.map(_(env)))) - TestGeneration.addSuite(benchmarks) - TestGeneration.addSuite(new RegressionTestSuite(if (xlen == 64) rv64RegrTestNames else rv32RegrTestNames)) - } - - // boom specific tests - params(BoomTilesKey).headOption.map { tileParams => - val coreParams = tileParams.core - val vm = coreParams.useVM - val env = if (vm) List("p","v") else List("p") - coreParams.fpu foreach { case cfg => - if (xlen == 32) { - TestGeneration.addSuites(env.map(rv32uf)) - if (cfg.fLen >= 64) { - TestGeneration.addSuites(env.map(rv32ud)) - } - } else if (cfg.fLen >= 64) { - TestGeneration.addSuites(env.map(rv64ud)) - TestGeneration.addSuites(env.map(rv64uf)) - TestGeneration.addSuite(rv32udBenchmarks) - } - } - if (coreParams.useAtomics) { - if (tileParams.dcache.flatMap(_.scratch).isEmpty) { - TestGeneration.addSuites(env.map(if (xlen == 64) rv64ua else rv32ua)) - } else { - TestGeneration.addSuites(env.map(if (xlen == 64) rv64uaSansLRSC else rv32uaSansLRSC)) - } - } - if (coreParams.useCompressed) TestGeneration.addSuites(env.map(if (xlen == 64) rv64uc else rv32uc)) - - // Include our BOOM-specific overrides. - val (rvi, rvu) = - if (xlen == 64) ((if (vm) BoomTestSuites.rv64i else BoomTestSuites.rv64pi), rv64u) - else ((if (vm) rv32i else rv32pi), rv32u) - - TestGeneration.addSuites(rvi.map(_("p"))) - TestGeneration.addSuites(rvu.map(_("p"))) - TestGeneration.addSuites((if (vm) List("v") else List()).flatMap(env => rvu.map(_(env)))) - TestGeneration.addSuite(benchmarks) - rv64RegrTestNames -= "rv64mi-p-breakpoint" // TODO: breakpoints not implemented yet - TestGeneration.addSuite(new RegressionTestSuite(if (xlen == 64) rv64RegrTestNames else rv32RegrTestNames)) - } + implicit val p: Parameters = params + TestSuiteHelper.addRocketTestSuites + TestSuiteHelper.addBoomTestSuites } + // specify the name that the generator outputs files as val longName = names.topModuleProject + "." + names.topModuleClass + "." + names.configs + + // generate files generateFirrtl generateAnno generateTestSuiteMakefrags diff --git a/generators/example/src/main/scala/TestHarness.scala b/generators/example/src/main/scala/TestHarness.scala index c59a081e..778fcc81 100644 --- a/generators/example/src/main/scala/TestHarness.scala +++ b/generators/example/src/main/scala/TestHarness.scala @@ -8,14 +8,19 @@ import firrtl.transforms.{BlackBoxResourceAnno, BlackBoxSourceHelper} import freechips.rocketchip.diplomacy.LazyModule import freechips.rocketchip.config.{Field, Parameters} import freechips.rocketchip.util.GeneratorApp +import freechips.rocketchip.devices.debug.{Debug} -// -------------------------- +// ------------------------------- // BOOM and/or Rocket Test Harness -// -------------------------- +// ------------------------------- case object BuildBoomRocketTop extends Field[(Clock, Bool, Parameters) => BoomRocketTopModule[BoomRocketTop]] +case object BuildBoomRocketTopWithDTM extends Field[(Clock, Bool, Parameters) => BoomRocketTopWithDTMModule[BoomRocketTopWithDTM]] -class BoomRocketTestHarness(implicit val p: Parameters) extends Module { +/** + * Test harness using TSI to bringup the system + */ +class TestHarness(implicit val p: Parameters) extends Module { val io = IO(new Bundle { val success = Output(Bool()) }) @@ -24,6 +29,7 @@ class BoomRocketTestHarness(implicit val p: Parameters) extends Module { override def desiredName = "TestHarness" val dut = p(BuildBoomRocketTop)(clock, reset.toBool, p) + dut.debug := DontCare dut.connectSimAXIMem() dut.connectSimAXIMMIO() @@ -41,5 +47,41 @@ class BoomRocketTestHarness(implicit val p: Parameters) extends Module { axi.w.bits := DontCare } }) + io.success := dut.connectSimSerial() } + +/** + * Test harness using the Debug Test Module (DTM) to bringup the system + */ +class TestHarnessWithDTM(implicit p: Parameters) extends Module +{ + val io = IO(new Bundle { + val success = Output(Bool()) + }) + + // force Chisel to rename module + override def desiredName = "TestHarness" + + val dut = p(BuildBoomRocketTopWithDTM)(clock, reset.toBool, p) + + dut.reset := reset.asBool | dut.debug.ndreset + dut.connectSimAXIMem() + dut.connectSimAXIMMIO() + dut.dontTouchPorts() + dut.tieOffInterrupts() + dut.l2_frontend_bus_axi4.foreach(axi => { + axi.tieoff() + experimental.DataMirror.directionOf(axi.ar.ready) match { + case core.ActualDirection.Input => + axi.r.bits := DontCare + axi.b.bits := DontCare + case core.ActualDirection.Output => + axi.aw.bits := DontCare + axi.ar.bits := DontCare + axi.w.bits := DontCare + } + }) + + Debug.connectDebug(dut.debug, clock, reset.asBool, io.success) +} diff --git a/generators/example/src/main/scala/TestSuites.scala b/generators/example/src/main/scala/TestSuites.scala new file mode 100644 index 00000000..11425bdb --- /dev/null +++ b/generators/example/src/main/scala/TestSuites.scala @@ -0,0 +1,142 @@ +package example + +import scala.collection.mutable.{LinkedHashSet} + +import freechips.rocketchip.subsystem.{RocketTilesKey} +import freechips.rocketchip.tile.{XLen} +import freechips.rocketchip.config.{Parameters} +import freechips.rocketchip.util.{GeneratorApp} +import freechips.rocketchip.system.{TestGeneration, RegressionTestSuite} + +import boom.system.{BoomTilesKey} + +/** + * A set of pre-chosen regression tests + */ +object RegressionTestSuites +{ + val rv64RegrTestNames = LinkedHashSet( + "rv64ud-v-fcvt", + "rv64ud-p-fdiv", + "rv64ud-v-fadd", + "rv64uf-v-fadd", + "rv64um-v-mul", + "rv64mi-p-breakpoint", + "rv64uc-v-rvc", + "rv64ud-v-structural", + "rv64si-p-wfi", + "rv64um-v-divw", + "rv64ua-v-lrsc", + "rv64ui-v-fence_i", + "rv64ud-v-fcvt_w", + "rv64uf-v-fmin", + "rv64ui-v-sb", + "rv64ua-v-amomax_d", + "rv64ud-v-move", + "rv64ud-v-fclass", + "rv64ua-v-amoand_d", + "rv64ua-v-amoxor_d", + "rv64si-p-sbreak", + "rv64ud-v-fmadd", + "rv64uf-v-ldst", + "rv64um-v-mulh", + "rv64si-p-dirty") + + val rv32RegrTestNames = LinkedHashSet( + "rv32mi-p-ma_addr", + "rv32mi-p-csr", + "rv32ui-p-sh", + "rv32ui-p-lh", + "rv32uc-p-rvc", + "rv32mi-p-sbreak", + "rv32ui-p-sll") +} + +/** + * Helper functions to add BOOM or Rocket tests + */ +object TestSuiteHelper +{ + import freechips.rocketchip.system.DefaultTestSuites._ + import RegressionTestSuites._ + + /** + * Add BOOM tests (asm, bmark, regression) + */ + def addBoomTestSuites(implicit p: Parameters) = { + val xlen = p(XLen) + p(BoomTilesKey).find(_.hartId == 0).map { tileParams => + val coreParams = tileParams.core + val vm = coreParams.useVM + val env = if (vm) List("p","v") else List("p") + coreParams.fpu foreach { case cfg => + if (xlen == 32) { + TestGeneration.addSuites(env.map(rv32uf)) + if (cfg.fLen >= 64) { + TestGeneration.addSuites(env.map(rv32ud)) + } + } else if (cfg.fLen >= 64) { + TestGeneration.addSuites(env.map(rv64ud)) + TestGeneration.addSuites(env.map(rv64uf)) + TestGeneration.addSuite(rv32udBenchmarks) + } + } + if (coreParams.useAtomics) { + if (tileParams.dcache.flatMap(_.scratch).isEmpty) { + TestGeneration.addSuites(env.map(if (xlen == 64) rv64ua else rv32ua)) + } else { + TestGeneration.addSuites(env.map(if (xlen == 64) rv64uaSansLRSC else rv32uaSansLRSC)) + } + } + if (coreParams.useCompressed) TestGeneration.addSuites(env.map(if (xlen == 64) rv64uc else rv32uc)) + val (rvi, rvu) = + if (xlen == 64) ((if (vm) rv64i else rv64pi), rv64u) + else ((if (vm) rv32i else rv32pi), rv32u) + + TestGeneration.addSuites(rvi.map(_("p"))) + TestGeneration.addSuites(rvu.map(_("p"))) + TestGeneration.addSuites((if (vm) List("v") else List()).flatMap(env => rvu.map(_(env)))) + TestGeneration.addSuite(benchmarks) + TestGeneration.addSuite(new RegressionTestSuite(if (xlen == 64) rv64RegrTestNames else rv32RegrTestNames)) + } + } + + /** + * Add Rocket tests (asm, bmark, regression) + */ + def addRocketTestSuites(implicit p: Parameters) = { + val xlen = p(XLen) + p(RocketTilesKey).find(_.hartId == 0).map { tileParams => + val coreParams = tileParams.core + val vm = coreParams.useVM + val env = if (vm) List("p","v") else List("p") + coreParams.fpu foreach { case cfg => + if (xlen == 32) { + TestGeneration.addSuites(env.map(rv32uf)) + if (cfg.fLen >= 64) + TestGeneration.addSuites(env.map(rv32ud)) + } else { + TestGeneration.addSuite(rv32udBenchmarks) + TestGeneration.addSuites(env.map(rv64uf)) + if (cfg.fLen >= 64) + TestGeneration.addSuites(env.map(rv64ud)) + } + } + if (coreParams.useAtomics) { + if (tileParams.dcache.flatMap(_.scratch).isEmpty) + TestGeneration.addSuites(env.map(if (xlen == 64) rv64ua else rv32ua)) + else + TestGeneration.addSuites(env.map(if (xlen == 64) rv64uaSansLRSC else rv32uaSansLRSC)) + } + if (coreParams.useCompressed) TestGeneration.addSuites(env.map(if (xlen == 64) rv64uc else rv32uc)) + val (rvi, rvu) = + if (xlen == 64) ((if (vm) rv64i else rv64pi), rv64u) + else ((if (vm) rv32i else rv32pi), rv32u) + + TestGeneration.addSuites(rvi.map(_("p"))) + TestGeneration.addSuites((if (vm) List("v") else List()).flatMap(env => rvu.map(_(env)))) + TestGeneration.addSuite(benchmarks) + TestGeneration.addSuite(new RegressionTestSuite(if (xlen == 64) rv64RegrTestNames else rv32RegrTestNames)) + } + } +} diff --git a/generators/example/src/main/scala/Top.scala b/generators/example/src/main/scala/Top.scala index 5ee73906..b861fdec 100644 --- a/generators/example/src/main/scala/Top.scala +++ b/generators/example/src/main/scala/Top.scala @@ -12,17 +12,17 @@ import testchipip._ import sifive.blocks.devices.gpio._ -// ------------------------------- +// ------------------------------------ // BOOM and/or Rocket Top Level Systems -// ------------------------------- +// ------------------------------------ -class BoomRocketTop(implicit p: Parameters) extends boom.system.ExampleBoomAndRocketSystem +class BoomRocketTop(implicit p: Parameters) extends boom.system.BoomRocketSystem with HasNoDebug with HasPeripherySerial { override lazy val module = new BoomRocketTopModule(this) } -class BoomRocketTopModule[+L <: BoomRocketTop](l: L) extends boom.system.ExampleBoomAndRocketSystemModule(l) +class BoomRocketTopModule[+L <: BoomRocketTop](l: L) extends boom.system.BoomRocketSystemModule(l) with HasNoDebugModuleImp with HasPeripherySerialModuleImp with DontTouch @@ -67,3 +67,12 @@ class BoomRocketTopWithGPIO(implicit p: Parameters) extends BoomRocketTop class BoomRocketTopWithGPIOModule(l: BoomRocketTopWithGPIO) extends BoomRocketTopModule(l) with HasPeripheryGPIOModuleImp + +//--------------------------------------------------------------------------------------------------------- + +class BoomRocketTopWithDTM(implicit p: Parameters) extends boom.system.BoomRocketSystem +{ + override lazy val module = new BoomRocketTopWithDTMModule(this) +} + +class BoomRocketTopWithDTMModule[+L <: BoomRocketTopWithDTM](l: L) extends boom.system.BoomRocketSystemModule(l) diff --git a/generators/firechip/src/main/scala/Generator.scala b/generators/firechip/src/main/scala/Generator.scala new file mode 100644 index 00000000..06febd3a --- /dev/null +++ b/generators/firechip/src/main/scala/Generator.scala @@ -0,0 +1,133 @@ +//See LICENSE for license details. + +package firesim.firesim + +import java.io.{File} + +import chisel3.experimental.RawModule +import chisel3.internal.firrtl.{Circuit, Port} + +import freechips.rocketchip.diplomacy.{ValName, AutoBundle} +import freechips.rocketchip.devices.debug.DebugIO +import freechips.rocketchip.util.{HasGeneratorUtilities, ParsedInputNames, ElaborationArtefacts} +import freechips.rocketchip.system.DefaultTestSuites._ +import freechips.rocketchip.system.{TestGeneration, RegressionTestSuite} +import freechips.rocketchip.config.Parameters +import freechips.rocketchip.subsystem.RocketTilesKey +import freechips.rocketchip.tile.XLen + +import boom.system.{BoomTilesKey, BoomTestSuites} + +import firesim.util.{GeneratorArgs, HasTargetAgnosticUtilites, HasFireSimGeneratorUtilities} + +trait HasTestSuites { + val rv64RegrTestNames = collection.mutable.LinkedHashSet( + "rv64ud-v-fcvt", + "rv64ud-p-fdiv", + "rv64ud-v-fadd", + "rv64uf-v-fadd", + "rv64um-v-mul", + // "rv64mi-p-breakpoint", // Not implemented in BOOM + // "rv64uc-v-rvc", // Not implemented in BOOM + "rv64ud-v-structural", + "rv64si-p-wfi", + "rv64um-v-divw", + "rv64ua-v-lrsc", + "rv64ui-v-fence_i", + "rv64ud-v-fcvt_w", + "rv64uf-v-fmin", + "rv64ui-v-sb", + "rv64ua-v-amomax_d", + "rv64ud-v-move", + "rv64ud-v-fclass", + "rv64ua-v-amoand_d", + "rv64ua-v-amoxor_d", + "rv64si-p-sbreak", + "rv64ud-v-fmadd", + "rv64uf-v-ldst", + "rv64um-v-mulh", + "rv64si-p-dirty") + + val rv32RegrTestNames = collection.mutable.LinkedHashSet( + "rv32mi-p-ma_addr", + "rv32mi-p-csr", + "rv32ui-p-sh", + "rv32ui-p-lh", + "rv32uc-p-rvc", + "rv32mi-p-sbreak", + "rv32ui-p-sll") + + def addTestSuites(targetName: String, params: Parameters) { + val coreParams = + if (params(RocketTilesKey).nonEmpty) { + params(RocketTilesKey).head.core + } else { + params(BoomTilesKey).head.core + } + val xlen = params(XLen) + val vm = coreParams.useVM + val env = if (vm) List("p","v") else List("p") + coreParams.fpu foreach { case cfg => + if (xlen == 32) { + TestGeneration.addSuites(env.map(rv32uf)) + if (cfg.fLen >= 64) + TestGeneration.addSuites(env.map(rv32ud)) + } else { + TestGeneration.addSuite(rv32udBenchmarks) + TestGeneration.addSuites(env.map(rv64uf)) + if (cfg.fLen >= 64) + TestGeneration.addSuites(env.map(rv64ud)) + } + } + if (coreParams.useAtomics) TestGeneration.addSuites(env.map(if (xlen == 64) rv64ua else rv32ua)) + if (coreParams.useCompressed) TestGeneration.addSuites(env.map(if (xlen == 64) rv64uc else rv32uc)) + val (rvi, rvu) = + if (params(BoomTilesKey).nonEmpty) ((if (vm) BoomTestSuites.rv64i else BoomTestSuites.rv64pi), rv64u) + else if (xlen == 64) ((if (vm) rv64i else rv64pi), rv64u) + else ((if (vm) rv32i else rv32pi), rv32u) + + TestGeneration.addSuites(rvi.map(_("p"))) + TestGeneration.addSuites((if (vm) List("v") else List()).flatMap(env => rvu.map(_(env)))) + TestGeneration.addSuite(benchmarks) + TestGeneration.addSuite(new RegressionTestSuite(if (xlen == 64) rv64RegrTestNames else rv32RegrTestNames)) + TestGeneration.addSuite(FastBlockdevTests) + TestGeneration.addSuite(SlowBlockdevTests) + if (!targetName.contains("NoNIC")) + TestGeneration.addSuite(NICLoopbackTests) + } +} + +// Mixed into an App or into a TestSuite +trait IsFireSimGeneratorLike extends HasFireSimGeneratorUtilities with HasTestSuites { + /** Output software test Makefrags, which provide targets for integration testing. */ + def generateTestSuiteMakefrags { + addTestSuites(names.topModuleClass, targetParams) + writeOutputFile(s"$longName.d", TestGeneration.generateMakefrag) // Subsystem-specific test suites + } + + // Output miscellaneous files produced as a side-effect of elaboration + def generateArtefacts { + ElaborationArtefacts.files.foreach { case (extension, contents) => + writeOutputFile(s"${longName}.${extension}", contents ()) + } + } +} + +object FireSimGenerator extends App with IsFireSimGeneratorLike { + lazy val generatorArgs = GeneratorArgs(args) + lazy val genDir = new File(names.targetDir) + elaborateAndCompileWithMidas + generateTestSuiteMakefrags + generateHostVerilogHeader + generateArtefacts + generateTclEnvFile +} + +// For now, provide a separate generator app when not specifically building for FireSim +object Generator extends freechips.rocketchip.util.GeneratorApp with HasTestSuites { + val longName = names.topModuleProject + "." + names.topModuleClass + "." + names.configs + generateFirrtl + generateAnno + generateTestSuiteMakefrags + generateArtefacts +} diff --git a/generators/firechip/src/main/scala/SimConfigs.scala b/generators/firechip/src/main/scala/SimConfigs.scala new file mode 100644 index 00000000..1118fe07 --- /dev/null +++ b/generators/firechip/src/main/scala/SimConfigs.scala @@ -0,0 +1,54 @@ +//See LICENSE for license details. +package firesim.firesim + +import freechips.rocketchip.config.{Parameters, Config, Field} + +import midas.{EndpointKey} +import midas.widgets.{EndpointMap} +import midas.models._ + +import firesim.endpoints._ +import firesim.configs._ + +/******************************************************************************* +* Full PLATFORM_CONFIG Configurations. These set simulator parameters. +* +* In general, if you're adding or removing features from any of these, you +* should CREATE A NEW ONE, WITH A NEW NAME. This is because the manager +* will store this name as part of the tags for the AGFI, so that later you can +* reconstruct what is in a particular AGFI. These tags are also used to +* determine which driver to build. +*******************************************************************************/ +class FireSimConfig extends Config( + new WithSerialWidget ++ + new WithUARTWidget ++ + new WithSimpleNICWidget ++ + new WithBlockDevWidget ++ + new WithDefaultMemModel ++ + new WithTracerVWidget ++ + new BasePlatformConfig) + +class FireSimClockDivConfig extends Config( + new WithDefaultMemModel(clockDivision = 2) ++ + new FireSimConfig) + +class FireSimDDR3Config extends Config( + new FCFS16GBQuadRank ++ + new FireSimConfig) + +class FireSimDDR3LLC4MBConfig extends Config( + new FCFS16GBQuadRankLLC4MB ++ + new FireSimConfig) + +class FireSimDDR3FRFCFSConfig extends Config( + new FRFCFS16GBQuadRank ++ + new FireSimConfig) + +class FireSimDDR3FRFCFSLLC4MBConfig extends Config( + new FRFCFS16GBQuadRankLLC4MB ++ + new FireSimConfig) + +class FireSimDDR3FRFCFSLLC4MB3ClockDivConfig extends Config( + new FRFCFS16GBQuadRankLLC4MB3Div ++ + new FireSimConfig) + diff --git a/generators/firechip/src/main/scala/TargetConfigs.scala b/generators/firechip/src/main/scala/TargetConfigs.scala new file mode 100644 index 00000000..9be95d89 --- /dev/null +++ b/generators/firechip/src/main/scala/TargetConfigs.scala @@ -0,0 +1,205 @@ +package firesim.firesim + +import java.io.File + +import chisel3.util.{log2Up} +import freechips.rocketchip.config.{Parameters, Config} +import freechips.rocketchip.tile._ +import freechips.rocketchip.tilelink._ +import freechips.rocketchip.subsystem._ +import freechips.rocketchip.devices.tilelink.BootROMParams +import freechips.rocketchip.devices.debug.DebugModuleParams +import boom.system.BoomTilesKey +import testchipip.{WithBlockDevice, BlockDeviceKey, BlockDeviceConfig} +import sifive.blocks.devices.uart.{PeripheryUARTKey, UARTParams} +import icenet._ + +class WithBootROM extends Config((site, here, up) => { + case BootROMParams => { + val chipyardBootROM = new File(s"./generators/testchipip/bootrom/bootrom.rv${site(XLen)}.img") + val firesimBootROM = new File(s"./target-rtl/chipyard/generators/testchipip/bootrom/bootrom.rv${site(XLen)}.img") + + val bootROMPath = if (chipyardBootROM.exists()) { + chipyardBootROM.getAbsolutePath() + } else { + firesimBootROM.getAbsolutePath() + } + BootROMParams(contentFileName = bootROMPath) + } +}) + +class WithPeripheryBusFrequency(freq: BigInt) extends Config((site, here, up) => { + case PeripheryBusKey => up(PeripheryBusKey).copy(frequency=freq) +}) + +class WithUARTKey extends Config((site, here, up) => { + case PeripheryUARTKey => List(UARTParams( + address = BigInt(0x54000000L), + nTxEntries = 256, + nRxEntries = 256)) +}) + +class WithNICKey extends Config((site, here, up) => { + case NICKey => NICConfig( + inBufFlits = 8192, + ctrlQueueDepth = 64) +}) + +class WithRocketL2TLBs(entries: Int) extends Config((site, here, up) => { + case RocketTilesKey => up(RocketTilesKey) map (tile => tile.copy( + core = tile.core.copy( + nL2TLBEntries = entries + ) + )) +}) + +class WithPerfCounters extends Config((site, here, up) => { + case RocketTilesKey => up(RocketTilesKey) map (tile => tile.copy( + core = tile.core.copy(nPerfCounters = 29) + )) +}) + +class WithBoomL2TLBs(entries: Int) extends Config((site, here, up) => { + case BoomTilesKey => up(BoomTilesKey) map (tile => tile.copy( + core = tile.core.copy(nL2TLBEntries = entries) + )) +}) + +// Disables clock-gating; doesn't play nice with our FAME-1 pass +class WithoutClockGating extends Config((site, here, up) => { + case DebugModuleParams => up(DebugModuleParams, site).copy(clockGate = false) +}) + +// Testing configurations +// This enables printfs used in testing +class WithScalaTestFeatures extends Config((site, here, up) => { + case PrintTracePort => true +}) + +/******************************************************************************* +* Full TARGET_CONFIG configurations. These set parameters of the target being +* simulated. +* +* In general, if you're adding or removing features from any of these, you +* should CREATE A NEW ONE, WITH A NEW NAME. This is because the manager +* will store this name as part of the tags for the AGFI, so that later you can +* reconstruct what is in a particular AGFI. These tags are also used to +* determine which driver to build. +*******************************************************************************/ +class FireSimRocketChipConfig extends Config( + new WithBootROM ++ + new WithPeripheryBusFrequency(BigInt(3200000000L)) ++ + new WithExtMemSize(0x400000000L) ++ // 16GB + new WithoutTLMonitors ++ + new WithUARTKey ++ + new WithNICKey ++ + new WithBlockDevice ++ + new WithRocketL2TLBs(1024) ++ + new WithPerfCounters ++ + new WithoutClockGating ++ + new freechips.rocketchip.system.DefaultConfig) + +class WithNDuplicatedRocketCores(n: Int) extends Config((site, here, up) => { + case RocketTilesKey => List.tabulate(n)(i => up(RocketTilesKey).head.copy(hartId = i)) +}) + +// single core config +class FireSimRocketChipSingleCoreConfig extends Config(new FireSimRocketChipConfig) + +// dual core config +class FireSimRocketChipDualCoreConfig extends Config( + new WithNDuplicatedRocketCores(2) ++ + new FireSimRocketChipSingleCoreConfig) + +// quad core config +class FireSimRocketChipQuadCoreConfig extends Config( + new WithNDuplicatedRocketCores(4) ++ + new FireSimRocketChipSingleCoreConfig) + +// hexa core config +class FireSimRocketChipHexaCoreConfig extends Config( + new WithNDuplicatedRocketCores(6) ++ + new FireSimRocketChipSingleCoreConfig) + +// octa core config +class FireSimRocketChipOctaCoreConfig extends Config( + new WithNDuplicatedRocketCores(8) ++ + new FireSimRocketChipSingleCoreConfig) + +class FireSimBoomConfig extends Config( + new WithBootROM ++ + new WithPeripheryBusFrequency(BigInt(3200000000L)) ++ + new WithExtMemSize(0x400000000L) ++ // 16GB + new WithoutTLMonitors ++ + new WithUARTKey ++ + new WithNICKey ++ + new WithBlockDevice ++ + new WithBoomL2TLBs(1024) ++ + new WithoutClockGating ++ + // Using a small config because it has 64-bit system bus, and compiles quickly + new boom.system.SmallBoomConfig) + +// A safer implementation than the one in BOOM in that it +// duplicates whatever BOOMTileKey.head is present N times. This prevents +// accidentally (and silently) blowing away configurations that may change the +// tile in the "up" view +class WithNDuplicatedBoomCores(n: Int) extends Config((site, here, up) => { + case BoomTilesKey => List.tabulate(n)(i => up(BoomTilesKey).head.copy(hartId = i)) + case MaxHartIdBits => log2Up(site(BoomTilesKey).size) +}) + +class FireSimBoomDualCoreConfig extends Config( + new WithNDuplicatedBoomCores(2) ++ + new FireSimBoomConfig) + +class FireSimBoomQuadCoreConfig extends Config( + new WithNDuplicatedBoomCores(4) ++ + new FireSimBoomConfig) + +//********************************************************************************** +//* Supernode Configurations +//*********************************************************************************/ +class WithNumNodes(n: Int) extends Config((pname, site, here) => { + case NumNodes => n +}) + +class SupernodeFireSimRocketChipConfig extends Config( + new WithNumNodes(4) ++ + new WithExtMemSize(0x200000000L) ++ // 8GB + new FireSimRocketChipConfig) + +class SupernodeFireSimRocketChipSingleCoreConfig extends Config( + new WithNumNodes(4) ++ + new WithExtMemSize(0x200000000L) ++ // 8GB + new FireSimRocketChipSingleCoreConfig) + +class SupernodeSixNodeFireSimRocketChipSingleCoreConfig extends Config( + new WithNumNodes(6) ++ + new WithExtMemSize(0x40000000L) ++ // 1GB + new FireSimRocketChipSingleCoreConfig) + +class SupernodeEightNodeFireSimRocketChipSingleCoreConfig extends Config( + new WithNumNodes(8) ++ + new WithExtMemSize(0x40000000L) ++ // 1GB + new FireSimRocketChipSingleCoreConfig) + +class SupernodeFireSimRocketChipDualCoreConfig extends Config( + new WithNumNodes(4) ++ + new WithExtMemSize(0x200000000L) ++ // 8GB + new FireSimRocketChipDualCoreConfig) + +class SupernodeFireSimRocketChipQuadCoreConfig extends Config( + new WithNumNodes(4) ++ + new WithExtMemSize(0x200000000L) ++ // 8GB + new FireSimRocketChipQuadCoreConfig) + +class SupernodeFireSimRocketChipHexaCoreConfig extends Config( + new WithNumNodes(4) ++ + new WithExtMemSize(0x200000000L) ++ // 8GB + new FireSimRocketChipHexaCoreConfig) + +class SupernodeFireSimRocketChipOctaCoreConfig extends Config( + new WithNumNodes(4) ++ + new WithExtMemSize(0x200000000L) ++ // 8GB + new FireSimRocketChipOctaCoreConfig) + diff --git a/generators/firechip/src/main/scala/TargetLandTestSuites.scala b/generators/firechip/src/main/scala/TargetLandTestSuites.scala new file mode 100644 index 00000000..b20fa8dd --- /dev/null +++ b/generators/firechip/src/main/scala/TargetLandTestSuites.scala @@ -0,0 +1,45 @@ +//See LICENSE for license details. +package firesim.firesim + +import scala.collection.mutable.LinkedHashSet + +import freechips.rocketchip.system.{TestGeneration, RocketTestSuite} + +/* This imports tests from FireChip to test devices that aren't natively + * tested by the riscv assembly tests. + * Firesim's target-specific makefrag gives the recipes for building the + * binaries. + */ + +class BlockdevTestSuite(prefix: String, val names: LinkedHashSet[String]) extends RocketTestSuite { + val envName = "" + // fc_test_dir is is defined in firesim's Makefrag + val dir = "$(fc_test_dir)" + val makeTargetName = prefix + "-blkdev-tests" + def kind = "blockdev" + // Blockdev tests need an image, which complicates this + def additionalArgs = "+blkdev-in-mem0=128 +nic-loopback0" + override def toString = s"$makeTargetName = \\\n" + + // Make variable with the binaries of the suite + names.map(n => s"\t$n.riscv").mkString(" \\\n") + "\n\n" + + // Variables with binary specific arguments + names.map(n => s"$n.riscv_ARGS=$additionalArgs").mkString(" \n") + + postScript +} + +object FastBlockdevTests extends BlockdevTestSuite("fast", LinkedHashSet("blkdev")) +object SlowBlockdevTests extends BlockdevTestSuite("slow", LinkedHashSet("big-blkdev")) + +class NICTestSuite(prefix: String, val names: LinkedHashSet[String]) extends RocketTestSuite { + val envName = "" + val dir = "$(fc_test_dir)" + val makeTargetName = prefix + "-nic-tests" + def kind = "nic" + def additionalArgs = "+netbw0=100 +linklatency0=6405 +netburst0=8 +slotid=0 +nic-loopback0" + override def toString = s"$makeTargetName = \\\n" + + names.map(n => s"\t$n.riscv").mkString(" \\\n") + "\n\n" + + names.map(n => s"$n.riscv_ARGS=$additionalArgs").mkString(" \n") + + postScript +} + +object NICLoopbackTests extends NICTestSuite("loopback", LinkedHashSet("nic-loopback")) diff --git a/generators/firechip/src/main/scala/TargetMixins.scala b/generators/firechip/src/main/scala/TargetMixins.scala new file mode 100644 index 00000000..7b4d5d4f --- /dev/null +++ b/generators/firechip/src/main/scala/TargetMixins.scala @@ -0,0 +1,106 @@ +package firesim.firesim + +import chisel3._ +import freechips.rocketchip.config.{Field, Parameters} +import freechips.rocketchip.diplomacy._ +import freechips.rocketchip.tilelink._ +import freechips.rocketchip.subsystem._ +import freechips.rocketchip.amba.axi4._ +import freechips.rocketchip.util._ +import freechips.rocketchip.subsystem._ +import freechips.rocketchip.rocket.TracedInstruction +import firesim.endpoints.{TraceOutputTop, DeclockedTracedInstruction} + +import midas.models.AXI4BundleWithEdge +import midas.targetutils.ExcludeInstanceAsserts + +/** Copied from RC and modified to change the IO type of the Imp to include the Diplomatic edges + * associated with each port. This drives FASED functional model sizing + */ +trait CanHaveFASEDOptimizedMasterAXI4MemPort { this: BaseSubsystem => + val module: CanHaveFASEDOptimizedMasterAXI4MemPortModuleImp + + val memAXI4Node = p(ExtMem).map { case MemoryPortParams(memPortParams, nMemoryChannels) => + val portName = "axi4" + val device = new MemoryDevice + + val memAXI4Node = AXI4SlaveNode(Seq.tabulate(nMemoryChannels) { channel => + val base = AddressSet.misaligned(memPortParams.base, memPortParams.size) + val filter = AddressSet(channel * mbus.blockBytes, ~((nMemoryChannels-1) * mbus.blockBytes)) + + AXI4SlavePortParameters( + slaves = Seq(AXI4SlaveParameters( + address = base.flatMap(_.intersect(filter)), + resources = device.reg, + regionType = RegionType.UNCACHED, // cacheable + executable = true, + supportsWrite = TransferSizes(1, mbus.blockBytes), + supportsRead = TransferSizes(1, mbus.blockBytes), + interleavedId = Some(0))), // slave does not interleave read responses + beatBytes = memPortParams.beatBytes) + }) + + memAXI4Node := mbus.toDRAMController(Some(portName)) { + AXI4UserYanker() := AXI4IdIndexer(memPortParams.idBits) := TLToAXI4() + } + + memAXI4Node + } +} + +/** Actually generates the corresponding IO in the concrete Module */ +trait CanHaveFASEDOptimizedMasterAXI4MemPortModuleImp extends LazyModuleImp { + val outer: CanHaveFASEDOptimizedMasterAXI4MemPort + + val mem_axi4 = outer.memAXI4Node.map(x => IO(HeterogeneousBag(AXI4BundleWithEdge.fromNode(x.in)))) + (mem_axi4 zip outer.memAXI4Node) foreach { case (io, node) => + (io zip node.in).foreach { case (io, (bundle, _)) => io <> bundle } + } + + def connectSimAXIMem() { + (mem_axi4 zip outer.memAXI4Node).foreach { case (io, node) => + (io zip node.in).foreach { case (io, (_, edge)) => + val mem = LazyModule(new SimAXIMem(edge, size = p(ExtMem).get.master.size)) + Module(mem.module).io.axi4.head <> io + } + } + } +} + +/* Wires out tile trace ports to the top; and wraps them in a Bundle that the + * TracerV endpoint can match on. + */ +object PrintTracePort extends Field[Boolean](false) + +trait HasTraceIO { + this: HasTiles => + val module: HasTraceIOImp + + // Bind all the trace nodes to a BB; we'll use this to generate the IO in the imp + val traceNexus = BundleBridgeNexus[Vec[TracedInstruction]] + val tileTraceNodes = tiles.map(tile => tile.traceNode) + tileTraceNodes foreach { traceNexus := _ } +} + +trait HasTraceIOImp extends LazyModuleImp { + val outer: HasTraceIO + + val traceIO = IO(Output(new TraceOutputTop( + DeclockedTracedInstruction.fromNode(outer.traceNexus.in)))) + (traceIO.traces zip outer.traceNexus.in).foreach({ case (port, (tileTrace, _)) => + port := DeclockedTracedInstruction.fromVec(tileTrace) + }) + + // Enabled to test TracerV trace capture + if (p(PrintTracePort)) { + val traceprint = Wire(UInt(512.W)) + traceprint := traceIO.asUInt + printf("TRACEPORT: %x\n", traceprint) + } +} + +// Prevent MIDAS from synthesizing assertions in the dummy TLB included in BOOM +trait ExcludeInvalidBoomAssertions extends LazyModuleImp { + ExcludeInstanceAsserts(("NonBlockingDCache", "dtlb")) +} + diff --git a/generators/firechip/src/main/scala/Targets.scala b/generators/firechip/src/main/scala/Targets.scala new file mode 100644 index 00000000..7f8bb830 --- /dev/null +++ b/generators/firechip/src/main/scala/Targets.scala @@ -0,0 +1,176 @@ +package firesim.firesim + +import chisel3._ +import freechips.rocketchip._ +import freechips.rocketchip.subsystem._ +import freechips.rocketchip.diplomacy._ +import freechips.rocketchip.tilelink._ +import freechips.rocketchip.devices.tilelink._ +import freechips.rocketchip.config.Parameters +import freechips.rocketchip.util.{HeterogeneousBag} +import freechips.rocketchip.amba.axi4.AXI4Bundle +import freechips.rocketchip.config.{Field, Parameters} +import freechips.rocketchip.diplomacy.LazyModule +import boom.system.{BoomRocketSubsystem, BoomRocketSubsystemModuleImp} +import icenet._ +import testchipip._ +import testchipip.SerialAdapter.SERIAL_IF_WIDTH +import sifive.blocks.devices.uart._ +import midas.models.AXI4BundleWithEdge +import java.io.File + +/******************************************************************************* +* Top level DESIGN configurations. These describe the basic instantiations of +* the designs being simulated. +* +* In general, if you're adding or removing features from any of these, you +* should CREATE A NEW ONE, WITH A NEW NAME. This is because the manager +* will store this name as part of the tags for the AGFI, so that later you can +* reconstruct what is in a particular AGFI. These tags are also used to +* determine which driver to build. +*******************************************************************************/ + +class FireSim(implicit p: Parameters) extends RocketSubsystem + with HasHierarchicalBusTopology + with CanHaveFASEDOptimizedMasterAXI4MemPort + with HasPeripheryBootROM + with HasNoDebug + with HasPeripherySerial + with HasPeripheryUART + with HasPeripheryIceNIC + with HasPeripheryBlockDevice + with HasTraceIO +{ + override lazy val module = new FireSimModuleImp(this) +} + +class FireSimModuleImp[+L <: FireSim](l: L) extends RocketSubsystemModuleImp(l) + with HasRTCModuleImp + with CanHaveFASEDOptimizedMasterAXI4MemPortModuleImp + with HasPeripheryBootROMModuleImp + with HasNoDebugModuleImp + with HasPeripherySerialModuleImp + with HasPeripheryUARTModuleImp + with HasPeripheryIceNICModuleImpValidOnly + with HasPeripheryBlockDeviceModuleImp + with HasTraceIOImp + + +class FireSimNoNIC(implicit p: Parameters) extends RocketSubsystem + with HasHierarchicalBusTopology + with CanHaveFASEDOptimizedMasterAXI4MemPort + with HasPeripheryBootROM + with HasNoDebug + with HasPeripherySerial + with HasPeripheryUART + with HasPeripheryBlockDevice + with HasTraceIO +{ + override lazy val module = new FireSimNoNICModuleImp(this) +} + +class FireSimNoNICModuleImp[+L <: FireSimNoNIC](l: L) extends RocketSubsystemModuleImp(l) + with HasRTCModuleImp + with CanHaveFASEDOptimizedMasterAXI4MemPortModuleImp + with HasPeripheryBootROMModuleImp + with HasNoDebugModuleImp + with HasPeripherySerialModuleImp + with HasPeripheryUARTModuleImp + with HasPeripheryBlockDeviceModuleImp + with HasTraceIOImp + + +class FireBoom(implicit p: Parameters) extends BoomRocketSubsystem + with HasHierarchicalBusTopology + with CanHaveFASEDOptimizedMasterAXI4MemPort + with HasPeripheryBootROM + with HasNoDebug + with HasPeripherySerial + with HasPeripheryUART + with HasPeripheryIceNIC + with HasPeripheryBlockDevice + with HasTraceIO +{ + override lazy val module = new FireBoomModuleImp(this) +} + +class FireBoomModuleImp[+L <: FireBoom](l: L) extends BoomRocketSubsystemModuleImp(l) + with HasRTCModuleImp + with CanHaveFASEDOptimizedMasterAXI4MemPortModuleImp + with HasPeripheryBootROMModuleImp + with HasNoDebugModuleImp + with HasPeripherySerialModuleImp + with HasPeripheryUARTModuleImp + with HasPeripheryIceNICModuleImpValidOnly + with HasPeripheryBlockDeviceModuleImp + with HasTraceIOImp + with ExcludeInvalidBoomAssertions + +class FireBoomNoNIC(implicit p: Parameters) extends BoomRocketSubsystem + with HasHierarchicalBusTopology + with CanHaveFASEDOptimizedMasterAXI4MemPort + with HasPeripheryBootROM + with HasNoDebug + with HasPeripherySerial + with HasPeripheryUART + with HasPeripheryBlockDevice + with HasTraceIO +{ + override lazy val module = new FireBoomNoNICModuleImp(this) +} + +class FireBoomNoNICModuleImp[+L <: FireBoomNoNIC](l: L) extends BoomRocketSubsystemModuleImp(l) + with HasRTCModuleImp + with CanHaveFASEDOptimizedMasterAXI4MemPortModuleImp + with HasPeripheryBootROMModuleImp + with HasNoDebugModuleImp + with HasPeripherySerialModuleImp + with HasPeripheryUARTModuleImp + with HasPeripheryBlockDeviceModuleImp + with HasTraceIOImp + with ExcludeInvalidBoomAssertions + +case object NumNodes extends Field[Int] + +class SupernodeIO( + nNodes: Int, + serialWidth: Int, + bagPrototype: HeterogeneousBag[AXI4BundleWithEdge])(implicit p: Parameters) + extends Bundle { + + val serial = Vec(nNodes, new SerialIO(serialWidth)) + val mem_axi = Vec(nNodes, bagPrototype.cloneType) + val bdev = Vec(nNodes, new BlockDeviceIO) + val net = Vec(nNodes, new NICIOvonly) + val uart = Vec(nNodes, new UARTPortIO) + + override def cloneType = new SupernodeIO(nNodes, serialWidth, bagPrototype).asInstanceOf[this.type] +} + + +class FireSimSupernode(implicit p: Parameters) extends Module { + val nNodes = p(NumNodes) + val nodes = Seq.fill(nNodes) { + Module(LazyModule(new FireSim).module) + } + + val io = IO(new SupernodeIO(nNodes, SERIAL_IF_WIDTH, nodes(0).mem_axi4.get)) + + io.mem_axi.zip(nodes.map(_.mem_axi4)).foreach { + case (out, mem_axi4) => out <> mem_axi4.get + } + io.serial <> nodes.map(_.serial) + io.bdev <> nodes.map(_.bdev) + io.net <> nodes.map(_.net) + io.uart <> nodes.map(_.uart(0)) + nodes.foreach{ case n => { + n.debug.clockeddmi.get.dmi.req.valid := false.B + n.debug.clockeddmi.get.dmi.resp.ready := false.B + n.debug.clockeddmi.get.dmiClock := clock + n.debug.clockeddmi.get.dmiReset := reset.toBool + n.debug.clockeddmi.get.dmi.req.bits.data := DontCare + n.debug.clockeddmi.get.dmi.req.bits.addr := DontCare + n.debug.clockeddmi.get.dmi.req.bits.op := DontCare + } } +} + diff --git a/generators/firechip/src/test/scala/ScalaTestSuite.scala b/generators/firechip/src/test/scala/ScalaTestSuite.scala new file mode 100644 index 00000000..54848ac8 --- /dev/null +++ b/generators/firechip/src/test/scala/ScalaTestSuite.scala @@ -0,0 +1,138 @@ +//See LICENSE for license details. +package firesim.firesim + +import java.io.File + +import scala.concurrent.{Future, Await, ExecutionContext} +import scala.sys.process.{stringSeqToProcess, ProcessLogger} +import scala.io.Source + +import freechips.rocketchip.diplomacy._ +import freechips.rocketchip.system.{RocketTestSuite, BenchmarkTestSuite} +import freechips.rocketchip.system.TestGeneration._ +import freechips.rocketchip.system.DefaultTestSuites._ + +import firesim.util.GeneratorArgs + +abstract class FireSimTestSuite( + topModuleClass: String, + targetConfigs: String, + platformConfigs: String, + N: Int = 8 + ) extends firesim.TestSuiteCommon with IsFireSimGeneratorLike { + import scala.concurrent.duration._ + import ExecutionContext.Implicits.global + + lazy val generatorArgs = GeneratorArgs( + midasFlowKind = "midas", + targetDir = "generated-src", + topModuleProject = "firesim.firesim", + topModuleClass = topModuleClass, + targetConfigProject = "firesim.firesim", + targetConfigs = targetConfigs ++ "_WithScalaTestFeatures", + platformConfigProject = "firesim.firesim", + platformConfigs = platformConfigs) + + // From HasFireSimGeneratorUtilities + // For the firesim utilities to use the same directory as the test suite + override lazy val testDir = genDir + + // From TestSuiteCommon + val targetTuple = generatorArgs.tupleName + val commonMakeArgs = Seq(s"DESIGN=${generatorArgs.topModuleClass}", + s"TARGET_CONFIG=${generatorArgs.targetConfigs}", + s"PLATFORM_CONFIG=${generatorArgs.platformConfigs}") + override lazy val platform = hostParams(midas.Platform) + + def invokeMlSimulator(backend: String, name: String, debug: Boolean, additionalArgs: Seq[String] = Nil) = { + make((Seq(s"${outDir.getAbsolutePath}/${name}.%s".format(if (debug) "vpd" else "out"), + s"EMUL=${backend}") + ++ additionalArgs):_*) + } + + def runTest(backend: String, name: String, debug: Boolean, additionalArgs: Seq[String] = Nil) = { + behavior of s"${name} running on ${backend} in MIDAS-level simulation" + compileMlSimulator(backend, debug) + if (isCmdAvailable(backend)) { + it should s"pass" in { + assert(invokeMlSimulator(backend, name, debug, additionalArgs) == 0) + } + } + } + + //def runReplay(backend: String, replayBackend: String, name: String) = { + // val dir = (new File(outDir, backend)).getAbsolutePath + // (Seq("make", s"replay-$replayBackend", + // s"SAMPLE=${dir}/${name}.sample", s"output_dir=$dir") ++ makeArgs).! + //} + + def runSuite(backend: String, debug: Boolean = false)(suite: RocketTestSuite) { + // compile emulators + behavior of s"${suite.makeTargetName} running on $backend" + if (isCmdAvailable(backend)) { + val postfix = suite match { + case _: BenchmarkTestSuite | _: BlockdevTestSuite | _: NICTestSuite => ".riscv" + case _ => "" + } + val results = suite.names.toSeq sliding (N, N) map { t => + val subresults = t map (name => + Future(name -> invokeMlSimulator(backend, s"$name$postfix", debug))) + Await result (Future sequence subresults, Duration.Inf) + } + results.flatten foreach { case (name, exitcode) => + it should s"pass $name" in { assert(exitcode == 0) } + } + //replayBackends foreach { replayBackend => + // if (platformParams(midas.EnableSnapshot) && isCmdAvailable("vcs")) { + // assert((Seq("make", s"vcs-$replayBackend") ++ makeArgs).! == 0) // compile vcs + // suite.names foreach { name => + // it should s"replay $name in $replayBackend" in { + // assert(runReplay(backend, replayBackend, s"$name$postfix") == 0) + // } + // } + // } else { + // suite.names foreach { name => + // ignore should s"replay $name in $backend" + // } + // } + //} + } else { + ignore should s"pass $backend" + } + } + + // Checks the collected trace log matches the behavior of a chisel printf + def diffTracelog(verilatedLog: String) { + behavior of "captured instruction trace" + it should s"match the chisel printf in ${verilatedLog}" in { + def getLines(file: File, dropLines: Int = 0): Seq[String] = { + val lines = Source.fromFile(file).getLines.toList + lines.filter(_.startsWith("TRACEPORT")).drop(dropLines) + } + val resetLength = 50 + val verilatedOutput = getLines(new File(outDir, s"/${verilatedLog}")) + val synthPrintOutput = getLines(new File(genDir, s"/TRACEFILE"), resetLength + 1) + assert(verilatedOutput.size == synthPrintOutput.size, "Outputs differ in length") + assert(verilatedOutput.nonEmpty) + for ( (vPrint, sPrint) <- verilatedOutput.zip(synthPrintOutput) ) { + assert(vPrint == sPrint) + } + } + } + + clean + mkdirs + elaborateAndCompileWithMidas + generateTestSuiteMakefrags + runTest("verilator", "rv64ui-p-simple", false, Seq(s"""EXTRA_SIM_ARGS=+trace-test-output0""")) + diffTracelog("rv64ui-p-simple.out") + runSuite("verilator")(benchmarks) + runSuite("verilator")(FastBlockdevTests) +} + +class RocketF1Tests extends FireSimTestSuite("FireSimNoNIC", "FireSimRocketChipConfig", "FireSimConfig") +class RocketF1ClockDivTests extends FireSimTestSuite("FireSimNoNIC", "FireSimRocketChipConfig", "FireSimClockDivConfig") +class BoomF1Tests extends FireSimTestSuite("FireBoomNoNIC", "FireSimBoomConfig", "FireSimConfig") +class RocketNICF1Tests extends FireSimTestSuite("FireSim", "FireSimRocketChipConfig", "FireSimConfig") { + runSuite("verilator")(NICLoopbackTests) +} diff --git a/generators/icenet b/generators/icenet new file mode 160000 index 00000000..bba264d6 --- /dev/null +++ b/generators/icenet @@ -0,0 +1 @@ +Subproject commit bba264d68d366180f6f9b55061ee9408425d8229 diff --git a/generators/rocket-chip b/generators/rocket-chip index b8baef6f..50de8a34 160000 --- a/generators/rocket-chip +++ b/generators/rocket-chip @@ -1 +1 @@ -Subproject commit b8baef6f26fa36c9b4e0b2a5eec12cd76ae5daf8 +Subproject commit 50de8a34c19c12de5066cd7ada50ebb5f5b2ea26 diff --git a/generators/sifive-cache b/generators/sifive-cache new file mode 160000 index 00000000..13d0c2f1 --- /dev/null +++ b/generators/sifive-cache @@ -0,0 +1 @@ +Subproject commit 13d0c2f17853a658ae86eae793718c71ac82dddf diff --git a/generators/testchipip b/generators/testchipip index cd176871..85db33c3 160000 --- a/generators/testchipip +++ b/generators/testchipip @@ -1 +1 @@ -Subproject commit cd1768712ead82d1a76278b65b7f6ea41ae82dc9 +Subproject commit 85db33c398c54eba6c979f798e975ad9a29020b4 diff --git a/scripts/build-static-libfesvr.sh b/scripts/build-static-libfesvr.sh new file mode 100755 index 00000000..360028ad --- /dev/null +++ b/scripts/build-static-libfesvr.sh @@ -0,0 +1,17 @@ +#!/usr/bin/env bash + +# This ungodly script surreptitiously builds an archive from existing fesvr objects +# Invoke from riscv-fesvr/build + +if [ "x$RISCV" = "x" ] +then + echo "Please set the RISCV environment variable to your preferred install path." + exit 1 +fi + +set -e + +objs=$(head -n 1 <(make -f <( echo -e 'include Makefile\n$(info $(value fesvr_objs))') -n)) +ar rcs -o libfesvr.a $objs +cp -f libfesvr.a $RISCV/lib + diff --git a/scripts/build-toolchains.sh b/scripts/build-toolchains.sh index 9b659109..e743afe4 100755 --- a/scripts/build-toolchains.sh +++ b/scripts/build-toolchains.sh @@ -1,38 +1,160 @@ #!/usr/bin/env bash +#this script is based on the firesim build toolchains script + # exit script if any command fails set -e set -o pipefail unamestr=$(uname) RDIR=$(pwd) -: ${REBAR_DIR:=$(pwd)} #default value is the PWD unless overridden +: ${CHIPYARD_DIR:=$(pwd)} #default value is the PWD unless overridden -if [ $# -ne 0 ]; then - TOOLCHAIN=$1 - if [ $1 == "riscv" ]; then - TOOLCHAIN="riscv-tools" - elif [ $1 == "hwacha" ]; then - TOOLCHAIN="esp-tools" - fi -else - TOOLCHAIN="riscv-tools" +PRECOMPILED_REPO_HASH=56a40961c98db5e8f904f15dc6efd0870bfefd9e + +function usage +{ + echo "usage: ./scripts/build-toolchains.sh [riscv-tools] [esp-tools] [ec2fast | --ec2fast] " + echo " riscv: if set, builds the riscv toolchain (this is also the default)" + echo " hwacha: if set, builds esp-tools toolchain" + echo " ec2fast: if set, pulls in a pre-compiled RISC-V toolchain for an EC2 manager instance" +} + +#taken from riscv-tools to check for open-ocd autoconf versions +check_version() { + $1 --version | awk "NR==1 {if (\$NF>$2) {exit 0} exit 1}" || ( + echo $3 requires at least version $2 of $1. Aborting. + exit 1 + ) +} + +if [ "$1" == "--help" -o "$1" == "-h" -o "$1" == "-H" ]; then + usage + exit 3 +fi + +TOOLCHAIN="riscv-tools" +EC2FASTINSTALL="false" +FASTINSTALL="false" +while test $# -gt 0 +do + case "$1" in + riscv-tools) + TOOLCHAIN="riscv-tools" + ;; + esp-tools) + TOOLCHAIN="esp-tools" + ;; + ec2fast | --ec2fast) # I don't want to break this api + EC2FASTINSTALL=true + ;; + -h | -H | --help) + usage + exit 3 + ;; + --*) echo "ERROR: bad option $1" + usage + exit 1 + ;; + *) echo "ERROR: bad argument $1" + usage + exit 2 + ;; + esac + shift +done + + +if [ "$EC2FASTINSTALL" = "true" ]; then + if [ "$TOOLCHAIN" = "riscv-tools" ]; then + cd $RDIR + git clone https://github.com/firesim/firesim-riscv-tools-prebuilt.git + cd firesim-riscv-tools-prebuilt + git checkout $PRECOMPILED_REPO_HASH + PREBUILTHASH="$(cat HASH)" + git -C $CHIPYARD_DIR submodule update --init toolchains/$TOOLCHAIN + cd "$CHIPYARD_DIR/toolchains/$TOOLCHAIN" + GITHASH="$(git rev-parse HEAD)" + cd $RDIR + echo "prebuilt hash: $PREBUILTHASH" + echo "git hash: $GITHASH" + if [[ $PREBUILTHASH == $GITHASH && "$EC2FASTINSTALL" == "true" ]]; then + FASTINSTALL=true + echo "Using fast pre-compiled install for riscv-tools" + else + echo "Error: hash of precompiled toolchain doesn't match the riscv-tools submodule hash." + exit + fi + else + echo "Error: No precompiled toolchain for esp-tools or other non-native riscv-tools." + exit + fi fi INSTALL_DIR="$TOOLCHAIN-install" -mkdir -p "$(pwd)/$INSTALL_DIR" RISCV="$(pwd)/$INSTALL_DIR" # install risc-v tools export RISCV="$RISCV" -git -C $REBAR_DIR submodule update --init --recursive toolchains/$TOOLCHAIN #--jobs 8 -cd "$REBAR_DIR/toolchains/$TOOLCHAIN" -export MAKEFLAGS="-j16" -./build.sh + +if [ "$FASTINSTALL" = true ]; then + cd firesim-riscv-tools-prebuilt + ./installrelease.sh + mv distrib "$RISCV" + # copy HASH in case user wants it later + cp HASH "$RISCV" + cd $RDIR + rm -rf firesim-riscv-tools-prebuilt +else + mkdir -p "$RISCV" + git -C $CHIPYARD_DIR submodule update --init --recursive toolchains/$TOOLCHAIN #--jobs 8 + cd "$CHIPYARD_DIR/toolchains/$TOOLCHAIN" + export MAKEFLAGS="-j16" + #build the actual toolchain + #./build.sh + source build.common + echo "Starting RISC-V Toolchain build process" + build_project riscv-fesvr --prefix=$RISCV + build_project riscv-isa-sim --prefix=$RISCV --with-fesvr=$RISCV + build_project riscv-gnu-toolchain --prefix=$RISCV + CC= CXX= build_project riscv-pk --prefix=$RISCV --host=riscv64-unknown-elf + build_project riscv-tests --prefix=$RISCV/riscv64-unknown-elf + echo -e "\\nRISC-V Toolchain installation completed!" + + # build static libfesvr library for linking into firesim driver (or others) + cd riscv-fesvr/build + $CHIPYARD_DIR/scripts/build-static-libfesvr.sh + cd $RDIR + # build linux toolchain + cd "$CHIPYARD_DIR/toolchains/$TOOLCHAIN/riscv-gnu-toolchain/build" + make -j16 linux + echo -e "\\nRISC-V Linux GNU Toolchain installation completed!" + +fi + cd $RDIR -echo "export RISCV=$RISCV" > env.sh +echo "export CHIPYARD_TOOLCHAIN_SOURCED=1" > env.sh +echo "export RISCV=$RISCV" >> env.sh echo "export PATH=$RISCV/bin:$RDIR/$DTCversion:\$PATH" >> env.sh -echo "export LD_LIBRARY_PATH=$RISCV/lib" >> env.sh +echo "export LD_LIBRARY_PATH=$RISCV/lib\${LD_LIBRARY_PATH:+":${LD_LIBRARY_PATH}"}" >> env.sh echo "Toolchain Build Complete!" + + +if [ "$FASTINSTALL" = "false" ]; then + # commands that can't run on EC2 (specifically, OpenOCD because of autoconf version_ + # see if the instance info page exists. if not, we are not on ec2. + # this is one of the few methods that works without sudo + if wget -T 1 -t 3 -O /dev/null http://169.254.169.254/; then + echo "Skipping RISC-V OpenOCD" + else + echo "Building RISC-V OpenOCD" + cd "$CHIPYARD_DIR/toolchains/$TOOLCHAIN" + check_version automake 1.14 "OpenOCD build" + check_version autoconf 2.64 "OpenOCD build" + build_project riscv-openocd --prefix=$RISCV --enable-remote-bitbang --enable-jtag_vpi --disable-werror + echo -e "\\nRISC-V OpenOCD installation completed!" + cd $RDIR + fi +fi diff --git a/scripts/firesim-setup.sh b/scripts/firesim-setup.sh new file mode 100755 index 00000000..302294bf --- /dev/null +++ b/scripts/firesim-setup.sh @@ -0,0 +1,18 @@ +#!/usr/bin/env bash + +# Sets up FireSim for use as a library within REBAR + +set -e +set -o pipefail + +RDIR=$(pwd) +scripts_dir="$( cd "$( dirname "${BASH_SOURCE[0]}" )" >/dev/null 2>&1 && pwd )" + +cd $scripts_dir/.. + +# Reenable the FireSim submodule +git config --unset submodule.sims/firesim.update || true +git submodule update --init sims/firesim +cd sims/firesim +./build-setup.sh $@ --library +cd $RDIR diff --git a/scripts/gen-tags.sh b/scripts/gen-tags.sh index 52df9aa7..afc7e228 100755 --- a/scripts/gen-tags.sh +++ b/scripts/gen-tags.sh @@ -1,10 +1,10 @@ #!/usr/bin/env bash -# run this script in the main rebar directory to generate ctags for all relevant repos +# run this script in the main Chipyard directory to generate ctags for all relevant repos # note: this requires exuberant-ctags # tested with: Exuberant Ctags 5.8 # instructions: -# cd /path/to/rebar/ +# cd /path/to/chipyard/ # ./scripts/gen-tags.sh # # input: diff --git a/scripts/init-submodules-no-riscv-tools.sh b/scripts/init-submodules-no-riscv-tools.sh index 27005cbb..3a95f5c6 100755 --- a/scripts/init-submodules-no-riscv-tools.sh +++ b/scripts/init-submodules-no-riscv-tools.sh @@ -6,14 +6,31 @@ set -o pipefail unamestr=$(uname) RDIR=$(pwd) +scripts_dir="$( cd "$( dirname "${BASH_SOURCE[0]}" )" >/dev/null 2>&1 && pwd )" # ignore riscv-tools for submodule init recursive # you must do this globally (otherwise riscv-tools deep # in the submodule tree will get pulled anyway -git config --global submodule.riscv-tools.update none -git config --global submodule.esp-tools.update none +git config submodule.toolchains/riscv-tools.update none +git config submodule.toolchains/esp-tools.update none git config --global submodule.experimental-blocks.update none +# Disable updates to the FireSim submodule until explicitly requested +git config submodule.sims/firesim.update none +# Disable updates to the hammer-cad-plugins repo +git config submodule.vlsi/hammer-cad-plugins.update none git submodule update --init --recursive #--jobs 8 # unignore riscv-tools,catapult-shell2 globally -git config --global --unset submodule.riscv-tools.update +git config --unset submodule.toolchains/riscv-tools.update +git config --unset submodule.toolchains/esp-tools.update git config --global --unset submodule.experimental-blocks.update +git config --unset submodule.vlsi/hammer-cad-plugins.update + +# Renable firesim and init only the required submodules to provide +# all required scala deps, without doing a full build-setup +git config --unset submodule.sims/firesim.update +cd $scripts_dir/../sims/ +git submodule update --init firesim +cd firesim/sim +git submodule update --init midas +cd $RDIR +git config submodule.sims/firesim.update none diff --git a/scripts/init-vlsi.sh b/scripts/init-vlsi.sh new file mode 100755 index 00000000..294f8628 --- /dev/null +++ b/scripts/init-vlsi.sh @@ -0,0 +1,13 @@ +#!/usr/bin/env bash +# exit script if any command fails +set -e +set -o pipefail + + + +# Initialize HAMMER and CAD-plugins +git submodule update --init --recursive vlsi/hammer +git submodule update --init --recursive vlsi/hammer-cad-plugins + +# Initialize HAMMER tech plugin +git submodule update --init --recursive vlsi/hammer-$1-plugin \ No newline at end of file diff --git a/scripts/regression.sh b/scripts/regression.sh deleted file mode 100755 index 3175891c..00000000 --- a/scripts/regression.sh +++ /dev/null @@ -1,31 +0,0 @@ -#!/bin/bash - -# NOTE: TEMPORARY UNTIL CI IS ONLINE - -# Run by just giving the test to run (run-bmark-tests | run-asm-tests) -# Runs in vsim and verisim - -set -ex -set -euo pipefail - -cd sims/vsim/ - -make SUB_PROJECT=rocketchip CONFIG=DefaultConfig -make SUB_PROJECT=rocketchip CONFIG=DefaultConfig $1 -make SUB_PROJECT=boom CONFIG=BoomConfig -make SUB_PROJECT=boom CONFIG=BoomConfig $1 -make SUB_PROJECT=example CONFIG=DefaultRocketConfig -make SUB_PROJECT=example CONFIG=DefaultRocketConfig $1 -make SUB_PROJECT=boomexample CONFIG=DefaultBoomConfig -make SUB_PROJECT=boomexample CONFIG=DefaultBoomConfig $1 - -cd ../verisim/ - -make SUB_PROJECT=rocketchip CONFIG=DefaultConfig -make SUB_PROJECT=rocketchip CONFIG=DefaultConfig $1 -make SUB_PROJECT=boom CONFIG=BoomConfig -make SUB_PROJECT=boom CONFIG=BoomConfig $1 -make SUB_PROJECT=example CONFIG=DefaultRocketConfig -make SUB_PROJECT=example CONFIG=DefaultRocketConfig $1 -make SUB_PROJECT=boomexample CONFIG=DefaultBoomConfig -make SUB_PROJECT=boomexample CONFIG=DefaultBoomConfig $1 diff --git a/sims/firesim b/sims/firesim new file mode 160000 index 00000000..4cd75833 --- /dev/null +++ b/sims/firesim @@ -0,0 +1 @@ +Subproject commit 4cd75833dfc1f9f796a1c5505ece6937fd253189 diff --git a/sims/vsim/.gitignore b/sims/vcs/.gitignore similarity index 100% rename from sims/vsim/.gitignore rename to sims/vcs/.gitignore diff --git a/sims/vsim/Makefile b/sims/vcs/Makefile similarity index 82% rename from sims/vsim/Makefile rename to sims/vcs/Makefile index d34fb5eb..fa05531f 100644 --- a/sims/vsim/Makefile +++ b/sims/vcs/Makefile @@ -28,6 +28,8 @@ sim_debug = $(sim_dir)/$(sim_prefix)-$(MODEL_PACKAGE)-$(CONFIG)-debug PERMISSIVE_ON=+permissive PERMISSIVE_OFF=+permissive-off +WAVEFORM_FLAG=+vcdplusfile=$(sim_out_name).vpd + .PHONY: default debug default: $(sim) debug: $(sim_debug) @@ -54,13 +56,12 @@ VCS_NONCC_OPTS = \ -error=PCWM-L \ -timescale=1ns/10ps \ -quiet \ + -q \ +rad \ +v2k \ +vcs+lic+wait \ +vc+list \ - -f $(sim_top_blackboxes) \ - -f $(sim_harness_blackboxes) \ - -f $(sim_dotf) \ + -f $(sim_common_files) \ -sverilog \ +incdir+$(build_dir) \ +define+CLOCK_PERIOD=1.0 \ @@ -78,29 +79,23 @@ VCS_OPTS = -notice -line $(VCS_CC_OPTS) $(VCS_NONCC_OPTS) ######################################################################################### # vcs simulator rules ######################################################################################### -$(sim): $(sim_vsrcs) $(sim_dotf) +$(sim): $(sim_vsrcs) $(sim_common_files) rm -rf csrc && $(VCS) $(VCS_OPTS) -o $@ \ -debug_pp -$(sim_debug) : $(sim_vsrcs) $(sim_dotf) +$(sim_debug) : $(sim_vsrcs) $(sim_common_files) rm -rf csrc && $(VCS) $(VCS_OPTS) -o $@ \ +define+DEBUG -debug_pp -######################################################################################### -# helper rules to run simulator with debug -######################################################################################### -run-binary-debug: $(sim_debug) - $(sim_debug) $(PERMISSIVE_ON) $(SIM_FLAGS) +vcdplusfile=$(sim_out_name).vpd $(PERMISSIVE_OFF) $(BINARY) 3>&1 1>&2 2>&3 | spike-dasm > $(sim_out_name).out - ######################################################################################### # create a vcs vpd rule ######################################################################################### $(output_dir)/%.vpd: $(output_dir)/% $(sim_debug) - $(sim_debug) $(PERMISSIVE_ON) +vcdplusfile=$@ +max-cycles=$(timeout_cycles) $(PERMISSIVE_OFF) $< + $(sim_debug) $(PERMISSIVE_ON) +max-cycles=$(timeout_cycles) $(SIM_FLAGS) $(VERBOSE_FLAGS) +vcdplusfile=$@ $(PERMISSIVE_OFF) $< ######################################################################################### # general cleanup rule ######################################################################################### .PHONY: clean clean: - rm -rf $(gen_dir)/* csrc $(sim_prefix)-* ucli.key vc_hdrs.h + rm -rf $(gen_dir) csrc $(sim_prefix)-* ucli.key vc_hdrs.h diff --git a/sims/verisim/.gitignore b/sims/verilator/.gitignore similarity index 100% rename from sims/verisim/.gitignore rename to sims/verilator/.gitignore diff --git a/sims/verisim/Makefile b/sims/verilator/Makefile similarity index 74% rename from sims/verisim/Makefile rename to sims/verilator/Makefile index 655d67cc..d717aa63 100644 --- a/sims/verisim/Makefile +++ b/sims/verilator/Makefile @@ -28,6 +28,8 @@ sim_debug = $(sim_dir)/$(sim_prefix)-$(MODEL_PACKAGE)-$(CONFIG)-debug PERMISSIVE_ON= PERMISSIVE_OFF= +WAVEFORM_FLAG=-v$(sim_out_name).vcd + .PHONY: default debug default: $(sim) debug: $(sim_debug) @@ -38,6 +40,31 @@ debug: $(sim_debug) include $(base_dir)/common.mk include $(sim_dir)/verilator.mk +######################################################################################### +# verilator binary and flags +######################################################################################### +VERILATOR := $(INSTALLED_VERILATOR) --cc --exe + +CXXFLAGS := $(CXXFLAGS) -O1 -std=c++11 -I$(RISCV)/include -D__STDC_FORMAT_MACROS +LDFLAGS := $(LDFLAGS) -L$(RISCV)/lib -Wl,-rpath,$(RISCV)/lib -L$(sim_dir) -lfesvr -lpthread + +VERILATOR_CC_OPTS = \ + -O3 \ + -CFLAGS "$(CXXFLAGS) -DTEST_HARNESS=V$(VLOG_MODEL) -DVERILATOR" \ + -CFLAGS "-I$(build_dir) -include $(build_dir)/$(long_name).plusArgs" \ + -LDFLAGS "$(LDFLAGS)" + +VERILATOR_NONCC_OPTS = \ + --top-module $(VLOG_MODEL) \ + +define+PRINTF_COND=\$$c\(\"verbose\",\"\&\&\"\,\"done_reset\"\) \ + +define+STOP_COND=\$$c\(\"done_reset\"\) \ + --assert \ + --output-split 20000 \ + $(sim_vsrcs) \ + -f $(sim_common_files) + +VERILATOR_OPTS = $(VERILATOR_CC_OPTS) $(VERILATOR_NONCC_OPTS) + ######################################################################################### # verilator build paths and file names ######################################################################################### @@ -53,50 +80,39 @@ model_mk_debug = $(model_dir_debug)/V$(VLOG_MODEL).mk ######################################################################################### # build makefile fragment that builds the verilator sim rules ######################################################################################### -LDFLAGS := $(LDFLAGS) -L$(RISCV)/lib -Wl,-rpath,$(RISCV)/lib -L$(sim_dir) -lfesvr -lpthread -$(model_mk): $(sim_vsrcs) $(sim_dotf) $(INSTALLED_VERILATOR) +$(model_mk): $(sim_vsrcs) $(sim_common_files) $(INSTALLED_VERILATOR) rm -rf $(build_dir)/$(long_name) mkdir -p $(build_dir)/$(long_name) - $(VERILATOR) $(VERILATOR_FLAGS) -Mdir $(build_dir)/$(long_name) \ - -o $(sim) $(sim_vsrcs) -f $(sim_dotf) -f $(sim_top_blackboxes) -f $(sim_harness_blackboxes) -LDFLAGS "$(LDFLAGS)" \ - -CFLAGS "-I$(build_dir) -include $(build_dir)/$(long_name).plusArgs -include $(model_header)" + $(VERILATOR) $(VERILATOR_OPTS) -o $(sim) -Mdir $(model_dir) -CFLAGS "-include $(model_header)" touch $@ -$(model_mk_debug): $(sim_vsrcs) $(sim_dotf) $(INSTALLED_VERILATOR) +$(model_mk_debug): $(sim_vsrcs) $(sim_common_files) $(INSTALLED_VERILATOR) rm -rf $(build_dir)/$(long_name) mkdir -p $(build_dir)/$(long_name).debug - $(VERILATOR) $(VERILATOR_FLAGS) -Mdir $(build_dir)/$(long_name).debug --trace \ - -o $(sim_debug) $(sim_vsrcs) -f $(sim_dotf) -f $(sim_top_blackboxes) -f $(sim_harness_blackboxes) -LDFLAGS "$(LDFLAGS)" \ - -CFLAGS "-I$(build_dir) -include $(build_dir)/$(long_name).plusArgs -include $(model_header_debug)" + $(VERILATOR) $(VERILATOR_OPTS) -o $(sim_debug) --trace -Mdir $(model_dir_debug) -CFLAGS "-include $(model_header_debug)" touch $@ ######################################################################################### # invoke make to make verilator sim rules ######################################################################################### $(sim): $(model_mk) - $(MAKE) VM_PARALLEL_BUILDS=1 -C $(build_dir)/$(long_name) -f V$(VLOG_MODEL).mk + $(MAKE) VM_PARALLEL_BUILDS=1 -C $(model_dir) -f V$(VLOG_MODEL).mk $(sim_debug): $(model_mk_debug) - $(MAKE) VM_PARALLEL_BUILDS=1 -C $(build_dir)/$(long_name).debug -f V$(VLOG_MODEL).mk + $(MAKE) VM_PARALLEL_BUILDS=1 -C $(model_dir_debug) -f V$(VLOG_MODEL).mk ######################################################################################### -# helper rules to run simulator with debug -######################################################################################### -run-binary-debug: $(sim_debug) - $(sim_debug) $(SIM_FLAGS) -v$(sim_out_name).vcd $(BINARY) 3>&1 1>&2 2>&3 | spike-dasm > $(sim_out_name).out - -######################################################################################### -# create a verisim vpd rule +# create a verilator vpd rule ######################################################################################### $(output_dir)/%.vpd: $(output_dir)/% $(sim_debug) rm -f $@.vcd && mkfifo $@.vcd vcd2vpd $@.vcd $@ > /dev/null & - $(sim_debug) -v$@.vcd +max-cycles=$(timeout_cycles) $< + $(sim_debug) $(PERMISSIVE_ON) +max-cycles=$(timeout_cycles) $(SIM_FLAGS) $(VERBOSE_FLAGS) -v$@.vcd $(PERMISSIVE_OFF) $< ######################################################################################### # general cleanup rule ######################################################################################### .PHONY: clean clean: - rm -rf $(gen_dir)/* $(sim_prefix)-* + rm -rf $(gen_dir) $(sim_prefix)-* diff --git a/sims/verisim/verilator.mk b/sims/verilator/verilator.mk similarity index 52% rename from sims/verisim/verilator.mk rename to sims/verilator/verilator.mk index a5c953c1..12ab165d 100644 --- a/sims/verisim/verilator.mk +++ b/sims/verilator/verilator.mk @@ -5,9 +5,10 @@ ######################################################################################### # verilator version, binary, and path ######################################################################################### -VERILATOR_VERSION=4.008 -VERILATOR_SRCDIR=verilator/src/verilator-$(VERILATOR_VERSION) -INSTALLED_VERILATOR=$(abspath verilator/install/bin/verilator) +VERILATOR_VERSION = 4.016 +VERILATOR_INSTALL_DIR ?= verilator_install +VERILATOR_SRCDIR = $(VERILATOR_INSTALL_DIR)/src/verilator-$(VERILATOR_VERSION) +INSTALLED_VERILATOR = $(abspath $(VERILATOR_INSTALL_DIR)/install/bin/verilator) ######################################################################################### # build and install our own verilator to work around versioning issues @@ -15,7 +16,7 @@ INSTALLED_VERILATOR=$(abspath verilator/install/bin/verilator) $(INSTALLED_VERILATOR): $(VERILATOR_SRCDIR)/bin/verilator $(MAKE) -C $(VERILATOR_SRCDIR) installbin installdata touch $@ - + .PHONY: verilator_install: $(INSTALLED_VERILATOR) @@ -25,26 +26,14 @@ $(VERILATOR_SRCDIR)/bin/verilator: $(VERILATOR_SRCDIR)/Makefile $(VERILATOR_SRCDIR)/Makefile: $(VERILATOR_SRCDIR)/configure mkdir -p $(dir $@) - cd $(dir $@) && ./configure --prefix=$(abspath verilator/install) + cd $(dir $@) && ./configure --prefix=$(abspath $(VERILATOR_INSTALL_DIR)/install) -$(VERILATOR_SRCDIR)/configure: verilator/verilator-$(VERILATOR_VERSION).tar.gz +$(VERILATOR_SRCDIR)/configure: $(VERILATOR_INSTALL_DIR)/verilator-$(VERILATOR_VERSION).tar.gz rm -rf $(dir $@) mkdir -p $(dir $@) cat $^ | tar -xz --strip-components=1 -C $(dir $@) touch $@ -verilator/verilator-$(VERILATOR_VERSION).tar.gz: +$(VERILATOR_INSTALL_DIR)/verilator-$(VERILATOR_VERSION).tar.gz: mkdir -p $(dir $@) - wget http://www.veripool.org/ftp/verilator-$(VERILATOR_VERSION).tgz -O $@ - -######################################################################################### -# verilator binary and flags -######################################################################################### -VERILATOR := $(INSTALLED_VERILATOR) --cc --exe -CXXFLAGS := $(CXXFLAGS) -O1 -std=c++11 -I$(RISCV)/include -D__STDC_FORMAT_MACROS -VERILATOR_FLAGS := --top-module $(VLOG_MODEL) \ - +define+PRINTF_COND=\$$c\(\"verbose\",\"\&\&\"\,\"done_reset\"\) \ - +define+STOP_COND=\$$c\(\"done_reset\"\) --assert \ - --output-split 20000 \ - -Wno-STMTDLY --x-assign unique \ - -O3 -CFLAGS "$(CXXFLAGS) -DTEST_HARNESS=V$(VLOG_MODEL) -DVERILATOR" + wget https://www.veripool.org/ftp/verilator-$(VERILATOR_VERSION).tgz -O $@ diff --git a/tests/Makefile b/tests/Makefile index edabb264..80142ad7 100644 --- a/tests/Makefile +++ b/tests/Makefile @@ -3,7 +3,7 @@ OBJDUMP=riscv64-unknown-elf-objdump CFLAGS=-mcmodel=medany -std=gnu99 -O2 -fno-common -fno-builtin-printf -Wall LDFLAGS=-static -nostdlib -nostartfiles -lgcc -PROGRAMS = pwm blkdev accum charcount +PROGRAMS = pwm blkdev accum charcount nic-loopback big-blkdev pingd default: $(addsuffix .riscv,$(PROGRAMS)) diff --git a/tests/big-blkdev.c b/tests/big-blkdev.c new file mode 100644 index 00000000..d065217a --- /dev/null +++ b/tests/big-blkdev.c @@ -0,0 +1,79 @@ +#include +#include + +#include "mmio.h" +#include "blkdev.h" + +#define SECTOR_WORDS (BLKDEV_SECTOR_SIZE / sizeof(uint64_t)) +#define TEST_SECTORS 128 + +unsigned long sector_buf[SECTOR_WORDS]; + +void write_sector(unsigned int secnum) +{ + int req_tag, resp_tag; + + for (int i = 0; i < SECTOR_WORDS; i++) + sector_buf[i] = (secnum << 6) | i; + + while (reg_read8(BLKDEV_NREQUEST) == 0); + req_tag = blkdev_send_request((unsigned long) sector_buf, secnum, 1, 1); + while (reg_read8(BLKDEV_NCOMPLETE) == 0); + resp_tag = reg_read8(BLKDEV_COMPLETE); + + if (req_tag != resp_tag) { + printf("Response tag %d does not match request tag %d\n", + req_tag, resp_tag); + exit(EXIT_FAILURE); + } +} + +void check_sector(unsigned int secnum) +{ + int req_tag, resp_tag; + + while (reg_read8(BLKDEV_NREQUEST) == 0); + req_tag = blkdev_send_request((unsigned long) sector_buf, secnum, 1, 0); + while (reg_read8(BLKDEV_NCOMPLETE) == 0); + resp_tag = reg_read8(BLKDEV_COMPLETE); + + if (req_tag != resp_tag) { + printf("Response tag %d does not match request tag %d\n", + req_tag, resp_tag); + exit(EXIT_FAILURE); + } + + for (int i = 0; i < SECTOR_WORDS; i++) { + unsigned long expected = (secnum << 6) | i; + unsigned long actual = sector_buf[i]; + if (actual != expected) { + printf("Word %d in sector %x does not match expected\n", + i, secnum); + printf("Expected %lx, got %lx\n", + expected, actual); + exit(EXIT_FAILURE); + } + } +} + +int main(void) +{ + unsigned int nsectors = blkdev_nsectors(); + unsigned int stride = nsectors / TEST_SECTORS; + + printf("Writing %u of %u sectors\n", TEST_SECTORS, nsectors); + + for (int i = 0; i < TEST_SECTORS; i++) { + int sector = i * stride; + write_sector(sector); + } + + printf("Checking sectors\n", nsectors); + + for (int i = 0; i < TEST_SECTORS; i++) { + int sector = i * stride; + check_sector(sector); + } + + return 0; +} diff --git a/tests/blkdev.c b/tests/blkdev.c index 7716b46a..994a341b 100644 --- a/tests/blkdev.c +++ b/tests/blkdev.c @@ -2,30 +2,7 @@ #include #include "mmio.h" - -#define BLKDEV_BASE 0x10015000 -#define BLKDEV_ADDR BLKDEV_BASE -#define BLKDEV_OFFSET (BLKDEV_BASE + 8) -#define BLKDEV_LEN (BLKDEV_BASE + 12) -#define BLKDEV_WRITE (BLKDEV_BASE + 16) -#define BLKDEV_REQUEST (BLKDEV_BASE + 17) -#define BLKDEV_NREQUEST (BLKDEV_BASE + 18) -#define BLKDEV_COMPLETE (BLKDEV_BASE + 19) -#define BLKDEV_NCOMPLETE (BLKDEV_BASE + 20) -#define BLKDEV_NSECTORS (BLKDEV_BASE + 24) -#define BLKDEV_MAX_REQUEST_LENGTH (BLKDEV_BASE + 28) -#define BLKDEV_SECTOR_SIZE 512 -#define BLKDEV_SECTOR_SHIFT 9 - -size_t blkdev_nsectors(void) -{ - return reg_read32(BLKDEV_NSECTORS); -} - -size_t blkdev_max_req_len(void) -{ - return reg_read32(BLKDEV_MAX_REQUEST_LENGTH); -} +#include "blkdev.h" void blkdev_read(void *addr, unsigned long offset, size_t nsectors) { @@ -38,12 +15,9 @@ void blkdev_read(void *addr, unsigned long offset, size_t nsectors) printf("sending %d reads\n", ntags); for (i = 0; i < ntags; i++) { - reg_write64(BLKDEV_ADDR, (unsigned long) addr); - reg_write32(BLKDEV_OFFSET, offset); - reg_write32(BLKDEV_LEN, nsectors_per_tag); - reg_write8(BLKDEV_WRITE, 0); - - req_tag = reg_read8(BLKDEV_REQUEST); + req_tag = blkdev_send_request( + (unsigned long) addr, offset, + nsectors_per_tag, 0); addr += (nsectors_per_tag << BLKDEV_SECTOR_SHIFT); offset += nsectors_per_tag; } @@ -67,12 +41,9 @@ void blkdev_write(unsigned long offset, void *addr, size_t nsectors) printf("sending %d writes\n", ntags); for (i = 0; i < ntags; i++) { - reg_write64(BLKDEV_ADDR, (unsigned long) addr); - reg_write32(BLKDEV_OFFSET, offset); - reg_write32(BLKDEV_LEN, nsectors_per_tag); - reg_write8(BLKDEV_WRITE, 1); - - req_tag = reg_read8(BLKDEV_REQUEST); + req_tag = blkdev_send_request( + (unsigned long) addr, offset, + nsectors_per_tag, 1); addr += (nsectors_per_tag << BLKDEV_SECTOR_SHIFT); offset += nsectors_per_tag; } diff --git a/tests/blkdev.h b/tests/blkdev.h new file mode 100644 index 00000000..be7ec064 --- /dev/null +++ b/tests/blkdev.h @@ -0,0 +1,38 @@ +#define BLKDEV_BASE 0x10015000 +#define BLKDEV_ADDR BLKDEV_BASE +#define BLKDEV_OFFSET (BLKDEV_BASE + 8) +#define BLKDEV_LEN (BLKDEV_BASE + 12) +#define BLKDEV_WRITE (BLKDEV_BASE + 16) +#define BLKDEV_REQUEST (BLKDEV_BASE + 17) +#define BLKDEV_NREQUEST (BLKDEV_BASE + 18) +#define BLKDEV_COMPLETE (BLKDEV_BASE + 19) +#define BLKDEV_NCOMPLETE (BLKDEV_BASE + 20) +#define BLKDEV_NSECTORS (BLKDEV_BASE + 24) +#define BLKDEV_MAX_REQUEST_LENGTH (BLKDEV_BASE + 28) +#define BLKDEV_SECTOR_SIZE 512 +#define BLKDEV_SECTOR_SHIFT 9 + +static inline size_t blkdev_nsectors(void) +{ + return reg_read32(BLKDEV_NSECTORS); +} + +static inline size_t blkdev_max_req_len(void) +{ + return reg_read32(BLKDEV_MAX_REQUEST_LENGTH); +} + +static inline unsigned int blkdev_send_request( + unsigned long addr, + unsigned int offset, + unsigned int len, + unsigned char write) +{ + reg_write64(BLKDEV_ADDR, addr); + reg_write32(BLKDEV_OFFSET, offset); + reg_write32(BLKDEV_LEN, len); + reg_write8(BLKDEV_WRITE, write); + + asm volatile ("fence"); + return reg_read8(BLKDEV_REQUEST); +} diff --git a/tests/nic-loopback.c b/tests/nic-loopback.c new file mode 100644 index 00000000..1d3c7b96 --- /dev/null +++ b/tests/nic-loopback.c @@ -0,0 +1,98 @@ +#include "mmio.h" +#include +#include +#include + +#include "nic.h" +#include "encoding.h" + +#define NPACKETS 10 +#define TEST_OFFSET 3 +#define TEST_LEN 356 +#define ARRAY_LEN 360 +#define NTRIALS 3 + +uint32_t src[NPACKETS][ARRAY_LEN]; +uint32_t dst[NPACKETS][ARRAY_LEN]; +uint64_t lengths[NPACKETS]; + +static inline void send_recv() +{ + uint64_t send_packet, recv_addr; + int ncomps, send_comps_left = NPACKETS, recv_comps_left = NPACKETS; + int recv_idx = 0; + + for (int i = 0; i < NPACKETS; i++) { + uint64_t pkt_size = TEST_LEN * sizeof(uint32_t); + uint64_t src_addr = (uint64_t) &src[i][TEST_OFFSET]; + send_packet = (pkt_size << 48) | src_addr; + recv_addr = (uint64_t) dst[i]; + reg_write64(SIMPLENIC_SEND_REQ, send_packet); + reg_write64(SIMPLENIC_RECV_REQ, recv_addr); + } + + while (send_comps_left > 0 || recv_comps_left > 0) { + ncomps = nic_send_comp_avail(); + asm volatile ("fence"); + for (int i = 0; i < ncomps; i++) + reg_read16(SIMPLENIC_SEND_COMP); + send_comps_left -= ncomps; + + ncomps = nic_recv_comp_avail(); + asm volatile ("fence"); + for (int i = 0; i < ncomps; i++) { + lengths[recv_idx] = reg_read16(SIMPLENIC_RECV_COMP); + recv_idx++; + } + recv_comps_left -= ncomps; + } +} + +void run_test(void) +{ + unsigned long start, end; + int i, j; + + memset(dst, 0, sizeof(dst)); + asm volatile ("fence"); + + start = rdcycle(); + send_recv(); + end = rdcycle(); + + printf("send/recv %lu cycles\n", end - start); + + for (i = 0; i < NPACKETS; i++) { + if (lengths[i] != TEST_LEN * sizeof(uint32_t)) { + printf("recv got wrong # bytes\n"); + exit(EXIT_FAILURE); + } + + for (j = 0; j < TEST_LEN; j++) { + if (dst[i][j] != src[i][j + TEST_OFFSET]) { + printf("Data mismatch @ %d, %d: %x != %x\n", + i, j, dst[i][j], src[i][j + TEST_OFFSET]); + exit(EXIT_FAILURE); + } + } + } +} + +int main(void) +{ + int i, j; + + for (i = 0; i < NPACKETS; i++) { + for (j = 0; j < ARRAY_LEN; j++) + src[i][j] = i * ARRAY_LEN + j; + } + + for (i = 0; i < NTRIALS; i++) { + printf("Trial %d\n", i); + run_test(); + } + + printf("All correct\n"); + + return 0; +} diff --git a/tests/nic.h b/tests/nic.h index 55a86a2d..bee4c395 100644 --- a/tests/nic.h +++ b/tests/nic.h @@ -8,22 +8,22 @@ static inline int nic_send_req_avail(void) { - return reg_read16(SIMPLENIC_COUNTS) & 0xf; + return reg_read32(SIMPLENIC_COUNTS) & 0xff; } static inline int nic_recv_req_avail(void) { - return (reg_read16(SIMPLENIC_COUNTS) >> 4) & 0xf; + return (reg_read32(SIMPLENIC_COUNTS) >> 8) & 0xff; } static inline int nic_send_comp_avail(void) { - return (reg_read16(SIMPLENIC_COUNTS) >> 8) & 0xf; + return (reg_read32(SIMPLENIC_COUNTS) >> 16) & 0xff; } static inline int nic_recv_comp_avail(void) { - return (reg_read16(SIMPLENIC_COUNTS) >> 12) & 0xf; + return (reg_read32(SIMPLENIC_COUNTS) >> 24) & 0xff; } static void nic_send(void *data, unsigned long len) diff --git a/tests/pingd.c b/tests/pingd.c new file mode 100644 index 00000000..9e02cafe --- /dev/null +++ b/tests/pingd.c @@ -0,0 +1,254 @@ +#include "mmio.h" +#include "nic.h" + +#include +#include +#include +#include + +#define ETH_MAX_WORDS 190 +#define NET_IP_ALIGN 2 +#define ETH_HEADER_SIZE 14 +#define MAC_ADDR_SIZE 6 +#define IP_ADDR_SIZE 4 + +#define IPV4_ETHTYPE 0x0800 +#define ARP_ETHTYPE 0x0806 +#define ICMP_PROT 1 +#define ECHO_REPLY 0 +#define ECHO_REQUEST 8 +#define ARP_REQUEST 1 +#define ARP_REPLY 2 +#define HTYPE_ETH 1 + +static inline uint16_t ntohs(uint16_t nint) +{ + return ((nint & 0xff) << 8) | ((nint >> 8) & 0xff); +} + +static inline uint16_t htons(uint16_t nint) +{ + return ntohs(nint); +} + +struct eth_header { + uint8_t padding[NET_IP_ALIGN]; + uint8_t dst_mac[MAC_ADDR_SIZE]; + uint8_t src_mac[MAC_ADDR_SIZE]; + uint16_t ethtype; +}; + +struct arp_header { + uint16_t htype; + uint16_t ptype; + uint8_t hlen; + uint8_t plen; + uint16_t oper; + uint8_t sha[MAC_ADDR_SIZE]; + uint8_t spa[IP_ADDR_SIZE]; + uint8_t tha[MAC_ADDR_SIZE]; + uint8_t tpa[IP_ADDR_SIZE]; +}; + +struct ipv4_header { + uint8_t ver_ihl; + uint8_t dscp_ecn; + uint16_t length; + uint16_t ident; + uint16_t flags_frag_off; + uint8_t ttl; + uint8_t prot; + uint16_t cksum; + uint32_t src_addr; + uint32_t dst_addr; +}; + +struct icmp_header { + uint8_t type; + uint8_t code; + uint16_t cksum; + uint32_t rest; +}; + +static int checksum(uint16_t *data, int len) +{ + int i; + uint32_t sum = 0; + + for (i = 0; i < len; i++) + sum += ntohs(data[i]); + + while ((sum >> 16) != 0) + sum = (sum & 0xffff) + (sum >> 16); + + sum = ~sum & 0xffff; + + return sum; +} + +#define ceil_div(n, d) (((n) - 1) / (d) + 1) + +static int process_arp(void *buf, uint8_t *mac) +{ + struct eth_header *eth = buf; + struct arp_header *arp; + size_t size = ETH_HEADER_SIZE + sizeof(*arp); + uint8_t tmp_addr[IP_ADDR_SIZE]; + + // Verify arp packet + arp = buf + sizeof(*eth); + if (ntohs(arp->oper) != ARP_REQUEST) { + printf("Wrong arp operation: %d\n", ntohs(arp->oper)); + return -1; + } + + if (ntohs(arp->htype) != HTYPE_ETH) { + printf("Wrong ARP HTYPE\n"); + return -1; + } + + if (ntohs(arp->ptype) != IPV4_ETHTYPE) { + printf("Wrong ARP PTYPE\n"); + return -1; + } + + if (arp->hlen != 6) { + printf("Wrong ARP HLEN: %d\n", arp->hlen); + return -1; + } + + if (arp->plen != 4) { + printf("Wrong ARP PLEN: %d\n", arp->plen); + return -1; + } + + // Make the source the destination, and add our mac address + memcpy(eth->dst_mac, eth->src_mac, MAC_ADDR_SIZE); + memcpy(eth->src_mac, mac, MAC_ADDR_SIZE); + + // create ARP reply + arp->oper = htons(ARP_REPLY); + + // Make tha the sha, and fill in sha with actual mac address + memcpy(arp->tha, arp->sha, MAC_ADDR_SIZE); + memcpy(arp->sha, mac, MAC_ADDR_SIZE); + + // Swap spa and tpa in arp packet + memcpy(tmp_addr, arp->tpa, IP_ADDR_SIZE); + memcpy(arp->tpa, arp->spa, IP_ADDR_SIZE); + memcpy(arp->spa, tmp_addr, IP_ADDR_SIZE); + + size = ceil_div(size + NET_IP_ALIGN, 8) * 8; + nic_send(buf, size); + + return 0; +} +static int process_icmp(void *buf, uint8_t *mac) +{ + struct eth_header *eth = buf; + struct ipv4_header *ipv4; + struct icmp_header *icmp; + int ihl, icmp_size; + ssize_t size; + uint32_t tmp_addr; + + // verify IPv4 + ipv4 = buf + sizeof(*eth); + ihl = ipv4->ver_ihl & 0xf; + + if (checksum((uint16_t *) ipv4, ihl << 1) != 0) { + printf("Bad IP header checksum %04x\n", ipv4->cksum); + return -1; + } + + if (ipv4->prot != ICMP_PROT) { + printf("Wrong IP protocol %d\n", ipv4->prot); + return -1; + } + + // verify ICMP + icmp = (buf + sizeof(*eth) + (ihl << 2)); + + if (icmp->type != ECHO_REQUEST) { + printf("Wrong ICMP type %d\n", icmp->type); + return -1; + } + + if (icmp->code != 0) { + printf("Wrong ICMP code %d\n", icmp->code); + return -1; + } + + icmp_size = ntohs(ipv4->length) - (ihl << 2); + if (checksum((uint16_t *) icmp, icmp_size >> 1) != 0) { + printf("Bad ICMP checksum %04x\n", icmp->cksum); + return -1; + } + + // Set the destination and source MACs + memcpy(eth->dst_mac, eth->src_mac, MAC_ADDR_SIZE); + memcpy(eth->src_mac, mac, MAC_ADDR_SIZE); + + // Swap the source and destination IP addresses + tmp_addr = ipv4->dst_addr; + ipv4->dst_addr = ipv4->src_addr; + ipv4->src_addr = tmp_addr; + + // compute the IPv4 header checksum + ipv4->cksum = 0; + ipv4->cksum = htons(checksum((uint16_t *) ipv4, ihl << 1)); + + // set the ICMP type to reply and compute checksum + icmp->cksum = 0; + icmp->type = ECHO_REPLY; + icmp->cksum = htons(checksum((uint16_t *) icmp, icmp_size >> 1)); + size = ntohs(ipv4->length) + ETH_HEADER_SIZE; + + size = ceil_div(size + NET_IP_ALIGN, 8) * 8; + nic_send(buf, size); + + return 0; +} + +static int process_packet(void *buf, uint8_t *mac) +{ + struct eth_header *eth; + + // read the ICMP request + nic_recv(buf); + eth = buf; + printf("Got packet: [ethtype=%04x]\n", ntohs(eth->ethtype)); + // Check ethernet type + switch (ntohs(eth->ethtype)) { + case IPV4_ETHTYPE: + return process_icmp(buf, mac); + case ARP_ETHTYPE: + return process_arp(buf, mac); + default: + printf("Wrong ethtype %x\n", ntohs(eth->ethtype)); + return -1; + } +} + +uint64_t buffer[ETH_MAX_WORDS]; + +int main(void) +{ + uint64_t macaddr_long; + uint8_t *macaddr; + + macaddr_long = nic_macaddr(); + macaddr = (uint8_t *) &macaddr_long; + + printf("macaddr - %02x", macaddr[0]); + for (int i = 1; i < MAC_ADDR_SIZE; i++) + printf(":%02x", macaddr[i]); + printf("\n"); + + for (;;) { + if (process_packet(buffer, macaddr)) + return -1; + } + + return 0; +} diff --git a/tools/barstools b/tools/barstools index 82636b3f..26096e07 160000 --- a/tools/barstools +++ b/tools/barstools @@ -1 +1 @@ -Subproject commit 82636b3ff43ecf6a0f0a7d46ebc2456b31e9703f +Subproject commit 26096e07f6ce3e12b2114132c2859ef56fb0cfaf diff --git a/tools/firrtl b/tools/firrtl index 99ae1d66..84a1c7b1 160000 --- a/tools/firrtl +++ b/tools/firrtl @@ -1 +1 @@ -Subproject commit 99ae1d6649f1731c5dec2098b10733735232b72c +Subproject commit 84a1c7b1f7311ce036cb7d3d5eb652466b87dce4 diff --git a/variables.mk b/variables.mk index f3fc05b1..66eb0518 100644 --- a/variables.mk +++ b/variables.mk @@ -29,7 +29,7 @@ SUB_PROJECT ?= example ifeq ($(SUB_PROJECT),example) SBT_PROJECT ?= example - MODEL ?= BoomRocketTestHarness + MODEL ?= TestHarness VLOG_MODEL ?= TestHarness MODEL_PACKAGE ?= $(SBT_PROJECT) CONFIG ?= DefaultRocketConfig @@ -38,21 +38,9 @@ ifeq ($(SUB_PROJECT),example) TB ?= TestDriver TOP ?= BoomRocketTop endif -# for BOOM developers -ifeq ($(SUB_PROJECT),boom) - SBT_PROJECT ?= boom - MODEL ?= TestHarness - VLOG_MODEL ?= TestHarness - MODEL_PACKAGE ?= boom.system - CONFIG ?= BoomConfig - CONFIG_PACKAGE ?= boom.system - GENERATOR_PACKAGE ?= boom.system - TB ?= TestDriver - TOP ?= ExampleBoomAndRocketSystem -endif # for Rocket-chip developers ifeq ($(SUB_PROJECT),rocketchip) - SBT_PROJECT ?= rebarrocketchip + SBT_PROJECT ?= rocketchip MODEL ?= TestHarness VLOG_MODEL ?= TestHarness MODEL_PACKAGE ?= freechips.rocketchip.system @@ -74,13 +62,26 @@ ifeq ($(SUB_PROJECT),hwacha) TB ?= TestDriver TOP ?= ExampleRocketSystem endif +# Stand-in firechip variables: +# TODO: need a seperate generator and test harnesses for each target +#ifeq ($(SUB_PROJECT),firechip) +# SBT_PROJECT ?= $(SUB_PROJECT) +# MODEL ?= TestHarness +# VLOG_MODEL ?= TestHarness +# MODEL_PACKAGE ?= freechips.rocketchip.system +# CONFIG ?= FireSimRocketChipConfig +# CONFIG_PACKAGE ?= firesim.firesim +# GENERATOR_PACKAGE ?= firesim.firesim +# TB ?= TestDriver +# TOP ?= FireSimNoNIC +#endif ######################################################################################### # path to rocket-chip and testchipip ######################################################################################### -ROCKETCHIP_DIR = $(base_dir)/generators/rocket-chip -TESTCHIP_DIR = $(base_dir)/generators/testchipip -REBAR_FIRRTL_DIR = $(base_dir)/tools/firrtl +ROCKETCHIP_DIR = $(base_dir)/generators/rocket-chip +TESTCHIP_DIR = $(base_dir)/generators/testchipip +CHIPYARD_FIRRTL_DIR = $(base_dir)/tools/firrtl ######################################################################################### # names of various files needed to compile and run things @@ -95,23 +96,27 @@ ifeq ($(GENERATOR_PACKAGE),hwacha) long_name=$(MODEL_PACKAGE).$(CONFIG) endif -FIRRTL_FILE ?= $(build_dir)/$(long_name).fir -ANNO_FILE ?= $(build_dir)/$(long_name).anno.json -VERILOG_FILE ?= $(build_dir)/$(long_name).top.v -TOP_FIR ?= $(build_dir)/$(long_name).top.fir -TOP_ANNO ?= $(build_dir)/$(long_name).top.anno.json +FIRRTL_FILE ?= $(build_dir)/$(long_name).fir +ANNO_FILE ?= $(build_dir)/$(long_name).anno.json + +TOP_FILE ?= $(build_dir)/$(long_name).top.v +TOP_FIR ?= $(build_dir)/$(long_name).top.fir +TOP_ANNO ?= $(build_dir)/$(long_name).top.anno.json +TOP_SMEMS_FILE ?= $(build_dir)/$(long_name).top.mems.v +TOP_SMEMS_CONF ?= $(build_dir)/$(long_name).top.mems.conf +TOP_SMEMS_FIR ?= $(build_dir)/$(long_name).top.mems.fir + HARNESS_FILE ?= $(build_dir)/$(long_name).harness.v HARNESS_FIR ?= $(build_dir)/$(long_name).harness.fir HARNESS_ANNO ?= $(build_dir)/$(long_name).harness.anno.json HARNESS_SMEMS_FILE ?= $(build_dir)/$(long_name).harness.mems.v HARNESS_SMEMS_CONF ?= $(build_dir)/$(long_name).harness.mems.conf HARNESS_SMEMS_FIR ?= $(build_dir)/$(long_name).harness.mems.fir -SMEMS_FILE ?= $(build_dir)/$(long_name).mems.v -SMEMS_CONF ?= $(build_dir)/$(long_name).mems.conf -SMEMS_FIR ?= $(build_dir)/$(long_name).mems.fir -sim_dotf ?= $(build_dir)/sim_files.f -sim_harness_blackboxes ?= $(build_dir)/firrtl_black_box_resource_files.harness.f -sim_top_blackboxes ?= $(build_dir)/firrtl_black_box_resource_files.top.f + +sim_files ?= $(build_dir)/sim_files.f +sim_top_blackboxes ?= $(build_dir)/firrtl_black_box_resource_files.top.f +sim_harness_blackboxes ?= $(build_dir)/firrtl_black_box_resource_files.harness.f +sim_common_files ?= $(build_dir)/sim_files.common.f ######################################################################################### # java arguments used in sbt @@ -135,7 +140,8 @@ output_dir=$(sim_dir)/output/$(long_name) # helper variables to run binaries ######################################################################################### BINARY ?= -SIM_FLAGS ?= +max-cycles=$(timeout_cycles) +SIM_FLAGS ?= +VERBOSE_FLAGS ?= +verbose sim_out_name = $(notdir $(basename $(BINARY))).$(long_name) ######################################################################################### @@ -153,9 +159,9 @@ rocketchip_vsrc_dir = $(ROCKETCHIP_DIR)/src/main/resources/vsrc # sources needed to run simulators ######################################################################################### sim_vsrcs = \ - $(VERILOG_FILE) \ + $(TOP_FILE) \ $(HARNESS_FILE) \ - $(SMEMS_FILE) \ + $(TOP_SMEMS_FILE) \ $(HARNESS_SMEMS_FILE) ######################################################################################### diff --git a/vlsi/.gitignore b/vlsi/.gitignore new file mode 100644 index 00000000..4cbcfe8f --- /dev/null +++ b/vlsi/.gitignore @@ -0,0 +1,6 @@ +inputs.yml +__pycache__ +hammer*.log +build +src/test/output-*.json +generated-src \ No newline at end of file diff --git a/vlsi/Makefile b/vlsi/Makefile new file mode 100644 index 00000000..519d1448 --- /dev/null +++ b/vlsi/Makefile @@ -0,0 +1,107 @@ +######################################################################################### +# vlsi makefile +######################################################################################### + +######################################################################################### +# general path variables +######################################################################################### +base_dir=$(abspath ..) +vlsi_dir=$(abspath .) +sim_dir=$(abspath .) + +######################################################################################### +# include shared variables +######################################################################################### +include $(base_dir)/variables.mk + +######################################################################################### +# vlsi types and rules +######################################################################################### +sim_name ?= vcs # needed for GenerateSimFiles, but is unused +tech_name ?= +tech_dir ?= $(vlsi_dir)/hammer-$(tech_name)-plugin/$(tech_name) +SMEMS_COMP ?= $(tech_dir)/sram-compiler.json +SMEMS_CACHE ?= $(tech_dir)/sram-cache.json +SMEMS_HAMMER ?= $(build_dir)/$(long_name).mems.hammer.json +MACROCOMPILER_MODE ?= -l $(SMEMS_CACHE) -hir $(SMEMS_HAMMER) +OBJ_DIR ?= $(vlsi_dir)/build +ENV_YML ?= $(vlsi_dir)/bwrc-env.yml +INPUT_CONFS ?= example.yml $(dir $(tech_dir))/bwrc.yml +HAMMER_EXEC ?= ./example-vlsi + +######################################################################################### +# general rules +######################################################################################### +ALL_RTL = $(TOP_FILE) $(TOP_SMEMS_FILE) $(extra_v_includes) +extra_v_includes = $(build_dir)/EICG_wrapper.v + +.PHONY: default verilog +default: all + +all: drc lvs + +verilog: $(ALL_RTL) + +######################################################################################### +# import other necessary rules and variables +######################################################################################### +include $(base_dir)/common.mk + +######################################################################################### +# srams +######################################################################################### +SRAM_GENERATOR_CONF = $(build_dir)/sram_generator-input.yml +SRAM_CONF=$(build_dir)/sram_generator-output.json + +## SRAM Generator +.PHONY: sram_generator srams +srams: sram_generator +sram_generator: $(SRAM_CONF) + +# This should be built alongside $(SMEMS_FILE) +$(SMEMS_HAMMER): $(SMEMS_FILE) + +$(SRAM_GENERATOR_CONF): $(SMEMS_HAMMER) + mkdir -p $(dir $@) + echo "vlsi.inputs.sram_parameters: '$(SMEMS_HAMMER)'" >> $@ + echo "vlsi.inputs.sram_parameters_meta: [\"transclude\", \"json2list\"]">> $@ + +$(SRAM_CONF): $(SRAM_GENERATOR_CONF) + cd $(vlsi_dir) && $(HAMMER_EXEC) -e $(ENV_YML) $(foreach x,$(INPUT_CONFS) $(SRAM_GENERATOR_CONF), -p $(x)) --obj_dir $(build_dir) sram_generator + cd $(vlsi_dir) && cp output.json $@ + +######################################################################################### +# synthesis input configuration +######################################################################################### +SYN_CONF = $(OBJ_DIR)/inputs.yml +GENERATED_CONFS = $(SYN_CONF) $(SRAM_CONF) + +$(SYN_CONF): $(ALL_RTL) $(extra_v_includes) $(sim_top_blackboxes) + mkdir -p $(dir $@) + echo "synthesis.inputs:" > $@ + echo " top_module: $(TOP)" >> $@ + echo " input_files:" >> $@ + for x in $(ALL_RTL) $(extra_v_includes) `cat $(sim_top_blackboxes)`; do \ + echo ' - "'$$x'"' >> $@; \ + done + +######################################################################################### +# AUTO BUILD FLOW +######################################################################################### + +.PHONY: buildfile +buildfile: $(OBJ_DIR)/hammer.d +# Tip: Set HAMMER_D_DEPS to an empty string to avoid unnecessary RTL rebuilds +# TODO: make this dependency smarter so that we don't need this at all +HAMMER_D_DEPS ?= $(GENERATED_CONFS) +$(OBJ_DIR)/hammer.d: $(HAMMER_D_DEPS) + $(HAMMER_EXEC) -e $(ENV_YML) $(foreach x,$(INPUT_CONFS) $(GENERATED_CONFS), -p $(x)) --obj_dir $(OBJ_DIR) build + +-include $(OBJ_DIR)/hammer.d + +######################################################################################### +# general cleanup rule +######################################################################################### +.PHONY: clean +clean: + rm -rf $(OBJ_DIR) hammer-vlsi*.log __pycache__ output.json $(GENERATED_CONFS) $(gen_dir) diff --git a/vlsi/README.md b/vlsi/README.md new file mode 100644 index 00000000..aa07dd0f --- /dev/null +++ b/vlsi/README.md @@ -0,0 +1,9 @@ +This is the starting point for a vlsi flow from this repository. + +This flow will not work without the necessary CAD and technology plugins for HAMMER. + +If you are a UCB-affiliate, you may be able to acquire access to the tech-plugins. + +# Initial Setup Instructions (For All technologies) +Run the `init-vlsi.sh` script to pull correct versions of hammer, hammer-cad-plugins, and the hammer-tech-plugins +```scripts/init-vlsi.sh TECH_NAME``` \ No newline at end of file diff --git a/vlsi/example-vlsi b/vlsi/example-vlsi new file mode 100755 index 00000000..3f65d9a5 --- /dev/null +++ b/vlsi/example-vlsi @@ -0,0 +1,19 @@ +#!/usr/bin/env python3 + +import hammer_vlsi +from hammer_vlsi import CLIDriver, HammerToolHookAction + +from typing import Dict, Callable, Optional, List + +def example_place_tap_cells(x: hammer_vlsi.HammerTool) -> bool: + x.append(''' +# TODO +''') + return True + +class ExampleDriver(CLIDriver): + def get_extra_par_hooks(self) -> List[HammerToolHookAction]: + return [hammer_vlsi.HammerTool.make_replacement_hook("place_tap_cells", example_place_tap_cells)] + +if __name__ == '__main__': + ExampleDriver().main() diff --git a/vlsi/hammer b/vlsi/hammer new file mode 160000 index 00000000..a27886fb --- /dev/null +++ b/vlsi/hammer @@ -0,0 +1 @@ +Subproject commit a27886fb42c121f3ba5f684acaf5856b2ec293e1 diff --git a/vlsi/hammer-cad-plugins b/vlsi/hammer-cad-plugins new file mode 160000 index 00000000..72809f53 --- /dev/null +++ b/vlsi/hammer-cad-plugins @@ -0,0 +1 @@ +Subproject commit 72809f538c4bbe91c103de52e92baad9df6d8f9a