fixed merge conflict
This commit is contained in:
@@ -34,11 +34,19 @@ Here the key is built from a string where the `checksum` portion converts the fi
|
||||
This directory contains all the collateral for the Chipyard CI to work.
|
||||
The following is included:
|
||||
|
||||
`build-toolchains.sh` # build either riscv-tools or esp-tools
|
||||
`create-hash.sh` # create hashes of riscv-tools/esp-tools so circleci caching can work
|
||||
`do-rtl-build.sh` # use verilator to build a sim executable (remotely)
|
||||
`config.yml` # main circleci config script to enumerate jobs/workflows
|
||||
`defaults.sh` # default variables used
|
||||
`build-toolchains.sh` # build either riscv-tools or esp-tools
|
||||
`create-hash.sh` # create hashes of riscv-tools/esp-tools so circleci caching can work
|
||||
`do-rtl-build.sh` # use verilator to build a sim executable (remotely)
|
||||
`config.yml` # main circleci config script to enumerate jobs/workflows
|
||||
`defaults.sh` # default variables used
|
||||
`check-commit.sh` # check that submodule commits are valid
|
||||
`build-extra-tests.sh` # build default chipyard tests located in tests/
|
||||
`clean-old-files.sh` # clean up build server files
|
||||
`do-fpga-rtl-build.sh` # similar to `do-rtl-build` but using fpga/
|
||||
`install-verilator.sh` # install verilator on build server
|
||||
`run-firesim-scala-tests.sh` # run firesim scala tests
|
||||
`run-tests.sh # run tests for a specific set of designs
|
||||
`images/` # docker image used in CI
|
||||
|
||||
How things are setup for Chipyard
|
||||
---------------------------------
|
||||
|
||||
@@ -120,23 +120,33 @@ dir="vlsi"
|
||||
branches=("master")
|
||||
search
|
||||
|
||||
submodules=("fpga-shells")
|
||||
dir="fpga"
|
||||
branches=("master")
|
||||
search
|
||||
|
||||
# turn off verbose printing to make this easier to read
|
||||
set +x
|
||||
|
||||
# print all result strings
|
||||
# print 0's
|
||||
for str in "${all_names[@]}";
|
||||
do
|
||||
echo "$str"
|
||||
if [ 0 = $(echo "$str" | awk '{print$3}') ]; then
|
||||
echo "$str"
|
||||
fi
|
||||
done
|
||||
|
||||
# check if there was a non-zero return code
|
||||
echo ""
|
||||
|
||||
# check if there was a non-zero return code and print 1's
|
||||
EXIT=0
|
||||
for str in "${all_names[@]}";
|
||||
do
|
||||
if [ ! 0 = $(echo "$str" | awk '{print$3}') ]; then
|
||||
exit 1
|
||||
echo "$str"
|
||||
EXIT=1
|
||||
fi
|
||||
done
|
||||
|
||||
echo "Done checking all submodules"
|
||||
|
||||
exit $EXIT
|
||||
|
||||
@@ -49,6 +49,7 @@ commands:
|
||||
- add_ssh_keys:
|
||||
fingerprints:
|
||||
- "3e:c3:02:5b:ed:64:8c:b7:b0:04:43:bc:83:43:73:1e"
|
||||
- "32:d6:89:d2:97:fa:db:de:a8:2d:2a:f2:70:dd:80:89"
|
||||
- checkout
|
||||
|
||||
setup-tools:
|
||||
@@ -81,12 +82,15 @@ commands:
|
||||
build-script:
|
||||
type: string
|
||||
default: "do-rtl-build.sh"
|
||||
build-type:
|
||||
type: string
|
||||
default: "sim"
|
||||
steps:
|
||||
- setup-tools:
|
||||
tools-version: "<< parameters.tools-version >>"
|
||||
- run:
|
||||
name: Building << parameters.group-key >> subproject using Verilator
|
||||
command: .circleci/<< parameters.build-script >> << parameters.group-key >>
|
||||
command: .circleci/<< parameters.build-script >> << parameters.group-key >> << parameters.build-type >>
|
||||
no_output_timeout: << parameters.timeout >>
|
||||
- save_cache:
|
||||
key: << parameters.group-key >>-{{ .Branch }}-{{ .Revision }}
|
||||
@@ -367,6 +371,12 @@ jobs:
|
||||
project-key: "firesim-multiclock"
|
||||
run-script: "run-firesim-scala-tests.sh"
|
||||
timeout: "20m"
|
||||
prepare-chipyard-fpga:
|
||||
executor: main-env
|
||||
steps:
|
||||
- prepare-rtl:
|
||||
group-key: "group-fpga"
|
||||
build-type: "fpga"
|
||||
|
||||
# Order and dependencies of jobs to run
|
||||
workflows:
|
||||
@@ -505,3 +515,8 @@ workflows:
|
||||
- install-riscv-toolchain
|
||||
- install-verilator
|
||||
- build-extra-tests
|
||||
|
||||
# Prepare the fpga builds (just Verilog)
|
||||
- prepare-chipyard-fpga:
|
||||
requires:
|
||||
- install-riscv-toolchain
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
#!/bin/bash
|
||||
|
||||
copy () {
|
||||
rsync -avzp -e 'ssh' $1 $2
|
||||
rsync -avzp -e 'ssh' --exclude '.git' $1 $2
|
||||
}
|
||||
|
||||
run () {
|
||||
@@ -33,8 +33,10 @@ REMOTE_ESP_DIR=$REMOTE_WORK_DIR/esp-tools-install
|
||||
REMOTE_CHIPYARD_DIR=$REMOTE_WORK_DIR/chipyard
|
||||
REMOTE_SIM_DIR=$REMOTE_CHIPYARD_DIR/sims/verilator
|
||||
REMOTE_FIRESIM_DIR=$REMOTE_CHIPYARD_DIR/sims/firesim/sim
|
||||
REMOTE_FPGA_DIR=$REMOTE_CHIPYARD_DIR/fpga
|
||||
REMOTE_JAVA_OPTS="-Xmx10G -Xss8M"
|
||||
# Disable the supershell to greatly improve the readability of SBT output when captured by Circle CI
|
||||
REMOTE_JAVA_ARGS="-Xmx9G -Xss8M -Dsbt.ivy.home=$REMOTE_WORK_DIR/.ivy2 -Dsbt.supershell=false -Dsbt.global.base=$REMOTE_WORK_DIR/.sbt -Dsbt.boot.directory=$REMOTE_WORK_DIR/.sbt/boot"
|
||||
REMOTE_SBT_OPTS="-Dsbt.ivy.home=$REMOTE_WORK_DIR/.ivy2 -Dsbt.supershell=false -Dsbt.global.base=$REMOTE_WORK_DIR/.sbt -Dsbt.boot.directory=$REMOTE_WORK_DIR/.sbt/boot"
|
||||
REMOTE_VERILATOR_DIR=$REMOTE_PREFIX-$CIRCLE_SHA1-verilator-install
|
||||
|
||||
# local variables (aka within the docker container)
|
||||
@@ -52,6 +54,7 @@ grouping["group-peripherals"]="chipyard-dmirocket chipyard-blkdev chipyard-spifl
|
||||
grouping["group-accels"]="chipyard-nvdla chipyard-sha3 chipyard-hwacha chipyard-gemmini chipyard-streaming-fir chipyard-streaming-passthrough"
|
||||
grouping["group-tracegen"]="tracegen tracegen-boom"
|
||||
grouping["group-other"]="icenet testchipip"
|
||||
grouping["group-fpga"]="arty vcu118"
|
||||
|
||||
# key value store to get the build strings
|
||||
declare -A mapping
|
||||
@@ -82,3 +85,6 @@ mapping["firesim-multiclock"]="SCALA_TEST=firesim.firesim.RocketMulticlockF1Test
|
||||
mapping["fireboom"]="SCALA_TEST=firesim.firesim.BoomF1Tests"
|
||||
mapping["icenet"]="SUB_PROJECT=icenet"
|
||||
mapping["testchipip"]="SUB_PROJECT=testchipip"
|
||||
|
||||
mapping["arty"]="SUB_PROJECT=arty verilog"
|
||||
mapping["vcu118"]="SUB_PROJECT=vcu118 verilog"
|
||||
|
||||
@@ -1,7 +1,11 @@
|
||||
#!/bin/bash
|
||||
|
||||
# create the different verilator builds
|
||||
# argument is the make command string
|
||||
# usage:
|
||||
# do-rtl-build.sh <make command string> sim
|
||||
# run rtl build for simulations and copy back results
|
||||
# do-rtl-build.sh <make command string> fpga
|
||||
# run rtl build for fpga and don't copy back results
|
||||
|
||||
# turn echo on and error on earliest command
|
||||
set -ex
|
||||
@@ -15,6 +19,7 @@ trap clean EXIT
|
||||
|
||||
cd $LOCAL_CHIPYARD_DIR
|
||||
./scripts/init-submodules-no-riscv-tools.sh
|
||||
./scripts/init-fpga.sh
|
||||
|
||||
# set stricthostkeychecking to no (must happen before rsync)
|
||||
run "echo \"Ping $SERVER\""
|
||||
@@ -50,12 +55,23 @@ else
|
||||
copy $LOCAL_RISCV_DIR/ $SERVER:$REMOTE_RISCV_DIR
|
||||
fi
|
||||
|
||||
# choose what make dir to use
|
||||
case $2 in
|
||||
"sim")
|
||||
REMOTE_MAKE_DIR=$REMOTE_SIM_DIR
|
||||
;;
|
||||
"fpga")
|
||||
REMOTE_MAKE_DIR=$REMOTE_FPGA_DIR
|
||||
;;
|
||||
esac
|
||||
|
||||
# enter the verilator directory and build the specific config on remote server
|
||||
run "export RISCV=\"$TOOLS_DIR\"; \
|
||||
make -C $REMOTE_SIM_DIR clean;"
|
||||
make -C $REMOTE_MAKE_DIR clean;"
|
||||
|
||||
read -a keys <<< ${grouping[$1]}
|
||||
|
||||
# need to set the PATH to use the new verilator (with the new verilator root)
|
||||
for key in "${keys[@]}"
|
||||
do
|
||||
run "export RISCV=\"$TOOLS_DIR\"; \
|
||||
@@ -63,11 +79,14 @@ do
|
||||
export PATH=\"$REMOTE_VERILATOR_DIR/bin:\$PATH\"; \
|
||||
export VERILATOR_ROOT=\"$REMOTE_VERILATOR_DIR\"; \
|
||||
export COURSIER_CACHE=\"$REMOTE_WORK_DIR/.coursier-cache\"; \
|
||||
make -j$REMOTE_MAKE_NPROC -C $REMOTE_SIM_DIR FIRRTL_LOGLEVEL=info JAVA_ARGS=\"$REMOTE_JAVA_ARGS\" ${mapping[$key]}"
|
||||
make -j$REMOTE_MAKE_NPROC -C $REMOTE_MAKE_DIR FIRRTL_LOGLEVEL=info JAVA_OPTS=\"$REMOTE_JAVA_OPTS\" SBT_OPTS=\"$REMOTE_SBT_OPTS\" ${mapping[$key]}"
|
||||
done
|
||||
|
||||
run "rm -rf $REMOTE_CHIPYARD_DIR/project"
|
||||
|
||||
# copy back the final build
|
||||
mkdir -p $LOCAL_CHIPYARD_DIR
|
||||
copy $SERVER:$REMOTE_CHIPYARD_DIR/ $LOCAL_CHIPYARD_DIR
|
||||
# choose to copy back results
|
||||
if [ $2 = "sim" ]; then
|
||||
# copy back the final build
|
||||
mkdir -p $LOCAL_CHIPYARD_DIR
|
||||
copy $SERVER:$REMOTE_CHIPYARD_DIR/ $LOCAL_CHIPYARD_DIR
|
||||
fi
|
||||
|
||||
@@ -49,4 +49,4 @@ run "export RISCV=\"$TOOLS_DIR\"; \
|
||||
export PATH=\"$REMOTE_VERILATOR_DIR/bin:\$PATH\"; \
|
||||
export VERILATOR_ROOT=\"$REMOTE_VERILATOR_DIR\"; \
|
||||
export COURSIER_CACHE=\"$REMOTE_WORK_DIR/.coursier-cache\"; \
|
||||
make -C $REMOTE_FIRESIM_DIR JAVA_ARGS=\"$REMOTE_JAVA_ARGS\" testOnly ${mapping[$1]}"
|
||||
make -C $REMOTE_FIRESIM_DIR JAVA_OPTS=\"$REMOTE_JAVA_OPTS\" SBT_OPTS=\"$REMOTE_SBT_OPTS\" testOnly ${mapping[$1]}"
|
||||
|
||||
2
.gitignore
vendored
2
.gitignore
vendored
@@ -19,4 +19,4 @@ tags
|
||||
*~
|
||||
env-riscv-tools.sh
|
||||
env-esp-tools.sh
|
||||
.bloop/
|
||||
.bsp/
|
||||
|
||||
3
.gitmodules
vendored
3
.gitmodules
vendored
@@ -131,3 +131,6 @@
|
||||
[submodule "generators/riscv-sodor"]
|
||||
path = generators/riscv-sodor
|
||||
url = https://github.com/ucb-bar/riscv-sodor.git
|
||||
[submodule "fpga/fpga-shells"]
|
||||
path = fpga/fpga-shells
|
||||
url = https://github.com/sifive/fpga-shells.git
|
||||
|
||||
61
CHANGELOG.md
61
CHANGELOG.md
@@ -2,6 +2,67 @@
|
||||
|
||||
This changelog follows the format defined here: https://keepachangelog.com/en/1.0.0/
|
||||
|
||||
## [1.4.0] - 2021-01-19
|
||||
|
||||
A more detailed account of everything included is included in the dev to master PR for this release: https://github.com/ucb-bar/chipyard/pull/599
|
||||
|
||||
### Added
|
||||
* OpenSBI Support (#633)
|
||||
* Support for Diplomacy-based clocking (#614, #682)
|
||||
* Support for Diplomacy-based IOBinders (#699)
|
||||
* Sodor core integration (#648)
|
||||
* Simple Divider-Only PLL for Multiclock RTL Simulation (#676)
|
||||
* Enable parallel Hammer simulations (#600)
|
||||
* OpenRoad nangate45 Hammer backend (#608)
|
||||
* Add support for "LBWIF" backing memory through serialized TileLink (#673)
|
||||
* Add variable to control FIRRTL logging verbosity (#627)
|
||||
* Add RANDOM_SEED variable to set random init for VCS and Verilator simulations (#629)
|
||||
* Fast LoadMem support (#635)
|
||||
* Multithreaded Verilator (#654)
|
||||
* Support for custom Verilator optimization flags (#728)
|
||||
* Add config-fragment to use broadcast manager instead of L2 for coherence (#721)
|
||||
* Added optional ignore QEMU flag to `build-toolchains.sh` (#709)
|
||||
* Split `JAVA_ARGS` into `JAVA_OPTS` and `SBT_OPTS` (#719)
|
||||
* Experimental support for SBT thin client. Enable with `export ENABLE_SBT_THIN_CLIENT=1` (https://github.com/sbt/sbt/pull/5620) (#719)
|
||||
* Helper `make` targets to launch SBT console (`sbt`) and shutdown/start thin server (<start/shutdown>-sbt-server) (#719)
|
||||
* Allow users to override `CC` and `CXX` for `build-toolchains.sh` (#739)
|
||||
* Support VCU118/Arty local FPGA prototypes through `fpga-shells` (#747)
|
||||
* A 16-core LargeBOOM configuration has been added to FireChip to highlight the resource-optimizing platform configurations added to FireSim in firesim/firesim#636 (#756)
|
||||
|
||||
### Changed
|
||||
* Bump Chisel to 3.4.1.x (#742, #719, #751)
|
||||
* Bump RocketChip to a7b016e (#742, #719)
|
||||
* Bump FireSim to 1.11
|
||||
* Bump Gemmini to v0.5
|
||||
* Bump to SBT 1.4.4 (#719)
|
||||
* Split IOBinders into IOBinders and HarnessBinders | punch out clocks to harness for simwidgets and bridges (#670, #674)
|
||||
* Have FireSim build recipes use Chipyard configs rather than FireChip configs (#695)
|
||||
* FireMarshal boot default to OpenSBI rather than BBL (#633)
|
||||
* Override default baud rate for FireChip (#625)
|
||||
* DTM only supports HTIF in DMI mode (#672)
|
||||
* Unify HTIF implementation between Chipyard and Firesim (#683)
|
||||
* Renamed Ariane to CVA6 (#710)
|
||||
* `build.sbt` refactoring/fixes for RC/Chisel/Firrtl bump (#719)
|
||||
* Use `; x; y; z;` syntax to run multiple SBT commands (#719)
|
||||
* CI Improvements: Cleanup `check-commit` printout. Don't transfer `.git` folders. (#750)
|
||||
|
||||
### Fixed
|
||||
* Multi-SHA3 configs (#597)
|
||||
* Allow dramsim_ini folder to be set at the command line (#598)
|
||||
* Emit HTIF Node in device tree (#607)
|
||||
* Fixes for AXI4 MMIO and FBus ports (#618)
|
||||
* Only punch realistic subset of DebugIO through chiptop | default to JTAG+Serial (#664)
|
||||
* IceNet bug fixes (#720)
|
||||
* smartelf2hex.sh bug fixes (#677, #693)
|
||||
* env.sh zsh compatibility (#705)
|
||||
* build-toolchains.sh bug fixes (#745 #739)
|
||||
* Bump Dromajo to work with older version of glibc (#709)
|
||||
|
||||
### Removed
|
||||
* Support for synchronous ChipTop reset (#703)
|
||||
* Split `JAVA_ARGS` into `JAVA_OPTS` and `SBT_OPTS` (#719)
|
||||
|
||||
|
||||
## [1.3.0] - 2020-05-31
|
||||
|
||||
A more detailed account of everything included is included in the dev to master PR for this release: https://github.com/ucb-bar/chipyard/pull/500
|
||||
|
||||
202
LICENSE.SiFive
Normal file
202
LICENSE.SiFive
Normal file
@@ -0,0 +1,202 @@
|
||||
|
||||
Apache License
|
||||
Version 2.0, January 2004
|
||||
http://www.apache.org/licenses/
|
||||
|
||||
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
|
||||
|
||||
1. Definitions.
|
||||
|
||||
"License" shall mean the terms and conditions for use, reproduction,
|
||||
and distribution as defined by Sections 1 through 9 of this document.
|
||||
|
||||
"Licensor" shall mean the copyright owner or entity authorized by
|
||||
the copyright owner that is granting the License.
|
||||
|
||||
"Legal Entity" shall mean the union of the acting entity and all
|
||||
other entities that control, are controlled by, or are under common
|
||||
control with that entity. For the purposes of this definition,
|
||||
"control" means (i) the power, direct or indirect, to cause the
|
||||
direction or management of such entity, whether by contract or
|
||||
otherwise, or (ii) ownership of fifty percent (50%) or more of the
|
||||
outstanding shares, or (iii) beneficial ownership of such entity.
|
||||
|
||||
"You" (or "Your") shall mean an individual or Legal Entity
|
||||
exercising permissions granted by this License.
|
||||
|
||||
"Source" form shall mean the preferred form for making modifications,
|
||||
including but not limited to software source code, documentation
|
||||
source, and configuration files.
|
||||
|
||||
"Object" form shall mean any form resulting from mechanical
|
||||
transformation or translation of a Source form, including but
|
||||
not limited to compiled object code, generated documentation,
|
||||
and conversions to other media types.
|
||||
|
||||
"Work" shall mean the work of authorship, whether in Source or
|
||||
Object form, made available under the License, as indicated by a
|
||||
copyright notice that is included in or attached to the work
|
||||
(an example is provided in the Appendix below).
|
||||
|
||||
"Derivative Works" shall mean any work, whether in Source or Object
|
||||
form, that is based on (or derived from) the Work and for which the
|
||||
editorial revisions, annotations, elaborations, or other modifications
|
||||
represent, as a whole, an original work of authorship. For the purposes
|
||||
of this License, Derivative Works shall not include works that remain
|
||||
separable from, or merely link (or bind by name) to the interfaces of,
|
||||
the Work and Derivative Works thereof.
|
||||
|
||||
"Contribution" shall mean any work of authorship, including
|
||||
the original version of the Work and any modifications or additions
|
||||
to that Work or Derivative Works thereof, that is intentionally
|
||||
submitted to Licensor for inclusion in the Work by the copyright owner
|
||||
or by an individual or Legal Entity authorized to submit on behalf of
|
||||
the copyright owner. For the purposes of this definition, "submitted"
|
||||
means any form of electronic, verbal, or written communication sent
|
||||
to the Licensor or its representatives, including but not limited to
|
||||
communication on electronic mailing lists, source code control systems,
|
||||
and issue tracking systems that are managed by, or on behalf of, the
|
||||
Licensor for the purpose of discussing and improving the Work, but
|
||||
excluding communication that is conspicuously marked or otherwise
|
||||
designated in writing by the copyright owner as "Not a Contribution."
|
||||
|
||||
"Contributor" shall mean Licensor and any individual or Legal Entity
|
||||
on behalf of whom a Contribution has been received by Licensor and
|
||||
subsequently incorporated within the Work.
|
||||
|
||||
2. Grant of Copyright License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
copyright license to reproduce, prepare Derivative Works of,
|
||||
publicly display, publicly perform, sublicense, and distribute the
|
||||
Work and such Derivative Works in Source or Object form.
|
||||
|
||||
3. Grant of Patent License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
(except as stated in this section) patent license to make, have made,
|
||||
use, offer to sell, sell, import, and otherwise transfer the Work,
|
||||
where such license applies only to those patent claims licensable
|
||||
by such Contributor that are necessarily infringed by their
|
||||
Contribution(s) alone or by combination of their Contribution(s)
|
||||
with the Work to which such Contribution(s) was submitted. If You
|
||||
institute patent litigation against any entity (including a
|
||||
cross-claim or counterclaim in a lawsuit) alleging that the Work
|
||||
or a Contribution incorporated within the Work constitutes direct
|
||||
or contributory patent infringement, then any patent licenses
|
||||
granted to You under this License for that Work shall terminate
|
||||
as of the date such litigation is filed.
|
||||
|
||||
4. Redistribution. You may reproduce and distribute copies of the
|
||||
Work or Derivative Works thereof in any medium, with or without
|
||||
modifications, and in Source or Object form, provided that You
|
||||
meet the following conditions:
|
||||
|
||||
(a) You must give any other recipients of the Work or
|
||||
Derivative Works a copy of this License; and
|
||||
|
||||
(b) You must cause any modified files to carry prominent notices
|
||||
stating that You changed the files; and
|
||||
|
||||
(c) You must retain, in the Source form of any Derivative Works
|
||||
that You distribute, all copyright, patent, trademark, and
|
||||
attribution notices from the Source form of the Work,
|
||||
excluding those notices that do not pertain to any part of
|
||||
the Derivative Works; and
|
||||
|
||||
(d) If the Work includes a "NOTICE" text file as part of its
|
||||
distribution, then any Derivative Works that You distribute must
|
||||
include a readable copy of the attribution notices contained
|
||||
within such NOTICE file, excluding those notices that do not
|
||||
pertain to any part of the Derivative Works, in at least one
|
||||
of the following places: within a NOTICE text file distributed
|
||||
as part of the Derivative Works; within the Source form or
|
||||
documentation, if provided along with the Derivative Works; or,
|
||||
within a display generated by the Derivative Works, if and
|
||||
wherever such third-party notices normally appear. The contents
|
||||
of the NOTICE file are for informational purposes only and
|
||||
do not modify the License. You may add Your own attribution
|
||||
notices within Derivative Works that You distribute, alongside
|
||||
or as an addendum to the NOTICE text from the Work, provided
|
||||
that such additional attribution notices cannot be construed
|
||||
as modifying the License.
|
||||
|
||||
You may add Your own copyright statement to Your modifications and
|
||||
may provide additional or different license terms and conditions
|
||||
for use, reproduction, or distribution of Your modifications, or
|
||||
for any such Derivative Works as a whole, provided Your use,
|
||||
reproduction, and distribution of the Work otherwise complies with
|
||||
the conditions stated in this License.
|
||||
|
||||
5. Submission of Contributions. Unless You explicitly state otherwise,
|
||||
any Contribution intentionally submitted for inclusion in the Work
|
||||
by You to the Licensor shall be under the terms and conditions of
|
||||
this License, without any additional terms or conditions.
|
||||
Notwithstanding the above, nothing herein shall supersede or modify
|
||||
the terms of any separate license agreement you may have executed
|
||||
with Licensor regarding such Contributions.
|
||||
|
||||
6. Trademarks. This License does not grant permission to use the trade
|
||||
names, trademarks, service marks, or product names of the Licensor,
|
||||
except as required for reasonable and customary use in describing the
|
||||
origin of the Work and reproducing the content of the NOTICE file.
|
||||
|
||||
7. Disclaimer of Warranty. Unless required by applicable law or
|
||||
agreed to in writing, Licensor provides the Work (and each
|
||||
Contributor provides its Contributions) on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
||||
implied, including, without limitation, any warranties or conditions
|
||||
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
|
||||
PARTICULAR PURPOSE. You are solely responsible for determining the
|
||||
appropriateness of using or redistributing the Work and assume any
|
||||
risks associated with Your exercise of permissions under this License.
|
||||
|
||||
8. Limitation of Liability. In no event and under no legal theory,
|
||||
whether in tort (including negligence), contract, or otherwise,
|
||||
unless required by applicable law (such as deliberate and grossly
|
||||
negligent acts) or agreed to in writing, shall any Contributor be
|
||||
liable to You for damages, including any direct, indirect, special,
|
||||
incidental, or consequential damages of any character arising as a
|
||||
result of this License or out of the use or inability to use the
|
||||
Work (including but not limited to damages for loss of goodwill,
|
||||
work stoppage, computer failure or malfunction, or any and all
|
||||
other commercial damages or losses), even if such Contributor
|
||||
has been advised of the possibility of such damages.
|
||||
|
||||
9. Accepting Warranty or Additional Liability. While redistributing
|
||||
the Work or Derivative Works thereof, You may choose to offer,
|
||||
and charge a fee for, acceptance of support, warranty, indemnity,
|
||||
or other liability obligations and/or rights consistent with this
|
||||
License. However, in accepting such obligations, You may act only
|
||||
on Your own behalf and on Your sole responsibility, not on behalf
|
||||
of any other Contributor, and only if You agree to indemnify,
|
||||
defend, and hold each Contributor harmless for any liability
|
||||
incurred by, or claims asserted against, such Contributor by reason
|
||||
of your accepting any such warranty or additional liability.
|
||||
|
||||
END OF TERMS AND CONDITIONS
|
||||
|
||||
APPENDIX: How to apply the Apache License to your work.
|
||||
|
||||
To apply the Apache License to your work, attach the following
|
||||
boilerplate notice, with the fields enclosed by brackets "[]"
|
||||
replaced with your own identifying information. (Don't include
|
||||
the brackets!) The text should be enclosed in the appropriate
|
||||
comment syntax for the file format. We also recommend that a
|
||||
file or class name and description of purpose be included on the
|
||||
same "printed page" as the copyright notice for easier
|
||||
identification within third-party archives.
|
||||
|
||||
Copyright 2016-2017 SiFive, Inc.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
@@ -47,12 +47,16 @@ If used for research, please cite Chipyard by the following publication:
|
||||
}
|
||||
```
|
||||
|
||||
* **Chipyard**
|
||||
* A. Amid, et al. *IEEE Micro'20* [PDF](https://ieeexplore.ieee.org/document/9099108).
|
||||
* A. Amid, et al. *DAC'20* [PDF](https://ieeexplore.ieee.org/document/9218756).
|
||||
|
||||
These additional publications cover many of the internal components used in Chipyard. However, for the most up-to-date details, users should refer to the Chipyard docs.
|
||||
|
||||
* **Generators**
|
||||
* **Rocket Chip**: K. Asanovic, et al., *UCB EECS TR*. [PDF](http://www2.eecs.berkeley.edu/Pubs/TechRpts/2016/EECS-2016-17.pdf).
|
||||
* **BOOM**: C. Celio, et al., *Hot Chips 30*. [PDF](https://www.hotchips.org/hc30/1conf/1.03_Berkeley_BROOM_HC30.Berkeley.Celio.v02.pdf).
|
||||
* **SonicBOOM (BOOMv3): J. Zhao, et al., *CARRV'20*. [PDF](https://carrv.github.io/2020/papers/CARRV2020_paper_15_Zhao.pdf).
|
||||
* **SonicBOOM (BOOMv3)**: J. Zhao, et al., *CARRV'20*. [PDF](https://carrv.github.io/2020/papers/CARRV2020_paper_15_Zhao.pdf).
|
||||
* **Hwacha**: Y. Lee, et al., *ESSCIRC'14*. [PDF](http://hwacha.org/papers/riscv-esscirc2014.pdf).
|
||||
* **Gemmini**: H. Genc, et al., *arXiv*. [PDF](https://arxiv.org/pdf/1911.09925).
|
||||
* **Sims**
|
||||
|
||||
266
build.sbt
266
build.sbt
@@ -1,30 +1,34 @@
|
||||
import Tests._
|
||||
|
||||
// This gives us a nicer handle to the root project instead of using the
|
||||
// This gives us a nicer handle to the root project instead of using the
|
||||
// implicit one
|
||||
lazy val chipyardRoot = Project("chipyardRoot", file("."))
|
||||
|
||||
lazy val commonSettings = Seq(
|
||||
organization := "edu.berkeley.cs",
|
||||
version := "1.0",
|
||||
version := "1.3",
|
||||
scalaVersion := "2.12.10",
|
||||
traceLevel := 15,
|
||||
test in assembly := {},
|
||||
assemblyMergeStrategy in assembly := { _ match {
|
||||
case PathList("META-INF", "MANIFEST.MF") => MergeStrategy.discard
|
||||
case _ => MergeStrategy.first}},
|
||||
scalacOptions ++= Seq("-deprecation","-unchecked","-Xsource:2.11"),
|
||||
libraryDependencies += "org.scalatest" %% "scalatest" % "3.0.8" % "test",
|
||||
libraryDependencies += "org.json4s" %% "json4s-jackson" % "3.6.1",
|
||||
libraryDependencies += "org.scala-lang" % "scala-reflect" % scalaVersion.value,
|
||||
libraryDependencies += "com.github.scopt" %% "scopt" % "3.7.0",
|
||||
libraryDependencies += "org.scala-lang.modules" % "scala-jline" % "2.12.1",
|
||||
libraryDependencies += "com.typesafe.play" %% "play-json" % "2.6.10",
|
||||
libraryDependencies += "org.typelevel" %% "spire" % "0.16.2",
|
||||
libraryDependencies += "org.scalanlp" %% "breeze" % "1.0",
|
||||
addCompilerPlugin("org.scalamacros" % "paradise" % "2.1.0" cross CrossVersion.full),
|
||||
addCompilerPlugin("org.scalamacros" % "paradise" % "2.1.1" cross CrossVersion.full),
|
||||
unmanagedBase := (chipyardRoot / unmanagedBase).value,
|
||||
allDependencies := allDependencies.value.filterNot(_.organization == "edu.berkeley.cs"),
|
||||
allDependencies := {
|
||||
// drop specific maven dependencies in subprojects in favor of Chipyard's version
|
||||
val dropDeps = Seq(
|
||||
("edu.berkeley.cs", "firrtl"),
|
||||
("edu.berkeley.cs", "chisel3"),
|
||||
("edu.berkeley.cs", "rocketchip"),
|
||||
("edu.berkeley.cs", "chisel-iotesters"),
|
||||
("edu.berkeley.cs", "treadle"),
|
||||
("edu.berkeley.cs", "firrtl-interpreter"))
|
||||
|
||||
allDependencies.value.filterNot { dep =>
|
||||
dropDeps.contains((dep.organization, dep.name))
|
||||
}
|
||||
},
|
||||
exportJars := true,
|
||||
resolvers ++= Seq(
|
||||
Resolver.sonatypeRepo("snapshots"),
|
||||
@@ -40,19 +44,6 @@ lazy val firesimDir = if (firesimAsLibrary) {
|
||||
file("../../sim")
|
||||
}
|
||||
|
||||
// Checks for -DROCKET_USE_MAVEN.
|
||||
// If it's there, use a maven dependency.
|
||||
// Else, depend on subprojects in git submodules.
|
||||
def conditionalDependsOn(prj: Project): Project = {
|
||||
if (sys.props.contains("ROCKET_USE_MAVEN")) {
|
||||
prj.settings(Seq(
|
||||
libraryDependencies += "edu.berkeley.cs" %% "testchipip" % "1.0-020719-SNAPSHOT",
|
||||
))
|
||||
} else {
|
||||
prj.dependsOn(testchipip)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* It has been a struggle for us to override settings in subprojects.
|
||||
* An example would be adding a dependency to rocketchip on midas's targetutils library,
|
||||
@@ -72,152 +63,259 @@ def freshProject(name: String, dir: File): Project = {
|
||||
// Fork each scala test for now, to work around persistent mutable state
|
||||
// in Rocket-Chip based generators
|
||||
def isolateAllTests(tests: Seq[TestDefinition]) = tests map { test =>
|
||||
val options = ForkOptions()
|
||||
new Group(test.name, Seq(test), SubProcess(options))
|
||||
} toSeq
|
||||
val options = ForkOptions()
|
||||
new Group(test.name, Seq(test), SubProcess(options))
|
||||
} toSeq
|
||||
|
||||
// Subproject definitions begin
|
||||
//
|
||||
// FIRRTL is handled as an unmanaged dependency. Make will build the firrtl jar
|
||||
// before launching sbt if any of the firrtl source files has been updated
|
||||
// The jar is dropped in chipyard's lib/ directory, which is used as the unmanagedBase
|
||||
// for all subprojects
|
||||
lazy val chisel = (project in file("tools/chisel3"))
|
||||
|
||||
// -- Rocket Chip --
|
||||
|
||||
// This needs to stay in sync with the chisel3 and firrtl git submodules
|
||||
val chiselVersion = "3.4.1"
|
||||
lazy val chiselRef = ProjectRef(workspaceDirectory / "chisel3", "chisel")
|
||||
lazy val chiselLib = "edu.berkeley.cs" %% "chisel3" % chiselVersion
|
||||
lazy val chiselLibDeps = (chiselRef / Keys.libraryDependencies)
|
||||
// While not built from source, *must* be in sync with the chisel3 git submodule
|
||||
// Building from source requires extending sbt-sriracha or a similar plugin and
|
||||
// keeping scalaVersion in sync with chisel3 to the minor version
|
||||
lazy val chiselPluginLib = "edu.berkeley.cs" % "chisel3-plugin" % chiselVersion cross CrossVersion.full
|
||||
|
||||
val firrtlVersion = "1.4.1"
|
||||
lazy val firrtlRef = ProjectRef(workspaceDirectory / "firrtl", "firrtl")
|
||||
lazy val firrtlLib = "edu.berkeley.cs" %% "firrtl" % firrtlVersion
|
||||
val firrtlLibDeps = settingKey[Seq[sbt.librarymanagement.ModuleID]]("FIRRTL Library Dependencies sans antlr4")
|
||||
Global / firrtlLibDeps := {
|
||||
// drop antlr4 compile dep. but keep antlr4-runtime dep. (compile needs the plugin to be setup)
|
||||
(firrtlRef / Keys.libraryDependencies).value.filterNot(_.name == "antlr4")
|
||||
}
|
||||
|
||||
// Rocket-chip dependencies (subsumes making RC a RootProject)
|
||||
lazy val hardfloat = (project in rocketChipDir / "hardfloat")
|
||||
.sourceDependency(chiselRef, chiselLib)
|
||||
.settings(addCompilerPlugin(chiselPluginLib))
|
||||
.settings(libraryDependencies ++= chiselLibDeps.value)
|
||||
.dependsOn(midasTargetUtils)
|
||||
.settings(commonSettings)
|
||||
.settings(
|
||||
libraryDependencies ++= Seq(
|
||||
"org.scala-lang" % "scala-reflect" % scalaVersion.value,
|
||||
"org.json4s" %% "json4s-jackson" % "3.6.1",
|
||||
"org.scalatest" %% "scalatest" % "3.2.0" % "test"
|
||||
)
|
||||
)
|
||||
|
||||
lazy val rocketMacros = (project in rocketChipDir / "macros")
|
||||
.settings(commonSettings)
|
||||
.settings(
|
||||
libraryDependencies ++= Seq(
|
||||
"org.scala-lang" % "scala-reflect" % scalaVersion.value,
|
||||
"org.json4s" %% "json4s-jackson" % "3.6.1",
|
||||
"org.scalatest" %% "scalatest" % "3.2.0" % "test"
|
||||
)
|
||||
)
|
||||
|
||||
lazy val rocketConfig = (project in rocketChipDir / "api-config-chipsalliance/build-rules/sbt")
|
||||
.settings(commonSettings)
|
||||
.settings(
|
||||
libraryDependencies ++= Seq(
|
||||
"org.scala-lang" % "scala-reflect" % scalaVersion.value,
|
||||
"org.json4s" %% "json4s-jackson" % "3.6.1",
|
||||
"org.scalatest" %% "scalatest" % "3.2.0" % "test"
|
||||
)
|
||||
)
|
||||
|
||||
lazy val rocketchip = freshProject("rocketchip", rocketChipDir)
|
||||
.sourceDependency(chiselRef, chiselLib)
|
||||
.settings(addCompilerPlugin(chiselPluginLib))
|
||||
.settings(libraryDependencies ++= chiselLibDeps.value)
|
||||
.dependsOn(hardfloat, rocketMacros, rocketConfig)
|
||||
.settings(commonSettings)
|
||||
.settings(
|
||||
libraryDependencies ++= Seq(
|
||||
"org.scala-lang" % "scala-reflect" % scalaVersion.value,
|
||||
"org.json4s" %% "json4s-jackson" % "3.6.1",
|
||||
"org.scalatest" %% "scalatest" % "3.2.0" % "test"
|
||||
)
|
||||
)
|
||||
.settings( // Settings for scalafix
|
||||
semanticdbEnabled := true,
|
||||
semanticdbVersion := scalafixSemanticdb.revision,
|
||||
scalacOptions += "-Ywarn-unused-import"
|
||||
)
|
||||
lazy val rocketLibDeps = (rocketchip / Keys.libraryDependencies)
|
||||
|
||||
// -- Chipyard-managed External Projects --
|
||||
|
||||
lazy val firrtl_interpreter = (project in file("tools/firrtl-interpreter"))
|
||||
.sourceDependency(firrtlRef, firrtlLib)
|
||||
.settings(commonSettings)
|
||||
.settings(libraryDependencies ++= (Global / firrtlLibDeps).value)
|
||||
lazy val firrtlInterpreterLibDeps = (firrtl_interpreter / Keys.libraryDependencies)
|
||||
|
||||
lazy val treadle = (project in file("tools/treadle"))
|
||||
.sourceDependency(firrtlRef, firrtlLib)
|
||||
.settings(commonSettings)
|
||||
.settings(libraryDependencies ++= (Global / firrtlLibDeps).value)
|
||||
lazy val treadleLibDeps = (treadle / Keys.libraryDependencies)
|
||||
|
||||
lazy val chisel_testers = (project in file("tools/chisel-testers"))
|
||||
.dependsOn(chisel, firrtl_interpreter, treadle)
|
||||
.settings(
|
||||
commonSettings,
|
||||
libraryDependencies ++= Seq(
|
||||
"junit" % "junit" % "4.12",
|
||||
"org.scalatest" %% "scalatest" % "3.0.5",
|
||||
"org.scalacheck" %% "scalacheck" % "1.14.0",
|
||||
"com.github.scopt" %% "scopt" % "3.7.0"
|
||||
)
|
||||
)
|
||||
.sourceDependency(chiselRef, chiselLib)
|
||||
.settings(addCompilerPlugin(chiselPluginLib))
|
||||
.settings(libraryDependencies ++= chiselLibDeps.value)
|
||||
.dependsOn(firrtl_interpreter, treadle)
|
||||
.settings(libraryDependencies ++= firrtlInterpreterLibDeps.value)
|
||||
.settings(libraryDependencies ++= treadleLibDeps.value)
|
||||
.settings(commonSettings)
|
||||
lazy val chiselTestersLibDeps = (chisel_testers / Keys.libraryDependencies)
|
||||
|
||||
// -- Normal Projects --
|
||||
|
||||
// Contains annotations & firrtl passes you may wish to use in rocket-chip without
|
||||
// introducing a circular dependency between RC and MIDAS
|
||||
lazy val midasTargetUtils = ProjectRef(firesimDir, "targetutils")
|
||||
|
||||
// Rocket-chip dependencies (subsumes making RC a RootProject)
|
||||
lazy val hardfloat = (project in rocketChipDir / "hardfloat")
|
||||
.settings(commonSettings).dependsOn(midasTargetUtils)
|
||||
|
||||
lazy val rocketMacros = (project in rocketChipDir / "macros")
|
||||
.settings(commonSettings)
|
||||
|
||||
lazy val rocketConfig = (project in rocketChipDir / "api-config-chipsalliance/build-rules/sbt")
|
||||
.settings(commonSettings)
|
||||
|
||||
lazy val rocketchip = freshProject("rocketchip", rocketChipDir)
|
||||
.settings(commonSettings)
|
||||
.dependsOn(chisel, hardfloat, rocketMacros, rocketConfig)
|
||||
|
||||
lazy val testchipip = (project in file("generators/testchipip"))
|
||||
.dependsOn(rocketchip, sifive_blocks)
|
||||
.settings(libraryDependencies ++= rocketLibDeps.value)
|
||||
.settings(commonSettings)
|
||||
lazy val testchipipLib = "edu.berkeley.cs" %% "testchipip" % "1.0-020719-SNAPSHOT"
|
||||
|
||||
lazy val iocell = (project in file("./tools/barstools/iocell/"))
|
||||
.dependsOn(chisel)
|
||||
.settings(commonSettings)
|
||||
|
||||
lazy val chipyard = conditionalDependsOn(project in file("generators/chipyard"))
|
||||
.dependsOn(boom, hwacha, sifive_blocks, sifive_cache, utilities, iocell,
|
||||
lazy val chipyard = (project in file("generators/chipyard"))
|
||||
.sourceDependency(testchipip, testchipipLib)
|
||||
.dependsOn(rocketchip, boom, hwacha, sifive_blocks, sifive_cache, utilities, iocell,
|
||||
sha3, // On separate line to allow for cleaner tutorial-setup patches
|
||||
dsptools, `rocket-dsptools`,
|
||||
gemmini, icenet, tracegen, cva6, nvdla, sodor)
|
||||
.settings(libraryDependencies ++= rocketLibDeps.value)
|
||||
.settings(commonSettings)
|
||||
|
||||
lazy val tracegen = conditionalDependsOn(project in file("generators/tracegen"))
|
||||
lazy val tracegen = (project in file("generators/tracegen"))
|
||||
.sourceDependency(testchipip, testchipipLib)
|
||||
.dependsOn(rocketchip, sifive_cache, boom, utilities)
|
||||
.settings(libraryDependencies ++= rocketLibDeps.value)
|
||||
.settings(commonSettings)
|
||||
|
||||
lazy val utilities = conditionalDependsOn(project in file("generators/utilities"))
|
||||
lazy val utilities = (project in file("generators/utilities"))
|
||||
.sourceDependency(testchipip, testchipipLib)
|
||||
.settings(commonSettings)
|
||||
|
||||
lazy val icenet = (project in file("generators/icenet"))
|
||||
.dependsOn(rocketchip, testchipip)
|
||||
.sourceDependency(testchipip, testchipipLib)
|
||||
.dependsOn(rocketchip)
|
||||
.settings(libraryDependencies ++= rocketLibDeps.value)
|
||||
.settings(commonSettings)
|
||||
|
||||
lazy val hwacha = (project in file("generators/hwacha"))
|
||||
.dependsOn(rocketchip)
|
||||
.settings(libraryDependencies ++= rocketLibDeps.value)
|
||||
.settings(commonSettings)
|
||||
|
||||
lazy val boom = conditionalDependsOn(project in file("generators/boom"))
|
||||
lazy val boom = (project in file("generators/boom"))
|
||||
.sourceDependency(testchipip, testchipipLib)
|
||||
.dependsOn(rocketchip)
|
||||
.settings(libraryDependencies ++= rocketLibDeps.value)
|
||||
.settings(commonSettings)
|
||||
|
||||
lazy val cva6 = (project in file("generators/cva6"))
|
||||
.dependsOn(rocketchip)
|
||||
.settings(libraryDependencies ++= rocketLibDeps.value)
|
||||
.settings(commonSettings)
|
||||
|
||||
lazy val sodor = (project in file("generators/riscv-sodor"))
|
||||
.dependsOn(rocketchip)
|
||||
.settings(libraryDependencies ++= rocketLibDeps.value)
|
||||
.settings(commonSettings)
|
||||
|
||||
lazy val sha3 = (project in file("generators/sha3"))
|
||||
.dependsOn(rocketchip, chisel_testers, midasTargetUtils)
|
||||
.settings(libraryDependencies ++= rocketLibDeps.value)
|
||||
.settings(libraryDependencies ++= chiselTestersLibDeps.value)
|
||||
.settings(commonSettings)
|
||||
|
||||
lazy val gemmini = (project in file("generators/gemmini"))
|
||||
.dependsOn(rocketchip, chisel_testers, testchipip)
|
||||
.sourceDependency(testchipip, testchipipLib)
|
||||
.dependsOn(rocketchip, chisel_testers)
|
||||
.settings(libraryDependencies ++= rocketLibDeps.value)
|
||||
.settings(libraryDependencies ++= chiselTestersLibDeps.value)
|
||||
.settings(commonSettings)
|
||||
|
||||
lazy val nvdla = (project in file("generators/nvdla"))
|
||||
.dependsOn(rocketchip)
|
||||
.settings(libraryDependencies ++= rocketLibDeps.value)
|
||||
.settings(commonSettings)
|
||||
|
||||
lazy val tapeout = conditionalDependsOn(project in file("./tools/barstools/tapeout/"))
|
||||
.dependsOn(chisel_testers, chipyard)
|
||||
lazy val iocell = (project in file("./tools/barstools/iocell/"))
|
||||
.sourceDependency(chiselRef, chiselLib)
|
||||
.settings(addCompilerPlugin(chiselPluginLib))
|
||||
.settings(libraryDependencies ++= chiselLibDeps.value)
|
||||
.settings(commonSettings)
|
||||
|
||||
lazy val tapeout = (project in file("./tools/barstools/tapeout/"))
|
||||
.dependsOn(chisel_testers, chipyard) // must depend on chipyard to get scala resources
|
||||
.settings(libraryDependencies ++= chiselTestersLibDeps.value)
|
||||
.settings(commonSettings)
|
||||
.settings(libraryDependencies ++= Seq("io.github.daviddenton" %% "handlebars-scala-fork" % "2.3.0"))
|
||||
|
||||
lazy val mdf = (project in file("./tools/barstools/mdf/scalalib/"))
|
||||
.settings(commonSettings)
|
||||
|
||||
lazy val barstoolsMacros = (project in file("./tools/barstools/macros/"))
|
||||
.dependsOn(firrtl_interpreter, mdf, rocketchip)
|
||||
.sourceDependency(chiselRef, chiselLib)
|
||||
.settings(addCompilerPlugin(chiselPluginLib))
|
||||
.settings(libraryDependencies ++= chiselLibDeps.value)
|
||||
.dependsOn(firrtl_interpreter, mdf, chisel_testers)
|
||||
.settings(libraryDependencies ++= chiselTestersLibDeps.value)
|
||||
.settings(libraryDependencies ++= firrtlInterpreterLibDeps.value)
|
||||
.enablePlugins(sbtassembly.AssemblyPlugin)
|
||||
.settings(commonSettings)
|
||||
|
||||
lazy val dsptools = freshProject("dsptools", file("./tools/dsptools"))
|
||||
.dependsOn(chisel, chisel_testers)
|
||||
.dependsOn(chisel_testers)
|
||||
.settings(libraryDependencies ++= chiselTestersLibDeps.value)
|
||||
.settings(
|
||||
commonSettings,
|
||||
libraryDependencies ++= Seq(
|
||||
"junit" % "junit" % "4.13" % "test",
|
||||
"org.scalatest" %% "scalatest" % "3.0.8",
|
||||
"org.scalacheck" %% "scalacheck" % "1.14.3" % "test"
|
||||
commonSettings,
|
||||
libraryDependencies ++= Seq(
|
||||
"org.typelevel" %% "spire" % "0.16.2",
|
||||
"org.scalanlp" %% "breeze" % "1.1",
|
||||
"junit" % "junit" % "4.13" % "test",
|
||||
"org.scalatest" %% "scalatest" % "3.0.+" % "test",
|
||||
"org.scalacheck" %% "scalacheck" % "1.14.3" % "test",
|
||||
))
|
||||
|
||||
lazy val `rocket-dsptools` = freshProject("rocket-dsptools", file("./tools/dsptools/rocket"))
|
||||
.dependsOn(rocketchip, dsptools)
|
||||
.settings(libraryDependencies ++= rocketLibDeps.value)
|
||||
.settings(commonSettings)
|
||||
|
||||
lazy val sifive_blocks = (project in file("generators/sifive-blocks"))
|
||||
.dependsOn(rocketchip)
|
||||
.settings(libraryDependencies ++= rocketLibDeps.value)
|
||||
.settings(commonSettings)
|
||||
|
||||
lazy val sifive_cache = (project in file("generators/sifive-cache")).settings(
|
||||
lazy val sifive_cache = (project in file("generators/sifive-cache"))
|
||||
.settings(
|
||||
commonSettings,
|
||||
scalaSource in Compile := baseDirectory.value / "design/craft"
|
||||
).dependsOn(rocketchip)
|
||||
scalaSource in Compile := baseDirectory.value / "design/craft")
|
||||
.dependsOn(rocketchip)
|
||||
.settings(libraryDependencies ++= rocketLibDeps.value)
|
||||
|
||||
// Library components of FireSim
|
||||
lazy val midas = ProjectRef(firesimDir, "midas")
|
||||
lazy val firesimLib = ProjectRef(firesimDir, "firesimLib")
|
||||
|
||||
lazy val firechip = conditionalDependsOn(project in file("generators/firechip"))
|
||||
lazy val firechip = (project in file("generators/firechip"))
|
||||
.sourceDependency(testchipip, testchipipLib)
|
||||
.dependsOn(chipyard, midasTargetUtils, midas, firesimLib % "test->test;compile->compile")
|
||||
.settings(
|
||||
commonSettings,
|
||||
testGrouping in Test := isolateAllTests( (definedTests in Test).value ),
|
||||
testOptions in Test += Tests.Argument("-oF")
|
||||
)
|
||||
lazy val fpga_shells = (project in file("./fpga/fpga-shells"))
|
||||
.dependsOn(rocketchip, sifive_blocks)
|
||||
.settings(libraryDependencies ++= rocketLibDeps.value)
|
||||
.settings(commonSettings)
|
||||
|
||||
lazy val fpga_platforms = (project in file("./fpga"))
|
||||
.dependsOn(chipyard, fpga_shells)
|
||||
.settings(commonSettings)
|
||||
|
||||
60
common.mk
60
common.mk
@@ -17,7 +17,8 @@ HELP_COMPILATION_VARIABLES += \
|
||||
" EXTRA_SIM_CXXFLAGS = additional CXXFLAGS for building simulators" \
|
||||
" EXTRA_SIM_LDFLAGS = additional LDFLAGS for building simulators" \
|
||||
" EXTRA_SIM_SOURCES = additional simulation sources needed for simulator" \
|
||||
" EXTRA_SIM_REQS = additional make requirements to build the simulator"
|
||||
" EXTRA_SIM_REQS = additional make requirements to build the simulator" \
|
||||
" ENABLE_SBT_THIN_CLIENT = if set, use sbt's experimental thin client"
|
||||
|
||||
EXTRA_GENERATOR_REQS ?=
|
||||
EXTRA_SIM_CXXFLAGS ?=
|
||||
@@ -41,7 +42,9 @@ HELP_COMMANDS += \
|
||||
" run-binary-fast = run [./$(shell basename $(sim))] and don't log instructions" \
|
||||
" run-binary-debug = run [./$(shell basename $(sim_debug))] and log instructions and waveform to files" \
|
||||
" verilog = generate intermediate verilog files from chisel elaboration and firrtl passes" \
|
||||
" run-tests = run all assembly and benchmark tests"
|
||||
" firrtl = generate intermediate firrtl files from chisel elaboration" \
|
||||
" run-tests = run all assembly and benchmark tests" \
|
||||
" launch-sbt = start sbt terminal"
|
||||
|
||||
#########################################################################################
|
||||
# include additional subproject make fragments
|
||||
@@ -58,42 +61,28 @@ include $(base_dir)/tools/dromajo/dromajo.mk
|
||||
# Returns a list of files in directory $1 with file extension $2.
|
||||
lookup_srcs = $(shell find -L $(1)/ -name target -prune -o -iname "*.$(2)" -print 2> /dev/null)
|
||||
|
||||
SOURCE_DIRS = $(addprefix $(base_dir)/,generators sims/firesim/sim tools/barstools/iocell)
|
||||
SOURCE_DIRS = $(addprefix $(base_dir)/,generators sims/firesim/sim tools/barstools/iocell fpga/fpga-shells fpga/src)
|
||||
SCALA_SOURCES = $(call lookup_srcs,$(SOURCE_DIRS),scala)
|
||||
VLOG_SOURCES = $(call lookup_srcs,$(SOURCE_DIRS),sv) $(call lookup_srcs,$(SOURCE_DIRS),v)
|
||||
# This assumes no SBT meta-build sources
|
||||
SBT_SOURCE_DIRS = $(addprefix $(base_dir)/,generators sims/firesim/sim tools)
|
||||
SBT_SOURCES = $(call lookup_srcs,$(SBT_SOURCE_DIRS),sbt) $(base_dir)/build.sbt $(base_dir)/project/plugins.sbt
|
||||
SBT_SOURCES = $(call lookup_srcs,$(SBT_SOURCE_DIRS),sbt) $(base_dir)/build.sbt $(base_dir)/project/plugins.sbt $(base_dir)/project/build.properties
|
||||
|
||||
#########################################################################################
|
||||
# jar creation variables and rules
|
||||
# SBT Server Setup (start server / rebuild proj. defs. if SBT_SOURCES change)
|
||||
#########################################################################################
|
||||
FIRRTL_JAR := $(base_dir)/lib/firrtl.jar
|
||||
FIRRTL_TEST_JAR := $(base_dir)/test_lib/firrtl-test.jar
|
||||
|
||||
$(FIRRTL_JAR): $(call lookup_srcs,$(CHIPYARD_FIRRTL_DIR),scala)
|
||||
$(MAKE) -C $(CHIPYARD_FIRRTL_DIR) SBT="$(SBT)" root_dir=$(CHIPYARD_FIRRTL_DIR) build-scala
|
||||
mkdir -p $(@D)
|
||||
cp -p $(CHIPYARD_FIRRTL_DIR)/utils/bin/firrtl.jar $@
|
||||
touch $@
|
||||
|
||||
$(FIRRTL_TEST_JAR): $(call lookup_srcs,$(CHIPYARD_FIRRTL_DIR),scala)
|
||||
cd $(CHIPYARD_FIRRTL_DIR) && $(SBT) "test:assembly"
|
||||
mkdir -p $(@D)
|
||||
cp -p $(CHIPYARD_FIRRTL_DIR)/utils/bin/firrtl-test.jar $@
|
||||
touch $@
|
||||
|
||||
#########################################################################################
|
||||
# Bloop Project Definitions
|
||||
#########################################################################################
|
||||
$(BLOOP_CONFIG_DIR)/TIMESTAMP: $(SBT_SOURCES)
|
||||
cd $(base_dir) && $(SBT) "project chipyardRoot" "bloopInstall"
|
||||
$(SBT_THIN_CLIENT_TIMESTAMP): $(SBT_SOURCES)
|
||||
ifneq (,$(wildcard $(SBT_THIN_CLIENT_TIMESTAMP)))
|
||||
cd $(base_dir) && $(SBT) "reload"
|
||||
touch $@
|
||||
else
|
||||
cd $(base_dir) && $(SBT) "exit"
|
||||
endif
|
||||
|
||||
#########################################################################################
|
||||
# create list of simulation file inputs
|
||||
#########################################################################################
|
||||
$(sim_files): $(call lookup_srcs,$(base_dir)/generators/utilities/src/main/scala,scala) $(FIRRTL_JAR) $(SCALA_BUILDTOOL_DEPS)
|
||||
$(sim_files): $(call lookup_srcs,$(base_dir)/generators/utilities/src/main/scala,scala) $(SCALA_BUILDTOOL_DEPS)
|
||||
$(call run_scala_main,utilities,utilities.GenerateSimFiles,-td $(build_dir) -sim $(sim_name))
|
||||
|
||||
#########################################################################################
|
||||
@@ -227,7 +216,7 @@ ifneq ($(filter run% %.run %.out %.vpd %.vcd,$(MAKECMDGOALS)),)
|
||||
endif
|
||||
|
||||
#######################################
|
||||
# Rules for building DRAMSim2 library #
|
||||
# Rules for building DRAMSim2 library
|
||||
#######################################
|
||||
|
||||
dramsim_dir = $(base_dir)/tools/DRAMSim2
|
||||
@@ -236,6 +225,23 @@ dramsim_lib = $(dramsim_dir)/libdramsim.a
|
||||
$(dramsim_lib):
|
||||
$(MAKE) -C $(dramsim_dir) $(notdir $@)
|
||||
|
||||
################################################
|
||||
# Helper to run SBT or manage the SBT server
|
||||
################################################
|
||||
|
||||
SBT_COMMAND ?= shell
|
||||
.PHONY: launch-sbt
|
||||
launch-sbt:
|
||||
cd $(base_dir) && $(SBT_NON_THIN) "$(SBT_COMMAND)"
|
||||
|
||||
.PHONY: shutdown-sbt-server
|
||||
shutdown-sbt-server:
|
||||
cd $(base_dir) && $(SBT) "shutdown"
|
||||
|
||||
.PHONY: start-sbt-server
|
||||
start-sbt-server:
|
||||
cd $(base_dir) && $(SBT) "exit"
|
||||
|
||||
#########################################################################################
|
||||
# print help text
|
||||
#########################################################################################
|
||||
|
||||
@@ -54,7 +54,7 @@ sends the TSI command recieved by the simulation stub into the DUT which then co
|
||||
command into a TileLink request. This conversion is done by the ``SerialAdapter`` module
|
||||
(located in the ``generators/testchipip`` project). In simulation, FESVR
|
||||
resets the DUT, writes into memory the test program, and indicates to the DUT to start the program
|
||||
through an interrupt (see :ref:`Chipyard Boot Process`). Using TSI is currently the fastest
|
||||
through an interrupt (see :ref:`customization/Boot-Process:Chipyard Boot Process`). Using TSI is currently the fastest
|
||||
mechanism to communicate with the DUT in simulation.
|
||||
|
||||
In the case of a chip tapeout bringup, TSI commands can be sent over a custom communication
|
||||
@@ -96,7 +96,7 @@ Starting the TSI or DMI Simulation
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
All default Chipyard configurations use TSI to communicate between the simulation and the simulated SoC/DUT. Hence, when running a
|
||||
software RTL simulation, as is indicated in the :ref:`Software RTL Simulation` section, you are in-fact using TSI to communicate with the DUT. As a
|
||||
software RTL simulation, as is indicated in the :ref:`simulation/Software-RTL-Simulation:Software RTL Simulation` section, you are in-fact using TSI to communicate with the DUT. As a
|
||||
reminder, to run a software RTL simulation, run:
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
Debugging BOOM
|
||||
======================
|
||||
|
||||
In addition to the default debugging techniques specified in :ref:`Debugging RTL`,
|
||||
single-core BOOM designs can utilize the Dromajo co-simulator (see :ref:`Dromajo`)
|
||||
In addition to the default debugging techniques specified in :ref:`Advanced-Concepts/Debugging-RTL:Debugging RTL`,
|
||||
single-core BOOM designs can utilize the Dromajo co-simulator (see :ref:`Tools/Dromajo:Dromajo`)
|
||||
to verify functionality.
|
||||
|
||||
.. warning:: Dromajo currently only works in single-core BOOM systems without accelerators.
|
||||
|
||||
@@ -58,7 +58,7 @@ Tops
|
||||
|
||||
A SoC Top then extends the ``System`` class with traits for custom components.
|
||||
In Chipyard, this includes things like adding a NIC, UART, and GPIO as well as setting up the hardware for the bringup method.
|
||||
Please refer to :ref:`Communicating with the DUT` for more information on these bringup methods.
|
||||
Please refer to :ref:`Advanced-Concepts/Chip-Communication:Communicating with the DUT` for more information on these bringup methods.
|
||||
|
||||
TestHarness
|
||||
-------------------------
|
||||
|
||||
@@ -14,15 +14,15 @@ Processor Cores
|
||||
|
||||
**Rocket Core**
|
||||
An in-order RISC-V core.
|
||||
See :ref:`Rocket Core` for more information.
|
||||
See :ref:`Generators/Rocket:Rocket Core` for more information.
|
||||
|
||||
**BOOM (Berkeley Out-of-Order Machine)**
|
||||
An out-of-order RISC-V core.
|
||||
See :ref:`Berkeley Out-of-Order Machine (BOOM)` for more information.
|
||||
See :ref:`Generators/BOOM:Berkeley Out-of-Order Machine (BOOM)` for more information.
|
||||
|
||||
**CVA6 Core**
|
||||
An in-order RISC-V core written in System Verilog. Previously called Ariane.
|
||||
See :ref:`CVA6 Core` for more information.
|
||||
See :ref:`Generators/CVA6:CVA6 Core` for more information.
|
||||
|
||||
Accelerators
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
@@ -31,7 +31,7 @@ Accelerators
|
||||
A decoupled vector architecture co-processor.
|
||||
Hwacha currently implements a non-standard RISC-V extension, using a vector architecture programming model.
|
||||
Hwacha integrates with a Rocket or BOOM core using the RoCC (Rocket Custom Co-processor) interface.
|
||||
See :ref:`Hwacha` for more information.
|
||||
See :ref:`Generators/Hwacha:Hwacha` for more information.
|
||||
|
||||
**Gemmini**
|
||||
A matrix-multiply accelerator targeting neural-networks
|
||||
@@ -64,24 +64,24 @@ Tools
|
||||
A hardware description library embedded in Scala.
|
||||
Chisel is used to write RTL generators using meta-programming, by embedding hardware generation primitives in the Scala programming language.
|
||||
The Chisel compiler elaborates the generator into a FIRRTL output.
|
||||
See :ref:`Chisel` for more information.
|
||||
See :ref:`Tools/Chisel:Chisel` for more information.
|
||||
|
||||
**FIRRTL**
|
||||
An intermediate representation library for RTL description of digital designs.
|
||||
FIRRTL is used as a formalized digital circuit representation between Chisel and Verilog.
|
||||
FIRRTL enables digital circuits manipulation between Chisel elaboration and Verilog generation.
|
||||
See :ref:`FIRRTL` for more information.
|
||||
See :ref:`Tools/FIRRTL:FIRRTL` for more information.
|
||||
|
||||
**Barstools**
|
||||
A collection of common FIRRTL transformations used to manipulate a digital circuit without changing the generator source RTL.
|
||||
See :ref:`Barstools` for more information.
|
||||
See :ref:`Tools/Barstools:Barstools` for more information.
|
||||
|
||||
**Dsptools**
|
||||
A Chisel library for writing custom signal processing hardware, as well as integrating custom signal processing hardware into an SoC (especially a Rocket-based SoC).
|
||||
|
||||
**Dromajo**
|
||||
A RV64GC emulator primarily used for co-simulation and was originally developed by Esperanto Technologies.
|
||||
See :ref:`Dromajo` for more information.
|
||||
See :ref:`Tools/Dromajo:Dromajo` for more information.
|
||||
|
||||
Toolchains
|
||||
-------------------------------------------
|
||||
@@ -106,15 +106,15 @@ Software
|
||||
Sims
|
||||
-------------------------------------------
|
||||
|
||||
**verilator (Verilator wrapper)**
|
||||
**Verilator**
|
||||
Verilator is an open source Verilog simulator.
|
||||
The ``verilator`` directory provides wrappers which construct Verilator-based simulators from relevant generated RTL, allowing for execution of test RISC-V programs on the simulator (including vcd waveform files).
|
||||
See :ref:`Verilator (Open-Source)` for more information.
|
||||
See :ref:`Simulation/Software-RTL-Simulation:Verilator (Open-Source)` for more information.
|
||||
|
||||
**vcs (VCS wrapper)**
|
||||
**VCS**
|
||||
VCS is a proprietary Verilog simulator.
|
||||
Assuming the user has valid VCS licenses and installations, the ``vcs`` directory provides wrappers which construct VCS-based simulators from relevant generated RTL, allowing for execution of test RISC-V programs on the simulator (including vcd/vpd waveform files).
|
||||
See :ref:`Synopsys VCS (License Required)` for more information.
|
||||
See :ref:`Simulation/Software-RTL-Simulation:Synopsys VCS (License Required)` for more information.
|
||||
|
||||
**FireSim**
|
||||
FireSim is an open-source FPGA-accelerated simulation platform, using Amazon Web Services (AWS) EC2 F1 instances on the public cloud.
|
||||
@@ -122,7 +122,16 @@ Sims
|
||||
To model I/O, FireSim includes synthesizeable and timing-accurate models for standard interfaces like DRAM, Ethernet, UART, and others.
|
||||
The use of the elastic public cloud enable FireSim to scale simulations up to thousands of nodes.
|
||||
In order to use FireSim, the repository must be cloned and executed on AWS instances.
|
||||
See :ref:`FireSim` for more information.
|
||||
See :ref:`Simulation/FPGA-Accelerated-Simulation:FireSim` for more information.
|
||||
|
||||
Prototyping
|
||||
-------------------------------------------
|
||||
|
||||
**FPGA Prototyping**
|
||||
FPGA prototyping is supported in Chipyard using SiFive's ``fpga-shells``.
|
||||
Some examples of FPGAs supported are the Xilinx Arty 35T and VCU118 boards.
|
||||
For a fast and deterministic simulation with plenty of debugging tools, please consider using the :ref:`Simulation/FPGA-Accelerated-Simulation:FireSim` platform.
|
||||
See :ref:`Prototyping/index:Prototyping Flow` for more information on FPGA prototypes.
|
||||
|
||||
VLSI
|
||||
-------------------------------------------
|
||||
@@ -132,4 +141,4 @@ VLSI
|
||||
The HAMMER flow provide automated scripts which generate relevant tool commands based on a higher level description of physical design constraints.
|
||||
The Hammer flow also allows for re-use of process technology knowledge by enabling the construction of process-technology-specific plug-ins, which describe particular constraints relating to that process technology (obsolete standard cells, metal layer routing constraints, etc.).
|
||||
The Hammer flow requires access to proprietary EDA tools and process technology libraries.
|
||||
See :ref:`Core HAMMER` for more information.
|
||||
See :ref:`VLSI/Hammer:Core HAMMER` for more information.
|
||||
|
||||
@@ -17,7 +17,7 @@ Configs
|
||||
A *config* is a collection of multiple generator parameters being set to specific values.
|
||||
Configs are additive, can override each other, and can be composed of other configs (sometimes referred to as config fragments).
|
||||
The naming convention for an additive config or config fragment is ``With<YourConfigName>``, while the naming convention for a non-additive config will be ``<YourConfig>``.
|
||||
Configs can take arguments which will in-turn set parameters in the design or reference other parameters in the design (see :ref:`Parameters`).
|
||||
Configs can take arguments which will in-turn set parameters in the design or reference other parameters in the design (see :ref:`Chipyard-Basics/Configs-Parameters-Mixins:Parameters`).
|
||||
|
||||
This example shows a basic config fragment class that takes in zero arguments and instead uses hardcoded values to set the RTL design parameters.
|
||||
In this example, ``MyAcceleratorConfig`` is a Scala case class that defines a set of variables that the generator can use when referencing the ``MyAcceleratorKey`` in the design.
|
||||
@@ -121,7 +121,7 @@ This is shown in the ``Top`` class where things such as ``CanHavePeripherySerial
|
||||
Additional References
|
||||
---------------------------
|
||||
|
||||
Another description of traits/mixins and config fragments is given in :ref:`Keys, Traits, and Configs`.
|
||||
Another description of traits/mixins and config fragments is given in :ref:`Customization/Keys-Traits-Configs:Keys, Traits, and Configs`.
|
||||
Additionally, a brief explanation of some of these topics (with slightly different naming) is given in the following video: https://www.youtube.com/watch?v=Eko86PGEoDY.
|
||||
|
||||
.. Note:: Chipyard uses the name "config fragments" over "config mixins" to avoid confusion between a mixin applying to a config or to the system ``Top`` (even though both are technically Scala mixins).
|
||||
|
||||
@@ -73,7 +73,7 @@ This depends on what you are planning to do with Chipyard.
|
||||
|
||||
* If you intend to run a simulation of one of the vanilla Chipyard examples, go to :ref:`sw-rtl-sim-intro` and follow the instructions.
|
||||
|
||||
* If you intend to run a simulation of a custom Chipyard SoC Configuration, go to :ref:`Simulating A Custom Project` and follow the instructions.
|
||||
* If you intend to run a simulation of a custom Chipyard SoC Configuration, go to :ref:`Simulation/Software-RTL-Simulation:Simulating A Custom Project` and follow the instructions.
|
||||
|
||||
* If you intend to run a full-system FireSim simulation, go to :ref:`firesim-sim-intro` and follow the instructions.
|
||||
|
||||
|
||||
@@ -34,7 +34,7 @@ FESVR is a program that runs on the host CPU and can read/write arbitrary
|
||||
parts of the target system memory using the Tethered Serial Interface (TSI).
|
||||
|
||||
FESVR uses TSI to load a baremetal executable or second-stage bootloader into
|
||||
the SoC memory. In :ref:`Software RTL Simulation`, this will be the binary you
|
||||
the SoC memory. In :ref:`Simulation/Software-RTL-Simulation:Software RTL Simulation`, this will be the binary you
|
||||
pass to the simulator. Once it is finished loading the program, FESVR will
|
||||
write to the software interrupt register for CPU 0, which will bring CPU 0
|
||||
out of its WFI loop. Once it receives the interrupt, CPU 0 will write to
|
||||
|
||||
@@ -22,7 +22,7 @@ that writes zeros to the memory at a configured address.
|
||||
|
||||
We use ``TLHelper.makeClientNode`` to create a TileLink client node for us.
|
||||
We then connect the client node to the memory system through the front bus (fbus).
|
||||
For more info on creating TileLink client nodes, take a look at :ref:`Client Node`.
|
||||
For more info on creating TileLink client nodes, take a look at :ref:`TileLink-Diplomacy-Reference/NodeTypes:Client Node`.
|
||||
|
||||
Once we've created our top-level module including the DMA widget, we can create a configuration for it as we did before.
|
||||
|
||||
|
||||
@@ -5,7 +5,7 @@ Adding a Firrtl Transform
|
||||
|
||||
Similar to how LLVM IR passes can perform transformations and optimizations on software, FIRRTL transforms can
|
||||
modify Chisel-elaborated RTL.
|
||||
As mentioned in Section :ref:`firrtl`, transforms are modifications that happen on the FIRRTL IR that can modify a circuit.
|
||||
As mentioned in Section :ref:`Tools/FIRRTL:firrtl`, transforms are modifications that happen on the FIRRTL IR that can modify a circuit.
|
||||
Transforms are a powerful tool to take in the FIRRTL IR that is emitted from Chisel and run analysis or convert the circuit into a new form.
|
||||
|
||||
Where to add transforms
|
||||
@@ -24,7 +24,7 @@ If you look inside of the `tools/barstools/tapeout/src/main/scala/transforms/Gen
|
||||
you can see that FIRRTL is invoked twice, once for the "Top" and once for the "Harness". If you want to add transforms to just modify the DUT, you can add them to ``topTransforms``.
|
||||
Otherwise, if you want to add transforms to just modify the test harness, you can add them to ``harnessTransforms``.
|
||||
|
||||
For more information on Barstools, please visit the :ref:`Barstools` section.
|
||||
For more information on Barstools, please visit the :ref:`Tools/Barstools:Barstools` section.
|
||||
|
||||
Examples of transforms
|
||||
----------------------
|
||||
|
||||
@@ -13,7 +13,7 @@ if you use the ``WithNMedCores`` or ``WithNSmallCores`` configurations, you can
|
||||
configure 4 KiB direct-mapped caches for L1I and L1D.
|
||||
|
||||
If you only want to change the size or associativity, there are config
|
||||
fragments for those too. See :ref:`Config Fragments` for how to add these to a custom ``Config``.
|
||||
fragments for those too. See :ref:`Customization/Keys-Traits-Configs:Config Fragments` for how to add these to a custom ``Config``.
|
||||
|
||||
.. code-block:: scala
|
||||
|
||||
|
||||
@@ -8,11 +8,11 @@ A diagram of IceNet's microarchitecture is shown below.
|
||||
|
||||
.. image:: ../_static/images/nic-design.png
|
||||
|
||||
There are four basic parts of the NIC: the :ref:`Controller`, which takes requests
|
||||
from and sends responses to the CPU; the :ref:`Send Path`, which reads data from
|
||||
memory and sends it out to the network; the :ref:`Receive Path`, which receives
|
||||
There are four basic parts of the NIC: the :ref:`Generators/IceNet:Controller`, which takes requests
|
||||
from and sends responses to the CPU; the :ref:`Generators/IceNet:Send Path`, which reads data from
|
||||
memory and sends it out to the network; the :ref:`Generators/IceNet:Receive Path`, which receives
|
||||
data from the network and writes it to memory; and, optionally,
|
||||
the :ref:`Pause Handler`, which generates Ethernet pause frames for the purpose
|
||||
the :ref:`Generators/IceNet:Pause Handler`, which generates Ethernet pause frames for the purpose
|
||||
of flow control.
|
||||
|
||||
Controller
|
||||
@@ -78,7 +78,7 @@ Configuration
|
||||
To add IceNIC to your design, add ``HasPeripheryIceNIC`` to your lazy module
|
||||
and ``HasPeripheryIceNICModuleImp`` to the module implementation. If you
|
||||
are confused about the distinction between lazy module and module
|
||||
implementation, refer to :ref:`Cake Pattern / Mixin`.
|
||||
implementation, refer to :ref:`Chipyard-Basics/Configs-Parameters-Mixins:Cake Pattern / Mixin`.
|
||||
|
||||
Then add the ``WithIceNIC`` config fragment to your configuration. This will
|
||||
define ``NICKey``, which IceNIC uses to determine its parameters. The config fragment
|
||||
|
||||
@@ -30,7 +30,7 @@ The tiles connect to the ``SystemBus``, which connect it to the L2 cache banks.
|
||||
The L2 cache banks then connect to the ``MemoryBus``, which connects to the
|
||||
DRAM controller through a TileLink to AXI converter.
|
||||
|
||||
To learn more about the memory hierarchy, see :ref:`Memory Hierarchy`.
|
||||
To learn more about the memory hierarchy, see :ref:`Customization/Memory-Hierarchy:Memory Hierarchy`.
|
||||
|
||||
MMIO
|
||||
----
|
||||
|
||||
@@ -2,9 +2,9 @@ Test Chip IP
|
||||
============
|
||||
|
||||
Chipyard includes a Test Chip IP library which provides various hardware
|
||||
widgets that may be useful when designing SoCs. This includes a :ref:`Serial Adapter`,
|
||||
:ref:`Block Device Controller`, :ref:`TileLink SERDES`, :ref:`TileLink Switcher`,
|
||||
:ref:`TileLink Ring Network`, and :ref:`UART Adapter`.
|
||||
widgets that may be useful when designing SoCs. This includes a :ref:`Generators/TestChipIP:Serial Adapter`,
|
||||
:ref:`Generators/TestChipIP:Block Device Controller`, :ref:`Generators/TestChipIP:TileLink SERDES`, :ref:`Generators/TestChipIP:TileLink Switcher`,
|
||||
:ref:`Generators/TestChipIP:TileLink Ring Network`, and :ref:`Generators/TestChipIP:UART Adapter`.
|
||||
|
||||
Serial Adapter
|
||||
--------------
|
||||
@@ -14,7 +14,7 @@ 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
|
||||
system. The frontend server uses this functionality to load the test program
|
||||
into memory and to poll for completion of the program. More information on
|
||||
this can be found in :ref:`Chipyard Boot Process`.
|
||||
this can be found in :ref:`Customization/Boot-Process:Chipyard Boot Process`.
|
||||
|
||||
Block Device Controller
|
||||
-----------------------
|
||||
@@ -69,7 +69,7 @@ to the TLXbar provided by RocketChip, but uses ring networks internally rather
|
||||
than crossbars. This can be useful for chips with very wide TileLink networks
|
||||
(many cores and L2 banks) that can sacrifice cross-section bandwidth to relieve
|
||||
wire routing congestion. Documentation on how to use the ring network can be
|
||||
found in :ref:`The System Bus`. The implementation itself can be found
|
||||
found in :ref:`Customization/Memory-Hierarchy:The System Bus`. The implementation itself can be found
|
||||
`here <https://github.com/ucb-bar/testchipip/blob/master/src/main/scala/Ring.scala>`_,
|
||||
and may serve as an example of how to implement your own TileLink network with
|
||||
a different topology.
|
||||
|
||||
@@ -4,7 +4,7 @@ Included RTL Generators
|
||||
============================
|
||||
|
||||
A Generator can be thought of as a generalized RTL design, written using a mix of meta-programming and standard RTL.
|
||||
This type of meta-programming is enabled by the Chisel hardware description language (see :ref:`Chisel`).
|
||||
This type of meta-programming is enabled by the Chisel hardware description language (see :ref:`Tools/Chisel:Chisel`).
|
||||
A standard RTL design is essentially just a single instance of a design coming from a generator.
|
||||
However, by using meta-programming and parameter systems, generators can allow for integration of complex hardware designs in automated ways.
|
||||
The following pages introduce the generators integrated with the Chipyard framework.
|
||||
|
||||
26
docs/Prototyping/Arty.rst
Normal file
26
docs/Prototyping/Arty.rst
Normal file
@@ -0,0 +1,26 @@
|
||||
Running a Design on Arty
|
||||
========================
|
||||
|
||||
Basic Arty Design
|
||||
-----------------
|
||||
|
||||
The default Xilinx Arty 35T harness is setup to have JTAG available over the board's PMOD pins, and UART available over its FTDI serial USB adapter. The pin mappings for JTAG signals are identical to those described in the `SiFive Freedom E310 Arty 35T Getting Started Guide <https://static.dev.sifive.com/SiFive-E310-arty-gettingstarted-v1.0.6.pdf>`__.
|
||||
The JTAG interface allows a user to connect to the core via OpenOCD, run bare-metal applications, and debug these applications with gdb. UART allows a user to communicate with the core over a USB connection and serial console running on a PC.
|
||||
To extend this design, a user may create their own Chipyard configuration and add the ``WithArtyTweaks`` located in ``fpga/src/main/scala/arty/Configs.scala``.
|
||||
Adding this config. fragment will enable and connect the JTAG and UART interfaces to your Chipyard design.
|
||||
|
||||
.. literalinclude:: ../../fpga/src/main/scala/arty/Configs.scala
|
||||
:language: scala
|
||||
:start-after: DOC include start: AbstractArty and Rocket
|
||||
:end-before: DOC include end: AbstractArty and Rocket
|
||||
|
||||
Future peripherals to be supported include the Arty 35T SPI Flash EEPROM, and I2C/PWM/SPI over the Arty 35T GPIO pins. These peripherals are available as part of sifive-blocks.
|
||||
|
||||
Brief Implementation Description and Guidance for Adding/Changing Xilinx Collateral
|
||||
-----------------------------------------------------------------------------------
|
||||
|
||||
Like the VCU118, the basis for the Arty 35T design is the creation of a special test harness that connects the external IO (which exist as Xilinx IP blackboxes) to the Chipyard design.
|
||||
This is done with the ``ArtyTestHarness`` in the basic default Arty 35T target. However, unlike the ``VCU118TestHarness``, the ``ArtyTestHarness`` uses no ``Overlays``, and instead directly connects chip top IO to the ports of the external IO blackboxes, using functions such as ``IOBUF`` provided by ``fpga-shells``.
|
||||
Unlike the VCU118 and other more complicated test harnesses, the Arty 35T Vivado collateral is not generated by ``Overlays``, but rather are a static collection of ``create_ip`` and ``set_properties`` statements located in the files within ``fpga/fpga-shells/xilinx/arty/tcl`` and ``fpga/fpga-shells/xilinx/arty/constraints``.
|
||||
If the user wishes to re-map FPGA package pins to different harness-level IO, this may be changed within ``fpga/fpga-shells/xilinx/arty/constraints/arty-master.xdc``. The addition of new Xilinx IP blocks may be done in ``fpga-shells/xilinx/arty/tcl/ip.tcl``, mapped to harness-level IOs in ``arty-master.xdc``, and wired through from the test harness to the chip top using ``HarnessBinders`` and ``IOBinders``.
|
||||
Examples of a simple ``IOBinder`` and ``HarnessBinder`` for routing signals (in this case the debug and JTAG resets) from the core to the test harness are the ``WithResetPassthrough`` and ``WithArtyResetHarnessBinder``.
|
||||
70
docs/Prototyping/General.rst
Normal file
70
docs/Prototyping/General.rst
Normal file
@@ -0,0 +1,70 @@
|
||||
General Setup and Usage
|
||||
==============================
|
||||
|
||||
Sources and Submodule Setup
|
||||
---------------------------
|
||||
|
||||
All FPGA prototyping-related collateral and sources are located in the ``fpga`` top-level Chipyard directory.
|
||||
This includes the ``fpga-shells`` submodule and the ``src`` directory that hold both Scala, TCL and other collateral.
|
||||
However, the ``fpga-shells`` submodule repository is not initialized by default.
|
||||
To initialize the ``fpga-shells`` submodule repository, run the included initialization script from the Chipyard top-level directory:
|
||||
|
||||
.. code-block:: shell
|
||||
|
||||
# in the chipyard top level folder
|
||||
./scripts/init-fpga.sh
|
||||
|
||||
Generating a Bitstream
|
||||
----------------------
|
||||
|
||||
Generating a bitstream for any FPGA target using Vivado is similar to building RTL for a software RTL simulation.
|
||||
Similar to a software RTL simulation (:ref:`Simulation/Software-RTL-Simulation:Simulating A Custom Project`), you can run the following command in the ``fpga`` directory to build a bitstream using Vivado:
|
||||
|
||||
.. code-block:: shell
|
||||
|
||||
make SBT_PROJECT=... MODEL=... VLOG_MODEL=... MODEL_PACKAGE=... CONFIG=... CONFIG_PACKAGE=... GENERATOR_PACKAGE=... TB=... TOP=... BOARD=... FPGA_BRAND=... bitstream
|
||||
|
||||
# or
|
||||
|
||||
make SUB_PROJECT=<sub_project> bitstream
|
||||
|
||||
The ``SUB_PROJECT`` make variable is a way to meta make variable that sets all of the other make variables to a specific default.
|
||||
For example:
|
||||
|
||||
.. code-block:: shell
|
||||
|
||||
make SUB_PROJECT=vcu118 bitstream
|
||||
|
||||
# converts to
|
||||
|
||||
make SBT_PROJECT=fpga_platforms MODEL=VCU118FPGATestHarness VLOG_MODEL=VCU118FPGATestHarness MODEL_PACKAGE=chipyard.fpga.vcu118 CONFIG=RocketVCU118Config CONFIG_PACKAGE=chipyard.fpga.vcu118 GENERATOR_PACKAGE=chipyard TB=none TOP=ChipTop BOARD=vcu118 FPGA_BRAND=... bitstream
|
||||
|
||||
Some ``SUB_PROJECT`` defaults are already defined for use, including ``vcu118`` and ``arty``.
|
||||
These default ``SUB_PROJECT``'s setup the necessary test harnesses, packages, and more for the Chipyard make system.
|
||||
Like a software RTL simulation make invocation, all of the make variables can be overridden with user specific values (ex. include the ``SUB_PROJECT`` with a ``CONFIG`` and ``CONFIG_PACKAGE`` override).
|
||||
In most cases, you will just need to run a command with a ``SUB_PROJECT`` and an overridden ``CONFIG`` to point to.
|
||||
For example, building the BOOM configuration on the VCU118:
|
||||
|
||||
.. code-block:: shell
|
||||
|
||||
make SUB_PROJECT=vcu118 CONFIG=BoomVCU118Config bitstream
|
||||
|
||||
That command will build the RTL and generate a bitstream using Vivado.
|
||||
The generated bitstream will be located in your designs specific build folder (``generated-src/<LONG_NAME>/obj``).
|
||||
However, like a software RTL simulation, you can also run the intermediate make steps to just generate Verilog or FIRRTL.
|
||||
|
||||
Debugging with ILAs on Supported FPGAs
|
||||
--------------------------------------
|
||||
|
||||
ILA (integrated logic analyzers) can be added to certain designs for debugging relevant signals.
|
||||
First, open up the post synthesis checkpoint located in the build directory for your design in Vivado (it should be labeled ``post_synth.dcp``).
|
||||
Then using Vivado, add ILAs (and other debugging tools) for your design (search online for more information on how to add an ILA).
|
||||
This can be done by modifying the post synthesis checkpoint, saving it, and running ``make ... debug-bitstream``.
|
||||
This will create a new bitstream called ``top.bit`` in a folder named ``generated-src/<LONG_NAME>/debug_obj/``.
|
||||
For example, running the bitstream build for an added ILA for a BOOM config.:
|
||||
|
||||
.. code-block:: shell
|
||||
|
||||
make SUB_PROJECT=vcu118 CONFIG=BoomVCU118Config debug-bitstream
|
||||
|
||||
.. IMPORTANT:: For more extensive debugging tools for FPGA simulations including printf synthesis, assert synthesis, instruction traces, ILAs, out-of-band profiling, co-simulation, and more, please refer to the :ref:`Simulation/FPGA-Accelerated-Simulation:FireSim` platform.
|
||||
60
docs/Prototyping/VCU118.rst
Normal file
60
docs/Prototyping/VCU118.rst
Normal file
@@ -0,0 +1,60 @@
|
||||
Running a Design on VCU118
|
||||
==========================
|
||||
|
||||
Basic VCU118 Design
|
||||
-------------------
|
||||
|
||||
The default Xilinx VCU118 harness is setup to have UART, a SPI SDCard, and DDR backing memory.
|
||||
This allows it to run RISC-V Linux from an SDCard while piping the terminal over UART to the host machine (the machine connected to the VCU118).
|
||||
To extend this design, you can create your own Chipyard configuration and add the ``WithVCU118Tweaks`` located in ``fpga/src/main/scala/vcu118/Configs.scala``.
|
||||
Adding this config fragment will enable and connect the UART, SPI SDCard, and DDR backing memory to your Chipyard design/config.
|
||||
|
||||
.. literalinclude:: ../../fpga/src/main/scala/vcu118/Configs.scala
|
||||
:language: scala
|
||||
:start-after: DOC include start: AbstractVCU118 and Rocket
|
||||
:end-before: DOC include end: AbstractVCU118 and Rocket
|
||||
|
||||
Brief Implementation Description + More Complicated Designs
|
||||
-----------------------------------------------------------
|
||||
|
||||
The basis for a VCU118 design revolves around creating a special test harness to connect the external IOs to your Chipyard design.
|
||||
This is done with the ``VCU118TestHarness`` in the basic default VCU118 FPGA target.
|
||||
The ``VCU118TestHarness`` (located in ``fpga/src/main/scala/vcu118/TestHarness.scala``) uses ``Overlays`` that connect to the VCU118 external IOs.
|
||||
Generally, the ``Overlays`` take an IO from the ``ChipTop`` (labeled as ``topDesign`` in the file) when "placed" and connect it to the external IO and generate necessary Vivado collateral.
|
||||
For example, the following shows a UART ``Overlay`` being "placed" into the design with a IO input called ``io_uart_bb``.
|
||||
|
||||
.. literalinclude:: ../../fpga/src/main/scala/vcu118/TestHarness.scala
|
||||
:language: scala
|
||||
:start-after: DOC include start: UartOverlay
|
||||
:end-before: DOC include end: UartOverlay
|
||||
|
||||
Here the ``UARTOverlayKey`` is referenced and used to "place" the necessary connections (and collateral) to connect to the UART.
|
||||
The ``UARTDesignInput`` is used to pass in the UART IO from the ``ChipTop``/``topDesign`` to the ``Overlay``.
|
||||
Note that the ``BundleBridgeSource`` can be viewed as a glorified wire (that is defined in the ``LazyModule`` scope).
|
||||
This pattern is similar for all other ``Overlays`` in the test harness.
|
||||
They must be "placed" and given a set of inputs (IOs, parameters).
|
||||
The main exception to this pattern is the ``Overlay`` used to generate the clock(s) for the FPGA.
|
||||
|
||||
.. literalinclude:: ../../fpga/src/main/scala/vcu118/TestHarness.scala
|
||||
:language: scala
|
||||
:start-after: DOC include start: ClockOverlay
|
||||
:end-before: DOC include end: ClockOverlay
|
||||
|
||||
Without going into too much detail, the clocks overlay is placed in the harness and a PLL node (``harnessSysPLL``) generates the necessary clocks specified by ``ClockSinkNodes``.
|
||||
For ease of use, you can change the ``FPGAFrequencyKey`` to change the default clock frequency of the FPGA design.
|
||||
|
||||
After the harness is created, the ``BundleBridgeSource``'s must be connected to the ``ChipTop`` IOs.
|
||||
This is done with harness binders and io binders (see ``fpga/src/main/scala/vcu118/HarnessBinders.scala`` and ``fpga/src/main/scala/vcu118/IOBinders.scala``).
|
||||
For more information on harness binders and io binders, refer to :ref:`Customization/IOBinders:IOBinders and HarnessBinders`.
|
||||
|
||||
Introduction to the Bringup Platform
|
||||
------------------------------------
|
||||
|
||||
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).
|
||||
Extensions include another UART (connected over FMC), I2C (connected over FMC), miscellaneous GPIOS (can be connected to anything), and a TSI Host Widget.
|
||||
The TSI Host Widget is used to interact with the DUT from the prototype over a SerDes link (sometimes called the Low BandWidth InterFace - LBWIF) and provide access to a channel of the FPGA's DRAM.
|
||||
|
||||
.. Note:: Remember that since whenever a new test harness is created (or the config changes, or the config packages changes, or...), you need to modify the make invocation.
|
||||
For example, ``make SUB_PROJECT=vcu118 CONFIG=MyNewVCU118Config CONFIG_PACKAGE=this.is.my.scala.package bitstream``.
|
||||
See :ref:`Prototyping/General:Generating a Bitstream` for information on the various make variables.
|
||||
16
docs/Prototyping/index.rst
Normal file
16
docs/Prototyping/index.rst
Normal file
@@ -0,0 +1,16 @@
|
||||
Prototyping Flow
|
||||
================
|
||||
|
||||
Chipyard supports FPGA prototyping for local FPGAs supported by `fpga-shells <https://github.com/sifive/fpga-shells>`__.
|
||||
This includes popular FPGAs such as the Xilinx VCU118 and the Xilinx Arty 35T board.
|
||||
|
||||
.. Note:: While ``fpga-shells`` provides harnesses for other FPGA development boards such as the Xilinx VC707 and some MicroSemi PolarFire, only harnesses for the Xilinx VCU118 and Xilinx Arty 35T boards are currently supported in Chipyard.
|
||||
However, the VCU118 and Arty 35T examples demonstrate how a user may implement support for other harnesses provided by fpga-shells.
|
||||
|
||||
.. toctree::
|
||||
:maxdepth: 2
|
||||
:caption: Prototyping Flow:
|
||||
|
||||
General
|
||||
VCU118
|
||||
Arty
|
||||
@@ -3,14 +3,14 @@ Simulation
|
||||
|
||||
Chipyard supports two classes of simulation:
|
||||
|
||||
#. Software RTL simulation using commercial or open-source (Verilator) RTL simulators
|
||||
#. Software RTL simulation using commercial or open-source (Verilator) RTL simulators
|
||||
#. FPGA-accelerated full-system simulation using FireSim
|
||||
|
||||
Software RTL simulators of Chipyard designs run at O(1 KHz), but compile
|
||||
quickly and provide full waveforms. Conversly, FPGA-accelerated simulators run
|
||||
quickly and provide full waveforms. Conversely, FPGA-accelerated simulators run
|
||||
at O(100 MHz), making them appropriate for booting an operating system and
|
||||
running a complete workload, but have multi-hour compile times and poorer debug
|
||||
visability.
|
||||
visibility.
|
||||
|
||||
Click next to see how to run a simulation.
|
||||
|
||||
@@ -20,4 +20,3 @@ Click next to see how to run a simulation.
|
||||
|
||||
Software-RTL-Simulation
|
||||
FPGA-Accelerated-Simulation
|
||||
|
||||
|
||||
@@ -59,7 +59,7 @@ TileLink messages.
|
||||
|
||||
The ``edge`` object represents the edge of the Diplomacy graph. It contains
|
||||
some useful helper functions which will be documented in
|
||||
:ref:`TileLink Edge Object Methods`.
|
||||
:ref:`TileLink-Diplomacy-Reference/EdgeFunctions:TileLink Edge Object Methods`.
|
||||
|
||||
Manager Node
|
||||
------------
|
||||
@@ -116,7 +116,7 @@ most MMIO peripherals should set it to.
|
||||
|
||||
The next six arguments start with ``support`` and determine the different
|
||||
A channel message types that the manager can accept. The definitions of the
|
||||
message types are explained in :ref:`TileLink Edge Object Methods`.
|
||||
message types are explained in :ref:`TileLink-Diplomacy-Reference/EdgeFunctions:TileLink Edge Object Methods`.
|
||||
The ``TransferSizes`` case class specifies the range of logical sizes (in bytes)
|
||||
that the manager can accept for the particular message type. This is an inclusive
|
||||
range and all logical sizes must be powers of two. So in this case, the manager
|
||||
@@ -137,7 +137,7 @@ to handle TileLink requests, it is usually much easier to use a register node.
|
||||
This type of node provides a ``regmap`` method that allows you to specify
|
||||
control/status registers and automatically generates the logic to handle the
|
||||
TileLink protocol. More information about how to use register nodes can be
|
||||
found in :ref:`Register Router`.
|
||||
found in :ref:`TileLink-Diplomacy-Reference/Register-Router:Register Router`.
|
||||
|
||||
Identity Node
|
||||
-------------
|
||||
@@ -176,7 +176,7 @@ If we want to connect the client and manager groups together, we can now do this
|
||||
:end-before: DOC include end: MyClientManagerComplex
|
||||
|
||||
The meaning of the ``:=*`` operator is explained in more detail in the
|
||||
:ref:`Diplomacy Connectors` section. In summary, it connects two nodes together
|
||||
:ref:`TileLink-Diplomacy-Reference/Diplomacy-Connectors:Diplomacy Connectors` section. In summary, it connects two nodes together
|
||||
using multiple edges. The edges in the identity node are assigned in order,
|
||||
so in this case ``client1.node`` will eventually connect to ``manager1.node``
|
||||
and ``client2.node`` will connect to ``manager2.node``.
|
||||
@@ -192,7 +192,7 @@ produces the same number of outputs. However, unlike the identity node, the
|
||||
adapter node does not simply pass the connections through unchanged.
|
||||
It can change the logical and physical interfaces between input and output and
|
||||
rewrite messages going through. RocketChip provides a library of adapters,
|
||||
which are catalogued in :ref:`Diplomatic Widgets`.
|
||||
which are catalogued in :ref:`TileLink-Diplomacy-Reference/Widgets:Diplomatic Widgets`.
|
||||
|
||||
You will rarely need to create an adapter node yourself, but the invocation is
|
||||
as follows.
|
||||
|
||||
@@ -32,7 +32,7 @@ The default value is 4 bytes. The ``concurrency`` argument is the size of the
|
||||
internal queue for TileLink requests. By default, this value is 0, which means
|
||||
there will be no queue. This value must be greater than 0 if you wish to
|
||||
decoupled requests and responses for register accesses. This is discussed
|
||||
in :ref:`Using Functions`.
|
||||
in :ref:`TileLink-Diplomacy-Reference/Register-Router:Using Functions`.
|
||||
|
||||
The main way to interact with the node is to call the ``regmap`` method, which
|
||||
takes a sequence of pairs. The first element of the pair is an offset from the
|
||||
@@ -128,7 +128,7 @@ Register Routers for Other Protocols
|
||||
|
||||
One useful feature of the register router interface is that you can easily
|
||||
change the protocol being used. For instance, in the first example in
|
||||
:ref:`Basic Usage`, you could simply change the ``TLRegisterNode`` to
|
||||
:ref:`TileLink-Diplomacy-Reference/Register-Router:Basic Usage`, you could simply change the ``TLRegisterNode`` to
|
||||
and ``AXI4RegisterNode``.
|
||||
|
||||
.. literalinclude:: ../../generators/chipyard/src/main/scala/example/RegisterNodeExample.scala
|
||||
|
||||
@@ -81,7 +81,7 @@ The arguments for the five-argument constructor are
|
||||
AXI4Buffer
|
||||
----------
|
||||
|
||||
Similar to the :ref:`TLBuffer`, but for AXI4. It also takes ``BufferParams`` objects
|
||||
Similar to the :ref:`TileLink-Diplomacy-Reference/Widgets:TLBuffer`, but for AXI4. It also takes ``BufferParams`` objects
|
||||
as arguments.
|
||||
|
||||
**Arguments:**
|
||||
@@ -200,10 +200,11 @@ transactions.
|
||||
AXI4Fragmenter
|
||||
--------------
|
||||
|
||||
The AXI4Fragmenter is similar to the :ref:`TLFragmenter`, except it can only
|
||||
break multi-beat AXI4 transactions into single-beat transactions. This
|
||||
effectively serves as an AXI4 to AXI4-Lite converter. The constructor for this
|
||||
widget does not take any arguments.
|
||||
The AXI4Fragmenter is similar to the :ref:`TileLink-Diplomacy-Reference/Widgets:TLFragmenter`.
|
||||
The AXI4Fragmenter slices all AXI accesses into simple power-of-two sized and aligned transfers
|
||||
of the largest size supported by the manager. This makes it suitable as a first stage transformation
|
||||
to apply before an AXI4=>TL bridge. It also makes it suitable for placing after TL=>AXI4 bridge
|
||||
driving an AXI-lite slave.
|
||||
|
||||
**Example Usage:**
|
||||
|
||||
@@ -237,7 +238,7 @@ you will want to use a TLSourceShrinker.
|
||||
AXI4IdIndexer
|
||||
-------------
|
||||
|
||||
The AXI4 equivalent of :ref:`TLSourceShrinker`. This limits the number of
|
||||
The AXI4 equivalent of :ref:`TileLink-Diplomacy-Reference/Widgets:TLSourceShrinker`. This limits the number of
|
||||
AWID/ARID bits in the slave AXI4 interface. Useful for connecting to external
|
||||
or black box AXI4 ports.
|
||||
|
||||
@@ -257,7 +258,7 @@ or black box AXI4 ports.
|
||||
|
||||
The AXI4IdIndexer will create a ``user`` field on the slave interface, as it
|
||||
stores the ID of the master requests in this field. If connecting to an AXI4
|
||||
interface that doesn't have a ``user`` field, you'll need to use the :ref:`AXI4UserYanker`.
|
||||
interface that doesn't have a ``user`` field, you'll need to use the :ref:`TileLink-Diplomacy-Reference/Widgets:AXI4UserYanker`.
|
||||
|
||||
TLWidthWidget
|
||||
-------------
|
||||
@@ -301,7 +302,7 @@ The possible values of ``policy`` are:
|
||||
ordering guaranteed
|
||||
- ``TLFIFOFixer.allVolatile`` - All managers that have a RegionType of
|
||||
``VOLATILE``, ``PUT_EFFECTS``, or ``GET_EFFECTS`` will have ordering
|
||||
guaranteed (see :ref:`Manager Node` for explanation of region types).
|
||||
guaranteed (see :ref:`TileLink-Diplomacy-Reference/NodeTypes:Manager Node` for explanation of region types).
|
||||
|
||||
TLXbar and AXI4Xbar
|
||||
-------------------
|
||||
@@ -377,14 +378,14 @@ override the default arguments of the constructors for these widgets.
|
||||
AXI4Fragmenter() :=
|
||||
axi4master.node
|
||||
|
||||
You will need to add an :ref:`AXI4Deinterleaver` after the TLToAXI4 converter
|
||||
You will need to add an :ref:`TileLink-Diplomacy-Reference/Widgets:AXI4Deinterleaver` after the TLToAXI4 converter
|
||||
because it cannot deal with interleaved read responses. The TLToAXI4 converter
|
||||
also uses the AXI4 user field to store some information, so you will need an
|
||||
:ref:`AXI4UserYanker` if you want to connect to an AXI4 port without user
|
||||
:ref:`TileLink-Diplomacy-Reference/Widgets:AXI4UserYanker` if you want to connect to an AXI4 port without user
|
||||
fields.
|
||||
|
||||
Before you connect an AXI4 port to the AXI4ToTL widget, you will need to
|
||||
add an :ref:`AXI4Fragmenter` and :ref:`AXI4UserYanker` because the converter cannot
|
||||
add an :ref:`TileLink-Diplomacy-Reference/Widgets:AXI4Fragmenter` and :ref:`TileLink-Diplomacy-Reference/Widgets:AXI4UserYanker` because the converter cannot
|
||||
deal with multi-beat transactions or user fields.
|
||||
|
||||
TLROM
|
||||
|
||||
@@ -23,15 +23,15 @@ An external module reference is a FIRRTL construct that enables a design to refe
|
||||
A list of unique SRAM configurations is output to a ``.conf`` file by FIRRTL, which is used to map technology SRAMs.
|
||||
Without this transform, FIRRTL will map all ``SeqMem`` s to flip-flop arrays with equivalent behavior, which may lead to a design that is difficult to route.
|
||||
|
||||
The ``.conf`` file is consumed by a tool called MacroCompiler, which is part of the :ref:`Barstools` scala package.
|
||||
The ``.conf`` file is consumed by a tool called MacroCompiler, which is part of the :ref:`Tools/Barstools:Barstools` scala package.
|
||||
MacroCompiler is also passed an ``.mdf`` file that describes the available list of technology SRAMs or the capabilities of the SRAM compiler, if one is provided by the foundry.
|
||||
Typically a foundry SRAM compiler will be able to generate a set of different SRAMs collateral based on some requirements on size, aspect ratio, etc. (see :ref:`SRAM MDF Fields`).
|
||||
Typically a foundry SRAM compiler will be able to generate a set of different SRAMs collateral based on some requirements on size, aspect ratio, etc. (see :ref:`Tools/Barstools:SRAM MDF Fields`).
|
||||
Using a user-customizable cost function, MacroCompiler will select the SRAMs that are the best fit for each dimensionality in the ``.conf`` file.
|
||||
This may include over provisioning (e.g. using a 64x1024 SRAM for a requested 60x1024, if the latter is not available) or arraying.
|
||||
Arraying can be done in both width and depth, as well as to solve masking constraints.
|
||||
For example, a 128x2048 array could be composed of four 64x1024 arrays, with two macros in parallel to create two 128x1024 virtual SRAMs which are combinationally muxed to add depth.
|
||||
If this macro requires byte-granularity write masking, but no technology SRAMs support masking, then the tool may choose to use thirty-two 8x1024 arrays in a similar configuration.
|
||||
For information on writing ``.mdf`` files, look at `MDF on github <https://github.com/ucb-bar/plsi-mdf>`__ and a brief description in :ref:`SRAM MDF Fields` section.
|
||||
For information on writing ``.mdf`` files, look at `MDF on github <https://github.com/ucb-bar/plsi-mdf>`__ and a brief description in :ref:`Tools/Barstools:SRAM MDF Fields` section.
|
||||
|
||||
The output of MacroCompiler is a Verilog file containing modules that wrap the technology SRAMs into the specified interface names from the ``.conf``.
|
||||
If the technology supports an SRAM compiler, then MacroCompiler will also emit HammerIR that can be passed to Hammer to run the compiler itself and generate design collateral.
|
||||
@@ -103,7 +103,7 @@ This is necessary to facilitate post-synthesis and post-place-and-route simulati
|
||||
Simulations after you the design goes through a VLSI flow will use the verilog netlist generated from the flow and will need an untouched test harness to drive it.
|
||||
Separating these components into separate files makes this straightforward.
|
||||
Without the separation the file that included the test harness would also redefine the DUT which is often disallowed in simulation tools.
|
||||
To do this, there is a FIRRTL ``App`` in :ref:`Barstools` called ``GenerateTopAndHarness``, which runs the appropriate transforms to elaborate the modules separately.
|
||||
To do this, there is a FIRRTL ``App`` in :ref:`Tools/Barstools:Barstools` called ``GenerateTopAndHarness``, which runs the appropriate transforms to elaborate the modules separately.
|
||||
This also renames modules in the test harness so that any modules that are instantiated in both the test harness and the chip are uniquified.
|
||||
|
||||
.. Note:: For VLSI projects, this ``App`` is run instead of the normal FIRRTL ``App`` to elaborate Verilog.
|
||||
@@ -131,5 +131,5 @@ This, unfortunately, breaks the process-agnostic RTL abstraction, so it is recom
|
||||
The simplest way to do this is to have a config fragment that when included updates instantiates the IO cells and connects them in the test harness.
|
||||
When simulating chip-specific designs, it is important to include the IO cells.
|
||||
The IO cell behavioral models will often assert if they are connected incorrectly, which is a useful runtime check.
|
||||
They also keep the IO interface at the chip and test harness boundary (see :ref:`Separating the Top module from the TestHarness module`) consistent after synthesis and place-and-route,
|
||||
They also keep the IO interface at the chip and test harness boundary (see :ref:`Tools/Barstools:Separating the Top module from the TestHarness module`) consistent after synthesis and place-and-route,
|
||||
which allows the RTL simulation test harness to be reused.
|
||||
|
||||
@@ -4,4 +4,4 @@ Chisel Testers
|
||||
`Chisel Testers <https://github.com/freechipsproject/chisel-testers>`__ is a library for writing tests for Chisel designs.
|
||||
It provides a Scala API for interacting with a DUT.
|
||||
It can use multiple backends, including things such as Treadle and Verilator.
|
||||
See :ref:`Treadle and FIRRTL Interpreter` and :ref:`sw-rtl-sim-intro` for more information on these simulation methods.
|
||||
See :ref:`Tools/Treadle:Treadle and FIRRTL Interpreter` and :ref:`sw-rtl-sim-intro` for more information on these simulation methods.
|
||||
|
||||
@@ -13,7 +13,7 @@ The Chisel generator starts elaboration using the module and configuration class
|
||||
This is where the Chisel "library functions" are called with the parameters given and Chisel tries to construct a circuit based on the Chisel code.
|
||||
If a runtime error happens here, Chisel is stating that it cannot "build" your circuit due to "violations" between your code and the Chisel "library".
|
||||
However, if that passes, the output of the generator gives you an FIRRTL file and other misc collateral!
|
||||
See :ref:`FIRRTL` for more information on how to get a FIRRTL file to Verilog.
|
||||
See :ref:`Tools/FIRRTL:FIRRTL` for more information on how to get a FIRRTL file to Verilog.
|
||||
|
||||
For an interactive tutorial on how to use Chisel and get started please visit the `Chisel Bootcamp <https://github.com/freechipsproject/chisel-bootcamp>`__.
|
||||
Otherwise, for all things Chisel related including API documentation, news, etc, visit their `website <https://chisel-lang.org/>`__.
|
||||
|
||||
@@ -19,4 +19,4 @@ An example of a divergence and Dromajo's printout is shown below.
|
||||
Dromajo shows the divergence compared to simulation (PC, inst, inst-bits, write data, etc) and also provides the register state on failure.
|
||||
It is useful to catch bugs that affect architectural state before a simulation hangs or crashes.
|
||||
|
||||
To use Dromajo with BOOM, refer to :ref:`Debugging RTL` section on Dromajo.
|
||||
To use Dromajo with BOOM, refer to :ref:`Advanced-Concepts/Debugging-RTL:Debugging RTL` section on Dromajo.
|
||||
|
||||
308
docs/VLSI/Basic-Flow.rst
Normal file
308
docs/VLSI/Basic-Flow.rst
Normal file
@@ -0,0 +1,308 @@
|
||||
.. _hammer_basic_flow:
|
||||
|
||||
Using Hammer To Place and Route a Custom Block
|
||||
=================================================
|
||||
|
||||
.. IMPORTANT:: In order to use the Hammer VLSI flow, you need access to Hammer tools and technology plugins. You can obtain these by emailing hammer-plugins-access@lists.berkeley.edu with a request for which plugin(s) you would like access to. Make sure your email includes your github ID and proof (through affiliation or otherwise) that you have licensed access to relevant tools.
|
||||
|
||||
Initialize the Hammer Plug-ins
|
||||
----------------------------------
|
||||
In the Chipyard root, run:
|
||||
|
||||
.. code-block:: shell
|
||||
|
||||
./scripts/init-vlsi.sh <tech-plugin-name>
|
||||
|
||||
This will pull the Hammer & CAD tool plugin submodules, assuming the technology plugins are available on github.
|
||||
Currently only the asap7 technology plugin is available on github.
|
||||
If you have additional private technology plugins (this is a typical use-case for proprietry process technologies with require NDAs and secure servers), you can clone them directly
|
||||
into VLSI directory with the name ``hammer-<tech-plugin-name>-plugin``.
|
||||
For example, for an imaginary process technology called tsmintel3:
|
||||
|
||||
.. code-block:: shell
|
||||
|
||||
cd vlsi
|
||||
git clone git@my-secure-server.berkeley.edu:tsmintel3/hammer-tsmintel3-plugin.git
|
||||
|
||||
|
||||
Next, we define the Hammer environment into the shell:
|
||||
|
||||
.. code-block:: shell
|
||||
|
||||
cd vlsi # (if you haven't done so yet)
|
||||
export HAMMER_HOME=$PWD/hammer
|
||||
source $HAMMER_HOME/sourceme.sh
|
||||
|
||||
|
||||
.. Note:: Some VLSI EDA tools are supported only on RHEL-based operating systems. We recommend using Chipyard on RHEL7 and above. However, many VLSI server still have old operating systems such as RHEL6, which have software packages older than the basic chipyard requirements. In order to build Chipyard on RHEL6, you will likely need to use tool packages such as devtoolset (for example, devtoolset-8) and/or build from source gcc, git, gmake, make, dtc, cc, bison, libexpat and liby.
|
||||
|
||||
Setting up the Hammer Configuration Files
|
||||
--------------------------------------------
|
||||
|
||||
The first configuration file that needs to be set up is the Hammer environment configuration file ``env.yml``. In this file you need to set the paths to the EDA tools and license servers you will be using. You do not have to fill all the fields in this configuration file, you only need to fill in the paths for the tools that you will be using.
|
||||
If you are working within a shared server farm environment with an LSF cluster setup (for example, the Berkeley Wireless Research Center), please note the additional possible environment configuration listed in the :ref:`VLSI/Basic-Flow:Advanced Environment Setup` segment of this documentation page.
|
||||
|
||||
Hammer relies on YAML-based configuration files. While these configuration can be consolidated within a single files (as is the case in the ASAP7 tutorial :ref:`tutorial` and the ``nangate45``
|
||||
OpenRoad example), the generally suggested way to work with an arbitrary process technology or tools plugins would be to use three configuration files, matching the three Hammer concerns - tools, tech, and design.
|
||||
The ``vlsi`` directory includes three such example configuration files matching the three concerns: ``example-tools.yml``, ``example-tech.yml``, and ``example-design.yml``.
|
||||
|
||||
The ``example-tools.yml`` file configures which EDA tools hammer will use. This example file uses Cadence Innovus, Genus and Voltus, Synopsys VCS, and Mentor Calibre (which are likely the tools you will use if you're working in the Berkeley Wireless Research Center). Note that tool versions are highly sensitive to the process-technology in-use. Hence, tool versions that work with one process technology may not work with another (for example, ASAP7 will not work with an Innovus version newer than 18.1, while other proprietary process technologies will likely require newer versions such as 19.1).
|
||||
|
||||
The ``example-design.yml`` file contains basic build system information (how many cores/threads to use, etc.), as well as configurations that are specific to the design we are working on such as clock signal name and frequency, power modes, floorplan, and additional constraints that we will add later on.
|
||||
|
||||
Finally, the ``example-tech`` file is a template file for a process technology plugin configuration. We will copy this file, and replace its fields with the appropriate process technology details for the tech plugin that we have access to. For example, for the ``asap7`` tech plugin we will replace the <tech_name> field with "asap7", the Node size "N" with "7", and the path to the process technology files installation directory.
|
||||
|
||||
We recommend copying these example configuration files and customizing them with a different name, so you can have different configuration files for different process technologies and designs (e.g. create tech-tsmintel3.yml from example-tech.yml)
|
||||
|
||||
|
||||
Building the Design
|
||||
---------------------
|
||||
After we have set the configuration files, we will now elaborate our Chipyard Chisel design into Verilog, while also performing the required transformations in order to make the Verilog VLSI-friendly.
|
||||
Additionally, we will automatically generate another set of Hammer configuration files matching to this design, which will be used in order to configure the physical design tools.
|
||||
We will do so by calling ``make buildfile`` with appropriate Chipyard configuration variables and Hammer configuration files.
|
||||
As in the rest of the Chipyard flows, we specify our SoC configuration using the ``CONFIG`` make variable.
|
||||
However, unlike the rest of the Chipyard flows, in the case of physical design we might be interested in working in a hierarchical fashion and therefore we would like to work on a single module.
|
||||
Therefore, we can also specify a ``VLSI_TOP`` make variable with the same of a specific Verilog module (which should also match the name of the equivalent Chisel module) which we would like to work on.
|
||||
The makefile will automatically call tools such as Barstools and the MacroCopmiler (:ref:`Tools/Barstools:barstools`) in order to make the generated Verilog more VLSI friendly.
|
||||
By default, the MacroCopmiler will attempt to map memories into the SRAM options within the Hammer technology plugin. However, if you are wokring with a new process technology are prefer to work with flipflop arrays, you can configure the MacroCompiler using the ``MACROCOMPILER_MODE`` make variable. For example, the ASAP7 process technology does not have associated SRAMs, and therefore the ASAP7 Hammer tutorial (:ref:`tutorial`) uses the ``MACROCOMPILER_MODE='--mode synflops'`` option (Note that synthesizing a design with only flipflops is very slow and will often may not meet constraints).
|
||||
|
||||
We call the ``make buildfile`` command while also specifying the name of the process technology we are working with (same ``tech_name`` for the configuration files and plugin name) and the configuration files we created. Note, in the ASAP7 tutorial ((:ref:`tutorial`)) these configuration files are merged into a single file called ``example-asap7.yml``.
|
||||
|
||||
Hence, if we want to monolithically place and route the entire SoC, the relevant command would be
|
||||
.. code-block:: shell
|
||||
|
||||
make buildfile CONFIG=<chipyard_config_name> tech_name=<tech_name> INPUT_CONFS="example-design.yml example-tools.yml example-tech.yml"
|
||||
|
||||
In a more typical scenario of working on a single module, for example the Gemmini accelerator within the GemminiRocketConfig Chipyard SoC configuration, the relevant command would be
|
||||
.. code-block:: shell
|
||||
|
||||
make buildfile CONFIG=GemminiRocketConfig VLSI_TOP=Gemmini tech_name=tsmintel3 INPUT_CONFS="example-design.yml example-tools.yml example-tech.yml"
|
||||
|
||||
Running the VLSI Flow
|
||||
---------------------
|
||||
|
||||
Running a basic VLSI flow using the Hammer default configurations is fairly simple, and consists of simple ``make`` command with the previously mentioned Make variables.
|
||||
|
||||
Synthesis
|
||||
^^^^^^^^^
|
||||
|
||||
In order to run synthesis, we run ``make syn`` with the matching Make variables.
|
||||
Post-synthesis logs and collateral will be saved in ``build/<config-name>/syn-rundir``. The raw QoR data (area, timing, gate counts, etc.) will be found in ``build/<config-name>/syn-rundir/reports``.
|
||||
|
||||
Hence, if we want to monolithically synthesize the entire SoC, the relevant command would be
|
||||
.. code-block:: shell
|
||||
|
||||
make syn CONFIG=<chipyard_config_name> tech_name=<tech_name> INPUT_CONFS="example-design.yml example-tools.yml example-tech.yml"
|
||||
|
||||
In a more typical scenario of working on a single module, for example the Gemmini accelerator within the GemminiRocketConfig Chipyard SoC configuration, the relevant command would be
|
||||
.. code-block:: shell
|
||||
|
||||
make syn CONFIG=GemminiRocketConfig VLSI_TOP=Gemmini tech_name=tsmintel3 INPUT_CONFS="example-design.yml example-tools.yml example-tech.yml"
|
||||
|
||||
|
||||
It is worth checking the final-qor.rpt report to make sure that the synthesized design meets timing before moving to the place-and-route step.
|
||||
|
||||
Place-and-Route
|
||||
^^^^^^^^^^^^^^^
|
||||
In order to run place-and-route, we run ``make par`` with the matching Make variables.
|
||||
Post-PnR logs and collateral will be saved in ``build/<config-name>/par-rundir``. Specifically, the resulting GDSII file will be in that directory with the suffix ``*.gds``. and timing reports can be found in ``build/<config-name>/par-rundir/timingReports``.
|
||||
Place-and-route is requires more design details in contrast to synthesis. For example, place-and-route requires some basic floorplanning constraints. The default ``example-design.yml`` configuration file template allows the tool (specifically, the Cadence Innovus tool) to use it's automatic floorplanning capability within the top level of the design (``ChipTop``). However, if we choose to place-and-route a specific block which is not the SoC top level, we need to change the top-level path name to match the ``VLSI_TOP`` make parameter we are using.
|
||||
|
||||
Hence, if we want to monolitically place-and-route the entire SoC with the default tech plug-in parameters for power-straps and corners, the relevant command would be
|
||||
.. code-block:: shell
|
||||
|
||||
make par CONFIG=<chipyard_config_name> tech_name=<tech_name> INPUT_CONFS="example-design.yml example-tools.yml example-tech.yml"
|
||||
|
||||
In a more typical scenario of working on a single module, for example the Gemmini accelerator within the GemminiRocketConfig Chipyard SoC configuration,
|
||||
|
||||
.. code-block:: shell
|
||||
|
||||
vlsi.inputs.placement_constraints:
|
||||
- path: "Gemmini"
|
||||
type: toplevel
|
||||
x: 0
|
||||
y: 0
|
||||
width: 300
|
||||
height: 300
|
||||
margins:
|
||||
left: 0
|
||||
right: 0
|
||||
top: 0
|
||||
bottom: 0
|
||||
|
||||
The relevant ``make`` command would then be
|
||||
.. code-block:: shell
|
||||
|
||||
make par CONFIG=GemminiRocketConfig VLSI_TOP=Gemmini tech_name=tsmintel3 INPUT_CONFS="example-design.yml example-tools.yml example-tech.yml"
|
||||
|
||||
Note that the width and height specification can vary widely between different modulesi and level of the module hierarchy. Make sure to set sane width and height values.
|
||||
Place-and-route generally requires more fine-grained input specifications regarding power nets, clock nets, pin assignments and floorplanning. While the template configuration files provide defaults for automatic tool defaults, these will usually result in very bad QoR, and therefore it is recommended to specify better-informed floorplans, pin assignments and power nets. For more information about cutomizing theses parameters, please refer to the :ref:`VLSI/Basic-Flow:Customizing Your VLSI Flow in Hammer` sections or to the Hammer documentation.
|
||||
Additionally, some Hammer process technology plugins do not provide sufficient default values for requires settings such as power nets and pin assignments (for example, ASAP7). In those cases, these constraints will need to be specified manually in the top-level configuration yml files, as is the case in the ``example-asap7.yml`` configuration file.
|
||||
|
||||
Place-and-route tools are very sensitive to process technologes (significantly more sensitive than synthesis tools), and different process technologies may work only on specific tool versions. It is recommended to check what is the appropriate tool version for the specific process technology you are working with.
|
||||
|
||||
|
||||
.. Note:: If you edit the yml configuration files in between synthesis and place-and-route, the `make par` command will automatically re-run synthesis. If you would like to avoid that and are confident that your configuration file changes do not affect synthesis results, you may use the `make redo-par` instead.
|
||||
|
||||
|
||||
|
||||
Power Estimation
|
||||
^^^^^^^^^^^^^^^^^^^^
|
||||
Power estimation in Hammer can be performed in one of two stages: post-synthesis (post-syn) or post-place-and-route (post-par). The most accurate power estimation is post-par, and it includes finer grained details of the places instances and wire lengths.
|
||||
Post-par power estimation can be based on static average signal toggles rates (also known as "static power estimation"), or based on simulation-extracted signal toggle data (also known as "dynamic power estimation").
|
||||
|
||||
.. Warning:: In order to run post-par power estimation, make sure that a power estimation tool (such as Cadence Voltus) has been defined in your ``example-tools.yml`` file. Make sure that the power estimation tool (for example, Cadence Voltus) version matches the physical design tool (for example, Cadence Innovus) version, otherwise you will encounter a database mismatch error.
|
||||
|
||||
Simulation-exacted power estimation often requires a dedicated testharness for the block under evalution (DUT). While the Hammer flow supports such configurations (further details can be found in the Hammer documentation), Chipyard's integrated flows support an automated full digital SoC simulation-extracted post-par power estimation through the integration of software RTL simulation flows with the Hammer VLSI flow. As such, full digital SoC simulation-extracted power estimation can be performed by specifying a simple binary executable with the associated ``make`` command.
|
||||
|
||||
.. code-block:: shell
|
||||
|
||||
make power-par BINARY=/path/to/baremetal/binary/rv64ui-p-addi.riscv CONFIG=<chipyard_config_name> tech_name=tsmintel3 INPUT_CONFS="example-design.yml example-tools.yml example-tech.yml"
|
||||
|
||||
|
||||
The simulation-extracted power estimation flow implicitly uses Hammer's gate-level simulation flow (in order to generate the ``saif`` activity data file). This gate-level simulation flow can also be run independantly from the power estimation flow using the ``make sim-par`` command.
|
||||
|
||||
|
||||
.. Note:: The gate-level simulation flow (and there the simulation-extracted power-estimation) is currently integrated only with the Synopsys VCS simulation (Verilator does not support gate-level simulation. Support for Cadence Incisive is work-in-progress)
|
||||
|
||||
|
||||
Signoff
|
||||
^^^^^^^^^
|
||||
|
||||
During chip tapeout, you will need to perform sign-off check to make sure the generated GDSII can be fabricated as intended. This is done using dedicated signoff tools that perform design rule checking (DRC) and layout versus schematic (LVS) verification.
|
||||
In most cases, placed-and-routed designs will not pass DRC and LVS on first attempts due to nuanced design rules and subtle/silent failures of the place-and-route tools. Passing DRC and LVS will often requires adding manual placement constraints to "force" the EDA tools into certain patterns.
|
||||
If you have placed-and-routed a design with the goal of getting area and power estimates, DRC and LVS are not strictly neccessary and the results will likely be quite similar. If you are intending to tapeout and fabricate a chip, DRC and LVS are mandatory and will likely requires multiple-iterations of refining manual placement constraints.
|
||||
Having a large number of DRC/LVS violations can have a significant impact on the runtime of the place-and-route procedure (since the tools will try to fix each of them several times). A large number of DRC/LVS violations may also be an indication that the design is not necessarily realistic for this particular process technology, which may have power/area implications.
|
||||
|
||||
Since signoff checks are required only for a complete chip tapeout, they are currently not fully automated in Hammer, and often require some additional manual inclusion of custom Makefiles associated with specific process technologies. However, the general steps from running signoff within Hammer (under the assumption of a fully automated tech plug-in) are Make commands similar to the previous steps.
|
||||
|
||||
In order to run DRC, the relevant ``make`` command is ``make drc``. As in the previous stages, the make command should be accompanied by the relevant configuration Make variables:
|
||||
|
||||
.. code-block:: shell
|
||||
|
||||
make drc CONFIG=GemminiRocketConfig VLSI_TOP=Gemmini tech_name=tsmintel3 INPUT_CONFS="example-design.yml example-tools.yml example-tech.yml"
|
||||
|
||||
|
||||
DRC does not emit easily audited reports, as the rule names violated can be quite esoteric. It is often more productive to rather use the scripts generated by Hammer to open the DRC error database within the appropriate tool. These generated scripts can be called from ``./build/<config-name>/drc-rundir/generated-scripts/view_drc``.
|
||||
|
||||
|
||||
In order to run LVS, the relevant ``make`` command is ``make lvs``. As in the previous stages, the make command should be accompanied by the relevant configuration Make variables:
|
||||
|
||||
.. code-block:: shell
|
||||
|
||||
make lvs CONFIG=GemminiRocketConfig VLSI_TOP=Gemmini tech_name=tsmintel3 INPUT_CONFS="example-design.yml example-tools.yml example-tech.yml"
|
||||
|
||||
LVS does not emit easily audited reports, as the violations are often cryptic when seen textually. As a result it is often more productive to visually see the LVS issues using the generated scripts that enable opening the LVS error database within the appropriate tool. These generated scripts can be called from ``./build/<config-name>/lvs-rundir/generated-scripts/view_lvs``.
|
||||
|
||||
|
||||
Customizing Your VLSI Flow in Hammer
|
||||
----------------------------------------
|
||||
|
||||
Advanced Environment Setup
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
If you have access to a shared LSF cluster and you would like Hammer to submit it's compute-intensive jobs to the LSF cluster rather than your login machine, you can add the following code segment to your ``env.yml`` file (completing the relevant values for the bsub binary path, the number of CPUs requested, and the requested LSF queue):
|
||||
|
||||
.. code-block:: shell
|
||||
|
||||
#submit command (use LSF)
|
||||
vlsi.submit:
|
||||
command: "lsf"
|
||||
settings: [{"lsf": {
|
||||
"bsub_binary": "</path/to/bsub/binary/bsub>",
|
||||
"num_cpus": <N>,
|
||||
"queue": "<lsf_queu>",
|
||||
"extra_args": ["-R", "span[hosts=1]"]
|
||||
}
|
||||
}]
|
||||
settings_meta: "append"
|
||||
|
||||
|
||||
|
||||
Composing a Hierarchical Design
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
For large designs, a monolithic VLSI flow may take the EDA tools a very long time to process and optimize, to the extent that it may not be feasable sometimes.
|
||||
Hammer supports a hierarchical physical design flow, which decomposes the design into several specified sub-components and runs the flow on each sub-components separetly. Hammer is then able to assemble these blocks together into a top-level design. This hierarchical approach speeds up the VLSI flow for large designs, especially designs in which there may me multiple instantiations of the same sub-components(since the sub-component can simply be replicated in the layout).
|
||||
While hierarchical physical design can be performed in multiple ways (top-down, bottom-up, abutment etc.), Hammer currently supports only the bottom-up approach.
|
||||
The bottom-up approach traverses a tree representing the hierarchy starting from the leaves and towards the direction of the root (the "top level"), and runs the physical design flow on each node of the hierarchy tree using the previously layed-out children nodes.
|
||||
As nodes get closer to the root (or "top level") of the hierarchy, largers sections of the design get layed-out.
|
||||
|
||||
The Hammer hierarchical flow relies on a manually-specified descrition of the desired heirarchy tree. The specification of the heirarchy tree is defined based on the instance names in the generated Verilog, which sometime make this specification challenging due to inconsisent instance names. Additionally, the specification of the heirarchy tree is intertwined with the manual specification of a floorplan for the design.
|
||||
|
||||
For example, if we choose to specifiy the previously mentioned ``GemminiRocketConfig`` configuration in a hierarchical fashion in which the Gemmini accelerator and the last-level cache are run separetly from the top-level SoC, we would replace the floorplan example in ``example-design.yml`` from the :ref:`VLSI/Basic-Flow:Place-and-Route` section with the following specification:
|
||||
|
||||
.. code-block:: shell
|
||||
|
||||
vlsi.inputs.hiearchical.top_module: "ChipTop"
|
||||
vlsi.inputs.hierarchical.mode: manual"
|
||||
vlsi.inputs.manual_modules:
|
||||
- ChipTop:
|
||||
- RocketTile
|
||||
- InclusiveCache
|
||||
- RocketTile:
|
||||
- Gemmini
|
||||
vlsi.manual_placement_constraints:
|
||||
- ChipTop
|
||||
- path: "ChipTop"
|
||||
type: toplevel
|
||||
x: 0
|
||||
y: 0
|
||||
width: 500
|
||||
height: 500
|
||||
margins:
|
||||
left: 0
|
||||
right: 0
|
||||
top: 0
|
||||
bottom: 0
|
||||
- RocketTile
|
||||
- path: "chiptop.system.tile_prci_domain.tile"
|
||||
type: hierarchical
|
||||
master: ChipTop
|
||||
x: 0
|
||||
y: 0
|
||||
width: 250
|
||||
height: 250
|
||||
margins:
|
||||
left: 0
|
||||
right: 0
|
||||
top: 0
|
||||
bottom: 0
|
||||
- Gemmini
|
||||
- path: "chiptop.system.tile_prci_domain.tile.gemmini"
|
||||
type: hierarchical
|
||||
master: RocketTile
|
||||
x: 0
|
||||
y: 0
|
||||
width: 200
|
||||
height: 200
|
||||
margins:
|
||||
left: 0
|
||||
right: 0
|
||||
top: 0
|
||||
bottom: 0
|
||||
- InclusiveCache
|
||||
- path: "chiptop.system.subsystem_l2_wrapper.l2"
|
||||
type: hierarchical
|
||||
master: ChipTop
|
||||
x: 0
|
||||
y: 0
|
||||
width: 100
|
||||
height: 100
|
||||
margins:
|
||||
left: 0
|
||||
right: 0
|
||||
top: 0
|
||||
bottom: 0
|
||||
|
||||
|
||||
In this specification, ``vlsi.inputs.hierarchical.mode`` indicates the manual specification of the heirarchy tree (which is the only mode currently supported by Hammer), ``vlsi.inputs.hiearchical.top_module`` sets the root of the hierarchical tree, ``vlsi.inputs.hierarchical.manual_modules`` enumerates the tree of hierarchical modules, and ``vlsi.inputs.hierarchical.manual_placement_constraints`` enumerates the floorplan for each module.
|
||||
|
||||
|
||||
.. Specifying a Custom Floorplan
|
||||
.. ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
|
||||
Customizing Generated Tcl Scripts
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
The ``example-vlsi`` python script is the Hammer entry script with placeholders for hooks. Hooks are additional snippets of python and TCL (via ``x.append()``) to extend the Hammer APIs. Hooks can be inserted using the ``make_pre/post/replacement_hook`` methods as shown in the ``example-vlsi`` entry script example. In this particular example, a list of hooks is paased in the ``get_extra_par_hooks`` function in the ``ExampleDriver`` class. Refer to the `Hammer documentation on hooks <https://hammer-vlsi.readthedocs.io/en/latest/Hammer-Use/Hooks.html>`__ for a detailed description of how these are injected into the VLSI flow.
|
||||
@@ -10,7 +10,7 @@ Transforming the RTL
|
||||
--------------------
|
||||
|
||||
Building a chip requires specializing the generic verilog emitted by FIRRTL to adhere to the constraints imposed by the technology used for fabrication.
|
||||
This includes mapping Chisel memories to available technology macros such as SRAMs, mapping the input and output of your chip to connect to technology IO cells, see :ref:`Barstools`.
|
||||
This includes mapping Chisel memories to available technology macros such as SRAMs, mapping the input and output of your chip to connect to technology IO cells, see :ref:`Tools/Barstools:Barstools`.
|
||||
In addition to these required transformations, it may also be beneficial to transform the RTL to make it more amenable to hierarchical physical design easier.
|
||||
This often includes modifying the logical hierarchy to match the physical hierarchy through grouping components together or flattening components into a single larger module.
|
||||
|
||||
@@ -49,6 +49,6 @@ Running the VLSI tool flow
|
||||
--------------------------
|
||||
|
||||
For the full documentation on how to use the VLSI tool flow, see the `Hammer Documentation <https://hammer-vlsi.readthedocs.io/>`__.
|
||||
For an example of how to use the VLSI in the context of Chipyard, see :ref:`ASAP7 Tutorial`.
|
||||
For an example of how to use the VLSI in the context of Chipyard, see :ref:`VLSI/Tutorial:ASAP7 Tutorial`.
|
||||
|
||||
|
||||
|
||||
@@ -30,7 +30,7 @@ This example gives a suggested file structure and build system. The ``vlsi/`` fo
|
||||
|
||||
* Verilog wrapper around the accelerator and dummy hard macro.
|
||||
|
||||
* example.yml
|
||||
* example-asap7.yml
|
||||
|
||||
* Hammer IR for this tutorial.
|
||||
|
||||
@@ -77,7 +77,7 @@ Pull the Hammer environment into the shell:
|
||||
source $HAMMER_HOME/sourceme.sh
|
||||
|
||||
Building the Design
|
||||
-------------------
|
||||
--------------------
|
||||
To elaborate the ``Sha3RocketConfig`` (Rocket Chip w/ the accelerator) and set up all prerequisites for the build system to push just the accelerator + hard macro through the flow:
|
||||
|
||||
.. code-block:: shell
|
||||
|
||||
@@ -10,5 +10,6 @@ In particular, we aim to support the Hammer physical design generator flow.
|
||||
|
||||
Building-A-Chip
|
||||
Hammer
|
||||
Basic-Flow
|
||||
Tutorial
|
||||
Advanced-Usage
|
||||
|
||||
@@ -190,3 +190,6 @@ texinfo_documents = [
|
||||
intersphinx_mapping = {'python' : ('https://docs.python.org/', None),
|
||||
'boom' : ('https://docs.boom-core.org/en/latest/', None),
|
||||
'firesim' : ('http://docs.fires.im/en/latest/', None) }
|
||||
|
||||
# resolve label conflict between documents
|
||||
autosectionlabel_prefix_document = True
|
||||
|
||||
@@ -11,7 +11,7 @@ Welcome to Chipyard's documentation!
|
||||
Chipyard is a framework for designing and evaluating full-system hardware using agile teams.
|
||||
It is composed of a collection of tools and libraries designed to provide an integration between open-source and commercial tools for the development of systems-on-chip.
|
||||
|
||||
.. IMPORTANT:: **New to Chipyard?** Jump to the :ref:`Initial Repository Setup` page for setup instructions.
|
||||
.. IMPORTANT:: **New to Chipyard?** Jump to the :ref:`Chipyard-Basics/Initial-Repo-Setup:Initial Repository Setup` page for setup instructions.
|
||||
|
||||
Getting Help
|
||||
------------
|
||||
@@ -45,6 +45,8 @@ Table of Contents
|
||||
|
||||
TileLink-Diplomacy-Reference/index
|
||||
|
||||
Prototyping/index
|
||||
|
||||
|
||||
Indices and tables
|
||||
==================
|
||||
|
||||
1
fpga/.gitignore
vendored
Normal file
1
fpga/.gitignore
vendored
Normal file
@@ -0,0 +1 @@
|
||||
generated-src
|
||||
128
fpga/Makefile
Normal file
128
fpga/Makefile
Normal file
@@ -0,0 +1,128 @@
|
||||
#########################################################################################
|
||||
# fpga prototype makefile
|
||||
#########################################################################################
|
||||
|
||||
#########################################################################################
|
||||
# general path variables
|
||||
#########################################################################################
|
||||
base_dir=$(abspath ..)
|
||||
sim_dir=$(abspath .)
|
||||
|
||||
# do not generate simulation files
|
||||
sim_name := none
|
||||
|
||||
#########################################################################################
|
||||
# include shared variables
|
||||
#########################################################################################
|
||||
SUB_PROJECT ?= vcu118
|
||||
|
||||
ifeq ($(SUB_PROJECT),vcu118)
|
||||
SBT_PROJECT ?= fpga_platforms
|
||||
MODEL ?= VCU118FPGATestHarness
|
||||
VLOG_MODEL ?= VCU118FPGATestHarness
|
||||
MODEL_PACKAGE ?= chipyard.fpga.vcu118
|
||||
CONFIG ?= RocketVCU118Config
|
||||
CONFIG_PACKAGE ?= chipyard.fpga.vcu118
|
||||
GENERATOR_PACKAGE ?= chipyard
|
||||
TB ?= none # unused
|
||||
TOP ?= ChipTop
|
||||
BOARD ?= vcu118
|
||||
FPGA_BRAND ?= xilinx
|
||||
endif
|
||||
|
||||
ifeq ($(SUB_PROJECT),bringup)
|
||||
SBT_PROJECT ?= fpga_platforms
|
||||
MODEL ?= BringupVCU118FPGATestHarness
|
||||
VLOG_MODEL ?= BringupVCU118FPGATestHarness
|
||||
MODEL_PACKAGE ?= chipyard.fpga.vcu118.bringup
|
||||
CONFIG ?= RocketBringupConfig
|
||||
CONFIG_PACKAGE ?= chipyard.fpga.vcu118.bringup
|
||||
GENERATOR_PACKAGE ?= chipyard
|
||||
TB ?= none # unused
|
||||
TOP ?= ChipTop
|
||||
BOARD ?= vcu118
|
||||
FPGA_BRAND ?= xilinx
|
||||
endif
|
||||
|
||||
ifeq ($(SUB_PROJECT),arty)
|
||||
# TODO: Fix with Arty
|
||||
SBT_PROJECT ?= fpga_platforms
|
||||
MODEL ?= ArtyFPGATestHarness
|
||||
VLOG_MODEL ?= ArtyFPGATestHarness
|
||||
MODEL_PACKAGE ?= chipyard.fpga.arty
|
||||
CONFIG ?= TinyRocketArtyConfig
|
||||
CONFIG_PACKAGE ?= chipyard.fpga.arty
|
||||
GENERATOR_PACKAGE ?= chipyard
|
||||
TB ?= none # unused
|
||||
TOP ?= ChipTop
|
||||
BOARD ?= arty
|
||||
FPGA_BRAND ?= xilinx
|
||||
endif
|
||||
|
||||
include $(base_dir)/variables.mk
|
||||
|
||||
# default variables to build the arty example
|
||||
# setup the board to use
|
||||
|
||||
.PHONY: default
|
||||
default: $(mcs)
|
||||
|
||||
#########################################################################################
|
||||
# misc. directories
|
||||
#########################################################################################
|
||||
fpga_dir := $(base_dir)/fpga/fpga-shells/$(FPGA_BRAND)
|
||||
fpga_common_script_dir := $(fpga_dir)/common/tcl
|
||||
|
||||
#########################################################################################
|
||||
# import other necessary rules and variables
|
||||
#########################################################################################
|
||||
include $(base_dir)/common.mk
|
||||
|
||||
#########################################################################################
|
||||
# copy from other directory
|
||||
#########################################################################################
|
||||
all_vsrcs := \
|
||||
$(sim_vsrcs) \
|
||||
$(base_dir)/generators/sifive-blocks/vsrc/SRLatch.v \
|
||||
$(fpga_dir)/common/vsrc/PowerOnResetFPGAOnly.v
|
||||
|
||||
#########################################################################################
|
||||
# vivado rules
|
||||
#########################################################################################
|
||||
# combine all sources into single .f
|
||||
synth_list_f := $(build_dir)/$(long_name).vsrcs.f
|
||||
$(synth_list_f): $(sim_common_files) $(all_vsrcs)
|
||||
$(foreach file,$(all_vsrcs),echo "$(file)" >> $@;)
|
||||
cat $(sim_common_files) >> $@
|
||||
|
||||
BIT_FILE := $(build_dir)/obj/$(MODEL).bit
|
||||
$(BIT_FILE): $(synth_list_f)
|
||||
cd $(build_dir); vivado \
|
||||
-nojournal -mode batch \
|
||||
-source $(fpga_common_script_dir)/vivado.tcl \
|
||||
-tclargs \
|
||||
-top-module "$(MODEL)" \
|
||||
-F "$(synth_list_f)" \
|
||||
-ip-vivado-tcls "$(shell find '$(build_dir)' -name '*.vivado.tcl')" \
|
||||
-board "$(BOARD)"
|
||||
|
||||
.PHONY: bitstream
|
||||
bitstream: $(BIT_FILE)
|
||||
|
||||
.PHONY: debug-bitstream
|
||||
debug-bitstream: $(build_dir)/obj/post_synth.dcp
|
||||
cd $(build_dir); vivado \
|
||||
-nojournal -mode batch \
|
||||
-source $(sim_dir)/scripts/run_impl_bitstream.tcl \
|
||||
-tclargs \
|
||||
$(build_dir)/obj/post_synth.dcp \
|
||||
$(BOARD) \
|
||||
$(build_dir)/debug_obj \
|
||||
$(fpga_common_script_dir)
|
||||
|
||||
#########################################################################################
|
||||
# general cleanup rules
|
||||
#########################################################################################
|
||||
.PHONY: clean
|
||||
clean:
|
||||
rm -rf $(gen_dir)
|
||||
1
fpga/fpga-shells
Submodule
1
fpga/fpga-shells
Submodule
Submodule fpga/fpga-shells added at f9fb9fd338
60
fpga/scripts/run_impl_bitstream.tcl
Normal file
60
fpga/scripts/run_impl_bitstream.tcl
Normal file
@@ -0,0 +1,60 @@
|
||||
#### Command line arguments to this script
|
||||
# argv[0] = absolute path to post_synth checkpoint file
|
||||
# argv[1] = part
|
||||
# argv[2] = output directory
|
||||
# argv[3] = common fpga brand tcl
|
||||
|
||||
set synth_checkpoint_file [lindex $argv 0]
|
||||
set board [lindex $argv 1]
|
||||
set wrkdir [lindex $argv 2]
|
||||
|
||||
set scriptdir [lindex $argv 3]
|
||||
|
||||
# Set the variable for all the common files
|
||||
set commondir [file dirname $scriptdir]
|
||||
|
||||
# Set the variable that points to board specific files
|
||||
set boarddir [file join [file dirname $commondir] $board]
|
||||
source [file join $boarddir tcl board.tcl]
|
||||
|
||||
# Set the project part to the part passed into this script
|
||||
set_part $part_fpga
|
||||
|
||||
# Create output directories if they doesn't exist
|
||||
file mkdir $wrkdir
|
||||
set rptdir [file join $wrkdir report]
|
||||
file mkdir $rptdir
|
||||
|
||||
# Load synthesis checkpoint
|
||||
open_checkpoint $synth_checkpoint_file
|
||||
|
||||
# opt
|
||||
opt_design
|
||||
write_checkpoint -force [file join $wrkdir post_opt]
|
||||
|
||||
# place
|
||||
place_design
|
||||
phys_opt_design
|
||||
write_checkpoint -force [file join $wrkdir post_place]
|
||||
|
||||
report_timing_summary -file [file join $rptdir post_place_timing_summary.rpt]
|
||||
report_drc -file [file join $rptdir post_place_drc.rpt]
|
||||
|
||||
# route
|
||||
route_design
|
||||
write_checkpoint -force [file join $wrkdir post_route]
|
||||
report_timing_summary -file [file join $rptdir post_route_timing_summary.rpt]
|
||||
report_timing -sort_by group -max_paths 100 -path_type summary -file [file join $rptdir post_route_timing.rpt]
|
||||
report_clock_utilization -file [file join $rptdir post_route_clock_utilization.rpt]
|
||||
report_utilization -file [file join $rptdir post_route_utilization.rpt]
|
||||
report_drc -file [file join $rptdir post_route_drc.rpt]
|
||||
report_cdc -details -file [file join $rptdir post_route_cdc.rpt]
|
||||
report_clock_interaction -file [file join $rptdir post_route_clock_interaction.rpt]
|
||||
report_bus_skew -file [file join $rptdir post_route_bus_skew.rpt]
|
||||
report_design_analysis -logic_level_distribution -of_timing_paths [get_timing_paths -max_paths 1000 -slack_lesser_than 0] -file [file join $rptdir post_route_timing_violations.rpt]
|
||||
|
||||
# bitstream
|
||||
write_verilog -force [file join $wrkdir post_route.v]
|
||||
write_xdc -no_fixed_only -force [file join $wrkdir post_route.xdc]
|
||||
write_bitstream -force [file join $wrkdir top.bit]
|
||||
write_debug_probes -force [file join $wrkdir debug_nets.ltx]
|
||||
1
fpga/src/main/resources/vcu118/sdboot/.gitignore
vendored
Normal file
1
fpga/src/main/resources/vcu118/sdboot/.gitignore
vendored
Normal file
@@ -0,0 +1 @@
|
||||
build
|
||||
42
fpga/src/main/resources/vcu118/sdboot/Makefile
Normal file
42
fpga/src/main/resources/vcu118/sdboot/Makefile
Normal file
@@ -0,0 +1,42 @@
|
||||
# RISCV environment variable must be set
|
||||
ROOT_DIR := $(dir $(abspath $(lastword $(MAKEFILE_LIST))))
|
||||
BUILD_DIR := $(ROOT_DIR)/build
|
||||
|
||||
CC=$(RISCV)/bin/riscv64-unknown-elf-gcc
|
||||
OBJCOPY=$(RISCV)/bin/riscv64-unknown-elf-objcopy
|
||||
OBJDUMP=$(RISCV)/bin/riscv64-unknown-elf-objdump
|
||||
CFLAGS=-march=rv64ima -mcmodel=medany -O2 -std=gnu11 -Wall -nostartfiles
|
||||
CFLAGS+= -fno-common -g -DENTROPY=0 -mabi=lp64 -DNONSMP_HART=0
|
||||
CFLAGS+= -I $(ROOT_DIR)/include -I.
|
||||
LFLAGS=-static -nostdlib -L $(ROOT_DIR)/linker -T sdboot.elf.lds
|
||||
|
||||
PBUS_CLK ?= 1000000 # default to 1MHz but really should be overridden
|
||||
|
||||
default: elf bin dump
|
||||
|
||||
elf := $(BUILD_DIR)/sdboot.elf
|
||||
$(elf): head.S kprintf.c sd.c
|
||||
mkdir -p $(BUILD_DIR)
|
||||
$(CC) $(CFLAGS) -DTL_CLK="$(PBUS_CLK)UL" $(LFLAGS) -o $@ head.S sd.c kprintf.c
|
||||
|
||||
.PHONY: elf
|
||||
elf: $(elf)
|
||||
|
||||
bin := $(BUILD_DIR)/sdboot.bin
|
||||
$(bin): $(elf)
|
||||
mkdir -p $(BUILD_DIR)
|
||||
$(OBJCOPY) -O binary --change-addresses=-0x10000 $< $@
|
||||
|
||||
.PHONY: bin
|
||||
bin: $(bin)
|
||||
|
||||
dump := $(BUILD_DIR)/sdboot.dump
|
||||
$(dump): $(elf)
|
||||
$(OBJDUMP) -D -S $< > $@
|
||||
|
||||
.PHONY: dump
|
||||
dump: $(dump)
|
||||
|
||||
.PHONY: clean
|
||||
clean::
|
||||
rm -rf $(BUILD_DIR)
|
||||
10
fpga/src/main/resources/vcu118/sdboot/common.h
Normal file
10
fpga/src/main/resources/vcu118/sdboot/common.h
Normal file
@@ -0,0 +1,10 @@
|
||||
// See LICENSE.Sifive for license details.
|
||||
#ifndef _SDBOOT_COMMON_H
|
||||
#define _SDBOOT_COMMON_H
|
||||
|
||||
#ifndef PAYLOAD_DEST
|
||||
#define PAYLOAD_DEST MEMORY_MEM_ADDR
|
||||
#endif
|
||||
|
||||
|
||||
#endif
|
||||
21
fpga/src/main/resources/vcu118/sdboot/head.S
Normal file
21
fpga/src/main/resources/vcu118/sdboot/head.S
Normal file
@@ -0,0 +1,21 @@
|
||||
// See LICENSE.Sifive for license details.
|
||||
#include <platform.h>
|
||||
#include <smp.h>
|
||||
#include "common.h"
|
||||
|
||||
.section .text.init
|
||||
.option norvc
|
||||
.globl _prog_start
|
||||
_prog_start:
|
||||
smp_pause(s1, s2)
|
||||
li sp, (PAYLOAD_DEST + 0xffff000)
|
||||
call main
|
||||
smp_resume(s1, s2)
|
||||
csrr a0, mhartid // hartid for next level bootloader
|
||||
la a1, dtb // dtb address for next level bootloader
|
||||
li s1, PAYLOAD_DEST
|
||||
jr s1
|
||||
|
||||
.section .dtb
|
||||
.align 3
|
||||
dtb:
|
||||
36
fpga/src/main/resources/vcu118/sdboot/include/bits.h
Normal file
36
fpga/src/main/resources/vcu118/sdboot/include/bits.h
Normal file
@@ -0,0 +1,36 @@
|
||||
// See LICENSE.Sifive for license details.
|
||||
#ifndef _RISCV_BITS_H
|
||||
#define _RISCV_BITS_H
|
||||
|
||||
#define likely(x) __builtin_expect((x), 1)
|
||||
#define unlikely(x) __builtin_expect((x), 0)
|
||||
|
||||
#define ROUNDUP(a, b) ((((a)-1)/(b)+1)*(b))
|
||||
#define ROUNDDOWN(a, b) ((a)/(b)*(b))
|
||||
|
||||
#define MAX(a, b) ((a) > (b) ? (a) : (b))
|
||||
#define MIN(a, b) ((a) < (b) ? (a) : (b))
|
||||
#define CLAMP(a, lo, hi) MIN(MAX(a, lo), hi)
|
||||
|
||||
#define EXTRACT_FIELD(val, which) (((val) & (which)) / ((which) & ~((which)-1)))
|
||||
#define INSERT_FIELD(val, which, fieldval) (((val) & ~(which)) | ((fieldval) * ((which) & ~((which)-1))))
|
||||
|
||||
#define STR(x) XSTR(x)
|
||||
#define XSTR(x) #x
|
||||
|
||||
#if __riscv_xlen == 64
|
||||
# define SLL32 sllw
|
||||
# define STORE sd
|
||||
# define LOAD ld
|
||||
# define LWU lwu
|
||||
# define LOG_REGBYTES 3
|
||||
#else
|
||||
# define SLL32 sll
|
||||
# define STORE sw
|
||||
# define LOAD lw
|
||||
# define LWU lw
|
||||
# define LOG_REGBYTES 2
|
||||
#endif
|
||||
#define REGBYTES (1 << LOG_REGBYTES)
|
||||
|
||||
#endif
|
||||
18
fpga/src/main/resources/vcu118/sdboot/include/const.h
Normal file
18
fpga/src/main/resources/vcu118/sdboot/include/const.h
Normal file
@@ -0,0 +1,18 @@
|
||||
// See LICENSE.Sifive for license details.
|
||||
/* Derived from <linux/const.h> */
|
||||
|
||||
#ifndef _SIFIVE_CONST_H
|
||||
#define _SIFIVE_CONST_H
|
||||
|
||||
#ifdef __ASSEMBLER__
|
||||
#define _AC(X,Y) X
|
||||
#define _AT(T,X) X
|
||||
#else
|
||||
#define _AC(X,Y) (X##Y)
|
||||
#define _AT(T,X) ((T)(X))
|
||||
#endif /* !__ASSEMBLER__*/
|
||||
|
||||
#define _BITUL(x) (_AC(1,UL) << (x))
|
||||
#define _BITULL(x) (_AC(1,ULL) << (x))
|
||||
|
||||
#endif /* _SIFIVE_CONST_H */
|
||||
@@ -0,0 +1,14 @@
|
||||
// See LICENSE.Sifive for license details.
|
||||
|
||||
#ifndef _SIFIVE_CLINT_H
|
||||
#define _SIFIVE_CLINT_H
|
||||
|
||||
|
||||
#define CLINT_MSIP 0x0000
|
||||
#define CLINT_MSIP_size 0x4
|
||||
#define CLINT_MTIMECMP 0x4000
|
||||
#define CLINT_MTIMECMP_size 0x8
|
||||
#define CLINT_MTIME 0xBFF8
|
||||
#define CLINT_MTIME_size 0x8
|
||||
|
||||
#endif /* _SIFIVE_CLINT_H */
|
||||
24
fpga/src/main/resources/vcu118/sdboot/include/devices/gpio.h
Normal file
24
fpga/src/main/resources/vcu118/sdboot/include/devices/gpio.h
Normal file
@@ -0,0 +1,24 @@
|
||||
// See LICENSE.Sifive for license details.
|
||||
|
||||
#ifndef _SIFIVE_GPIO_H
|
||||
#define _SIFIVE_GPIO_H
|
||||
|
||||
#define GPIO_INPUT_VAL (0x00)
|
||||
#define GPIO_INPUT_EN (0x04)
|
||||
#define GPIO_OUTPUT_EN (0x08)
|
||||
#define GPIO_OUTPUT_VAL (0x0C)
|
||||
#define GPIO_PULLUP_EN (0x10)
|
||||
#define GPIO_DRIVE (0x14)
|
||||
#define GPIO_RISE_IE (0x18)
|
||||
#define GPIO_RISE_IP (0x1C)
|
||||
#define GPIO_FALL_IE (0x20)
|
||||
#define GPIO_FALL_IP (0x24)
|
||||
#define GPIO_HIGH_IE (0x28)
|
||||
#define GPIO_HIGH_IP (0x2C)
|
||||
#define GPIO_LOW_IE (0x30)
|
||||
#define GPIO_LOW_IP (0x34)
|
||||
#define GPIO_IOF_EN (0x38)
|
||||
#define GPIO_IOF_SEL (0x3C)
|
||||
#define GPIO_OUTPUT_XOR (0x40)
|
||||
|
||||
#endif /* _SIFIVE_GPIO_H */
|
||||
31
fpga/src/main/resources/vcu118/sdboot/include/devices/plic.h
Normal file
31
fpga/src/main/resources/vcu118/sdboot/include/devices/plic.h
Normal file
@@ -0,0 +1,31 @@
|
||||
// See LICENSE.Sifive for license details.
|
||||
|
||||
#ifndef PLIC_H
|
||||
#define PLIC_H
|
||||
|
||||
#include <const.h>
|
||||
|
||||
// 32 bits per source
|
||||
#define PLIC_PRIORITY_OFFSET _AC(0x0000,UL)
|
||||
#define PLIC_PRIORITY_SHIFT_PER_SOURCE 2
|
||||
// 1 bit per source (1 address)
|
||||
#define PLIC_PENDING_OFFSET _AC(0x1000,UL)
|
||||
#define PLIC_PENDING_SHIFT_PER_SOURCE 0
|
||||
|
||||
//0x80 per target
|
||||
#define PLIC_ENABLE_OFFSET _AC(0x2000,UL)
|
||||
#define PLIC_ENABLE_SHIFT_PER_TARGET 7
|
||||
|
||||
|
||||
#define PLIC_THRESHOLD_OFFSET _AC(0x200000,UL)
|
||||
#define PLIC_CLAIM_OFFSET _AC(0x200004,UL)
|
||||
#define PLIC_THRESHOLD_SHIFT_PER_TARGET 12
|
||||
#define PLIC_CLAIM_SHIFT_PER_TARGET 12
|
||||
|
||||
#define PLIC_MAX_SOURCE 1023
|
||||
#define PLIC_SOURCE_MASK 0x3FF
|
||||
|
||||
#define PLIC_MAX_TARGET 15871
|
||||
#define PLIC_TARGET_MASK 0x3FFF
|
||||
|
||||
#endif /* PLIC_H */
|
||||
79
fpga/src/main/resources/vcu118/sdboot/include/devices/spi.h
Normal file
79
fpga/src/main/resources/vcu118/sdboot/include/devices/spi.h
Normal file
@@ -0,0 +1,79 @@
|
||||
// See LICENSE.Sifive for license details.
|
||||
|
||||
#ifndef _SIFIVE_SPI_H
|
||||
#define _SIFIVE_SPI_H
|
||||
|
||||
/* Register offsets */
|
||||
|
||||
#define SPI_REG_SCKDIV 0x00
|
||||
#define SPI_REG_SCKMODE 0x04
|
||||
#define SPI_REG_CSID 0x10
|
||||
#define SPI_REG_CSDEF 0x14
|
||||
#define SPI_REG_CSMODE 0x18
|
||||
|
||||
#define SPI_REG_DCSSCK 0x28
|
||||
#define SPI_REG_DSCKCS 0x2a
|
||||
#define SPI_REG_DINTERCS 0x2c
|
||||
#define SPI_REG_DINTERXFR 0x2e
|
||||
|
||||
#define SPI_REG_FMT 0x40
|
||||
#define SPI_REG_TXFIFO 0x48
|
||||
#define SPI_REG_RXFIFO 0x4c
|
||||
#define SPI_REG_TXCTRL 0x50
|
||||
#define SPI_REG_RXCTRL 0x54
|
||||
|
||||
#define SPI_REG_FCTRL 0x60
|
||||
#define SPI_REG_FFMT 0x64
|
||||
|
||||
#define SPI_REG_IE 0x70
|
||||
#define SPI_REG_IP 0x74
|
||||
|
||||
/* Fields */
|
||||
|
||||
#define SPI_SCK_POL 0x1
|
||||
#define SPI_SCK_PHA 0x2
|
||||
|
||||
#define SPI_FMT_PROTO(x) ((x) & 0x3)
|
||||
#define SPI_FMT_ENDIAN(x) (((x) & 0x1) << 2)
|
||||
#define SPI_FMT_DIR(x) (((x) & 0x1) << 3)
|
||||
#define SPI_FMT_LEN(x) (((x) & 0xf) << 16)
|
||||
|
||||
/* TXCTRL register */
|
||||
#define SPI_TXWM(x) ((x) & 0xffff)
|
||||
/* RXCTRL register */
|
||||
#define SPI_RXWM(x) ((x) & 0xffff)
|
||||
|
||||
#define SPI_IP_TXWM 0x1
|
||||
#define SPI_IP_RXWM 0x2
|
||||
|
||||
#define SPI_FCTRL_EN 0x1
|
||||
|
||||
#define SPI_INSN_CMD_EN 0x1
|
||||
#define SPI_INSN_ADDR_LEN(x) (((x) & 0x7) << 1)
|
||||
#define SPI_INSN_PAD_CNT(x) (((x) & 0xf) << 4)
|
||||
#define SPI_INSN_CMD_PROTO(x) (((x) & 0x3) << 8)
|
||||
#define SPI_INSN_ADDR_PROTO(x) (((x) & 0x3) << 10)
|
||||
#define SPI_INSN_DATA_PROTO(x) (((x) & 0x3) << 12)
|
||||
#define SPI_INSN_CMD_CODE(x) (((x) & 0xff) << 16)
|
||||
#define SPI_INSN_PAD_CODE(x) (((x) & 0xff) << 24)
|
||||
|
||||
#define SPI_TXFIFO_FULL (1 << 31)
|
||||
#define SPI_RXFIFO_EMPTY (1 << 31)
|
||||
|
||||
/* Values */
|
||||
|
||||
#define SPI_CSMODE_AUTO 0
|
||||
#define SPI_CSMODE_HOLD 2
|
||||
#define SPI_CSMODE_OFF 3
|
||||
|
||||
#define SPI_DIR_RX 0
|
||||
#define SPI_DIR_TX 1
|
||||
|
||||
#define SPI_PROTO_S 0
|
||||
#define SPI_PROTO_D 1
|
||||
#define SPI_PROTO_Q 2
|
||||
|
||||
#define SPI_ENDIAN_MSB 0
|
||||
#define SPI_ENDIAN_LSB 1
|
||||
|
||||
#endif /* _SIFIVE_SPI_H */
|
||||
28
fpga/src/main/resources/vcu118/sdboot/include/devices/uart.h
Normal file
28
fpga/src/main/resources/vcu118/sdboot/include/devices/uart.h
Normal file
@@ -0,0 +1,28 @@
|
||||
// See LICENSE.Sifive for license details.
|
||||
|
||||
#ifndef _SIFIVE_UART_H
|
||||
#define _SIFIVE_UART_H
|
||||
|
||||
/* Register offsets */
|
||||
#define UART_REG_TXFIFO 0x00
|
||||
#define UART_REG_RXFIFO 0x04
|
||||
#define UART_REG_TXCTRL 0x08
|
||||
#define UART_REG_RXCTRL 0x0c
|
||||
#define UART_REG_IE 0x10
|
||||
#define UART_REG_IP 0x14
|
||||
#define UART_REG_DIV 0x18
|
||||
|
||||
/* TXCTRL register */
|
||||
#define UART_TXEN 0x1
|
||||
#define UART_TXNSTOP 0x2
|
||||
#define UART_TXWM(x) (((x) & 0xffff) << 16)
|
||||
|
||||
/* RXCTRL register */
|
||||
#define UART_RXEN 0x1
|
||||
#define UART_RXWM(x) (((x) & 0xffff) << 16)
|
||||
|
||||
/* IP register */
|
||||
#define UART_IP_TXWM 0x1
|
||||
#define UART_IP_RXWM 0x2
|
||||
|
||||
#endif /* _SIFIVE_UART_H */
|
||||
107
fpga/src/main/resources/vcu118/sdboot/include/platform.h
Normal file
107
fpga/src/main/resources/vcu118/sdboot/include/platform.h
Normal file
@@ -0,0 +1,107 @@
|
||||
// See LICENSE for license details.
|
||||
|
||||
#ifndef _CHIPYARD_PLATFORM_H
|
||||
#define _CHIPYARD_PLATFORM_H
|
||||
|
||||
#include "const.h"
|
||||
#include "devices/clint.h"
|
||||
#include "devices/gpio.h"
|
||||
#include "devices/plic.h"
|
||||
#include "devices/spi.h"
|
||||
#include "devices/uart.h"
|
||||
|
||||
// Some things missing from the official encoding.h
|
||||
#if __riscv_xlen == 32
|
||||
#define MCAUSE_INT 0x80000000UL
|
||||
#define MCAUSE_CAUSE 0x7FFFFFFFUL
|
||||
#else
|
||||
#define MCAUSE_INT 0x8000000000000000UL
|
||||
#define MCAUSE_CAUSE 0x7FFFFFFFFFFFFFFFUL
|
||||
#endif
|
||||
|
||||
/****************************************************************************
|
||||
* Platform definitions
|
||||
*****************************************************************************/
|
||||
|
||||
// CPU info
|
||||
#define NUM_CORES 1
|
||||
#define GLOBAL_INT_SIZE 38
|
||||
#define GLOBAL_INT_MAX_PRIORITY 7
|
||||
|
||||
// Memory map
|
||||
#define CLINT_CTRL_ADDR _AC(0x2000000,UL)
|
||||
#define CLINT_CTRL_SIZE _AC(0x10000,UL)
|
||||
#define DEBUG_CTRL_ADDR _AC(0x0,UL)
|
||||
#define DEBUG_CTRL_SIZE _AC(0x1000,UL)
|
||||
#define ERROR_MEM_ADDR _AC(0x3000,UL)
|
||||
#define ERROR_MEM_SIZE _AC(0x1000,UL)
|
||||
#define GPIO_CTRL_ADDR _AC(0x64002000,UL)
|
||||
#define GPIO_CTRL_SIZE _AC(0x1000,UL)
|
||||
#define MASKROM_MEM_ADDR _AC(0x10000,UL)
|
||||
#define MASKROM_MEM_SIZE _AC(0x10000,UL)
|
||||
#define MEMORY_MEM_ADDR _AC(0x80000000,UL)
|
||||
#define MEMORY_MEM_SIZE _AC(0x10000000,UL)
|
||||
#define PLIC_CTRL_ADDR _AC(0xc000000,UL)
|
||||
#define PLIC_CTRL_SIZE _AC(0x4000000,UL)
|
||||
#define SPI_CTRL_ADDR _AC(0x64001000,UL)
|
||||
#define SPI_CTRL_SIZE _AC(0x1000,UL)
|
||||
#define SPI1_CTRL_ADDR _AC(0x64004000,UL)
|
||||
#define SPI1_CTRL_SIZE _AC(0x1000,UL)
|
||||
#define TEST_CTRL_ADDR _AC(0x4000,UL)
|
||||
#define TEST_CTRL_SIZE _AC(0x1000,UL)
|
||||
#define UART_CTRL_ADDR _AC(0x64000000,UL)
|
||||
#define UART_CTRL_SIZE _AC(0x1000,UL)
|
||||
#define UART1_CTRL_ADDR _AC(0x64003000,UL)
|
||||
#define UART1_CTRL_SIZE _AC(0x1000,UL)
|
||||
#define I2C_CTRL_ADDR _AC(0x64005000,UL)
|
||||
#define I2C_CTRL_SIZE _AC(0x1000,UL)
|
||||
|
||||
// IOF masks
|
||||
|
||||
|
||||
// Interrupt numbers
|
||||
#define UART_INT_BASE 1
|
||||
#define UART1_INT_BASE 2
|
||||
#define I2C_INT_BASE 3
|
||||
#define GPIO_INT_BASE 4
|
||||
#define SPI_INT_BASE 36
|
||||
#define SPI1_INT_BASE 37
|
||||
|
||||
// Helper functions
|
||||
#define _REG64(p, i) (*(volatile uint64_t *)((p) + (i)))
|
||||
#define _REG32(p, i) (*(volatile uint32_t *)((p) + (i)))
|
||||
#define _REG16(p, i) (*(volatile uint16_t *)((p) + (i)))
|
||||
// Bulk set bits in `reg` to either 0 or 1.
|
||||
// E.g. SET_BITS(MY_REG, 0x00000007, 0) would generate MY_REG &= ~0x7
|
||||
// E.g. SET_BITS(MY_REG, 0x00000007, 1) would generate MY_REG |= 0x7
|
||||
#define SET_BITS(reg, mask, value) if ((value) == 0) { (reg) &= ~(mask); } else { (reg) |= (mask); }
|
||||
#define AXI_PCIE_HOST_1_00_A_REG(offset) _REG32(AXI_PCIE_HOST_1_00_A_CTRL_ADDR, offset)
|
||||
#define CLINT_REG(offset) _REG32(CLINT_CTRL_ADDR, offset)
|
||||
#define DEBUG_REG(offset) _REG32(DEBUG_CTRL_ADDR, offset)
|
||||
#define ERROR_REG(offset) _REG32(ERROR_CTRL_ADDR, offset)
|
||||
#define GPIO_REG(offset) _REG32(GPIO_CTRL_ADDR, offset)
|
||||
#define MASKROM_REG(offset) _REG32(MASKROM_CTRL_ADDR, offset)
|
||||
#define MEMORY_REG(offset) _REG32(MEMORY_CTRL_ADDR, offset)
|
||||
#define PLIC_REG(offset) _REG32(PLIC_CTRL_ADDR, offset)
|
||||
#define SPI_REG(offset) _REG32(SPI_CTRL_ADDR, offset)
|
||||
#define TEST_REG(offset) _REG32(TEST_CTRL_ADDR, offset)
|
||||
#define UART_REG(offset) _REG32(UART_CTRL_ADDR, offset)
|
||||
#define AXI_PCIE_HOST_1_00_A_REG64(offset) _REG64(AXI_PCIE_HOST_1_00_A_CTRL_ADDR, offset)
|
||||
#define CLINT_REG64(offset) _REG64(CLINT_CTRL_ADDR, offset)
|
||||
#define DEBUG_REG64(offset) _REG64(DEBUG_CTRL_ADDR, offset)
|
||||
#define ERROR_REG64(offset) _REG64(ERROR_CTRL_ADDR, offset)
|
||||
#define GPIO_REG64(offset) _REG64(GPIO_CTRL_ADDR, offset)
|
||||
#define MASKROM_REG64(offset) _REG64(MASKROM_CTRL_ADDR, offset)
|
||||
#define MEMORY_REG64(offset) _REG64(MEMORY_CTRL_ADDR, offset)
|
||||
#define PLIC_REG64(offset) _REG64(PLIC_CTRL_ADDR, offset)
|
||||
#define SPI_REG64(offset) _REG64(SPI_CTRL_ADDR, offset)
|
||||
#define SPI1_REG64(offset) _REG64(SPI1_CTRL_ADDR, offset)
|
||||
#define TEST_REG64(offset) _REG64(TEST_CTRL_ADDR, offset)
|
||||
#define UART_REG64(offset) _REG64(UART_CTRL_ADDR, offset)
|
||||
#define UART1_REG64(offset) _REG64(UART1_CTRL_ADDR, offset)
|
||||
#define I2C_REG64(offset) _REG64(I2C_CTRL_ADDR, offset)
|
||||
|
||||
// Misc
|
||||
|
||||
|
||||
#endif /* _CHIPYARD_PLATFORM_H */
|
||||
17
fpga/src/main/resources/vcu118/sdboot/include/sections.h
Normal file
17
fpga/src/main/resources/vcu118/sdboot/include/sections.h
Normal file
@@ -0,0 +1,17 @@
|
||||
// See LICENSE.Sifive for license details.
|
||||
#ifndef _SECTIONS_H
|
||||
#define _SECTIONS_H
|
||||
|
||||
extern unsigned char _rom[];
|
||||
extern unsigned char _rom_end[];
|
||||
|
||||
extern unsigned char _ram[];
|
||||
extern unsigned char _ram_end[];
|
||||
|
||||
extern unsigned char _ftext[];
|
||||
extern unsigned char _etext[];
|
||||
extern unsigned char _fbss[];
|
||||
extern unsigned char _ebss[];
|
||||
extern unsigned char _end[];
|
||||
|
||||
#endif /* _SECTIONS_H */
|
||||
143
fpga/src/main/resources/vcu118/sdboot/include/smp.h
Normal file
143
fpga/src/main/resources/vcu118/sdboot/include/smp.h
Normal file
@@ -0,0 +1,143 @@
|
||||
// See LICENSE.Sifive for license details.
|
||||
#ifndef SIFIVE_SMP
|
||||
#define SIFIVE_SMP
|
||||
#include "platform.h"
|
||||
|
||||
// The maximum number of HARTs this code supports
|
||||
#ifndef MAX_HARTS
|
||||
#define MAX_HARTS 32
|
||||
#endif
|
||||
#define CLINT_END_HART_IPI CLINT_CTRL_ADDR + (MAX_HARTS*4)
|
||||
#define CLINT1_END_HART_IPI CLINT1_CTRL_ADDR + (MAX_HARTS*4)
|
||||
|
||||
// The hart that non-SMP tests should run on
|
||||
#ifndef NONSMP_HART
|
||||
#define NONSMP_HART 0
|
||||
#endif
|
||||
|
||||
/* If your test cannot handle multiple-threads, use this:
|
||||
* smp_disable(reg1)
|
||||
*/
|
||||
#define smp_disable(reg1, reg2) \
|
||||
csrr reg1, mhartid ;\
|
||||
li reg2, NONSMP_HART ;\
|
||||
beq reg1, reg2, hart0_entry ;\
|
||||
42: ;\
|
||||
wfi ;\
|
||||
j 42b ;\
|
||||
hart0_entry:
|
||||
|
||||
/* If your test needs to temporarily block multiple-threads, do this:
|
||||
* smp_pause(reg1, reg2)
|
||||
* ... single-threaded work ...
|
||||
* smp_resume(reg1, reg2)
|
||||
* ... multi-threaded work ...
|
||||
*/
|
||||
|
||||
#define smp_pause(reg1, reg2) \
|
||||
li reg2, 0x8 ;\
|
||||
csrw mie, reg2 ;\
|
||||
li reg1, NONSMP_HART ;\
|
||||
csrr reg2, mhartid ;\
|
||||
bne reg1, reg2, 42f
|
||||
|
||||
#ifdef CLINT1_CTRL_ADDR
|
||||
// If a second CLINT exists, then make sure we:
|
||||
// 1) Trigger a software interrupt on all harts of both CLINTs.
|
||||
// 2) Locate your own hart's software interrupt pending register and clear it.
|
||||
// 3) Wait for all harts on both CLINTs to clear their software interrupt
|
||||
// pending register.
|
||||
// WARNING: This code makes these assumptions, which are only true for Fadu as
|
||||
// of now:
|
||||
// 1) hart0 uses CLINT0 at offset 0
|
||||
// 2) hart2 uses CLINT1 at offset 0
|
||||
// 3) hart3 uses CLINT1 at offset 1
|
||||
// 4) There are no other harts or CLINTs in the system.
|
||||
#define smp_resume(reg1, reg2) \
|
||||
/* Trigger software interrupt on CLINT0 */ \
|
||||
li reg1, CLINT_CTRL_ADDR ;\
|
||||
41: ;\
|
||||
li reg2, 1 ;\
|
||||
sw reg2, 0(reg1) ;\
|
||||
addi reg1, reg1, 4 ;\
|
||||
li reg2, CLINT_END_HART_IPI ;\
|
||||
blt reg1, reg2, 41b ;\
|
||||
/* Trigger software interrupt on CLINT1 */ \
|
||||
li reg1, CLINT1_CTRL_ADDR ;\
|
||||
41: ;\
|
||||
li reg2, 1 ;\
|
||||
sw reg2, 0(reg1) ;\
|
||||
addi reg1, reg1, 4 ;\
|
||||
li reg2, CLINT1_END_HART_IPI ;\
|
||||
blt reg1, reg2, 41b ;\
|
||||
/* Wait to receive software interrupt */ \
|
||||
42: ;\
|
||||
wfi ;\
|
||||
csrr reg2, mip ;\
|
||||
andi reg2, reg2, 0x8 ;\
|
||||
beqz reg2, 42b ;\
|
||||
/* Clear own software interrupt bit */ \
|
||||
csrr reg2, mhartid ;\
|
||||
bnez reg2, 41f; \
|
||||
/* hart0 case: Use CLINT0 */ \
|
||||
li reg1, CLINT_CTRL_ADDR ;\
|
||||
slli reg2, reg2, 2 ;\
|
||||
add reg2, reg2, reg1 ;\
|
||||
sw zero, 0(reg2) ;\
|
||||
j 42f; \
|
||||
41: \
|
||||
/* hart 2, 3 case: Use CLINT1 and remap hart IDs to 0 and 1 */ \
|
||||
li reg1, CLINT1_CTRL_ADDR ;\
|
||||
addi reg2, reg2, -2; \
|
||||
slli reg2, reg2, 2 ;\
|
||||
add reg2, reg2, reg1 ;\
|
||||
sw zero, 0(reg2) ; \
|
||||
42: \
|
||||
/* Wait for all software interrupt bits to be cleared on CLINT0 */ \
|
||||
li reg1, CLINT_CTRL_ADDR ;\
|
||||
41: ;\
|
||||
lw reg2, 0(reg1) ;\
|
||||
bnez reg2, 41b ;\
|
||||
addi reg1, reg1, 4 ;\
|
||||
li reg2, CLINT_END_HART_IPI ;\
|
||||
blt reg1, reg2, 41b; \
|
||||
/* Wait for all software interrupt bits to be cleared on CLINT1 */ \
|
||||
li reg1, CLINT1_CTRL_ADDR ;\
|
||||
41: ;\
|
||||
lw reg2, 0(reg1) ;\
|
||||
bnez reg2, 41b ;\
|
||||
addi reg1, reg1, 4 ;\
|
||||
li reg2, CLINT1_END_HART_IPI ;\
|
||||
blt reg1, reg2, 41b; \
|
||||
/* End smp_resume() */
|
||||
|
||||
#else
|
||||
|
||||
#define smp_resume(reg1, reg2) \
|
||||
li reg1, CLINT_CTRL_ADDR ;\
|
||||
41: ;\
|
||||
li reg2, 1 ;\
|
||||
sw reg2, 0(reg1) ;\
|
||||
addi reg1, reg1, 4 ;\
|
||||
li reg2, CLINT_END_HART_IPI ;\
|
||||
blt reg1, reg2, 41b ;\
|
||||
42: ;\
|
||||
wfi ;\
|
||||
csrr reg2, mip ;\
|
||||
andi reg2, reg2, 0x8 ;\
|
||||
beqz reg2, 42b ;\
|
||||
li reg1, CLINT_CTRL_ADDR ;\
|
||||
csrr reg2, mhartid ;\
|
||||
slli reg2, reg2, 2 ;\
|
||||
add reg2, reg2, reg1 ;\
|
||||
sw zero, 0(reg2) ;\
|
||||
41: ;\
|
||||
lw reg2, 0(reg1) ;\
|
||||
bnez reg2, 41b ;\
|
||||
addi reg1, reg1, 4 ;\
|
||||
li reg2, CLINT_END_HART_IPI ;\
|
||||
blt reg1, reg2, 41b
|
||||
|
||||
#endif /* ifdef CLINT1_CTRL_ADDR */
|
||||
|
||||
#endif
|
||||
75
fpga/src/main/resources/vcu118/sdboot/kprintf.c
Normal file
75
fpga/src/main/resources/vcu118/sdboot/kprintf.c
Normal file
@@ -0,0 +1,75 @@
|
||||
// See LICENSE.Sifive for license details.
|
||||
#include <stdarg.h>
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
#include "kprintf.h"
|
||||
|
||||
static inline void _kputs(const char *s)
|
||||
{
|
||||
char c;
|
||||
for (; (c = *s) != '\0'; s++)
|
||||
kputc(c);
|
||||
}
|
||||
|
||||
void kputs(const char *s)
|
||||
{
|
||||
_kputs(s);
|
||||
kputc('\r');
|
||||
kputc('\n');
|
||||
}
|
||||
|
||||
void kprintf(const char *fmt, ...)
|
||||
{
|
||||
va_list vl;
|
||||
bool is_format, is_long, is_char;
|
||||
char c;
|
||||
|
||||
va_start(vl, fmt);
|
||||
is_format = false;
|
||||
is_long = false;
|
||||
is_char = false;
|
||||
while ((c = *fmt++) != '\0') {
|
||||
if (is_format) {
|
||||
switch (c) {
|
||||
case 'l':
|
||||
is_long = true;
|
||||
continue;
|
||||
case 'h':
|
||||
is_char = true;
|
||||
continue;
|
||||
case 'x': {
|
||||
unsigned long n;
|
||||
long i;
|
||||
if (is_long) {
|
||||
n = va_arg(vl, unsigned long);
|
||||
i = (sizeof(unsigned long) << 3) - 4;
|
||||
} else {
|
||||
n = va_arg(vl, unsigned int);
|
||||
i = is_char ? 4 : (sizeof(unsigned int) << 3) - 4;
|
||||
}
|
||||
for (; i >= 0; i -= 4) {
|
||||
long d;
|
||||
d = (n >> i) & 0xF;
|
||||
kputc(d < 10 ? '0' + d : 'a' + d - 10);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case 's':
|
||||
_kputs(va_arg(vl, const char *));
|
||||
break;
|
||||
case 'c':
|
||||
kputc(va_arg(vl, int));
|
||||
break;
|
||||
}
|
||||
is_format = false;
|
||||
is_long = false;
|
||||
is_char = false;
|
||||
} else if (c == '%') {
|
||||
is_format = true;
|
||||
} else {
|
||||
kputc(c);
|
||||
}
|
||||
}
|
||||
va_end(vl);
|
||||
}
|
||||
49
fpga/src/main/resources/vcu118/sdboot/kprintf.h
Normal file
49
fpga/src/main/resources/vcu118/sdboot/kprintf.h
Normal file
@@ -0,0 +1,49 @@
|
||||
// See LICENSE.Sifive for license details.
|
||||
#ifndef _SDBOOT_KPRINTF_H
|
||||
#define _SDBOOT_KPRINTF_H
|
||||
|
||||
#include <platform.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#define REG32(p, i) ((p)[(i) >> 2])
|
||||
|
||||
#ifndef UART_CTRL_ADDR
|
||||
#ifndef UART_NUM
|
||||
#define UART_NUM 0
|
||||
#endif
|
||||
|
||||
#define _CONCAT3(A, B, C) A ## B ## C
|
||||
#define _UART_CTRL_ADDR(UART_NUM) _CONCAT3(UART, UART_NUM, _CTRL_ADDR)
|
||||
#define UART_CTRL_ADDR _UART_CTRL_ADDR(UART_NUM)
|
||||
#endif
|
||||
static volatile uint32_t * const uart = (void *)(UART_CTRL_ADDR);
|
||||
|
||||
static inline void kputc(char c)
|
||||
{
|
||||
volatile uint32_t *tx = ®32(uart, UART_REG_TXFIFO);
|
||||
#ifdef __riscv_atomic
|
||||
int32_t r;
|
||||
do {
|
||||
__asm__ __volatile__ (
|
||||
"amoor.w %0, %2, %1\n"
|
||||
: "=r" (r), "+A" (*tx)
|
||||
: "r" (c));
|
||||
} while (r < 0);
|
||||
#else
|
||||
while ((int32_t)(*tx) < 0);
|
||||
*tx = c;
|
||||
#endif
|
||||
}
|
||||
|
||||
extern void kputs(const char *);
|
||||
extern void kprintf(const char *, ...);
|
||||
|
||||
#ifdef DEBUG
|
||||
#define dprintf(s, ...) kprintf((s), ##__VA_ARGS__)
|
||||
#define dputs(s) kputs((s))
|
||||
#else
|
||||
#define dprintf(s, ...) do { } while (0)
|
||||
#define dputs(s) do { } while (0)
|
||||
#endif
|
||||
|
||||
#endif /* _SDBOOT_KPRINTF_H */
|
||||
5
fpga/src/main/resources/vcu118/sdboot/linker/memory.lds
Normal file
5
fpga/src/main/resources/vcu118/sdboot/linker/memory.lds
Normal file
@@ -0,0 +1,5 @@
|
||||
MEMORY
|
||||
{
|
||||
bootrom_mem (rx) : ORIGIN = 0x10000, LENGTH = 0x2000
|
||||
memory_mem (rwx) : ORIGIN = 0x80000000, LENGTH = 0x40000000
|
||||
}
|
||||
80
fpga/src/main/resources/vcu118/sdboot/linker/sdboot.elf.lds
Normal file
80
fpga/src/main/resources/vcu118/sdboot/linker/sdboot.elf.lds
Normal file
@@ -0,0 +1,80 @@
|
||||
OUTPUT_ARCH("riscv")
|
||||
ENTRY(_prog_start)
|
||||
|
||||
INCLUDE memory.lds
|
||||
|
||||
PHDRS
|
||||
{
|
||||
text PT_LOAD;
|
||||
data PT_LOAD;
|
||||
bss PT_LOAD;
|
||||
}
|
||||
|
||||
SECTIONS
|
||||
{
|
||||
PROVIDE(_ram = ORIGIN(memory_mem));
|
||||
PROVIDE(_ram_end = _ram + LENGTH(memory_mem));
|
||||
|
||||
.text ALIGN((ORIGIN(bootrom_mem) + 0x0), 8) : AT(ALIGN((ORIGIN(bootrom_mem) + 0x0), 8)) {
|
||||
PROVIDE(_ftext = .);
|
||||
*(.text.init)
|
||||
*(.text.unlikely .text.unlikely.*)
|
||||
*(.text .text.* .gnu.linkonce.t.*)
|
||||
PROVIDE(_etext = .);
|
||||
. += 0x40; /* to create a gap between .text and .data b/c ifetch can fetch ahead from .data */
|
||||
} >bootrom_mem :text
|
||||
|
||||
.eh_frame ALIGN((ADDR(.text) + SIZEOF(.text)), 8) : AT(ALIGN((LOADADDR(.text) + SIZEOF(.text)), 8)) {
|
||||
*(.eh_frame)
|
||||
} >bootrom_mem :text
|
||||
|
||||
.srodata ALIGN((ADDR(.eh_frame) + SIZEOF(.eh_frame)), 8) : AT(ALIGN((LOADADDR(.eh_frame) + SIZEOF(.eh_frame)), 8)) ALIGN_WITH_INPUT {
|
||||
*(.srodata.cst16)
|
||||
*(.srodata.cst8)
|
||||
*(.srodata.cst4)
|
||||
*(.srodata.cst2)
|
||||
*(.srodata.*)
|
||||
} >bootrom_mem :data
|
||||
|
||||
.data ALIGN((ADDR(.srodata) + SIZEOF(.srodata)), 8) : AT(ALIGN((LOADADDR(.srodata) + SIZEOF(.srodata)), 8)) ALIGN_WITH_INPUT {
|
||||
*(.data .data.* .gnu.linkonce.d.*)
|
||||
*(.tohost) /* TODO: Support sections that aren't explicitly listed in this linker script */
|
||||
} >bootrom_mem :data
|
||||
|
||||
.sdata ALIGN((ADDR(.data) + SIZEOF(.data)), 8) : AT(ALIGN((LOADADDR(.data) + SIZEOF(.data)), 8)) ALIGN_WITH_INPUT {
|
||||
*(.sdata .sdata.* .gnu.linkonce.s.*)
|
||||
} >bootrom_mem :data
|
||||
|
||||
.rodata ALIGN((ADDR(.sdata) + SIZEOF(.sdata)), 8) : AT(ALIGN((LOADADDR(.sdata) + SIZEOF(.sdata)), 8)) ALIGN_WITH_INPUT {
|
||||
*(.rodata .rodata.* .gnu.linkonce.r.*)
|
||||
*(.dtb) /* Must be last if this code is added to RC's BootROM */
|
||||
} >bootrom_mem :data
|
||||
|
||||
PROVIDE(_data = ADDR(.rodata));
|
||||
PROVIDE(_data_lma = LOADADDR(.rodata));
|
||||
PROVIDE(_edata = .);
|
||||
|
||||
.bss ALIGN((ORIGIN(memory_mem) + 0x0), 8) : AT(ALIGN((ORIGIN(memory_mem) + 0x0), 8)) ALIGN(8) {
|
||||
PROVIDE(_fbss = .);
|
||||
PROVIDE(__global_pointer$ = . + 0x7C0);
|
||||
*(.sbss .sbss.* .gnu.linkonce.sb.*)
|
||||
*(.bss .bss.* .gnu.linkonce.b.*)
|
||||
. = ALIGN(8);
|
||||
PROVIDE(_ebss = .);
|
||||
} >memory_mem :bss
|
||||
|
||||
PROVIDE(_end = .);
|
||||
|
||||
/*
|
||||
* heap_stack_region_usable_end: (ORIGIN(memory_mem) + LENGTH(memory_mem))
|
||||
* heap_stack_min_size: 4096
|
||||
* heap_stack_max_size: 1048576
|
||||
*/
|
||||
PROVIDE(_sp = ALIGN(MIN((ORIGIN(memory_mem) + LENGTH(memory_mem)), _ebss + 1048576) - 7, 8));
|
||||
PROVIDE(_heap_end = _sp - 2048);
|
||||
|
||||
/* This section is a noop and is only used for the ASSERT */
|
||||
.stack : {
|
||||
ASSERT(_sp >= (_ebss + 4096), "Error: No room left for the heap and stack");
|
||||
}
|
||||
}
|
||||
236
fpga/src/main/resources/vcu118/sdboot/sd.c
Normal file
236
fpga/src/main/resources/vcu118/sdboot/sd.c
Normal file
@@ -0,0 +1,236 @@
|
||||
// See LICENSE.Sifive for license details.
|
||||
#include <stdint.h>
|
||||
|
||||
#include <platform.h>
|
||||
|
||||
#include "common.h"
|
||||
|
||||
#define DEBUG
|
||||
#include "kprintf.h"
|
||||
|
||||
#define MAX_CORES 8
|
||||
|
||||
// A sector is 512 bytes, so ((1 << 11) * 512) = 1 MiB
|
||||
#define PAYLOAD_SIZE (16 << 11)
|
||||
|
||||
// The sector at which the BBL partition starts
|
||||
#define BBL_PARTITION_START_SECTOR 34
|
||||
|
||||
#ifndef TL_CLK
|
||||
#error Must define TL_CLK
|
||||
#endif
|
||||
|
||||
#define F_CLK TL_CLK
|
||||
|
||||
static volatile uint32_t * const spi = (void *)(SPI_CTRL_ADDR);
|
||||
|
||||
static inline uint8_t spi_xfer(uint8_t d)
|
||||
{
|
||||
int32_t r;
|
||||
|
||||
REG32(spi, SPI_REG_TXFIFO) = d;
|
||||
do {
|
||||
r = REG32(spi, SPI_REG_RXFIFO);
|
||||
} while (r < 0);
|
||||
return r;
|
||||
}
|
||||
|
||||
static inline uint8_t sd_dummy(void)
|
||||
{
|
||||
return spi_xfer(0xFF);
|
||||
}
|
||||
|
||||
static uint8_t sd_cmd(uint8_t cmd, uint32_t arg, uint8_t crc)
|
||||
{
|
||||
unsigned long n;
|
||||
uint8_t r;
|
||||
|
||||
REG32(spi, SPI_REG_CSMODE) = SPI_CSMODE_HOLD;
|
||||
sd_dummy();
|
||||
spi_xfer(cmd);
|
||||
spi_xfer(arg >> 24);
|
||||
spi_xfer(arg >> 16);
|
||||
spi_xfer(arg >> 8);
|
||||
spi_xfer(arg);
|
||||
spi_xfer(crc);
|
||||
|
||||
n = 1000;
|
||||
do {
|
||||
r = sd_dummy();
|
||||
if (!(r & 0x80)) {
|
||||
// dprintf("sd:cmd: %hx\r\n", r);
|
||||
goto done;
|
||||
}
|
||||
} while (--n > 0);
|
||||
kputs("sd_cmd: timeout");
|
||||
done:
|
||||
return r;
|
||||
}
|
||||
|
||||
static inline void sd_cmd_end(void)
|
||||
{
|
||||
sd_dummy();
|
||||
REG32(spi, SPI_REG_CSMODE) = SPI_CSMODE_AUTO;
|
||||
}
|
||||
|
||||
|
||||
static void sd_poweron(void)
|
||||
{
|
||||
long i;
|
||||
REG32(spi, SPI_REG_SCKDIV) = (F_CLK / 300000UL);
|
||||
REG32(spi, SPI_REG_CSMODE) = SPI_CSMODE_OFF;
|
||||
for (i = 10; i > 0; i--) {
|
||||
sd_dummy();
|
||||
}
|
||||
REG32(spi, SPI_REG_CSMODE) = SPI_CSMODE_AUTO;
|
||||
}
|
||||
|
||||
static int sd_cmd0(void)
|
||||
{
|
||||
int rc;
|
||||
dputs("CMD0");
|
||||
rc = (sd_cmd(0x40, 0, 0x95) != 0x01);
|
||||
sd_cmd_end();
|
||||
return rc;
|
||||
}
|
||||
|
||||
static int sd_cmd8(void)
|
||||
{
|
||||
int rc;
|
||||
dputs("CMD8");
|
||||
rc = (sd_cmd(0x48, 0x000001AA, 0x87) != 0x01);
|
||||
sd_dummy(); /* command version; reserved */
|
||||
sd_dummy(); /* reserved */
|
||||
rc |= ((sd_dummy() & 0xF) != 0x1); /* voltage */
|
||||
rc |= (sd_dummy() != 0xAA); /* check pattern */
|
||||
sd_cmd_end();
|
||||
return rc;
|
||||
}
|
||||
|
||||
static void sd_cmd55(void)
|
||||
{
|
||||
sd_cmd(0x77, 0, 0x65);
|
||||
sd_cmd_end();
|
||||
}
|
||||
|
||||
static int sd_acmd41(void)
|
||||
{
|
||||
uint8_t r;
|
||||
dputs("ACMD41");
|
||||
do {
|
||||
sd_cmd55();
|
||||
r = sd_cmd(0x69, 0x40000000, 0x77); /* HCS = 1 */
|
||||
} while (r == 0x01);
|
||||
return (r != 0x00);
|
||||
}
|
||||
|
||||
static int sd_cmd58(void)
|
||||
{
|
||||
int rc;
|
||||
dputs("CMD58");
|
||||
rc = (sd_cmd(0x7A, 0, 0xFD) != 0x00);
|
||||
rc |= ((sd_dummy() & 0x80) != 0x80); /* Power up status */
|
||||
sd_dummy();
|
||||
sd_dummy();
|
||||
sd_dummy();
|
||||
sd_cmd_end();
|
||||
return rc;
|
||||
}
|
||||
|
||||
static int sd_cmd16(void)
|
||||
{
|
||||
int rc;
|
||||
dputs("CMD16");
|
||||
rc = (sd_cmd(0x50, 0x200, 0x15) != 0x00);
|
||||
sd_cmd_end();
|
||||
return rc;
|
||||
}
|
||||
|
||||
static uint16_t crc16_round(uint16_t crc, uint8_t data) {
|
||||
crc = (uint8_t)(crc >> 8) | (crc << 8);
|
||||
crc ^= data;
|
||||
crc ^= (uint8_t)(crc >> 4) & 0xf;
|
||||
crc ^= crc << 12;
|
||||
crc ^= (crc & 0xff) << 5;
|
||||
return crc;
|
||||
}
|
||||
|
||||
#define SPIN_SHIFT 6
|
||||
#define SPIN_UPDATE(i) (!((i) & ((1 << SPIN_SHIFT)-1)))
|
||||
#define SPIN_INDEX(i) (((i) >> SPIN_SHIFT) & 0x3)
|
||||
|
||||
static const char spinner[] = { '-', '/', '|', '\\' };
|
||||
|
||||
static int copy(void)
|
||||
{
|
||||
volatile uint8_t *p = (void *)(PAYLOAD_DEST);
|
||||
long i = PAYLOAD_SIZE;
|
||||
int rc = 0;
|
||||
|
||||
dputs("CMD18");
|
||||
kprintf("LOADING ");
|
||||
|
||||
// John: Let's go slow until we get this working
|
||||
//REG32(spi, SPI_REG_SCKDIV) = (F_CLK / 16666666UL);
|
||||
REG32(spi, SPI_REG_SCKDIV) = (F_CLK / 5000000UL);
|
||||
if (sd_cmd(0x52, BBL_PARTITION_START_SECTOR, 0xE1) != 0x00) {
|
||||
sd_cmd_end();
|
||||
return 1;
|
||||
}
|
||||
do {
|
||||
uint16_t crc, crc_exp;
|
||||
long n;
|
||||
|
||||
crc = 0;
|
||||
n = 512;
|
||||
while (sd_dummy() != 0xFE);
|
||||
do {
|
||||
uint8_t x = sd_dummy();
|
||||
*p++ = x;
|
||||
crc = crc16_round(crc, x);
|
||||
} while (--n > 0);
|
||||
|
||||
crc_exp = ((uint16_t)sd_dummy() << 8);
|
||||
crc_exp |= sd_dummy();
|
||||
|
||||
if (crc != crc_exp) {
|
||||
kputs("\b- CRC mismatch ");
|
||||
rc = 1;
|
||||
break;
|
||||
}
|
||||
|
||||
if (SPIN_UPDATE(i)) {
|
||||
kputc('\b');
|
||||
kputc(spinner[SPIN_INDEX(i)]);
|
||||
}
|
||||
} while (--i > 0);
|
||||
sd_cmd_end();
|
||||
|
||||
sd_cmd(0x4C, 0, 0x01);
|
||||
sd_cmd_end();
|
||||
kputs("\b ");
|
||||
return rc;
|
||||
}
|
||||
|
||||
int main(void)
|
||||
{
|
||||
REG32(uart, UART_REG_TXCTRL) = UART_TXEN;
|
||||
|
||||
kputs("INIT");
|
||||
sd_poweron();
|
||||
if (sd_cmd0() ||
|
||||
sd_cmd8() ||
|
||||
sd_acmd41() ||
|
||||
sd_cmd58() ||
|
||||
sd_cmd16() ||
|
||||
copy()) {
|
||||
kputs("ERROR");
|
||||
return 1;
|
||||
}
|
||||
|
||||
kputs("BOOT");
|
||||
|
||||
__asm__ __volatile__ ("fence.i" : : : "memory");
|
||||
|
||||
return 0;
|
||||
}
|
||||
41
fpga/src/main/scala/arty/Configs.scala
Normal file
41
fpga/src/main/scala/arty/Configs.scala
Normal file
@@ -0,0 +1,41 @@
|
||||
// See LICENSE for license details.
|
||||
package chipyard.fpga.arty
|
||||
|
||||
import freechips.rocketchip.config._
|
||||
import freechips.rocketchip.subsystem._
|
||||
import freechips.rocketchip.devices.debug._
|
||||
import freechips.rocketchip.devices.tilelink._
|
||||
import freechips.rocketchip.diplomacy.{DTSModel, DTSTimebase}
|
||||
import freechips.rocketchip.system._
|
||||
import freechips.rocketchip.tile._
|
||||
|
||||
import sifive.blocks.devices.uart._
|
||||
|
||||
import testchipip.{SerialTLKey}
|
||||
|
||||
import chipyard.{BuildSystem}
|
||||
|
||||
class WithDefaultPeripherals extends Config((site, here, up) => {
|
||||
case PeripheryUARTKey => List(
|
||||
UARTParams(address = 0x10013000))
|
||||
case DTSTimebase => BigInt(32768)
|
||||
case JtagDTMKey => new JtagDTMConfig (
|
||||
idcodeVersion = 2,
|
||||
idcodePartNum = 0x000,
|
||||
idcodeManufId = 0x489,
|
||||
debugIdleCycles = 5)
|
||||
case SerialTLKey => None // remove serialized tl port
|
||||
})
|
||||
// DOC include start: AbstractArty and Rocket
|
||||
class WithArtyTweaks extends Config(
|
||||
new WithArtyJTAGHarnessBinder ++
|
||||
new WithArtyUARTHarnessBinder ++
|
||||
new WithArtyResetHarnessBinder ++
|
||||
new WithDebugResetPassthrough ++
|
||||
new WithDefaultPeripherals ++
|
||||
new freechips.rocketchip.subsystem.WithNBreakpoints(2))
|
||||
|
||||
class TinyRocketArtyConfig extends Config(
|
||||
new WithArtyTweaks ++
|
||||
new chipyard.TinyRocketConfig)
|
||||
// DOC include end: AbstractArty and Rocket
|
||||
71
fpga/src/main/scala/arty/HarnessBinders.scala
Normal file
71
fpga/src/main/scala/arty/HarnessBinders.scala
Normal file
@@ -0,0 +1,71 @@
|
||||
package chipyard.fpga.arty
|
||||
|
||||
import chisel3._
|
||||
|
||||
import freechips.rocketchip.devices.debug._
|
||||
import freechips.rocketchip.jtag.{JTAGIO}
|
||||
import freechips.rocketchip.subsystem._
|
||||
|
||||
import sifive.blocks.devices.uart._
|
||||
import sifive.blocks.devices.jtag._
|
||||
import sifive.blocks.devices.pinctrl._
|
||||
|
||||
import sifive.fpgashells.ip.xilinx.{IBUFG, IOBUF, PULLUP, PowerOnResetFPGAOnly}
|
||||
|
||||
import chipyard.harness.{ComposeHarnessBinder, OverrideHarnessBinder}
|
||||
|
||||
class WithArtyResetHarnessBinder extends ComposeHarnessBinder({
|
||||
(system: HasPeripheryDebugModuleImp, th: ArtyFPGATestHarness, ports: Seq[Bool]) => {
|
||||
require(ports.size == 2)
|
||||
|
||||
withClockAndReset(th.clock_32MHz, th.ck_rst) {
|
||||
// Debug module reset
|
||||
th.dut_ndreset := ports(0)
|
||||
|
||||
// JTAG reset
|
||||
ports(1) := PowerOnResetFPGAOnly(th.clock_32MHz)
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
class WithArtyJTAGHarnessBinder extends OverrideHarnessBinder({
|
||||
(system: HasPeripheryDebug, th: ArtyFPGATestHarness, ports: Seq[Data]) => {
|
||||
ports.map {
|
||||
case j: JTAGIO =>
|
||||
withClockAndReset(th.harnessClock, th.hReset) {
|
||||
val io_jtag = Wire(new JTAGPins(() => new BasePin(), false)).suggestName("jtag")
|
||||
|
||||
JTAGPinsFromPort(io_jtag, j)
|
||||
|
||||
io_jtag.TCK.i.ival := IBUFG(IOBUF(th.jd_2).asClock).asBool
|
||||
|
||||
IOBUF(th.jd_5, io_jtag.TMS)
|
||||
PULLUP(th.jd_5)
|
||||
|
||||
IOBUF(th.jd_4, io_jtag.TDI)
|
||||
PULLUP(th.jd_4)
|
||||
|
||||
IOBUF(th.jd_0, io_jtag.TDO)
|
||||
|
||||
// mimic putting a pullup on this line (part of reset vote)
|
||||
th.SRST_n := IOBUF(th.jd_6)
|
||||
PULLUP(th.jd_6)
|
||||
|
||||
// ignore the po input
|
||||
io_jtag.TCK.i.po.map(_ := DontCare)
|
||||
io_jtag.TDI.i.po.map(_ := DontCare)
|
||||
io_jtag.TMS.i.po.map(_ := DontCare)
|
||||
io_jtag.TDO.i.po.map(_ := DontCare)
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
class WithArtyUARTHarnessBinder extends OverrideHarnessBinder({
|
||||
(system: HasPeripheryUARTModuleImp, th: ArtyFPGATestHarness, ports: Seq[UARTPortIO]) => {
|
||||
withClockAndReset(th.clock_32MHz, th.ck_rst) {
|
||||
IOBUF(th.uart_txd_in, ports.head.txd)
|
||||
ports.head.rxd := IOBUF(th.uart_rxd_out)
|
||||
}
|
||||
}
|
||||
})
|
||||
24
fpga/src/main/scala/arty/IOBinders.scala
Normal file
24
fpga/src/main/scala/arty/IOBinders.scala
Normal file
@@ -0,0 +1,24 @@
|
||||
package chipyard.fpga.arty
|
||||
|
||||
import chisel3._
|
||||
import chisel3.experimental.{IO}
|
||||
|
||||
import freechips.rocketchip.util._
|
||||
import freechips.rocketchip.devices.debug._
|
||||
|
||||
import chipyard.iobinders.{ComposeIOBinder}
|
||||
|
||||
class WithDebugResetPassthrough extends ComposeIOBinder({
|
||||
(system: HasPeripheryDebugModuleImp) => {
|
||||
// Debug module reset
|
||||
val io_ndreset: Bool = IO(Output(Bool())).suggestName("ndreset")
|
||||
io_ndreset := system.debug.get.ndreset
|
||||
|
||||
// JTAG reset
|
||||
val sjtag = system.debug.get.systemjtag.get
|
||||
val io_sjtag_reset: Bool = IO(Input(Bool())).suggestName("sjtag_reset")
|
||||
sjtag.reset := io_sjtag_reset
|
||||
|
||||
(Seq(io_ndreset, io_sjtag_reset), Nil)
|
||||
}
|
||||
})
|
||||
44
fpga/src/main/scala/arty/TestHarness.scala
Normal file
44
fpga/src/main/scala/arty/TestHarness.scala
Normal file
@@ -0,0 +1,44 @@
|
||||
package chipyard.fpga.arty
|
||||
|
||||
import chisel3._
|
||||
|
||||
import freechips.rocketchip.diplomacy.{LazyModule}
|
||||
import freechips.rocketchip.config.{Parameters}
|
||||
|
||||
import sifive.fpgashells.shell.xilinx.artyshell.{ArtyShell}
|
||||
|
||||
import chipyard.{BuildTop, HasHarnessSignalReferences, HasTestHarnessFunctions}
|
||||
import chipyard.harness.{ApplyHarnessBinders}
|
||||
import chipyard.iobinders.{HasIOBinders}
|
||||
|
||||
class ArtyFPGATestHarness(override implicit val p: Parameters) extends ArtyShell with HasHarnessSignalReferences {
|
||||
|
||||
val lazyDut = LazyModule(p(BuildTop)(p)).suggestName("chiptop")
|
||||
|
||||
// Convert harness resets from Bool to Reset type.
|
||||
val hReset = Wire(Reset())
|
||||
hReset := ck_rst
|
||||
|
||||
val dReset = Wire(AsyncReset())
|
||||
dReset := reset_core.asAsyncReset
|
||||
|
||||
// default to 32MHz clock
|
||||
withClockAndReset(clock_32MHz, hReset) {
|
||||
val dut = Module(lazyDut.module)
|
||||
}
|
||||
|
||||
val harnessClock = clock_32MHz
|
||||
val harnessReset = hReset
|
||||
val success = false.B
|
||||
|
||||
val dutReset = dReset
|
||||
|
||||
// must be after HasHarnessSignalReferences assignments
|
||||
lazyDut match { case d: HasTestHarnessFunctions =>
|
||||
d.harnessFunctions.foreach(_(this))
|
||||
}
|
||||
lazyDut match { case d: HasIOBinders =>
|
||||
ApplyHarnessBinders(this, d.lazySystem, d.portMap)
|
||||
}
|
||||
}
|
||||
|
||||
74
fpga/src/main/scala/vcu118/Configs.scala
Normal file
74
fpga/src/main/scala/vcu118/Configs.scala
Normal file
@@ -0,0 +1,74 @@
|
||||
package chipyard.fpga.vcu118
|
||||
|
||||
import sys.process._
|
||||
|
||||
import freechips.rocketchip.config.{Config, Parameters}
|
||||
import freechips.rocketchip.subsystem.{SystemBusKey, PeripheryBusKey, ControlBusKey, ExtMem}
|
||||
import freechips.rocketchip.devices.debug.{DebugModuleKey, ExportDebug, JTAG}
|
||||
import freechips.rocketchip.devices.tilelink.{DevNullParams, BootROMLocated}
|
||||
import freechips.rocketchip.diplomacy.{DTSModel, DTSTimebase, RegionType, AddressSet}
|
||||
import freechips.rocketchip.tile.{XLen}
|
||||
|
||||
import sifive.blocks.devices.spi.{PeripherySPIKey, SPIParams}
|
||||
import sifive.blocks.devices.uart.{PeripheryUARTKey, UARTParams}
|
||||
|
||||
import sifive.fpgashells.shell.{DesignKey}
|
||||
import sifive.fpgashells.shell.xilinx.{VCU118ShellPMOD, VCU118DDRSize}
|
||||
|
||||
import testchipip.{SerialTLKey}
|
||||
|
||||
import chipyard.{BuildSystem, ExtTLMem}
|
||||
|
||||
class WithDefaultPeripherals extends Config((site, here, up) => {
|
||||
case PeripheryUARTKey => List(UARTParams(address = BigInt(0x64000000L)))
|
||||
case PeripherySPIKey => List(SPIParams(rAddress = BigInt(0x64001000L)))
|
||||
case VCU118ShellPMOD => "SDIO"
|
||||
})
|
||||
|
||||
class WithSystemModifications extends Config((site, here, up) => {
|
||||
case PeripheryBusKey => up(PeripheryBusKey, site).copy(dtsFrequency = Some(site(FPGAFrequencyKey).toInt*1000000))
|
||||
case DTSTimebase => BigInt(1000000)
|
||||
case BootROMLocated(x) => up(BootROMLocated(x), site).map { p =>
|
||||
// invoke makefile for sdboot
|
||||
val freqMHz = site(FPGAFrequencyKey).toInt * 1000000
|
||||
val make = s"make -C fpga/src/main/resources/vcu118/sdboot PBUS_CLK=${freqMHz} bin"
|
||||
require (make.! == 0, "Failed to build bootrom")
|
||||
p.copy(hang = 0x10000, contentFileName = s"./fpga/src/main/resources/vcu118/sdboot/build/sdboot.bin")
|
||||
}
|
||||
case ExtMem => up(ExtMem, site).map(x => x.copy(master = x.master.copy(size = site(VCU118DDRSize)))) // set extmem to DDR size
|
||||
case SerialTLKey => None // remove serialized tl port
|
||||
})
|
||||
|
||||
// DOC include start: AbstractVCU118 and Rocket
|
||||
class WithVCU118Tweaks extends Config(
|
||||
new WithUART ++
|
||||
new WithSPISDCard ++
|
||||
new WithDDRMem ++
|
||||
new WithUARTIOPassthrough ++
|
||||
new WithSPIIOPassthrough ++
|
||||
new WithTLIOPassthrough ++
|
||||
new WithDefaultPeripherals ++
|
||||
new chipyard.config.WithTLBackingMemory ++ // use TL backing memory
|
||||
new WithSystemModifications ++ // setup busses, use sdboot bootrom, setup ext. mem. size
|
||||
new chipyard.config.WithNoDebug ++ // remove debug module
|
||||
new freechips.rocketchip.subsystem.WithoutTLMonitors ++
|
||||
new freechips.rocketchip.subsystem.WithNMemoryChannels(1))
|
||||
|
||||
class RocketVCU118Config extends Config(
|
||||
new WithVCU118Tweaks ++
|
||||
new chipyard.RocketConfig)
|
||||
// DOC include end: AbstractVCU118 and Rocket
|
||||
|
||||
class BoomVCU118Config extends Config(
|
||||
new WithFPGAFrequency(50) ++
|
||||
new WithVCU118Tweaks ++
|
||||
new chipyard.MegaBoomConfig)
|
||||
|
||||
class WithFPGAFrequency(MHz: Double) extends Config((site, here, up) => {
|
||||
case FPGAFrequencyKey => MHz
|
||||
})
|
||||
|
||||
class WithFPGAFreq25MHz extends WithFPGAFrequency(25)
|
||||
class WithFPGAFreq50MHz extends WithFPGAFrequency(50)
|
||||
class WithFPGAFreq75MHz extends WithFPGAFrequency(75)
|
||||
class WithFPGAFreq100MHz extends WithFPGAFrequency(100)
|
||||
110
fpga/src/main/scala/vcu118/CustomOverlays.scala
Normal file
110
fpga/src/main/scala/vcu118/CustomOverlays.scala
Normal file
@@ -0,0 +1,110 @@
|
||||
package chipyard.fpga.vcu118
|
||||
|
||||
import chisel3._
|
||||
|
||||
import freechips.rocketchip.diplomacy._
|
||||
import freechips.rocketchip.config.{Parameters, Field}
|
||||
import freechips.rocketchip.tilelink.{TLInwardNode, TLAsyncCrossingSink}
|
||||
|
||||
import sifive.fpgashells.shell._
|
||||
import sifive.fpgashells.ip.xilinx._
|
||||
import sifive.fpgashells.shell.xilinx._
|
||||
import sifive.fpgashells.clocks._
|
||||
import sifive.fpgashells.devices.xilinx.xilinxvcu118mig.{XilinxVCU118MIGPads, XilinxVCU118MIGParams, XilinxVCU118MIG}
|
||||
|
||||
class SysClock2VCU118PlacedOverlay(val shell: VCU118ShellBasicOverlays, name: String, val designInput: ClockInputDesignInput, val shellInput: ClockInputShellInput)
|
||||
extends LVDSClockInputXilinxPlacedOverlay(name, designInput, shellInput)
|
||||
{
|
||||
val node = shell { ClockSourceNode(freqMHz = 250, jitterPS = 50)(ValName(name)) }
|
||||
|
||||
shell { InModuleBody {
|
||||
shell.xdc.addPackagePin(io.p, "AW26")
|
||||
shell.xdc.addPackagePin(io.n, "AW27")
|
||||
shell.xdc.addIOStandard(io.p, "DIFF_SSTL12")
|
||||
shell.xdc.addIOStandard(io.n, "DIFF_SSTL12")
|
||||
} }
|
||||
}
|
||||
class SysClock2VCU118ShellPlacer(shell: VCU118ShellBasicOverlays, val shellInput: ClockInputShellInput)(implicit val valName: ValName)
|
||||
extends ClockInputShellPlacer[VCU118ShellBasicOverlays]
|
||||
{
|
||||
def place(designInput: ClockInputDesignInput) = new SysClock2VCU118PlacedOverlay(shell, valName.name, designInput, shellInput)
|
||||
}
|
||||
|
||||
case object VCU118DDR2Size extends Field[BigInt](0x40000000L * 2) // 2GB
|
||||
class DDR2VCU118PlacedOverlay(val shell: VCU118FPGATestHarness, name: String, val designInput: DDRDesignInput, val shellInput: DDRShellInput)
|
||||
extends DDRPlacedOverlay[XilinxVCU118MIGPads](name, designInput, shellInput)
|
||||
{
|
||||
val size = p(VCU118DDRSize)
|
||||
|
||||
val migParams = XilinxVCU118MIGParams(address = AddressSet.misaligned(di.baseAddress, size))
|
||||
val mig = LazyModule(new XilinxVCU118MIG(migParams))
|
||||
val ioNode = BundleBridgeSource(() => mig.module.io.cloneType)
|
||||
val topIONode = shell { ioNode.makeSink() }
|
||||
val ddrUI = shell { ClockSourceNode(freqMHz = 200) }
|
||||
val areset = shell { ClockSinkNode(Seq(ClockSinkParameters())) }
|
||||
areset := designInput.wrangler := ddrUI
|
||||
|
||||
// since this uses a separate clk/rst need to put an async crossing
|
||||
val asyncSink = LazyModule(new TLAsyncCrossingSink())
|
||||
val migClkRstNode = BundleBridgeSource(() => new Bundle {
|
||||
val clock = Output(Clock())
|
||||
val reset = Output(Bool())
|
||||
})
|
||||
val topMigClkRstIONode = shell { migClkRstNode.makeSink() }
|
||||
|
||||
def overlayOutput = DDROverlayOutput(ddr = mig.node)
|
||||
def ioFactory = new XilinxVCU118MIGPads(size)
|
||||
|
||||
InModuleBody {
|
||||
ioNode.bundle <> mig.module.io
|
||||
|
||||
// setup async crossing
|
||||
asyncSink.module.clock := migClkRstNode.bundle.clock
|
||||
asyncSink.module.reset := migClkRstNode.bundle.reset
|
||||
}
|
||||
|
||||
shell { InModuleBody {
|
||||
require (shell.sys_clock2.get.isDefined, "Use of DDRVCU118Overlay depends on SysClock2VCU118Overlay")
|
||||
val (sys, _) = shell.sys_clock2.get.get.overlayOutput.node.out(0)
|
||||
val (ui, _) = ddrUI.out(0)
|
||||
val (ar, _) = areset.in(0)
|
||||
|
||||
// connect the async fifo sync to sys_clock2
|
||||
topMigClkRstIONode.bundle.clock := sys.clock
|
||||
topMigClkRstIONode.bundle.reset := sys.reset
|
||||
|
||||
val port = topIONode.bundle.port
|
||||
io <> port
|
||||
ui.clock := port.c0_ddr4_ui_clk
|
||||
ui.reset := /*!port.mmcm_locked ||*/ port.c0_ddr4_ui_clk_sync_rst
|
||||
port.c0_sys_clk_i := sys.clock.asUInt
|
||||
port.sys_rst := sys.reset // pllReset
|
||||
port.c0_ddr4_aresetn := !ar.reset
|
||||
|
||||
// This was just copied from the SiFive example, but it's hard to follow.
|
||||
// The pins are emitted in the following order:
|
||||
// adr[0->13], we_n, cas_n, ras_n, bg, ba[0->1], reset_n, act_n, ck_c, ck_t, cke, cs_n, odt, dq[0->63], dqs_c[0->7], dqs_t[0->7], dm_dbi_n[0->7]
|
||||
val allddrpins = Seq(
|
||||
"AM27", "AL27", "AP26", "AP25", "AN28", "AM28", "AP28", "AP27", "AN26", "AM26", "AR28", "AR27", "AV25", "AT25", // adr[0->13]
|
||||
"AV28", "AU26", "AV26", "AU27", // we_n, cas_n, ras_n, bg
|
||||
"AR25", "AU28", // ba[0->1]
|
||||
"BD35", "AN25", "AT27", "AT26", "AW28", "AY29", "BB29", // reset_n, act_n, ck_c, ck_t, cke, cs_n, odt
|
||||
"BD30", "BE30", "BD32", "BE33", "BC33", "BD33", "BC31", "BD31", "BA32", "BB33", "BA30", "BA31", "AW31", "AW32", "AY32", "AY33", // dq[0->15]
|
||||
"AV30", "AW30", "AU33", "AU34", "AT31", "AU32", "AU31", "AV31", "AR33", "AT34", "AT29", "AT30", "AP30", "AR30", "AN30", "AN31", // dq[16->31]
|
||||
"BE34", "BF34", "BC35", "BC36", "BD36", "BE37", "BF36", "BF37", "BD37", "BE38", "BC39", "BD40", "BB38", "BB39", "BC38", "BD38", // dq[32->47]
|
||||
"BB36", "BB37", "BA39", "BA40", "AW40", "AY40", "AY38", "AY39", "AW35", "AW36", "AU40", "AV40", "AU38", "AU39", "AV38", "AV39", // dq[48->63]
|
||||
"BF31", "BA34", "AV29", "AP32", "BF35", "BF39", "BA36", "AW38", // dqs_c[0->7]
|
||||
"BF30", "AY34", "AU29", "AP31", "BE35", "BE39", "BA35", "AW37", // dqs_t[0->7]
|
||||
"BE32", "BB31", "AV33", "AR32", "BC34", "BE40", "AY37", "AV35") // dm_dbi_n[0->7]
|
||||
|
||||
(IOPin.of(io) zip allddrpins) foreach { case (io, pin) => shell.xdc.addPackagePin(io, pin) }
|
||||
} }
|
||||
|
||||
shell.sdc.addGroup(pins = Seq(mig.island.module.blackbox.io.c0_ddr4_ui_clk))
|
||||
}
|
||||
|
||||
class DDR2VCU118ShellPlacer(shell: VCU118FPGATestHarness, val shellInput: DDRShellInput)(implicit val valName: ValName)
|
||||
extends DDRShellPlacer[VCU118FPGATestHarness] {
|
||||
def place(designInput: DDRDesignInput) = new DDR2VCU118PlacedOverlay(shell, valName.name, designInput, shellInput)
|
||||
}
|
||||
|
||||
334
fpga/src/main/scala/vcu118/FMCUtil.scala
Normal file
334
fpga/src/main/scala/vcu118/FMCUtil.scala
Normal file
@@ -0,0 +1,334 @@
|
||||
package chipyard.fpga.vcu118
|
||||
|
||||
import scala.collection.immutable.HashMap
|
||||
|
||||
// TODO: was typed by hand, so this needs a once-over before it can be considered trustworthy
|
||||
|
||||
object FMCMap {
|
||||
// Take an FMC pin name and return the VCU118 package pin
|
||||
// See https://www.xilinx.com/support/documentation/boards_and_kits/vcu118/ug1224-vcu118-eval-bd.pdf
|
||||
// Pages 97-98
|
||||
// Omitted pins are not connected to a GPIO
|
||||
def apply(fmcPin: String): String = HashMap(
|
||||
"C10" -> "BD13",
|
||||
"C11" -> "BE13",
|
||||
"C14" -> "BB13",
|
||||
"C15" -> "BB12",
|
||||
"C18" -> "AW8",
|
||||
"C19" -> "AW7",
|
||||
"C22" -> "AP12",
|
||||
"C23" -> "AR12",
|
||||
"C26" -> "AL14",
|
||||
"C27" -> "AM14",
|
||||
"D1" -> "AK35",
|
||||
"D8" -> "BF10",
|
||||
"D9" -> "BF9",
|
||||
"D11" -> "BE14",
|
||||
"D12" -> "BF14",
|
||||
"D14" -> "BA14",
|
||||
"D15" -> "BB14",
|
||||
"D17" -> "AY8",
|
||||
"D18" -> "AY7",
|
||||
"D20" -> "AR14",
|
||||
"D21" -> "AT14",
|
||||
"D23" -> "AN16",
|
||||
"D24" -> "AP16",
|
||||
"D26" -> "AK15",
|
||||
"D27" -> "AL15",
|
||||
"F1" -> "BA7",
|
||||
"G2" -> "AV14",
|
||||
"G3" -> "AV13",
|
||||
"G6" -> "AY9",
|
||||
"G7" -> "BA9",
|
||||
"G9" -> "BD12",
|
||||
"G10" -> "BE12",
|
||||
"G12" -> "BE15",
|
||||
"G13" -> "BF15",
|
||||
"G15" -> "BC14",
|
||||
"G16" -> "BC13",
|
||||
"G18" -> "AV9",
|
||||
"G19" -> "AV8",
|
||||
"G21" -> "AW11",
|
||||
"G22" -> "AY10",
|
||||
"G24" -> "AW13",
|
||||
"G25" -> "AY13",
|
||||
"G27" -> "AT12",
|
||||
"G28" -> "AU12",
|
||||
"G30" -> "AN15",
|
||||
"G31" -> "AP15",
|
||||
"G33" -> "AM13",
|
||||
"G34" -> "AM12",
|
||||
"G36" -> "AK14",
|
||||
"G37" -> "AK13",
|
||||
"H2" -> "BB7",
|
||||
"H4" -> "BC9",
|
||||
"H5" -> "BC8",
|
||||
"H7" -> "BC11",
|
||||
"H8" -> "BD11",
|
||||
"H10" -> "BF12",
|
||||
"H11" -> "BF11",
|
||||
"H13" -> "BC15",
|
||||
"H14" -> "BD15",
|
||||
"H16" -> "BA16",
|
||||
"H17" -> "BA15",
|
||||
"H19" -> "BB16",
|
||||
"H20" -> "BC16",
|
||||
"H22" -> "AW12",
|
||||
"H23" -> "AY12",
|
||||
"H25" -> "AU11",
|
||||
"H26" -> "AV11",
|
||||
"H28" -> "AP13",
|
||||
"H29" -> "AR13",
|
||||
"H31" -> "AV10",
|
||||
"H32" -> "AW10",
|
||||
"H34" -> "AK12",
|
||||
"H35" -> "AL12",
|
||||
"H37" -> "AJ13",
|
||||
"H38" -> "AJ12"
|
||||
)(fmcPin)
|
||||
}
|
||||
|
||||
object FMCPMap {
|
||||
// Take an FMC+ pin name and return the VCU118 package pin
|
||||
// See https://www.xilinx.com/support/documentation/boards_and_kits/vcu118/ug1224-vcu118-eval-bd.pdf
|
||||
// Pages 100-106
|
||||
// Omitted pins are not connected to a GPIO
|
||||
def apply(fmcpPin: String): String = HashMap(
|
||||
"A2" -> "AN45",
|
||||
"A3" -> "AN46",
|
||||
"A6" -> "AL45",
|
||||
"A7" -> "AL45",
|
||||
"A10" -> "AJ45",
|
||||
"A11" -> "AJ46",
|
||||
"A14" -> "W45",
|
||||
"A15" -> "W46",
|
||||
"A18" -> "U45",
|
||||
"A19" -> "U46",
|
||||
"A22" -> "AP42",
|
||||
"A23" -> "AP43",
|
||||
"A26" -> "AM42",
|
||||
"A27" -> "AM43",
|
||||
"A30" -> "AL40",
|
||||
"A31" -> "AL41",
|
||||
"A34" -> "T42",
|
||||
"A35" -> "T43",
|
||||
"A38" -> "P42",
|
||||
"A39" -> "P43",
|
||||
"B4" -> "AF43",
|
||||
"B5" -> "AF44",
|
||||
"B8" -> "AG45",
|
||||
"B9" -> "AG46",
|
||||
"B12" -> "N45",
|
||||
"B13" -> "N46",
|
||||
"B16" -> "R45",
|
||||
"B17" -> "R46",
|
||||
"B24" -> "AJ40",
|
||||
"B25" -> "AJ41",
|
||||
"B28" -> "AK42",
|
||||
"B29" -> "AK43",
|
||||
"B32" -> "K42",
|
||||
"B33" -> "K43",
|
||||
"B36" -> "M42",
|
||||
"B37" -> "M43",
|
||||
"C2" -> "AT42",
|
||||
"C3" -> "AT43",
|
||||
"C6" -> "AR45",
|
||||
"C7" -> "AR46",
|
||||
"C10" -> "AT35",
|
||||
"C11" -> "AT36",
|
||||
"C14" -> "AP35",
|
||||
"C15" -> "AR35",
|
||||
"C18" -> "AG31",
|
||||
"C19" -> "AH31",
|
||||
"C22" -> "R31",
|
||||
"C23" -> "P31",
|
||||
"C26" -> "V33",
|
||||
"C27" -> "V34",
|
||||
"D1" -> "AK35",
|
||||
"D8" -> "AL30",
|
||||
"D9" -> "AL31",
|
||||
"D11" -> "AP38",
|
||||
"D12" -> "AR38",
|
||||
"D14" -> "AJ33",
|
||||
"D15" -> "AK33",
|
||||
"D17" -> "AJ35",
|
||||
"D18" -> "AJ36",
|
||||
"D20" -> "R34",
|
||||
"D21" -> "P34",
|
||||
"D23" -> "Y32",
|
||||
"D24" -> "W32",
|
||||
"D26" -> "V32",
|
||||
"D27" -> "U33",
|
||||
"E2" -> "V15",
|
||||
"E3" -> "U15",
|
||||
"E6" -> "R14",
|
||||
"E7" -> "P14",
|
||||
"E9" -> "W14",
|
||||
"E10" -> "V14",
|
||||
"E12" -> "V13",
|
||||
"E13" -> "U12",
|
||||
"E15" -> "T14",
|
||||
"E16" -> "R13",
|
||||
"E18" -> "M15",
|
||||
"E19" -> "L15",
|
||||
"F1" -> "AM34",
|
||||
"F4" -> "N14",
|
||||
"F5" -> "N13",
|
||||
"F7" -> "AA13",
|
||||
"F8" -> "Y13",
|
||||
"F10" -> "U11",
|
||||
"F11" -> "T11",
|
||||
"F13" -> "T16",
|
||||
"F14" -> "T15",
|
||||
"F16" -> "M13",
|
||||
"F17" -> "M12",
|
||||
"F19" -> "L14",
|
||||
"F20" -> "L13",
|
||||
"G2" -> "P35",
|
||||
"G3" -> "P36",
|
||||
"G6" -> "AL35",
|
||||
"G7" -> "AL36",
|
||||
"G9" -> "AT39",
|
||||
"G10" -> "AT40",
|
||||
"G12" -> "AK29",
|
||||
"G13" -> "AK30",
|
||||
"G15" -> "AH33",
|
||||
"G16" -> "AH34",
|
||||
"G18" -> "AG34",
|
||||
"G19" -> "AH35",
|
||||
"G21" -> "N32",
|
||||
"G22" -> "M32",
|
||||
"G24" -> "N34",
|
||||
"G25" -> "N35",
|
||||
"G27" -> "Y34",
|
||||
"G28" -> "W34",
|
||||
"G30" -> "U35",
|
||||
"G31" -> "T36",
|
||||
"G33" -> "P37",
|
||||
"G34" -> "N37",
|
||||
"G36" -> "L34",
|
||||
"G37" -> "K34",
|
||||
"H2" -> "AM33",
|
||||
"H4" -> "AL32",
|
||||
"H5" -> "AM32",
|
||||
"H7" -> "AJ32",
|
||||
"H8" -> "AK32",
|
||||
"H10" -> "AR37",
|
||||
"H11" -> "AT37",
|
||||
"H13" -> "AP36",
|
||||
"H14" -> "AP37",
|
||||
"H16" -> "AJ30",
|
||||
"H17" -> "AJ31",
|
||||
"H19" -> "AG32",
|
||||
"H20" -> "AG33",
|
||||
"H22" -> "N33",
|
||||
"H23" -> "M33",
|
||||
"H25" -> "M35",
|
||||
"H26" -> "L35",
|
||||
"H28" -> "T34",
|
||||
"H29" -> "T35",
|
||||
"H31" -> "M36",
|
||||
"H32" -> "L36",
|
||||
"H34" -> "N38",
|
||||
"H35" -> "M38",
|
||||
"H37" -> "L33",
|
||||
"H38" -> "K33",
|
||||
"J6" -> "W12",
|
||||
"J7" -> "V12",
|
||||
"J9" -> "AA14",
|
||||
"J10" -> "Y14",
|
||||
"J12" -> "R12",
|
||||
"J13" -> "P12",
|
||||
"J15" -> "M11",
|
||||
"J16" -> "L11",
|
||||
"J18" -> "P15",
|
||||
"J19" -> "N15",
|
||||
"J21" -> "K12",
|
||||
"J22" -> "J12",
|
||||
"K7" -> "AA12",
|
||||
"K8" -> "Y12",
|
||||
"K10" -> "U13",
|
||||
"K11" -> "T13",
|
||||
"K13" -> "V16",
|
||||
"K14" -> "U16",
|
||||
"K16" -> "R11",
|
||||
"K17" -> "P11",
|
||||
"K19" -> "K14",
|
||||
"K20" -> "K13",
|
||||
"K22" -> "K11",
|
||||
"K23" -> "J11",
|
||||
"L4" -> "R40",
|
||||
"L5" -> "R41",
|
||||
"L8" -> "AB38",
|
||||
"L9" -> "AB39",
|
||||
"L12" -> "AF38",
|
||||
"L13" -> "AF39",
|
||||
"L16" -> "AN34",
|
||||
"L17" -> "AN35",
|
||||
"L20" -> "AN33",
|
||||
"L21" -> "AP33",
|
||||
"L24" -> "AK34",
|
||||
"L25" -> "AL34",
|
||||
"L28" -> "AM36",
|
||||
"L29" -> "AN36",
|
||||
"M2" -> "AU45",
|
||||
"M3" -> "AU46",
|
||||
"M6" -> "AW45",
|
||||
"M7" -> "AW46",
|
||||
"M10" -> "BA45",
|
||||
"M11" -> "BA46",
|
||||
"M14" -> "BC45",
|
||||
"M15" -> "BC46",
|
||||
"M18" -> "W40",
|
||||
"M19" -> "W41",
|
||||
"M22" -> "U40",
|
||||
"M23" -> "U41",
|
||||
"M26" -> "H42",
|
||||
"M27" -> "H43",
|
||||
"M30" -> "F42",
|
||||
"M31" -> "F43",
|
||||
"M34" -> "D42",
|
||||
"M35" -> "D43",
|
||||
"M38" -> "B42",
|
||||
"M39" -> "B43",
|
||||
"Y2" -> "AV42",
|
||||
"Y3" -> "AV43",
|
||||
"Y6" -> "BB42",
|
||||
"Y7" -> "BB43",
|
||||
"Y10" -> "AE45",
|
||||
"Y11" -> "AE46",
|
||||
"Y14" -> "AC45",
|
||||
"Y15" -> "AC46",
|
||||
"Y18" -> "AA45",
|
||||
"Y19" -> "AA46",
|
||||
"Y22" -> "Y43",
|
||||
"Y23" -> "Y44",
|
||||
"Y26" -> "AE40",
|
||||
"Y27" -> "AE41",
|
||||
"Y30" -> "AA40",
|
||||
"Y31" -> "AA41",
|
||||
"Y34" -> "J45",
|
||||
"Y35" -> "J46",
|
||||
"Y38" -> "E45",
|
||||
"Y39" -> "E46",
|
||||
"Z1" -> "AM29",
|
||||
"Z4" -> "AY42",
|
||||
"Z5" -> "AY43",
|
||||
"Z8" -> "BD42",
|
||||
"Z9" -> "BD43",
|
||||
"Z12" -> "AD43",
|
||||
"Z13" -> "AD44",
|
||||
"Z16" -> "AB43",
|
||||
"Z17" -> "AB44",
|
||||
"Z20" -> "AN40",
|
||||
"Z21" -> "AN41",
|
||||
"Z24" -> "AG40",
|
||||
"Z25" -> "AG41",
|
||||
"Z28" -> "AC40",
|
||||
"Z29" -> "AC41",
|
||||
"Z32" -> "L45",
|
||||
"Z33" -> "L46",
|
||||
"Z36" -> "G45",
|
||||
"Z37" -> "G46"
|
||||
)(fmcpPin)
|
||||
}
|
||||
45
fpga/src/main/scala/vcu118/HarnessBinders.scala
Normal file
45
fpga/src/main/scala/vcu118/HarnessBinders.scala
Normal file
@@ -0,0 +1,45 @@
|
||||
package chipyard.fpga.vcu118
|
||||
|
||||
import chisel3._
|
||||
import chisel3.experimental.{BaseModule}
|
||||
|
||||
import freechips.rocketchip.util.{HeterogeneousBag}
|
||||
import freechips.rocketchip.tilelink.{TLBundle}
|
||||
|
||||
import sifive.blocks.devices.uart.{HasPeripheryUARTModuleImp, UARTPortIO}
|
||||
import sifive.blocks.devices.spi.{HasPeripherySPI, SPIPortIO}
|
||||
|
||||
import chipyard.{HasHarnessSignalReferences, CanHaveMasterTLMemPort}
|
||||
import chipyard.harness.{OverrideHarnessBinder}
|
||||
|
||||
/*** UART ***/
|
||||
class WithUART extends OverrideHarnessBinder({
|
||||
(system: HasPeripheryUARTModuleImp, th: BaseModule with HasHarnessSignalReferences, ports: Seq[UARTPortIO]) => {
|
||||
th match { case vcu118th: VCU118FPGATestHarnessImp => {
|
||||
vcu118th.vcu118Outer.io_uart_bb.bundle <> ports.head
|
||||
} }
|
||||
}
|
||||
})
|
||||
|
||||
/*** SPI ***/
|
||||
class WithSPISDCard extends OverrideHarnessBinder({
|
||||
(system: HasPeripherySPI, th: BaseModule with HasHarnessSignalReferences, ports: Seq[SPIPortIO]) => {
|
||||
th match { case vcu118th: VCU118FPGATestHarnessImp => {
|
||||
vcu118th.vcu118Outer.io_spi_bb.bundle <> ports.head
|
||||
} }
|
||||
}
|
||||
})
|
||||
|
||||
/*** Experimental DDR ***/
|
||||
class WithDDRMem extends OverrideHarnessBinder({
|
||||
(system: CanHaveMasterTLMemPort, th: BaseModule with HasHarnessSignalReferences, ports: Seq[HeterogeneousBag[TLBundle]]) => {
|
||||
th match { case vcu118th: VCU118FPGATestHarnessImp => {
|
||||
require(ports.size == 1)
|
||||
|
||||
val bundles = vcu118th.vcu118Outer.ddrClient.out.map(_._1)
|
||||
val ddrClientBundle = Wire(new HeterogeneousBag(bundles.map(_.cloneType)))
|
||||
bundles.zip(ddrClientBundle).foreach { case (bundle, io) => bundle <> io }
|
||||
ddrClientBundle <> ports.head
|
||||
} }
|
||||
}
|
||||
})
|
||||
52
fpga/src/main/scala/vcu118/IOBinders.scala
Normal file
52
fpga/src/main/scala/vcu118/IOBinders.scala
Normal file
@@ -0,0 +1,52 @@
|
||||
package chipyard.fpga.vcu118
|
||||
|
||||
import chisel3._
|
||||
import chisel3.experimental.{IO, DataMirror}
|
||||
|
||||
import freechips.rocketchip.diplomacy.{ResourceBinding, Resource, ResourceAddress, InModuleBody}
|
||||
import freechips.rocketchip.subsystem.{BaseSubsystem}
|
||||
import freechips.rocketchip.util.{HeterogeneousBag}
|
||||
import freechips.rocketchip.tilelink.{TLBundle}
|
||||
|
||||
import sifive.blocks.devices.uart.{HasPeripheryUARTModuleImp}
|
||||
import sifive.blocks.devices.spi.{HasPeripherySPI, HasPeripherySPIModuleImp, MMCDevice}
|
||||
|
||||
import chipyard.{CanHaveMasterTLMemPort}
|
||||
import chipyard.iobinders.{OverrideIOBinder, OverrideLazyIOBinder}
|
||||
|
||||
class WithUARTIOPassthrough extends OverrideIOBinder({
|
||||
(system: HasPeripheryUARTModuleImp) => {
|
||||
val io_uart_pins_temp = system.uart.zipWithIndex.map { case (dio, i) => IO(dio.cloneType).suggestName(s"uart_$i") }
|
||||
(io_uart_pins_temp zip system.uart).map { case (io, sysio) =>
|
||||
io <> sysio
|
||||
}
|
||||
(io_uart_pins_temp, Nil)
|
||||
}
|
||||
})
|
||||
|
||||
class WithSPIIOPassthrough extends OverrideLazyIOBinder({
|
||||
(system: HasPeripherySPI) => {
|
||||
// attach resource to 1st SPI
|
||||
ResourceBinding {
|
||||
Resource(new MMCDevice(system.tlSpiNodes.head.device, 1), "reg").bind(ResourceAddress(0))
|
||||
}
|
||||
|
||||
InModuleBody {
|
||||
system.asInstanceOf[BaseSubsystem].module match { case system: HasPeripherySPIModuleImp => {
|
||||
val io_spi_pins_temp = system.spi.zipWithIndex.map { case (dio, i) => IO(dio.cloneType).suggestName(s"spi_$i") }
|
||||
(io_spi_pins_temp zip system.spi).map { case (io, sysio) =>
|
||||
io <> sysio
|
||||
}
|
||||
(io_spi_pins_temp, Nil)
|
||||
} }
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
class WithTLIOPassthrough extends OverrideIOBinder({
|
||||
(system: CanHaveMasterTLMemPort) => {
|
||||
val io_tl_mem_pins_temp = IO(DataMirror.internal.chiselTypeClone[HeterogeneousBag[TLBundle]](system.mem_tl)).suggestName("tl_slave")
|
||||
io_tl_mem_pins_temp <> system.mem_tl
|
||||
(Seq(io_tl_mem_pins_temp), Nil)
|
||||
}
|
||||
})
|
||||
139
fpga/src/main/scala/vcu118/TestHarness.scala
Normal file
139
fpga/src/main/scala/vcu118/TestHarness.scala
Normal file
@@ -0,0 +1,139 @@
|
||||
package chipyard.fpga.vcu118
|
||||
|
||||
import chisel3._
|
||||
import chisel3.experimental.{IO}
|
||||
|
||||
import freechips.rocketchip.diplomacy._
|
||||
import freechips.rocketchip.config._
|
||||
import freechips.rocketchip.subsystem._
|
||||
import freechips.rocketchip.tilelink._
|
||||
|
||||
import sifive.fpgashells.shell.xilinx._
|
||||
import sifive.fpgashells.ip.xilinx._
|
||||
import sifive.fpgashells.shell._
|
||||
import sifive.fpgashells.clocks._
|
||||
|
||||
import sifive.blocks.devices.uart._
|
||||
import sifive.blocks.devices.spi._
|
||||
import sifive.blocks.devices.gpio._
|
||||
|
||||
import chipyard.{HasHarnessSignalReferences, HasTestHarnessFunctions, BuildTop, ChipTop, ExtTLMem, CanHaveMasterTLMemPort}
|
||||
import chipyard.iobinders.{HasIOBinders}
|
||||
import chipyard.harness.{ApplyHarnessBinders}
|
||||
|
||||
case object FPGAFrequencyKey extends Field[Double](100.0)
|
||||
|
||||
class VCU118FPGATestHarness(override implicit val p: Parameters) extends VCU118ShellBasicOverlays {
|
||||
|
||||
def dp = designParameters
|
||||
|
||||
val pmod_is_sdio = p(VCU118ShellPMOD) == "SDIO"
|
||||
val jtag_location = Some(if (pmod_is_sdio) "FMC_J2" else "PMOD_J52")
|
||||
|
||||
// Order matters; ddr depends on sys_clock
|
||||
val uart = Overlay(UARTOverlayKey, new UARTVCU118ShellPlacer(this, UARTShellInput()))
|
||||
val sdio = if (pmod_is_sdio) Some(Overlay(SPIOverlayKey, new SDIOVCU118ShellPlacer(this, SPIShellInput()))) else None
|
||||
val jtag = Overlay(JTAGDebugOverlayKey, new JTAGDebugVCU118ShellPlacer(this, JTAGDebugShellInput(location = jtag_location)))
|
||||
val cjtag = Overlay(cJTAGDebugOverlayKey, new cJTAGDebugVCU118ShellPlacer(this, cJTAGDebugShellInput()))
|
||||
val jtagBScan = Overlay(JTAGDebugBScanOverlayKey, new JTAGDebugBScanVCU118ShellPlacer(this, JTAGDebugBScanShellInput()))
|
||||
val fmc = Overlay(PCIeOverlayKey, new PCIeVCU118FMCShellPlacer(this, PCIeShellInput()))
|
||||
val edge = Overlay(PCIeOverlayKey, new PCIeVCU118EdgeShellPlacer(this, PCIeShellInput()))
|
||||
val sys_clock2 = Overlay(ClockInputOverlayKey, new SysClock2VCU118ShellPlacer(this, ClockInputShellInput()))
|
||||
val ddr2 = Overlay(DDROverlayKey, new DDR2VCU118ShellPlacer(this, DDRShellInput()))
|
||||
|
||||
val topDesign = LazyModule(p(BuildTop)(dp)).suggestName("chiptop")
|
||||
|
||||
// DOC include start: ClockOverlay
|
||||
// place all clocks in the shell
|
||||
require(dp(ClockInputOverlayKey).size >= 1)
|
||||
val sysClkNode = dp(ClockInputOverlayKey)(0).place(ClockInputDesignInput()).overlayOutput.node
|
||||
|
||||
/*** Connect/Generate clocks ***/
|
||||
|
||||
// connect to the PLL that will generate multiple clocks
|
||||
val harnessSysPLL = dp(PLLFactoryKey)()
|
||||
harnessSysPLL := sysClkNode
|
||||
|
||||
// create and connect to the dutClock
|
||||
val dutClock = ClockSinkNode(freqMHz = dp(FPGAFrequencyKey))
|
||||
val dutWrangler = LazyModule(new ResetWrangler)
|
||||
val dutGroup = ClockGroup()
|
||||
dutClock := dutWrangler.node := dutGroup := harnessSysPLL
|
||||
// DOC include end: ClockOverlay
|
||||
|
||||
/*** UART ***/
|
||||
|
||||
// DOC include start: UartOverlay
|
||||
// 1st UART goes to the VCU118 dedicated UART
|
||||
|
||||
val io_uart_bb = BundleBridgeSource(() => (new UARTPortIO(dp(PeripheryUARTKey).head)))
|
||||
dp(UARTOverlayKey).head.place(UARTDesignInput(io_uart_bb))
|
||||
// DOC include end: UartOverlay
|
||||
|
||||
/*** SPI ***/
|
||||
|
||||
// 1st SPI goes to the VCU118 SDIO port
|
||||
|
||||
val io_spi_bb = BundleBridgeSource(() => (new SPIPortIO(dp(PeripherySPIKey).head)))
|
||||
dp(SPIOverlayKey).head.place(SPIDesignInput(dp(PeripherySPIKey).head, io_spi_bb))
|
||||
|
||||
/*** DDR ***/
|
||||
|
||||
val ddrNode = dp(DDROverlayKey).head.place(DDRDesignInput(dp(ExtTLMem).get.master.base, dutWrangler.node, harnessSysPLL)).overlayOutput.ddr
|
||||
|
||||
// connect 1 mem. channel to the FPGA DDR
|
||||
val inParams = topDesign match { case td: ChipTop =>
|
||||
td.lazySystem match { case lsys: CanHaveMasterTLMemPort =>
|
||||
lsys.memTLNode.edges.in(0)
|
||||
}
|
||||
}
|
||||
val ddrClient = TLClientNode(Seq(inParams.master))
|
||||
ddrNode := ddrClient
|
||||
|
||||
// module implementation
|
||||
override lazy val module = new VCU118FPGATestHarnessImp(this)
|
||||
}
|
||||
|
||||
class VCU118FPGATestHarnessImp(_outer: VCU118FPGATestHarness) extends LazyRawModuleImp(_outer) with HasHarnessSignalReferences {
|
||||
|
||||
val vcu118Outer = _outer
|
||||
|
||||
val reset = IO(Input(Bool()))
|
||||
_outer.xdc.addPackagePin(reset, "L19")
|
||||
_outer.xdc.addIOStandard(reset, "LVCMOS12")
|
||||
|
||||
val resetIBUF = Module(new IBUF)
|
||||
resetIBUF.io.I := reset
|
||||
|
||||
val sysclk: Clock = _outer.sysClkNode.out.head._1.clock
|
||||
|
||||
val powerOnReset: Bool = PowerOnResetFPGAOnly(sysclk)
|
||||
_outer.sdc.addAsyncPath(Seq(powerOnReset))
|
||||
|
||||
val ereset: Bool = _outer.chiplink.get() match {
|
||||
case Some(x: ChipLinkVCU118PlacedOverlay) => !x.ereset_n
|
||||
case _ => false.B
|
||||
}
|
||||
|
||||
_outer.pllReset := (resetIBUF.io.O || powerOnReset || ereset)
|
||||
|
||||
// reset setup
|
||||
val hReset = Wire(Reset())
|
||||
hReset := _outer.dutClock.in.head._1.reset
|
||||
|
||||
val harnessClock = _outer.dutClock.in.head._1.clock
|
||||
val harnessReset = WireInit(hReset)
|
||||
val dutReset = hReset.asAsyncReset
|
||||
val success = false.B
|
||||
|
||||
childClock := harnessClock
|
||||
childReset := harnessReset
|
||||
|
||||
// harness binders are non-lazy
|
||||
_outer.topDesign match { case d: HasTestHarnessFunctions =>
|
||||
d.harnessFunctions.foreach(_(this))
|
||||
}
|
||||
_outer.topDesign match { case d: HasIOBinders =>
|
||||
ApplyHarnessBinders(this, d.lazySystem, d.portMap)
|
||||
}
|
||||
}
|
||||
28
fpga/src/main/scala/vcu118/bringup/BringupGPIOs.scala
Normal file
28
fpga/src/main/scala/vcu118/bringup/BringupGPIOs.scala
Normal file
@@ -0,0 +1,28 @@
|
||||
package chipyard.fpga.vcu118.bringup
|
||||
|
||||
import scala.collection.mutable.{LinkedHashMap}
|
||||
|
||||
object BringupGPIOs {
|
||||
// map of the pin name (akin to die pin name) to (fpga package pin, IOSTANDARD)
|
||||
val pinMapping = LinkedHashMap(
|
||||
// these connect to LEDs and switches on the VCU118 (and use 1.2V)
|
||||
"led0" -> ("AT32", "LVCMOS12"), // 0
|
||||
"led1" -> ("AV34", "LVCMOS12"), // 1
|
||||
"led2" -> ("AY30", "LVCMOS12"), // 2
|
||||
"led3" -> ("BB32", "LVCMOS12"), // 3
|
||||
"led4" -> ("BF32", "LVCMOS12"), // 4
|
||||
"led5" -> ("AU37", "LVCMOS12"), // 5
|
||||
"led6" -> ("AV36", "LVCMOS12"), // 6
|
||||
"led7" -> ("BA37", "LVCMOS12"), // 7
|
||||
"sw0" -> ("B17", "LVCMOS12"), // 8
|
||||
"sw1" -> ("G16", "LVCMOS12"), // 9
|
||||
"sw2" -> ("J16", "LVCMOS12"), // 10
|
||||
"sw3" -> ("D21", "LVCMOS12") // 11
|
||||
)
|
||||
|
||||
// return list of names (ordered)
|
||||
def names: Seq[String] = pinMapping.keys.toSeq
|
||||
|
||||
// return number of GPIOs
|
||||
def width: Int = pinMapping.size
|
||||
}
|
||||
97
fpga/src/main/scala/vcu118/bringup/Configs.scala
Normal file
97
fpga/src/main/scala/vcu118/bringup/Configs.scala
Normal file
@@ -0,0 +1,97 @@
|
||||
package chipyard.fpga.vcu118.bringup
|
||||
|
||||
import math.min
|
||||
|
||||
import freechips.rocketchip.config.{Config, Parameters}
|
||||
import freechips.rocketchip.diplomacy.{DTSModel, DTSTimebase, RegionType, AddressSet, ResourceBinding, Resource, ResourceAddress}
|
||||
import freechips.rocketchip.tilelink._
|
||||
import freechips.rocketchip.diplomacy._
|
||||
import freechips.rocketchip.subsystem.{MasterPortParams}
|
||||
|
||||
import sifive.blocks.devices.gpio.{PeripheryGPIOKey, GPIOParams}
|
||||
import sifive.blocks.devices.i2c.{PeripheryI2CKey, I2CParams}
|
||||
import sifive.blocks.devices.uart.{PeripheryUARTKey, UARTParams}
|
||||
|
||||
import sifive.fpgashells.shell.{DesignKey}
|
||||
import sifive.fpgashells.shell.xilinx.{VCU118ShellPMOD, VCU118DDRSize}
|
||||
|
||||
import testchipip.{PeripheryTSIHostKey, TSIHostParams, TSIHostSerdesParams}
|
||||
|
||||
import chipyard.{BuildSystem}
|
||||
|
||||
import chipyard.fpga.vcu118.{WithVCU118Tweaks, WithFPGAFrequency, VCU118DDR2Size}
|
||||
|
||||
class WithBringupPeripherals extends Config((site, here, up) => {
|
||||
case PeripheryUARTKey => up(PeripheryUARTKey, site) ++ List(UARTParams(address = BigInt(0x64003000L)))
|
||||
case PeripheryI2CKey => List(I2CParams(address = BigInt(0x64005000L)))
|
||||
case PeripheryGPIOKey => {
|
||||
if (BringupGPIOs.width > 0) {
|
||||
require(BringupGPIOs.width <= 64) // currently only support 64 GPIOs (change addrs to get more)
|
||||
val gpioAddrs = Seq(BigInt(0x64002000), BigInt(0x64007000))
|
||||
val maxGPIOSupport = 32 // max gpios supported by SiFive driver (split by 32)
|
||||
List.tabulate(((BringupGPIOs.width - 1)/maxGPIOSupport) + 1)(n => {
|
||||
GPIOParams(address = gpioAddrs(n), width = min(BringupGPIOs.width - maxGPIOSupport*n, maxGPIOSupport))
|
||||
})
|
||||
}
|
||||
else {
|
||||
List.empty[GPIOParams]
|
||||
}
|
||||
}
|
||||
case TSIClockMaxFrequencyKey => 100
|
||||
case PeripheryTSIHostKey => List(
|
||||
TSIHostParams(
|
||||
offchipSerialIfWidth = 4,
|
||||
mmioBaseAddress = BigInt(0x64006000),
|
||||
mmioSourceId = 1 << 13, // manager source
|
||||
serdesParams = TSIHostSerdesParams(
|
||||
clientPortParams = TLMasterPortParameters.v1(
|
||||
clients = Seq(TLMasterParameters.v1(
|
||||
name = "tl-tsi-host-serdes",
|
||||
sourceId = IdRange(0, (1 << 13))))),
|
||||
managerPortParams = TLSlavePortParameters.v1(
|
||||
managers = Seq(TLSlaveParameters.v1(
|
||||
address = Seq(AddressSet(0, BigInt("FFFFFFFF", 16))), // access everything on chip
|
||||
regionType = RegionType.UNCACHED,
|
||||
executable = true,
|
||||
supportsGet = TransferSizes(1, 64),
|
||||
supportsPutFull = TransferSizes(1, 64),
|
||||
supportsPutPartial = TransferSizes(1, 64),
|
||||
supportsAcquireT = TransferSizes(1, 64),
|
||||
supportsAcquireB = TransferSizes(1, 64),
|
||||
supportsArithmetic = TransferSizes(1, 64),
|
||||
supportsLogical = TransferSizes(1, 64))),
|
||||
endSinkId = 1 << 6, // manager sink
|
||||
beatBytes = 8)),
|
||||
targetMasterPortParams = MasterPortParams(
|
||||
base = BigInt("80000000", 16),
|
||||
size = site(VCU118DDR2Size),
|
||||
beatBytes = 8, // comes from test chip
|
||||
idBits = 4) // comes from VCU118 idBits in XilinxVCU118MIG
|
||||
))
|
||||
})
|
||||
|
||||
class WithBringupVCU118System extends Config((site, here, up) => {
|
||||
case BuildSystem => (p: Parameters) => new BringupVCU118DigitalTop()(p) // use the VCU118-extended bringup digital top
|
||||
})
|
||||
|
||||
class WithBringupAdditions extends Config(
|
||||
new WithBringupUART ++
|
||||
new WithBringupI2C ++
|
||||
new WithBringupGPIO ++
|
||||
new WithBringupTSIHost ++
|
||||
new WithTSITLIOPassthrough ++
|
||||
new WithI2CIOPassthrough ++
|
||||
new WithGPIOIOPassthrough ++
|
||||
new WithBringupPeripherals ++
|
||||
new WithBringupVCU118System)
|
||||
|
||||
class RocketBringupConfig extends Config(
|
||||
new WithBringupAdditions ++
|
||||
new WithVCU118Tweaks ++
|
||||
new chipyard.RocketConfig)
|
||||
|
||||
class BoomBringupConfig extends Config(
|
||||
new WithFPGAFrequency(50) ++
|
||||
new WithBringupAdditions ++
|
||||
new WithVCU118Tweaks ++
|
||||
new chipyard.MegaBoomConfig)
|
||||
203
fpga/src/main/scala/vcu118/bringup/CustomOverlays.scala
Normal file
203
fpga/src/main/scala/vcu118/bringup/CustomOverlays.scala
Normal file
@@ -0,0 +1,203 @@
|
||||
package chipyard.fpga.vcu118.bringup
|
||||
|
||||
import chisel3._
|
||||
import chisel3.experimental.{attach}
|
||||
|
||||
import freechips.rocketchip.diplomacy._
|
||||
import freechips.rocketchip.config.{Parameters, Field}
|
||||
import freechips.rocketchip.tilelink.{TLInwardNode, TLAsyncCrossingSink}
|
||||
|
||||
import sifive.fpgashells.shell._
|
||||
import sifive.fpgashells.ip.xilinx._
|
||||
import sifive.fpgashells.shell.xilinx._
|
||||
import sifive.fpgashells.clocks._
|
||||
import sifive.fpgashells.devices.xilinx.xilinxvcu118mig.{XilinxVCU118MIGPads, XilinxVCU118MIGParams, XilinxVCU118MIG}
|
||||
|
||||
import testchipip.{TSIHostWidgetIO}
|
||||
|
||||
import chipyard.fpga.vcu118.{FMCPMap}
|
||||
|
||||
/* Connect the I2C to certain FMC pins */
|
||||
class BringupI2CVCU118PlacedOverlay(val shell: VCU118ShellBasicOverlays, name: String, val designInput: I2CDesignInput, val shellInput: I2CShellInput)
|
||||
extends I2CXilinxPlacedOverlay(name, designInput, shellInput)
|
||||
{
|
||||
shell { InModuleBody {
|
||||
require(shellInput.index == 0) // only support 1 I2C <-> FMC connection
|
||||
val i2cLocations = List(List(FMCPMap("K11"), FMCPMap("E2")))
|
||||
val packagePinsWithPackageIOs = Seq((i2cLocations(shellInput.index)(0), IOPin(io.scl)),
|
||||
(i2cLocations(shellInput.index)(1), IOPin(io.sda)))
|
||||
|
||||
packagePinsWithPackageIOs foreach { case (pin, io) => {
|
||||
shell.xdc.addPackagePin(io, pin)
|
||||
shell.xdc.addIOStandard(io, "LVCMOS18")
|
||||
shell.xdc.addIOB(io)
|
||||
} }
|
||||
} }
|
||||
}
|
||||
|
||||
class BringupI2CVCU118ShellPlacer(val shell: VCU118ShellBasicOverlays, val shellInput: I2CShellInput)(implicit val valName: ValName)
|
||||
extends I2CShellPlacer[VCU118ShellBasicOverlays]
|
||||
{
|
||||
def place(designInput: I2CDesignInput) = new BringupI2CVCU118PlacedOverlay(shell, valName.name, designInput, shellInput)
|
||||
}
|
||||
|
||||
/* Connect the UART to certain FMC pins */
|
||||
class BringupUARTVCU118PlacedOverlay(val shell: VCU118ShellBasicOverlays, name: String, val designInput: UARTDesignInput, val shellInput: UARTShellInput)
|
||||
extends UARTXilinxPlacedOverlay(name, designInput, shellInput, true)
|
||||
{
|
||||
shell { InModuleBody {
|
||||
val packagePinsWithPackageIOs = Seq((FMCPMap("E9"), IOPin(io.ctsn.get)), // unused
|
||||
(FMCPMap("E10"), IOPin(io.rtsn.get)), // unused
|
||||
(FMCPMap("C15"), IOPin(io.rxd)),
|
||||
(FMCPMap("C14"), IOPin(io.txd)))
|
||||
|
||||
packagePinsWithPackageIOs foreach { case (pin, io) => {
|
||||
shell.xdc.addPackagePin(io, pin)
|
||||
shell.xdc.addIOStandard(io, "LVCMOS18")
|
||||
shell.xdc.addIOB(io)
|
||||
} }
|
||||
|
||||
// add pullup on ctsn (ctsn is an input that is not used or driven)
|
||||
packagePinsWithPackageIOs take 1 foreach { case (pin, io) => {
|
||||
shell.xdc.addPullup(io)
|
||||
} }
|
||||
} }
|
||||
}
|
||||
|
||||
class BringupUARTVCU118ShellPlacer(shell: VCU118ShellBasicOverlays, val shellInput: UARTShellInput)(implicit val valName: ValName)
|
||||
extends UARTShellPlacer[VCU118ShellBasicOverlays] {
|
||||
def place(designInput: UARTDesignInput) = new BringupUARTVCU118PlacedOverlay(shell, valName.name, designInput, shellInput)
|
||||
}
|
||||
|
||||
/* Connect GPIOs to FPGA I/Os */
|
||||
abstract class GPIOXilinxPlacedOverlay(name: String, di: GPIODesignInput, si: GPIOShellInput)
|
||||
extends GPIOPlacedOverlay(name, di, si)
|
||||
{
|
||||
def shell: XilinxShell
|
||||
|
||||
shell { InModuleBody {
|
||||
(io.gpio zip tlgpioSink.bundle.pins).map { case (ioPin, sinkPin) =>
|
||||
val iobuf = Module(new IOBUF)
|
||||
iobuf.suggestName(s"gpio_iobuf")
|
||||
attach(ioPin, iobuf.io.IO)
|
||||
sinkPin.i.ival := iobuf.io.O
|
||||
iobuf.io.T := !sinkPin.o.oe
|
||||
iobuf.io.I := sinkPin.o.oval
|
||||
}
|
||||
} }
|
||||
}
|
||||
|
||||
class BringupGPIOVCU118PlacedOverlay(val shell: VCU118ShellBasicOverlays, name: String, val designInput: GPIODesignInput, val shellInput: GPIOShellInput, gpioNames: Seq[String])
|
||||
extends GPIOXilinxPlacedOverlay(name, designInput, shellInput)
|
||||
{
|
||||
shell { InModuleBody {
|
||||
require(gpioNames.length == io.gpio.length)
|
||||
|
||||
val packagePinsWithIOStdWithPackageIOs = (gpioNames zip io.gpio).map { case (name, io) =>
|
||||
val (pin, iostd) = BringupGPIOs.pinMapping(name)
|
||||
(pin, iostd, IOPin(io))
|
||||
}
|
||||
|
||||
packagePinsWithIOStdWithPackageIOs foreach { case (pin, iostd, io) => {
|
||||
shell.xdc.addPackagePin(io, pin)
|
||||
shell.xdc.addIOStandard(io, iostd)
|
||||
if (iostd == "LVCMOS12") { shell.xdc.addDriveStrength(io, "8") }
|
||||
} }
|
||||
} }
|
||||
}
|
||||
|
||||
class BringupGPIOVCU118ShellPlacer(shell: VCU118ShellBasicOverlays, val shellInput: GPIOShellInput, gpioNames: Seq[String])(implicit val valName: ValName)
|
||||
extends GPIOShellPlacer[VCU118ShellBasicOverlays] {
|
||||
def place(designInput: GPIODesignInput) = new BringupGPIOVCU118PlacedOverlay(shell, valName.name, designInput, shellInput, gpioNames)
|
||||
}
|
||||
|
||||
case class TSIHostShellInput()
|
||||
case class TSIHostDesignInput(
|
||||
serialIfWidth: Int,
|
||||
node: BundleBridgeSource[TSIHostWidgetIO]
|
||||
)(
|
||||
implicit val p: Parameters)
|
||||
case class TSIHostOverlayOutput()
|
||||
trait TSIHostShellPlacer[Shell] extends ShellPlacer[TSIHostDesignInput, TSIHostShellInput, TSIHostOverlayOutput]
|
||||
|
||||
case object TSIHostOverlayKey extends Field[Seq[DesignPlacer[TSIHostDesignInput, TSIHostShellInput, TSIHostOverlayOutput]]](Nil)
|
||||
|
||||
abstract class TSIHostPlacedOverlay[IO <: Data](val name: String, val di: TSIHostDesignInput, val si: TSIHostShellInput)
|
||||
extends IOPlacedOverlay[IO, TSIHostDesignInput, TSIHostShellInput, TSIHostOverlayOutput]
|
||||
{
|
||||
implicit val p = di.p
|
||||
}
|
||||
|
||||
case object TSIHostVCU118DDRSize extends Field[BigInt](0x40000000L * 2) // 2GB
|
||||
class TSIHostVCU118PlacedOverlay(val shell: BringupVCU118FPGATestHarness, name: String, val designInput: TSIHostDesignInput, val shellInput: TSIHostShellInput)
|
||||
extends TSIHostPlacedOverlay[TSIHostWidgetIO](name, designInput, shellInput)
|
||||
{
|
||||
val tlTsiSerialSink = di.node.makeSink()
|
||||
val tsiIoNode = BundleBridgeSource(() => new TSIHostWidgetIO(di.serialIfWidth))
|
||||
val topTSIIONode = shell { tsiIoNode.makeSink() }
|
||||
|
||||
def overlayOutput = TSIHostOverlayOutput()
|
||||
def ioFactory = new TSIHostWidgetIO(di.serialIfWidth)
|
||||
|
||||
InModuleBody {
|
||||
// connect TSI serial
|
||||
val tsiSourcePort = tsiIoNode.bundle
|
||||
val tsiSinkPort = tlTsiSerialSink.bundle
|
||||
tsiSinkPort.serial_clock := tsiSourcePort.serial_clock
|
||||
tsiSourcePort.serial.out.bits := tsiSinkPort.serial.out.bits
|
||||
tsiSourcePort.serial.out.valid := tsiSinkPort.serial.out.valid
|
||||
tsiSinkPort.serial.out.ready := tsiSourcePort.serial.out.ready
|
||||
tsiSinkPort.serial.in.bits := tsiSourcePort.serial.in.bits
|
||||
tsiSinkPort.serial.in.valid := tsiSourcePort.serial.in.valid
|
||||
tsiSourcePort.serial.in.ready := tsiSinkPort.serial.in.ready
|
||||
}
|
||||
}
|
||||
|
||||
case object TSIClockMaxFrequencyKey extends Field[Int](50) // in MHz
|
||||
class BringupTSIHostVCU118PlacedOverlay(override val shell: BringupVCU118FPGATestHarness, override val name: String, override val designInput: TSIHostDesignInput, override val shellInput: TSIHostShellInput)
|
||||
extends TSIHostVCU118PlacedOverlay(shell, name, designInput, shellInput)
|
||||
{
|
||||
// connect the TSI port
|
||||
shell { InModuleBody {
|
||||
// connect TSI signals
|
||||
val tsiPort = topTSIIONode.bundle
|
||||
io <> tsiPort
|
||||
|
||||
require(di.serialIfWidth == 4)
|
||||
|
||||
val clkIo = IOPin(io.serial_clock)
|
||||
val packagePinsWithPackageIOs = Seq(
|
||||
(FMCPMap("D8"), clkIo),
|
||||
(FMCPMap("D17"), IOPin(io.serial.out.ready)),
|
||||
(FMCPMap("D18"), IOPin(io.serial.out.valid)),
|
||||
(FMCPMap("D11"), IOPin(io.serial.out.bits, 0)),
|
||||
(FMCPMap("D12"), IOPin(io.serial.out.bits, 1)),
|
||||
(FMCPMap("D14"), IOPin(io.serial.out.bits, 2)),
|
||||
(FMCPMap("D15"), IOPin(io.serial.out.bits, 3)),
|
||||
(FMCPMap("D26"), IOPin(io.serial.in.ready)),
|
||||
(FMCPMap("D27"), IOPin(io.serial.in.valid)),
|
||||
(FMCPMap("D20"), IOPin(io.serial.in.bits, 0)),
|
||||
(FMCPMap("D21"), IOPin(io.serial.in.bits, 1)),
|
||||
(FMCPMap("D23"), IOPin(io.serial.in.bits, 2)),
|
||||
(FMCPMap("D24"), IOPin(io.serial.in.bits, 3)))
|
||||
|
||||
packagePinsWithPackageIOs foreach { case (pin, io) => {
|
||||
shell.xdc.addPackagePin(io, pin)
|
||||
shell.xdc.addIOStandard(io, "LVCMOS18")
|
||||
} }
|
||||
|
||||
// Don't add an IOB to the clock
|
||||
(packagePinsWithPackageIOs take 1) foreach { case (pin, io) => {
|
||||
shell.xdc.addIOB(io)
|
||||
} }
|
||||
|
||||
shell.sdc.addClock("TSI_CLK", clkIo, p(TSIClockMaxFrequencyKey))
|
||||
shell.sdc.addGroup(pins = Seq(clkIo))
|
||||
shell.xdc.clockDedicatedRouteFalse(clkIo)
|
||||
} }
|
||||
}
|
||||
|
||||
class BringupTSIHostVCU118ShellPlacer(shell: BringupVCU118FPGATestHarness, val shellInput: TSIHostShellInput)(implicit val valName: ValName)
|
||||
extends TSIHostShellPlacer[BringupVCU118FPGATestHarness] {
|
||||
def place(designInput: TSIHostDesignInput) = new BringupTSIHostVCU118PlacedOverlay(shell, valName.name, designInput, shellInput)
|
||||
}
|
||||
26
fpga/src/main/scala/vcu118/bringup/DigitalTop.scala
Normal file
26
fpga/src/main/scala/vcu118/bringup/DigitalTop.scala
Normal file
@@ -0,0 +1,26 @@
|
||||
package chipyard.fpga.vcu118.bringup
|
||||
|
||||
import chisel3._
|
||||
|
||||
import freechips.rocketchip.subsystem._
|
||||
import freechips.rocketchip.system._
|
||||
import freechips.rocketchip.config.Parameters
|
||||
import freechips.rocketchip.devices.tilelink._
|
||||
import freechips.rocketchip.diplomacy._
|
||||
import freechips.rocketchip.tilelink._
|
||||
|
||||
import chipyard.{DigitalTop, DigitalTopModule}
|
||||
|
||||
// ------------------------------------
|
||||
// Bringup VCU118 DigitalTop
|
||||
// ------------------------------------
|
||||
|
||||
class BringupVCU118DigitalTop(implicit p: Parameters) extends DigitalTop
|
||||
with sifive.blocks.devices.i2c.HasPeripheryI2C
|
||||
with testchipip.HasPeripheryTSIHostWidget
|
||||
{
|
||||
override lazy val module = new BringupVCU118DigitalTopModule(this)
|
||||
}
|
||||
|
||||
class BringupVCU118DigitalTopModule[+L <: BringupVCU118DigitalTop](l: L) extends DigitalTopModule(l)
|
||||
with sifive.blocks.devices.i2c.HasPeripheryI2CModuleImp
|
||||
70
fpga/src/main/scala/vcu118/bringup/HarnessBinders.scala
Normal file
70
fpga/src/main/scala/vcu118/bringup/HarnessBinders.scala
Normal file
@@ -0,0 +1,70 @@
|
||||
package chipyard.fpga.vcu118.bringup
|
||||
|
||||
import chisel3._
|
||||
import chisel3.experimental.{Analog, IO, BaseModule}
|
||||
|
||||
import freechips.rocketchip.util.{HeterogeneousBag}
|
||||
import freechips.rocketchip.tilelink.{TLBundle}
|
||||
|
||||
import sifive.blocks.devices.uart.{HasPeripheryUARTModuleImp, UARTPortIO}
|
||||
import sifive.blocks.devices.spi.{HasPeripherySPI, SPIPortIO}
|
||||
import sifive.blocks.devices.i2c.{HasPeripheryI2CModuleImp, I2CPort}
|
||||
import sifive.blocks.devices.gpio.{HasPeripheryGPIOModuleImp, GPIOPortIO}
|
||||
|
||||
import testchipip.{HasPeripheryTSIHostWidget, TSIHostWidgetIO}
|
||||
|
||||
import chipyard.{HasHarnessSignalReferences}
|
||||
import chipyard.harness.{ComposeHarnessBinder, OverrideHarnessBinder}
|
||||
|
||||
/*** UART ***/
|
||||
class WithBringupUART extends ComposeHarnessBinder({
|
||||
(system: HasPeripheryUARTModuleImp, th: BaseModule with HasHarnessSignalReferences, ports: Seq[UARTPortIO]) => {
|
||||
th match { case vcu118th: BringupVCU118FPGATestHarnessImp => {
|
||||
require(ports.size == 2)
|
||||
|
||||
vcu118th.bringupOuter.io_fmc_uart_bb.bundle <> ports.last
|
||||
} }
|
||||
}
|
||||
})
|
||||
|
||||
/*** I2C ***/
|
||||
class WithBringupI2C extends OverrideHarnessBinder({
|
||||
(system: HasPeripheryI2CModuleImp, th: BaseModule with HasHarnessSignalReferences, ports: Seq[I2CPort]) => {
|
||||
th match { case vcu118th: BringupVCU118FPGATestHarnessImp => {
|
||||
require(ports.size == 1)
|
||||
|
||||
vcu118th.bringupOuter.io_i2c_bb.bundle <> ports.head
|
||||
} }
|
||||
}
|
||||
})
|
||||
|
||||
/*** GPIO ***/
|
||||
class WithBringupGPIO extends OverrideHarnessBinder({
|
||||
(system: HasPeripheryGPIOModuleImp, th: BaseModule with HasHarnessSignalReferences, ports: Seq[GPIOPortIO]) => {
|
||||
th match { case vcu118th: BringupVCU118FPGATestHarnessImp => {
|
||||
(vcu118th.bringupOuter.io_gpio_bb zip ports).map { case (bb_io, dut_io) =>
|
||||
bb_io.bundle <> dut_io
|
||||
}
|
||||
} }
|
||||
}
|
||||
})
|
||||
|
||||
/*** TSI Host Widget ***/
|
||||
class WithBringupTSIHost extends OverrideHarnessBinder({
|
||||
(system: HasPeripheryTSIHostWidget, th: BaseModule with HasHarnessSignalReferences, ports: Seq[Data]) => {
|
||||
th match { case vcu118th: BringupVCU118FPGATestHarnessImp => {
|
||||
require(ports.size == 2) // 1st goes to the TL mem, 2nd goes to the serial link
|
||||
|
||||
ports.head match { case tlPort: HeterogeneousBag[TLBundle] =>
|
||||
val tsiBundles = vcu118th.bringupOuter.tsiDdrClient.out.map(_._1)
|
||||
val tsiDdrClientBundle = Wire(new HeterogeneousBag(tsiBundles.map(_.cloneType)))
|
||||
tsiBundles.zip(tsiDdrClientBundle).foreach { case (bundle, io) => bundle <> io }
|
||||
tsiDdrClientBundle <> tlPort
|
||||
}
|
||||
|
||||
ports.last match { case serialPort: TSIHostWidgetIO =>
|
||||
vcu118th.bringupOuter.io_tsi_serial_bb.bundle <> serialPort
|
||||
}
|
||||
} }
|
||||
}
|
||||
})
|
||||
47
fpga/src/main/scala/vcu118/bringup/IOBinders.scala
Normal file
47
fpga/src/main/scala/vcu118/bringup/IOBinders.scala
Normal file
@@ -0,0 +1,47 @@
|
||||
package chipyard.fpga.vcu118.bringup
|
||||
|
||||
import chisel3._
|
||||
import chisel3.experimental.{IO, DataMirror}
|
||||
|
||||
import freechips.rocketchip.util.{HeterogeneousBag}
|
||||
import freechips.rocketchip.tilelink.{TLBundle}
|
||||
|
||||
import sifive.blocks.devices.gpio.{HasPeripheryGPIOModuleImp}
|
||||
import sifive.blocks.devices.i2c.{HasPeripheryI2CModuleImp}
|
||||
|
||||
import testchipip.{HasPeripheryTSIHostWidget, TSIHostWidgetIO}
|
||||
|
||||
import chipyard.iobinders.{OverrideIOBinder}
|
||||
|
||||
class WithGPIOIOPassthrough extends OverrideIOBinder({
|
||||
(system: HasPeripheryGPIOModuleImp) => {
|
||||
val io_gpio_pins_temp = system.gpio.zipWithIndex.map { case (dio, i) => IO(dio.cloneType).suggestName(s"gpio_$i") }
|
||||
(io_gpio_pins_temp zip system.gpio).map { case (io, sysio) =>
|
||||
io <> sysio
|
||||
}
|
||||
(io_gpio_pins_temp, Nil)
|
||||
}
|
||||
})
|
||||
|
||||
class WithI2CIOPassthrough extends OverrideIOBinder({
|
||||
(system: HasPeripheryI2CModuleImp) => {
|
||||
val io_i2c_pins_temp = system.i2c.zipWithIndex.map { case (dio, i) => IO(dio.cloneType).suggestName(s"i2c_$i") }
|
||||
(io_i2c_pins_temp zip system.i2c).map { case (io, sysio) =>
|
||||
io <> sysio
|
||||
}
|
||||
(io_i2c_pins_temp, Nil)
|
||||
}
|
||||
})
|
||||
|
||||
class WithTSITLIOPassthrough extends OverrideIOBinder({
|
||||
(system: HasPeripheryTSIHostWidget) => {
|
||||
require(system.tsiTLMem.size == 1)
|
||||
val io_tsi_tl_mem_pins_temp = IO(DataMirror.internal.chiselTypeClone[HeterogeneousBag[TLBundle]](system.tsiTLMem.head)).suggestName("tsi_tl_slave")
|
||||
io_tsi_tl_mem_pins_temp <> system.tsiTLMem.head
|
||||
|
||||
require(system.tsiSerial.size == 1)
|
||||
val io_tsi_serial_pins_temp = IO(DataMirror.internal.chiselTypeClone[TSIHostWidgetIO](system.tsiSerial.head)).suggestName("tsi_serial")
|
||||
io_tsi_serial_pins_temp <> system.tsiSerial.head
|
||||
(Seq(io_tsi_tl_mem_pins_temp, io_tsi_serial_pins_temp), Nil)
|
||||
}
|
||||
})
|
||||
100
fpga/src/main/scala/vcu118/bringup/TestHarness.scala
Normal file
100
fpga/src/main/scala/vcu118/bringup/TestHarness.scala
Normal file
@@ -0,0 +1,100 @@
|
||||
package chipyard.fpga.vcu118.bringup
|
||||
|
||||
import chisel3._
|
||||
|
||||
import freechips.rocketchip.diplomacy._
|
||||
import freechips.rocketchip.config._
|
||||
import freechips.rocketchip.subsystem._
|
||||
import freechips.rocketchip.tilelink._
|
||||
|
||||
import sifive.fpgashells.shell.xilinx._
|
||||
import sifive.fpgashells.ip.xilinx._
|
||||
import sifive.fpgashells.shell._
|
||||
import sifive.fpgashells.clocks._
|
||||
|
||||
import sifive.blocks.devices.uart._
|
||||
import sifive.blocks.devices.spi._
|
||||
import sifive.blocks.devices.i2c._
|
||||
import sifive.blocks.devices.gpio._
|
||||
|
||||
import testchipip.{HasPeripheryTSIHostWidget, PeripheryTSIHostKey, TSIHostWidgetIO, TLSinkSetter}
|
||||
|
||||
import chipyard.fpga.vcu118.{VCU118FPGATestHarness, VCU118FPGATestHarnessImp, DDR2VCU118ShellPlacer, SysClock2VCU118ShellPlacer}
|
||||
|
||||
import chipyard.{ChipTop}
|
||||
|
||||
class BringupVCU118FPGATestHarness(override implicit val p: Parameters) extends VCU118FPGATestHarness {
|
||||
|
||||
/*** UART ***/
|
||||
|
||||
require(dp(PeripheryUARTKey).size == 2)
|
||||
|
||||
// 2nd UART goes to the FMC UART
|
||||
|
||||
val uart_fmc = Overlay(UARTOverlayKey, new BringupUARTVCU118ShellPlacer(this, UARTShellInput()))
|
||||
|
||||
val io_fmc_uart_bb = BundleBridgeSource(() => (new UARTPortIO(dp(PeripheryUARTKey).last)))
|
||||
dp(UARTOverlayKey).last.place(UARTDesignInput(io_fmc_uart_bb))
|
||||
|
||||
/*** I2C ***/
|
||||
|
||||
val i2c = Overlay(I2COverlayKey, new BringupI2CVCU118ShellPlacer(this, I2CShellInput()))
|
||||
|
||||
val io_i2c_bb = BundleBridgeSource(() => (new I2CPort))
|
||||
dp(I2COverlayKey).head.place(I2CDesignInput(io_i2c_bb))
|
||||
|
||||
/*** GPIO ***/
|
||||
|
||||
val gpio = Seq.tabulate(dp(PeripheryGPIOKey).size)(i => {
|
||||
val maxGPIOSupport = 32 // max gpio per gpio chip
|
||||
val names = BringupGPIOs.names.slice(maxGPIOSupport*i, maxGPIOSupport*(i+1))
|
||||
Overlay(GPIOOverlayKey, new BringupGPIOVCU118ShellPlacer(this, GPIOShellInput(), names))
|
||||
})
|
||||
|
||||
val io_gpio_bb = dp(PeripheryGPIOKey).map { p => BundleBridgeSource(() => (new GPIOPortIO(p))) }
|
||||
(dp(GPIOOverlayKey) zip dp(PeripheryGPIOKey)).zipWithIndex.map { case ((placer, params), i) =>
|
||||
placer.place(GPIODesignInput(params, io_gpio_bb(i)))
|
||||
}
|
||||
|
||||
/*** TSI Host Widget ***/
|
||||
require(dp(PeripheryTSIHostKey).size == 1)
|
||||
|
||||
// use the 2nd system clock for the 2nd DDR
|
||||
val sysClk2Node = dp(ClockInputOverlayKey).last.place(ClockInputDesignInput()).overlayOutput.node
|
||||
|
||||
val ddr2PLL = dp(PLLFactoryKey)()
|
||||
ddr2PLL := sysClk2Node
|
||||
|
||||
val ddr2Clock = ClockSinkNode(freqMHz = dp(FPGAFrequencyKey))
|
||||
val ddr2Wrangler = LazyModule(new ResetWrangler)
|
||||
val ddr2Group = ClockGroup()
|
||||
ddr2Clock := ddr2Wrangler.node := ddr2Group := ddr2PLL
|
||||
|
||||
val tsi_host = Overlay(TSIHostOverlayKey, new BringupTSIHostVCU118ShellPlacer(this, TSIHostShellInput()))
|
||||
|
||||
val ddr2Node = dp(DDROverlayKey).last.place(DDRDesignInput(dp(PeripheryTSIHostKey).head.targetMasterPortParams.base, ddr2Wrangler.node, ddr2PLL)).overlayOutput.ddr
|
||||
|
||||
val io_tsi_serial_bb = BundleBridgeSource(() => (new TSIHostWidgetIO(dp(PeripheryTSIHostKey).head.offchipSerialIfWidth)))
|
||||
dp(TSIHostOverlayKey).head.place(TSIHostDesignInput(dp(PeripheryTSIHostKey).head.offchipSerialIfWidth, io_tsi_serial_bb))
|
||||
|
||||
// connect 1 mem. channel to the FPGA DDR
|
||||
val inTsiParams = topDesign match { case td: ChipTop =>
|
||||
td.lazySystem match { case lsys: HasPeripheryTSIHostWidget =>
|
||||
lsys.tsiMemTLNodes.head.edges.in(0)
|
||||
}
|
||||
}
|
||||
val tsiDdrClient = TLClientNode(Seq(inTsiParams.master))
|
||||
(ddr2Node
|
||||
:= TLFragmenter(8,64,holdFirstDeny=true)
|
||||
:= TLCacheCork()
|
||||
:= TLAtomicAutomata(passthrough=false)
|
||||
:= TLSinkSetter(64)
|
||||
:= tsiDdrClient)
|
||||
|
||||
// module implementation
|
||||
override lazy val module = new BringupVCU118FPGATestHarnessImp(this)
|
||||
}
|
||||
|
||||
class BringupVCU118FPGATestHarnessImp(_outer: BringupVCU118FPGATestHarness) extends VCU118FPGATestHarnessImp(_outer) {
|
||||
lazy val bringupOuter = _outer
|
||||
}
|
||||
Submodule generators/boom updated: dc22cacf71...e1a70afed7
@@ -7,7 +7,7 @@ import scala.collection.mutable.{ArrayBuffer}
|
||||
import freechips.rocketchip.prci.{ClockGroupIdentityNode, ClockSinkParameters, ClockSinkNode, ClockGroup}
|
||||
import freechips.rocketchip.subsystem.{BaseSubsystem, SubsystemDriveAsyncClockGroupsKey}
|
||||
import freechips.rocketchip.config.{Parameters, Field}
|
||||
import freechips.rocketchip.diplomacy.{LazyModule, LazyModuleImp, LazyRawModuleImp, LazyModuleImpLike}
|
||||
import freechips.rocketchip.diplomacy.{LazyModule, LazyModuleImp, LazyRawModuleImp, LazyModuleImpLike, BindingScope}
|
||||
import freechips.rocketchip.util.{ResetCatchAndSync}
|
||||
import chipyard.iobinders._
|
||||
|
||||
@@ -23,7 +23,7 @@ case object BuildSystem extends Field[Parameters => LazyModule]((p: Parameters)
|
||||
* drive clock and reset generation
|
||||
*/
|
||||
|
||||
class ChipTop(implicit p: Parameters) extends LazyModule
|
||||
class ChipTop(implicit p: Parameters) extends LazyModule with BindingScope
|
||||
with HasTestHarnessFunctions with HasIOBinders {
|
||||
// The system module specified by BuildSystem
|
||||
lazy val lazySystem = LazyModule(p(BuildSystem)(p)).suggestName("system")
|
||||
|
||||
@@ -141,7 +141,7 @@ class WithNPerfCounters(n: Int = 29) extends Config((site, here, up) => {
|
||||
|
||||
class WithRocketICacheScratchpad extends Config((site, here, up) => {
|
||||
case RocketTilesKey => up(RocketTilesKey, site) map { r =>
|
||||
r.copy(icache = r.icache.map(_.copy(itimAddr = Some(0x100000 + r.hartId * 0x10000))))
|
||||
r.copy(icache = r.icache.map(_.copy(itimAddr = Some(0x300000 + r.hartId * 0x10000))))
|
||||
}
|
||||
})
|
||||
|
||||
@@ -151,6 +151,11 @@ class WithRocketDCacheScratchpad extends Config((site, here, up) => {
|
||||
}
|
||||
})
|
||||
|
||||
// Replaces the L2 with a broadcast manager for maintaining coherence
|
||||
class WithBroadcastManager extends Config((site, here, up) => {
|
||||
case BankedL2Key => up(BankedL2Key, site).copy(coherenceManager = CoherenceManagerWrapper.broadcastManager)
|
||||
})
|
||||
|
||||
class WithHwachaTest extends Config((site, here, up) => {
|
||||
case TestSuitesKey => (tileParams: Seq[TileParams], suiteHelper: TestSuiteHelper, p: Parameters) => {
|
||||
up(TestSuitesKey).apply(tileParams, suiteHelper, p)
|
||||
@@ -179,6 +184,15 @@ class WithNoDebug extends Config((site, here, up) => {
|
||||
case DebugModuleKey => None
|
||||
})
|
||||
|
||||
class WithTLSerialLocation(masterWhere: TLBusWrapperLocation, slaveWhere: TLBusWrapperLocation) extends Config((site, here, up) => {
|
||||
case SerialTLAttachKey => up(SerialTLAttachKey, site).copy(masterWhere = masterWhere, slaveWhere = slaveWhere)
|
||||
})
|
||||
|
||||
class WithTLBackingMemory extends Config((site, here, up) => {
|
||||
case ExtMem => None // disable AXI backing memory
|
||||
case ExtTLMem => up(ExtMem, site) // enable TL backing memory
|
||||
})
|
||||
|
||||
class WithTileFrequency(fMHz: Double) extends ClockNameContainsAssignment("core", fMHz)
|
||||
|
||||
class WithPeripheryBusFrequencyAsDefault extends Config((site, here, up) => {
|
||||
|
||||
@@ -13,14 +13,6 @@ import freechips.rocketchip.subsystem._
|
||||
|
||||
// For subsystem/BusTopology.scala
|
||||
|
||||
/**
|
||||
* Keys that serve as a means to define crossing types from a Parameters instance
|
||||
*/
|
||||
case object SbusToMbusXTypeKey extends Field[ClockCrossingType](NoCrossing)
|
||||
case object SbusToCbusXTypeKey extends Field[ClockCrossingType](NoCrossing)
|
||||
case object CbusToPbusXTypeKey extends Field[ClockCrossingType](SynchronousCrossing())
|
||||
case object FbusToSbusXTypeKey extends Field[ClockCrossingType](SynchronousCrossing())
|
||||
|
||||
// Biancolin: This, modified from Henry's email
|
||||
/** Parameterization of a topology containing a banked coherence manager and a bus for attaching memory devices. */
|
||||
case class CoherentMulticlockBusTopologyParams(
|
||||
@@ -78,3 +70,13 @@ class WithMulticlockCoherentBusTopology extends Config((site, here, up) => {
|
||||
l2 = site(BankedL2Key),
|
||||
sbusToMbusXType = site(SbusToMbusXTypeKey)))
|
||||
})
|
||||
|
||||
class WithMulticlockIncoherentBusTopology extends Config((site, here, up) => {
|
||||
case TLNetworkTopologyLocated(InSubsystem) => List(
|
||||
JustOneBusTopologyParams(sbus = site(SystemBusKey)),
|
||||
HierarchicalMulticlockBusTopologyParams(
|
||||
pbus = site(PeripheryBusKey),
|
||||
fbus = site(FrontBusKey),
|
||||
cbus = site(ControlBusKey),
|
||||
xTypes = SubsystemCrossingParams()))
|
||||
})
|
||||
|
||||
@@ -20,6 +20,7 @@ class DigitalTop(implicit p: Parameters) extends ChipyardSystem
|
||||
with sifive.blocks.devices.uart.HasPeripheryUART // Enables optionally adding the sifive UART
|
||||
with sifive.blocks.devices.gpio.HasPeripheryGPIO // Enables optionally adding the sifive GPIOs
|
||||
with sifive.blocks.devices.spi.HasPeripherySPIFlash // Enables optionally adding the sifive SPI flash controller
|
||||
with sifive.blocks.devices.spi.HasPeripherySPI // Enables optionally adding the sifive SPI port
|
||||
with icenet.CanHavePeripheryIceNIC // Enables optionally adding the IceNIC for FireSim
|
||||
with chipyard.example.CanHavePeripheryInitZero // Enables optionally adding the initzero example widget
|
||||
with chipyard.example.CanHavePeripheryGCD // Enables optionally adding the GCD example widget
|
||||
@@ -35,6 +36,7 @@ class DigitalTopModule[+L <: DigitalTop](l: L) extends ChipyardSystemModule(l)
|
||||
with sifive.blocks.devices.uart.HasPeripheryUARTModuleImp
|
||||
with sifive.blocks.devices.gpio.HasPeripheryGPIOModuleImp
|
||||
with sifive.blocks.devices.spi.HasPeripherySPIFlashModuleImp
|
||||
with sifive.blocks.devices.spi.HasPeripherySPIModuleImp
|
||||
with chipyard.example.CanHavePeripheryGCDModuleImp
|
||||
with freechips.rocketchip.util.DontTouch
|
||||
// DOC include end: DigitalTop
|
||||
|
||||
@@ -11,7 +11,7 @@ import chisel3.internal.sourceinfo.{SourceInfo}
|
||||
import freechips.rocketchip.prci._
|
||||
import freechips.rocketchip.config.{Field, Parameters}
|
||||
import freechips.rocketchip.devices.tilelink._
|
||||
import freechips.rocketchip.devices.debug.{HasPeripheryDebug, HasPeripheryDebugModuleImp, ExportDebug}
|
||||
import freechips.rocketchip.devices.debug.{HasPeripheryDebug, HasPeripheryDebugModuleImp, ExportDebug, DebugModuleKey}
|
||||
import freechips.rocketchip.diplomacy._
|
||||
import freechips.rocketchip.diplomaticobjectmodel.model.{OMInterrupt}
|
||||
import freechips.rocketchip.diplomaticobjectmodel.logicaltree.{RocketTileLogicalTreeNode, LogicalModuleTree}
|
||||
@@ -31,7 +31,7 @@ trait CanHaveHTIF { this: BaseSubsystem =>
|
||||
// Advertise HTIF if system can communicate with fesvr
|
||||
if (this match {
|
||||
case _: CanHavePeripheryTLSerial if p(SerialTLKey).nonEmpty => true
|
||||
case _: HasPeripheryDebug if p(ExportDebug).dmi => true
|
||||
case _: HasPeripheryDebug if (!p(DebugModuleKey).isEmpty && p(ExportDebug).dmi) => true
|
||||
case _ => false
|
||||
}) {
|
||||
ResourceBinding {
|
||||
|
||||
@@ -7,7 +7,7 @@ package chipyard
|
||||
|
||||
import chisel3._
|
||||
|
||||
import freechips.rocketchip.config.{Parameters}
|
||||
import freechips.rocketchip.config.{Parameters, Field}
|
||||
import freechips.rocketchip.subsystem._
|
||||
import freechips.rocketchip.tilelink._
|
||||
import freechips.rocketchip.devices.tilelink._
|
||||
@@ -23,7 +23,8 @@ import freechips.rocketchip.util.{DontTouch}
|
||||
*/
|
||||
class ChipyardSystem(implicit p: Parameters) extends ChipyardSubsystem
|
||||
with HasAsyncExtInterrupts
|
||||
with CanHaveMasterAXI4MemPort
|
||||
with CanHaveMasterTLMemPort // export TL port for outer memory
|
||||
with CanHaveMasterAXI4MemPort // expose AXI port for outer mem
|
||||
with CanHaveMasterAXI4MMIOPort
|
||||
with CanHaveSlaveAXI4Port
|
||||
{
|
||||
@@ -40,3 +41,50 @@ class ChipyardSystemModule[+L <: ChipyardSystem](_outer: L) extends ChipyardSubs
|
||||
with HasRTCModuleImp
|
||||
with HasExtInterruptsModuleImp
|
||||
with DontTouch
|
||||
|
||||
// ------------------------------------
|
||||
// TL Mem Port Mixin
|
||||
// ------------------------------------
|
||||
|
||||
// Similar to ExtMem but instantiates a TL mem port
|
||||
case object ExtTLMem extends Field[Option[MemoryPortParams]](None)
|
||||
|
||||
/** Adds a port to the system intended to master an TL DRAM controller. */
|
||||
trait CanHaveMasterTLMemPort { this: BaseSubsystem =>
|
||||
|
||||
require(!(p(ExtTLMem).nonEmpty && p(ExtMem).nonEmpty),
|
||||
"Can only have 1 backing memory port. Use ExtTLMem for a TL memory port or ExtMem for an AXI memory port.")
|
||||
|
||||
private val memPortParamsOpt = p(ExtTLMem)
|
||||
private val portName = "tl_mem"
|
||||
private val device = new MemoryDevice
|
||||
private val idBits = memPortParamsOpt.map(_.master.idBits).getOrElse(1)
|
||||
|
||||
val memTLNode = TLManagerNode(memPortParamsOpt.map({ case MemoryPortParams(memPortParams, nMemoryChannels) =>
|
||||
Seq.tabulate(nMemoryChannels) { channel =>
|
||||
val base = AddressSet.misaligned(memPortParams.base, memPortParams.size)
|
||||
val filter = AddressSet(channel * mbus.blockBytes, ~((nMemoryChannels-1) * mbus.blockBytes))
|
||||
|
||||
TLSlavePortParameters.v1(
|
||||
managers = Seq(TLSlaveParameters.v1(
|
||||
address = base.flatMap(_.intersect(filter)),
|
||||
resources = device.reg,
|
||||
regionType = RegionType.UNCACHED, // cacheable
|
||||
executable = true,
|
||||
supportsGet = TransferSizes(1, mbus.blockBytes),
|
||||
supportsPutFull = TransferSizes(1, mbus.blockBytes),
|
||||
supportsPutPartial = TransferSizes(1, mbus.blockBytes))),
|
||||
beatBytes = memPortParams.beatBytes)
|
||||
}
|
||||
}).toList.flatten)
|
||||
|
||||
mbus.coupleTo(s"memory_controller_port_named_$portName") {
|
||||
(memTLNode
|
||||
:*= TLBuffer()
|
||||
:*= TLSourceShrinker(1 << idBits)
|
||||
:*= TLWidthWidget(mbus.beatBytes)
|
||||
:*= _)
|
||||
}
|
||||
|
||||
val mem_tl = InModuleBody { memTLNode.makeIOs() }
|
||||
}
|
||||
|
||||
@@ -1,30 +0,0 @@
|
||||
|
||||
package chipyard.clocking
|
||||
|
||||
import chisel3._
|
||||
|
||||
import freechips.rocketchip.config.{Parameters}
|
||||
import freechips.rocketchip.diplomacy._
|
||||
import freechips.rocketchip.prci._
|
||||
import freechips.rocketchip.util.{ResetCatchAndSync}
|
||||
|
||||
/**
|
||||
* Instantiates a reset synchronizer on all clock-reset pairs in a clock group
|
||||
*/
|
||||
class ClockGroupResetSynchronizer(implicit p: Parameters) extends LazyModule {
|
||||
val node = ClockGroupAdapterNode()
|
||||
lazy val module = new LazyRawModuleImp(this) {
|
||||
(node.out zip node.in).map { case ((oG, _), (iG, _)) =>
|
||||
(oG.member.data zip iG.member.data).foreach { case (o, i) =>
|
||||
o.clock := i.clock
|
||||
o.reset := ResetCatchAndSync(i.clock, i.reset.asBool)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
object ClockGroupResetSynchronizer {
|
||||
def apply()(implicit p: Parameters, valName: ValName) = LazyModule(new ClockGroupResetSynchronizer()).node
|
||||
}
|
||||
|
||||
|
||||
@@ -50,6 +50,6 @@ class AbstractConfig extends Config(
|
||||
new freechips.rocketchip.subsystem.WithNoSlavePort ++ // no top-level MMIO slave port (overrides default set in rocketchip)
|
||||
new freechips.rocketchip.subsystem.WithInclusiveCache ++ // use Sifive L2 cache
|
||||
new freechips.rocketchip.subsystem.WithNExtTopInterrupts(0) ++ // no external interrupts
|
||||
new chipyard.WithMulticlockCoherentBusTopology ++ // hierarchical buses including mbus+l2
|
||||
new chipyard.WithMulticlockCoherentBusTopology ++ // hierarchical buses including mbus+l2
|
||||
new freechips.rocketchip.system.BaseConfig) // "base" rocketchip system
|
||||
|
||||
|
||||
@@ -11,6 +11,16 @@ class RocketConfig extends Config(
|
||||
new freechips.rocketchip.subsystem.WithNBigCores(1) ++ // single rocket-core
|
||||
new chipyard.config.AbstractConfig)
|
||||
|
||||
class TinyRocketConfig extends Config(
|
||||
new chipyard.config.WithTLSerialLocation(
|
||||
freechips.rocketchip.subsystem.FBUS,
|
||||
freechips.rocketchip.subsystem.PBUS) ++ // attach TL serial adapter to f/p busses
|
||||
new chipyard.WithMulticlockIncoherentBusTopology ++ // use incoherent bus topology
|
||||
new freechips.rocketchip.subsystem.WithNBanks(0) ++ // remove L2$
|
||||
new freechips.rocketchip.subsystem.WithNoMemPort ++ // remove backing memory
|
||||
new freechips.rocketchip.subsystem.With1TinyCore ++ // single tiny rocket-core
|
||||
new chipyard.config.AbstractConfig)
|
||||
|
||||
class HwachaRocketConfig extends Config(
|
||||
new chipyard.config.WithHwachaTest ++
|
||||
new hwacha.DefaultHwachaConfig ++ // use Hwacha vector accelerator
|
||||
@@ -179,7 +189,7 @@ class MMIORocketConfig extends Config(
|
||||
class MulticlockRocketConfig extends Config(
|
||||
new freechips.rocketchip.subsystem.WithNBigCores(1) ++
|
||||
// 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
|
||||
new chipyard.config.WithSystemBusFrequency(800.0) ++ // Ditto
|
||||
new chipyard.config.WithMemoryBusFrequency(1000.0) ++ // 2x the U540 freq (appropriate for a 128b Mbus)
|
||||
new chipyard.config.WithPeripheryBusFrequency(100) ++ // Retains the default pbus frequency
|
||||
|
||||
@@ -7,6 +7,7 @@ import freechips.rocketchip.config.{Config}
|
||||
class Sodor1StageConfig extends Config(
|
||||
// Create a Sodor 1-stage core
|
||||
new sodor.common.WithNSodorCores(1, internalTile = sodor.common.Stage1Factory) ++
|
||||
new testchipip.WithSerialTLWidth(32) ++
|
||||
new testchipip.WithSerialPBusMem ++
|
||||
new freechips.rocketchip.subsystem.WithScratchpadsOnly ++ // use sodor tile-internal scratchpad
|
||||
new freechips.rocketchip.subsystem.WithNoMemPort ++ // use no external memory
|
||||
@@ -16,6 +17,7 @@ class Sodor1StageConfig extends Config(
|
||||
class Sodor2StageConfig extends Config(
|
||||
// Create a Sodor 2-stage core
|
||||
new sodor.common.WithNSodorCores(1, internalTile = sodor.common.Stage2Factory) ++
|
||||
new testchipip.WithSerialTLWidth(32) ++
|
||||
new testchipip.WithSerialPBusMem ++
|
||||
new freechips.rocketchip.subsystem.WithScratchpadsOnly ++ // use sodor tile-internal scratchpad
|
||||
new freechips.rocketchip.subsystem.WithNoMemPort ++ // use no external memory
|
||||
@@ -25,6 +27,7 @@ class Sodor2StageConfig extends Config(
|
||||
class Sodor3StageConfig extends Config(
|
||||
// Create a Sodor 1-stage core with two ports
|
||||
new sodor.common.WithNSodorCores(1, internalTile = sodor.common.Stage3Factory(ports = 2)) ++
|
||||
new testchipip.WithSerialTLWidth(32) ++
|
||||
new testchipip.WithSerialPBusMem ++
|
||||
new freechips.rocketchip.subsystem.WithScratchpadsOnly ++ // use sodor tile-internal scratchpad
|
||||
new freechips.rocketchip.subsystem.WithNoMemPort ++ // use no external memory
|
||||
@@ -34,6 +37,7 @@ class Sodor3StageConfig extends Config(
|
||||
class Sodor3StageSinglePortConfig extends Config(
|
||||
// Create a Sodor 3-stage core with one ports (instruction and data memory access controlled by arbiter)
|
||||
new sodor.common.WithNSodorCores(1, internalTile = sodor.common.Stage3Factory(ports = 1)) ++
|
||||
new testchipip.WithSerialTLWidth(32) ++
|
||||
new testchipip.WithSerialPBusMem ++
|
||||
new freechips.rocketchip.subsystem.WithScratchpadsOnly ++ // use sodor tile-internal scratchpad
|
||||
new freechips.rocketchip.subsystem.WithNoMemPort ++ // use no external memory
|
||||
@@ -43,6 +47,7 @@ class Sodor3StageSinglePortConfig extends Config(
|
||||
class Sodor5StageConfig extends Config(
|
||||
// Create a Sodor 5-stage core
|
||||
new sodor.common.WithNSodorCores(1, internalTile = sodor.common.Stage5Factory) ++
|
||||
new testchipip.WithSerialTLWidth(32) ++
|
||||
new testchipip.WithSerialPBusMem ++
|
||||
new freechips.rocketchip.subsystem.WithScratchpadsOnly ++ // use sodor tile-internal scratchpad
|
||||
new freechips.rocketchip.subsystem.WithNoMemPort ++ // use no external memory
|
||||
@@ -52,6 +57,7 @@ class Sodor5StageConfig extends Config(
|
||||
class SodorUCodeConfig extends Config(
|
||||
// Construct a Sodor microcode-based single-bus core
|
||||
new sodor.common.WithNSodorCores(1, internalTile = sodor.common.UCodeFactory) ++
|
||||
new testchipip.WithSerialTLWidth(32) ++
|
||||
new testchipip.WithSerialPBusMem ++
|
||||
new freechips.rocketchip.subsystem.WithScratchpadsOnly ++ // use sodor tile-internal scratchpad
|
||||
new freechips.rocketchip.subsystem.WithNoMemPort ++ // use no external memory
|
||||
|
||||
@@ -11,7 +11,7 @@ import testchipip.TLHelper
|
||||
|
||||
// DOC include start: MyClient
|
||||
class MyClient(implicit p: Parameters) extends LazyModule {
|
||||
val node = TLHelper.makeClientNode(TLClientParameters(
|
||||
val node = TLHelper.makeClientNode(TLMasterParameters.v1(
|
||||
name = "my-client",
|
||||
sourceId = IdRange(0, 4),
|
||||
requestFifo = true,
|
||||
@@ -29,7 +29,7 @@ class MyClient(implicit p: Parameters) extends LazyModule {
|
||||
class MyManager(implicit p: Parameters) extends LazyModule {
|
||||
val device = new SimpleDevice("my-device", Seq("tutorial,my-device0"))
|
||||
val beatBytes = 8
|
||||
val node = TLHelper.makeManagerNode(beatBytes, TLManagerParameters(
|
||||
val node = TLHelper.makeManagerNode(beatBytes, TLSlaveParameters.v1(
|
||||
address = Seq(AddressSet(0x20000, 0xfff)),
|
||||
resources = device.reg,
|
||||
regionType = RegionType.UNCACHED,
|
||||
@@ -83,7 +83,7 @@ class MyClientGroup(implicit p: Parameters) extends LazyModule {
|
||||
|
||||
// DOC include start: MyManagerGroup
|
||||
class MyManager1(beatBytes: Int)(implicit p: Parameters) extends LazyModule {
|
||||
val node = TLHelper.makeManagerNode(beatBytes, TLManagerParameters(
|
||||
val node = TLHelper.makeManagerNode(beatBytes, TLSlaveParameters.v1(
|
||||
address = Seq(AddressSet(0x0, 0xfff))))
|
||||
|
||||
lazy val module = new LazyModuleImp(this) {
|
||||
@@ -92,7 +92,7 @@ class MyManager1(beatBytes: Int)(implicit p: Parameters) extends LazyModule {
|
||||
}
|
||||
|
||||
class MyManager2(beatBytes: Int)(implicit p: Parameters) extends LazyModule {
|
||||
val node = TLHelper.makeManagerNode(beatBytes, TLManagerParameters(
|
||||
val node = TLHelper.makeManagerNode(beatBytes, TLSlaveParameters.v1(
|
||||
address = Seq(AddressSet(0x1000, 0xfff))))
|
||||
|
||||
lazy val module = new LazyModuleImp(this) {
|
||||
|
||||
@@ -15,6 +15,7 @@ import freechips.rocketchip.interrupts._
|
||||
import freechips.rocketchip.util._
|
||||
import freechips.rocketchip.tile._
|
||||
import freechips.rocketchip.amba.axi4._
|
||||
import freechips.rocketchip.prci.ClockSinkParameters
|
||||
|
||||
// Example parameter class copied from CVA6, not included in documentation but for compile check only
|
||||
// If you are here for documentation, DO NOT copy MyCoreParams and MyTileParams directly - always figure
|
||||
@@ -39,16 +40,20 @@ case class MyCoreParams(
|
||||
val mulDiv: Option[MulDivParams] = Some(MulDivParams()) // copied from Rocket
|
||||
val fpu: Option[FPUParams] = Some(FPUParams()) // copied fma latencies from Rocket
|
||||
val nLocalInterrupts: Int = 0
|
||||
val useNMI: Boolean = false
|
||||
val nPMPs: Int = 0 // TODO: Check
|
||||
val pmpGranularity: Int = 4 // copied from Rocket
|
||||
val nBreakpoints: Int = 0 // TODO: Check
|
||||
val useBPWatch: Boolean = false
|
||||
val mcontextWidth: Int = 0
|
||||
val scontextWidth: Int = 0
|
||||
val nPerfCounters: Int = 29
|
||||
val haveBasicCounters: Boolean = true
|
||||
val haveFSDirty: Boolean = false
|
||||
val misaWritable: Boolean = false
|
||||
val haveCFlush: Boolean = false
|
||||
val nL2TLBEntries: Int = 512 // copied from Rocket
|
||||
val nL2TLBWays: Int = 1
|
||||
val mtvecInit: Option[BigInt] = Some(BigInt(0)) // copied from Rocket
|
||||
val mtvecWritable: Boolean = true // copied from Rocket
|
||||
val instBits: Int = if (useCompressed) 16 else 32
|
||||
@@ -81,6 +86,7 @@ case class MyTileParams(
|
||||
val boundaryBuffers: Boolean = false
|
||||
val dcache: Option[DCacheParams] = Some(DCacheParams())
|
||||
val icache: Option[ICacheParams] = Some(ICacheParams())
|
||||
val clockSinkParams: ClockSinkParameters = ClockSinkParameters()
|
||||
def instantiate(crossing: TileCrossingParamsLike, lookup: LookupByHartIdImpl)(implicit p: Parameters): MyTile = {
|
||||
new MyTile(this, crossing, lookup)
|
||||
}
|
||||
|
||||
Submodule generators/cva6 updated: 8a11e2c976...139741a584
@@ -4,12 +4,13 @@ package firesim.firesim
|
||||
|
||||
import chisel3._
|
||||
import chisel3.experimental.annotate
|
||||
import chisel3.util.experimental.BoringUtils
|
||||
|
||||
import freechips.rocketchip.config.{Field, Config, Parameters}
|
||||
import freechips.rocketchip.diplomacy.{LazyModule}
|
||||
import freechips.rocketchip.devices.debug.{Debug, HasPeripheryDebugModuleImp}
|
||||
import freechips.rocketchip.amba.axi4.{AXI4Bundle}
|
||||
import freechips.rocketchip.subsystem.{CanHaveMasterAXI4MemPort, HasExtInterruptsModuleImp, BaseSubsystem, HasTilesModuleImp, ExtMem}
|
||||
import freechips.rocketchip.subsystem._
|
||||
import freechips.rocketchip.tile.{RocketTile}
|
||||
import sifive.blocks.devices.uart._
|
||||
|
||||
@@ -86,7 +87,12 @@ class WithNICBridge extends OverrideHarnessBinder({
|
||||
|
||||
class WithUARTBridge extends OverrideHarnessBinder({
|
||||
(system: HasPeripheryUARTModuleImp, th: FireSim, ports: Seq[UARTPortIO]) =>
|
||||
ports.map { p => UARTBridge(th.harnessClock, p)(system.p) }; Nil
|
||||
val uartSyncClock = Wire(Clock())
|
||||
uartSyncClock := false.B.asClock
|
||||
val pbusClockNode = system.outer.asInstanceOf[HasTileLinkLocations].locateTLBusWrapper(PBUS).fixedClockNode
|
||||
val pbusClock = pbusClockNode.in.head._1.clock
|
||||
BoringUtils.bore(pbusClock, Seq(uartSyncClock))
|
||||
ports.map { p => UARTBridge(uartSyncClock, p)(system.p) }; Nil
|
||||
})
|
||||
|
||||
class WithBlockDeviceBridge extends OverrideHarnessBinder({
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user