Merge remote-tracking branch 'origin/main' into use-fat-jar
This commit is contained in:
2
.github/actions/cleanup-conda/action.yml
vendored
2
.github/actions/cleanup-conda/action.yml
vendored
@@ -15,7 +15,7 @@ runs:
|
|||||||
conda env remove -n $env
|
conda env remove -n $env
|
||||||
done
|
done
|
||||||
fi
|
fi
|
||||||
IS_NUMBER_REGEX='[0-9]+$'
|
IS_NUMBER_REGEX='^[0-9]+$'
|
||||||
conda env list | awk '{print $1}' | tail -n +4 | while read envname; do
|
conda env list | awk '{print $1}' | tail -n +4 | while read envname; do
|
||||||
ENV_DATE=$(echo $envname | sed "s/cy-[[:digit:]]\+-\(.*\)-\(riscv\|esp\)-tools/\1/")
|
ENV_DATE=$(echo $envname | sed "s/cy-[[:digit:]]\+-\(.*\)-\(riscv\|esp\)-tools/\1/")
|
||||||
if ! [[ $ENV_DATE =~ $IS_NUMBER_REGEX ]]; then
|
if ! [[ $ENV_DATE =~ $IS_NUMBER_REGEX ]]; then
|
||||||
|
|||||||
2
.github/scripts/check-commit.sh
vendored
2
.github/scripts/check-commit.sh
vendored
@@ -45,7 +45,7 @@ search () {
|
|||||||
done
|
done
|
||||||
}
|
}
|
||||||
|
|
||||||
submodules=("cva6" "boom" "ibex" "hwacha" "icenet" "nvdla" "rocket-chip" "sha3" "sifive-blocks" "sifive-cache" "testchipip" "riscv-sodor" "mempress")
|
submodules=("cva6" "boom" "ibex" "gemmini" "hwacha" "icenet" "nvdla" "rocket-chip" "sha3" "sifive-blocks" "sifive-cache" "testchipip" "riscv-sodor" "mempress")
|
||||||
dir="generators"
|
dir="generators"
|
||||||
branches=("master" "main" "dev")
|
branches=("master" "main" "dev")
|
||||||
search
|
search
|
||||||
|
|||||||
6
.github/scripts/defaults.sh
vendored
6
.github/scripts/defaults.sh
vendored
@@ -33,7 +33,7 @@ REMOTE_COURSIER_CACHE=$REMOTE_WORK_DIR/.coursier-cache
|
|||||||
# key value store to get the build groups
|
# key value store to get the build groups
|
||||||
declare -A grouping
|
declare -A grouping
|
||||||
grouping["group-cores"]="chipyard-cva6 chipyard-ibex chipyard-rocket chipyard-hetero chipyard-boom chipyard-sodor chipyard-digitaltop chipyard-multiclock-rocket chipyard-nomem-scratchpad chipyard-spike chipyard-clone"
|
grouping["group-cores"]="chipyard-cva6 chipyard-ibex chipyard-rocket chipyard-hetero chipyard-boom chipyard-sodor chipyard-digitaltop chipyard-multiclock-rocket chipyard-nomem-scratchpad chipyard-spike chipyard-clone"
|
||||||
grouping["group-peripherals"]="chipyard-dmirocket chipyard-spiflashwrite chipyard-mmios chipyard-nocores chipyard-manyperipherals"
|
grouping["group-peripherals"]="chipyard-dmirocket chipyard-dmiboom chipyard-spiflashwrite chipyard-mmios chipyard-nocores chipyard-manyperipherals chipyard-chiplike"
|
||||||
grouping["group-accels"]="chipyard-mempress chipyard-sha3 chipyard-hwacha chipyard-gemmini chipyard-manymmioaccels"
|
grouping["group-accels"]="chipyard-mempress chipyard-sha3 chipyard-hwacha chipyard-gemmini chipyard-manymmioaccels"
|
||||||
grouping["group-constellation"]="chipyard-constellation"
|
grouping["group-constellation"]="chipyard-constellation"
|
||||||
grouping["group-tracegen"]="tracegen tracegen-boom"
|
grouping["group-tracegen"]="tracegen tracegen-boom"
|
||||||
@@ -50,13 +50,15 @@ mapping["chipyard-digitaltop"]=" TOP=DigitalTop"
|
|||||||
mapping["chipyard-manymmioaccels"]=" CONFIG=ManyMMIOAcceleratorRocketConfig"
|
mapping["chipyard-manymmioaccels"]=" CONFIG=ManyMMIOAcceleratorRocketConfig"
|
||||||
mapping["chipyard-hetero"]=" CONFIG=LargeBoomAndRocketConfig"
|
mapping["chipyard-hetero"]=" CONFIG=LargeBoomAndRocketConfig"
|
||||||
mapping["chipyard-boom"]=" CONFIG=MediumBoomCosimConfig"
|
mapping["chipyard-boom"]=" CONFIG=MediumBoomCosimConfig"
|
||||||
mapping["chipyard-spike"]=" CONFIG=SpikeFastUARTConfig EXTRA_SIM_FLAGS='+spike-ipc=10'"
|
mapping["chipyard-dmiboom"]=" CONFIG=dmiMediumBoomCosimConfig"
|
||||||
|
mapping["chipyard-spike"]=" CONFIG=SpikeConfig EXTRA_SIM_FLAGS='+spike-ipc=10'"
|
||||||
mapping["chipyard-hwacha"]=" CONFIG=HwachaRocketConfig"
|
mapping["chipyard-hwacha"]=" CONFIG=HwachaRocketConfig"
|
||||||
mapping["chipyard-gemmini"]=" CONFIG=GemminiRocketConfig"
|
mapping["chipyard-gemmini"]=" CONFIG=GemminiRocketConfig"
|
||||||
mapping["chipyard-cva6"]=" CONFIG=CVA6Config"
|
mapping["chipyard-cva6"]=" CONFIG=CVA6Config"
|
||||||
mapping["chipyard-ibex"]=" CONFIG=IbexConfig"
|
mapping["chipyard-ibex"]=" CONFIG=IbexConfig"
|
||||||
mapping["chipyard-spiflashwrite"]=" CONFIG=SmallSPIFlashRocketConfig EXTRA_SIM_FLAGS='+spiflash0=${LOCAL_CHIPYARD_DIR}/tests/spiflash.img'"
|
mapping["chipyard-spiflashwrite"]=" CONFIG=SmallSPIFlashRocketConfig EXTRA_SIM_FLAGS='+spiflash0=${LOCAL_CHIPYARD_DIR}/tests/spiflash.img'"
|
||||||
mapping["chipyard-manyperipherals"]=" CONFIG=ManyPeripheralsRocketConfig EXTRA_SIM_FLAGS='+spiflash0=${LOCAL_CHIPYARD_DIR}/tests/spiflash.img'"
|
mapping["chipyard-manyperipherals"]=" CONFIG=ManyPeripheralsRocketConfig EXTRA_SIM_FLAGS='+spiflash0=${LOCAL_CHIPYARD_DIR}/tests/spiflash.img'"
|
||||||
|
mapping["chipyard-chiplike"]=" CONFIG=ChipLikeQuadRocketConfig MODEL=FlatTestHarness MODEL_PACKAGE=chipyard.example verilog"
|
||||||
mapping["chipyard-cloneboom"]=" CONFIG=Cloned64MegaBoomConfig verilog"
|
mapping["chipyard-cloneboom"]=" CONFIG=Cloned64MegaBoomConfig verilog"
|
||||||
mapping["chipyard-nocores"]=" CONFIG=NoCoresConfig verilog"
|
mapping["chipyard-nocores"]=" CONFIG=NoCoresConfig verilog"
|
||||||
mapping["tracegen"]=" CONFIG=NonBlockingTraceGenL2Config"
|
mapping["tracegen"]=" CONFIG=NonBlockingTraceGenL2Config"
|
||||||
|
|||||||
2
.github/scripts/remote-do-rtl-build.sh
vendored
2
.github/scripts/remote-do-rtl-build.sh
vendored
@@ -16,8 +16,6 @@ source $SCRIPT_DIR/defaults.sh
|
|||||||
|
|
||||||
cd $REMOTE_CHIPYARD_DIR
|
cd $REMOTE_CHIPYARD_DIR
|
||||||
./scripts/init-submodules-no-riscv-tools.sh --force
|
./scripts/init-submodules-no-riscv-tools.sh --force
|
||||||
./scripts/init-fpga.sh
|
|
||||||
|
|
||||||
|
|
||||||
# Constellation can run without espresso, but this improves
|
# Constellation can run without espresso, but this improves
|
||||||
# elaboration time drastically
|
# elaboration time drastically
|
||||||
|
|||||||
7
.github/scripts/run-tests.sh
vendored
7
.github/scripts/run-tests.sh
vendored
@@ -33,11 +33,16 @@ case $1 in
|
|||||||
run_bmark ${mapping[$1]}
|
run_bmark ${mapping[$1]}
|
||||||
;;
|
;;
|
||||||
chipyard-dmirocket)
|
chipyard-dmirocket)
|
||||||
run_bmark ${mapping[$1]}
|
$LOCAL_CHIPYARD_DIR/scripts/generate-ckpt.sh -b $RISCV/riscv64-unknown-elf/share/riscv-tests/benchmarks/dhrystone.riscv -i 10000
|
||||||
|
make -C $LOCAL_SIM_DIR $DISABLE_SIM_PREREQ ${mapping[$1]} run-binary LOADARCH=$PWD/dhrystone.riscv.0x80000000.10000.loadarch
|
||||||
;;
|
;;
|
||||||
chipyard-boom)
|
chipyard-boom)
|
||||||
run_bmark ${mapping[$1]}
|
run_bmark ${mapping[$1]}
|
||||||
;;
|
;;
|
||||||
|
chipyard-dmiboom)
|
||||||
|
$LOCAL_CHIPYARD_DIR/scripts/generate-ckpt.sh -b $RISCV/riscv64-unknown-elf/share/riscv-tests/benchmarks/dhrystone.riscv -i 10000
|
||||||
|
make -C $LOCAL_SIM_DIR $DISABLE_SIM_PREREQ ${mapping[$1]} run-binary LOADARCH=$PWD/dhrystone.riscv.0x80000000.10000.loadarch
|
||||||
|
;;
|
||||||
chipyard-spike)
|
chipyard-spike)
|
||||||
run_bmark ${mapping[$1]}
|
run_bmark ${mapping[$1]}
|
||||||
;;
|
;;
|
||||||
|
|||||||
53
.github/workflows/chipyard-run-tests.yml
vendored
53
.github/workflows/chipyard-run-tests.yml
vendored
@@ -390,6 +390,35 @@ jobs:
|
|||||||
|
|
||||||
##########################################################################
|
##########################################################################
|
||||||
|
|
||||||
|
chipyard-spike-gemmini-run-tests:
|
||||||
|
name: chipyard-spike-gemmini-run-tests
|
||||||
|
needs: prepare-chipyard-accels # technically doesn't depend on RTL but should be after the build.sh for Gemmini
|
||||||
|
runs-on: ferry
|
||||||
|
steps:
|
||||||
|
- name: Delete old checkout
|
||||||
|
run: |
|
||||||
|
ls -alh .
|
||||||
|
rm -rf ${{ github.workspace }}/* || true
|
||||||
|
rm -rf ${{ github.workspace }}/.* || true
|
||||||
|
ls -alh .
|
||||||
|
- name: Checkout
|
||||||
|
uses: actions/checkout@v3
|
||||||
|
- name: Git workaround
|
||||||
|
uses: ./.github/actions/git-workaround
|
||||||
|
- name: Create conda env
|
||||||
|
uses: ./.github/actions/create-conda-env
|
||||||
|
- name: Build Gemmini FireMarshal
|
||||||
|
run: |
|
||||||
|
conda activate ${{ env.conda-env-name-no-time }}-$(date --date "${{ env.workflow-timestamp }}" +%Y%m%d)-riscv-tools
|
||||||
|
cd ${{ github.workspace }} && ./scripts/init-submodules-no-riscv-tools.sh --force
|
||||||
|
cd ${{ github.workspace }} && source ./scripts/fix-open-files.sh
|
||||||
|
git submodule update --init software/firemarshal && cd software/firemarshal && ./init-submodules.sh
|
||||||
|
cd ${{ github.workspace }}/generators/gemmini/software && ${{ github.workspace }}/software/firemarshal/marshal -v -d build gemmini-smoke.json
|
||||||
|
- name: Running Gemmini FireMarshal smoke test
|
||||||
|
run: |
|
||||||
|
conda activate ${{ env.conda-env-name-no-time }}-$(date --date "${{ env.workflow-timestamp }}" +%Y%m%d)-riscv-tools
|
||||||
|
cd ${{ github.workspace }}/generators/gemmini/software && ${{ github.workspace }}/software/firemarshal/marshal -v -d launch -s gemmini-smoke.json
|
||||||
|
|
||||||
chipyard-rocket-run-tests:
|
chipyard-rocket-run-tests:
|
||||||
name: chipyard-rocket-run-tests
|
name: chipyard-rocket-run-tests
|
||||||
needs: prepare-chipyard-cores
|
needs: prepare-chipyard-cores
|
||||||
@@ -574,6 +603,29 @@ jobs:
|
|||||||
group-key: "group-peripherals"
|
group-key: "group-peripherals"
|
||||||
project-key: "chipyard-dmirocket"
|
project-key: "chipyard-dmirocket"
|
||||||
|
|
||||||
|
chipyard-dmiboom-run-tests:
|
||||||
|
name: chipyard-dmiboom-run-tests
|
||||||
|
needs: prepare-chipyard-peripherals
|
||||||
|
runs-on: self-hosted
|
||||||
|
steps:
|
||||||
|
- name: Delete old checkout
|
||||||
|
run: |
|
||||||
|
ls -alh .
|
||||||
|
rm -rf ${{ github.workspace }}/* || true
|
||||||
|
rm -rf ${{ github.workspace }}/.* || true
|
||||||
|
ls -alh .
|
||||||
|
- name: Checkout
|
||||||
|
uses: actions/checkout@v3
|
||||||
|
- name: Git workaround
|
||||||
|
uses: ./.github/actions/git-workaround
|
||||||
|
- name: Create conda env
|
||||||
|
uses: ./.github/actions/create-conda-env
|
||||||
|
- name: Run tests
|
||||||
|
uses: ./.github/actions/run-tests
|
||||||
|
with:
|
||||||
|
group-key: "group-peripherals"
|
||||||
|
project-key: "chipyard-dmiboom"
|
||||||
|
|
||||||
chipyard-spiflashwrite-run-tests:
|
chipyard-spiflashwrite-run-tests:
|
||||||
name: chipyard-spiflashwrite-run-tests
|
name: chipyard-spiflashwrite-run-tests
|
||||||
needs: prepare-chipyard-peripherals
|
needs: prepare-chipyard-peripherals
|
||||||
@@ -915,6 +967,7 @@ jobs:
|
|||||||
chipyard-cva6-run-tests,
|
chipyard-cva6-run-tests,
|
||||||
chipyard-ibex-run-tests,
|
chipyard-ibex-run-tests,
|
||||||
chipyard-sodor-run-tests,
|
chipyard-sodor-run-tests,
|
||||||
|
chipyard-dmiboom-run-tests,
|
||||||
chipyard-dmirocket-run-tests,
|
chipyard-dmirocket-run-tests,
|
||||||
chipyard-spiflashwrite-run-tests,
|
chipyard-spiflashwrite-run-tests,
|
||||||
chipyard-manyperipherals-run-tests,
|
chipyard-manyperipherals-run-tests,
|
||||||
|
|||||||
9
.gitmodules
vendored
9
.gitmodules
vendored
@@ -73,9 +73,6 @@
|
|||||||
[submodule "fpga/fpga-shells"]
|
[submodule "fpga/fpga-shells"]
|
||||||
path = fpga/fpga-shells
|
path = fpga/fpga-shells
|
||||||
url = https://github.com/chipsalliance/rocket-chip-fpga-shells.git
|
url = https://github.com/chipsalliance/rocket-chip-fpga-shells.git
|
||||||
[submodule "tools/api-config-chipsalliance"]
|
|
||||||
path = tools/api-config-chipsalliance
|
|
||||||
url = https://github.com/chipsalliance/api-config-chipsalliance.git
|
|
||||||
[submodule "tools/rocket-dsp-utils"]
|
[submodule "tools/rocket-dsp-utils"]
|
||||||
path = tools/rocket-dsp-utils
|
path = tools/rocket-dsp-utils
|
||||||
url = https://github.com/ucb-bar/rocket-dsp-utils
|
url = https://github.com/ucb-bar/rocket-dsp-utils
|
||||||
@@ -121,3 +118,9 @@
|
|||||||
[submodule "generators/mempress"]
|
[submodule "generators/mempress"]
|
||||||
path = generators/mempress
|
path = generators/mempress
|
||||||
url = https://github.com/ucb-bar/mempress.git
|
url = https://github.com/ucb-bar/mempress.git
|
||||||
|
[submodule "tools/cde"]
|
||||||
|
path = tools/cde
|
||||||
|
url = https://github.com/chipsalliance/cde.git
|
||||||
|
[submodule "software/embench/embench-iot"]
|
||||||
|
path = software/embench/embench-iot
|
||||||
|
url = https://github.com/embench/embench-iot.git
|
||||||
|
|||||||
28
CHANGELOG.md
28
CHANGELOG.md
@@ -2,6 +2,34 @@
|
|||||||
|
|
||||||
This changelog follows the format defined here: https://keepachangelog.com/en/1.0.0/
|
This changelog follows the format defined here: https://keepachangelog.com/en/1.0.0/
|
||||||
|
|
||||||
|
## [1.9.1] - 2023-04-21
|
||||||
|
|
||||||
|
Various fixes for Linux boot, More Chip/bringup examples, Chisel 3.5.6 bump
|
||||||
|
|
||||||
|
### Added
|
||||||
|
* QoL improvement to IOBinders + custom ChipTop example by @jerryz123 in https://github.com/ucb-bar/chipyard/pull/1399
|
||||||
|
* PLL integration example + FlatChipTop/TestHarness by @jerryz123 in https://github.com/ucb-bar/chipyard/pull/1427
|
||||||
|
* Bump TestChipIp to improve default serial_tl behavior by @jerryz123 in https://github.com/ucb-bar/chipyard/pull/1435
|
||||||
|
* Bump testchipip to standardize TL serdesser bundle params by @jerryz123 in https://github.com/ucb-bar/chipyard/pull/1446
|
||||||
|
* HarnessBinder asserts to catch bad clock generation by @jerryz123 in https://github.com/ucb-bar/chipyard/pull/1460
|
||||||
|
|
||||||
|
### Changed
|
||||||
|
* New Scala-based Config Finder by @abejgonzalez in https://github.com/ucb-bar/chipyard/pull/1424
|
||||||
|
* Bump to latest rocket-chip/chisel3.5.6 by @jerryz123 in https://github.com/ucb-bar/chipyard/pull/1411
|
||||||
|
* Resolve merge conflicts in chisel3.5.6 bump by @jerryz123 in https://github.com/ucb-bar/chipyard/pull/1430
|
||||||
|
* bump testchipip by @joey0320 in https://github.com/ucb-bar/chipyard/pull/1434
|
||||||
|
* ADD: improve Makefile in tests/, add explicit arch flags by @T-K-233 in https://github.com/ucb-bar/chipyard/pull/1439
|
||||||
|
* Various submodule bumps by @abejgonzalez in https://github.com/ucb-bar/chipyard/pull/1448
|
||||||
|
* Support not instantiating tile reset/clock contorl features by @jerryz123 in https://github.com/ucb-bar/chipyard/pull/1459
|
||||||
|
|
||||||
|
### Fixed
|
||||||
|
* Various improvements and fixes by @jerryz123 in https://github.com/ucb-bar/chipyard/pull/1420
|
||||||
|
* Ensure conda cleanup regex properly filters out non-numeric chars by @abejgonzalez in https://github.com/ucb-bar/chipyard/pull/1425
|
||||||
|
* Fix ChipLikeQuadRocketConfig crossing by @jerryz123 in https://github.com/ucb-bar/chipyard/pull/1436
|
||||||
|
* Uniquify module names that are common to Top & Model by @joey0320 in https://github.com/ucb-bar/chipyard/pull/1442
|
||||||
|
* Support for no-bootROM systems by @jerryz123 in https://github.com/ucb-bar/chipyard/pull/1458
|
||||||
|
* Support for no-UART systems by @jerryz123 in https://github.com/ucb-bar/chipyard/pull/1457
|
||||||
|
|
||||||
## [1.9.0] - 2023-03-23
|
## [1.9.0] - 2023-03-23
|
||||||
|
|
||||||
Faster FIRRTL build support work CIRCT. New software support for RISC-V GCC12 and Linux 6.2. Various bumps and fixes of all submodules.
|
Faster FIRRTL build support work CIRCT. New software support for RISC-V GCC12 and Linux 6.2. Various bumps and fixes of all submodules.
|
||||||
|
|||||||
@@ -2,9 +2,6 @@
|
|||||||
|
|
||||||
# Chipyard Framework [](https://github.com/ucb-bar/chipyard/actions)
|
# Chipyard Framework [](https://github.com/ucb-bar/chipyard/actions)
|
||||||
|
|
||||||
| We're running the First FireSim and Chipyard User/Developer Workshop at ASPLOS 2023 on March 26, 2023! This workshop will feature a full-day of submitted talks from users and developers in the FireSim and Chipyard community. Learn more and **submit your work** on the [2023 Workshop Page](https://fires.im/workshop-2023/)! |
|
|
||||||
|-----|
|
|
||||||
|
|
||||||
## Quick Links
|
## Quick Links
|
||||||
|
|
||||||
* **Stable Documentation**: https://chipyard.readthedocs.io/
|
* **Stable Documentation**: https://chipyard.readthedocs.io/
|
||||||
|
|||||||
26
build.sbt
26
build.sbt
@@ -82,7 +82,7 @@ def isolateAllTests(tests: Seq[TestDefinition]) = tests map { test =>
|
|||||||
new Group(test.name, Seq(test), SubProcess(options))
|
new Group(test.name, Seq(test), SubProcess(options))
|
||||||
} toSeq
|
} toSeq
|
||||||
|
|
||||||
val chiselVersion = "3.5.5"
|
val chiselVersion = "3.5.6"
|
||||||
|
|
||||||
lazy val chiselSettings = Seq(
|
lazy val chiselSettings = Seq(
|
||||||
libraryDependencies ++= Seq("edu.berkeley.cs" %% "chisel3" % chiselVersion,
|
libraryDependencies ++= Seq("edu.berkeley.cs" %% "chisel3" % chiselVersion,
|
||||||
@@ -118,11 +118,8 @@ lazy val rocketMacros = (project in rocketChipDir / "macros")
|
|||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
|
||||||
lazy val rocketConfig = (project in rocketChipDir / "api-config-chipsalliance/build-rules/sbt")
|
|
||||||
.settings(commonSettings)
|
|
||||||
|
|
||||||
lazy val rocketchip = freshProject("rocketchip", rocketChipDir)
|
lazy val rocketchip = freshProject("rocketchip", rocketChipDir)
|
||||||
.dependsOn(hardfloat, rocketMacros, rocketConfig)
|
.dependsOn(hardfloat, rocketMacros, cde)
|
||||||
.settings(commonSettings)
|
.settings(commonSettings)
|
||||||
.settings(chiselSettings)
|
.settings(chiselSettings)
|
||||||
.settings(
|
.settings(
|
||||||
@@ -158,7 +155,12 @@ lazy val chipyard = (project in file("generators/chipyard"))
|
|||||||
gemmini, icenet, tracegen, cva6, nvdla, sodor, ibex, fft_generator,
|
gemmini, icenet, tracegen, cva6, nvdla, sodor, ibex, fft_generator,
|
||||||
constellation, mempress)
|
constellation, mempress)
|
||||||
.settings(libraryDependencies ++= rocketLibDeps.value)
|
.settings(libraryDependencies ++= rocketLibDeps.value)
|
||||||
.settings(commonSettings)
|
.settings(
|
||||||
|
libraryDependencies ++= Seq(
|
||||||
|
"org.reflections" % "reflections" % "0.10.2"
|
||||||
|
)
|
||||||
|
)
|
||||||
|
.settings(commonSettings)
|
||||||
|
|
||||||
lazy val mempress = (project in file("generators/mempress"))
|
lazy val mempress = (project in file("generators/mempress"))
|
||||||
.dependsOn(rocketchip, midasTargetUtils)
|
.dependsOn(rocketchip, midasTargetUtils)
|
||||||
@@ -254,16 +256,12 @@ lazy val dsptools = freshProject("dsptools", file("./tools/dsptools"))
|
|||||||
"org.scalacheck" %% "scalacheck" % "1.14.3" % "test",
|
"org.scalacheck" %% "scalacheck" % "1.14.3" % "test",
|
||||||
))
|
))
|
||||||
|
|
||||||
lazy val `api-config-chipsalliance` = freshProject("api-config-chipsalliance", file("./tools/api-config-chipsalliance"))
|
lazy val cde = (project in file("tools/cde"))
|
||||||
.settings(
|
.settings(commonSettings)
|
||||||
commonSettings,
|
.settings(Compile / scalaSource := baseDirectory.value / "cde/src/chipsalliance/rocketchip")
|
||||||
libraryDependencies ++= Seq(
|
|
||||||
"org.scalatest" %% "scalatest" % "3.0.+" % "test",
|
|
||||||
"org.scalacheck" %% "scalacheck" % "1.14.3" % "test",
|
|
||||||
))
|
|
||||||
|
|
||||||
lazy val `rocket-dsp-utils` = freshProject("rocket-dsp-utils", file("./tools/rocket-dsp-utils"))
|
lazy val `rocket-dsp-utils` = freshProject("rocket-dsp-utils", file("./tools/rocket-dsp-utils"))
|
||||||
.dependsOn(rocketchip, `api-config-chipsalliance`, dsptools)
|
.dependsOn(rocketchip, cde, dsptools)
|
||||||
.settings(libraryDependencies ++= rocketLibDeps.value)
|
.settings(libraryDependencies ++= rocketLibDeps.value)
|
||||||
.settings(commonSettings)
|
.settings(commonSettings)
|
||||||
|
|
||||||
|
|||||||
68
common.mk
68
common.mk
@@ -48,7 +48,7 @@ HELP_COMMANDS += \
|
|||||||
" firrtl = generate intermediate firrtl files from chisel elaboration" \
|
" firrtl = generate intermediate firrtl files from chisel elaboration" \
|
||||||
" run-tests = run all assembly and benchmark tests" \
|
" run-tests = run all assembly and benchmark tests" \
|
||||||
" launch-sbt = start sbt terminal" \
|
" launch-sbt = start sbt terminal" \
|
||||||
|
" find-config-fragments = list all config. fragments"
|
||||||
|
|
||||||
#########################################################################################
|
#########################################################################################
|
||||||
# include additional subproject make fragments
|
# include additional subproject make fragments
|
||||||
@@ -239,32 +239,28 @@ $(SFC_MFC_TARGETS) &: $(BTL_CLASSPATH_TARGETS) $(FIRRTL_FILE) $(FINAL_ANNO_FILE)
|
|||||||
$(SED) -i 's/.*/& /' $(MFC_SMEMS_CONF) # need trailing space for SFC macrocompiler
|
$(SED) -i 's/.*/& /' $(MFC_SMEMS_CONF) # need trailing space for SFC macrocompiler
|
||||||
# DOC include end: FirrtlCompiler
|
# DOC include end: FirrtlCompiler
|
||||||
|
|
||||||
$(TOP_MODS_FILELIST) $(MODEL_MODS_FILELIST) $(ALL_MODS_FILELIST) $(BB_MODS_FILELIST) &: $(MFC_MODEL_HRCHY_JSON) $(MFC_FILELIST) $(MFC_BB_MODS_FILELIST)
|
$(TOP_MODS_FILELIST) $(MODEL_MODS_FILELIST) $(ALL_MODS_FILELIST) $(BB_MODS_FILELIST) $(MFC_MODEL_HRCHY_JSON_UNIQUIFIED) &: $(MFC_MODEL_HRCHY_JSON) $(MFC_TOP_HRCHY_JSON) $(MFC_FILELIST) $(MFC_BB_MODS_FILELIST)
|
||||||
$(base_dir)/scripts/split-module-files.py \
|
$(base_dir)/scripts/uniquify-module-names.py \
|
||||||
--model-hier-json $(MFC_MODEL_HRCHY_JSON) \
|
--model-hier-json $(MFC_MODEL_HRCHY_JSON) \
|
||||||
|
--top-hier-json $(MFC_TOP_HRCHY_JSON) \
|
||||||
|
--in-all-filelist $(MFC_FILELIST) \
|
||||||
--dut $(TOP) \
|
--dut $(TOP) \
|
||||||
|
--model $(MODEL) \
|
||||||
|
--target-dir $(GEN_COLLATERAL_DIR) \
|
||||||
--out-dut-filelist $(TOP_MODS_FILELIST) \
|
--out-dut-filelist $(TOP_MODS_FILELIST) \
|
||||||
--out-model-filelist $(MODEL_MODS_FILELIST) \
|
--out-model-filelist $(MODEL_MODS_FILELIST) \
|
||||||
--in-all-filelist $(MFC_FILELIST) \
|
--out-model-hier-json $(MFC_MODEL_HRCHY_JSON_UNIQUIFIED) \
|
||||||
--target-dir $(GEN_COLLATERAL_DIR)
|
--gcpath $(GEN_COLLATERAL_DIR)
|
||||||
$(SED) -e 's;^;$(GEN_COLLATERAL_DIR)/;' $(MFC_BB_MODS_FILELIST) > $(BB_MODS_FILELIST)
|
$(SED) -e 's;^;$(GEN_COLLATERAL_DIR)/;' $(MFC_BB_MODS_FILELIST) > $(BB_MODS_FILELIST)
|
||||||
$(SED) -i 's/\.\///' $(TOP_MODS_FILELIST)
|
$(SED) -i 's/\.\///' $(TOP_MODS_FILELIST)
|
||||||
$(SED) -i 's/\.\///' $(MODEL_MODS_FILELIST)
|
$(SED) -i 's/\.\///' $(MODEL_MODS_FILELIST)
|
||||||
$(SED) -i 's/\.\///' $(BB_MODS_FILELIST)
|
$(SED) -i 's/\.\///' $(BB_MODS_FILELIST)
|
||||||
sort -u $(TOP_MODS_FILELIST) $(MODEL_MODS_FILELIST) $(BB_MODS_FILELIST) > $(ALL_MODS_FILELIST)
|
sort -u $(TOP_MODS_FILELIST) $(MODEL_MODS_FILELIST) $(BB_MODS_FILELIST) > $(ALL_MODS_FILELIST)
|
||||||
|
|
||||||
$(TOP_BB_MODS_FILELIST) $(MODEL_BB_MODS_FILELIST) &: $(BB_MODS_FILELIST) $(MFC_TOP_HRCHY_JSON) $(FINAL_ANNO_FILE)
|
$(TOP_SMEMS_CONF) $(MODEL_SMEMS_CONF) &: $(MFC_SMEMS_CONF) $(MFC_MODEL_HRCHY_JSON_UNIQUIFIED)
|
||||||
$(base_dir)/scripts/split-bb-files.py \
|
|
||||||
--in-bb-f $(BB_MODS_FILELIST) \
|
|
||||||
--in-top-hrchy-json $(MFC_TOP_HRCHY_JSON) \
|
|
||||||
--in-anno-json $(FINAL_ANNO_FILE) \
|
|
||||||
--out-top-bb-f $(TOP_BB_MODS_FILELIST) \
|
|
||||||
--out-model-bb-f $(MODEL_BB_MODS_FILELIST)
|
|
||||||
|
|
||||||
$(TOP_SMEMS_CONF) $(MODEL_SMEMS_CONF) &: $(MFC_SMEMS_CONF) $(MFC_MODEL_HRCHY_JSON)
|
|
||||||
$(base_dir)/scripts/split-mems-conf.py \
|
$(base_dir)/scripts/split-mems-conf.py \
|
||||||
--in-smems-conf $(MFC_SMEMS_CONF) \
|
--in-smems-conf $(MFC_SMEMS_CONF) \
|
||||||
--in-model-hrchy-json $(MFC_MODEL_HRCHY_JSON) \
|
--in-model-hrchy-json $(MFC_MODEL_HRCHY_JSON_UNIQUIFIED) \
|
||||||
--dut-module-name $(TOP) \
|
--dut-module-name $(TOP) \
|
||||||
--model-module-name $(MODEL) \
|
--model-module-name $(MODEL) \
|
||||||
--out-dut-smems-conf $(TOP_SMEMS_CONF) \
|
--out-dut-smems-conf $(TOP_SMEMS_CONF) \
|
||||||
@@ -284,7 +280,7 @@ $(MODEL_SMEMS_FILE) $(MODEL_SMEMS_FIR) &: $(BTL_CLASSPATH_TARGETS) $(MODEL_SMEMS
|
|||||||
# note: {MODEL,TOP}_BB_MODS_FILELIST is added as a req. so that the files get generated,
|
# note: {MODEL,TOP}_BB_MODS_FILELIST is added as a req. so that the files get generated,
|
||||||
# however it is really unneeded since ALL_MODS_FILELIST includes all BB files
|
# however it is really unneeded since ALL_MODS_FILELIST includes all BB files
|
||||||
########################################################################################
|
########################################################################################
|
||||||
$(sim_common_files): $(sim_files) $(ALL_MODS_FILELIST) $(TOP_SMEMS_FILE) $(MODEL_SMEMS_FILE) $(TOP_BB_MODS_FILELIST) $(MODEL_BB_MODS_FILELIST)
|
$(sim_common_files): $(sim_files) $(ALL_MODS_FILELIST) $(TOP_SMEMS_FILE) $(MODEL_SMEMS_FILE) $(BB_MODS_FILELIST)
|
||||||
sort -u $(sim_files) $(ALL_MODS_FILELIST) | grep -v '.*\.\(svh\|h\)$$' > $@
|
sort -u $(sim_files) $(ALL_MODS_FILELIST) | grep -v '.*\.\(svh\|h\)$$' > $@
|
||||||
echo "$(TOP_SMEMS_FILE)" >> $@
|
echo "$(TOP_SMEMS_FILE)" >> $@
|
||||||
echo "$(MODEL_SMEMS_FILE)" >> $@
|
echo "$(MODEL_SMEMS_FILE)" >> $@
|
||||||
@@ -304,6 +300,11 @@ check-binary:
|
|||||||
ifeq (,$(BINARY))
|
ifeq (,$(BINARY))
|
||||||
$(error BINARY variable is not set. Set it to the simulation binary)
|
$(error BINARY variable is not set. Set it to the simulation binary)
|
||||||
endif
|
endif
|
||||||
|
ifneq (none,$(BINARY))
|
||||||
|
ifeq ("$(wildcard $(BINARY))","")
|
||||||
|
$(error BINARY=$(BINARY) not found)
|
||||||
|
endif
|
||||||
|
endif
|
||||||
|
|
||||||
# allow you to override sim prereq
|
# allow you to override sim prereq
|
||||||
ifeq (,$(BREAK_SIM_PREREQ))
|
ifeq (,$(BREAK_SIM_PREREQ))
|
||||||
@@ -321,34 +322,23 @@ run-binary-fast: $(SIM_PREREQ) check-binary | $(output_dir)
|
|||||||
|
|
||||||
# run simulator with as much debug info as possible
|
# run simulator with as much debug info as possible
|
||||||
run-binary-debug: $(SIM_DEBUG_PREREQ) check-binary | $(output_dir)
|
run-binary-debug: $(SIM_DEBUG_PREREQ) check-binary | $(output_dir)
|
||||||
|
ifneq (none,$(BINARY))
|
||||||
|
riscv64-unknown-elf-objdump -D $(BINARY) > $(sim_out_name).dump
|
||||||
|
endif
|
||||||
(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)
|
(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
|
||||||
|
|
||||||
#########################################################################################
|
#########################################################################################
|
||||||
# helper rules to run simulator with fast loadmem via hex files
|
# helper rules to run simulator with fast loadmem
|
||||||
|
# LEGACY - use LOADMEM=1 instead
|
||||||
#########################################################################################
|
#########################################################################################
|
||||||
$(binary_hex): $(firstword $(BINARY)) | $(output_dir)
|
|
||||||
$(base_dir)/scripts/smartelf2hex.sh $(firstword $(BINARY)) > $(binary_hex)
|
|
||||||
|
|
||||||
run-binary-hex: check-binary
|
|
||||||
run-binary-hex: $(SIM_PREREQ) $(binary_hex) | $(output_dir)
|
|
||||||
run-binary-hex: run-binary
|
run-binary-hex: run-binary
|
||||||
run-binary-hex: override LOADMEM_ADDR = 80000000
|
run-binary-hex: override SIM_FLAGS += +loadmem=$(BINARY)
|
||||||
run-binary-hex: override LOADMEM = $(binary_hex)
|
|
||||||
run-binary-hex: override SIM_FLAGS += +loadmem=$(LOADMEM) +loadmem_addr=$(LOADMEM_ADDR)
|
|
||||||
run-binary-debug-hex: check-binary
|
|
||||||
run-binary-debug-hex: $(SIM_DEBUG_REREQ) $(binary_hex) | $(output_dir)
|
|
||||||
run-binary-debug-hex: run-binary-debug
|
run-binary-debug-hex: run-binary-debug
|
||||||
run-binary-debug-hex: override LOADMEM_ADDR = 80000000
|
run-binary-debug-hex: override SIM_FLAGS += +loadmem=$(BINARY)
|
||||||
run-binary-debug-hex: override LOADMEM = $(binary_hex)
|
|
||||||
run-binary-debug-hex: override SIM_FLAGS += +loadmem=$(LOADMEM) +loadmem_addr=$(LOADMEM_ADDR)
|
|
||||||
run-binary-fast-hex: check-binary
|
|
||||||
run-binary-fast-hex: $(SIM_PREREQ) $(binary_hex) | $(output_dir)
|
|
||||||
run-binary-fast-hex: run-binary-fast
|
run-binary-fast-hex: run-binary-fast
|
||||||
run-binary-fast-hex: override LOADMEM_ADDR = 80000000
|
run-binary-fast-hex: override SIM_FLAGS += +loadmem=$(BINARY)
|
||||||
run-binary-fast-hex: override LOADMEM = $(binary_hex)
|
|
||||||
run-binary-fast-hex: override SIM_FLAGS += +loadmem=$(LOADMEM) +loadmem_addr=$(LOADMEM_ADDR)
|
|
||||||
|
|
||||||
#########################################################################################
|
#########################################################################################
|
||||||
# run assembly/benchmarks rules
|
# run assembly/benchmarks rules
|
||||||
@@ -398,13 +388,9 @@ define \n
|
|||||||
|
|
||||||
endef
|
endef
|
||||||
|
|
||||||
CONFIG_FRAG_LEVELS ?= 3
|
|
||||||
.PHONY: find-config-fragments
|
.PHONY: find-config-fragments
|
||||||
find-config-fragments: private IN_F := $(shell mktemp -d -t cy-XXXXXXXX)/scala_files.f
|
find-config-fragments:
|
||||||
find-config-fragments: $(SCALA_SOURCES)
|
$(call run_scala_main,chipyard,chipyard.ConfigFinder,)
|
||||||
@$(foreach file,$(SCALA_SOURCES),echo $(file) >> $(IN_F)${\n})
|
|
||||||
$(base_dir)/scripts/config-finder.py -l $(CONFIG_FRAG_LEVELS) $(IN_F)
|
|
||||||
@rm -rf $(dir $(IN_F))
|
|
||||||
|
|
||||||
.PHONY: help
|
.PHONY: help
|
||||||
help:
|
help:
|
||||||
|
|||||||
@@ -89,7 +89,7 @@ dependencies:
|
|||||||
- graphviz
|
- graphviz
|
||||||
- expect
|
- expect
|
||||||
- dtc
|
- dtc
|
||||||
- verilator==4.226
|
- verilator==5.008
|
||||||
- screen
|
- screen
|
||||||
- elfutils
|
- elfutils
|
||||||
- libdwarf-dev==0.0.0.20190110_28_ga81397fc4 # from ucb-bar channel - using mainline libdwarf-feedstock
|
- libdwarf-dev==0.0.0.20190110_28_ga81397fc4 # from ucb-bar channel - using mainline libdwarf-feedstock
|
||||||
@@ -103,7 +103,7 @@ dependencies:
|
|||||||
- sty
|
- sty
|
||||||
- open_pdks.sky130a
|
- open_pdks.sky130a
|
||||||
- pip:
|
- pip:
|
||||||
- hammer-vlsi[asap7]==1.1.0
|
- hammer-vlsi[asap7]==1.1.1
|
||||||
|
|
||||||
# doc requirements
|
# doc requirements
|
||||||
- sphinx
|
- sphinx
|
||||||
@@ -131,7 +131,7 @@ dependencies:
|
|||||||
- pytest-mock
|
- pytest-mock
|
||||||
- moto
|
- moto
|
||||||
- mypy
|
- mypy
|
||||||
- s3fs
|
- s3fs==0.4.2
|
||||||
- aiohttp
|
- aiohttp
|
||||||
- pip:
|
- pip:
|
||||||
- sure
|
- sure
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
39
docs/Advanced-Concepts/Architectural-Checkpoints.rst
Normal file
39
docs/Advanced-Concepts/Architectural-Checkpoints.rst
Normal file
@@ -0,0 +1,39 @@
|
|||||||
|
.. _checkpointing:
|
||||||
|
|
||||||
|
Architectural Checkpoints
|
||||||
|
=========================
|
||||||
|
|
||||||
|
Chipyard supports generating architectural checkpoints using Spike.
|
||||||
|
These checkpoints contain a snapshot of the architectural state of a RISC-V SoC at some point in the execution of a program.
|
||||||
|
The checkpoints include the contents of cacheable memory, core architectural registers, and core CSRs.
|
||||||
|
RTL simulations of SoCs can resume execution from checkpoints after restoring the architectural state.
|
||||||
|
|
||||||
|
.. note::
|
||||||
|
Currently, only checkpoints of single-core systems are supported
|
||||||
|
|
||||||
|
Generating Checkpoints
|
||||||
|
------------------------
|
||||||
|
|
||||||
|
``scripts/generate-ckpt.sh`` is a script that runs spike with the right commands to generate an architectural checkpoint
|
||||||
|
``scripts/generate-ckpt.sh -h`` lists options for checkpoint generation.
|
||||||
|
|
||||||
|
Example: run the ``hello.riscv`` binary for 1000 instructions before generating a checkpoint.
|
||||||
|
This should produce a directory named ``hello.riscv.0x80000000.1000.loadarch``
|
||||||
|
|
||||||
|
.. code::
|
||||||
|
|
||||||
|
scripts/generate-ckpt.sh -b tests/hello.riscv -i 1000
|
||||||
|
|
||||||
|
|
||||||
|
Loading Checkpoints in RTL Simulation
|
||||||
|
--------------------------------------
|
||||||
|
|
||||||
|
Checkpoints can be loaded in RTL simulations with the ``LOADARCH`` flag.
|
||||||
|
The target config **MUST** use dmi-based bringup (as opposed to the default TSI-based bringup), and support fast ``LOADMEM``.
|
||||||
|
The target config should also match the architectural configuration of however spike was configured when generating the checkpoint.
|
||||||
|
|
||||||
|
.. code::
|
||||||
|
|
||||||
|
cd sims/vcs
|
||||||
|
make CONFIG=dmiRocketConfig run-binary LOADARCH=../../hello.riscv.0x80000000.1000.loadarch
|
||||||
|
|
||||||
@@ -47,12 +47,12 @@ Using the Tethered Serial Interface (TSI)
|
|||||||
By default, Chipyard uses the Tethered Serial Interface (TSI) to communicate with the DUT.
|
By default, Chipyard uses the Tethered Serial Interface (TSI) to communicate with the DUT.
|
||||||
TSI protocol is an implementation of HTIF that is used to send commands to the RISC-V DUT.
|
TSI protocol is an implementation of HTIF that is used to send commands to the RISC-V DUT.
|
||||||
These TSI commands are simple R/W commands that are able to access the DUT's memory space.
|
These TSI commands are simple R/W commands that are able to access the DUT's memory space.
|
||||||
During simulation, the host sends TSI commands to a simulation stub in the test harness called ``SimSerial``
|
During simulation, the host sends TSI commands to a simulation stub in the test harness called ``SimTSI``
|
||||||
(C++ class) that resides in a ``SimSerial`` Verilog module (both are located in the ``generators/testchipip``
|
(C++ class) that resides in a ``SimTSI`` Verilog module (both are located in the ``generators/testchipip``
|
||||||
project).
|
project).
|
||||||
This ``SimSerial`` Verilog module then sends the TSI command recieved by the simulation stub
|
This ``SimTSI`` Verilog module then sends the TSI command recieved by the simulation stub
|
||||||
to an adapter that converts the TSI command into a TileLink request.
|
to an adapter that converts the TSI command into a TileLink request.
|
||||||
This conversion is done by the ``SerialAdapter`` module (located in the ``generators/testchipip`` project).
|
This conversion is done by the ``TSIToTileLink`` module (located in the ``generators/testchipip`` project).
|
||||||
After the transaction is converted to TileLink, the ``TLSerdesser`` (located in ``generators/testchipip``) serializes the
|
After the transaction is converted to TileLink, the ``TLSerdesser`` (located in ``generators/testchipip``) serializes the
|
||||||
transaction and sends it to the chip (this ``TLSerdesser`` is sometimes also referred to as a digital serial-link or SerDes).
|
transaction and sends it to the chip (this ``TLSerdesser`` is sometimes also referred to as a digital serial-link or SerDes).
|
||||||
Once the serialized transaction is received on the chip, it is deserialized and masters a TileLink bus on the chip
|
Once the serialized transaction is received on the chip, it is deserialized and masters a TileLink bus on the chip
|
||||||
@@ -76,7 +76,7 @@ simulation stub called ``SimDTM`` (C++ class) that resides in a ``SimDTM`` Veril
|
|||||||
sends the DMI command recieved by the simulation stub into the DUT which then converts the DMI
|
sends the DMI command recieved by the simulation stub into the DUT which then converts the DMI
|
||||||
command into a TileLink request. This conversion is done by the DTM named ``DebugModule`` in the ``generators/rocket-chip`` project.
|
command into a TileLink request. This conversion is done by the DTM named ``DebugModule`` in the ``generators/rocket-chip`` project.
|
||||||
When the DTM receives the program to load, it starts to write the binary byte-wise into memory.
|
When the DTM receives the program to load, it starts to write the binary byte-wise into memory.
|
||||||
This is considerably slower than the TSI protocol communication pipeline (i.e. ``SimSerial``/``SerialAdapter``/TileLink)
|
This is considerably slower than the TSI protocol communication pipeline (i.e. ``SimTSI``/``TSIToTileLink``/TileLink)
|
||||||
which directly writes the program binary to memory.
|
which directly writes the program binary to memory.
|
||||||
|
|
||||||
Starting the TSI or DMI Simulation
|
Starting the TSI or DMI Simulation
|
||||||
@@ -206,13 +206,17 @@ This type of simulation setup is done in the following multi-clock configuration
|
|||||||
:start-after: DOC include start: MulticlockAXIOverSerialConfig
|
:start-after: DOC include start: MulticlockAXIOverSerialConfig
|
||||||
:end-before: DOC include end: MulticlockAXIOverSerialConfig
|
:end-before: DOC include end: MulticlockAXIOverSerialConfig
|
||||||
|
|
||||||
Bringup Setup of the Example Test Chip after Tapeout
|
Softcore-driven Bringup Setup of the Example Test Chip after Tapeout
|
||||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
|
.. warning::
|
||||||
|
Bringing up test chips with a FPGA softcore as described here is discouraged.
|
||||||
|
An alternative approach using the FPGA to "bridge" between a host computer and the test chip is the preferred approach.
|
||||||
|
|
||||||
Assuming this example test chip is taped out and now ready to be tested, we can communicate with the chip using this serial-link.
|
Assuming this example test chip is taped out and now ready to be tested, we can communicate with the chip using this serial-link.
|
||||||
For example, a common test setup used at Berkeley to evaluate Chipyard-based test-chips includes an FPGA running a RISC-V soft-core that is able to speak to the DUT (over an FMC).
|
For example, a common test setup used at Berkeley to evaluate Chipyard-based test-chips includes an FPGA running a RISC-V soft-core that is able to speak to the DUT (over an FMC).
|
||||||
This RISC-V soft-core would serve as the host of the test that will run on the DUT.
|
This RISC-V soft-core would serve as the host of the test that will run on the DUT.
|
||||||
This is done by the RISC-V soft-core running FESVR, sending TSI commands to a ``SerialAdapter`` / ``TLSerdesser`` programmed on the FPGA.
|
This is done by the RISC-V soft-core running FESVR, sending TSI commands to a ``TSIToTileLink`` / ``TLSerdesser`` programmed on the FPGA.
|
||||||
Once the commands are converted to serialized TileLink, then they can be sent over some medium to the DUT
|
Once the commands are converted to serialized TileLink, then they can be sent over some medium to the DUT
|
||||||
(like an FMC cable or a set of wires connecting FPGA outputs to the DUT board).
|
(like an FMC cable or a set of wires connecting FPGA outputs to the DUT board).
|
||||||
Similar to simulation, if the chip requests offchip memory, it can then send the transaction back over the serial-link.
|
Similar to simulation, if the chip requests offchip memory, it can then send the transaction back over the serial-link.
|
||||||
@@ -222,4 +226,4 @@ The following image shows this flow:
|
|||||||
.. image:: ../_static/images/chip-bringup.png
|
.. image:: ../_static/images/chip-bringup.png
|
||||||
|
|
||||||
In fact, this exact type of bringup setup is what the following section discusses:
|
In fact, this exact type of bringup setup is what the following section discusses:
|
||||||
:ref:`Prototyping/VCU118:Introduction to the Bringup Design`.
|
:ref:_legacy-vcu118-bringup.
|
||||||
|
|||||||
@@ -18,12 +18,12 @@ for a new clock domain.
|
|||||||
This is useful for simulating systems in which modules in the harness have independent clock domains
|
This is useful for simulating systems in which modules in the harness have independent clock domains
|
||||||
from the DUT.
|
from the DUT.
|
||||||
|
|
||||||
Requests for a harness clock is done by the ``HarnessClockInstantiator`` class in ``generators/chipyard/src/main/scala/TestHarness.scala``.
|
Requests for a harness clock is done by the ``HarnessClockInstantiator`` class in ``generators/chipyard/src/main/scala/harness/TestHarness.scala``.
|
||||||
This class is accessed in harness components by referencing the Rocket Chip parameters key ``p(HarnessClockInstantiatorKey)``.
|
This class is accessed in harness components by referencing the Rocket Chip parameters key ``p(HarnessClockInstantiatorKey)``.
|
||||||
Then you can request a clock and syncronized reset at a particular frequency by invoking the ``requestClockBundle`` function.
|
Then you can request a clock and syncronized reset at a particular frequency by invoking the ``requestClockBundle`` function.
|
||||||
Take the following example:
|
Take the following example:
|
||||||
|
|
||||||
.. literalinclude:: ../../generators/chipyard/src/main/scala/HarnessBinders.scala
|
.. literalinclude:: ../../generators/chipyard/src/main/scala/harness/HarnessBinders.scala
|
||||||
:language: scala
|
:language: scala
|
||||||
:start-after: DOC include start: HarnessClockInstantiatorEx
|
:start-after: DOC include start: HarnessClockInstantiatorEx
|
||||||
:end-before: DOC include end: HarnessClockInstantiatorEx
|
:end-before: DOC include end: HarnessClockInstantiatorEx
|
||||||
|
|||||||
@@ -2,24 +2,24 @@ Accessing Scala Resources
|
|||||||
===============================
|
===============================
|
||||||
|
|
||||||
A simple way to copy over a source file to the build directory to be used for a simulation compile or VLSI flow is to use the ``addResource`` function given by FIRRTL.
|
A simple way to copy over a source file to the build directory to be used for a simulation compile or VLSI flow is to use the ``addResource`` function given by FIRRTL.
|
||||||
An example of its use can be seen in `generators/testchipip/src/main/scala/SerialAdapter.scala <https://github.com/ucb-bar/testchipip/blob/master/src/main/scala/SerialAdapter.scala>`_.
|
An example of its use can be seen in `generators/testchipip/src/main/scala/SimTSI.scala <https://github.com/ucb-bar/testchipip/blob/master/src/main/scala/SimTSI.scala>`_.
|
||||||
Here is the example inlined:
|
Here is the example inlined:
|
||||||
|
|
||||||
.. code-block:: scala
|
.. code-block:: scala
|
||||||
|
|
||||||
class SimSerial(w: Int) extends BlackBox with HasBlackBoxResource {
|
class SimTSI extends BlackBox with HasBlackBoxResource {
|
||||||
val io = IO(new Bundle {
|
val io = IO(new Bundle {
|
||||||
val clock = Input(Clock())
|
val clock = Input(Clock())
|
||||||
val reset = Input(Bool())
|
val reset = Input(Bool())
|
||||||
val serial = Flipped(new SerialIO(w))
|
val tsi = Flipped(new TSIIO)
|
||||||
val exit = Output(Bool())
|
val exit = Output(Bool())
|
||||||
})
|
})
|
||||||
|
|
||||||
addResource("/testchipip/vsrc/SimSerial.v")
|
addResource("/testchipip/vsrc/SimTSI.v")
|
||||||
addResource("/testchipip/csrc/SimSerial.cc")
|
addResource("/testchipip/csrc/SimTSI.cc")
|
||||||
}
|
}
|
||||||
|
|
||||||
In this example, the ``SimSerial`` files will be copied from a specific folder (in this case the ``path/to/testchipip/src/main/resources/testchipip/...``) to the build folder.
|
In this example, the ``SimTSI`` files will be copied from a specific folder (in this case the ``path/to/testchipip/src/main/resources/testchipip/...``) to the build folder.
|
||||||
The ``addResource`` path retrieves resources from the ``src/main/resources`` directory.
|
The ``addResource`` path retrieves resources from the ``src/main/resources`` directory.
|
||||||
So to get an item at ``src/main/resources/fileA.v`` you can use ``addResource("/fileA.v")``.
|
So to get an item at ``src/main/resources/fileA.v`` you can use ``addResource("/fileA.v")``.
|
||||||
However, one caveat of this approach is that to retrieve the file during the FIRRTL compile, you must have that project in the FIRRTL compiler's classpath.
|
However, one caveat of this approach is that to retrieve the file during the FIRRTL compile, you must have that project in the FIRRTL compiler's classpath.
|
||||||
|
|||||||
@@ -18,6 +18,13 @@ The ``IOBinders`` are responsible for instantiating the IO cells for ``ChipTop``
|
|||||||
The ``HarnessBinders`` are responsible for instantiating test harness collateral that connects to the ``ChipTop`` ports.
|
The ``HarnessBinders`` are responsible for instantiating test harness collateral that connects to the ``ChipTop`` ports.
|
||||||
Most types of devices and testing collateral can be instantiated using custom ``IOBinders`` and ``HarnessBinders``.
|
Most types of devices and testing collateral can be instantiated using custom ``IOBinders`` and ``HarnessBinders``.
|
||||||
|
|
||||||
|
Custom ChipTops
|
||||||
|
^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
|
The default standard ``ChipTop`` provides a mimimal, barebones template for ``IOBinders`` to generate IOCells around ``DigitalTop`` traits.
|
||||||
|
For tapeouts, integrating Analog IP, or other non-standard use cases, Chipyard supports specifying a custom ``ChipTop`` using the ``BuildTop`` key.
|
||||||
|
An example of a custom ChipTop which uses non-standard IOCells is provided in `generators/chipyard/src/main/scala/example/CustomChipTop.scala <https://github.com/ucb-bar/chipyard/blob/main/generators/chipyard/src/main/scala/example/CustomChipTop.scala>`__
|
||||||
|
|
||||||
|
|
||||||
System/DigitalTop
|
System/DigitalTop
|
||||||
-------------------------
|
-------------------------
|
||||||
|
|||||||
@@ -16,3 +16,4 @@ They expect you to know about Chisel, Parameters, configs, etc.
|
|||||||
CDEs
|
CDEs
|
||||||
Harness-Clocks
|
Harness-Clocks
|
||||||
Managing-Published-Scala-Dependencies
|
Managing-Published-Scala-Dependencies
|
||||||
|
Architectural-Checkpoints
|
||||||
|
|||||||
@@ -83,8 +83,8 @@ This example shows the Chipyard default top that composes multiple traits togeth
|
|||||||
:end-before: DOC include end: DigitalTop
|
:end-before: DOC include end: DigitalTop
|
||||||
|
|
||||||
|
|
||||||
There are two "cakes" or mixins here. One for the lazy module (ex. ``CanHavePeripherySerial``) and one for the lazy module
|
There are two "cakes" or mixins here. One for the lazy module (ex. ``CanHavePeripheryTLSerial``) and one for the lazy module
|
||||||
implementation (ex. ``CanHavePeripherySerialModuleImp`` where ``Imp`` refers to implementation). The lazy module defines
|
implementation (ex. ``CanHavePeripheryTLSerialModuleImp`` where ``Imp`` refers to implementation). The lazy module defines
|
||||||
all the logical connections between generators and exchanges configuration information among them, while the
|
all the logical connections between generators and exchanges configuration information among them, while the
|
||||||
lazy module implementation performs the actual Chisel RTL elaboration.
|
lazy module implementation performs the actual Chisel RTL elaboration.
|
||||||
|
|
||||||
@@ -93,19 +93,17 @@ In the ``DigitalTop`` example class, the "outer" ``DigitalTop`` instantiates the
|
|||||||
of the module until all logical connections are determined and all configuration information is exchanged.
|
of the module until all logical connections are determined and all configuration information is exchanged.
|
||||||
The ``System`` outer base class, as well as the
|
The ``System`` outer base class, as well as the
|
||||||
``CanHavePeriphery<X>`` outer traits contain code to perform high-level logical
|
``CanHavePeriphery<X>`` outer traits contain code to perform high-level logical
|
||||||
connections. For example, the ``CanHavePeripherySerial`` outer trait contains code
|
connections. For example, the ``CanHavePeripheryTLSerial`` outer trait contains code
|
||||||
to optionally lazily instantiate the ``SerialAdapter``, and connect the ``SerialAdapter``'s
|
to optionally lazily instantiate the ``TLSerdesser``, and connect the ``TLSerdesser`` 's
|
||||||
TileLink node to the Front bus.
|
TileLink node to the Front bus.
|
||||||
|
|
||||||
The ``ModuleImp`` classes and traits perform elaboration of real RTL.
|
The ``ModuleImp`` classes and traits perform elaboration of real RTL.
|
||||||
For example, the ``CanHavePeripherySerialModuleImp`` trait optionally physically connects
|
|
||||||
the ``SerialAdapter`` module, and instantiates queues.
|
|
||||||
|
|
||||||
In the test harness, the SoC is elaborated with
|
In the test harness, the SoC is elaborated with
|
||||||
``val dut = p(BuildTop)(p)``.
|
``val dut = p(BuildTop)(p)``.
|
||||||
|
|
||||||
After elaboration, the system submodule of ``ChipTop`` will be a ``DigitalTop`` module, which contains a
|
After elaboration, the system submodule of ``ChipTop`` will be a ``DigitalTop`` module, which contains a
|
||||||
``SerialAdapter`` module (among others), if the config specified for that block to be instantiated.
|
``TLSerdesser`` module (among others), if the config specified for that block to be instantiated.
|
||||||
|
|
||||||
From a high level, classes which extend ``LazyModule`` *must* reference
|
From a high level, classes which extend ``LazyModule`` *must* reference
|
||||||
their module implementation through ``lazy val module``, and they
|
their module implementation through ``lazy val module``, and they
|
||||||
@@ -116,7 +114,7 @@ other normal modules OR lazy modules (for nested Diplomacy
|
|||||||
graphs, for example).
|
graphs, for example).
|
||||||
|
|
||||||
The naming convention for an additive mixin or trait is ``CanHave<YourMixin>``.
|
The naming convention for an additive mixin or trait is ``CanHave<YourMixin>``.
|
||||||
This is shown in the ``Top`` class where things such as ``CanHavePeripherySerial`` connect a RTL component to a bus and expose signals to the top-level.
|
This is shown in the ``Top`` class where things such as ``CanHavePeripheryTLSerial`` connect a RTL component to a bus and expose signals to the top-level.
|
||||||
|
|
||||||
Additional References
|
Additional References
|
||||||
---------------------------
|
---------------------------
|
||||||
|
|||||||
@@ -31,7 +31,7 @@ Like ``IOBinders``, ``HarnessBinders`` are defined using macros (``OverrideHarne
|
|||||||
|
|
||||||
For exmaple, the ``WithUARTAdapter`` will connect the UART SW display adapter to the ports generated by the ``WithUARTIOCells`` described earlier, if those ports are present.
|
For exmaple, the ``WithUARTAdapter`` will connect the UART SW display adapter to the ports generated by the ``WithUARTIOCells`` described earlier, if those ports are present.
|
||||||
|
|
||||||
.. literalinclude:: ../../generators/chipyard/src/main/scala/HarnessBinders.scala
|
.. literalinclude:: ../../generators/chipyard/src/main/scala/harness/HarnessBinders.scala
|
||||||
:language: scala
|
:language: scala
|
||||||
:start-after: DOC include start: WithUARTAdapter
|
:start-after: DOC include start: WithUARTAdapter
|
||||||
:end-before: DOC include end: WithUARTAdapter
|
:end-before: DOC include end: WithUARTAdapter
|
||||||
|
|||||||
@@ -79,5 +79,4 @@ We can use this config fragment when composing our configs.
|
|||||||
Chipyard Config Fragments
|
Chipyard Config Fragments
|
||||||
-------------------------
|
-------------------------
|
||||||
|
|
||||||
For discoverability, users can run ``make find-config-fragments`` to see a list of config. fragments
|
For discoverability, users can run ``make find-config-fragments`` to see a list of config. fragments.
|
||||||
(config. fragments that match "class NAME extends CONFIG\n" on a single line and a subset of their children) and their file path in a fully initialized Chipyard repository.
|
|
||||||
|
|||||||
@@ -2,16 +2,16 @@ Test Chip IP
|
|||||||
============
|
============
|
||||||
|
|
||||||
Chipyard includes a Test Chip IP library which provides various hardware
|
Chipyard includes a Test Chip IP library which provides various hardware
|
||||||
widgets that may be useful when designing SoCs. This includes a :ref:`Generators/TestChipIP:Serial Adapter`,
|
widgets that may be useful when designing SoCs. This includes a :ref:`Generators/TestChipIP:SimTSI`,
|
||||||
:ref:`Generators/TestChipIP:Block Device Controller`, :ref:`Generators/TestChipIP:TileLink SERDES`, :ref:`Generators/TestChipIP:TileLink Switcher`,
|
:ref:`Generators/TestChipIP:Block Device Controller`, :ref:`Generators/TestChipIP:TileLink SERDES`, :ref:`Generators/TestChipIP:TileLink Switcher`,
|
||||||
:ref:`Generators/TestChipIP:TileLink Ring Network`, and :ref:`Generators/TestChipIP:UART Adapter`.
|
:ref:`Generators/TestChipIP:TileLink Ring Network`, and :ref:`Generators/TestChipIP:UART Adapter`.
|
||||||
|
|
||||||
Serial Adapter
|
SimTSI
|
||||||
--------------
|
--------------
|
||||||
|
|
||||||
The serial adapter is used by tethered test chips to communicate with the host
|
The SimTSI and TSIToTileLink are used by tethered test chips to communicate with the host
|
||||||
processor. An instance of RISC-V frontend server running on the host CPU
|
processor. An instance of RISC-V frontend server running on the host CPU
|
||||||
can send commands to the serial adapter to read and write data from the memory
|
can send commands to the TSIToTileLink to read and write data from the memory
|
||||||
system. The frontend server uses this functionality to load the test program
|
system. The frontend server uses this functionality to load the test program
|
||||||
into memory and to poll for completion of the program. More information on
|
into memory and to poll for completion of the program. More information on
|
||||||
this can be found in :ref:`Customization/Boot-Process:Chipyard Boot Process`.
|
this can be found in :ref:`Customization/Boot-Process:Chipyard Boot Process`.
|
||||||
|
|||||||
@@ -1,18 +1,11 @@
|
|||||||
General Setup and Usage
|
General Setup and Usage
|
||||||
==============================
|
==============================
|
||||||
|
|
||||||
Sources and Submodule Setup
|
Sources
|
||||||
---------------------------
|
---------------------------
|
||||||
|
|
||||||
All FPGA prototyping-related collateral and sources are located in the ``fpga`` top-level Chipyard directory.
|
All FPGA prototyping-related collateral and sources are located in the ``fpga`` top-level Chipyard directory.
|
||||||
This includes the ``fpga-shells`` submodule and the ``src`` directory that hold both Scala, TCL and other collateral.
|
This includes the ``fpga-shells`` submodule and the ``src`` directory that hold both Scala, TCL and other collateral.
|
||||||
However, the ``fpga-shells`` submodule repository is not initialized by default.
|
|
||||||
To initialize the ``fpga-shells`` submodule repository, run the included initialization script from the Chipyard top-level directory:
|
|
||||||
|
|
||||||
.. code-block:: shell
|
|
||||||
|
|
||||||
# in the chipyard top level folder
|
|
||||||
./scripts/init-fpga.sh
|
|
||||||
|
|
||||||
Generating a Bitstream
|
Generating a Bitstream
|
||||||
----------------------
|
----------------------
|
||||||
|
|||||||
@@ -47,8 +47,14 @@ After the harness is created, the ``BundleBridgeSource``'s must be connected to
|
|||||||
This is done with harness binders and io binders (see ``fpga/src/main/scala/vcu118/HarnessBinders.scala`` and ``fpga/src/main/scala/vcu118/IOBinders.scala``).
|
This is done with harness binders and io binders (see ``fpga/src/main/scala/vcu118/HarnessBinders.scala`` and ``fpga/src/main/scala/vcu118/IOBinders.scala``).
|
||||||
For more information on harness binders and io binders, refer to :ref:`Customization/IOBinders:IOBinders and HarnessBinders`.
|
For more information on harness binders and io binders, refer to :ref:`Customization/IOBinders:IOBinders and HarnessBinders`.
|
||||||
|
|
||||||
Introduction to the Bringup Design
|
(Legacy) Introduction to the Legacy Bringup Design
|
||||||
----------------------------------
|
--------------------------------------------------
|
||||||
|
|
||||||
|
.. warning::
|
||||||
|
The bringup VCU118 design described here is designed for old versions of Chipyard SoCs, pre-1.9.1.
|
||||||
|
The key difference is that these designs rely on a clock generated on-chip to synchronize the slow serialized-TileLink interface.
|
||||||
|
After Chipyard 1.9.1, the FPGA host is expected to pass the clock to the chip, instead of the other way around.
|
||||||
|
A new bringup solution will be developed for post-1.9.1 Chipyard designs.
|
||||||
|
|
||||||
An example of a more complicated design used for Chipyard test chips can be viewed in ``fpga/src/main/scala/vcu118/bringup/``.
|
An example of a more complicated design used for Chipyard test chips can be viewed in ``fpga/src/main/scala/vcu118/bringup/``.
|
||||||
This example extends the default test harness and creates new ``Overlays`` to connect to a DUT (connected to the FMC port).
|
This example extends the default test harness and creates new ``Overlays`` to connect to a DUT (connected to the FMC port).
|
||||||
|
|||||||
@@ -151,25 +151,17 @@ Fast Memory Loading
|
|||||||
-------------------
|
-------------------
|
||||||
|
|
||||||
The simulator loads the program binary over a simulated serial line. This can be quite slow if there is a lot of static data, so the simulator also allows data to be loaded from a file directly into the DRAM model.
|
The simulator loads the program binary over a simulated serial line. This can be quite slow if there is a lot of static data, so the simulator also allows data to be loaded from a file directly into the DRAM model.
|
||||||
|
Loadmem files should be ELF files. In the most common use case, this can be the binary.
|
||||||
|
|
||||||
.. code-block:: shell
|
.. code-block:: shell
|
||||||
|
|
||||||
make run-binary BINARY=test.riscv LOADMEM=testdata.hex LOADMEM_ADDR=81000000
|
make run-binary BINARY=test.riscv LOADMEM=test.riscv
|
||||||
|
|
||||||
The ``.hex`` file should be a text file with a hexadecimal number on each line.
|
Usually the ``LOADMEM`` ELF is the same as the ``BINARY`` ELF, so ``LOADMEM=1`` can be used as a shortcut.
|
||||||
|
|
||||||
.. code-block:: text
|
|
||||||
|
|
||||||
deadbeef
|
|
||||||
0123
|
|
||||||
|
|
||||||
Each line uses little-endian order, so this file would produce the bytes "ef be ad de 01 23". ``LOADMEM_ADDR`` specifies which address in memory (in hexadecimal) to write the first byte to. The default is 0x81000000.
|
|
||||||
|
|
||||||
A special target that facilitates automatically generating a hex file for an entire elf RISC-V exectuable and then running the simulator with the appropriate flags is also available.
|
|
||||||
|
|
||||||
.. code-block:: shell
|
.. code-block:: shell
|
||||||
|
|
||||||
make run-binary-hex BINARY=test.riscv
|
make run-binary BINARY=test.riscv LOADMEM=1
|
||||||
|
|
||||||
Generating Waveforms
|
Generating Waveforms
|
||||||
-----------------------
|
-----------------------
|
||||||
|
|||||||
@@ -32,4 +32,21 @@ In this configuration, Spike is cache-coherent, and communicates with the uncore
|
|||||||
|
|
||||||
make CONFIG=SpikeConfig run-binary BINARY=hello.riscv
|
make CONFIG=SpikeConfig run-binary BINARY=hello.riscv
|
||||||
|
|
||||||
|
Spike-as-a-Tile also supports Tightly-Coupled-Memory (TCM) for the SpikeTile, in which the main system memory is entirely modeled
|
||||||
|
within the Spike tile, allowing for very fast simulatoin performance.
|
||||||
|
|
||||||
|
.. code-block:: shell
|
||||||
|
|
||||||
|
make CONFIG=SpikeUltraFastConfig run-binary BINARY=hello.riscv
|
||||||
|
|
||||||
|
Spike-as-a-Tile can be configured with custom IPC, commit logging, and other behaviors. Spike-specific flags can be added as plusargs to ``EXTRA_SIM_FLAGS``
|
||||||
|
|
||||||
|
.. code-block:: shell
|
||||||
|
|
||||||
|
make CONFIG=SpikeUltraFastConfig run-binary BINARY=hello.riscv EXTRA_SPIKE_FLAGS="+spike-ipc=10000 +spike-fast-clint +spike-debug" LOADMEM=1
|
||||||
|
|
||||||
|
|
||||||
|
* ``+spike-ipc=``: Sets the maximum number of instructions Spike can retire in a single "tick", or cycle of the uncore simulation.
|
||||||
|
* ``+spike-fast-clint``: Enables fast-forwarding through WFI stalls by generating fake timer interrupts
|
||||||
|
* ``+spike-debug``: Enables debug Spike logging
|
||||||
|
* ``+spike-verbose``: Enables Spike commit-log generation
|
||||||
|
|||||||
@@ -115,7 +115,7 @@ Timing reports are found in ``build/par-rundir/timingReports``. They are gzipped
|
|||||||
|
|
||||||
.. code-block:: shell
|
.. code-block:: shell
|
||||||
|
|
||||||
./view_gds.py build/chipyard.TestHarness.TinyRocketConfig/par-rundir/ChipTop.gds
|
./view_gds.py build/chipyard.harness.TestHarness.TinyRocketConfig/par-rundir/ChipTop.gds
|
||||||
|
|
||||||
By default, this script only shows the M2 thru M4 routing. Layers can be toggled in the layout viewer's side pane and ``view_gds.py`` has a mapping of layer numbers to layer names.
|
By default, this script only shows the M2 thru M4 routing. Layers can be toggled in the layout viewer's side pane and ``view_gds.py`` has a mapping of layer numbers to layer names.
|
||||||
|
|
||||||
@@ -126,9 +126,9 @@ To run DRC & LVS, and view the results in Calibre:
|
|||||||
.. code-block:: shell
|
.. code-block:: shell
|
||||||
|
|
||||||
make drc CONFIG=TinyRocketConfig
|
make drc CONFIG=TinyRocketConfig
|
||||||
./build/chipyard.TestHarness.TinyRocketConfig-ChipTop/drc-rundir/generated-scripts/view-drc
|
./build/chipyard.harness.TestHarness.TinyRocketConfig-ChipTop/drc-rundir/generated-scripts/view-drc
|
||||||
make lvs CONFIG=TinyRocketConfig
|
make lvs CONFIG=TinyRocketConfig
|
||||||
./build/chipyard.TestHarness.TinyRocketConfig-ChipTop/lvs-rundir/generated-scripts/view-lvs
|
./build/chipyard.harness.TestHarness.TinyRocketConfig-ChipTop/lvs-rundir/generated-scripts/view-lvs
|
||||||
|
|
||||||
Some DRC errors are expected from this PDK, as explained in the `ASAP7 plugin readme <https://github.com/ucb-bar/hammer/blob/master/hammer/technology/asap7>`__.
|
Some DRC errors are expected from this PDK, as explained in the `ASAP7 plugin readme <https://github.com/ucb-bar/hammer/blob/master/hammer/technology/asap7>`__.
|
||||||
Furthermore, the dummy SRAMs that are provided in this tutorial and PDK do not have any geometry inside, so will certainly cause DRC errors.
|
Furthermore, the dummy SRAMs that are provided in this tutorial and PDK do not have any geometry inside, so will certainly cause DRC errors.
|
||||||
|
|||||||
@@ -121,7 +121,7 @@ It is recommended that you edit these variables directly in the Makefile rather
|
|||||||
|
|
||||||
The ``buildfile`` make target has dependencies on both (1) the Verilog that is elaborated from all Chisel sources
|
The ``buildfile`` make target has dependencies on both (1) the Verilog that is elaborated from all Chisel sources
|
||||||
and (2) the mapping of memory instances in the design to SRAM macros;
|
and (2) the mapping of memory instances in the design to SRAM macros;
|
||||||
all files related to these two steps reside in the ``generated-src/chipyard.TestHarness.TinyRocketConfig-ChipTop`` directory.
|
all files related to these two steps reside in the ``generated-src/chipyard.harness.TestHarness.TinyRocketConfig-ChipTop`` directory.
|
||||||
Note that the files in ``generated-src`` vary for each tool/technology flow.
|
Note that the files in ``generated-src`` vary for each tool/technology flow.
|
||||||
This especially applies to the Sky130 Commercial vs OpenROAD tutorial flows
|
This especially applies to the Sky130 Commercial vs OpenROAD tutorial flows
|
||||||
(due to the ``ENABLE_YOSYS_FLOW`` flag present for the OpenROAD flow), so these flows should be run in separate
|
(due to the ``ENABLE_YOSYS_FLOW`` flag present for the OpenROAD flow), so these flows should be run in separate
|
||||||
@@ -168,9 +168,9 @@ To run DRC & LVS, and view the results in Calibre:
|
|||||||
.. code-block:: shell
|
.. code-block:: shell
|
||||||
|
|
||||||
make drc tutorial=sky130-commercial
|
make drc tutorial=sky130-commercial
|
||||||
./build/chipyard.TestHarness.TinyRocketConfig-ChipTop/drc-rundir/generated-scripts/view_drc
|
./build/chipyard.harness.TestHarness.TinyRocketConfig-ChipTop/drc-rundir/generated-scripts/view_drc
|
||||||
make lvs tutorial=sky130-commercial
|
make lvs tutorial=sky130-commercial
|
||||||
./build/chipyard.TestHarness.TinyRocketConfig-ChipTop/lvs-rundir/generated-scripts/view_lvs
|
./build/chipyard.harness.TestHarness.TinyRocketConfig-ChipTop/lvs-rundir/generated-scripts/view_lvs
|
||||||
|
|
||||||
Some DRC errors are expected from this PDK, especially with regards to the SRAMs, as explained in the
|
Some DRC errors are expected from this PDK, especially with regards to the SRAMs, as explained in the
|
||||||
`Sky130 Hammer plugin README <https://github.com/ucb-bar/hammer/blob/master/hammer/technology/sky130>`__.
|
`Sky130 Hammer plugin README <https://github.com/ucb-bar/hammer/blob/master/hammer/technology/sky130>`__.
|
||||||
|
|||||||
@@ -149,7 +149,7 @@ It is recommended that you edit these variables directly in the Makefile rather
|
|||||||
|
|
||||||
The ``buildfile`` make target has dependencies on both (1) the Verilog that is elaborated from all Chisel sources
|
The ``buildfile`` make target has dependencies on both (1) the Verilog that is elaborated from all Chisel sources
|
||||||
and (2) the mapping of memory instances in the design to SRAM macros;
|
and (2) the mapping of memory instances in the design to SRAM macros;
|
||||||
all files related to these two steps reside in the ``generated-src/chipyard.TestHarness.TinyRocketConfig-ChipTop`` directory.
|
all files related to these two steps reside in the ``generated-src/chipyard.harness.TestHarness.TinyRocketConfig-ChipTop`` directory.
|
||||||
Note that the files in ``generated-src`` vary for each tool/technology flow.
|
Note that the files in ``generated-src`` vary for each tool/technology flow.
|
||||||
This especially applies to the Sky130 Commercial vs OpenROAD tutorial flows
|
This especially applies to the Sky130 Commercial vs OpenROAD tutorial flows
|
||||||
(due to the ``ENABLE_YOSYS_FLOW`` flag, explained below), so these flows should be run in separate
|
(due to the ``ENABLE_YOSYS_FLOW`` flag, explained below), so these flows should be run in separate
|
||||||
@@ -197,7 +197,7 @@ Hammer generates a convenient script to launch these sessions
|
|||||||
|
|
||||||
.. code-block:: shell
|
.. code-block:: shell
|
||||||
|
|
||||||
cd ./build/chipyard.TestHarness.TinyRocketConfig-ChipTop/par-rundir
|
cd ./build/chipyard.harness.TestHarness.TinyRocketConfig-ChipTop/par-rundir
|
||||||
./generated-scripts/open_chip
|
./generated-scripts/open_chip
|
||||||
|
|
||||||
Note that the conda OpenROAD package was compiled with the GUI disabled, so in order to view the layout,
|
Note that the conda OpenROAD package was compiled with the GUI disabled, so in order to view the layout,
|
||||||
@@ -212,7 +212,7 @@ These databases can be restored using the same ``open_chip`` script for debuggin
|
|||||||
|
|
||||||
.. code-block:: shell
|
.. code-block:: shell
|
||||||
|
|
||||||
cd build/chipyard.TestHarness.TinyRocketConfig-ChipTop/par-rundir
|
cd build/chipyard.harness.TestHarness.TinyRocketConfig-ChipTop/par-rundir
|
||||||
./generated_scripts/open_chip -h
|
./generated_scripts/open_chip -h
|
||||||
"
|
"
|
||||||
Usage: ./generated-scripts/open_chip [-t] [openroad_db_name]
|
Usage: ./generated-scripts/open_chip [-t] [openroad_db_name]
|
||||||
@@ -245,9 +245,9 @@ To run DRC & LVS in Magic & Netgen, respectively:
|
|||||||
.. code-block:: shell
|
.. code-block:: shell
|
||||||
|
|
||||||
make drc tutorial=sky130-openroad
|
make drc tutorial=sky130-openroad
|
||||||
./build/chipyard.TestHarness.TinyRocketConfig-ChipTop/drc-rundir/generated-scripts/view_drc
|
./build/chipyard.harness.TestHarness.TinyRocketConfig-ChipTop/drc-rundir/generated-scripts/view_drc
|
||||||
make lvs tutorial=sky130-openroad
|
make lvs tutorial=sky130-openroad
|
||||||
./build/chipyard.TestHarness.TinyRocketConfig-ChipTop/lvs-rundir/generated-scripts/view_lvs
|
./build/chipyard.harness.TestHarness.TinyRocketConfig-ChipTop/lvs-rundir/generated-scripts/view_lvs
|
||||||
|
|
||||||
Note that in ``sky130-openroad.yml`` we have set the following YAML keys:
|
Note that in ``sky130-openroad.yml`` we have set the following YAML keys:
|
||||||
|
|
||||||
|
|||||||
Submodule fpga/fpga-shells updated: b6cd1bb7fe...9f4c6ac571
@@ -1,7 +1,7 @@
|
|||||||
// See LICENSE for license details.
|
// See LICENSE for license details.
|
||||||
package chipyard.fpga.arty
|
package chipyard.fpga.arty
|
||||||
|
|
||||||
import freechips.rocketchip.config._
|
import org.chipsalliance.cde.config._
|
||||||
import freechips.rocketchip.subsystem._
|
import freechips.rocketchip.subsystem._
|
||||||
import freechips.rocketchip.devices.debug._
|
import freechips.rocketchip.devices.debug._
|
||||||
import freechips.rocketchip.devices.tilelink._
|
import freechips.rocketchip.devices.tilelink._
|
||||||
@@ -17,11 +17,11 @@ import chipyard.{BuildSystem}
|
|||||||
|
|
||||||
// DOC include start: AbstractArty and Rocket
|
// DOC include start: AbstractArty and Rocket
|
||||||
class WithArtyTweaks extends Config(
|
class WithArtyTweaks extends Config(
|
||||||
|
new WithArtyResetHarnessBinder ++
|
||||||
new WithArtyJTAGHarnessBinder ++
|
new WithArtyJTAGHarnessBinder ++
|
||||||
new WithArtyUARTHarnessBinder ++
|
new WithArtyUARTHarnessBinder ++
|
||||||
new WithArtyResetHarnessBinder ++
|
|
||||||
new WithDebugResetPassthrough ++
|
new WithDebugResetPassthrough ++
|
||||||
|
new chipyard.harness.WithAllClocksFromHarnessClockInstantiator ++
|
||||||
new chipyard.config.WithDTSTimebase(32768) ++
|
new chipyard.config.WithDTSTimebase(32768) ++
|
||||||
new testchipip.WithNoSerialTL
|
new testchipip.WithNoSerialTL
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -2,7 +2,7 @@ package chipyard.fpga.arty
|
|||||||
|
|
||||||
import chisel3._
|
import chisel3._
|
||||||
|
|
||||||
import freechips.rocketchip.devices.debug.{HasPeripheryDebug, HasPeripheryDebugModuleImp}
|
import freechips.rocketchip.devices.debug.{HasPeripheryDebug}
|
||||||
import freechips.rocketchip.jtag.{JTAGIO}
|
import freechips.rocketchip.jtag.{JTAGIO}
|
||||||
|
|
||||||
import sifive.blocks.devices.uart.{UARTPortIO, HasPeripheryUARTModuleImp}
|
import sifive.blocks.devices.uart.{UARTPortIO, HasPeripheryUARTModuleImp}
|
||||||
@@ -15,15 +15,15 @@ import chipyard.harness.{ComposeHarnessBinder, OverrideHarnessBinder}
|
|||||||
import chipyard.iobinders.JTAGChipIO
|
import chipyard.iobinders.JTAGChipIO
|
||||||
|
|
||||||
class WithArtyResetHarnessBinder extends ComposeHarnessBinder({
|
class WithArtyResetHarnessBinder extends ComposeHarnessBinder({
|
||||||
(system: HasPeripheryDebugModuleImp, th: ArtyFPGATestHarness, ports: Seq[Bool]) => {
|
(system: HasPeripheryDebug, th: ArtyFPGATestHarness, ports: Seq[Data]) => {
|
||||||
require(ports.size == 2)
|
val resetPorts = ports.collect { case b: Bool => b }
|
||||||
|
require(resetPorts.size == 2)
|
||||||
withClockAndReset(th.clock_32MHz, th.ck_rst) {
|
withClockAndReset(th.clock_32MHz, th.ck_rst) {
|
||||||
// Debug module reset
|
// Debug module reset
|
||||||
th.dut_ndreset := ports(0)
|
th.dut_ndreset := resetPorts(0)
|
||||||
|
|
||||||
// JTAG reset
|
// JTAG reset
|
||||||
ports(1) := PowerOnResetFPGAOnly(th.clock_32MHz)
|
resetPorts(1) := PowerOnResetFPGAOnly(th.clock_32MHz)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
@@ -63,6 +63,7 @@ class WithArtyJTAGHarnessBinder extends OverrideHarnessBinder({
|
|||||||
io_jtag.TMS.i.po.map(_ := DontCare)
|
io_jtag.TMS.i.po.map(_ := DontCare)
|
||||||
io_jtag.TDO.i.po.map(_ := DontCare)
|
io_jtag.TDO.i.po.map(_ := DontCare)
|
||||||
}
|
}
|
||||||
|
case b: Bool =>
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -3,12 +3,12 @@ package chipyard.fpga.arty
|
|||||||
import chisel3._
|
import chisel3._
|
||||||
import chisel3.experimental.{IO}
|
import chisel3.experimental.{IO}
|
||||||
|
|
||||||
import freechips.rocketchip.devices.debug.{HasPeripheryDebugModuleImp}
|
import freechips.rocketchip.devices.debug.{HasPeripheryDebug}
|
||||||
|
|
||||||
import chipyard.iobinders.{ComposeIOBinder}
|
import chipyard.iobinders.{ComposeIOBinder}
|
||||||
|
|
||||||
class WithDebugResetPassthrough extends ComposeIOBinder({
|
class WithDebugResetPassthrough extends ComposeIOBinder({
|
||||||
(system: HasPeripheryDebugModuleImp) => {
|
(system: HasPeripheryDebug) => {
|
||||||
// Debug module reset
|
// Debug module reset
|
||||||
val io_ndreset: Bool = IO(Output(Bool())).suggestName("ndreset")
|
val io_ndreset: Bool = IO(Output(Bool())).suggestName("ndreset")
|
||||||
io_ndreset := system.debug.get.ndreset
|
io_ndreset := system.debug.get.ndreset
|
||||||
|
|||||||
@@ -3,12 +3,12 @@ package chipyard.fpga.arty
|
|||||||
import chisel3._
|
import chisel3._
|
||||||
|
|
||||||
import freechips.rocketchip.diplomacy.{LazyModule}
|
import freechips.rocketchip.diplomacy.{LazyModule}
|
||||||
import freechips.rocketchip.config.{Parameters}
|
import freechips.rocketchip.prci.{ClockBundle, ClockBundleParameters}
|
||||||
|
import org.chipsalliance.cde.config.{Parameters}
|
||||||
|
|
||||||
import sifive.fpgashells.shell.xilinx.artyshell.{ArtyShell}
|
import sifive.fpgashells.shell.xilinx.artyshell.{ArtyShell}
|
||||||
|
|
||||||
import chipyard.{BuildTop, HasHarnessSignalReferences}
|
import chipyard.harness.{ApplyHarnessBinders, BuildTop, HasHarnessSignalReferences}
|
||||||
import chipyard.harness.{ApplyHarnessBinders}
|
|
||||||
import chipyard.iobinders.{HasIOBinders}
|
import chipyard.iobinders.{HasIOBinders}
|
||||||
|
|
||||||
class ArtyFPGATestHarness(override implicit val p: Parameters) extends ArtyShell with HasHarnessSignalReferences {
|
class ArtyFPGATestHarness(override implicit val p: Parameters) extends ArtyShell with HasHarnessSignalReferences {
|
||||||
@@ -37,4 +37,9 @@ class ArtyFPGATestHarness(override implicit val p: Parameters) extends ArtyShell
|
|||||||
lazyDut match { case d: HasIOBinders =>
|
lazyDut match { case d: HasIOBinders =>
|
||||||
ApplyHarnessBinders(this, d.lazySystem, d.portMap)
|
ApplyHarnessBinders(this, d.lazySystem, d.portMap)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
val implicitHarnessClockBundle = Wire(new ClockBundle(ClockBundleParameters()))
|
||||||
|
implicitHarnessClockBundle.clock := buildtopClock
|
||||||
|
implicitHarnessClockBundle.reset := buildtopReset
|
||||||
|
harnessClockInstantiator.instantiateHarnessClocks(implicitHarnessClockBundle)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
// See LICENSE for license details.
|
// See LICENSE for license details.
|
||||||
package chipyard.fpga.arty100t
|
package chipyard.fpga.arty100t
|
||||||
|
|
||||||
import freechips.rocketchip.config._
|
import org.chipsalliance.cde.config._
|
||||||
import freechips.rocketchip.subsystem._
|
import freechips.rocketchip.subsystem._
|
||||||
import freechips.rocketchip.devices.debug._
|
import freechips.rocketchip.devices.debug._
|
||||||
import freechips.rocketchip.devices.tilelink._
|
import freechips.rocketchip.devices.tilelink._
|
||||||
@@ -22,6 +22,7 @@ class WithNoDesignKey extends Config((site, here, up) => {
|
|||||||
})
|
})
|
||||||
|
|
||||||
class WithArty100TTweaks extends Config(
|
class WithArty100TTweaks extends Config(
|
||||||
|
new chipyard.harness.WithAllClocksFromHarnessClockInstantiator ++
|
||||||
new WithArty100TUARTTSI ++
|
new WithArty100TUARTTSI ++
|
||||||
new WithArty100TDDRTL ++
|
new WithArty100TDDRTL ++
|
||||||
new WithNoDesignKey ++
|
new WithNoDesignKey ++
|
||||||
|
|||||||
@@ -3,8 +3,9 @@ package chipyard.fpga.arty100t
|
|||||||
import chisel3._
|
import chisel3._
|
||||||
import chisel3.util._
|
import chisel3.util._
|
||||||
import freechips.rocketchip.diplomacy._
|
import freechips.rocketchip.diplomacy._
|
||||||
import freechips.rocketchip.config.{Parameters}
|
import org.chipsalliance.cde.config.{Parameters}
|
||||||
import freechips.rocketchip.tilelink.{TLClientNode, TLBlockDuringReset}
|
import freechips.rocketchip.tilelink.{TLClientNode, TLBlockDuringReset}
|
||||||
|
import freechips.rocketchip.prci.{ClockBundle, ClockBundleParameters}
|
||||||
|
|
||||||
import sifive.fpgashells.shell.xilinx._
|
import sifive.fpgashells.shell.xilinx._
|
||||||
import sifive.fpgashells.shell._
|
import sifive.fpgashells.shell._
|
||||||
@@ -13,8 +14,8 @@ import sifive.fpgashells.ip.xilinx.{IBUF, PowerOnResetFPGAOnly}
|
|||||||
|
|
||||||
import sifive.blocks.devices.uart._
|
import sifive.blocks.devices.uart._
|
||||||
|
|
||||||
import chipyard._
|
import chipyard.{ChipTop, CanHaveMasterTLMemPort, ExtTLMem}
|
||||||
import chipyard.harness.{ApplyHarnessBinders}
|
import chipyard.harness._
|
||||||
import chipyard.iobinders.{HasIOBinders}
|
import chipyard.iobinders.{HasIOBinders}
|
||||||
|
|
||||||
class Arty100THarness(override implicit val p: Parameters) extends Arty100TShell with HasHarnessSignalReferences
|
class Arty100THarness(override implicit val p: Parameters) extends Arty100TShell with HasHarnessSignalReferences
|
||||||
@@ -87,6 +88,11 @@ class Arty100THarness(override implicit val p: Parameters) extends Arty100TShell
|
|||||||
chiptop match { case d: HasIOBinders =>
|
chiptop match { case d: HasIOBinders =>
|
||||||
ApplyHarnessBinders(this, d.lazySystem, d.portMap)
|
ApplyHarnessBinders(this, d.lazySystem, d.portMap)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
val implicitHarnessClockBundle = Wire(new ClockBundle(ClockBundleParameters()))
|
||||||
|
implicitHarnessClockBundle.clock := buildtopClock
|
||||||
|
implicitHarnessClockBundle.reset := buildtopReset
|
||||||
|
harnessClockInstantiator.instantiateHarnessClocks(implicitHarnessClockBundle)
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,7 +2,6 @@ package chipyard.fpga.arty100t
|
|||||||
|
|
||||||
import chisel3._
|
import chisel3._
|
||||||
|
|
||||||
import freechips.rocketchip.devices.debug.{HasPeripheryDebug, HasPeripheryDebugModuleImp}
|
|
||||||
import freechips.rocketchip.jtag.{JTAGIO}
|
import freechips.rocketchip.jtag.{JTAGIO}
|
||||||
import freechips.rocketchip.subsystem.{PeripheryBusKey}
|
import freechips.rocketchip.subsystem.{PeripheryBusKey}
|
||||||
import freechips.rocketchip.tilelink.{TLBundle}
|
import freechips.rocketchip.tilelink.{TLBundle}
|
||||||
@@ -26,24 +25,25 @@ class WithArty100TUARTTSI(uartBaudRate: BigInt = 115200) extends OverrideHarness
|
|||||||
ports.map({ port =>
|
ports.map({ port =>
|
||||||
val ath = th.asInstanceOf[Arty100THarness]
|
val ath = th.asInstanceOf[Arty100THarness]
|
||||||
val freq = p(PeripheryBusKey).dtsFrequency.get
|
val freq = p(PeripheryBusKey).dtsFrequency.get
|
||||||
val bits = SerialAdapter.asyncQueue(port, th.buildtopClock, th.buildtopReset)
|
val bits = port.bits
|
||||||
|
port.clock := th.buildtopClock
|
||||||
withClockAndReset(th.buildtopClock, th.buildtopReset) {
|
withClockAndReset(th.buildtopClock, th.buildtopReset) {
|
||||||
val ram = SerialAdapter.connectHarnessRAM(system.serdesser.get, bits, th.buildtopReset)
|
val ram = TSIHarness.connectRAM(system.serdesser.get, bits, th.buildtopReset)
|
||||||
val uart_to_serial = Module(new UARTToSerial(
|
val uart_to_serial = Module(new UARTToSerial(
|
||||||
freq, UARTParams(0, initBaudRate=uartBaudRate)))
|
freq, UARTParams(0, initBaudRate=uartBaudRate)))
|
||||||
val serial_width_adapter = Module(new SerialWidthAdapter(
|
val serial_width_adapter = Module(new SerialWidthAdapter(
|
||||||
narrowW = 8, wideW = SerialAdapter.SERIAL_TSI_WIDTH))
|
narrowW = 8, wideW = TSI.WIDTH))
|
||||||
serial_width_adapter.io.narrow.flipConnect(uart_to_serial.io.serial)
|
serial_width_adapter.io.narrow.flipConnect(uart_to_serial.io.serial)
|
||||||
|
|
||||||
ram.module.io.tsi_ser.flipConnect(serial_width_adapter.io.wide)
|
ram.module.io.tsi.flipConnect(serial_width_adapter.io.wide)
|
||||||
|
|
||||||
ath.io_uart_bb.bundle <> uart_to_serial.io.uart
|
ath.io_uart_bb.bundle <> uart_to_serial.io.uart
|
||||||
ath.other_leds(1) := uart_to_serial.io.dropped
|
ath.other_leds(1) := uart_to_serial.io.dropped
|
||||||
|
|
||||||
ath.other_leds(9) := ram.module.io.adapter_state(0)
|
ath.other_leds(9) := ram.module.io.tsi2tl_state(0)
|
||||||
ath.other_leds(10) := ram.module.io.adapter_state(1)
|
ath.other_leds(10) := ram.module.io.tsi2tl_state(1)
|
||||||
ath.other_leds(11) := ram.module.io.adapter_state(2)
|
ath.other_leds(11) := ram.module.io.tsi2tl_state(2)
|
||||||
ath.other_leds(12) := ram.module.io.adapter_state(3)
|
ath.other_leds(12) := ram.module.io.tsi2tl_state(3)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,7 +2,7 @@ package chipyard.fpga.vc707
|
|||||||
|
|
||||||
import sys.process._
|
import sys.process._
|
||||||
|
|
||||||
import freechips.rocketchip.config.{Config, Parameters}
|
import org.chipsalliance.cde.config.{Config, Parameters}
|
||||||
import freechips.rocketchip.subsystem.{SystemBusKey, PeripheryBusKey, ControlBusKey, ExtMem}
|
import freechips.rocketchip.subsystem.{SystemBusKey, PeripheryBusKey, ControlBusKey, ExtMem}
|
||||||
import freechips.rocketchip.devices.debug.{DebugModuleKey, ExportDebug, JTAG}
|
import freechips.rocketchip.devices.debug.{DebugModuleKey, ExportDebug, JTAG}
|
||||||
import freechips.rocketchip.devices.tilelink.{DevNullParams, BootROMLocated}
|
import freechips.rocketchip.devices.tilelink.{DevNullParams, BootROMLocated}
|
||||||
@@ -17,7 +17,8 @@ import sifive.fpgashells.shell.xilinx.{VC7074GDDRSize}
|
|||||||
|
|
||||||
import testchipip.{SerialTLKey}
|
import testchipip.{SerialTLKey}
|
||||||
|
|
||||||
import chipyard.{BuildSystem, ExtTLMem, DefaultClockFrequencyKey}
|
import chipyard.{BuildSystem, ExtTLMem}
|
||||||
|
import chipyard.harness.{DefaultClockFrequencyKey}
|
||||||
|
|
||||||
class WithDefaultPeripherals extends Config((site, here, up) => {
|
class WithDefaultPeripherals extends Config((site, here, up) => {
|
||||||
case PeripheryUARTKey => List(UARTParams(address = BigInt(0x64000000L)))
|
case PeripheryUARTKey => List(UARTParams(address = BigInt(0x64000000L)))
|
||||||
@@ -39,6 +40,7 @@ class WithSystemModifications extends Config((site, here, up) => {
|
|||||||
|
|
||||||
class WithVC707Tweaks extends Config (
|
class WithVC707Tweaks extends Config (
|
||||||
// harness binders
|
// harness binders
|
||||||
|
new chipyard.harness.WithAllClocksFromHarnessClockInstantiator ++
|
||||||
new WithVC707UARTHarnessBinder ++
|
new WithVC707UARTHarnessBinder ++
|
||||||
new WithVC707SPISDCardHarnessBinder ++
|
new WithVC707SPISDCardHarnessBinder ++
|
||||||
new WithVC707DDRMemHarnessBinder ++
|
new WithVC707DDRMemHarnessBinder ++
|
||||||
|
|||||||
@@ -4,8 +4,9 @@ import chisel3._
|
|||||||
import chisel3.experimental.{IO}
|
import chisel3.experimental.{IO}
|
||||||
|
|
||||||
import freechips.rocketchip.diplomacy.{LazyModule, LazyRawModuleImp, BundleBridgeSource}
|
import freechips.rocketchip.diplomacy.{LazyModule, LazyRawModuleImp, BundleBridgeSource}
|
||||||
import freechips.rocketchip.config.{Parameters}
|
import org.chipsalliance.cde.config.{Parameters}
|
||||||
import freechips.rocketchip.tilelink.{TLClientNode}
|
import freechips.rocketchip.tilelink.{TLClientNode}
|
||||||
|
import freechips.rocketchip.prci.{ClockBundle, ClockBundleParameters}
|
||||||
|
|
||||||
import sifive.fpgashells.shell.xilinx.{VC707Shell, UARTVC707ShellPlacer, PCIeVC707ShellPlacer, ChipLinkVC707PlacedOverlay}
|
import sifive.fpgashells.shell.xilinx.{VC707Shell, UARTVC707ShellPlacer, PCIeVC707ShellPlacer, ChipLinkVC707PlacedOverlay}
|
||||||
import sifive.fpgashells.ip.xilinx.{IBUF, PowerOnResetFPGAOnly}
|
import sifive.fpgashells.ip.xilinx.{IBUF, PowerOnResetFPGAOnly}
|
||||||
@@ -16,9 +17,9 @@ import sifive.fpgashells.devices.xilinx.xilinxvc707pciex1.{XilinxVC707PCIeX1IO}
|
|||||||
import sifive.blocks.devices.uart.{PeripheryUARTKey, UARTPortIO}
|
import sifive.blocks.devices.uart.{PeripheryUARTKey, UARTPortIO}
|
||||||
import sifive.blocks.devices.spi.{PeripherySPIKey, SPIPortIO}
|
import sifive.blocks.devices.spi.{PeripherySPIKey, SPIPortIO}
|
||||||
|
|
||||||
import chipyard.{HasHarnessSignalReferences, BuildTop, ChipTop, ExtTLMem, CanHaveMasterTLMemPort, DefaultClockFrequencyKey}
|
import chipyard.{ChipTop, ExtTLMem, CanHaveMasterTLMemPort}
|
||||||
import chipyard.iobinders.{HasIOBinders}
|
import chipyard.iobinders.{HasIOBinders}
|
||||||
import chipyard.harness.{ApplyHarnessBinders}
|
import chipyard.harness.{ApplyHarnessBinders, HasHarnessSignalReferences, BuildTop, DefaultClockFrequencyKey}
|
||||||
|
|
||||||
class VC707FPGATestHarness(override implicit val p: Parameters) extends VC707Shell { outer =>
|
class VC707FPGATestHarness(override implicit val p: Parameters) extends VC707Shell { outer =>
|
||||||
|
|
||||||
@@ -132,4 +133,9 @@ class VC707FPGATestHarnessImp(_outer: VC707FPGATestHarness) extends LazyRawModul
|
|||||||
// check the top-level reference clock is equal to the default
|
// check the top-level reference clock is equal to the default
|
||||||
// non-exhaustive since you need all ChipTop clocks to equal the default
|
// non-exhaustive since you need all ChipTop clocks to equal the default
|
||||||
require(getRefClockFreq == p(DefaultClockFrequencyKey))
|
require(getRefClockFreq == p(DefaultClockFrequencyKey))
|
||||||
|
|
||||||
|
val implicitHarnessClockBundle = Wire(new ClockBundle(ClockBundleParameters()))
|
||||||
|
implicitHarnessClockBundle.clock := buildtopClock
|
||||||
|
implicitHarnessClockBundle.reset := buildtopReset
|
||||||
|
harnessClockInstantiator.instantiateHarnessClocks(implicitHarnessClockBundle)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,7 +2,7 @@ package chipyard.fpga.vcu118
|
|||||||
|
|
||||||
import sys.process._
|
import sys.process._
|
||||||
|
|
||||||
import freechips.rocketchip.config.{Config, Parameters}
|
import org.chipsalliance.cde.config.{Config, Parameters}
|
||||||
import freechips.rocketchip.subsystem.{SystemBusKey, PeripheryBusKey, ControlBusKey, ExtMem}
|
import freechips.rocketchip.subsystem.{SystemBusKey, PeripheryBusKey, ControlBusKey, ExtMem}
|
||||||
import freechips.rocketchip.devices.debug.{DebugModuleKey, ExportDebug, JTAG}
|
import freechips.rocketchip.devices.debug.{DebugModuleKey, ExportDebug, JTAG}
|
||||||
import freechips.rocketchip.devices.tilelink.{DevNullParams, BootROMLocated}
|
import freechips.rocketchip.devices.tilelink.{DevNullParams, BootROMLocated}
|
||||||
@@ -17,7 +17,8 @@ import sifive.fpgashells.shell.xilinx.{VCU118ShellPMOD, VCU118DDRSize}
|
|||||||
|
|
||||||
import testchipip.{SerialTLKey}
|
import testchipip.{SerialTLKey}
|
||||||
|
|
||||||
import chipyard.{BuildSystem, ExtTLMem, DefaultClockFrequencyKey}
|
import chipyard.{BuildSystem, ExtTLMem}
|
||||||
|
import chipyard.harness.{DefaultClockFrequencyKey}
|
||||||
|
|
||||||
class WithDefaultPeripherals extends Config((site, here, up) => {
|
class WithDefaultPeripherals extends Config((site, here, up) => {
|
||||||
case PeripheryUARTKey => List(UARTParams(address = BigInt(0x64000000L)))
|
case PeripheryUARTKey => List(UARTParams(address = BigInt(0x64000000L)))
|
||||||
@@ -41,6 +42,7 @@ class WithSystemModifications extends Config((site, here, up) => {
|
|||||||
// DOC include start: AbstractVCU118 and Rocket
|
// DOC include start: AbstractVCU118 and Rocket
|
||||||
class WithVCU118Tweaks extends Config(
|
class WithVCU118Tweaks extends Config(
|
||||||
// harness binders
|
// harness binders
|
||||||
|
new chipyard.harness.WithAllClocksFromHarnessClockInstantiator ++
|
||||||
new WithUART ++
|
new WithUART ++
|
||||||
new WithSPISDCard ++
|
new WithSPISDCard ++
|
||||||
new WithDDRMem ++
|
new WithDDRMem ++
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ package chipyard.fpga.vcu118
|
|||||||
import chisel3._
|
import chisel3._
|
||||||
|
|
||||||
import freechips.rocketchip.diplomacy._
|
import freechips.rocketchip.diplomacy._
|
||||||
import freechips.rocketchip.config.{Parameters, Field}
|
import org.chipsalliance.cde.config.{Parameters, Field}
|
||||||
import freechips.rocketchip.tilelink.{TLInwardNode, TLAsyncCrossingSink}
|
import freechips.rocketchip.tilelink.{TLInwardNode, TLAsyncCrossingSink}
|
||||||
|
|
||||||
import sifive.fpgashells.shell._
|
import sifive.fpgashells.shell._
|
||||||
|
|||||||
@@ -9,8 +9,8 @@ import freechips.rocketchip.tilelink.{TLBundle}
|
|||||||
import sifive.blocks.devices.uart.{HasPeripheryUARTModuleImp, UARTPortIO}
|
import sifive.blocks.devices.uart.{HasPeripheryUARTModuleImp, UARTPortIO}
|
||||||
import sifive.blocks.devices.spi.{HasPeripherySPI, SPIPortIO}
|
import sifive.blocks.devices.spi.{HasPeripherySPI, SPIPortIO}
|
||||||
|
|
||||||
import chipyard.{HasHarnessSignalReferences, CanHaveMasterTLMemPort}
|
import chipyard.{CanHaveMasterTLMemPort}
|
||||||
import chipyard.harness.{OverrideHarnessBinder}
|
import chipyard.harness.{HasHarnessSignalReferences, OverrideHarnessBinder}
|
||||||
|
|
||||||
/*** UART ***/
|
/*** UART ***/
|
||||||
class WithUART extends OverrideHarnessBinder({
|
class WithUART extends OverrideHarnessBinder({
|
||||||
|
|||||||
@@ -4,8 +4,9 @@ import chisel3._
|
|||||||
import chisel3.experimental.{IO}
|
import chisel3.experimental.{IO}
|
||||||
|
|
||||||
import freechips.rocketchip.diplomacy.{LazyModule, LazyRawModuleImp, BundleBridgeSource}
|
import freechips.rocketchip.diplomacy.{LazyModule, LazyRawModuleImp, BundleBridgeSource}
|
||||||
import freechips.rocketchip.config.{Parameters}
|
import org.chipsalliance.cde.config.{Parameters}
|
||||||
import freechips.rocketchip.tilelink.{TLClientNode}
|
import freechips.rocketchip.tilelink.{TLClientNode}
|
||||||
|
import freechips.rocketchip.prci.{ClockBundle, ClockBundleParameters}
|
||||||
|
|
||||||
import sifive.fpgashells.shell.xilinx._
|
import sifive.fpgashells.shell.xilinx._
|
||||||
import sifive.fpgashells.ip.xilinx.{IBUF, PowerOnResetFPGAOnly}
|
import sifive.fpgashells.ip.xilinx.{IBUF, PowerOnResetFPGAOnly}
|
||||||
@@ -17,7 +18,7 @@ import sifive.blocks.devices.spi.{PeripherySPIKey, SPIPortIO}
|
|||||||
|
|
||||||
import chipyard._
|
import chipyard._
|
||||||
import chipyard.iobinders.{HasIOBinders}
|
import chipyard.iobinders.{HasIOBinders}
|
||||||
import chipyard.harness.{ApplyHarnessBinders}
|
import chipyard.harness._
|
||||||
|
|
||||||
class VCU118FPGATestHarness(override implicit val p: Parameters) extends VCU118ShellBasicOverlays {
|
class VCU118FPGATestHarness(override implicit val p: Parameters) extends VCU118ShellBasicOverlays {
|
||||||
|
|
||||||
@@ -134,4 +135,9 @@ class VCU118FPGATestHarnessImp(_outer: VCU118FPGATestHarness) extends LazyRawMod
|
|||||||
// check the top-level reference clock is equal to the default
|
// check the top-level reference clock is equal to the default
|
||||||
// non-exhaustive since you need all ChipTop clocks to equal the default
|
// non-exhaustive since you need all ChipTop clocks to equal the default
|
||||||
require(getRefClockFreq == p(DefaultClockFrequencyKey))
|
require(getRefClockFreq == p(DefaultClockFrequencyKey))
|
||||||
|
|
||||||
|
val implicitHarnessClockBundle = Wire(new ClockBundle(ClockBundleParameters()))
|
||||||
|
implicitHarnessClockBundle.clock := buildtopClock
|
||||||
|
implicitHarnessClockBundle.reset := buildtopReset
|
||||||
|
harnessClockInstantiator.instantiateHarnessClocks(implicitHarnessClockBundle)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,7 +2,7 @@ package chipyard.fpga.vcu118.bringup
|
|||||||
|
|
||||||
import math.min
|
import math.min
|
||||||
|
|
||||||
import freechips.rocketchip.config.{Config, Parameters}
|
import org.chipsalliance.cde.config.{Config, Parameters}
|
||||||
import freechips.rocketchip.diplomacy.{DTSModel, DTSTimebase, RegionType, AddressSet, ResourceBinding, Resource, ResourceAddress}
|
import freechips.rocketchip.diplomacy.{DTSModel, DTSTimebase, RegionType, AddressSet, ResourceBinding, Resource, ResourceAddress}
|
||||||
import freechips.rocketchip.tilelink._
|
import freechips.rocketchip.tilelink._
|
||||||
import freechips.rocketchip.diplomacy._
|
import freechips.rocketchip.diplomacy._
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ import chisel3._
|
|||||||
import chisel3.experimental.{attach}
|
import chisel3.experimental.{attach}
|
||||||
|
|
||||||
import freechips.rocketchip.diplomacy._
|
import freechips.rocketchip.diplomacy._
|
||||||
import freechips.rocketchip.config.{Parameters, Field}
|
import org.chipsalliance.cde.config.{Parameters, Field}
|
||||||
import freechips.rocketchip.tilelink.{TLInwardNode, TLAsyncCrossingSink}
|
import freechips.rocketchip.tilelink.{TLInwardNode, TLAsyncCrossingSink}
|
||||||
|
|
||||||
import sifive.fpgashells.shell._
|
import sifive.fpgashells.shell._
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ import chisel3._
|
|||||||
|
|
||||||
import freechips.rocketchip.subsystem._
|
import freechips.rocketchip.subsystem._
|
||||||
import freechips.rocketchip.system._
|
import freechips.rocketchip.system._
|
||||||
import freechips.rocketchip.config.Parameters
|
import org.chipsalliance.cde.config.Parameters
|
||||||
import freechips.rocketchip.devices.tilelink._
|
import freechips.rocketchip.devices.tilelink._
|
||||||
import freechips.rocketchip.diplomacy._
|
import freechips.rocketchip.diplomacy._
|
||||||
import freechips.rocketchip.tilelink._
|
import freechips.rocketchip.tilelink._
|
||||||
|
|||||||
@@ -13,8 +13,7 @@ import sifive.blocks.devices.gpio.{HasPeripheryGPIOModuleImp, GPIOPortIO}
|
|||||||
|
|
||||||
import testchipip.{HasPeripheryTSIHostWidget, TSIHostWidgetIO}
|
import testchipip.{HasPeripheryTSIHostWidget, TSIHostWidgetIO}
|
||||||
|
|
||||||
import chipyard.{HasHarnessSignalReferences}
|
import chipyard.harness.{ComposeHarnessBinder, OverrideHarnessBinder, HasHarnessSignalReferences}
|
||||||
import chipyard.harness.{ComposeHarnessBinder, OverrideHarnessBinder}
|
|
||||||
|
|
||||||
/*** UART ***/
|
/*** UART ***/
|
||||||
class WithBringupUART extends ComposeHarnessBinder({
|
class WithBringupUART extends ComposeHarnessBinder({
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ package chipyard.fpga.vcu118.bringup
|
|||||||
import chisel3._
|
import chisel3._
|
||||||
|
|
||||||
import freechips.rocketchip.diplomacy._
|
import freechips.rocketchip.diplomacy._
|
||||||
import freechips.rocketchip.config._
|
import org.chipsalliance.cde.config._
|
||||||
import freechips.rocketchip.subsystem._
|
import freechips.rocketchip.subsystem._
|
||||||
import freechips.rocketchip.tilelink._
|
import freechips.rocketchip.tilelink._
|
||||||
|
|
||||||
|
|||||||
Submodule generators/boom updated: deae9f7046...679f358755
@@ -1,3 +1,4 @@
|
|||||||
|
#include <cstdint>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <riscv/sim.h>
|
#include <riscv/sim.h>
|
||||||
@@ -5,6 +6,25 @@
|
|||||||
#include <svdpi.h>
|
#include <svdpi.h>
|
||||||
#include <sstream>
|
#include <sstream>
|
||||||
#include <set>
|
#include <set>
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <sys/mman.h>
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <sys/syscall.h>
|
||||||
|
#include <fcntl.h>
|
||||||
|
|
||||||
|
#if __has_include ("cospike_dtm.h")
|
||||||
|
#define COSPIKE_DTM
|
||||||
|
#include "testchip_dtm.h"
|
||||||
|
extern testchip_dtm_t* dtm;
|
||||||
|
bool spike_loadarch_done = false;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if __has_include ("mm.h")
|
||||||
|
#define COSPIKE_SIMDRAM
|
||||||
|
#include "mm.h"
|
||||||
|
extern std::map<long long int, backing_data_t> backing_mem_data;
|
||||||
|
#endif
|
||||||
|
|
||||||
#define CLINT_BASE (0x2000000)
|
#define CLINT_BASE (0x2000000)
|
||||||
#define CLINT_SIZE (0x1000)
|
#define CLINT_SIZE (0x1000)
|
||||||
@@ -20,6 +40,7 @@ typedef struct system_info_t {
|
|||||||
|
|
||||||
system_info_t* info = NULL;
|
system_info_t* info = NULL;
|
||||||
sim_t* sim = NULL;
|
sim_t* sim = NULL;
|
||||||
|
bool cospike_debug;
|
||||||
reg_t tohost_addr = 0;
|
reg_t tohost_addr = 0;
|
||||||
reg_t fromhost_addr = 0;
|
reg_t fromhost_addr = 0;
|
||||||
std::set<reg_t> magic_addrs;
|
std::set<reg_t> magic_addrs;
|
||||||
@@ -42,7 +63,8 @@ extern "C" void cospike_set_sysinfo(char* isa, int pmpregions,
|
|||||||
) {
|
) {
|
||||||
if (!info) {
|
if (!info) {
|
||||||
info = new system_info_t;
|
info = new system_info_t;
|
||||||
info->isa = std::string(isa);
|
// technically the targets aren't zicntr compliant, but they implement the zicntr registers
|
||||||
|
info->isa = std::string(isa) + "_zicntr";
|
||||||
info->pmpregions = pmpregions;
|
info->pmpregions = pmpregions;
|
||||||
info->mem0_base = mem0_base;
|
info->mem0_base = mem0_base;
|
||||||
info->mem0_size = mem0_size;
|
info->mem0_size = mem0_size;
|
||||||
@@ -64,10 +86,11 @@ extern "C" void cospike_cosim(long long int cycle,
|
|||||||
int raise_exception,
|
int raise_exception,
|
||||||
int raise_interrupt,
|
int raise_interrupt,
|
||||||
unsigned long long int cause,
|
unsigned long long int cause,
|
||||||
unsigned long long int wdata)
|
unsigned long long int wdata,
|
||||||
|
int priv)
|
||||||
{
|
{
|
||||||
assert(info);
|
assert(info);
|
||||||
if (!sim) {
|
if (unlikely(!sim)) {
|
||||||
printf("Configuring spike cosim\n");
|
printf("Configuring spike cosim\n");
|
||||||
std::vector<mem_cfg_t> mem_cfg;
|
std::vector<mem_cfg_t> mem_cfg;
|
||||||
std::vector<size_t> hartids;
|
std::vector<size_t> hartids;
|
||||||
@@ -110,7 +133,7 @@ extern "C" void cospike_cosim(long long int cycle,
|
|||||||
abort();
|
abort();
|
||||||
std::vector<std::string> htif_args;
|
std::vector<std::string> htif_args;
|
||||||
bool in_permissive = false;
|
bool in_permissive = false;
|
||||||
bool cospike_debug = false;
|
cospike_debug = false;
|
||||||
for (int i = 1; i < vinfo.argc; i++) {
|
for (int i = 1; i < vinfo.argc; i++) {
|
||||||
std::string arg(vinfo.argv[i]);
|
std::string arg(vinfo.argv[i]);
|
||||||
if (arg == "+permissive") {
|
if (arg == "+permissive") {
|
||||||
@@ -136,7 +159,7 @@ extern "C" void cospike_cosim(long long int cycle,
|
|||||||
.support_impebreak = true
|
.support_impebreak = true
|
||||||
};
|
};
|
||||||
|
|
||||||
printf("%s\n", info->isa.c_str());
|
printf("isa string is %s\n", info->isa.c_str());
|
||||||
for (int i = 0; i < htif_args.size(); i++) {
|
for (int i = 0; i < htif_args.size(); i++) {
|
||||||
printf("%s\n", htif_args[i].c_str());
|
printf("%s\n", htif_args[i].c_str());
|
||||||
}
|
}
|
||||||
@@ -146,13 +169,29 @@ extern "C" void cospike_cosim(long long int cycle,
|
|||||||
plugin_devices,
|
plugin_devices,
|
||||||
htif_args,
|
htif_args,
|
||||||
dm_config,
|
dm_config,
|
||||||
nullptr,
|
"cospike.log",
|
||||||
false,
|
false,
|
||||||
nullptr,
|
nullptr,
|
||||||
false,
|
false,
|
||||||
nullptr
|
nullptr
|
||||||
);
|
);
|
||||||
|
|
||||||
|
#ifdef COSPIKE_SIMDRAM
|
||||||
|
// match sim_t's backing memory with the SimDRAM memory
|
||||||
|
bus_t temp_mem_bus;
|
||||||
|
for (auto& pair : mems) temp_mem_bus.add_device(pair.first, pair.second);
|
||||||
|
|
||||||
|
for (auto& pair : backing_mem_data) {
|
||||||
|
size_t base = pair.first;
|
||||||
|
size_t size = pair.second.size;
|
||||||
|
printf("Matching spike memory initial state for region %lx-%lx\n", base, base + size);
|
||||||
|
if (!temp_mem_bus.store(base, size, pair.second.data)) {
|
||||||
|
printf("Error, unable to match memory at address %lx\n", base);
|
||||||
|
abort();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
sim->configure_log(true, true);
|
sim->configure_log(true, true);
|
||||||
// Use our own reset vector
|
// Use our own reset vector
|
||||||
for (int i = 0; i < info->nharts; i++) {
|
for (int i = 0; i < info->nharts; i++) {
|
||||||
@@ -166,93 +205,207 @@ extern "C" void cospike_cosim(long long int cycle,
|
|||||||
fromhost_addr = ((htif_t*)sim)->get_fromhost_addr();
|
fromhost_addr = ((htif_t*)sim)->get_fromhost_addr();
|
||||||
printf("Tohost : %lx\n", tohost_addr);
|
printf("Tohost : %lx\n", tohost_addr);
|
||||||
printf("Fromhost: %lx\n", fromhost_addr);
|
printf("Fromhost: %lx\n", fromhost_addr);
|
||||||
|
printf("Memory base : %lx\n", info->mem0_base);
|
||||||
|
printf("Memory Size : %lx\n", info->mem0_size);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (priv & 0x4) { // debug
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
processor_t* p = sim->get_core(hartid);
|
processor_t* p = sim->get_core(hartid);
|
||||||
state_t* s = p->get_state();
|
state_t* s = p->get_state();
|
||||||
|
#ifdef COSPIKE_DTM
|
||||||
|
if (dtm && dtm->loadarch_done && !spike_loadarch_done) {
|
||||||
|
printf("Restoring spike state from testchip_dtm loadarch\n");
|
||||||
|
// copy the loadarch state into the cosim
|
||||||
|
loadarch_state_t &ls = dtm->loadarch_state[hartid];
|
||||||
|
s->pc = ls.pc;
|
||||||
|
s->prv = ls.prv;
|
||||||
|
s->csrmap[CSR_MSTATUS]->write(s->csrmap[CSR_MSTATUS]->read() | MSTATUS_VS | MSTATUS_XS | MSTATUS_FS);
|
||||||
|
#define RESTORE(CSRID, csr) s->csrmap[CSRID]->write(ls.csr);
|
||||||
|
RESTORE(CSR_FCSR , fcsr);
|
||||||
|
RESTORE(CSR_VSTART , vstart);
|
||||||
|
RESTORE(CSR_VXSAT , vxsat);
|
||||||
|
RESTORE(CSR_VXRM , vxrm);
|
||||||
|
RESTORE(CSR_VCSR , vcsr);
|
||||||
|
RESTORE(CSR_VTYPE , vtype);
|
||||||
|
RESTORE(CSR_STVEC , stvec);
|
||||||
|
RESTORE(CSR_SSCRATCH , sscratch);
|
||||||
|
RESTORE(CSR_SEPC , sepc);
|
||||||
|
RESTORE(CSR_SCAUSE , scause);
|
||||||
|
RESTORE(CSR_STVAL , stval);
|
||||||
|
RESTORE(CSR_SATP , satp);
|
||||||
|
RESTORE(CSR_MSTATUS , mstatus);
|
||||||
|
RESTORE(CSR_MEDELEG , medeleg);
|
||||||
|
RESTORE(CSR_MIDELEG , mideleg);
|
||||||
|
RESTORE(CSR_MIE , mie);
|
||||||
|
RESTORE(CSR_MTVEC , mtvec);
|
||||||
|
RESTORE(CSR_MSCRATCH , mscratch);
|
||||||
|
RESTORE(CSR_MEPC , mepc);
|
||||||
|
RESTORE(CSR_MCAUSE , mcause);
|
||||||
|
RESTORE(CSR_MTVAL , mtval);
|
||||||
|
RESTORE(CSR_MIP , mip);
|
||||||
|
RESTORE(CSR_MCYCLE , mcycle);
|
||||||
|
RESTORE(CSR_MINSTRET , minstret);
|
||||||
|
if (ls.VLEN != p->VU.VLEN) {
|
||||||
|
printf("VLEN mismatch loadarch: $d != spike: $d\n", ls.VLEN, p->VU.VLEN);
|
||||||
|
abort();
|
||||||
|
}
|
||||||
|
if (ls.ELEN != p->VU.ELEN) {
|
||||||
|
printf("ELEN mismatch loadarch: $d != spike: $d\n", ls.ELEN, p->VU.ELEN);
|
||||||
|
abort();
|
||||||
|
}
|
||||||
|
for (size_t i = 0; i < 32; i++) {
|
||||||
|
s->XPR.write(i, ls.XPR[i]);
|
||||||
|
s->FPR.write(i, { (uint64_t)ls.FPR[i], (uint64_t)-1 });
|
||||||
|
memcpy(p->VU.reg_file + i * ls.VLEN / 8, ls.VPR[i], ls.VLEN / 8);
|
||||||
|
}
|
||||||
|
spike_loadarch_done = true;
|
||||||
|
p->clear_waiting_for_interrupt();
|
||||||
|
}
|
||||||
|
#endif
|
||||||
uint64_t s_pc = s->pc;
|
uint64_t s_pc = s->pc;
|
||||||
|
uint64_t interrupt_cause = cause & 0x7FFFFFFFFFFFFFFF;
|
||||||
|
bool ssip_interrupt = interrupt_cause == 0x1;
|
||||||
|
bool msip_interrupt = interrupt_cause == 0x3;
|
||||||
|
bool debug_interrupt = interrupt_cause == 0xe;
|
||||||
if (raise_interrupt) {
|
if (raise_interrupt) {
|
||||||
printf("%d interrupt %lx\n", cycle, cause);
|
printf("%d interrupt %lx\n", cycle, cause);
|
||||||
uint64_t interrupt_cause = cause & 0x7FFFFFFFFFFFFFFF;
|
|
||||||
if (interrupt_cause == 3) {
|
if (ssip_interrupt) {
|
||||||
|
// do nothing
|
||||||
|
} else if (msip_interrupt) {
|
||||||
s->mip->backdoor_write_with_mask(MIP_MSIP, MIP_MSIP);
|
s->mip->backdoor_write_with_mask(MIP_MSIP, MIP_MSIP);
|
||||||
|
} else if (debug_interrupt) {
|
||||||
|
return;
|
||||||
} else {
|
} else {
|
||||||
printf("Unknown interrupt %lx\n", interrupt_cause);
|
printf("Unknown interrupt %lx\n", interrupt_cause);
|
||||||
|
abort();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (raise_exception)
|
if (raise_exception)
|
||||||
printf("%d exception %lx\n", cycle, cause);
|
printf("%d exception %lx\n", cycle, cause);
|
||||||
if (valid) {
|
if (valid) {
|
||||||
printf("%d Cosim: %lx", cycle, iaddr);
|
printf("%d Cosim: %lx", cycle, iaddr);
|
||||||
if (has_wdata) {
|
// if (has_wdata) {
|
||||||
printf(" %lx", wdata);
|
// printf(" s: %lx", wdata);
|
||||||
}
|
// }
|
||||||
printf("\n");
|
printf("\n");
|
||||||
}
|
}
|
||||||
if (valid || raise_interrupt || raise_exception)
|
if (valid || raise_interrupt || raise_exception) {
|
||||||
p->step(1);
|
p->step(1);
|
||||||
|
if (unlikely(cospike_debug)) {
|
||||||
|
printf("spike pc is %lx\n", s->pc);
|
||||||
|
printf("spike mstatus is %lx\n", s->mstatus->read());
|
||||||
|
printf("spike mip is %lx\n", s->mip->read());
|
||||||
|
printf("spike mie is %lx\n", s->mie->read());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (valid) {
|
if (valid && !raise_exception) {
|
||||||
if (s_pc != iaddr) {
|
if (s_pc != iaddr) {
|
||||||
printf("%d PC mismatch %lx != %lx\n", cycle, s_pc, iaddr);
|
printf("%d PC mismatch spike %llx != DUT %llx\n", cycle, s_pc, iaddr);
|
||||||
|
if (unlikely(cospike_debug)) {
|
||||||
|
printf("spike mstatus is %lx\n", s->mstatus->read());
|
||||||
|
printf("spike mcause is %lx\n", s->mcause->read());
|
||||||
|
printf("spike mtval is %lx\n" , s->mtval->read());
|
||||||
|
printf("spike mtinst is %lx\n", s->mtinst->read());
|
||||||
|
}
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Try to remember magic_mem addrs, and ignore these in the future
|
|
||||||
auto& mem_write = s->log_mem_write;
|
auto& mem_write = s->log_mem_write;
|
||||||
if (!mem_write.empty() && tohost_addr && std::get<0>(mem_write[0]) == tohost_addr) {
|
auto& log = s->log_reg_write;
|
||||||
reg_t wdata = std::get<1>(mem_write[0]);
|
auto& mem_read = s->log_mem_read;
|
||||||
if (wdata >= info->mem0_base && wdata < (info->mem0_base + info->mem0_size)) {
|
|
||||||
printf("Probable magic mem %x\n", wdata);
|
for (auto memwrite : mem_write) {
|
||||||
magic_addrs.insert(wdata);
|
reg_t waddr = std::get<0>(memwrite);
|
||||||
|
uint64_t w_data = std::get<1>(memwrite);
|
||||||
|
if ((waddr == CLINT_BASE + 4*hartid) && w_data == 0) {
|
||||||
|
s->mip->backdoor_write_with_mask(MIP_MSIP, 0);
|
||||||
|
}
|
||||||
|
// Try to remember magic_mem addrs, and ignore these in the future
|
||||||
|
if ( waddr == tohost_addr && w_data >= info->mem0_base && w_data < (info->mem0_base + info->mem0_size)) {
|
||||||
|
printf("Probable magic mem %lx\n", w_data);
|
||||||
|
magic_addrs.insert(w_data);
|
||||||
|
}
|
||||||
|
// Try to remember magic_mem addrs, and ignore these in the future
|
||||||
|
if ( waddr == tohost_addr && w_data >= info->mem0_base && w_data < (info->mem0_base + info->mem0_size)) {
|
||||||
|
printf("Probable magic mem %lx\n", w_data);
|
||||||
|
magic_addrs.insert(w_data);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (has_wdata) {
|
bool scalar_wb = false;
|
||||||
auto& log = s->log_reg_write;
|
bool vector_wb = false;
|
||||||
auto& mem_read = s->log_mem_read;
|
uint32_t vector_cnt = 0;
|
||||||
|
|
||||||
|
for (auto ®write : log) {
|
||||||
|
|
||||||
|
//TODO: scaling to multi issue reads?
|
||||||
reg_t mem_read_addr = mem_read.empty() ? 0 : std::get<0>(mem_read[0]);
|
reg_t mem_read_addr = mem_read.empty() ? 0 : std::get<0>(mem_read[0]);
|
||||||
for (auto regwrite : log) {
|
|
||||||
int rd = regwrite.first >> 4;
|
int rd = regwrite.first >> 4;
|
||||||
int type = regwrite.first & 0xf;
|
int type = regwrite.first & 0xf;
|
||||||
// 0 => int
|
|
||||||
// 1 => fp
|
// 0 => int
|
||||||
// 2 => vec
|
// 1 => fp
|
||||||
// 3 => vec hint
|
// 2 => vec
|
||||||
// 4 => csr
|
// 3 => vec hint
|
||||||
if ((rd != 0 && type == 0) || type == 1) {
|
// 4 => csr
|
||||||
// Override reads from some CSRs
|
|
||||||
uint64_t csr_addr = (insn >> 20) & 0xfff;
|
bool ignore_read = (!mem_read.empty() &&
|
||||||
bool csr_read = (insn & 0x7f) == 0x73;
|
((magic_addrs.count(mem_read_addr) ||
|
||||||
if (csr_read) printf("CSR read %lx\n", csr_addr);
|
(tohost_addr && mem_read_addr == tohost_addr) ||
|
||||||
if (csr_read && (
|
(fromhost_addr && mem_read_addr == fromhost_addr) ||
|
||||||
(csr_addr == 0x301) || // misa
|
(CLINT_BASE <= mem_read_addr && mem_read_addr < (CLINT_BASE + CLINT_SIZE)))));
|
||||||
(csr_addr == 0xf13) || // mimpid
|
|
||||||
(csr_addr == 0xf12) || // marchid
|
// check the type is compliant with writeback first
|
||||||
(csr_addr == 0xf11) || // mvendorid
|
if ((type == 0 || type == 1))
|
||||||
(csr_addr == 0xb00) || // mcycle
|
scalar_wb = true;
|
||||||
(csr_addr == 0xb02) || // minstret
|
if (type == 2) {
|
||||||
(csr_addr >= 0x3b0 && csr_addr <= 0x3ef) // pmpaddr
|
vector_wb = true;
|
||||||
)) {
|
|
||||||
printf("CSR override\n");
|
|
||||||
s->XPR.write(rd, wdata);
|
|
||||||
} else if (!mem_read.empty() && ((magic_addrs.count(mem_read_addr) ||
|
|
||||||
(tohost_addr && mem_read_addr == tohost_addr) ||
|
|
||||||
(fromhost_addr && mem_read_addr == fromhost_addr) ||
|
|
||||||
(CLINT_BASE <= mem_read_addr && mem_read_addr < (CLINT_BASE + CLINT_SIZE))
|
|
||||||
))) {
|
|
||||||
// Don't check reads from tohost, reads from magic memory, or reads from clint
|
|
||||||
// Technically this could be buggy because log_mem_read only reports vaddrs, but
|
|
||||||
// no software ever should access tohost/fromhost/clint with vaddrs anyways
|
|
||||||
printf("Read override %lx\n", mem_read_addr);
|
|
||||||
s->XPR.write(rd, wdata);
|
|
||||||
} else if (wdata != regwrite.second.v[0]) {
|
|
||||||
printf("%d wdata mismatch reg %d %lx != %lx\n", cycle, rd, regwrite.second.v[0], wdata);
|
|
||||||
exit(1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
if (type == 3) continue;
|
||||||
|
|
||||||
|
|
||||||
|
if ((rd != 0 && type == 0) || type == 1) {
|
||||||
|
// Override reads from some CSRs
|
||||||
|
uint64_t csr_addr = (insn >> 20) & 0xfff;
|
||||||
|
bool csr_read = (insn & 0x7f) == 0x73;
|
||||||
|
if (csr_read)
|
||||||
|
printf("CSR read %lx\n", csr_addr);
|
||||||
|
if (csr_read && ((csr_addr == 0xf13) || // mimpid
|
||||||
|
(csr_addr == 0xf12) || // marchid
|
||||||
|
(csr_addr == 0xf11) || // mvendorid
|
||||||
|
(csr_addr == 0xb00) || // mcycle
|
||||||
|
(csr_addr == 0xb02) || // minstret
|
||||||
|
(csr_addr >= 0x7a0 && csr_addr <= 0x7aa) || // debug trigger registers
|
||||||
|
(csr_addr >= 0x3b0 && csr_addr <= 0x3ef) // pmpaddr
|
||||||
|
)) {
|
||||||
|
printf("CSR override\n");
|
||||||
|
s->XPR.write(rd, wdata);
|
||||||
|
} else if (ignore_read) {
|
||||||
|
// Don't check reads from tohost, reads from magic memory, or reads
|
||||||
|
// from clint Technically this could be buggy because log_mem_read
|
||||||
|
// only reports vaddrs, but no software ever should access
|
||||||
|
// tohost/fromhost/clint with vaddrs anyways
|
||||||
|
printf("Read override %lx\n", mem_read_addr);
|
||||||
|
s->XPR.write(rd, wdata);
|
||||||
|
} else if (wdata != regwrite.second.v[0]) {
|
||||||
|
printf("%d wdata mismatch reg %d %lx != %lx\n", cycle, rd,
|
||||||
|
regwrite.second.v[0], wdata);
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO FIX: Rocketchip TracedInstruction.wdata should be Valid(UInt)
|
||||||
|
// if (scalar_wb ^ has_wdata) {
|
||||||
|
// printf("Scalar wdata behavior divergence between spike and DUT\n");
|
||||||
|
// exit(-1);
|
||||||
|
// }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// }
|
|
||||||
|
|||||||
@@ -1,394 +0,0 @@
|
|||||||
// See LICENSE.SiFive for license details.
|
|
||||||
// See LICENSE.Berkeley for license details.
|
|
||||||
|
|
||||||
#if VM_TRACE
|
|
||||||
#include <memory>
|
|
||||||
#if CY_FST_TRACE
|
|
||||||
#include "verilated_fst_c.h"
|
|
||||||
#else
|
|
||||||
#include "verilated.h"
|
|
||||||
#include "verilated_vcd_c.h"
|
|
||||||
#endif // CY_FST_TRACE
|
|
||||||
#endif // VM_TRACE
|
|
||||||
#include <fesvr/dtm.h>
|
|
||||||
#include <fesvr/tsi.h>
|
|
||||||
#include "remote_bitbang.h"
|
|
||||||
#include <iostream>
|
|
||||||
#include <fcntl.h>
|
|
||||||
#include <signal.h>
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <unistd.h>
|
|
||||||
#include <getopt.h>
|
|
||||||
|
|
||||||
// For option parsing, which is split across this file, Verilog, and
|
|
||||||
// FESVR's HTIF, a few external files must be pulled in. The list of
|
|
||||||
// files and what they provide is enumerated:
|
|
||||||
//
|
|
||||||
// $RISCV/include/fesvr/htif.h:
|
|
||||||
// defines:
|
|
||||||
// - HTIF_USAGE_OPTIONS
|
|
||||||
// - HTIF_LONG_OPTIONS_OPTIND
|
|
||||||
// - HTIF_LONG_OPTIONS
|
|
||||||
// $(ROCKETCHIP_DIR)/generated-src(-debug)?/$(CONFIG).plusArgs:
|
|
||||||
// defines:
|
|
||||||
// - PLUSARG_USAGE_OPTIONS
|
|
||||||
// variables:
|
|
||||||
// - static const char * verilog_plusargs
|
|
||||||
|
|
||||||
extern tsi_t* tsi;
|
|
||||||
extern dtm_t* dtm;
|
|
||||||
extern remote_bitbang_t * jtag;
|
|
||||||
|
|
||||||
static uint64_t trace_count = 0;
|
|
||||||
bool verbose = false;
|
|
||||||
bool done_reset = false;
|
|
||||||
|
|
||||||
void handle_sigterm(int sig)
|
|
||||||
{
|
|
||||||
dtm->stop();
|
|
||||||
}
|
|
||||||
|
|
||||||
double sc_time_stamp()
|
|
||||||
{
|
|
||||||
return trace_count;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void usage(const char * program_name)
|
|
||||||
{
|
|
||||||
printf("Usage: %s [EMULATOR OPTION]... [VERILOG PLUSARG]... [HOST OPTION]... BINARY [TARGET OPTION]...\n",
|
|
||||||
program_name);
|
|
||||||
fputs("\
|
|
||||||
Run a BINARY on the Rocket Chip emulator.\n\
|
|
||||||
\n\
|
|
||||||
Mandatory arguments to long options are mandatory for short options too.\n\
|
|
||||||
\n\
|
|
||||||
EMULATOR OPTIONS\n\
|
|
||||||
-c, --cycle-count Print the cycle count before exiting\n\
|
|
||||||
+cycle-count\n\
|
|
||||||
-h, --help Display this help and exit\n\
|
|
||||||
-m, --max-cycles=CYCLES Kill the emulation after CYCLES\n\
|
|
||||||
+max-cycles=CYCLES\n\
|
|
||||||
-s, --seed=SEED Use random number seed SEED\n\
|
|
||||||
-r, --rbb-port=PORT Use PORT for remote bit bang (with OpenOCD and GDB) \n\
|
|
||||||
If not specified, a random port will be chosen\n\
|
|
||||||
automatically.\n\
|
|
||||||
-V, --verbose Enable all Chisel printfs (cycle-by-cycle info)\n\
|
|
||||||
+verbose\n\
|
|
||||||
", stdout);
|
|
||||||
#if VM_TRACE == 0
|
|
||||||
fputs("\
|
|
||||||
\n\
|
|
||||||
EMULATOR DEBUG OPTIONS (only supported in debug build -- try `make debug`)\n",
|
|
||||||
stdout);
|
|
||||||
#endif
|
|
||||||
fputs("\
|
|
||||||
-v, --vcd=FILE, Write vcd trace to FILE (or '-' for stdout)\n\
|
|
||||||
-x, --dump-start=CYCLE Start VCD tracing at CYCLE\n\
|
|
||||||
+dump-start\n\
|
|
||||||
", stdout);
|
|
||||||
fputs("\n" PLUSARG_USAGE_OPTIONS, stdout);
|
|
||||||
fputs("\n" HTIF_USAGE_OPTIONS, stdout);
|
|
||||||
printf("\n"
|
|
||||||
"EXAMPLES\n"
|
|
||||||
" - run a bare metal test:\n"
|
|
||||||
" %s $RISCV/riscv64-unknown-elf/share/riscv-tests/isa/rv64ui-p-add\n"
|
|
||||||
" - run a bare metal test showing cycle-by-cycle information:\n"
|
|
||||||
" %s +verbose $RISCV/riscv64-unknown-elf/share/riscv-tests/isa/rv64ui-p-add 2>&1 | spike-dasm\n"
|
|
||||||
#if VM_TRACE
|
|
||||||
" - run a bare metal test to generate a VCD waveform:\n"
|
|
||||||
" %s -v rv64ui-p-add.vcd $RISCV/riscv64-unknown-elf/share/riscv-tests/isa/rv64ui-p-add\n"
|
|
||||||
#endif
|
|
||||||
" - run an ELF (you wrote, called 'hello') using the proxy kernel:\n"
|
|
||||||
" %s pk hello\n",
|
|
||||||
program_name, program_name, program_name
|
|
||||||
#if VM_TRACE
|
|
||||||
, program_name
|
|
||||||
#endif
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
int main(int argc, char** argv)
|
|
||||||
{
|
|
||||||
unsigned random_seed = (unsigned)time(NULL) ^ (unsigned)getpid();
|
|
||||||
uint64_t max_cycles = -1;
|
|
||||||
int ret = 0;
|
|
||||||
bool print_cycles = false;
|
|
||||||
// Port numbers are 16 bit unsigned integers.
|
|
||||||
uint16_t rbb_port = 0;
|
|
||||||
#if VM_TRACE
|
|
||||||
const char* vcdfile_name = NULL;
|
|
||||||
FILE * vcdfile = NULL;
|
|
||||||
uint64_t start = 0;
|
|
||||||
#endif
|
|
||||||
int verilog_plusargs_legal = 1;
|
|
||||||
|
|
||||||
int verilated_argc = 1;
|
|
||||||
char** verilated_argv = new char*[argc];
|
|
||||||
verilated_argv[0] = argv[0];
|
|
||||||
|
|
||||||
opterr = 1;
|
|
||||||
|
|
||||||
while (1) {
|
|
||||||
static struct option long_options[] = {
|
|
||||||
{"cycle-count", no_argument, 0, 'c' },
|
|
||||||
{"help", no_argument, 0, 'h' },
|
|
||||||
{"max-cycles", required_argument, 0, 'm' },
|
|
||||||
{"seed", required_argument, 0, 's' },
|
|
||||||
{"rbb-port", required_argument, 0, 'r' },
|
|
||||||
{"verbose", no_argument, 0, 'V' },
|
|
||||||
{"permissive", no_argument, 0, 'p' },
|
|
||||||
{"permissive-off", no_argument, 0, 'o' },
|
|
||||||
#if VM_TRACE
|
|
||||||
{"vcd", required_argument, 0, 'v' },
|
|
||||||
{"dump-start", required_argument, 0, 'x' },
|
|
||||||
#endif
|
|
||||||
HTIF_LONG_OPTIONS
|
|
||||||
};
|
|
||||||
int option_index = 0;
|
|
||||||
#if VM_TRACE
|
|
||||||
int c = getopt_long(argc, argv, "-chm:s:r:v:Vx:po", long_options, &option_index);
|
|
||||||
#else
|
|
||||||
int c = getopt_long(argc, argv, "-chm:s:r:Vpo", long_options, &option_index);
|
|
||||||
#endif
|
|
||||||
if (c == -1) break;
|
|
||||||
retry:
|
|
||||||
switch (c) {
|
|
||||||
// Process long and short EMULATOR options
|
|
||||||
case '?': usage(argv[0]); return 1;
|
|
||||||
case 'c': print_cycles = true; break;
|
|
||||||
case 'h': usage(argv[0]); return 0;
|
|
||||||
case 'm': max_cycles = atoll(optarg); break;
|
|
||||||
case 's': random_seed = atoi(optarg); break;
|
|
||||||
case 'r': rbb_port = atoi(optarg); break;
|
|
||||||
case 'V': verbose = true; break;
|
|
||||||
case 'p': opterr = 0; break;
|
|
||||||
case 'o': opterr = 1; break;
|
|
||||||
#if VM_TRACE
|
|
||||||
case 'v': {
|
|
||||||
vcdfile_name = optarg;
|
|
||||||
vcdfile = strcmp(optarg, "-") == 0 ? stdout : fopen(optarg, "w");
|
|
||||||
if (!vcdfile) {
|
|
||||||
std::cerr << "Unable to open " << optarg << " for VCD write\n";
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case 'x': start = atoll(optarg); break;
|
|
||||||
#endif
|
|
||||||
// Process legacy '+' EMULATOR arguments by replacing them with
|
|
||||||
// their getopt equivalents
|
|
||||||
case 1: {
|
|
||||||
std::string arg = optarg;
|
|
||||||
if (arg.substr(0, 1) != "+") {
|
|
||||||
optind--;
|
|
||||||
goto done_processing;
|
|
||||||
}
|
|
||||||
if (arg == "+verbose")
|
|
||||||
c = 'V';
|
|
||||||
else if (arg.substr(0, 12) == "+max-cycles=") {
|
|
||||||
c = 'm';
|
|
||||||
optarg = optarg+12;
|
|
||||||
}
|
|
||||||
#if VM_TRACE
|
|
||||||
else if (arg.substr(0, 12) == "+dump-start=") {
|
|
||||||
c = 'x';
|
|
||||||
optarg = optarg+12;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
else if (arg.substr(0, 12) == "+cycle-count")
|
|
||||||
c = 'c';
|
|
||||||
else if (arg == "+permissive")
|
|
||||||
{
|
|
||||||
c = 'p';
|
|
||||||
verilated_argv[verilated_argc++] = optarg;
|
|
||||||
}
|
|
||||||
else if (arg == "+permissive-off")
|
|
||||||
{
|
|
||||||
c = 'o';
|
|
||||||
verilated_argv[verilated_argc++] = optarg;
|
|
||||||
}
|
|
||||||
// If we don't find a legacy '+' EMULATOR argument, it still could be
|
|
||||||
// a VERILOG_PLUSARG and not an error.
|
|
||||||
else if (verilog_plusargs_legal) {
|
|
||||||
const char ** plusarg = &verilog_plusargs[0];
|
|
||||||
int legal_verilog_plusarg = 0;
|
|
||||||
while (*plusarg && (legal_verilog_plusarg == 0)){
|
|
||||||
if (arg.substr(1, strlen(*plusarg)) == *plusarg) {
|
|
||||||
legal_verilog_plusarg = 1;
|
|
||||||
}
|
|
||||||
plusarg ++;
|
|
||||||
}
|
|
||||||
if (!legal_verilog_plusarg) {
|
|
||||||
verilog_plusargs_legal = 0;
|
|
||||||
} else {
|
|
||||||
c = 'P';
|
|
||||||
}
|
|
||||||
goto retry;
|
|
||||||
}
|
|
||||||
// If we STILL don't find a legacy '+' argument, it still could be
|
|
||||||
// an HTIF (HOST) argument and not an error. If this is the case, then
|
|
||||||
// we're done processing EMULATOR and VERILOG arguments.
|
|
||||||
else {
|
|
||||||
static struct option htif_long_options [] = { HTIF_LONG_OPTIONS };
|
|
||||||
struct option * htif_option = &htif_long_options[0];
|
|
||||||
while (htif_option->name) {
|
|
||||||
if (arg.substr(1, strlen(htif_option->name)) == htif_option->name) {
|
|
||||||
optind--;
|
|
||||||
goto done_processing;
|
|
||||||
}
|
|
||||||
htif_option++;
|
|
||||||
}
|
|
||||||
if(opterr) {
|
|
||||||
std::cerr << argv[0] << ": invalid plus-arg (Verilog or HTIF) \""
|
|
||||||
<< arg << "\"\n";
|
|
||||||
c = '?';
|
|
||||||
} else {
|
|
||||||
c = 'P';
|
|
||||||
}
|
|
||||||
}
|
|
||||||
goto retry;
|
|
||||||
}
|
|
||||||
case 'P': // Verilog PlusArg, add to the argument list for verilator environment
|
|
||||||
verilated_argv[verilated_argc++] = optarg;
|
|
||||||
break;
|
|
||||||
// Realize that we've hit HTIF (HOST) arguments or error out
|
|
||||||
default:
|
|
||||||
if (c >= HTIF_LONG_OPTIONS_OPTIND) {
|
|
||||||
optind--;
|
|
||||||
goto done_processing;
|
|
||||||
}
|
|
||||||
c = '?';
|
|
||||||
goto retry;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
done_processing:
|
|
||||||
if (optind == argc) {
|
|
||||||
std::cerr << "No binary specified for emulator\n";
|
|
||||||
usage(argv[0]);
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Copy remaining HTIF arguments (if any) and the binary file name into the verilator argument stack
|
|
||||||
while (optind < argc) verilated_argv[verilated_argc++] = argv[optind++];
|
|
||||||
|
|
||||||
if (verbose)
|
|
||||||
fprintf(stderr, "using random seed %u\n", random_seed);
|
|
||||||
|
|
||||||
srand(random_seed);
|
|
||||||
srand48(random_seed);
|
|
||||||
|
|
||||||
Verilated::randReset(2);
|
|
||||||
Verilated::commandArgs(verilated_argc, verilated_argv);
|
|
||||||
TEST_HARNESS *tile = new TEST_HARNESS;
|
|
||||||
|
|
||||||
#if VM_TRACE
|
|
||||||
Verilated::traceEverOn(true); // Verilator must compute traced signals
|
|
||||||
#if CY_FST_TRACE
|
|
||||||
std::unique_ptr<VerilatedFstC> tfp(new VerilatedFstC);
|
|
||||||
#else
|
|
||||||
std::unique_ptr<VerilatedVcdFILE> vcdfd(new VerilatedVcdFILE(vcdfile));
|
|
||||||
std::unique_ptr<VerilatedVcdC> tfp(new VerilatedVcdC(vcdfd.get()));
|
|
||||||
#endif // CY_FST_TRACE
|
|
||||||
if (vcdfile_name) {
|
|
||||||
tile->trace(tfp.get(), 99); // Trace 99 levels of hierarchy
|
|
||||||
tfp->open(vcdfile_name);
|
|
||||||
}
|
|
||||||
#endif // VM_TRACE
|
|
||||||
|
|
||||||
// RocketChip currently only supports RBB port 0, so this needs to stay here
|
|
||||||
jtag = new remote_bitbang_t(rbb_port);
|
|
||||||
|
|
||||||
signal(SIGTERM, handle_sigterm);
|
|
||||||
|
|
||||||
bool dump;
|
|
||||||
// start reset off low so a rising edge triggers async reset
|
|
||||||
tile->reset = 0;
|
|
||||||
tile->clock = 0;
|
|
||||||
tile->eval();
|
|
||||||
// reset for several cycles to handle pipelined reset
|
|
||||||
for (int i = 0; i < 100; i++) {
|
|
||||||
tile->reset = 1;
|
|
||||||
tile->clock = 0;
|
|
||||||
tile->eval();
|
|
||||||
#if VM_TRACE
|
|
||||||
dump = tfp && trace_count >= start;
|
|
||||||
if (dump)
|
|
||||||
tfp->dump(static_cast<vluint64_t>(trace_count * 2));
|
|
||||||
#endif
|
|
||||||
tile->clock = 1;
|
|
||||||
tile->eval();
|
|
||||||
#if VM_TRACE
|
|
||||||
if (dump)
|
|
||||||
tfp->dump(static_cast<vluint64_t>(trace_count * 2 + 1));
|
|
||||||
#endif
|
|
||||||
trace_count ++;
|
|
||||||
}
|
|
||||||
tile->reset = 0;
|
|
||||||
done_reset = true;
|
|
||||||
|
|
||||||
do {
|
|
||||||
tile->clock = 0;
|
|
||||||
tile->eval();
|
|
||||||
#if VM_TRACE
|
|
||||||
dump = tfp && trace_count >= start;
|
|
||||||
if (dump)
|
|
||||||
tfp->dump(static_cast<vluint64_t>(trace_count * 2));
|
|
||||||
#endif
|
|
||||||
|
|
||||||
tile->clock = 1;
|
|
||||||
tile->eval();
|
|
||||||
#if VM_TRACE
|
|
||||||
if (dump)
|
|
||||||
tfp->dump(static_cast<vluint64_t>(trace_count * 2 + 1));
|
|
||||||
#endif
|
|
||||||
trace_count++;
|
|
||||||
}
|
|
||||||
// for verilator multithreading. need to do 1 loop before checking if
|
|
||||||
// tsi exists, since tsi is created by verilated thread on the first
|
|
||||||
// serial_tick.
|
|
||||||
while ((!dtm || !dtm->done()) &&
|
|
||||||
(!jtag || !jtag->done()) &&
|
|
||||||
(!tsi || !tsi->done()) &&
|
|
||||||
!tile->io_success && trace_count < max_cycles);
|
|
||||||
|
|
||||||
#if VM_TRACE
|
|
||||||
if (tfp)
|
|
||||||
tfp->close();
|
|
||||||
if (vcdfile)
|
|
||||||
fclose(vcdfile);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
if (dtm && dtm->exit_code())
|
|
||||||
{
|
|
||||||
fprintf(stderr, "*** FAILED *** via dtm (code = %d, seed %d) after %ld cycles\n", dtm->exit_code(), random_seed, trace_count);
|
|
||||||
ret = dtm->exit_code();
|
|
||||||
}
|
|
||||||
else if (tsi && tsi->exit_code())
|
|
||||||
{
|
|
||||||
fprintf(stderr, "*** FAILED *** (code = %d, seed %d) after %ld cycles\n", tsi->exit_code(), random_seed, trace_count);
|
|
||||||
ret = tsi->exit_code();
|
|
||||||
}
|
|
||||||
else if (jtag && jtag->exit_code())
|
|
||||||
{
|
|
||||||
fprintf(stderr, "*** FAILED *** via jtag (code = %d, seed %d) after %ld cycles\n", jtag->exit_code(), random_seed, trace_count);
|
|
||||||
ret = jtag->exit_code();
|
|
||||||
}
|
|
||||||
else if (trace_count == max_cycles)
|
|
||||||
{
|
|
||||||
fprintf(stderr, "*** FAILED *** via trace_count (timeout, seed %d) after %ld cycles\n", random_seed, trace_count);
|
|
||||||
ret = 2;
|
|
||||||
}
|
|
||||||
else if (verbose || print_cycles)
|
|
||||||
{
|
|
||||||
fprintf(stderr, "*** PASSED *** Completed after %ld cycles\n", trace_count);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (dtm) delete dtm;
|
|
||||||
if (tsi) delete tsi;
|
|
||||||
if (jtag) delete jtag;
|
|
||||||
if (tile) delete tile;
|
|
||||||
if (verilated_argv) delete[] verilated_argv;
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
@@ -2,11 +2,23 @@
|
|||||||
#include <riscv/processor.h>
|
#include <riscv/processor.h>
|
||||||
#include <riscv/log_file.h>
|
#include <riscv/log_file.h>
|
||||||
#include <fesvr/context.h>
|
#include <fesvr/context.h>
|
||||||
|
#include <fesvr/htif.h>
|
||||||
|
#include <fesvr/memif.h>
|
||||||
|
#include <fesvr/elfloader.h>
|
||||||
#include <map>
|
#include <map>
|
||||||
#include <sstream>
|
#include <sstream>
|
||||||
#include <vpi_user.h>
|
#include <vpi_user.h>
|
||||||
#include <svdpi.h>
|
#include <svdpi.h>
|
||||||
|
|
||||||
|
#if __has_include("spiketile_tsi.h")
|
||||||
|
#define SPIKETILE_HTIF_TSI
|
||||||
|
extern htif_t* tsi;
|
||||||
|
#endif
|
||||||
|
#if __has_include("spiketile_dtm.h")
|
||||||
|
#define SPIKETILE_HTIF_DTM
|
||||||
|
extern htif_t* dtm;
|
||||||
|
#endif
|
||||||
|
|
||||||
enum transfer_t {
|
enum transfer_t {
|
||||||
NToB,
|
NToB,
|
||||||
NToT,
|
NToT,
|
||||||
@@ -73,8 +85,18 @@ public:
|
|||||||
void dcache_b(uint64_t address, uint64_t source, int param);
|
void dcache_b(uint64_t address, uint64_t source, int param);
|
||||||
bool dcache_c(uint64_t *address, uint64_t* source, int* param, unsigned char* voluntary, unsigned char* has_data, uint64_t* data[8]);
|
bool dcache_c(uint64_t *address, uint64_t* source, int* param, unsigned char* voluntary, unsigned char* has_data, uint64_t* data[8]);
|
||||||
void dcache_d(uint64_t sourceid, uint64_t data[8], unsigned char has_data, unsigned char grantack);
|
void dcache_d(uint64_t sourceid, uint64_t data[8], unsigned char has_data, unsigned char grantack);
|
||||||
|
|
||||||
|
void tcm_a(uint64_t address, uint64_t data, uint32_t mask, uint32_t opcode, uint32_t size);
|
||||||
|
bool tcm_d(uint64_t *data);
|
||||||
|
|
||||||
|
void loadmem(size_t base, const char* fname);
|
||||||
|
|
||||||
void drain_stq();
|
void drain_stq();
|
||||||
bool stq_empty() { return st_q.size() == 0; };
|
bool stq_empty() { return st_q.size() == 0; };
|
||||||
|
void flush_icache();
|
||||||
|
|
||||||
|
const cfg_t &get_cfg() const { return cfg; }
|
||||||
|
const std::map<size_t, processor_t*>& get_harts() const { return harts; }
|
||||||
|
|
||||||
~chipyard_simif_t() { };
|
~chipyard_simif_t() { };
|
||||||
chipyard_simif_t(size_t icache_ways,
|
chipyard_simif_t(size_t icache_ways,
|
||||||
@@ -86,9 +108,18 @@ public:
|
|||||||
char* readonly_uncacheable,
|
char* readonly_uncacheable,
|
||||||
char* executable,
|
char* executable,
|
||||||
size_t icache_sourceids,
|
size_t icache_sourceids,
|
||||||
size_t dcache_sourceids);
|
size_t dcache_sourceids,
|
||||||
|
size_t tcm_base,
|
||||||
|
size_t tcm_size,
|
||||||
|
const char* isastr,
|
||||||
|
size_t pmpregions);
|
||||||
uint64_t cycle;
|
uint64_t cycle;
|
||||||
bool use_stq;
|
bool use_stq;
|
||||||
|
htif_t *htif;
|
||||||
|
bool fast_clint;
|
||||||
|
cfg_t cfg;
|
||||||
|
std::map<size_t, processor_t*> harts;
|
||||||
|
bool accessed_tofrom_host;
|
||||||
private:
|
private:
|
||||||
bool handle_cache_access(reg_t addr, size_t len,
|
bool handle_cache_access(reg_t addr, size_t len,
|
||||||
uint8_t* load_bytes,
|
uint8_t* load_bytes,
|
||||||
@@ -133,6 +164,11 @@ private:
|
|||||||
uint64_t mmio_stdata;
|
uint64_t mmio_stdata;
|
||||||
size_t mmio_len;
|
size_t mmio_len;
|
||||||
uint64_t mmio_lddata;
|
uint64_t mmio_lddata;
|
||||||
|
|
||||||
|
uint64_t tcm_base;
|
||||||
|
uint64_t tcm_size;
|
||||||
|
uint8_t* tcm;
|
||||||
|
std::vector<uint64_t> tcm_q;
|
||||||
};
|
};
|
||||||
|
|
||||||
class tile_t {
|
class tile_t {
|
||||||
@@ -163,6 +199,7 @@ extern "C" void spike_tile(int hartid, char* isa,
|
|||||||
int dcache_sets, int dcache_ways,
|
int dcache_sets, int dcache_ways,
|
||||||
char* cacheable, char* uncacheable, char* readonly_uncacheable, char* executable,
|
char* cacheable, char* uncacheable, char* readonly_uncacheable, char* executable,
|
||||||
int icache_sourceids, int dcache_sourceids,
|
int icache_sourceids, int dcache_sourceids,
|
||||||
|
long long int tcm_base, long long int tcm_size,
|
||||||
long long int reset_vector,
|
long long int reset_vector,
|
||||||
long long int ipc,
|
long long int ipc,
|
||||||
long long int cycle,
|
long long int cycle,
|
||||||
@@ -237,7 +274,18 @@ extern "C" void spike_tile(int hartid, char* isa,
|
|||||||
int* mmio_a_size,
|
int* mmio_a_size,
|
||||||
|
|
||||||
unsigned char mmio_d_valid,
|
unsigned char mmio_d_valid,
|
||||||
long long int mmio_d_data
|
long long int mmio_d_data,
|
||||||
|
|
||||||
|
unsigned char tcm_a_valid,
|
||||||
|
long long int tcm_a_address,
|
||||||
|
long long int tcm_a_data,
|
||||||
|
int tcm_a_mask,
|
||||||
|
int tcm_a_opcode,
|
||||||
|
int tcm_a_size,
|
||||||
|
|
||||||
|
unsigned char* tcm_d_valid,
|
||||||
|
unsigned char tcm_d_ready,
|
||||||
|
long long int* tcm_d_data
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
if (!host) {
|
if (!host) {
|
||||||
@@ -248,36 +296,26 @@ extern "C" void spike_tile(int hartid, char* isa,
|
|||||||
if (tiles.find(hartid) == tiles.end()) {
|
if (tiles.find(hartid) == tiles.end()) {
|
||||||
printf("Constructing spike processor_t\n");
|
printf("Constructing spike processor_t\n");
|
||||||
isa_parser_t *isa_parser = new isa_parser_t(isa, "MSU");
|
isa_parser_t *isa_parser = new isa_parser_t(isa, "MSU");
|
||||||
|
std::string* isastr = new std::string(isa);
|
||||||
chipyard_simif_t* simif = new chipyard_simif_t(icache_ways, icache_sets,
|
chipyard_simif_t* simif = new chipyard_simif_t(icache_ways, icache_sets,
|
||||||
dcache_ways, dcache_sets,
|
dcache_ways, dcache_sets,
|
||||||
cacheable, uncacheable, readonly_uncacheable, executable,
|
cacheable, uncacheable, readonly_uncacheable, executable,
|
||||||
icache_sourceids, dcache_sourceids);
|
icache_sourceids, dcache_sourceids,
|
||||||
std::string* isastr = new std::string(isa);
|
tcm_base, tcm_size,
|
||||||
cfg_t* cfg = new cfg_t(std::make_pair(0, 0),
|
isastr->c_str(), pmpregions);
|
||||||
nullptr,
|
|
||||||
isastr->c_str(),
|
|
||||||
"MSU",
|
|
||||||
"vlen:128,elen:64",
|
|
||||||
false,
|
|
||||||
endianness_little,
|
|
||||||
pmpregions,
|
|
||||||
std::vector<mem_cfg_t>(),
|
|
||||||
std::vector<size_t>(),
|
|
||||||
false,
|
|
||||||
0);
|
|
||||||
processor_t* p = new processor_t(isa_parser,
|
processor_t* p = new processor_t(isa_parser,
|
||||||
cfg,
|
&simif->get_cfg(),
|
||||||
simif,
|
simif,
|
||||||
hartid,
|
hartid,
|
||||||
false,
|
false,
|
||||||
log_file->get(),
|
log_file->get(),
|
||||||
sout);
|
sout);
|
||||||
|
simif->harts[hartid] = p;
|
||||||
p->enable_log_commits();
|
|
||||||
|
|
||||||
s_vpi_vlog_info vinfo;
|
s_vpi_vlog_info vinfo;
|
||||||
if (!vpi_get_vlog_info(&vinfo))
|
if (!vpi_get_vlog_info(&vinfo))
|
||||||
abort();
|
abort();
|
||||||
|
std::string loadmem_file = "";
|
||||||
for (int i = 1; i < vinfo.argc; i++) {
|
for (int i = 1; i < vinfo.argc; i++) {
|
||||||
std::string arg(vinfo.argv[i]);
|
std::string arg(vinfo.argv[i]);
|
||||||
if (arg == "+spike-debug") {
|
if (arg == "+spike-debug") {
|
||||||
@@ -286,7 +324,18 @@ extern "C" void spike_tile(int hartid, char* isa,
|
|||||||
if (arg == "+spike-stq") {
|
if (arg == "+spike-stq") {
|
||||||
simif->use_stq = true;
|
simif->use_stq = true;
|
||||||
}
|
}
|
||||||
|
if (arg.find("+loadmem=") == 0) {
|
||||||
|
loadmem_file = arg.substr(strlen("+loadmem="));
|
||||||
|
}
|
||||||
|
if (arg == "+spike-fast-clint") {
|
||||||
|
simif->fast_clint = true;
|
||||||
|
}
|
||||||
|
if (arg == "+spike-verbose") {
|
||||||
|
p->enable_log_commits();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
if (loadmem_file != "" && tcm_size > 0)
|
||||||
|
simif->loadmem(tcm_base, loadmem_file.c_str());
|
||||||
|
|
||||||
p->reset();
|
p->reset();
|
||||||
p->get_state()->pc = reset_vector;
|
p->get_state()->pc = reset_vector;
|
||||||
@@ -296,11 +345,22 @@ extern "C" void spike_tile(int hartid, char* isa,
|
|||||||
tile_t* tile = tiles[hartid];
|
tile_t* tile = tiles[hartid];
|
||||||
chipyard_simif_t* simif = tile->simif;
|
chipyard_simif_t* simif = tile->simif;
|
||||||
processor_t* proc = tile->proc;
|
processor_t* proc = tile->proc;
|
||||||
|
#if defined(SPIKETILE_HTIF_TSI)
|
||||||
|
if (!simif->htif && tsi)
|
||||||
|
simif->htif = tsi;
|
||||||
|
#endif
|
||||||
|
#if defined(SPIKETILE_HTIF_DTM)
|
||||||
|
if (!simif->htif && dtm)
|
||||||
|
simif->htif = dtm;
|
||||||
|
#endif
|
||||||
|
|
||||||
simif->cycle = cycle;
|
simif->cycle = cycle;
|
||||||
if (debug) {
|
if (debug) {
|
||||||
proc->halt_request = proc->HR_REGULAR;
|
proc->halt_request = proc->HR_REGULAR;
|
||||||
}
|
}
|
||||||
|
if (!debug && proc->halt_request != proc->HR_NONE) {
|
||||||
|
proc->halt_request = proc->HR_NONE;
|
||||||
|
}
|
||||||
|
|
||||||
proc->get_state()->mip->backdoor_write_with_mask(MIP_MTIP, mtip ? MIP_MTIP : 0);
|
proc->get_state()->mip->backdoor_write_with_mask(MIP_MTIP, mtip ? MIP_MTIP : 0);
|
||||||
proc->get_state()->mip->backdoor_write_with_mask(MIP_MSIP, msip ? MIP_MSIP : 0);
|
proc->get_state()->mip->backdoor_write_with_mask(MIP_MSIP, msip ? MIP_MSIP : 0);
|
||||||
@@ -309,6 +369,7 @@ extern "C" void spike_tile(int hartid, char* isa,
|
|||||||
|
|
||||||
tile->max_insns = ipc;
|
tile->max_insns = ipc;
|
||||||
uint64_t pre_insns = proc->get_state()->minstret->read();
|
uint64_t pre_insns = proc->get_state()->minstret->read();
|
||||||
|
simif->accessed_tofrom_host = false;
|
||||||
tile->spike_context.switch_to();
|
tile->spike_context.switch_to();
|
||||||
*insns_retired = proc->get_state()->minstret->read() - pre_insns;
|
*insns_retired = proc->get_state()->minstret->read() - pre_insns;
|
||||||
if (simif->use_stq) {
|
if (simif->use_stq) {
|
||||||
@@ -357,6 +418,13 @@ extern "C" void spike_tile(int hartid, char* isa,
|
|||||||
if (mmio_d_valid) {
|
if (mmio_d_valid) {
|
||||||
simif->mmio_d(mmio_d_data);
|
simif->mmio_d(mmio_d_data);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (tcm_a_valid) {
|
||||||
|
simif->tcm_a(tcm_a_address, tcm_a_data, tcm_a_mask, tcm_a_opcode, tcm_a_size);
|
||||||
|
}
|
||||||
|
if (tcm_d_ready) {
|
||||||
|
*tcm_d_valid = simif->tcm_d((uint64_t*)tcm_d_data);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -369,14 +437,35 @@ chipyard_simif_t::chipyard_simif_t(size_t icache_ways,
|
|||||||
char* readonly_uncacheable,
|
char* readonly_uncacheable,
|
||||||
char* executable,
|
char* executable,
|
||||||
size_t ic_sourceids,
|
size_t ic_sourceids,
|
||||||
size_t dc_sourceids
|
size_t dc_sourceids,
|
||||||
|
size_t tcm_base,
|
||||||
|
size_t tcm_size,
|
||||||
|
const char* isastr,
|
||||||
|
size_t pmpregions
|
||||||
) :
|
) :
|
||||||
cycle(0),
|
cycle(0),
|
||||||
use_stq(false),
|
use_stq(false),
|
||||||
|
htif(nullptr),
|
||||||
|
fast_clint(false),
|
||||||
|
cfg(std::make_pair(0, 0),
|
||||||
|
nullptr,
|
||||||
|
isastr,
|
||||||
|
"MSU",
|
||||||
|
"vlen:128,elen:64",
|
||||||
|
false,
|
||||||
|
endianness_little,
|
||||||
|
pmpregions,
|
||||||
|
std::vector<mem_cfg_t>(),
|
||||||
|
std::vector<size_t>(),
|
||||||
|
false,
|
||||||
|
0),
|
||||||
|
accessed_tofrom_host(false),
|
||||||
icache_ways(icache_ways),
|
icache_ways(icache_ways),
|
||||||
icache_sets(icache_sets),
|
icache_sets(icache_sets),
|
||||||
dcache_ways(dcache_ways),
|
dcache_ways(dcache_ways),
|
||||||
dcache_sets(dcache_sets),
|
dcache_sets(dcache_sets),
|
||||||
|
tcm_base(tcm_base),
|
||||||
|
tcm_size(tcm_size),
|
||||||
mmio_valid(false),
|
mmio_valid(false),
|
||||||
mmio_inflight(false)
|
mmio_inflight(false)
|
||||||
{
|
{
|
||||||
@@ -432,6 +521,14 @@ chipyard_simif_t::chipyard_simif_t(size_t icache_ways,
|
|||||||
uint64_t size_int = std::stoul(size);
|
uint64_t size_int = std::stoul(size);
|
||||||
executables.push_back(mem_region_t { base_int, size_int });
|
executables.push_back(mem_region_t { base_int, size_int });
|
||||||
}
|
}
|
||||||
|
|
||||||
|
tcm = (uint8_t*)malloc(tcm_size);
|
||||||
|
}
|
||||||
|
|
||||||
|
void chipyard_simif_t::flush_icache() {
|
||||||
|
for (auto &w : icache) {
|
||||||
|
for (size_t i = 0; i < icache_sets; i++) w[i].state = NONE;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool chipyard_simif_t::reservable(reg_t addr) {
|
bool chipyard_simif_t::reservable(reg_t addr) {
|
||||||
@@ -440,12 +537,20 @@ bool chipyard_simif_t::reservable(reg_t addr) {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (addr >= tcm_base && addr < tcm_base + tcm_size) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool chipyard_simif_t::mmio_fetch(reg_t addr, size_t len, uint8_t* bytes) {
|
bool chipyard_simif_t::mmio_fetch(reg_t addr, size_t len, uint8_t* bytes) {
|
||||||
bool executable = false;
|
bool executable = false;
|
||||||
|
|
||||||
|
if (addr >= tcm_base && addr < tcm_base + tcm_size) {
|
||||||
|
memcpy(bytes, tcm + addr - tcm_base, len);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
for (auto& r: executables) {
|
for (auto& r: executables) {
|
||||||
if (addr >= r.base && addr + len <= r.base + r.size) {
|
if (addr >= r.base && addr + len <= r.base + r.size) {
|
||||||
executable = true;
|
executable = true;
|
||||||
@@ -466,6 +571,16 @@ bool chipyard_simif_t::mmio_load(reg_t addr, size_t len, uint8_t* bytes) {
|
|||||||
bool found = false;
|
bool found = false;
|
||||||
bool cacheable = false;
|
bool cacheable = false;
|
||||||
bool readonly = false;
|
bool readonly = false;
|
||||||
|
reg_t tohost_addr = htif ? htif->get_tohost_addr() : 0;
|
||||||
|
reg_t fromhost_addr = htif ? htif->get_fromhost_addr() : 0;
|
||||||
|
if (addr == tohost_addr || addr == fromhost_addr) {
|
||||||
|
accessed_tofrom_host = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (addr >= tcm_base && addr < tcm_base + tcm_size) {
|
||||||
|
memcpy(bytes, tcm + addr - tcm_base, len);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
for (auto& r: cacheables) {
|
for (auto& r: cacheables) {
|
||||||
if (addr >= r.base && addr + len <= r.base + r.size) {
|
if (addr >= r.base && addr + len <= r.base + r.size) {
|
||||||
cacheable = true;
|
cacheable = true;
|
||||||
@@ -497,6 +612,8 @@ bool chipyard_simif_t::mmio_load(reg_t addr, size_t len, uint8_t* bytes) {
|
|||||||
while (!handle_cache_access(addr, len, bytes, nullptr, LOAD)) {
|
while (!handle_cache_access(addr, len, bytes, nullptr, LOAD)) {
|
||||||
host->switch_to();
|
host->switch_to();
|
||||||
}
|
}
|
||||||
|
uint64_t lddata = 0;
|
||||||
|
memcpy(&lddata, bytes, len);
|
||||||
} else {
|
} else {
|
||||||
handle_mmio_access(addr, len, bytes, nullptr, LOAD, readonly);
|
handle_mmio_access(addr, len, bytes, nullptr, LOAD, readonly);
|
||||||
}
|
}
|
||||||
@@ -523,6 +640,7 @@ void chipyard_simif_t::handle_mmio_access(reg_t addr, size_t len,
|
|||||||
mmio_st = type == STORE;
|
mmio_st = type == STORE;
|
||||||
if (type == STORE) {
|
if (type == STORE) {
|
||||||
assert(len <= 8);
|
assert(len <= 8);
|
||||||
|
mmio_stdata = 0;
|
||||||
memcpy(&mmio_stdata, store_bytes, len);
|
memcpy(&mmio_stdata, store_bytes, len);
|
||||||
}
|
}
|
||||||
mmio_len = len;
|
mmio_len = len;
|
||||||
@@ -829,9 +947,21 @@ bool chipyard_simif_t::dcache_c(uint64_t* address, uint64_t* source, int* param,
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool chipyard_simif_t::mmio_store(reg_t addr, size_t len, const uint8_t* bytes) {
|
bool chipyard_simif_t::mmio_store(reg_t addr, size_t len, const uint8_t* bytes) {
|
||||||
|
reg_t tohost_addr = htif ? htif->get_tohost_addr() : 0;
|
||||||
|
reg_t fromhost_addr = htif ? htif->get_fromhost_addr() : 0;
|
||||||
|
|
||||||
|
if (addr == tohost_addr || addr == fromhost_addr) {
|
||||||
|
accessed_tofrom_host = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (addr >= tcm_base && addr < tcm_base + tcm_size) {
|
||||||
|
memcpy(tcm + addr - tcm_base, bytes, len);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
bool found = false;
|
bool found = false;
|
||||||
bool cacheable = false;
|
bool cacheable = false;
|
||||||
for (auto& r: cacheables) {
|
for (auto& r: cacheables) {
|
||||||
if (addr >= r.base && addr + len <= r.base + r.size) {
|
if (addr >= r.base && addr + len <= r.base + r.size) {
|
||||||
cacheable = true;
|
cacheable = true;
|
||||||
found = true;
|
found = true;
|
||||||
@@ -849,6 +979,8 @@ bool chipyard_simif_t::mmio_store(reg_t addr, size_t len, const uint8_t* bytes)
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if (cacheable) {
|
if (cacheable) {
|
||||||
|
uint64_t temp = 0;
|
||||||
|
memcpy(&temp, bytes, len);
|
||||||
if (use_stq) {
|
if (use_stq) {
|
||||||
assert(len <= 8);
|
assert(len <= 8);
|
||||||
uint64_t stdata;
|
uint64_t stdata;
|
||||||
@@ -899,27 +1031,104 @@ void chipyard_simif_t::dcache_d(uint64_t sourceid, uint64_t data[8], unsigned ch
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void chipyard_simif_t::tcm_a(uint64_t address, uint64_t data, uint32_t mask, uint32_t opcode, uint32_t size) {
|
||||||
|
bool load = opcode == 4;
|
||||||
|
uint64_t rdata = 0;
|
||||||
|
memcpy(&rdata, tcm + address - tcm_base, 8);
|
||||||
|
tcm_q.push_back(rdata);
|
||||||
|
|
||||||
|
if (!load) {
|
||||||
|
for (size_t i = 0; i < 8; i++) {
|
||||||
|
if ((mask >> i) & 1) {
|
||||||
|
memcpy(tcm + address - tcm_base + i, ((uint8_t*)&data) + i, 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool chipyard_simif_t::tcm_d(uint64_t* data) {
|
||||||
|
if (tcm_q.size() == 0)
|
||||||
|
return false;
|
||||||
|
*data = tcm_q[0];
|
||||||
|
tcm_q.erase(tcm_q.begin());
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void chipyard_simif_t::loadmem(size_t base, const char* fname) {
|
||||||
|
class loadmem_memif_t : public memif_t {
|
||||||
|
public:
|
||||||
|
loadmem_memif_t(chipyard_simif_t* _simif, size_t _start) : memif_t(nullptr), simif(_simif), start(_start) {}
|
||||||
|
void write(addr_t taddr, size_t len, const void* src) override
|
||||||
|
{
|
||||||
|
addr_t addr = taddr - start;
|
||||||
|
memcpy(simif->tcm + addr, src, len);
|
||||||
|
}
|
||||||
|
void read(addr_t taddr, size_t len, void* bytes) override {
|
||||||
|
assert(false);
|
||||||
|
}
|
||||||
|
endianness_t get_target_endianness() const override {
|
||||||
|
return endianness_little;
|
||||||
|
}
|
||||||
|
private:
|
||||||
|
chipyard_simif_t* simif;
|
||||||
|
size_t start;
|
||||||
|
} loadmem_memif(this, tcm_base);
|
||||||
|
|
||||||
|
reg_t entry;
|
||||||
|
load_elf(fname, &loadmem_memif, &entry);
|
||||||
|
}
|
||||||
|
|
||||||
bool insn_should_fence(uint64_t bits) {
|
bool insn_should_fence(uint64_t bits) {
|
||||||
uint8_t opcode = bits & 0x7f;
|
uint8_t opcode = bits & 0x7f;
|
||||||
return opcode == 0b0101111 || opcode == 0b0001111;
|
return opcode == 0b0101111 || opcode == 0b0001111;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool insn_is_wfi(uint64_t bits) {
|
||||||
|
return bits == 0x10500073;
|
||||||
|
}
|
||||||
|
|
||||||
void spike_thread_main(void* arg)
|
void spike_thread_main(void* arg)
|
||||||
{
|
{
|
||||||
tile_t* tile = (tile_t*) arg;
|
tile_t* tile = (tile_t*) arg;
|
||||||
|
processor_t* proc = tile->proc;
|
||||||
|
chipyard_simif_t* simif = tile->simif;
|
||||||
|
state_t* state = proc->get_state();
|
||||||
while (true) {
|
while (true) {
|
||||||
while (tile->max_insns == 0) {
|
while (tile->max_insns == 0) {
|
||||||
host->switch_to();
|
host->switch_to();
|
||||||
}
|
}
|
||||||
while (tile->max_insns != 0) {
|
while (tile->max_insns != 0) {
|
||||||
// TODO: Fences don't work
|
// TODO: Fences don't work
|
||||||
// uint64_t last_bits = tile->proc->get_last_bits();
|
//uint64_t last_bits = proc->get_last_bits();
|
||||||
// if (insn_should_fence(last_bits) && !tile->simif->stq_empty()) {
|
// if (insn_should_fence(last_bits) && !simif->stq_empty()) {
|
||||||
// host->switch_to();
|
// host->switch_to();
|
||||||
// }
|
// }
|
||||||
tile->proc->step(1);
|
uint64_t old_minstret = state->minstret->read();
|
||||||
|
proc->step(1);
|
||||||
tile->max_insns--;
|
tile->max_insns--;
|
||||||
tile->proc->get_state()->mcycle->write(tile->simif->cycle);
|
if (proc->is_waiting_for_interrupt()) {
|
||||||
|
if (simif->fast_clint) {
|
||||||
|
state->mip->backdoor_write_with_mask(MIP_MTIP, MIP_MTIP);
|
||||||
|
tile->max_insns = tile->max_insns <= 1 ? 0 : 1;
|
||||||
|
} else {
|
||||||
|
tile->max_insns = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (state->debug_mode) {
|
||||||
|
// TODO: Fix. This needs to apply the same hack as rocket-chip...
|
||||||
|
// JALRs in debug mode should flush the ICache.
|
||||||
|
// There is no API to determine if a JALR was executed, so hack the
|
||||||
|
// pc of the JALR in the debug rom here instead.
|
||||||
|
if (state->pc == 0x838) {
|
||||||
|
simif->flush_icache();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// If we get stuck in WFI, or we start polling tohost/fromhost, switch to host thread
|
||||||
|
if ((old_minstret == state->minstret->read()) || simif->accessed_tofrom_host) {
|
||||||
|
tile->max_insns = 0;
|
||||||
|
}
|
||||||
|
state->mcycle->write(simif->cycle);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -16,7 +16,8 @@ import "DPI-C" function void cospike_cosim(input longint cycle,
|
|||||||
input bit raise_exception,
|
input bit raise_exception,
|
||||||
input bit raise_interrupt,
|
input bit raise_interrupt,
|
||||||
input longint cause,
|
input longint cause,
|
||||||
input longint wdata
|
input longint wdata,
|
||||||
|
input int priv
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
||||||
@@ -42,6 +43,7 @@ module SpikeCosim #(
|
|||||||
input [63:0] trace_0_cause,
|
input [63:0] trace_0_cause,
|
||||||
input trace_0_has_wdata,
|
input trace_0_has_wdata,
|
||||||
input [63:0] trace_0_wdata,
|
input [63:0] trace_0_wdata,
|
||||||
|
input [2:0] trace_0_priv,
|
||||||
|
|
||||||
input trace_1_valid,
|
input trace_1_valid,
|
||||||
input [63:0] trace_1_iaddr,
|
input [63:0] trace_1_iaddr,
|
||||||
@@ -50,7 +52,8 @@ module SpikeCosim #(
|
|||||||
input trace_1_interrupt,
|
input trace_1_interrupt,
|
||||||
input [63:0] trace_1_cause,
|
input [63:0] trace_1_cause,
|
||||||
input trace_1_has_wdata,
|
input trace_1_has_wdata,
|
||||||
input [63:0] trace_1_wdata
|
input [63:0] trace_1_wdata,
|
||||||
|
input [2:0] trace_1_priv
|
||||||
);
|
);
|
||||||
|
|
||||||
initial begin
|
initial begin
|
||||||
@@ -62,12 +65,12 @@ module SpikeCosim #(
|
|||||||
if (trace_0_valid || trace_0_exception || trace_0_cause) begin
|
if (trace_0_valid || trace_0_exception || trace_0_cause) begin
|
||||||
cospike_cosim(cycle, hartid, trace_0_has_wdata, trace_0_valid, trace_0_iaddr,
|
cospike_cosim(cycle, hartid, trace_0_has_wdata, trace_0_valid, trace_0_iaddr,
|
||||||
trace_0_insn, trace_0_exception, trace_0_interrupt, trace_0_cause,
|
trace_0_insn, trace_0_exception, trace_0_interrupt, trace_0_cause,
|
||||||
trace_0_wdata);
|
trace_0_wdata, trace_0_priv);
|
||||||
end
|
end
|
||||||
if (trace_1_valid || trace_1_exception || trace_1_cause) begin
|
if (trace_1_valid || trace_1_exception || trace_1_cause) begin
|
||||||
cospike_cosim(cycle, hartid, trace_1_has_wdata, trace_1_valid, trace_1_iaddr,
|
cospike_cosim(cycle, hartid, trace_1_has_wdata, trace_1_valid, trace_1_iaddr,
|
||||||
trace_1_insn, trace_1_exception, trace_1_interrupt, trace_1_cause,
|
trace_1_insn, trace_1_exception, trace_1_interrupt, trace_1_cause,
|
||||||
trace_1_wdata);
|
trace_1_wdata, trace_1_priv);
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -13,6 +13,8 @@ import "DPI-C" function void spike_tile(input int hartid,
|
|||||||
input string executable,
|
input string executable,
|
||||||
input int icache_sourceids,
|
input int icache_sourceids,
|
||||||
input int dcache_sourceids,
|
input int dcache_sourceids,
|
||||||
|
input longint tcm_base,
|
||||||
|
input longint tcm_size,
|
||||||
input longint reset_vector,
|
input longint reset_vector,
|
||||||
input longint ipc,
|
input longint ipc,
|
||||||
input longint cycle,
|
input longint cycle,
|
||||||
@@ -89,7 +91,18 @@ import "DPI-C" function void spike_tile(input int hartid,
|
|||||||
output int mmio_a_size,
|
output int mmio_a_size,
|
||||||
|
|
||||||
input bit mmio_d_valid,
|
input bit mmio_d_valid,
|
||||||
input longint mmio_d_data
|
input longint mmio_d_data,
|
||||||
|
|
||||||
|
input bit tcm_a_valid,
|
||||||
|
input longint tcm_a_address,
|
||||||
|
input longint tcm_a_data,
|
||||||
|
input int tcm_a_mask,
|
||||||
|
input int tcm_a_opcode,
|
||||||
|
input int tcm_a_size,
|
||||||
|
|
||||||
|
output bit tcm_d_valid,
|
||||||
|
input bit tcm_d_ready,
|
||||||
|
output longint tcm_d_data
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
||||||
@@ -106,7 +119,9 @@ module SpikeBlackBox #(
|
|||||||
parameter READONLY_UNCACHEABLE,
|
parameter READONLY_UNCACHEABLE,
|
||||||
parameter EXECUTABLE,
|
parameter EXECUTABLE,
|
||||||
parameter ICACHE_SOURCEIDS,
|
parameter ICACHE_SOURCEIDS,
|
||||||
parameter DCACHE_SOURCEIDS )(
|
parameter DCACHE_SOURCEIDS,
|
||||||
|
parameter TCM_BASE,
|
||||||
|
parameter TCM_SIZE)(
|
||||||
input clock,
|
input clock,
|
||||||
input reset,
|
input reset,
|
||||||
input [63:0] reset_vector,
|
input [63:0] reset_vector,
|
||||||
@@ -185,7 +200,18 @@ module SpikeBlackBox #(
|
|||||||
output [31:0] mmio_a_size,
|
output [31:0] mmio_a_size,
|
||||||
|
|
||||||
input mmio_d_valid,
|
input mmio_d_valid,
|
||||||
input [63:0] mmio_d_data
|
input [63:0] mmio_d_data,
|
||||||
|
|
||||||
|
input tcm_a_valid,
|
||||||
|
input [63:0] tcm_a_address,
|
||||||
|
input [63:0] tcm_a_data,
|
||||||
|
input [31:0] tcm_a_mask,
|
||||||
|
input [31:0] tcm_a_opcode,
|
||||||
|
input [31:0] tcm_a_size,
|
||||||
|
|
||||||
|
output tcm_d_valid,
|
||||||
|
input tcm_d_ready,
|
||||||
|
output [63:0] tcm_d_data
|
||||||
);
|
);
|
||||||
|
|
||||||
longint __insns_retired;
|
longint __insns_retired;
|
||||||
@@ -257,7 +283,13 @@ module SpikeBlackBox #(
|
|||||||
reg [63:0] __dcache_c_data_6_reg;
|
reg [63:0] __dcache_c_data_6_reg;
|
||||||
reg [63:0] __dcache_c_data_7_reg;
|
reg [63:0] __dcache_c_data_7_reg;
|
||||||
|
|
||||||
|
wire __tcm_d_ready;
|
||||||
|
bit __tcm_d_valid;
|
||||||
|
longint __tcm_d_data;
|
||||||
|
|
||||||
|
reg __tcm_d_valid_reg;
|
||||||
|
reg [63:0] __tcm_d_data_reg;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
always @(posedge clock) begin
|
always @(posedge clock) begin
|
||||||
@@ -322,12 +354,18 @@ module SpikeBlackBox #(
|
|||||||
__dcache_c_data_6_reg <= 64'h0;
|
__dcache_c_data_6_reg <= 64'h0;
|
||||||
__dcache_c_data_7 = 64'h0;
|
__dcache_c_data_7 = 64'h0;
|
||||||
__dcache_c_data_7_reg <= 64'h0;
|
__dcache_c_data_7_reg <= 64'h0;
|
||||||
|
|
||||||
|
__tcm_d_valid = 1'b0;
|
||||||
|
__tcm_d_valid_reg <= 1'b0;
|
||||||
|
__tcm_d_data = 64'h0;
|
||||||
|
__tcm_d_data_reg <= 64'h0;
|
||||||
spike_tile_reset(HARTID);
|
spike_tile_reset(HARTID);
|
||||||
end else begin
|
end else begin
|
||||||
spike_tile(HARTID, ISA, PMPREGIONS,
|
spike_tile(HARTID, ISA, PMPREGIONS,
|
||||||
ICACHE_SETS, ICACHE_WAYS, DCACHE_SETS, DCACHE_WAYS,
|
ICACHE_SETS, ICACHE_WAYS, DCACHE_SETS, DCACHE_WAYS,
|
||||||
CACHEABLE, UNCACHEABLE, READONLY_UNCACHEABLE, EXECUTABLE,
|
CACHEABLE, UNCACHEABLE, READONLY_UNCACHEABLE, EXECUTABLE,
|
||||||
ICACHE_SOURCEIDS, DCACHE_SOURCEIDS,
|
ICACHE_SOURCEIDS, DCACHE_SOURCEIDS,
|
||||||
|
TCM_BASE, TCM_SIZE,
|
||||||
reset_vector, ipc, cycle, __insns_retired,
|
reset_vector, ipc, cycle, __insns_retired,
|
||||||
debug, mtip, msip, meip, seip,
|
debug, mtip, msip, meip, seip,
|
||||||
|
|
||||||
@@ -350,7 +388,10 @@ module SpikeBlackBox #(
|
|||||||
dcache_d_data_4, dcache_d_data_5, dcache_d_data_6, dcache_d_data_7,
|
dcache_d_data_4, dcache_d_data_5, dcache_d_data_6, dcache_d_data_7,
|
||||||
|
|
||||||
__mmio_a_ready, __mmio_a_valid, __mmio_a_address, __mmio_a_data, __mmio_a_store, __mmio_a_size,
|
__mmio_a_ready, __mmio_a_valid, __mmio_a_address, __mmio_a_data, __mmio_a_store, __mmio_a_size,
|
||||||
mmio_d_valid, mmio_d_data
|
mmio_d_valid, mmio_d_data,
|
||||||
|
|
||||||
|
tcm_a_valid, tcm_a_address, tcm_a_data, tcm_a_mask, tcm_a_opcode, tcm_a_size,
|
||||||
|
__tcm_d_valid, __tcm_d_ready, __tcm_d_data
|
||||||
);
|
);
|
||||||
__insns_retired_reg <= __insns_retired;
|
__insns_retired_reg <= __insns_retired;
|
||||||
|
|
||||||
@@ -385,6 +426,10 @@ module SpikeBlackBox #(
|
|||||||
__mmio_a_data_reg <= __mmio_a_data;
|
__mmio_a_data_reg <= __mmio_a_data;
|
||||||
__mmio_a_store_reg <= __mmio_a_store;
|
__mmio_a_store_reg <= __mmio_a_store;
|
||||||
__mmio_a_size_reg <= __mmio_a_size;
|
__mmio_a_size_reg <= __mmio_a_size;
|
||||||
|
|
||||||
|
__tcm_d_valid_reg <= __tcm_d_valid;
|
||||||
|
__tcm_d_data_reg <= __tcm_d_data;
|
||||||
|
|
||||||
end
|
end
|
||||||
end // always @ (posedge clock)
|
end // always @ (posedge clock)
|
||||||
assign insns_retired = __insns_retired_reg;
|
assign insns_retired = __insns_retired_reg;
|
||||||
@@ -424,6 +469,8 @@ module SpikeBlackBox #(
|
|||||||
assign mmio_a_size = __mmio_a_size_reg;
|
assign mmio_a_size = __mmio_a_size_reg;
|
||||||
assign __mmio_a_ready = mmio_a_ready;
|
assign __mmio_a_ready = mmio_a_ready;
|
||||||
|
|
||||||
|
assign tcm_d_valid = __tcm_d_valid_reg;
|
||||||
|
assign tcm_d_data = __tcm_d_data_reg;
|
||||||
|
assign __tcm_d_ready = tcm_d_ready;
|
||||||
|
|
||||||
endmodule;
|
endmodule;
|
||||||
|
|||||||
@@ -6,7 +6,7 @@ import scala.collection.mutable.{ArrayBuffer}
|
|||||||
|
|
||||||
import freechips.rocketchip.prci.{ClockGroupIdentityNode, ClockSinkParameters, ClockSinkNode, ClockGroup}
|
import freechips.rocketchip.prci.{ClockGroupIdentityNode, ClockSinkParameters, ClockSinkNode, ClockGroup}
|
||||||
import freechips.rocketchip.subsystem.{BaseSubsystem, SubsystemDriveAsyncClockGroupsKey}
|
import freechips.rocketchip.subsystem.{BaseSubsystem, SubsystemDriveAsyncClockGroupsKey}
|
||||||
import freechips.rocketchip.config.{Parameters, Field}
|
import org.chipsalliance.cde.config.{Parameters, Field}
|
||||||
import freechips.rocketchip.diplomacy.{LazyModule, LazyModuleImp, LazyRawModuleImp, LazyModuleImpLike, BindingScope}
|
import freechips.rocketchip.diplomacy.{LazyModule, LazyModuleImp, LazyRawModuleImp, LazyModuleImpLike, BindingScope}
|
||||||
import freechips.rocketchip.util.{ResetCatchAndSync}
|
import freechips.rocketchip.util.{ResetCatchAndSync}
|
||||||
import chipyard.iobinders._
|
import chipyard.iobinders._
|
||||||
|
|||||||
19
generators/chipyard/src/main/scala/ConfigFinder.scala
Normal file
19
generators/chipyard/src/main/scala/ConfigFinder.scala
Normal file
@@ -0,0 +1,19 @@
|
|||||||
|
package chipyard
|
||||||
|
|
||||||
|
import org.reflections.Reflections
|
||||||
|
import org.reflections.scanners.Scanners.SubTypes
|
||||||
|
import scala.jdk.CollectionConverters._
|
||||||
|
import scala.collection.{SortedSet}
|
||||||
|
|
||||||
|
import org.chipsalliance.cde.config.{Config}
|
||||||
|
|
||||||
|
object ConfigFinder {
|
||||||
|
def main(args: Array[String]) = {
|
||||||
|
val reflections = new Reflections()
|
||||||
|
val classes = reflections.get(SubTypes.of(classOf[Config]).asClass()).asScala
|
||||||
|
val sortedClasses = SortedSet[String]() ++ classes.map(_.getName)
|
||||||
|
for (cls <- sortedClasses) {
|
||||||
|
println(cls)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -4,7 +4,7 @@ import chisel3._
|
|||||||
import chisel3.experimental.{IntParam, StringParam, IO}
|
import chisel3.experimental.{IntParam, StringParam, IO}
|
||||||
import chisel3.util._
|
import chisel3.util._
|
||||||
|
|
||||||
import freechips.rocketchip.config.{Parameters, Field, Config}
|
import org.chipsalliance.cde.config.{Parameters, Field, Config}
|
||||||
import freechips.rocketchip.subsystem._
|
import freechips.rocketchip.subsystem._
|
||||||
import freechips.rocketchip.diplomacy._
|
import freechips.rocketchip.diplomacy._
|
||||||
import freechips.rocketchip.devices.tilelink._
|
import freechips.rocketchip.devices.tilelink._
|
||||||
@@ -18,7 +18,8 @@ case class SpikeCosimConfig(
|
|||||||
mem0_base: BigInt,
|
mem0_base: BigInt,
|
||||||
mem0_size: BigInt,
|
mem0_size: BigInt,
|
||||||
nharts: Int,
|
nharts: Int,
|
||||||
bootrom: String
|
bootrom: String,
|
||||||
|
has_dtm: Boolean
|
||||||
)
|
)
|
||||||
|
|
||||||
class SpikeCosim(cfg: SpikeCosimConfig) extends BlackBox(Map(
|
class SpikeCosim(cfg: SpikeCosimConfig) extends BlackBox(Map(
|
||||||
@@ -32,6 +33,7 @@ class SpikeCosim(cfg: SpikeCosimConfig) extends BlackBox(Map(
|
|||||||
{
|
{
|
||||||
addResource("/csrc/cospike.cc")
|
addResource("/csrc/cospike.cc")
|
||||||
addResource("/vsrc/cospike.v")
|
addResource("/vsrc/cospike.v")
|
||||||
|
if (cfg.has_dtm) addResource("/csrc/cospike_dtm.h")
|
||||||
val io = IO(new Bundle {
|
val io = IO(new Bundle {
|
||||||
val clock = Input(Clock())
|
val clock = Input(Clock())
|
||||||
val reset = Input(Bool())
|
val reset = Input(Bool())
|
||||||
@@ -46,6 +48,7 @@ class SpikeCosim(cfg: SpikeCosimConfig) extends BlackBox(Map(
|
|||||||
val cause = UInt(64.W)
|
val cause = UInt(64.W)
|
||||||
val has_wdata = Bool()
|
val has_wdata = Bool()
|
||||||
val wdata = UInt(64.W)
|
val wdata = UInt(64.W)
|
||||||
|
val priv = UInt(3.W)
|
||||||
}))
|
}))
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@@ -64,12 +67,8 @@ object SpikeCosim
|
|||||||
require(trace.numInsns <= 2)
|
require(trace.numInsns <= 2)
|
||||||
cosim.io.cycle := cycle
|
cosim.io.cycle := cycle
|
||||||
cosim.io.trace.map(t => {
|
cosim.io.trace.map(t => {
|
||||||
|
t := DontCare
|
||||||
t.valid := false.B
|
t.valid := false.B
|
||||||
t.iaddr := 0.U
|
|
||||||
t.insn := 0.U
|
|
||||||
t.exception := false.B
|
|
||||||
t.interrupt := false.B
|
|
||||||
t.cause := 0.U
|
|
||||||
})
|
})
|
||||||
cosim.io.hartid := hartid.U
|
cosim.io.hartid := hartid.U
|
||||||
for (i <- 0 until trace.numInsns) {
|
for (i <- 0 until trace.numInsns) {
|
||||||
@@ -83,6 +82,7 @@ object SpikeCosim
|
|||||||
cosim.io.trace(i).cause := trace.insns(i).cause
|
cosim.io.trace(i).cause := trace.insns(i).cause
|
||||||
cosim.io.trace(i).has_wdata := trace.insns(i).wdata.isDefined.B
|
cosim.io.trace(i).has_wdata := trace.insns(i).wdata.isDefined.B
|
||||||
cosim.io.trace(i).wdata := trace.insns(i).wdata.getOrElse(0.U)
|
cosim.io.trace(i).wdata := trace.insns(i).wdata.getOrElse(0.U)
|
||||||
|
cosim.io.trace(i).priv := trace.insns(i).priv
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ import chisel3._
|
|||||||
|
|
||||||
import freechips.rocketchip.subsystem._
|
import freechips.rocketchip.subsystem._
|
||||||
import freechips.rocketchip.system._
|
import freechips.rocketchip.system._
|
||||||
import freechips.rocketchip.config.Parameters
|
import org.chipsalliance.cde.config.Parameters
|
||||||
import freechips.rocketchip.devices.tilelink._
|
import freechips.rocketchip.devices.tilelink._
|
||||||
|
|
||||||
// ------------------------------------
|
// ------------------------------------
|
||||||
@@ -14,7 +14,7 @@ import freechips.rocketchip.devices.tilelink._
|
|||||||
// DOC include start: DigitalTop
|
// DOC include start: DigitalTop
|
||||||
class DigitalTop(implicit p: Parameters) extends ChipyardSystem
|
class DigitalTop(implicit p: Parameters) extends ChipyardSystem
|
||||||
with testchipip.CanHavePeripheryCustomBootPin // Enables optional custom boot pin
|
with testchipip.CanHavePeripheryCustomBootPin // Enables optional custom boot pin
|
||||||
with testchipip.HasPeripheryBootAddrReg // Use programmable boot address register
|
with testchipip.CanHavePeripheryBootAddrReg // Use programmable boot address register
|
||||||
with testchipip.CanHaveTraceIO // Enables optionally adding trace IO
|
with testchipip.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
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ package chipyard.iobinders
|
|||||||
import chisel3._
|
import chisel3._
|
||||||
import chisel3.experimental.{Analog, IO, DataMirror}
|
import chisel3.experimental.{Analog, IO, DataMirror}
|
||||||
|
|
||||||
import freechips.rocketchip.config._
|
import org.chipsalliance.cde.config._
|
||||||
import freechips.rocketchip.diplomacy._
|
import freechips.rocketchip.diplomacy._
|
||||||
import freechips.rocketchip.devices.debug._
|
import freechips.rocketchip.devices.debug._
|
||||||
import freechips.rocketchip.jtag.{JTAGIO}
|
import freechips.rocketchip.jtag.{JTAGIO}
|
||||||
@@ -25,7 +25,6 @@ import barstools.iocell.chisel._
|
|||||||
import testchipip._
|
import testchipip._
|
||||||
import icenet.{CanHavePeripheryIceNIC, SimNetwork, NicLoopback, NICKey, NICIOvonly}
|
import icenet.{CanHavePeripheryIceNIC, SimNetwork, NicLoopback, NICKey, NICIOvonly}
|
||||||
import chipyard.{CanHaveMasterTLMemPort}
|
import chipyard.{CanHaveMasterTLMemPort}
|
||||||
import chipyard.clocking.{HasChipyardPRCI, DividerOnlyClockGenerator}
|
|
||||||
|
|
||||||
import scala.reflect.{ClassTag}
|
import scala.reflect.{ClassTag}
|
||||||
|
|
||||||
@@ -51,6 +50,12 @@ case object IOBinders extends Field[Map[String, Seq[IOBinderFunction]]](
|
|||||||
Map[String, Seq[IOBinderFunction]]().withDefaultValue(Nil)
|
Map[String, Seq[IOBinderFunction]]().withDefaultValue(Nil)
|
||||||
)
|
)
|
||||||
|
|
||||||
|
case object DontTouchIOBindersPorts extends Field[Boolean](true)
|
||||||
|
|
||||||
|
class WithDontTouchIOBinders(b: Boolean = true) extends Config((site, here, up) => {
|
||||||
|
case DontTouchIOBindersPorts => b
|
||||||
|
})
|
||||||
|
|
||||||
abstract trait HasIOBinders { this: LazyModule =>
|
abstract trait HasIOBinders { this: LazyModule =>
|
||||||
val lazySystem: LazyModule
|
val lazySystem: LazyModule
|
||||||
private val iobinders = p(IOBinders)
|
private val iobinders = p(IOBinders)
|
||||||
@@ -67,10 +72,33 @@ abstract trait HasIOBinders { this: LazyModule =>
|
|||||||
})
|
})
|
||||||
|
|
||||||
// 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)
|
||||||
lazy val iocells = (lzyFlattened.values ++ impFlattened.values).unzip._2.flatten.toBuffer
|
val iocells = InModuleBody { (lzyFlattened.values ++ impFlattened.values).unzip._2.flatten.toBuffer }
|
||||||
|
|
||||||
// A mapping between stringified DigitalSystem traits and their corresponding ChipTop ports
|
// A mapping between stringified DigitalSystem traits and their corresponding ChipTop ports
|
||||||
lazy val portMap = iobinders.keys.map(k => k -> (lzyFlattened(k)._1 ++ impFlattened(k)._1)).toMap
|
val portMap = InModuleBody { iobinders.keys.map(k => k -> (lzyFlattened(k)._1 ++ impFlattened(k)._1)).toMap }
|
||||||
|
|
||||||
|
// A mapping between stringified DigitalSystem traits and their corresponding ChipTop iocells
|
||||||
|
val iocellMap = InModuleBody { iobinders.keys.map(k => k -> (lzyFlattened(k)._2 ++ impFlattened(k)._2)).toMap }
|
||||||
|
|
||||||
|
InModuleBody {
|
||||||
|
if (p(DontTouchIOBindersPorts)) {
|
||||||
|
portMap.values.foreach(_.foreach(dontTouch(_)))
|
||||||
|
}
|
||||||
|
|
||||||
|
println("IOCells generated by IOBinders:")
|
||||||
|
for ((k, v) <- iocellMap) {
|
||||||
|
if (!v.isEmpty) {
|
||||||
|
val cells = v.map(_.getClass.getSimpleName).groupBy(identity).mapValues(_.size)
|
||||||
|
|
||||||
|
println(s" IOBinder for $k generated:")
|
||||||
|
for ((t, c) <- cells) { println(s" $c X $t") }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
println()
|
||||||
|
val totals = iocells.map(_.getClass.getSimpleName).groupBy(identity).mapValues(_.size)
|
||||||
|
println(s" Total generated ${iocells.size} IOCells:")
|
||||||
|
for ((t, c) <- totals) { println(s" $c X $t") }
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Note: The parameters instance is accessible only through LazyModule
|
// Note: The parameters instance is accessible only through LazyModule
|
||||||
@@ -219,7 +247,7 @@ class WithDebugIOCells extends OverrideLazyIOBinder({
|
|||||||
def clockBundle = clockSinkNode.get.in.head._1
|
def clockBundle = clockSinkNode.get.in.head._1
|
||||||
|
|
||||||
|
|
||||||
InModuleBody { system.asInstanceOf[BaseSubsystem].module match { case system: HasPeripheryDebugModuleImp => {
|
InModuleBody { system.asInstanceOf[BaseSubsystem] match { case system: HasPeripheryDebug => {
|
||||||
system.debug.map({ debug =>
|
system.debug.map({ debug =>
|
||||||
// We never use the PSDIO, so tie it off on-chip
|
// We never use the PSDIO, so tie it off on-chip
|
||||||
system.psd.psd.foreach { _ <> 0.U.asTypeOf(new PSDTestMode) }
|
system.psd.psd.foreach { _ <> 0.U.asTypeOf(new PSDTestMode) }
|
||||||
@@ -396,45 +424,4 @@ class WithDontTouchPorts extends OverrideIOBinder({
|
|||||||
(system: DontTouch) => system.dontTouchPorts(); (Nil, Nil)
|
(system: DontTouch) => system.dontTouchPorts(); (Nil, Nil)
|
||||||
})
|
})
|
||||||
|
|
||||||
class ClockWithFreq(val freqMHz: Double) extends Bundle {
|
|
||||||
val clock = Clock()
|
|
||||||
}
|
|
||||||
|
|
||||||
class WithDividerOnlyClockGenerator extends OverrideLazyIOBinder({
|
|
||||||
(system: HasChipyardPRCI) => {
|
|
||||||
// Connect the implicit clock
|
|
||||||
implicit val p = GetSystemParameters(system)
|
|
||||||
val implicitClockSinkNode = ClockSinkNode(Seq(ClockSinkParameters(name = Some("implicit_clock"))))
|
|
||||||
system.connectImplicitClockSinkNode(implicitClockSinkNode)
|
|
||||||
InModuleBody {
|
|
||||||
val implicit_clock = implicitClockSinkNode.in.head._1.clock
|
|
||||||
val implicit_reset = implicitClockSinkNode.in.head._1.reset
|
|
||||||
system.asInstanceOf[BaseSubsystem].module match { case l: LazyModuleImp => {
|
|
||||||
l.clock := implicit_clock
|
|
||||||
l.reset := implicit_reset
|
|
||||||
}}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Connect all other requested clocks
|
|
||||||
val referenceClockSource = ClockSourceNode(Seq(ClockSourceParameters()))
|
|
||||||
val dividerOnlyClockGen = LazyModule(new DividerOnlyClockGenerator("buildTopClockGenerator"))
|
|
||||||
|
|
||||||
(system.allClockGroupsNode
|
|
||||||
:= dividerOnlyClockGen.node
|
|
||||||
:= referenceClockSource)
|
|
||||||
|
|
||||||
InModuleBody {
|
|
||||||
val clock_wire = Wire(Input(new ClockWithFreq(dividerOnlyClockGen.module.referenceFreq)))
|
|
||||||
val reset_wire = Wire(Input(AsyncReset()))
|
|
||||||
val (clock_io, clockIOCell) = IOCell.generateIOFromSignal(clock_wire, "clock", p(IOCellKey))
|
|
||||||
val (reset_io, resetIOCell) = IOCell.generateIOFromSignal(reset_wire, "reset", p(IOCellKey))
|
|
||||||
|
|
||||||
referenceClockSource.out.unzip._1.map { o =>
|
|
||||||
o.clock := clock_wire.clock
|
|
||||||
o.reset := reset_wire
|
|
||||||
}
|
|
||||||
|
|
||||||
(Seq(clock_io, reset_io), clockIOCell ++ resetIOCell)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|||||||
@@ -4,9 +4,10 @@ import chisel3._
|
|||||||
import chisel3.util._
|
import chisel3.util._
|
||||||
import chisel3.experimental.{IntParam, StringParam, IO}
|
import chisel3.experimental.{IntParam, StringParam, IO}
|
||||||
|
|
||||||
import freechips.rocketchip.config._
|
import org.chipsalliance.cde.config._
|
||||||
import freechips.rocketchip.subsystem._
|
import freechips.rocketchip.subsystem._
|
||||||
import freechips.rocketchip.devices.tilelink._
|
import freechips.rocketchip.devices.tilelink._
|
||||||
|
import freechips.rocketchip.devices.debug.{ExportDebug, DMI}
|
||||||
import freechips.rocketchip.diplomacy._
|
import freechips.rocketchip.diplomacy._
|
||||||
import freechips.rocketchip.rocket._
|
import freechips.rocketchip.rocket._
|
||||||
import freechips.rocketchip.tilelink._
|
import freechips.rocketchip.tilelink._
|
||||||
@@ -15,8 +16,7 @@ import freechips.rocketchip.util._
|
|||||||
import freechips.rocketchip.tile._
|
import freechips.rocketchip.tile._
|
||||||
import freechips.rocketchip.prci.ClockSinkParameters
|
import freechips.rocketchip.prci.ClockSinkParameters
|
||||||
|
|
||||||
case class SpikeCoreParams(
|
case class SpikeCoreParams() extends CoreParams {
|
||||||
) extends CoreParams {
|
|
||||||
val useVM = true
|
val useVM = true
|
||||||
val useHypervisor = false
|
val useHypervisor = false
|
||||||
val useSupervisor = true
|
val useSupervisor = true
|
||||||
@@ -79,7 +79,8 @@ case class SpikeTileParams(
|
|||||||
hartId: Int = 0,
|
hartId: Int = 0,
|
||||||
val core: SpikeCoreParams = SpikeCoreParams(),
|
val core: SpikeCoreParams = SpikeCoreParams(),
|
||||||
icacheParams: ICacheParams = ICacheParams(nWays = 32),
|
icacheParams: ICacheParams = ICacheParams(nWays = 32),
|
||||||
dcacheParams: DCacheParams = DCacheParams(nWays = 32)
|
dcacheParams: DCacheParams = DCacheParams(nWays = 32),
|
||||||
|
tcmParams: Option[MasterPortParams] = None // tightly coupled memory
|
||||||
) extends InstantiableTileParams[SpikeTile]
|
) extends InstantiableTileParams[SpikeTile]
|
||||||
{
|
{
|
||||||
val name = Some("spike_tile")
|
val name = Some("spike_tile")
|
||||||
@@ -145,6 +146,27 @@ class SpikeTile(
|
|||||||
sourceId = IdRange(0, 1),
|
sourceId = IdRange(0, 1),
|
||||||
requestFifo = true))))))
|
requestFifo = true))))))
|
||||||
|
|
||||||
|
tlSlaveXbar.node :*= slaveNode
|
||||||
|
val tcmNode = spikeTileParams.tcmParams.map { tcmP =>
|
||||||
|
val device = new MemoryDevice
|
||||||
|
val base = AddressSet.misaligned(tcmP.base, tcmP.size)
|
||||||
|
val tcmNode = TLManagerNode(Seq(TLSlavePortParameters.v1(
|
||||||
|
managers = Seq(TLSlaveParameters.v1(
|
||||||
|
address = base,
|
||||||
|
resources = device.reg,
|
||||||
|
regionType = RegionType.IDEMPOTENT, // not cacheable
|
||||||
|
executable = true,
|
||||||
|
supportsGet = TransferSizes(1, 8),
|
||||||
|
supportsPutFull = TransferSizes(1, 8),
|
||||||
|
supportsPutPartial = TransferSizes(1, 8),
|
||||||
|
fifoId = Some(0)
|
||||||
|
)),
|
||||||
|
beatBytes = 8
|
||||||
|
)))
|
||||||
|
connectTLSlave(tcmNode := TLBuffer(), 8)
|
||||||
|
tcmNode
|
||||||
|
}
|
||||||
|
|
||||||
tlOtherMastersNode := TLBuffer() := tlMasterXbar.node
|
tlOtherMastersNode := TLBuffer() := tlMasterXbar.node
|
||||||
masterNode :=* tlOtherMastersNode
|
masterNode :=* tlOtherMastersNode
|
||||||
tlMasterXbar.node := TLWidthWidget(64) := TLBuffer():= icacheNode
|
tlMasterXbar.node := TLWidthWidget(64) := TLBuffer():= icacheNode
|
||||||
@@ -166,7 +188,10 @@ class SpikeBlackBox(
|
|||||||
cacheable_regions: String,
|
cacheable_regions: String,
|
||||||
uncacheable_regions: String,
|
uncacheable_regions: String,
|
||||||
readonly_uncacheable_regions: String,
|
readonly_uncacheable_regions: String,
|
||||||
executable_regions: String) extends BlackBox(Map(
|
executable_regions: String,
|
||||||
|
tcm_base: BigInt,
|
||||||
|
tcm_size: BigInt,
|
||||||
|
use_dtm: Boolean) extends BlackBox(Map(
|
||||||
"HARTID" -> IntParam(hartId),
|
"HARTID" -> IntParam(hartId),
|
||||||
"ISA" -> StringParam(isa),
|
"ISA" -> StringParam(isa),
|
||||||
"PMPREGIONS" -> IntParam(pmpregions),
|
"PMPREGIONS" -> IntParam(pmpregions),
|
||||||
@@ -179,7 +204,9 @@ class SpikeBlackBox(
|
|||||||
"UNCACHEABLE" -> StringParam(uncacheable_regions),
|
"UNCACHEABLE" -> StringParam(uncacheable_regions),
|
||||||
"READONLY_UNCACHEABLE" -> StringParam(readonly_uncacheable_regions),
|
"READONLY_UNCACHEABLE" -> StringParam(readonly_uncacheable_regions),
|
||||||
"CACHEABLE" -> StringParam(cacheable_regions),
|
"CACHEABLE" -> StringParam(cacheable_regions),
|
||||||
"EXECUTABLE" -> StringParam(executable_regions)
|
"EXECUTABLE" -> StringParam(executable_regions),
|
||||||
|
"TCM_BASE" -> IntParam(tcm_base),
|
||||||
|
"TCM_SIZE" -> IntParam(tcm_size)
|
||||||
)) with HasBlackBoxResource {
|
)) with HasBlackBoxResource {
|
||||||
|
|
||||||
val io = IO(new Bundle {
|
val io = IO(new Bundle {
|
||||||
@@ -258,10 +285,30 @@ class SpikeBlackBox(
|
|||||||
val data = Input(UInt(64.W))
|
val data = Input(UInt(64.W))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
val tcm = new Bundle {
|
||||||
|
val a = new Bundle {
|
||||||
|
val valid = Input(Bool())
|
||||||
|
val address = Input(UInt(64.W))
|
||||||
|
val data = Input(UInt(64.W))
|
||||||
|
val mask = Input(UInt(32.W))
|
||||||
|
val opcode = Input(UInt(32.W))
|
||||||
|
val size = Input(UInt(32.W))
|
||||||
|
}
|
||||||
|
val d = new Bundle {
|
||||||
|
val valid = Output(Bool())
|
||||||
|
val ready = Input(Bool())
|
||||||
|
val data = Output(UInt(64.W))
|
||||||
|
}
|
||||||
|
}
|
||||||
})
|
})
|
||||||
addResource("/vsrc/spiketile.v")
|
addResource("/vsrc/spiketile.v")
|
||||||
addResource("/csrc/spiketile.cc")
|
addResource("/csrc/spiketile.cc")
|
||||||
|
if (use_dtm) {
|
||||||
|
addResource("/csrc/spiketile_dtm.h")
|
||||||
|
} else {
|
||||||
|
addResource("/csrc/spiketile_tsi.h")
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class SpikeTileModuleImp(outer: SpikeTile) extends BaseTileModuleImp(outer) {
|
class SpikeTileModuleImp(outer: SpikeTile) extends BaseTileModuleImp(outer) {
|
||||||
@@ -285,11 +332,19 @@ class SpikeTileModuleImp(outer: SpikeTile) extends BaseTileModuleImp(outer) {
|
|||||||
val (dcache_tl, dcacheEdge) = outer.dcacheNode.out(0)
|
val (dcache_tl, dcacheEdge) = outer.dcacheNode.out(0)
|
||||||
val (mmio_tl, mmioEdge) = outer.mmioNode.out(0)
|
val (mmio_tl, mmioEdge) = outer.mmioNode.out(0)
|
||||||
|
|
||||||
|
// Note: This assumes that if the debug module exposes the ClockedDMI port,
|
||||||
|
// then the DTM-based bringup with SimDTM will be used. This isn't required to be
|
||||||
|
// true, but it usually is
|
||||||
|
val useDTM = p(ExportDebug).protocols.contains(DMI)
|
||||||
val spike = Module(new SpikeBlackBox(hartId, isaDTS, tileParams.core.nPMPs,
|
val spike = Module(new SpikeBlackBox(hartId, isaDTS, tileParams.core.nPMPs,
|
||||||
tileParams.icache.get.nSets, tileParams.icache.get.nWays,
|
tileParams.icache.get.nSets, tileParams.icache.get.nWays,
|
||||||
tileParams.dcache.get.nSets, tileParams.dcache.get.nWays,
|
tileParams.dcache.get.nSets, tileParams.dcache.get.nWays,
|
||||||
tileParams.dcache.get.nMSHRs,
|
tileParams.dcache.get.nMSHRs,
|
||||||
cacheable_regions, uncacheable_regions, readonly_uncacheable_regions, executable_regions))
|
cacheable_regions, uncacheable_regions, readonly_uncacheable_regions, executable_regions,
|
||||||
|
outer.spikeTileParams.tcmParams.map(_.base).getOrElse(0),
|
||||||
|
outer.spikeTileParams.tcmParams.map(_.size).getOrElse(0),
|
||||||
|
useDTM
|
||||||
|
))
|
||||||
spike.io.clock := clock.asBool
|
spike.io.clock := clock.asBool
|
||||||
val cycle = RegInit(0.U(64.W))
|
val cycle = RegInit(0.U(64.W))
|
||||||
cycle := cycle + 1.U
|
cycle := cycle + 1.U
|
||||||
@@ -304,64 +359,63 @@ class SpikeTileModuleImp(outer: SpikeTile) extends BaseTileModuleImp(outer) {
|
|||||||
spike.io.msip := int_bundle.msip
|
spike.io.msip := int_bundle.msip
|
||||||
spike.io.meip := int_bundle.meip
|
spike.io.meip := int_bundle.meip
|
||||||
spike.io.seip := int_bundle.seip.get
|
spike.io.seip := int_bundle.seip.get
|
||||||
spike.io.ipc := PlusArg("spike-ipc", 10000, width=64)
|
spike.io.ipc := PlusArg("spike-ipc", width=32, default=10000)
|
||||||
|
|
||||||
val blockBits = log2Ceil(p(CacheBlockBytes))
|
val blockBits = log2Ceil(p(CacheBlockBytes))
|
||||||
|
spike.io.icache.a.ready := icache_tl.a.ready
|
||||||
val icache_a_q = Module(new Queue(new TLBundleA(icacheEdge.bundle), 1, flow=true, pipe=true))
|
icache_tl.a.valid := spike.io.icache.a.valid
|
||||||
spike.io.icache.a.ready := icache_a_q.io.enq.ready && icache_a_q.io.count === 0.U
|
icache_tl.a.bits := icacheEdge.Get(
|
||||||
icache_tl.a <> icache_a_q.io.deq
|
|
||||||
icache_a_q.io.enq.valid := spike.io.icache.a.valid
|
|
||||||
icache_a_q.io.enq.bits := icacheEdge.Get(
|
|
||||||
fromSource = spike.io.icache.a.sourceid,
|
fromSource = spike.io.icache.a.sourceid,
|
||||||
toAddress = (spike.io.icache.a.address >> blockBits) << blockBits,
|
toAddress = (spike.io.icache.a.address >> blockBits) << blockBits,
|
||||||
lgSize = blockBits.U)._2
|
lgSize = blockBits.U)._2
|
||||||
|
|
||||||
icache_tl.d.ready := true.B
|
icache_tl.d.ready := true.B
|
||||||
spike.io.icache.d.valid := icache_tl.d.valid
|
spike.io.icache.d.valid := icache_tl.d.valid
|
||||||
spike.io.icache.d.sourceid := icache_tl.d.bits.source
|
spike.io.icache.d.sourceid := icache_tl.d.bits.source
|
||||||
spike.io.icache.d.data := icache_tl.d.bits.data.asTypeOf(Vec(8, UInt(64.W)))
|
spike.io.icache.d.data := icache_tl.d.bits.data.asTypeOf(Vec(8, UInt(64.W)))
|
||||||
|
|
||||||
val dcache_a_q = Module(new Queue(new TLBundleA(dcacheEdge.bundle), 1, flow=true, pipe=true))
|
spike.io.dcache.a.ready := dcache_tl.a.ready
|
||||||
spike.io.dcache.a.ready := dcache_a_q.io.enq.ready && dcache_a_q.io.count === 0.U
|
dcache_tl.a.valid := spike.io.dcache.a.valid
|
||||||
dcache_tl.a <> dcache_a_q.io.deq
|
if (dcacheEdge.manager.anySupportAcquireB) {
|
||||||
dcache_a_q.io.enq.valid := spike.io.dcache.a.valid
|
dcache_tl.a.bits := dcacheEdge.AcquireBlock(
|
||||||
dcache_a_q.io.enq.bits := dcacheEdge.AcquireBlock(
|
fromSource = spike.io.dcache.a.sourceid,
|
||||||
fromSource = spike.io.dcache.a.sourceid,
|
toAddress = (spike.io.dcache.a.address >> blockBits) << blockBits,
|
||||||
toAddress = (spike.io.dcache.a.address >> blockBits) << blockBits,
|
lgSize = blockBits.U,
|
||||||
lgSize = blockBits.U,
|
growPermissions = Mux(spike.io.dcache.a.state_old, 2.U, Mux(spike.io.dcache.a.state_new, 1.U, 0.U)))._2
|
||||||
growPermissions = Mux(spike.io.dcache.a.state_old, 2.U, Mux(spike.io.dcache.a.state_new, 1.U, 0.U)))._2
|
} else {
|
||||||
|
dcache_tl.a.bits := DontCare
|
||||||
|
}
|
||||||
dcache_tl.b.ready := true.B
|
dcache_tl.b.ready := true.B
|
||||||
spike.io.dcache.b.valid := dcache_tl.b.valid
|
spike.io.dcache.b.valid := dcache_tl.b.valid
|
||||||
spike.io.dcache.b.address := dcache_tl.b.bits.address
|
spike.io.dcache.b.address := dcache_tl.b.bits.address
|
||||||
spike.io.dcache.b.source := dcache_tl.b.bits.source
|
spike.io.dcache.b.source := dcache_tl.b.bits.source
|
||||||
spike.io.dcache.b.param := dcache_tl.b.bits.param
|
spike.io.dcache.b.param := dcache_tl.b.bits.param
|
||||||
|
|
||||||
val dcache_c_q = Module(new Queue(new TLBundleC(dcacheEdge.bundle), 1, flow=true, pipe=true))
|
spike.io.dcache.c.ready := dcache_tl.c.ready
|
||||||
spike.io.dcache.c.ready := dcache_c_q.io.enq.ready && dcache_c_q.io.count === 0.U
|
dcache_tl.c.valid := spike.io.dcache.c.valid
|
||||||
dcache_tl.c <> dcache_c_q.io.deq
|
if (dcacheEdge.manager.anySupportAcquireB) {
|
||||||
dcache_c_q.io.enq.valid := spike.io.dcache.c.valid
|
dcache_tl.c.bits := Mux(spike.io.dcache.c.voluntary,
|
||||||
dcache_c_q.io.enq.bits := Mux(spike.io.dcache.c.voluntary,
|
dcacheEdge.Release(
|
||||||
dcacheEdge.Release(
|
|
||||||
fromSource = spike.io.dcache.c.sourceid,
|
|
||||||
toAddress = spike.io.dcache.c.address,
|
|
||||||
lgSize = blockBits.U,
|
|
||||||
shrinkPermissions = spike.io.dcache.c.param,
|
|
||||||
data = spike.io.dcache.c.data.asUInt)._2,
|
|
||||||
Mux(spike.io.dcache.c.has_data,
|
|
||||||
dcacheEdge.ProbeAck(
|
|
||||||
fromSource = spike.io.dcache.c.sourceid,
|
fromSource = spike.io.dcache.c.sourceid,
|
||||||
toAddress = spike.io.dcache.c.address,
|
toAddress = spike.io.dcache.c.address,
|
||||||
lgSize = blockBits.U,
|
lgSize = blockBits.U,
|
||||||
reportPermissions = spike.io.dcache.c.param,
|
shrinkPermissions = spike.io.dcache.c.param,
|
||||||
data = spike.io.dcache.c.data.asUInt),
|
data = spike.io.dcache.c.data.asUInt)._2,
|
||||||
dcacheEdge.ProbeAck(
|
Mux(spike.io.dcache.c.has_data,
|
||||||
fromSource = spike.io.dcache.c.sourceid,
|
dcacheEdge.ProbeAck(
|
||||||
toAddress = spike.io.dcache.c.address,
|
fromSource = spike.io.dcache.c.sourceid,
|
||||||
lgSize = blockBits.U,
|
toAddress = spike.io.dcache.c.address,
|
||||||
reportPermissions = spike.io.dcache.c.param)
|
lgSize = blockBits.U,
|
||||||
))
|
reportPermissions = spike.io.dcache.c.param,
|
||||||
|
data = spike.io.dcache.c.data.asUInt),
|
||||||
|
dcacheEdge.ProbeAck(
|
||||||
|
fromSource = spike.io.dcache.c.sourceid,
|
||||||
|
toAddress = spike.io.dcache.c.address,
|
||||||
|
lgSize = blockBits.U,
|
||||||
|
reportPermissions = spike.io.dcache.c.param)
|
||||||
|
))
|
||||||
|
} else {
|
||||||
|
dcache_tl.c.bits := DontCare
|
||||||
|
}
|
||||||
|
|
||||||
val has_data = dcacheEdge.hasData(dcache_tl.d.bits)
|
val has_data = dcacheEdge.hasData(dcache_tl.d.bits)
|
||||||
val should_finish = dcacheEdge.isRequest(dcache_tl.d.bits)
|
val should_finish = dcacheEdge.isRequest(dcache_tl.d.bits)
|
||||||
@@ -376,12 +430,10 @@ class SpikeTileModuleImp(outer: SpikeTile) extends BaseTileModuleImp(outer) {
|
|||||||
dcache_tl.e.valid := dcache_tl.d.valid && should_finish
|
dcache_tl.e.valid := dcache_tl.d.valid && should_finish
|
||||||
dcache_tl.e.bits := dcacheEdge.GrantAck(dcache_tl.d.bits)
|
dcache_tl.e.bits := dcacheEdge.GrantAck(dcache_tl.d.bits)
|
||||||
|
|
||||||
val mmio_a_q = Module(new Queue(new TLBundleA(mmioEdge.bundle), 1, flow=true, pipe=true))
|
spike.io.mmio.a.ready := mmio_tl.a.ready
|
||||||
spike.io.mmio.a.ready := mmio_a_q.io.enq.ready && mmio_a_q.io.count === 0.U
|
mmio_tl.a.valid := spike.io.mmio.a.valid
|
||||||
mmio_tl.a <> mmio_a_q.io.deq
|
val log_size = (0 until 4).map { i => Mux(spike.io.mmio.a.size === (1 << i).U, i.U, 0.U) }.reduce(_|_)
|
||||||
mmio_a_q.io.enq.valid := spike.io.mmio.a.valid
|
mmio_tl.a.bits := Mux(spike.io.mmio.a.store,
|
||||||
val log_size = MuxCase(0.U, (0 until 3).map { i => (spike.io.mmio.a.size === (1 << i).U) -> i.U })
|
|
||||||
mmio_a_q.io.enq.bits := Mux(spike.io.mmio.a.store,
|
|
||||||
mmioEdge.Put(0.U, spike.io.mmio.a.address, log_size, spike.io.mmio.a.data)._2,
|
mmioEdge.Put(0.U, spike.io.mmio.a.address, log_size, spike.io.mmio.a.data)._2,
|
||||||
mmioEdge.Get(0.U, spike.io.mmio.a.address, log_size)._2)
|
mmioEdge.Get(0.U, spike.io.mmio.a.address, log_size)._2)
|
||||||
|
|
||||||
@@ -389,9 +441,33 @@ class SpikeTileModuleImp(outer: SpikeTile) extends BaseTileModuleImp(outer) {
|
|||||||
spike.io.mmio.d.valid := mmio_tl.d.valid
|
spike.io.mmio.d.valid := mmio_tl.d.valid
|
||||||
spike.io.mmio.d.data := mmio_tl.d.bits.data
|
spike.io.mmio.d.data := mmio_tl.d.bits.data
|
||||||
|
|
||||||
|
spike.io.tcm := DontCare
|
||||||
|
spike.io.tcm.a.valid := false.B
|
||||||
|
spike.io.tcm.d.ready := true.B
|
||||||
|
outer.tcmNode.map { tcmNode =>
|
||||||
|
val (tcm_tl, tcmEdge) = tcmNode.in(0)
|
||||||
|
val debug_tcm_tl = WireInit(tcm_tl)
|
||||||
|
dontTouch(debug_tcm_tl)
|
||||||
|
tcm_tl.a.ready := true.B
|
||||||
|
spike.io.tcm.a.valid := tcm_tl.a.valid
|
||||||
|
spike.io.tcm.a.address := tcm_tl.a.bits.address
|
||||||
|
spike.io.tcm.a.data := tcm_tl.a.bits.data
|
||||||
|
spike.io.tcm.a.mask := tcm_tl.a.bits.mask
|
||||||
|
spike.io.tcm.a.opcode := tcm_tl.a.bits.opcode
|
||||||
|
spike.io.tcm.a.size := tcm_tl.a.bits.size
|
||||||
|
|
||||||
|
spike.io.tcm.d.ready := tcm_tl.d.ready
|
||||||
|
tcm_tl.d.bits := tcmEdge.AccessAck(RegNext(tcm_tl.a.bits))
|
||||||
|
when (RegNext(tcm_tl.a.bits.opcode === TLMessages.Get)) {
|
||||||
|
tcm_tl.d.bits.opcode := TLMessages.AccessAckData
|
||||||
|
}
|
||||||
|
tcm_tl.d.valid := spike.io.tcm.d.valid
|
||||||
|
tcm_tl.d.bits.data := spike.io.tcm.d.data
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class WithNSpikeCores(n: Int = 1, overrideIdOffset: Option[Int] = None) extends Config((site, here, up) => {
|
class WithNSpikeCores(n: Int = 1, tileParams: SpikeTileParams = SpikeTileParams(),
|
||||||
|
overrideIdOffset: Option[Int] = None) extends Config((site, here, up) => {
|
||||||
case TilesLocated(InSubsystem) => {
|
case TilesLocated(InSubsystem) => {
|
||||||
// Calculate the next available hart ID (since hart ID cannot be duplicated)
|
// Calculate the next available hart ID (since hart ID cannot be duplicated)
|
||||||
val prev = up(TilesLocated(InSubsystem), site)
|
val prev = up(TilesLocated(InSubsystem), site)
|
||||||
@@ -399,8 +475,21 @@ class WithNSpikeCores(n: Int = 1, overrideIdOffset: Option[Int] = None) extends
|
|||||||
// Create TileAttachParams for every core to be instantiated
|
// Create TileAttachParams for every core to be instantiated
|
||||||
(0 until n).map { i =>
|
(0 until n).map { i =>
|
||||||
SpikeTileAttachParams(
|
SpikeTileAttachParams(
|
||||||
tileParams = SpikeTileParams(hartId = i + idOffset)
|
tileParams = tileParams.copy(hartId = i + idOffset)
|
||||||
)
|
)
|
||||||
} ++ prev
|
} ++ prev
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
|
class WithSpikeTCM extends Config((site, here, up) => {
|
||||||
|
case TilesLocated(InSubsystem) => {
|
||||||
|
val prev = up(TilesLocated(InSubsystem))
|
||||||
|
require(prev.size == 1)
|
||||||
|
val spike = prev(0).asInstanceOf[SpikeTileAttachParams]
|
||||||
|
Seq(spike.copy(tileParams = spike.tileParams.copy(
|
||||||
|
tcmParams = Some(up(ExtMem).get.master)
|
||||||
|
)))
|
||||||
|
}
|
||||||
|
case ExtMem => None
|
||||||
|
case BankedL2Key => up(BankedL2Key).copy(nBanks = 0)
|
||||||
|
})
|
||||||
|
|||||||
@@ -9,9 +9,10 @@ import chisel3._
|
|||||||
import chisel3.internal.sourceinfo.{SourceInfo}
|
import chisel3.internal.sourceinfo.{SourceInfo}
|
||||||
|
|
||||||
import freechips.rocketchip.prci._
|
import freechips.rocketchip.prci._
|
||||||
import freechips.rocketchip.config.{Field, Parameters}
|
import org.chipsalliance.cde.config.{Field, Parameters}
|
||||||
import freechips.rocketchip.devices.tilelink._
|
import freechips.rocketchip.devices.tilelink._
|
||||||
import freechips.rocketchip.devices.debug.{HasPeripheryDebug, HasPeripheryDebugModuleImp, ExportDebug, DebugModuleKey}
|
import freechips.rocketchip.devices.debug.{HasPeripheryDebug, ExportDebug, DebugModuleKey}
|
||||||
|
import sifive.blocks.devices.uart.{HasPeripheryUART, PeripheryUARTKey}
|
||||||
import freechips.rocketchip.diplomacy._
|
import freechips.rocketchip.diplomacy._
|
||||||
import freechips.rocketchip.tile._
|
import freechips.rocketchip.tile._
|
||||||
import freechips.rocketchip.tilelink._
|
import freechips.rocketchip.tilelink._
|
||||||
@@ -45,9 +46,35 @@ trait CanHaveHTIF { this: BaseSubsystem =>
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// This trait adds the "chosen" node to DTS, which
|
||||||
|
// can be used to pass information to OS about the earlycon
|
||||||
|
case object ChosenInDTS extends Field[Boolean](true)
|
||||||
|
trait CanHaveChosenInDTS { this: BaseSubsystem =>
|
||||||
|
if (p(ChosenInDTS)) {
|
||||||
|
this match {
|
||||||
|
case t: HasPeripheryUART if (!p(PeripheryUARTKey).isEmpty) => {
|
||||||
|
val chosen = new Device {
|
||||||
|
def describe(resources: ResourceBindings): Description = {
|
||||||
|
val stdout = resources("stdout").map(_.value)
|
||||||
|
Description("chosen", resources("uart").headOption.map { case Binding(_, value) =>
|
||||||
|
"stdout-path" -> Seq(value)
|
||||||
|
}.toMap)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ResourceBinding {
|
||||||
|
t.uarts.foreach(u => Resource(chosen, "uart").bind(ResourceAlias(u.device.label)))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
case _ =>
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
class ChipyardSubsystem(implicit p: Parameters) extends BaseSubsystem
|
class ChipyardSubsystem(implicit p: Parameters) extends BaseSubsystem
|
||||||
with HasTiles
|
with HasTiles
|
||||||
|
with HasPeripheryDebug
|
||||||
with CanHaveHTIF
|
with CanHaveHTIF
|
||||||
|
with CanHaveChosenInDTS
|
||||||
{
|
{
|
||||||
def coreMonitorBundles = tiles.map {
|
def coreMonitorBundles = tiles.map {
|
||||||
case r: RocketTile => r.module.core.rocketImpl.coreMonitorBundle
|
case r: RocketTile => r.module.core.rocketImpl.coreMonitorBundle
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ package chipyard
|
|||||||
|
|
||||||
import chisel3._
|
import chisel3._
|
||||||
|
|
||||||
import freechips.rocketchip.config.{Parameters, Field}
|
import org.chipsalliance.cde.config.{Parameters, Field}
|
||||||
import freechips.rocketchip.subsystem._
|
import freechips.rocketchip.subsystem._
|
||||||
import freechips.rocketchip.tilelink._
|
import freechips.rocketchip.tilelink._
|
||||||
import freechips.rocketchip.devices.tilelink._
|
import freechips.rocketchip.devices.tilelink._
|
||||||
@@ -31,6 +31,14 @@ class ChipyardSystem(implicit p: Parameters) extends ChipyardSubsystem
|
|||||||
|
|
||||||
val bootROM = p(BootROMLocated(location)).map { BootROM.attach(_, this, CBUS) }
|
val bootROM = p(BootROMLocated(location)).map { BootROM.attach(_, this, CBUS) }
|
||||||
val maskROMs = p(MaskROMLocated(location)).map { MaskROM.attach(_, this, CBUS) }
|
val maskROMs = p(MaskROMLocated(location)).map { MaskROM.attach(_, this, CBUS) }
|
||||||
|
|
||||||
|
// If there is no bootrom, the tile reset vector bundle will be tied to zero
|
||||||
|
if (bootROM.isEmpty) {
|
||||||
|
val fakeResetVectorSourceNode = BundleBridgeSource[UInt]()
|
||||||
|
InModuleBody { fakeResetVectorSourceNode.bundle := 0.U }
|
||||||
|
tileResetVectorNexusNode := fakeResetVectorSourceNode
|
||||||
|
}
|
||||||
|
|
||||||
override lazy val module = new ChipyardSystemModule(this)
|
override lazy val module = new ChipyardSystemModule(this)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,108 +0,0 @@
|
|||||||
package chipyard
|
|
||||||
|
|
||||||
import chisel3._
|
|
||||||
|
|
||||||
import scala.collection.mutable.{ArrayBuffer, LinkedHashMap}
|
|
||||||
import freechips.rocketchip.diplomacy.{LazyModule}
|
|
||||||
import freechips.rocketchip.config.{Field, Parameters}
|
|
||||||
import freechips.rocketchip.util.{ResetCatchAndSync}
|
|
||||||
import freechips.rocketchip.prci.{ClockBundle, ClockBundleParameters, ClockSinkParameters, ClockParameters}
|
|
||||||
|
|
||||||
import chipyard.harness.{ApplyHarnessBinders, HarnessBinders}
|
|
||||||
import chipyard.iobinders.HasIOBinders
|
|
||||||
import chipyard.clocking.{SimplePllConfiguration, ClockDividerN}
|
|
||||||
|
|
||||||
// -------------------------------
|
|
||||||
// Chipyard Test Harness
|
|
||||||
// -------------------------------
|
|
||||||
|
|
||||||
case object BuildTop extends Field[Parameters => LazyModule]((p: Parameters) => new ChipTop()(p))
|
|
||||||
case object DefaultClockFrequencyKey extends Field[Double](100.0) // MHz
|
|
||||||
|
|
||||||
trait HasHarnessSignalReferences {
|
|
||||||
implicit val p: Parameters
|
|
||||||
// clock/reset of the chiptop reference clock (can be different than the implicit harness clock/reset)
|
|
||||||
var refClockFreq: Double = p(DefaultClockFrequencyKey)
|
|
||||||
def setRefClockFreq(freqMHz: Double) = { refClockFreq = freqMHz }
|
|
||||||
def getRefClockFreq: Double = refClockFreq
|
|
||||||
def buildtopClock: Clock
|
|
||||||
def buildtopReset: Reset
|
|
||||||
def success: Bool
|
|
||||||
}
|
|
||||||
|
|
||||||
class HarnessClockInstantiator {
|
|
||||||
private val _clockMap: LinkedHashMap[String, (Double, ClockBundle)] = LinkedHashMap.empty
|
|
||||||
|
|
||||||
// request a clock bundle at a particular frequency
|
|
||||||
def requestClockBundle(name: String, freqRequested: Double): ClockBundle = {
|
|
||||||
val clockBundle = Wire(new ClockBundle(ClockBundleParameters()))
|
|
||||||
_clockMap(name) = (freqRequested, clockBundle)
|
|
||||||
clockBundle
|
|
||||||
}
|
|
||||||
|
|
||||||
// connect all clock wires specified to a divider only PLL
|
|
||||||
def instantiateHarnessDividerPLL(refClock: ClockBundle): Unit = {
|
|
||||||
val sinks = _clockMap.map({ case (name, (freq, bundle)) =>
|
|
||||||
ClockSinkParameters(take=Some(ClockParameters(freqMHz=freq / (1000 * 1000))), name=Some(name))
|
|
||||||
}).toSeq
|
|
||||||
|
|
||||||
val pllConfig = new SimplePllConfiguration("harnessDividerOnlyClockGenerator", sinks)
|
|
||||||
pllConfig.emitSummaries()
|
|
||||||
|
|
||||||
val dividedClocks = LinkedHashMap[Int, Clock]()
|
|
||||||
def instantiateDivider(div: Int): Clock = {
|
|
||||||
val divider = Module(new ClockDividerN(div))
|
|
||||||
divider.suggestName(s"ClockDivideBy${div}")
|
|
||||||
divider.io.clk_in := refClock.clock
|
|
||||||
dividedClocks(div) = divider.io.clk_out
|
|
||||||
divider.io.clk_out
|
|
||||||
}
|
|
||||||
|
|
||||||
// connect wires to clock source
|
|
||||||
for (sinkParams <- sinks) {
|
|
||||||
// bypass the reference freq. (don't create a divider + reset sync)
|
|
||||||
val (divClock, divReset) = if (sinkParams.take.get.freqMHz != pllConfig.referenceFreqMHz) {
|
|
||||||
val div = pllConfig.sinkDividerMap(sinkParams)
|
|
||||||
val divClock = dividedClocks.getOrElse(div, instantiateDivider(div))
|
|
||||||
(divClock, ResetCatchAndSync(divClock, refClock.reset.asBool))
|
|
||||||
} else {
|
|
||||||
(refClock.clock, refClock.reset)
|
|
||||||
}
|
|
||||||
|
|
||||||
_clockMap(sinkParams.name.get)._2.clock := divClock
|
|
||||||
_clockMap(sinkParams.name.get)._2.reset := divReset
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
case object HarnessClockInstantiatorKey extends Field[HarnessClockInstantiator](new HarnessClockInstantiator)
|
|
||||||
|
|
||||||
class TestHarness(implicit val p: Parameters) extends Module with HasHarnessSignalReferences {
|
|
||||||
val io = IO(new Bundle {
|
|
||||||
val success = Output(Bool())
|
|
||||||
})
|
|
||||||
|
|
||||||
val buildtopClock = Wire(Clock())
|
|
||||||
val buildtopReset = Wire(Reset())
|
|
||||||
|
|
||||||
val lazyDut = LazyModule(p(BuildTop)(p)).suggestName("chiptop")
|
|
||||||
val dut = Module(lazyDut.module)
|
|
||||||
|
|
||||||
io.success := false.B
|
|
||||||
|
|
||||||
val success = io.success
|
|
||||||
|
|
||||||
lazyDut match { case d: HasIOBinders =>
|
|
||||||
ApplyHarnessBinders(this, d.lazySystem, d.portMap)
|
|
||||||
}
|
|
||||||
|
|
||||||
val refClkBundle = p(HarnessClockInstantiatorKey).requestClockBundle("buildtop_reference_clock", getRefClockFreq * (1000 * 1000))
|
|
||||||
|
|
||||||
buildtopClock := refClkBundle.clock
|
|
||||||
buildtopReset := WireInit(refClkBundle.reset)
|
|
||||||
|
|
||||||
val implicitHarnessClockBundle = Wire(new ClockBundle(ClockBundleParameters()))
|
|
||||||
implicitHarnessClockBundle.clock := clock
|
|
||||||
implicitHarnessClockBundle.reset := reset
|
|
||||||
p(HarnessClockInstantiatorKey).instantiateHarnessDividerPLL(implicitHarnessClockBundle)
|
|
||||||
}
|
|
||||||
@@ -4,7 +4,7 @@ import scala.collection.mutable.{LinkedHashSet}
|
|||||||
|
|
||||||
import freechips.rocketchip.subsystem._
|
import freechips.rocketchip.subsystem._
|
||||||
import freechips.rocketchip.tile.{XLen, TileParams}
|
import freechips.rocketchip.tile.{XLen, TileParams}
|
||||||
import freechips.rocketchip.config.{Parameters, Field, Config}
|
import org.chipsalliance.cde.config.{Parameters, Field, Config}
|
||||||
import freechips.rocketchip.system.{TestGeneration, RegressionTestSuite, RocketTestSuite}
|
import freechips.rocketchip.system.{TestGeneration, RegressionTestSuite, RocketTestSuite}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
123
generators/chipyard/src/main/scala/clocking/ClockBinders.scala
Normal file
123
generators/chipyard/src/main/scala/clocking/ClockBinders.scala
Normal file
@@ -0,0 +1,123 @@
|
|||||||
|
package chipyard.clocking
|
||||||
|
|
||||||
|
import chisel3._
|
||||||
|
import chisel3.util._
|
||||||
|
import chipyard.iobinders.{OverrideLazyIOBinder, GetSystemParameters, IOCellKey}
|
||||||
|
import freechips.rocketchip.prci._
|
||||||
|
import freechips.rocketchip.diplomacy._
|
||||||
|
import freechips.rocketchip.subsystem._
|
||||||
|
import freechips.rocketchip.tilelink._
|
||||||
|
import barstools.iocell.chisel._
|
||||||
|
|
||||||
|
class ClockWithFreq(val freqMHz: Double) extends Bundle {
|
||||||
|
val clock = Clock()
|
||||||
|
}
|
||||||
|
|
||||||
|
// This uses the FakePLL, which uses a ClockAtFreq Verilog blackbox to generate
|
||||||
|
// the requested clocks. This also adds TileLink ClockDivider and ClockSelector
|
||||||
|
// blocks, which allow memory-mapped control of clock division, and clock muxing
|
||||||
|
// between the FakePLL and the slow off-chip clock
|
||||||
|
// Note: This will not simulate properly with firesim
|
||||||
|
class WithPLLSelectorDividerClockGenerator extends OverrideLazyIOBinder({
|
||||||
|
(system: HasChipyardPRCI) => {
|
||||||
|
// Connect the implicit clock
|
||||||
|
implicit val p = GetSystemParameters(system)
|
||||||
|
val implicitClockSinkNode = ClockSinkNode(Seq(ClockSinkParameters(name = Some("implicit_clock"))))
|
||||||
|
system.connectImplicitClockSinkNode(implicitClockSinkNode)
|
||||||
|
InModuleBody {
|
||||||
|
val implicit_clock = implicitClockSinkNode.in.head._1.clock
|
||||||
|
val implicit_reset = implicitClockSinkNode.in.head._1.reset
|
||||||
|
system.asInstanceOf[BaseSubsystem].module match { case l: LazyModuleImp => {
|
||||||
|
l.clock := implicit_clock
|
||||||
|
l.reset := implicit_reset
|
||||||
|
}}
|
||||||
|
}
|
||||||
|
val tlbus = system.asInstanceOf[BaseSubsystem].locateTLBusWrapper(system.prciParams.slaveWhere)
|
||||||
|
val baseAddress = system.prciParams.baseAddress
|
||||||
|
val clockDivider = system.prci_ctrl_domain { LazyModule(new TLClockDivider (baseAddress + 0x20000, tlbus.beatBytes)) }
|
||||||
|
val clockSelector = system.prci_ctrl_domain { LazyModule(new TLClockSelector(baseAddress + 0x30000, tlbus.beatBytes)) }
|
||||||
|
val pllCtrl = system.prci_ctrl_domain { LazyModule(new FakePLLCtrl (baseAddress + 0x40000, tlbus.beatBytes)) }
|
||||||
|
|
||||||
|
tlbus.toVariableWidthSlave(Some("clock-div-ctrl")) { clockDivider.tlNode := TLBuffer() }
|
||||||
|
tlbus.toVariableWidthSlave(Some("clock-sel-ctrl")) { clockSelector.tlNode := TLBuffer() }
|
||||||
|
tlbus.toVariableWidthSlave(Some("pll-ctrl")) { pllCtrl.tlNode := TLBuffer() }
|
||||||
|
|
||||||
|
system.allClockGroupsNode := clockDivider.clockNode := clockSelector.clockNode
|
||||||
|
|
||||||
|
// Connect all other requested clocks
|
||||||
|
val slowClockSource = ClockSourceNode(Seq(ClockSourceParameters()))
|
||||||
|
val pllClockSource = ClockSourceNode(Seq(ClockSourceParameters()))
|
||||||
|
|
||||||
|
// The order of the connections to clockSelector.clockNode configures the inputs
|
||||||
|
// of the clockSelector's clockMux. Default to using the slowClockSource,
|
||||||
|
// software should enable the PLL, then switch to the pllClockSource
|
||||||
|
clockSelector.clockNode := slowClockSource
|
||||||
|
clockSelector.clockNode := pllClockSource
|
||||||
|
|
||||||
|
val pllCtrlSink = BundleBridgeSink[FakePLLCtrlBundle]()
|
||||||
|
pllCtrlSink := pllCtrl.ctrlNode
|
||||||
|
|
||||||
|
InModuleBody {
|
||||||
|
val clock_wire = Wire(Input(new ClockWithFreq(100)))
|
||||||
|
val reset_wire = Wire(Input(AsyncReset()))
|
||||||
|
val (clock_io, clockIOCell) = IOCell.generateIOFromSignal(clock_wire, "clock", p(IOCellKey))
|
||||||
|
val (reset_io, resetIOCell) = IOCell.generateIOFromSignal(reset_wire, "reset", p(IOCellKey))
|
||||||
|
|
||||||
|
slowClockSource.out.unzip._1.map { o =>
|
||||||
|
o.clock := clock_wire.clock
|
||||||
|
o.reset := reset_wire
|
||||||
|
}
|
||||||
|
|
||||||
|
// For a real chip you should replace this ClockSourceAtFreqFromPlusArg
|
||||||
|
// with a blackbox of whatever PLL is being integrated
|
||||||
|
val fake_pll = Module(new ClockSourceAtFreqFromPlusArg("pll_freq_mhz"))
|
||||||
|
fake_pll.io.power := pllCtrlSink.in(0)._1.power
|
||||||
|
fake_pll.io.gate := pllCtrlSink.in(0)._1.gate
|
||||||
|
|
||||||
|
pllClockSource.out.unzip._1.map { o =>
|
||||||
|
o.clock := fake_pll.io.clk
|
||||||
|
o.reset := reset_wire
|
||||||
|
}
|
||||||
|
|
||||||
|
(Seq(clock_io, reset_io), clockIOCell ++ resetIOCell)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
// This passes all clocks through to the TestHarness
|
||||||
|
class WithPassthroughClockGenerator extends OverrideLazyIOBinder({
|
||||||
|
(system: HasChipyardPRCI) => {
|
||||||
|
// Connect the implicit clock
|
||||||
|
implicit val p = GetSystemParameters(system)
|
||||||
|
val implicitClockSinkNode = ClockSinkNode(Seq(ClockSinkParameters(name = Some("implicit_clock"))))
|
||||||
|
system.connectImplicitClockSinkNode(implicitClockSinkNode)
|
||||||
|
InModuleBody {
|
||||||
|
val implicit_clock = implicitClockSinkNode.in.head._1.clock
|
||||||
|
val implicit_reset = implicitClockSinkNode.in.head._1.reset
|
||||||
|
system.asInstanceOf[BaseSubsystem].module match { case l: LazyModuleImp => {
|
||||||
|
l.clock := implicit_clock
|
||||||
|
l.reset := implicit_reset
|
||||||
|
}}
|
||||||
|
}
|
||||||
|
|
||||||
|
// This aggregate node should do nothing
|
||||||
|
val clockGroupAggNode = ClockGroupAggregateNode("fake")
|
||||||
|
val clockGroupsSourceNode = ClockGroupSourceNode(Seq(ClockGroupSourceParameters()))
|
||||||
|
system.allClockGroupsNode := clockGroupAggNode := clockGroupsSourceNode
|
||||||
|
|
||||||
|
InModuleBody {
|
||||||
|
val reset_io = IO(Input(AsyncReset()))
|
||||||
|
require(clockGroupAggNode.out.size == 1)
|
||||||
|
val (bundle, edge) = clockGroupAggNode.out(0)
|
||||||
|
|
||||||
|
val clock_ios = (bundle.member.data zip edge.sink.members).map { case (b, m) =>
|
||||||
|
val freq = m.take.get.freqMHz
|
||||||
|
val clock_io = IO(Input(new ClockWithFreq(freq))).suggestName(s"clock_${m.name.get}")
|
||||||
|
b.clock := clock_io.clock
|
||||||
|
b.reset := reset_io
|
||||||
|
clock_io
|
||||||
|
}.toSeq
|
||||||
|
((clock_ios :+ reset_io), Nil)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
@@ -4,7 +4,7 @@ import chisel3._
|
|||||||
import chisel3.util._
|
import chisel3.util._
|
||||||
import chisel3.experimental.{Analog, IO}
|
import chisel3.experimental.{Analog, IO}
|
||||||
|
|
||||||
import freechips.rocketchip.config._
|
import org.chipsalliance.cde.config._
|
||||||
import freechips.rocketchip.subsystem._
|
import freechips.rocketchip.subsystem._
|
||||||
import freechips.rocketchip.diplomacy._
|
import freechips.rocketchip.diplomacy._
|
||||||
import freechips.rocketchip.prci._
|
import freechips.rocketchip.prci._
|
||||||
|
|||||||
@@ -2,7 +2,7 @@ package chipyard.clocking
|
|||||||
|
|
||||||
import chisel3._
|
import chisel3._
|
||||||
|
|
||||||
import freechips.rocketchip.config.{Parameters, Config, Field}
|
import org.chipsalliance.cde.config.{Parameters, Config, Field}
|
||||||
import freechips.rocketchip.diplomacy._
|
import freechips.rocketchip.diplomacy._
|
||||||
import freechips.rocketchip.prci._
|
import freechips.rocketchip.prci._
|
||||||
|
|
||||||
|
|||||||
@@ -2,7 +2,7 @@ package chipyard.clocking
|
|||||||
|
|
||||||
import chisel3._
|
import chisel3._
|
||||||
|
|
||||||
import freechips.rocketchip.config.{Parameters}
|
import org.chipsalliance.cde.config.{Parameters}
|
||||||
import freechips.rocketchip.diplomacy._
|
import freechips.rocketchip.diplomacy._
|
||||||
import freechips.rocketchip.prci._
|
import freechips.rocketchip.prci._
|
||||||
import freechips.rocketchip.util.ElaborationArtefacts
|
import freechips.rocketchip.util.ElaborationArtefacts
|
||||||
@@ -92,57 +92,3 @@ class SimplePllConfiguration(
|
|||||||
def referenceSinkParams(): ClockSinkParameters = sinkDividerMap.find(_._2 == 1).get._1
|
def referenceSinkParams(): ClockSinkParameters = sinkDividerMap.find(_._2 == 1).get._1
|
||||||
}
|
}
|
||||||
|
|
||||||
case class DividerOnlyClockGeneratorNode(pllName: String)(implicit valName: ValName)
|
|
||||||
extends MixedNexusNode(ClockImp, ClockGroupImp)(
|
|
||||||
dFn = { _ => ClockGroupSourceParameters() },
|
|
||||||
uFn = { u =>
|
|
||||||
require(u.size == 1)
|
|
||||||
require(!u.head.members.contains(None),
|
|
||||||
"All output clocks in group must set their take parameters. Use a ClockGroupDealiaser")
|
|
||||||
ClockSinkParameters(
|
|
||||||
name = Some(s"${pllName}_reference_input"),
|
|
||||||
take = Some(ClockParameters(new SimplePllConfiguration(pllName, u.head.members).referenceFreqMHz))) }
|
|
||||||
)
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Generates a digital-divider-only PLL model that verilator can simulate.
|
|
||||||
* Inspects all take-specified frequencies in the output ClockGroup, calculates a
|
|
||||||
* fast reference clock (roughly LCM(requested frequencies)) which is passed up the
|
|
||||||
* diplomatic graph, and then generates dividers for each unique requested
|
|
||||||
* frequency.
|
|
||||||
*
|
|
||||||
* Output resets are not synchronized to generated clocks and should be
|
|
||||||
* synchronized by the user in a manner they see fit.
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
class DividerOnlyClockGenerator(pllName: String)(implicit p: Parameters, valName: ValName) extends LazyModule {
|
|
||||||
val node = DividerOnlyClockGeneratorNode(pllName)
|
|
||||||
|
|
||||||
lazy val module = new Impl
|
|
||||||
class Impl extends LazyRawModuleImp(this) {
|
|
||||||
require(node.out.size == 1, "Idealized PLL expects to generate a single output clock group. Use a ClockGroupAggregator")
|
|
||||||
val (refClock, ClockEdgeParameters(_, refSinkParam, _, _)) = node.in.head
|
|
||||||
val (outClocks, ClockGroupEdgeParameters(_, outSinkParams, _, _)) = node.out.head
|
|
||||||
|
|
||||||
val referenceFreq = refSinkParam.take.get.freqMHz
|
|
||||||
val pllConfig = new SimplePllConfiguration(pllName, outSinkParams.members)
|
|
||||||
pllConfig.emitSummaries()
|
|
||||||
|
|
||||||
val dividedClocks = mutable.HashMap[Int, Clock]()
|
|
||||||
def instantiateDivider(div: Int): Clock = {
|
|
||||||
val divider = Module(new ClockDividerN(div))
|
|
||||||
divider.suggestName(s"ClockDivideBy${div}")
|
|
||||||
divider.io.clk_in := refClock.clock
|
|
||||||
dividedClocks(div) = divider.io.clk_out
|
|
||||||
divider.io.clk_out
|
|
||||||
}
|
|
||||||
|
|
||||||
for (((sinkBName, sinkB), sinkP) <- outClocks.member.elements.zip(outSinkParams.members)) {
|
|
||||||
val div = pllConfig.sinkDividerMap(sinkP)
|
|
||||||
sinkB.clock := dividedClocks.getOrElse(div, instantiateDivider(div))
|
|
||||||
// Reset handling and synchronization is expected to be handled by a downstream node
|
|
||||||
sinkB.reset := refClock.reset
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|||||||
36
generators/chipyard/src/main/scala/clocking/FakePLL.scala
Normal file
36
generators/chipyard/src/main/scala/clocking/FakePLL.scala
Normal file
@@ -0,0 +1,36 @@
|
|||||||
|
package chipyard.clocking
|
||||||
|
|
||||||
|
import chisel3._
|
||||||
|
import chisel3.util._
|
||||||
|
import org.chipsalliance.cde.config.Parameters
|
||||||
|
import freechips.rocketchip.diplomacy._
|
||||||
|
import freechips.rocketchip.tilelink._
|
||||||
|
import freechips.rocketchip.devices.tilelink._
|
||||||
|
import freechips.rocketchip.regmapper._
|
||||||
|
import freechips.rocketchip.util._
|
||||||
|
|
||||||
|
class FakePLLCtrlBundle extends Bundle {
|
||||||
|
val gate = Bool()
|
||||||
|
val power = Bool()
|
||||||
|
}
|
||||||
|
|
||||||
|
class FakePLLCtrl(address: BigInt, beatBytes: Int)(implicit p: Parameters) extends LazyModule
|
||||||
|
{
|
||||||
|
val device = new SimpleDevice(s"pll", Nil)
|
||||||
|
val tlNode = TLRegisterNode(Seq(AddressSet(address, 4096-1)), device, "reg/control", beatBytes=beatBytes)
|
||||||
|
val ctrlNode = BundleBridgeSource(() => Output(new FakePLLCtrlBundle))
|
||||||
|
lazy val module = new LazyModuleImp(this) {
|
||||||
|
// This PLL only has 2 address, the gate and power
|
||||||
|
// Both should be set to turn on the PLL
|
||||||
|
// TODO: Should these be reset by the top level reset pin?
|
||||||
|
val gate_reg = Module(new AsyncResetRegVec(w=1, init=0))
|
||||||
|
val power_reg = Module(new AsyncResetRegVec(w=1, init=0))
|
||||||
|
|
||||||
|
ctrlNode.out(0)._1.gate := gate_reg.io.q
|
||||||
|
ctrlNode.out(0)._1.power := power_reg.io.q
|
||||||
|
tlNode.regmap(
|
||||||
|
0 -> Seq(RegField.rwReg(1, gate_reg.io)),
|
||||||
|
4 -> Seq(RegField.rwReg(1, power_reg.io))
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -4,7 +4,7 @@ import chisel3._
|
|||||||
|
|
||||||
import scala.collection.mutable.{ArrayBuffer}
|
import scala.collection.mutable.{ArrayBuffer}
|
||||||
|
|
||||||
import freechips.rocketchip.config.{Parameters, Field, Config}
|
import org.chipsalliance.cde.config.{Parameters, Field, Config}
|
||||||
import freechips.rocketchip.diplomacy._
|
import freechips.rocketchip.diplomacy._
|
||||||
import freechips.rocketchip.tilelink._
|
import freechips.rocketchip.tilelink._
|
||||||
import freechips.rocketchip.devices.tilelink._
|
import freechips.rocketchip.devices.tilelink._
|
||||||
@@ -15,12 +15,13 @@ import freechips.rocketchip.tile._
|
|||||||
import freechips.rocketchip.prci._
|
import freechips.rocketchip.prci._
|
||||||
|
|
||||||
import testchipip.{TLTileResetCtrl}
|
import testchipip.{TLTileResetCtrl}
|
||||||
import chipyard.{DefaultClockFrequencyKey}
|
import chipyard.harness.{DefaultClockFrequencyKey}
|
||||||
|
|
||||||
case class ChipyardPRCIControlParams(
|
case class ChipyardPRCIControlParams(
|
||||||
slaveWhere: TLBusWrapperLocation = CBUS,
|
slaveWhere: TLBusWrapperLocation = CBUS,
|
||||||
baseAddress: BigInt = 0x100000,
|
baseAddress: BigInt = 0x100000,
|
||||||
enableTileClockGating: Boolean = true
|
enableTileClockGating: Boolean = true,
|
||||||
|
enableTileResetSetting: Boolean = true
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
@@ -72,12 +73,13 @@ trait HasChipyardPRCI { this: BaseSubsystem with InstantiatesTiles =>
|
|||||||
val frequencySpecifier = ClockGroupFrequencySpecifier(p(ClockFrequencyAssignersKey), p(DefaultClockFrequencyKey))
|
val frequencySpecifier = ClockGroupFrequencySpecifier(p(ClockFrequencyAssignersKey), p(DefaultClockFrequencyKey))
|
||||||
val clockGroupCombiner = ClockGroupCombiner()
|
val clockGroupCombiner = ClockGroupCombiner()
|
||||||
val resetSynchronizer = ClockGroupResetSynchronizer()
|
val resetSynchronizer = ClockGroupResetSynchronizer()
|
||||||
val tileClockGater = prci_ctrl_domain {
|
val tileClockGater = if (prciParams.enableTileClockGating) { prci_ctrl_domain {
|
||||||
TileClockGater(prciParams.baseAddress + 0x00000, tlbus, prciParams.enableTileClockGating)
|
TileClockGater(prciParams.baseAddress + 0x00000, tlbus)
|
||||||
}
|
} } else { ClockGroupEphemeralNode() }
|
||||||
val tileResetSetter = prci_ctrl_domain {
|
val tileResetSetter = if (prciParams.enableTileResetSetting) { prci_ctrl_domain {
|
||||||
TileResetSetter(prciParams.baseAddress + 0x10000, tlbus, tile_prci_domains.map(_.tile_reset_domain.clockNode.portParams(0).name.get), Nil)
|
TileResetSetter(prciParams.baseAddress + 0x10000, tlbus, tile_prci_domains.map(_.tile_reset_domain.clockNode.portParams(0).name.get), Nil)
|
||||||
}
|
} } else { ClockGroupEphemeralNode() }
|
||||||
|
|
||||||
(aggregator
|
(aggregator
|
||||||
:= frequencySpecifier
|
:= frequencySpecifier
|
||||||
:= clockGroupCombiner
|
:= clockGroupCombiner
|
||||||
|
|||||||
@@ -0,0 +1,56 @@
|
|||||||
|
package chipyard.clocking
|
||||||
|
|
||||||
|
import chisel3._
|
||||||
|
|
||||||
|
import org.chipsalliance.cde.config.Parameters
|
||||||
|
import freechips.rocketchip.diplomacy._
|
||||||
|
import freechips.rocketchip.tilelink._
|
||||||
|
import freechips.rocketchip.devices.tilelink._
|
||||||
|
import freechips.rocketchip.regmapper._
|
||||||
|
import freechips.rocketchip.util._
|
||||||
|
import freechips.rocketchip.prci._
|
||||||
|
import freechips.rocketchip.util.ElaborationArtefacts
|
||||||
|
|
||||||
|
import testchipip._
|
||||||
|
|
||||||
|
// This module adds a TileLink memory-mapped clock divider to the clock graph
|
||||||
|
// The output clock/reset pairs from this module should be synchronized later
|
||||||
|
class TLClockDivider(address: BigInt, beatBytes: Int, divBits: Int = 8)(implicit p: Parameters) extends LazyModule {
|
||||||
|
val device = new SimpleDevice(s"clk-div-ctrl", Nil)
|
||||||
|
val clockNode = ClockGroupIdentityNode()
|
||||||
|
val tlNode = TLRegisterNode(Seq(AddressSet(address, 4096-1)), device, "reg/control", beatBytes=beatBytes)
|
||||||
|
|
||||||
|
lazy val module = new LazyModuleImp(this) {
|
||||||
|
require (clockNode.out.size == 1)
|
||||||
|
val sources = clockNode.in.head._1.member.data.toSeq
|
||||||
|
val sinks = clockNode.out.head._1.member.elements.toSeq
|
||||||
|
require (sources.size == sinks.size)
|
||||||
|
val nSinks = sinks.size
|
||||||
|
|
||||||
|
val regs = (0 until nSinks) .map { i =>
|
||||||
|
val sinkName = sinks(i)._1
|
||||||
|
val asyncReset = sources(i).reset
|
||||||
|
val reg = withReset (asyncReset) {
|
||||||
|
Module(new AsyncResetRegVec(w=divBits, init=0))
|
||||||
|
}
|
||||||
|
println(s"${(address+i*4).toString(16)}: Clock domain $sinkName divider")
|
||||||
|
sinks(i)._2.clock := withClockAndReset(sources(i).clock, asyncReset) {
|
||||||
|
val divider = Module(new testchipip.ClockDivideOrPass(divBits, depth = 3, genClockGate = p(ClockGateImpl)))
|
||||||
|
divider.io.divisor := reg.io.q
|
||||||
|
divider.io.resetAsync := ResetStretcher(sources(i).clock, asyncReset, 20).asAsyncReset
|
||||||
|
divider.io.clockOut
|
||||||
|
}
|
||||||
|
|
||||||
|
// Note this is not synchronized to the output clock, which takes time to appear
|
||||||
|
// so this is still asyncreset
|
||||||
|
// Stretch the reset for 40 cycles, to give enough time to reset any downstream
|
||||||
|
// digital logic
|
||||||
|
sinks(i)._2.reset := ResetStretcher(sources(i).clock, asyncReset, 40).asAsyncReset
|
||||||
|
reg
|
||||||
|
}
|
||||||
|
|
||||||
|
tlNode.regmap((0 until nSinks).map { i =>
|
||||||
|
i * 4 -> Seq(RegField.rwReg(divBits, regs(i).io))
|
||||||
|
}: _*)
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,73 @@
|
|||||||
|
package chipyard.clocking
|
||||||
|
|
||||||
|
import chisel3._
|
||||||
|
import chisel3.util._
|
||||||
|
import org.chipsalliance.cde.config.Parameters
|
||||||
|
import freechips.rocketchip.diplomacy._
|
||||||
|
import freechips.rocketchip.tilelink._
|
||||||
|
import freechips.rocketchip.devices.tilelink._
|
||||||
|
import freechips.rocketchip.regmapper._
|
||||||
|
import freechips.rocketchip.util._
|
||||||
|
import freechips.rocketchip.prci._
|
||||||
|
import freechips.rocketchip.util.ElaborationArtefacts
|
||||||
|
|
||||||
|
import testchipip._
|
||||||
|
|
||||||
|
object ResetStretcher {
|
||||||
|
def apply(clock: Clock, reset: Reset, cycles: Int): Reset = {
|
||||||
|
withClockAndReset(clock, reset) {
|
||||||
|
val n = log2Ceil(cycles)
|
||||||
|
val count = Module(new AsyncResetRegVec(w=n, init=0))
|
||||||
|
val resetout = Module(new AsyncResetRegVec(w=1, init=1))
|
||||||
|
count.io.en := resetout.io.q
|
||||||
|
count.io.d := count.io.q + 1.U
|
||||||
|
resetout.io.en := resetout.io.q
|
||||||
|
resetout.io.d := count.io.q < (cycles-1).U
|
||||||
|
|
||||||
|
resetout.io.q.asBool
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
case class ClockSelNode()(implicit valName: ValName)
|
||||||
|
extends MixedNexusNode(ClockImp, ClockGroupImp)(
|
||||||
|
dFn = { d => ClockGroupSourceParameters() },
|
||||||
|
uFn = { u => ClockSinkParameters() }
|
||||||
|
)
|
||||||
|
|
||||||
|
// This module adds a TileLink memory-mapped clock mux for each downstream clock domain
|
||||||
|
// in the clock graph. The output clock/reset should be synchronized downstream
|
||||||
|
class TLClockSelector(address: BigInt, beatBytes: Int)(implicit p: Parameters) extends LazyModule {
|
||||||
|
val device = new SimpleDevice("clk-sel-ctrl", Nil)
|
||||||
|
val tlNode = TLRegisterNode(Seq(AddressSet(address, 4096-1)), device, "reg/control", beatBytes=beatBytes)
|
||||||
|
|
||||||
|
val clockNode = ClockSelNode()
|
||||||
|
|
||||||
|
lazy val module = new LazyModuleImp(this) {
|
||||||
|
val asyncReset = clockNode.in.map(_._1).map(_.reset).toSeq(0)
|
||||||
|
val clocks = clockNode.in.map(_._1).map(_.clock)
|
||||||
|
val (outClocks, _) = clockNode.out.head
|
||||||
|
val (sinkNames, sinks) = outClocks.member.elements.toSeq.unzip
|
||||||
|
|
||||||
|
val regs = (0 until sinks.size).map { i =>
|
||||||
|
val sinkName = sinkNames(i)
|
||||||
|
val sel = Wire(UInt(log2Ceil(clocks.size).W))
|
||||||
|
val reg = withReset(asyncReset) { Module(new AsyncResetRegVec(w=log2Ceil(clocks.size), init=0)) }
|
||||||
|
sel := reg.io.q
|
||||||
|
println(s"${(address+i*4).toString(16)}: Clock domain $sinkName clock mux")
|
||||||
|
|
||||||
|
val mux = testchipip.ClockMutexMux(clocks).suggestName(s"${sinkName}_clkmux")
|
||||||
|
mux.io.sel := sel
|
||||||
|
mux.io.resetAsync := asyncReset.asAsyncReset
|
||||||
|
sinks(i).clock := mux.io.clockOut
|
||||||
|
// Stretch the reset for 20 cycles, to give time to reset any downstream digital logic
|
||||||
|
sinks(i).reset := ResetStretcher(clocks(0), asyncReset, 20).asAsyncReset
|
||||||
|
|
||||||
|
reg
|
||||||
|
}
|
||||||
|
tlNode.regmap((0 until sinks.size).map { i =>
|
||||||
|
i * 4 -> Seq(RegField.rwReg(log2Ceil(clocks.size), regs(i).io))
|
||||||
|
}: _*)
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -4,7 +4,7 @@ import chisel3._
|
|||||||
import chisel3.util._
|
import chisel3.util._
|
||||||
import chisel3.experimental.{Analog, IO}
|
import chisel3.experimental.{Analog, IO}
|
||||||
|
|
||||||
import freechips.rocketchip.config._
|
import org.chipsalliance.cde.config._
|
||||||
import freechips.rocketchip.subsystem._
|
import freechips.rocketchip.subsystem._
|
||||||
import freechips.rocketchip.diplomacy._
|
import freechips.rocketchip.diplomacy._
|
||||||
import freechips.rocketchip.prci._
|
import freechips.rocketchip.prci._
|
||||||
@@ -19,7 +19,7 @@ import freechips.rocketchip.subsystem._
|
|||||||
* flag will generate the registers, preserving the same memory map and behavior, but will not
|
* flag will generate the registers, preserving the same memory map and behavior, but will not
|
||||||
* generate any gaters
|
* generate any gaters
|
||||||
*/
|
*/
|
||||||
class TileClockGater(address: BigInt, beatBytes: Int, enable: Boolean)(implicit p: Parameters, valName: ValName) extends LazyModule
|
class TileClockGater(address: BigInt, beatBytes: Int)(implicit p: Parameters, valName: ValName) extends LazyModule
|
||||||
{
|
{
|
||||||
val device = new SimpleDevice(s"clock-gater", Nil)
|
val device = new SimpleDevice(s"clock-gater", Nil)
|
||||||
val clockNode = ClockGroupIdentityNode()
|
val clockNode = ClockGroupIdentityNode()
|
||||||
@@ -31,8 +31,8 @@ class TileClockGater(address: BigInt, beatBytes: Int, enable: Boolean)(implicit
|
|||||||
val regs = (0 until nSinks).map({i =>
|
val regs = (0 until nSinks).map({i =>
|
||||||
val sinkName = sinks(i)._1
|
val sinkName = sinks(i)._1
|
||||||
val reg = withReset(sources(i).reset) { Module(new AsyncResetRegVec(w=1, init=1)) }
|
val reg = withReset(sources(i).reset) { Module(new AsyncResetRegVec(w=1, init=1)) }
|
||||||
if (sinkName.contains("tile") && enable) {
|
if (sinkName.contains("tile")) {
|
||||||
println(s"ClockGate for ${sinkName} regmapped at ${(address+i*4).toString(16)}")
|
println(s"${(address+i*4).toString(16)}: Tile $sinkName clock gate")
|
||||||
sinks(i)._2.clock := ClockGate(sources(i).clock, reg.io.q.asBool)
|
sinks(i)._2.clock := ClockGate(sources(i).clock, reg.io.q.asBool)
|
||||||
sinks(i)._2.reset := sources(i).reset
|
sinks(i)._2.reset := sources(i).reset
|
||||||
} else {
|
} else {
|
||||||
@@ -47,8 +47,8 @@ class TileClockGater(address: BigInt, beatBytes: Int, enable: Boolean)(implicit
|
|||||||
}
|
}
|
||||||
|
|
||||||
object TileClockGater {
|
object TileClockGater {
|
||||||
def apply(address: BigInt, tlbus: TLBusWrapper, enable: Boolean)(implicit p: Parameters, v: ValName) = {
|
def apply(address: BigInt, tlbus: TLBusWrapper)(implicit p: Parameters, v: ValName) = {
|
||||||
val gater = LazyModule(new TileClockGater(address, tlbus.beatBytes, enable))
|
val gater = LazyModule(new TileClockGater(address, tlbus.beatBytes))
|
||||||
tlbus.toVariableWidthSlave(Some("clock-gater")) { gater.tlNode := TLBuffer() }
|
tlbus.toVariableWidthSlave(Some("clock-gater")) { gater.tlNode := TLBuffer() }
|
||||||
gater.clockNode
|
gater.clockNode
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ import chisel3._
|
|||||||
import chisel3.util._
|
import chisel3.util._
|
||||||
import chisel3.experimental.{Analog, IO}
|
import chisel3.experimental.{Analog, IO}
|
||||||
|
|
||||||
import freechips.rocketchip.config._
|
import org.chipsalliance.cde.config._
|
||||||
import freechips.rocketchip.subsystem._
|
import freechips.rocketchip.subsystem._
|
||||||
import freechips.rocketchip.diplomacy._
|
import freechips.rocketchip.diplomacy._
|
||||||
import freechips.rocketchip.prci._
|
import freechips.rocketchip.prci._
|
||||||
@@ -39,16 +39,16 @@ class TileResetSetter(address: BigInt, beatBytes: Int, tileNames: Seq[String], i
|
|||||||
}): _*)
|
}): _*)
|
||||||
|
|
||||||
val tileMap = tileNames.zipWithIndex.map({ case (n, i) =>
|
val tileMap = tileNames.zipWithIndex.map({ case (n, i) =>
|
||||||
n -> (tile_async_resets(i), r_tile_resets(i).io.q)
|
n -> (tile_async_resets(i), r_tile_resets(i).io.q, address + i * 4)
|
||||||
})
|
})
|
||||||
|
|
||||||
(clockNode.out zip clockNode.in).map { case ((o, _), (i, _)) =>
|
(clockNode.out zip clockNode.in).map { case ((o, _), (i, _)) =>
|
||||||
(o.member.elements zip i.member.elements).foreach { case ((name, oD), (_, iD)) =>
|
(o.member.elements zip i.member.elements).foreach { case ((name, oD), (_, iD)) =>
|
||||||
oD.clock := iD.clock
|
oD.clock := iD.clock
|
||||||
oD.reset := iD.reset
|
oD.reset := iD.reset
|
||||||
for ((n, (rIn, rOut)) <- tileMap) {
|
for ((n, (rIn, rOut, addr)) <- tileMap) {
|
||||||
if (name.contains(n)) {
|
if (name.contains(n)) {
|
||||||
println(name, n)
|
println(s"${addr.toString(16)}: Tile $name reset control")
|
||||||
// Async because the reset coming out of the AsyncResetRegVec is
|
// Async because the reset coming out of the AsyncResetRegVec is
|
||||||
// clocked to the bus this is attached to, not the clock in this
|
// clocked to the bus this is attached to, not the clock in this
|
||||||
// clock bundle. We expect a ClockGroupResetSynchronizer downstream
|
// clock bundle. We expect a ClockGroupResetSynchronizer downstream
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
package chipyard.config
|
package chipyard.config
|
||||||
|
|
||||||
import freechips.rocketchip.config.{Config}
|
import org.chipsalliance.cde.config.{Config}
|
||||||
|
|
||||||
// --------------
|
// --------------
|
||||||
// Chipyard abstract ("base") configuration
|
// Chipyard abstract ("base") configuration
|
||||||
@@ -12,17 +12,18 @@ import freechips.rocketchip.config.{Config}
|
|||||||
|
|
||||||
class AbstractConfig extends Config(
|
class AbstractConfig extends Config(
|
||||||
// The HarnessBinders control generation of hardware in the TestHarness
|
// The HarnessBinders control generation of hardware in the TestHarness
|
||||||
new chipyard.harness.WithUARTAdapter ++ // add UART adapter to display UART on stdout, if uart is present
|
new chipyard.harness.WithUARTAdapter ++ // add UART adapter to display UART on stdout, if uart is present
|
||||||
new chipyard.harness.WithBlackBoxSimMem ++ // add SimDRAM DRAM model for axi4 backing memory, if axi4 mem is enabled
|
new chipyard.harness.WithBlackBoxSimMem ++ // add SimDRAM DRAM model for axi4 backing memory, if axi4 mem is enabled
|
||||||
new chipyard.harness.WithSimSerial ++ // add external serial-adapter and RAM
|
new chipyard.harness.WithSimTSIOverSerialTL ++ // add external serial-adapter and RAM
|
||||||
new chipyard.harness.WithSimDebug ++ // add SimJTAG or SimDTM adapters if debug module is enabled
|
new chipyard.harness.WithSimDebug ++ // add SimJTAG or SimDTM adapters if debug module is enabled
|
||||||
new chipyard.harness.WithGPIOTiedOff ++ // tie-off chiptop GPIOs, if GPIOs are present
|
new chipyard.harness.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.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.WithSimAXIMMIO ++ // add SimAXIMem for axi4 mmio port, if enabled
|
||||||
new chipyard.harness.WithTieOffInterrupts ++ // tie-off interrupt ports, if present
|
new chipyard.harness.WithTieOffInterrupts ++ // tie-off interrupt ports, if present
|
||||||
new chipyard.harness.WithTieOffL2FBusAXI ++ // tie-off external AXI4 master, if present
|
new chipyard.harness.WithTieOffL2FBusAXI ++ // tie-off external AXI4 master, if present
|
||||||
new chipyard.harness.WithCustomBootPinPlusArg ++
|
new chipyard.harness.WithCustomBootPinPlusArg ++ // drive custom-boot pin with a plusarg, if custom-boot-pin is present
|
||||||
new chipyard.harness.WithClockAndResetFromHarness ++
|
new chipyard.harness.WithClockAndResetFromHarness ++ // all Clock/Reset I/O in ChipTop should be driven by harnessClockInstantiator
|
||||||
|
new chipyard.harness.WithAbsoluteFreqHarnessClockInstantiator ++ // generate clocks in harness with unsynthesizable ClockSourceAtFreqMHz
|
||||||
|
|
||||||
// The IOBinders instantiate ChipTop IOs to match desired digital IOs
|
// The IOBinders instantiate ChipTop IOs to match desired digital IOs
|
||||||
// IOCells are generated for "Chip-like" IOs, while simulation-only IOs are directly punched through
|
// IOCells are generated for "Chip-like" IOs, while simulation-only IOs are directly punched through
|
||||||
@@ -40,18 +41,24 @@ class AbstractConfig extends Config(
|
|||||||
new chipyard.iobinders.WithTraceIOPunchthrough ++
|
new chipyard.iobinders.WithTraceIOPunchthrough ++
|
||||||
new chipyard.iobinders.WithExtInterruptIOCells ++
|
new chipyard.iobinders.WithExtInterruptIOCells ++
|
||||||
new chipyard.iobinders.WithCustomBootPin ++
|
new chipyard.iobinders.WithCustomBootPin ++
|
||||||
new chipyard.iobinders.WithDividerOnlyClockGenerator ++
|
|
||||||
|
|
||||||
|
// By default, punch out IOs to the Harness
|
||||||
|
new chipyard.clocking.WithPassthroughClockGenerator ++
|
||||||
|
|
||||||
|
new testchipip.WithCustomBootPin ++ // add a custom-boot-pin to support pin-driven boot address
|
||||||
|
new testchipip.WithBootAddrReg ++ // add a boot-addr-reg for configurable boot address
|
||||||
new testchipip.WithSerialTLWidth(32) ++ // fatten the serialTL interface to improve testing performance
|
new testchipip.WithSerialTLWidth(32) ++ // fatten the serialTL interface to improve testing performance
|
||||||
new testchipip.WithDefaultSerialTL ++ // use serialized tilelink port to external serialadapter/harnessRAM
|
new testchipip.WithDefaultSerialTL ++ // use serialized tilelink port to external serialadapter/harnessRAM
|
||||||
|
new chipyard.config.WithDebugModuleAbstractDataWords(8) ++ // increase debug module data capacity
|
||||||
new chipyard.config.WithBootROM ++ // use default bootrom
|
new chipyard.config.WithBootROM ++ // use default bootrom
|
||||||
new chipyard.config.WithUART ++ // add a UART
|
new chipyard.config.WithUART ++ // add a UART
|
||||||
new chipyard.config.WithL2TLBs(1024) ++ // use L2 TLBs
|
new chipyard.config.WithL2TLBs(1024) ++ // use L2 TLBs
|
||||||
new chipyard.config.WithNoSubsystemDrivenClocks ++ // drive the subsystem diplomatic clocks from ChipTop instead of using implicit clocks
|
new chipyard.config.WithNoSubsystemDrivenClocks ++ // drive the subsystem diplomatic clocks from ChipTop instead of using implicit clocks
|
||||||
new chipyard.config.WithInheritBusFrequencyAssignments ++ // Unspecified clocks within a bus will receive the bus frequency if set
|
new chipyard.config.WithInheritBusFrequencyAssignments ++ // Unspecified clocks within a bus will receive the bus frequency if set
|
||||||
new chipyard.config.WithPeripheryBusFrequencyAsDefault ++ // Unspecified frequencies with match the pbus frequency (which is always set)
|
new chipyard.config.WithPeripheryBusFrequencyAsDefault ++ // Unspecified frequencies with match the pbus frequency (which is always set)
|
||||||
new chipyard.config.WithMemoryBusFrequency(100.0) ++ // Default 100 MHz mbus
|
new chipyard.config.WithMemoryBusFrequency(500.0) ++ // Default 500 MHz mbus
|
||||||
new chipyard.config.WithPeripheryBusFrequency(100.0) ++ // Default 100 MHz pbus
|
new chipyard.config.WithPeripheryBusFrequency(500.0) ++ // Default 500 MHz pbus
|
||||||
|
new freechips.rocketchip.subsystem.WithNMemoryChannels(2) ++ // Default 2 memory channels
|
||||||
new freechips.rocketchip.subsystem.WithClockGateModel ++ // add default EICG_wrapper clock gate model
|
new freechips.rocketchip.subsystem.WithClockGateModel ++ // add default EICG_wrapper clock gate model
|
||||||
new freechips.rocketchip.subsystem.WithJtagDTM ++ // set the debug module to expose a JTAG port
|
new freechips.rocketchip.subsystem.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)
|
||||||
@@ -60,4 +67,5 @@ class AbstractConfig extends Config(
|
|||||||
new freechips.rocketchip.subsystem.WithNExtTopInterrupts(0) ++ // no external interrupts
|
new freechips.rocketchip.subsystem.WithNExtTopInterrupts(0) ++ // no external interrupts
|
||||||
new freechips.rocketchip.subsystem.WithDontDriveBusClocksFromSBus ++ // leave the bus clocks undriven by sbus
|
new freechips.rocketchip.subsystem.WithDontDriveBusClocksFromSBus ++ // leave the bus clocks undriven by sbus
|
||||||
new freechips.rocketchip.subsystem.WithCoherentBusTopology ++ // hierarchical buses including sbus/mbus/pbus/fbus/cbus/l2
|
new freechips.rocketchip.subsystem.WithCoherentBusTopology ++ // hierarchical buses including sbus/mbus/pbus/fbus/cbus/l2
|
||||||
|
new freechips.rocketchip.subsystem.WithDTS("ucb-bar,chipyard", Nil) ++ // custom device name for DTS
|
||||||
new freechips.rocketchip.system.BaseConfig) // "base" rocketchip system
|
new freechips.rocketchip.system.BaseConfig) // "base" rocketchip system
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
package chipyard
|
package chipyard
|
||||||
|
|
||||||
import freechips.rocketchip.config.{Config}
|
import org.chipsalliance.cde.config.{Config}
|
||||||
|
|
||||||
// ---------------------
|
// ---------------------
|
||||||
// BOOM Configs
|
// BOOM Configs
|
||||||
@@ -53,3 +53,18 @@ class MediumBoomCosimConfig extends Config(
|
|||||||
new chipyard.config.WithTraceIO ++ // enable the traceio
|
new chipyard.config.WithTraceIO ++ // enable the traceio
|
||||||
new boom.common.WithNMediumBooms(1) ++
|
new boom.common.WithNMediumBooms(1) ++
|
||||||
new chipyard.config.AbstractConfig)
|
new chipyard.config.AbstractConfig)
|
||||||
|
|
||||||
|
class dmiMediumBoomConfig extends Config(
|
||||||
|
new chipyard.harness.WithSerialTLTiedOff ++ // don't attach anything to serial-tl
|
||||||
|
new chipyard.config.WithDMIDTM ++ // have debug module expose a clocked DMI port
|
||||||
|
new boom.common.WithNMediumBooms(1) ++
|
||||||
|
new chipyard.config.AbstractConfig)
|
||||||
|
|
||||||
|
class dmiMediumBoomCosimConfig extends Config(
|
||||||
|
new chipyard.harness.WithCospike ++ // attach spike-cosim
|
||||||
|
new chipyard.config.WithTraceIO ++ // enable the traceio
|
||||||
|
new chipyard.harness.WithSerialTLTiedOff ++ // don't attach anythint to serial-tl
|
||||||
|
new chipyard.config.WithDMIDTM ++ // have debug module expose a clocked DMI port
|
||||||
|
new boom.common.WithNMediumBooms(1) ++
|
||||||
|
new chipyard.config.AbstractConfig)
|
||||||
|
|
||||||
|
|||||||
@@ -2,7 +2,7 @@ package chipyard
|
|||||||
|
|
||||||
import chisel3._
|
import chisel3._
|
||||||
|
|
||||||
import freechips.rocketchip.config.{Config}
|
import org.chipsalliance.cde.config.{Config}
|
||||||
|
|
||||||
// ---------------------
|
// ---------------------
|
||||||
// CVA6 Configs
|
// CVA6 Configs
|
||||||
@@ -13,7 +13,7 @@ class CVA6Config extends Config(
|
|||||||
new chipyard.config.AbstractConfig)
|
new chipyard.config.AbstractConfig)
|
||||||
|
|
||||||
class dmiCVA6Config extends Config(
|
class dmiCVA6Config extends Config(
|
||||||
new chipyard.harness.WithSerialAdapterTiedOff ++ // Tie off the serial port, override default instantiation of SimSerial
|
new chipyard.harness.WithSerialTLTiedOff ++ // Tie off the serial-tilelink port
|
||||||
new chipyard.config.WithDMIDTM ++ // have debug module expose a clocked DMI port
|
new chipyard.config.WithDMIDTM ++ // have debug module expose a clocked DMI port
|
||||||
new cva6.WithNCVA6Cores(1) ++ // single CVA6 core
|
new cva6.WithNCVA6Cores(1) ++ // single CVA6 core
|
||||||
new chipyard.config.AbstractConfig)
|
new chipyard.config.AbstractConfig)
|
||||||
|
|||||||
38
generators/chipyard/src/main/scala/config/ChipConfigs.scala
Normal file
38
generators/chipyard/src/main/scala/config/ChipConfigs.scala
Normal file
@@ -0,0 +1,38 @@
|
|||||||
|
package chipyard
|
||||||
|
|
||||||
|
import org.chipsalliance.cde.config.{Config}
|
||||||
|
import freechips.rocketchip.diplomacy._
|
||||||
|
|
||||||
|
// A simple config demonstrating how to set up a basic chip in Chipyard
|
||||||
|
class ChipLikeQuadRocketConfig extends Config(
|
||||||
|
//==================================
|
||||||
|
// Set up TestHarness
|
||||||
|
//==================================
|
||||||
|
new chipyard.harness.WithAbsoluteFreqHarnessClockInstantiator ++ // use absolute frequencies for simulations in the harness
|
||||||
|
// NOTE: This only simulates properly in VCS
|
||||||
|
|
||||||
|
//==================================
|
||||||
|
// Set up tiles
|
||||||
|
//==================================
|
||||||
|
new freechips.rocketchip.subsystem.WithAsynchronousRocketTiles(3, 3) ++ // Add rational crossings between RocketTile and uncore
|
||||||
|
new freechips.rocketchip.subsystem.WithNBigCores(4) ++ // quad-core (4 RocketTiles)
|
||||||
|
|
||||||
|
//==================================
|
||||||
|
// Set up I/O
|
||||||
|
//==================================
|
||||||
|
new testchipip.WithSerialTLWidth(4) ++
|
||||||
|
new chipyard.harness.WithSimAXIMemOverSerialTL ++ // Attach fast SimDRAM to TestHarness
|
||||||
|
new chipyard.config.WithSerialTLBackingMemory ++ // Backing memory is over serial TL protocol
|
||||||
|
new freechips.rocketchip.subsystem.WithExtMemSize((1 << 30) * 4L) ++ // 4GB max external memory
|
||||||
|
new freechips.rocketchip.subsystem.WithNMemoryChannels(1) ++ // 1 memory channel
|
||||||
|
|
||||||
|
//==================================
|
||||||
|
// Set up clock./reset
|
||||||
|
//==================================
|
||||||
|
new chipyard.clocking.WithPLLSelectorDividerClockGenerator ++ // Use a PLL-based clock selector/divider generator structure
|
||||||
|
|
||||||
|
// Create the uncore clock group
|
||||||
|
new chipyard.clocking.WithClockGroupsCombinedByName("uncore", "implicit", "sbus", "mbus", "cbus", "system_bus", "fbus", "pbus") ++
|
||||||
|
|
||||||
|
new chipyard.config.AbstractConfig)
|
||||||
|
|
||||||
@@ -1,6 +1,6 @@
|
|||||||
package chipyard
|
package chipyard
|
||||||
|
|
||||||
import freechips.rocketchip.config.{Config}
|
import org.chipsalliance.cde.config.{Config}
|
||||||
|
|
||||||
// ---------------------
|
// ---------------------
|
||||||
// Heterogenous Configs
|
// Heterogenous Configs
|
||||||
|
|||||||
@@ -2,7 +2,7 @@ package chipyard
|
|||||||
|
|
||||||
import chisel3._
|
import chisel3._
|
||||||
|
|
||||||
import freechips.rocketchip.config.{Config}
|
import org.chipsalliance.cde.config.{Config}
|
||||||
|
|
||||||
// ---------------------
|
// ---------------------
|
||||||
// Ibex Configs
|
// Ibex Configs
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
package chipyard
|
package chipyard
|
||||||
|
|
||||||
import freechips.rocketchip.config.{Config}
|
import org.chipsalliance.cde.config.{Config}
|
||||||
import freechips.rocketchip.diplomacy.{AsynchronousCrossing}
|
import freechips.rocketchip.diplomacy.{AsynchronousCrossing}
|
||||||
|
|
||||||
// ------------------------------
|
// ------------------------------
|
||||||
@@ -9,6 +9,7 @@ import freechips.rocketchip.diplomacy.{AsynchronousCrossing}
|
|||||||
|
|
||||||
// DOC include start: FFTRocketConfig
|
// DOC include start: FFTRocketConfig
|
||||||
class FFTRocketConfig extends Config(
|
class FFTRocketConfig extends Config(
|
||||||
|
new chipyard.iobinders.WithDontTouchIOBinders(false) ++ // TODO: hack around dontTouch not working in SFC
|
||||||
new fftgenerator.WithFFTGenerator(numPoints=8, width=16, decPt=8) ++ // add 8-point mmio fft at the default addr (0x2400) with 16bit fixed-point numbers.
|
new fftgenerator.WithFFTGenerator(numPoints=8, width=16, decPt=8) ++ // add 8-point mmio fft at the default addr (0x2400) with 16bit fixed-point numbers.
|
||||||
new freechips.rocketchip.subsystem.WithNBigCores(1) ++
|
new freechips.rocketchip.subsystem.WithNBigCores(1) ++
|
||||||
new chipyard.config.AbstractConfig)
|
new chipyard.config.AbstractConfig)
|
||||||
@@ -58,6 +59,7 @@ class LargeNVDLARocketConfig extends Config(
|
|||||||
new chipyard.config.AbstractConfig)
|
new chipyard.config.AbstractConfig)
|
||||||
|
|
||||||
class ManyMMIOAcceleratorRocketConfig extends Config(
|
class ManyMMIOAcceleratorRocketConfig extends Config(
|
||||||
|
new chipyard.iobinders.WithDontTouchIOBinders(false) ++ // TODO: hack around dontTouch not working in SFC
|
||||||
new fftgenerator.WithFFTGenerator(numPoints=8, width=16, decPt=8) ++ // add 8-point mmio fft at the default addr (0x2400) with 16bit fixed-point numbers.
|
new fftgenerator.WithFFTGenerator(numPoints=8, width=16, decPt=8) ++ // add 8-point mmio fft at the default addr (0x2400) with 16bit fixed-point numbers.
|
||||||
new nvidia.blocks.dla.WithNVDLA("small") ++ // add a small NVDLA
|
new nvidia.blocks.dla.WithNVDLA("small") ++ // add a small NVDLA
|
||||||
new chipyard.example.WithStreamingPassthrough ++ // use top with tilelink-controlled streaming passthrough
|
new chipyard.example.WithStreamingPassthrough ++ // use top with tilelink-controlled streaming passthrough
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
package chipyard
|
package chipyard
|
||||||
|
|
||||||
import freechips.rocketchip.config.{Config}
|
import org.chipsalliance.cde.config.{Config}
|
||||||
import freechips.rocketchip.diplomacy.{AsynchronousCrossing}
|
import freechips.rocketchip.diplomacy.{AsynchronousCrossing}
|
||||||
import freechips.rocketchip.subsystem.{SBUS, MBUS}
|
import freechips.rocketchip.subsystem.{SBUS, MBUS}
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
package chipyard
|
package chipyard
|
||||||
|
|
||||||
import freechips.rocketchip.config.{Config}
|
import org.chipsalliance.cde.config.{Config}
|
||||||
|
|
||||||
// A empty config with no cores. Useful for testing
|
// A empty config with no cores. Useful for testing
|
||||||
class NoCoresConfig extends Config(
|
class NoCoresConfig extends Config(
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
package chipyard
|
package chipyard
|
||||||
|
|
||||||
import freechips.rocketchip.config.{Config}
|
import org.chipsalliance.cde.config.{Config}
|
||||||
import freechips.rocketchip.diplomacy.{AsynchronousCrossing}
|
import freechips.rocketchip.diplomacy.{AsynchronousCrossing}
|
||||||
|
|
||||||
// ---------------------------------------------------------
|
// ---------------------------------------------------------
|
||||||
@@ -58,7 +58,7 @@ class LBWIFRocketConfig extends Config(
|
|||||||
|
|
||||||
// DOC include start: DmiRocket
|
// DOC include start: DmiRocket
|
||||||
class dmiRocketConfig extends Config(
|
class dmiRocketConfig extends Config(
|
||||||
new chipyard.harness.WithSerialAdapterTiedOff ++ // don't attach an external SimSerial
|
new chipyard.harness.WithSerialTLTiedOff ++ // don't attach anything to serial-tl
|
||||||
new chipyard.config.WithDMIDTM ++ // have debug module expose a clocked DMI port
|
new 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)
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
package chipyard
|
package chipyard
|
||||||
|
|
||||||
import freechips.rocketchip.config.{Config}
|
import org.chipsalliance.cde.config.{Config}
|
||||||
import freechips.rocketchip.diplomacy.{AsynchronousCrossing}
|
import freechips.rocketchip.diplomacy.{AsynchronousCrossing}
|
||||||
|
|
||||||
// ------------------------------
|
// ------------------------------
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
package chipyard
|
package chipyard
|
||||||
|
|
||||||
import freechips.rocketchip.config.{Config}
|
import org.chipsalliance.cde.config.{Config}
|
||||||
import freechips.rocketchip.diplomacy.{AsynchronousCrossing}
|
import freechips.rocketchip.diplomacy.{AsynchronousCrossing}
|
||||||
|
|
||||||
// --------------
|
// --------------
|
||||||
@@ -12,6 +12,7 @@ class RocketConfig extends Config(
|
|||||||
new chipyard.config.AbstractConfig)
|
new chipyard.config.AbstractConfig)
|
||||||
|
|
||||||
class TinyRocketConfig extends Config(
|
class TinyRocketConfig extends Config(
|
||||||
|
new chipyard.iobinders.WithDontTouchIOBinders(false) ++ // TODO FIX: Don't dontTouch the ports
|
||||||
new chipyard.config.WithTLSerialLocation(
|
new chipyard.config.WithTLSerialLocation(
|
||||||
freechips.rocketchip.subsystem.FBUS,
|
freechips.rocketchip.subsystem.FBUS,
|
||||||
freechips.rocketchip.subsystem.PBUS) ++ // attach TL serial adapter to f/p busses
|
freechips.rocketchip.subsystem.PBUS) ++ // attach TL serial adapter to f/p busses
|
||||||
@@ -85,6 +86,7 @@ class MbusScratchpadRocketConfig extends Config(
|
|||||||
// DOC include end: mbusscratchpadrocket
|
// DOC include end: mbusscratchpadrocket
|
||||||
|
|
||||||
class MulticlockRocketConfig extends Config(
|
class MulticlockRocketConfig extends Config(
|
||||||
|
new freechips.rocketchip.subsystem.WithAsynchronousRocketTiles(3, 3) ++ // Add async crossings between RocketTile and uncore
|
||||||
new freechips.rocketchip.subsystem.WithNBigCores(1) ++
|
new freechips.rocketchip.subsystem.WithNBigCores(1) ++
|
||||||
// Frequency specifications
|
// Frequency specifications
|
||||||
new chipyard.config.WithTileFrequency(1600.0) ++ // Matches the maximum frequency of U540
|
new chipyard.config.WithTileFrequency(1600.0) ++ // Matches the maximum frequency of U540
|
||||||
@@ -95,7 +97,6 @@ class MulticlockRocketConfig extends Config(
|
|||||||
// Crossing specifications
|
// Crossing specifications
|
||||||
new chipyard.config.WithCbusToPbusCrossingType(AsynchronousCrossing()) ++ // Add Async crossing between PBUS and CBUS
|
new chipyard.config.WithCbusToPbusCrossingType(AsynchronousCrossing()) ++ // Add Async crossing between PBUS and CBUS
|
||||||
new chipyard.config.WithSbusToMbusCrossingType(AsynchronousCrossing()) ++ // Add Async crossings between backside of L2 and MBUS
|
new chipyard.config.WithSbusToMbusCrossingType(AsynchronousCrossing()) ++ // Add Async crossings between backside of L2 and MBUS
|
||||||
new freechips.rocketchip.subsystem.WithRationalRocketTiles ++ // Add rational crossings between RocketTile and uncore
|
|
||||||
new testchipip.WithAsynchronousSerialSlaveCrossing ++ // Add Async crossing between serial and MBUS. Its master-side is tied to the FBUS
|
new testchipip.WithAsynchronousSerialSlaveCrossing ++ // Add Async crossing between serial and MBUS. Its master-side is tied to the FBUS
|
||||||
new chipyard.config.AbstractConfig)
|
new chipyard.config.AbstractConfig)
|
||||||
|
|
||||||
@@ -124,5 +125,12 @@ class MulticlockAXIOverSerialConfig extends Config(
|
|||||||
new chipyard.config.WithSerialTLBackingMemory ++ // remove axi4 mem port in favor of SerialTL memory
|
new chipyard.config.WithSerialTLBackingMemory ++ // remove axi4 mem port in favor of SerialTL memory
|
||||||
|
|
||||||
new freechips.rocketchip.subsystem.WithNBigCores(2) ++
|
new freechips.rocketchip.subsystem.WithNBigCores(2) ++
|
||||||
|
new freechips.rocketchip.subsystem.WithNMemoryChannels(1) ++ // 1 memory channel
|
||||||
new chipyard.config.AbstractConfig)
|
new chipyard.config.AbstractConfig)
|
||||||
// DOC include end: MulticlockAXIOverSerialConfig
|
// DOC include end: MulticlockAXIOverSerialConfig
|
||||||
|
|
||||||
|
class CustomIOChipTopRocketConfig extends Config(
|
||||||
|
new chipyard.example.WithCustomChipTop ++
|
||||||
|
new chipyard.example.WithCustomIOCells ++
|
||||||
|
new freechips.rocketchip.subsystem.WithNBigCores(1) ++ // single rocket-core
|
||||||
|
new chipyard.config.AbstractConfig)
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
package chipyard
|
package chipyard
|
||||||
|
|
||||||
import freechips.rocketchip.config.{Config}
|
import org.chipsalliance.cde.config.{Config}
|
||||||
import freechips.rocketchip.diplomacy.{AsynchronousCrossing}
|
import freechips.rocketchip.diplomacy.{AsynchronousCrossing}
|
||||||
|
|
||||||
// --------------
|
// --------------
|
||||||
|
|||||||
@@ -2,7 +2,7 @@ package chipyard
|
|||||||
|
|
||||||
import chisel3._
|
import chisel3._
|
||||||
|
|
||||||
import freechips.rocketchip.config.{Config}
|
import org.chipsalliance.cde.config.{Config}
|
||||||
|
|
||||||
class Sodor1StageConfig extends Config(
|
class Sodor1StageConfig extends Config(
|
||||||
// Create a Sodor 1-stage core
|
// Create a Sodor 1-stage core
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
package chipyard
|
package chipyard
|
||||||
|
|
||||||
import freechips.rocketchip.config.{Config}
|
import org.chipsalliance.cde.config.{Config}
|
||||||
|
|
||||||
// Configs which instantiate a Spike-simulated
|
// Configs which instantiate a Spike-simulated
|
||||||
// tile that interacts with the Chipyard SoC
|
// tile that interacts with the Chipyard SoC
|
||||||
@@ -10,10 +10,47 @@ class SpikeConfig extends Config(
|
|||||||
new chipyard.WithNSpikeCores(1) ++
|
new chipyard.WithNSpikeCores(1) ++
|
||||||
new chipyard.config.AbstractConfig)
|
new chipyard.config.AbstractConfig)
|
||||||
|
|
||||||
|
class dmiSpikeConfig extends Config(
|
||||||
|
new chipyard.harness.WithSerialTLTiedOff ++ // don't attach anything to serial-tilelink
|
||||||
|
new chipyard.config.WithDMIDTM ++ // have debug module expose a clocked DMI port
|
||||||
|
new SpikeConfig)
|
||||||
|
|
||||||
// Avoids polling on the UART registers
|
// Avoids polling on the UART registers
|
||||||
class SpikeFastUARTConfig extends Config(
|
class SpikeFastUARTConfig extends Config(
|
||||||
new chipyard.WithNSpikeCores(1) ++
|
new chipyard.WithNSpikeCores(1) ++
|
||||||
new chipyard.config.WithUARTFIFOEntries(128, 128) ++
|
new chipyard.config.WithUARTFIFOEntries(128, 128) ++
|
||||||
new chipyard.config.WithMemoryBusFrequency(1) ++
|
new chipyard.config.WithMemoryBusFrequency(2) ++
|
||||||
new chipyard.config.WithPeripheryBusFrequency(1) ++
|
new chipyard.config.WithPeripheryBusFrequency(2) ++
|
||||||
|
new chipyard.config.AbstractConfig)
|
||||||
|
|
||||||
|
// Makes the UART fast, also builds no L2 and a ludicrous L1D
|
||||||
|
class SpikeUltraFastConfig extends Config(
|
||||||
|
new chipyard.WithSpikeTCM ++
|
||||||
|
new chipyard.WithNSpikeCores(1) ++
|
||||||
|
new testchipip.WithSerialPBusMem ++
|
||||||
|
new chipyard.config.WithUARTFIFOEntries(128, 128) ++
|
||||||
|
new chipyard.config.WithMemoryBusFrequency(2) ++
|
||||||
|
new chipyard.config.WithPeripheryBusFrequency(2) ++
|
||||||
|
new chipyard.config.WithBroadcastManager ++
|
||||||
|
new chipyard.config.AbstractConfig)
|
||||||
|
|
||||||
|
class dmiSpikeUltraFastConfig extends Config(
|
||||||
|
new chipyard.harness.WithSerialTLTiedOff ++ // don't attach anything to serial-tilelink
|
||||||
|
new chipyard.config.WithDMIDTM ++ // have debug module expose a clocked DMI port
|
||||||
|
new SpikeUltraFastConfig)
|
||||||
|
|
||||||
|
// Add the default firechip devices
|
||||||
|
class SpikeUltraFastDevicesConfig extends Config(
|
||||||
|
new chipyard.harness.WithSimBlockDevice ++
|
||||||
|
new chipyard.harness.WithLoopbackNIC ++
|
||||||
|
new icenet.WithIceNIC ++
|
||||||
|
new testchipip.WithBlockDevice ++
|
||||||
|
|
||||||
|
new chipyard.WithSpikeTCM ++
|
||||||
|
new chipyard.WithNSpikeCores(1) ++
|
||||||
|
new testchipip.WithSerialPBusMem ++
|
||||||
|
new chipyard.config.WithUARTFIFOEntries(128, 128) ++
|
||||||
|
new chipyard.config.WithMemoryBusFrequency(2) ++
|
||||||
|
new chipyard.config.WithPeripheryBusFrequency(2) ++
|
||||||
|
new chipyard.config.WithBroadcastManager ++
|
||||||
new chipyard.config.AbstractConfig)
|
new chipyard.config.AbstractConfig)
|
||||||
|
|||||||
@@ -1,15 +1,16 @@
|
|||||||
package chipyard
|
package chipyard
|
||||||
|
|
||||||
import freechips.rocketchip.config.{Config}
|
import org.chipsalliance.cde.config.{Config}
|
||||||
import freechips.rocketchip.rocket.{DCacheParams}
|
import freechips.rocketchip.rocket.{DCacheParams}
|
||||||
|
|
||||||
class AbstractTraceGenConfig extends Config(
|
class AbstractTraceGenConfig extends Config(
|
||||||
|
new chipyard.harness.WithAbsoluteFreqHarnessClockInstantiator ++
|
||||||
new chipyard.harness.WithBlackBoxSimMem ++
|
new chipyard.harness.WithBlackBoxSimMem ++
|
||||||
new chipyard.harness.WithTraceGenSuccess ++
|
new chipyard.harness.WithTraceGenSuccess ++
|
||||||
new chipyard.harness.WithClockAndResetFromHarness ++
|
new chipyard.harness.WithClockAndResetFromHarness ++
|
||||||
new chipyard.iobinders.WithAXI4MemPunchthrough ++
|
new chipyard.iobinders.WithAXI4MemPunchthrough ++
|
||||||
new chipyard.iobinders.WithTraceGenSuccessPunchthrough ++
|
new chipyard.iobinders.WithTraceGenSuccessPunchthrough ++
|
||||||
new chipyard.iobinders.WithDividerOnlyClockGenerator ++
|
new chipyard.clocking.WithPassthroughClockGenerator ++
|
||||||
new chipyard.config.WithTracegenSystem ++
|
new chipyard.config.WithTracegenSystem ++
|
||||||
new chipyard.config.WithNoSubsystemDrivenClocks ++
|
new chipyard.config.WithNoSubsystemDrivenClocks ++
|
||||||
new chipyard.config.WithPeripheryBusFrequencyAsDefault ++
|
new chipyard.config.WithPeripheryBusFrequencyAsDefault ++
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
package chipyard
|
package chipyard
|
||||||
|
|
||||||
import freechips.rocketchip.config.{Config}
|
import org.chipsalliance.cde.config.{Config}
|
||||||
import constellation.channel._
|
import constellation.channel._
|
||||||
import constellation.routing._
|
import constellation.routing._
|
||||||
import constellation.topology._
|
import constellation.topology._
|
||||||
@@ -77,6 +77,7 @@ class TutorialSha3BlackBoxConfig extends Config(
|
|||||||
|
|
||||||
// Tutorial Phase 5: Map a multicore heterogeneous SoC with multiple cores and memory-mapped accelerators
|
// Tutorial Phase 5: Map a multicore heterogeneous SoC with multiple cores and memory-mapped accelerators
|
||||||
class TutorialNoCConfig extends Config(
|
class TutorialNoCConfig extends Config(
|
||||||
|
new chipyard.iobinders.WithDontTouchIOBinders(false) ++
|
||||||
// Try changing the dimensions of the Mesh topology
|
// Try changing the dimensions of the Mesh topology
|
||||||
new constellation.soc.WithGlobalNoC(constellation.soc.GlobalNoCParams(
|
new constellation.soc.WithGlobalNoC(constellation.soc.GlobalNoCParams(
|
||||||
NoCParams(
|
NoCParams(
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ import scala.util.matching.Regex
|
|||||||
import chisel3._
|
import chisel3._
|
||||||
import chisel3.util.{log2Up}
|
import chisel3.util.{log2Up}
|
||||||
|
|
||||||
import freechips.rocketchip.config.{Field, Parameters, Config}
|
import org.chipsalliance.cde.config.{Field, Parameters, Config}
|
||||||
import freechips.rocketchip.subsystem._
|
import freechips.rocketchip.subsystem._
|
||||||
import freechips.rocketchip.prci._
|
import freechips.rocketchip.prci._
|
||||||
import freechips.rocketchip.diplomacy._
|
import freechips.rocketchip.diplomacy._
|
||||||
@@ -13,7 +13,7 @@ import freechips.rocketchip.tilelink.{HasTLBusParams}
|
|||||||
|
|
||||||
import chipyard._
|
import chipyard._
|
||||||
import chipyard.clocking._
|
import chipyard.clocking._
|
||||||
|
import chipyard.harness.{DefaultClockFrequencyKey}
|
||||||
|
|
||||||
// The default RocketChip BaseSubsystem drives its diplomatic clock graph
|
// The default RocketChip BaseSubsystem drives its diplomatic clock graph
|
||||||
// with the implicit clocks of Subsystem. Don't do that, instead we extend
|
// with the implicit clocks of Subsystem. Don't do that, instead we extend
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ import scala.util.matching.Regex
|
|||||||
import chisel3._
|
import chisel3._
|
||||||
import chisel3.util.{log2Up}
|
import chisel3.util.{log2Up}
|
||||||
|
|
||||||
import freechips.rocketchip.config.{Config}
|
import org.chipsalliance.cde.config.{Config}
|
||||||
import freechips.rocketchip.devices.tilelink.{BootROMLocated, PLICKey}
|
import freechips.rocketchip.devices.tilelink.{BootROMLocated, PLICKey}
|
||||||
import freechips.rocketchip.devices.debug.{Debug, ExportDebug, DebugModuleKey, DMI}
|
import freechips.rocketchip.devices.debug.{Debug, ExportDebug, DebugModuleKey, DMI}
|
||||||
import freechips.rocketchip.stage.phases.TargetDirKey
|
import freechips.rocketchip.stage.phases.TargetDirKey
|
||||||
@@ -87,3 +87,7 @@ class WithExtMemIdBits(n: Int) extends Config((site, here, up) => {
|
|||||||
class WithNoPLIC extends Config((site, here, up) => {
|
class WithNoPLIC extends Config((site, here, up) => {
|
||||||
case PLICKey => None
|
case PLICKey => None
|
||||||
})
|
})
|
||||||
|
|
||||||
|
class WithDebugModuleAbstractDataWords(words: Int = 16) extends Config((site, here, up) => {
|
||||||
|
case DebugModuleKey => up(DebugModuleKey).map(_.copy(nAbstractDataWords=words))
|
||||||
|
})
|
||||||
|
|||||||
@@ -2,7 +2,7 @@ package chipyard.config
|
|||||||
|
|
||||||
import chisel3._
|
import chisel3._
|
||||||
|
|
||||||
import freechips.rocketchip.config.{Field, Parameters, Config}
|
import org.chipsalliance.cde.config.{Field, Parameters, Config}
|
||||||
import freechips.rocketchip.tile._
|
import freechips.rocketchip.tile._
|
||||||
import freechips.rocketchip.diplomacy._
|
import freechips.rocketchip.diplomacy._
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
package chipyard.config
|
package chipyard.config
|
||||||
|
|
||||||
import freechips.rocketchip.config.{Config}
|
import org.chipsalliance.cde.config.{Config}
|
||||||
import freechips.rocketchip.subsystem.{SystemBusKey, BankedL2Key, CoherenceManagerWrapper}
|
import freechips.rocketchip.subsystem.{SystemBusKey, BankedL2Key, CoherenceManagerWrapper}
|
||||||
import freechips.rocketchip.diplomacy.{DTSTimebase}
|
import freechips.rocketchip.diplomacy.{DTSTimebase}
|
||||||
|
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user