Merge remote-tracking branch 'origin/lazy-harnessbinders' into local-fpga-temp

This commit is contained in:
abejgonzalez
2020-10-13 16:23:41 -07:00
51 changed files with 1439 additions and 1139 deletions

View File

@@ -48,7 +48,7 @@ search () {
done done
} }
submodules=("ariane" "boom" "gemmini" "hwacha" "icenet" "nvdla" "rocket-chip" "sha3" "sifive-blocks" "sifive-cache" "testchipip") submodules=("ariane" "boom" "gemmini" "hwacha" "icenet" "nvdla" "rocket-chip" "sha3" "sifive-blocks" "sifive-cache" "testchipip" "riscv-sodor")
dir="generators" dir="generators"
if [ "$CIRCLE_BRANCH" == "master" ] || [ "$CIRCLE_BRANCH" == "dev" ] if [ "$CIRCLE_BRANCH" == "master" ] || [ "$CIRCLE_BRANCH" == "dev" ]
then then

View File

@@ -73,7 +73,7 @@ commands:
tools-version: tools-version:
type: string type: string
default: "riscv-tools" default: "riscv-tools"
project-key: group-key:
type: string type: string
timeout: timeout:
type: string type: string
@@ -85,11 +85,11 @@ commands:
- setup-tools: - setup-tools:
tools-version: "<< parameters.tools-version >>" tools-version: "<< parameters.tools-version >>"
- run: - run:
name: Building << parameters.project-key >> subproject using Verilator name: Building << parameters.group-key >> subproject using Verilator
command: .circleci/<< parameters.build-script >> << parameters.project-key >> command: .circleci/<< parameters.build-script >> << parameters.group-key >>
no_output_timeout: << parameters.timeout >> no_output_timeout: << parameters.timeout >>
- save_cache: - save_cache:
key: << parameters.project-key >>-{{ .Branch }}-{{ .Revision }} key: << parameters.group-key >>-{{ .Branch }}-{{ .Revision }}
paths: paths:
- "/home/riscvuser/project" - "/home/riscvuser/project"
@@ -99,11 +99,10 @@ commands:
tools-version: tools-version:
type: string type: string
default: "riscv-tools" default: "riscv-tools"
group-key:
type: string
project-key: project-key:
type: string type: string
extra-cache-restore:
type: string
default: ""
run-script: run-script:
type: string type: string
default: "run-tests.sh" default: "run-tests.sh"
@@ -115,13 +114,7 @@ commands:
tools-version: "<< parameters.tools-version >>" tools-version: "<< parameters.tools-version >>"
- restore_cache: - restore_cache:
keys: keys:
- << parameters.project-key >>-{{ .Branch }}-{{ .Revision }} - << parameters.group-key >>-{{ .Branch }}-{{ .Revision }}
- when:
condition: << parameters.extra-cache-restore >>
steps:
- restore_cache:
keys:
- << parameters.extra-cache-restore >>-{{ .Branch }}-{{ .Revision }}
- run: - run:
name: Run << parameters.project-key >> subproject tests name: Run << parameters.project-key >> subproject tests
command: .circleci/<< parameters.run-script >> << parameters.project-key >> command: .circleci/<< parameters.run-script >> << parameters.project-key >>
@@ -194,177 +187,161 @@ jobs:
key: extra-tests-{{ .Branch }}-{{ .Revision }} key: extra-tests-{{ .Branch }}-{{ .Revision }}
paths: paths:
- "/home/riscvuser/project/tests" - "/home/riscvuser/project/tests"
prepare-chipyard-rocket:
prepare-chipyard-cores:
executor: main-env executor: main-env
steps: steps:
- prepare-rtl: - prepare-rtl:
project-key: "chipyard-rocket" group-key: "group-cores"
prepare-chipyard-sha3: prepare-chipyard-peripherals:
executor: main-env executor: main-env
steps: steps:
- prepare-rtl: - prepare-rtl:
project-key: "chipyard-sha3" group-key: "group-peripherals"
prepare-chipyard-streaming-fir: prepare-chipyard-accels:
executor: main-env
steps:
- prepare-rtl:
project-key: "chipyard-streaming-fir"
prepare-chipyard-streaming-passthrough:
executor: main-env
steps:
- prepare-rtl:
project-key: "chipyard-streaming-passthrough"
prepare-chipyard-hetero:
executor: main-env
steps:
- prepare-rtl:
project-key: "chipyard-hetero"
timeout: "240m"
prepare-chipyard-boom:
executor: main-env
steps:
- prepare-rtl:
project-key: "chipyard-boom"
prepare-rocketchip:
executor: main-env
steps:
- prepare-rtl:
project-key: "rocketchip"
prepare-chipyard-blkdev:
executor: main-env
steps:
- prepare-rtl:
project-key: "chipyard-blkdev"
prepare-chipyard-hwacha:
executor: main-env executor: main-env
steps: steps:
- prepare-rtl: - prepare-rtl:
tools-version: "esp-tools" tools-version: "esp-tools"
project-key: "chipyard-hwacha" group-key: "group-accels"
prepare-chipyard-gemmini: prepare-chipyard-tracegen:
executor: main-env executor: main-env
steps: steps:
- prepare-rtl: - prepare-rtl:
tools-version: "esp-tools" group-key: "group-tracegen"
project-key: "chipyard-gemmini" prepare-chipyard-other:
prepare-tracegen:
executor: main-env executor: main-env
steps: steps:
- prepare-rtl: - prepare-rtl:
project-key: "tracegen" group-key: "group-other"
prepare-tracegen-boom:
executor: main-env
steps:
- prepare-rtl:
project-key: "tracegen-boom"
prepare-chipyard-ariane:
executor: main-env
steps:
- prepare-rtl:
project-key: "chipyard-ariane"
prepare-icenet:
executor: main-env
steps:
- prepare-rtl:
project-key: "icenet"
prepare-testchipip:
executor: main-env
steps:
- prepare-rtl:
project-key: "testchipip"
prepare-chipyard-nvdla:
executor: main-env
steps:
- prepare-rtl:
project-key: "chipyard-nvdla"
prepare-chipyard-spiflashwrite:
executor: main-env
steps:
- prepare-rtl:
project-key: "chipyard-spiflashwrite"
prepare-chipyard-spiflashread:
executor: main-env
steps:
- prepare-rtl:
project-key: "chipyard-spiflashread"
prepare-chipyard-mmios:
executor: main-env
steps:
- prepare-rtl:
project-key: "chipyard-mmios"
chipyard-rocket-run-tests: chipyard-rocket-run-tests:
executor: main-env executor: main-env
steps: steps:
- run-tests: - run-tests:
group-key: "group-cores"
project-key: "chipyard-rocket" project-key: "chipyard-rocket"
chipyard-sha3-run-tests:
executor: main-env
steps:
- run-tests:
project-key: "chipyard-sha3"
chipyard-streaming-fir-run-tests:
executor: main-env
steps:
- run-tests:
project-key: "chipyard-streaming-fir"
chipyard-streaming-passthrough-run-tests:
executor: main-env
steps:
- run-tests:
project-key: "chipyard-streaming-passthrough"
chipyard-hetero-run-tests: chipyard-hetero-run-tests:
executor: main-env executor: main-env
steps: steps:
- run-tests: - run-tests:
group-key: "group-cores"
project-key: "chipyard-hetero" project-key: "chipyard-hetero"
timeout: "15m" timeout: "15m"
chipyard-boom-run-tests: chipyard-boom-run-tests:
executor: main-env executor: main-env
steps: steps:
- run-tests: - run-tests:
group-key: "group-cores"
project-key: "chipyard-boom" project-key: "chipyard-boom"
rocketchip-run-tests: chipyard-ariane-run-tests:
executor: main-env executor: main-env
steps: steps:
- run-tests: - run-tests:
project-key: "rocketchip" group-key: "group-cores"
project-key: "chipyard-ariane"
timeout: "30m"
chipyard-sodor-run-tests:
executor: main-env
steps:
- run-tests:
group-key: "group-cores"
project-key: "chipyard-sodor"
timeout: "30m"
chipyard-dmirocket-run-tests:
executor: main-env
steps:
- run-tests:
group-key: "group-peripherals"
project-key: "chipyard-dmirocket"
chipyard-spiflashwrite-run-tests:
executor: main-env
steps:
- run-tests:
group-key: "group-peripherals"
project-key: "chipyard-spiflashwrite"
chipyard-spiflashread-run-tests:
executor: main-env
steps:
- run-tests:
group-key: "group-peripherals"
project-key: "chipyard-spiflashread"
chipyard-lbwif-run-tests:
executor: main-env
steps:
- run-tests:
group-key: "group-peripherals"
project-key: "chipyard-lbwif"
chipyard-sha3-run-tests:
executor: main-env
steps:
- run-tests:
group-key: "group-accels"
project-key: "chipyard-sha3"
chipyard-streaming-fir-run-tests:
executor: main-env
steps:
- run-tests:
group-key: "group-accels"
project-key: "chipyard-streaming-fir"
chipyard-streaming-passthrough-run-tests:
executor: main-env
steps:
- run-tests:
group-key: "group-accels"
project-key: "chipyard-streaming-passthrough"
chipyard-hwacha-run-tests: chipyard-hwacha-run-tests:
executor: main-env executor: main-env
steps: steps:
- run-tests: - run-tests:
tools-version: "esp-tools" tools-version: "esp-tools"
group-key: "group-accels"
project-key: "chipyard-hwacha" project-key: "chipyard-hwacha"
chipyard-gemmini-run-tests: chipyard-gemmini-run-tests:
executor: main-env executor: main-env
steps: steps:
- run-tests: - run-tests:
tools-version: "esp-tools" tools-version: "esp-tools"
group-key: "group-accels"
project-key: "chipyard-gemmini" project-key: "chipyard-gemmini"
chipyard-spiflashwrite-run-tests: chipyard-nvdla-run-tests:
executor: main-env executor: main-env
steps: steps:
- run-tests: - run-tests:
project-key: "chipyard-spiflashwrite" group-key: "group-accels"
chipyard-spiflashread-run-tests: project-key: "chipyard-nvdla"
executor: main-env
steps:
- run-tests:
project-key: "chipyard-spiflashread"
tracegen-run-tests: tracegen-run-tests:
executor: main-env executor: main-env
steps: steps:
- run-tests: - run-tests:
group-key: "group-tracegen"
project-key: "tracegen" project-key: "tracegen"
tracegen-boom-run-tests: tracegen-boom-run-tests:
executor: main-env executor: main-env
steps: steps:
- run-tests: - run-tests:
group-key: "group-tracegen"
project-key: "tracegen-boom" project-key: "tracegen-boom"
icenet-run-tests:
executor: main-env
steps:
- run-tests:
group-key: "group-other"
project-key: "icenet"
timeout: "30m"
testchipip-run-tests:
executor: main-env
steps:
- run-tests:
group-key: "group-other"
project-key: "testchipip"
timeout: "30m"
firesim-run-tests: firesim-run-tests:
executor: main-env executor: main-env
steps: steps:
- run-tests: - run-tests:
extra-cache-restore: "extra-tests" group-key: "extra-tests"
project-key: "firesim" project-key: "firesim"
run-script: "run-firesim-scala-tests.sh" run-script: "run-firesim-scala-tests.sh"
timeout: "20m" timeout: "20m"
@@ -372,7 +349,7 @@ jobs:
executor: main-env executor: main-env
steps: steps:
- run-tests: - run-tests:
extra-cache-restore: "extra-tests" group-key: "extra-tests"
project-key: "fireboom" project-key: "fireboom"
run-script: "run-firesim-scala-tests.sh" run-script: "run-firesim-scala-tests.sh"
timeout: "45m" timeout: "45m"
@@ -380,33 +357,10 @@ jobs:
executor: main-env executor: main-env
steps: steps:
- run-tests: - run-tests:
extra-cache-restore: "extra-tests" group-key: "extra-tests"
project-key: "firesim-multiclock" project-key: "firesim-multiclock"
run-script: "run-firesim-scala-tests.sh" run-script: "run-firesim-scala-tests.sh"
timeout: "20m" timeout: "20m"
chipyard-ariane-run-tests:
executor: main-env
steps:
- run-tests:
project-key: "chipyard-ariane"
timeout: "30m"
chipyard-nvdla-run-tests:
executor: main-env
steps:
- run-tests:
project-key: "chipyard-nvdla"
icenet-run-tests:
executor: main-env
steps:
- run-tests:
project-key: "icenet"
timeout: "30m"
testchipip-run-tests:
executor: main-env
steps:
- run-tests:
project-key: "testchipip"
timeout: "30m"
# Order and dependencies of jobs to run # Order and dependencies of jobs to run
workflows: workflows:
@@ -446,154 +400,88 @@ workflows:
- install-riscv-toolchain - install-riscv-toolchain
# Prepare the verilator builds # Prepare the verilator builds
- prepare-chipyard-rocket: - prepare-chipyard-cores:
requires: requires:
- install-riscv-toolchain - install-riscv-toolchain
- install-verilator - install-verilator
- prepare-chipyard-peripherals:
- prepare-chipyard-sha3:
requires: requires:
- install-riscv-toolchain - install-riscv-toolchain
- install-verilator - install-verilator
- prepare-chipyard-accels:
- prepare-chipyard-streaming-fir:
requires:
- install-riscv-toolchain
- install-verilator
- prepare-chipyard-streaming-passthrough:
requires:
- install-riscv-toolchain
- install-verilator
- prepare-chipyard-hetero:
requires:
- install-riscv-toolchain
- install-verilator
- prepare-chipyard-boom:
requires:
- install-riscv-toolchain
- install-verilator
- prepare-rocketchip:
requires:
- install-riscv-toolchain
- install-verilator
- prepare-chipyard-blkdev:
requires:
- install-riscv-toolchain
- install-verilator
- prepare-chipyard-hwacha:
requires: requires:
- install-esp-toolchain - install-esp-toolchain
- install-verilator - install-verilator
- prepare-chipyard-tracegen:
- prepare-chipyard-gemmini:
requires:
- install-esp-toolchain
- install-verilator
- prepare-tracegen:
requires: requires:
- install-riscv-toolchain - install-riscv-toolchain
- install-verilator - install-verilator
- prepare-chipyard-other:
- prepare-tracegen-boom:
requires: requires:
- install-riscv-toolchain - install-riscv-toolchain
- install-verilator - install-verilator
- prepare-chipyard-ariane:
requires:
- install-riscv-toolchain
- install-verilator
- prepare-icenet:
requires:
- install-riscv-toolchain
- install-verilator
- prepare-testchipip:
requires:
- install-riscv-toolchain
- install-verilator
- prepare-chipyard-nvdla:
requires:
- install-riscv-toolchain
- install-verilator
- prepare-chipyard-spiflashwrite:
requires:
- install-riscv-toolchain
- install-verilator
- prepare-chipyard-spiflashread:
requires:
- install-riscv-toolchain
- install-verilator
- prepare-chipyard-mmios:
requires:
- install-riscv-toolchain
# Run the respective tests
# Run the example tests # Run the example tests
- chipyard-rocket-run-tests: - chipyard-rocket-run-tests:
requires: requires:
- prepare-chipyard-rocket - prepare-chipyard-cores
- chipyard-hetero-run-tests:
requires:
- prepare-chipyard-cores
- chipyard-boom-run-tests:
requires:
- prepare-chipyard-cores
- chipyard-ariane-run-tests:
requires:
- prepare-chipyard-cores
- chipyard-sodor-run-tests:
requires:
- prepare-chipyard-cores
- chipyard-dmirocket-run-tests:
requires:
- prepare-chipyard-peripherals
- chipyard-spiflashwrite-run-tests:
requires:
- prepare-chipyard-peripherals
- chipyard-spiflashread-run-tests:
requires:
- prepare-chipyard-peripherals
- chipyard-lbwif-run-tests:
requires:
- prepare-chipyard-peripherals
- chipyard-sha3-run-tests: - chipyard-sha3-run-tests:
requires: requires:
- prepare-chipyard-sha3 - prepare-chipyard-accels
- chipyard-streaming-fir-run-tests: - chipyard-streaming-fir-run-tests:
requires: requires:
- prepare-chipyard-streaming-fir - prepare-chipyard-accels
- chipyard-streaming-passthrough-run-tests: - chipyard-streaming-passthrough-run-tests:
requires: requires:
- prepare-chipyard-streaming-passthrough - prepare-chipyard-accels
- chipyard-hetero-run-tests:
requires:
- prepare-chipyard-hetero
- chipyard-boom-run-tests:
requires:
- prepare-chipyard-boom
- rocketchip-run-tests:
requires:
- prepare-rocketchip
- chipyard-hwacha-run-tests: - chipyard-hwacha-run-tests:
requires: requires:
- prepare-chipyard-hwacha - prepare-chipyard-accels
- chipyard-gemmini-run-tests: - chipyard-gemmini-run-tests:
requires: requires:
- prepare-chipyard-gemmini - prepare-chipyard-accels
- chipyard-nvdla-run-tests:
requires:
- prepare-chipyard-accels
- tracegen-run-tests: - tracegen-run-tests:
requires: requires:
- prepare-tracegen - prepare-chipyard-tracegen
- tracegen-boom-run-tests: - tracegen-boom-run-tests:
requires: requires:
- prepare-tracegen-boom - prepare-chipyard-tracegen
- chipyard-spiflashwrite-run-tests: - icenet-run-tests:
requires: requires:
- prepare-chipyard-spiflashwrite - prepare-chipyard-other
- testchipip-run-tests:
- chipyard-spiflashread-run-tests:
requires: requires:
- prepare-chipyard-spiflashread - prepare-chipyard-other
# Run the firesim tests # Run the firesim tests
- firesim-run-tests: - firesim-run-tests:
@@ -612,17 +500,4 @@ workflows:
- install-verilator - install-verilator
- build-extra-tests - build-extra-tests
- chipyard-ariane-run-tests:
requires:
- prepare-chipyard-ariane
- chipyard-nvdla-run-tests:
requires:
- prepare-chipyard-nvdla
- icenet-run-tests:
requires:
- prepare-icenet
- testchipip-run-tests:
requires:
- prepare-testchipip

View File

@@ -45,9 +45,19 @@ LOCAL_CHIPYARD_DIR=$LOCAL_CHECKOUT_DIR
LOCAL_SIM_DIR=$LOCAL_CHIPYARD_DIR/sims/verilator LOCAL_SIM_DIR=$LOCAL_CHIPYARD_DIR/sims/verilator
LOCAL_FIRESIM_DIR=$LOCAL_CHIPYARD_DIR/sims/firesim/sim LOCAL_FIRESIM_DIR=$LOCAL_CHIPYARD_DIR/sims/firesim/sim
# key value store to get the build groups
declare -A grouping
grouping["group-cores"]="chipyard-ariane chipyard-rocket chipyard-hetero chipyard-boom chipyard-sodor"
grouping["group-peripherals"]="chipyard-dmirocket chipyard-blkdev chipyard-spiflashread chipyard-spiflashwrite chipyard-mmios chipyard-lbwif"
grouping["group-accels"]="chipyard-nvdla chipyard-sha3 chipyard-hwacha chipyard-gemmini chipyard-streaming-fir chipyard-streaming-passthrough"
grouping["group-tracegen"]="tracegen tracegen-boom"
grouping["group-other"]="icenet testchipip"
# key value store to get the build strings # key value store to get the build strings
declare -A mapping declare -A mapping
mapping["chipyard-rocket"]="" mapping["chipyard-rocket"]=""
mapping["chipyard-dmirocket"]=" CONFIG=dmiRocketConfig"
mapping["chipyard-lbwif"]=" CONFIG=LBWIFRocketConfig"
mapping["chipyard-sha3"]=" CONFIG=Sha3RocketConfig" mapping["chipyard-sha3"]=" CONFIG=Sha3RocketConfig"
mapping["chipyard-streaming-fir"]=" CONFIG=StreamingFIRRocketConfig" mapping["chipyard-streaming-fir"]=" CONFIG=StreamingFIRRocketConfig"
mapping["chipyard-streaming-passthrough"]=" CONFIG=StreamingPassthroughRocketConfig" mapping["chipyard-streaming-passthrough"]=" CONFIG=StreamingPassthroughRocketConfig"
@@ -60,12 +70,13 @@ mapping["chipyard-ariane"]=" CONFIG=ArianeConfig"
mapping["chipyard-spiflashread"]=" CONFIG=LargeSPIFlashROMRocketConfig" mapping["chipyard-spiflashread"]=" CONFIG=LargeSPIFlashROMRocketConfig"
mapping["chipyard-spiflashwrite"]=" CONFIG=SmallSPIFlashRocketConfig" mapping["chipyard-spiflashwrite"]=" CONFIG=SmallSPIFlashRocketConfig"
mapping["chipyard-mmios"]=" CONFIG=MMIORocketConfig verilog" mapping["chipyard-mmios"]=" CONFIG=MMIORocketConfig verilog"
mapping["tracegen"]=" CONFIG=NonBlockingTraceGenL2Config TOP=TraceGenSystem" mapping["tracegen"]=" CONFIG=NonBlockingTraceGenL2Config"
mapping["tracegen-boom"]=" CONFIG=BoomTraceGenConfig TOP=TraceGenSystem" mapping["tracegen-boom"]=" CONFIG=BoomTraceGenConfig"
mapping["chipyard-nvdla"]=" CONFIG=SmallNVDLARocketConfig" mapping["chipyard-nvdla"]=" CONFIG=SmallNVDLARocketConfig"
mapping["chipyard-sodor"]=" CONFIG=Sodor5StageConfig"
mapping["firesim"]="SCALA_TEST=firesim.firesim.RocketNICF1Tests" mapping["firesim"]="SCALA_TEST=firesim.firesim.RocketNICF1Tests"
mapping["firesim-multiclock"]="SCALA_TEST=firesim.firesim.RocketMulticlockF1Tests" mapping["firesim-multiclock"]="SCALA_TEST=firesim.firesim.RocketMulticlockF1Tests"
mapping["fireboom"]="SCALA_TEST=firesim.firesim.BoomF1Tests" mapping["fireboom"]="SCALA_TEST=firesim.firesim.BoomF1Tests"
mapping["icenet"]="SUB_PROJECT=icenet" mapping["icenet"]="SUB_PROJECT=icenet"
mapping["testchipip"]="SUB_PROJECT=testchipip" mapping["testchipip"]="SUB_PROJECT=testchipip"

View File

@@ -31,7 +31,7 @@ run "cp -r ~/.sbt $REMOTE_WORK_DIR"
TOOLS_DIR=$REMOTE_RISCV_DIR TOOLS_DIR=$REMOTE_RISCV_DIR
LD_LIB_DIR=$REMOTE_RISCV_DIR/lib LD_LIB_DIR=$REMOTE_RISCV_DIR/lib
if [ $1 = "chipyard-gemmini" ]; then if [ $1 = "group-accels" ]; then
export RISCV=$LOCAL_ESP_DIR export RISCV=$LOCAL_ESP_DIR
export LD_LIBRARY_PATH=$LOCAL_ESP_DIR/lib export LD_LIBRARY_PATH=$LOCAL_ESP_DIR/lib
export PATH=$RISCV/bin:$PATH export PATH=$RISCV/bin:$PATH
@@ -40,9 +40,7 @@ if [ $1 = "chipyard-gemmini" ]; then
git submodule update --init --recursive gemmini-rocc-tests git submodule update --init --recursive gemmini-rocc-tests
cd gemmini-rocc-tests cd gemmini-rocc-tests
./build.sh ./build.sh
fi
if [ $1 = "chipyard-hwacha" ] || [ $1 = "chipyard-gemmini" ]; then
TOOLS_DIR=$REMOTE_ESP_DIR TOOLS_DIR=$REMOTE_ESP_DIR
LD_LIB_DIR=$REMOTE_ESP_DIR/lib LD_LIB_DIR=$REMOTE_ESP_DIR/lib
run "mkdir -p $REMOTE_ESP_DIR" run "mkdir -p $REMOTE_ESP_DIR"
@@ -54,16 +52,19 @@ fi
# enter the verilator directory and build the specific config on remote server # enter the verilator directory and build the specific config on remote server
run "export RISCV=\"$TOOLS_DIR\"; \ run "export RISCV=\"$TOOLS_DIR\"; \
export LD_LIBRARY_PATH=\"$LD_LIB_DIR\"; \ make -C $REMOTE_SIM_DIR clean;"
export PATH=\"$REMOTE_VERILATOR_DIR/bin:\$PATH\"; \
export VERILATOR_ROOT=\"$REMOTE_VERILATOR_DIR\"; \
export COURSIER_CACHE=\"$REMOTE_WORK_DIR/.coursier-cache\"; \
make -C $REMOTE_SIM_DIR clean; \
make -j$REMOTE_MAKE_NPROC -C $REMOTE_SIM_DIR FIRRTL_LOGLEVEL=info JAVA_ARGS=\"$REMOTE_JAVA_ARGS\" ${mapping[$1]}"
run "rm -rf $REMOTE_CHIPYARD_DIR/project"
# copy back the final build read -a keys <<< ${grouping[$1]}
for key in "${keys[@]}"
do
run "export RISCV=\"$TOOLS_DIR\"; \
export LD_LIBRARY_PATH=\"$LD_LIB_DIR\"; \
export PATH=\"$REMOTE_VERILATOR_DIR/bin:\$PATH\"; \
export VERILATOR_ROOT=\"$REMOTE_VERILATOR_DIR\"; \
export COURSIER_CACHE=\"$REMOTE_WORK_DIR/.coursier-cache\"; \
make -j$REMOTE_MAKE_NPROC -C $REMOTE_SIM_DIR FIRRTL_LOGLEVEL=info JAVA_ARGS=\"$REMOTE_JAVA_ARGS\" ${mapping[$key]}"
done
run "rm -rf $REMOTE_CHIPYARD_DIR/project" run "rm -rf $REMOTE_CHIPYARD_DIR/project"

View File

@@ -32,6 +32,12 @@ case $1 in
chipyard-rocket) chipyard-rocket)
run_bmark ${mapping[$1]} run_bmark ${mapping[$1]}
;; ;;
chipyard-dmirocket)
run_bmark ${mapping[$1]}
;;
chipyard-lbwif)
run_bmark ${mapping[$1]}
;;
chipyard-boom) chipyard-boom)
run_bmark ${mapping[$1]} run_bmark ${mapping[$1]}
;; ;;
@@ -86,7 +92,10 @@ case $1 in
run_tracegen ${mapping[$1]} run_tracegen ${mapping[$1]}
;; ;;
chipyard-ariane) chipyard-ariane)
make run-binary-fast -C $LOCAL_SIM_DIR ${mapping[$1]} BINARY=$RISCV/riscv64-unknown-elf/share/riscv-tests/benchmarks/dhrystone.riscv make run-binary-fast -C $LOCAL_SIM_DIR ${mapping[$1]} BINARY=$RISCV/riscv64-unknown-elf/share/riscv-tests/benchmarks/multiply.riscv
;;
chipyard-sodor)
run_asm ${mapping[$1]}
;; ;;
chipyard-nvdla) chipyard-nvdla)
make -C $LOCAL_CHIPYARD_DIR/tests make -C $LOCAL_CHIPYARD_DIR/tests

3
.gitmodules vendored
View File

@@ -128,6 +128,9 @@
[submodule "tools/dromajo/dromajo-src"] [submodule "tools/dromajo/dromajo-src"]
path = tools/dromajo/dromajo-src path = tools/dromajo/dromajo-src
url = https://github.com/riscv-boom/dromajo.git url = https://github.com/riscv-boom/dromajo.git
[submodule "generators/riscv-sodor"]
path = generators/riscv-sodor
url = https://github.com/ucb-bar/riscv-sodor.git
[submodule "fpga/fpga-shells"] [submodule "fpga/fpga-shells"]
path = fpga/fpga-shells path = fpga/fpga-shells
url = git@github.com:sifive/fpga-shells.git url = git@github.com:sifive/fpga-shells.git

View File

@@ -132,7 +132,7 @@ lazy val chipyard = conditionalDependsOn(project in file("generators/chipyard"))
.dependsOn(boom, hwacha, sifive_blocks, sifive_cache, utilities, iocell, .dependsOn(boom, hwacha, sifive_blocks, sifive_cache, utilities, iocell,
sha3, // On separate line to allow for cleaner tutorial-setup patches sha3, // On separate line to allow for cleaner tutorial-setup patches
dsptools, `rocket-dsptools`, dsptools, `rocket-dsptools`,
gemmini, icenet, tracegen, ariane, nvdla) gemmini, icenet, tracegen, ariane, nvdla, sodor)
.settings(commonSettings) .settings(commonSettings)
lazy val tracegen = conditionalDependsOn(project in file("generators/tracegen")) lazy val tracegen = conditionalDependsOn(project in file("generators/tracegen"))
@@ -158,6 +158,10 @@ lazy val ariane = (project in file("generators/ariane"))
.dependsOn(rocketchip) .dependsOn(rocketchip)
.settings(commonSettings) .settings(commonSettings)
lazy val sodor = (project in file("generators/riscv-sodor"))
.dependsOn(rocketchip)
.settings(commonSettings)
lazy val sha3 = (project in file("generators/sha3")) lazy val sha3 = (project in file("generators/sha3"))
.dependsOn(rocketchip, chisel_testers, midasTargetUtils) .dependsOn(rocketchip, chisel_testers, midasTargetUtils)
.settings(commonSettings) .settings(commonSettings)

View File

@@ -62,7 +62,8 @@ SOURCE_DIRS = $(addprefix $(base_dir)/,generators sims/firesim/sim tools/barstoo
SCALA_SOURCES = $(call lookup_srcs,$(SOURCE_DIRS),scala) SCALA_SOURCES = $(call lookup_srcs,$(SOURCE_DIRS),scala)
VLOG_SOURCES = $(call lookup_srcs,$(SOURCE_DIRS),sv) $(call lookup_srcs,$(SOURCE_DIRS),v) VLOG_SOURCES = $(call lookup_srcs,$(SOURCE_DIRS),sv) $(call lookup_srcs,$(SOURCE_DIRS),v)
# This assumes no SBT meta-build sources # This assumes no SBT meta-build sources
SBT_SOURCES = $(call lookup_srcs,$(base_dir),sbt) 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
######################################################################################### #########################################################################################
# jar creation variables and rules # jar creation variables and rules

View File

@@ -130,38 +130,8 @@ Using the JTAG Interface
------------------------ ------------------------
The main way to use JTAG with a Rocket Chip based system is to instantiate the Debug Transfer Module (DTM) The main way to use JTAG with a Rocket Chip based system is to instantiate the Debug Transfer Module (DTM)
and configure it to use a JTAG interface (by default the DTM is setup to use the DMI interface mentioned above). and configure it to use a JTAG interface. The default Chipyard designs instantiate the DTM and configure it
to use JTAG. You may attach OpenOCD and GDB to any of the default JTAG-enabled designs.
Creating a DTM+JTAG Config
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
First, a DTM config must be created for the system that you want to create.
This step is similar to the DMI simulation section within the :ref:`Starting the TSI or DMI Simulation` section.
The configuration is very similar to a DMI-based configuration. The main difference
is the addition of the ``WithJtagDTM`` config fragment that configures the instantiated DTM to use the JTAG protocol as the
bringup method.
.. literalinclude:: ../../generators/chipyard/src/main/scala/config/RocketConfigs.scala
:language: scala
:start-after: DOC include start: JtagRocket
:end-before: DOC include end: JtagRocket
Building a DTM+JTAG Simulator
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
After creating the config, call the ``make`` command like the following to build a simulator for your RTL:
.. code-block:: bash
cd sims/verilator
# or
cd sims/vcs
make CONFIG=jtagRocketConfig
In this example, the simulation will use the config that you previously specified, as well as set
the other parameters that are needed to satisfy the build system. After that point, you
should have a JTAG enabled simulator that you can attach to using OpenOCD and GDB!
Debugging with JTAG Debugging with JTAG
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

View File

@@ -12,11 +12,14 @@ to verify functionality.
Setting up Dromajo Co-simulation Setting up Dromajo Co-simulation
-------------------------------------- --------------------------------------
Dromajo co-simulation is setup to work when two config fragments are added to a BOOM config. Dromajo co-simulation is setup to work when three config fragments are added to a BOOM config.
First, a ``chipyard.config.WithTraceIO`` config fragment must be added so that BOOM's traceport is enabled.
Second, a ``chipyard.iobinders.WithSimDromajoBridge`` config fragment must be added to * A ``chipyard.config.WithTraceIO`` config fragment must be added so that BOOM's traceport is enabled.
connect the Dromajo co-simulator to the traceport. * A ``chipyard.iobinders.WithTraceIOPunchthrough`` config fragment must be added to add the ``TraceIO`` to the ``ChipTop``
Once both config fragments are added Dromajo should be enabled. * A ``chipyard.harness.WithSimDromajoBridge`` config fragment must be added to instantiate a Dromajo cosimulator in the ``TestHarness`` and connect it to the ``ChipTop``'s ``TraceIO``
Once all config fragments are added Dromajo should be enabled.
To build/run Dromajo with a BOOM design, run your configuration the following make commands: To build/run Dromajo with a BOOM design, run your configuration the following make commands:

View File

@@ -14,9 +14,9 @@ ChipTop/DUT
``ChipTop`` is the top-level module that instantiates the ``System`` submodule, usually an instance of the concrete class ``DigitalTop``. ``ChipTop`` is the top-level module that instantiates the ``System`` submodule, usually an instance of the concrete class ``DigitalTop``.
The vast majority of the design resides in the ``System``. The vast majority of the design resides in the ``System``.
Other components that exist inside the ``ChipTop`` layer are generally IO cells, clock receivers and multiplexers, reset synchronizers, and other analog IP that needs to exist outside of the ``System``. Other components that exist inside the ``ChipTop`` layer are generally IO cells, clock receivers and multiplexers, reset synchronizers, and other analog IP that needs to exist outside of the ``System``.
The ``IOBinders`` are responsible for instantiating the IO cells and defining the test harness collateral that connects to the top-level ports. The ``IOBinders`` are responsible for instantiating the IO cells for ``ChipTop`` IO that correspond to IO of the ``System``.
Most of these types of devices can be instantiated using custom ``IOBinders``, so the provided ``ChipTop`` and ``ChipTopCaughtReset`` classes are sufficient. The ``HarnessBinders`` are responsible for instantiating test harness collateral that connects to the ``ChipTop`` ports.
However, if needed, the ``BaseChipTop`` abstract class can be extended for building more custom ``ChipTop`` designs. Most types of devices and testing collateral can be instantiated using custom ``IOBinders`` and ``HarnessBinders``.
System/DigitalTop System/DigitalTop

View File

@@ -1,41 +1,43 @@
IOBinders and HarnessBinders
============================
In Chipyard we use special ``Parameters`` keys, ``IOBinders`` and ``HarnessBinders`` to bridge the gap between digital system IOs and TestHarness collateral.
IOBinders IOBinders
========= =========
In Chipyard we use a special ``Parameters`` key, ``IOBinders`` to instantiate IO cells in the ``ChipTop`` layer and determine what modules to bind to the IOs of a ``ChipTop`` in the ``TestHarness``. The ``IOBinder`` functions are responsible for instantiating IO cells and IOPorts in the ``ChipTop`` layer.
``IOBinders`` are typically defined using the ``OverrideIOBinder`` or ``ComposeIOBinder`` macros. An ``IOBinder`` consists of a function matching ``Systems`` with a given trait that generates IO ports and IOCells, and returns a list of generated ports and cells.
For example, the ``WithUARTIOCells`` IOBinder will, for any ``System`` that might have UART ports (``HasPeripheryUARTModuleImp``, generate ports within the ``ChipTop`` (``ports``) as well as IOCells with the appropriate type and direction (``cells2d``). This function returns a the list of generated ports, and the list of generated IOCells. The list of generated ports is passed to the ``HarnessBinders`` such that they can be connected to ``TestHarness`` devices.
.. literalinclude:: ../../generators/chipyard/src/main/scala/IOBinders.scala .. literalinclude:: ../../generators/chipyard/src/main/scala/IOBinders.scala
:language: scala :language: scala
:start-after: DOC include start: IOBinders :start-after: DOC include start: WithUARTIOCells
:end-before: DOC include end: IOBinders :end-before: DOC include end: WithUARTIOCells
HarnessBinders
==============
This special key solves the problem of duplicating test-harnesses for each different ``System`` type. The ``HarnessBinder`` functions determine what modules to bind to the IOs of a ``ChipTop`` in the ``TestHarness``. The ``HarnessBinder`` interface is designed to be reused across various simulation/implementation modes, enabling decoupling of the target design from simulation and testing concerns.
You could just as well create a custom harness module that attaches IOs explicitly.
Instead, the ``IOBinders`` key provides a map from Scala traits to attachment behaviors.
Each ``IOBinder`` returns a tuple of three values: the list of ``ChipTop`` ports created by the ``IOBinder``, the list of all IO cell modules instantiated by the ``IOBinder``, and an optional function to be called inside the test harness.
This function is responsible for instantiating logic inside the ``TestHarness`` to appropriately drive the ``ChipTop`` IO ports created by the ``IOBinder``.
Conveniently, because the ``IOBinder`` is generating the port, it may also use the port inside this function, which prevents the ``BaseChipTop`` code from ever needing to access the port ``val``, thus having the ``IOBinder`` house all port specific code.
This scheme prevents the need to have two separate binder functions for each ``System`` trait.
When creating custom ``IOBinders`` it is important to use ``suggestName`` to name ports; otherwise Chisel will raise an exception trying to name the IOs.
The example ``IOBinders`` demonstrate this.
As an example, the ``WithGPIOTiedOff`` IOBinder creates IO cells for the GPIO module(s) instantiated in the ``System``, then punches out new ``Analog`` ports for each one. * For SW RTL or GL simulations, the default set of ``HarnessBinders`` instantiate software-simulated models of various devices, for example external memory or UART, and connect those models to the IOs of the ``ChipTop``.
The test harness simply ties these off, but additional logic could be inserted to perform some kind of test in the ``TestHarness``. * For FireSim simulations, FireSim-specific ``HarnessBinders`` instantiate ``Bridges``, which faciliate cycle-accurate simulation across the simulated chip's IOs. See the FireSim documentation for more details.
* In the future, a Chipyard FPGA prototyping flow may use ``HarnessBinders`` to connect ``ChipTop`` IOs to other devices or IOs in the FPGA harness.
.. literalinclude:: ../../generators/chipyard/src/main/scala/IOBinders.scala Like ``IOBinders``, ``HarnessBinders`` are defined using macros (``OverrideHarnessBinder, ComposeHarnessBinder``), and match ``Systems`` with a given trait. However, ``HarnessBinders`` are also passed a reference to the ``TestHarness`` (``th: HasHarnessSignalReferences``) and the list of ports generated by the corresponding ``IOBinder`` (``ports: Seq[Data]``).
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
:language: scala :language: scala
:start-after: DOC include start: WithGPIOTiedOff :start-after: DOC include start: WithUARTAdapter
:end-before: DOC include end: WithGPIOTiedOff :end-before: DOC include end: WithUARTAdapter
The ``IOBinder`` and ``HarnessBinder`` system is designed to enable decoupling of concerns between the target design and the simulation system.
``IOBinders`` also do not need to create ports. Some ``IOBinders`` can simply insert circuitry inside the ``ChipTop`` layer. For a given set of chip IOs, there may be not only multiple simulation platforms ("harnesses", so-to-speak), but also multiple simulation strategies. For example, the choice of whether to connect the backing AXI4 memory port to an accurate DRAM model (``SimDRAM``) or a simple simulated memory model (``SimAXIMem``) is isolated in ``HarnessBinders``, and does not affect target RTL generation.
For example, the ``WithSimAXIMemTiedOff`` IOBinder specifies that any ``System`` which matches ``CanHaveMasterAXI4MemPortModuleImp`` will have a ``SimAXIMem`` connected inside ``ChipTop``.
.. literalinclude:: ../../generators/chipyard/src/main/scala/IOBinders.scala Similarly, for a given simulation platform and strategy, there may be multiple strategies for generating the chip IOs. This target-design configuration is isolated in the ``IOBinders``.
:language: scala
:start-after: DOC include start: WithSimAXIMem
:end-before: DOC include end: WithSimAXIMem
These classes are all ``Config`` objects, which can be mixed into the configs to specify IO connection behaviors.
There are two macros for generating these ``Config``s. ``OverrideIOBinder`` overrides any existing behaviors set for a particular IO in the ``Config`` object. This macro is frequently used because typically top-level IOs drive or are driven by only one source, so a composition of ``IOBinders`` does not make sense. The ``ComposeIOBinder`` macro provides the functionality of not overriding existing behaviors.

17
docs/Generators/Sodor.rst Normal file
View File

@@ -0,0 +1,17 @@
Sodor Core
====================================
`Sodor <https://github.com/ucb-bar/riscv-sodor>`__ is a collection of 5 simple RV32MI cores designed for educational purpose.
The `Sodor core` is wrapped in an tile during generation so it can be used as a component within the `Rocket Chip SoC generator`.
The cores contain a small scratchpad memory to which the program are loaded through a TileLink slave port, and the cores **DO NOT**
support external memory.
The five available cores and their corresponding generator configuration are:
* 1-stage (essentially an ISA simulator) - ``Sodor1StageConfig``
* 2-stage (demonstrates pipelining in Chisel) - ``Sodor2StageConfig``
* 3-stage (uses sequential memory; supports both Harvard (``Sodor3StageConfig``) and Princeton (``Sodor3StageSinglePortConfig``) versions)
* 5-stage (can toggle between fully bypassed or fully interlocked) - ``Sodor5StageConfig``
* "bus"-based micro-coded implementation - ``SodorUCodeConfig``
For more information, please refer to the `GitHub repository <https://github.com/ucb-bar/riscv-sodor>`__.

View File

@@ -29,4 +29,5 @@ so changes to the generators themselves will automatically be used when building
SHA3 SHA3
Ariane Ariane
NVDLA NVDLA
Sodor

View File

@@ -0,0 +1,42 @@
// See LICENSE for license details.
/**
* An unsynthesizable divide-by-N clock divider.
* Duty cycle is 100 * (ceil(DIV / 2)) / DIV.
*/
module ClockDividerN #(parameter DIV)(output logic clk_out = 1'b0, input clk_in);
localparam CWIDTH = $clog2(DIV);
localparam LOW_CYCLES = DIV / 2;
localparam HIGH_TRANSITION = LOW_CYCLES - 1;
localparam LOW_TRANSITION = DIV - 1;
generate
if (DIV == 1) begin
// This needs to be procedural because of the assignment on declaration
always @(clk_in) begin
clk_out = clk_in;
end
end else begin
reg [CWIDTH - 1: 0] count = HIGH_TRANSITION[CWIDTH-1:0];
// The blocking assignment to clock out is used to conform what was done
// in RC's clock dividers.
// It should have the effect of preventing registers in the divided clock
// domain latching register updates launched by the fast clock-domain edge
// that occurs at the same simulated time (as the divided clock edge).
always @(posedge clk_in) begin
if (count == LOW_TRANSITION[CWIDTH-1:0]) begin
clk_out = 1'b0;
count <= '0;
end
else begin
if (count == HIGH_TRANSITION[CWIDTH-1:0]) begin
clk_out = 1'b1;
end
count <= count + 1'b1;
end
end
end
endgenerate
endmodule // ClockDividerN

View File

@@ -9,7 +9,7 @@ import freechips.rocketchip.subsystem.{BaseSubsystem, SubsystemDriveAsyncClockGr
import freechips.rocketchip.config.{Parameters, Field} import freechips.rocketchip.config.{Parameters, Field}
import freechips.rocketchip.diplomacy.{LazyModule, LazyModuleImp, LazyRawModuleImp, LazyModuleImpLike} import freechips.rocketchip.diplomacy.{LazyModule, LazyModuleImp, LazyRawModuleImp, LazyModuleImpLike}
import freechips.rocketchip.util.{ResetCatchAndSync} import freechips.rocketchip.util.{ResetCatchAndSync}
import chipyard.iobinders.{IOBinders, TestHarnessFunction, IOBinderTuple} import chipyard.iobinders._
import barstools.iocell.chisel._ import barstools.iocell.chisel._
@@ -26,14 +26,12 @@ case object BuildSystem extends Field[Parameters => LazyModule]((p: Parameters)
class ChipTop(implicit p: Parameters) extends LazyModule with HasTestHarnessFunctions { class ChipTop(implicit p: Parameters) extends LazyModule with HasTestHarnessFunctions {
// A publicly accessible list of IO cells (useful for a floorplanning tool, for example) // A publicly accessible list of IO cells (useful for a floorplanning tool, for example)
val iocells = ArrayBuffer.empty[IOCell] val iocells = ArrayBuffer.empty[IOCell]
// A list of functions to call in the test harness
val harnessFunctions = ArrayBuffer.empty[TestHarnessFunction]
// The system module specified by BuildSystem // The system module specified by BuildSystem
val lSystem = LazyModule(p(BuildSystem)(p)).suggestName("system") val lazySystem = LazyModule(p(BuildSystem)(p)).suggestName("system")
// The implicitClockSinkNode provides the implicit clock and reset for the System // The implicitClockSinkNode provides the implicit clock and reset for the System
val implicitClockSinkNode = ClockSinkNode(Seq(ClockSinkParameters())) val implicitClockSinkNode = ClockSinkNode(Seq(ClockSinkParameters(name = Some("implicit_clock"))))
// Generate Clocks and Reset // Generate Clocks and Reset
p(ClockingSchemeKey)(this) p(ClockingSchemeKey)(this)
@@ -48,18 +46,14 @@ class ChipTop(implicit p: Parameters) extends LazyModule with HasTestHarnessFunc
val implicit_reset = implicitClockSinkNode.in.head._1.reset val implicit_reset = implicitClockSinkNode.in.head._1.reset
// The implicit clock and reset for the system is also, by convention, used for all the IOBinders // Note: IOBinders cannot rely on the implicit clock/reset, as this is a LazyRawModuleImp
// TODO: This may not be the right thing to do in all cases val (_ports, _iocells, _portMap) = ApplyIOBinders(lazySystem, p(IOBinders))
withClockAndReset(implicit_clock, implicit_reset) { // We ignore _ports for now...
val (_ports, _iocells, _harnessFunctions) = p(IOBinders).values.flatMap(f => f(lSystem) ++ f(lSystem.module)).unzip3 iocells ++= _iocells
// We ignore _ports for now... portMap ++= _portMap
iocells ++= _iocells.flatten
harnessFunctions ++= _harnessFunctions.flatten
println(s"ChipTop: sz:${harnessFunctions.size}")
}
// Connect the implicit clock/reset, if present // Connect the implicit clock/reset, if present
lSystem.module match { case l: LazyModuleImp => { lazySystem.module match { case l: LazyModuleImp => {
l.clock := implicit_clock l.clock := implicit_clock
l.reset := implicit_reset l.reset := implicit_reset
}} }}

View File

@@ -5,12 +5,15 @@ import chisel3._
import scala.collection.mutable.{ArrayBuffer} import scala.collection.mutable.{ArrayBuffer}
import freechips.rocketchip.prci._ import freechips.rocketchip.prci._
import freechips.rocketchip.subsystem.{BaseSubsystem, SubsystemDriveAsyncClockGroupsKey} import freechips.rocketchip.subsystem.{BaseSubsystem, SubsystemDriveAsyncClockGroupsKey, InstantiatesTiles}
import freechips.rocketchip.config.{Parameters, Field} import freechips.rocketchip.config.{Parameters, Field, Config}
import freechips.rocketchip.diplomacy.{OutwardNodeHandle, InModuleBody, LazyModule} import freechips.rocketchip.diplomacy.{OutwardNodeHandle, InModuleBody, LazyModule}
import freechips.rocketchip.util.{ResetCatchAndSync, Pow2ClockDivider} import freechips.rocketchip.util.{ResetCatchAndSync, Pow2ClockDivider}
import barstools.iocell.chisel._ import barstools.iocell.chisel._
import testchipip.{TLTileResetCtrl}
import chipyard.clocking.{DividerOnlyClockGenerator, ClockGroupNamePrefixer, ClockGroupFrequencySpecifier}
/** /**
* Chipyard provides three baseline, top-level reset schemes, set using the * Chipyard provides three baseline, top-level reset schemes, set using the
@@ -58,16 +61,15 @@ object GenerateReset {
val reset_wire = Wire(Input(Reset())) val reset_wire = Wire(Input(Reset()))
val (reset_io, resetIOCell) = p(GlobalResetSchemeKey) match { val (reset_io, resetIOCell) = p(GlobalResetSchemeKey) match {
case GlobalResetSynchronous => case GlobalResetSynchronous =>
IOCell.generateIOFromSignal(reset_wire, Some("iocell_reset")) IOCell.generateIOFromSignal(reset_wire, "reset")
case GlobalResetAsynchronousFull => case GlobalResetAsynchronousFull =>
IOCell.generateIOFromSignal(reset_wire, Some("iocell_reset"), abstractResetAsAsync = true) IOCell.generateIOFromSignal(reset_wire, "reset", abstractResetAsAsync = true)
case GlobalResetAsynchronous => { case GlobalResetAsynchronous => {
val async_reset_wire = Wire(Input(AsyncReset())) val async_reset_wire = Wire(Input(AsyncReset()))
reset_wire := ResetCatchAndSync(clock, async_reset_wire.asBool()) reset_wire := ResetCatchAndSync(clock, async_reset_wire.asBool())
IOCell.generateIOFromSignal(async_reset_wire, Some("iocell_reset"), abstractResetAsAsync = true) IOCell.generateIOFromSignal(async_reset_wire, "reset", abstractResetAsAsync = true)
} }
} }
reset_io.suggestName("reset")
chiptop.iocells ++= resetIOCell chiptop.iocells ++= resetIOCell
chiptop.harnessFunctions += ((th: HasHarnessSignalReferences) => { chiptop.harnessFunctions += ((th: HasHarnessSignalReferences) => {
reset_io := th.dutReset reset_io := th.dutReset
@@ -78,101 +80,72 @@ object GenerateReset {
} }
case object ClockingSchemeKey extends Field[ChipTop => Unit](ClockingSchemeGenerators.harnessClock) case object ClockingSchemeKey extends Field[ChipTop => Unit](ClockingSchemeGenerators.dividerOnlyClockGenerator)
/*
* This is a Seq of assignment functions, that accept a clock name and return an optional frequency.
* Functions that appear later in this seq have higher precedence that earlier ones.
* If no function returns a non-empty value, the value specified in
* [[DefaultClockFrequencyKey]] will be used.
*/
case object ClockFrequencyAssignersKey extends Field[Seq[(String) => Option[Double]]](Seq.empty)
case object DefaultClockFrequencyKey extends Field[Double]()
class ClockNameMatchesAssignment(name: String, fMHz: Double) extends Config((site, here, up) => {
case ClockFrequencyAssignersKey => up(ClockFrequencyAssignersKey, site) ++
Seq((cName: String) => if (cName == name) Some(fMHz) else None)
})
class ClockNameContainsAssignment(name: String, fMHz: Double) extends Config((site, here, up) => {
case ClockFrequencyAssignersKey => up(ClockFrequencyAssignersKey, site) ++
Seq((cName: String) => if (cName.contains(name)) Some(fMHz) else None)
})
object ClockingSchemeGenerators { object ClockingSchemeGenerators {
// A simple clock provider, for testing val dividerOnlyClockGenerator: ChipTop => Unit = { chiptop =>
val harnessClock: ChipTop => Unit = { chiptop =>
implicit val p = chiptop.p implicit val p = chiptop.p
val implicitClockSourceNode = ClockSourceNode(Seq(ClockSourceParameters())) // Requires existence of undriven asyncClockGroups in subsystem
chiptop.implicitClockSinkNode := implicitClockSourceNode val systemAsyncClockGroup = chiptop.lazySystem match {
case l: BaseSubsystem if (p(SubsystemDriveAsyncClockGroupsKey).isEmpty) =>
// Drive the diplomaticclock graph of the DigitalTop (if present) l.asyncClockGroupsNode
val simpleClockGroupSourceNode = chiptop.lSystem match {
case l: BaseSubsystem if (p(SubsystemDriveAsyncClockGroupsKey).isEmpty) => {
val n = ClockGroupSourceNode(Seq(ClockGroupSourceParameters()))
l.asyncClockGroupsNode := n
Some(n)
}
case _ => None
} }
// Add a control register for each tile's reset
val resetSetter = chiptop.lazySystem match {
case sys: BaseSubsystem with InstantiatesTiles => TLTileResetCtrl(sys)
case _ => ClockGroupEphemeralNode()
}
val aggregator = LazyModule(new ClockGroupAggregator("allClocks")).node
(chiptop.implicitClockSinkNode
:= ClockGroup()
:= aggregator)
(systemAsyncClockGroup
:= resetSetter
:= ClockGroupNamePrefixer()
:= aggregator)
val referenceClockSource = ClockSourceNode(Seq(ClockSourceParameters()))
(aggregator
:= ClockGroupFrequencySpecifier(p(ClockFrequencyAssignersKey), p(DefaultClockFrequencyKey))
:= DividerOnlyClockGenerator()
:= referenceClockSource)
InModuleBody { InModuleBody {
//this needs directionality so generateIOFromSignal works
val clock_wire = Wire(Input(Clock())) val clock_wire = Wire(Input(Clock()))
val reset_wire = GenerateReset(chiptop, clock_wire) val reset_wire = GenerateReset(chiptop, clock_wire)
val (clock_io, clockIOCell) = IOCell.generateIOFromSignal(clock_wire, Some("iocell_clock")) val (clock_io, clockIOCell) = IOCell.generateIOFromSignal(clock_wire, "clock")
chiptop.iocells ++= clockIOCell chiptop.iocells ++= clockIOCell
clock_io.suggestName("clock")
implicitClockSourceNode.out.unzip._1.map { o => referenceClockSource.out.unzip._1.map { o =>
o.clock := clock_wire o.clock := clock_wire
o.reset := reset_wire o.reset := reset_wire
} }
simpleClockGroupSourceNode.map { n => n.out.unzip._1.map { out: ClockGroupBundle =>
out.member.data.foreach { o =>
o.clock := clock_wire
o.reset := reset_wire
}
}}
chiptop.harnessFunctions += ((th: HasHarnessSignalReferences) => { chiptop.harnessFunctions += ((th: HasHarnessSignalReferences) => {
clock_io := th.harnessClock clock_io := th.harnessClock
Nil Nil })
})
} }
}
val harnessDividedClock: ChipTop => Unit = { chiptop =>
implicit val p = chiptop.p
require(false, "Divided clock is broken until we fix passing onchip clocks to TestHarness objects")
val implicitClockSourceNode = ClockSourceNode(Seq(ClockSourceParameters()))
chiptop.implicitClockSinkNode := implicitClockSourceNode
val simpleClockGroupSourceNode = chiptop.lSystem match {
case l: BaseSubsystem if (p(SubsystemDriveAsyncClockGroupsKey).isEmpty) => {
val n = ClockGroupSourceNode(Seq(ClockGroupSourceParameters()))
l.asyncClockGroupsNode := n
Some(n)
}
case _ => throw new Exception("Harness multiclock assumes BaseSubsystem")
}
InModuleBody {
// this needs directionality so generateIOFromSignal works
val clock_wire = Wire(Input(Clock()))
val reset_wire = GenerateReset(chiptop, clock_wire)
val (clock_io, clockIOCell) = IOCell.generateIOFromSignal(clock_wire, Some("iocell_clock"))
chiptop.iocells ++= clockIOCell
clock_io.suggestName("clock")
val div_clock = Pow2ClockDivider(clock_wire, 2)
implicitClockSourceNode.out.unzip._1.map { o =>
o.clock := div_clock
o.reset := reset_wire
}
simpleClockGroupSourceNode.map { n => n.out.unzip._1.map { out: ClockGroupBundle =>
out.member.elements.map { case (name, data) =>
// This is mega hacks, how are you actually supposed to do this?
data.clock := (if (name.contains("core")) clock_wire else div_clock)
data.reset := reset_wire
}
}}
chiptop.harnessFunctions += ((th: HasHarnessSignalReferences) => {
clock_io := th.harnessClock
Nil
})
}
} }
} }

View File

@@ -7,7 +7,7 @@ import freechips.rocketchip.config.{Field, Parameters, Config}
import freechips.rocketchip.subsystem._ import freechips.rocketchip.subsystem._
import freechips.rocketchip.diplomacy.{LazyModule, ValName} import freechips.rocketchip.diplomacy.{LazyModule, ValName}
import freechips.rocketchip.devices.tilelink.{BootROMLocated} import freechips.rocketchip.devices.tilelink.{BootROMLocated}
import freechips.rocketchip.devices.debug.{Debug} import freechips.rocketchip.devices.debug.{Debug, ExportDebug, DebugModuleKey, DMI}
import freechips.rocketchip.groundtest.{GroundTestSubsystem} import freechips.rocketchip.groundtest.{GroundTestSubsystem}
import freechips.rocketchip.tile._ import freechips.rocketchip.tile._
import freechips.rocketchip.rocket.{RocketCoreParams, MulDivParams, DCacheParams, ICacheParams} import freechips.rocketchip.rocket.{RocketCoreParams, MulDivParams, DCacheParams, ICacheParams}
@@ -26,8 +26,7 @@ import sifive.blocks.devices.gpio._
import sifive.blocks.devices.uart._ import sifive.blocks.devices.uart._
import sifive.blocks.devices.spi._ import sifive.blocks.devices.spi._
import chipyard.{BuildTop, BuildSystem, ClockingSchemeGenerators, ClockingSchemeKey, TestSuitesKey, TestSuiteHelper} import chipyard._
// ----------------------- // -----------------------
// Common Config Fragments // Common Config Fragments
@@ -159,7 +158,17 @@ class WithNoSubsystemDrivenClocks extends Config((site, here, up) => {
case SubsystemDriveAsyncClockGroupsKey => None case SubsystemDriveAsyncClockGroupsKey => None
}) })
class WithTileDividedClock extends Config((site, here, up) => { class WithDMIDTM extends Config((site, here, up) => {
case ClockingSchemeKey => ClockingSchemeGenerators.harnessDividedClock case ExportDebug => up(ExportDebug, site).copy(protocols = Set(DMI))
})
class WithNoDebug extends Config((site, here, up) => {
case DebugModuleKey => None
})
class WithTileFrequency(fMHz: Double) extends ClockNameContainsAssignment("core", fMHz)
class WithPeripheryBusFrequencyAsDefault extends Config((site, here, up) => {
case DefaultClockFrequencyKey => (site(PeripheryBusKey).dtsFrequency.get / (1000 * 1000)).toDouble
}) })

View File

@@ -16,7 +16,7 @@ class DigitalTop(implicit p: Parameters) extends ChipyardSystem
with testchipip.CanHaveTraceIO // Enables optionally adding trace IO with testchipip.CanHaveTraceIO // Enables optionally adding trace IO
with testchipip.CanHaveBackingScratchpad // Enables optionally adding a backing scratchpad with testchipip.CanHaveBackingScratchpad // Enables optionally adding a backing scratchpad
with testchipip.CanHavePeripheryBlockDevice // Enables optionally adding the block device with testchipip.CanHavePeripheryBlockDevice // Enables optionally adding the block device
with testchipip.CanHavePeripherySerial // Enables optionally adding the TSI serial-adapter and port with testchipip.CanHavePeripheryTLSerial // Enables optionally adding the backing memory and serial adapter
with sifive.blocks.devices.uart.HasPeripheryUART // Enables optionally adding the sifive UART with sifive.blocks.devices.uart.HasPeripheryUART // Enables optionally adding the sifive UART
with sifive.blocks.devices.gpio.HasPeripheryGPIO // Enables optionally adding the sifive GPIOs with sifive.blocks.devices.gpio.HasPeripheryGPIO // Enables optionally adding the sifive GPIOs
with sifive.blocks.devices.spi.HasPeripherySPIFlash // Enables optionally adding the sifive SPI flash controller with sifive.blocks.devices.spi.HasPeripherySPIFlash // Enables optionally adding the sifive SPI flash controller
@@ -36,15 +36,12 @@ class DigitalTop(implicit p: Parameters) extends ChipyardSystem
class DigitalTopModule[+L <: DigitalTop](l: L) extends ChipyardSystemModule(l) class DigitalTopModule[+L <: DigitalTop](l: L) extends ChipyardSystemModule(l)
with testchipip.CanHaveTraceIOModuleImp with testchipip.CanHaveTraceIOModuleImp
with testchipip.CanHavePeripheryBlockDeviceModuleImp
with testchipip.CanHavePeripherySerialModuleImp
with sifive.blocks.devices.uart.HasPeripheryUARTModuleImp with sifive.blocks.devices.uart.HasPeripheryUARTModuleImp
with sifive.blocks.devices.gpio.HasPeripheryGPIOModuleImp with sifive.blocks.devices.gpio.HasPeripheryGPIOModuleImp
with sifive.blocks.devices.spi.HasPeripherySPIFlashModuleImp with sifive.blocks.devices.spi.HasPeripherySPIFlashModuleImp
with sifive.blocks.devices.spi.HasPeripherySPIModuleImp with sifive.blocks.devices.spi.HasPeripherySPIModuleImp
with sifive.blocks.devices.pwm.HasPeripheryPWMModuleImp with sifive.blocks.devices.pwm.HasPeripheryPWMModuleImp
with sifive.blocks.devices.i2c.HasPeripheryI2CModuleImp with sifive.blocks.devices.i2c.HasPeripheryI2CModuleImp
with icenet.CanHavePeripheryIceNICModuleImp
with chipyard.example.CanHavePeripheryGCDModuleImp with chipyard.example.CanHavePeripheryGCDModuleImp
with freechips.rocketchip.util.DontTouch with freechips.rocketchip.util.DontTouch
// DOC include end: DigitalTop // DOC include end: DigitalTop

View File

@@ -0,0 +1,260 @@
package chipyard.harness
import chisel3._
import chisel3.experimental.{Analog, BaseModule}
import freechips.rocketchip.config.{Field, Config, Parameters}
import freechips.rocketchip.diplomacy.{LazyModule, LazyModuleImpLike}
import freechips.rocketchip.amba.axi4.{AXI4Bundle, AXI4SlaveNode, AXI4MasterNode, AXI4EdgeParameters}
import freechips.rocketchip.devices.debug._
import freechips.rocketchip.jtag.{JTAGIO}
import freechips.rocketchip.system.{SimAXIMem}
import freechips.rocketchip.subsystem._
import sifive.blocks.devices.gpio._
import sifive.blocks.devices.uart._
import sifive.blocks.devices.spi._
import barstools.iocell.chisel._
import testchipip._
import chipyard.HasHarnessSignalReferences
import chipyard.iobinders.GetSystemParameters
import tracegen.{TraceGenSystemModuleImp}
import icenet.{CanHavePeripheryIceNIC, SimNetwork, NicLoopback, NICKey, NICIOvonly}
import scala.reflect.{ClassTag}
case object HarnessBinders extends Field[Map[String, (Any, HasHarnessSignalReferences, Seq[Data]) => Seq[Any]]](
Map[String, (Any, HasHarnessSignalReferences, Seq[Data]) => Seq[Any]]().withDefaultValue((t: Any, th: HasHarnessSignalReferences, d: Seq[Data]) => Nil)
)
object ApplyHarnessBinders {
def apply(th: HasHarnessSignalReferences, sys: LazyModule, portMap: Map[String, Seq[Data]])(implicit p: Parameters) = {
val pm = portMap.withDefaultValue(Nil)
p(HarnessBinders).map { case (s, f) => f(sys, th, pm(s)) ++ f(sys.module, th, pm(s)) }
}
}
class HarnessBinder[T, S <: HasHarnessSignalReferences, U <: Data](composer: ((T, S, Seq[U]) => Seq[Any]) => (T, S, Seq[U]) => Seq[Any])(implicit tag: ClassTag[T], thtag: ClassTag[S], ptag: ClassTag[U]) extends Config((site, here, up) => {
case HarnessBinders => up(HarnessBinders, site) + (tag.runtimeClass.toString ->
((t: Any, th: HasHarnessSignalReferences, ports: Seq[Data]) => {
val pts = ports.collect({case p: U => p})
require (pts.length == ports.length, s"Port type mismatch between IOBinder and HarnessBinder: ${ptag}")
val upfn = up(HarnessBinders, site)(tag.runtimeClass.toString)
th match {
case th: S =>
t match {
case system: T => composer(upfn)(system, th, pts)
case _ => Nil
}
case _ => Nil
}
})
)
})
class OverrideHarnessBinder[T, S <: HasHarnessSignalReferences, U <: Data](fn: => (T, S, Seq[U]) => Seq[Any])
(implicit tag: ClassTag[T], thtag: ClassTag[S], ptag: ClassTag[U])
extends HarnessBinder[T, S, U]((upfn: (T, S, Seq[U]) => Seq[Any]) => fn)
class ComposeHarnessBinder[T, S <: HasHarnessSignalReferences, U <: Data](fn: => (T, S, Seq[U]) => Seq[Any])
(implicit tag: ClassTag[T], thtag: ClassTag[S], ptag: ClassTag[U])
extends HarnessBinder[T, S, U]((upfn: (T, S, Seq[U]) => Seq[Any]) => (t, th, p) => upfn(t, th, p) ++ fn(t, th, p))
class WithGPIOTiedOff extends OverrideHarnessBinder({
(system: HasPeripheryGPIOModuleImp, th: BaseModule with HasHarnessSignalReferences, ports: Seq[Analog]) => {
ports.foreach { _ <> AnalogConst(0) }
Nil
}
})
// DOC include start: WithUARTAdapter
class WithUARTAdapter extends OverrideHarnessBinder({
(system: HasPeripheryUARTModuleImp, th: BaseModule with HasHarnessSignalReferences, ports: Seq[UARTPortIO]) => {
UARTAdapter.connect(ports)(system.p)
Nil
}
})
// DOC include end: WithUARTAdapter
class WithSimSPIFlashModel(rdOnly: Boolean = true) extends OverrideHarnessBinder({
(system: HasPeripherySPIFlashModuleImp, th: BaseModule with HasHarnessSignalReferences, ports: Seq[SPIChipIO]) => {
SimSPIFlashModel.connect(ports, th.harnessReset, rdOnly)(system.p)
Nil
}
})
class WithSimBlockDevice extends OverrideHarnessBinder({
(system: CanHavePeripheryBlockDevice, th: BaseModule with HasHarnessSignalReferences, ports: Seq[ClockedIO[BlockDeviceIO]]) => {
implicit val p: Parameters = GetSystemParameters(system)
ports.map { b => SimBlockDevice.connect(b.clock, th.harnessReset.asBool, Some(b.bits)) }
Nil
}
})
class WithBlockDeviceModel extends OverrideHarnessBinder({
(system: CanHavePeripheryBlockDevice, th: BaseModule with HasHarnessSignalReferences, ports: Seq[ClockedIO[BlockDeviceIO]]) => {
implicit val p: Parameters = GetSystemParameters(system)
ports.map { b => withClockAndReset(b.clock, th.harnessReset) { BlockDeviceModel.connect(Some(b.bits)) } }
Nil
}
})
class WithLoopbackNIC extends OverrideHarnessBinder({
(system: CanHavePeripheryIceNIC, th: BaseModule with HasHarnessSignalReferences, ports: Seq[ClockedIO[NICIOvonly]]) => {
implicit val p: Parameters = GetSystemParameters(system)
ports.map { n =>
withClockAndReset(n.clock, th.harnessReset) {
NicLoopback.connect(Some(n.bits), p(NICKey))
}
}
Nil
}
})
class WithSimNetwork extends OverrideHarnessBinder({
(system: CanHavePeripheryIceNIC, th: BaseModule with HasHarnessSignalReferences, ports: Seq[ClockedIO[NICIOvonly]]) => {
implicit val p: Parameters = GetSystemParameters(system)
ports.map { n => SimNetwork.connect(Some(n.bits), n.clock, th.harnessReset.asBool) }
Nil
}
})
class WithSimAXIMem extends OverrideHarnessBinder({
(system: CanHaveMasterAXI4MemPort, th: BaseModule with HasHarnessSignalReferences, ports: Seq[ClockedIO[AXI4Bundle]]) => {
val p: Parameters = chipyard.iobinders.GetSystemParameters(system)
(ports zip system.memAXI4Node.edges.in).map { case (port, edge) =>
val mem = LazyModule(new SimAXIMem(edge, size=p(ExtMem).get.master.size)(p))
withClockAndReset(port.clock, th.harnessReset) {
Module(mem.module).suggestName("mem")
}
mem.io_axi4.head <> port.bits
}
Nil
}
})
class WithBlackBoxSimMem extends OverrideHarnessBinder({
(system: CanHaveMasterAXI4MemPort, th: BaseModule with HasHarnessSignalReferences, ports: Seq[ClockedIO[AXI4Bundle]]) => {
val p: Parameters = chipyard.iobinders.GetSystemParameters(system)
(ports zip system.memAXI4Node.edges.in).map { case (port, edge) =>
val memSize = p(ExtMem).get.master.size
val lineSize = p(CacheBlockBytes)
val mem = Module(new SimDRAM(memSize, lineSize, edge.bundle)).suggestName("simdram")
mem.io.axi <> port.bits
mem.io.clock := port.clock
mem.io.reset := th.harnessReset
}
Nil
}
})
class WithSimAXIMMIO extends OverrideHarnessBinder({
(system: CanHaveMasterAXI4MMIOPort, th: BaseModule with HasHarnessSignalReferences, ports: Seq[ClockedIO[AXI4Bundle]]) => {
val p: Parameters = chipyard.iobinders.GetSystemParameters(system)
(ports zip system.mmioAXI4Node.edges.in).map { case (port, edge) =>
val mmio_mem = LazyModule(new SimAXIMem(edge, size = p(ExtBus).get.size)(p))
withClockAndReset(port.clock, th.harnessReset) {
Module(mmio_mem.module).suggestName("mmio_mem")
}
mmio_mem.io_axi4.head <> port.bits
}
Nil
}
})
class WithTieOffInterrupts extends OverrideHarnessBinder({
(system: HasExtInterruptsModuleImp, th: BaseModule with HasHarnessSignalReferences, ports: Seq[UInt]) => {
ports.foreach { _ := 0.U }
Nil
}
})
class WithTieOffL2FBusAXI extends OverrideHarnessBinder({
(system: CanHaveSlaveAXI4Port, th: BaseModule with HasHarnessSignalReferences, ports: Seq[ClockedIO[AXI4Bundle]]) => {
ports.foreach({ p => p := DontCare; p.bits.tieoff() })
Nil
}
})
class WithSimDebug extends OverrideHarnessBinder({
(system: HasPeripheryDebugModuleImp, th: BaseModule with HasHarnessSignalReferences, ports: Seq[Data]) => {
ports.map {
case d: ClockedDMIIO =>
val dtm_success = WireInit(false.B)
when (dtm_success) { th.success := true.B }
val dtm = Module(new SimDTM()(system.p)).connect(th.harnessClock, th.harnessReset.asBool, d, dtm_success)
case j: JTAGIO =>
val dtm_success = WireInit(false.B)
when (dtm_success) { th.success := true.B }
val jtag = Module(new SimJTAG(tickDelay=3)).connect(j, th.harnessClock, th.harnessReset.asBool, ~(th.harnessReset.asBool), dtm_success)
}
Nil
}
})
class WithTiedOffDebug extends OverrideHarnessBinder({
(system: HasPeripheryDebugModuleImp, th: BaseModule with HasHarnessSignalReferences, ports: Seq[Data]) => {
ports.map {
case j: JTAGIO =>
j.TCK := true.B.asClock
j.TMS := true.B
j.TDI := true.B
j.TRSTn.foreach { r => r := true.B }
case d: ClockedDMIIO =>
d.dmi.req.valid := false.B
d.dmi.req.bits := DontCare
d.dmi.resp.ready := true.B
d.dmiClock := false.B.asClock
d.dmiReset := true.B
case a: ClockedAPBBundle =>
a.tieoff()
a.clock := false.B.asClock
a.reset := true.B.asAsyncReset
a.psel := false.B
a.penable := false.B
}
Nil
}
})
class WithSerialAdapterTiedOff extends OverrideHarnessBinder({
(system: CanHavePeripheryTLSerial, th: BaseModule with HasHarnessSignalReferences, ports: Seq[ClockedIO[SerialIO]]) => {
implicit val p = chipyard.iobinders.GetSystemParameters(system)
ports.map({ port =>
val ram = SerialAdapter.connectHarnessRAM(system.serdesser.get, port, th.harnessReset)
SerialAdapter.tieoff(ram.module.io.tsi_ser)
})
}
})
class WithSimSerial extends OverrideHarnessBinder({
(system: CanHavePeripheryTLSerial, th: BaseModule with HasHarnessSignalReferences, ports: Seq[ClockedIO[SerialIO]]) => {
implicit val p = chipyard.iobinders.GetSystemParameters(system)
ports.map({ port =>
val ram = SerialAdapter.connectHarnessRAM(system.serdesser.get, port, th.harnessReset)
val success = SerialAdapter.connectSimSerial(ram.module.io.tsi_ser, port.clock, th.harnessReset.asBool)
when (success) { th.success := true.B }
})
}
})
class WithTraceGenSuccess extends OverrideHarnessBinder({
(system: TraceGenSystemModuleImp, th: BaseModule with HasHarnessSignalReferences, ports: Seq[Bool]) => {
ports.map { p => when (p) { th.success := true.B } }
Nil
}
})
class WithSimDromajoBridge extends ComposeHarnessBinder({
(system: CanHaveTraceIOModuleImp, th: BaseModule with HasHarnessSignalReferences, ports: Seq[TraceOutputTop]) => {
ports.map { p => p.traces.map(tileTrace => SimDromajoBridge(tileTrace)(system.p)) }
Nil
}
})

View File

@@ -1,12 +1,13 @@
package chipyard package chipyard.iobinders
package object iobinders {
import chisel3._ import chisel3._
import chisel3.experimental.{Analog, IO} import chisel3.util.experimental.{BoringUtils}
import chisel3.experimental.{Analog, IO, DataMirror}
import freechips.rocketchip.config.{Field, Config, Parameters} import freechips.rocketchip.config._
import freechips.rocketchip.diplomacy.{LazyModule, LazyModuleImpLike} import freechips.rocketchip.diplomacy.{LazyModule, LazyModuleImpLike}
import freechips.rocketchip.devices.debug._ import freechips.rocketchip.devices.debug._
import freechips.rocketchip.jtag.{JTAGIO}
import freechips.rocketchip.subsystem._ import freechips.rocketchip.subsystem._
import freechips.rocketchip.system.{SimAXIMem} import freechips.rocketchip.system.{SimAXIMem}
import freechips.rocketchip.amba.axi4.{AXI4Bundle, AXI4SlaveNode, AXI4MasterNode, AXI4EdgeParameters} import freechips.rocketchip.amba.axi4.{AXI4Bundle, AXI4SlaveNode, AXI4MasterNode, AXI4EdgeParameters}
@@ -21,7 +22,9 @@ import tracegen.{TraceGenSystemModuleImp}
import barstools.iocell.chisel._ import barstools.iocell.chisel._
import testchipip._ import testchipip._
import icenet.{CanHavePeripheryIceNICModuleImp, SimNetwork, NicLoopback, NICKey} import icenet.{CanHavePeripheryIceNIC, SimNetwork, NicLoopback, NICKey, NICIOvonly}
import chipyard.GlobalResetSchemeKey
import scala.reflect.{ClassTag} import scala.reflect.{ClassTag}
@@ -37,20 +40,22 @@ import scala.reflect.{ClassTag}
// You can add your own binder by adding a new (key, fn) pair, typically by using // You can add your own binder by adding a new (key, fn) pair, typically by using
// the OverrideIOBinder or ComposeIOBinder macros // the OverrideIOBinder or ComposeIOBinder macros
case object IOBinders extends Field[Map[String, (Any) => (Seq[Data], Seq[IOCell])]](
Map[String, (Any) => (Seq[Data], Seq[IOCell])]().withDefaultValue((Any) => (Nil, Nil))
// DOC include start: IOBinders
// This type describes a function callable on the TestHarness instance. Its return type is unused.
type TestHarnessFunction = (chipyard.HasHarnessSignalReferences) => Seq[Any]
// IOBinders will return a Seq of this tuple, which contains three fields:
// 1. A Seq containing all IO ports created by the IOBinder function
// 2. A Seq containing all IO cell modules created by the IOBinder function
// 3. An optional function to call inside the test harness (e.g. to connect the IOs)
type IOBinderTuple = (Seq[Data], Seq[IOCell], Option[TestHarnessFunction])
case object IOBinders extends Field[Map[String, (Any) => Seq[IOBinderTuple]]](
Map[String, (Any) => Seq[IOBinderTuple]]().withDefaultValue((Any) => Nil)
) )
object ApplyIOBinders {
def apply(sys: LazyModule, map: Map[String, (Any) => (Seq[Data], Seq[IOCell])]):
(Iterable[Data], Iterable[IOCell], Map[String, Seq[Data]]) = {
val lzy = map.map({ case (s,f) => s -> f(sys) })
val imp = map.map({ case (s,f) => s -> f(sys.module) })
val unzipped = (lzy.values ++ imp.values).unzip
val ports: Iterable[Data] = unzipped._1.flatten
val cells: Iterable[IOCell] = unzipped._2.flatten
val portMap: Map[String, Seq[Data]] = map.keys.map(k => k -> (lzy(k)._1 ++ imp(k)._1)).toMap
(ports, cells, portMap)
}
}
// Note: The parameters instance is accessible only through LazyModule // Note: The parameters instance is accessible only through LazyModule
// or LazyModuleImpLike. The self-type requirement in traits like // or LazyModuleImpLike. The self-type requirement in traits like
@@ -67,47 +72,55 @@ object GetSystemParameters {
} }
} }
// This macro overrides previous matches on some Top mixin. This is useful for class IOBinder[T, S <: Data](composer: (Any => (Seq[Data], Seq[IOCell])) => T => (Seq[Data], Seq[IOCell]))(implicit tag: ClassTag[T]) extends Config((site, here, up) => {
// binders which drive IO, since those typically cannot be composed
class OverrideIOBinder[T](fn: => (T) => Seq[IOBinderTuple])(implicit tag: ClassTag[T]) extends Config((site, here, up) => {
case IOBinders => up(IOBinders, site) + (tag.runtimeClass.toString -> case IOBinders => up(IOBinders, site) + (tag.runtimeClass.toString ->
((t: Any) => { ((t: Any) => {
val upfn = up(IOBinders, site)(tag.runtimeClass.toString)
t match { t match {
case system: T => fn(system) case system: T => composer(upfn)(system)
case _ => Nil case _ => (Nil, Nil)
} }
}) })
) )
}) })
// This macro overrides previous matches on some Top mixin. This is useful for
// binders which drive IO, since those typically cannot be composed
class OverrideIOBinder[T, S <: Data](fn: => (T) => (Seq[S], Seq[IOCell]))(implicit tag: ClassTag[T]) extends IOBinder[T, S](upfn => fn)
// This macro composes with previous matches on some Top mixin. This is useful for // This macro composes with previous matches on some Top mixin. This is useful for
// annotation-like binders, since those can typically be composed // annotation-like binders, since those can typically be composed
class ComposeIOBinder[T](fn: => (T) => Seq[IOBinderTuple])(implicit tag: ClassTag[T]) extends Config((site, here, up) => { class ComposeIOBinder[T, S <: Data](fn: => (T) => (Seq[S], Seq[IOCell]))(implicit tag: ClassTag[T]) extends IOBinder[T, S](upfn => t => {
case IOBinders => up(IOBinders, site) + (tag.runtimeClass.toString -> val r = upfn(t)
((t: Any) => { val h = fn(t)
t match { (r._1 ++ h._1, r._2 ++ h._2)
case system: T => (up(IOBinders, site)(tag.runtimeClass.toString)(system)
++ fn(system))
case _ => Nil
}
})
)
}) })
// DOC include end: IOBinders
object AddIOCells { object BoreHelper {
/** def apply(name: String, source: Clock): Clock = {
* Add IO cells to a SiFive GPIO devices and name the IO ports. val clock_io = IO(Output(Clock())).suggestName(name)
* @param gpios A Seq of GPIO port bundles val clock_wire = Wire(Clock()).suggestName(s"chiptop_${name}")
* @param genFn A callable function to generate a DigitalGPIOCell module to use dontTouch(clock_wire)
* @return Returns a tuple of (a 2D Seq of Analog IOs corresponding to individual GPIO pins; a 2D Seq of IOCell module references) clock_wire := false.B.asClock // necessary for BoringUtils to work properly
*/ BoringUtils.bore(source, Seq(clock_wire))
def gpio(gpios: Seq[GPIOPortIO], genFn: () => DigitalGPIOCell = IOCell.genericGPIO): (Seq[Seq[Analog]], Seq[Seq[IOCell]]) = { clock_io := clock_wire
gpios.zipWithIndex.map({ case (gpio, i) => clock_io
}
}
case object IOCellKey extends Field[IOCellTypeParams](GenericIOCellParams())
class WithGPIOCells extends OverrideIOBinder({
(system: HasPeripheryGPIOModuleImp) => {
val (ports2d, cells2d) = system.gpio.zipWithIndex.map({ case (gpio, i) =>
gpio.pins.zipWithIndex.map({ case (pin, j) => gpio.pins.zipWithIndex.map({ case (pin, j) =>
val g = IO(Analog(1.W)).suggestName(s"gpio_${i}_${j}") val g = IO(Analog(1.W)).suggestName(s"gpio_${i}_${j}")
val iocell = genFn().suggestName(s"iocell_gpio_${i}_${j}") val iocell = system.p(IOCellKey).gpio().suggestName(s"iocell_gpio_${i}_${j}")
iocell.io.o := pin.o.oval iocell.io.o := pin.o.oval
iocell.io.oe := pin.o.oe iocell.io.oe := pin.o.oe
iocell.io.ie := pin.o.ie iocell.io.ie := pin.o.ie
@@ -116,40 +129,37 @@ object AddIOCells {
(g, iocell) (g, iocell)
}).unzip }).unzip
}).unzip }).unzip
val ports: Seq[Analog] = ports2d.flatten
(ports, cells2d.flatten)
} }
})
/** // DOC include start: WithUARTIOCells
* Add IO cells to a SiFive UART devices and name the IO ports. class WithUARTIOCells extends OverrideIOBinder({
* @param uartPins A Seq of UART port bundles (system: HasPeripheryUARTModuleImp) => {
* @return Returns a tuple of (A Seq of top-level UARTPortIO IOs; a 2D Seq of IOCell module references) val (ports: Seq[UARTPortIO], cells2d) = system.uart.zipWithIndex.map({ case (u, i) =>
*/ val (port, ios) = IOCell.generateIOFromSignal(u, s"uart_${i}", system.p(IOCellKey))
def uart(uartPins: Seq[UARTPortIO]): (Seq[UARTPortIO], Seq[Seq[IOCell]]) = {
uartPins.zipWithIndex.map({ case (u, i) =>
val (port, ios) = IOCell.generateIOFromSignal(u, Some(s"iocell_uart_${i}"))
port.suggestName(s"uart_${i}")
(port, ios) (port, ios)
}).unzip }).unzip
(ports, cells2d.flatten)
} }
})
// DOC include end: WithUARTIOCells
/** class WithSPIIOCells extends OverrideIOBinder({
* Add IO cells to a SiFive SPI devices and name the IO ports. (system: HasPeripherySPIFlashModuleImp) => {
* @param spiPins A Seq of SPI port bundles val (ports: Seq[SPIChipIO], cells2d) = system.qspi.zipWithIndex.map({ case (s, i) =>
* @param basename The base name for this port (defaults to "spi") val name = s"spi_${i}"
* @param genFn A callable function to generate a DigitalGPIOCell module to use val port = IO(new SPIChipIO(s.c.csWidth)).suggestName(name)
* @return Returns a tuple of (A Seq of top-level SPIChipIO IOs; a 2D Seq of IOCell module references) val iocellBase = s"iocell_${name}"
*/
def spi(spiPins: Seq[SPIPortIO], basename: String = "spi", genFn: () => DigitalGPIOCell = IOCell.genericGPIO): (Seq[SPIChipIO], Seq[Seq[IOCell]]) = {
spiPins.zipWithIndex.map({ case (s, i) =>
val port = IO(new SPIChipIO(s.c.csWidth)).suggestName(s"${basename}_${i}")
val iocellBase = s"iocell_${basename}_${i}"
// SCK and CS are unidirectional outputs // SCK and CS are unidirectional outputs
val sckIOs = IOCell.generateFromSignal(s.sck, port.sck, Some(s"${iocellBase}_sck")) val sckIOs = IOCell.generateFromSignal(s.sck, port.sck, Some(s"${iocellBase}_sck"), system.p(IOCellKey))
val csIOs = IOCell.generateFromSignal(s.cs, port.cs, Some(s"${iocellBase}_cs")) val csIOs = IOCell.generateFromSignal(s.cs, port.cs, Some(s"${iocellBase}_cs"), system.p(IOCellKey))
// DQ are bidirectional, so then need special treatment // DQ are bidirectional, so then need special treatment
val dqIOs = s.dq.zip(port.dq).zipWithIndex.map { case ((pin, ana), j) => val dqIOs = s.dq.zip(port.dq).zipWithIndex.map { case ((pin, ana), j) =>
val iocell = genFn().suggestName(s"${iocellBase}_dq_${j}") val iocell = system.p(IOCellKey).gpio().suggestName(s"${iocellBase}_dq_${j}")
iocell.io.o := pin.o iocell.io.o := pin.o
iocell.io.oe := pin.oe iocell.io.oe := pin.oe
iocell.io.ie := true.B iocell.io.ie := true.B
@@ -160,285 +170,162 @@ object AddIOCells {
(port, dqIOs ++ csIOs ++ sckIOs) (port, dqIOs ++ csIOs ++ sckIOs)
}).unzip }).unzip
} (ports, cells2d.flatten)
/**
* Add IO cells to a debug module and name the IO ports.
* @param psd A PSDIO bundle
* @param resetctrlOpt An optional ResetCtrlIO bundle
* @param debugOpt An optional DebugIO bundle
* @return Returns a tuple3 of (Top-level PSDIO IO; Optional top-level DebugIO IO; a list of IOCell module references)
*/
def debug(psd: PSDIO, resetctrlOpt: Option[ResetCtrlIO], debugOpt: Option[DebugIO])(implicit p: Parameters):
(PSDIO, Option[ResetCtrlIO], Option[DebugIO], Seq[IOCell]) = {
val (psdPort, psdIOs) = IOCell.generateIOFromSignal(
psd, Some("iocell_psd"), abstractResetAsAsync = p(GlobalResetSchemeKey).pinIsAsync)
val debugTuple = debugOpt.map(d =>
IOCell.generateIOFromSignal(d, Some("iocell_debug"), abstractResetAsAsync = p(GlobalResetSchemeKey).pinIsAsync))
val debugPortOpt: Option[DebugIO] = debugTuple.map(_._1)
val debugIOs: Seq[IOCell] = debugTuple.map(_._2).toSeq.flatten
debugPortOpt.foreach(_.suggestName("debug"))
val resetctrlTuple = resetctrlOpt.map(d =>
IOCell.generateIOFromSignal(d, Some("iocell_resetctrl"), abstractResetAsAsync = p(GlobalResetSchemeKey).pinIsAsync))
val resetctrlPortOpt: Option[ResetCtrlIO] = resetctrlTuple.map(_._1)
val resetctrlIOs: Seq[IOCell] = resetctrlTuple.map(_._2).toSeq.flatten
resetctrlPortOpt.foreach(_.suggestName("resetctrl"))
psdPort.suggestName("psd")
(psdPort, resetctrlPortOpt, debugPortOpt, psdIOs ++ debugIOs ++ resetctrlIOs)
}
/**
* Add IO cells to a serial module and name the IO ports.
* @param serial A SerialIO bundle
* @return Returns a tuple of (Top-level SerialIO IO; a list of IOCell module references)
*/
def serial(serial: SerialIO): (SerialIO, Seq[IOCell]) = {
val (port, ios) = IOCell.generateIOFromSignal(serial, Some("iocell_serial"))
port.suggestName("serial")
(port, ios)
}
def axi4(io: Seq[AXI4Bundle], node: AXI4SlaveNode, name: String): Seq[(AXI4Bundle, AXI4EdgeParameters, Seq[IOCell])] = {
io.zip(node.edges.in).zipWithIndex.map{ case ((mem_axi4, edge), i) => {
val (port, ios) = IOCell.generateIOFromSignal(mem_axi4, Some(s"iocell_${name}_axi4_slave_${i}"))
port.suggestName(s"${name}_axi4_slave_${i}")
(port, edge, ios)
}}
}
def axi4(io: Seq[AXI4Bundle], node: AXI4MasterNode, name: String): Seq[(AXI4Bundle, AXI4EdgeParameters, Seq[IOCell])] = {
io.zip(node.edges.out).zipWithIndex.map{ case ((mem_axi4, edge), i) => {
//val (port, ios) = IOCell.generateIOFromSignal(mem_axi4, Some(s"iocell_${name}_axi4_master_${i}"))
val port = IO(Flipped(AXI4Bundle(edge.bundle)))
val ios = IOCell.generateFromSignal(mem_axi4, port, Some(s"iocell_${name}_axi4_master_${i}"))
port.suggestName(s"${name}_axi4_master_${i}")
(port, edge, ios)
}}
}
def blockDev(bdev: BlockDeviceIO): (BlockDeviceIO, Seq[IOCell]) = {
val (port, ios) = IOCell.generateIOFromSignal(bdev, Some("iocell_bdev"))
port.suggestName("bdev")
(port, ios)
}
}
// DOC include start: WithGPIOTiedOff
class WithGPIOTiedOff extends OverrideIOBinder({
(system: HasPeripheryGPIOModuleImp) => {
val (ports2d, ioCells2d) = AddIOCells.gpio(system.gpio)
val harnessFn = (th: HasHarnessSignalReferences) => { ports2d.flatten.foreach(_ <> AnalogConst(0)); Nil }
Seq((ports2d.flatten, ioCells2d.flatten, Some(harnessFn)))
}
})
// DOC include end: WithGPIOTiedOff
class WithUARTAdapter extends OverrideIOBinder({
(system: HasPeripheryUARTModuleImp) => {
val (ports, ioCells2d) = AddIOCells.uart(system.uart)
val harnessFn = (th: HasHarnessSignalReferences) => { UARTAdapter.connect(ports)(system.p); Nil }
Seq((ports, ioCells2d.flatten, Some(harnessFn)))
} }
}) })
class WithSimSPIFlashModel(rdOnly: Boolean = true) extends OverrideIOBinder({ class WithExtInterruptIOCells extends OverrideIOBinder({
(system: HasPeripherySPIFlashModuleImp) => { (system: HasExtInterruptsModuleImp) => {
val (ports, ioCells2d) = AddIOCells.spi(system.qspi, "qspi") if (system.outer.nExtInterrupts > 0) {
val harnessFn = (th: HasHarnessSignalReferences) => { SimSPIFlashModel.connect(ports, th.harnessReset, rdOnly)(system.p); Nil } val (port: UInt, cells) = IOCell.generateIOFromSignal(system.interrupts, "ext_interrupts", system.p(IOCellKey))
Seq((ports, ioCells2d.flatten, Some(harnessFn))) (Seq(port), cells)
} } else {
}) (Nil, Nil)
class WithSimBlockDevice extends OverrideIOBinder({
(system: CanHavePeripheryBlockDeviceModuleImp) => system.bdev.map { bdev =>
val (port, ios) = AddIOCells.blockDev(bdev)
val harnessFn = (th: HasHarnessSignalReferences) => {
// TODO: Using harness clock/reset will be incorrect when systemClock =/= harnessClock
SimBlockDevice.connect(th.harnessClock, th.harnessReset.asBool, Some(port))(system.p)
Nil
} }
Seq((Seq(port), ios, Some(harnessFn))) }
}.getOrElse(Nil)
}) })
class WithBlockDeviceModel extends OverrideIOBinder({
(system: CanHavePeripheryBlockDeviceModuleImp) => system.bdev.map { bdev =>
val (port, ios) = AddIOCells.blockDev(bdev)
val harnessFn = (th: HasHarnessSignalReferences) => {
BlockDeviceModel.connect(Some(port))(system.p)
Nil
}
Seq((Seq(port), ios, Some(harnessFn)))
}.getOrElse(Nil)
})
class WithLoopbackNIC extends OverrideIOBinder({ class WithDebugIOCells extends OverrideIOBinder({
(system: CanHavePeripheryIceNICModuleImp) => system.connectNicLoopback(); Nil (system: HasPeripheryDebugModuleImp) => {
}) system.debug.map({ debug =>
val p = system.p
val tlbus = system.outer.asInstanceOf[BaseSubsystem].locateTLBusWrapper(p(ExportDebug).slaveWhere)
val debug_clock = Wire(Clock()).suggestName("debug_clock")
val debug_reset = Wire(Reset()).suggestName("debug_reset")
debug_clock := false.B.asClock // must provide default assignment to avoid firrtl unassigned error
debug_reset := false.B // must provide default assignment to avoid firrtl unassigned error
BoringUtils.bore(tlbus.module.clock, Seq(debug_clock))
BoringUtils.bore(tlbus.module.reset, Seq(debug_reset))
class WithSimNIC extends OverrideIOBinder({ // We never use the PSDIO, so tie it off on-chip
(system: CanHavePeripheryIceNICModuleImp) => system.connectSimNetwork(system.clock, system.reset.asBool); Nil system.psd.psd.foreach { _ <> 0.U.asTypeOf(new PSDTestMode) }
}) system.resetctrl.map { rcio => rcio.hartIsInReset.map { _ := debug_reset.asBool } }
system.debug.map { d =>
// DOC include start: WithSimAXIMem // Tie off extTrigger
class WithSimAXIMem extends OverrideIOBinder({ d.extTrigger.foreach { t =>
(system: CanHaveMasterAXI4MemPort) => { t.in.req := false.B
implicit val p: Parameters = GetSystemParameters(system) t.out.ack := t.out.req
val peiTuples = AddIOCells.axi4(system.mem_axi4, system.memAXI4Node, "mem") }
// TODO: we are inlining the connectMem method of SimAXIMem because // Tie off disableDebug
// it takes in a dut rather than seq of axi4 ports d.disableDebug.foreach { d => d := false.B }
val harnessFn = (th: HasHarnessSignalReferences) => { // Drive JTAG on-chip IOs
peiTuples.map { case (port, edge, ios) => d.systemjtag.map { j =>
val mem = LazyModule(new SimAXIMem(edge, size = p(ExtMem).get.master.size)) j.reset := debug_reset
Module(mem.module).suggestName("mem") j.mfr_id := system.p(JtagDTMKey).idcodeManufId.U(11.W)
mem.io_axi4.head <> port j.part_number := system.p(JtagDTMKey).idcodePartNum.U(16.W)
j.version := system.p(JtagDTMKey).idcodeVersion.U(4.W)
}
} }
Nil Debug.connectDebugClockAndReset(Some(debug), debug_clock)(system.p)
}
Seq((peiTuples.map(_._1), peiTuples.flatMap(_._3), Some(harnessFn)))
}
})
// DOC include end: WithSimAXIMem
class WithBlackBoxSimMem extends OverrideIOBinder({ // Add IOCells for the DMI/JTAG/APB ports
(system: CanHaveMasterAXI4MemPort) => { val dmiTuple = debug.clockeddmi.map { d =>
implicit val p: Parameters = GetSystemParameters(system) IOCell.generateIOFromSignal(d, "dmi", p(IOCellKey), abstractResetAsAsync = p(GlobalResetSchemeKey).pinIsAsync)
val peiTuples = AddIOCells.axi4(system.mem_axi4, system.memAXI4Node, "mem")
val harnessFn = (th: HasHarnessSignalReferences) => {
peiTuples.map { case (port, edge, ios) =>
val memSize = p(ExtMem).get.master.size
val lineSize = p(CacheBlockBytes)
val mem = Module(new SimDRAM(memSize, lineSize, edge.bundle))
mem.io.axi <> port
// TODO: Using harness clock/reset will be incorrect when systemClock =/= harnessClock
mem.io.clock := th.harnessClock
mem.io.reset := th.harnessReset
} }
Nil
} val jtagTuple = debug.systemjtag.map { j =>
Seq((peiTuples.map(_._1), peiTuples.flatMap(_._3), Some(harnessFn))) IOCell.generateIOFromSignal(j.jtag, "jtag", p(IOCellKey), abstractResetAsAsync = p(GlobalResetSchemeKey).pinIsAsync)
}
val apbTuple = debug.apb.map { a =>
IOCell.generateIOFromSignal(a, "apb", p(IOCellKey), abstractResetAsAsync = p(GlobalResetSchemeKey).pinIsAsync)
}
val allTuples = (dmiTuple ++ jtagTuple ++ apbTuple).toSeq
(allTuples.map(_._1).toSeq, allTuples.flatMap(_._2).toSeq)
}).getOrElse((Nil, Nil))
} }
}) })
class WithSimAXIMMIO extends OverrideIOBinder({ class WithSerialTLIOCells extends OverrideIOBinder({
(system: CanHavePeripheryTLSerial) => system.serial_tl.map({ s =>
val sys = system.asInstanceOf[BaseSubsystem]
val (port, cells) = IOCell.generateIOFromSignal(s.getWrappedValue, "serial_tl", sys.p(IOCellKey))
(Seq(port), cells)
}).getOrElse((Nil, Nil))
})
class WithAXI4MemPunchthrough extends OverrideIOBinder({
(system: CanHaveMasterAXI4MemPort) => {
val ports: Seq[ClockedIO[AXI4Bundle]] = system.mem_axi4.zipWithIndex.map({ case (m, i) =>
val p = IO(new ClockedIO(DataMirror.internal.chiselTypeClone[AXI4Bundle](m))).suggestName(s"axi4_mem_${i}")
p.bits <> m
p.clock := BoreHelper("axi4_mem_clock", system.asInstanceOf[BaseSubsystem].mbus.module.clock)
p
})
(ports, Nil)
}
})
class WithAXI4MMIOPunchthrough extends OverrideIOBinder({
(system: CanHaveMasterAXI4MMIOPort) => { (system: CanHaveMasterAXI4MMIOPort) => {
implicit val p: Parameters = GetSystemParameters(system) val ports: Seq[ClockedIO[AXI4Bundle]] = system.mmio_axi4.zipWithIndex.map({ case (m, i) =>
val peiTuples = AddIOCells.axi4(system.mmio_axi4, system.mmioAXI4Node, "mmio_mem") val p = IO(new ClockedIO(DataMirror.internal.chiselTypeClone[AXI4Bundle](m))).suggestName(s"axi4_mmio_${i}")
val harnessFn = (th: HasHarnessSignalReferences) => { p.bits <> m
peiTuples.zipWithIndex.map { case ((port, edge, ios), i) => p.clock := BoreHelper("axi4_mmio_clock", system.asInstanceOf[BaseSubsystem].mbus.module.clock)
val mmio_mem = LazyModule(new SimAXIMem(edge, size = 4096)) p
Module(mmio_mem.module).suggestName(s"mmio_mem_${i}") })
mmio_mem.io_axi4.head <> port (ports, Nil)
}
Nil
}
Seq((peiTuples.map(_._1), peiTuples.flatMap(_._3), Some(harnessFn)))
} }
}) })
class WithL2FBusAXI4Punchthrough extends OverrideIOBinder({
(system: CanHaveSlaveAXI4Port) => {
val ports: Seq[ClockedIO[AXI4Bundle]] = system.l2_frontend_bus_axi4.zipWithIndex.map({ case (m, i) =>
val p = IO(new ClockedIO(Flipped(DataMirror.internal.chiselTypeClone[AXI4Bundle](m)))).suggestName(s"axi4_fbus_${i}")
m <> p.bits
p.clock := BoreHelper("axi4_fbus_clock", system.asInstanceOf[BaseSubsystem].fbus.module.clock)
p
})
(ports, Nil)
}
})
class WithBlockDeviceIOPunchthrough extends OverrideIOBinder({
(system: CanHavePeripheryBlockDevice) => {
val ports: Seq[ClockedIO[BlockDeviceIO]] = system.bdev.map({ bdev =>
val p = IO(new ClockedIO(new BlockDeviceIO()(GetSystemParameters(system)))).suggestName("blockdev")
p <> bdev
p
}).toSeq
(ports, Nil)
}
})
class WithNICIOPunchthrough extends OverrideIOBinder({
(system: CanHavePeripheryIceNIC) => {
val ports: Seq[ClockedIO[NICIOvonly]] = system.icenicOpt.map({ n =>
val p = IO(new ClockedIO(new NICIOvonly)).suggestName("nic")
p <> n
p
}).toSeq
(ports, Nil)
}
})
class WithTraceGenSuccessPunchthrough extends OverrideIOBinder({
(system: TraceGenSystemModuleImp) => {
val success: Bool = IO(Output(Bool())).suggestName("success")
success := system.success
(Seq(success), Nil)
}
})
class WithTraceIOPunchthrough extends OverrideIOBinder({
(system: CanHaveTraceIOModuleImp) => {
val ports: Option[TraceOutputTop] = system.traceIO.map { t =>
val trace = IO(DataMirror.internal.chiselTypeClone[TraceOutputTop](t)).suggestName("trace")
trace <> t
trace
}
(ports.toSeq, Nil)
}
})
class WithDontTouchPorts extends OverrideIOBinder({ class WithDontTouchPorts extends OverrideIOBinder({
(system: DontTouch) => system.dontTouchPorts(); Nil (system: DontTouch) => system.dontTouchPorts(); (Nil, Nil)
}) })
class WithTieOffInterrupts extends OverrideIOBinder({
(system: HasExtInterruptsModuleImp) => {
val (port, ioCells) = IOCell.generateIOFromSignal(system.interrupts, Some("iocell_interrupts"))
port.suggestName("interrupts")
val harnessFn = (th: HasHarnessSignalReferences) => { port := 0.U; Nil }
Seq((Seq(port), ioCells, Some(harnessFn)))
}
})
class WithTieOffL2FBusAXI extends OverrideIOBinder({
(system: CanHaveSlaveAXI4Port) => {
val peiTuples = AddIOCells.axi4(system.l2_frontend_bus_axi4, system.l2FrontendAXI4Node, "l2_fbus")
val harnessFn = (th: HasHarnessSignalReferences) => {
peiTuples.zipWithIndex.map { case ((port, edge, ios), i) =>
port := DontCare // tieoff doesn't completely tie-off, for some reason
port.tieoff()
}
Nil
}
Seq((peiTuples.map(_._1), peiTuples.flatMap(_._3), Some(harnessFn)))
}
})
// TODO we need to rethink what "Tie-off-debug" means. The current system punches out
// excessive IOs.
class WithTiedOffDebug extends OverrideIOBinder({
(system: HasPeripheryDebugModuleImp) => {
val (psdPort, resetctrlOpt, debugPortOpt, ioCells) =
AddIOCells.debug(system.psd, system.resetctrl, system.debug)(system.p)
val harnessFn = (th: HasHarnessSignalReferences) => {
Debug.tieoffDebug(debugPortOpt, resetctrlOpt, Some(psdPort))(system.p)
// tieoffDebug doesn't actually tie everything off :/
debugPortOpt.foreach { d =>
d.clockeddmi.foreach({ cdmi => cdmi.dmi.req.bits := DontCare; cdmi.dmiClock := th.harnessClock })
d.dmactiveAck := DontCare
d.clock := th.harnessClock // TODO fix: This should be driven from within the chip
}
Nil
}
Seq((Seq(psdPort) ++ resetctrlOpt ++ debugPortOpt.toSeq, Nil, Some(harnessFn)))
}
})
// TODO we need to rethink what this does. The current system punches out excessive IOs.
// Some of the debug clock/reset should be driven from on-chip
class WithSimDebug extends OverrideIOBinder({
(system: HasPeripheryDebugModuleImp) => {
val (psdPort, resetctrlPortOpt, debugPortOpt, ioCells) =
AddIOCells.debug(system.psd, system.resetctrl, system.debug)(system.p)
val harnessFn = (th: HasHarnessSignalReferences) => {
val dtm_success = Wire(Bool())
Debug.connectDebug(debugPortOpt, resetctrlPortOpt, psdPort, th.harnessClock, th.harnessReset.asBool, dtm_success)(system.p)
when (dtm_success) { th.success := true.B }
th.dutReset := th.harnessReset.asBool | debugPortOpt.map { debug => AsyncResetReg(debug.ndreset).asBool }.getOrElse(false.B)
Nil
}
Seq((Seq(psdPort) ++ debugPortOpt.toSeq, ioCells, Some(harnessFn)))
}
})
class WithTiedOffSerial extends OverrideIOBinder({
(system: CanHavePeripherySerialModuleImp) => system.serial.map({ serial =>
val (port, ioCells) = AddIOCells.serial(serial)
val harnessFn = (th: HasHarnessSignalReferences) => {
SerialAdapter.tieoff(port)
Nil
}
Seq((Seq(port), ioCells, Some(harnessFn)))
}).getOrElse(Nil)
})
class WithSimSerial extends OverrideIOBinder({
(system: CanHavePeripherySerialModuleImp) => system.serial.map({ serial =>
val (port, ioCells) = AddIOCells.serial(serial)
val harnessFn = (th: HasHarnessSignalReferences) => {
val ser_success = SerialAdapter.connectSimSerial(port, th.harnessClock, th.harnessReset)
when (ser_success) { th.success := true.B }
Nil
}
Seq((Seq(port), ioCells, Some(harnessFn)))
}).getOrElse(Nil)
})
class WithTraceGenSuccessBinder extends OverrideIOBinder({
(system: TraceGenSystemModuleImp) => {
val (successPort, ioCells) = IOCell.generateIOFromSignal(system.success, Some("iocell_success"))
successPort.suggestName("success")
val harnessFn = (th: HasHarnessSignalReferences) => { when (successPort) { th.success := true.B }; Nil }
Seq((Seq(successPort), ioCells, Some(harnessFn)))
}
})
class WithSimDromajoBridge extends ComposeIOBinder({
(system: CanHaveTraceIOModuleImp) => {
system.traceIO match { case Some(t) => t.traces.map(tileTrace => SimDromajoBridge(tileTrace)(system.p)) }
Nil
}
})
} /* end package object */

View File

@@ -25,13 +25,13 @@ import freechips.rocketchip.amba.axi4._
import boom.common.{BoomTile} import boom.common.{BoomTile}
import testchipip.{DromajoHelper, CanHavePeripherySerial, SerialKey} import testchipip.{DromajoHelper, CanHavePeripheryTLSerial, SerialTLKey}
trait CanHaveHTIF { this: BaseSubsystem => trait CanHaveHTIF { this: BaseSubsystem =>
// Advertise HTIF if system can communicate with fesvr // Advertise HTIF if system can communicate with fesvr
if (this match { if (this match {
case _: CanHavePeripherySerial if p(SerialKey) => true case _: CanHavePeripheryTLSerial if p(SerialTLKey).nonEmpty => true
case _: HasPeripheryDebug if p(ExportDebug).protocols.nonEmpty => true case _: HasPeripheryDebug if p(ExportDebug).dmi => true
case _ => false case _ => false
}) { }) {
ResourceBinding { ResourceBinding {

View File

@@ -1,19 +1,22 @@
package chipyard package chipyard
import chisel3._ import chisel3._
import scala.collection.mutable.{ArrayBuffer}
import freechips.rocketchip.diplomacy.{LazyModule} import freechips.rocketchip.diplomacy.{LazyModule}
import freechips.rocketchip.config.{Field, Parameters} import freechips.rocketchip.config.{Field, Parameters}
import chipyard.iobinders.{TestHarnessFunction}
import chipyard.harness.{ApplyHarnessBinders, HarnessBinders}
// ------------------------------- // -------------------------------
// Chipyard Test Harness // Chipyard Test Harness
// ------------------------------- // -------------------------------
case object BuildTop extends Field[Parameters => LazyModule with HasTestHarnessFunctions]((p: Parameters) => new ChipTop()(p)) case object BuildTop extends Field[Parameters => LazyModule]((p: Parameters) => new ChipTop()(p))
trait HasTestHarnessFunctions { trait HasTestHarnessFunctions {
val harnessFunctions: Seq[TestHarnessFunction] val lazySystem: LazyModule
val harnessFunctions = ArrayBuffer.empty[HasHarnessSignalReferences => Seq[Any]]
val portMap = scala.collection.mutable.Map[String, Seq[Data]]()
} }
trait HasHarnessSignalReferences { trait HasHarnessSignalReferences {
@@ -28,8 +31,8 @@ class TestHarness(implicit val p: Parameters) extends Module with HasHarnessSign
val success = Output(Bool()) val success = Output(Bool())
}) })
val ldut = LazyModule(p(BuildTop)(p)).suggestName("chiptop") val lazyDut = LazyModule(p(BuildTop)(p)).suggestName("chiptop")
val dut = Module(ldut.module) val dut = Module(lazyDut.module)
io.success := false.B io.success := false.B
val harnessClock = clock val harnessClock = clock
@@ -39,7 +42,9 @@ class TestHarness(implicit val p: Parameters) extends Module with HasHarnessSign
// dutReset assignment can be overridden via a harnessFunction, but by default it is just reset // dutReset assignment can be overridden via a harnessFunction, but by default it is just reset
val dutReset = WireDefault(if (p(GlobalResetSchemeKey).pinIsAsync) reset.asAsyncReset else reset) val dutReset = WireDefault(if (p(GlobalResetSchemeKey).pinIsAsync) reset.asAsyncReset else reset)
ldut.harnessFunctions.foreach(_(this)) lazyDut match { case d: HasTestHarnessFunctions =>
d.harnessFunctions.foreach(_(this))
ApplyHarnessBinders(this, d.lazySystem, d.portMap.toMap)
}
} }

View File

@@ -92,8 +92,8 @@ class TestSuiteHelper
} }
if (coreParams.useCompressed) addSuites(env.map(if (xlen == 64) rv64uc else rv32uc)) if (coreParams.useCompressed) addSuites(env.map(if (xlen == 64) rv64uc else rv32uc))
val (rvi, rvu) = val (rvi, rvu) =
if (xlen == 64) ((if (vm) rv64i else rv64pi), rv64u) if (xlen == 64) ((if (vm) rv64i else rv64pi), (if (coreParams.mulDiv.isDefined) rv64u else List(rv64ui)))
else ((if (vm) rv32i else rv32pi), rv32u) else ((if (vm) rv32i else rv32pi), (if (coreParams.mulDiv.isDefined) rv32u else List(rv32ui)))
addSuites(rvi.map(_("p"))) addSuites(rvi.map(_("p")))
addSuites(rvu.map(_("p"))) addSuites(rvu.map(_("p")))

View File

@@ -0,0 +1,23 @@
// See LICENSE for license details.
package chipyard.clocking
import chisel3._
import chisel3.util._
class ClockDividerN(div: Int) extends BlackBox(Map("DIV" -> div)) with HasBlackBoxResource {
require(div > 0);
val io = IO(new Bundle {
val clk_out = Output(Clock())
val clk_in = Input(Clock())
})
addResource("/vsrc/ClockDividerN.sv")
}
object ClockDivideByN {
def apply(clockIn: Clock, div: Int): Clock = {
val clockDivider = Module(new ClockDividerN(div))
clockDivider.io.clk_in := clockIn
clockDivider.io.clk_out
}
}

View File

@@ -0,0 +1,70 @@
package chipyard.clocking
import chisel3._
import freechips.rocketchip.config.{Parameters}
import freechips.rocketchip.diplomacy._
import freechips.rocketchip.prci._
/**
* This sort of node can be used when it is a connectivity passthrough, but modifies
* the flow of parameters (which may result in changing the names of the underlying signals).
*/
class ClockGroupParameterModifier(
sourceFn: ClockGroupSourceParameters => ClockGroupSourceParameters = { m => m },
sinkFn: ClockGroupSinkParameters => ClockGroupSinkParameters = { s => s })(
implicit p: Parameters, v: ValName) extends LazyModule {
val node = ClockGroupAdapterNode(sourceFn, sinkFn)
lazy val module = new LazyRawModuleImp(this) {
(node.out zip node.in).map { case ((o, _), (i, _)) =>
(o.member.data zip i.member.data).foreach { case (oD, iD) => oD := iD }
}
}
}
/**
* Pushes the ClockGroup's name into each member's name field as a prefix. This is
* intended to be used before a ClockGroupAggregator so that sources from
* different aggregated ClockGroups can be disambiguated by their names.
*/
object ClockGroupNamePrefixer {
def apply()(implicit p: Parameters, valName: ValName): ClockGroupAdapterNode =
LazyModule(new ClockGroupParameterModifier(sinkFn = { s => s.copy(members = s.members.zipWithIndex.map { case (m, idx) =>
m.copy(name = m.name match {
// This matches what the chisel would do if the names were not modified
case Some(clockName) => Some(s"${s.name}_${clockName}")
case None => Some(s"${s.name}_${idx}")
})
})})).node
}
/**
* [Word from on high is that Strings are in...]
* Overrides the take field of all clocks in a group, by attempting to apply a
* series of assignment functions:
* (name: String) => freq-in-MHz: Option[Double]
* to each sink. Later functions that return non-empty values take priority.
* 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 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))
})
}
LazyModule(new ClockGroupParameterModifier(sinkFn = { s => s.copy(members = s.members.map(lookupFrequencyForName)) })).node
}
}

View File

@@ -0,0 +1,97 @@
package chipyard.clocking
import chisel3._
import freechips.rocketchip.config.{Parameters}
import freechips.rocketchip.diplomacy._
import freechips.rocketchip.prci._
import freechips.rocketchip.util.ElaborationArtefacts
import scala.collection.mutable
import scala.collection.immutable.ListMap
/**
* TODO: figure out how much division is acceptable in our simulators and redefine this.
*/
object FrequencyUtils {
def computeReferenceFrequencyMHz(
requestedOutputs: Seq[ClockParameters],
maximumAllowableDivisor: Int = 0xFFFF): ClockParameters = {
require(requestedOutputs.nonEmpty)
require(!requestedOutputs.contains(0.0))
val freqs = requestedOutputs.map(f => BigInt(Math.round(f.freqMHz * 1000 * 1000)))
val refFreq = freqs.reduce((a, b) => a * b / a.gcd(b)).toDouble / (1000 * 1000)
assert((refFreq / freqs.min.toDouble) < maximumAllowableDivisor.toDouble)
ClockParameters(refFreq)
}
}
class SimplePllConfiguration(name: String, val sinks: Seq[ClockSinkParameters]) {
val referenceFreqMHz = FrequencyUtils.computeReferenceFrequencyMHz(sinks.flatMap(_.take)).freqMHz
val sinkDividerMap = ListMap((sinks.map({s => (s, Math.round(referenceFreqMHz / s.take.get.freqMHz).toInt) })):_*)
private val preamble = s"""
|${name} Frequency Summary
| Input Reference Frequency: ${referenceFreqMHz} MHz\n""".stripMargin
private val outputSummaries = sinkDividerMap.map { case (sink, division) =>
val requested = sink.take.get.freqMHz
val actual = referenceFreqMHz / division.toDouble
s" Output clock ${sink.name.get}, requested: ${requested} MHz, actual: ${actual} MHz (division of ${division})"
}
val summaryString = preamble + outputSummaries.mkString("\n")
ElaborationArtefacts.add(s"${name}.freq-summary", summaryString)
println(summaryString)
}
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(FrequencyUtils.computeReferenceFrequencyMHz(u.head.members.flatMap(_.take)))) }
)
/**
* 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.
*/
class DividerOnlyClockGenerator(pllName: String)(implicit p: Parameters, valName: ValName) extends LazyModule {
val node = DividerOnlyClockGeneratorNode(pllName)
lazy val module = new 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)
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))
sinkB.reset := refClock.reset
}
}
}
object DividerOnlyClockGenerator {
def apply()(implicit p: Parameters, valName: ValName) = LazyModule(new DividerOnlyClockGenerator(valName.name)).node
}

View File

@@ -5,19 +5,46 @@ import freechips.rocketchip.config.{Config}
// -------------- // --------------
// Chipyard abstract ("base") configuration // Chipyard abstract ("base") configuration
// NOTE: This configuration is NOT INSTANTIABLE, as it defines a empty system with no tiles // NOTE: This configuration is NOT INSTANTIABLE, as it defines a empty system with no tiles
//
// The default set of IOBinders instantiate IOcells and ChipTop IOs for digital IO bundles.
// The default set of HarnessBinders instantiate TestHarness hardware for interacting with ChipTop IOs
// -------------- // --------------
class AbstractConfig extends Config( class AbstractConfig extends Config(
new chipyard.iobinders.WithUARTAdapter ++ // display UART with a SimUARTAdapter // The HarnessBinders control generation of hardware in the TestHarness
new chipyard.iobinders.WithTieOffInterrupts ++ // tie off top-level interrupts new chipyard.harness.WithUARTAdapter ++ // add UART adapter to display UART on stdout, if uart is present
new chipyard.iobinders.WithBlackBoxSimMem ++ // drive the master AXI4 memory with a blackbox DRAMSim model new chipyard.harness.WithBlackBoxSimMem ++ // add SimDRAM DRAM model for axi4 backing memory, if axi4 mem is enabled
new chipyard.iobinders.WithTiedOffDebug ++ // tie off debug (since we are using SimSerial for testing) new chipyard.harness.WithSimSerial ++ // add external serial-adapter and RAM
new chipyard.iobinders.WithSimSerial ++ // drive TSI with SimSerial for testing new chipyard.harness.WithSimDebug ++ // add SimJTAG or SimDTM adapters if debug module is enabled
new testchipip.WithTSI ++ // use testchipip serial offchip link 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
// 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
new chipyard.iobinders.WithAXI4MemPunchthrough ++
new chipyard.iobinders.WithAXI4MMIOPunchthrough ++
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.WithUARTIOCells ++
new chipyard.iobinders.WithSPIIOCells ++
new chipyard.iobinders.WithTraceIOPunchthrough ++
new chipyard.iobinders.WithExtInterruptIOCells ++
new testchipip.WithDefaultSerialTL ++ // use serialized tilelink port to external serialadapter/harnessRAM
new chipyard.config.WithBootROM ++ // use default bootrom new chipyard.config.WithBootROM ++ // use default bootrom
new chipyard.config.WithUART ++ // add a UART new chipyard.config.WithUART ++ // add a UART
new chipyard.config.WithL2TLBs(1024) ++ // use L2 TLBs 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.WithNoSubsystemDrivenClocks ++ // drive the subsystem diplomatic clocks from ChipTop instead of using implicit clocks
new chipyard.config.WithPeripheryBusFrequencyAsDefault ++ // Unspecified clocks will match the frequency specified by the pbus dtsFrequency parameter
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) new freechips.rocketchip.subsystem.WithNoMMIOPort ++ // no top-level MMIO master port (overrides default set in rocketchip)
new freechips.rocketchip.subsystem.WithNoSlavePort ++ // no top-level MMIO slave port (overrides default set in rocketchip) new freechips.rocketchip.subsystem.WithNoSlavePort ++ // no top-level MMIO slave port (overrides default set in rocketchip)
new freechips.rocketchip.subsystem.WithInclusiveCache ++ // use Sifive L2 cache new freechips.rocketchip.subsystem.WithInclusiveCache ++ // use Sifive L2 cache

View File

@@ -13,7 +13,7 @@ class ArianeConfig extends Config(
new chipyard.config.AbstractConfig) new chipyard.config.AbstractConfig)
class dmiArianeConfig extends Config( class dmiArianeConfig extends Config(
new chipyard.iobinders.WithTiedOffSerial ++ // Tie off the serial port, override default instantiation of SimSerial new chipyard.harness.WithSerialAdapterTiedOff ++ // Tie off the serial port, override default instantiation of SimSerial
new chipyard.iobinders.WithSimDebug ++ // add SimDebug and use it to drive simulation, override default tie-off debug new chipyard.config.WithDMIDTM ++ // have debug module expose a clocked DMI port
new ariane.WithNArianeCores(1) ++ // single Ariane core new ariane.WithNArianeCores(1) ++ // single Ariane core
new chipyard.config.AbstractConfig) new chipyard.config.AbstractConfig)

View File

@@ -33,13 +33,13 @@ class HwachaLargeBoomConfig extends Config(
new chipyard.config.AbstractConfig) new chipyard.config.AbstractConfig)
class LoopbackNICLargeBoomConfig extends Config( class LoopbackNICLargeBoomConfig extends Config(
new chipyard.iobinders.WithLoopbackNIC ++ // drive NIC IOs with loopback new chipyard.harness.WithLoopbackNIC ++ // drive NIC IOs with loopback
new icenet.WithIceNIC ++ // build a NIC new icenet.WithIceNIC ++ // build a NIC
new boom.common.WithNLargeBooms(1) ++ new boom.common.WithNLargeBooms(1) ++
new chipyard.config.AbstractConfig) new chipyard.config.AbstractConfig)
class DromajoBoomConfig extends Config( class DromajoBoomConfig extends Config(
new chipyard.iobinders.WithSimDromajoBridge ++ // attach Dromajo new chipyard.harness.WithSimDromajoBridge ++ // attach Dromajo
new chipyard.config.WithTraceIO ++ // enable the traceio new chipyard.config.WithTraceIO ++ // enable the traceio
new boom.common.WithNSmallBooms(1) ++ new boom.common.WithNSmallBooms(1) ++
new chipyard.config.AbstractConfig) new chipyard.config.AbstractConfig)

View File

@@ -12,29 +12,21 @@ class RocketConfig extends Config(
class HwachaRocketConfig extends Config( class HwachaRocketConfig extends Config(
new chipyard.config.WithHwachaTest ++ new chipyard.config.WithHwachaTest ++
new hwacha.DefaultHwachaConfig ++ // use Hwacha vector accelerator new hwacha.DefaultHwachaConfig ++ // use Hwacha vector accelerator
new freechips.rocketchip.subsystem.WithNBigCores(1) ++ new freechips.rocketchip.subsystem.WithNBigCores(1) ++
new chipyard.config.AbstractConfig) new chipyard.config.AbstractConfig)
// DOC include start: GemminiRocketConfig // DOC include start: GemminiRocketConfig
class GemminiRocketConfig extends Config( class GemminiRocketConfig extends Config(
new gemmini.DefaultGemminiConfig ++ // use Gemmini systolic array GEMM accelerator new gemmini.DefaultGemminiConfig ++ // use Gemmini systolic array GEMM accelerator
new freechips.rocketchip.subsystem.WithNBigCores(1) ++ new freechips.rocketchip.subsystem.WithNBigCores(1) ++
new chipyard.config.AbstractConfig) new chipyard.config.AbstractConfig)
// DOC include end: GemminiRocketConfig // DOC include end: GemminiRocketConfig
// DOC include start: JtagRocket
class jtagRocketConfig extends Config(
new chipyard.iobinders.WithSimDebug ++ // add SimDebug, in addition to default SimSerial
new freechips.rocketchip.subsystem.WithJtagDTM ++ // sets DTM communication interface to JTAG
new freechips.rocketchip.subsystem.WithNBigCores(1) ++
new chipyard.config.AbstractConfig)
// DOC include end: JtagRocket
// DOC include start: DmiRocket // DOC include start: DmiRocket
class dmiRocketConfig extends Config( class dmiRocketConfig extends Config(
new chipyard.iobinders.WithTiedOffSerial ++ // tie-off serial, override default add SimSerial new chipyard.harness.WithSerialAdapterTiedOff ++ // don't attach an external SimSerial
new chipyard.iobinders.WithSimDebug ++ // add SimDebug, override default tie-off debug new chipyard.config.WithDMIDTM ++ // have debug module expose a clocked DMI port
new freechips.rocketchip.subsystem.WithNBigCores(1) ++ new freechips.rocketchip.subsystem.WithNBigCores(1) ++
new chipyard.config.AbstractConfig) new chipyard.config.AbstractConfig)
// DOC include end: DmiRocket // DOC include end: DmiRocket
@@ -48,54 +40,53 @@ class GCDTLRocketConfig extends Config(
// DOC include start: GCDAXI4BlackBoxRocketConfig // DOC include start: GCDAXI4BlackBoxRocketConfig
class GCDAXI4BlackBoxRocketConfig extends Config( class GCDAXI4BlackBoxRocketConfig extends Config(
new chipyard.example.WithGCD(useAXI4=true, useBlackBox=true) ++ // Use GCD blackboxed verilog, connect by AXI4->Tilelink new chipyard.example.WithGCD(useAXI4=true, useBlackBox=true) ++ // Use GCD blackboxed verilog, connect by AXI4->Tilelink
new freechips.rocketchip.subsystem.WithNBigCores(1) ++ new freechips.rocketchip.subsystem.WithNBigCores(1) ++
new chipyard.config.AbstractConfig) new chipyard.config.AbstractConfig)
// DOC include end: GCDAXI4BlackBoxRocketConfig // DOC include end: GCDAXI4BlackBoxRocketConfig
class LargeSPIFlashROMRocketConfig extends Config( class LargeSPIFlashROMRocketConfig extends Config(
new chipyard.iobinders.WithSimSPIFlashModel(true) ++ // add the SPI flash model in the harness (read-only) new chipyard.harness.WithSimSPIFlashModel(true) ++ // add the SPI flash model in the harness (read-only)
new chipyard.config.WithSPIFlash ++ // add the SPI flash controller new chipyard.config.WithSPIFlash ++ // add the SPI flash controller
new freechips.rocketchip.subsystem.WithNBigCores(1) ++ new freechips.rocketchip.subsystem.WithNBigCores(1) ++
new chipyard.config.AbstractConfig) new chipyard.config.AbstractConfig)
class SmallSPIFlashRocketConfig extends Config( class SmallSPIFlashRocketConfig extends Config(
new chipyard.iobinders.WithSimSPIFlashModel(false) ++ // add the SPI flash model in the harness (writeable) new chipyard.harness.WithSimSPIFlashModel(false) ++ // add the SPI flash model in the harness (writeable)
new chipyard.config.WithSPIFlash(0x100000) ++ // add the SPI flash controller (1 MiB) new chipyard.config.WithSPIFlash(0x100000) ++ // add the SPI flash controller (1 MiB)
new freechips.rocketchip.subsystem.WithNBigCores(1) ++ new freechips.rocketchip.subsystem.WithNBigCores(1) ++
new chipyard.config.AbstractConfig) new chipyard.config.AbstractConfig)
class SimAXIRocketConfig extends Config( class SimAXIRocketConfig extends Config(
new chipyard.iobinders.WithSimAXIMem ++ // drive the master AXI4 memory with a SimAXIMem, a 1-cycle magic memory, instead of default SimDRAM 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) ++ new freechips.rocketchip.subsystem.WithNBigCores(1) ++
new chipyard.config.AbstractConfig) new chipyard.config.AbstractConfig)
class SimBlockDeviceRocketConfig extends Config( class SimBlockDeviceRocketConfig extends Config(
new chipyard.iobinders.WithSimBlockDevice ++ // drive block-device IOs with SimBlockDevice new chipyard.harness.WithSimBlockDevice ++ // drive block-device IOs with SimBlockDevice
new testchipip.WithBlockDevice ++ // add block-device module to peripherybus new testchipip.WithBlockDevice ++ // add block-device module to peripherybus
new freechips.rocketchip.subsystem.WithNBigCores(1) ++ new freechips.rocketchip.subsystem.WithNBigCores(1) ++
new chipyard.config.AbstractConfig) new chipyard.config.AbstractConfig)
class BlockDeviceModelRocketConfig extends Config( class BlockDeviceModelRocketConfig extends Config(
new chipyard.iobinders.WithBlockDeviceModel ++ // drive block-device IOs with a BlockDeviceModel new chipyard.harness.WithBlockDeviceModel ++ // drive block-device IOs with a BlockDeviceModel
new testchipip.WithBlockDevice ++ // add block-device module to periphery bus new testchipip.WithBlockDevice ++ // add block-device module to periphery bus
new freechips.rocketchip.subsystem.WithNBigCores(1) ++ new freechips.rocketchip.subsystem.WithNBigCores(1) ++
new chipyard.config.AbstractConfig) new chipyard.config.AbstractConfig)
// DOC include start: GPIORocketConfig // DOC include start: GPIORocketConfig
class GPIORocketConfig extends Config( class GPIORocketConfig extends Config(
new chipyard.iobinders.WithGPIOTiedOff ++ // tie off GPIO inputs into the top new chipyard.config.WithGPIO ++ // add GPIOs to the peripherybus
new chipyard.config.WithGPIO ++ // add GPIOs to the peripherybus
new freechips.rocketchip.subsystem.WithNBigCores(1) ++ new freechips.rocketchip.subsystem.WithNBigCores(1) ++
new chipyard.config.AbstractConfig) new chipyard.config.AbstractConfig)
// DOC include end: GPIORocketConfig // DOC include end: GPIORocketConfig
class QuadRocketConfig extends Config( class QuadRocketConfig extends Config(
new freechips.rocketchip.subsystem.WithNBigCores(4) ++ // quad-core (4 RocketTiles) new freechips.rocketchip.subsystem.WithNBigCores(4) ++ // quad-core (4 RocketTiles)
new chipyard.config.AbstractConfig) new chipyard.config.AbstractConfig)
class RV32RocketConfig extends Config( class RV32RocketConfig extends Config(
new freechips.rocketchip.subsystem.WithRV32 ++ // set RocketTiles to be 32-bit new freechips.rocketchip.subsystem.WithRV32 ++ // set RocketTiles to be 32-bit
new freechips.rocketchip.subsystem.WithNBigCores(1) ++ new freechips.rocketchip.subsystem.WithNBigCores(1) ++
new chipyard.config.AbstractConfig) new chipyard.config.AbstractConfig)
@@ -113,19 +104,20 @@ class Sha3RocketConfig extends Config(
// DOC include start: InitZeroRocketConfig // DOC include start: InitZeroRocketConfig
class InitZeroRocketConfig extends Config( class InitZeroRocketConfig extends Config(
new chipyard.example.WithInitZero(0x88000000L, 0x1000L) ++ // add InitZero new chipyard.example.WithInitZero(0x88000000L, 0x1000L) ++ // add InitZero
new freechips.rocketchip.subsystem.WithNBigCores(1) ++ new freechips.rocketchip.subsystem.WithNBigCores(1) ++
new chipyard.config.AbstractConfig) new chipyard.config.AbstractConfig)
// DOC include end: InitZeroRocketConfig // DOC include end: InitZeroRocketConfig
class LoopbackNICRocketConfig extends Config( class LoopbackNICRocketConfig extends Config(
new chipyard.iobinders.WithLoopbackNIC ++ // drive NIC IOs with loopback new chipyard.harness.WithLoopbackNIC ++ // drive NIC IOs with loopback
new icenet.WithIceNIC ++ // add an IceNIC new icenet.WithIceNIC ++ // add an IceNIC
new freechips.rocketchip.subsystem.WithNBigCores(1) ++ new freechips.rocketchip.subsystem.WithNBigCores(1) ++
new chipyard.config.AbstractConfig) new chipyard.config.AbstractConfig)
// DOC include start: l1scratchpadrocket // DOC include start: l1scratchpadrocket
class ScratchpadOnlyRocketConfig extends Config( class ScratchpadOnlyRocketConfig extends Config(
new testchipip.WithSerialPBusMem ++
new freechips.rocketchip.subsystem.WithNMemoryChannels(0) ++ // remove offchip mem port new freechips.rocketchip.subsystem.WithNMemoryChannels(0) ++ // remove offchip mem port
new freechips.rocketchip.subsystem.WithNBanks(0) ++ new freechips.rocketchip.subsystem.WithNBanks(0) ++
new freechips.rocketchip.subsystem.WithNoMemPort ++ new freechips.rocketchip.subsystem.WithNoMemPort ++
@@ -135,8 +127,8 @@ class ScratchpadOnlyRocketConfig extends Config(
// DOC include end: l1scratchpadrocket // DOC include end: l1scratchpadrocket
class L1ScratchpadRocketConfig extends Config( class L1ScratchpadRocketConfig extends Config(
new chipyard.config.WithRocketICacheScratchpad ++ // use rocket ICache scratchpad new chipyard.config.WithRocketICacheScratchpad ++ // use rocket ICache scratchpad
new chipyard.config.WithRocketDCacheScratchpad ++ // use rocket DCache scratchpad new chipyard.config.WithRocketDCacheScratchpad ++ // use rocket DCache scratchpad
new freechips.rocketchip.subsystem.WithNBigCores(1) ++ new freechips.rocketchip.subsystem.WithNBigCores(1) ++
new chipyard.config.AbstractConfig) new chipyard.config.AbstractConfig)
@@ -150,47 +142,47 @@ class MbusScratchpadRocketConfig extends Config(
// DOC include start: RingSystemBusRocket // DOC include start: RingSystemBusRocket
class RingSystemBusRocketConfig extends Config( class RingSystemBusRocketConfig extends Config(
new testchipip.WithRingSystemBus ++ // Ring-topology system bus new testchipip.WithRingSystemBus ++ // Ring-topology system bus
new freechips.rocketchip.subsystem.WithNBigCores(1) ++ new freechips.rocketchip.subsystem.WithNBigCores(1) ++
new chipyard.config.AbstractConfig) new chipyard.config.AbstractConfig)
// DOC include end: RingSystemBusRocket // DOC include end: RingSystemBusRocket
class StreamingPassthroughRocketConfig extends Config( class StreamingPassthroughRocketConfig extends Config(
new chipyard.example.WithStreamingPassthrough ++ // use top with tilelink-controlled streaming passthrough new chipyard.example.WithStreamingPassthrough ++ // use top with tilelink-controlled streaming passthrough
new freechips.rocketchip.subsystem.WithNBigCores(1) ++ new freechips.rocketchip.subsystem.WithNBigCores(1) ++
new chipyard.config.AbstractConfig) new chipyard.config.AbstractConfig)
// DOC include start: StreamingFIRRocketConfig // DOC include start: StreamingFIRRocketConfig
class StreamingFIRRocketConfig extends Config ( class StreamingFIRRocketConfig extends Config (
new chipyard.example.WithStreamingFIR ++ // use top with tilelink-controlled streaming FIR new chipyard.example.WithStreamingFIR ++ // use top with tilelink-controlled streaming FIR
new freechips.rocketchip.subsystem.WithNBigCores(1) ++ new freechips.rocketchip.subsystem.WithNBigCores(1) ++
new chipyard.config.AbstractConfig) new chipyard.config.AbstractConfig)
// DOC include end: StreamingFIRRocketConfig // DOC include end: StreamingFIRRocketConfig
class SmallNVDLARocketConfig extends Config( class SmallNVDLARocketConfig extends Config(
new nvidia.blocks.dla.WithNVDLA("small") ++ // add a small NVDLA new nvidia.blocks.dla.WithNVDLA("small") ++ // add a small NVDLA
new freechips.rocketchip.subsystem.WithNBigCores(1) ++ new freechips.rocketchip.subsystem.WithNBigCores(1) ++
new chipyard.config.AbstractConfig) new chipyard.config.AbstractConfig)
class LargeNVDLARocketConfig extends Config( class LargeNVDLARocketConfig extends Config(
new nvidia.blocks.dla.WithNVDLA("large", true) ++ // add a large NVDLA with synth. rams new nvidia.blocks.dla.WithNVDLA("large", true) ++ // add a large NVDLA with synth. rams
new freechips.rocketchip.subsystem.WithNBigCores(1) ++ new freechips.rocketchip.subsystem.WithNBigCores(1) ++
new chipyard.config.AbstractConfig) new chipyard.config.AbstractConfig)
class MMIORocketConfig extends Config( class MMIORocketConfig extends Config(
new chipyard.iobinders.WithTieOffL2FBusAXI ++ // Tie-off the incoming MMIO port new freechips.rocketchip.subsystem.WithDefaultMMIOPort ++ // add default external master port
new chipyard.iobinders.WithSimAXIMMIO ++ // Attach a simulated memory to the outwards MMIO port
new freechips.rocketchip.subsystem.WithDefaultMMIOPort ++ // add default external master port
new freechips.rocketchip.subsystem.WithDefaultSlavePort ++ // add default external slave port new freechips.rocketchip.subsystem.WithDefaultSlavePort ++ // add default external slave port
new freechips.rocketchip.subsystem.WithNBigCores(1) ++ new freechips.rocketchip.subsystem.WithNBigCores(1) ++
new chipyard.config.AbstractConfig) new chipyard.config.AbstractConfig)
// NOTE: This config doesn't work yet because SimWidgets in the TestHarness
// always get the TestHarness clock. The Tiles and Uncore receive the correct clocks
class DividedClockRocketConfig extends Config( class DividedClockRocketConfig extends Config(
new chipyard.config.WithTileDividedClock ++ // Put the Tile on its own clock domain new chipyard.config.WithTileFrequency(200.0) ++
new freechips.rocketchip.subsystem.WithRationalRocketTiles ++ // Add rational crossings between RocketTile and uncore new freechips.rocketchip.subsystem.WithRationalRocketTiles ++ // Add rational crossings between RocketTile and uncore
new freechips.rocketchip.subsystem.WithNBigCores(1) ++ new freechips.rocketchip.subsystem.WithNBigCores(1) ++
new chipyard.config.AbstractConfig) new chipyard.config.AbstractConfig)
class LBWIFRocketConfig extends Config(
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)

View File

@@ -0,0 +1,59 @@
package chipyard
import chisel3._
import freechips.rocketchip.config.{Config}
class Sodor1StageConfig extends Config(
// Create a Sodor 1-stage core
new sodor.common.WithNSodorCores(1, internalTile = sodor.common.Stage1Factory) ++
new testchipip.WithSerialPBusMem ++
new freechips.rocketchip.subsystem.WithScratchpadsOnly ++ // use sodor tile-internal scratchpad
new freechips.rocketchip.subsystem.WithNMemoryChannels(0) ++ // use no external memory
new freechips.rocketchip.subsystem.WithNBanks(0) ++
new chipyard.config.AbstractConfig)
class Sodor2StageConfig extends Config(
// Create a Sodor 2-stage core
new sodor.common.WithNSodorCores(1, internalTile = sodor.common.Stage2Factory) ++
new testchipip.WithSerialPBusMem ++
new freechips.rocketchip.subsystem.WithScratchpadsOnly ++ // use sodor tile-internal scratchpad
new freechips.rocketchip.subsystem.WithNMemoryChannels(0) ++ // use no external memory
new freechips.rocketchip.subsystem.WithNBanks(0) ++
new chipyard.config.AbstractConfig)
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.WithSerialPBusMem ++
new freechips.rocketchip.subsystem.WithScratchpadsOnly ++ // use sodor tile-internal scratchpad
new freechips.rocketchip.subsystem.WithNMemoryChannels(0) ++ // use no external memory
new freechips.rocketchip.subsystem.WithNBanks(0) ++
new chipyard.config.AbstractConfig)
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.WithSerialPBusMem ++
new freechips.rocketchip.subsystem.WithScratchpadsOnly ++ // use sodor tile-internal scratchpad
new freechips.rocketchip.subsystem.WithNMemoryChannels(0) ++ // use no external memory
new freechips.rocketchip.subsystem.WithNBanks(0) ++
new chipyard.config.AbstractConfig)
class Sodor5StageConfig extends Config(
// Create a Sodor 5-stage core
new sodor.common.WithNSodorCores(1, internalTile = sodor.common.Stage5Factory) ++
new testchipip.WithSerialPBusMem ++
new freechips.rocketchip.subsystem.WithScratchpadsOnly ++ // use sodor tile-internal scratchpad
new freechips.rocketchip.subsystem.WithNMemoryChannels(0) ++ // use no external memory
new freechips.rocketchip.subsystem.WithNBanks(0) ++
new chipyard.config.AbstractConfig)
class SodorUCodeConfig extends Config(
// Construct a Sodor microcode-based single-bus core
new sodor.common.WithNSodorCores(1, internalTile = sodor.common.UCodeFactory) ++
new testchipip.WithSerialPBusMem ++
new freechips.rocketchip.subsystem.WithScratchpadsOnly ++ // use sodor tile-internal scratchpad
new freechips.rocketchip.subsystem.WithNMemoryChannels(0) ++ // use no external memory
new freechips.rocketchip.subsystem.WithNBanks(0) ++
new chipyard.config.AbstractConfig)

View File

@@ -3,51 +3,38 @@ package chipyard
import freechips.rocketchip.config.{Config} import freechips.rocketchip.config.{Config}
import freechips.rocketchip.rocket.{DCacheParams} import freechips.rocketchip.rocket.{DCacheParams}
class TraceGenConfig extends Config( class AbstractTraceGenConfig extends Config(
new chipyard.iobinders.WithBlackBoxSimMem ++ new chipyard.harness.WithBlackBoxSimMem ++
new chipyard.iobinders.WithTraceGenSuccessBinder ++ new chipyard.harness.WithTraceGenSuccess ++
new chipyard.iobinders.WithAXI4MemPunchthrough ++
new chipyard.iobinders.WithTraceGenSuccessPunchthrough ++
new chipyard.config.WithTracegenSystem ++ new chipyard.config.WithTracegenSystem ++
new chipyard.config.WithNoSubsystemDrivenClocks ++ new chipyard.config.WithNoSubsystemDrivenClocks ++
new tracegen.WithTraceGen()(List.fill(2) { DCacheParams(nMSHRs = 0, nSets = 16, nWays = 2) }) ++ new chipyard.config.WithPeripheryBusFrequencyAsDefault ++
new freechips.rocketchip.subsystem.WithCoherentBusTopology ++ new freechips.rocketchip.subsystem.WithCoherentBusTopology ++
new freechips.rocketchip.groundtest.GroundTestBaseConfig) new freechips.rocketchip.groundtest.GroundTestBaseConfig)
class TraceGenConfig extends Config(
new tracegen.WithTraceGen()(List.fill(2) { DCacheParams(nMSHRs = 0, nSets = 16, nWays = 2) }) ++
new AbstractTraceGenConfig)
class NonBlockingTraceGenConfig extends Config( class NonBlockingTraceGenConfig extends Config(
new chipyard.iobinders.WithBlackBoxSimMem ++
new chipyard.iobinders.WithTraceGenSuccessBinder ++
new chipyard.config.WithTracegenSystem ++
new chipyard.config.WithNoSubsystemDrivenClocks ++
new tracegen.WithTraceGen()(List.fill(2) { DCacheParams(nMSHRs = 2, nSets = 16, nWays = 2) }) ++ new tracegen.WithTraceGen()(List.fill(2) { DCacheParams(nMSHRs = 2, nSets = 16, nWays = 2) }) ++
new freechips.rocketchip.subsystem.WithCoherentBusTopology ++ new AbstractTraceGenConfig)
new freechips.rocketchip.groundtest.GroundTestBaseConfig)
class BoomTraceGenConfig extends Config( class BoomTraceGenConfig extends Config(
new chipyard.iobinders.WithBlackBoxSimMem ++
new chipyard.iobinders.WithTraceGenSuccessBinder ++
new chipyard.config.WithTracegenSystem ++
new chipyard.config.WithNoSubsystemDrivenClocks ++
new tracegen.WithBoomTraceGen()(List.fill(2) { DCacheParams(nMSHRs = 8, nSets = 16, nWays = 2) }) ++ new tracegen.WithBoomTraceGen()(List.fill(2) { DCacheParams(nMSHRs = 8, nSets = 16, nWays = 2) }) ++
new freechips.rocketchip.subsystem.WithInclusiveCache ++ new freechips.rocketchip.subsystem.WithInclusiveCache ++
new freechips.rocketchip.subsystem.WithCoherentBusTopology ++ new AbstractTraceGenConfig)
new freechips.rocketchip.groundtest.GroundTestBaseConfig)
class NonBlockingTraceGenL2Config extends Config( class NonBlockingTraceGenL2Config extends Config(
new chipyard.iobinders.WithBlackBoxSimMem ++
new chipyard.iobinders.WithTraceGenSuccessBinder ++
new chipyard.config.WithTracegenSystem ++
new chipyard.config.WithNoSubsystemDrivenClocks ++
new tracegen.WithL2TraceGen()(List.fill(2)(DCacheParams(nMSHRs = 2, nSets = 16, nWays = 4))) ++ new tracegen.WithL2TraceGen()(List.fill(2)(DCacheParams(nMSHRs = 2, nSets = 16, nWays = 4))) ++
new freechips.rocketchip.subsystem.WithInclusiveCache ++ new freechips.rocketchip.subsystem.WithInclusiveCache ++
new freechips.rocketchip.subsystem.WithCoherentBusTopology ++ new AbstractTraceGenConfig)
new freechips.rocketchip.groundtest.GroundTestBaseConfig)
class NonBlockingTraceGenL2RingConfig extends Config( class NonBlockingTraceGenL2RingConfig extends Config(
new chipyard.iobinders.WithBlackBoxSimMem ++
new chipyard.iobinders.WithTraceGenSuccessBinder ++
new chipyard.config.WithTracegenSystem ++
new chipyard.config.WithNoSubsystemDrivenClocks ++
new tracegen.WithL2TraceGen()(List.fill(2)(DCacheParams(nMSHRs = 2, nSets = 16, nWays = 4))) ++ new tracegen.WithL2TraceGen()(List.fill(2)(DCacheParams(nMSHRs = 2, nSets = 16, nWays = 4))) ++
new testchipip.WithRingSystemBus ++ new testchipip.WithRingSystemBus ++
new freechips.rocketchip.subsystem.WithInclusiveCache ++ new freechips.rocketchip.subsystem.WithInclusiveCache ++
new freechips.rocketchip.subsystem.WithCoherentBusTopology ++ new AbstractTraceGenConfig)
new freechips.rocketchip.groundtest.GroundTestBaseConfig)

View File

@@ -12,27 +12,16 @@ import freechips.rocketchip.config.{Config}
// This file was originally developed for the cancelled ASPLOS-2020 // This file was originally developed for the cancelled ASPLOS-2020
// Chipyard tutorial. While the configs here work, the corresponding // Chipyard tutorial. While the configs here work, the corresponding
// slideware has not yet been created // slideware has not yet been created.
// NOTE: Configs should be read bottom-up, since they are applied bottom-up // NOTE: Configs should be read bottom-up, since they are applied bottom-up
// NOTE: The TutorialConfigs build off of the AbstractConfig defined in AbstractConfig.scala
// Users should try to understand the functionality of the AbstractConfig before proceeding
// with the TutorialConfigs below
// Tutorial Phase 1: Configure the cores, caches // Tutorial Phase 1: Configure the cores, caches
class TutorialStarterConfig extends Config( class TutorialStarterConfig extends Config(
// IOBinders specify how to connect to IOs in our TestHarness
// These config fragments do not affect
new chipyard.iobinders.WithUARTAdapter ++ // Connect a SimUART adapter to display UART on stdout
new chipyard.iobinders.WithBlackBoxSimMem ++ // Connect simulated external memory
new chipyard.iobinders.WithTieOffInterrupts ++ // Do not simulate external interrupts
new chipyard.iobinders.WithTiedOffDebug ++ // Disconnect the debug module, since we use TSI for bring-up
new chipyard.iobinders.WithSimSerial ++ // Connect external SimSerial widget to drive TSI
// Config fragments below this line affect hardware generation
// of the Top
new testchipip.WithTSI ++ // Add a TSI (Test Serial Interface) widget to bring-up the core
new chipyard.config.WithBootROM ++ // Use the Chipyard BootROM
new chipyard.config.WithUART ++ // Add a UART
new chipyard.config.WithNoSubsystemDrivenClocks ++ // Don't drive the subsystem clocks from within the subsystem
// CUSTOMIZE THE CORE // CUSTOMIZE THE CORE
// Uncomment out one (or multiple) of the lines below, and choose // Uncomment out one (or multiple) of the lines below, and choose
// how many cores you want. // how many cores you want.
@@ -43,30 +32,11 @@ class TutorialStarterConfig extends Config(
// Uncomment this line, and specify a size if you want to have a L2 // Uncomment this line, and specify a size if you want to have a L2
// new freechips.rocketchip.subsystem.WithInclusiveCache(nBanks=1, nWays=4, capacityKB=128) ++ // new freechips.rocketchip.subsystem.WithInclusiveCache(nBanks=1, nWays=4, capacityKB=128) ++
// For simpler designs, we want to minimize IOs on new chipyard.config.AbstractConfig
// our Top. These config fragments remove unnecessary
// ports
new freechips.rocketchip.subsystem.WithNoMMIOPort ++
new freechips.rocketchip.subsystem.WithNoSlavePort ++
new freechips.rocketchip.subsystem.WithNExtTopInterrupts(0) ++
new freechips.rocketchip.subsystem.WithCoherentBusTopology ++ // hierarchical buses including mbus+l2
// BaseConfig configures "bare" rocketchip system
new freechips.rocketchip.system.BaseConfig
) )
// Tutorial Phase 2: Integrate a TileLink or AXI4 MMIO device // Tutorial Phase 2: Integrate a TileLink or AXI4 MMIO device
class TutorialMMIOConfig extends Config( class TutorialMMIOConfig extends Config(
new chipyard.iobinders.WithUARTAdapter ++
new chipyard.iobinders.WithBlackBoxSimMem ++
new chipyard.iobinders.WithTieOffInterrupts ++
new chipyard.iobinders.WithTiedOffDebug ++
new chipyard.iobinders.WithSimSerial ++
new testchipip.WithTSI ++
new chipyard.config.WithBootROM ++
new chipyard.config.WithUART ++
new chipyard.config.WithNoSubsystemDrivenClocks ++
// Attach either a TileLink or AXI4 version of GCD // Attach either a TileLink or AXI4 version of GCD
// Uncomment one of the below lines // Uncomment one of the below lines
@@ -75,63 +45,26 @@ class TutorialMMIOConfig extends Config(
// For this demonstration we assume the base system is a single-core Rocket, for fast elaboration // For this demonstration we assume the base system is a single-core Rocket, for fast elaboration
new freechips.rocketchip.subsystem.WithNBigCores(1) ++ new freechips.rocketchip.subsystem.WithNBigCores(1) ++
new freechips.rocketchip.subsystem.WithInclusiveCache ++ new chipyard.config.AbstractConfig
new freechips.rocketchip.subsystem.WithNoMMIOPort ++
new freechips.rocketchip.subsystem.WithNoSlavePort ++
new freechips.rocketchip.subsystem.WithNExtTopInterrupts(0) ++
new freechips.rocketchip.subsystem.WithCoherentBusTopology ++
new freechips.rocketchip.system.BaseConfig
) )
// Tutorial Phase 3: Integrate a SHA3 RoCC accelerator // Tutorial Phase 3: Integrate a SHA3 RoCC accelerator
class TutorialSha3Config extends Config( class TutorialSha3Config extends Config(
new chipyard.iobinders.WithUARTAdapter ++
new chipyard.iobinders.WithBlackBoxSimMem ++
new chipyard.iobinders.WithTieOffInterrupts ++
new chipyard.iobinders.WithTiedOffDebug ++
new chipyard.iobinders.WithSimSerial ++
new testchipip.WithTSI ++
new chipyard.config.WithBootROM ++
new chipyard.config.WithUART ++
new chipyard.config.WithNoSubsystemDrivenClocks ++
// Uncomment this line once you added SHA3 to the build.sbt, and cloned the SHA3 repo // Uncomment this line once you added SHA3 to the build.sbt, and cloned the SHA3 repo
// new sha3.WithSha3Accel ++ // new sha3.WithSha3Accel ++
// For this demonstration we assume the base system is a single-core Rocket, for fast elaboration // For this demonstration we assume the base system is a single-core Rocket, for fast elaboration
new freechips.rocketchip.subsystem.WithNBigCores(1) ++ new freechips.rocketchip.subsystem.WithNBigCores(1) ++
new freechips.rocketchip.subsystem.WithInclusiveCache ++ new chipyard.config.AbstractConfig
new freechips.rocketchip.subsystem.WithNoMMIOPort ++
new freechips.rocketchip.subsystem.WithNoSlavePort ++
new freechips.rocketchip.subsystem.WithNExtTopInterrupts(0) ++
new freechips.rocketchip.subsystem.WithCoherentBusTopology ++
new freechips.rocketchip.system.BaseConfig
) )
// Tutorial Phase 4: Integrate a Black-box verilog version of the SHA3 RoCC accelerator // Tutorial Phase 4: Integrate a Black-box verilog version of the SHA3 RoCC accelerator
class TutorialSha3BlackBoxConfig extends Config( class TutorialSha3BlackBoxConfig extends Config(
new chipyard.iobinders.WithUARTAdapter ++
new chipyard.iobinders.WithBlackBoxSimMem ++
new chipyard.iobinders.WithTieOffInterrupts ++
new chipyard.iobinders.WithTiedOffDebug ++
new chipyard.iobinders.WithSimSerial ++
new testchipip.WithTSI ++
new chipyard.config.WithBootROM ++
new chipyard.config.WithUART ++
new chipyard.config.WithNoSubsystemDrivenClocks ++
// Uncomment these lines once SHA3 is integrated // Uncomment these lines once SHA3 is integrated
// new sha3.WithSha3BlackBox ++ // Specify we want the Black-box verilog version of Sha3 Ctrl // new sha3.WithSha3BlackBox ++ // Specify we want the Black-box verilog version of Sha3 Ctrl
// new sha3.WithSha3Accel ++ // new sha3.WithSha3Accel ++
// For this demonstration we assume the base system is a single-core Rocket, for fast elaboration // For this demonstration we assume the base system is a single-core Rocket, for fast elaboration
new freechips.rocketchip.subsystem.WithNBigCores(1) ++ new freechips.rocketchip.subsystem.WithNBigCores(1) ++
new freechips.rocketchip.subsystem.WithInclusiveCache ++ new chipyard.config.AbstractConfig
new freechips.rocketchip.subsystem.WithNoMMIOPort ++
new freechips.rocketchip.subsystem.WithNoSlavePort ++
new freechips.rocketchip.subsystem.WithNExtTopInterrupts(0) ++
new freechips.rocketchip.subsystem.WithCoherentBusTopology ++
new freechips.rocketchip.system.BaseConfig
) )

View File

@@ -8,90 +8,131 @@ import chisel3.experimental.annotate
import freechips.rocketchip.config.{Field, Config, Parameters} import freechips.rocketchip.config.{Field, Config, Parameters}
import freechips.rocketchip.diplomacy.{LazyModule} import freechips.rocketchip.diplomacy.{LazyModule}
import freechips.rocketchip.devices.debug.{Debug, HasPeripheryDebugModuleImp} import freechips.rocketchip.devices.debug.{Debug, HasPeripheryDebugModuleImp}
import freechips.rocketchip.subsystem.{CanHaveMasterAXI4MemPort, HasExtInterruptsModuleImp, BaseSubsystem, HasTilesModuleImp} import freechips.rocketchip.amba.axi4.{AXI4Bundle}
import freechips.rocketchip.subsystem.{CanHaveMasterAXI4MemPort, HasExtInterruptsModuleImp, BaseSubsystem, HasTilesModuleImp, ExtMem}
import freechips.rocketchip.tile.{RocketTile} import freechips.rocketchip.tile.{RocketTile}
import sifive.blocks.devices.uart.HasPeripheryUARTModuleImp import sifive.blocks.devices.uart._
import sifive.blocks.devices.gpio.{HasPeripheryGPIOModuleImp}
import testchipip.{CanHavePeripherySerialModuleImp, CanHavePeripheryBlockDeviceModuleImp} import testchipip._
import icenet.CanHavePeripheryIceNICModuleImp import icenet.{CanHavePeripheryIceNIC, SimNetwork, NicLoopback, NICKey, NICIOvonly}
import junctions.{NastiKey, NastiParameters} import junctions.{NastiKey, NastiParameters}
import midas.models.{FASEDBridge, AXI4EdgeSummary, CompleteConfig} import midas.models.{FASEDBridge, AXI4EdgeSummary, CompleteConfig}
import midas.targetutils.{MemModelAnnotation} import midas.targetutils.{FAMEModelAnnotation, MemModelAnnotation, EnableModelMultiThreadingAnnotation}
import firesim.bridges._ import firesim.bridges._
import firesim.configs.MemModelKey import firesim.configs.MemModelKey
import tracegen.{TraceGenSystemModuleImp} import tracegen.{TraceGenSystemModuleImp}
import ariane.ArianeTile import ariane.ArianeTile
import boom.common.{BoomTile} import boom.common.{BoomTile}
import barstools.iocell.chisel._
import chipyard.iobinders.{IOBinders, OverrideIOBinder, ComposeIOBinder, GetSystemParameters} import chipyard.iobinders.{IOBinders, OverrideIOBinder, ComposeIOBinder, GetSystemParameters, IOCellKey}
import testchipip.{CanHaveTraceIOModuleImp} import chipyard.{HasHarnessSignalReferences}
import chipyard.harness._
object MainMemoryConsts { object MainMemoryConsts {
val regionNamePrefix = "MainMemory" val regionNamePrefix = "MainMemory"
def globalName = s"${regionNamePrefix}_${NodeIdx()}" def globalName = s"${regionNamePrefix}_${NodeIdx()}"
} }
class WithSerialBridge extends OverrideIOBinder({ trait Unsupported {
(system: CanHavePeripherySerialModuleImp) => require(false, "We do not support this IOCell type")
system.serial.foreach(s => SerialBridge(system.clock, s, MainMemoryConsts.globalName)(system.p)); Nil }
class FireSimAnalogIOCell extends RawModule with AnalogIOCell with Unsupported {
val io = IO(new AnalogIOCellBundle)
}
class FireSimDigitalGPIOCell extends RawModule with DigitalGPIOCell with Unsupported {
val io = IO(new DigitalGPIOCellBundle)
}
class FireSimDigitalInIOCell extends RawModule with DigitalInIOCell {
val io = IO(new DigitalInIOCellBundle)
io.i := io.pad
}
class FireSimDigitalOutIOCell extends RawModule with DigitalOutIOCell {
val io = IO(new DigitalOutIOCellBundle)
io.pad := io.o
}
case class FireSimIOCellParams() extends IOCellTypeParams {
def analog() = Module(new FireSimAnalogIOCell)
def gpio() = Module(new FireSimDigitalGPIOCell)
def input() = Module(new FireSimDigitalInIOCell)
def output() = Module(new FireSimDigitalOutIOCell)
}
class WithFireSimIOCellModels extends Config((site, here, up) => {
case IOCellKey => FireSimIOCellParams()
}) })
class WithNICBridge extends OverrideIOBinder({ class WithSerialBridge extends OverrideHarnessBinder({
(system: CanHavePeripheryIceNICModuleImp) => (system: CanHavePeripheryTLSerial, th: FireSim, ports: Seq[ClockedIO[SerialIO]]) => {
system.net.foreach(n => NICBridge(system.clock, n)(system.p)); Nil ports.map { port =>
implicit val p = GetSystemParameters(system)
val ram = SerialAdapter.connectHarnessRAM(system.serdesser.get, port, th.harnessReset)
SerialBridge(port.clock, ram.module.io.tsi_ser, p(ExtMem).map(_ => MainMemoryConsts.globalName))
}
Nil
}
}) })
class WithUARTBridge extends OverrideIOBinder({ class WithNICBridge extends OverrideHarnessBinder({
(system: HasPeripheryUARTModuleImp) => (system: CanHavePeripheryIceNIC, th: FireSim, ports: Seq[ClockedIO[NICIOvonly]]) => {
system.uart.foreach(u => UARTBridge(system.clock, u)(system.p)); Nil val p: Parameters = GetSystemParameters(system)
ports.map { n => NICBridge(n.clock, n.bits)(p) }
Nil
}
}) })
class WithBlockDeviceBridge extends OverrideIOBinder({ class WithUARTBridge extends OverrideHarnessBinder({
(system: CanHavePeripheryBlockDeviceModuleImp) => (system: HasPeripheryUARTModuleImp, th: FireSim, ports: Seq[UARTPortIO]) =>
system.bdev.foreach(b => BlockDevBridge(system.clock, b, system.reset.toBool)(system.p)); Nil ports.map { p => UARTBridge(th.harnessClock, p)(system.p) }; Nil
}) })
class WithBlockDeviceBridge extends OverrideHarnessBinder({
class WithFASEDBridge extends OverrideIOBinder({ (system: CanHavePeripheryBlockDevice, th: FireSim, ports: Seq[ClockedIO[BlockDeviceIO]]) => {
(system: CanHaveMasterAXI4MemPort) => {
implicit val p: Parameters = GetSystemParameters(system) implicit val p: Parameters = GetSystemParameters(system)
(system.mem_axi4 zip system.memAXI4Node.edges.in).foreach({ case (axi4, edge) => ports.map { b => BlockDevBridge(b.clock, b.bits, th.harnessReset.toBool) }
val nastiKey = NastiParameters(axi4.r.bits.data.getWidth, Nil
axi4.ar.bits.addr.getWidth, }
axi4.ar.bits.id.getWidth) })
class WithFASEDBridge extends OverrideHarnessBinder({
(system: CanHaveMasterAXI4MemPort, th: FireSim, ports: Seq[ClockedIO[AXI4Bundle]]) => {
implicit val p: Parameters = GetSystemParameters(system)
(ports zip system.memAXI4Node.edges.in).map { case (axi4, edge) =>
val nastiKey = NastiParameters(axi4.bits.r.bits.data.getWidth,
axi4.bits.ar.bits.addr.getWidth,
axi4.bits.ar.bits.id.getWidth)
system match { system match {
case s: BaseSubsystem => FASEDBridge(s.module.clock, axi4, s.module.reset.toBool, case s: BaseSubsystem => FASEDBridge(axi4.clock, axi4.bits, th.harnessReset.asBool,
CompleteConfig(p(firesim.configs.MemModelKey), CompleteConfig(p(firesim.configs.MemModelKey),
nastiKey, nastiKey,
Some(AXI4EdgeSummary(edge)), Some(AXI4EdgeSummary(edge)),
Some(MainMemoryConsts.globalName))) Some(MainMemoryConsts.globalName)))
case _ => throw new Exception("Attempting to attach FASED Bridge to misconfigured design") case _ => throw new Exception("Attempting to attach FASED Bridge to misconfigured design")
} }
}) }
Nil Nil
} }
}) })
class WithTracerVBridge extends ComposeIOBinder({ class WithTracerVBridge extends ComposeHarnessBinder({
(system: CanHaveTraceIOModuleImp) => (system: CanHaveTraceIOModuleImp, th: FireSim, ports: Seq[TraceOutputTop]) => {
system.traceIO.foreach(_.traces.map(tileTrace => TracerVBridge(tileTrace)(system.p))); Nil ports.map { p => p.traces.map(tileTrace => TracerVBridge(tileTrace)(system.p)) }
}) Nil
class WithDromajoBridge extends ComposeIOBinder({
(system: CanHaveTraceIOModuleImp) => {
system.traceIO.foreach(_.traces.map(tileTrace => DromajoBridge(tileTrace)(system.p))); Nil
} }
}) })
class WithDromajoBridge extends ComposeHarnessBinder({
(system: CanHaveTraceIOModuleImp, th: FireSim, ports: Seq[TraceOutputTop]) =>
ports.map { p => p.traces.map(tileTrace => DromajoBridge(tileTrace)(system.p)) }; Nil
})
class WithTraceGenBridge extends OverrideIOBinder({
(system: TraceGenSystemModuleImp) => class WithTraceGenBridge extends OverrideHarnessBinder({
GroundTestBridge(system.clock, system.success)(system.p); Nil (system: TraceGenSystemModuleImp, th: FireSim, ports: Seq[Bool]) =>
ports.map { p => GroundTestBridge(th.harnessClock, p)(system.p) }; Nil
}) })
class WithFireSimMultiCycleRegfile extends ComposeIOBinder({ class WithFireSimMultiCycleRegfile extends ComposeIOBinder({
@@ -105,52 +146,40 @@ class WithFireSimMultiCycleRegfile extends ComposeIOBinder({
val core = b.module.core val core = b.module.core
core.iregfile match { core.iregfile match {
case irf: boom.exu.RegisterFileSynthesizable => annotate(MemModelAnnotation(irf.regfile)) case irf: boom.exu.RegisterFileSynthesizable => annotate(MemModelAnnotation(irf.regfile))
case _ => Nil
} }
if (core.fp_pipeline != null) core.fp_pipeline.fregfile match { if (core.fp_pipeline != null) core.fp_pipeline.fregfile match {
case frf: boom.exu.RegisterFileSynthesizable => annotate(MemModelAnnotation(frf.regfile)) case frf: boom.exu.RegisterFileSynthesizable => annotate(MemModelAnnotation(frf.regfile))
case _ => Nil
} }
} }
case _ => case _ =>
} }
Nil (Nil, Nil)
} }
}) })
class WithTiedOffSystemGPIO extends OverrideIOBinder({ class WithFireSimFAME5 extends ComposeIOBinder({
(system: HasPeripheryGPIOModuleImp) => (system: HasTilesModuleImp) => {
system.gpio.foreach(_.pins.foreach(_.i.ival := false.B)); Nil system.outer.tiles.map {
}) case b: BoomTile =>
annotate(FAMEModelAnnotation(b.module))
class WithTiedOffSystemDebug extends OverrideIOBinder({ annotate(EnableModelMultiThreadingAnnotation(b.module))
(system: HasPeripheryDebugModuleImp) => { case r: RocketTile =>
Debug.tieoffDebug(system.debug, system.resetctrl, Some(system.psd))(system.p) annotate(FAMEModelAnnotation(r.module))
// tieoffDebug doesn't actually tie everything off :/ annotate(EnableModelMultiThreadingAnnotation(r.module))
system.debug.foreach { d =>
d.clockeddmi.foreach({ cdmi => cdmi.dmi.req.bits := DontCare })
d.dmactiveAck := DontCare
} }
Nil (Nil, Nil)
} }
}) })
class WithTiedOffSystemInterrupts extends OverrideIOBinder({
(system: HasExtInterruptsModuleImp) =>
system.interrupts := 0.U; Nil
})
// Shorthand to register all of the provided bridges above // Shorthand to register all of the provided bridges above
class WithDefaultFireSimBridges extends Config( class WithDefaultFireSimBridges extends Config(
new WithTiedOffSystemGPIO ++
new WithTiedOffSystemDebug ++
new WithTiedOffSystemInterrupts ++
new WithSerialBridge ++ new WithSerialBridge ++
new WithNICBridge ++ new WithNICBridge ++
new WithUARTBridge ++ new WithUARTBridge ++
new WithBlockDeviceBridge ++ new WithBlockDeviceBridge ++
new WithFASEDBridge ++ new WithFASEDBridge ++
new WithFireSimMultiCycleRegfile ++ new WithFireSimMultiCycleRegfile ++
new WithTracerVBridge new WithFireSimFAME5 ++
new WithTracerVBridge ++
new WithFireSimIOCellModels
) )

View File

@@ -8,13 +8,15 @@ import chisel3.experimental.{IO}
import freechips.rocketchip.prci._ import freechips.rocketchip.prci._
import freechips.rocketchip.subsystem.{BaseSubsystem, SubsystemDriveAsyncClockGroupsKey} import freechips.rocketchip.subsystem.{BaseSubsystem, SubsystemDriveAsyncClockGroupsKey}
import freechips.rocketchip.config.{Field, Config, Parameters} import freechips.rocketchip.config.{Field, Config, Parameters}
import freechips.rocketchip.diplomacy.{LazyModule, InModuleBody} import freechips.rocketchip.diplomacy.{LazyModule, InModuleBody, ValName}
import freechips.rocketchip.util.{ResetCatchAndSync} import freechips.rocketchip.util.{ResetCatchAndSync, RecordMap}
import midas.widgets.{Bridge, PeekPokeBridge, RationalClockBridge, RationalClock} import midas.widgets.{Bridge, PeekPokeBridge, RationalClockBridge, RationalClock}
import chipyard.{BuildSystem, BuildTop, HasHarnessSignalReferences, ChipyardSubsystem, ClockingSchemeKey, ChipTop} import chipyard._
import chipyard.iobinders.{IOBinders} import chipyard.harness._
import chipyard.iobinders._
import chipyard.clocking.{FrequencyUtils, ClockGroupNamePrefixer, ClockGroupFrequencySpecifier, SimplePllConfiguration}
// Determines the number of times to instantiate the DUT in the harness. // Determines the number of times to instantiate the DUT in the harness.
// Subsumes legacy supernode support // Subsumes legacy supernode support
@@ -24,16 +26,6 @@ class WithNumNodes(n: Int) extends Config((pname, site, here) => {
case NumNodes => n case NumNodes => n
}) })
// Note, the main prerequisite for supporting an additional clock domain in a
// FireSim simulation is to supply an additional clock parameter
// (RationalClock) to the clock bridge (RationalClockBridge). The bridge
// produces a vector of clocks, based on the provided parameter list, which you
// may use freely without further modifications to your target design.
case class FireSimClockParameters(additionalClocks: Seq[RationalClock]) {
def numClocks(): Int = additionalClocks.size + 1
}
case object FireSimClockKey extends Field[FireSimClockParameters](FireSimClockParameters(Seq()))
// Hacky: Set before each node is generated. Ideally we'd give IO binders // Hacky: Set before each node is generated. Ideally we'd give IO binders
// accesses to the the Harness's parameters instance. We could then alter that. // accesses to the the Harness's parameters instance. We could then alter that.
object NodeIdx { object NodeIdx {
@@ -42,107 +34,113 @@ object NodeIdx {
def apply(): Int = idx def apply(): Int = idx
} }
/**
* Under FireSim's current multiclock implementation there can be only a
* single clock bridge. This requires, therefore, that it be instantiated in
* the harness and reused across all supernode instances. This class attempts to
* memoize its instantiation such that it can be referenced from within a ClockScheme function.
*/
class ClockBridgeInstantiator {
private var _clockRecord: Option[RecordMap[Clock]] = None
def getClockRecord: RecordMap[Clock] = _clockRecord.get
def getClockRecordOrInstantiate(allClocks: Seq[RationalClock], baseClockName: String): RecordMap[Clock] = {
if (_clockRecord.isEmpty) {
require(allClocks.exists(_.name == baseClockName),
s"Provided base-clock name, ${baseClockName}, does not match a defined clock. Available clocks:\n " +
allClocks.map(_.name).mkString("\n "))
val baseClock = allClocks.find(_.name == baseClockName).get
val simplified = allClocks.map { c =>
c.copy(multiplier = c.multiplier * baseClock.divisor, divisor = c.divisor * baseClock.multiplier)
.simplify
}
/**
* Removes clocks that have the same frequency before instantiating the
* clock bridge to avoid unnecessary BUFGCE use.
*/
val distinct = simplified.foldLeft(Seq(RationalClock(baseClockName, 1, 1))) { case (list, candidate) =>
if (list.exists { clock => clock.equalFrequency(candidate) }) list else list :+ candidate
}
val clockBridge = Module(new RationalClockBridge(distinct))
val cbVecTuples = distinct.zip(clockBridge.io.clocks)
val outputWire = Wire(RecordMap(simplified.map { c => (c.name, Clock()) }:_*))
for (parameter <- simplified) {
val (_, cbClockField) = cbVecTuples.find(_._1.equalFrequency(parameter)).get
outputWire(parameter.name).get := cbClockField
}
_clockRecord = Some(outputWire)
}
getClockRecord
}
}
case object ClockBridgeInstantiatorKey extends Field[ClockBridgeInstantiator](new ClockBridgeInstantiator)
case object FireSimBaseClockNameKey extends Field[String]("implicit_clock")
class WithFireSimSimpleClocks extends Config((site, here, up) => { class WithFireSimSimpleClocks extends Config((site, here, up) => {
case ClockingSchemeKey => { chiptop: ChipTop => case ClockingSchemeKey => { chiptop: ChipTop =>
implicit val p = chiptop.p implicit val p = chiptop.p
// Figure out what provides this in the chipyard scheme
implicit val valName = ValName("FireSimClocking")
val implicitClockSourceNode = ClockSourceNode(Seq(ClockSourceParameters())) // Requires existence of undriven asyncClockGroups in subsystem
chiptop.implicitClockSinkNode := implicitClockSourceNode val systemAsyncClockGroup = chiptop.lazySystem match {
case l: BaseSubsystem if (p(SubsystemDriveAsyncClockGroupsKey).isEmpty) =>
// Drive the diplomaticclock graph of the DigitalTop (if present) l.asyncClockGroupsNode
val simpleClockGroupSourceNode = chiptop.lSystem match {
case l: BaseSubsystem if (p(SubsystemDriveAsyncClockGroupsKey).isEmpty) => {
val n = ClockGroupSourceNode(Seq(ClockGroupSourceParameters()))
l.asyncClockGroupsNode := n
Some(n)
}
case _ => None
} }
val aggregator = LazyModule(new ClockGroupAggregator("allClocks")).node
(chiptop.implicitClockSinkNode := ClockGroup() := aggregator)
(systemAsyncClockGroup := ClockGroupNamePrefixer() := aggregator)
val inputClockSource = ClockGroupSourceNode(Seq(ClockGroupSourceParameters()))
(aggregator
:= ClockGroupFrequencySpecifier(p(ClockFrequencyAssignersKey), p(DefaultClockFrequencyKey))
:= inputClockSource)
InModuleBody { InModuleBody {
val clock = IO(Input(Clock())).suggestName("clock") val (clockGroupBundle, clockGroupEdge) = inputClockSource.out.head
val input_clocks = IO(Input(RecordMap((clockGroupEdge.sink.members.map { m => (m.name.get, Clock()) }):_* )))
.suggestName("clocks")
val reset = IO(Input(Reset())).suggestName("reset") val reset = IO(Input(Reset())).suggestName("reset")
implicitClockSourceNode.out.unzip._1.map { o => (clockGroupBundle.member.data zip input_clocks.data).foreach { case (clockBundle, inputClock) =>
o.clock := clock clockBundle.clock := inputClock
o.reset := reset
} }
simpleClockGroupSourceNode.map { n => n.out.unzip._1.map { out: ClockGroupBundle => // Assign resets. The synchronization scheme is still WIP.
out.member.data.foreach { o => for ((name, clockBundle) <- clockGroupBundle.member.elements) {
o.clock := clock if (name.contains("core")) {
o.reset := reset clockBundle.reset := ResetCatchAndSync(clockBundle.clock, reset.asBool)
} else {
clockBundle.reset := reset
} }
}} }
val pllConfig = new SimplePllConfiguration("FireSim RationalClockBridge", clockGroupEdge.sink.members)
val rationalClockSpecs = for ((sinkP, division) <- pllConfig.sinkDividerMap) yield {
RationalClock(sinkP.name.get, 1, division)
}
chiptop.harnessFunctions += ((th: HasHarnessSignalReferences) => { chiptop.harnessFunctions += ((th: HasHarnessSignalReferences) => {
clock := th.harnessClock
reset := th.harnessReset reset := th.harnessReset
Nil input_clocks := p(ClockBridgeInstantiatorKey)
}) .getClockRecordOrInstantiate(rationalClockSpecs.toSeq, p(FireSimBaseClockNameKey))
} Nil })
}
})
class WithFireSimRationalTileDomain(multiplier: Int, divisor: Int) extends Config((site, here, up) => {
case FireSimClockKey => FireSimClockParameters(Seq(RationalClock("TileDomain", multiplier, divisor)))
case ClockingSchemeKey => { chiptop: ChipTop =>
implicit val p = chiptop.p
val implicitClockSourceNode = ClockSourceNode(Seq(ClockSourceParameters()))
chiptop.implicitClockSinkNode := implicitClockSourceNode
// Drive the diplomaticclock graph of the DigitalTop (if present)
val simpleClockGroupSourceNode = chiptop.lSystem match {
case l: BaseSubsystem if (p(SubsystemDriveAsyncClockGroupsKey).isEmpty) => {
val n = ClockGroupSourceNode(Seq(ClockGroupSourceParameters()))
l.asyncClockGroupsNode := n
Some(n)
}
case _ => None
}
InModuleBody {
val uncore_clock = IO(Input(Clock())).suggestName("uncore_clock")
val tile_clock = IO(Input(Clock())).suggestName("tile_clock")
val reset = IO(Input(Reset())).suggestName("reset")
implicitClockSourceNode.out.unzip._1.map { o =>
o.clock := uncore_clock
o.reset := reset
}
simpleClockGroupSourceNode.map { n => n.out.unzip._1.map { out: ClockGroupBundle =>
out.member.elements.map { case (name, data) =>
// This is mega hacks, how are you actually supposed to do this?
if (name.contains("core")) {
data.clock := tile_clock
data.reset := ResetCatchAndSync(tile_clock, reset.asBool)
} else {
data.clock := uncore_clock
data.reset := reset
}
}
}}
chiptop.harnessFunctions += ((th: HasHarnessSignalReferences) => {
uncore_clock := th.harnessClock
reset := th.harnessReset
th match {
case f: FireSim => tile_clock := f.additionalClocks(0)
case _ => throw new Exception("FireSimMultiClock must be used with FireSim")
}
Nil
})
} }
} }
}) })
class FireSim(implicit val p: Parameters) extends RawModule with HasHarnessSignalReferences { class FireSim(implicit val p: Parameters) extends RawModule with HasHarnessSignalReferences {
freechips.rocketchip.util.property.cover.setPropLib(new midas.passes.FireSimPropertyLibrary()) freechips.rocketchip.util.property.cover.setPropLib(new midas.passes.FireSimPropertyLibrary())
val clockBridge = Module(new RationalClockBridge(p(FireSimClockKey).additionalClocks:_*)) val harnessClock = Wire(Clock())
val harnessClock = clockBridge.io.clocks.head // This is the reference clock
val additionalClocks = clockBridge.io.clocks.tail
val harnessReset = WireInit(false.B) val harnessReset = WireInit(false.B)
val peekPokeBridge = PeekPokeBridge(harnessClock, harnessReset) val peekPokeBridge = PeekPokeBridge(harnessClock, harnessReset)
def dutReset = { require(false, "dutReset should not be used in Firesim"); false.B } def dutReset = { require(false, "dutReset should not be used in Firesim"); false.B }
@@ -159,8 +157,12 @@ class FireSim(implicit val p: Parameters) extends RawModule with HasHarnessSigna
case AsyncClockGroupsKey => p(AsyncClockGroupsKey).copy case AsyncClockGroupsKey => p(AsyncClockGroupsKey).copy
}))) })))
val module = Module(lazyModule.module) val module = Module(lazyModule.module)
require(lazyModule.harnessFunctions.size == 1, "There should only be 1 harness function to connect clock+reset") lazyModule match { case d: HasTestHarnessFunctions =>
lazyModule.harnessFunctions.foreach(_(this)) require(d.harnessFunctions.size == 1, "There should only be 1 harness function to connect clock+reset")
d.harnessFunctions.foreach(_(this))
ApplyHarnessBinders(this, d.lazySystem, p(HarnessBinders), d.portMap.toMap)
}
NodeIdx.increment() NodeIdx.increment()
} }
harnessClock := p(ClockBridgeInstantiatorKey).getClockRecord("implicit_clock").get
} }

View File

@@ -13,7 +13,7 @@ import freechips.rocketchip.subsystem._
import freechips.rocketchip.devices.tilelink.{BootROMLocated, BootROMParams} import freechips.rocketchip.devices.tilelink.{BootROMLocated, BootROMParams}
import freechips.rocketchip.devices.debug.{DebugModuleParams, DebugModuleKey} import freechips.rocketchip.devices.debug.{DebugModuleParams, DebugModuleKey}
import freechips.rocketchip.diplomacy.LazyModule import freechips.rocketchip.diplomacy.LazyModule
import testchipip.{BlockDeviceKey, BlockDeviceConfig, SerialKey, TracePortKey, TracePortParams} import testchipip.{BlockDeviceKey, BlockDeviceConfig, TracePortKey, TracePortParams}
import sifive.blocks.devices.uart.{PeripheryUARTKey, UARTParams} import sifive.blocks.devices.uart.{PeripheryUARTKey, UARTParams}
import scala.math.{min, max} import scala.math.{min, max}
@@ -84,11 +84,13 @@ class WithFireSimConfigTweaks extends Config(
// Required: Adds IO to attach SerialBridge. The SerialBridges is responsible // Required: Adds IO to attach SerialBridge. The SerialBridges is responsible
// for signalling simulation termination under simulation success. This fragment can // for signalling simulation termination under simulation success. This fragment can
// be removed if you supply an auxiliary bridge that signals simulation termination // be removed if you supply an auxiliary bridge that signals simulation termination
new testchipip.WithTSI ++ new testchipip.WithDefaultSerialTL ++
// Optional: Removing this will require using an initramfs under linux // Optional: Removing this will require using an initramfs under linux
new testchipip.WithBlockDevice ++ new testchipip.WithBlockDevice ++
// Required*: Scale default baud rate with periphery bus frequency // Required*: Scale default baud rate with periphery bus frequency
new chipyard.config.WithUART(BigInt(3686400L)) new chipyard.config.WithUART(BigInt(3686400L)) ++
// Required: Do not support debug module w. JTAG until FIRRTL stops emitting @(posedge ~clock)
new chipyard.config.WithNoDebug
) )
/******************************************************************************* /*******************************************************************************
@@ -129,7 +131,7 @@ class FireSimSmallSystemConfig extends Config(
new WithoutClockGating ++ new WithoutClockGating ++
new WithoutTLMonitors ++ new WithoutTLMonitors ++
new freechips.rocketchip.subsystem.WithExtMemSize(1 << 28) ++ new freechips.rocketchip.subsystem.WithExtMemSize(1 << 28) ++
new testchipip.WithTSI ++ new testchipip.WithDefaultSerialTL ++
new testchipip.WithBlockDevice ++ new testchipip.WithBlockDevice ++
new chipyard.config.WithUART ++ new chipyard.config.WithUART ++
new freechips.rocketchip.subsystem.WithInclusiveCache(nWays = 2, capacityKB = 64) ++ new freechips.rocketchip.subsystem.WithInclusiveCache(nWays = 2, capacityKB = 64) ++
@@ -192,7 +194,7 @@ class FireSimArianeConfig extends Config(
//* Multiclock Configurations //* Multiclock Configurations
//*********************************************************************************/ //*********************************************************************************/
class FireSimMulticlockRocketConfig extends Config( class FireSimMulticlockRocketConfig extends Config(
new WithFireSimRationalTileDomain(2, 1) ++ new chipyard.config.WithTileFrequency(6400.0) ++ //lol
new WithDefaultFireSimBridges ++ new WithDefaultFireSimBridges ++
new WithDefaultMemModel ++ new WithDefaultMemModel ++
new WithFireSimConfigTweaks ++ new WithFireSimConfigTweaks ++

View File

@@ -85,6 +85,18 @@ object GenerateSimFiles extends App with HasGenerateSimConfig {
out.close() out.close()
} }
def resources(sim: Simulator): Seq[String] = Seq( def resources(sim: Simulator): Seq[String] = Seq(
"/testchipip/csrc/SimSerial.cc",
"/testchipip/csrc/testchip_tsi.cc",
"/testchipip/csrc/testchip_tsi.h",
"/testchipip/csrc/SimDRAM.cc",
"/testchipip/csrc/mm.h",
"/testchipip/csrc/mm.cc",
"/testchipip/csrc/mm_dramsim2.h",
"/testchipip/csrc/mm_dramsim2.cc",
"/csrc/SimDTM.cc",
"/csrc/SimJTAG.cc",
"/csrc/remote_bitbang.h",
"/csrc/remote_bitbang.cc",
"/vsrc/EICG_wrapper.v", "/vsrc/EICG_wrapper.v",
) ++ (sim match { ) ++ (sim match {
case NotSimulator => Seq() case NotSimulator => Seq()

View File

@@ -8,7 +8,9 @@ binary=$1
segments=`readelf --segments --wide $binary` segments=`readelf --segments --wide $binary`
entry_hex=`echo -e "$segments" | grep "Entry point" | cut -f3 -d' ' | sed 's/0x//' | tr [:lower:] [:upper:]` entry_hex=`echo -e "$segments" | grep "Entry point" | cut -f3 -d' ' | sed 's/0x//' | tr [:lower:] [:upper:]`
entry_dec=`bc <<< "ibase=16;$entry_hex"` entry_dec=`bc <<< "ibase=16;$entry_hex"`
length_hex=`echo "$segments" | grep LOAD | tail -n 1 | tr -s [:space:] | cut -f4,6 -d' '` length_hex=`echo "$segments" | grep "LOAD\|TLS" | tail -n 1 | tr -s [:space:] | cut -f4,6 -d' '`
length_dec=`echo $length_hex | tr -d x | tr [:lower:] [:upper:] | tr ' ' + | sed 's/^/ibase=16;/' | sed "s/$/-$entry_hex/" | bc` length_dec=`echo $length_hex | tr -d x | tr [:lower:] [:upper:] | tr ' ' + | sed 's/^/ibase=16;/' | sed "s/$/-$entry_hex/" | bc`
power_2_length=`echo "x=l($length_dec)/l(2); scale=0; 2^((x+1)/1)" | bc -l` power_2_length=`echo "x=l($length_dec)/l(2); scale=0; 2^((x+1)/1)" | bc -l`
elf2hex 64 $power_2_length $binary $entry_dec width=64
depth=$((power_2_length / width))
elf2hex $width $depth $binary $entry_dec

View File

@@ -9,7 +9,7 @@ index 5d642c1..56f6fda 100644
- sha3, // On separate line to allow for cleaner tutorial-setup patches - sha3, // On separate line to allow for cleaner tutorial-setup patches
+// sha3, // On separate line to allow for cleaner tutorial-setup patches +// sha3, // On separate line to allow for cleaner tutorial-setup patches
dsptools, `rocket-dsptools`, dsptools, `rocket-dsptools`,
gemmini, icenet, tracegen, ariane, nvdla) gemmini, icenet, tracegen, ariane, nvdla, sodor)
.settings(commonSettings) .settings(commonSettings)
@@ -158,9 +158,9 @@ lazy val ariane = (project in file("generators/ariane")) @@ -158,9 +158,9 @@ lazy val ariane = (project in file("generators/ariane"))
.dependsOn(rocketchip) .dependsOn(rocketchip)