Merge branch 'dev' of github.com:ucb-bar/chipyard into verilator-makefile-fix

This commit is contained in:
Zitao Fang
2020-09-25 20:33:05 -07:00
65 changed files with 1785 additions and 1336 deletions

View File

@@ -82,7 +82,12 @@ search
submodules=("coremark" "firemarshal" "nvdla-workload" "spec2017") submodules=("coremark" "firemarshal" "nvdla-workload" "spec2017")
dir="software" dir="software"
branches=("master") if [ "$CIRCLE_BRANCH" == "master" ] || [ "$CIRCLE_BRANCH" == "dev" ]
then
branches=("master")
else
branches=("master" "dev")
fi
search search
submodules=("DRAMSim2" "axe" "barstools" "chisel-testers" "dsptools" "firrtl-interpreter" "torture" "treadle") submodules=("DRAMSim2" "axe" "barstools" "chisel-testers" "dsptools" "firrtl-interpreter" "torture" "treadle")

View File

@@ -6,7 +6,7 @@ version: 2.1
parameters: parameters:
tools-cache-version: tools-cache-version:
type: string type: string
default: "v5" default: "v6"
# default execution env.s # default execution env.s
executors: executors:
@@ -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,154 @@ 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-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 +342,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 +350,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 +393,86 @@ 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-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 +491,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"
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,9 +70,10 @@ 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["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"

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 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,7 @@ 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-nvdla) chipyard-nvdla)
make -C $LOCAL_CHIPYARD_DIR/tests make -C $LOCAL_CHIPYARD_DIR/tests

1
.gitignore vendored
View File

@@ -6,6 +6,7 @@ target
*.stamp *.stamp
*.vcd *.vcd
*.swp *.swp
*.swo
*.log *.log
*# *#
*~ *~

View File

@@ -3,22 +3,49 @@
######################################################################################### #########################################################################################
SHELL=/bin/bash SHELL=/bin/bash
ifndef RISCV ifndef RISCV
$(error RISCV is unset. You must set RISCV yourself, or through the Chipyard auto-generated env file) $(error RISCV is unset. You must set RISCV yourself, or through the Chipyard auto-generated env file)
else else
$(info Running with RISCV=$(RISCV)) $(info Running with RISCV=$(RISCV))
endif endif
#########################################################################################
# specify user-interface variables
#########################################################################################
HELP_COMPILATION_VARIABLES += \
" EXTRA_GENERATOR_REQS = additional make requirements needed for the main generator" \
" EXTRA_SIM_CXXFLAGS = additional CXXFLAGS for building simulators" \
" EXTRA_SIM_LDFLAGS = additional LDFLAGS for building simulators" \
" EXTRA_SIM_SOURCES = additional simulation sources needed for simulator" \
" EXTRA_SIM_REQS = additional make requirements to build the simulator"
EXTRA_GENERATOR_REQS ?=
EXTRA_SIM_CXXFLAGS ?=
EXTRA_SIM_LDFLAGS ?=
EXTRA_SIM_SOURCES ?=
EXTRA_SIM_REQS ?=
#----------------------------------------------------------------------------
HELP_SIMULATION_VARIABLES += \
" EXTRA_SIM_FLAGS = additional runtime simulation flags (passed within +permissive)" \
" NUMACTL = set to '1' to wrap simulator in the appropriate numactl command"
EXTRA_SIM_FLAGS ?=
NUMACTL ?= 0
NUMA_PREFIX = $(if $(filter $(NUMACTL),0),,$(shell $(base_dir)/scripts/numa_prefix))
#----------------------------------------------------------------------------
HELP_COMMANDS += \
" run-binary = run [./$(shell basename $(sim))] and log instructions to file" \
" run-binary-fast = run [./$(shell basename $(sim))] and don't log instructions" \
" run-binary-debug = run [./$(shell basename $(sim_debug))] and log instructions and waveform to files" \
" verilog = generate intermediate verilog files from chisel elaboration and firrtl passes" \
" run-tests = run all assembly and benchmark tests"
######################################################################################### #########################################################################################
# extra make variables/rules from subprojects # include additional subproject make fragments
# # see HELP_COMPILATION_VARIABLES
# EXTRA_GENERATOR_REQS - requirements needed for the main generator
# EXTRA_SIM_FLAGS - runtime simulation flags
# EXTRA_SIM_CC_FLAGS - cc flags for simulators
# EXTRA_SIM_SOURCES - simulation sources needed for simulator
# EXTRA_SIM_REQS - requirements to build the simulator
######################################################################################### #########################################################################################
include $(base_dir)/generators/ariane/ariane.mk include $(base_dir)/generators/ariane/ariane.mk
include $(base_dir)/generators/tracegen/tracegen.mk include $(base_dir)/generators/tracegen/tracegen.mk
@@ -35,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
@@ -55,7 +83,6 @@ $(FIRRTL_TEST_JAR): $(call lookup_srcs,$(CHIPYARD_FIRRTL_DIR),scala)
cp -p $(CHIPYARD_FIRRTL_DIR)/utils/bin/firrtl-test.jar $@ cp -p $(CHIPYARD_FIRRTL_DIR)/utils/bin/firrtl-test.jar $@
touch $@ touch $@
######################################################################################### #########################################################################################
# Bloop Project Definitions # Bloop Project Definitions
######################################################################################### #########################################################################################
@@ -140,20 +167,18 @@ verilog: $(sim_vsrcs)
# helper rules to run simulations # helper rules to run simulations
######################################################################################### #########################################################################################
.PHONY: run-binary run-binary-fast run-binary-debug run-fast .PHONY: run-binary run-binary-fast run-binary-debug run-fast
# run normal binary with hardware-logged insn dissassembly
run-binary: $(output_dir) $(sim) run-binary: $(output_dir) $(sim)
(set -o pipefail && $(sim) $(PERMISSIVE_ON) $(SIM_FLAGS) $(EXTRA_SIM_FLAGS) $(SEED_FLAG) $(VERBOSE_FLAGS) $(PERMISSIVE_OFF) $(BINARY) </dev/null 2> >(spike-dasm > $(sim_out_name).out) | tee $(sim_out_name).log) (set -o pipefail && $(NUMA_PREFIX) $(sim) $(PERMISSIVE_ON) $(SIM_FLAGS) $(EXTRA_SIM_FLAGS) $(SEED_FLAG) $(VERBOSE_FLAGS) $(PERMISSIVE_OFF) $(BINARY) </dev/null 2> >(spike-dasm > $(sim_out_name).out) | tee $(sim_out_name).log)
######################################################################################### # run simulator as fast as possible (no insn disassembly)
# helper rules to run simulator as fast as possible
#########################################################################################
run-binary-fast: $(output_dir) $(sim) run-binary-fast: $(output_dir) $(sim)
(set -o pipefail && $(sim) $(PERMISSIVE_ON) $(SIM_FLAGS) $(EXTRA_SIM_FLAGS) $(SEED_FLAG) $(PERMISSIVE_OFF) $(BINARY) </dev/null | tee $(sim_out_name).log) (set -o pipefail && $(NUMA_PREFIX) $(sim) $(PERMISSIVE_ON) $(SIM_FLAGS) $(EXTRA_SIM_FLAGS) $(SEED_FLAG) $(PERMISSIVE_OFF) $(BINARY) </dev/null | tee $(sim_out_name).log)
######################################################################################### # run simulator with as much debug info as possible
# helper rules to run simulator with as much debug info as possible
#########################################################################################
run-binary-debug: $(output_dir) $(sim_debug) run-binary-debug: $(output_dir) $(sim_debug)
(set -o pipefail && $(sim_debug) $(PERMISSIVE_ON) $(SIM_FLAGS) $(EXTRA_SIM_FLAGS) $(SEED_FLAG) $(VERBOSE_FLAGS) $(WAVEFORM_FLAG) $(PERMISSIVE_OFF) $(BINARY) </dev/null 2> >(spike-dasm > $(sim_out_name).out) | tee $(sim_out_name).log) (set -o pipefail && $(NUMA_PREFIX) $(sim_debug) $(PERMISSIVE_ON) $(SIM_FLAGS) $(EXTRA_SIM_FLAGS) $(SEED_FLAG) $(VERBOSE_FLAGS) $(WAVEFORM_FLAG) $(PERMISSIVE_OFF) $(BINARY) </dev/null 2> >(spike-dasm > $(sim_out_name).out) | tee $(sim_out_name).log)
run-fast: run-asm-tests-fast run-bmark-tests-fast run-fast: run-asm-tests-fast run-bmark-tests-fast
@@ -189,10 +214,10 @@ $(output_dir)/%: $(RISCV)/riscv64-unknown-elf/share/riscv-tests/isa/% $(output_d
ln -sf $< $@ ln -sf $< $@
$(output_dir)/%.run: $(output_dir)/% $(sim) $(output_dir)/%.run: $(output_dir)/% $(sim)
(set -o pipefail && $(sim) $(PERMISSIVE_ON) $(SIM_FLAGS) $(EXTRA_SIM_FLAGS) $(SEED_FLAG) $(PERMISSIVE_OFF) $< </dev/null | tee $<.log) && touch $@ (set -o pipefail && $(NUMA_PREFIX) $(sim) $(PERMISSIVE_ON) $(SIM_FLAGS) $(EXTRA_SIM_FLAGS) $(SEED_FLAG) $(PERMISSIVE_OFF) $< </dev/null | tee $<.log) && touch $@
$(output_dir)/%.out: $(output_dir)/% $(sim) $(output_dir)/%.out: $(output_dir)/% $(sim)
(set -o pipefail && $(sim) $(PERMISSIVE_ON) $(SIM_FLAGS) $(EXTRA_SIM_FLAGS) $(SEED_FLAG) $(VERBOSE_FLAGS) $(PERMISSIVE_OFF) $< </dev/null 2> >(spike-dasm > $@) | tee $<.log) (set -o pipefail && $(NUMA_PREFIX) $(sim) $(PERMISSIVE_ON) $(SIM_FLAGS) $(EXTRA_SIM_FLAGS) $(SEED_FLAG) $(VERBOSE_FLAGS) $(PERMISSIVE_OFF) $< </dev/null 2> >(spike-dasm > $@) | tee $<.log)
######################################################################################### #########################################################################################
# include build/project specific makefrags made from the generator # include build/project specific makefrags made from the generator
@@ -211,6 +236,13 @@ dramsim_lib = $(dramsim_dir)/libdramsim.a
$(dramsim_lib): $(dramsim_lib):
$(MAKE) -C $(dramsim_dir) $(notdir $@) $(MAKE) -C $(dramsim_dir) $(notdir $@)
#########################################################################################
# print help text
#########################################################################################
.PHONY: help
help:
@for line in $(HELP_LINES); do echo "$$line"; done
######################################################################################### #########################################################################################
# Implicit rule handling # Implicit rule handling
######################################################################################### #########################################################################################

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.

View File

@@ -40,8 +40,7 @@ For a proprietry VCS simulation, enter the ``sims/vcs`` directory
# Enter VCS directory # Enter VCS directory
cd sims/vcs cd sims/vcs
.. _sw-sim-help:
.. _sim-default:
Simulating The Default Example Simulating The Default Example
------------------------------- -------------------------------
@@ -82,6 +81,22 @@ For example:
.. _sw-sim-custom: .. _sw-sim-custom:
Makefile Variables and Commands
-------------------------------
You can get a list of useful Makefile variables and commands available from the Verilator or VCS directories. simply run ``make help``:
.. code-block:: shell
# Enter Verilator directory
cd sims/verilator
make help
# Enter VCS directory
cd sims/vcs
make help
.. _sim-default:
Simulating A Custom Project Simulating A Custom Project
------------------------------- -------------------------------
@@ -167,3 +182,18 @@ An open-source vcd-capable waveform viewer is `GTKWave <http://gtkwave.sourcefor
For a VCS simulation, this will generate a vpd file (this is a proprietary waveform representation format used by Synopsys) that can be loaded to vpd-supported waveform viewers. For a VCS simulation, this will generate a vpd file (this is a proprietary waveform representation format used by Synopsys) that can be loaded to vpd-supported waveform viewers.
If you have Synopsys licenses, we recommend using the DVE waveform viewer. If you have Synopsys licenses, we recommend using the DVE waveform viewer.
.. _sw-sim-verilator-opts:
Additional Verilator Options
-------------------------------
When building the verilator simulator there are some additional options:
.. code-block:: shell
make VERILATOR_THREADS=8 NUMACTL=1
The ``VERILATOR_THREADS=<num>`` option enables the compiled Verilator simulator to use ``<num>`` parallel threads.
On a multi-socket machine, you will want to make sure all threads are on the same socket by using ``NUMACTL=1`` to enable ``numactl``.
By enabling this, you will use Chipyard's ``numa_prefix`` wrapper, which is a simple wrapper around ``numactl`` that runs your verilated simulator like this: ``$(numa_prefix) ./simulator-<name> <simulator-args>``.
Note that both these flags are mutually exclusive, you can use either independently (though it makes sense to use ``NUMACTL`` just with ``VERILATOR_THREADS=8`` during a Verilator simulation).

View File

@@ -4,118 +4,59 @@ import chisel3._
import scala.collection.mutable.{ArrayBuffer} import scala.collection.mutable.{ArrayBuffer}
import freechips.rocketchip.prci.{ClockGroupIdentityNode, ClockSinkParameters, ClockSinkNode, ClockGroup}
import freechips.rocketchip.subsystem.{BaseSubsystem, SubsystemDriveAsyncClockGroupsKey}
import freechips.rocketchip.config.{Parameters, Field} import freechips.rocketchip.config.{Parameters, Field}
import freechips.rocketchip.diplomacy.{LazyModule} import freechips.rocketchip.diplomacy.{LazyModule, LazyModuleImp, LazyRawModuleImp, LazyModuleImpLike}
import freechips.rocketchip.util.{ResetCatchAndSync} import freechips.rocketchip.util.{ResetCatchAndSync}
import chipyard.config.ConfigValName._ import chipyard.iobinders._
import chipyard.iobinders.{IOBinders, TestHarnessFunction, IOBinderTuple}
import barstools.iocell.chisel._ import barstools.iocell.chisel._
case object BuildSystem extends Field[Parameters => LazyModule]((p: Parameters) => LazyModule(new DigitalTop()(p))) case object BuildSystem extends Field[Parameters => LazyModule]((p: Parameters) => new DigitalTop()(p))
/**
* Chipyard provides three baseline, top-level reset schemes, set using the
* [[GlobalResetSchemeKey]] in a Parameters instance. These are:
*
* 1) Synchronous: The input coming to the chip is synchronous to the provided
* clocks and will be used without modification as a synchronous reset.
* This is safe only for use in FireSim and SW simulation.
*
* 2) Asynchronous: The input reset is asynchronous to the input clock, but it
* is caught and synchronized to that clock before it is dissemenated.
* Thus, downsteam modules will be emitted with synchronously reset state
* elements.
*
* 3) Asynchronous Full: The input reset is asynchronous to the input clock,
* and is used globally as an async reset. Downstream modules will be emitted
* with asynchronously reset state elements.
*
*/
sealed trait GlobalResetScheme {
def pinIsAsync: Boolean
}
sealed trait HasAsyncInput { self: GlobalResetScheme =>
def pinIsAsync = true
}
sealed trait HasSyncInput { self: GlobalResetScheme =>
def pinIsAsync = false
}
case object GlobalResetSynchronous extends GlobalResetScheme with HasSyncInput
case object GlobalResetAsynchronous extends GlobalResetScheme with HasAsyncInput
case object GlobalResetAsynchronousFull extends GlobalResetScheme with HasAsyncInput
case object GlobalResetSchemeKey extends Field[GlobalResetScheme](GlobalResetSynchronous)
/** /**
* The base class used for building chips. This constructor instantiates a module specified by the BuildSystem parameter, * The base class used for building chips. This constructor instantiates a module specified by the BuildSystem parameter,
* named "system", which is an instance of DigitalTop by default. The default clock and reset for "system" are set by two * named "system", which is an instance of DigitalTop by default. The diplomatic clocks of System, as well as its implicit clock,
* wires, "systemClock" and "systemReset", which are intended to be driven by traits mixed-in with this base class. * is aggregated into the clockGroupNode. The parameterized functions controlled by ClockingSchemeKey and GlobalResetSchemeKey
* drive clock and reset generation
*/ */
abstract class BaseChipTop()(implicit val p: Parameters) extends RawModule 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 clock
// These are given so that IOCell can use DataMirror and generate ports with
// the right flow (Input/Output)
val systemClock = Wire(Input(Clock()))
val systemReset = Wire(Input(Reset()))
// The system module specified by BuildSystem // The system module specified by BuildSystem
val lSystem = p(BuildSystem)(p).suggestName("system") val lazySystem = LazyModule(p(BuildSystem)(p)).suggestName("system")
val system = withClockAndReset(systemClock, systemReset) { Module(lSystem.module) }
// Call all of the IOBinders and provide them with a default clock and reset // The implicitClockSinkNode provides the implicit clock and reset for the System
withClockAndReset(systemClock, systemReset) { val implicitClockSinkNode = ClockSinkNode(Seq(ClockSinkParameters()))
// Call each IOBinder on both the lazyModule instance and the module
// instance. Generally, an IOBinder PF should only be defined on one, so // Generate Clocks and Reset
// this should not lead to two invocations. p(ClockingSchemeKey)(this)
val (_ports, _iocells, _harnessFunctions) = p(IOBinders).values.flatMap(f => f(lSystem) ++ f(system)).unzip3
// NOTE: Making this a LazyRawModule is moderately dangerous, as anonymous children
// of ChipTop (ex: ClockGroup) do not receive clock or reset.
// However. anonymous children of ChipTop should not need an implicit Clock or Reset
// anyways, they probably need to be explicitly clocked.
lazy val module: LazyModuleImpLike = new LazyRawModuleImp(this) {
// These become the implicit clock and reset to the System
val implicit_clock = implicitClockSinkNode.in.head._1.clock
val implicit_reset = implicitClockSinkNode.in.head._1.reset
// Note: IOBinders cannot rely on the implicit clock/reset, as this is a LazyRawModuleImp
val (_ports, _iocells, _portMap) = ApplyIOBinders(lazySystem, p(IOBinders))
// We ignore _ports for now... // We ignore _ports for now...
iocells ++= _iocells.flatten iocells ++= _iocells
harnessFunctions ++= _harnessFunctions.flatten portMap ++= _portMap
}
// Connect the implicit clock/reset, if present
lazySystem.module match { case l: LazyModuleImp => {
l.clock := implicit_clock
l.reset := implicit_reset
}}
}
} }
/**
* A simple clock and reset implementation that punches out clock and reset ports with the same
* names as the implicit clock and reset for standard Module classes. Three basic reset schemes
* are provided. See [[GlobalResetScheme]].
*/
trait HasChipTopSimpleClockAndReset { this: BaseChipTop =>
val (clock, systemClockIO) = IOCell.generateIOFromSignal(systemClock, Some("iocell_clock"))
val (reset, systemResetIO) = p(GlobalResetSchemeKey) match {
case GlobalResetSynchronous =>
IOCell.generateIOFromSignal(systemReset, Some("iocell_reset"))
case GlobalResetAsynchronousFull =>
IOCell.generateIOFromSignal(systemReset, Some("iocell_reset"), abstractResetAsAsync = true)
case GlobalResetAsynchronous =>
val asyncResetCore = Wire(Input(AsyncReset()))
systemReset := ResetCatchAndSync(systemClock, asyncResetCore.asBool)
IOCell.generateIOFromSignal(asyncResetCore, Some("iocell_reset"), abstractResetAsAsync = true)
}
iocells ++= systemClockIO
iocells ++= systemResetIO
// Add a TestHarnessFunction that connects clock and reset
harnessFunctions += { (th: TestHarness) => {
// Connect clock; it's not done implicitly with RawModule
clock := th.clock
// Connect reset; it's not done implicitly with RawModule
// Note that we need to use dutReset, not harnessReset
reset := th.dutReset
Nil
} }
}
class ChipTop()(implicit p: Parameters) extends BaseChipTop()(p)
with HasChipTopSimpleClockAndReset

View File

@@ -0,0 +1,175 @@
package chipyard
import chisel3._
import scala.collection.mutable.{ArrayBuffer}
import freechips.rocketchip.prci._
import freechips.rocketchip.subsystem.{BaseSubsystem, SubsystemDriveAsyncClockGroupsKey}
import freechips.rocketchip.config.{Parameters, Field}
import freechips.rocketchip.diplomacy.{OutwardNodeHandle, InModuleBody, LazyModule}
import freechips.rocketchip.util.{ResetCatchAndSync, Pow2ClockDivider}
import barstools.iocell.chisel._
/**
* Chipyard provides three baseline, top-level reset schemes, set using the
* [[GlobalResetSchemeKey]] in a Parameters instance. These are:
*
* 1) Synchronous: The input coming to the chip is synchronous to the provided
* clocks and will be used without modification as a synchronous reset.
* This is safe only for use in FireSim and SW simulation.
*
* 2) Asynchronous: The input reset is asynchronous to the input clock, but it
* is caught and synchronized to that clock before it is dissemenated.
* Thus, downsteam modules will be emitted with synchronously reset state
* elements.
*
* 3) Asynchronous Full: The input reset is asynchronous to the input clock,
* and is used globally as an async reset. Downstream modules will be emitted
* with asynchronously reset state elements.
*
*/
sealed trait GlobalResetScheme {
def pinIsAsync: Boolean
}
sealed trait HasAsyncInput { self: GlobalResetScheme =>
def pinIsAsync = true
}
sealed trait HasSyncInput { self: GlobalResetScheme =>
def pinIsAsync = false
}
case object GlobalResetSynchronous extends GlobalResetScheme with HasSyncInput
case object GlobalResetAsynchronous extends GlobalResetScheme with HasAsyncInput
case object GlobalResetAsynchronousFull extends GlobalResetScheme with HasAsyncInput
case object GlobalResetSchemeKey extends Field[GlobalResetScheme](GlobalResetSynchronous)
/**
* A simple reset implementation that punches out reset ports
* for standard Module classes. Three basic reset schemes
* are provided. See [[GlobalResetScheme]].
*/
object GenerateReset {
def apply(chiptop: ChipTop, clock: Clock): Reset = {
implicit val p = chiptop.p
// this needs directionality so generateIOFromSignal works
val reset_wire = Wire(Input(Reset()))
val (reset_io, resetIOCell) = p(GlobalResetSchemeKey) match {
case GlobalResetSynchronous =>
IOCell.generateIOFromSignal(reset_wire, "reset")
case GlobalResetAsynchronousFull =>
IOCell.generateIOFromSignal(reset_wire, "reset", abstractResetAsAsync = true)
case GlobalResetAsynchronous => {
val async_reset_wire = Wire(Input(AsyncReset()))
reset_wire := ResetCatchAndSync(clock, async_reset_wire.asBool())
IOCell.generateIOFromSignal(async_reset_wire, "reset", abstractResetAsAsync = true)
}
}
chiptop.iocells ++= resetIOCell
chiptop.harnessFunctions += ((th: HasHarnessSignalReferences) => {
reset_io := th.dutReset
Nil
})
reset_wire
}
}
case object ClockingSchemeKey extends Field[ChipTop => Unit](ClockingSchemeGenerators.harnessClock)
object ClockingSchemeGenerators {
// A simple clock provider, for testing
val harnessClock: ChipTop => Unit = { 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.lazySystem match {
case l: BaseSubsystem if (p(SubsystemDriveAsyncClockGroupsKey).isEmpty) => {
val n = ClockGroupSourceNode(Seq(ClockGroupSourceParameters()))
l.asyncClockGroupsNode := n
Some(n)
}
case _ => None
}
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, "clock")
chiptop.iocells ++= clockIOCell
implicitClockSourceNode.out.unzip._1.map { o =>
o.clock := clock_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) => {
clock_io := th.harnessClock
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.lazySystem 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, "clock")
chiptop.iocells ++= clockIOCell
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

@@ -6,12 +6,13 @@ import chisel3.util.{log2Up}
import freechips.rocketchip.config.{Field, Parameters, Config} 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.BootROMParams 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}
import freechips.rocketchip.util.{AsyncResetReg} import freechips.rocketchip.util.{AsyncResetReg}
import freechips.rocketchip.prci._
import testchipip._ import testchipip._
import tracegen.{TraceGenSystem} import tracegen.{TraceGenSystem}
@@ -25,23 +26,15 @@ 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, TestSuitesKey, TestSuiteHelper} import chipyard.{BuildTop, BuildSystem, ClockingSchemeGenerators, ClockingSchemeKey, TestSuitesKey, TestSuiteHelper}
/**
* TODO: Why do we need this?
*/
object ConfigValName {
implicit val valName = ValName("TestHarness")
}
import ConfigValName._
// ----------------------- // -----------------------
// Common Config Fragments // Common Config Fragments
// ----------------------- // -----------------------
class WithBootROM extends Config((site, here, up) => { class WithBootROM extends Config((site, here, up) => {
case BootROMParams => BootROMParams( case BootROMLocated(x) => up(BootROMLocated(x), site).map(_.copy(contentFileName = s"./bootrom/bootrom.rv${site(XLen)}.img"))
contentFileName = s"./bootrom/bootrom.rv${site(XLen)}.img")
}) })
// DOC include start: gpio config fragment // DOC include start: gpio config fragment
@@ -73,7 +66,7 @@ class WithL2TLBs(entries: Int) extends Config((site, here, up) => {
}) })
class WithTracegenSystem extends Config((site, here, up) => { class WithTracegenSystem extends Config((site, here, up) => {
case BuildSystem => (p: Parameters) => LazyModule(new TraceGenSystem()(p)) case BuildSystem => (p: Parameters) => new TraceGenSystem()(p)
}) })
/** /**
@@ -105,7 +98,8 @@ class WithMultiRoCCHwacha(harts: Int*) extends Config(
case MultiRoCCKey => { case MultiRoCCKey => {
up(MultiRoCCKey, site) ++ harts.distinct.map{ i => up(MultiRoCCKey, site) ++ harts.distinct.map{ i =>
(i -> Seq((p: Parameters) => { (i -> Seq((p: Parameters) => {
LazyModule(new Hwacha()(p)).suggestName("hwacha") val hwacha = LazyModule(new Hwacha()(p))
hwacha
})) }))
} }
} }
@@ -156,3 +150,23 @@ class WithHwachaTest extends Config((site, here, up) => {
"SRC_EXTENSION = $(base_dir)/hwacha/$(src_path)/*.scala" + "\nDISASM_EXTENSION = --extension=hwacha" "SRC_EXTENSION = $(base_dir)/hwacha/$(src_path)/*.scala" + "\nDISASM_EXTENSION = --extension=hwacha"
} }
}) })
// The default RocketChip BaseSubsystem drives its diplomatic clock graph
// with the implicit clocks of Subsystem. Don't do that, instead we extend
// the diplomacy graph upwards into the ChipTop, where we connect it to
// our clock drivers
class WithNoSubsystemDrivenClocks extends Config((site, here, up) => {
case SubsystemDriveAsyncClockGroupsKey => None
})
class WithTileDividedClock extends Config((site, here, up) => {
case ClockingSchemeKey => ClockingSchemeGenerators.harnessDividedClock
})
class WithDMIDTM extends Config((site, here, up) => {
case ExportDebug => up(ExportDebug, site).copy(protocols = Set(DMI))
})
class WithNoDebug extends Config((site, here, up) => {
case DebugModuleKey => None
})

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
@@ -32,12 +32,9 @@ 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 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,259 @@
package chipyard.harness
import chisel3._
import chisel3.experimental.{Analog}
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, map: Map[String, (Any, HasHarnessSignalReferences, Seq[Data]) => Seq[Any]], portMap: Map[String, Seq[Data]]) = {
val pm = portMap.withDefaultValue(Nil)
map.map { case (s, f) => f(sys, th, pm(s)) ++ f(sys.module, th, pm(s)) }
}
}
class OverrideHarnessBinder[T, S <: Data](fn: => (T, HasHarnessSignalReferences, Seq[S]) => Seq[Any])(implicit tag: ClassTag[T], ptag: ClassTag[S]) 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: S => p})
require (pts.length == ports.length, s"Port type mismatch between IOBinder and HarnessBinder: ${ptag}")
t match {
case system: T => fn(system, th, pts)
case _ => Nil
}
})
)
})
class ComposeHarnessBinder[T, S <: Data](fn: => (T, HasHarnessSignalReferences, Seq[S]) => Seq[Any])(implicit tag: ClassTag[T], ptag: ClassTag[S]) 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: S => p})
require (pts.length == ports.length, s"Port type mismatch between IOBinder and HarnessBinder: ${ptag}")
t match {
case system: T => up(HarnessBinders, site)(tag.runtimeClass.toString)(system, th, pts) ++ fn(system, th, pts)
case _ => Nil
}
})
)
})
class WithGPIOTiedOff extends OverrideHarnessBinder({
(system: HasPeripheryGPIOModuleImp, th: HasHarnessSignalReferences, ports: Seq[Analog]) => {
ports.foreach { _ <> AnalogConst(0) }
Nil
}
})
// DOC include start: WithUARTAdapter
class WithUARTAdapter extends OverrideHarnessBinder({
(system: HasPeripheryUARTModuleImp, th: HasHarnessSignalReferences, ports: Seq[UARTPortIO]) => {
UARTAdapter.connect(ports)(system.p)
Nil
}
})
// DOC include end: WithUARTAdapter
class WithSimSPIFlashModel(rdOnly: Boolean = true) extends OverrideHarnessBinder({
(system: HasPeripherySPIFlashModuleImp, th: HasHarnessSignalReferences, ports: Seq[SPIChipIO]) => {
SimSPIFlashModel.connect(ports, th.harnessReset, rdOnly)(system.p)
Nil
}
})
class WithSimBlockDevice extends OverrideHarnessBinder({
(system: CanHavePeripheryBlockDevice, th: 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: 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: 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: 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: 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: 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: 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: HasHarnessSignalReferences, ports: Seq[UInt]) => {
ports.foreach { _ := 0.U }
Nil
}
})
class WithTieOffL2FBusAXI extends OverrideHarnessBinder({
(system: CanHaveSlaveAXI4Port, th: HasHarnessSignalReferences, ports: Seq[ClockedIO[AXI4Bundle]]) => {
ports.foreach({ p => p := DontCare; p.bits.tieoff() })
Nil
}
})
class WithSimDebug extends OverrideHarnessBinder({
(system: HasPeripheryDebugModuleImp, th: 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: 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: 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: 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: HasHarnessSignalReferences, ports: Seq[Bool]) => {
ports.map { p => when (p) { th.success := true.B } }
Nil
}
})
class WithSimDromajoBridge extends ComposeHarnessBinder({
(system: CanHaveTraceIOModuleImp, th: 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.TestHarness) => 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,14 +72,18 @@ object GetSystemParameters {
} }
} }
class IOBinder(f: (View, View, View) => PartialFunction[Any, Any]) extends Config(f)
// This macro overrides previous matches on some Top mixin. This is useful for // This macro overrides previous matches on some Top mixin. This is useful for
// binders which drive IO, since those typically cannot be composed // 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) => { class OverrideIOBinder[T, S <: Data](fn: => (T) => (Seq[S], Seq[IOCell]))(implicit tag: ClassTag[T]) extends IOBinder((site, here, up) => {
case IOBinders => up(IOBinders, site) + (tag.runtimeClass.toString -> case IOBinders => up(IOBinders, site) + (tag.runtimeClass.toString ->
((t: Any) => { ((t: Any) => {
t match { t match {
case system: T => fn(system) case system: T =>
case _ => Nil val (ports, cells) = fn(system)
(ports, cells)
case _ => (Nil, Nil)
} }
}) })
) )
@@ -82,32 +91,44 @@ class OverrideIOBinder[T](fn: => (T) => Seq[IOBinderTuple])(implicit tag: ClassT
// 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((site, here, up) => {
case IOBinders => up(IOBinders, site) + (tag.runtimeClass.toString -> case IOBinders => up(IOBinders, site) + (tag.runtimeClass.toString ->
((t: Any) => { ((t: Any) => {
t match { t match {
case system: T => (up(IOBinders, site)(tag.runtimeClass.toString)(system) case system: T =>
++ fn(system)) val r = up(IOBinders, site)(tag.runtimeClass.toString)(system)
case _ => Nil val h = fn(system)
val ports = r._1 ++ h._1
val cells = r._2 ++ h._2
(ports, cells)
case _ => (Nil, Nil)
} }
}) })
) )
}) })
// DOC include end: IOBinders object BoreHelper {
def apply(name: String, source: Clock): Clock = {
val clock_io = IO(Output(Clock())).suggestName(name)
val clock_wire = Wire(Clock()).suggestName(s"chiptop_${name}")
dontTouch(clock_wire)
clock_wire := false.B.asClock // necessary for BoringUtils to work properly
BoringUtils.bore(source, Seq(clock_wire))
clock_io := clock_wire
clock_io
}
}
object AddIOCells {
/** case object IOCellKey extends Field[IOCellTypeParams](GenericIOCellParams())
* Add IO cells to a SiFive GPIO devices and name the IO ports.
* @param gpios A Seq of GPIO port bundles
* @param genFn A callable function to generate a DigitalGPIOCell module to use class WithGPIOCells extends OverrideIOBinder({
* @return Returns a tuple of (a 2D Seq of Analog IOs corresponding to individual GPIO pins; a 2D Seq of IOCell module references) (system: HasPeripheryGPIOModuleImp) => {
*/ val (ports2d, cells2d) = system.gpio.zipWithIndex.map({ case (gpio, i) =>
def gpio(gpios: Seq[GPIOPortIO], genFn: () => DigitalGPIOCell = IOCell.genericGPIO): (Seq[Seq[Analog]], Seq[Seq[IOCell]]) = {
gpios.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 +137,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,279 +178,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.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.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: chipyard.TestHarness) => { 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: chipyard.TestHarness) => { 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: chipyard.TestHarness) => { SimSPIFlashModel.connect(ports, th.reset, 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: chipyard.TestHarness) => {
SimBlockDevice.connect(th.clock, th.reset.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: chipyard.TestHarness) => {
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: chipyard.TestHarness) => { // 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: chipyard.TestHarness) => {
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
mem.io.clock := th.clock
mem.io.reset := th.reset
} }
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: chipyard.TestHarness) => { 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: chipyard.TestHarness) => { 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: chipyard.TestHarness) => {
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)))
}
})
class WithTiedOffDebug extends OverrideIOBinder({
(system: HasPeripheryDebugModuleImp) => {
val (psdPort, resetctrlOpt, debugPortOpt, ioCells) =
AddIOCells.debug(system.psd, system.resetctrl, system.debug)(system.p)
val harnessFn = (th: chipyard.TestHarness) => {
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.clock })
d.dmactiveAck := DontCare
d.clock := th.clock
}
Nil
}
Seq((Seq(psdPort) ++ resetctrlOpt ++ debugPortOpt.toSeq, Nil, Some(harnessFn)))
}
})
class WithSimDebug extends OverrideIOBinder({
(system: HasPeripheryDebugModuleImp) => {
val (psdPort, resetctrlPortOpt, debugPortOpt, ioCells) =
AddIOCells.debug(system.psd, system.resetctrl, system.debug)(system.p)
val harnessFn = (th: chipyard.TestHarness) => {
val dtm_success = Wire(Bool())
Debug.connectDebug(debugPortOpt, resetctrlPortOpt, psdPort, th.clock, th.harnessReset, dtm_success)(system.p)
when (dtm_success) { th.success := true.B }
th.dutReset := th.harnessReset | 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: chipyard.TestHarness) => {
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: chipyard.TestHarness) => {
val ser_success = SerialAdapter.connectSimSerial(port, th.clock, 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: chipyard.TestHarness) => { 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

@@ -8,6 +8,7 @@ package chipyard
import chisel3._ import chisel3._
import chisel3.internal.sourceinfo.{SourceInfo} import chisel3.internal.sourceinfo.{SourceInfo}
import freechips.rocketchip.prci._
import freechips.rocketchip.config.{Field, Parameters} import freechips.rocketchip.config.{Field, Parameters}
import freechips.rocketchip.devices.tilelink._ import freechips.rocketchip.devices.tilelink._
import freechips.rocketchip.devices.debug.{HasPeripheryDebug, HasPeripheryDebugModuleImp, ExportDebug} import freechips.rocketchip.devices.debug.{HasPeripheryDebug, HasPeripheryDebugModuleImp, ExportDebug}
@@ -24,14 +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 {
@@ -47,7 +47,6 @@ trait CanHaveHTIF { this: BaseSubsystem =>
} }
} }
class ChipyardSubsystem(implicit p: Parameters) extends BaseSubsystem class ChipyardSubsystem(implicit p: Parameters) extends BaseSubsystem
with HasTiles with HasTiles
with CanHaveHTIF with CanHaveHTIF
@@ -56,25 +55,17 @@ class ChipyardSubsystem(implicit p: Parameters) extends BaseSubsystem
case r: RocketTile => r.module.core.rocketImpl.coreMonitorBundle case r: RocketTile => r.module.core.rocketImpl.coreMonitorBundle
case b: BoomTile => b.module.core.coreMonitorBundle case b: BoomTile => b.module.core.coreMonitorBundle
}.toList }.toList
override lazy val module = new ChipyardSubsystemModuleImp(this) override lazy val module = new ChipyardSubsystemModuleImp(this)
} }
class ChipyardSubsystemModuleImp[+L <: ChipyardSubsystem](_outer: L) extends BaseSubsystemModuleImp(_outer) class ChipyardSubsystemModuleImp[+L <: ChipyardSubsystem](_outer: L) extends BaseSubsystemModuleImp(_outer)
with HasResetVectorWire
with HasTilesModuleImp with HasTilesModuleImp
{ {
for (i <- 0 until outer.tiles.size) {
val wire = tile_inputs(i)
wire.hartid := outer.hartIdList(i).U
wire.reset_vector := global_reset_vector
}
// create file with core params // create file with core params
ElaborationArtefacts.add("""core.config""", outer.tiles.map(x => x.module.toString).mkString("\n")) ElaborationArtefacts.add("""core.config""", outer.tiles.map(x => x.module.toString).mkString("\n"))
// Generate C header with relevant information for Dromajo // Generate C header with relevant information for Dromajo
// This is included in the `dromajo_params.h` header file // This is included in the `dromajo_params.h` header file
DromajoHelper.addArtefacts() DromajoHelper.addArtefacts(InSubsystem)
} }

View File

@@ -26,8 +26,10 @@ class ChipyardSystem(implicit p: Parameters) extends ChipyardSubsystem
with CanHaveMasterAXI4MemPort with CanHaveMasterAXI4MemPort
with CanHaveMasterAXI4MMIOPort with CanHaveMasterAXI4MMIOPort
with CanHaveSlaveAXI4Port with CanHaveSlaveAXI4Port
with HasPeripheryBootROM
{ {
val bootROM = p(BootROMLocated(location)).map { BootROM.attach(_, this, CBUS) }
val maskROMs = p(MaskROMLocated(location)).map { MaskROM.attach(_, this, CBUS) }
override lazy val module = new ChipyardSystemModule(this) override lazy val module = new ChipyardSystemModule(this)
} }
@@ -37,5 +39,4 @@ class ChipyardSystem(implicit p: Parameters) extends ChipyardSubsystem
class ChipyardSystemModule[+L <: ChipyardSystem](_outer: L) extends ChipyardSubsystemModuleImp(_outer) class ChipyardSystemModule[+L <: ChipyardSystem](_outer: L) extends ChipyardSubsystemModuleImp(_outer)
with HasRTCModuleImp with HasRTCModuleImp
with HasExtInterruptsModuleImp with HasExtInterruptsModuleImp
with HasPeripheryBootROMModuleImp
with DontTouch with DontTouch

View File

@@ -1,37 +1,50 @@
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.config.ConfigValName._ import chipyard.harness.{ApplyHarnessBinders, HarnessBinders}
// ------------------------------- // -------------------------------
// BOOM and/or Rocket Test Harness // Chipyard Test Harness
// ------------------------------- // -------------------------------
case object BuildTop extends Field[Parameters => HasTestHarnessFunctions]((p: Parameters) => Module(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]]()
} }
class TestHarness(implicit val p: Parameters) extends Module { trait HasHarnessSignalReferences {
def harnessClock: Clock
def harnessReset: Reset
def dutReset: Reset
def success: Bool
}
class TestHarness(implicit val p: Parameters) extends Module with HasHarnessSignalReferences {
val io = IO(new Bundle { val io = IO(new Bundle {
val success = Output(Bool()) val success = Output(Bool())
}) })
val dut = p(BuildTop)(p) val lazyDut = LazyModule(p(BuildTop)(p)).suggestName("chiptop")
val dut = Module(lazyDut.module)
io.success := false.B io.success := false.B
val harnessClock = clock
val harnessReset = WireInit(reset)
val success = io.success
// 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)
dut.harnessFunctions.foreach(_(this)) lazyDut match { case d: HasTestHarnessFunctions =>
d.harnessFunctions.foreach(_(this))
def success = io.success ApplyHarnessBinders(this, d.lazySystem, p(HarnessBinders), d.portMap.toMap)
def harnessReset = this.reset.asBool }
} }

View File

@@ -5,18 +5,45 @@ 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 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,14 +104,14 @@ 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)
@@ -135,8 +126,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,37 +141,49 @@ 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(
new chipyard.config.WithTileDividedClock ++ // Put the Tile on its own clock domain
new freechips.rocketchip.subsystem.WithRationalRocketTiles ++ // Add rational crossings between RocketTile and uncore
new freechips.rocketchip.subsystem.WithNBigCores(1) ++
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

@@ -3,46 +3,37 @@ 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 tracegen.WithTraceGen()(List.fill(2) { DCacheParams(nMSHRs = 0, nSets = 16, nWays = 2) }) ++ new chipyard.config.WithNoSubsystemDrivenClocks ++
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 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 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 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 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,26 +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
// 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.
@@ -42,29 +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 ++
// 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
@@ -73,61 +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 ++
// 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 ++
// 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,13 +8,13 @@ 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.amba.axi4.{AXI4Bundle}
import freechips.rocketchip.subsystem.{CanHaveMasterAXI4MemPort, HasExtInterruptsModuleImp, BaseSubsystem, HasTilesModuleImp} import freechips.rocketchip.subsystem.{CanHaveMasterAXI4MemPort, HasExtInterruptsModuleImp, BaseSubsystem, HasTilesModuleImp}
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}
@@ -25,73 +25,119 @@ 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: HasHarnessSignalReferences, ports: Seq[ClockedIO[SerialIO]]) => {
system.net.foreach(n => NICBridge(system.clock, n)(system.p)); Nil ports.map { p =>
val ram = SerialAdapter.connectHarnessRAM(system.serdesser.get, p, th.harnessReset)
withClockAndReset(p.clock, th.harnessReset) {
SerialBridge(p.clock, ram.module.io.tsi_ser, MainMemoryConsts.globalName)(GetSystemParameters(system))
}
}
Nil
}
}) })
class WithUARTBridge extends OverrideIOBinder({ class WithNICBridge extends OverrideHarnessBinder({
(system: HasPeripheryUARTModuleImp) => (system: CanHavePeripheryIceNIC, th: HasHarnessSignalReferences, ports: Seq[ClockedIO[NICIOvonly]]) => {
system.uart.foreach(u => UARTBridge(system.clock, u)(system.p)); Nil val p: Parameters = GetSystemParameters(system)
ports.map { n => withClockAndReset(n.clock, th.harnessReset) { NICBridge(n.clock, n.bits)(p) } }
Nil
}
}) })
class WithBlockDeviceBridge extends OverrideIOBinder({ class WithUARTBridge extends OverrideHarnessBinder({
(system: CanHavePeripheryBlockDeviceModuleImp) => (system: HasPeripheryUARTModuleImp, th: HasHarnessSignalReferences, 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: HasHarnessSignalReferences, ports: Seq[ClockedIO[BlockDeviceIO]]) => {
(system: CanHaveMasterAXI4MemPort) => {
implicit val p: Parameters = GetSystemParameters(system) implicit val p: Parameters = GetSystemParameters(system)
(system.mem_axi4 zip system.memAXI4Node.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: HasHarnessSignalReferences, 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: HasHarnessSignalReferences, ports: Seq[TraceOutputTop]) => {
system.traceIO.foreach(_.traces.map(tileTrace => TracerVBridge(tileTrace)(system.p))); Nil ports.map { p =>
}) p.traces.map(
tileTrace => withClockAndReset(tileTrace.clock, tileTrace.reset) { TracerVBridge(tileTrace)(system.p) }
)
}
class WithDromajoBridge extends ComposeIOBinder({ Nil
(system: CanHaveTraceIOModuleImp) => {
system.traceIO.foreach(_.traces.map(tileTrace => DromajoBridge(tileTrace)(system.p))); Nil
} }
}) })
class WithDromajoBridge extends ComposeHarnessBinder({
(system: CanHaveTraceIOModuleImp, th: HasHarnessSignalReferences, 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: HasHarnessSignalReferences, ports: Seq[Bool]) =>
ports.map { p => GroundTestBridge(th.harnessClock, p)(system.p) }; Nil
}) })
class WithFireSimMultiCycleRegfile extends ComposeIOBinder({ class WithFireSimMultiCycleRegfile extends ComposeIOBinder({
@@ -105,52 +151,25 @@ 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({
(system: HasPeripheryGPIOModuleImp) =>
system.gpio.foreach(_.pins.foreach(_.i.ival := false.B)); Nil
})
class WithTiedOffSystemDebug extends OverrideIOBinder({
(system: HasPeripheryDebugModuleImp) => {
Debug.tieoffDebug(system.debug, system.resetctrl, Some(system.psd))(system.p)
// tieoffDebug doesn't actually tie everything off :/
system.debug.foreach { d =>
d.clockeddmi.foreach({ cdmi => cdmi.dmi.req.bits := DontCare })
d.dmactiveAck := DontCare
}
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 WithTracerVBridge ++
new WithFireSimIOCellModels
) )

View File

@@ -3,14 +3,19 @@
package firesim.firesim package firesim.firesim
import chisel3._ import chisel3._
import chisel3.experimental.{IO}
import freechips.rocketchip.prci._
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} import freechips.rocketchip.diplomacy.{LazyModule, InModuleBody}
import freechips.rocketchip.util.{ResetCatchAndSync}
import midas.widgets.{Bridge, PeekPokeBridge, RationalClockBridge} import midas.widgets.{Bridge, PeekPokeBridge, RationalClockBridge, RationalClock}
import chipyard.{BuildSystem} import chipyard._
import chipyard.iobinders.{IOBinders} import chipyard.harness._
import chipyard.iobinders._
// 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
@@ -20,6 +25,16 @@ 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 {
@@ -28,33 +43,130 @@ object NodeIdx {
def apply(): Int = idx def apply(): Int = idx
} }
class FireSim(implicit val p: Parameters) extends RawModule { class WithFireSimSimpleClocks extends Config((site, here, up) => {
freechips.rocketchip.util.property.cover.setPropLib(new midas.passes.FireSimPropertyLibrary()) case ClockingSchemeKey => { chiptop: ChipTop =>
val clockBridge = Module(new RationalClockBridge) implicit val p = chiptop.p
val clock = clockBridge.io.clocks.head
val reset = WireInit(false.B) val implicitClockSourceNode = ClockSourceNode(Seq(ClockSourceParameters()))
withClockAndReset(clock, reset) { chiptop.implicitClockSinkNode := implicitClockSourceNode
// Instantiate multiple instances of the DUT to implement supernode
val targets = Seq.fill(p(NumNodes)) { // Drive the diplomaticclock graph of the DigitalTop (if present)
// It's not a RC bump without some hacks... val simpleClockGroupSourceNode = chiptop.lazySystem match {
// Copy the AsyncClockGroupsKey to generate a fresh node on each case l: BaseSubsystem if (p(SubsystemDriveAsyncClockGroupsKey).isEmpty) => {
// instantiation of the dut, otherwise the initial instance will be val n = ClockGroupSourceNode(Seq(ClockGroupSourceParameters()))
// reused across each node l.asyncClockGroupsNode := n
import freechips.rocketchip.subsystem.AsyncClockGroupsKey Some(n)
val lazyModule = p(BuildSystem)(p.alterPartial({ }
case AsyncClockGroupsKey => p(AsyncClockGroupsKey).copy case _ => None
}))
(lazyModule, Module(lazyModule.module))
} }
val peekPokeBridge = PeekPokeBridge(clock, reset) InModuleBody {
// A Seq of partial functions that will instantiate the right bridge only val clock = IO(Input(Clock())).suggestName("clock")
// if that Mixin trait is present in the target's LazyModule class instance val reset = IO(Input(Reset())).suggestName("reset")
//
// Apply each partial function to each DUT instance implicitClockSourceNode.out.unzip._1.map { o =>
for ((lazyModule, module) <- targets) { o.clock := clock
p(IOBinders).values.foreach(f => f(lazyModule) ++ f(module)) o.reset := reset
NodeIdx.increment() }
simpleClockGroupSourceNode.map { n => n.out.unzip._1.map { out: ClockGroupBundle =>
out.member.data.foreach { o =>
o.clock := clock
o.reset := reset
}
}}
chiptop.harnessFunctions += ((th: HasHarnessSignalReferences) => {
clock := th.harnessClock
reset := th.harnessReset
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.lazySystem 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 {
freechips.rocketchip.util.property.cover.setPropLib(new midas.passes.FireSimPropertyLibrary())
val clockBridge = Module(new RationalClockBridge(p(FireSimClockKey).additionalClocks:_*))
val harnessClock = clockBridge.io.clocks.head // This is the reference clock
val additionalClocks = clockBridge.io.clocks.tail
val harnessReset = WireInit(false.B)
val peekPokeBridge = PeekPokeBridge(harnessClock, harnessReset)
def dutReset = { require(false, "dutReset should not be used in Firesim"); false.B }
def success = { require(false, "success should not be used in Firesim"); false.B }
// Instantiate multiple instances of the DUT to implement supernode
for (i <- 0 until p(NumNodes)) {
// It's not a RC bump without some hacks...
// Copy the AsyncClockGroupsKey to generate a fresh node on each
// instantiation of the dut, otherwise the initial instance will be
// reused across each node
import freechips.rocketchip.subsystem.AsyncClockGroupsKey
val lazyModule = LazyModule(p(BuildTop)(p.alterPartial({
case AsyncClockGroupsKey => p(AsyncClockGroupsKey).copy
})))
val module = Module(lazyModule.module)
lazyModule match { case d: HasTestHarnessFunctions =>
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()
}
} }

View File

@@ -1,107 +0,0 @@
//See LICENSE for license details.
package firesim.firesim
import chisel3._
import freechips.rocketchip.config.{Field, Config, Parameters}
import freechips.rocketchip.diplomacy.{LazyModule, LazyModuleImp, RationalCrossing}
import freechips.rocketchip.subsystem._
import freechips.rocketchip.util.{ResetCatchAndSync}
import midas.widgets.{Bridge, PeekPokeBridge, RationalClockBridge, RationalClock}
import firesim.configs._
import boom.common.{WithRationalBoomTiles}
import chipyard.{BuildSystem, DigitalTop, DigitalTopModule}
import chipyard.config.ConfigValName._
import chipyard.iobinders.{IOBinders}
// WIP! This file is a sketch of one means of defining a multiclock target-design
// that can be simulated in FireSim, pending a canonicalized form in Chipyard.
//
// 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()))
trait HasAdditionalClocks extends LazyModuleImp {
val clocks = IO(Vec(p(FireSimClockKey).numClocks, Input(Clock())))
}
// Presupposes only 1 or 2 clocks.
trait HasFireSimClockingImp extends HasAdditionalClocks {
val outer: HasTiles
val (tileClock, tileReset) = p(FireSimClockKey).additionalClocks.headOption match {
case Some(RationalClock(_, numer, denom)) if numer != denom => (clocks(1), ResetCatchAndSync(clocks(1), reset.toBool))
case None => (clocks.head, reset)
}
outer.tiles.foreach({ case tile =>
tile.module.clock := tileClock
tile.module.reset := tileReset
})
}
// Config Fragment
class WithSingleRationalTileDomain(multiplier: Int, divisor: Int) extends Config(
new WithRationalRocketTiles ++
new WithRationalBoomTiles ++
new Config((site, here, up) => {
case FireSimClockKey => FireSimClockParameters(Seq(RationalClock("TileDomain", multiplier, divisor)))
})
)
class HalfRateUncore extends WithSingleRationalTileDomain(2,1)
class WithFiresimMulticlockTop extends Config((site, here, up) => {
case BuildSystem => (p: Parameters) => LazyModule(new FiresimMulticlockTop()(p)).suggestName("system")
})
// Complete Config
class FireSimQuadRocketMulticlockConfig extends Config(
new HalfRateUncore ++
new WithFiresimMulticlockTop ++
new FireSimQuadRocketConfig)
// Top Definition
class FiresimMulticlockTop(implicit p: Parameters) extends chipyard.DigitalTop
{
override lazy val module = new FiresimMulticlockTopModule(this)
}
class FiresimMulticlockTopModule[+L <: DigitalTop](l: L) extends chipyard.DigitalTopModule(l) with HasFireSimClockingImp
// Harness Definition
class FireSimMulticlockPOC(implicit val p: Parameters) extends RawModule {
freechips.rocketchip.util.property.cover.setPropLib(new midas.passes.FireSimPropertyLibrary())
val clockBridge = Module(new RationalClockBridge(p(FireSimClockKey).additionalClocks:_*))
val refClock = clockBridge.io.clocks.head
val reset = WireInit(false.B)
withClockAndReset(refClock, reset) {
// Instantiate multiple instances of the DUT to implement supernode
val targets = Seq.fill(p(NumNodes)) {
val lazyModule = p(BuildSystem)(p)
(lazyModule, Module(lazyModule.module))
}
val peekPokeBridge = PeekPokeBridge(refClock, reset)
// A Seq of partial functions that will instantiate the right bridge only
// if that Mixin trait is present in the target's class instance
//
// Apply each partial function to each DUT instance
for ((lazyModule, module) <- targets) {
p(IOBinders).values.foreach(f => f(lazyModule) ++ f(module))
}
targets.collect({ case (_, t: HasAdditionalClocks) => t.clocks := clockBridge.io.clocks })
}
}

View File

@@ -10,10 +10,10 @@ import freechips.rocketchip.tile._
import freechips.rocketchip.tilelink._ import freechips.rocketchip.tilelink._
import freechips.rocketchip.rocket.DCacheParams import freechips.rocketchip.rocket.DCacheParams
import freechips.rocketchip.subsystem._ import freechips.rocketchip.subsystem._
import freechips.rocketchip.devices.tilelink.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}
@@ -22,19 +22,18 @@ import testchipip.WithRingSystemBus
import firesim.bridges._ import firesim.bridges._
import firesim.configs._ import firesim.configs._
import chipyard.config.ConfigValName._
class WithBootROM extends Config((site, here, up) => { class WithBootROM extends Config((site, here, up) => {
case BootROMParams => { case BootROMLocated(x) => {
val chipyardBootROM = new File(s"./generators/testchipip/bootrom/bootrom.rv${site(XLen)}.img") val chipyardBootROM = new File(s"./generators/testchipip/bootrom/bootrom.rv${site(XLen)}.img")
val firesimBootROM = new File(s"./target-rtl/chipyard/generators/testchipip/bootrom/bootrom.rv${site(XLen)}.img") val firesimBootROM = new File(s"./target-rtl/chipyard/generators/testchipip/bootrom/bootrom.rv${site(XLen)}.img")
val bootROMPath = if (chipyardBootROM.exists()) { val bootROMPath = if (chipyardBootROM.exists()) {
chipyardBootROM.getAbsolutePath() chipyardBootROM.getAbsolutePath()
} else { } else {
firesimBootROM.getAbsolutePath() firesimBootROM.getAbsolutePath()
} }
BootROMParams(contentFileName = bootROMPath) up(BootROMLocated(x), site).map(_.copy(contentFileName = bootROMPath))
} }
}) })
@@ -67,6 +66,8 @@ class WithNVDLASmall extends nvidia.blocks.dla.WithNVDLA("small")
// Tweaks that are generally applied to all firesim configs // Tweaks that are generally applied to all firesim configs
class WithFireSimConfigTweaks extends Config( class WithFireSimConfigTweaks extends Config(
// Required*: Uses FireSim ClockBridge and PeekPokeBridge to drive the system with a single clock/reset
new WithFireSimSimpleClocks ++
// Required*: When using FireSim-as-top to provide a correct path to the target bootrom source // Required*: When using FireSim-as-top to provide a correct path to the target bootrom source
new WithBootROM ++ new WithBootROM ++
// Optional*: Removing this will require adjusting the UART baud rate and // Optional*: Removing this will require adjusting the UART baud rate and
@@ -83,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
) )
/******************************************************************************* /*******************************************************************************
@@ -128,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) ++
@@ -186,3 +189,14 @@ class FireSimArianeConfig extends Config(
new WithDefaultMemModel ++ new WithDefaultMemModel ++
new WithFireSimConfigTweaks ++ new WithFireSimConfigTweaks ++
new chipyard.ArianeConfig) new chipyard.ArianeConfig)
//**********************************************************************************
//* Multiclock Configurations
//*********************************************************************************/
class FireSimMulticlockRocketConfig extends Config(
new WithFireSimRationalTileDomain(2, 1) ++
new WithDefaultFireSimBridges ++
new WithDefaultMemModel ++
new WithFireSimConfigTweaks ++
new chipyard.DividedClockRocketConfig)

View File

@@ -106,8 +106,8 @@ class BoomF1Tests extends FireSimTestSuite("FireSim", "DDR3FRFCFSLLC4MB_FireSimL
class RocketNICF1Tests extends FireSimTestSuite("FireSim", "WithNIC_DDR3FRFCFSLLC4MB_FireSimRocketConfig", "BaseF1Config") class RocketNICF1Tests extends FireSimTestSuite("FireSim", "WithNIC_DDR3FRFCFSLLC4MB_FireSimRocketConfig", "BaseF1Config")
// Multiclock tests // Multiclock tests
class RocketMulticlockF1Tests extends FireSimTestSuite( class RocketMulticlockF1Tests extends FireSimTestSuite(
"FireSimMulticlockPOC", "FireSim",
"FireSimQuadRocketMulticlockConfig", "FireSimMulticlockRocketConfig",
"WithSynthAsserts_BaseF1Config") "WithSynthAsserts_BaseF1Config")
class ArianeF1Tests extends FireSimTestSuite("FireSim", "WithNIC_DDR3FRFCFSLLC4MB_FireSimArianeConfig", "BaseF1Config") class ArianeF1Tests extends FireSimTestSuite("FireSim", "WithNIC_DDR3FRFCFSLLC4MB_FireSimArianeConfig", "BaseF1Config")

View File

@@ -12,6 +12,10 @@ class TraceGenSystem(implicit p: Parameters) extends BaseSubsystem
with CanHaveMasterAXI4MemPort { with CanHaveMasterAXI4MemPort {
def coreMonitorBundles = Nil def coreMonitorBundles = Nil
val tileStatusNodes = tiles.collect {
case t: GroundTestTile => t.statusNode.makeSink()
case t: BoomTraceGenTile => t.statusNode.makeSink()
}
override lazy val module = new TraceGenSystemModuleImp(this) override lazy val module = new TraceGenSystemModuleImp(this)
} }
@@ -20,12 +24,8 @@ class TraceGenSystemModuleImp(outer: TraceGenSystem)
{ {
val success = IO(Output(Bool())) val success = IO(Output(Bool()))
outer.tiles.zipWithIndex.map { case(t, i) => t.module.constants.hartid := i.U } val status = dontTouch(DebugCombiner(outer.tileStatusNodes.map(_.bundle)))
val status = dontTouch(DebugCombiner(outer.tiles.collect {
case t: GroundTestTile => t.module.status
case t: BoomTraceGenTile => t.module.status
}))
success := outer.tileCeaseSinkNode.in.head._1.asUInt.andR success := outer.tileCeaseSinkNode.in.head._1.asUInt.andR
} }

View File

@@ -3,7 +3,7 @@ package tracegen
import chisel3._ import chisel3._
import chisel3.util._ import chisel3.util._
import freechips.rocketchip.config.Parameters import freechips.rocketchip.config.Parameters
import freechips.rocketchip.diplomacy.{SimpleDevice, LazyModule, SynchronousCrossing, ClockCrossingType} import freechips.rocketchip.diplomacy.{SimpleDevice, LazyModule, SynchronousCrossing, ClockCrossingType, BundleBridgeSource}
import freechips.rocketchip.groundtest._ import freechips.rocketchip.groundtest._
import freechips.rocketchip.rocket._ import freechips.rocketchip.rocket._
import freechips.rocketchip.rocket.constants.{MemoryOpConstants} import freechips.rocketchip.rocket.constants.{MemoryOpConstants}
@@ -206,11 +206,13 @@ class BoomTraceGenTile private(
val cpuDevice: SimpleDevice = new SimpleDevice("groundtest", Nil) val cpuDevice: SimpleDevice = new SimpleDevice("groundtest", Nil)
val intOutwardNode: IntOutwardNode = IntIdentityNode() val intOutwardNode: IntOutwardNode = IntIdentityNode()
val slaveNode: TLInwardNode = TLIdentityNode() val slaveNode: TLInwardNode = TLIdentityNode()
val statusNode = BundleBridgeSource(() => new GroundTestStatus)
val boom_params = p.alterMap(Map(TileKey -> BoomTileParams( val boom_params = p.alterMap(Map(TileKey -> BoomTileParams(
dcache=params.dcache, dcache=params.dcache,
core=BoomCoreParams(nPMPs=0, numLdqEntries=32, numStqEntries=32, useVM=false)))) core=BoomCoreParams(nPMPs=0, numLdqEntries=16, numStqEntries=16, useVM=false))))
val dcache = LazyModule(new BoomNonBlockingDCache(hartId)(boom_params)) val dcache = LazyModule(new BoomNonBlockingDCache(staticIdForMetadataUseOnly)(boom_params))
val masterNode: TLOutwardNode = TLIdentityNode() := visibilityNode := dcache.node val masterNode: TLOutwardNode = TLIdentityNode() := visibilityNode := dcache.node
@@ -220,11 +222,11 @@ class BoomTraceGenTile private(
class BoomTraceGenTileModuleImp(outer: BoomTraceGenTile) class BoomTraceGenTileModuleImp(outer: BoomTraceGenTile)
extends BaseTileModuleImp(outer){ extends BaseTileModuleImp(outer){
val status = IO(new GroundTestStatus) val status = outer.statusNode.bundle
val halt_and_catch_fire = None val halt_and_catch_fire = None
val tracegen = Module(new TraceGenerator(outer.params.traceParams)) val tracegen = Module(new TraceGenerator(outer.params.traceParams))
tracegen.io.hartid := constants.hartid tracegen.io.hartid := outer.hartIdSinkNode.bundle
val ptw = Module(new DummyPTW(1)) val ptw = Module(new DummyPTW(1))
val lsu = Module(new LSU()(outer.boom_params, outer.dcache.module.edge)) val lsu = Module(new LSU()(outer.boom_params, outer.dcache.module.edge))

View File

@@ -1,11 +1,15 @@
// See LICENSE.SiFive for license details. // See LICENSE.SiFive for license details.
// See LICENSE.Berkeley for license details. // See LICENSE.Berkeley for license details.
#include "verilated.h"
#if VM_TRACE #if VM_TRACE
#include <memory> #include <memory>
#if CY_FST_TRACE
#include "verilated_fst_c.h"
#else
#include "verilated.h"
#include "verilated_vcd_c.h" #include "verilated_vcd_c.h"
#endif #endif // CY_FST_TRACE
#endif // VM_TRACE
#include <fesvr/dtm.h> #include <fesvr/dtm.h>
#include <fesvr/tsi.h> #include <fesvr/tsi.h>
#include "remote_bitbang.h" #include "remote_bitbang.h"
@@ -113,6 +117,7 @@ int main(int argc, char** argv)
// Port numbers are 16 bit unsigned integers. // Port numbers are 16 bit unsigned integers.
uint16_t rbb_port = 0; uint16_t rbb_port = 0;
#if VM_TRACE #if VM_TRACE
const char* vcdfile_name = NULL;
FILE * vcdfile = NULL; FILE * vcdfile = NULL;
uint64_t start = 0; uint64_t start = 0;
#endif #endif
@@ -157,6 +162,7 @@ int main(int argc, char** argv)
case 'o': opterr = 1; break; case 'o': opterr = 1; break;
#if VM_TRACE #if VM_TRACE
case 'v': { case 'v': {
vcdfile_name = optarg;
vcdfile = strcmp(optarg, "-") == 0 ? stdout : fopen(optarg, "w"); vcdfile = strcmp(optarg, "-") == 0 ? stdout : fopen(optarg, "w");
if (!vcdfile) { if (!vcdfile) {
std::cerr << "Unable to open " << optarg << " for VCD write\n"; std::cerr << "Unable to open " << optarg << " for VCD write\n";
@@ -264,17 +270,20 @@ done_processing:
#if VM_TRACE #if VM_TRACE
Verilated::traceEverOn(true); // Verilator must compute traced signals Verilated::traceEverOn(true); // Verilator must compute traced signals
#if CY_FST_TRACE
std::unique_ptr<VerilatedFstC> tfp(new VerilatedFstC);
#else
std::unique_ptr<VerilatedVcdFILE> vcdfd(new VerilatedVcdFILE(vcdfile)); std::unique_ptr<VerilatedVcdFILE> vcdfd(new VerilatedVcdFILE(vcdfile));
std::unique_ptr<VerilatedVcdC> tfp(new VerilatedVcdC(vcdfd.get())); std::unique_ptr<VerilatedVcdC> tfp(new VerilatedVcdC(vcdfd.get()));
if (vcdfile) { #endif // CY_FST_TRACE
if (vcdfile_name) {
tile->trace(tfp.get(), 99); // Trace 99 levels of hierarchy tile->trace(tfp.get(), 99); // Trace 99 levels of hierarchy
tfp->open(""); tfp->open(vcdfile_name);
} }
#endif #endif // VM_TRACE
// RocketChip currently only supports RBB port 0, so this needs to stay here
jtag = new remote_bitbang_t(rbb_port); jtag = new remote_bitbang_t(rbb_port);
dtm = new dtm_t(argc, argv);
tsi = new tsi_t(argc, argv);
signal(SIGTERM, handle_sigterm); signal(SIGTERM, handle_sigterm);
@@ -304,8 +313,7 @@ done_processing:
tile->reset = 0; tile->reset = 0;
done_reset = true; done_reset = true;
while (!dtm->done() && !jtag->done() && !tsi->done() && do {
!tile->io_success && trace_count < max_cycles) {
tile->clock = 0; tile->clock = 0;
tile->eval(); tile->eval();
#if VM_TRACE #if VM_TRACE
@@ -322,6 +330,13 @@ done_processing:
#endif #endif
trace_count++; trace_count++;
} }
// for verilator multithreading. need to do 1 loop before checking if
// tsi exists, since tsi is created by verilated thread on the first
// serial_tick.
while ((!dtm || !dtm->done()) &&
(!jtag || !jtag->done()) &&
(!tsi || !tsi->done()) &&
!tile->io_success && trace_count < max_cycles);
#if VM_TRACE #if VM_TRACE
if (tfp) if (tfp)
@@ -330,17 +345,17 @@ done_processing:
fclose(vcdfile); fclose(vcdfile);
#endif #endif
if (dtm->exit_code()) if (dtm && dtm->exit_code())
{ {
fprintf(stderr, "*** FAILED *** via dtm (code = %d, seed %d) after %ld cycles\n", dtm->exit_code(), random_seed, trace_count); fprintf(stderr, "*** FAILED *** via dtm (code = %d, seed %d) after %ld cycles\n", dtm->exit_code(), random_seed, trace_count);
ret = dtm->exit_code(); ret = dtm->exit_code();
} }
else if (tsi->exit_code()) else if (tsi && tsi->exit_code())
{ {
fprintf(stderr, "*** FAILED *** (code = %d, seed %d) after %ld cycles\n", tsi->exit_code(), random_seed, trace_count); fprintf(stderr, "*** FAILED *** (code = %d, seed %d) after %ld cycles\n", tsi->exit_code(), random_seed, trace_count);
ret = tsi->exit_code(); ret = tsi->exit_code();
} }
else if (jtag->exit_code()) else if (jtag && jtag->exit_code())
{ {
fprintf(stderr, "*** FAILED *** via jtag (code = %d, seed %d) after %ld cycles\n", jtag->exit_code(), random_seed, trace_count); fprintf(stderr, "*** FAILED *** via jtag (code = %d, seed %d) after %ld cycles\n", jtag->exit_code(), random_seed, trace_count);
ret = jtag->exit_code(); ret = jtag->exit_code();

View File

@@ -6,8 +6,8 @@
set -e set -e
set -o pipefail set -o pipefail
RDIR=$(pwd) DIR="$(dirname "$(readlink -f "${BASH_SOURCE[0]}")")"
CHIPYARD_DIR="${CHIPYARD_DIR:-$(git rev-parse --show-toplevel)}" CHIPYARD_DIR="$(dirname "$DIR")"
usage() { usage() {
echo "usage: ${0} [OPTIONS] [riscv-tools | esp-tools | ec2fast]" echo "usage: ${0} [OPTIONS] [riscv-tools | esp-tools | ec2fast]"
@@ -134,18 +134,16 @@ SRCDIR="$(pwd)/toolchains" module_all qemu --prefix="${RISCV}" --target-list=ris
git submodule update --init $CHIPYARD_DIR/tools/dromajo/dromajo-src git submodule update --init $CHIPYARD_DIR/tools/dromajo/dromajo-src
make -C $CHIPYARD_DIR/tools/dromajo/dromajo-src/src make -C $CHIPYARD_DIR/tools/dromajo/dromajo-src/src
cd "$RDIR"
# create specific env.sh # create specific env.sh
{ cat > "$CHIPYARD_DIR/env-$TOOLCHAIN.sh" <<EOF
echo "# auto-generated by build-toolchains.sh" # auto-generated by build-toolchains.sh
echo "export CHIPYARD_TOOLCHAIN_SOURCED=1" export CHIPYARD_TOOLCHAIN_SOURCED=1
echo "export RISCV=$(printf '%q' "$RISCV")" export RISCV=$(printf '%q' "$RISCV")
echo "export PATH=\${RISCV}/bin:\${PATH}" export PATH=\${RISCV}/bin:\${PATH}
echo "export LD_LIBRARY_PATH=\${RISCV}/lib\${LD_LIBRARY_PATH:+":\${LD_LIBRARY_PATH}"}" export LD_LIBRARY_PATH=\${RISCV}/lib\${LD_LIBRARY_PATH:+":\${LD_LIBRARY_PATH}"}
} > env-$TOOLCHAIN.sh EOF
# create general env.sh # create general env.sh
echo "# line auto-generated by build-toolchains.sh" >> env.sh echo "# line auto-generated by build-toolchains.sh" >> env.sh
echo "source \$( realpath \$(dirname "\${BASH_SOURCE[0]:-\${\(%\):-%x}}") )/env-$TOOLCHAIN.sh" >> env.sh echo "source $(printf '%q' "$CHIPYARD_DIR/env-$TOOLCHAIN.sh")" >> env.sh
echo "Toolchain Build Complete!" echo "Toolchain Build Complete!"

View File

@@ -15,7 +15,7 @@ case ${ncpu} in
esac esac
# Allow user to override MAKE # Allow user to override MAKE
[ -n "${MAKE}" ] || MAKE=$(command -v gnumake || command -v gmake || command -v make) [ -n "${MAKE:+x}" ] || MAKE=$(command -v gnumake || command -v gmake || command -v make)
readonly MAKE readonly MAKE

View File

@@ -17,10 +17,11 @@ if [ "$MINGIT" != "$(echo -e "$MINGIT\n$MYGIT" | sort -V | head -n1)" ]; then
false false
fi fi
RDIR=$(git rev-parse --show-toplevel) DIR="$(dirname "$(readlink -f "${BASH_SOURCE[0]}")")"
CHIPYARD_DIR="$(dirname "$DIR")"
# Ignore toolchain submodules # Ignore toolchain submodules
cd "$RDIR" cd "$CHIPYARD_DIR"
for name in toolchains/*-tools/*/ ; do for name in toolchains/*-tools/*/ ; do
git config submodule."${name%/}".update none git config submodule."${name%/}".update none
done done
@@ -71,8 +72,11 @@ git config submodule.sims/firesim.update none
git submodule update --init software/firemarshal git submodule update --init software/firemarshal
# Configure firemarshal to know where our firesim installation is # Configure firemarshal to know where our firesim installation is
if [ ! -f $RDIR/software/firemarshal/marshal-config.yaml ]; then if [ ! -f ./software/firemarshal/marshal-config.yaml ]; then
echo "firesim-dir: '../../sims/firesim/'" > $RDIR/software/firemarshal/marshal-config.yaml echo "firesim-dir: '../../sims/firesim/'" > ./software/firemarshal/marshal-config.yaml
fi fi
echo "# line auto-generated by init-submodules-no-riscv-tools.sh" >> $RDIR/env.sh
echo "PATH=\$( realpath \$(dirname "\${BASH_SOURCE[0]:-\${\(%\):-%x}}") )/software/firemarshal:\$PATH" >> $RDIR/env.sh echo "# line auto-generated by init-submodules-no-riscv-tools.sh" >> env.sh
echo '__DIR="$(dirname "$(readlink -f "${BASH_SOURCE[0]}")")"' >> env.sh
echo "PATH=\$__DIR/bin:\$PATH" >> env.sh
echo "PATH=\$__DIR/software/firemarshal:\$PATH" >> env.sh

76
scripts/numa_prefix Executable file
View File

@@ -0,0 +1,76 @@
#!/usr/bin/env python
#============================================================================
# - really simple script, which just prints out the numactl cmd to
# prefix before your actual command. it determines this based on free
# memory size attached to every node.
# - when you run this on a machine without `numactl`, the output is empty,
# so `$(numa_prefix) <cmd> <args>` turns in to `<cmd> <args>`.
# - when the machine has `numactl` installed, regardless of the socket-count
# on the machine, the resulting command is:
# `numactl -m <socket> -C <core-id list> -- <cmd> <args>`
# - example output from `numactl -H` on a 2 socket machine:
# available: 2 nodes (0-1)
# node 0 cpus: 0 2 4 6 8 10 12 14 16 18 20 22
# node 0 size: 131026 MB
# node 0 free: 7934 MB
# node 1 cpus: 1 3 5 7 9 11 13 15 17 19 21 23
# node 1 size: 65536 MB
# node 1 free: 429 MB
# node distances:
# node 0 1
# 0: 10 20
# 1: 20 10
#============================================================================
import subprocess
import re
import sys
which_proc = subprocess.Popen(["which", "numactl"], stdout=subprocess.PIPE)
out, err = which_proc.communicate()
if out != "":
numactl_proc = subprocess.Popen(["numactl", "-H"], stdout=subprocess.PIPE)
out, err = numactl_proc.communicate()
lines = out.split("\n")
line_idx = 0
head_line = lines[line_idx]
line_idx += 1
node_match = re.match(r"^ *available: +(\d+) nodes", head_line)
if node_match:
avail_nodes = node_match.group(1)
best_node_id = ""
best_cpus = ""
best_free_size = 0
# loop through available nodes, selecting the node with the most free mem
for i in avail_nodes:
cpu_line = lines[line_idx]
# mem. size unused. skip and use mem. free
mem_free_line = lines[line_idx + 2]
line_idx += 3
cpu_match = re.match(r"^ *node (\d+) cpus: (\d.*\d)$", cpu_line)
if cpu_match:
node_id = cpu_match.group(1)
cpus = cpu_match.group(2).replace(" ", ",")
mem_free_match = re.match(r"^ *node " + node_id + " free: (\d+) \S+$", mem_free_line)
if mem_free_match:
free_size = mem_free_match.group(1)
if int(free_size) > int(best_free_size):
best_node_id = node_id
best_cpus = cpus
best_free_size = free_size
else:
sys.exit("[ERROR] Malformed mem free line: " + mem_free_line)
else:
sys.exit("[ERROR] Malformed cpus line: " + cpu_line)
sys.stdout.write("numactl -m " + best_node_id + " -C " + best_cpus + " --")
else:
sys.exit("[ERROR] Malformed head line: " + head_line)

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

@@ -24,4 +24,4 @@ sudo apt-get install -y device-tree-compiler
git clone http://git.veripool.org/git/verilator git clone http://git.veripool.org/git/verilator
cd verilator cd verilator
git checkout v4.034 git checkout v4.034
autoconf && ./configure && make -j16 && sudo make install autoconf && ./configure && make -j$(nproc) && sudo make install

23
sims/common-sim-flags.mk Normal file
View File

@@ -0,0 +1,23 @@
#----------------------------------------------------------------------------------------
# common gcc configuration/optimization
#----------------------------------------------------------------------------------------
SIM_OPT_CXXFLAGS := -O3
SIM_CXXFLAGS = \
$(CXXFLAGS) \
$(SIM_OPT_CXXFLAGS) \
-std=c++11 \
-I$(RISCV)/include \
-I$(dramsim_dir) \
-I$(build_dir) \
$(EXTRA_SIM_CXXFLAGS)
SIM_LDFLAGS = \
$(LDFLAGS) \
-L$(RISCV)/lib \
-Wl,-rpath,$(RISCV)/lib \
-L$(sim_dir) \
-L$(dramsim_dir) \
-lfesvr \
-ldramsim \
$(EXTRA_SIM_LDFLAGS)

View File

@@ -41,16 +41,24 @@ include $(base_dir)/common.mk
######################################################################################### #########################################################################################
VCS = vcs -full64 VCS = vcs -full64
VCS_OPTS = -notice -line $(VCS_CC_OPTS) $(VCS_NONCC_OPTS) $(VCS_DEFINE_OPTS) $(EXTRA_SIM_SOURCES) VCS_OPTS = $(VCS_CC_OPTS) $(VCS_NONCC_OPTS) $(PREPROC_DEFINES)
#########################################################################################
# vcs build paths
#########################################################################################
model_dir = $(build_dir)/$(long_name)
model_dir_debug = $(build_dir)/$(long_name).debug
######################################################################################### #########################################################################################
# vcs simulator rules # vcs simulator rules
######################################################################################### #########################################################################################
$(sim): $(sim_vsrcs) $(sim_common_files) $(dramsim_lib) $(EXTRA_SIM_REQS) $(sim): $(sim_vsrcs) $(sim_common_files) $(dramsim_lib) $(EXTRA_SIM_REQS)
rm -rf csrc && $(VCS) $(VCS_OPTS) -o $@ rm -rf $(model_dir)
$(VCS) $(VCS_OPTS) $(EXTRA_SIM_SOURCES) -o $@ -Mdir=$(model_dir)
$(sim_debug): $(sim_vsrcs) $(sim_common_files) $(dramsim_lib) $(EXTRA_SIM_REQS) $(sim_debug): $(sim_vsrcs) $(sim_common_files) $(dramsim_lib) $(EXTRA_SIM_REQS)
rm -rf csrc && $(VCS) $(VCS_OPTS) -o $@ \ rm -rf $(model_dir_debug)
$(VCS) $(VCS_OPTS) $(EXTRA_SIM_SOURCES) -o $@ -Mdir=$(model_dir_debug) \
+define+DEBUG +define+DEBUG
######################################################################################### #########################################################################################
@@ -61,8 +69,14 @@ $(output_dir)/%.vpd: $(output_dir)/% $(sim_debug)
(set -o pipefail && $(sim_debug) $(PERMISSIVE_ON) $(SIM_FLAGS) $(EXTRA_SIM_FLAGS) $(VERBOSE_FLAGS) +vcdplusfile=$@ $(PERMISSIVE_OFF) $< </dev/null 2> >(spike-dasm > $<.out) | tee $<.log) (set -o pipefail && $(sim_debug) $(PERMISSIVE_ON) $(SIM_FLAGS) $(EXTRA_SIM_FLAGS) $(VERBOSE_FLAGS) +vcdplusfile=$@ $(PERMISSIVE_OFF) $< </dev/null 2> >(spike-dasm > $<.out) | tee $<.log)
######################################################################################### #########################################################################################
# general cleanup rule # general cleanup rules
######################################################################################### #########################################################################################
.PHONY: clean .PHONY: clean clean-sim clean-sim-debug
clean: clean:
rm -rf $(gen_dir) csrc $(sim_prefix)-* ucli.key vc_hdrs.h rm -rf $(gen_dir) $(sim_prefix)-* ucli.key
clean-sim:
rm -rf $(model_dir) $(build_dir)/vc_hdrs.h $(sim) $(sim).daidir ucli.key
clean-sim-debug:
rm -rf $(model_dir_debug) $(build_dir)/vc_hdrs.h $(sim_debug) $(sim_debug).daidir ucli.key

View File

@@ -22,7 +22,7 @@ include $(base_dir)/variables.mk
sim_name = verilator sim_name = verilator
######################################################################################### #########################################################################################
# vcs simulator types and rules # verilator simulator types and rules
######################################################################################### #########################################################################################
sim_prefix = simulator sim_prefix = simulator
sim = $(sim_dir)/$(sim_prefix)-$(MODEL_PACKAGE)-$(CONFIG) sim = $(sim_dir)/$(sim_prefix)-$(MODEL_PACKAGE)-$(CONFIG)
@@ -47,35 +47,53 @@ debug: $(sim_debug)
include $(base_dir)/common.mk include $(base_dir)/common.mk
######################################################################################### #########################################################################################
# verilator binary and flags # verilator-specific user-interface variables and commands
#########################################################################################
HELP_COMPILATION_VARIABLES += \
" VERILATOR_PROFILE = 'none' if no verilator profiling (default)" \
" 'all' if full verilator runtime profiling" \
" 'threads' if runtime thread profiling only" \
" VERILATOR_THREADS = how many threads the simulator will use (default 1)" \
" VERILATOR_FST_MODE = enable FST waveform instead of VCD. use with debug build"
#########################################################################################
# verilator/cxx binary and flags
######################################################################################### #########################################################################################
VERILATOR := verilator --cc --exe VERILATOR := verilator --cc --exe
CXXFLAGS := \ #----------------------------------------------------------------------------------------
$(CXXFLAGS) -O1 -std=c++11 \ # user configs
-I$(RISCV)/include \ #----------------------------------------------------------------------------------------
-I$(dramsim_dir) \ VERILATOR_PROFILE ?= none
-D__STDC_FORMAT_MACROS \ RUNTIME_PROFILING_CFLAGS := $(if $(filter $(VERILATOR_PROFILE),all),-g -pg,)
$(EXTRA_SIM_CC_FLAGS) RUNTIME_PROFILING_VFLAGS := $(if $(filter $(VERILATOR_PROFILE),all),\
--prof-threads --prof-cfuncs,\
$(if $(filter $(VERILATOR_PROFILE),threads),\
--prof-threads,))
LDFLAGS := \ VERILATOR_THREADS ?= 1
$(LDFLAGS) \ RUNTIME_THREADS := --threads $(VERILATOR_THREADS) --threads-dpi all
-L$(sim_dir) \
-lpthread
VERILATOR_CC_OPTS = \ VERILATOR_FST_MODE ?= 0
TRACING_OPTS := $(if $(filter $(VERILATOR_FST_MODE),0),\
--trace,--trace-fst --trace-threads 1)
TRACING_CFLAGS := $(if $(filter $(VERILATOR_FST_MODE),0),,-DCY_FST_TRACE)
#----------------------------------------------------------------------------------------
# verilation configuration/optimization
#----------------------------------------------------------------------------------------
# we initially had --noassert for performance, but several modules use
# assertions, including dramsim, so we enable --assert by default
VERILATOR_OPT_FLAGS := \
-O3 \ -O3 \
-CFLAGS "$(CXXFLAGS) -DTEST_HARNESS=V$(VLOG_MODEL) -DVERILATOR" \ --x-assign fast \
-CFLAGS "-I$(build_dir) -include $(build_dir)/$(long_name).plusArgs -include $(build_dir)/verilator.h" \ --x-initial fast \
-LDFLAGS "$(LDFLAGS)" \ --output-split 10000 \
$(RISCV)/lib/libfesvr.a \ --output-split-cfuncs 100
$(dramsim_lib)
# default flags added for ariane # default flags added for external IP (ariane/NVDLA)
ARIANE_VERILATOR_FLAGS = \ VERILOG_IP_VERILATOR_FLAGS := \
--unroll-count 256 \ --unroll-count 256 \
-Werror-PINMISSING \
-Werror-IMPLICIT \
-Wno-PINCONNECTEMPTY \ -Wno-PINCONNECTEMPTY \
-Wno-ASSIGNDLY \ -Wno-ASSIGNDLY \
-Wno-DECLFILENAME \ -Wno-DECLFILENAME \
@@ -85,29 +103,66 @@ ARIANE_VERILATOR_FLAGS = \
-Wno-style \ -Wno-style \
-Wall -Wall
# normal flags used for chipyard builds (that are incompatible with ariane) # normal flags used for chipyard builds (that are incompatible with vlog ip aka ariane/NVDLA)
CHIPYARD_VERILATOR_FLAGS = \ CHIPYARD_VERILATOR_FLAGS := \
--assert --assert
# options dependent on whether external IP (ariane/NVDLA) or just chipyard is used
# NOTE: defer the evaluation of this until it is used!
PLATFORM_OPTS = $(shell \
if grep -qiP "module\s+(Ariane|NVDLA)" $(build_dir)/*.*v; \
then echo "$(VERILOG_IP_VERILATOR_FLAGS)"; \
else echo "$(CHIPYARD_VERILATOR_FLAGS)"; fi)
# Use --timescale to approximate timescale behavior of pre-4.034 # Use --timescale to approximate timescale behavior of pre-4.034
TIMESCALE_OPTS := $(shell verilator --version | perl -lne 'if (/(\d.\d+)/ && $$1 >= 4.034) { print "--timescale 1ns/1ps"; }') TIMESCALE_OPTS := $(shell verilator --version | perl -lne 'if (/(\d.\d+)/ && $$1 >= 4.034) { print "--timescale 1ns/1ps"; }')
VERILATOR_NONCC_OPTS = \
$(TIMESCALE_OPTS) \
--top-module $(VLOG_MODEL) \
--vpi \
-Wno-fatal \
$(shell if ! grep -iq "module.*ariane" $(build_dir)/*.*v; then echo "$(CHIPYARD_VERILATOR_FLAGS)"; else echo "$(ARIANE_VERILATOR_FLAGS)"; fi) \
--output-split 10000 \
--output-split-cfuncs 100 \
--max-num-width 1048576 \
-f $(sim_common_files) \
$(sim_vsrcs)
VERILATOR_DEFINES = \ # see: https://github.com/ucb-bar/riscv-mini/issues/31
MAX_WIDTH_OPTS = $(shell verilator --version | perl -lne 'if (/(\d.\d+)/ && $$1 > 4.016) { print "--max-num-width 1048576"; }')
PREPROC_DEFINES := \
+define+PRINTF_COND=\$$c\(\"verbose\",\"\&\&\"\,\"done_reset\"\) \ +define+PRINTF_COND=\$$c\(\"verbose\",\"\&\&\"\,\"done_reset\"\) \
+define+STOP_COND=\$$c\(\"done_reset\"\) +define+STOP_COND=\$$c\(\"done_reset\"\)
VERILATOR_OPTS = $(VERILATOR_CC_OPTS) $(VERILATOR_NONCC_OPTS) $(VERILATOR_DEFINES) $(EXTRA_SIM_SOURCES) VERILATOR_NONCC_OPTS = \
$(RUNTIME_PROFILING_VFLAGS) \
$(RUNTIME_THREADS) \
$(VERILATOR_OPT_FLAGS) \
$(PLATFORM_OPTS) \
-Wno-fatal \
$(TIMESCALE_OPTS) \
$(MAX_WIDTH_OPTS) \
$(PREPROC_DEFINES) \
--top-module $(VLOG_MODEL) \
--vpi \
-f $(sim_common_files) \
$(sim_vsrcs)
#----------------------------------------------------------------------------------------
# gcc configuration/optimization
#----------------------------------------------------------------------------------------
include $(base_dir)/sims/common-sim-flags.mk
VERILATOR_CXXFLAGS = \
$(SIM_CXXFLAGS) \
$(RUNTIME_PROFILING_CFLAGS) \
$(TRACING_CFLAGS) \
-D__STDC_FORMAT_MACROS \
-DTEST_HARNESS=V$(VLOG_MODEL) \
-DVERILATOR \
-include $(build_dir)/$(long_name).plusArgs \
-include $(build_dir)/verilator.h
VERILATOR_LDFLAGS = $(SIM_LDFLAGS)
VERILATOR_CC_OPTS = \
-CFLAGS "$(VERILATOR_CXXFLAGS)" \
-LDFLAGS "$(VERILATOR_LDFLAGS)"
#----------------------------------------------------------------------------------------
# full verilator+gcc opts
#----------------------------------------------------------------------------------------
VERILATOR_OPTS = $(VERILATOR_CC_OPTS) $(VERILATOR_NONCC_OPTS)
######################################################################################### #########################################################################################
# verilator build paths and file names # verilator build paths and file names
@@ -127,13 +182,13 @@ model_mk_debug = $(model_dir_debug)/V$(VLOG_MODEL).mk
$(model_mk): $(sim_vsrcs) $(sim_common_files) $(EXTRA_SIM_REQS) $(model_mk): $(sim_vsrcs) $(sim_common_files) $(EXTRA_SIM_REQS)
rm -rf $(model_dir) rm -rf $(model_dir)
mkdir -p $(model_dir) mkdir -p $(model_dir)
$(VERILATOR) $(VERILATOR_OPTS) -o $(sim) -Mdir $(model_dir) -CFLAGS "-include $(model_header)" $(VERILATOR) $(VERILATOR_OPTS) $(EXTRA_SIM_SOURCES) -o $(sim) -Mdir $(model_dir) -CFLAGS "-include $(model_header)"
touch $@ touch $@
$(model_mk_debug): $(sim_vsrcs) $(sim_common_files) $(EXTRA_SIM_REQS) $(model_mk_debug): $(sim_vsrcs) $(sim_common_files) $(EXTRA_SIM_REQS)
rm -rf $(model_dir_debug) rm -rf $(model_dir_debug)
mkdir -p $(model_dir_debug) mkdir -p $(model_dir_debug)
$(VERILATOR) $(VERILATOR_OPTS) -o $(sim_debug) --trace -Mdir $(model_dir_debug) -CFLAGS "-include $(model_header_debug)" $(VERILATOR) $(VERILATOR_OPTS) $(EXTRA_SIM_SOURCES) -o $(sim_debug) $(TRACING_OPTS) -Mdir $(model_dir_debug) -CFLAGS "-include $(model_header_debug)"
touch $@ touch $@
######################################################################################### #########################################################################################
@@ -152,11 +207,17 @@ $(sim_debug): $(model_mk_debug) $(dramsim_lib)
$(output_dir)/%.vpd: $(output_dir)/% $(sim_debug) $(output_dir)/%.vpd: $(output_dir)/% $(sim_debug)
rm -f $@.vcd && mkfifo $@.vcd rm -f $@.vcd && mkfifo $@.vcd
vcd2vpd $@.vcd $@ > /dev/null & vcd2vpd $@.vcd $@ > /dev/null &
(set -o pipefail && $(sim_debug) $(PERMISSIVE_ON) $(SIM_FLAGS) $(EXTRA_SIM_FLAGS) $(SEED_FLAG) $(VERBOSE_FLAGS) -v$@.vcd $(PERMISSIVE_OFF) $< </dev/null 2> >(spike-dasm > $<.out) | tee $<.log) (set -o pipefail && $(NUMA_PREFIX) $(sim_debug) $(PERMISSIVE_ON) $(SIM_FLAGS) $(EXTRA_SIM_FLAGS) $(SEED_FLAG) $(VERBOSE_FLAGS) -v$@.vcd $(PERMISSIVE_OFF) $< </dev/null 2> >(spike-dasm > $<.out) | tee $<.log)
######################################################################################### #########################################################################################
# general cleanup rule # general cleanup rules
######################################################################################### #########################################################################################
.PHONY: clean .PHONY: clean clean-sim clean-sim-debug
clean: clean:
rm -rf $(gen_dir) $(sim_prefix)-* rm -rf $(gen_dir) $(sim_prefix)-*
clean-sim:
rm -rf $(model_dir) $(sim)
clean-sim-debug:
rm -rf $(model_dir_debug) $(sim_debug)

View File

@@ -49,7 +49,7 @@ ifdef ENABLE_DROMAJO
EXTRA_SIM_FLAGS += $(DROMAJO_FLAGS) EXTRA_SIM_FLAGS += $(DROMAJO_FLAGS)
# CC flags needed for all simulations # CC flags needed for all simulations
EXTRA_SIM_CC_FLAGS += -I$(DROMAJO_DIR) EXTRA_SIM_CXXFLAGS += -I$(DROMAJO_DIR)
# sourced needed for simulation # sourced needed for simulation
EXTRA_SIM_SOURCES += $(DROMAJO_LIB) EXTRA_SIM_SOURCES += $(DROMAJO_LIB)

View File

@@ -1,23 +1,51 @@
######################################################################################### #########################################################################################
# makefile variables shared across multiple makefiles # makefile variables shared across multiple makefiles
# - to use the help text, your Makefile should have a 'help' target that just
# prints all the HELP_LINES
######################################################################################### #########################################################################################
HELP_COMPILATION_VARIABLES =
HELP_PROJECT_VARIABLES = \
" SUB_PROJECT = use the specific subproject default variables [$(SUB_PROJECT)]" \
" SBT_PROJECT = the SBT project that you should find the classes/packages in [$(SBT_PROJECT)]" \
" MODEL = the top level module of the project in Chisel (normally the harness) [$(MODEL)]" \
" VLOG_MODEL = the top level module of the project in Firrtl/Verilog (normally the harness) [$(VLOG_MODEL)]" \
" MODEL_PACKAGE = the scala package to find the MODEL in [$(MODEL_PACKAGE)]" \
" CONFIG = the configuration class to give the parameters for the project [$(CONFIG)]" \
" CONFIG_PACKAGE = the scala package to find the CONFIG class [$(CONFIG_PACKAGE)]" \
" GENERATOR_PACKAGE = the scala package to find the Generator class in [$(GENERATOR_PACKAGE)]" \
" TB = testbench wrapper over the TestHarness needed to simulate in a verilog simulator [$(TB)]" \
" TOP = top level module of the project (normally the module instantiated by the harness) [$(TOP)]"
######################################################################################### HELP_SIMULATION_VARIABLES = \
# variables to invoke the generator " BINARY = riscv elf binary that the simulator will run when using the run-binary* targets" \
# descriptions: " VERBOSE_FLAGS = flags used when doing verbose simulation [$(VERBOSE_FLAGS)]"
# SBT_PROJECT = the SBT project that you should find the classes/packages in
# MODEL = the top level module of the project in Chisel (normally the harness) # include default simulation rules
# VLOG_MODEL = the top level module of the project in Firrtl/Verilog (normally the harness) HELP_COMMANDS = \
# MODEL_PACKAGE = the scala package to find the MODEL in " help = display this help" \
# CONFIG = the configuration class to give the parameters for the project " default = compiles non-debug simulator [./$(shell basename $(sim))]" \
# CONFIG_PACKAGE = the scala package to find the CONFIG class " debug = compiles debug simulator [./$(shell basename $(sim_debug))]" \
# GENERATOR_PACKAGE = the scala package to find the Generator class in " clean = remove all debug/non-debug simulators and intermediate files" \
# TB = wrapper over the TestHarness needed to simulate in a verilog simulator " clean-sim = removes non-debug simulator and simulator-generated files" \
# TOP = top level module of the project (normally the module instantiated by the harness) " clean-sim-debug = removes debug simulator and simulator-generated files"
#
# project specific: HELP_LINES = "" \
# SUB_PROJECT = use the specific subproject default variables " design specifier variables:" \
######################################################################################### " ---------------------------" \
$(HELP_PROJECT_VARIABLES) \
"" \
" compilation variables:" \
" ----------------------" \
$(HELP_COMPILATION_VARIABLES) \
"" \
" simulation variables:" \
" ---------------------" \
$(HELP_SIMULATION_VARIABLES) \
"" \
" some useful general commands:" \
" -----------------------------" \
$(HELP_COMMANDS) \
""
######################################################################################### #########################################################################################
# subproject overrides # subproject overrides
@@ -140,7 +168,7 @@ override SCALA_BUILDTOOL_DEPS += $(BLOOP_CONFIG_DIR)/TIMESTAMP
# 1) the sed removes a leading {file:<path>} that sometimes needs to be # 1) the sed removes a leading {file:<path>} that sometimes needs to be
# provided to SBT when a project but not for bloop. # provided to SBT when a project but not for bloop.
# 2) Generally, one could could pass '--' to indicate all remaining arguments are # 2) Generally, one could could pass '--' to indicate all remaining arguments are
# destined for the scala Main, however a bug in Bloop's argument parsing causes the # destined for the scala Main, however a bug in Bloop's argument parsing causes the
# --nailgun-port argument to be lost in this case. Workaround this by prefixing # --nailgun-port argument to be lost in this case. Workaround this by prefixing
# every main-destined argument with "--args" # every main-destined argument with "--args"
define run_scala_main define run_scala_main

26
vcs.mk
View File

@@ -11,15 +11,23 @@ endif
CLOCK_PERIOD ?= 1.0 CLOCK_PERIOD ?= 1.0
RESET_DELAY ?= 777.7 RESET_DELAY ?= 777.7
#----------------------------------------------------------------------------------------
# gcc configuration/optimization
#----------------------------------------------------------------------------------------
include $(base_dir)/sims/common-sim-flags.mk
VCS_CXXFLAGS = $(SIM_CXXFLAGS)
VCS_LDFLAGS = $(SIM_LDFLAGS)
# vcs requires LDFLAGS to not include library names (i.e. -l needs to be separate)
VCS_CC_OPTS = \ VCS_CC_OPTS = \
-CC "-I$(RISCV)/include" \ -CFLAGS "$(VCS_CXXFLAGS)" \
-CC "-I$(dramsim_dir)" \ -LDFLAGS "$(filter-out -l%,$(VCS_LDFLAGS))" \
-CC "-std=c++11" \ $(filter -l%,$(VCS_LDFLAGS))
-CC "$(EXTRA_SIM_CC_FLAGS)"
VCS_NONCC_OPTS = \ VCS_NONCC_OPTS = \
$(dramsim_lib) \ -notice \
$(RISCV)/lib/libfesvr.a \ -line \
+lint=all,noVCDE,noONGS,noUI \ +lint=all,noVCDE,noONGS,noUI \
-error=PCWM-L \ -error=PCWM-L \
-error=noZMMCM \ -error=noZMMCM \
@@ -27,7 +35,6 @@ VCS_NONCC_OPTS = \
-quiet \ -quiet \
-q \ -q \
+rad \ +rad \
+v2k \
+vcs+lic+wait \ +vcs+lic+wait \
+vc+list \ +vc+list \
-f $(sim_common_files) \ -f $(sim_common_files) \
@@ -35,10 +42,9 @@ VCS_NONCC_OPTS = \
+v2k +verilog2001ext+.v95+.vt+.vp +libext+.v \ +v2k +verilog2001ext+.v95+.vt+.vp +libext+.v \
-debug_pp \ -debug_pp \
+incdir+$(build_dir) \ +incdir+$(build_dir) \
$(sim_vsrcs) \ $(sim_vsrcs)
+libext+.v
VCS_DEFINE_OPTS = \ PREPROC_DEFINES = \
+define+VCS \ +define+VCS \
+define+CLOCK_PERIOD=$(CLOCK_PERIOD) \ +define+CLOCK_PERIOD=$(CLOCK_PERIOD) \
+define+RESET_DELAY=$(RESET_DELAY) \ +define+RESET_DELAY=$(RESET_DELAY) \

View File

@@ -34,7 +34,7 @@ INPUT_CONFS ?= $(if $(filter $(tech_name),nangate45),\
example-asap7.yml) example-asap7.yml)
HAMMER_EXEC ?= example-vlsi HAMMER_EXEC ?= example-vlsi
VLSI_TOP ?= $(TOP) VLSI_TOP ?= $(TOP)
VLSI_HARNESS_DUT_NAME ?= dut VLSI_HARNESS_DUT_NAME ?= chiptop
VLSI_OBJ_DIR ?= $(vlsi_dir)/build VLSI_OBJ_DIR ?= $(vlsi_dir)/build
ifneq ($(CUSTOM_VLOG),) ifneq ($(CUSTOM_VLOG),)
OBJ_DIR ?= $(VLSI_OBJ_DIR)/custom-$(VLSI_TOP) OBJ_DIR ?= $(VLSI_OBJ_DIR)/custom-$(VLSI_TOP)
@@ -115,15 +115,20 @@ $(SIM_CONF): $(VLSI_RTL) $(HARNESS_FILE) $(HARNESS_SMEMS_FILE) $(sim_common_file
done done
echo " options_meta: 'append'" >> $@ echo " options_meta: 'append'" >> $@
echo " defines:" >> $@ echo " defines:" >> $@
for x in $(subst +define+,,$(VCS_DEFINE_OPTS)); do \ for x in $(subst +define+,,$(PREPROC_DEFINES)); do \
echo ' - "'$$x'"' >> $@; \ echo ' - "'$$x'"' >> $@; \
done done
echo " defines_meta: 'append'" >> $@ echo " defines_meta: 'append'" >> $@
echo " compiler_opts:" >> $@ echo " compiler_cc_opts:" >> $@
for x in $(filter-out "",$(filter-out -CC,$(VCS_CC_OPTS))); do \ for x in $(filter-out "",$(VCS_CXXFLAGS)); do \
echo ' - "'$$x'"' >> $@; \ echo ' - "'$$x'"' >> $@; \
done done
echo " compiler_opts_meta: 'append'" >> $@ echo " compiler_cc_opts_meta: 'append'" >> $@
echo " compiler_ld_opts:" >> $@
for x in $(filter-out "",$(VCS_LDFLAGS)); do \
echo ' - "'$$x'"' >> $@; \
done
echo " compiler_ld_opts_meta: 'append'" >> $@
echo " execution_flags_prepend: ['$(PERMISSIVE_ON)']" >> $@ echo " execution_flags_prepend: ['$(PERMISSIVE_ON)']" >> $@
echo " execution_flags_append: ['$(PERMISSIVE_OFF)']" >> $@ echo " execution_flags_append: ['$(PERMISSIVE_OFF)']" >> $@
echo " execution_flags:" >> $@ echo " execution_flags:" >> $@