Merge remote-tracking branch 'upstream/main' into graphics

This commit is contained in:
Hansung Kim
2023-07-22 14:45:48 -07:00
175 changed files with 5277 additions and 4019 deletions

View File

@@ -10,8 +10,8 @@ runs:
else
echo "Creating a conda environment for each toolchain with the toolchain installed"
conda activate base
conda-lock install -n ${{ env.conda-env-name-no-time }}-$(date --date "${{ env.workflow-timestamp }}" +%Y%m%d)-riscv-tools ./conda-reqs/conda-lock-reqs/conda-requirements-riscv-tools-linux-64.conda-lock.yml
conda-lock install -n ${{ env.conda-env-name-no-time }}-$(date --date "${{ env.workflow-timestamp }}" +%Y%m%d)-esp-tools ./conda-reqs/conda-lock-reqs/conda-requirements-esp-tools-linux-64.conda-lock.yml
conda-lock install --conda $(which conda) -n ${{ env.conda-env-name-no-time }}-$(date --date "${{ env.workflow-timestamp }}" +%Y%m%d)-riscv-tools ./conda-reqs/conda-lock-reqs/conda-requirements-riscv-tools-linux-64.conda-lock.yml
conda-lock install --conda $(which conda) -n ${{ env.conda-env-name-no-time }}-$(date --date "${{ env.workflow-timestamp }}" +%Y%m%d)-esp-tools ./conda-reqs/conda-lock-reqs/conda-requirements-esp-tools-linux-64.conda-lock.yml
conda deactivate
echo "Add extra toolchain collateral to RISC-V install area"

View File

@@ -45,7 +45,7 @@ search () {
done
}
submodules=("cva6" "boom" "ibex" "gemmini" "hwacha" "icenet" "nvdla" "rocket-chip" "sha3" "sifive-blocks" "sifive-cache" "testchipip" "riscv-sodor" "mempress")
submodules=("cva6" "boom" "ibex" "gemmini" "hwacha" "icenet" "nvdla" "rocket-chip" "sha3" "sifive-blocks" "sifive-cache" "testchipip" "riscv-sodor" "mempress" "bar-fetchers" "shuttle")
dir="generators"
branches=("master" "main" "dev")
search
@@ -91,11 +91,6 @@ dir="tools"
branches=("master" "dev")
search
submodules=("firesim")
dir="sims"
branches=("master" "main" "dev" "1.13.x")
search
submodules=("fpga-shells")
dir="fpga"
branches=("main")

View File

@@ -28,37 +28,42 @@ REMOTE_COURSIER_CACHE=$REMOTE_WORK_DIR/.coursier-cache
# key value store to get the build groups
declare -A grouping
grouping["group-cores"]="chipyard-cva6 chipyard-ibex chipyard-rocket chipyard-hetero chipyard-boom chipyard-sodor chipyard-digitaltop chipyard-multiclock-rocket chipyard-nomem-scratchpad chipyard-spike chipyard-clone"
grouping["group-peripherals"]="chipyard-dmirocket chipyard-spiflashwrite chipyard-mmios chipyard-nocores chipyard-manyperipherals chipyard-chiplike"
grouping["group-accels"]="chipyard-mempress chipyard-sha3 chipyard-hwacha chipyard-gemmini chipyard-manymmioaccels"
grouping["group-cores"]="chipyard-cva6 chipyard-ibex chipyard-rocket chipyard-hetero chipyard-boom chipyard-sodor chipyard-digitaltop chipyard-multiclock-rocket chipyard-nomem-scratchpad chipyard-spike chipyard-clone chipyard-prefetchers chipyard-shuttle"
grouping["group-peripherals"]="chipyard-dmirocket chipyard-dmiboom chipyard-spiflashwrite chipyard-mmios chipyard-nocores chipyard-manyperipherals chipyard-chiplike chipyard-tethered"
grouping["group-accels"]="chipyard-mempress chipyard-sha3 chipyard-hwacha chipyard-gemmini chipyard-manymmioaccels chipyard-nvdla"
grouping["group-constellation"]="chipyard-constellation"
grouping["group-tracegen"]="tracegen tracegen-boom"
grouping["group-other"]="icenet testchipip constellation"
grouping["group-other"]="icenet testchipip constellation rocketchip-amba rocketchip-tlsimple rocketchip-tlwidth rocketchip-tlxbar"
grouping["group-fpga"]="arty vcu118 vc707"
# key value store to get the build strings
declare -A mapping
mapping["chipyard-rocket"]=""
mapping["chipyard-rocket"]=" CONFIG=QuadChannelRocketConfig"
mapping["chipyard-dmirocket"]=" CONFIG=dmiRocketConfig"
mapping["chipyard-sha3"]=" CONFIG=Sha3RocketConfig"
mapping["chipyard-mempress"]=" CONFIG=MempressRocketConfig"
mapping["chipyard-prefetchers"]=" CONFIG=PrefetchingRocketConfig"
mapping["chipyard-digitaltop"]=" TOP=DigitalTop"
mapping["chipyard-manymmioaccels"]=" CONFIG=ManyMMIOAcceleratorRocketConfig"
mapping["chipyard-nvdla"]=" CONFIG=SmallNVDLARocketConfig verilog"
mapping["chipyard-hetero"]=" CONFIG=LargeBoomAndRocketConfig"
mapping["chipyard-boom"]=" CONFIG=MediumBoomCosimConfig"
mapping["chipyard-spike"]=" CONFIG=SpikeFastUARTConfig EXTRA_SIM_FLAGS='+spike-ipc=10'"
mapping["chipyard-dmiboom"]=" CONFIG=dmiMediumBoomCosimConfig"
mapping["chipyard-spike"]=" CONFIG=SpikeConfig EXTRA_SIM_FLAGS='+spike-ipc=10'"
mapping["chipyard-hwacha"]=" CONFIG=HwachaRocketConfig"
mapping["chipyard-gemmini"]=" CONFIG=GemminiRocketConfig"
mapping["chipyard-cva6"]=" CONFIG=CVA6Config"
mapping["chipyard-ibex"]=" CONFIG=IbexConfig"
mapping["chipyard-spiflashwrite"]=" CONFIG=SmallSPIFlashRocketConfig EXTRA_SIM_FLAGS='+spiflash0=${LOCAL_CHIPYARD_DIR}/tests/spiflash.img'"
mapping["chipyard-manyperipherals"]=" CONFIG=ManyPeripheralsRocketConfig EXTRA_SIM_FLAGS='+spiflash0=${LOCAL_CHIPYARD_DIR}/tests/spiflash.img'"
mapping["chipyard-chiplike"]=" CONFIG=ChipLikeQuadRocketConfig MODEL=FlatTestHarness MODEL_PACKAGE=chipyard.example verilog"
mapping["chipyard-chiplike"]=" CONFIG=ChipLikeRocketConfig MODEL=FlatTestHarness MODEL_PACKAGE=chipyard.example verilog"
mapping["chipyard-tethered"]=" CONFIG=VerilatorCITetheredChipLikeRocketConfig"
mapping["chipyard-cloneboom"]=" CONFIG=Cloned64MegaBoomConfig verilog"
mapping["chipyard-nocores"]=" CONFIG=NoCoresConfig verilog"
mapping["tracegen"]=" CONFIG=NonBlockingTraceGenL2Config"
mapping["tracegen-boom"]=" CONFIG=BoomTraceGenConfig"
mapping["chipyard-sodor"]=" CONFIG=Sodor5StageConfig"
mapping["chipyard-shuttle"]=" CONFIG=ShuttleConfig"
mapping["chipyard-multiclock-rocket"]=" CONFIG=MulticlockRocketConfig"
mapping["chipyard-nomem-scratchpad"]=" CONFIG=MMIOScratchpadOnlyRocketConfig"
mapping["chipyard-constellation"]=" CONFIG=SharedNoCConfig"
@@ -68,6 +73,10 @@ mapping["firesim"]="SCALA_TEST=firesim.firesim.RocketNICF1Tests"
mapping["fireboom"]="SCALA_TEST=firesim.firesim.BoomF1Tests"
mapping["icenet"]="SUB_PROJECT=icenet"
mapping["testchipip"]="SUB_PROJECT=testchipip"
mapping["rocketchip-amba"]="SUB_PROJECT=rocketchip CONFIG=AMBAUnitTestConfig"
mapping["rocketchip-tlsimple"]="SUB_PROJECT=rocketchip CONFIG=TLSimpleUnitTestConfig"
mapping["rocketchip-tlwidth"]="SUB_PROJECT=rocketchip CONFIG=TLWidthUnitTestConfig"
mapping["rocketchip-tlxbar"]="SUB_PROJECT=rocketchip CONFIG=TLXbarUnitTestConfig"
mapping["arty"]="SUB_PROJECT=arty verilog"
mapping["vcu118"]="SUB_PROJECT=vcu118 verilog"

View File

@@ -1,7 +1,9 @@
#!/bin/bash
export HOME="${HOME:-/root}"
CONDA_INSTALL_PREFIX=/opt/conda
CONDA_INSTALLER_VERSION=4.12.0-0
CONDA_INSTALLER_VERSION=23.1.0-1
CONDA_INSTALLER="https://github.com/conda-forge/miniforge/releases/download/${CONDA_INSTALLER_VERSION}/Miniforge3-${CONDA_INSTALLER_VERSION}-Linux-x86_64.sh"
CONDA_CMD="conda" # some installers install mamba or micromamba
@@ -143,15 +145,18 @@ else
$SUDO bash ./install_conda.sh -b -p "$CONDA_INSTALL_PREFIX" $conda_install_extra
rm ./install_conda.sh
# get most up-to-date conda version
"${DRY_RUN_ECHO[@]}" $SUDO "$CONDA_EXE" update $DRY_RUN_OPTION -y -n base -c conda-forge conda
# see https://conda-forge.org/docs/user/tipsandtricks.html#multiple-channels
# for more information on strict channel_priority
"${DRY_RUN_ECHO[@]}" $SUDO "$CONDA_EXE" config --system --set channel_priority strict
# for more information on flexible channel_priority
"${DRY_RUN_ECHO[@]}" $SUDO "$CONDA_EXE" config --system --set channel_priority flexible
# By default, don't mess with people's PS1, I personally find it annoying
"${DRY_RUN_ECHO[@]}" $SUDO "$CONDA_EXE" config --system --set changeps1 false
# don't automatically activate the 'base' environment when intializing shells
# don't automatically activate the 'base' environment when initializing shells
"${DRY_RUN_ECHO[@]}" $SUDO "$CONDA_EXE" config --system --set auto_activate_base false
# don't automatically update conda to avoid https://github.com/conda-forge/conda-libmamba-solver-feedstock/issues/2
"${DRY_RUN_ECHO[@]}" $SUDO "$CONDA_EXE" config --system --set auto_update_conda false
# automatically use the ucb-bar channel for specific packages https://anaconda.org/ucb-bar/repo
"${DRY_RUN_ECHO[@]}" $SUDO "$CONDA_EXE" config --system --add channels ucb-bar
# conda-build is a special case and must always be installed into the base environment
$SUDO "$CONDA_EXE" install $DRY_RUN_OPTION -y -n base conda-build
@@ -160,12 +165,12 @@ else
# see https://www.anaconda.com/blog/a-faster-conda-for-a-growing-community
$SUDO "$CONDA_EXE" install $DRY_RUN_OPTION -y -n base conda-libmamba-solver
# conda-lock is a special case and must always be installed into the base environment
$SUDO "$CONDA_EXE" install $DRY_RUN_OPTION -y -n base conda-lock
# Use the fast solver by default
"${DRY_RUN_ECHO[@]}" $SUDO "$CONDA_EXE" config --system --set experimental_solver libmamba
# conda-lock is a special case and must always be installed into the base environment
$SUDO "$CONDA_EXE" install $DRY_RUN_OPTION -y -n base conda-lock=1.4
conda_init_extra_args=()
if [[ "$INSTALL_TYPE" == system ]]; then
# if we're installing into a root-owned directory using sudo, or we're already root

View File

@@ -16,8 +16,6 @@ source $SCRIPT_DIR/defaults.sh
cd $REMOTE_CHIPYARD_DIR
./scripts/init-submodules-no-riscv-tools.sh --force
./scripts/init-fpga.sh
# Constellation can run without espresso, but this improves
# elaboration time drastically

View File

@@ -14,8 +14,9 @@ cd $REMOTE_CHIPYARD_DIR
./scripts/init-submodules-no-riscv-tools.sh --force
# Run Firesim Scala Tests
export FIRESIM_ENV_SOURCED=1;
export FIRESIM_ENV_SOURCED=1
export COURSIER_CACHE=$REMOTE_COURSIER_CACHE
export JVM_MEMORY=10G
export JAVA_TMP_DIR=$REMOTE_JAVA_TMP_DIR
export TEST_DISABLE_VIVADO=1
make -C $REMOTE_FIRESIM_DIR TARGET_SBT_PROJECT="{file:$REMOTE_CHIPYARD_DIR}firechip" testOnly ${mapping[$1]}

View File

@@ -10,13 +10,14 @@ SCRIPT_DIR="$( cd "$( dirname "$0" )" && pwd )"
source $SCRIPT_DIR/defaults.sh
DISABLE_SIM_PREREQ="BREAK_SIM_PREREQ=1"
MAPPING_FLAGS=${mapping[$1]}
run_bmark () {
make run-bmark-tests-fast -j$CI_MAKE_NPROC -C $LOCAL_SIM_DIR $DISABLE_SIM_PREREQ $@
make run-bmark-tests-fast -j$CI_MAKE_NPROC -C $LOCAL_SIM_DIR $DISABLE_SIM_PREREQ $MAPPING_FLAGS $@
}
run_asm () {
make run-asm-tests-fast -j$CI_MAKE_NPROC -C $LOCAL_SIM_DIR $DISABLE_SIM_PREREQ $@
make run-asm-tests-fast -j$CI_MAKE_NPROC -C $LOCAL_SIM_DIR $DISABLE_SIM_PREREQ $MAPPING_FLAGS $@
}
run_both () {
@@ -25,102 +26,137 @@ run_both () {
}
run_tracegen () {
make tracegen -C $LOCAL_SIM_DIR $DISABLE_SIM_PREREQ $@
make tracegen -C $LOCAL_SIM_DIR $DISABLE_SIM_PREREQ $MAPPING_FLAGS $@
}
run_binary () {
make run-binary-fast -C $LOCAL_SIM_DIR $DISABLE_SIM_PREREQ $MAPPING_FLAGS $@
}
case $1 in
chipyard-rocket)
run_bmark ${mapping[$1]}
run_bmark
make -C $LOCAL_CHIPYARD_DIR/tests
# Test run-binary with and without loadmem
run_binary BINARY=$LOCAL_CHIPYARD_DIR/tests/hello.riscv LOADMEM=1
run_binary BINARY=$LOCAL_CHIPYARD_DIR/tests/hello.riscv
;;
chipyard-dmirocket)
run_bmark ${mapping[$1]}
# Test checkpoint-restore
$LOCAL_CHIPYARD_DIR/scripts/generate-ckpt.sh -b $RISCV/riscv64-unknown-elf/share/riscv-tests/benchmarks/dhrystone.riscv -i 10000
run_binary LOADARCH=$PWD/dhrystone.riscv.0x80000000.10000.loadarch
;;
chipyard-boom)
run_bmark
;;
chipyard-shuttle)
run_bmark ${mapping[$1]}
;;
chipyard-dmiboom)
# Test checkpoint-restore
$LOCAL_CHIPYARD_DIR/scripts/generate-ckpt.sh -b $RISCV/riscv64-unknown-elf/share/riscv-tests/benchmarks/dhrystone.riscv -i 10000
run_binary LOADARCH=$PWD/dhrystone.riscv.0x80000000.10000.loadarch
;;
chipyard-spike)
run_bmark ${mapping[$1]}
run_bmark
;;
chipyard-hetero)
run_bmark ${mapping[$1]}
run_bmark
;;
chipyard-prefetchers)
run_binary BINARY=$RISCV/riscv64-unknown-elf/share/riscv-tests/benchmarks/dhrystone.riscv
;;
rocketchip)
run_bmark ${mapping[$1]}
run_bmark
;;
chipyard-hwacha)
make run-rv64uv-p-asm-tests -j$CI_MAKE_NPROC -C $LOCAL_SIM_DIR $DISABLE_SIM_PREREQ ${mapping[$1]}
make run-rv64uv-p-asm-tests -j$CI_MAKE_NPROC -C $LOCAL_SIM_DIR $DISABLE_SIM_PREREQ $MAPPING_FLAGS
;;
chipyard-gemmini)
GEMMINI_SOFTWARE_DIR=$LOCAL_SIM_DIR/../../generators/gemmini/software/gemmini-rocc-tests
rm -rf $GEMMINI_SOFTWARE_DIR/riscv-tests
cd $LOCAL_SIM_DIR
make -C $LOCAL_SIM_DIR $DISABLE_SIM_PREREQ ${mapping[$1]} run-binary-fast BINARY=$GEMMINI_SOFTWARE_DIR/build/bareMetalC/aligned-baremetal
make -C $LOCAL_SIM_DIR $DISABLE_SIM_PREREQ ${mapping[$1]} run-binary-fast BINARY=$GEMMINI_SOFTWARE_DIR/build/bareMetalC/raw_hazard-baremetal
make -C $LOCAL_SIM_DIR $DISABLE_SIM_PREREQ ${mapping[$1]} run-binary-fast BINARY=$GEMMINI_SOFTWARE_DIR/build/bareMetalC/mvin_mvout-baremetal
run_binary BINARY=$GEMMINI_SOFTWARE_DIR/build/bareMetalC/aligned-baremetal
run_binary BINARY=$GEMMINI_SOFTWARE_DIR/build/bareMetalC/raw_hazard-baremetal
run_binary BINARY=$GEMMINI_SOFTWARE_DIR/build/bareMetalC/mvin_mvout-baremetal
;;
chipyard-sha3)
(cd $LOCAL_CHIPYARD_DIR/generators/sha3/software && ./build.sh)
make -C $LOCAL_SIM_DIR $DISABLE_SIM_PREREQ ${mapping[$1]} run-binary-fast BINARY=$LOCAL_CHIPYARD_DIR/generators/sha3/software/tests/bare/sha3-rocc.riscv
run_binary BINARY=$LOCAL_CHIPYARD_DIR/generators/sha3/software/tests/bare/sha3-rocc.riscv
;;
chipyard-mempress)
(cd $LOCAL_CHIPYARD_DIR/generators/mempress/software/src && make)
make -C $LOCAL_SIM_DIR $DISABLE_SIM_PREREQ ${mapping[$1]} run-binary-fast BINARY=$LOCAL_CHIPYARD_DIR/generators/mempress/software/src/mempress-rocc.riscv
run_binary BINARY=$LOCAL_CHIPYARD_DIR/generators/mempress/software/src/mempress-rocc.riscv
;;
chipyard-manymmioaccels)
make -C $LOCAL_CHIPYARD_DIR/tests
# test streaming-passthrough
make -C $LOCAL_SIM_DIR $DISABLE_SIM_PREREQ ${mapping[$1]} run-binary-fast BINARY=$LOCAL_CHIPYARD_DIR/tests/streaming-passthrough.riscv
run_binary BINARY=$LOCAL_CHIPYARD_DIR/tests/streaming-passthrough.riscv
# test streaming-fir
make -C $LOCAL_SIM_DIR $DISABLE_SIM_PREREQ ${mapping[$1]} run-binary-fast BINARY=$LOCAL_CHIPYARD_DIR/tests/streaming-fir.riscv
# test nvdla
make -C $LOCAL_SIM_DIR $DISABLE_SIM_PREREQ ${mapping[$1]} BINARY=$LOCAL_CHIPYARD_DIR/tests/nvdla.riscv run-binary-fast
run_binary BINARY=$LOCAL_CHIPYARD_DIR/tests/streaming-fir.riscv
# test fft
make -C $LOCAL_SIM_DIR $DISABLE_SIM_PREREQ ${mapping[$1]} BINARY=$LOCAL_CHIPYARD_DIR/tests/fft.riscv run-binary-fast
run_binary BINARY=$LOCAL_CHIPYARD_DIR/tests/fft.riscv
;;
chipyard-nvdla)
make -C $LOCAL_CHIPYARD_DIR/tests
run_binary BINARY=$LOCAL_CHIPYARD_DIR/tests/nvdla.riscv
;;
chipyard-manyperipherals)
# SPI Flash read tests, then bmark tests
# SPI Flash read tests
make -C $LOCAL_CHIPYARD_DIR/tests
make -C $LOCAL_SIM_DIR $DISABLE_SIM_PREREQ ${mapping[$1]} BINARY=$LOCAL_CHIPYARD_DIR/tests/spiflashread.riscv run-binary-fast
run_bmark ${mapping[$1]}
run_binary BINARY=$LOCAL_CHIPYARD_DIR/tests/spiflashread.riscv
;;
chipyard-spiflashwrite)
make -C $LOCAL_CHIPYARD_DIR/tests
make -C $LOCAL_SIM_DIR $DISABLE_SIM_PREREQ ${mapping[$1]} BINARY=$LOCAL_CHIPYARD_DIR/tests/spiflashwrite.riscv run-binary-fast
run_binary BINARY=$LOCAL_CHIPYARD_DIR/tests/spiflashwrite.riscv
[[ "`xxd $LOCAL_CHIPYARD_DIR/tests/spiflash.img | grep 1337\ 00ff\ aa55\ face | wc -l`" == "6" ]] || false
;;
chipyard-tethered)
make -C $LOCAL_CHIPYARD_DIR/tests
run_binary BINARY=$LOCAL_CHIPYARD_DIR/tests/hello.riscv LOADMEM=1 EXTRA_SIM_FLAGS="+cflush_addr=0x2010200"
;;
tracegen)
run_tracegen ${mapping[$1]}
run_tracegen
;;
tracegen-boom)
run_tracegen ${mapping[$1]}
run_tracegen
;;
chipyard-cva6)
make run-binary-fast -C $LOCAL_SIM_DIR $DISABLE_SIM_PREREQ ${mapping[$1]} BINARY=$RISCV/riscv64-unknown-elf/share/riscv-tests/benchmarks/multiply.riscv
run_binary BINARY=$RISCV/riscv64-unknown-elf/share/riscv-tests/benchmarks/multiply.riscv
;;
chipyard-ibex)
run_bmark ${mapping[$1]} #TODO: Find 32-bit test
# Ibex cannot run the riscv-tests binaries for some reason
# run_binary BINARY=$RISCV/riscv64-unknown-elf/share/riscv-tests/isa/rv32ui-p-simple
;;
chipyard-sodor)
run_asm ${mapping[$1]}
run_asm
;;
chipyard-constellation)
make run-binary-hex BINARY=$RISCV/riscv64-unknown-elf/share/riscv-tests/benchmarks/dhrystone.riscv -C $LOCAL_SIM_DIR $DISABLE_SIM_PREREQ ${mapping[$1]}
run_binary LOADMEM=1 BINARY=$RISCV/riscv64-unknown-elf/share/riscv-tests/benchmarks/dhrystone.riscv
;;
icenet)
make run-binary-fast BINARY=none -C $LOCAL_SIM_DIR $DISABLE_SIM_PREREQ ${mapping[$1]}
run_binary BINARY=none
;;
testchipip)
make run-binary-fast BINARY=none -C $LOCAL_SIM_DIR $DISABLE_SIM_PREREQ ${mapping[$1]}
run_binary BINARY=none
;;
constellation)
make run-binary-fast BINARY=none -C $LOCAL_SIM_DIR $DISABLE_SIM_PREREQ ${mapping[$1]}
run_binary BINARY=none
;;
rocketchip-amba)
run_binary BINARY=none
;;
rocketchip-tlsimple)
run_binary BINARY=none
;;
rocketchip-tlwidth)
run_binary BINARY=none
;;
rocketchip-tlxbar)
run_binary BINARY=none
;;
*)
echo "No set of tests for $1. Did you spell it right?"

View File

@@ -6,6 +6,9 @@ on:
branches:
- main
- '1.[0-9]*.x'
schedule:
# run at 00:00 on sunday
- cron: "0 0 * * 0"
defaults:
run:
@@ -62,7 +65,7 @@ jobs:
name: setup-repo
needs: [change-filters, cancel-prior-workflows]
if: needs.change-filters.outputs.needs-rtl == 'true'
runs-on: ferry
runs-on: jktqos
steps:
- name: Delete old checkout
run: |
@@ -80,12 +83,12 @@ jobs:
eval "$(conda shell.bash hook)"
mkdir ${{ env.JAVA_TMP_DIR }}
export MAKEFLAGS="-j32"
./build-setup.sh -f
./build-setup.sh -f -v
run-cfg-finder:
name: run-cfg-finder
needs: [setup-repo]
runs-on: ferry
runs-on: jktqos
steps:
- name: Run config finder
run: |
@@ -98,7 +101,7 @@ jobs:
run-tutorial:
name: run-tutorial
needs: [setup-repo]
runs-on: ferry
runs-on: jktqos
steps:
- name: Run smoke test
run: |
@@ -115,7 +118,7 @@ jobs:
cd vlsi
# NOTE: most conda installs are in separate conda envs because they mess up
# NOTE: most conda installs are in separate conda envs because they mess up
# each other's versions (for no apparent reason) and we need the latest versions
conda config --add channels defaults
conda config --add channels litex-hub
@@ -165,9 +168,10 @@ jobs:
cleanup:
name: cleanup
needs: [run-tutorial]
runs-on: ferry
if: ${{ always() && contains(join(needs.*.result, ','), 'success') }}
runs-on: jktqos
if: ${{ always() }}
steps:
- name: Delete repo copy and conda env
run: |
rm -rf ${{ env.REMOTE_WORK_DIR }}
rm -rf ${{ env.JAVA_TMP_DIR }}

View File

@@ -166,7 +166,7 @@ jobs:
- name: Generate keys
id: genkey
run: |
echo "::set-output name=extra-tests-cache-key::extra-tests-${{ github.sha }}"
echo "extra-tests-cache-key=extra-tests-${{ github.sha }}" >> $GITHUB_OUTPUT
- uses: actions/cache@v3
id: build-extra-tools-cache
with:
@@ -178,11 +178,11 @@ jobs:
conda activate ${{ env.conda-env-name-no-time }}-$(date --date "${{ env.workflow-timestamp }}" +%Y%m%d)-riscv-tools
.github/scripts/build-extra-tests.sh
create-conda-env-knight:
name: create-conda-env-knight
create-conda-env-jktgz:
name: create-conda-env-jktgz
needs: [change-filters, cancel-prior-workflows]
if: needs.change-filters.outputs.needs-rtl == 'true'
runs-on: knight
runs-on: jktgz
steps:
- name: Delete old checkout
run: |
@@ -199,11 +199,11 @@ jobs:
- name: Create conda env
uses: ./.github/actions/create-conda-env
create-conda-env-ferry:
name: create-conda-env-ferry
create-conda-env-jktqos:
name: create-conda-env-jktqos
needs: [change-filters, cancel-prior-workflows]
if: needs.change-filters.outputs.needs-rtl == 'true'
runs-on: ferry
runs-on: jktqos
steps:
- name: Delete old checkout
run: |
@@ -225,7 +225,7 @@ jobs:
# When adding new prep jobs, please add them to `needs` below
setup-complete:
name: setup-complete
needs: [create-conda-env-knight, create-conda-env-ferry, build-extra-tests]
needs: [create-conda-env-jktgz, create-conda-env-jktqos, build-extra-tests]
runs-on: ubuntu-latest
steps:
- name: Set up complete
@@ -393,7 +393,7 @@ jobs:
chipyard-spike-gemmini-run-tests:
name: chipyard-spike-gemmini-run-tests
needs: prepare-chipyard-accels # technically doesn't depend on RTL but should be after the build.sh for Gemmini
runs-on: ferry
runs-on: jktqos
steps:
- name: Delete old checkout
run: |
@@ -442,6 +442,29 @@ jobs:
group-key: "group-cores"
project-key: "chipyard-rocket"
chipyard-prefetchers-run-tests:
name: chipyard-prefetchers-run-tests
needs: prepare-chipyard-cores
runs-on: self-hosted
steps:
- name: Delete old checkout
run: |
ls -alh .
rm -rf ${{ github.workspace }}/* || true
rm -rf ${{ github.workspace }}/.* || true
ls -alh .
- name: Checkout
uses: actions/checkout@v3
- name: Git workaround
uses: ./.github/actions/git-workaround
- name: Create conda env
uses: ./.github/actions/create-conda-env
- name: Run tests
uses: ./.github/actions/run-tests
with:
group-key: "group-cores"
project-key: "chipyard-prefetchers"
chipyard-hetero-run-tests:
name: chipyard-hetero-run-tests
needs: prepare-chipyard-cores
@@ -488,6 +511,29 @@ jobs:
group-key: "group-cores"
project-key: "chipyard-boom"
chipyard-shuttle-run-tests:
name: chipyard-shuttle-run-tests
needs: prepare-chipyard-cores
runs-on: self-hosted
steps:
- name: Delete old checkout
run: |
ls -alh .
rm -rf ${{ github.workspace }}/* || true
rm -rf ${{ github.workspace }}/.* || true
ls -alh .
- name: Checkout
uses: actions/checkout@v3
- name: Git workaround
uses: ./.github/actions/git-workaround
- name: Create conda env
uses: ./.github/actions/create-conda-env
- name: Run tests
uses: ./.github/actions/run-tests
with:
group-key: "group-cores"
project-key: "chipyard-shuttle"
chipyard-cva6-run-tests:
name: chipyard-cva6-run-tests
needs: prepare-chipyard-cores
@@ -603,6 +649,29 @@ jobs:
group-key: "group-peripherals"
project-key: "chipyard-dmirocket"
chipyard-dmiboom-run-tests:
name: chipyard-dmiboom-run-tests
needs: prepare-chipyard-peripherals
runs-on: self-hosted
steps:
- name: Delete old checkout
run: |
ls -alh .
rm -rf ${{ github.workspace }}/* || true
rm -rf ${{ github.workspace }}/.* || true
ls -alh .
- name: Checkout
uses: actions/checkout@v3
- name: Git workaround
uses: ./.github/actions/git-workaround
- name: Create conda env
uses: ./.github/actions/create-conda-env
- name: Run tests
uses: ./.github/actions/run-tests
with:
group-key: "group-peripherals"
project-key: "chipyard-dmiboom"
chipyard-spiflashwrite-run-tests:
name: chipyard-spiflashwrite-run-tests
needs: prepare-chipyard-peripherals
@@ -649,6 +718,29 @@ jobs:
group-key: "group-peripherals"
project-key: "chipyard-manyperipherals"
chipyard-tethered-run-tests:
name: chipyard-tethered-run-tests
needs: prepare-chipyard-peripherals
runs-on: self-hosted
steps:
- name: Delete old checkout
run: |
ls -alh .
rm -rf ${{ github.workspace }}/* || true
rm -rf ${{ github.workspace }}/.* || true
ls -alh .
- name: Checkout
uses: actions/checkout@v3
- name: Git workaround
uses: ./.github/actions/git-workaround
- name: Create conda env
uses: ./.github/actions/create-conda-env
- name: Run tests
uses: ./.github/actions/run-tests
with:
group-key: "group-peripherals"
project-key: "chipyard-tethered"
chipyard-sha3-run-tests:
name: chipyard-sha3-run-tests
needs: prepare-chipyard-accels
@@ -718,6 +810,29 @@ jobs:
group-key: "group-accels"
project-key: "chipyard-manymmioaccels"
# chipyard-nvdla-run-tests:
# name: chipyard-nvdla-run-tests
# needs: prepare-chipyard-accels
# runs-on: self-hosted
# steps:
# - name: Delete old checkout
# run: |
# ls -alh .
# rm -rf ${{ github.workspace }}/* || true
# rm -rf ${{ github.workspace }}/.* || true
# ls -alh .
# - name: Checkout
# uses: actions/checkout@v3
# - name: Git workaround
# uses: ./.github/actions/git-workaround
# - name: Create conda env
# uses: ./.github/actions/create-conda-env
# - name: Run tests
# uses: ./.github/actions/run-tests
# with:
# group-key: "group-accels"
# project-key: "chipyard-nvdla"
chipyard-mempress-run-tests:
name: chipyard-mempress-run-tests
needs: prepare-chipyard-accels
@@ -834,6 +949,45 @@ jobs:
group-key: "group-other"
project-key: "testchipip"
rocketchip-run-tests:
name: rocketchip-run-tests
needs: prepare-chipyard-other
runs-on: self-hosted
steps:
- name: Delete old checkout
run: |
ls -alh .
rm -rf ${{ github.workspace }}/* || true
rm -rf ${{ github.workspace }}/.* || true
ls -alh .
- name: Checkout
uses: actions/checkout@v3
- name: Git workaround
uses: ./.github/actions/git-workaround
- name: Create conda env
uses: ./.github/actions/create-conda-env
- name: Run amba tests
uses: ./.github/actions/run-tests
with:
group-key: "group-other"
project-key: "rocketchip-amba"
# Below tests segfault with verilator, work fine in VCS
# - name: Run tlsimple tests
# uses: ./.github/actions/run-tests
# with:
# group-key: "group-other"
# project-key: "rocketchip-tlsimple"
# - name: Run tlwidth tests
# uses: ./.github/actions/run-tests
# with:
# group-key: "group-other"
# project-key: "rocketchip-tlwidth"
# - name: Run tlxbar tests
# uses: ./.github/actions/run-tests
# with:
# group-key: "group-other"
# project-key: "rocketchip-tlxbar"
constellation-run-tests:
name: constellation-run-tests
needs: prepare-chipyard-other
@@ -941,21 +1095,26 @@ jobs:
chipyard-rocket-run-tests,
chipyard-hetero-run-tests,
chipyard-boom-run-tests,
chipyard-shuttle-run-tests,
chipyard-cva6-run-tests,
chipyard-ibex-run-tests,
chipyard-sodor-run-tests,
chipyard-dmiboom-run-tests,
chipyard-dmirocket-run-tests,
chipyard-spiflashwrite-run-tests,
chipyard-manyperipherals-run-tests,
chipyard-tethered-run-tests,
chipyard-sha3-run-tests,
chipyard-gemmini-run-tests,
chipyard-manymmioaccels-run-tests,
chipyard-manymmioaccels-run-tests, # chipyard-nvdla-run-tests,
chipyard-prefetchers-run-tests,
chipyard-mempress-run-tests,
chipyard-constellation-run-tests,
tracegen-boom-run-tests,
tracegen-run-tests,
icenet-run-tests,
testchipip-run-tests,
rocketchip-run-tests,
constellation-run-tests,
prepare-chipyard-fpga, # firesim-run-tests,
fireboom-run-tests]

View File

@@ -0,0 +1,56 @@
{
"categories": [
{
"title": "## Added",
"labels": ["changelog:added"]
},
{
"title": "## Changed",
"labels": ["changelog:changed"]
},
{
"title": "## Fixed",
"labels": ["changelog:fixed"]
},
{
"title": "## Removed",
"labels": ["changelog:removed"]
},
{
"title": "## Uncategorized",
"labels": []
}
],
"ignore_labels": [
"changelog:omit"
],
"sort": {
"order": "ASC",
"on_property": "mergedAt"
},
"template": "${{CHANGELOG}}\n\n**Full Changelog:** ${{RELEASE_DIFF}}\n",
"pr_template": "- ${{TITLE}} (by @${{AUTHOR}} in ${{URL}})${{RELEASE_NOTES}}",
"empty_template": "- no changes",
"transformers": [
{
"pattern": "<!--.*-->",
"flags": "gus",
"target": ""
}
],
"custom_placeholders": [
{
"name": "RELEASE_NOTES",
"source": "BODY",
"transformer": {
"pattern": ".*#### Release Notes(?:[\n\\s]|(?:<!--.*?-->))*((?:\\S(?!!--)).*?)[\n\\s]*\n#.*",
"flags": "gus",
"target": "\n $1"
}
}
],
"trim_values": false,
"max_tags_to_fetch": 200,
"max_pull_requests": 500,
"max_back_track_time_days": 365
}

51
.github/workflows/release-notes.yml vendored Normal file
View File

@@ -0,0 +1,51 @@
# adapted from https://github.com/chipsalliance/chisel/blob/main/.github/workflows/release-notes.yml
name: Generate Release Notes
on:
release:
types: [created]
workflow_dispatch:
inputs:
toTag:
description: 'Tag or ref for which to generate release notes'
required: true
fromTag:
# If you leave this blank, it'll select previous SemVer version
# WARNING: Cannot use anything older than a005498 because of the git tree merge
description: 'Tag or ref from which to start generating release notes'
required: false
jobs:
generate_release_notes:
name: Generate Release Notes
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v3
- name: Build Release Notes
id: release-notes
uses: mikepenz/release-changelog-builder-action@v3.7.0
with:
configuration: .github/workflows/config/release-notes.json
failOnError: true
# Amazingly, on release where the inputs are empty, this just does the right thing
# The "toTag" is the released tag, and the "fromTag" is the previous tag according to SemVer
fromTag: ${{ github.event.inputs.fromTag }}
toTag: ${{ github.event.inputs.toTag }}
token: ${{ secrets.GITHUB_TOKEN }}
- name: Report Release Notes
# Put output through env variable to make it robust to quotes
env:
CHANGELOG: ${{steps.release-notes.outputs.changelog}}
run: echo "$CHANGELOG" >> $GITHUB_STEP_SUMMARY
- name: Upload Release Notes (on release)
if: github.event_name == 'release'
uses: softprops/action-gh-release@v0.1.15
with:
body: ${{ steps.release-notes.outputs.changelog }}
- name: Error on uncategorized PRs
if: steps.release-notes.outputs.uncategorized_prs != 0
run: exit 1

24
.github/workflows/require-label.yml vendored Normal file
View File

@@ -0,0 +1,24 @@
# adapted from https://github.com/chipsalliance/chisel/blob/main/.github/workflows/require-label.yml
name: Require Release Notes Label
on:
pull_request:
branches:
- main
types:
- opened
- synchronize
- reopened
- labeled
- unlabeled
jobs:
check_labels:
name: Check Labels
runs-on: ubuntu-latest
steps:
- uses: docker://agilepathway/pull-request-label-checker:v1.4.25
with:
one_of: changelog:added,changelog:changed,changelog:fixed,changelog:omit,changelog:removed
repo_token: ${{ secrets.GITHUB_TOKEN }}

2
.gitignore vendored
View File

@@ -26,3 +26,5 @@ project/metals.sbt
project/project/
.ivy2
.sbt
.classpath_cache/
.vscode/

9
.gitmodules vendored
View File

@@ -121,3 +121,12 @@
[submodule "tools/cde"]
path = tools/cde
url = https://github.com/chipsalliance/cde.git
[submodule "software/embench/embench-iot"]
path = software/embench/embench-iot
url = https://github.com/embench/embench-iot.git
[submodule "shuttle"]
path = generators/shuttle
url = https://github.com/ucb-bar/shuttle.git
[submodule "generators/bar-fetchers"]
path = generators/bar-fetchers
url = https://github.com/ucb-bar/bar-fetchers.git

View File

@@ -2,6 +2,117 @@
This changelog follows the format defined here: https://keepachangelog.com/en/1.0.0/
## [1.10.0] - 2023-6-16
Adds superscalar in-order core, prefetchers, architectural checkpointing, examples for custom-chiptop/tapeout-chip/flat-chiptop. FireSim bumped with new local FPGA support: Xilinx VCU118 (w/XDMA), Xilinx Alveo U250/U280 (w/XDMA, in addition to previous Vitis support), RHSResearch NiteFury II (w/XDMA). FireSim now also supports Xcelium for metasims.
### Added
* QoL improvement to IOBinders + custom ChipTop example by @jerryz123 in https://github.com/ucb-bar/chipyard/pull/1399
* New Scala-based Config Finder by @abejgonzalez in https://github.com/ucb-bar/chipyard/pull/1424
* ADD: improve Makefile in tests/, add explicit arch flags by @T-K-233 in https://github.com/ucb-bar/chipyard/pull/1439
* Add mt-helloworld example by @jerryz123 in https://github.com/ucb-bar/chipyard/pull/1428
* Add tutorial software by @abejgonzalez in https://github.com/ucb-bar/chipyard/pull/1447
* Support not instantiating the TileClockGater/ResetSetter PRCI control by @jerryz123 in https://github.com/ucb-bar/chipyard/pull/1459
* ELF-based-loadmem | architectural restartable checkpoints by @jerryz123 in https://github.com/ucb-bar/chipyard/pull/1438
* Add embench build support by @jerryz123 in https://github.com/ucb-bar/chipyard/pull/1479
* Support multi-run of binaries by @jerryz123 in https://github.com/ucb-bar/chipyard/pull/1480
* Integrate barf (prefetchers) by @jerryz123 in https://github.com/ucb-bar/chipyard/pull/1505
* Add higher level explanations of RoCC + more resources by @nikhiljha in https://github.com/ucb-bar/chipyard/pull/1486
* Support banked/partitioned scratchpads by @jerryz123 in https://github.com/ucb-bar/chipyard/pull/1431
* Add dual-issue in-order "shuttle" core by @jerryz123 in https://github.com/ucb-bar/chipyard/pull/1495
* Improve peripheral fragments to include more peripheral devices and support instantiating multiple instances of same device by @T-K-233 in https://github.com/ucb-bar/chipyard/pull/1511
### Changed
* Bump to latest rocket-chip/chisel3.5.6 by @jerryz123 in https://github.com/ucb-bar/chipyard/pull/1411
* Resolve merge conflicts in chisel3.5.6 bump by @jerryz123 in https://github.com/ucb-bar/chipyard/pull/1430
* PLL integration example + FlatChipTop/TestHarness by @jerryz123 in https://github.com/ucb-bar/chipyard/pull/1427
* bump testchipip by @joey0320 in https://github.com/ucb-bar/chipyard/pull/1434
* Fix ChipLikeQuadRocketConfig crossing by @jerryz123 in https://github.com/ucb-bar/chipyard/pull/1436
* Bump TestChipIp to improve default serial_tl behavior by @jerryz123 in https://github.com/ucb-bar/chipyard/pull/1435
* Bump testchipip to standardize TL serdesser bundle params by @jerryz123 in https://github.com/ucb-bar/chipyard/pull/1446
* Bump to Hammer 1.1.1 by @harrisonliew in https://github.com/ucb-bar/chipyard/pull/1451
* Always initialize fpga-shells with init-submodules.sh by @jerryz123 in https://github.com/ucb-bar/chipyard/pull/1456
* Support uni-directional TLSerdesser by @jerryz123 in https://github.com/ucb-bar/chipyard/pull/1476
* Move xcelium.mk out of top-level by @jerryz123 in https://github.com/ucb-bar/chipyard/pull/1482
* Set default config back to 1-channel by @jerryz123 in https://github.com/ucb-bar/chipyard/pull/1483
* Unify supernode/harness-clocking across chipyard/firesim/fpga by @jerryz123 in https://github.com/ucb-bar/chipyard/pull/1474
* Use fat jar's to remove SBT invocations by @abejgonzalez in https://github.com/ucb-bar/chipyard/pull/1375
* Bump to latest rocket-chip by @jerryz123 in https://github.com/ucb-bar/chipyard/pull/1475
* Improvements to chipyard clocking by @jerryz123 in https://github.com/ucb-bar/chipyard/pull/1489
* Downgrade cryptography | Pin linux sysroot by @abejgonzalez in https://github.com/ucb-bar/chipyard/pull/1494
* bump mempress by @joey0320 in https://github.com/ucb-bar/chipyard/pull/1498
* bump sha3 by @joey0320 in https://github.com/ucb-bar/chipyard/pull/1499
* Bump FireMarshal by @abejgonzalez in https://github.com/ucb-bar/chipyard/pull/1502
* Split NVDLA config out of ManyMMIOAccels config to reduce CI load by @jerryz123 in https://github.com/ucb-bar/chipyard/pull/1503
* Ignore barstools compilation if not needed by @abejgonzalez in https://github.com/ucb-bar/chipyard/pull/1504
* Disable NVDLA simulations in CI by @jerryz123 in https://github.com/ucb-bar/chipyard/pull/1507
* Update NoC example config to match new PRCI organization by @jerryz123 in https://github.com/ucb-bar/chipyard/pull/1509
* Bump gemmini by @jerryz123 in https://github.com/ucb-bar/chipyard/pull/1519
### Fixed
* Various improvements and fixes by @jerryz123 in https://github.com/ucb-bar/chipyard/pull/1420
* Ensure conda cleanup regex properly filters out non-numeric chars by @abejgonzalez in https://github.com/ucb-bar/chipyard/pull/1425
* Clear screen on prompt by @abejgonzalez in https://github.com/ucb-bar/chipyard/pull/1449
* misc: many fixes to cospike by @tianrui-wei in https://github.com/ucb-bar/chipyard/pull/1450
* Uniquify module names that are common to Top & Model by @joey0320 in https://github.com/ucb-bar/chipyard/pull/1442
* Use pk/encoding.h for hello/mt-hello by @jerryz123 in https://github.com/ucb-bar/chipyard/pull/1454
* Fix no-uart configs by @jerryz123 in https://github.com/ucb-bar/chipyard/pull/1457
* Fix support for no-bootROM systems by @jerryz123 in https://github.com/ucb-bar/chipyard/pull/1458
* Check that HarnessClockInstantiator doesn't receive requests for similarly-named-clocks with different frequencies by @jerryz123 in https://github.com/ucb-bar/chipyard/pull/1460
* uniquify module names by @joey0320 in https://github.com/ucb-bar/chipyard/pull/1452
* Flip serial_tl_clock to be generated off-chip by @jerryz123 in https://github.com/ucb-bar/chipyard/pull/1445
* Move TestHarness to chipyard.harness, make chipyard/harness directory by @jerryz123 in https://github.com/ucb-bar/chipyard/pull/1463
* Separate out conda-lock generation into new script by @abejgonzalez in https://github.com/ucb-bar/chipyard/pull/1466
* Bump DRAMSim2 to avoid verbose log files by @jerryz123 in https://github.com/ucb-bar/chipyard/pull/1468
* Bump Verilator and use `TestDriver.v` as top by @abejgonzalez in https://github.com/ucb-bar/chipyard/pull/1398
* Add 1GB / 4GB DRAM firechip configs for FireSim VCU118 by @sagark in https://github.com/ucb-bar/chipyard/pull/1471
* Rename SerialAdapter+SimSerial to TSIToTileLink/SimTSI/TSIHarness by @jerryz123 in https://github.com/ucb-bar/chipyard/pull/1465
* Make BootAddrReg optional by @jerryz123 in https://github.com/ucb-bar/chipyard/pull/1464
* Fix vcd/fst/fsdb waveform generation by @jerryz123 in https://github.com/ucb-bar/chipyard/pull/1473
* Switch RTL sims to absolute clock-generators by @jerryz123 in https://github.com/ucb-bar/chipyard/pull/1472
* Generate objdump | check BINARY | cospike fixes by @jerryz123 in https://github.com/ucb-bar/chipyard/pull/1467
* Small QOL fixes for Xcelium by @abejgonzalez in https://github.com/ucb-bar/chipyard/pull/1485
* (VCU118 DDR HarnessBinder)Fix data field width mismatch between DDR AXI and TileLink MemoryBus by @jerryhethatday in https://github.com/ucb-bar/chipyard/pull/1487
* Force conda-lock to v1 by @abejgonzalez in https://github.com/ucb-bar/chipyard/pull/1492
* Loosen/tighten conda requirements | Fix conda-lock req by @abejgonzalez in https://github.com/ucb-bar/chipyard/pull/1497
* Misc Makefile Fixes by @abejgonzalez in https://github.com/ucb-bar/chipyard/pull/1496
* Bump constellation to fix interconnect FIFO-fixers by @jerryz123 in https://github.com/ucb-bar/chipyard/pull/1510
* [ci skip] Fix broken docs link by @jerryz123 in https://github.com/ucb-bar/chipyard/pull/1515
* Revert changes to peripheral fragments by @jerryz123 in https://github.com/ucb-bar/chipyard/pull/1518
### New Contributors
* @tianrui-wei made their first contribution in https://github.com/ucb-bar/chipyard/pull/1450
* @jerryhethatday made their first contribution in https://github.com/ucb-bar/chipyard/pull/1487
* @nikhiljha made their first contribution in https://github.com/ucb-bar/chipyard/pull/1486
## [1.9.1] - 2023-04-21
Various fixes for Linux boot, More Chip/bringup examples, Chisel 3.5.6 bump
### Added
* QoL improvement to IOBinders + custom ChipTop example by @jerryz123 in https://github.com/ucb-bar/chipyard/pull/1399
* PLL integration example + FlatChipTop/TestHarness by @jerryz123 in https://github.com/ucb-bar/chipyard/pull/1427
* Bump TestChipIp to improve default serial_tl behavior by @jerryz123 in https://github.com/ucb-bar/chipyard/pull/1435
* Bump testchipip to standardize TL serdesser bundle params by @jerryz123 in https://github.com/ucb-bar/chipyard/pull/1446
* HarnessBinder asserts to catch bad clock generation by @jerryz123 in https://github.com/ucb-bar/chipyard/pull/1460
### Changed
* New Scala-based Config Finder by @abejgonzalez in https://github.com/ucb-bar/chipyard/pull/1424
* Bump to latest rocket-chip/chisel3.5.6 by @jerryz123 in https://github.com/ucb-bar/chipyard/pull/1411
* Resolve merge conflicts in chisel3.5.6 bump by @jerryz123 in https://github.com/ucb-bar/chipyard/pull/1430
* bump testchipip by @joey0320 in https://github.com/ucb-bar/chipyard/pull/1434
* ADD: improve Makefile in tests/, add explicit arch flags by @T-K-233 in https://github.com/ucb-bar/chipyard/pull/1439
* Various submodule bumps by @abejgonzalez in https://github.com/ucb-bar/chipyard/pull/1448
* Support not instantiating tile reset/clock contorl features by @jerryz123 in https://github.com/ucb-bar/chipyard/pull/1459
### Fixed
* Various improvements and fixes by @jerryz123 in https://github.com/ucb-bar/chipyard/pull/1420
* Ensure conda cleanup regex properly filters out non-numeric chars by @abejgonzalez in https://github.com/ucb-bar/chipyard/pull/1425
* Fix ChipLikeQuadRocketConfig crossing by @jerryz123 in https://github.com/ucb-bar/chipyard/pull/1436
* Uniquify module names that are common to Top & Model by @joey0320 in https://github.com/ucb-bar/chipyard/pull/1442
* Support for no-bootROM systems by @jerryz123 in https://github.com/ucb-bar/chipyard/pull/1458
* Support for no-UART systems by @jerryz123 in https://github.com/ucb-bar/chipyard/pull/1457
## [1.9.0] - 2023-03-23
Faster FIRRTL build support work CIRCT. New software support for RISC-V GCC12 and Linux 6.2. Various bumps and fixes of all submodules.

View File

@@ -2,9 +2,6 @@
# Chipyard Framework [![Test](https://github.com/ucb-bar/chipyard/actions/workflows/chipyard-run-tests.yml/badge.svg)](https://github.com/ucb-bar/chipyard/actions)
| We're running the First FireSim and Chipyard User/Developer Workshop at ASPLOS 2023 on March 26, 2023! This workshop will feature a full-day of submitted talks from users and developers in the FireSim and Chipyard community. Learn more and **submit your work** on the [2023 Workshop Page](https://fires.im/workshop-2023/)! |
|-----|
## Quick Links
* **Stable Documentation**: https://chipyard.readthedocs.io/
@@ -26,9 +23,8 @@ Chipyard is actively developed in the [Berkeley Architecture Research Group][ucb
## Resources
* Chipyard Stable Documentation: https://chipyard.readthedocs.io/
* Chipyard (x FireSim) Tutorial: https://fires.im/tutorial
* Chipyard Basics slides: https://fires.im/isca22-slides-pdf/02_chipyard_basics.pdf
* Chipyard Tutorial Exercise slides: https://fires.im/isca22-slides-pdf/03_building_custom_socs.pdf
* Chipyard (x FireSim) Tutorial: https://fires.im/tutorial-recent/
* Chipyard Basics slides: https://fires.im/asplos23-slides-pdf/02_chipyard_basics.pdf
## Need help?
@@ -77,6 +73,7 @@ These additional publications cover many of the internal components used in Chip
* **FASED**: D. Biancolin, et al., *FPGA'19*. [PDF](https://people.eecs.berkeley.edu/~biancolin/papers/fased-fpga19.pdf).
* **Golden Gate**: A. Magyar, et al., *ICCAD'19*. [PDF](https://davidbiancolin.github.io/papers/goldengate-iccad19.pdf).
* **FirePerf**: S. Karandikar, et al., *ASPLOS'20*. [PDF](https://sagark.org/assets/pubs/fireperf-asplos2020.pdf).
* **FireSim ISCA@50 Retrospective**: S. Karandikar, et al., *ISCA@50 Retrospective: 1996-2020*. [PDF](https://sites.coecis.cornell.edu/isca50retrospective/files/2023/06/Karandikar_2018_FireSim.pdf)
* **Tools**
* **Chisel**: J. Bachrach, et al., *DAC'12*. [PDF](https://people.eecs.berkeley.edu/~krste/papers/chisel-dac2012.pdf).
* **FIRRTL**: A. Izraelevitz, et al., *ICCAD'17*. [PDF](https://ieeexplore.ieee.org/document/8203780).

View File

@@ -4,14 +4,34 @@ import Tests._
// implicit one
lazy val chipyardRoot = Project("chipyardRoot", file("."))
// keep chisel/firrtl specific class files, rename other conflicts
val chiselFirrtlMergeStrategy = CustomMergeStrategy.rename { dep =>
import sbtassembly.Assembly.{Project, Library}
val nm = dep match {
case p: Project => p.name
case l: Library => l.moduleCoord.name
}
if (Seq("firrtl", "chisel3").contains(nm.split("_")(0))) { // split by _ to avoid checking on major/minor version
dep.target
} else {
"renamed/" + dep.target
}
}
lazy val commonSettings = Seq(
organization := "edu.berkeley.cs",
version := "1.6",
scalaVersion := "2.13.10",
assembly / test := {},
assembly / assemblyMergeStrategy := { _ match {
case PathList("META-INF", "MANIFEST.MF") => MergeStrategy.discard
case _ => MergeStrategy.first}},
assembly / assemblyMergeStrategy := {
case PathList("chisel3", "stage", xs @ _*) => chiselFirrtlMergeStrategy
case PathList("firrtl", "stage", xs @ _*) => chiselFirrtlMergeStrategy
// should be safe in JDK11: https://stackoverflow.com/questions/54834125/sbt-assembly-deduplicate-module-info-class
case x if x.endsWith("module-info.class") => MergeStrategy.discard
case x =>
val oldStrategy = (assembly / assemblyMergeStrategy).value
oldStrategy(x)
},
scalacOptions ++= Seq(
"-deprecation",
"-unchecked",
@@ -86,8 +106,6 @@ lazy val hardfloat = (project in rocketChipDir / "hardfloat")
.settings(commonSettings)
.settings(
libraryDependencies ++= Seq(
"org.scala-lang" % "scala-reflect" % scalaVersion.value,
"org.json4s" %% "json4s-jackson" % "3.6.6",
"org.scalatest" %% "scalatest" % "3.2.0" % "test"
)
)
@@ -97,8 +115,6 @@ lazy val rocketMacros = (project in rocketChipDir / "macros")
.settings(
libraryDependencies ++= Seq(
"org.scala-lang" % "scala-reflect" % scalaVersion.value,
"org.json4s" %% "json4s-jackson" % "3.6.6",
"org.scalatest" %% "scalatest" % "3.2.0" % "test"
)
)
@@ -110,7 +126,8 @@ lazy val rocketchip = freshProject("rocketchip", rocketChipDir)
libraryDependencies ++= Seq(
"org.scala-lang" % "scala-reflect" % scalaVersion.value,
"org.json4s" %% "json4s-jackson" % "3.6.6",
"org.scalatest" %% "scalatest" % "3.2.0" % "test"
"org.scalatest" %% "scalatest" % "3.2.0" % "test",
"org.scala-graph" %% "graph-core" % "1.13.5"
)
)
.settings( // Settings for scalafix
@@ -137,7 +154,7 @@ lazy val chipyard = (project in file("generators/chipyard"))
sha3, // On separate line to allow for cleaner tutorial-setup patches
dsptools, `rocket-dsp-utils`,
gemmini, icenet, tracegen, cva6, nvdla, sodor, ibex, fft_generator,
constellation, mempress)
constellation, mempress, barf, shuttle)
.settings(libraryDependencies ++= rocketLibDeps.value)
.settings(
libraryDependencies ++= Seq(
@@ -152,6 +169,11 @@ lazy val mempress = (project in file("generators/mempress"))
.settings(chiselTestSettings)
.settings(commonSettings)
lazy val barf = (project in file("generators/bar-fetchers"))
.dependsOn(rocketchip)
.settings(libraryDependencies ++= rocketLibDeps.value)
.settings(commonSettings)
lazy val constellation = (project in file("generators/constellation"))
.dependsOn(rocketchip)
.settings(libraryDependencies ++= rocketLibDeps.value)
@@ -182,6 +204,11 @@ lazy val boom = (project in file("generators/boom"))
.settings(libraryDependencies ++= rocketLibDeps.value)
.settings(commonSettings)
lazy val shuttle = (project in file("generators/shuttle"))
.dependsOn(rocketchip)
.settings(libraryDependencies ++= rocketLibDeps.value)
.settings(commonSettings)
lazy val cva6 = (project in file("generators/cva6"))
.dependsOn(rocketchip)
.settings(libraryDependencies ++= rocketLibDeps.value)
@@ -214,18 +241,13 @@ lazy val nvdla = (project in file("generators/nvdla"))
.settings(libraryDependencies ++= rocketLibDeps.value)
.settings(commonSettings)
lazy val iocell = Project(id = "iocell", base = file("./tools/barstools/") / "src")
.settings(
Compile / scalaSource := baseDirectory.value / "main" / "scala" / "barstools" / "iocell",
Compile / resourceDirectory := baseDirectory.value / "main" / "resources"
)
lazy val iocell = Project(id = "iocell", base = file("./tools/barstools/") / "iocell")
.settings(chiselSettings)
.settings(commonSettings)
lazy val tapeout = (project in file("./tools/barstools/"))
.settings(chiselSettings)
.settings(chiselTestSettings)
.enablePlugins(sbtassembly.AssemblyPlugin)
.settings(commonSettings)
lazy val dsptools = freshProject("dsptools", file("./tools/dsptools"))

231
common.mk
View File

@@ -16,11 +16,12 @@ HELP_COMPILATION_VARIABLES += \
" EXTRA_SIM_LDFLAGS = additional LDFLAGS for building simulators" \
" EXTRA_SIM_SOURCES = additional simulation sources needed for simulator" \
" EXTRA_SIM_REQS = additional make requirements to build the simulator" \
" ENABLE_SBT_THIN_CLIENT = if set, use sbt's experimental thin client (works best when overridding SBT_BIN with the mainline sbt script)" \
" ENABLE_CUSTOM_FIRRTL_PASS = if set, enable custom firrtl passes (SFC lowers to LowFIRRTL & MFC converts to Verilog)" \
" ENABLE_YOSYS_FLOW = if set, add compilation flags to enable the vlsi flow for yosys(tutorial flow)" \
" EXTRA_CHISEL_OPTIONS = additional options to pass to the Chisel compiler" \
" EXTRA_FIRRTL_OPTIONS = additional options to pass to the FIRRTL compiler"
" EXTRA_BASE_FIRRTL_OPTIONS = additional options to pass to the Scala FIRRTL compiler" \
" MFC_BASE_LOWERING_OPTIONS = override lowering options to pass to the MLIR FIRRTL compiler" \
" ASPECTS = comma separated list of Chisel aspect flows to run (e.x. chipyard.upf.ChipTopUPFAspect)"
EXTRA_GENERATOR_REQS ?= $(BOOTROM_TARGETS)
EXTRA_SIM_CXXFLAGS ?=
@@ -29,6 +30,11 @@ EXTRA_SIM_SOURCES ?=
EXTRA_SIM_REQS ?=
ENABLE_CUSTOM_FIRRTL_PASS += $(ENABLE_YOSYS_FLOW)
ifneq ($(ASPECTS), )
comma = ,
ASPECT_ARGS = $(foreach aspect, $(subst $(comma), , $(ASPECTS)), --with-aspect $(aspect))
endif
#----------------------------------------------------------------------------
HELP_SIMULATION_VARIABLES += \
" EXTRA_SIM_FLAGS = additional runtime simulation flags (passed within +permissive)" \
@@ -45,11 +51,13 @@ HELP_COMMANDS += \
" run-binary = run [./$(shell basename $(sim))] and log instructions to file" \
" run-binary-fast = run [./$(shell basename $(sim))] and don't log instructions" \
" run-binary-debug = run [./$(shell basename $(sim_debug))] and log instructions and waveform to files" \
" run-binaries = run [./$(shell basename $(sim))] and log instructions to file" \
" run-binaries-fast = run [./$(shell basename $(sim))] and don't log instructions" \
" run-binaries-debug = run [./$(shell basename $(sim_debug))] and log instructions and waveform to files" \
" verilog = generate intermediate verilog files from chisel elaboration and firrtl passes" \
" firrtl = generate intermediate firrtl files from chisel elaboration" \
" run-tests = run all assembly and benchmark tests" \
" launch-sbt = start sbt terminal" \
" {shutdown,start}-sbt-server = shutdown or start sbt server if using ENABLE_SBT_THIN_CLIENT" \
" find-config-fragments = list all config. fragments"
#########################################################################################
@@ -66,7 +74,7 @@ include $(base_dir)/tools/torture.mk
#########################################################################################
# Prerequisite lists
#########################################################################################
# Returns a list of files in directory $1 with file extension $2.
# Returns a list of files in directories $1 with single file extension $2.
# If available, use 'fd' to find the list of files, which is faster than 'find'.
ifeq ($(shell which fd 2> /dev/null),)
lookup_srcs = $(shell find -L $(1)/ -name target -prune -o \( -iname "*.$(2)" ! -iname ".*" \) -print 2> /dev/null)
@@ -74,9 +82,17 @@ else
lookup_srcs = $(shell fd -L -t f -e $(2) . $(1))
endif
SOURCE_DIRS = $(addprefix $(base_dir)/,generators sims/firesim/sim tools/barstools fpga/fpga-shells fpga/src)
SCALA_SOURCES = $(call lookup_srcs,$(SOURCE_DIRS),scala)
VLOG_SOURCES = $(call lookup_srcs,$(SOURCE_DIRS),sv) $(call lookup_srcs,$(SOURCE_DIRS),v)
# Returns a list of files in directories $1 with *any* of the file extensions in $2
lookup_srcs_by_multiple_type = $(foreach type,$(2),$(call lookup_srcs,$(1),$(type)))
SCALA_EXT = scala
VLOG_EXT = sv v
CHIPYARD_SOURCE_DIRS = $(addprefix $(base_dir)/,generators sims/firesim/sim fpga/fpga-shells fpga/src)
CHIPYARD_SCALA_SOURCES = $(call lookup_srcs_by_multiple_type,$(CHIPYARD_SOURCE_DIRS),$(SCALA_EXT))
CHIPYARD_VLOG_SOURCES = $(call lookup_srcs_by_multiple_type,$(CHIPYARD_SOURCE_DIRS),$(VLOG_EXT))
BARSTOOLS_SOURCE_DIRS = $(addprefix $(base_dir)/,tools/barstools)
BARSTOOLS_SCALA_SOURCES = $(call lookup_srcs_by_multiple_type,$(BARSTOOLS_SOURCE_DIRS),$(SCALA_EXT))
BARSTOOLS_VLOG_SOURCES = $(call lookup_srcs_by_multiple_type,$(BARSTOOLS_SOURCE_DIRS),$(VLOG_EXT))
# This assumes no SBT meta-build sources
SBT_SOURCE_DIRS = $(addprefix $(base_dir)/,generators sims/firesim/sim tools)
SBT_SOURCES = $(call lookup_srcs,$(SBT_SOURCE_DIRS),sbt) $(base_dir)/build.sbt $(base_dir)/project/plugins.sbt $(base_dir)/project/build.properties
@@ -102,16 +118,29 @@ $(BOOTROM_TARGETS): $(build_dir)/bootrom.%.img: $(TESTCHIP_RSRCS_DIR)/testchipip
cp -f $< $@
#########################################################################################
# create firrtl file rule and variables
# compile scala jars
#########################################################################################
$(CHIPYARD_CLASSPATH_TARGETS) &: $(CHIPYARD_SCALA_SOURCES) $(SCALA_BUILDTOOL_DEPS)
mkdir -p $(dir $@)
$(call run_sbt_assembly,$(SBT_PROJECT),$(CHIPYARD_CLASSPATH))
# order only dependency between sbt runs needed to avoid concurrent sbt runs
$(TAPEOUT_CLASSPATH_TARGETS) &: $(BARSTOOLS_SCALA_SOURCES) $(SCALA_BUILDTOOL_DEPS) | $(CHIPYARD_CLASSPATH_TARGETS)
mkdir -p $(dir $@)
$(call run_sbt_assembly,tapeout,$(TAPEOUT_CLASSPATH))
#########################################################################################
# verilog generation pipeline
#########################################################################################
# AG: must re-elaborate if cva6 sources have changed... otherwise just run firrtl compile
$(FIRRTL_FILE) $(ANNO_FILE) $(CHISEL_LOG_FILE) &: $(SCALA_SOURCES) $(SCALA_BUILDTOOL_DEPS) $(EXTRA_GENERATOR_REQS)
$(FIRRTL_FILE) $(ANNO_FILE) $(CHISEL_LOG_FILE) &: $(CHIPYARD_CLASSPATH_TARGETS) $(EXTRA_GENERATOR_REQS)
mkdir -p $(build_dir)
(set -o pipefail && $(call run_scala_main,$(SBT_PROJECT),$(GENERATOR_PACKAGE).Generator,\
(set -o pipefail && $(call run_jar_scala_main,$(CHIPYARD_CLASSPATH),$(GENERATOR_PACKAGE).Generator,\
--target-dir $(build_dir) \
--name $(long_name) \
--top-module $(MODEL_PACKAGE).$(MODEL) \
--legacy-configs $(CONFIG_PACKAGE):$(CONFIG) \
$(ASPECT_ARGS) \
$(EXTRA_CHISEL_OPTIONS)) | tee $(CHISEL_LOG_FILE))
define mfc_extra_anno_contents
@@ -162,7 +191,7 @@ SFC_MFC_TARGETS = \
$(GEN_COLLATERAL_DIR)
SFC_REPL_SEQ_MEM = --infer-rw --repl-seq-mem -c:$(MODEL):-o:$(SFC_SMEMS_CONF)
MFC_BASE_LOWERING_OPTIONS = emittedLineLength=2048,noAlwaysComb,disallowLocalVariables,verifLabels,locationInfoStyle=wrapInAtSquareBracket
MFC_BASE_LOWERING_OPTIONS ?= emittedLineLength=2048,noAlwaysComb,disallowLocalVariables,verifLabels,locationInfoStyle=wrapInAtSquareBracket
# DOC include start: FirrtlCompiler
# There are two possible cases for this step. In the first case, SFC
@@ -175,26 +204,33 @@ MFC_BASE_LOWERING_OPTIONS = emittedLineLength=2048,noAlwaysComb,disallowLocalVar
# hack: lower to low firrtl if Fixed types are found
# hack: when using dontTouch, io.cpu annotations are not removed by SFC,
# hence we remove them manually by using jq before passing them to firtool
$(SFC_LEVEL) $(EXTRA_FIRRTL_OPTIONS) $(FINAL_ANNO_FILE) $(MFC_LOWERING_OPTIONS) &: $(FIRRTL_FILE) $(EXTRA_ANNO_FILE) $(SFC_EXTRA_ANNO_FILE) $(VLOG_SOURCES)
$(SFC_LEVEL) $(EXTRA_FIRRTL_OPTIONS) &: $(FIRRTL_FILE)
ifeq (,$(ENABLE_CUSTOM_FIRRTL_PASS))
$(eval SFC_LEVEL := $(if $(shell grep "Fixed<" $(FIRRTL_FILE)), low, none))
$(eval EXTRA_FIRRTL_OPTIONS += $(if $(shell grep "Fixed<" $(FIRRTL_FILE)), $(SFC_REPL_SEQ_MEM),))
echo $(if $(shell grep "Fixed<" $(FIRRTL_FILE)), low, none) > $(SFC_LEVEL)
echo "$(EXTRA_BASE_FIRRTL_OPTIONS)" $(if $(shell grep "Fixed<" $(FIRRTL_FILE)), "$(SFC_REPL_SEQ_MEM)",) > $(EXTRA_FIRRTL_OPTIONS)
else
$(eval SFC_LEVEL := low)
$(eval EXTRA_FIRRTL_OPTIONS += $(SFC_REPL_SEQ_MEM))
echo low > $(SFC_LEVEL)
echo "$(EXTRA_BASE_FIRRTL_OPTIONS)" "$(SFC_REPL_SEQ_MEM)" > $(EXTRA_FIRRTL_OPTIONS)
endif
$(MFC_LOWERING_OPTIONS):
mkdir -p $(dir $@)
ifeq (,$(ENABLE_YOSYS_FLOW))
$(eval MFC_LOWERING_OPTIONS = $(MFC_BASE_LOWERING_OPTIONS))
echo "$(MFC_BASE_LOWERING_OPTIONS)" > $@
else
$(eval MFC_LOWERING_OPTIONS = $(MFC_BASE_LOWERING_OPTIONS),disallowPackedArrays)
echo "$(MFC_BASE_LOWERING_OPTIONS),disallowPackedArrays" > $@
endif
if [ $(SFC_LEVEL) = low ]; then jq -s '[.[][]]' $(EXTRA_ANNO_FILE) $(SFC_EXTRA_ANNO_FILE) > $(FINAL_ANNO_FILE); fi
if [ $(SFC_LEVEL) = none ]; then cat $(EXTRA_ANNO_FILE) > $(FINAL_ANNO_FILE); fi
$(FINAL_ANNO_FILE): $(EXTRA_ANNO_FILE) $(SFC_EXTRA_ANNO_FILE) $(SFC_LEVEL)
if [ $(shell cat $(SFC_LEVEL)) = low ]; then jq -s '[.[][]]' $(EXTRA_ANNO_FILE) $(SFC_EXTRA_ANNO_FILE) > $@; fi
if [ $(shell cat $(SFC_LEVEL)) = none ]; then cat $(EXTRA_ANNO_FILE) > $@; fi
touch $@
$(SFC_MFC_TARGETS) &: private TMP_DIR := $(shell mktemp -d -t cy-XXXXXXXX)
$(SFC_MFC_TARGETS) &: $(FIRRTL_FILE) $(FINAL_ANNO_FILE) $(SFC_LEVEL) $(EXTRA_FIRRTL_OPTIONS)
$(SFC_MFC_TARGETS) &: $(TAPEOUT_CLASSPATH_TARGETS) $(FIRRTL_FILE) $(FINAL_ANNO_FILE) $(SFC_LEVEL) $(EXTRA_FIRRTL_OPTIONS) $(MFC_LOWERING_OPTIONS) $(CHIPYARD_VLOG_SOURCES) $(BARSTOOLS_VLOG_SOURCES)
rm -rf $(GEN_COLLATERAL_DIR)
$(call run_scala_main,tapeout,barstools.tapeout.transforms.GenerateModelStageMain,\
$(call run_jar_scala_main,$(TAPEOUT_CLASSPATH),barstools.tapeout.transforms.GenerateModelStageMain,\
--no-dedup \
--output-file $(SFC_FIRRTL_BASENAME) \
--output-annotation-file $(SFC_ANNO_FILE) \
@@ -203,12 +239,12 @@ $(SFC_MFC_TARGETS) &: $(FIRRTL_FILE) $(FINAL_ANNO_FILE) $(SFC_LEVEL) $(EXTRA_FIR
--annotation-file $(FINAL_ANNO_FILE) \
--log-level $(FIRRTL_LOGLEVEL) \
--allow-unrecognized-annotations \
-X $(SFC_LEVEL) \
$(EXTRA_FIRRTL_OPTIONS))
-X $(shell cat $(SFC_LEVEL)) \
$(shell cat $(EXTRA_FIRRTL_OPTIONS)))
-mv $(SFC_FIRRTL_BASENAME).lo.fir $(SFC_FIRRTL_FILE) 2> /dev/null # Optionally change file type when SFC generates LowFIRRTL
@if [ $(SFC_LEVEL) = low ]; then cat $(SFC_ANNO_FILE) | jq 'del(.[] | select(.target | test("io.cpu"))?)' > $(TMP_DIR)/unnec-anno-deleted.sfc.anno.json; fi
@if [ $(SFC_LEVEL) = low ]; then cat $(TMP_DIR)/unnec-anno-deleted.sfc.anno.json | jq 'del(.[] | select(.class | test("SRAMAnnotation"))?)' > $(TMP_DIR)/unnec-anno-deleted2.sfc.anno.json; fi
@if [ $(SFC_LEVEL) = low ]; then cat $(TMP_DIR)/unnec-anno-deleted2.sfc.anno.json > $(SFC_ANNO_FILE) && rm $(TMP_DIR)/unnec-anno-deleted.sfc.anno.json && rm $(TMP_DIR)/unnec-anno-deleted2.sfc.anno.json; fi
@if [ $(shell cat $(SFC_LEVEL)) = low ]; then cat $(SFC_ANNO_FILE) | jq 'del(.[] | select(.target | test("io.cpu"))?)' > $(TMP_DIR)/unnec-anno-deleted.sfc.anno.json; fi
@if [ $(shell cat $(SFC_LEVEL)) = low ]; then cat $(TMP_DIR)/unnec-anno-deleted.sfc.anno.json | jq 'del(.[] | select(.class | test("SRAMAnnotation"))?)' > $(TMP_DIR)/unnec-anno-deleted2.sfc.anno.json; fi
@if [ $(shell cat $(SFC_LEVEL)) = low ]; then cat $(TMP_DIR)/unnec-anno-deleted2.sfc.anno.json > $(SFC_ANNO_FILE) && rm $(TMP_DIR)/unnec-anno-deleted.sfc.anno.json && rm $(TMP_DIR)/unnec-anno-deleted2.sfc.anno.json; fi
firtool \
--format=fir \
--dedup \
@@ -219,7 +255,7 @@ $(SFC_MFC_TARGETS) &: $(FIRRTL_FILE) $(FINAL_ANNO_FILE) $(SFC_LEVEL) $(EXTRA_FIR
--disable-annotation-classless \
--disable-annotation-unknown \
--mlir-timing \
--lowering-options=$(MFC_LOWERING_OPTIONS) \
--lowering-options=$(shell cat $(MFC_LOWERING_OPTIONS)) \
--repl-seq-mem \
--repl-seq-mem-file=$(MFC_SMEMS_CONF) \
--repl-seq-mem-circuit=$(MODEL) \
@@ -231,36 +267,24 @@ $(SFC_MFC_TARGETS) &: $(FIRRTL_FILE) $(FINAL_ANNO_FILE) $(SFC_LEVEL) $(EXTRA_FIR
$(SED) -i 's/.*/& /' $(MFC_SMEMS_CONF) # need trailing space for SFC macrocompiler
# DOC include end: FirrtlCompiler
$(TOP_MODS_FILELIST) $(MODEL_MODS_FILELIST) $(ALL_MODS_FILELIST) $(BB_MODS_FILELIST) $(MFC_MODEL_HRCHY_JSON_UNIQUIFIED) &: $(MFC_MODEL_HRCHY_JSON) $(MFC_FILELIST) $(MFC_BB_MODS_FILELIST)
$(base_dir)/scripts/split-module-files.py \
$(TOP_MODS_FILELIST) $(MODEL_MODS_FILELIST) $(ALL_MODS_FILELIST) $(BB_MODS_FILELIST) $(MFC_MODEL_HRCHY_JSON_UNIQUIFIED) &: $(MFC_MODEL_HRCHY_JSON) $(MFC_TOP_HRCHY_JSON) $(MFC_FILELIST) $(MFC_BB_MODS_FILELIST)
$(base_dir)/scripts/uniquify-module-names.py \
--model-hier-json $(MFC_MODEL_HRCHY_JSON) \
--top-hier-json $(MFC_TOP_HRCHY_JSON) \
--in-all-filelist $(MFC_FILELIST) \
--dut $(TOP) \
--model $(MODEL) \
--target-dir $(GEN_COLLATERAL_DIR) \
--out-dut-filelist $(TOP_MODS_FILELIST) \
--out-model-filelist $(MODEL_MODS_FILELIST) \
--in-all-filelist $(MFC_FILELIST) \
--target-dir $(GEN_COLLATERAL_DIR)
--out-model-hier-json $(MFC_MODEL_HRCHY_JSON_UNIQUIFIED) \
--gcpath $(GEN_COLLATERAL_DIR)
$(SED) -e 's;^;$(GEN_COLLATERAL_DIR)/;' $(MFC_BB_MODS_FILELIST) > $(BB_MODS_FILELIST)
$(SED) -i 's/\.\///' $(TOP_MODS_FILELIST)
$(SED) -i 's/\.\///' $(MODEL_MODS_FILELIST)
$(SED) -i 's/\.\///' $(BB_MODS_FILELIST)
$(base_dir)/scripts/uniqify-module-names.py \
--top-filelist $(TOP_MODS_FILELIST) \
--mod-filelist $(MODEL_MODS_FILELIST) \
--gen-collateral-path $(GEN_COLLATERAL_DIR) \
--model-hier-json $(MFC_MODEL_HRCHY_JSON) \
--out-model-hier-json $(MFC_MODEL_HRCHY_JSON_UNIQUIFIED) \
--dut $(TOP) \
--model $(MODEL)
sort -u $(TOP_MODS_FILELIST) $(MODEL_MODS_FILELIST) $(BB_MODS_FILELIST) > $(ALL_MODS_FILELIST)
$(TOP_BB_MODS_FILELIST) $(MODEL_BB_MODS_FILELIST) &: $(BB_MODS_FILELIST) $(MFC_TOP_HRCHY_JSON) $(FINAL_ANNO_FILE)
$(base_dir)/scripts/split-bb-files.py \
--in-bb-f $(BB_MODS_FILELIST) \
--in-top-hrchy-json $(MFC_TOP_HRCHY_JSON) \
--in-anno-json $(FINAL_ANNO_FILE) \
--out-top-bb-f $(TOP_BB_MODS_FILELIST) \
--out-model-bb-f $(MODEL_BB_MODS_FILELIST)
$(TOP_SMEMS_CONF) $(MODEL_SMEMS_CONF) &: $(MFC_SMEMS_CONF) $(MFC_MODEL_HRCHY_JSON_UNIQUIFIED)
$(base_dir)/scripts/split-mems-conf.py \
--in-smems-conf $(MFC_SMEMS_CONF) \
@@ -272,19 +296,19 @@ $(TOP_SMEMS_CONF) $(MODEL_SMEMS_CONF) &: $(MFC_SMEMS_CONF) $(MFC_MODEL_HRCHY_JS
# This file is for simulation only. VLSI flows should replace this file with one containing hard SRAMs
TOP_MACROCOMPILER_MODE ?= --mode synflops
$(TOP_SMEMS_FILE) $(TOP_SMEMS_FIR) &: $(TOP_SMEMS_CONF)
$(call run_scala_main,tapeout,barstools.macros.MacroCompiler,-n $(TOP_SMEMS_CONF) -v $(TOP_SMEMS_FILE) -f $(TOP_SMEMS_FIR) $(TOP_MACROCOMPILER_MODE))
$(TOP_SMEMS_FILE) $(TOP_SMEMS_FIR) &: $(TAPEOUT_CLASSPATH_TARGETS) $(TOP_SMEMS_CONF)
$(call run_jar_scala_main,$(TAPEOUT_CLASSPATH),barstools.macros.MacroCompiler,-n $(TOP_SMEMS_CONF) -v $(TOP_SMEMS_FILE) -f $(TOP_SMEMS_FIR) $(TOP_MACROCOMPILER_MODE))
MODEL_MACROCOMPILER_MODE = --mode synflops
$(MODEL_SMEMS_FILE) $(MODEL_SMEMS_FIR) &: $(MODEL_SMEMS_CONF) | $(TOP_SMEMS_FILE)
$(call run_scala_main,tapeout,barstools.macros.MacroCompiler, -n $(MODEL_SMEMS_CONF) -v $(MODEL_SMEMS_FILE) -f $(MODEL_SMEMS_FIR) $(MODEL_MACROCOMPILER_MODE))
$(MODEL_SMEMS_FILE) $(MODEL_SMEMS_FIR) &: $(TAPEOUT_CLASSPATH_TARGETS) $(MODEL_SMEMS_CONF) | $(TOP_SMEMS_FILE)
$(call run_jar_scala_main,$(TAPEOUT_CLASSPATH),barstools.macros.MacroCompiler, -n $(MODEL_SMEMS_CONF) -v $(MODEL_SMEMS_FILE) -f $(MODEL_SMEMS_FIR) $(MODEL_MACROCOMPILER_MODE))
########################################################################################
# remove duplicate files and headers in list of simulation file inputs
# note: {MODEL,TOP}_BB_MODS_FILELIST is added as a req. so that the files get generated,
# however it is really unneeded since ALL_MODS_FILELIST includes all BB files
########################################################################################
$(sim_common_files): $(sim_files) $(ALL_MODS_FILELIST) $(TOP_SMEMS_FILE) $(MODEL_SMEMS_FILE) $(TOP_BB_MODS_FILELIST) $(MODEL_BB_MODS_FILELIST)
$(sim_common_files): $(sim_files) $(ALL_MODS_FILELIST) $(TOP_SMEMS_FILE) $(MODEL_SMEMS_FILE) $(BB_MODS_FILELIST)
sort -u $(sim_files) $(ALL_MODS_FILELIST) | grep -v '.*\.\(svh\|h\)$$' > $@
echo "$(TOP_SMEMS_FILE)" >> $@
echo "$(MODEL_SMEMS_FILE)" >> $@
@@ -299,56 +323,81 @@ verilog: $(sim_common_files)
# helper rules to run simulations
#########################################################################################
.PHONY: run-binary run-binary-fast run-binary-debug run-fast
%.check-exists check-binary check-binaries
check-binary:
ifeq (,$(BINARY))
$(error BINARY variable is not set. Set it to the simulation binary)
endif
check-binaries:
ifeq (,$(BINARIES))
$(error BINARIES variable is not set. Set it to the list of simulation binaries to run)
endif
%.check-exists:
if [ "$*" != "none" ] && [ ! -f "$*" ]; then printf "\n\nBinary $* not found\n\n"; exit 1; fi
# allow you to override sim prereq
ifeq (,$(BREAK_SIM_PREREQ))
SIM_PREREQ = $(sim)
SIM_DEBUG_PREREQ = $(sim_debug)
endif
# Function to generate the loadmem flag. First arg is the binary
ifeq ($(LOADMEM),1)
# If LOADMEM=1, assume BINARY is the loadmem elf
get_loadmem_flag = +loadmem=$(1)
else ifneq ($(LOADMEM),)
# Otherwise, assume the variable points to an elf file
get_loadmem_flag = +loadmem=$(LOADMEM)
endif
ifneq ($(LOADARCH),)
get_loadarch_flag = +loadarch=$(subst mem.elf,loadarch,$(1))
endif
# get the output path base name for simulation outputs, First arg is the binary
get_sim_out_name = $(output_dir)/$(call get_out_name,$(1))
# sim flags that are common to run-binary/run-binary-fast/run-binary-debug
get_common_sim_flags = $(SIM_FLAGS) $(EXTRA_SIM_FLAGS) $(SEED_FLAG) $(call get_loadmem_flag,$(1)) $(call get_loadarch_flag,$(1))
.PHONY: %.run %.run.debug %.run.fast
# run normal binary with hardware-logged insn dissassembly
run-binary: $(SIM_PREREQ) check-binary | $(output_dir)
(set -o pipefail && $(NUMA_PREFIX) $(sim) $(PERMISSIVE_ON) $(SIM_FLAGS) $(EXTRA_SIM_FLAGS) $(SEED_FLAG) $(VERBOSE_FLAGS) $(PERMISSIVE_OFF) $(BINARY) </dev/null 2> >(spike-dasm > $(sim_out_name).out) | tee $(sim_out_name).log)
run-binary: check-binary $(BINARY).run
run-binaries: check-binaries $(addsuffix .run,$(BINARIES))
%.run: %.check-exists $(SIM_PREREQ) | $(output_dir)
(set -o pipefail && $(NUMA_PREFIX) $(sim) $(PERMISSIVE_ON) $(call get_common_sim_flags,$*) $(VERBOSE_FLAGS) $(PERMISSIVE_OFF) $* </dev/null 2> >(spike-dasm > $(call get_sim_out_name,$*).out) | tee $(call get_sim_out_name,$*).log)
# run simulator as fast as possible (no insn disassembly)
run-binary-fast: $(SIM_PREREQ) check-binary | $(output_dir)
(set -o pipefail && $(NUMA_PREFIX) $(sim) $(PERMISSIVE_ON) $(SIM_FLAGS) $(EXTRA_SIM_FLAGS) $(SEED_FLAG) $(PERMISSIVE_OFF) $(BINARY) </dev/null | tee $(sim_out_name).log)
run-binary-fast: check-binary $(BINARY).run.fast
run-binaries-fast: check-binaries $(addsuffix .run.fast,$(BINARIES))
%.run.fast: %.check-exists $(SIM_PREREQ) | $(output_dir)
(set -o pipefail && $(NUMA_PREFIX) $(sim) $(PERMISSIVE_ON) $(call get_common_sim_flags,$*) $(PERMISSIVE_OFF) $* </dev/null | tee $(call get_sim_out_name,$*).log)
# run simulator with as much debug info as possible
run-binary-debug: $(SIM_DEBUG_PREREQ) check-binary | $(output_dir)
(set -o pipefail && $(NUMA_PREFIX) $(sim_debug) $(PERMISSIVE_ON) $(SIM_FLAGS) $(EXTRA_SIM_FLAGS) $(SEED_FLAG) $(VERBOSE_FLAGS) $(WAVEFORM_FLAG) $(PERMISSIVE_OFF) $(BINARY) </dev/null 2> >(spike-dasm > $(sim_out_name).out) | tee $(sim_out_name).log)
run-binary-debug: check-binary $(BINARY).run.debug
run-binaries-debug: check-binaries $(addsuffix .run.debug,$(BINARIES))
%.run.debug: %.check-exists $(SIM_DEBUG_PREREQ) | $(output_dir)
if [ "$*" != "none" ]; then riscv64-unknown-elf-objdump -D -S $* > $(call get_sim_out_name,$*).dump ; fi
(set -o pipefail && $(NUMA_PREFIX) $(sim_debug) $(PERMISSIVE_ON) $(call get_common_sim_flags,$*) $(VERBOSE_FLAGS) $(call get_waveform_flag,$(call get_sim_out_name,$*)) $(PERMISSIVE_OFF) $* </dev/null 2> >(spike-dasm > $(call get_sim_out_name,$*).out) | tee $(call get_sim_out_name,$*).log)
run-fast: run-asm-tests-fast run-bmark-tests-fast
#########################################################################################
# helper rules to run simulator with fast loadmem via hex files
# helper rules to run simulator with fast loadmem
# LEGACY - use LOADMEM=1 instead
#########################################################################################
$(binary_hex): $(firstword $(BINARY)) | $(output_dir)
$(base_dir)/scripts/smartelf2hex.sh $(firstword $(BINARY)) > $(binary_hex)
run-binary-hex: check-binary
run-binary-hex: $(SIM_PREREQ) $(binary_hex) | $(output_dir)
run-binary-hex: run-binary
run-binary-hex: override LOADMEM_ADDR = 80000000
run-binary-hex: override LOADMEM = $(binary_hex)
run-binary-hex: override SIM_FLAGS += +loadmem=$(LOADMEM) +loadmem_addr=$(LOADMEM_ADDR)
run-binary-debug-hex: check-binary
run-binary-debug-hex: $(SIM_DEBUG_REREQ) $(binary_hex) | $(output_dir)
run-binary-debug-hex: run-binary-debug
run-binary-debug-hex: override LOADMEM_ADDR = 80000000
run-binary-debug-hex: override LOADMEM = $(binary_hex)
run-binary-debug-hex: override SIM_FLAGS += +loadmem=$(LOADMEM) +loadmem_addr=$(LOADMEM_ADDR)
run-binary-fast-hex: check-binary
run-binary-fast-hex: $(SIM_PREREQ) $(binary_hex) | $(output_dir)
run-binary-fast-hex: run-binary-fast
run-binary-fast-hex: override LOADMEM_ADDR = 80000000
run-binary-fast-hex: override LOADMEM = $(binary_hex)
run-binary-fast-hex: override SIM_FLAGS += +loadmem=$(LOADMEM) +loadmem_addr=$(LOADMEM_ADDR)
run-binary-hex: $(BINARY).run
run-binary-hex: override SIM_FLAGS += +loadmem=$(BINARY)
run-binary-debug-hex: $(BINARY).run.debug
run-binary-debug-hex: override SIM_FLAGS += +loadmem=$(BINARY)
run-binary-fast-hex: $(BINARY).run.fast
run-binary-fast-hex: override SIM_FLAGS += +loadmem=$(BINARY)
#########################################################################################
# run assembly/benchmarks rules
@@ -375,7 +424,6 @@ endif
#######################################
# Rules for building DRAMSim2 library
#######################################
dramsim_dir = $(base_dir)/tools/DRAMSim2
dramsim_lib = $(dramsim_dir)/libdramsim.a
@@ -383,27 +431,12 @@ $(dramsim_lib):
$(MAKE) -C $(dramsim_dir) $(notdir $@)
################################################
# Helper to run SBT or manage the SBT server
# Helper to run SBT
################################################
SBT_COMMAND ?= shell
.PHONY: launch-sbt
launch-sbt:
cd $(base_dir) && $(SBT_NON_THIN) "$(SBT_COMMAND)"
.PHONY: check-thin-client
check-thin-client:
ifeq (,$(ENABLE_SBT_THIN_CLIENT))
$(error ENABLE_SBT_THIN_CLIENT not set.)
endif
.PHONY: shutdown-sbt-server
shutdown-sbt-server: check-thin-client
cd $(base_dir) && $(SBT) "shutdown"
.PHONY: start-sbt-server
start-sbt-server: check-thin-client
cd $(base_dir) && $(SBT) "exit"
cd $(base_dir) && $(SBT) "$(SBT_COMMAND)"
#########################################################################################
# print help text (and other help)

View File

@@ -23,9 +23,9 @@ dependencies:
# bundle FireSim driver with deps into installer shell-script
- constructor
- gcc
- gxx
- sysroot_linux-64>=2.17 # needed to match pre-built CI XRT glibc version
- gcc<13
- gxx<13
- sysroot_linux-64=2.17 # needed to match pre-built CI XRT glibc version
- conda-gcc-specs
- binutils
@@ -89,11 +89,11 @@ dependencies:
- graphviz
- expect
- dtc
- verilator==4.226
- verilator==5.008
- screen
- elfutils
- libdwarf-dev==0.0.0.20190110_28_ga81397fc4 # from ucb-bar channel - using mainline libdwarf-feedstock
- conda-lock>=1
- conda-lock=1.4
# clang-format for driver coding style enforcement.
- clang-format
@@ -131,7 +131,7 @@ dependencies:
- pytest-mock
- moto
- mypy
- s3fs
- s3fs==0.4.2
- aiohttp
- pip:
- sure
@@ -143,6 +143,7 @@ dependencies:
- mypy-boto3-s3
- mypy_boto3_ec2
- botocore-stubs
- cryptography<41
- pytz
- types-pytz
- pyyaml

View File

@@ -15,4 +15,4 @@ dependencies:
# https://docs.conda.io/projects/conda/en/latest/user-guide/concepts/pkg-specs.html#package-match-specifications
# documentation on package_spec syntax for constraining versions
- esp-tools=1.0.1 # from ucb-bar channel - https://github.com/ucb-bar/esp-tools-feedstock
- esp-tools==1.0.1 # from ucb-bar channel - https://github.com/ucb-bar/esp-tools-feedstock

View File

@@ -15,4 +15,4 @@ dependencies:
# https://docs.conda.io/projects/conda/en/latest/user-guide/concepts/pkg-specs.html#package-match-specifications
# documentation on package_spec syntax for constraining versions
- riscv-tools=1.0.3 # from ucb-bar channel - https://github.com/ucb-bar/riscv-tools-feedstock
- riscv-tools==1.0.3 # from ucb-bar channel - https://github.com/ucb-bar/riscv-tools-feedstock

View File

@@ -0,0 +1,39 @@
.. _checkpointing:
Architectural Checkpoints
=========================
Chipyard supports generating architectural checkpoints using Spike.
These checkpoints contain a snapshot of the architectural state of a RISC-V SoC at some point in the execution of a program.
The checkpoints include the contents of cacheable memory, core architectural registers, and core CSRs.
RTL simulations of SoCs can resume execution from checkpoints after restoring the architectural state.
.. note::
Currently, only checkpoints of single-core systems are supported
Generating Checkpoints
------------------------
``scripts/generate-ckpt.sh`` is a script that runs spike with the right commands to generate an architectural checkpoint
``scripts/generate-ckpt.sh -h`` lists options for checkpoint generation.
Example: run the ``hello.riscv`` binary for 1000 instructions before generating a checkpoint.
This should produce a directory named ``hello.riscv.0x80000000.1000.loadarch``
.. code::
scripts/generate-ckpt.sh -b tests/hello.riscv -i 1000
Loading Checkpoints in RTL Simulation
--------------------------------------
Checkpoints can be loaded in RTL simulations with the ``LOADARCH`` flag.
The target config **MUST** use dmi-based bringup (as opposed to the default TSI-based bringup), and support fast ``LOADMEM``.
The target config should also match the architectural configuration of however spike was configured when generating the checkpoint.
.. code::
cd sims/vcs
make CONFIG=dmiRocketConfig run-binary LOADARCH=../../hello.riscv.0x80000000.1000.loadarch

View File

@@ -21,24 +21,37 @@ Consider the following example using CDEs.
class WithX(b: Boolean) extends Config((site, here, up) => {
case SomeKeyX => b
}
})
class WithY(b: Boolean) extends Config((site, here, up) => {
case SomeKeyY => b
}
})
When forming a query based on a ``Parameters`` object, like ``p(SomeKeyX)``, the configuration system traverses the "chain" of config fragments until it finds a partial function which is defined at the key, and then returns that value.
.. code:: scala
val params = Config(new WithX(true) ++ new WithY(true)) // "chain" together config fragments
val params = new Config(new WithX(true) ++ new WithY(true)) // "chain" together config fragments
params(SomeKeyX) // evaluates to true
params(SomeKeyY) // evaluates to true
params(SomeKeyZ) // evaluates to false
In this example, the evaluation of ``params(SomeKeyX)`` will terminate in the partial function defined in ``WithX(true)``, while the evaluation of ``params(SomeKeyY)`` will terminate in the partial function defined in ``WithY(true)``. Note that when no partial functions match, the evaluation will return the default value for that parameter.
Config fragments take precedence from left to right, meaning that a fragment at the start of the chain can override the value of a fragment to the right. It helps to read the fragment chain from right to left.
.. code:: scala
case object SomeKeyX extends Field[Int](0)
class WithX(n: Int) extends Config((site, here, up) => {
case SomeKeyX => n
})
val params = new Config(new WithX(10) ++ new WithX(5))
println(params(SomeKeyX)) // evaluates to 10
The real power of CDEs arises from the ``(site, here, up)`` parameters to the partial functions, which provide useful "views" into the global parameterization that the partial functions may access to determine a parameterization.
.. note::
@@ -54,10 +67,10 @@ Site
class WithXEqualsYSite extends Config((site, here, up) => {
case SomeKeyX => site(SomeKeyY) // expands to site(SomeKeyY, site)
}
})
val params_1 = Config(new WithXEqualsYSite ++ new WithY(true))
val params_2 = Config(new WithY(true) ++ new WithXEqualsYSite)
val params_1 = new Config(new WithXEqualsYSite ++ new WithY(true))
val params_2 = new Config(new WithY(true) ++ new WithXEqualsYSite)
params_1(SomeKeyX) // evaluates to true
params_2(SomeKeyX) // evaluates to true
@@ -75,10 +88,10 @@ Here
class WithXEqualsYHere extends Config((site, here, up) => {
case SomeKeyY => false
case SomeKeyX => here(SomeKeyY, site)
}
})
val params_1 = Config(new WithXEqualsYHere ++ new WithY(true))
val params_2 = Config(new WithY(true) ++ new WithXEqualsYHere)
val params_1 = new Config(new WithXEqualsYHere ++ new WithY(true))
val params_2 = new Config(new WithY(true) ++ new WithXEqualsYHere)
params_1(SomeKeyX) // evaluates to false
params_2(SomeKeyX) // evaluates to false
@@ -95,10 +108,10 @@ Up
class WithXEqualsYUp extends Config((site, here, up) => {
case SomeKeyX => up(SomeKeyY, site)
}
})
val params_1 = Config(new WithXEqualsYUp ++ new WithY(true))
val params_2 = Config(new WithY(true) ++ new WithXEqualsYUp)
val params_1 = new Config(new WithXEqualsYUp ++ new WithY(true))
val params_2 = new Config(new WithY(true) ++ new WithXEqualsYUp)
params_1(SomeKeyX) // evaluates to true
params_2(SomeKeyX) // evaluates to false

View File

@@ -47,12 +47,12 @@ Using the Tethered Serial Interface (TSI)
By default, Chipyard uses the Tethered Serial Interface (TSI) to communicate with the DUT.
TSI protocol is an implementation of HTIF that is used to send commands to the RISC-V DUT.
These TSI commands are simple R/W commands that are able to access the DUT's memory space.
During simulation, the host sends TSI commands to a simulation stub in the test harness called ``SimSerial``
(C++ class) that resides in a ``SimSerial`` Verilog module (both are located in the ``generators/testchipip``
During simulation, the host sends TSI commands to a simulation stub in the test harness called ``SimTSI``
(C++ class) that resides in a ``SimTSI`` Verilog module (both are located in the ``generators/testchipip``
project).
This ``SimSerial`` Verilog module then sends the TSI command recieved by the simulation stub
This ``SimTSI`` Verilog module then sends the TSI command recieved by the simulation stub
to an adapter that converts the TSI command into a TileLink request.
This conversion is done by the ``SerialAdapter`` module (located in the ``generators/testchipip`` project).
This conversion is done by the ``TSIToTileLink`` module (located in the ``generators/testchipip`` project).
After the transaction is converted to TileLink, the ``TLSerdesser`` (located in ``generators/testchipip``) serializes the
transaction and sends it to the chip (this ``TLSerdesser`` is sometimes also referred to as a digital serial-link or SerDes).
Once the serialized transaction is received on the chip, it is deserialized and masters a TileLink bus on the chip
@@ -76,7 +76,7 @@ simulation stub called ``SimDTM`` (C++ class) that resides in a ``SimDTM`` Veril
sends the DMI command recieved by the simulation stub into the DUT which then converts the DMI
command into a TileLink request. This conversion is done by the DTM named ``DebugModule`` in the ``generators/rocket-chip`` project.
When the DTM receives the program to load, it starts to write the binary byte-wise into memory.
This is considerably slower than the TSI protocol communication pipeline (i.e. ``SimSerial``/``SerialAdapter``/TileLink)
This is considerably slower than the TSI protocol communication pipeline (i.e. ``SimTSI``/``TSIToTileLink``/TileLink)
which directly writes the program binary to memory.
Starting the TSI or DMI Simulation
@@ -206,13 +206,17 @@ This type of simulation setup is done in the following multi-clock configuration
:start-after: DOC include start: MulticlockAXIOverSerialConfig
:end-before: DOC include end: MulticlockAXIOverSerialConfig
Bringup Setup of the Example Test Chip after Tapeout
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Softcore-driven Bringup Setup of the Example Test Chip after Tapeout
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
.. warning::
Bringing up test chips with a FPGA softcore as described here is discouraged.
An alternative approach using the FPGA to "bridge" between a host computer and the test chip is the preferred approach.
Assuming this example test chip is taped out and now ready to be tested, we can communicate with the chip using this serial-link.
For example, a common test setup used at Berkeley to evaluate Chipyard-based test-chips includes an FPGA running a RISC-V soft-core that is able to speak to the DUT (over an FMC).
This RISC-V soft-core would serve as the host of the test that will run on the DUT.
This is done by the RISC-V soft-core running FESVR, sending TSI commands to a ``SerialAdapter`` / ``TLSerdesser`` programmed on the FPGA.
This is done by the RISC-V soft-core running FESVR, sending TSI commands to a ``TSIToTileLink`` / ``TLSerdesser`` programmed on the FPGA.
Once the commands are converted to serialized TileLink, then they can be sent over some medium to the DUT
(like an FMC cable or a set of wires connecting FPGA outputs to the DUT board).
Similar to simulation, if the chip requests offchip memory, it can then send the transaction back over the serial-link.
@@ -222,4 +226,4 @@ The following image shows this flow:
.. image:: ../_static/images/chip-bringup.png
In fact, this exact type of bringup setup is what the following section discusses:
:ref:`Prototyping/VCU118:Introduction to the Bringup Design`.
:ref:_legacy-vcu118-bringup.

View File

@@ -5,34 +5,20 @@ Creating Clocks in the Test Harness
Chipyard currently allows the SoC design (everything under ``ChipTop``) to
have independent clock domains through diplomacy.
This implies that some reference clock enters the ``ChipTop`` and then is divided down into
separate clock domains.
From the perspective of the ``TestHarness`` module, the ``ChipTop`` clock and reset is
provided from a clock and reset called ``buildtopClock`` and ``buildtopReset``.
In the default case, this ``buildtopClock`` and ``buildtopReset`` is directly wired to the
clock and reset IO's of the ``TestHarness`` module.
However, the ``TestHarness`` has the ability to generate a standalone clock and reset signal
that is separate from the reference clock/reset of ``ChipTop``.
This allows harness components (including harness binders) the ability to "request" a clock
for a new clock domain.
This is useful for simulating systems in which modules in the harness have independent clock domains
from the DUT.
``ChipTop`` clock ports are driven by ``harnessClockInstantiator.requestClock(freq)``.
``ChipTop`` reset ports are driven by the ``referenceReset()`` function, which is intended to provide an asynchronous reset.
Requests for a harness clock is done by the ``HarnessClockInstantiator`` class in ``generators/chipyard/src/main/scala/TestHarness.scala``.
This class is accessed in harness components by referencing the Rocket Chip parameters key ``p(HarnessClockInstantiatorKey)``.
Then you can request a clock and syncronized reset at a particular frequency by invoking the ``requestClockBundle`` function.
The ``HarnessBinder`` s in ``ChipTop`` are clocked by the ``HarnessBinderClockFrequencyKey`` value. The reset is provided as a synchronous reset, sync'd to the clock.
Requests for a harness clock is done by the ``HarnessClockInstantiator`` class in ``generators/chipyard/src/main/scala/harness/HarnessClocks.scala``.
Then you can request a clock and syncronized reset at a particular frequency by invoking the ``requestClock`` function.
Take the following example:
.. literalinclude:: ../../generators/chipyard/src/main/scala/HarnessBinders.scala
.. literalinclude:: ../../generators/chipyard/src/main/scala/harness/HarnessBinders.scala
:language: scala
:start-after: DOC include start: HarnessClockInstantiatorEx
:end-before: DOC include end: HarnessClockInstantiatorEx
Here you can see the ``p(HarnessClockInstantiatorKey)`` is used to request a clock and reset at ``memFreq`` frequency.
Here you can see the ``th.harnessClockInstantiator`` is used to request a clock and reset at ``memFreq`` frequency.
.. note::
In the case that the reference clock entering ``ChipTop`` is not the overall reference clock of the simulation
(i.e. the clock/reset coming into the ``TestHarness`` module), the ``buildtopClock`` and ``buildtopReset`` can
differ from the implicit ``TestHarness`` clock and reset. For example, if the ``ChipTop`` reference is 500MHz but an
extra harness clock is requested at 1GHz, the ``TestHarness`` implicit clock/reset will be at 1GHz while the ``buildtopClock``
and ``buildtopReset`` will be at 500MHz.

View File

@@ -2,24 +2,24 @@ 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 ``addResource`` function given by FIRRTL.
An example of its use can be seen in `generators/testchipip/src/main/scala/SerialAdapter.scala <https://github.com/ucb-bar/testchipip/blob/master/src/main/scala/SerialAdapter.scala>`_.
An example of its use can be seen in `generators/testchipip/src/main/scala/SimTSI.scala <https://github.com/ucb-bar/testchipip/blob/master/src/main/scala/SimTSI.scala>`_.
Here is the example inlined:
.. code-block:: scala
class SimSerial(w: Int) extends BlackBox with HasBlackBoxResource {
class SimTSI extends BlackBox with HasBlackBoxResource {
val io = IO(new Bundle {
val clock = Input(Clock())
val reset = Input(Bool())
val serial = Flipped(new SerialIO(w))
val tsi = Flipped(new TSIIO)
val exit = Output(Bool())
})
addResource("/testchipip/vsrc/SimSerial.v")
addResource("/testchipip/csrc/SimSerial.cc")
addResource("/testchipip/vsrc/SimTSI.v")
addResource("/testchipip/csrc/SimTSI.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.
In this example, the ``SimTSI`` files will be copied from a specific folder (in this case the ``path/to/testchipip/src/main/resources/testchipip/...``) to the build folder.
The ``addResource`` path retrieves resources from the ``src/main/resources`` directory.
So to get an item at ``src/main/resources/fileA.v`` you can use ``addResource("/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.

View File

@@ -16,3 +16,4 @@ They expect you to know about Chisel, Parameters, configs, etc.
CDEs
Harness-Clocks
Managing-Published-Scala-Dependencies
Architectural-Checkpoints

View File

@@ -83,8 +83,8 @@ This example shows the Chipyard default top that composes multiple traits togeth
:end-before: DOC include end: DigitalTop
There are two "cakes" or mixins here. One for the lazy module (ex. ``CanHavePeripherySerial``) and one for the lazy module
implementation (ex. ``CanHavePeripherySerialModuleImp`` where ``Imp`` refers to implementation). The lazy module defines
There are two "cakes" or mixins here. One for the lazy module (ex. ``CanHavePeripheryTLSerial``) and one for the lazy module
implementation (ex. ``CanHavePeripheryTLSerialModuleImp`` where ``Imp`` refers to implementation). The lazy module defines
all the logical connections between generators and exchanges configuration information among them, while the
lazy module implementation performs the actual Chisel RTL elaboration.
@@ -93,19 +93,17 @@ In the ``DigitalTop`` example class, the "outer" ``DigitalTop`` instantiates the
of the module until all logical connections are determined and all configuration information is exchanged.
The ``System`` outer base class, as well as the
``CanHavePeriphery<X>`` outer traits contain code to perform high-level logical
connections. For example, the ``CanHavePeripherySerial`` outer trait contains code
to optionally lazily instantiate the ``SerialAdapter``, and connect the ``SerialAdapter``'s
connections. For example, the ``CanHavePeripheryTLSerial`` outer trait contains code
to optionally lazily instantiate the ``TLSerdesser``, and connect the ``TLSerdesser`` 's
TileLink node to the Front bus.
The ``ModuleImp`` classes and traits perform elaboration of real RTL.
For example, the ``CanHavePeripherySerialModuleImp`` trait optionally physically connects
the ``SerialAdapter`` module, and instantiates queues.
In the test harness, the SoC is elaborated with
``val dut = p(BuildTop)(p)``.
After elaboration, the system submodule of ``ChipTop`` will be a ``DigitalTop`` module, which contains a
``SerialAdapter`` module (among others), if the config specified for that block to be instantiated.
``TLSerdesser`` module (among others), if the config specified for that block to be instantiated.
From a high level, classes which extend ``LazyModule`` *must* reference
their module implementation through ``lazy val module``, and they
@@ -116,7 +114,7 @@ other normal modules OR lazy modules (for nested Diplomacy
graphs, for example).
The naming convention for an additive mixin or trait is ``CanHave<YourMixin>``.
This is shown in the ``Top`` class where things such as ``CanHavePeripherySerial`` connect a RTL component to a bus and expose signals to the top-level.
This is shown in the ``Top`` class where things such as ``CanHavePeripheryTLSerial`` connect a RTL component to a bus and expose signals to the top-level.
Additional References
---------------------------

View File

@@ -27,29 +27,28 @@ Conda allows users to create an "environment" that holds system dependencies lik
.. Note:: Chipyard can also run on systems without a Conda installation. However, users on these systems must manually install toolchains and dependencies.
First, Chipyard requires Conda to be installed on the system.
Please refer to the `Conda installation instructions <https://github.com/conda-forge/miniforge/#download>`__ on how to install Conda with the **Miniforge** installer.
Afterwards, verify that Conda is a sufficient version (we test on version 4.12.0 but higher is most likely fine).
.. Note:: If you have installed conda separately from this documentation (i.e. from miniconda or full Anaconda), please ensure you follow https://conda-forge.org/docs/user/introduction.html#how-can-i-install-packages-from-conda-forge to use ``conda-forge`` packages without any issues.
.. code-block:: shell
conda --version # must be version 4.12.0 or higher
First, Chipyard requires the latest Conda to be installed on the system.
Please refer to the `Conda installation instructions <https://github.com/conda-forge/miniforge/#download>`__ on how to install the latest Conda with the **Miniforge** installer.
After Conda is installed and is on your ``PATH``, we need to install a version of ``git`` to initially checkout the repository.
For this you can use the system package manager like ``yum`` or ``apt`` to install ``git``.
This ``git`` is only used to first checkout the repository, we will later install a newer version of ``git`` with Conda.
Next, we install `libmamba <https://www.anaconda.com/blog/a-faster-conda-for-a-growing-community>`__ for much faster dependency solving when initially setting up the repository.
.. code-block:: shell
conda install -n base conda-libmamba-solver
conda config --set solver libmamba
Finally we need to install ``conda-lock`` into the ``base`` conda environment.
This is done by the following:
.. code-block:: shell
conda install -n base conda-lock
conda install -n base conda-lock=1.4
conda activate base
.. Note:: We also recommended switching to `libmamba <https://www.anaconda.com/blog/a-faster-conda-for-a-growing-community>`__ for much faster dependency solving.
Setting up the Chipyard Repo
-------------------------------------------
@@ -71,7 +70,27 @@ Run the following script based off which compiler you would like to use.
.. Note:: Prior versions of Chipyard recommended ``esp-tools`` for Gemmini development. Gemmini should now be used with the standard ``riscv-tools``.
.. Warning:: The following script will complete a "full" installation of Chipyard which may take a long time depending on the system.
Ensure that this script completes fully (no interruptions) before continuing on.
Ensure that this script completes fully (no interruptions) before continuing on. User can use the ``--skip`` or ``-s`` flag to skip steps:
``-s 1`` skips initializing Conda environment
``-s 2`` skips initializing Chipyard submodules
``-s 3`` skips initializing toolchain collateral (Spike, PK, tests, libgloss)
``-s 4`` skips initializing ctags
``-s 5`` skips pre-compiling Chipyard Scala sources
``-s 6`` skips initializing FireSim
``-s 7`` skips pre-compiling FireSim sources
``-s 8`` skips initializing FireMarshal
``-s 9`` skips pre-compiling FireMarshal default buildroot Linux sources
``-s 10`` skips running repository clean-up
.. code-block:: shell
@@ -120,7 +139,7 @@ You can source this file in your ``.bashrc`` or equivalent environment setup fil
However, it is recommended that the final ``env.sh`` file sourced is the ``env.sh`` located in the
Chipyard repo that you expect to run ``make`` commands in.
Pre-built Docker Image
DEPRECATED: Pre-built Docker Image
-------------------------------------------
An alternative to setting up the Chipyard repository locally is to pull the pre-built Docker image from Docker Hub. The image comes with all dependencies installed, Chipyard cloned, and toolchains initialized. This image sets up baseline Chipyard (not including FireMarshal, FireSim, and Hammer initializations). Each image comes with a tag that corresponds to the version of Chipyard cloned/set-up in that image. Not including a tag during the pull will pull the image with the latest version of Chipyard.

View File

@@ -52,8 +52,22 @@ Then add ``yourproject`` to the Chipyard top-level build.sbt file.
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
the ``chipyard`` project, change the final line in build.sbt to the following.
the ``chipyard`` project, add your project to the list of sub-projects in the
`.dependsOn()` for `lazy val chipyard`. The original code may change over time, but it
should look something like this:
.. code-block:: scala
lazy val chipyard = (project in file(".")).settings(commonSettings).dependsOn(testchipip, yourproject)
lazy val chipyard = (project in file("generators/chipyard"))
.dependsOn(testchipip, rocketchip, boom, hwacha, sifive_blocks, sifive_cache, iocell,
sha3, dsptools, `rocket-dsp-utils`,
gemmini, icenet, tracegen, cva6, nvdla, sodor, ibex, fft_generator,
yourproject, // <- added to the middle of the list for simplicity
constellation, mempress)
.settings(libraryDependencies ++= rocketLibDeps.value)
.settings(
libraryDependencies ++= Seq(
"org.reflections" % "reflections" % "0.10.2"
)
)
.settings(commonSettings)

View File

@@ -31,7 +31,7 @@ Like ``IOBinders``, ``HarnessBinders`` are defined using macros (``OverrideHarne
For exmaple, the ``WithUARTAdapter`` will connect the UART SW display adapter to the ports generated by the ``WithUARTIOCells`` described earlier, if those ports are present.
.. literalinclude:: ../../generators/chipyard/src/main/scala/HarnessBinders.scala
.. literalinclude:: ../../generators/chipyard/src/main/scala/harness/HarnessBinders.scala
:language: scala
:start-after: DOC include start: WithUARTAdapter
:end-before: DOC include end: WithUARTAdapter

View File

@@ -94,7 +94,7 @@ memory channel.
Instead of connecting to off-chip DRAM, you can instead connect a scratchpad
and remove the off-chip link. This is done by adding a fragment like
``testchipip.WithBackingScratchpad`` to your configuration and removing the
``testchipip.WithScratchpad`` to your configuration and removing the
memory port with ``freechips.rocketchip.subsystem.WithNoMemPort``.
.. literalinclude:: ../../generators/chipyard/src/main/scala/config/RocketConfigs.scala

View File

@@ -1,10 +1,15 @@
.. _rocc-accelerators:
Adding a RoCC Accelerator
----------------------------
-------------------------
RoCC accelerators are lazy modules that extend the ``LazyRoCC`` class.
Their implementation should extends the ``LazyRoCCModule`` class.
A RoCC accelerator is a component that can be added into a particular Rocket or BooM tile.
It receives instructions that match a certain opcode, talks to other parts of the core or SoC (L1, L2, PTW, FPU), and then optionally writes back a value into the register corresponding with the ``rd`` field of the instruction.
RoCC accelerators are instantiated via modules that extend the ``LazyRoCC`` class.
These modules lazily instantiate another module which extends the ``LazyRoCCModule`` class.
This extra layer of indirection is used so that Diplomacy can figure out how to connect the RoCC module to the chip, without needing to instantiate the module ahead of time.
Lazy modules are further explained in the :ref:`Chipyard-Basics/Configs-Parameters-Mixins:Cake Pattern / Mixin` section.
Below is a minimal instantiation of a RoCC accelerator.
.. code-block:: scala
@@ -31,7 +36,6 @@ Their implementation should extends the ``LazyRoCCModule`` class.
...
}
The ``opcodes`` parameter for ``LazyRoCC`` is the set of custom opcodes that will map to this accelerator.
More on this in the next subsection.
@@ -46,6 +50,47 @@ the ``busy`` signal, which indicates when the accelerator is still handling an i
and the ``interrupt`` signal, which can be used to interrupt the CPU.
Look at the examples in ``generators/rocket-chip/src/main/scala/tile/LazyRoCC.scala`` for detailed information on the different IOs.
There is also more information about each of the signals in `the RoCC Documentation written by UCSD <https://docs.google.com/document/d/1CH2ep4YcL_ojsa3BVHEW-uwcKh1FlFTjH_kg5v8bxVw/edit>`_, although it is updated out of tree and may be out of date.
Accessing Memory via L1 Cache
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
A RoCC accelerator can access memory through the L1 Cache of the core it is attached to.
This is a simpler interface for accelerator architects to implement, but will generally have lower achievable throughput than a dedicated TileLink port.
In your ``LazyRoCCModuleImp``, the signal ``io.mem`` is a ``HellaCacheIO``, which is defined in ``generators/rocket-chip/src/main/scala/rocket/HellaCache.scala``.
.. code-block:: scala
class HellaCacheIO(implicit p: Parameters) extends CoreBundle()(p) {
val req = Decoupled(new HellaCacheReq)
val s1_kill = Output(Bool()) // kill previous cycle's req
val s1_data = Output(new HellaCacheWriteData()) // data for previous cycle's req
val s2_nack = Input(Bool()) // req from two cycles ago is rejected
val s2_nack_cause_raw = Input(Bool()) // reason for nack is store-load RAW hazard (performance hint)
val s2_kill = Output(Bool()) // kill req from two cycles ago
val s2_uncached = Input(Bool()) // advisory signal that the access is MMIO
val s2_paddr = Input(UInt(paddrBits.W)) // translated address
val resp = Flipped(Valid(new HellaCacheResp))
val replay_next = Input(Bool())
val s2_xcpt = Input(new HellaCacheExceptions)
val s2_gpa = Input(UInt(vaddrBitsExtended.W))
val s2_gpa_is_pte = Input(Bool())
val uncached_resp = tileParams.dcache.get.separateUncachedResp.option(Flipped(Decoupled(new HellaCacheResp)))
val ordered = Input(Bool())
val perf = Input(new HellaCachePerfEvents())
val keep_clock_enabled = Output(Bool()) // should D$ avoid clock-gating itself?
val clock_enabled = Input(Bool()) // is D$ currently being clocked?
}
At a high level, you must tag requests that you send across this interface using the ``io.mem.req.tag``, and the tag will be returned to you when the data is ready.
Responses may come back out of order if you issue multiple requests, so you can use these tags to tell what data came back.
Note that the number of tag bits is controled by ``dcacheReqTagBits``, which is usually set to 6.
Using more than 6 bits will cause errors or hangs.
Adding RoCC accelerator to Config
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
@@ -67,3 +112,4 @@ For instance, if we wanted to add the previously defined accelerator and route c
new RocketConfig)
To add RoCC instructions in your program, use the RoCC C macros provided in ``tests/rocc.h``. You can find examples in the files ``tests/accum.c`` and ``charcount.c``.

View File

@@ -0,0 +1,9 @@
Prefetchers
====================================
The BAR-fetchers library is a collection of Chisel-implemented prefetchers, designed for compatibility with Chipyard and Rocket-Chip SoCs.
This package implements a generic prefetcher API, and example implementations of NextLine, Strided, and AMPM prefetchers.
Prefetchers can be instantiated in front of a L1D HellaCache, or as TileLink nodes in front of some TileLink bus.
An example configuration using prefetchers is found in the ``PrefetchingRocketConfig``

View File

@@ -0,0 +1,8 @@
Shuttle RISC-V Core
===================
Shuttle is a Rocket-based superscalar in-order RISC-V core, supporting the base RV64IMAFDC instruction set with supervisor and user-mode. Shuttle is a 6-stage core that can be configured to be dual, three, or quad-issue, although dual-issue is the most sensible design point. Shuttle is not designed to meet any power, performance, or area targets. It exists purely as a demonstrative example of another RISC-V CPU design point.
The superscalar microarchitecture presents the most advantages for 1) floating-point kernels and 2) RoCC accelerator kernels, as scalar control code can execute concurrently with floating point or RoCC instructions, maintaining high utilization of those units.
Shuttle is tape-out proven, and has similar physical design complexity as Rocket.

View File

@@ -2,16 +2,16 @@ Test Chip IP
============
Chipyard includes a Test Chip IP library which provides various hardware
widgets that may be useful when designing SoCs. This includes a :ref:`Generators/TestChipIP:Serial Adapter`,
widgets that may be useful when designing SoCs. This includes a :ref:`Generators/TestChipIP:SimTSI`,
:ref:`Generators/TestChipIP:Block Device Controller`, :ref:`Generators/TestChipIP:TileLink SERDES`, :ref:`Generators/TestChipIP:TileLink Switcher`,
:ref:`Generators/TestChipIP:TileLink Ring Network`, and :ref:`Generators/TestChipIP:UART Adapter`.
Serial Adapter
SimTSI
--------------
The serial adapter is used by tethered test chips to communicate with the host
The SimTSI and TSIToTileLink are used by tethered test chips to communicate with the host
processor. An instance of RISC-V frontend server running on the host CPU
can send commands to the serial adapter to read and write data from the memory
can send commands to the TSIToTileLink to read and write data from the memory
system. The frontend server uses this functionality to load the test program
into memory and to poll for completion of the program. More information on
this can be found in :ref:`Customization/Boot-Process:Chipyard Boot Process`.

View File

@@ -33,4 +33,6 @@ so changes to the generators themselves will automatically be used when building
fft
NVDLA
Sodor
Shuttle
Mempress
Prefetchers

View File

@@ -1,18 +1,11 @@
General Setup and Usage
==============================
Sources and Submodule Setup
Sources
---------------------------
All FPGA prototyping-related collateral and sources are located in the ``fpga`` top-level Chipyard directory.
This includes the ``fpga-shells`` submodule and the ``src`` directory that hold both Scala, TCL and other collateral.
However, the ``fpga-shells`` submodule repository is not initialized by default.
To initialize the ``fpga-shells`` submodule repository, run the included initialization script from the Chipyard top-level directory:
.. code-block:: shell
# in the chipyard top level folder
./scripts/init-fpga.sh
Generating a Bitstream
----------------------

View File

@@ -47,8 +47,14 @@ After the harness is created, the ``BundleBridgeSource``'s must be connected to
This is done with harness binders and io binders (see ``fpga/src/main/scala/vcu118/HarnessBinders.scala`` and ``fpga/src/main/scala/vcu118/IOBinders.scala``).
For more information on harness binders and io binders, refer to :ref:`Customization/IOBinders:IOBinders and HarnessBinders`.
Introduction to the Bringup Design
----------------------------------
(Legacy) Introduction to the Legacy Bringup Design
--------------------------------------------------
.. warning::
The bringup VCU118 design described here is designed for old versions of Chipyard SoCs, pre-1.9.1.
The key difference is that these designs rely on a clock generated on-chip to synchronize the slow serialized-TileLink interface.
After Chipyard 1.9.1, the FPGA host is expected to pass the clock to the chip, instead of the other way around.
A new bringup solution will be developed for post-1.9.1 Chipyard designs.
An example of a more complicated design used for Chipyard test chips can be viewed in ``fpga/src/main/scala/vcu118/bringup/``.
This example extends the default test harness and creates new ``Overlays`` to connect to a DUT (connected to the FMC port).

View File

@@ -26,9 +26,9 @@ Finally, source the following environment at the root of the FireSim directory:
cd sims/firesim
# (Recommended) The default manager environment (includes env.sh)
source sourceme-f1-manager.sh
source sourceme-manager.sh
.. Note:: Every time you want to use FireSim with a fresh shell, you must source this ``sourceme-f1-manager.sh``
.. Note:: Every time you want to use FireSim with a fresh shell, you must source ``sourceme-manager.sh``
At this point you're ready to use FireSim with Chipyard. If you're not already
familiar with FireSim, please return to the :fsim_doc:`FireSim Docs <Initial-Setup/Setting-up-your-Manager-Instance.html#completing-setup-using-the-manager>`,

View File

@@ -151,25 +151,17 @@ Fast Memory Loading
-------------------
The simulator loads the program binary over a simulated serial line. This can be quite slow if there is a lot of static data, so the simulator also allows data to be loaded from a file directly into the DRAM model.
Loadmem files should be ELF files. In the most common use case, this can be the binary.
.. code-block:: shell
make run-binary BINARY=test.riscv LOADMEM=testdata.hex LOADMEM_ADDR=81000000
make run-binary BINARY=test.riscv LOADMEM=test.riscv
The ``.hex`` file should be a text file with a hexadecimal number on each line.
.. code-block:: text
deadbeef
0123
Each line uses little-endian order, so this file would produce the bytes "ef be ad de 01 23". ``LOADMEM_ADDR`` specifies which address in memory (in hexadecimal) to write the first byte to. The default is 0x81000000.
A special target that facilitates automatically generating a hex file for an entire elf RISC-V exectuable and then running the simulator with the appropriate flags is also available.
Usually the ``LOADMEM`` ELF is the same as the ``BINARY`` ELF, so ``LOADMEM=1`` can be used as a shortcut.
.. code-block:: shell
make run-binary-hex BINARY=test.riscv
make run-binary BINARY=test.riscv LOADMEM=1
Generating Waveforms
-----------------------

View File

@@ -43,7 +43,7 @@ Spike-as-a-Tile can be configured with custom IPC, commit logging, and other beh
.. code-block:: shell
make CONFIG=SpikeUltraFastConfig run-binary-hex BINARY=hello.riscv EXTRA_SPIKE_FLAGS="+spike-ipc=10000 +spike-fast-clint +spike-debug"
make CONFIG=SpikeUltraFastConfig run-binary BINARY=hello.riscv EXTRA_SPIKE_FLAGS="+spike-ipc=10000 +spike-fast-clint +spike-debug" LOADMEM=1
* ``+spike-ipc=``: Sets the maximum number of instructions Spike can retire in a single "tick", or cycle of the uncore simulation.

View File

@@ -66,6 +66,12 @@ In the Chipyard root, ensure that you have the Chipyard conda environment activa
to pull and install the plugin submodules. Note that for technologies other than ``sky130`` or ``asap7``, the tech submodule must be added in the ``vlsi`` folder first.
Now navigate to the ``vlsi`` directory. The remainder of the tutorial will assume you are in this directory.
.. code-block:: shell
cd ~chipyard/vlsi
Building the Design
--------------------
To elaborate the ``TinyRocketConfig`` and set up all prerequisites for the build system to push the design and SRAM macros through the flow:
@@ -115,7 +121,7 @@ Timing reports are found in ``build/par-rundir/timingReports``. They are gzipped
.. code-block:: shell
./view_gds.py build/chipyard.TestHarness.TinyRocketConfig/par-rundir/ChipTop.gds
./view_gds.py build/chipyard.harness.TestHarness.TinyRocketConfig/par-rundir/ChipTop.gds
By default, this script only shows the M2 thru M4 routing. Layers can be toggled in the layout viewer's side pane and ``view_gds.py`` has a mapping of layer numbers to layer names.
@@ -126,9 +132,9 @@ To run DRC & LVS, and view the results in Calibre:
.. code-block:: shell
make drc CONFIG=TinyRocketConfig
./build/chipyard.TestHarness.TinyRocketConfig-ChipTop/drc-rundir/generated-scripts/view-drc
./build/chipyard.harness.TestHarness.TinyRocketConfig-ChipTop/drc-rundir/generated-scripts/view-drc
make lvs CONFIG=TinyRocketConfig
./build/chipyard.TestHarness.TinyRocketConfig-ChipTop/lvs-rundir/generated-scripts/view-lvs
./build/chipyard.harness.TestHarness.TinyRocketConfig-ChipTop/lvs-rundir/generated-scripts/view-lvs
Some DRC errors are expected from this PDK, as explained in the `ASAP7 plugin readme <https://github.com/ucb-bar/hammer/blob/master/hammer/technology/asap7>`__.
Furthermore, the dummy SRAMs that are provided in this tutorial and PDK do not have any geometry inside, so will certainly cause DRC errors.

View File

@@ -106,3 +106,22 @@ With the Synopsys plugin, hierarchical RTL and gate-level simulation is supporte
* ``-$(VLSI_TOP)`` suffixes denote simulations/power analysis on a submodule in a hierarchical flow (remember to override this variable). Note that you must provide the testbenches for these modules since the default testbench only simulates a Chipyard-based ``ChipTop`` DUT instance.
The simulation configuration (e.g. binaries) can be edited for your design. See the ``Makefile`` and refer to Hammer's documentation for how to set up simulation parameters for your design.
UPF Generation Flow
-------------------------------
This VLSI flow experimentally supports generating Chisel-based `UPF <https://vlsitutorials.com/upf-low-power-vlsi/>`__ files using `Chisel Aspects <https://javadoc.io/doc/edu.berkeley.cs/chisel3_2.13/latest/chisel3/aop/Aspect.html>`__.
To generate UPF for any design, first modify the ``UPFInputs`` object in ``generators/chipyard/src/main/scala/upf/UPFInputs.scala`` to fit your design power specifications.
This involves filling in the ``upfInfo`` list with ``PowerDomainInput`` objects representing all the power domains you want in your design, along with specifying hierarchy and domain attributes.
The given example in ``UPFInputs`` corresponds to a dual-core Rocket config with 3 power domains (1 parent domain with all uncore modules and 2 children corresponding to the Rocket tiles).
To run the flow:
.. code-block:: shell
cd chipyard/vlsi
make verilog ASPECTS=chipyard.upf.ChipTopUPFAspect
The output UPF files will be dumped in ``vlsi/generated-src/upf``.

View File

@@ -121,7 +121,7 @@ It is recommended that you edit these variables directly in the Makefile rather
The ``buildfile`` make target has dependencies on both (1) the Verilog that is elaborated from all Chisel sources
and (2) the mapping of memory instances in the design to SRAM macros;
all files related to these two steps reside in the ``generated-src/chipyard.TestHarness.TinyRocketConfig-ChipTop`` directory.
all files related to these two steps reside in the ``generated-src/chipyard.harness.TestHarness.TinyRocketConfig-ChipTop`` directory.
Note that the files in ``generated-src`` vary for each tool/technology flow.
This especially applies to the Sky130 Commercial vs OpenROAD tutorial flows
(due to the ``ENABLE_YOSYS_FLOW`` flag present for the OpenROAD flow), so these flows should be run in separate
@@ -168,9 +168,9 @@ To run DRC & LVS, and view the results in Calibre:
.. code-block:: shell
make drc tutorial=sky130-commercial
./build/chipyard.TestHarness.TinyRocketConfig-ChipTop/drc-rundir/generated-scripts/view_drc
./build/chipyard.harness.TestHarness.TinyRocketConfig-ChipTop/drc-rundir/generated-scripts/view_drc
make lvs tutorial=sky130-commercial
./build/chipyard.TestHarness.TinyRocketConfig-ChipTop/lvs-rundir/generated-scripts/view_lvs
./build/chipyard.harness.TestHarness.TinyRocketConfig-ChipTop/lvs-rundir/generated-scripts/view_lvs
Some DRC errors are expected from this PDK, especially with regards to the SRAMs, as explained in the
`Sky130 Hammer plugin README <https://github.com/ucb-bar/hammer/blob/master/hammer/technology/sky130>`__.

View File

@@ -149,7 +149,7 @@ It is recommended that you edit these variables directly in the Makefile rather
The ``buildfile`` make target has dependencies on both (1) the Verilog that is elaborated from all Chisel sources
and (2) the mapping of memory instances in the design to SRAM macros;
all files related to these two steps reside in the ``generated-src/chipyard.TestHarness.TinyRocketConfig-ChipTop`` directory.
all files related to these two steps reside in the ``generated-src/chipyard.harness.TestHarness.TinyRocketConfig-ChipTop`` directory.
Note that the files in ``generated-src`` vary for each tool/technology flow.
This especially applies to the Sky130 Commercial vs OpenROAD tutorial flows
(due to the ``ENABLE_YOSYS_FLOW`` flag, explained below), so these flows should be run in separate
@@ -197,7 +197,7 @@ Hammer generates a convenient script to launch these sessions
.. code-block:: shell
cd ./build/chipyard.TestHarness.TinyRocketConfig-ChipTop/par-rundir
cd ./build/chipyard.harness.TestHarness.TinyRocketConfig-ChipTop/par-rundir
./generated-scripts/open_chip
Note that the conda OpenROAD package was compiled with the GUI disabled, so in order to view the layout,
@@ -212,7 +212,7 @@ These databases can be restored using the same ``open_chip`` script for debuggin
.. code-block:: shell
cd build/chipyard.TestHarness.TinyRocketConfig-ChipTop/par-rundir
cd build/chipyard.harness.TestHarness.TinyRocketConfig-ChipTop/par-rundir
./generated_scripts/open_chip -h
"
Usage: ./generated-scripts/open_chip [-t] [openroad_db_name]
@@ -245,9 +245,9 @@ To run DRC & LVS in Magic & Netgen, respectively:
.. code-block:: shell
make drc tutorial=sky130-openroad
./build/chipyard.TestHarness.TinyRocketConfig-ChipTop/drc-rundir/generated-scripts/view_drc
./build/chipyard.harness.TestHarness.TinyRocketConfig-ChipTop/drc-rundir/generated-scripts/view_drc
make lvs tutorial=sky130-openroad
./build/chipyard.TestHarness.TinyRocketConfig-ChipTop/lvs-rundir/generated-scripts/view_lvs
./build/chipyard.harness.TestHarness.TinyRocketConfig-ChipTop/lvs-rundir/generated-scripts/view_lvs
Note that in ``sky130-openroad.yml`` we have set the following YAML keys:

View File

@@ -22,7 +22,11 @@ class WithArtyTweaks extends Config(
new WithArtyUARTHarnessBinder ++
new WithDebugResetPassthrough ++
new chipyard.config.WithDTSTimebase(32768) ++
new chipyard.harness.WithHarnessBinderClockFreqMHz(32) ++
new chipyard.harness.WithAllClocksFromHarnessClockInstantiator ++
new chipyard.config.WithDTSTimebase(32000) ++
new chipyard.config.WithSystemBusFrequency(32) ++
new chipyard.config.WithPeripheryBusFrequency(32) ++
new testchipip.WithNoSerialTL
)

View File

@@ -31,7 +31,7 @@ class WithArtyResetHarnessBinder extends ComposeHarnessBinder({
class WithArtyJTAGHarnessBinder extends OverrideHarnessBinder({
(system: HasPeripheryDebug, th: ArtyFPGATestHarness, ports: Seq[Data]) => {
ports.map {
case j: JTAGChipIO => withClockAndReset(th.buildtopClock, th.hReset) {
case j: JTAGChipIO => {
val jtag_wire = Wire(new JTAGIO)
jtag_wire.TDO.data := j.TDO
jtag_wire.TDO.driven := true.B

View File

@@ -3,18 +3,15 @@ package chipyard.fpga.arty
import chisel3._
import freechips.rocketchip.diplomacy.{LazyModule}
import freechips.rocketchip.prci.{ClockBundle, ClockBundleParameters}
import org.chipsalliance.cde.config.{Parameters}
import sifive.fpgashells.shell.xilinx.artyshell.{ArtyShell}
import chipyard.{BuildTop, HasHarnessSignalReferences}
import chipyard.harness.{ApplyHarnessBinders}
import chipyard.harness.{HasHarnessInstantiators}
import chipyard.iobinders.{HasIOBinders}
class ArtyFPGATestHarness(override implicit val p: Parameters) extends ArtyShell with HasHarnessSignalReferences {
val lazyDut = LazyModule(p(BuildTop)(p)).suggestName("chiptop")
class ArtyFPGATestHarness(override implicit val p: Parameters) extends ArtyShell with HasHarnessInstantiators {
// Convert harness resets from Bool to Reset type.
val hReset = Wire(Reset())
hReset := ~ck_rst
@@ -22,19 +19,11 @@ class ArtyFPGATestHarness(override implicit val p: Parameters) extends ArtyShell
val dReset = Wire(AsyncReset())
dReset := reset_core.asAsyncReset
// default to 32MHz clock
withClockAndReset(clock_32MHz, hReset) {
val dut = Module(lazyDut.module)
}
def success = {require(false, "Success not supported"); false.B }
val buildtopClock = clock_32MHz
val buildtopReset = hReset
val success = false.B
def referenceClockFreqMHz = 32.0
def referenceClock = clock_32MHz
def referenceReset = hReset
val dutReset = dReset
// must be after HasHarnessSignalReferences assignments
lazyDut match { case d: HasIOBinders =>
ApplyHarnessBinders(this, d.lazySystem, d.portMap)
}
instantiateChipTops()
}

View File

@@ -25,6 +25,15 @@ class WithArty100TTweaks extends Config(
new WithArty100TUARTTSI ++
new WithArty100TDDRTL ++
new WithNoDesignKey ++
new testchipip.WithUARTTSIClient ++
new chipyard.harness.WithSerialTLTiedOff ++
new chipyard.harness.WithHarnessBinderClockFreqMHz(50) ++
new chipyard.config.WithMemoryBusFrequency(50.0) ++
new chipyard.config.WithFrontBusFrequency(50.0) ++
new chipyard.config.WithSystemBusFrequency(50.0) ++
new chipyard.config.WithPeripheryBusFrequency(50.0) ++
new chipyard.harness.WithAllClocksFromHarnessClockInstantiator ++
new chipyard.clocking.WithPassthroughClockGenerator ++
new chipyard.config.WithNoDebug ++ // no jtag
new chipyard.config.WithNoUART ++ // use UART for the UART-TSI thing instad
new chipyard.config.WithTLBackingMemory ++ // FPGA-shells converts the AXI to TL for us
@@ -33,8 +42,6 @@ class WithArty100TTweaks extends Config(
class RocketArty100TConfig extends Config(
new WithArty100TTweaks ++
new chipyard.config.WithMemoryBusFrequency(50.0) ++
new chipyard.config.WithPeripheryBusFrequency(50.0) ++ // Match the sbus and pbus frequency
new chipyard.config.WithBroadcastManager ++ // no l2
new chipyard.RocketConfig)

View File

@@ -4,7 +4,9 @@ import chisel3._
import chisel3.util._
import freechips.rocketchip.diplomacy._
import org.chipsalliance.cde.config.{Parameters}
import freechips.rocketchip.tilelink.{TLClientNode, TLBlockDuringReset}
import freechips.rocketchip.tilelink._
import freechips.rocketchip.prci.{ClockBundle, ClockBundleParameters}
import freechips.rocketchip.subsystem.{SystemBusKey}
import sifive.fpgashells.shell.xilinx._
import sifive.fpgashells.shell._
@@ -14,20 +16,18 @@ import sifive.fpgashells.ip.xilinx.{IBUF, PowerOnResetFPGAOnly}
import sifive.blocks.devices.uart._
import chipyard._
import chipyard.harness.{ApplyHarnessBinders}
import chipyard.harness._
import chipyard.iobinders.{HasIOBinders}
class Arty100THarness(override implicit val p: Parameters) extends Arty100TShell with HasHarnessSignalReferences
{
class Arty100THarness(override implicit val p: Parameters) extends Arty100TShell {
def dp = designParameters
val chiptop = LazyModule(p(BuildTop)(p))
val clockOverlay = dp(ClockInputOverlayKey).map(_.place(ClockInputDesignInput())).head
val harnessSysPLL = dp(PLLFactoryKey)
val harnessSysPLLNode = harnessSysPLL()
println(s"Arty100T FPGA Base Clock Freq: ${dp(DefaultClockFrequencyKey)} MHz")
val dutClock = ClockSinkNode(freqMHz = dp(DefaultClockFrequencyKey))
val dutFreqMHz = (dp(SystemBusKey).dtsFrequency.get / (1000 * 1000)).toInt
val dutClock = ClockSinkNode(freqMHz = dutFreqMHz)
println(s"Arty100T FPGA Base Clock Freq: ${dutFreqMHz} MHz")
val dutWrangler = LazyModule(new ResetWrangler())
val dutGroup = ClockGroup()
dutClock := dutWrangler.node := dutGroup := harnessSysPLLNode
@@ -38,12 +38,10 @@ class Arty100THarness(override implicit val p: Parameters) extends Arty100TShell
val uartOverlay = dp(UARTOverlayKey).head.place(UARTDesignInput(io_uart_bb))
val ddrOverlay = dp(DDROverlayKey).head.place(DDRDesignInput(dp(ExtTLMem).get.master.base, dutWrangler.node, harnessSysPLLNode)).asInstanceOf[DDRArtyPlacedOverlay]
val ddrInParams = chiptop match { case td: ChipTop =>
td.lazySystem match { case lsys: CanHaveMasterTLMemPort =>
lsys.memTLNode.edges.in(0)
}
}
val ddrClient = TLClientNode(Seq(ddrInParams.master))
val ddrClient = TLClientNode(Seq(TLMasterPortParameters.v1(Seq(TLMasterParameters.v1(
name = "chip_ddr",
sourceId = IdRange(0, 1 << dp(ExtTLMem).get.master.idBits)
)))))
val ddrBlockDuringReset = LazyModule(new TLBlockDuringReset(4))
ddrOverlay.overlayOutput.ddr := ddrBlockDuringReset.node := ddrClient
@@ -52,17 +50,16 @@ class Arty100THarness(override implicit val p: Parameters) extends Arty100TShell
val status_leds = all_leds.take(3)
val other_leds = all_leds.drop(3)
def buildtopClock = dutClock.in.head._1.clock
def buildtopReset = dutClock.in.head._1.reset
def success = { require(false, "Unused"); false.B }
InModuleBody {
override lazy val module = new HarnessLikeImpl
class HarnessLikeImpl extends Impl with HasHarnessInstantiators {
clockOverlay.overlayOutput.node.out(0)._1.reset := ~resetPin
val clk_100mhz = clockOverlay.overlayOutput.node.out.head._1.clock
// Blink the status LEDs for sanity
withClock(clk_100mhz) {
withClockAndReset(clk_100mhz, dutClock.in.head._1.reset) {
val period = (BigInt(100) << 20) / status_leds.size
val counter = RegInit(0.U(log2Ceil(period).W))
val on = RegInit(0.U(log2Ceil(status_leds.size).W))
@@ -77,16 +74,18 @@ class Arty100THarness(override implicit val p: Parameters) extends Arty100TShell
harnessSysPLL.plls.foreach(_._1.getReset.get := pllReset)
ddrOverlay.mig.module.clock := buildtopClock
ddrOverlay.mig.module.reset := buildtopReset
ddrBlockDuringReset.module.clock := buildtopClock
ddrBlockDuringReset.module.reset := buildtopReset || !ddrOverlay.mig.module.io.port.init_calib_complete
def referenceClockFreqMHz = dutFreqMHz
def referenceClock = dutClock.in.head._1.clock
def referenceReset = dutClock.in.head._1.reset
def success = { require(false, "Unused"); false.B }
ddrOverlay.mig.module.clock := harnessBinderClock
ddrOverlay.mig.module.reset := harnessBinderReset
ddrBlockDuringReset.module.clock := harnessBinderClock
ddrBlockDuringReset.module.reset := harnessBinderReset.asBool || !ddrOverlay.mig.module.io.port.init_calib_complete
other_leds(6) := ddrOverlay.mig.module.io.port.init_calib_complete
chiptop match { case d: HasIOBinders =>
ApplyHarnessBinders(this, d.lazySystem, d.portMap)
}
instantiateChipTops()
}
}

View File

@@ -6,6 +6,7 @@ import freechips.rocketchip.jtag.{JTAGIO}
import freechips.rocketchip.subsystem.{PeripheryBusKey}
import freechips.rocketchip.tilelink.{TLBundle}
import freechips.rocketchip.util.{HeterogeneousBag}
import freechips.rocketchip.diplomacy.{LazyRawModuleImp}
import sifive.blocks.devices.uart.{UARTPortIO, HasPeripheryUARTModuleImp, UARTParams}
import sifive.blocks.devices.jtag.{JTAGPins, JTAGPinsFromPort}
@@ -20,38 +21,25 @@ import chipyard.iobinders.JTAGChipIO
import testchipip._
class WithArty100TUARTTSI(uartBaudRate: BigInt = 115200) extends OverrideHarnessBinder({
(system: CanHavePeripheryTLSerial, th: HasHarnessSignalReferences, ports: Seq[ClockedIO[SerialIO]]) => {
(system: CanHavePeripheryUARTTSI, th: HasHarnessInstantiators, ports: Seq[UARTTSIIO]) => {
implicit val p = chipyard.iobinders.GetSystemParameters(system)
require(ports.size <= 1)
val ath = th.asInstanceOf[LazyRawModuleImp].wrapper.asInstanceOf[Arty100THarness]
ports.map({ port =>
val ath = th.asInstanceOf[Arty100THarness]
val freq = p(PeripheryBusKey).dtsFrequency.get
val bits = SerialAdapter.asyncQueue(port, th.buildtopClock, th.buildtopReset)
withClockAndReset(th.buildtopClock, th.buildtopReset) {
val ram = SerialAdapter.connectHarnessRAM(system.serdesser.get, bits, th.buildtopReset)
val uart_to_serial = Module(new UARTToSerial(
freq, UARTParams(0, initBaudRate=uartBaudRate)))
val serial_width_adapter = Module(new SerialWidthAdapter(
narrowW = 8, wideW = SerialAdapter.SERIAL_TSI_WIDTH))
serial_width_adapter.io.narrow.flipConnect(uart_to_serial.io.serial)
ram.module.io.tsi_ser.flipConnect(serial_width_adapter.io.wide)
ath.io_uart_bb.bundle <> uart_to_serial.io.uart
ath.other_leds(1) := uart_to_serial.io.dropped
ath.other_leds(9) := ram.module.io.adapter_state(0)
ath.other_leds(10) := ram.module.io.adapter_state(1)
ath.other_leds(11) := ram.module.io.adapter_state(2)
ath.other_leds(12) := ram.module.io.adapter_state(3)
}
ath.io_uart_bb.bundle <> port.uart
ath.other_leds(1) := port.dropped
ath.other_leds(9) := port.tsi2tl_state(0)
ath.other_leds(10) := port.tsi2tl_state(1)
ath.other_leds(11) := port.tsi2tl_state(2)
ath.other_leds(12) := port.tsi2tl_state(3)
})
}
})
class WithArty100TDDRTL extends OverrideHarnessBinder({
(system: CanHaveMasterTLMemPort, th: HasHarnessSignalReferences, ports: Seq[HeterogeneousBag[TLBundle]]) => {
(system: CanHaveMasterTLMemPort, th: HasHarnessInstantiators, ports: Seq[HeterogeneousBag[TLBundle]]) => {
require(ports.size == 1)
val artyTh = th.asInstanceOf[Arty100THarness]
val artyTh = th.asInstanceOf[LazyRawModuleImp].wrapper.asInstanceOf[Arty100THarness]
val bundles = artyTh.ddrClient.out.map(_._1)
val ddrClientBundle = Wire(new HeterogeneousBag(bundles.map(_.cloneType)))
bundles.zip(ddrClientBundle).foreach { case (bundle, io) => bundle <> io }

View File

@@ -17,7 +17,8 @@ import sifive.fpgashells.shell.xilinx.{VC7074GDDRSize}
import testchipip.{SerialTLKey}
import chipyard.{BuildSystem, ExtTLMem, DefaultClockFrequencyKey}
import chipyard.{BuildSystem, ExtTLMem}
import chipyard.harness._
class WithDefaultPeripherals extends Config((site, here, up) => {
case PeripheryUARTKey => List(UARTParams(address = BigInt(0x64000000L)))
@@ -28,7 +29,7 @@ class WithSystemModifications extends Config((site, here, up) => {
case DTSTimebase => BigInt{(1e6).toLong}
case BootROMLocated(x) => up(BootROMLocated(x), site).map { p =>
// invoke makefile for sdboot
val freqMHz = (site(DefaultClockFrequencyKey) * 1e6).toLong
val freqMHz = (site(SystemBusKey).dtsFrequency.get / (1000 * 1000)).toLong
val make = s"make -C fpga/src/main/resources/vc707/sdboot PBUS_CLK=${freqMHz} bin"
require (make.! == 0, "Failed to build bootrom")
p.copy(hang = 0x10000, contentFileName = s"./fpga/src/main/resources/vc707/sdboot/build/sdboot.bin")
@@ -38,7 +39,17 @@ class WithSystemModifications extends Config((site, here, up) => {
})
class WithVC707Tweaks extends Config (
// clocking
new chipyard.harness.WithAllClocksFromHarnessClockInstantiator ++
new chipyard.clocking.WithPassthroughClockGenerator ++
new chipyard.config.WithMemoryBusFrequency(50.0) ++
new chipyard.config.WithSystemBusFrequency(50.0) ++
new chipyard.config.WithPeripheryBusFrequency(50.0) ++
new chipyard.harness.WithHarnessBinderClockFreqMHz(50) ++
new WithFPGAFrequency(50) ++ // default 50MHz freq
// harness binders
new chipyard.harness.WithAllClocksFromHarnessClockInstantiator ++
new WithVC707UARTHarnessBinder ++
new WithVC707SPISDCardHarnessBinder ++
new WithVC707DDRMemHarnessBinder ++
@@ -52,8 +63,7 @@ class WithVC707Tweaks extends Config (
new WithSystemModifications ++ // setup busses, use sdboot bootrom, setup ext. mem. size
new chipyard.config.WithNoDebug ++ // remove debug module
new freechips.rocketchip.subsystem.WithoutTLMonitors ++
new freechips.rocketchip.subsystem.WithNMemoryChannels(1) ++
new WithFPGAFrequency(50) // default 50MHz freq
new freechips.rocketchip.subsystem.WithNMemoryChannels(1)
)
class RocketVC707Config extends Config (

View File

@@ -1,24 +1,25 @@
package chipyard.fpga.vc707
import chisel3._
import chisel3.experimental.{IO}
import freechips.rocketchip.diplomacy.{LazyModule, LazyRawModuleImp, BundleBridgeSource}
import org.chipsalliance.cde.config.{Parameters}
import freechips.rocketchip.tilelink.{TLClientNode}
import freechips.rocketchip.tilelink._
import freechips.rocketchip.subsystem.{SystemBusKey}
import freechips.rocketchip.diplomacy.{IdRange, TransferSizes}
import sifive.fpgashells.shell.xilinx.{VC707Shell, UARTVC707ShellPlacer, PCIeVC707ShellPlacer, ChipLinkVC707PlacedOverlay}
import sifive.fpgashells.ip.xilinx.{IBUF, PowerOnResetFPGAOnly}
import sifive.fpgashells.shell.{ClockInputOverlayKey, ClockInputDesignInput, UARTOverlayKey, UARTDesignInput, UARTShellInput, LEDOverlayKey, LEDDesignInput, SwitchOverlayKey, SwitchDesignInput, ButtonOverlayKey, ButtonDesignInput, SPIOverlayKey, SPIDesignInput, ChipLinkOverlayKey, ChipLinkDesignInput, PCIeOverlayKey, PCIeDesignInput, PCIeShellInput, DDROverlayKey, DDRDesignInput, JTAGDebugOverlayKey, JTAGDebugDesignInput}
import sifive.fpgashells.shell._
import sifive.fpgashells.clocks.{ClockGroup, ClockSinkNode, PLLFactoryKey, ResetWrangler}
import sifive.fpgashells.devices.xilinx.xilinxvc707pciex1.{XilinxVC707PCIeX1IO}
import sifive.blocks.devices.uart.{PeripheryUARTKey, UARTPortIO}
import sifive.blocks.devices.spi.{PeripherySPIKey, SPIPortIO}
import chipyard.{HasHarnessSignalReferences, BuildTop, ChipTop, ExtTLMem, CanHaveMasterTLMemPort, DefaultClockFrequencyKey}
import chipyard._
import chipyard.iobinders.{HasIOBinders}
import chipyard.harness.{ApplyHarnessBinders}
import chipyard.harness._
class VC707FPGATestHarness(override implicit val p: Parameters) extends VC707Shell { outer =>
@@ -27,8 +28,6 @@ class VC707FPGATestHarness(override implicit val p: Parameters) extends VC707She
// Order matters; ddr depends on sys_clock
val uart = Overlay(UARTOverlayKey, new UARTVC707ShellPlacer(this, UARTShellInput()))
val topDesign = LazyModule(p(BuildTop)(dp)).suggestName("chiptop")
// place all clocks in the shell
require(dp(ClockInputOverlayKey).size >= 1)
val sysClkNode = dp(ClockInputOverlayKey).head.place(ClockInputDesignInput()).overlayOutput.node
@@ -40,8 +39,9 @@ class VC707FPGATestHarness(override implicit val p: Parameters) extends VC707She
harnessSysPLL := sysClkNode
// create and connect to the dutClock
println(s"VC707 FPGA Base Clock Freq: ${dp(DefaultClockFrequencyKey)} MHz")
val dutClock = ClockSinkNode(freqMHz = dp(DefaultClockFrequencyKey))
val dutFreqMHz = (dp(SystemBusKey).dtsFrequency.get / (1000 * 1000)).toInt
val dutClock = ClockSinkNode(freqMHz = dutFreqMHz)
println(s"VC707 FPGA Base Clock Freq: ${dutFreqMHz} MHz")
val dutWrangler = LazyModule(new ResetWrangler)
val dutGroup = ClockGroup()
dutClock := dutWrangler.node := dutGroup := harnessSysPLL
@@ -76,22 +76,18 @@ class VC707FPGATestHarness(override implicit val p: Parameters) extends VC707She
// Modify the last field of `DDRDesignInput` for 1GB RAM size
val ddrNode = dp(DDROverlayKey).head.place(DDRDesignInput(dp(ExtTLMem).get.master.base, dutWrangler.node, harnessSysPLL, true)).overlayOutput.ddr
val ddrClient = TLClientNode(Seq(TLMasterPortParameters.v1(Seq(TLMasterParameters.v1(
name = "chip_ddr",
sourceId = IdRange(0, 1 << dp(ExtTLMem).get.master.idBits)
)))))
// connect 1 mem. channel to the FPGA DDR
val inParams = topDesign match { case td: ChipTop =>
td.lazySystem match { case lsys: CanHaveMasterTLMemPort =>
lsys.memTLNode.edges.in(0)
}
}
val ddrClient = TLClientNode(Seq(inParams.master))
ddrNode := ddrClient
// module implementation
override lazy val module = new VC707FPGATestHarnessImp(this)
}
class VC707FPGATestHarnessImp(_outer: VC707FPGATestHarness) extends LazyRawModuleImp(_outer) with HasHarnessSignalReferences {
class VC707FPGATestHarnessImp(_outer: VC707FPGATestHarness) extends LazyRawModuleImp(_outer) with HasHarnessInstantiators {
val vc707Outer = _outer
val reset = IO(Input(Bool()))
@@ -116,20 +112,13 @@ class VC707FPGATestHarnessImp(_outer: VC707FPGATestHarness) extends LazyRawModul
val hReset = Wire(Reset())
hReset := _outer.dutClock.in.head._1.reset
val buildtopClock = _outer.dutClock.in.head._1.clock
val buildtopReset = WireInit(hReset)
val dutReset = hReset.asAsyncReset
val success = false.B
def referenceClockFreqMHz = _outer.dutFreqMHz
def referenceClock = _outer.dutClock.in.head._1.clock
def referenceReset = hReset
def success = { require(false, "Unused"); false.B }
childClock := buildtopClock
childReset := buildtopReset
childClock := referenceClock
childReset := referenceReset
// harness binders are non-lazy
_outer.topDesign match { case d: HasIOBinders =>
ApplyHarnessBinders(this, d.lazySystem, d.portMap)
}
// check the top-level reference clock is equal to the default
// non-exhaustive since you need all ChipTop clocks to equal the default
require(getRefClockFreq == p(DefaultClockFrequencyKey))
instantiateChipTops()
}

View File

@@ -17,7 +17,8 @@ import sifive.fpgashells.shell.xilinx.{VCU118ShellPMOD, VCU118DDRSize}
import testchipip.{SerialTLKey}
import chipyard.{BuildSystem, ExtTLMem, DefaultClockFrequencyKey}
import chipyard._
import chipyard.harness._
class WithDefaultPeripherals extends Config((site, here, up) => {
case PeripheryUARTKey => List(UARTParams(address = BigInt(0x64000000L)))
@@ -29,7 +30,7 @@ class WithSystemModifications extends Config((site, here, up) => {
case DTSTimebase => BigInt((1e6).toLong)
case BootROMLocated(x) => up(BootROMLocated(x), site).map { p =>
// invoke makefile for sdboot
val freqMHz = (site(DefaultClockFrequencyKey) * 1e6).toLong
val freqMHz = (site(SystemBusKey).dtsFrequency.get / (1000 * 1000)).toLong
val make = s"make -C fpga/src/main/resources/vcu118/sdboot PBUS_CLK=${freqMHz} bin"
require (make.! == 0, "Failed to build bootrom")
p.copy(hang = 0x10000, contentFileName = s"./fpga/src/main/resources/vcu118/sdboot/build/sdboot.bin")
@@ -40,6 +41,13 @@ class WithSystemModifications extends Config((site, here, up) => {
// DOC include start: AbstractVCU118 and Rocket
class WithVCU118Tweaks extends Config(
// clocking
new chipyard.harness.WithAllClocksFromHarnessClockInstantiator ++
new chipyard.clocking.WithPassthroughClockGenerator ++
new chipyard.config.WithMemoryBusFrequency(100) ++
new chipyard.config.WithSystemBusFrequency(100) ++
new chipyard.config.WithPeripheryBusFrequency(100) ++
new WithFPGAFrequency(100) ++ // default 100MHz freq
// harness binders
new WithUART ++
new WithSPISDCard ++
@@ -53,8 +61,7 @@ class WithVCU118Tweaks extends Config(
new WithSystemModifications ++ // setup busses, use sdboot bootrom, setup ext. mem. size
new chipyard.config.WithNoDebug ++ // remove debug module
new freechips.rocketchip.subsystem.WithoutTLMonitors ++
new freechips.rocketchip.subsystem.WithNMemoryChannels(1) ++
new WithFPGAFrequency(100) // default 100MHz freq
new freechips.rocketchip.subsystem.WithNMemoryChannels(1)
)
class RocketVCU118Config extends Config(

View File

@@ -9,12 +9,12 @@ import freechips.rocketchip.tilelink.{TLBundle}
import sifive.blocks.devices.uart.{HasPeripheryUARTModuleImp, UARTPortIO}
import sifive.blocks.devices.spi.{HasPeripherySPI, SPIPortIO}
import chipyard.{HasHarnessSignalReferences, CanHaveMasterTLMemPort}
import chipyard.harness.{OverrideHarnessBinder}
import chipyard._
import chipyard.harness._
/*** UART ***/
class WithUART extends OverrideHarnessBinder({
(system: HasPeripheryUARTModuleImp, th: BaseModule with HasHarnessSignalReferences, ports: Seq[UARTPortIO]) => {
(system: HasPeripheryUARTModuleImp, th: BaseModule with HasHarnessInstantiators, ports: Seq[UARTPortIO]) => {
th match { case vcu118th: VCU118FPGATestHarnessImp => {
vcu118th.vcu118Outer.io_uart_bb.bundle <> ports.head
} }
@@ -23,7 +23,7 @@ class WithUART extends OverrideHarnessBinder({
/*** SPI ***/
class WithSPISDCard extends OverrideHarnessBinder({
(system: HasPeripherySPI, th: BaseModule with HasHarnessSignalReferences, ports: Seq[SPIPortIO]) => {
(system: HasPeripherySPI, th: BaseModule with HasHarnessInstantiators, ports: Seq[SPIPortIO]) => {
th match { case vcu118th: VCU118FPGATestHarnessImp => {
vcu118th.vcu118Outer.io_spi_bb.bundle <> ports.head
} }
@@ -32,7 +32,7 @@ class WithSPISDCard extends OverrideHarnessBinder({
/*** Experimental DDR ***/
class WithDDRMem extends OverrideHarnessBinder({
(system: CanHaveMasterTLMemPort, th: BaseModule with HasHarnessSignalReferences, ports: Seq[HeterogeneousBag[TLBundle]]) => {
(system: CanHaveMasterTLMemPort, th: BaseModule with HasHarnessInstantiators, ports: Seq[HeterogeneousBag[TLBundle]]) => {
th match { case vcu118th: VCU118FPGATestHarnessImp => {
require(ports.size == 1)

View File

@@ -5,7 +5,9 @@ import chisel3.experimental.{IO}
import freechips.rocketchip.diplomacy.{LazyModule, LazyRawModuleImp, BundleBridgeSource}
import org.chipsalliance.cde.config.{Parameters}
import freechips.rocketchip.tilelink.{TLClientNode}
import freechips.rocketchip.tilelink._
import freechips.rocketchip.diplomacy.{IdRange, TransferSizes}
import freechips.rocketchip.subsystem.{SystemBusKey}
import sifive.fpgashells.shell.xilinx._
import sifive.fpgashells.ip.xilinx.{IBUF, PowerOnResetFPGAOnly}
@@ -17,7 +19,7 @@ import sifive.blocks.devices.spi.{PeripherySPIKey, SPIPortIO}
import chipyard._
import chipyard.iobinders.{HasIOBinders}
import chipyard.harness.{ApplyHarnessBinders}
import chipyard.harness._
class VCU118FPGATestHarness(override implicit val p: Parameters) extends VCU118ShellBasicOverlays {
@@ -37,8 +39,6 @@ class VCU118FPGATestHarness(override implicit val p: Parameters) extends VCU118S
val sys_clock2 = Overlay(ClockInputOverlayKey, new SysClock2VCU118ShellPlacer(this, ClockInputShellInput()))
val ddr2 = Overlay(DDROverlayKey, new DDR2VCU118ShellPlacer(this, DDRShellInput()))
val topDesign = LazyModule(p(BuildTop)(dp)).suggestName("chiptop")
// DOC include start: ClockOverlay
// place all clocks in the shell
require(dp(ClockInputOverlayKey).size >= 1)
@@ -51,8 +51,9 @@ class VCU118FPGATestHarness(override implicit val p: Parameters) extends VCU118S
harnessSysPLL := sysClkNode
// create and connect to the dutClock
println(s"VCU118 FPGA Base Clock Freq: ${dp(DefaultClockFrequencyKey)} MHz")
val dutClock = ClockSinkNode(freqMHz = dp(DefaultClockFrequencyKey))
val dutFreqMHz = (dp(SystemBusKey).dtsFrequency.get / (1000 * 1000)).toInt
val dutClock = ClockSinkNode(freqMHz = dutFreqMHz)
println(s"VCU118 FPGA Base Clock Freq: ${dutFreqMHz} MHz")
val dutWrangler = LazyModule(new ResetWrangler)
val dutGroup = ClockGroup()
dutClock := dutWrangler.node := dutGroup := harnessSysPLL
@@ -79,20 +80,17 @@ class VCU118FPGATestHarness(override implicit val p: Parameters) extends VCU118S
val ddrNode = dp(DDROverlayKey).head.place(DDRDesignInput(dp(ExtTLMem).get.master.base, dutWrangler.node, harnessSysPLL)).overlayOutput.ddr
// connect 1 mem. channel to the FPGA DDR
val inParams = topDesign match { case td: ChipTop =>
td.lazySystem match { case lsys: CanHaveMasterTLMemPort =>
lsys.memTLNode.edges.in(0)
}
}
val ddrClient = TLClientNode(Seq(inParams.master))
ddrNode := ddrClient
val ddrClient = TLClientNode(Seq(TLMasterPortParameters.v1(Seq(TLMasterParameters.v1(
name = "chip_ddr",
sourceId = IdRange(0, 1 << dp(ExtTLMem).get.master.idBits)
)))))
ddrNode := TLWidthWidget(dp(ExtTLMem).get.master.beatBytes) := ddrClient
// module implementation
override lazy val module = new VCU118FPGATestHarnessImp(this)
}
class VCU118FPGATestHarnessImp(_outer: VCU118FPGATestHarness) extends LazyRawModuleImp(_outer) with HasHarnessSignalReferences {
class VCU118FPGATestHarnessImp(_outer: VCU118FPGATestHarness) extends LazyRawModuleImp(_outer) with HasHarnessInstantiators {
val vcu118Outer = _outer
val reset = IO(Input(Bool()))
@@ -118,20 +116,13 @@ class VCU118FPGATestHarnessImp(_outer: VCU118FPGATestHarness) extends LazyRawMod
val hReset = Wire(Reset())
hReset := _outer.dutClock.in.head._1.reset
val buildtopClock = _outer.dutClock.in.head._1.clock
val buildtopReset = WireInit(hReset)
val dutReset = hReset.asAsyncReset
val success = false.B
def referenceClockFreqMHz = _outer.dutFreqMHz
def referenceClock = _outer.dutClock.in.head._1.clock
def referenceReset = hReset
def success = { require(false, "Unused"); false.B }
childClock := buildtopClock
childReset := buildtopReset
childClock := referenceClock
childReset := referenceReset
// harness binders are non-lazy
_outer.topDesign match { case d: HasIOBinders =>
ApplyHarnessBinders(this, d.lazySystem, d.portMap)
}
// check the top-level reference clock is equal to the default
// non-exhaustive since you need all ChipTop clocks to equal the default
require(getRefClockFreq == p(DefaultClockFrequencyKey))
instantiateChipTops()
}

View File

@@ -13,12 +13,11 @@ import sifive.blocks.devices.gpio.{HasPeripheryGPIOModuleImp, GPIOPortIO}
import testchipip.{HasPeripheryTSIHostWidget, TSIHostWidgetIO}
import chipyard.{HasHarnessSignalReferences}
import chipyard.harness.{ComposeHarnessBinder, OverrideHarnessBinder}
import chipyard.harness._
/*** UART ***/
class WithBringupUART extends ComposeHarnessBinder({
(system: HasPeripheryUARTModuleImp, th: BaseModule with HasHarnessSignalReferences, ports: Seq[UARTPortIO]) => {
(system: HasPeripheryUARTModuleImp, th: BaseModule with HasHarnessInstantiators, ports: Seq[UARTPortIO]) => {
th match { case vcu118th: BringupVCU118FPGATestHarnessImp => {
require(ports.size == 2)
@@ -29,7 +28,7 @@ class WithBringupUART extends ComposeHarnessBinder({
/*** I2C ***/
class WithBringupI2C extends OverrideHarnessBinder({
(system: HasPeripheryI2CModuleImp, th: BaseModule with HasHarnessSignalReferences, ports: Seq[I2CPort]) => {
(system: HasPeripheryI2CModuleImp, th: BaseModule with HasHarnessInstantiators, ports: Seq[I2CPort]) => {
th match { case vcu118th: BringupVCU118FPGATestHarnessImp => {
require(ports.size == 1)
@@ -40,7 +39,7 @@ class WithBringupI2C extends OverrideHarnessBinder({
/*** GPIO ***/
class WithBringupGPIO extends OverrideHarnessBinder({
(system: HasPeripheryGPIOModuleImp, th: BaseModule with HasHarnessSignalReferences, ports: Seq[GPIOPortIO]) => {
(system: HasPeripheryGPIOModuleImp, th: BaseModule with HasHarnessInstantiators, ports: Seq[GPIOPortIO]) => {
th match { case vcu118th: BringupVCU118FPGATestHarnessImp => {
(vcu118th.bringupOuter.io_gpio_bb zip ports).map { case (bb_io, dut_io) =>
bb_io.bundle <> dut_io
@@ -51,7 +50,7 @@ class WithBringupGPIO extends OverrideHarnessBinder({
/*** TSI Host Widget ***/
class WithBringupTSIHost extends OverrideHarnessBinder({
(system: HasPeripheryTSIHostWidget, th: BaseModule with HasHarnessSignalReferences, ports: Seq[Data]) => {
(system: HasPeripheryTSIHostWidget, th: BaseModule with HasHarnessInstantiators, ports: Seq[Data]) => {
th match { case vcu118th: BringupVCU118FPGATestHarnessImp => {
require(ports.size == 2) // 1st goes to the TL mem, 2nd goes to the serial link

View File

@@ -1,5 +1,4 @@
package chipyard.fpga.vcu118.bringup
import chisel3._
import freechips.rocketchip.diplomacy._
@@ -22,6 +21,7 @@ import testchipip.{HasPeripheryTSIHostWidget, PeripheryTSIHostKey, TSIHostWidget
import chipyard.fpga.vcu118.{VCU118FPGATestHarness, VCU118FPGATestHarnessImp, DDR2VCU118ShellPlacer, SysClock2VCU118ShellPlacer}
import chipyard.{ChipTop}
import chipyard.harness._
class BringupVCU118FPGATestHarness(override implicit val p: Parameters) extends VCU118FPGATestHarness {
@@ -78,12 +78,10 @@ class BringupVCU118FPGATestHarness(override implicit val p: Parameters) extends
dp(TSIHostOverlayKey).head.place(TSIHostDesignInput(dp(PeripheryTSIHostKey).head.offchipSerialIfWidth, io_tsi_serial_bb))
// connect 1 mem. channel to the FPGA DDR
val inTsiParams = topDesign match { case td: ChipTop =>
td.lazySystem match { case lsys: HasPeripheryTSIHostWidget =>
lsys.tsiMemTLNodes.head.edges.in(0)
}
}
val tsiDdrClient = TLClientNode(Seq(inTsiParams.master))
val tsiDdrClient = TLClientNode(Seq(TLMasterPortParameters.v1(Seq(TLMasterParameters.v1(
name = "chip_ddr",
sourceId = IdRange(0, 64)
)))))
(ddr2Node
:= TLFragmenter(8,64,holdFirstDeny=true)
:= TLCacheCork()

View File

@@ -1,13 +1,44 @@
#include <cstdint>
#include <vector>
#include <string>
#include <riscv/sim.h>
#include <riscv/mmu.h>
#include <riscv/encoding.h>
#include <vpi_user.h>
#include <svdpi.h>
#include <sstream>
#include <set>
#include <sys/types.h>
#include <sys/mman.h>
#include <sys/types.h>
#include <unistd.h>
#include <sys/syscall.h>
#include <fcntl.h>
#if __has_include ("cospike_dtm.h")
#define COSPIKE_DTM
#include "testchip_dtm.h"
extern testchip_dtm_t* dtm;
bool spike_loadarch_done = false;
#endif
#if __has_include ("mm.h")
#define COSPIKE_SIMDRAM
#include "mm.h"
extern std::map<long long int, backing_data_t> backing_mem_data;
#endif
#define CLINT_BASE (0x2000000)
#define CLINT_SIZE (0x1000)
#define CLINT_SIZE (0x10000)
#define UART_BASE (0x54000000)
#define UART_SIZE (0x1000)
#define PLIC_BASE (0xc000000)
#define PLIC_SIZE (0x4000000)
#define COSPIKE_PRINTF(...) { \
printf(__VA_ARGS__); \
fprintf(stderr, __VA_ARGS__); \
}
typedef struct system_info_t {
std::string isa;
@@ -16,14 +47,37 @@ typedef struct system_info_t {
uint64_t mem0_size;
int nharts;
std::vector<char> bootrom;
std::string priv;
};
class read_override_device_t : public abstract_device_t {
public:
read_override_device_t(std::string n, reg_t sz) : was_read_from(false), size(sz), name(n) { };
virtual bool load(reg_t addr, size_t len, uint8_t* bytes) override {
if (addr + len > size) return false;
COSPIKE_PRINTF("Read from device %s at %lx\n", name.c_str(), addr);
was_read_from = true;
return true;
}
virtual bool store(reg_t addr, size_t len, const uint8_t* bytes) override {
COSPIKE_PRINTF("Store to device %s at %lx\n", name.c_str(), addr);
return (addr + len <= size);
}
bool was_read_from;
private:
reg_t size;
std::string name;
};
system_info_t* info = NULL;
sim_t* sim = NULL;
bool cospike_debug;
reg_t tohost_addr = 0;
reg_t fromhost_addr = 0;
reg_t cospike_timeout = 0;
std::set<reg_t> magic_addrs;
cfg_t* cfg;
std::vector<std::shared_ptr<read_override_device_t>> read_override_devices;
static std::vector<std::pair<reg_t, mem_t*>> make_mems(const std::vector<mem_cfg_t> &layout)
{
@@ -35,14 +89,16 @@ static std::vector<std::pair<reg_t, mem_t*>> make_mems(const std::vector<mem_cfg
return mems;
}
extern "C" void cospike_set_sysinfo(char* isa, int pmpregions,
extern "C" void cospike_set_sysinfo(char* isa, char* priv, int pmpregions,
long long int mem0_base, long long int mem0_size,
int nharts,
char* bootrom
) {
if (!info) {
info = new system_info_t;
info->isa = std::string(isa);
// technically the targets aren't zicntr compliant, but they implement the zicntr registers
info->isa = std::string(isa) + "_zicntr";
info->priv = std::string(priv);
info->pmpregions = pmpregions;
info->mem0_base = mem0_base;
info->mem0_size = mem0_size;
@@ -64,11 +120,13 @@ extern "C" void cospike_cosim(long long int cycle,
int raise_exception,
int raise_interrupt,
unsigned long long int cause,
unsigned long long int wdata)
unsigned long long int wdata,
int priv)
{
assert(info);
if (!sim) {
printf("Configuring spike cosim\n");
if (unlikely(!sim)) {
COSPIKE_PRINTF("Configuring spike cosim\n");
std::vector<mem_cfg_t> mem_cfg;
std::vector<size_t> hartids;
mem_cfg.push_back(mem_cfg_t(info->mem0_base, info->mem0_size));
@@ -78,7 +136,7 @@ extern "C" void cospike_cosim(long long int cycle,
cfg = new cfg_t(std::make_pair(0, 0),
nullptr,
info->isa.c_str(),
"MSU",
info->priv.c_str(),
"vlen:128,elen:64",
false,
endianness_little,
@@ -91,34 +149,48 @@ extern "C" void cospike_cosim(long long int cycle,
std::vector<std::pair<reg_t, mem_t*>> mems = make_mems(cfg->mem_layout());
rom_device_t *boot_rom = new rom_device_t(info->bootrom);
mem_t *boot_addr_reg = new mem_t(0x1000);
size_t default_boot_rom_size = 0x10000;
size_t default_boot_rom_addr = 0x10000;
assert(info->bootrom.size() < default_boot_rom_size);
info->bootrom.resize(default_boot_rom_size);
std::shared_ptr<rom_device_t> boot_rom = std::make_shared<rom_device_t>(info->bootrom);
std::shared_ptr<mem_t> boot_addr_reg = std::make_shared<mem_t>(0x1000);
uint64_t default_boot_addr = 0x80000000;
boot_addr_reg->store(0, 8, (const uint8_t*)(&default_boot_addr));
boot_addr_reg.get()->store(0, 8, (const uint8_t*)(&default_boot_addr));
// Don't actually build a clint
mem_t* clint_mem = new mem_t(CLINT_SIZE);
std::shared_ptr<read_override_device_t> clint = std::make_shared<read_override_device_t>("clint", CLINT_SIZE);
std::shared_ptr<read_override_device_t> uart = std::make_shared<read_override_device_t>("uart", UART_SIZE);
std::shared_ptr<read_override_device_t> plic = std::make_shared<read_override_device_t>("plic", PLIC_SIZE);
std::vector<std::pair<reg_t, abstract_device_t*>> plugin_devices;
read_override_devices.push_back(clint);
read_override_devices.push_back(uart);
read_override_devices.push_back(plic);
std::vector<std::pair<reg_t, std::shared_ptr<abstract_device_t>>> devices;
// The device map is hardcoded here for now
plugin_devices.push_back(std::pair(0x4000, boot_addr_reg));
plugin_devices.push_back(std::pair(0x10000, boot_rom));
plugin_devices.push_back(std::pair(CLINT_BASE, clint_mem));
devices.push_back(std::pair(0x4000, boot_addr_reg));
devices.push_back(std::pair(default_boot_rom_addr, boot_rom));
devices.push_back(std::pair(CLINT_BASE, clint));
devices.push_back(std::pair(UART_BASE, uart));
devices.push_back(std::pair(PLIC_BASE, plic));
s_vpi_vlog_info vinfo;
if (!vpi_get_vlog_info(&vinfo))
abort();
std::vector<std::string> htif_args;
bool in_permissive = false;
bool cospike_debug = false;
cospike_debug = false;
for (int i = 1; i < vinfo.argc; i++) {
std::string arg(vinfo.argv[i]);
if (arg == "+permissive") {
in_permissive = true;
} else if (arg == "+permissive-off") {
in_permissive = false;
} else if (arg == "+cospike_debug") {
} else if (arg == "+cospike_debug" || arg == "+cospike-debug") {
cospike_debug = true;
} else if (arg.find("+cospike-timeout=") == 0) {
cospike_timeout = strtoull(arg.substr(17).c_str(), 0, 10);
} else if (!in_permissive) {
htif_args.push_back(arg);
}
@@ -136,14 +208,17 @@ extern "C" void cospike_cosim(long long int cycle,
.support_impebreak = true
};
printf("%s\n", info->isa.c_str());
COSPIKE_PRINTF("isa string: %s\n", info->isa.c_str());
COSPIKE_PRINTF("htif args: ");
for (int i = 0; i < htif_args.size(); i++) {
printf("%s\n", htif_args[i].c_str());
COSPIKE_PRINTF("%s", htif_args[i].c_str());
}
COSPIKE_PRINTF("\n");
std::vector<const device_factory_t*> plugin_device_factories;
sim = new sim_t(cfg, false,
mems,
plugin_devices,
plugin_device_factories,
htif_args,
dm_config,
nullptr,
@@ -152,107 +227,274 @@ extern "C" void cospike_cosim(long long int cycle,
false,
nullptr
);
for (auto &it : devices)
sim->add_device(it.first, it.second);
#ifdef COSPIKE_SIMDRAM
// match sim_t's backing memory with the SimDRAM memory
bus_t temp_mem_bus;
for (auto& pair : mems) temp_mem_bus.add_device(pair.first, pair.second);
for (auto& pair : backing_mem_data) {
size_t base = pair.first;
size_t size = pair.second.size;
COSPIKE_PRINTF("Matching spike memory initial state for region %lx-%lx\n", base, base + size);
if (!temp_mem_bus.store(base, size, pair.second.data)) {
COSPIKE_PRINTF("Error, unable to match memory at address %lx\n", base);
abort();
}
}
#endif
sim->configure_log(true, true);
// Use our own reset vector
for (int i = 0; i < info->nharts; i++) {
// Use our own reset vector
sim->get_core(hartid)->get_state()->pc = 0x10040;
// Set MMU to support up to sv39, as our normal hw configs do
sim->get_core(hartid)->set_impl(IMPL_MMU_SV48, false);
sim->get_core(hartid)->set_impl(IMPL_MMU_SV57, false);
// HACKS: Our processor's don't implement zicntr fully, they don't provide time
sim->get_core(hartid)->get_state()->csrmap.erase(CSR_TIME);
}
sim->set_debug(cospike_debug);
printf("Setting up htif for spike cosim\n");
sim->set_histogram(true);
sim->set_procs_debug(cospike_debug);
COSPIKE_PRINTF("Setting up htif for spike cosim\n");
((htif_t*)sim)->start();
printf("Spike cosim started\n");
COSPIKE_PRINTF("Spike cosim started\n");
tohost_addr = ((htif_t*)sim)->get_tohost_addr();
fromhost_addr = ((htif_t*)sim)->get_fromhost_addr();
printf("Tohost : %lx\n", tohost_addr);
printf("Fromhost: %lx\n", fromhost_addr);
COSPIKE_PRINTF("Tohost : %lx\n", tohost_addr);
COSPIKE_PRINTF("Fromhost: %lx\n", fromhost_addr);
COSPIKE_PRINTF("BootROM base : %lx\n", default_boot_rom_addr);
COSPIKE_PRINTF("BootROM size : %lx\n", boot_rom->contents().size());
COSPIKE_PRINTF("Memory base : %lx\n", info->mem0_base);
COSPIKE_PRINTF("Memory size : %lx\n", info->mem0_size);
}
if (priv & 0x4) { // debug
return;
}
if (cospike_timeout && cycle > cospike_timeout) {
if (sim) {
COSPIKE_PRINTF("Cospike reached timeout cycles = %ld, terminating\n", cospike_timeout);
delete sim;
}
exit(0);
}
processor_t* p = sim->get_core(hartid);
state_t* s = p->get_state();
#ifdef COSPIKE_DTM
if (dtm && dtm->loadarch_done && !spike_loadarch_done) {
COSPIKE_PRINTF("Restoring spike state from testchip_dtm loadarch\n");
// copy the loadarch state into the cosim
loadarch_state_t &ls = dtm->loadarch_state[hartid];
s->pc = ls.pc;
s->prv = ls.prv;
s->csrmap[CSR_MSTATUS]->write(s->csrmap[CSR_MSTATUS]->read() | MSTATUS_VS | MSTATUS_XS | MSTATUS_FS);
#define RESTORE(CSRID, csr) s->csrmap[CSRID]->write(ls.csr);
RESTORE(CSR_FCSR , fcsr);
RESTORE(CSR_VSTART , vstart);
RESTORE(CSR_VXSAT , vxsat);
RESTORE(CSR_VXRM , vxrm);
RESTORE(CSR_VCSR , vcsr);
RESTORE(CSR_VTYPE , vtype);
RESTORE(CSR_STVEC , stvec);
RESTORE(CSR_SSCRATCH , sscratch);
RESTORE(CSR_SEPC , sepc);
RESTORE(CSR_SCAUSE , scause);
RESTORE(CSR_STVAL , stval);
RESTORE(CSR_SATP , satp);
RESTORE(CSR_MSTATUS , mstatus);
RESTORE(CSR_MEDELEG , medeleg);
RESTORE(CSR_MIDELEG , mideleg);
RESTORE(CSR_MIE , mie);
RESTORE(CSR_MTVEC , mtvec);
RESTORE(CSR_MSCRATCH , mscratch);
RESTORE(CSR_MEPC , mepc);
RESTORE(CSR_MCAUSE , mcause);
RESTORE(CSR_MTVAL , mtval);
RESTORE(CSR_MIP , mip);
RESTORE(CSR_MCYCLE , mcycle);
RESTORE(CSR_MINSTRET , minstret);
if (ls.VLEN != p->VU.VLEN) {
COSPIKE_PRINTF("VLEN mismatch loadarch: $d != spike: $d\n", ls.VLEN, p->VU.VLEN);
abort();
}
if (ls.ELEN != p->VU.ELEN) {
COSPIKE_PRINTF("ELEN mismatch loadarch: $d != spike: $d\n", ls.ELEN, p->VU.ELEN);
abort();
}
for (size_t i = 0; i < 32; i++) {
s->XPR.write(i, ls.XPR[i]);
s->FPR.write(i, { (uint64_t)ls.FPR[i], (uint64_t)-1 });
memcpy(p->VU.reg_file + i * ls.VLEN / 8, ls.VPR[i], ls.VLEN / 8);
}
spike_loadarch_done = true;
p->clear_waiting_for_interrupt();
}
#endif
uint64_t s_pc = s->pc;
uint64_t interrupt_cause = cause & 0x7FFFFFFFFFFFFFFF;
bool ssip_interrupt = interrupt_cause == 0x1;
bool msip_interrupt = interrupt_cause == 0x3;
bool stip_interrupt = interrupt_cause == 0x5;
bool mtip_interrupt = interrupt_cause == 0x7;
bool debug_interrupt = interrupt_cause == 0xe;
if (raise_interrupt) {
printf("%d interrupt %lx\n", cycle, cause);
uint64_t interrupt_cause = cause & 0x7FFFFFFFFFFFFFFF;
if (interrupt_cause == 3) {
COSPIKE_PRINTF("%d interrupt %lx\n", cycle, cause);
if (ssip_interrupt || stip_interrupt) {
// do nothing
} else if (msip_interrupt) {
s->mip->backdoor_write_with_mask(MIP_MSIP, MIP_MSIP);
} else if (mtip_interrupt) {
s->mip->backdoor_write_with_mask(MIP_MTIP, MIP_MTIP);
} else if (debug_interrupt) {
return;
} else {
printf("Unknown interrupt %lx\n", interrupt_cause);
COSPIKE_PRINTF("Unknown interrupt %lx\n", interrupt_cause);
abort();
}
}
if (raise_exception)
printf("%d exception %lx\n", cycle, cause);
COSPIKE_PRINTF("%d exception %lx\n", cycle, cause);
if (valid) {
printf("%d Cosim: %lx", cycle, iaddr);
if (has_wdata) {
printf(" %lx", wdata);
}
printf("\n");
p->clear_waiting_for_interrupt();
COSPIKE_PRINTF("%d Cosim: %lx", cycle, iaddr);
// if (has_wdata) {
// COSPIKE_PRINTF(" s: %lx", wdata);
// }
COSPIKE_PRINTF("\n");
}
if (valid || raise_interrupt || raise_exception)
if (valid || raise_interrupt || raise_exception) {
p->clear_waiting_for_interrupt();
for (auto& e : read_override_devices) e.get()->was_read_from = false;
p->step(1);
if (unlikely(cospike_debug)) {
COSPIKE_PRINTF("spike pc is %lx\n", s->pc);
COSPIKE_PRINTF("spike mstatus is %lx\n", s->mstatus->read());
COSPIKE_PRINTF("spike mip is %lx\n", s->mip->read());
COSPIKE_PRINTF("spike mie is %lx\n", s->mie->read());
COSPIKE_PRINTF("spike wfi state is %d\n", p->is_waiting_for_interrupt());
}
}
if (valid) {
if (valid && !raise_exception) {
if (s_pc != iaddr) {
printf("%d PC mismatch %lx != %lx\n", cycle, s_pc, iaddr);
COSPIKE_PRINTF("%d PC mismatch spike %llx != DUT %llx\n", cycle, s_pc, iaddr);
if (unlikely(cospike_debug)) {
COSPIKE_PRINTF("spike mstatus is %lx\n", s->mstatus->read());
COSPIKE_PRINTF("spike mcause is %lx\n", s->mcause->read());
COSPIKE_PRINTF("spike mtval is %lx\n" , s->mtval->read());
COSPIKE_PRINTF("spike mtinst is %lx\n", s->mtinst->read());
}
exit(1);
}
// Try to remember magic_mem addrs, and ignore these in the future
auto& mem_write = s->log_mem_write;
if (!mem_write.empty() && tohost_addr && std::get<0>(mem_write[0]) == tohost_addr) {
reg_t wdata = std::get<1>(mem_write[0]);
if (wdata >= info->mem0_base && wdata < (info->mem0_base + info->mem0_size)) {
printf("Probable magic mem %x\n", wdata);
magic_addrs.insert(wdata);
auto& log = s->log_reg_write;
auto& mem_read = s->log_mem_read;
for (auto memwrite : mem_write) {
reg_t waddr = std::get<0>(memwrite);
uint64_t w_data = std::get<1>(memwrite);
if ((waddr == CLINT_BASE + 4*hartid) && w_data == 0) {
s->mip->backdoor_write_with_mask(MIP_MSIP, 0);
}
if ((waddr == CLINT_BASE + 0x4000 + 4*hartid)) {
s->mip->backdoor_write_with_mask(MIP_MTIP, 0);
}
// Try to remember magic_mem addrs, and ignore these in the future
if ( waddr == tohost_addr && w_data >= info->mem0_base && w_data < (info->mem0_base + info->mem0_size)) {
COSPIKE_PRINTF("Probable magic mem %lx\n", w_data);
magic_addrs.insert(w_data);
}
}
if (has_wdata) {
auto& log = s->log_reg_write;
auto& mem_read = s->log_mem_read;
bool scalar_wb = false;
bool vector_wb = false;
uint32_t vector_cnt = 0;
for (auto &regwrite : log) {
//TODO: scaling to multi issue reads?
reg_t mem_read_addr = mem_read.empty() ? 0 : std::get<0>(mem_read[0]);
for (auto regwrite : log) {
int rd = regwrite.first >> 4;
int type = regwrite.first & 0xf;
// 0 => int
// 1 => fp
// 2 => vec
// 3 => vec hint
// 4 => csr
if ((rd != 0 && type == 0) || type == 1) {
// Override reads from some CSRs
uint64_t csr_addr = (insn >> 20) & 0xfff;
bool csr_read = (insn & 0x7f) == 0x73;
if (csr_read) printf("CSR read %lx\n", csr_addr);
if (csr_read && (
(csr_addr == 0x301) || // misa
(csr_addr == 0xf13) || // mimpid
(csr_addr == 0xf12) || // marchid
(csr_addr == 0xf11) || // mvendorid
(csr_addr == 0xb00) || // mcycle
(csr_addr == 0xb02) || // minstret
(csr_addr >= 0x3b0 && csr_addr <= 0x3ef) // pmpaddr
)) {
printf("CSR override\n");
s->XPR.write(rd, wdata);
} else if (!mem_read.empty() && ((magic_addrs.count(mem_read_addr) ||
(tohost_addr && mem_read_addr == tohost_addr) ||
(fromhost_addr && mem_read_addr == fromhost_addr) ||
(CLINT_BASE <= mem_read_addr && mem_read_addr < (CLINT_BASE + CLINT_SIZE))
))) {
// Don't check reads from tohost, reads from magic memory, or reads from clint
// Technically this could be buggy because log_mem_read only reports vaddrs, but
// no software ever should access tohost/fromhost/clint with vaddrs anyways
printf("Read override %lx\n", mem_read_addr);
s->XPR.write(rd, wdata);
} else if (wdata != regwrite.second.v[0]) {
printf("%d wdata mismatch reg %d %lx != %lx\n", cycle, rd, regwrite.second.v[0], wdata);
exit(1);
}
}
int rd = regwrite.first >> 4;
int type = regwrite.first & 0xf;
// 0 => int
// 1 => fp
// 2 => vec
// 3 => vec hint
// 4 => csr
bool device_read = false;
for (auto& e : read_override_devices) if (e.get()->was_read_from) device_read = true;
bool lr_read = ((insn & MASK_LR_D) == MATCH_LR_D) || ((insn & MASK_LR_W) == MATCH_LR_W);
bool sc_read = ((insn & MASK_SC_D) == MATCH_SC_D) || ((insn & MASK_SC_W) == MATCH_SC_W);
bool ignore_read = sc_read || (!mem_read.empty() &&
(magic_addrs.count(mem_read_addr) ||
device_read ||
lr_read ||
(tohost_addr && mem_read_addr == tohost_addr) ||
(fromhost_addr && mem_read_addr == fromhost_addr)));
// check the type is compliant with writeback first
if ((type == 0 || type == 1))
scalar_wb = true;
if (type == 2) {
vector_wb = true;
}
if (type == 3) continue;
if ((rd != 0 && type == 0) || type == 1) {
// Override reads from some CSRs
uint64_t csr_addr = (insn >> 20) & 0xfff;
bool csr_read = (insn & 0x7f) == 0x73;
if (csr_read)
COSPIKE_PRINTF("CSR read %lx\n", csr_addr);
if (csr_read && ((csr_addr == 0x301) || // misa
(csr_addr == 0x306) || // mcounteren
(csr_addr == 0xf13) || // mimpid
(csr_addr == 0xf12) || // marchid
(csr_addr == 0xf11) || // mvendorid
(csr_addr == 0xb00) || // mcycle
(csr_addr == 0xb02) || // minstret
(csr_addr == 0xc00) || // cycle
(csr_addr == 0xc01) || // time
(csr_addr == 0xc02) || // instret
(csr_addr >= 0x7a0 && csr_addr <= 0x7aa) || // debug trigger registers
(csr_addr >= 0x3b0 && csr_addr <= 0x3ef) // pmpaddr
)) {
COSPIKE_PRINTF("CSR override\n");
s->XPR.write(rd, wdata);
} else if (ignore_read) {
// Don't check reads from tohost, reads from magic memory, or reads
// from clint Technically this could be buggy because log_mem_read
// only reports vaddrs, but no software ever should access
// tohost/fromhost/clint with vaddrs anyways
COSPIKE_PRINTF("Read override %lx = %lx\n", mem_read_addr, wdata);
s->XPR.write(rd, wdata);
} else if (wdata != regwrite.second.v[0]) {
COSPIKE_PRINTF("%d wdata mismatch reg %d %lx != %lx\n", cycle, rd,
regwrite.second.v[0], wdata);
exit(1);
}
}
// TODO FIX: Rocketchip TracedInstruction.wdata should be Valid(UInt)
// if (scalar_wb ^ has_wdata) {
// COSPIKE_PRINTF("Scalar wdata behavior divergence between spike and DUT\n");
// exit(-1);
// }
}
}
}
// }

View File

@@ -1,394 +0,0 @@
// See LICENSE.SiFive for license details.
// See LICENSE.Berkeley for license details.
#if VM_TRACE
#include <memory>
#if CY_FST_TRACE
#include "verilated_fst_c.h"
#else
#include "verilated.h"
#include "verilated_vcd_c.h"
#endif // CY_FST_TRACE
#endif // VM_TRACE
#include <fesvr/dtm.h>
#include <fesvr/tsi.h>
#include "remote_bitbang.h"
#include <iostream>
#include <fcntl.h>
#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <getopt.h>
// For option parsing, which is split across this file, Verilog, and
// FESVR's HTIF, a few external files must be pulled in. The list of
// files and what they provide is enumerated:
//
// $RISCV/include/fesvr/htif.h:
// defines:
// - HTIF_USAGE_OPTIONS
// - HTIF_LONG_OPTIONS_OPTIND
// - HTIF_LONG_OPTIONS
// $(ROCKETCHIP_DIR)/generated-src(-debug)?/$(CONFIG).plusArgs:
// defines:
// - PLUSARG_USAGE_OPTIONS
// variables:
// - static const char * verilog_plusargs
extern tsi_t* tsi;
extern dtm_t* dtm;
extern remote_bitbang_t * jtag;
static uint64_t trace_count = 0;
bool verbose = false;
bool done_reset = false;
void handle_sigterm(int sig)
{
dtm->stop();
}
double sc_time_stamp()
{
return trace_count;
}
static void usage(const char * program_name)
{
printf("Usage: %s [EMULATOR OPTION]... [VERILOG PLUSARG]... [HOST OPTION]... BINARY [TARGET OPTION]...\n",
program_name);
fputs("\
Run a BINARY on the Rocket Chip emulator.\n\
\n\
Mandatory arguments to long options are mandatory for short options too.\n\
\n\
EMULATOR OPTIONS\n\
-c, --cycle-count Print the cycle count before exiting\n\
+cycle-count\n\
-h, --help Display this help and exit\n\
-m, --max-cycles=CYCLES Kill the emulation after CYCLES\n\
+max-cycles=CYCLES\n\
-s, --seed=SEED Use random number seed SEED\n\
-r, --rbb-port=PORT Use PORT for remote bit bang (with OpenOCD and GDB) \n\
If not specified, a random port will be chosen\n\
automatically.\n\
-V, --verbose Enable all Chisel printfs (cycle-by-cycle info)\n\
+verbose\n\
", stdout);
#if VM_TRACE == 0
fputs("\
\n\
EMULATOR DEBUG OPTIONS (only supported in debug build -- try `make debug`)\n",
stdout);
#endif
fputs("\
-v, --vcd=FILE, Write vcd trace to FILE (or '-' for stdout)\n\
-x, --dump-start=CYCLE Start VCD tracing at CYCLE\n\
+dump-start\n\
", stdout);
fputs("\n" PLUSARG_USAGE_OPTIONS, stdout);
fputs("\n" HTIF_USAGE_OPTIONS, stdout);
printf("\n"
"EXAMPLES\n"
" - run a bare metal test:\n"
" %s $RISCV/riscv64-unknown-elf/share/riscv-tests/isa/rv64ui-p-add\n"
" - run a bare metal test showing cycle-by-cycle information:\n"
" %s +verbose $RISCV/riscv64-unknown-elf/share/riscv-tests/isa/rv64ui-p-add 2>&1 | spike-dasm\n"
#if VM_TRACE
" - run a bare metal test to generate a VCD waveform:\n"
" %s -v rv64ui-p-add.vcd $RISCV/riscv64-unknown-elf/share/riscv-tests/isa/rv64ui-p-add\n"
#endif
" - run an ELF (you wrote, called 'hello') using the proxy kernel:\n"
" %s pk hello\n",
program_name, program_name, program_name
#if VM_TRACE
, program_name
#endif
);
}
int main(int argc, char** argv)
{
unsigned random_seed = (unsigned)time(NULL) ^ (unsigned)getpid();
uint64_t max_cycles = -1;
int ret = 0;
bool print_cycles = false;
// Port numbers are 16 bit unsigned integers.
uint16_t rbb_port = 0;
#if VM_TRACE
const char* vcdfile_name = NULL;
FILE * vcdfile = NULL;
uint64_t start = 0;
#endif
int verilog_plusargs_legal = 1;
int verilated_argc = 1;
char** verilated_argv = new char*[argc];
verilated_argv[0] = argv[0];
opterr = 1;
while (1) {
static struct option long_options[] = {
{"cycle-count", no_argument, 0, 'c' },
{"help", no_argument, 0, 'h' },
{"max-cycles", required_argument, 0, 'm' },
{"seed", required_argument, 0, 's' },
{"rbb-port", required_argument, 0, 'r' },
{"verbose", no_argument, 0, 'V' },
{"permissive", no_argument, 0, 'p' },
{"permissive-off", no_argument, 0, 'o' },
#if VM_TRACE
{"vcd", required_argument, 0, 'v' },
{"dump-start", required_argument, 0, 'x' },
#endif
HTIF_LONG_OPTIONS
};
int option_index = 0;
#if VM_TRACE
int c = getopt_long(argc, argv, "-chm:s:r:v:Vx:po", long_options, &option_index);
#else
int c = getopt_long(argc, argv, "-chm:s:r:Vpo", long_options, &option_index);
#endif
if (c == -1) break;
retry:
switch (c) {
// Process long and short EMULATOR options
case '?': usage(argv[0]); return 1;
case 'c': print_cycles = true; break;
case 'h': usage(argv[0]); return 0;
case 'm': max_cycles = atoll(optarg); break;
case 's': random_seed = atoi(optarg); break;
case 'r': rbb_port = atoi(optarg); break;
case 'V': verbose = true; break;
case 'p': opterr = 0; break;
case 'o': opterr = 1; break;
#if VM_TRACE
case 'v': {
vcdfile_name = optarg;
vcdfile = strcmp(optarg, "-") == 0 ? stdout : fopen(optarg, "w");
if (!vcdfile) {
std::cerr << "Unable to open " << optarg << " for VCD write\n";
return 1;
}
break;
}
case 'x': start = atoll(optarg); break;
#endif
// Process legacy '+' EMULATOR arguments by replacing them with
// their getopt equivalents
case 1: {
std::string arg = optarg;
if (arg.substr(0, 1) != "+") {
optind--;
goto done_processing;
}
if (arg == "+verbose")
c = 'V';
else if (arg.substr(0, 12) == "+max-cycles=") {
c = 'm';
optarg = optarg+12;
}
#if VM_TRACE
else if (arg.substr(0, 12) == "+dump-start=") {
c = 'x';
optarg = optarg+12;
}
#endif
else if (arg.substr(0, 12) == "+cycle-count")
c = 'c';
else if (arg == "+permissive")
{
c = 'p';
verilated_argv[verilated_argc++] = optarg;
}
else if (arg == "+permissive-off")
{
c = 'o';
verilated_argv[verilated_argc++] = optarg;
}
// If we don't find a legacy '+' EMULATOR argument, it still could be
// a VERILOG_PLUSARG and not an error.
else if (verilog_plusargs_legal) {
const char ** plusarg = &verilog_plusargs[0];
int legal_verilog_plusarg = 0;
while (*plusarg && (legal_verilog_plusarg == 0)){
if (arg.substr(1, strlen(*plusarg)) == *plusarg) {
legal_verilog_plusarg = 1;
}
plusarg ++;
}
if (!legal_verilog_plusarg) {
verilog_plusargs_legal = 0;
} else {
c = 'P';
}
goto retry;
}
// If we STILL don't find a legacy '+' argument, it still could be
// an HTIF (HOST) argument and not an error. If this is the case, then
// we're done processing EMULATOR and VERILOG arguments.
else {
static struct option htif_long_options [] = { HTIF_LONG_OPTIONS };
struct option * htif_option = &htif_long_options[0];
while (htif_option->name) {
if (arg.substr(1, strlen(htif_option->name)) == htif_option->name) {
optind--;
goto done_processing;
}
htif_option++;
}
if(opterr) {
std::cerr << argv[0] << ": invalid plus-arg (Verilog or HTIF) \""
<< arg << "\"\n";
c = '?';
} else {
c = 'P';
}
}
goto retry;
}
case 'P': // Verilog PlusArg, add to the argument list for verilator environment
verilated_argv[verilated_argc++] = optarg;
break;
// Realize that we've hit HTIF (HOST) arguments or error out
default:
if (c >= HTIF_LONG_OPTIONS_OPTIND) {
optind--;
goto done_processing;
}
c = '?';
goto retry;
}
}
done_processing:
if (optind == argc) {
std::cerr << "No binary specified for emulator\n";
usage(argv[0]);
return 1;
}
// Copy remaining HTIF arguments (if any) and the binary file name into the verilator argument stack
while (optind < argc) verilated_argv[verilated_argc++] = argv[optind++];
if (verbose)
fprintf(stderr, "using random seed %u\n", random_seed);
srand(random_seed);
srand48(random_seed);
Verilated::randReset(2);
Verilated::commandArgs(verilated_argc, verilated_argv);
TEST_HARNESS *tile = new TEST_HARNESS;
#if VM_TRACE
Verilated::traceEverOn(true); // Verilator must compute traced signals
#if CY_FST_TRACE
std::unique_ptr<VerilatedFstC> tfp(new VerilatedFstC);
#else
std::unique_ptr<VerilatedVcdFILE> vcdfd(new VerilatedVcdFILE(vcdfile));
std::unique_ptr<VerilatedVcdC> tfp(new VerilatedVcdC(vcdfd.get()));
#endif // CY_FST_TRACE
if (vcdfile_name) {
tile->trace(tfp.get(), 99); // Trace 99 levels of hierarchy
tfp->open(vcdfile_name);
}
#endif // VM_TRACE
// RocketChip currently only supports RBB port 0, so this needs to stay here
jtag = new remote_bitbang_t(rbb_port);
signal(SIGTERM, handle_sigterm);
bool dump;
// start reset off low so a rising edge triggers async reset
tile->reset = 0;
tile->clock = 0;
tile->eval();
// reset for several cycles to handle pipelined reset
for (int i = 0; i < 100; i++) {
tile->reset = 1;
tile->clock = 0;
tile->eval();
#if VM_TRACE
dump = tfp && trace_count >= start;
if (dump)
tfp->dump(static_cast<vluint64_t>(trace_count * 2));
#endif
tile->clock = 1;
tile->eval();
#if VM_TRACE
if (dump)
tfp->dump(static_cast<vluint64_t>(trace_count * 2 + 1));
#endif
trace_count ++;
}
tile->reset = 0;
done_reset = true;
do {
tile->clock = 0;
tile->eval();
#if VM_TRACE
dump = tfp && trace_count >= start;
if (dump)
tfp->dump(static_cast<vluint64_t>(trace_count * 2));
#endif
tile->clock = 1;
tile->eval();
#if VM_TRACE
if (dump)
tfp->dump(static_cast<vluint64_t>(trace_count * 2 + 1));
#endif
trace_count++;
}
// for verilator multithreading. need to do 1 loop before checking if
// tsi exists, since tsi is created by verilated thread on the first
// serial_tick.
while ((!dtm || !dtm->done()) &&
(!jtag || !jtag->done()) &&
(!tsi || !tsi->done()) &&
!tile->io_success && trace_count < max_cycles);
#if VM_TRACE
if (tfp)
tfp->close();
if (vcdfile)
fclose(vcdfile);
#endif
if (dtm && dtm->exit_code())
{
fprintf(stderr, "*** FAILED *** via dtm (code = %d, seed %d) after %ld cycles\n", dtm->exit_code(), random_seed, trace_count);
ret = dtm->exit_code();
}
else if (tsi && tsi->exit_code())
{
fprintf(stderr, "*** FAILED *** (code = %d, seed %d) after %ld cycles\n", tsi->exit_code(), random_seed, trace_count);
ret = tsi->exit_code();
}
else if (jtag && jtag->exit_code())
{
fprintf(stderr, "*** FAILED *** via jtag (code = %d, seed %d) after %ld cycles\n", jtag->exit_code(), random_seed, trace_count);
ret = jtag->exit_code();
}
else if (trace_count == max_cycles)
{
fprintf(stderr, "*** FAILED *** via trace_count (timeout, seed %d) after %ld cycles\n", random_seed, trace_count);
ret = 2;
}
else if (verbose || print_cycles)
{
fprintf(stderr, "*** PASSED *** Completed after %ld cycles\n", trace_count);
}
if (dtm) delete dtm;
if (tsi) delete tsi;
if (jtag) delete jtag;
if (tile) delete tile;
if (verilated_argv) delete[] verilated_argv;
return ret;
}

View File

@@ -2,13 +2,22 @@
#include <riscv/processor.h>
#include <riscv/log_file.h>
#include <fesvr/context.h>
#include <fesvr/htif.h>
#include <fesvr/memif.h>
#include <fesvr/elfloader.h>
#include <map>
#include <sstream>
#include <vpi_user.h>
#include <svdpi.h>
#include "testchip_tsi.h"
extern testchip_tsi_t* tsi;
#if __has_include("spiketile_tsi.h")
#define SPIKETILE_HTIF_TSI
extern htif_t* tsi;
#endif
#if __has_include("spiketile_dtm.h")
#define SPIKETILE_HTIF_DTM
extern htif_t* dtm;
#endif
enum transfer_t {
NToB,
@@ -80,10 +89,11 @@ public:
void tcm_a(uint64_t address, uint64_t data, uint32_t mask, uint32_t opcode, uint32_t size);
bool tcm_d(uint64_t *data);
void loadmem(const char* fname);
void loadmem(size_t base, const char* fname);
void drain_stq();
bool stq_empty() { return st_q.size() == 0; };
void flush_icache();
const cfg_t &get_cfg() const { return cfg; }
const std::map<size_t, processor_t*>& get_harts() const { return harts; }
@@ -109,6 +119,7 @@ public:
bool fast_clint;
cfg_t cfg;
std::map<size_t, processor_t*> harts;
bool accessed_tofrom_host;
private:
bool handle_cache_access(reg_t addr, size_t len,
uint8_t* load_bytes,
@@ -324,7 +335,7 @@ extern "C" void spike_tile(int hartid, char* isa,
}
}
if (loadmem_file != "" && tcm_size > 0)
simif->loadmem(loadmem_file.c_str());
simif->loadmem(tcm_base, loadmem_file.c_str());
p->reset();
p->get_state()->pc = reset_vector;
@@ -334,14 +345,22 @@ extern "C" void spike_tile(int hartid, char* isa,
tile_t* tile = tiles[hartid];
chipyard_simif_t* simif = tile->simif;
processor_t* proc = tile->proc;
if (!simif->htif && tsi) {
simif->htif = (htif_t*) tsi;
}
#if defined(SPIKETILE_HTIF_TSI)
if (!simif->htif && tsi)
simif->htif = tsi;
#endif
#if defined(SPIKETILE_HTIF_DTM)
if (!simif->htif && dtm)
simif->htif = dtm;
#endif
simif->cycle = cycle;
if (debug) {
proc->halt_request = proc->HR_REGULAR;
}
if (!debug && proc->halt_request != proc->HR_NONE) {
proc->halt_request = proc->HR_NONE;
}
proc->get_state()->mip->backdoor_write_with_mask(MIP_MTIP, mtip ? MIP_MTIP : 0);
proc->get_state()->mip->backdoor_write_with_mask(MIP_MSIP, msip ? MIP_MSIP : 0);
@@ -350,6 +369,7 @@ extern "C" void spike_tile(int hartid, char* isa,
tile->max_insns = ipc;
uint64_t pre_insns = proc->get_state()->minstret->read();
simif->accessed_tofrom_host = false;
tile->spike_context.switch_to();
*insns_retired = proc->get_state()->minstret->read() - pre_insns;
if (simif->use_stq) {
@@ -439,6 +459,7 @@ chipyard_simif_t::chipyard_simif_t(size_t icache_ways,
std::vector<size_t>(),
false,
0),
accessed_tofrom_host(false),
icache_ways(icache_ways),
icache_sets(icache_sets),
dcache_ways(dcache_ways),
@@ -504,6 +525,12 @@ chipyard_simif_t::chipyard_simif_t(size_t icache_ways,
tcm = (uint8_t*)malloc(tcm_size);
}
void chipyard_simif_t::flush_icache() {
for (auto &w : icache) {
for (size_t i = 0; i < icache_sets; i++) w[i].state = NONE;
}
}
bool chipyard_simif_t::reservable(reg_t addr) {
for (auto& r: cacheables) {
if (addr >= r.base && addr < r.base + r.size) {
@@ -544,6 +571,12 @@ bool chipyard_simif_t::mmio_load(reg_t addr, size_t len, uint8_t* bytes) {
bool found = false;
bool cacheable = false;
bool readonly = false;
reg_t tohost_addr = htif ? htif->get_tohost_addr() : 0;
reg_t fromhost_addr = htif ? htif->get_fromhost_addr() : 0;
if (addr == tohost_addr || addr == fromhost_addr) {
accessed_tofrom_host = true;
}
if (addr >= tcm_base && addr < tcm_base + tcm_size) {
memcpy(bytes, tcm + addr - tcm_base, len);
return true;
@@ -579,6 +612,8 @@ bool chipyard_simif_t::mmio_load(reg_t addr, size_t len, uint8_t* bytes) {
while (!handle_cache_access(addr, len, bytes, nullptr, LOAD)) {
host->switch_to();
}
uint64_t lddata = 0;
memcpy(&lddata, bytes, len);
} else {
handle_mmio_access(addr, len, bytes, nullptr, LOAD, readonly);
}
@@ -605,6 +640,7 @@ void chipyard_simif_t::handle_mmio_access(reg_t addr, size_t len,
mmio_st = type == STORE;
if (type == STORE) {
assert(len <= 8);
mmio_stdata = 0;
memcpy(&mmio_stdata, store_bytes, len);
}
mmio_len = len;
@@ -911,6 +947,13 @@ bool chipyard_simif_t::dcache_c(uint64_t* address, uint64_t* source, int* param,
}
bool chipyard_simif_t::mmio_store(reg_t addr, size_t len, const uint8_t* bytes) {
reg_t tohost_addr = htif ? htif->get_tohost_addr() : 0;
reg_t fromhost_addr = htif ? htif->get_fromhost_addr() : 0;
if (addr == tohost_addr || addr == fromhost_addr) {
accessed_tofrom_host = true;
}
if (addr >= tcm_base && addr < tcm_base + tcm_size) {
memcpy(tcm + addr - tcm_base, bytes, len);
return true;
@@ -936,6 +979,8 @@ bool chipyard_simif_t::mmio_store(reg_t addr, size_t len, const uint8_t* bytes)
return false;
}
if (cacheable) {
uint64_t temp = 0;
memcpy(&temp, bytes, len);
if (use_stq) {
assert(len <= 8);
uint64_t stdata;
@@ -1009,30 +1054,28 @@ bool chipyard_simif_t::tcm_d(uint64_t* data) {
return true;
}
#define parse_nibble(c) ((c) >= 'a' ? (c)-'a'+10 : (c)-'0')
void chipyard_simif_t::loadmem(const char* fname) {
std::ifstream in(fname);
std::string line;
if (!in.is_open()) {
printf("SpikeTile couldn't open loadmem file %s\n", fname);
abort();
}
size_t fsize = 0;
size_t start = 0;
while (std::getline(in, line)) {
for (ssize_t i = line.length()-2, j = 0; i >= 0; i -= 2, j++) {
char byte = (parse_nibble(line[i]) << 4) | parse_nibble(line[i+1]);
ssize_t addr = (start + j) % tcm_size;
tcm[addr] = (uint8_t)byte;
void chipyard_simif_t::loadmem(size_t base, const char* fname) {
class loadmem_memif_t : public memif_t {
public:
loadmem_memif_t(chipyard_simif_t* _simif, size_t _start) : memif_t(nullptr), simif(_simif), start(_start) {}
void write(addr_t taddr, size_t len, const void* src) override
{
addr_t addr = taddr - start;
memcpy(simif->tcm + addr, src, len);
}
start += line.length()/2;
fsize += line.length()/2;
void read(addr_t taddr, size_t len, void* bytes) override {
assert(false);
}
endianness_t get_target_endianness() const override {
return endianness_little;
}
private:
chipyard_simif_t* simif;
size_t start;
} loadmem_memif(this, tcm_base);
if (fsize > tcm_size) {
fprintf(stderr, "Loadmem file is too large\n");
abort();
}
}
reg_t entry;
load_elf(fname, &loadmem_memif, &entry);
}
bool insn_should_fence(uint64_t bits) {
@@ -1060,33 +1103,31 @@ void spike_thread_main(void* arg)
// if (insn_should_fence(last_bits) && !simif->stq_empty()) {
// host->switch_to();
// }
uint64_t old_minstret = state->minstret->read();
proc->step(1);
tile->max_insns--;
if (proc->is_waiting_for_interrupt()) {
if (simif->fast_clint) {
// uint64_t mip = state->mip->read();
// uint64_t mie = state->mie->read();
//printf("Setting MTIP %x %x %x %x %lx\n", simif->cycle, old_minstret, mip, mie,
// state->pc);
state->mip->backdoor_write_with_mask(MIP_MTIP, MIP_MTIP);
tile->max_insns = tile->max_insns <= 1 ? 0 : 1;
} else {
//printf("SpikeTile in WFI\n");
tile->max_insns = 0;
}
}
if (tile->max_insns % 100 == 0) {
uint64_t old_minstret = state->minstret->read();
uint64_t tohost_addr = simif->htif ? simif->htif->get_tohost_addr() : 0;
uint64_t fromhost_addr = simif->htif ? simif->htif->get_fromhost_addr() : 0;
auto& mem_read = state->log_mem_read;
reg_t mem_read_addr = mem_read.empty() ? 0 : std::get<0>(mem_read[0]);
if ((old_minstret == state->minstret->read()) ||
(tohost_addr && mem_read_addr == tohost_addr) ||
(fromhost_addr && mem_read_addr == fromhost_addr)) {
tile->max_insns == 0;
if (state->debug_mode) {
// TODO: Fix. This needs to apply the same hack as rocket-chip...
// JALRs in debug mode should flush the ICache.
// There is no API to determine if a JALR was executed, so hack the
// pc of the JALR in the debug rom here instead.
if (state->pc == 0x838) {
simif->flush_icache();
}
}
// If we get stuck in WFI, or we start polling tohost/fromhost, switch to host thread
if ((old_minstret == state->minstret->read()) || simif->accessed_tofrom_host) {
tile->max_insns = 0;
}
state->mcycle->write(simif->cycle);
}
}

View File

@@ -1,5 +1,6 @@
import "DPI-C" function void cospike_set_sysinfo(
input string isa,
input string priv,
input int pmpregions,
input longint mem0_base,
input longint mem0_size,
@@ -16,12 +17,14 @@ import "DPI-C" function void cospike_cosim(input longint cycle,
input bit raise_exception,
input bit raise_interrupt,
input longint cause,
input longint wdata
input longint wdata,
input int priv
);
module SpikeCosim #(
parameter ISA,
parameter PRIV,
parameter PMPREGIONS,
parameter MEM0_BASE,
parameter MEM0_SIZE,
@@ -42,6 +45,7 @@ module SpikeCosim #(
input [63:0] trace_0_cause,
input trace_0_has_wdata,
input [63:0] trace_0_wdata,
input [2:0] trace_0_priv,
input trace_1_valid,
input [63:0] trace_1_iaddr,
@@ -50,11 +54,12 @@ module SpikeCosim #(
input trace_1_interrupt,
input [63:0] trace_1_cause,
input trace_1_has_wdata,
input [63:0] trace_1_wdata
input [63:0] trace_1_wdata,
input [2:0] trace_1_priv
);
initial begin
cospike_set_sysinfo(ISA, PMPREGIONS, MEM0_BASE, MEM0_SIZE, NHARTS, BOOTROM);
cospike_set_sysinfo(ISA, PRIV, PMPREGIONS, MEM0_BASE, MEM0_SIZE, NHARTS, BOOTROM);
end;
always @(posedge clock) begin
@@ -62,12 +67,12 @@ module SpikeCosim #(
if (trace_0_valid || trace_0_exception || trace_0_cause) begin
cospike_cosim(cycle, hartid, trace_0_has_wdata, trace_0_valid, trace_0_iaddr,
trace_0_insn, trace_0_exception, trace_0_interrupt, trace_0_cause,
trace_0_wdata);
trace_0_wdata, trace_0_priv);
end
if (trace_1_valid || trace_1_exception || trace_1_cause) begin
cospike_cosim(cycle, hartid, trace_1_has_wdata, trace_1_valid, trace_1_iaddr,
trace_1_insn, trace_1_exception, trace_1_interrupt, trace_1_cause,
trace_1_wdata);
trace_1_wdata, trace_1_priv);
end
end
end

View File

@@ -14,15 +14,18 @@ import testchipip.TileTraceIO
case class SpikeCosimConfig(
isa: String,
priv: String,
pmpregions: Int,
mem0_base: BigInt,
mem0_size: BigInt,
nharts: Int,
bootrom: String
bootrom: String,
has_dtm: Boolean
)
class SpikeCosim(cfg: SpikeCosimConfig) extends BlackBox(Map(
"ISA" -> StringParam(cfg.isa),
"PRIV" -> StringParam(cfg.priv),
"PMPREGIONS" -> IntParam(cfg.pmpregions),
"MEM0_BASE" -> IntParam(cfg.mem0_base),
"MEM0_SIZE" -> IntParam(cfg.mem0_size),
@@ -32,6 +35,7 @@ class SpikeCosim(cfg: SpikeCosimConfig) extends BlackBox(Map(
{
addResource("/csrc/cospike.cc")
addResource("/vsrc/cospike.v")
if (cfg.has_dtm) addResource("/csrc/cospike_dtm.h")
val io = IO(new Bundle {
val clock = Input(Clock())
val reset = Input(Bool())
@@ -46,6 +50,7 @@ class SpikeCosim(cfg: SpikeCosimConfig) extends BlackBox(Map(
val cause = UInt(64.W)
val has_wdata = Bool()
val wdata = UInt(64.W)
val priv = UInt(3.W)
}))
})
}
@@ -64,25 +69,23 @@ object SpikeCosim
require(trace.numInsns <= 2)
cosim.io.cycle := cycle
cosim.io.trace.map(t => {
t := DontCare
t.valid := false.B
t.iaddr := 0.U
t.insn := 0.U
t.exception := false.B
t.interrupt := false.B
t.cause := 0.U
})
cosim.io.hartid := hartid.U
for (i <- 0 until trace.numInsns) {
cosim.io.trace(i).valid := trace.insns(i).valid
val insn = trace.trace.insns(i)
cosim.io.trace(i).valid := insn.valid
val signed = Wire(SInt(64.W))
signed := trace.insns(i).iaddr.asSInt
signed := insn.iaddr.asSInt
cosim.io.trace(i).iaddr := signed.asUInt
cosim.io.trace(i).insn := trace.insns(i).insn
cosim.io.trace(i).exception := trace.insns(i).exception
cosim.io.trace(i).interrupt := trace.insns(i).interrupt
cosim.io.trace(i).cause := trace.insns(i).cause
cosim.io.trace(i).has_wdata := trace.insns(i).wdata.isDefined.B
cosim.io.trace(i).wdata := trace.insns(i).wdata.getOrElse(0.U)
cosim.io.trace(i).insn := insn.insn
cosim.io.trace(i).exception := insn.exception
cosim.io.trace(i).interrupt := insn.interrupt
cosim.io.trace(i).cause := insn.cause
cosim.io.trace(i).has_wdata := insn.wdata.isDefined.B
cosim.io.trace(i).wdata := insn.wdata.getOrElse(0.U)
cosim.io.trace(i).priv := insn.priv
}
}
}

View File

@@ -13,10 +13,11 @@ import freechips.rocketchip.devices.tilelink._
// DOC include start: DigitalTop
class DigitalTop(implicit p: Parameters) extends ChipyardSystem
with testchipip.CanHavePeripheryUARTTSI // Enables optional UART-based TSI transport
with testchipip.CanHavePeripheryCustomBootPin // Enables optional custom boot pin
with testchipip.HasPeripheryBootAddrReg // Use programmable boot address register
with testchipip.CanHavePeripheryBootAddrReg // Use programmable boot address register
with testchipip.CanHaveTraceIO // Enables optionally adding trace IO
with testchipip.CanHaveBackingScratchpad // Enables optionally adding a backing scratchpad
with testchipip.CanHaveBankedScratchpad // Enables optionally adding a banked scratchpad
with testchipip.CanHavePeripheryBlockDevice // Enables optionally adding the block device
with testchipip.CanHavePeripheryTLSerial // Enables optionally adding the backing memory and serial adapter
with sifive.blocks.devices.i2c.HasPeripheryI2C // Enables optionally adding the sifive I2C

View File

@@ -1,96 +0,0 @@
package chipyard
import chisel3._
import scala.collection.mutable.{ArrayBuffer, LinkedHashMap}
import freechips.rocketchip.diplomacy.{LazyModule}
import org.chipsalliance.cde.config.{Field, Parameters, Config}
import freechips.rocketchip.util.{ResetCatchAndSync}
import freechips.rocketchip.prci._
import chipyard.harness.{ApplyHarnessBinders, HarnessBinders}
import chipyard.iobinders.HasIOBinders
import chipyard.clocking.{SimplePllConfiguration, ClockDividerN}
import chipyard.HarnessClockInstantiatorKey
// HarnessClockInstantiators are classes which generate clocks that drive
// TestHarness simulation models and any Clock inputs to the ChipTop
trait HarnessClockInstantiator {
val _clockMap: LinkedHashMap[String, (Double, ClockBundle)] = LinkedHashMap.empty
// request a clock bundle at a particular frequency
def requestClockBundle(name: String, freqRequested: Double): ClockBundle = {
val clockBundle = Wire(new ClockBundle(ClockBundleParameters()))
_clockMap(name) = (freqRequested, clockBundle)
clockBundle
}
// refClock is the clock generated by TestDriver that is
// passed to the TestHarness as its implicit clock
def instantiateHarnessClocks(refClock: ClockBundle): Unit
}
// The DividerOnlyHarnessClockInstantiator uses synthesizable clock divisors
// to approximate frequency ratios between the requested clocks
class DividerOnlyHarnessClockInstantiator extends HarnessClockInstantiator {
// connect all clock wires specified to a divider only PLL
def instantiateHarnessClocks(refClock: ClockBundle): Unit = {
val sinks = _clockMap.map({ case (name, (freq, bundle)) =>
ClockSinkParameters(take=Some(ClockParameters(freqMHz=freq / (1000 * 1000))), name=Some(name))
}).toSeq
val pllConfig = new SimplePllConfiguration("harnessDividerOnlyClockGenerator", sinks)
pllConfig.emitSummaries()
val dividedClocks = LinkedHashMap[Int, Clock]()
def instantiateDivider(div: Int): Clock = {
val divider = Module(new ClockDividerN(div))
divider.suggestName(s"ClockDivideBy${div}")
divider.io.clk_in := refClock.clock
dividedClocks(div) = divider.io.clk_out
divider.io.clk_out
}
// connect wires to clock source
for (sinkParams <- sinks) {
// bypass the reference freq. (don't create a divider + reset sync)
val (divClock, divReset) = if (sinkParams.take.get.freqMHz != pllConfig.referenceFreqMHz) {
val div = pllConfig.sinkDividerMap(sinkParams)
val divClock = dividedClocks.getOrElse(div, instantiateDivider(div))
(divClock, ResetCatchAndSync(divClock, refClock.reset.asBool))
} else {
(refClock.clock, refClock.reset)
}
_clockMap(sinkParams.name.get)._2.clock := divClock
_clockMap(sinkParams.name.get)._2.reset := divReset
}
}
}
// The AbsoluteFreqHarnessClockInstantiator uses a Verilog blackbox to
// provide the precise requested frequency.
// This ClockInstantiator cannot be synthesized, run in Verilator, or run in FireSim
// It is useful for VCS/Xcelium-driven RTL simulations
class AbsoluteFreqHarnessClockInstantiator extends HarnessClockInstantiator {
def instantiateHarnessClocks(refClock: ClockBundle): Unit = {
val sinks = _clockMap.map({ case (name, (freq, bundle)) =>
ClockSinkParameters(take=Some(ClockParameters(freqMHz=freq / (1000 * 1000))), name=Some(name))
}).toSeq
// connect wires to clock source
for (sinkParams <- sinks) {
val source = Module(new ClockSourceAtFreq(sinkParams.take.get.freqMHz))
source.io.power := true.B
source.io.gate := false.B
_clockMap(sinkParams.name.get)._2.clock := source.io.clk
_clockMap(sinkParams.name.get)._2.reset := refClock.reset
}
}
}
class WithAbsoluteFreqHarnessClockInstantiator extends Config((site, here, up) => {
case HarnessClockInstantiatorKey => () => new AbsoluteFreqHarnessClockInstantiator
})

View File

@@ -25,7 +25,6 @@ import barstools.iocell.chisel._
import testchipip._
import icenet.{CanHavePeripheryIceNIC, SimNetwork, NicLoopback, NICKey, NICIOvonly}
import chipyard.{CanHaveMasterTLMemPort}
import chipyard.clocking.{HasChipyardPRCI, DividerOnlyClockGenerator}
import scala.reflect.{ClassTag}
@@ -304,6 +303,15 @@ class WithSerialTLIOCells extends OverrideIOBinder({
}).getOrElse((Nil, Nil))
})
class WithSerialTLPunchthrough extends OverrideIOBinder({
(system: CanHavePeripheryTLSerial) => system.serial_tl.map({ s =>
val sys = system.asInstanceOf[BaseSubsystem]
val port = IO(s.getWrappedValue.cloneType)
port <> s.getWrappedValue
(Seq(port), Nil)
}).getOrElse((Nil, Nil))
})
class WithAXI4MemPunchthrough extends OverrideLazyIOBinder({
(system: CanHaveMasterAXI4MemPort) => {
implicit val p: Parameters = GetSystemParameters(system)
@@ -412,6 +420,15 @@ class WithCustomBootPin extends OverrideIOBinder({
}).getOrElse((Nil, Nil))
})
class WithUARTTSIPunchthrough extends OverrideIOBinder({
(system: CanHavePeripheryUARTTSI) => system.uart_tsi.map({ p =>
val sys = system.asInstanceOf[BaseSubsystem]
val uart_tsi = IO(new UARTTSIIO(p.uartParams))
uart_tsi <> p
(Seq(uart_tsi), Nil)
}).getOrElse((Nil, Nil))
})
class WithTLMemPunchthrough extends OverrideIOBinder({
(system: CanHaveMasterTLMemPort) => {
val io_tl_mem_pins_temp = IO(DataMirror.internal.chiselTypeClone[HeterogeneousBag[TLBundle]](system.mem_tl)).suggestName("tl_slave")

View File

@@ -7,6 +7,7 @@ import chisel3.experimental.{IntParam, StringParam, IO}
import org.chipsalliance.cde.config._
import freechips.rocketchip.subsystem._
import freechips.rocketchip.devices.tilelink._
import freechips.rocketchip.devices.debug.{ExportDebug, DMI}
import freechips.rocketchip.diplomacy._
import freechips.rocketchip.rocket._
import freechips.rocketchip.tilelink._
@@ -61,6 +62,7 @@ case class SpikeCoreParams() extends CoreParams {
val useBitManipCrypto = false
val useCryptoNIST = false
val useCryptoSM = false
val useConditionalZero = false
override def vLen = 128
override def vMemDataBits = 128
@@ -189,7 +191,8 @@ class SpikeBlackBox(
readonly_uncacheable_regions: String,
executable_regions: String,
tcm_base: BigInt,
tcm_size: BigInt) extends BlackBox(Map(
tcm_size: BigInt,
use_dtm: Boolean) extends BlackBox(Map(
"HARTID" -> IntParam(hartId),
"ISA" -> StringParam(isa),
"PMPREGIONS" -> IntParam(pmpregions),
@@ -302,7 +305,11 @@ class SpikeBlackBox(
})
addResource("/vsrc/spiketile.v")
addResource("/csrc/spiketile.cc")
if (use_dtm) {
addResource("/csrc/spiketile_dtm.h")
} else {
addResource("/csrc/spiketile_tsi.h")
}
}
class SpikeTileModuleImp(outer: SpikeTile) extends BaseTileModuleImp(outer) {
@@ -326,13 +333,18 @@ class SpikeTileModuleImp(outer: SpikeTile) extends BaseTileModuleImp(outer) {
val (dcache_tl, dcacheEdge) = outer.dcacheNode.out(0)
val (mmio_tl, mmioEdge) = outer.mmioNode.out(0)
// Note: This assumes that if the debug module exposes the ClockedDMI port,
// then the DTM-based bringup with SimDTM will be used. This isn't required to be
// true, but it usually is
val useDTM = p(ExportDebug).protocols.contains(DMI)
val spike = Module(new SpikeBlackBox(hartId, isaDTS, tileParams.core.nPMPs,
tileParams.icache.get.nSets, tileParams.icache.get.nWays,
tileParams.dcache.get.nSets, tileParams.dcache.get.nWays,
tileParams.dcache.get.nMSHRs,
cacheable_regions, uncacheable_regions, readonly_uncacheable_regions, executable_regions,
outer.spikeTileParams.tcmParams.map(_.base).getOrElse(0),
outer.spikeTileParams.tcmParams.map(_.size).getOrElse(0)
outer.spikeTileParams.tcmParams.map(_.size).getOrElse(0),
useDTM
))
spike.io.clock := clock.asBool
val cycle = RegInit(0.U(64.W))
@@ -421,7 +433,7 @@ class SpikeTileModuleImp(outer: SpikeTile) extends BaseTileModuleImp(outer) {
spike.io.mmio.a.ready := mmio_tl.a.ready
mmio_tl.a.valid := spike.io.mmio.a.valid
val log_size = MuxCase(0.U, (0 until 3).map { i => (spike.io.mmio.a.size === (1 << i).U) -> i.U })
val log_size = (0 until 4).map { i => Mux(spike.io.mmio.a.size === (1 << i).U, i.U, 0.U) }.reduce(_|_)
mmio_tl.a.bits := Mux(spike.io.mmio.a.store,
mmioEdge.Put(0.U, spike.io.mmio.a.address, log_size, spike.io.mmio.a.data)._2,
mmioEdge.Get(0.U, spike.io.mmio.a.address, log_size)._2)

View File

@@ -1,63 +0,0 @@
package chipyard
import chisel3._
import scala.collection.mutable.{ArrayBuffer, LinkedHashMap}
import freechips.rocketchip.diplomacy.{LazyModule}
import org.chipsalliance.cde.config.{Field, Parameters}
import freechips.rocketchip.util.{ResetCatchAndSync}
import freechips.rocketchip.prci.{ClockBundle, ClockBundleParameters, ClockSinkParameters, ClockParameters}
import chipyard.harness.{ApplyHarnessBinders, HarnessBinders}
import chipyard.iobinders.HasIOBinders
import chipyard.clocking.{SimplePllConfiguration, ClockDividerN}
// -------------------------------
// Chipyard Test Harness
// -------------------------------
case object BuildTop extends Field[Parameters => LazyModule]((p: Parameters) => new ChipTop()(p))
case object DefaultClockFrequencyKey extends Field[Double](100.0) // MHz
case object HarnessClockInstantiatorKey extends Field[() => HarnessClockInstantiator](() => new DividerOnlyHarnessClockInstantiator)
trait HasHarnessSignalReferences {
implicit val p: Parameters
val harnessClockInstantiator = p(HarnessClockInstantiatorKey)()
// clock/reset of the chiptop reference clock (can be different than the implicit harness clock/reset)
var refClockFreq: Double = p(DefaultClockFrequencyKey)
def setRefClockFreq(freqMHz: Double) = { refClockFreq = freqMHz }
def getRefClockFreq: Double = refClockFreq
def buildtopClock: Clock
def buildtopReset: Reset
def success: Bool
}
class TestHarness(implicit val p: Parameters) extends Module with HasHarnessSignalReferences {
val io = IO(new Bundle {
val success = Output(Bool())
})
val buildtopClock = Wire(Clock())
val buildtopReset = Wire(Reset())
val lazyDut = LazyModule(p(BuildTop)(p)).suggestName("chiptop")
val dut = Module(lazyDut.module)
io.success := false.B
val success = io.success
lazyDut match { case d: HasIOBinders =>
ApplyHarnessBinders(this, d.lazySystem, d.portMap)
}
val refClkBundle = harnessClockInstantiator.requestClockBundle("buildtop_reference_clock", getRefClockFreq * (1000 * 1000))
buildtopClock := refClkBundle.clock
buildtopReset := WireInit(refClkBundle.reset)
val implicitHarnessClockBundle = Wire(new ClockBundle(ClockBundleParameters()))
implicitHarnessClockBundle.clock := clock
implicitHarnessClockBundle.reset := reset
harnessClockInstantiator.instantiateHarnessClocks(implicitHarnessClockBundle)
}

View File

@@ -13,53 +13,11 @@ class ClockWithFreq(val freqMHz: Double) extends Bundle {
val clock = Clock()
}
// This uses synthesizable clock divisors to approximate frequency rations
// between the requested clocks. This is currently the defualt clock generator "model",
// as it can be used in VCS/Xcelium/Verilator/FireSim
class WithDividerOnlyClockGenerator extends OverrideLazyIOBinder({
(system: HasChipyardPRCI) => {
// Connect the implicit clock
implicit val p = GetSystemParameters(system)
val implicitClockSinkNode = ClockSinkNode(Seq(ClockSinkParameters(name = Some("implicit_clock"))))
system.connectImplicitClockSinkNode(implicitClockSinkNode)
InModuleBody {
val implicit_clock = implicitClockSinkNode.in.head._1.clock
val implicit_reset = implicitClockSinkNode.in.head._1.reset
system.asInstanceOf[BaseSubsystem].module match { case l: LazyModuleImp => {
l.clock := implicit_clock
l.reset := implicit_reset
}}
}
// Connect all other requested clocks
val referenceClockSource = ClockSourceNode(Seq(ClockSourceParameters()))
val dividerOnlyClockGen = LazyModule(new DividerOnlyClockGenerator("buildTopClockGenerator"))
(system.allClockGroupsNode
:= dividerOnlyClockGen.node
:= referenceClockSource)
InModuleBody {
val clock_wire = Wire(Input(new ClockWithFreq(dividerOnlyClockGen.module.referenceFreq)))
val reset_wire = Wire(Input(AsyncReset()))
val (clock_io, clockIOCell) = IOCell.generateIOFromSignal(clock_wire, "clock", p(IOCellKey))
val (reset_io, resetIOCell) = IOCell.generateIOFromSignal(reset_wire, "reset", p(IOCellKey))
referenceClockSource.out.unzip._1.map { o =>
o.clock := clock_wire.clock
o.reset := reset_wire
}
(Seq(clock_io, reset_io), clockIOCell ++ resetIOCell)
}
}
})
// This uses the FakePLL, which uses a ClockAtFreq Verilog blackbox to generate
// the requested clocks. This also adds TileLink ClockDivider and ClockSelector
// blocks, which allow memory-mapped control of clock division, and clock muxing
// between the FakePLL and the slow off-chip clock
// Note: This will not simulate properly with verilator or firesim
// Note: This will not simulate properly with firesim
class WithPLLSelectorDividerClockGenerator extends OverrideLazyIOBinder({
(system: HasChipyardPRCI) => {
// Connect the implicit clock
@@ -80,9 +38,9 @@ class WithPLLSelectorDividerClockGenerator extends OverrideLazyIOBinder({
val clockSelector = system.prci_ctrl_domain { LazyModule(new TLClockSelector(baseAddress + 0x30000, tlbus.beatBytes)) }
val pllCtrl = system.prci_ctrl_domain { LazyModule(new FakePLLCtrl (baseAddress + 0x40000, tlbus.beatBytes)) }
tlbus.toVariableWidthSlave(Some("clock-div-ctrl")) { clockDivider.tlNode := TLBuffer() }
tlbus.toVariableWidthSlave(Some("clock-sel-ctrl")) { clockSelector.tlNode := TLBuffer() }
tlbus.toVariableWidthSlave(Some("pll-ctrl")) { pllCtrl.tlNode := TLBuffer() }
clockDivider.tlNode := system.prci_ctrl_domain { TLFragmenter(tlbus.beatBytes, tlbus.blockBytes) := system.prci_ctrl_bus.get }
clockSelector.tlNode := system.prci_ctrl_domain { TLFragmenter(tlbus.beatBytes, tlbus.blockBytes) := system.prci_ctrl_bus.get }
pllCtrl.tlNode := system.prci_ctrl_domain { TLFragmenter(tlbus.beatBytes, tlbus.blockBytes) := system.prci_ctrl_bus.get }
system.allClockGroupsNode := clockDivider.clockNode := clockSelector.clockNode
@@ -100,7 +58,7 @@ class WithPLLSelectorDividerClockGenerator extends OverrideLazyIOBinder({
pllCtrlSink := pllCtrl.ctrlNode
InModuleBody {
val clock_wire = Wire(Input(new ClockWithFreq(80)))
val clock_wire = Wire(Input(new ClockWithFreq(100)))
val reset_wire = Wire(Input(AsyncReset()))
val (clock_io, clockIOCell) = IOCell.generateIOFromSignal(clock_wire, "clock", p(IOCellKey))
val (reset_io, resetIOCell) = IOCell.generateIOFromSignal(reset_wire, "reset", p(IOCellKey))
@@ -125,3 +83,43 @@ class WithPLLSelectorDividerClockGenerator extends OverrideLazyIOBinder({
}
}
})
// This passes all clocks through to the TestHarness
class WithPassthroughClockGenerator extends OverrideLazyIOBinder({
(system: HasChipyardPRCI) => {
// Connect the implicit clock
implicit val p = GetSystemParameters(system)
val implicitClockSinkNode = ClockSinkNode(Seq(ClockSinkParameters(name = Some("implicit_clock"))))
system.connectImplicitClockSinkNode(implicitClockSinkNode)
InModuleBody {
val implicit_clock = implicitClockSinkNode.in.head._1.clock
val implicit_reset = implicitClockSinkNode.in.head._1.reset
system.asInstanceOf[BaseSubsystem].module match { case l: LazyModuleImp => {
l.clock := implicit_clock
l.reset := implicit_reset
}}
}
// This aggregate node should do nothing
val clockGroupAggNode = ClockGroupAggregateNode("fake")
val clockGroupsSourceNode = ClockGroupSourceNode(Seq(ClockGroupSourceParameters()))
system.allClockGroupsNode := clockGroupAggNode := clockGroupsSourceNode
InModuleBody {
val reset_io = IO(Input(AsyncReset()))
require(clockGroupAggNode.out.size == 1)
val (bundle, edge) = clockGroupAggNode.out(0)
val clock_ios = (bundle.member.data zip edge.sink.members).map { case (b, m) =>
require(m.take.isDefined, s"""Clock ${m.name.get} has no requested frequency
|Clocks: ${edge.sink.members.map(_.name.get)}""".stripMargin)
val freq = m.take.get.freqMHz
val clock_io = IO(Input(new ClockWithFreq(freq))).suggestName(s"clock_${m.name.get}")
b.clock := clock_io.clock
b.reset := reset_io
clock_io
}.toSeq
((clock_ios :+ reset_io), Nil)
}
}
})

View File

@@ -23,10 +23,9 @@ object ClockGroupCombiner {
case object ClockGroupCombinerKey extends Field[Seq[(String, ClockSinkParameters => Boolean)]](Nil)
// All clock groups with a name containing any substring in names will be combined into a single clock group
class WithClockGroupsCombinedByName(grouped_name: String, names: String*) extends Config((site, here, up) => {
case ClockGroupCombinerKey => {
val combiner: ClockSinkParameters => Boolean = { m => names.map(n => m.name.get.contains(n)).reduce(_||_) }
up(ClockGroupCombinerKey) ++ Seq((grouped_name, combiner))
class WithClockGroupsCombinedByName(groups: (String, Seq[String], Seq[String])*) extends Config((site, here, up) => {
case ClockGroupCombinerKey => groups.map { case (grouped_name, matched_names, unmatched_names) =>
(grouped_name, (m: ClockSinkParameters) => matched_names.exists(n => m.name.get.contains(n)) && !unmatched_names.exists(n => m.name.get.contains(n)))
}
})
@@ -49,9 +48,14 @@ class ClockGroupCombiner(implicit p: Parameters, v: ValName) extends LazyModule
val name = combiners(i)._1
i = i + 1
require(g.size >= 1)
require(g.forall(_.take.get == g.head.take.get))
(grouped ++ Seq(ClockSinkParameters(take = g.head.take, name = Some(name))), r)
val takes = g.map(_.take).flatten
require(takes.distinct.size <= 1,
s"Clock group $name has non-homogeneous requested ClockParameters $takes")
require(takes.size > 0,
s"Clock group $name has no inheritable frequencies")
(grouped ++ Seq(ClockSinkParameters(take = takes.headOption, name = Some(name))), r)
}
ClockGroupSinkParameters(
name = u.name,
members = grouped ++ rest

View File

@@ -60,23 +60,23 @@ object ClockGroupNamePrefixer {
* The default if all functions return None.
*/
object ClockGroupFrequencySpecifier {
def apply(
assigners: Seq[(String) => Option[Double]],
defaultFreq: Double)(
implicit p: Parameters, valName: ValName): ClockGroupAdapterNode = {
def apply(assigners: Seq[(String) => Option[Double]])(
implicit p: Parameters, valName: ValName): ClockGroupAdapterNode = {
def lookupFrequencyForName(clock: ClockSinkParameters): ClockSinkParameters = {
require(clock.name.nonEmpty, "All clocks in clock group must have an assigned name")
val clockFreq = assigners.foldLeft(defaultFreq)(
(currentFreq, candidateFunc) => candidateFunc(clock.name.get).getOrElse(currentFreq))
clock.copy(take = clock.take match {
case Some(cp) =>
println(s"Clock ${clock.name.get}: using diplomatically specified frequency of ${cp.freqMHz}.")
Some(cp)
case None => Some(ClockParameters(clockFreq))
})
}
def lookupFrequencyForName(clock: ClockSinkParameters): ClockSinkParameters = clock.copy(take = clock.take match {
case Some(cp) =>
println(s"Clock ${clock.name.get}: using diplomatically specified frequency of ${cp.freqMHz}.")
Some(cp)
case None => {
val freqs = assigners.map { f => f(clock.name.get) }.flatten
if (freqs.size > 0) {
println(s"Clock ${clock.name.get}: using specified frequency of ${freqs.last}")
Some(ClockParameters(freqs.last))
} else {
None
}
}
})
LazyModule(new ClockGroupParameterModifier(sinkFn = { s => s.copy(members = s.members.map(lookupFrequencyForName)) })).node
}

View File

@@ -92,57 +92,3 @@ class SimplePllConfiguration(
def referenceSinkParams(): ClockSinkParameters = sinkDividerMap.find(_._2 == 1).get._1
}
case class DividerOnlyClockGeneratorNode(pllName: String)(implicit valName: ValName)
extends MixedNexusNode(ClockImp, ClockGroupImp)(
dFn = { _ => ClockGroupSourceParameters() },
uFn = { u =>
require(u.size == 1)
require(!u.head.members.contains(None),
"All output clocks in group must set their take parameters. Use a ClockGroupDealiaser")
ClockSinkParameters(
name = Some(s"${pllName}_reference_input"),
take = Some(ClockParameters(new SimplePllConfiguration(pllName, u.head.members).referenceFreqMHz))) }
)
/**
* Generates a digital-divider-only PLL model that verilator can simulate.
* Inspects all take-specified frequencies in the output ClockGroup, calculates a
* fast reference clock (roughly LCM(requested frequencies)) which is passed up the
* diplomatic graph, and then generates dividers for each unique requested
* frequency.
*
* Output resets are not synchronized to generated clocks and should be
* synchronized by the user in a manner they see fit.
*
*/
class DividerOnlyClockGenerator(pllName: String)(implicit p: Parameters, valName: ValName) extends LazyModule {
val node = DividerOnlyClockGeneratorNode(pllName)
lazy val module = new Impl
class Impl extends LazyRawModuleImp(this) {
require(node.out.size == 1, "Idealized PLL expects to generate a single output clock group. Use a ClockGroupAggregator")
val (refClock, ClockEdgeParameters(_, refSinkParam, _, _)) = node.in.head
val (outClocks, ClockGroupEdgeParameters(_, outSinkParams, _, _)) = node.out.head
val referenceFreq = refSinkParam.take.get.freqMHz
val pllConfig = new SimplePllConfiguration(pllName, outSinkParams.members)
pllConfig.emitSummaries()
val dividedClocks = mutable.HashMap[Int, Clock]()
def instantiateDivider(div: Int): Clock = {
val divider = Module(new ClockDividerN(div))
divider.suggestName(s"ClockDivideBy${div}")
divider.io.clk_in := refClock.clock
dividedClocks(div) = divider.io.clk_out
divider.io.clk_out
}
for (((sinkBName, sinkB), sinkP) <- outClocks.member.elements.zip(outSinkParams.members)) {
val div = pllConfig.sinkDividerMap(sinkP)
sinkB.clock := dividedClocks.getOrElse(div, instantiateDivider(div))
// Reset handling and synchronization is expected to be handled by a downstream node
sinkB.reset := refClock.reset
}
}
}

View File

@@ -14,15 +14,17 @@ import freechips.rocketchip.util._
import freechips.rocketchip.tile._
import freechips.rocketchip.prci._
import testchipip.{TLTileResetCtrl}
import chipyard.{DefaultClockFrequencyKey}
import testchipip.{TLTileResetCtrl, ClockGroupFakeResetSynchronizer}
case class ChipyardPRCIControlParams(
slaveWhere: TLBusWrapperLocation = CBUS,
baseAddress: BigInt = 0x100000,
enableTileClockGating: Boolean = true,
enableTileResetSetting: Boolean = true
)
enableTileResetSetting: Boolean = true,
enableResetSynchronizers: Boolean = true // this should only be disabled to work around verilator async-reset initialization problems
) {
def generatePRCIXBar = enableTileClockGating || enableTileResetSetting
}
case object ChipyardPRCIControlKey extends Field[ChipyardPRCIControlParams](ChipyardPRCIControlParams())
@@ -37,6 +39,13 @@ trait HasChipyardPRCI { this: BaseSubsystem with InstantiatesTiles =>
val prci_ctrl_domain = LazyModule(new ClockSinkDomain(name=Some("chipyard-prci-control")))
prci_ctrl_domain.clockNode := tlbus.fixedClockNode
val prci_ctrl_bus = Option.when(prciParams.generatePRCIXBar) { prci_ctrl_domain { TLXbar() } }
prci_ctrl_bus.foreach(xbar => tlbus.coupleTo("prci_ctrl") { (xbar
:= TLFIFOFixer(TLFIFOFixer.all)
:= TLBuffer()
:= _)
})
// Aggregate all the clock groups into a single node
val aggregator = LazyModule(new ClockGroupAggregator("allClocks")).node
val allClockGroupsNode = ClockGroupEphemeralNode()
@@ -70,21 +79,47 @@ trait HasChipyardPRCI { this: BaseSubsystem with InstantiatesTiles =>
// 5. Add reset control registers to the tiles (if desired)
// The final clock group here contains physically distinct clock domains, which some PRCI node in a
// diplomatic IOBinder should drive
val frequencySpecifier = ClockGroupFrequencySpecifier(p(ClockFrequencyAssignersKey), p(DefaultClockFrequencyKey))
val frequencySpecifier = ClockGroupFrequencySpecifier(p(ClockFrequencyAssignersKey))
val clockGroupCombiner = ClockGroupCombiner()
val resetSynchronizer = ClockGroupResetSynchronizer()
val tileClockGater = if (prciParams.enableTileClockGating) { prci_ctrl_domain {
TileClockGater(prciParams.baseAddress + 0x00000, tlbus)
} } else { ClockGroupEphemeralNode() }
val tileResetSetter = if (prciParams.enableTileResetSetting) { prci_ctrl_domain {
TileResetSetter(prciParams.baseAddress + 0x10000, tlbus, tile_prci_domains.map(_.tile_reset_domain.clockNode.portParams(0).name.get), Nil)
} } else { ClockGroupEphemeralNode() }
val resetSynchronizer = prci_ctrl_domain {
if (prciParams.enableResetSynchronizers) ClockGroupResetSynchronizer() else ClockGroupFakeResetSynchronizer()
}
val tileClockGater = Option.when(prciParams.enableTileClockGating) { prci_ctrl_domain {
val clock_gater = LazyModule(new TileClockGater(prciParams.baseAddress + 0x00000, tlbus.beatBytes))
clock_gater.tlNode := TLFragmenter(tlbus.beatBytes, tlbus.blockBytes) := prci_ctrl_bus.get
clock_gater
} }
val tileResetSetter = Option.when(prciParams.enableTileResetSetting) { prci_ctrl_domain {
val reset_setter = LazyModule(new TileResetSetter(prciParams.baseAddress + 0x10000, tlbus.beatBytes,
tile_prci_domains.map(_.tile_reset_domain.clockNode.portParams(0).name.get), Nil))
reset_setter.tlNode := TLFragmenter(tlbus.beatBytes, tlbus.blockBytes) := prci_ctrl_bus.get
reset_setter
} }
if (!prciParams.enableResetSynchronizers) {
println(Console.RED + s"""
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
WARNING:
DISABLING THE RESET SYNCHRONIZERS RESULTS IN
A BROKEN DESIGN THAT WILL NOT BEHAVE
PROPERLY AS ASIC OR FPGA.
THESE SHOULD ONLY BE DISABLED TO WORK AROUND
LIMITATIONS IN ASYNC RESET INITIALIZATION IN
RTL SIMULATORS, NAMELY VERILATOR.
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
""" + Console.RESET)
}
(aggregator
:= frequencySpecifier
:= clockGroupCombiner
:= resetSynchronizer
:= tileClockGater
:= tileResetSetter
:= tileClockGater.map(_.clockNode).getOrElse(ClockGroupEphemeralNode()(ValName("temp")))
:= tileResetSetter.map(_.clockNode).getOrElse(ClockGroupEphemeralNode()(ValName("temp")))
:= allClockGroupsNode)
}

View File

@@ -26,20 +26,26 @@ class TLClockDivider(address: BigInt, beatBytes: Int, divBits: Int = 8)(implicit
val sinks = clockNode.out.head._1.member.elements.toSeq
require (sources.size == sinks.size)
val nSinks = sinks.size
// The implicit clock of this module is the clock of the tilelink bus
// busReset is sync'd to that clock, and will be asserted longer than the
// resets coming in through the clockNode, since the busReset is derived from
// the clockNode resets in downstream PRCI nodes
val busReset = reset
val regs = (0 until nSinks) .map { i =>
val sinkName = sinks(i)._1
val asyncReset = sources(i).reset
val reg = withReset (asyncReset) {
Module(new AsyncResetRegVec(w=divBits, init=0))
}
val reg = Module(new AsyncResetRegVec(w=divBits, init=0))
println(s"${(address+i*4).toString(16)}: Clock domain $sinkName divider")
sinks(i)._2.clock := withClockAndReset(sources(i).clock, asyncReset) {
val divider = Module(new testchipip.ClockDivideOrPass(divBits, depth = 3, genClockGate = p(ClockGateImpl)))
divider.io.divisor := reg.io.q
divider.io.resetAsync := ResetStretcher(sources(i).clock, asyncReset, 20).asAsyncReset
divider.io.clockOut
}
val divider = Module(new testchipip.ClockDivideOrPass(divBits, depth = 3, genClockGate = p(ClockGateImpl)))
divider.io.clockIn := sources(i).clock
// busReset is expected to be high for a long time, since reset will take a while to propagate
// to the TL bus. While reset is propagating, make sure we propagate a fast, undivided clock
// by setting divisor=0. The divisor signal into the ClockDividerOrPass is synchronized internally
divider.io.divisor := Mux(busReset.asBool, 0.U, reg.io.q)
divider.io.resetAsync := ResetStretcher(sources(i).clock, asyncReset, 20).asAsyncReset
sinks(i)._2.clock := divider.io.clockOut
// Note this is not synchronized to the output clock, which takes time to appear
// so this is still asyncreset

View File

@@ -13,23 +13,6 @@ import freechips.rocketchip.util.ElaborationArtefacts
import testchipip._
object ResetStretcher {
def apply(clock: Clock, reset: Reset, cycles: Int): Reset = {
withClockAndReset(clock, reset) {
val n = log2Ceil(cycles)
val count = Module(new AsyncResetRegVec(w=n, init=0))
val resetout = Module(new AsyncResetRegVec(w=1, init=1))
count.io.en := resetout.io.q
count.io.d := count.io.q + 1.U
resetout.io.en := resetout.io.q
resetout.io.d := count.io.q < (cycles-1).U
resetout.io.q.asBool
}
}
}
case class ClockSelNode()(implicit valName: ValName)
extends MixedNexusNode(ClockImp, ClockGroupImp)(
dFn = { d => ClockGroupSourceParameters() },

View File

@@ -46,10 +46,3 @@ class TileClockGater(address: BigInt, beatBytes: Int)(implicit p: Parameters, va
}
}
object TileClockGater {
def apply(address: BigInt, tlbus: TLBusWrapper)(implicit p: Parameters, v: ValName) = {
val gater = LazyModule(new TileClockGater(address, tlbus.beatBytes))
tlbus.toVariableWidthSlave(Some("clock-gater")) { gater.tlNode := TLBuffer() }
gater.clockNode
}
}

View File

@@ -62,12 +62,3 @@ class TileResetSetter(address: BigInt, beatBytes: Int, tileNames: Seq[String], i
}
}
}
object TileResetSetter {
def apply(address: BigInt, tlbus: TLBusWrapper, tileNames: Seq[String], initResetHarts: Seq[Int])(implicit p: Parameters, v: ValName) = {
val setter = LazyModule(new TileResetSetter(address, tlbus.beatBytes, tileNames, initResetHarts))
tlbus.toVariableWidthSlave(Some("tile-reset-setter")) { setter.tlNode := TLBuffer() }
setter.clockNode
}
}

View File

@@ -12,50 +12,58 @@ import org.chipsalliance.cde.config.{Config}
class AbstractConfig extends Config(
// The HarnessBinders control generation of hardware in the TestHarness
new chipyard.harness.WithUARTAdapter ++ // add UART adapter to display UART on stdout, if uart is present
new chipyard.harness.WithBlackBoxSimMem ++ // add SimDRAM DRAM model for axi4 backing memory, if axi4 mem is enabled
new chipyard.harness.WithSimSerial ++ // add external serial-adapter and RAM
new chipyard.harness.WithSimDebug ++ // add SimJTAG or SimDTM adapters if debug module is enabled
new chipyard.harness.WithGPIOTiedOff ++ // tie-off chiptop GPIOs, if GPIOs are present
new chipyard.harness.WithSimSPIFlashModel ++ // add simulated SPI flash memory, if SPI is enabled
new chipyard.harness.WithSimAXIMMIO ++ // add SimAXIMem for axi4 mmio port, if enabled
new chipyard.harness.WithTieOffInterrupts ++ // tie-off interrupt ports, if present
new chipyard.harness.WithTieOffL2FBusAXI ++ // tie-off external AXI4 master, if present
new chipyard.harness.WithCustomBootPinPlusArg ++
new chipyard.harness.WithClockAndResetFromHarness ++
new chipyard.harness.WithUARTAdapter ++ // add UART adapter to display UART on stdout, if uart is present
new chipyard.harness.WithBlackBoxSimMem ++ // add SimDRAM DRAM model for axi4 backing memory, if axi4 mem is enabled
new chipyard.harness.WithSimTSIOverSerialTL ++ // add external serial-adapter and RAM
new chipyard.harness.WithSimDebug ++ // add SimJTAG or SimDTM adapters if debug module is enabled
new chipyard.harness.WithGPIOTiedOff ++ // tie-off chiptop GPIOs, if GPIOs are present
new chipyard.harness.WithSimSPIFlashModel ++ // add simulated SPI flash memory, if SPI is enabled
new chipyard.harness.WithSimAXIMMIO ++ // add SimAXIMem for axi4 mmio port, if enabled
new chipyard.harness.WithTieOffInterrupts ++ // tie-off interrupt ports, if present
new chipyard.harness.WithTieOffL2FBusAXI ++ // tie-off external AXI4 master, if present
new chipyard.harness.WithCustomBootPinPlusArg ++ // drive custom-boot pin with a plusarg, if custom-boot-pin is present
new chipyard.harness.WithSimUARTToUARTTSI ++ // connect a SimUART to the UART-TSI port
new chipyard.harness.WithClockAndResetFromHarness ++ // all Clock/Reset I/O in ChipTop should be driven by harnessClockInstantiator
new chipyard.harness.WithAbsoluteFreqHarnessClockInstantiator ++ // generate clocks in harness with unsynthesizable ClockSourceAtFreqMHz
// The IOBinders instantiate ChipTop IOs to match desired digital IOs
// IOCells are generated for "Chip-like" IOs, while simulation-only IOs are directly punched through
// IOCells are generated for "Chip-like" IOs
new chipyard.iobinders.WithSerialTLIOCells ++
new chipyard.iobinders.WithDebugIOCells ++
new chipyard.iobinders.WithUARTIOCells ++
new chipyard.iobinders.WithGPIOCells ++
new chipyard.iobinders.WithSPIIOCells ++
new chipyard.iobinders.WithExtInterruptIOCells ++
new chipyard.iobinders.WithCustomBootPin ++
// The "punchthrough" IOBInders below don't generate IOCells, as these interfaces shouldn't really be mapped to ASIC IO
// Instead, they directly pass through the DigitalTop ports to ports in the ChipTop
new chipyard.iobinders.WithAXI4MemPunchthrough ++
new chipyard.iobinders.WithAXI4MMIOPunchthrough ++
new chipyard.iobinders.WithTLMemPunchthrough ++
new chipyard.iobinders.WithL2FBusAXI4Punchthrough ++
new chipyard.iobinders.WithBlockDeviceIOPunchthrough ++
new chipyard.iobinders.WithNICIOPunchthrough ++
new chipyard.iobinders.WithSerialTLIOCells ++
new chipyard.iobinders.WithDebugIOCells ++
new chipyard.iobinders.WithUARTIOCells ++
new chipyard.iobinders.WithGPIOCells ++
new chipyard.iobinders.WithSPIIOCells ++
new chipyard.iobinders.WithTraceIOPunchthrough ++
new chipyard.iobinders.WithExtInterruptIOCells ++
new chipyard.iobinders.WithCustomBootPin ++
new chipyard.iobinders.WithUARTTSIPunchthrough ++
// Default behavior is to use a divider-only clock-generator
// This works in VCS, Verilator, and FireSim/
// This should get replaced with a PLL-like config instead
new chipyard.clocking.WithDividerOnlyClockGenerator ++
// By default, punch out IOs to the Harness
new chipyard.clocking.WithPassthroughClockGenerator ++
new chipyard.clocking.WithClockGroupsCombinedByName(("uncore", Seq("sbus", "mbus", "pbus", "fbus", "cbus", "implicit"), Seq("tile"))) ++
new chipyard.config.WithPeripheryBusFrequency(500.0) ++ // Default 500 MHz pbus
new chipyard.config.WithMemoryBusFrequency(500.0) ++ // Default 500 MHz mbus
new testchipip.WithCustomBootPin ++ // add a custom-boot-pin to support pin-driven boot address
new testchipip.WithBootAddrReg ++ // add a boot-addr-reg for configurable boot address
new testchipip.WithSerialTLClientIdBits(4) ++ // support up to 1 << 4 simultaneous requests from serialTL port
new testchipip.WithSerialTLWidth(32) ++ // fatten the serialTL interface to improve testing performance
new testchipip.WithDefaultSerialTL ++ // use serialized tilelink port to external serialadapter/harnessRAM
new chipyard.config.WithDebugModuleAbstractDataWords(8) ++ // increase debug module data capacity
new chipyard.config.WithBootROM ++ // use default bootrom
new chipyard.config.WithUART ++ // add a UART
new chipyard.config.WithL2TLBs(1024) ++ // use L2 TLBs
new chipyard.config.WithNoSubsystemDrivenClocks ++ // drive the subsystem diplomatic clocks from ChipTop instead of using implicit clocks
new chipyard.config.WithInheritBusFrequencyAssignments ++ // Unspecified clocks within a bus will receive the bus frequency if set
new chipyard.config.WithPeripheryBusFrequencyAsDefault ++ // Unspecified frequencies with match the pbus frequency (which is always set)
new chipyard.config.WithMemoryBusFrequency(100.0) ++ // Default 100 MHz mbus
new chipyard.config.WithPeripheryBusFrequency(100.0) ++ // Default 100 MHz pbus
new freechips.rocketchip.subsystem.WithNMemoryChannels(1) ++ // Default 1 memory channels
new freechips.rocketchip.subsystem.WithClockGateModel ++ // add default EICG_wrapper clock gate model
new freechips.rocketchip.subsystem.WithJtagDTM ++ // set the debug module to expose a JTAG port
new freechips.rocketchip.subsystem.WithNoMMIOPort ++ // no top-level MMIO master port (overrides default set in rocketchip)

View File

@@ -53,3 +53,18 @@ class MediumBoomCosimConfig extends Config(
new chipyard.config.WithTraceIO ++ // enable the traceio
new boom.common.WithNMediumBooms(1) ++
new chipyard.config.AbstractConfig)
class dmiMediumBoomConfig extends Config(
new chipyard.harness.WithSerialTLTiedOff ++ // don't attach anything to serial-tl
new chipyard.config.WithDMIDTM ++ // have debug module expose a clocked DMI port
new boom.common.WithNMediumBooms(1) ++
new chipyard.config.AbstractConfig)
class dmiMediumBoomCosimConfig extends Config(
new chipyard.harness.WithCospike ++ // attach spike-cosim
new chipyard.config.WithTraceIO ++ // enable the traceio
new chipyard.harness.WithSerialTLTiedOff ++ // don't attach anythint to serial-tl
new chipyard.config.WithDMIDTM ++ // have debug module expose a clocked DMI port
new boom.common.WithNMediumBooms(1) ++
new chipyard.config.AbstractConfig)

View File

@@ -13,7 +13,7 @@ class CVA6Config extends Config(
new chipyard.config.AbstractConfig)
class dmiCVA6Config extends Config(
new chipyard.harness.WithSerialAdapterTiedOff ++ // Tie off the serial port, override default instantiation of SimSerial
new chipyard.harness.WithSerialTLTiedOff ++ // Tie off the serial-tilelink port
new chipyard.config.WithDMIDTM ++ // have debug module expose a clocked DMI port
new cva6.WithNCVA6Cores(1) ++ // single CVA6 core
new chipyard.config.AbstractConfig)

View File

@@ -2,43 +2,106 @@ package chipyard
import org.chipsalliance.cde.config.{Config}
import freechips.rocketchip.diplomacy._
import freechips.rocketchip.subsystem.{MBUS, SBUS}
import testchipip.{OBUS}
// A simple config demonstrating how to set up a basic chip in Chipyard
class ChipLikeQuadRocketConfig extends Config(
class ChipLikeRocketConfig extends Config(
//==================================
// Set up TestHarness
//==================================
new chipyard.WithAbsoluteFreqHarnessClockInstantiator ++ // use absolute frequencies for simulations in the harness
// NOTE: This only simulates properly in VCS
new chipyard.harness.WithAbsoluteFreqHarnessClockInstantiator ++ // use absolute frequencies for simulations in the harness
// NOTE: This only simulates properly in VCS
new chipyard.harness.WithSimAXIMemOverSerialTL ++ // Attach SimDRAM to serial-tl port
//==================================
// Set up tiles
//==================================
new freechips.rocketchip.subsystem.WithAsynchronousRocketTiles(3, 3) ++ // Add rational crossings between RocketTile and uncore
new freechips.rocketchip.subsystem.WithNBigCores(4) ++ // quad-core (4 RocketTiles)
new freechips.rocketchip.subsystem.WithNBigCores(1) ++ // 1 RocketTile
//==================================
// Set up I/O
//==================================
new testchipip.WithSerialTLWidth(4) ++
new chipyard.harness.WithSimAXIMemOverSerialTL ++ // Attach fast SimDRAM to TestHarness
new chipyard.config.WithSerialTLBackingMemory ++ // Backing memory is over serial TL protocol
new testchipip.WithSerialTLBackingMemory ++ // Backing memory is over serial TL protocol
new freechips.rocketchip.subsystem.WithExtMemSize((1 << 30) * 4L) ++ // 4GB max external memory
new freechips.rocketchip.subsystem.WithNMemoryChannels(1) ++ // 1 memory channel
//==================================
// Set up buses
//==================================
new testchipip.WithOffchipBusClient(MBUS) ++
new testchipip.WithOffchipBus ++
//==================================
// Set up clock./reset
//==================================
new chipyard.clocking.WithPLLSelectorDividerClockGenerator ++ // Use a PLL-based clock selector/divider generator structure
// Create two clock groups, uncore and fbus, in addition to the tile clock groups
new chipyard.clocking.WithClockGroupsCombinedByName("uncore", "implicit", "sbus", "mbus", "cbus", "system_bus") ++
new chipyard.clocking.WithClockGroupsCombinedByName("fbus", "fbus", "pbus") ++
// Set up the crossings
new chipyard.config.WithFbusToSbusCrossingType(AsynchronousCrossing()) ++ // Add Async crossing between SBUS and FBUS
new chipyard.config.WithCbusToPbusCrossingType(AsynchronousCrossing()) ++ // Add Async crossing between PBUS and CBUS
new chipyard.config.WithSbusToMbusCrossingType(AsynchronousCrossing()) ++ // Add Async crossings between backside of L2 and MBUS
new testchipip.WithAsynchronousSerialSlaveCrossing ++ // Add Async crossing between serial and MBUS. Its master-side is tied to the FBUS
// Create the uncore clock group
new chipyard.clocking.WithClockGroupsCombinedByName(("uncore", Seq("implicit", "sbus", "mbus", "cbus", "system_bus", "fbus", "pbus"), Nil)) ++
new chipyard.config.AbstractConfig)
// A simple config demonstrating a "bringup prototype" to bringup the ChipLikeRocketconfig
class ChipBringupHostConfig extends Config(
//=============================
// Set up TestHarness for standalone-sim
//=============================
new chipyard.harness.WithAbsoluteFreqHarnessClockInstantiator ++ // Generate absolute frequencies
new chipyard.harness.WithSerialTLTiedOff ++ // when doing standalone sim, tie off the serial-tl port
new chipyard.harness.WithSimTSIToUARTTSI ++ // Attach SimTSI-over-UART to the UART-TSI port
new chipyard.iobinders.WithSerialTLPunchthrough ++ // Don't generate IOCells for the serial TL (this design maps to FPGA)
//=============================
// Setup the SerialTL side on the bringup device
//=============================
new testchipip.WithSerialTLWidth(4) ++ // match width with the chip
new testchipip.WithSerialTLMem(base = 0x0, size = 0x80000000L, // accessible memory of the chip that doesn't come from the tethered host
idBits = 4, isMainMemory = false) ++ // This assumes off-chip mem starts at 0x8000_0000
new testchipip.WithSerialTLClockDirection(provideClockFreqMHz = Some(75)) ++ // bringup board drives the clock for the serial-tl receiver on the chip, use 75MHz clock
//============================
// Setup bus topology on the bringup system
//============================
new testchipip.WithOffchipBusClient(SBUS, // offchip bus hangs off the SBUS
blockRange = AddressSet.misaligned(0x80000000L, (BigInt(1) << 30) * 4)) ++ // offchip bus should not see the main memory of the testchip, since that can be accessed directly
new testchipip.WithOffchipBus ++ // offchip bus
//=============================
// Set up memory on the bringup system
//=============================
new freechips.rocketchip.subsystem.WithExtMemSize((1 << 30) * 4L) ++ // match what the chip believes the max size should be
//=============================
// Generate the TSI-over-UART side of the bringup system
//=============================
new testchipip.WithUARTTSIClient(initBaudRate = BigInt(921600)) ++ // nonstandard baud rate to improve performance
//=============================
// Set up clocks of the bringup system
//=============================
new chipyard.clocking.WithPassthroughClockGenerator ++ // pass all the clocks through, since this isn't a chip
new chipyard.config.WithFrontBusFrequency(75.0) ++ // run all buses of this system at 75 MHz
new chipyard.config.WithMemoryBusFrequency(75.0) ++
new chipyard.config.WithPeripheryBusFrequency(75.0) ++
// Base is the no-cores config
new chipyard.NoCoresConfig)
class TetheredChipLikeRocketConfig extends Config(
new chipyard.harness.WithAbsoluteFreqHarnessClockInstantiator ++ // use absolute freqs for sims in the harness
new chipyard.harness.WithMultiChipSerialTL(0, 1) ++ // connect the serial-tl ports of the chips together
new chipyard.harness.WithMultiChip(0, new ChipLikeRocketConfig) ++
new chipyard.harness.WithMultiChip(1, new ChipBringupHostConfig))
// Verilator does not initialize some of the async-reset reset-synchronizer
// flops properly, so this config disables them.
// This config should only be used for verilator simulations
class VerilatorCITetheredChipLikeRocketConfig extends Config(
new chipyard.harness.WithAbsoluteFreqHarnessClockInstantiator ++ // use absolute freqs for sims in the harness
new chipyard.harness.WithMultiChipSerialTL(0, 1) ++ // connect the serial-tl ports of the chips together
new chipyard.harness.WithMultiChip(0, new chipyard.config.WithNoResetSynchronizers ++ new ChipLikeRocketConfig) ++
new chipyard.harness.WithMultiChip(1, new ChipBringupHostConfig))

View File

@@ -61,7 +61,6 @@ class LargeNVDLARocketConfig extends Config(
class ManyMMIOAcceleratorRocketConfig extends Config(
new chipyard.iobinders.WithDontTouchIOBinders(false) ++ // TODO: hack around dontTouch not working in SFC
new fftgenerator.WithFFTGenerator(numPoints=8, width=16, decPt=8) ++ // add 8-point mmio fft at the default addr (0x2400) with 16bit fixed-point numbers.
new nvidia.blocks.dla.WithNVDLA("small") ++ // add a small NVDLA
new chipyard.example.WithStreamingPassthrough ++ // use top with tilelink-controlled streaming passthrough
new chipyard.example.WithStreamingFIR ++ // use top with tilelink-controlled streaming FIR
new freechips.rocketchip.subsystem.WithNBigCores(1) ++

View File

@@ -68,9 +68,9 @@ class MultiNoCConfig extends Config(
"serial-tl" -> 0),
outNodeMapping = ListMap(
"error" -> 1, "l2[0]" -> 2, "pbus" -> 3, "plic" -> 4,
"clint" -> 5, "dmInner" -> 6, "bootrom" -> 7, "tileClockGater" -> 8, "tileResetSetter" -> 9)),
"clint" -> 5, "dmInner" -> 6, "bootrom" -> 7, "clock" -> 8)),
NoCParams(
topology = TerminalRouter(BidirectionalLine(10)),
topology = TerminalRouter(BidirectionalLine(9)),
channelParamGen = (a, b) => UserChannelParams(Seq.fill(5) { UserVirtualChannelParams(4) }),
routingRelation = NonblockingVirtualSubnetworksRouting(TerminalRouterRouting(BidirectionalLineRouting()), 5, 1))
)) ++

View File

@@ -4,6 +4,15 @@ import org.chipsalliance.cde.config.{Config}
// A empty config with no cores. Useful for testing
class NoCoresConfig extends Config(
new testchipip.WithNoBootAddrReg ++
new testchipip.WithNoCustomBootPin ++
new chipyard.config.WithNoCLINT ++
new chipyard.config.WithNoBootROM ++
new chipyard.config.WithBroadcastManager ++
new chipyard.config.WithNoUART ++
new chipyard.config.WithNoTileClockGaters ++
new chipyard.config.WithNoTileResetSetters ++
new chipyard.config.WithNoBusErrorDevices ++
new chipyard.config.WithNoDebug ++
new chipyard.config.WithNoPLIC ++
new chipyard.config.AbstractConfig)

View File

@@ -2,6 +2,7 @@ package chipyard
import org.chipsalliance.cde.config.{Config}
import freechips.rocketchip.diplomacy.{AsynchronousCrossing}
import freechips.rocketchip.subsystem.{MBUS}
// ---------------------------------------------------------
// Configs which add non-default peripheral devices or ports
@@ -58,20 +59,37 @@ class LBWIFRocketConfig extends Config(
// DOC include start: DmiRocket
class dmiRocketConfig extends Config(
new chipyard.harness.WithSerialAdapterTiedOff ++ // don't attach an external SimSerial
new chipyard.harness.WithSerialTLTiedOff ++ // don't attach anything to serial-tl
new chipyard.config.WithDMIDTM ++ // have debug module expose a clocked DMI port
new freechips.rocketchip.subsystem.WithNBigCores(1) ++
new chipyard.config.AbstractConfig)
// DOC include end: DmiRocket
class ManyPeripheralsRocketConfig extends Config(
new testchipip.WithBlockDevice ++ // add block-device module to peripherybus
new testchipip.WithOffchipBusClient(MBUS) ++ // OBUS provides backing memory to the MBUS
new testchipip.WithOffchipBus ++ // OBUS must exist for serial-tl to master off-chip memory
new testchipip.WithSerialTLMem(isMainMemory=true) ++ // set lbwif memory base to DRAM_BASE, use as main memory
new chipyard.harness.WithSimSPIFlashModel(true) ++ // add the SPI flash model in the harness (read-only)
new chipyard.harness.WithSimBlockDevice ++ // drive block-device IOs with SimBlockDevice
new chipyard.config.WithSPIFlash ++ // add the SPI flash controller
new freechips.rocketchip.subsystem.WithDefaultMMIOPort ++ // add default external master port
new freechips.rocketchip.subsystem.WithDefaultSlavePort ++ // add default external slave port
new testchipip.WithBlockDevice ++ // add block-device module to peripherybus
new testchipip.WithSerialTLMem(isMainMemory=true) ++ // set lbwif memory base to DRAM_BASE, use as main memory
new freechips.rocketchip.subsystem.WithNoMemPort ++ // remove AXI4 backing memory
new freechips.rocketchip.subsystem.WithNBigCores(1) ++
new chipyard.config.AbstractConfig)
class QuadChannelRocketConfig extends Config(
new freechips.rocketchip.subsystem.WithNMemoryChannels(4) ++ // 4 AXI4 channels
new freechips.rocketchip.subsystem.WithNBigCores(1) ++
new chipyard.config.AbstractConfig)
class UARTTSIRocketConfig extends Config(
new chipyard.harness.WithSerialTLTiedOff ++
new testchipip.WithUARTTSIClient ++
new chipyard.config.WithMemoryBusFrequency(10) ++
new chipyard.config.WithFrontBusFrequency(10) ++
new chipyard.config.WithPeripheryBusFrequency(10) ++
new freechips.rocketchip.subsystem.WithNBigCores(1) ++ // single rocket-core
new chipyard.config.AbstractConfig)

View File

@@ -29,14 +29,6 @@ class RocketGPUConfig extends Config(
new freechips.rocketchip.subsystem.WithNCustomSmallCores(2) ++ // multiple rocket-core
new chipyard.config.AbstractConfig)
class UARTTSIRocketConfig extends Config(
new chipyard.harness.WithUARTSerial ++
new chipyard.config.WithNoUART ++
new chipyard.config.WithMemoryBusFrequency(10) ++
new chipyard.config.WithPeripheryBusFrequency(10) ++
new freechips.rocketchip.subsystem.WithNBigCores(1) ++ // single rocket-core
new chipyard.config.AbstractConfig)
class SimAXIRocketConfig extends Config(
new chipyard.harness.WithSimAXIMem ++ // drive the master AXI4 memory with a SimAXIMem, a 1-cycle magic memory, instead of default SimDRAM
new freechips.rocketchip.subsystem.WithNBigCores(1) ++

View File

@@ -0,0 +1,32 @@
package chipyard
import org.chipsalliance.cde.config.{Config}
//-----------------
// Shuttle Configs
//-----------------
class ShuttleConfig extends Config(
new shuttle.common.WithNShuttleCores ++ // 1x dual-issue shuttle core
new chipyard.config.AbstractConfig)
class ShuttleCosimConfig extends Config(
new chipyard.harness.WithCospike ++ // attach spike-cosim
new chipyard.config.WithTraceIO ++ // enable trace-io for cosim
new shuttle.common.WithShuttleDebugROB ++ // enable shuttle debug ROB for cosim
new shuttle.common.WithNShuttleCores ++
new chipyard.config.AbstractConfig)
class dmiShuttleCosimConfig extends Config(
new chipyard.harness.WithSerialTLTiedOff ++ // don't attach anything to serial-tl
new chipyard.harness.WithCospike ++ // attach spike-cosim
new chipyard.config.WithDMIDTM ++ // have debug module expose a clocked DMI port
new chipyard.config.WithTraceIO ++ // enable traceio for cosim
new shuttle.common.WithShuttleDebugROB ++ // enable shuttle debug ROB for cosim
new shuttle.common.WithNShuttleCores ++
new chipyard.config.AbstractConfig)
class GemminiShuttleConfig extends Config(
new gemmini.DefaultGemminiConfig ++ // use Gemmini systolic array GEMM accel
new shuttle.common.WithNShuttleCores ++
new chipyard.config.AbstractConfig)

View File

@@ -8,7 +8,6 @@ class Sodor1StageConfig extends Config(
// Create a Sodor 1-stage core
new sodor.common.WithNSodorCores(1, internalTile = sodor.common.Stage1Factory) ++
new testchipip.WithSerialTLWidth(32) ++
new testchipip.WithSerialPBusMem ++
new freechips.rocketchip.subsystem.WithScratchpadsOnly ++ // use sodor tile-internal scratchpad
new freechips.rocketchip.subsystem.WithNoMemPort ++ // use no external memory
new freechips.rocketchip.subsystem.WithNBanks(0) ++
@@ -18,7 +17,6 @@ class Sodor2StageConfig extends Config(
// Create a Sodor 2-stage core
new sodor.common.WithNSodorCores(1, internalTile = sodor.common.Stage2Factory) ++
new testchipip.WithSerialTLWidth(32) ++
new testchipip.WithSerialPBusMem ++
new freechips.rocketchip.subsystem.WithScratchpadsOnly ++ // use sodor tile-internal scratchpad
new freechips.rocketchip.subsystem.WithNoMemPort ++ // use no external memory
new freechips.rocketchip.subsystem.WithNBanks(0) ++
@@ -28,7 +26,6 @@ class Sodor3StageConfig extends Config(
// Create a Sodor 1-stage core with two ports
new sodor.common.WithNSodorCores(1, internalTile = sodor.common.Stage3Factory(ports = 2)) ++
new testchipip.WithSerialTLWidth(32) ++
new testchipip.WithSerialPBusMem ++
new freechips.rocketchip.subsystem.WithScratchpadsOnly ++ // use sodor tile-internal scratchpad
new freechips.rocketchip.subsystem.WithNoMemPort ++ // use no external memory
new freechips.rocketchip.subsystem.WithNBanks(0) ++
@@ -38,7 +35,6 @@ class Sodor3StageSinglePortConfig extends Config(
// Create a Sodor 3-stage core with one ports (instruction and data memory access controlled by arbiter)
new sodor.common.WithNSodorCores(1, internalTile = sodor.common.Stage3Factory(ports = 1)) ++
new testchipip.WithSerialTLWidth(32) ++
new testchipip.WithSerialPBusMem ++
new freechips.rocketchip.subsystem.WithScratchpadsOnly ++ // use sodor tile-internal scratchpad
new freechips.rocketchip.subsystem.WithNoMemPort ++ // use no external memory
new freechips.rocketchip.subsystem.WithNBanks(0) ++
@@ -48,7 +44,6 @@ class Sodor5StageConfig extends Config(
// Create a Sodor 5-stage core
new sodor.common.WithNSodorCores(1, internalTile = sodor.common.Stage5Factory) ++
new testchipip.WithSerialTLWidth(32) ++
new testchipip.WithSerialPBusMem ++
new freechips.rocketchip.subsystem.WithScratchpadsOnly ++ // use sodor tile-internal scratchpad
new freechips.rocketchip.subsystem.WithNoMemPort ++ // use no external memory
new freechips.rocketchip.subsystem.WithNBanks(0) ++
@@ -58,7 +53,6 @@ class SodorUCodeConfig extends Config(
// Construct a Sodor microcode-based single-bus core
new sodor.common.WithNSodorCores(1, internalTile = sodor.common.UCodeFactory) ++
new testchipip.WithSerialTLWidth(32) ++
new testchipip.WithSerialPBusMem ++
new freechips.rocketchip.subsystem.WithScratchpadsOnly ++ // use sodor tile-internal scratchpad
new freechips.rocketchip.subsystem.WithNoMemPort ++ // use no external memory
new freechips.rocketchip.subsystem.WithNBanks(0) ++

View File

@@ -10,6 +10,11 @@ class SpikeConfig extends Config(
new chipyard.WithNSpikeCores(1) ++
new chipyard.config.AbstractConfig)
class dmiSpikeConfig extends Config(
new chipyard.harness.WithSerialTLTiedOff ++ // don't attach anything to serial-tilelink
new chipyard.config.WithDMIDTM ++ // have debug module expose a clocked DMI port
new SpikeConfig)
// Avoids polling on the UART registers
class SpikeFastUARTConfig extends Config(
new chipyard.WithNSpikeCores(1) ++
@@ -22,13 +27,17 @@ class SpikeFastUARTConfig extends Config(
class SpikeUltraFastConfig extends Config(
new chipyard.WithSpikeTCM ++
new chipyard.WithNSpikeCores(1) ++
new testchipip.WithSerialPBusMem ++
new chipyard.config.WithUARTFIFOEntries(128, 128) ++
new chipyard.config.WithMemoryBusFrequency(2) ++
new chipyard.config.WithPeripheryBusFrequency(2) ++
new chipyard.config.WithBroadcastManager ++
new chipyard.config.AbstractConfig)
class dmiSpikeUltraFastConfig extends Config(
new chipyard.harness.WithSerialTLTiedOff ++ // don't attach anything to serial-tilelink
new chipyard.config.WithDMIDTM ++ // have debug module expose a clocked DMI port
new SpikeUltraFastConfig)
// Add the default firechip devices
class SpikeUltraFastDevicesConfig extends Config(
new chipyard.harness.WithSimBlockDevice ++
@@ -38,7 +47,6 @@ class SpikeUltraFastDevicesConfig extends Config(
new chipyard.WithSpikeTCM ++
new chipyard.WithNSpikeCores(1) ++
new testchipip.WithSerialPBusMem ++
new chipyard.config.WithUARTFIFOEntries(128, 128) ++
new chipyard.config.WithMemoryBusFrequency(2) ++
new chipyard.config.WithPeripheryBusFrequency(2) ++

View File

@@ -4,21 +4,24 @@ import org.chipsalliance.cde.config.{Config}
import freechips.rocketchip.rocket.{DCacheParams}
class AbstractTraceGenConfig extends Config(
new chipyard.harness.WithAbsoluteFreqHarnessClockInstantiator ++
new chipyard.harness.WithBlackBoxSimMem ++
new chipyard.harness.WithTraceGenSuccess ++
new chipyard.harness.WithClockAndResetFromHarness ++
new chipyard.iobinders.WithAXI4MemPunchthrough ++
new chipyard.iobinders.WithTraceGenSuccessPunchthrough ++
new chipyard.clocking.WithDividerOnlyClockGenerator ++
new chipyard.clocking.WithPassthroughClockGenerator ++
new chipyard.clocking.WithClockGroupsCombinedByName(("uncore", Seq("sbus", "implicit"), Nil)) ++
new chipyard.config.WithTracegenSystem ++
new chipyard.config.WithNoSubsystemDrivenClocks ++
new chipyard.config.WithPeripheryBusFrequencyAsDefault ++
new chipyard.config.WithMemoryBusFrequency(100.0) ++
new chipyard.config.WithPeripheryBusFrequency(100.0) ++
new chipyard.config.WithMemoryBusFrequency(1000.0) ++
new chipyard.config.WithSystemBusFrequency(1000.0) ++
new chipyard.config.WithPeripheryBusFrequency(1000.0) ++
new freechips.rocketchip.subsystem.WithCoherentBusTopology ++
new freechips.rocketchip.groundtest.GroundTestBaseConfig)
class TraceGenConfig extends Config(
new tracegen.WithTraceGen()(List.fill(2) { DCacheParams(nMSHRs = 0, nSets = 16, nWays = 2) }) ++
new AbstractTraceGenConfig)

View File

@@ -14,7 +14,6 @@ import freechips.rocketchip.tilelink.{HasTLBusParams}
import chipyard._
import chipyard.clocking._
// The default RocketChip BaseSubsystem drives its diplomatic clock graph
// with the implicit clocks of Subsystem. Don't do that, instead we extend
// the diplomacy graph upwards into the ChipTop, where we connect it to
@@ -37,14 +36,6 @@ class WithTileFrequency(fMHz: Double, hartId: Option[Int] = None) extends ClockN
},
fMHz)
class WithPeripheryBusFrequencyAsDefault extends Config((site, here, up) => {
case DefaultClockFrequencyKey => (site(PeripheryBusKey).dtsFrequency.get.toDouble / (1000 * 1000))
})
class WithSystemBusFrequencyAsDefault extends Config((site, here, up) => {
case DefaultClockFrequencyKey => (site(SystemBusKey).dtsFrequency.get.toDouble / (1000 * 1000))
})
class BusFrequencyAssignment[T <: HasTLBusParams](re: Regex, key: Field[T]) extends Config((site, here, up) => {
case ClockFrequencyAssignersKey => up(ClockFrequencyAssignersKey, site) ++
Seq((cName: String) => site(key).dtsFrequency.flatMap { f =>
@@ -116,17 +107,14 @@ class WithControlBusFrequency(freqMHz: Double) extends Config((site, here, up) =
class WithRationalMemoryBusCrossing extends WithSbusToMbusCrossingType(RationalCrossing(Symmetric))
class WithAsynchrousMemoryBusCrossing extends WithSbusToMbusCrossingType(AsynchronousCrossing())
class WithTestChipBusFreqs extends Config(
// Frequency specifications
new chipyard.config.WithTileFrequency(1600.0) ++ // Matches the maximum frequency of U540
new chipyard.config.WithSystemBusFrequency(800.0) ++ // Put the system bus at a lower freq, representative of ncore working at a lower frequency than the tiles. Same freq as U540
new chipyard.config.WithMemoryBusFrequency(1000.0) ++ // 2x the U540 freq (appropriate for a 128b Mbus)
new chipyard.config.WithPeripheryBusFrequency(800.0) ++ // Match the sbus and pbus frequency
new chipyard.config.WithSystemBusFrequencyAsDefault ++ // All unspecified clock frequencies, notably the implicit clock, will use the sbus freq (800 MHz)
// Crossing specifications
new chipyard.config.WithCbusToPbusCrossingType(AsynchronousCrossing()) ++ // Add Async crossing between PBUS and CBUS
new chipyard.config.WithSbusToMbusCrossingType(AsynchronousCrossing()) ++ // Add Async crossings between backside of L2 and MBUS
new freechips.rocketchip.subsystem.WithRationalRocketTiles ++ // Add rational crossings between RocketTile and uncore
new boom.common.WithRationalBoomTiles ++ // Add rational crossings between BoomTile and uncore
new testchipip.WithAsynchronousSerialSlaveCrossing // Add Async crossing between serial and MBUS. Its master-side is tied to the FBUS
)
class WithNoTileClockGaters extends Config((site, here, up) => {
case ChipyardPRCIControlKey => up(ChipyardPRCIControlKey).copy(enableTileClockGating = false)
})
class WithNoTileResetSetters extends Config((site, here, up) => {
case ChipyardPRCIControlKey => up(ChipyardPRCIControlKey).copy(enableTileResetSetting = false)
})
class WithNoResetSynchronizers extends Config((site, here, up) => {
case ChipyardPRCIControlKey => up(ChipyardPRCIControlKey).copy(enableResetSynchronizers = false)
})

View File

@@ -5,8 +5,9 @@ import chisel3._
import chisel3.util.{log2Up}
import org.chipsalliance.cde.config.{Config}
import freechips.rocketchip.devices.tilelink.{BootROMLocated, PLICKey}
import freechips.rocketchip.devices.debug.{Debug, ExportDebug, DebugModuleKey, DMI}
import freechips.rocketchip.devices.tilelink.{BootROMLocated, PLICKey, CLINTKey}
import freechips.rocketchip.devices.debug.{Debug, ExportDebug, DebugModuleKey, DMI, JtagDTMKey, JtagDTMConfig}
import freechips.rocketchip.diplomacy.{AsynchronousCrossing}
import freechips.rocketchip.stage.phases.TargetDirKey
import freechips.rocketchip.subsystem._
import freechips.rocketchip.tile.{XLen}
@@ -14,53 +15,125 @@ import freechips.rocketchip.tile.{XLen}
import sifive.blocks.devices.gpio._
import sifive.blocks.devices.uart._
import sifive.blocks.devices.spi._
import sifive.blocks.devices.i2c._
import testchipip._
import chipyard.{ExtTLMem}
// Set the bootrom to the Chipyard bootrom
class WithBootROM extends Config((site, here, up) => {
/**
* Config fragment for adding a BootROM to the SoC
*
* @param address the address of the BootROM device
* @param size the size of the BootROM
* @param hang the power-on reset vector, i.e. the program counter will be set to this value on reset
* @param contentFileName the path to the BootROM image
*/
class WithBootROM(address: BigInt = 0x10000, size: Int = 0x10000, hang: BigInt = 0x10040) extends Config((site, here, up) => {
case BootROMLocated(x) => up(BootROMLocated(x), site)
.map(_.copy(contentFileName = s"${site(TargetDirKey)}/bootrom.rv${site(XLen)}.img"))
.map(_.copy(
address = address,
size = size,
hang = hang,
contentFileName = s"${site(TargetDirKey)}/bootrom.rv${site(XLen)}.img"
))
})
// DOC include start: gpio config fragment
class WithGPIO extends Config((site, here, up) => {
case PeripheryGPIOKey => Seq(
GPIOParams(address = 0x10012000, width = 4, includeIOF = false))
/**
* Config fragment for adding a GPIO peripheral device to the SoC
*
* @param address the address of the GPIO device
* @param width the number of pins of the GPIO device
*/
class WithGPIO(address: BigInt = 0x10010000, width: Int = 4) extends Config ((site, here, up) => {
case PeripheryGPIOKey => up(PeripheryGPIOKey) ++ Seq(
GPIOParams(address = address, width = width, includeIOF = false))
})
// DOC include end: gpio config fragment
class WithUART(baudrate: BigInt = 115200) extends Config((site, here, up) => {
case PeripheryUARTKey => Seq(
UARTParams(address = 0x54000000L, nTxEntries = 256, nRxEntries = 256, initBaudRate = baudrate))
})
/**
* Config fragment for removing all UART peripheral devices from the SoC
*/
class WithNoUART extends Config((site, here, up) => {
case PeripheryUARTKey => Nil
})
/**
* Config fragment for adding a UART peripheral device to the SoC
*
* @param address the address of the UART device
* @param baudrate the baudrate of the UART device
*/
class WithUART(baudrate: BigInt = 115200, address: BigInt = 0x10020000) extends Config ((site, here, up) => {
case PeripheryUARTKey => up(PeripheryUARTKey) ++ Seq(
UARTParams(address = address, nTxEntries = 256, nRxEntries = 256, initBaudRate = baudrate))
})
class WithUARTFIFOEntries(txEntries: Int, rxEntries: Int) extends Config((site, here, up) => {
case PeripheryUARTKey => up(PeripheryUARTKey).map(_.copy(nTxEntries = txEntries, nRxEntries = rxEntries))
})
class WithSPIFlash(size: BigInt = 0x10000000) extends Config((site, here, up) => {
// Note: the default size matches freedom with the addresses below
case PeripherySPIFlashKey => Seq(
SPIFlashParams(rAddress = 0x10040000, fAddress = 0x20000000, fSize = size))
class WithUARTInitBaudRate(baudrate: BigInt = 115200) extends Config ((site, here, up) => {
case PeripheryUARTKey => up(PeripheryUARTKey).map(_.copy(initBaudRate=baudrate))
})
class WithDMIDTM extends Config((site, here, up) => {
case ExportDebug => up(ExportDebug, site).copy(protocols = Set(DMI))
/**
* Config fragment for adding a SPI peripheral device with Execute-in-Place capability to the SoC
*
* @param address the address of the SPI controller
* @param fAddress the address of the Execute-in-Place (XIP) region of the SPI flash memory
* @param size the size of the Execute-in-Place (XIP) region of the SPI flash memory
*/
class WithSPIFlash(size: BigInt = 0x10000000, address: BigInt = 0x10030000, fAddress: BigInt = 0x20000000) extends Config((site, here, up) => {
// Note: the default size matches freedom with the addresses below
case PeripherySPIFlashKey => up(PeripherySPIFlashKey) ++ Seq(
SPIFlashParams(rAddress = address, fAddress = fAddress, fSize = size))
})
/**
* Config fragment for adding a SPI peripheral device to the SoC
*
* @param address the address of the SPI controller
*/
class WithSPI(address: BigInt = 0x10031000) extends Config((site, here, up) => {
case PeripherySPIKey => up(PeripherySPIKey) ++ Seq(
SPIParams(rAddress = address))
})
/**
* Config fragment for adding a I2C peripheral device to the SoC
*
* @param address the address of the I2C controller
*/
class WithI2C(address: BigInt = 0x10040000) extends Config((site, here, up) => {
case PeripheryI2CKey => up(PeripheryI2CKey) ++ Seq(
I2CParams(address = address, controlXType = AsynchronousCrossing(), intXType = AsynchronousCrossing())
)
})
class WithNoDebug extends Config((site, here, up) => {
case DebugModuleKey => None
})
class WithTLSerialLocation(masterWhere: TLBusWrapperLocation, slaveWhere: TLBusWrapperLocation) extends Config((site, here, up) => {
case SerialTLAttachKey => up(SerialTLAttachKey, site).copy(masterWhere = masterWhere, slaveWhere = slaveWhere)
class WithDMIDTM extends Config((site, here, up) => {
case ExportDebug => up(ExportDebug, site).copy(protocols = Set(DMI))
})
/**
* Config fragment for adding a JTAG Debug Module to the SoC
*
* @param idcodeVersion the version of the JTAG protocol the Debug Module supports
* @param partNum the part number of the Debug Module
* @param manufId the 11-bit JEDEC Designer ID of the chip manufacturer
* @param debugIdleCycles the number of cycles the Debug Module waits before responding to a request
*/
class WithJTAGDTMKey(idcodeVersion: Int = 2, partNum: Int = 0x000, manufId: Int = 0x489, debugIdleCycles: Int = 5) extends Config((site, here, up) => {
case JtagDTMKey => new JtagDTMConfig (
idcodeVersion = idcodeVersion,
idcodePartNum = partNum,
idcodeManufId = manufId,
debugIdleCycles = debugIdleCycles)
})
class WithTLBackingMemory extends Config((site, here, up) => {
@@ -68,18 +141,6 @@ class WithTLBackingMemory extends Config((site, here, up) => {
case ExtTLMem => up(ExtMem, site) // enable TL backing memory
})
class WithSerialTLBackingMemory extends Config((site, here, up) => {
case ExtMem => None
case SerialTLKey => up(SerialTLKey, site).map { k => k.copy(
memParams = {
val memPortParams = up(ExtMem, site).get
require(memPortParams.nMemoryChannels == 1)
memPortParams.master
},
isMemoryDevice = true
)}
})
class WithExtMemIdBits(n: Int) extends Config((site, here, up) => {
case ExtMem => up(ExtMem, site).map(x => x.copy(master = x.master.copy(idBits = n)))
})
@@ -87,3 +148,23 @@ class WithExtMemIdBits(n: Int) extends Config((site, here, up) => {
class WithNoPLIC extends Config((site, here, up) => {
case PLICKey => None
})
class WithDebugModuleAbstractDataWords(words: Int = 16) extends Config((site, here, up) => {
case DebugModuleKey => up(DebugModuleKey).map(_.copy(nAbstractDataWords=words))
})
class WithNoCLINT extends Config((site, here, up) => {
case CLINTKey => None
})
class WithNoBootROM extends Config((site, here, up) => {
case BootROMLocated(_) => None
})
class WithNoBusErrorDevices extends Config((site, here, up) => {
case SystemBusKey => up(SystemBusKey).copy(errorDevice = None)
case ControlBusKey => up(ControlBusKey).copy(errorDevice = None)
case PeripheryBusKey => up(PeripheryBusKey).copy(errorDevice = None)
case MemoryBusKey => up(MemoryBusKey).copy(errorDevice = None)
case FrontBusKey => up(FrontBusKey).copy(errorDevice = None)
})

Some files were not shown because too many files have changed in this diff Show More