Merge remote-tracking branch 'origin/dev' into hammer-docs
This commit is contained in:
@@ -48,7 +48,7 @@ search () {
|
|||||||
done
|
done
|
||||||
}
|
}
|
||||||
|
|
||||||
submodules=("ariane" "boom" "gemmini" "hwacha" "icenet" "nvdla" "rocket-chip" "sha3" "sifive-blocks" "sifive-cache" "testchipip" "riscv-sodor")
|
submodules=("cva6" "boom" "gemmini" "hwacha" "icenet" "nvdla" "rocket-chip" "sha3" "sifive-blocks" "sifive-cache" "testchipip" "riscv-sodor")
|
||||||
dir="generators"
|
dir="generators"
|
||||||
if [ "$CIRCLE_BRANCH" == "master" ] || [ "$CIRCLE_BRANCH" == "dev" ]
|
if [ "$CIRCLE_BRANCH" == "master" ] || [ "$CIRCLE_BRANCH" == "dev" ]
|
||||||
then
|
then
|
||||||
|
|||||||
@@ -234,12 +234,12 @@ jobs:
|
|||||||
- run-tests:
|
- run-tests:
|
||||||
group-key: "group-cores"
|
group-key: "group-cores"
|
||||||
project-key: "chipyard-boom"
|
project-key: "chipyard-boom"
|
||||||
chipyard-ariane-run-tests:
|
chipyard-cva6-run-tests:
|
||||||
executor: main-env
|
executor: main-env
|
||||||
steps:
|
steps:
|
||||||
- run-tests:
|
- run-tests:
|
||||||
group-key: "group-cores"
|
group-key: "group-cores"
|
||||||
project-key: "chipyard-ariane"
|
project-key: "chipyard-cva6"
|
||||||
timeout: "30m"
|
timeout: "30m"
|
||||||
chipyard-sodor-run-tests:
|
chipyard-sodor-run-tests:
|
||||||
executor: main-env
|
executor: main-env
|
||||||
@@ -248,6 +248,12 @@ jobs:
|
|||||||
group-key: "group-cores"
|
group-key: "group-cores"
|
||||||
project-key: "chipyard-sodor"
|
project-key: "chipyard-sodor"
|
||||||
timeout: "30m"
|
timeout: "30m"
|
||||||
|
chipyard-multiclock-rocket-run-tests:
|
||||||
|
executor: main-env
|
||||||
|
steps:
|
||||||
|
- run-tests:
|
||||||
|
group-key: "group-cores"
|
||||||
|
project-key: "chipyard-multiclock-rocket"
|
||||||
chipyard-dmirocket-run-tests:
|
chipyard-dmirocket-run-tests:
|
||||||
executor: main-env
|
executor: main-env
|
||||||
steps:
|
steps:
|
||||||
@@ -431,7 +437,7 @@ workflows:
|
|||||||
- chipyard-boom-run-tests:
|
- chipyard-boom-run-tests:
|
||||||
requires:
|
requires:
|
||||||
- prepare-chipyard-cores
|
- prepare-chipyard-cores
|
||||||
- chipyard-ariane-run-tests:
|
- chipyard-cva6-run-tests:
|
||||||
requires:
|
requires:
|
||||||
- prepare-chipyard-cores
|
- prepare-chipyard-cores
|
||||||
- chipyard-sodor-run-tests:
|
- chipyard-sodor-run-tests:
|
||||||
|
|||||||
@@ -47,7 +47,7 @@ LOCAL_FIRESIM_DIR=$LOCAL_CHIPYARD_DIR/sims/firesim/sim
|
|||||||
|
|
||||||
# key value store to get the build groups
|
# key value store to get the build groups
|
||||||
declare -A grouping
|
declare -A grouping
|
||||||
grouping["group-cores"]="chipyard-ariane chipyard-rocket chipyard-hetero chipyard-boom chipyard-sodor"
|
grouping["group-cores"]="chipyard-cva6 chipyard-rocket chipyard-hetero chipyard-boom chipyard-sodor chipyard-digitaltop chipyard-multiclock-rocket"
|
||||||
grouping["group-peripherals"]="chipyard-dmirocket chipyard-blkdev chipyard-spiflashread chipyard-spiflashwrite chipyard-mmios chipyard-lbwif"
|
grouping["group-peripherals"]="chipyard-dmirocket chipyard-blkdev chipyard-spiflashread chipyard-spiflashwrite chipyard-mmios chipyard-lbwif"
|
||||||
grouping["group-accels"]="chipyard-nvdla chipyard-sha3 chipyard-hwacha chipyard-gemmini chipyard-streaming-fir chipyard-streaming-passthrough"
|
grouping["group-accels"]="chipyard-nvdla chipyard-sha3 chipyard-hwacha chipyard-gemmini chipyard-streaming-fir chipyard-streaming-passthrough"
|
||||||
grouping["group-tracegen"]="tracegen tracegen-boom"
|
grouping["group-tracegen"]="tracegen tracegen-boom"
|
||||||
@@ -59,6 +59,7 @@ mapping["chipyard-rocket"]=""
|
|||||||
mapping["chipyard-dmirocket"]=" CONFIG=dmiRocketConfig"
|
mapping["chipyard-dmirocket"]=" CONFIG=dmiRocketConfig"
|
||||||
mapping["chipyard-lbwif"]=" CONFIG=LBWIFRocketConfig"
|
mapping["chipyard-lbwif"]=" CONFIG=LBWIFRocketConfig"
|
||||||
mapping["chipyard-sha3"]=" CONFIG=Sha3RocketConfig"
|
mapping["chipyard-sha3"]=" CONFIG=Sha3RocketConfig"
|
||||||
|
mapping["chipyard-digitaltop"]=" TOP=DigitalTop"
|
||||||
mapping["chipyard-streaming-fir"]=" CONFIG=StreamingFIRRocketConfig"
|
mapping["chipyard-streaming-fir"]=" CONFIG=StreamingFIRRocketConfig"
|
||||||
mapping["chipyard-streaming-passthrough"]=" CONFIG=StreamingPassthroughRocketConfig"
|
mapping["chipyard-streaming-passthrough"]=" CONFIG=StreamingPassthroughRocketConfig"
|
||||||
mapping["chipyard-hetero"]=" CONFIG=LargeBoomAndRocketConfig"
|
mapping["chipyard-hetero"]=" CONFIG=LargeBoomAndRocketConfig"
|
||||||
@@ -66,7 +67,7 @@ mapping["chipyard-boom"]=" CONFIG=SmallBoomConfig"
|
|||||||
mapping["chipyard-blkdev"]=" CONFIG=SimBlockDeviceRocketConfig"
|
mapping["chipyard-blkdev"]=" CONFIG=SimBlockDeviceRocketConfig"
|
||||||
mapping["chipyard-hwacha"]=" CONFIG=HwachaRocketConfig"
|
mapping["chipyard-hwacha"]=" CONFIG=HwachaRocketConfig"
|
||||||
mapping["chipyard-gemmini"]=" CONFIG=GemminiRocketConfig"
|
mapping["chipyard-gemmini"]=" CONFIG=GemminiRocketConfig"
|
||||||
mapping["chipyard-ariane"]=" CONFIG=ArianeConfig"
|
mapping["chipyard-cva6"]=" CONFIG=CVA6Config"
|
||||||
mapping["chipyard-spiflashread"]=" CONFIG=LargeSPIFlashROMRocketConfig"
|
mapping["chipyard-spiflashread"]=" CONFIG=LargeSPIFlashROMRocketConfig"
|
||||||
mapping["chipyard-spiflashwrite"]=" CONFIG=SmallSPIFlashRocketConfig"
|
mapping["chipyard-spiflashwrite"]=" CONFIG=SmallSPIFlashRocketConfig"
|
||||||
mapping["chipyard-mmios"]=" CONFIG=MMIORocketConfig verilog"
|
mapping["chipyard-mmios"]=" CONFIG=MMIORocketConfig verilog"
|
||||||
@@ -74,6 +75,7 @@ mapping["tracegen"]=" CONFIG=NonBlockingTraceGenL2Config"
|
|||||||
mapping["tracegen-boom"]=" CONFIG=BoomTraceGenConfig"
|
mapping["tracegen-boom"]=" CONFIG=BoomTraceGenConfig"
|
||||||
mapping["chipyard-nvdla"]=" CONFIG=SmallNVDLARocketConfig"
|
mapping["chipyard-nvdla"]=" CONFIG=SmallNVDLARocketConfig"
|
||||||
mapping["chipyard-sodor"]=" CONFIG=Sodor5StageConfig"
|
mapping["chipyard-sodor"]=" CONFIG=Sodor5StageConfig"
|
||||||
|
mapping["chipyard-multiclock-rocket"]=" CONFIG=MulticlockRocketConfig"
|
||||||
|
|
||||||
mapping["firesim"]="SCALA_TEST=firesim.firesim.RocketNICF1Tests"
|
mapping["firesim"]="SCALA_TEST=firesim.firesim.RocketNICF1Tests"
|
||||||
mapping["firesim-multiclock"]="SCALA_TEST=firesim.firesim.RocketMulticlockF1Tests"
|
mapping["firesim-multiclock"]="SCALA_TEST=firesim.firesim.RocketMulticlockF1Tests"
|
||||||
|
|||||||
@@ -91,7 +91,7 @@ case $1 in
|
|||||||
tracegen-boom)
|
tracegen-boom)
|
||||||
run_tracegen ${mapping[$1]}
|
run_tracegen ${mapping[$1]}
|
||||||
;;
|
;;
|
||||||
chipyard-ariane)
|
chipyard-cva6)
|
||||||
make run-binary-fast -C $LOCAL_SIM_DIR ${mapping[$1]} BINARY=$RISCV/riscv64-unknown-elf/share/riscv-tests/benchmarks/multiply.riscv
|
make run-binary-fast -C $LOCAL_SIM_DIR ${mapping[$1]} BINARY=$RISCV/riscv64-unknown-elf/share/riscv-tests/benchmarks/multiply.riscv
|
||||||
;;
|
;;
|
||||||
chipyard-sodor)
|
chipyard-sodor)
|
||||||
|
|||||||
6
.gitmodules
vendored
6
.gitmodules
vendored
@@ -113,9 +113,9 @@
|
|||||||
[submodule "software/firemarshal"]
|
[submodule "software/firemarshal"]
|
||||||
path = software/firemarshal
|
path = software/firemarshal
|
||||||
url = https://github.com/firesim/FireMarshal.git
|
url = https://github.com/firesim/FireMarshal.git
|
||||||
[submodule "generators/ariane"]
|
[submodule "generators/cva6"]
|
||||||
path = generators/ariane
|
path = generators/cva6
|
||||||
url = https://github.com/ucb-bar/ariane-wrapper.git
|
url = https://github.com/ucb-bar/cva6-wrapper.git
|
||||||
[submodule "tools/DRAMSim2"]
|
[submodule "tools/DRAMSim2"]
|
||||||
path = tools/DRAMSim2
|
path = tools/DRAMSim2
|
||||||
url = https://github.com/firesim/DRAMSim2.git
|
url = https://github.com/firesim/DRAMSim2.git
|
||||||
|
|||||||
@@ -10,7 +10,7 @@ To get started using Chipyard, see the documentation on the Chipyard documentati
|
|||||||
|
|
||||||
Chipyard is an open source framework for agile development of Chisel-based systems-on-chip.
|
Chipyard is an open source framework for agile development of Chisel-based systems-on-chip.
|
||||||
It will allow you to leverage the Chisel HDL, Rocket Chip SoC generator, and other [Berkeley][berkeley] projects to produce a [RISC-V][riscv] SoC with everything from MMIO-mapped peripherals to custom accelerators.
|
It will allow you to leverage the Chisel HDL, Rocket Chip SoC generator, and other [Berkeley][berkeley] projects to produce a [RISC-V][riscv] SoC with everything from MMIO-mapped peripherals to custom accelerators.
|
||||||
Chipyard contains processor cores ([Rocket][rocket-chip], [BOOM][boom], [Ariane][ariane]), accelerators ([Hwacha][hwacha], [Gemmini][gemmini], [NVDLA][nvdla]), memory systems, and additional peripherals and tooling to help create a full featured SoC.
|
Chipyard contains processor cores ([Rocket][rocket-chip], [BOOM][boom], [CVA6 (Ariane)][cva6]), accelerators ([Hwacha][hwacha], [Gemmini][gemmini], [NVDLA][nvdla]), memory systems, and additional peripherals and tooling to help create a full featured SoC.
|
||||||
Chipyard supports multiple concurrent flows of agile hardware development, including software RTL simulation, FPGA-accelerated simulation ([FireSim][firesim]), automated VLSI flows ([Hammer][hammer]), and software workload generation for bare-metal and Linux-based systems ([FireMarshal][firemarshal]).
|
Chipyard supports multiple concurrent flows of agile hardware development, including software RTL simulation, FPGA-accelerated simulation ([FireSim][firesim]), automated VLSI flows ([Hammer][hammer]), and software workload generation for bare-metal and Linux-based systems ([FireMarshal][firemarshal]).
|
||||||
Chipyard is actively developed in the [Berkeley Architecture Research Group][ucb-bar] in the [Electrical Engineering and Computer Sciences Department][eecs] at the [University of California, Berkeley][berkeley].
|
Chipyard is actively developed in the [Berkeley Architecture Research Group][ucb-bar] in the [Electrical Engineering and Computer Sciences Department][eecs] at the [University of California, Berkeley][berkeley].
|
||||||
|
|
||||||
@@ -80,6 +80,6 @@ These additional publications cover many of the internal components used in Chip
|
|||||||
[rocket-chip]: https://github.com/freechipsproject/rocket-chip
|
[rocket-chip]: https://github.com/freechipsproject/rocket-chip
|
||||||
[boom]: https://github.com/riscv-boom/riscv-boom
|
[boom]: https://github.com/riscv-boom/riscv-boom
|
||||||
[firemarshal]: https://github.com/firesim/FireMarshal/
|
[firemarshal]: https://github.com/firesim/FireMarshal/
|
||||||
[ariane]: https://github.com/pulp-platform/ariane/
|
[cva6]: https://github.com/openhwgroup/cva6/
|
||||||
[gemmini]: https://github.com/ucb-bar/gemmini
|
[gemmini]: https://github.com/ucb-bar/gemmini
|
||||||
[nvdla]: http://nvdla.org/
|
[nvdla]: http://nvdla.org/
|
||||||
|
|||||||
@@ -132,7 +132,7 @@ lazy val chipyard = conditionalDependsOn(project in file("generators/chipyard"))
|
|||||||
.dependsOn(boom, hwacha, sifive_blocks, sifive_cache, utilities, iocell,
|
.dependsOn(boom, hwacha, sifive_blocks, sifive_cache, utilities, iocell,
|
||||||
sha3, // On separate line to allow for cleaner tutorial-setup patches
|
sha3, // On separate line to allow for cleaner tutorial-setup patches
|
||||||
dsptools, `rocket-dsptools`,
|
dsptools, `rocket-dsptools`,
|
||||||
gemmini, icenet, tracegen, ariane, nvdla, sodor)
|
gemmini, icenet, tracegen, cva6, nvdla, sodor)
|
||||||
.settings(commonSettings)
|
.settings(commonSettings)
|
||||||
|
|
||||||
lazy val tracegen = conditionalDependsOn(project in file("generators/tracegen"))
|
lazy val tracegen = conditionalDependsOn(project in file("generators/tracegen"))
|
||||||
@@ -154,7 +154,7 @@ lazy val boom = conditionalDependsOn(project in file("generators/boom"))
|
|||||||
.dependsOn(rocketchip)
|
.dependsOn(rocketchip)
|
||||||
.settings(commonSettings)
|
.settings(commonSettings)
|
||||||
|
|
||||||
lazy val ariane = (project in file("generators/ariane"))
|
lazy val cva6 = (project in file("generators/cva6"))
|
||||||
.dependsOn(rocketchip)
|
.dependsOn(rocketchip)
|
||||||
.settings(commonSettings)
|
.settings(commonSettings)
|
||||||
|
|
||||||
|
|||||||
@@ -47,7 +47,7 @@ HELP_COMMANDS += \
|
|||||||
# include additional subproject make fragments
|
# include additional subproject make fragments
|
||||||
# see HELP_COMPILATION_VARIABLES
|
# see HELP_COMPILATION_VARIABLES
|
||||||
#########################################################################################
|
#########################################################################################
|
||||||
include $(base_dir)/generators/ariane/ariane.mk
|
include $(base_dir)/generators/cva6/cva6.mk
|
||||||
include $(base_dir)/generators/tracegen/tracegen.mk
|
include $(base_dir)/generators/tracegen/tracegen.mk
|
||||||
include $(base_dir)/generators/nvdla/nvdla.mk
|
include $(base_dir)/generators/nvdla/nvdla.mk
|
||||||
include $(base_dir)/tools/dromajo/dromajo.mk
|
include $(base_dir)/tools/dromajo/dromajo.mk
|
||||||
@@ -103,7 +103,7 @@ $(sim_files): $(call lookup_srcs,$(base_dir)/generators/utilities/src/main/scala
|
|||||||
$(FIRRTL_FILE) $(ANNO_FILE): generator_temp
|
$(FIRRTL_FILE) $(ANNO_FILE): generator_temp
|
||||||
@echo "" > /dev/null
|
@echo "" > /dev/null
|
||||||
|
|
||||||
# AG: must re-elaborate if ariane sources have changed... otherwise just run firrtl compile
|
# AG: must re-elaborate if cva6 sources have changed... otherwise just run firrtl compile
|
||||||
generator_temp: $(SCALA_SOURCES) $(sim_files) $(EXTRA_GENERATOR_REQS)
|
generator_temp: $(SCALA_SOURCES) $(sim_files) $(EXTRA_GENERATOR_REQS)
|
||||||
mkdir -p $(build_dir)
|
mkdir -p $(build_dir)
|
||||||
$(call run_scala_main,$(SBT_PROJECT),$(GENERATOR_PACKAGE).Generator,\
|
$(call run_scala_main,$(SBT_PROJECT),$(GENERATOR_PACKAGE).Generator,\
|
||||||
|
|||||||
@@ -20,9 +20,9 @@ Processor Cores
|
|||||||
An out-of-order RISC-V core.
|
An out-of-order RISC-V core.
|
||||||
See :ref:`Berkeley Out-of-Order Machine (BOOM)` for more information.
|
See :ref:`Berkeley Out-of-Order Machine (BOOM)` for more information.
|
||||||
|
|
||||||
**Ariane Core**
|
**CVA6 Core**
|
||||||
An in-order RISC-V core written in System Verilog.
|
An in-order RISC-V core written in System Verilog. Previously called Ariane.
|
||||||
See :ref:`Ariane Core` for more information.
|
See :ref:`CVA6 Core` for more information.
|
||||||
|
|
||||||
Accelerators
|
Accelerators
|
||||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|||||||
@@ -296,6 +296,6 @@ Now you have finished all the steps to prepare your cores for Chipyard! To gener
|
|||||||
in :ref:`custom_chisel` to add your project to the build system, then create a config by following the steps in :ref:`hetero_socs_`.
|
in :ref:`custom_chisel` to add your project to the build system, then create a config by following the steps in :ref:`hetero_socs_`.
|
||||||
You can now run most desired workflows for the new config just as you would for the built-in cores (depending on the functionality your core supports).
|
You can now run most desired workflows for the new config just as you would for the built-in cores (depending on the functionality your core supports).
|
||||||
|
|
||||||
If you would like to see an example of a complete third-party Verilog core integrated into Chipyard, ``generators/ariane/src/main/scala/ArianeTile.scala``
|
If you would like to see an example of a complete third-party Verilog core integrated into Chipyard, ``generators/ariane/src/main/scala/CVA6Tile.scala``
|
||||||
provides a concrete example of the Ariane core. Note that this particular example includes additional nuances with respect to the interaction of the AXI
|
provides a concrete example of the CVA6 core. Note that this particular example includes additional nuances with respect to the interaction of the AXI
|
||||||
interface with the memory coherency system.
|
interface with the memory coherency system.
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ IOBinders and HarnessBinders
|
|||||||
In Chipyard we use special ``Parameters`` keys, ``IOBinders`` and ``HarnessBinders`` to bridge the gap between digital system IOs and TestHarness collateral.
|
In Chipyard we use special ``Parameters`` keys, ``IOBinders`` and ``HarnessBinders`` to bridge the gap between digital system IOs and TestHarness collateral.
|
||||||
|
|
||||||
IOBinders
|
IOBinders
|
||||||
=========
|
---------
|
||||||
|
|
||||||
The ``IOBinder`` functions are responsible for instantiating IO cells and IOPorts in the ``ChipTop`` layer.
|
The ``IOBinder`` functions are responsible for instantiating IO cells and IOPorts in the ``ChipTop`` layer.
|
||||||
|
|
||||||
@@ -19,7 +19,7 @@ For example, the ``WithUARTIOCells`` IOBinder will, for any ``System`` that migh
|
|||||||
:end-before: DOC include end: WithUARTIOCells
|
:end-before: DOC include end: WithUARTIOCells
|
||||||
|
|
||||||
HarnessBinders
|
HarnessBinders
|
||||||
==============
|
--------------
|
||||||
|
|
||||||
The ``HarnessBinder`` functions determine what modules to bind to the IOs of a ``ChipTop`` in the ``TestHarness``. The ``HarnessBinder`` interface is designed to be reused across various simulation/implementation modes, enabling decoupling of the target design from simulation and testing concerns.
|
The ``HarnessBinder`` functions determine what modules to bind to the IOs of a ``ChipTop`` in the ``TestHarness``. The ``HarnessBinder`` interface is designed to be reused across various simulation/implementation modes, enabling decoupling of the target design from simulation and testing concerns.
|
||||||
|
|
||||||
|
|||||||
@@ -1,14 +1,14 @@
|
|||||||
Ariane Core
|
CVA6 Core
|
||||||
====================================
|
====================================
|
||||||
|
|
||||||
`Ariane <https://github.com/pulp-platform/ariane>`__ is a 6-stage in-order scalar processor core, originally developed at ETH-Zurich by F. Zaruba and L. Benini.
|
`CVA6 <https://github.com/openhwgroup/cva6>`__ (previously called Ariane) is a 6-stage in-order scalar processor core, originally developed at ETH-Zurich by F. Zaruba and L. Benini.
|
||||||
The `Ariane core` is wrapped in an `Ariane tile` so it can be used as a component within the `Rocket Chip SoC generator`.
|
The `CVA6 core` is wrapped in an `CVA6 tile` so it can be used as a component within the `Rocket Chip SoC generator`.
|
||||||
The core by itself exposes an AXI interface, interrupt ports, and other misc. ports that are connected from within the tile to TileLink buses and other parameterization signals.
|
The core by itself exposes an AXI interface, interrupt ports, and other misc. ports that are connected from within the tile to TileLink buses and other parameterization signals.
|
||||||
|
|
||||||
.. Warning:: Since the core uses an AXI interface to connect to memory, it is highly recommended to use the core in a single-core setup (since AXI is a non-coherent memory interface).
|
.. Warning:: Since the core uses an AXI interface to connect to memory, it is highly recommended to use the core in a single-core setup (since AXI is a non-coherent memory interface).
|
||||||
|
|
||||||
While the core itself is not a generator, we expose the same parameterization that the Ariane core provides (i.e. change branch prediction parameters).
|
While the core itself is not a generator, we expose the same parameterization that the CVA6 core provides (i.e. change branch prediction parameters).
|
||||||
|
|
||||||
.. Warning:: This target does not support Verilator simulation at this time. Please use VCS.
|
.. Warning:: This target does not support Verilator simulation at this time. Please use VCS.
|
||||||
|
|
||||||
For more information, please refer to the `GitHub repository <https://github.com/pulp-platform/ariane>`__.
|
For more information, please refer to the `GitHub repository <https://github.com/openhwgroup/cva6>`__.
|
||||||
@@ -27,7 +27,7 @@ so changes to the generators themselves will automatically be used when building
|
|||||||
TestChipIP
|
TestChipIP
|
||||||
SiFive-Generators
|
SiFive-Generators
|
||||||
SHA3
|
SHA3
|
||||||
Ariane
|
CVA6
|
||||||
NVDLA
|
NVDLA
|
||||||
Sodor
|
Sodor
|
||||||
|
|
||||||
|
|||||||
Submodule generators/ariane deleted from 3a2eed602f
@@ -5,7 +5,7 @@
|
|||||||
* Duty cycle is 100 * (ceil(DIV / 2)) / DIV.
|
* Duty cycle is 100 * (ceil(DIV / 2)) / DIV.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
module ClockDividerN #(parameter DIV)(output logic clk_out = 1'b0, input clk_in);
|
module ClockDividerN #(parameter DIV = 1)(output logic clk_out = 1'b0, input clk_in);
|
||||||
|
|
||||||
localparam CWIDTH = $clog2(DIV);
|
localparam CWIDTH = $clog2(DIV);
|
||||||
localparam LOW_CYCLES = DIV / 2;
|
localparam LOW_CYCLES = DIV / 2;
|
||||||
|
|||||||
@@ -23,12 +23,10 @@ case object BuildSystem extends Field[Parameters => LazyModule]((p: Parameters)
|
|||||||
* drive clock and reset generation
|
* drive clock and reset generation
|
||||||
*/
|
*/
|
||||||
|
|
||||||
class ChipTop(implicit p: Parameters) extends LazyModule with HasTestHarnessFunctions {
|
class ChipTop(implicit p: Parameters) extends LazyModule
|
||||||
// A publicly accessible list of IO cells (useful for a floorplanning tool, for example)
|
with HasTestHarnessFunctions with HasIOBinders {
|
||||||
val iocells = ArrayBuffer.empty[IOCell]
|
|
||||||
|
|
||||||
// The system module specified by BuildSystem
|
// The system module specified by BuildSystem
|
||||||
val lazySystem = LazyModule(p(BuildSystem)(p)).suggestName("system")
|
lazy val lazySystem = LazyModule(p(BuildSystem)(p)).suggestName("system")
|
||||||
|
|
||||||
// The implicitClockSinkNode provides the implicit clock and reset for the System
|
// The implicitClockSinkNode provides the implicit clock and reset for the System
|
||||||
val implicitClockSinkNode = ClockSinkNode(Seq(ClockSinkParameters(name = Some("implicit_clock"))))
|
val implicitClockSinkNode = ClockSinkNode(Seq(ClockSinkParameters(name = Some("implicit_clock"))))
|
||||||
@@ -45,13 +43,6 @@ class ChipTop(implicit p: Parameters) extends LazyModule with HasTestHarnessFunc
|
|||||||
val implicit_clock = implicitClockSinkNode.in.head._1.clock
|
val implicit_clock = implicitClockSinkNode.in.head._1.clock
|
||||||
val implicit_reset = implicitClockSinkNode.in.head._1.reset
|
val implicit_reset = implicitClockSinkNode.in.head._1.reset
|
||||||
|
|
||||||
|
|
||||||
// Note: IOBinders cannot rely on the implicit clock/reset, as this is a LazyRawModuleImp
|
|
||||||
val (_ports, _iocells, _portMap) = ApplyIOBinders(lazySystem, p(IOBinders))
|
|
||||||
// We ignore _ports for now...
|
|
||||||
iocells ++= _iocells
|
|
||||||
portMap ++= _portMap
|
|
||||||
|
|
||||||
// Connect the implicit clock/reset, if present
|
// Connect the implicit clock/reset, if present
|
||||||
lazySystem.module match { case l: LazyModuleImp => {
|
lazySystem.module match { case l: LazyModuleImp => {
|
||||||
l.clock := implicit_clock
|
l.clock := implicit_clock
|
||||||
|
|||||||
@@ -15,40 +15,6 @@ import testchipip.{TLTileResetCtrl}
|
|||||||
|
|
||||||
import chipyard.clocking._
|
import chipyard.clocking._
|
||||||
|
|
||||||
/**
|
|
||||||
* Chipyard provides three baseline, top-level reset schemes, set using the
|
|
||||||
* [[GlobalResetSchemeKey]] in a Parameters instance. These are:
|
|
||||||
*
|
|
||||||
* 1) Synchronous: The input coming to the chip is synchronous to the provided
|
|
||||||
* clocks and will be used without modification as a synchronous reset.
|
|
||||||
* This is safe only for use in FireSim and SW simulation.
|
|
||||||
*
|
|
||||||
* 2) Asynchronous: The input reset is asynchronous to the input clock, but it
|
|
||||||
* is caught and synchronized to that clock before it is dissemenated.
|
|
||||||
* Thus, downsteam modules will be emitted with synchronously reset state
|
|
||||||
* elements.
|
|
||||||
*
|
|
||||||
* 3) Asynchronous Full: The input reset is asynchronous to the input clock,
|
|
||||||
* and is used globally as an async reset. Downstream modules will be emitted
|
|
||||||
* with asynchronously reset state elements.
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
sealed trait GlobalResetScheme {
|
|
||||||
def pinIsAsync: Boolean
|
|
||||||
}
|
|
||||||
sealed trait HasAsyncInput { self: GlobalResetScheme =>
|
|
||||||
def pinIsAsync = true
|
|
||||||
}
|
|
||||||
|
|
||||||
sealed trait HasSyncInput { self: GlobalResetScheme =>
|
|
||||||
def pinIsAsync = false
|
|
||||||
}
|
|
||||||
|
|
||||||
case object GlobalResetSynchronous extends GlobalResetScheme with HasSyncInput
|
|
||||||
case object GlobalResetAsynchronous extends GlobalResetScheme with HasAsyncInput
|
|
||||||
case object GlobalResetAsynchronousFull extends GlobalResetScheme with HasAsyncInput
|
|
||||||
case object GlobalResetSchemeKey extends Field[GlobalResetScheme](GlobalResetSynchronous)
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A simple reset implementation that punches out reset ports
|
* A simple reset implementation that punches out reset ports
|
||||||
* for standard Module classes. Three basic reset schemes
|
* for standard Module classes. Three basic reset schemes
|
||||||
@@ -58,24 +24,16 @@ object GenerateReset {
|
|||||||
def apply(chiptop: ChipTop, clock: Clock): Reset = {
|
def apply(chiptop: ChipTop, clock: Clock): Reset = {
|
||||||
implicit val p = chiptop.p
|
implicit val p = chiptop.p
|
||||||
// this needs directionality so generateIOFromSignal works
|
// this needs directionality so generateIOFromSignal works
|
||||||
val reset_wire = Wire(Input(Reset()))
|
val async_reset_wire = Wire(Input(AsyncReset()))
|
||||||
val (reset_io, resetIOCell) = p(GlobalResetSchemeKey) match {
|
val (reset_io, resetIOCell) = IOCell.generateIOFromSignal(async_reset_wire, "reset",
|
||||||
case GlobalResetSynchronous =>
|
abstractResetAsAsync = true)
|
||||||
IOCell.generateIOFromSignal(reset_wire, "reset")
|
|
||||||
case GlobalResetAsynchronousFull =>
|
|
||||||
IOCell.generateIOFromSignal(reset_wire, "reset", abstractResetAsAsync = true)
|
|
||||||
case GlobalResetAsynchronous => {
|
|
||||||
val async_reset_wire = Wire(Input(AsyncReset()))
|
|
||||||
reset_wire := ResetCatchAndSync(clock, async_reset_wire.asBool())
|
|
||||||
IOCell.generateIOFromSignal(async_reset_wire, "reset", abstractResetAsAsync = true)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
chiptop.iocells ++= resetIOCell
|
chiptop.iocells ++= resetIOCell
|
||||||
chiptop.harnessFunctions += ((th: HasHarnessSignalReferences) => {
|
chiptop.harnessFunctions += ((th: HasHarnessSignalReferences) => {
|
||||||
reset_io := th.dutReset
|
reset_io := th.dutReset
|
||||||
Nil
|
Nil
|
||||||
})
|
})
|
||||||
reset_wire
|
async_reset_wire
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
package chipyard.config
|
package chipyard.config
|
||||||
|
|
||||||
|
import scala.util.matching.Regex
|
||||||
import chisel3._
|
import chisel3._
|
||||||
import chisel3.util.{log2Up}
|
import chisel3.util.{log2Up}
|
||||||
|
|
||||||
@@ -11,6 +12,7 @@ import freechips.rocketchip.devices.debug.{Debug, ExportDebug, DebugModuleKey, D
|
|||||||
import freechips.rocketchip.groundtest.{GroundTestSubsystem}
|
import freechips.rocketchip.groundtest.{GroundTestSubsystem}
|
||||||
import freechips.rocketchip.tile._
|
import freechips.rocketchip.tile._
|
||||||
import freechips.rocketchip.rocket.{RocketCoreParams, MulDivParams, DCacheParams, ICacheParams}
|
import freechips.rocketchip.rocket.{RocketCoreParams, MulDivParams, DCacheParams, ICacheParams}
|
||||||
|
import freechips.rocketchip.tilelink.{HasTLBusParams}
|
||||||
import freechips.rocketchip.util.{AsyncResetReg, Symmetric}
|
import freechips.rocketchip.util.{AsyncResetReg, Symmetric}
|
||||||
import freechips.rocketchip.prci._
|
import freechips.rocketchip.prci._
|
||||||
|
|
||||||
@@ -21,7 +23,7 @@ import hwacha.{Hwacha}
|
|||||||
import gemmini.{Gemmini, GemminiConfigs}
|
import gemmini.{Gemmini, GemminiConfigs}
|
||||||
|
|
||||||
import boom.common.{BoomTileAttachParams}
|
import boom.common.{BoomTileAttachParams}
|
||||||
import ariane.{ArianeTileAttachParams}
|
import cva6.{CVA6TileAttachParams}
|
||||||
|
|
||||||
import sifive.blocks.devices.gpio._
|
import sifive.blocks.devices.gpio._
|
||||||
import sifive.blocks.devices.uart._
|
import sifive.blocks.devices.uart._
|
||||||
@@ -120,7 +122,7 @@ class WithTraceIO extends Config((site, here, up) => {
|
|||||||
case TilesLocated(InSubsystem) => up(TilesLocated(InSubsystem), site) map {
|
case TilesLocated(InSubsystem) => up(TilesLocated(InSubsystem), site) map {
|
||||||
case tp: BoomTileAttachParams => tp.copy(tileParams = tp.tileParams.copy(
|
case tp: BoomTileAttachParams => tp.copy(tileParams = tp.tileParams.copy(
|
||||||
trace = true))
|
trace = true))
|
||||||
case tp: ArianeTileAttachParams => tp.copy(tileParams = tp.tileParams.copy(
|
case tp: CVA6TileAttachParams => tp.copy(tileParams = tp.tileParams.copy(
|
||||||
trace = true))
|
trace = true))
|
||||||
case other => other
|
case other => other
|
||||||
}
|
}
|
||||||
@@ -183,6 +185,34 @@ class WithPeripheryBusFrequencyAsDefault extends Config((site, here, up) => {
|
|||||||
case DefaultClockFrequencyKey => (site(PeripheryBusKey).dtsFrequency.get / (1000 * 1000)).toDouble
|
case DefaultClockFrequencyKey => (site(PeripheryBusKey).dtsFrequency.get / (1000 * 1000)).toDouble
|
||||||
})
|
})
|
||||||
|
|
||||||
|
class WithSystemBusFrequencyAsDefault extends Config((site, here, up) => {
|
||||||
|
case DefaultClockFrequencyKey => (site(SystemBusKey).dtsFrequency.get / (1000 * 1000)).toDouble
|
||||||
|
})
|
||||||
|
|
||||||
|
class BusFrequencyAssignment[T <: HasTLBusParams](re: Regex, key: Field[T]) extends Config((site, here, up) => {
|
||||||
|
case ClockFrequencyAssignersKey => up(ClockFrequencyAssignersKey, site) ++
|
||||||
|
Seq((cName: String) => site(key).dtsFrequency.flatMap { f =>
|
||||||
|
re.findFirstIn(cName).map {_ => (f / (1000 * 1000)).toDouble }
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Provides a diplomatic frequency for all clock sinks with an unspecified
|
||||||
|
* frequency bound to each bus.
|
||||||
|
*
|
||||||
|
* For example, the L2 cache, when bound to the sbus, receives a separate
|
||||||
|
* clock that appears as "subsystem_sbus_<num>". This fragment ensures that
|
||||||
|
* clock requests the same frequency as the sbus itself.
|
||||||
|
*/
|
||||||
|
|
||||||
|
class WithInheritBusFrequencyAssignments extends Config(
|
||||||
|
new BusFrequencyAssignment("subsystem_sbus_\\d+".r, SystemBusKey) ++
|
||||||
|
new BusFrequencyAssignment("subsystem_pbus_\\d+".r, PeripheryBusKey) ++
|
||||||
|
new BusFrequencyAssignment("subsystem_cbus_\\d+".r, ControlBusKey) ++
|
||||||
|
new BusFrequencyAssignment("subsystem_fbus_\\d+".r, FrontBusKey) ++
|
||||||
|
new BusFrequencyAssignment("subsystem_mbus_\\d+".r, MemoryBusKey)
|
||||||
|
)
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Mixins to specify crossing types between the 5 traditional TL buses
|
* Mixins to specify crossing types between the 5 traditional TL buses
|
||||||
*
|
*
|
||||||
@@ -212,16 +242,19 @@ class WithFbusToSbusCrossingType(xType: ClockCrossingType) extends Config((site,
|
|||||||
* up the diplomatic graph to the clock sources.
|
* up the diplomatic graph to the clock sources.
|
||||||
*/
|
*/
|
||||||
class WithPeripheryBusFrequency(freqMHz: Double) extends Config((site, here, up) => {
|
class WithPeripheryBusFrequency(freqMHz: Double) extends Config((site, here, up) => {
|
||||||
case PeripheryBusKey => up(PeripheryBusKey).copy(dtsFrequency = Some(BigInt((freqMHz * 1e6).toLong)))
|
case PeripheryBusKey => up(PeripheryBusKey, site).copy(dtsFrequency = Some(BigInt((freqMHz * 1e6).toLong)))
|
||||||
})
|
})
|
||||||
class WithMemoryBusFrequency(freqMHz: Double) extends Config((site, here, up) => {
|
class WithMemoryBusFrequency(freqMHz: Double) extends Config((site, here, up) => {
|
||||||
case MemoryBusKey => up(MemoryBusKey).copy(dtsFrequency = Some(BigInt((freqMHz * 1e6).toLong)))
|
case MemoryBusKey => up(MemoryBusKey, site).copy(dtsFrequency = Some(BigInt((freqMHz * 1e6).toLong)))
|
||||||
})
|
})
|
||||||
class WithSystemBusFrequency(freqMHz: Double) extends Config((site, here, up) => {
|
class WithSystemBusFrequency(freqMHz: Double) extends Config((site, here, up) => {
|
||||||
case SystemBusKey => up(SystemBusKey).copy(dtsFrequency = Some(BigInt((freqMHz * 1e6).toLong)))
|
case SystemBusKey => up(SystemBusKey, site).copy(dtsFrequency = Some(BigInt((freqMHz * 1e6).toLong)))
|
||||||
|
})
|
||||||
|
class WithFrontBusFrequency(freqMHz: Double) extends Config((site, here, up) => {
|
||||||
|
case FrontBusKey => up(FrontBusKey, site).copy(dtsFrequency = Some(BigInt((freqMHz * 1e6).toLong)))
|
||||||
})
|
})
|
||||||
class WithControlBusFrequency(freqMHz: Double) extends Config((site, here, up) => {
|
class WithControlBusFrequency(freqMHz: Double) extends Config((site, here, up) => {
|
||||||
case ControlBusKey => up(ControlBusKey).copy(dtsFrequency = Some(BigInt((freqMHz * 1e6).toLong)))
|
case ControlBusKey => up(ControlBusKey, site).copy(dtsFrequency = Some(BigInt((freqMHz * 1e6).toLong)))
|
||||||
})
|
})
|
||||||
|
|
||||||
class WithRationalMemoryBusCrossing extends WithSbusToMbusCrossingType(RationalCrossing(Symmetric))
|
class WithRationalMemoryBusCrossing extends WithSbusToMbusCrossingType(RationalCrossing(Symmetric))
|
||||||
|
|||||||
@@ -36,17 +36,35 @@ case class CoherentMulticlockBusTopologyParams(
|
|||||||
(SBUS, L2, TLBusWrapperConnection(xType = NoCrossing, driveClockFromMaster = Some(true), nodeBinding = BIND_STAR)()),
|
(SBUS, L2, TLBusWrapperConnection(xType = NoCrossing, driveClockFromMaster = Some(true), nodeBinding = BIND_STAR)()),
|
||||||
(L2, MBUS, TLBusWrapperConnection.crossTo(
|
(L2, MBUS, TLBusWrapperConnection.crossTo(
|
||||||
xType = sbusToMbusXType,
|
xType = sbusToMbusXType,
|
||||||
driveClockFromMaster = Some(true),
|
driveClockFromMaster = None,
|
||||||
nodeBinding = BIND_QUERY))
|
nodeBinding = BIND_QUERY))
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// This differs from upstream only in that it does not use the legacy crossTo
|
||||||
|
// and crossFrom functions, and it ensures driveClockFromMaster = None
|
||||||
|
case class HierarchicalMulticlockBusTopologyParams(
|
||||||
|
pbus: PeripheryBusParams,
|
||||||
|
fbus: FrontBusParams,
|
||||||
|
cbus: PeripheryBusParams,
|
||||||
|
xTypes: SubsystemCrossingParams
|
||||||
|
) extends TLBusWrapperTopology(
|
||||||
|
instantiations = List(
|
||||||
|
(PBUS, pbus),
|
||||||
|
(FBUS, fbus),
|
||||||
|
(CBUS, cbus)),
|
||||||
|
connections = List(
|
||||||
|
(SBUS, CBUS, TLBusWrapperConnection. crossTo(xType = xTypes.sbusToCbusXType, driveClockFromMaster = None)),
|
||||||
|
(CBUS, PBUS, TLBusWrapperConnection. crossTo(xType = xTypes.cbusToPbusXType, driveClockFromMaster = None)),
|
||||||
|
(FBUS, SBUS, TLBusWrapperConnection.crossFrom(xType = xTypes.fbusToSbusXType, driveClockFromMaster = None)))
|
||||||
|
)
|
||||||
|
|
||||||
// For subsystem/Configs.scala
|
// For subsystem/Configs.scala
|
||||||
|
|
||||||
class WithMulticlockCoherentBusTopology extends Config((site, here, up) => {
|
class WithMulticlockCoherentBusTopology extends Config((site, here, up) => {
|
||||||
case TLNetworkTopologyLocated(InSubsystem) => List(
|
case TLNetworkTopologyLocated(InSubsystem) => List(
|
||||||
JustOneBusTopologyParams(sbus = site(SystemBusKey)),
|
JustOneBusTopologyParams(sbus = site(SystemBusKey)),
|
||||||
HierarchicalBusTopologyParams(
|
HierarchicalMulticlockBusTopologyParams(
|
||||||
pbus = site(PeripheryBusKey),
|
pbus = site(PeripheryBusKey),
|
||||||
fbus = site(FrontBusKey),
|
fbus = site(FrontBusKey),
|
||||||
cbus = site(ControlBusKey),
|
cbus = site(ControlBusKey),
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
package chipyard.harness
|
package chipyard.harness
|
||||||
|
|
||||||
import chisel3._
|
import chisel3._
|
||||||
import chisel3.experimental.{Analog}
|
import chisel3.experimental.{Analog, BaseModule}
|
||||||
|
|
||||||
import freechips.rocketchip.config.{Field, Config, Parameters}
|
import freechips.rocketchip.config.{Field, Config, Parameters}
|
||||||
import freechips.rocketchip.diplomacy.{LazyModule, LazyModuleImpLike}
|
import freechips.rocketchip.diplomacy.{LazyModule, LazyModuleImpLike}
|
||||||
@@ -27,48 +27,54 @@ import icenet.{CanHavePeripheryIceNIC, SimNetwork, NicLoopback, NICKey, NICIOvon
|
|||||||
|
|
||||||
import scala.reflect.{ClassTag}
|
import scala.reflect.{ClassTag}
|
||||||
|
|
||||||
case object HarnessBinders extends Field[Map[String, (Any, HasHarnessSignalReferences, Seq[Data]) => Seq[Any]]](
|
case object HarnessBinders extends Field[Map[String, (Any, HasHarnessSignalReferences, Seq[Data]) => Unit]](
|
||||||
Map[String, (Any, HasHarnessSignalReferences, Seq[Data]) => Seq[Any]]().withDefaultValue((t: Any, th: HasHarnessSignalReferences, d: Seq[Data]) => Nil)
|
Map[String, (Any, HasHarnessSignalReferences, Seq[Data]) => Unit]().withDefaultValue((t: Any, th: HasHarnessSignalReferences, d: Seq[Data]) => ())
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
object ApplyHarnessBinders {
|
object ApplyHarnessBinders {
|
||||||
def apply(th: HasHarnessSignalReferences, sys: LazyModule, map: Map[String, (Any, HasHarnessSignalReferences, Seq[Data]) => Seq[Any]], portMap: Map[String, Seq[Data]]) = {
|
def apply(th: HasHarnessSignalReferences, sys: LazyModule, portMap: Map[String, Seq[Data]])(implicit p: Parameters): Unit = {
|
||||||
val pm = portMap.withDefaultValue(Nil)
|
val pm = portMap.withDefaultValue(Nil)
|
||||||
map.map { case (s, f) => f(sys, th, pm(s)) ++ f(sys.module, th, pm(s)) }
|
p(HarnessBinders).foreach { case (s, f) =>
|
||||||
|
f(sys, th, pm(s))
|
||||||
|
f(sys.module, th, pm(s))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class OverrideHarnessBinder[T, S <: Data](fn: => (T, HasHarnessSignalReferences, Seq[S]) => Seq[Any])(implicit tag: ClassTag[T], ptag: ClassTag[S]) extends Config((site, here, up) => {
|
// The ClassTags here are necessary to overcome issues arising from type erasure
|
||||||
case HarnessBinders => up(HarnessBinders, site) + (tag.runtimeClass.toString ->
|
class HarnessBinder[T, S <: HasHarnessSignalReferences, U <: Data](composer: ((T, S, Seq[U]) => Unit) => (T, S, Seq[U]) => Unit)(implicit systemTag: ClassTag[T], harnessTag: ClassTag[S], portTag: ClassTag[U]) extends Config((site, here, up) => {
|
||||||
|
case HarnessBinders => up(HarnessBinders, site) + (systemTag.runtimeClass.toString ->
|
||||||
((t: Any, th: HasHarnessSignalReferences, ports: Seq[Data]) => {
|
((t: Any, th: HasHarnessSignalReferences, ports: Seq[Data]) => {
|
||||||
val pts = ports.collect({case p: S => p})
|
val pts = ports.collect({case p: U => p})
|
||||||
require (pts.length == ports.length, s"Port type mismatch between IOBinder and HarnessBinder: ${ptag}")
|
require (pts.length == ports.length, s"Port type mismatch between IOBinder and HarnessBinder: ${portTag}")
|
||||||
t match {
|
val upfn = up(HarnessBinders, site)(systemTag.runtimeClass.toString)
|
||||||
case system: T => fn(system, th, pts)
|
th match {
|
||||||
case _ => Nil
|
case th: S =>
|
||||||
|
t match {
|
||||||
|
case system: T => composer(upfn)(system, th, pts)
|
||||||
|
case _ =>
|
||||||
|
}
|
||||||
|
case _ =>
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
|
|
||||||
class ComposeHarnessBinder[T, S <: Data](fn: => (T, HasHarnessSignalReferences, Seq[S]) => Seq[Any])(implicit tag: ClassTag[T], ptag: ClassTag[S]) extends Config((site, here, up) => {
|
class OverrideHarnessBinder[T, S <: HasHarnessSignalReferences, U <: Data](fn: => (T, S, Seq[U]) => Unit)
|
||||||
case HarnessBinders => up(HarnessBinders, site) + (tag.runtimeClass.toString ->
|
(implicit tag: ClassTag[T], thtag: ClassTag[S], ptag: ClassTag[U])
|
||||||
((t: Any, th: HasHarnessSignalReferences, ports: Seq[Data]) => {
|
extends HarnessBinder[T, S, U]((upfn: (T, S, Seq[U]) => Unit) => fn)
|
||||||
val pts = ports.collect({case p: S => p})
|
|
||||||
require (pts.length == ports.length, s"Port type mismatch between IOBinder and HarnessBinder: ${ptag}")
|
class ComposeHarnessBinder[T, S <: HasHarnessSignalReferences, U <: Data](fn: => (T, S, Seq[U]) => Unit)
|
||||||
t match {
|
(implicit tag: ClassTag[T], thtag: ClassTag[S], ptag: ClassTag[U])
|
||||||
case system: T => up(HarnessBinders, site)(tag.runtimeClass.toString)(system, th, pts) ++ fn(system, th, pts)
|
extends HarnessBinder[T, S, U]((upfn: (T, S, Seq[U]) => Unit) => (t, th, p) => {
|
||||||
case _ => Nil
|
upfn(t, th, p)
|
||||||
}
|
fn(t, th, p)
|
||||||
})
|
})
|
||||||
)
|
|
||||||
})
|
|
||||||
|
|
||||||
class WithGPIOTiedOff extends OverrideHarnessBinder({
|
class WithGPIOTiedOff extends OverrideHarnessBinder({
|
||||||
(system: HasPeripheryGPIOModuleImp, th: HasHarnessSignalReferences, ports: Seq[Analog]) => {
|
(system: HasPeripheryGPIOModuleImp, th: HasHarnessSignalReferences, ports: Seq[Analog]) => {
|
||||||
ports.foreach { _ <> AnalogConst(0) }
|
ports.foreach { _ <> AnalogConst(0) }
|
||||||
Nil
|
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
@@ -76,7 +82,6 @@ class WithGPIOTiedOff extends OverrideHarnessBinder({
|
|||||||
class WithUARTAdapter extends OverrideHarnessBinder({
|
class WithUARTAdapter extends OverrideHarnessBinder({
|
||||||
(system: HasPeripheryUARTModuleImp, th: HasHarnessSignalReferences, ports: Seq[UARTPortIO]) => {
|
(system: HasPeripheryUARTModuleImp, th: HasHarnessSignalReferences, ports: Seq[UARTPortIO]) => {
|
||||||
UARTAdapter.connect(ports)(system.p)
|
UARTAdapter.connect(ports)(system.p)
|
||||||
Nil
|
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
// DOC include end: WithUARTAdapter
|
// DOC include end: WithUARTAdapter
|
||||||
@@ -84,7 +89,6 @@ class WithUARTAdapter extends OverrideHarnessBinder({
|
|||||||
class WithSimSPIFlashModel(rdOnly: Boolean = true) extends OverrideHarnessBinder({
|
class WithSimSPIFlashModel(rdOnly: Boolean = true) extends OverrideHarnessBinder({
|
||||||
(system: HasPeripherySPIFlashModuleImp, th: HasHarnessSignalReferences, ports: Seq[SPIChipIO]) => {
|
(system: HasPeripherySPIFlashModuleImp, th: HasHarnessSignalReferences, ports: Seq[SPIChipIO]) => {
|
||||||
SimSPIFlashModel.connect(ports, th.harnessReset, rdOnly)(system.p)
|
SimSPIFlashModel.connect(ports, th.harnessReset, rdOnly)(system.p)
|
||||||
Nil
|
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
@@ -92,7 +96,6 @@ class WithSimBlockDevice extends OverrideHarnessBinder({
|
|||||||
(system: CanHavePeripheryBlockDevice, th: HasHarnessSignalReferences, ports: Seq[ClockedIO[BlockDeviceIO]]) => {
|
(system: CanHavePeripheryBlockDevice, th: HasHarnessSignalReferences, ports: Seq[ClockedIO[BlockDeviceIO]]) => {
|
||||||
implicit val p: Parameters = GetSystemParameters(system)
|
implicit val p: Parameters = GetSystemParameters(system)
|
||||||
ports.map { b => SimBlockDevice.connect(b.clock, th.harnessReset.asBool, Some(b.bits)) }
|
ports.map { b => SimBlockDevice.connect(b.clock, th.harnessReset.asBool, Some(b.bits)) }
|
||||||
Nil
|
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
@@ -100,7 +103,6 @@ class WithBlockDeviceModel extends OverrideHarnessBinder({
|
|||||||
(system: CanHavePeripheryBlockDevice, th: HasHarnessSignalReferences, ports: Seq[ClockedIO[BlockDeviceIO]]) => {
|
(system: CanHavePeripheryBlockDevice, th: HasHarnessSignalReferences, ports: Seq[ClockedIO[BlockDeviceIO]]) => {
|
||||||
implicit val p: Parameters = GetSystemParameters(system)
|
implicit val p: Parameters = GetSystemParameters(system)
|
||||||
ports.map { b => withClockAndReset(b.clock, th.harnessReset) { BlockDeviceModel.connect(Some(b.bits)) } }
|
ports.map { b => withClockAndReset(b.clock, th.harnessReset) { BlockDeviceModel.connect(Some(b.bits)) } }
|
||||||
Nil
|
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
@@ -112,15 +114,13 @@ class WithLoopbackNIC extends OverrideHarnessBinder({
|
|||||||
NicLoopback.connect(Some(n.bits), p(NICKey))
|
NicLoopback.connect(Some(n.bits), p(NICKey))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Nil
|
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
class WithSimNetwork extends OverrideHarnessBinder({
|
class WithSimNetwork extends OverrideHarnessBinder({
|
||||||
(system: CanHavePeripheryIceNIC, th: HasHarnessSignalReferences, ports: Seq[ClockedIO[NICIOvonly]]) => {
|
(system: CanHavePeripheryIceNIC, th: BaseModule with HasHarnessSignalReferences, ports: Seq[ClockedIO[NICIOvonly]]) => {
|
||||||
implicit val p: Parameters = GetSystemParameters(system)
|
implicit val p: Parameters = GetSystemParameters(system)
|
||||||
ports.map { n => SimNetwork.connect(Some(n.bits), n.clock, th.harnessReset.asBool) }
|
ports.map { n => SimNetwork.connect(Some(n.bits), n.clock, th.harnessReset.asBool) }
|
||||||
Nil
|
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
@@ -134,7 +134,6 @@ class WithSimAXIMem extends OverrideHarnessBinder({
|
|||||||
}
|
}
|
||||||
mem.io_axi4.head <> port.bits
|
mem.io_axi4.head <> port.bits
|
||||||
}
|
}
|
||||||
Nil
|
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
@@ -149,7 +148,6 @@ class WithBlackBoxSimMem extends OverrideHarnessBinder({
|
|||||||
mem.io.clock := port.clock
|
mem.io.clock := port.clock
|
||||||
mem.io.reset := port.reset
|
mem.io.reset := port.reset
|
||||||
}
|
}
|
||||||
Nil
|
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
@@ -163,42 +161,39 @@ class WithSimAXIMMIO extends OverrideHarnessBinder({
|
|||||||
}
|
}
|
||||||
mmio_mem.io_axi4.head <> port.bits
|
mmio_mem.io_axi4.head <> port.bits
|
||||||
}
|
}
|
||||||
Nil
|
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
class WithTieOffInterrupts extends OverrideHarnessBinder({
|
class WithTieOffInterrupts extends OverrideHarnessBinder({
|
||||||
(system: HasExtInterruptsModuleImp, th: HasHarnessSignalReferences, ports: Seq[UInt]) => {
|
(system: HasExtInterruptsModuleImp, th: HasHarnessSignalReferences, ports: Seq[UInt]) => {
|
||||||
ports.foreach { _ := 0.U }
|
ports.foreach { _ := 0.U }
|
||||||
Nil
|
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
class WithTieOffL2FBusAXI extends OverrideHarnessBinder({
|
class WithTieOffL2FBusAXI extends OverrideHarnessBinder({
|
||||||
(system: CanHaveSlaveAXI4Port, th: HasHarnessSignalReferences, ports: Seq[ClockedIO[AXI4Bundle]]) => {
|
(system: CanHaveSlaveAXI4Port, th: HasHarnessSignalReferences, ports: Seq[ClockedIO[AXI4Bundle]]) => {
|
||||||
ports.foreach({ p => p := DontCare; p.bits.tieoff() })
|
ports.foreach({ p => p := DontCare; p.bits.tieoff() })
|
||||||
Nil
|
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
class WithSimDebug extends OverrideHarnessBinder({
|
class WithSimDebug extends OverrideHarnessBinder({
|
||||||
(system: HasPeripheryDebugModuleImp, th: HasHarnessSignalReferences, ports: Seq[Data]) => {
|
(system: HasPeripheryDebug, th: HasHarnessSignalReferences, ports: Seq[Data]) => {
|
||||||
|
implicit val p: Parameters = GetSystemParameters(system)
|
||||||
ports.map {
|
ports.map {
|
||||||
case d: ClockedDMIIO =>
|
case d: ClockedDMIIO =>
|
||||||
val dtm_success = WireInit(false.B)
|
val dtm_success = WireInit(false.B)
|
||||||
when (dtm_success) { th.success := true.B }
|
when (dtm_success) { th.success := true.B }
|
||||||
val dtm = Module(new SimDTM()(system.p)).connect(th.harnessClock, th.harnessReset.asBool, d, dtm_success)
|
val dtm = Module(new SimDTM).connect(th.harnessClock, th.harnessReset.asBool, d, dtm_success)
|
||||||
case j: JTAGIO =>
|
case j: JTAGIO =>
|
||||||
val dtm_success = WireInit(false.B)
|
val dtm_success = WireInit(false.B)
|
||||||
when (dtm_success) { th.success := true.B }
|
when (dtm_success) { th.success := true.B }
|
||||||
val jtag = Module(new SimJTAG(tickDelay=3)).connect(j, th.harnessClock, th.harnessReset.asBool, ~(th.harnessReset.asBool), dtm_success)
|
val jtag = Module(new SimJTAG(tickDelay=3)).connect(j, th.harnessClock, th.harnessReset.asBool, ~(th.harnessReset.asBool), dtm_success)
|
||||||
}
|
}
|
||||||
Nil
|
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
class WithTiedOffDebug extends OverrideHarnessBinder({
|
class WithTiedOffDebug extends OverrideHarnessBinder({
|
||||||
(system: HasPeripheryDebugModuleImp, th: HasHarnessSignalReferences, ports: Seq[Data]) => {
|
(system: HasPeripheryDebug, th: HasHarnessSignalReferences, ports: Seq[Data]) => {
|
||||||
ports.map {
|
ports.map {
|
||||||
case j: JTAGIO =>
|
case j: JTAGIO =>
|
||||||
j.TCK := true.B.asClock
|
j.TCK := true.B.asClock
|
||||||
@@ -218,7 +213,6 @@ class WithTiedOffDebug extends OverrideHarnessBinder({
|
|||||||
a.psel := false.B
|
a.psel := false.B
|
||||||
a.penable := false.B
|
a.penable := false.B
|
||||||
}
|
}
|
||||||
Nil
|
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
@@ -247,13 +241,11 @@ class WithSimSerial extends OverrideHarnessBinder({
|
|||||||
class WithTraceGenSuccess extends OverrideHarnessBinder({
|
class WithTraceGenSuccess extends OverrideHarnessBinder({
|
||||||
(system: TraceGenSystemModuleImp, th: HasHarnessSignalReferences, ports: Seq[Bool]) => {
|
(system: TraceGenSystemModuleImp, th: HasHarnessSignalReferences, ports: Seq[Bool]) => {
|
||||||
ports.map { p => when (p) { th.success := true.B } }
|
ports.map { p => when (p) { th.success := true.B } }
|
||||||
Nil
|
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
class WithSimDromajoBridge extends ComposeHarnessBinder({
|
class WithSimDromajoBridge extends ComposeHarnessBinder({
|
||||||
(system: CanHaveTraceIOModuleImp, th: HasHarnessSignalReferences, ports: Seq[TraceOutputTop]) => {
|
(system: CanHaveTraceIOModuleImp, th: HasHarnessSignalReferences, ports: Seq[TraceOutputTop]) => {
|
||||||
ports.map { p => p.traces.map(tileTrace => SimDromajoBridge(tileTrace)(system.p)) }
|
ports.map { p => p.traces.map(tileTrace => SimDromajoBridge(tileTrace)(system.p)) }
|
||||||
Nil
|
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -1,17 +1,17 @@
|
|||||||
package chipyard.iobinders
|
package chipyard.iobinders
|
||||||
|
|
||||||
import chisel3._
|
import chisel3._
|
||||||
import chisel3.util.experimental.{BoringUtils}
|
|
||||||
import chisel3.experimental.{Analog, IO, DataMirror}
|
import chisel3.experimental.{Analog, IO, DataMirror}
|
||||||
|
|
||||||
import freechips.rocketchip.config._
|
import freechips.rocketchip.config._
|
||||||
import freechips.rocketchip.diplomacy.{LazyModule, LazyModuleImpLike}
|
import freechips.rocketchip.diplomacy._
|
||||||
import freechips.rocketchip.devices.debug._
|
import freechips.rocketchip.devices.debug._
|
||||||
import freechips.rocketchip.jtag.{JTAGIO}
|
import freechips.rocketchip.jtag.{JTAGIO}
|
||||||
import freechips.rocketchip.subsystem._
|
import freechips.rocketchip.subsystem._
|
||||||
import freechips.rocketchip.system.{SimAXIMem}
|
import freechips.rocketchip.system.{SimAXIMem}
|
||||||
import freechips.rocketchip.amba.axi4.{AXI4Bundle, AXI4SlaveNode, AXI4MasterNode, AXI4EdgeParameters}
|
import freechips.rocketchip.amba.axi4.{AXI4Bundle, AXI4SlaveNode, AXI4MasterNode, AXI4EdgeParameters}
|
||||||
import freechips.rocketchip.util._
|
import freechips.rocketchip.util._
|
||||||
|
import freechips.rocketchip.prci.{ClockSinkNode, ClockSinkParameters}
|
||||||
import freechips.rocketchip.groundtest.{GroundTestSubsystemModuleImp, GroundTestSubsystem}
|
import freechips.rocketchip.groundtest.{GroundTestSubsystemModuleImp, GroundTestSubsystem}
|
||||||
|
|
||||||
import sifive.blocks.devices.gpio._
|
import sifive.blocks.devices.gpio._
|
||||||
@@ -24,10 +24,14 @@ import barstools.iocell.chisel._
|
|||||||
import testchipip._
|
import testchipip._
|
||||||
import icenet.{CanHavePeripheryIceNIC, SimNetwork, NicLoopback, NICKey, NICIOvonly}
|
import icenet.{CanHavePeripheryIceNIC, SimNetwork, NicLoopback, NICKey, NICIOvonly}
|
||||||
|
|
||||||
import chipyard.GlobalResetSchemeKey
|
|
||||||
|
|
||||||
import scala.reflect.{ClassTag}
|
import scala.reflect.{ClassTag}
|
||||||
|
|
||||||
|
object IOBinderTypes {
|
||||||
|
type IOBinderTuple = (Seq[Data], Seq[IOCell])
|
||||||
|
type IOBinderFunction = (Boolean, => Any) => ModuleValue[IOBinderTuple]
|
||||||
|
}
|
||||||
|
import IOBinderTypes._
|
||||||
|
|
||||||
// System for instantiating binders based
|
// System for instantiating binders based
|
||||||
// on the scala type of the Target (_not_ its IO). This avoids needing to
|
// on the scala type of the Target (_not_ its IO). This avoids needing to
|
||||||
// duplicate harnesses (essentially test harnesses) for each target.
|
// duplicate harnesses (essentially test harnesses) for each target.
|
||||||
@@ -40,21 +44,30 @@ import scala.reflect.{ClassTag}
|
|||||||
|
|
||||||
// You can add your own binder by adding a new (key, fn) pair, typically by using
|
// You can add your own binder by adding a new (key, fn) pair, typically by using
|
||||||
// the OverrideIOBinder or ComposeIOBinder macros
|
// the OverrideIOBinder or ComposeIOBinder macros
|
||||||
case object IOBinders extends Field[Map[String, (Any) => (Seq[Data], Seq[IOCell])]](
|
case object IOBinders extends Field[Map[String, Seq[IOBinderFunction]]](
|
||||||
Map[String, (Any) => (Seq[Data], Seq[IOCell])]().withDefaultValue((Any) => (Nil, Nil))
|
Map[String, Seq[IOBinderFunction]]().withDefaultValue(Nil)
|
||||||
)
|
)
|
||||||
object ApplyIOBinders {
|
|
||||||
def apply(sys: LazyModule, map: Map[String, (Any) => (Seq[Data], Seq[IOCell])]):
|
|
||||||
(Iterable[Data], Iterable[IOCell], Map[String, Seq[Data]]) = {
|
|
||||||
val lzy = map.map({ case (s,f) => s -> f(sys) })
|
|
||||||
val imp = map.map({ case (s,f) => s -> f(sys.module) })
|
|
||||||
val unzipped = (lzy.values ++ imp.values).unzip
|
|
||||||
|
|
||||||
val ports: Iterable[Data] = unzipped._1.flatten
|
abstract trait HasIOBinders { this: LazyModule =>
|
||||||
val cells: Iterable[IOCell] = unzipped._2.flatten
|
val lazySystem: LazyModule
|
||||||
val portMap: Map[String, Seq[Data]] = map.keys.map(k => k -> (lzy(k)._1 ++ imp(k)._1)).toMap
|
private val iobinders = p(IOBinders)
|
||||||
(ports, cells, portMap)
|
// Note: IOBinders cannot rely on the implicit clock/reset, as they may be called from the
|
||||||
}
|
// context of a LazyRawModuleImp
|
||||||
|
private val lzy = iobinders.map({ case (s,fns) => s -> fns.map(f => f(true, lazySystem)) })
|
||||||
|
private val imp = iobinders.map({ case (s,fns) => s -> fns.map(f => f(false, lazySystem.module)) })
|
||||||
|
|
||||||
|
private lazy val lzyFlattened: Map[String, IOBinderTuple] = lzy.map({
|
||||||
|
case (s,ms) => s -> (ms.map(_._1).flatten, ms.map(_._2).flatten)
|
||||||
|
})
|
||||||
|
private lazy val impFlattened: Map[String, IOBinderTuple] = imp.map({
|
||||||
|
case (s,ms) => s -> (ms.map(_._1).flatten, ms.map(_._2).flatten)
|
||||||
|
})
|
||||||
|
|
||||||
|
// A publicly accessible list of IO cells (useful for a floorplanning tool, for example)
|
||||||
|
lazy val iocells = (lzyFlattened.values ++ impFlattened.values).unzip._2.flatten.toBuffer
|
||||||
|
|
||||||
|
// A mapping between stringified DigitalSystem traits and their corresponding ChipTop ports
|
||||||
|
lazy val portMap = iobinders.keys.map(k => k -> (lzyFlattened(k)._1 ++ impFlattened(k)._1)).toMap
|
||||||
}
|
}
|
||||||
|
|
||||||
// Note: The parameters instance is accessible only through LazyModule
|
// Note: The parameters instance is accessible only through LazyModule
|
||||||
@@ -72,63 +85,45 @@ object GetSystemParameters {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class IOBinder(f: (View, View, View) => PartialFunction[Any, Any]) extends Config(f)
|
class IOBinder[T](composer: Seq[IOBinderFunction] => Seq[IOBinderFunction])(implicit tag: ClassTag[T]) extends Config((site, here, up) => {
|
||||||
|
case IOBinders => up(IOBinders, site) + (tag.runtimeClass.toString -> composer(up(IOBinders, site)(tag.runtimeClass.toString)))
|
||||||
// This macro overrides previous matches on some Top mixin. This is useful for
|
|
||||||
// binders which drive IO, since those typically cannot be composed
|
|
||||||
class OverrideIOBinder[T, S <: Data](fn: => (T) => (Seq[S], Seq[IOCell]))(implicit tag: ClassTag[T]) extends IOBinder((site, here, up) => {
|
|
||||||
case IOBinders => up(IOBinders, site) + (tag.runtimeClass.toString ->
|
|
||||||
((t: Any) => {
|
|
||||||
t match {
|
|
||||||
case system: T =>
|
|
||||||
val (ports, cells) = fn(system)
|
|
||||||
(ports, cells)
|
|
||||||
case _ => (Nil, Nil)
|
|
||||||
}
|
|
||||||
})
|
|
||||||
)
|
|
||||||
})
|
})
|
||||||
|
|
||||||
// This macro composes with previous matches on some Top mixin. This is useful for
|
class ConcreteIOBinder[T](composes: Boolean, fn: T => IOBinderTuple)(implicit tag: ClassTag[T]) extends IOBinder[T](
|
||||||
// annotation-like binders, since those can typically be composed
|
up => (if (composes) up else Nil) ++ Seq(((_, t) => { InModuleBody {
|
||||||
class ComposeIOBinder[T, S <: Data](fn: => (T) => (Seq[S], Seq[IOCell]))(implicit tag: ClassTag[T]) extends IOBinder((site, here, up) => {
|
t match {
|
||||||
case IOBinders => up(IOBinders, site) + (tag.runtimeClass.toString ->
|
case system: T => fn(system)
|
||||||
((t: Any) => {
|
case _ => (Nil, Nil)
|
||||||
t match {
|
|
||||||
case system: T =>
|
|
||||||
val r = up(IOBinders, site)(tag.runtimeClass.toString)(system)
|
|
||||||
val h = fn(system)
|
|
||||||
val ports = r._1 ++ h._1
|
|
||||||
val cells = r._2 ++ h._2
|
|
||||||
(ports, cells)
|
|
||||||
case _ => (Nil, Nil)
|
|
||||||
}
|
|
||||||
})
|
|
||||||
)
|
|
||||||
})
|
|
||||||
|
|
||||||
object BoreHelper {
|
|
||||||
def apply[T <: Data](name: String, source: T): T = {
|
|
||||||
val (io, wire) = source match {
|
|
||||||
case c: Clock =>
|
|
||||||
val wire = Wire(Clock())
|
|
||||||
// Provide a dummy assignment to prevent FIRRTL invalid assignment
|
|
||||||
// errors prior to running the wiring pass
|
|
||||||
wire := false.B.asClock
|
|
||||||
(IO(Output(Clock())), wire)
|
|
||||||
case r: Reset =>
|
|
||||||
val wire = Wire(Reset())
|
|
||||||
wire := false.B
|
|
||||||
(IO(Output(Reset())), wire)
|
|
||||||
}
|
}
|
||||||
io.suggestName(name)
|
}}): IOBinderFunction)
|
||||||
wire.suggestName(s"chiptop_${name}")
|
)
|
||||||
dontTouch(wire)
|
|
||||||
BoringUtils.bore(source, Seq(wire))
|
class LazyIOBinder[T](composes: Boolean, fn: T => ModuleValue[IOBinderTuple])(implicit tag: ClassTag[T]) extends IOBinder[T](
|
||||||
io := wire
|
up => (if (composes) up else Nil) ++ Seq(((isLazy, t) => {
|
||||||
io.asInstanceOf[source.type]
|
val empty = new ModuleValue[IOBinderTuple] {
|
||||||
}
|
def getWrappedValue: IOBinderTuple = (Nil, Nil)
|
||||||
}
|
}
|
||||||
|
if (isLazy) {
|
||||||
|
t match {
|
||||||
|
case system: T => fn(system)
|
||||||
|
case _ => empty
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
empty
|
||||||
|
}
|
||||||
|
}): IOBinderFunction)
|
||||||
|
)
|
||||||
|
|
||||||
|
// The "Override" binders override any previous IOBinders (lazy or concrete) defined on the same trait.
|
||||||
|
// The "Compose" binders do not override previously defined IOBinders on the same trait
|
||||||
|
// The default IOBinders evaluate only in the concrete "ModuleImp" phase of elaboration
|
||||||
|
// The "Lazy" IOBinders evaluate in the LazyModule phase, but can also generate hardware through InModuleBody
|
||||||
|
|
||||||
|
class OverrideIOBinder[T](fn: T => IOBinderTuple)(implicit tag: ClassTag[T]) extends ConcreteIOBinder[T](false, fn)
|
||||||
|
class ComposeIOBinder[T](fn: T => IOBinderTuple)(implicit tag: ClassTag[T]) extends ConcreteIOBinder[T](true, fn)
|
||||||
|
|
||||||
|
class OverrideLazyIOBinder[T](fn: T => ModuleValue[IOBinderTuple])(implicit tag: ClassTag[T]) extends LazyIOBinder[T](false, fn)
|
||||||
|
class ComposeLazyIOBinder[T](fn: T => ModuleValue[IOBinderTuple])(implicit tag: ClassTag[T]) extends LazyIOBinder[T](true, fn)
|
||||||
|
|
||||||
|
|
||||||
case object IOCellKey extends Field[IOCellTypeParams](GenericIOCellParams())
|
case object IOCellKey extends Field[IOCellTypeParams](GenericIOCellParams())
|
||||||
@@ -157,7 +152,7 @@ class WithGPIOCells extends OverrideIOBinder({
|
|||||||
class WithUARTIOCells extends OverrideIOBinder({
|
class WithUARTIOCells extends OverrideIOBinder({
|
||||||
(system: HasPeripheryUARTModuleImp) => {
|
(system: HasPeripheryUARTModuleImp) => {
|
||||||
val (ports: Seq[UARTPortIO], cells2d) = system.uart.zipWithIndex.map({ case (u, i) =>
|
val (ports: Seq[UARTPortIO], cells2d) = system.uart.zipWithIndex.map({ case (u, i) =>
|
||||||
val (port, ios) = IOCell.generateIOFromSignal(u, s"uart_${i}", system.p(IOCellKey))
|
val (port, ios) = IOCell.generateIOFromSignal(u, s"uart_${i}", system.p(IOCellKey), abstractResetAsAsync = true)
|
||||||
(port, ios)
|
(port, ios)
|
||||||
}).unzip
|
}).unzip
|
||||||
(ports, cells2d.flatten)
|
(ports, cells2d.flatten)
|
||||||
@@ -173,8 +168,8 @@ class WithSPIIOCells extends OverrideIOBinder({
|
|||||||
val iocellBase = s"iocell_${name}"
|
val iocellBase = s"iocell_${name}"
|
||||||
|
|
||||||
// SCK and CS are unidirectional outputs
|
// SCK and CS are unidirectional outputs
|
||||||
val sckIOs = IOCell.generateFromSignal(s.sck, port.sck, Some(s"${iocellBase}_sck"), system.p(IOCellKey))
|
val sckIOs = IOCell.generateFromSignal(s.sck, port.sck, Some(s"${iocellBase}_sck"), system.p(IOCellKey), IOCell.toAsyncReset)
|
||||||
val csIOs = IOCell.generateFromSignal(s.cs, port.cs, Some(s"${iocellBase}_cs"), system.p(IOCellKey))
|
val csIOs = IOCell.generateFromSignal(s.cs, port.cs, Some(s"${iocellBase}_cs"), system.p(IOCellKey), IOCell.toAsyncReset)
|
||||||
|
|
||||||
// DQ are bidirectional, so then need special treatment
|
// DQ are bidirectional, so then need special treatment
|
||||||
val dqIOs = s.dq.zip(port.dq).zipWithIndex.map { case ((pin, ana), j) =>
|
val dqIOs = s.dq.zip(port.dq).zipWithIndex.map { case ((pin, ana), j) =>
|
||||||
@@ -196,7 +191,7 @@ class WithSPIIOCells extends OverrideIOBinder({
|
|||||||
class WithExtInterruptIOCells extends OverrideIOBinder({
|
class WithExtInterruptIOCells extends OverrideIOBinder({
|
||||||
(system: HasExtInterruptsModuleImp) => {
|
(system: HasExtInterruptsModuleImp) => {
|
||||||
if (system.outer.nExtInterrupts > 0) {
|
if (system.outer.nExtInterrupts > 0) {
|
||||||
val (port: UInt, cells) = IOCell.generateIOFromSignal(system.interrupts, "ext_interrupts", system.p(IOCellKey))
|
val (port: UInt, cells) = IOCell.generateIOFromSignal(system.interrupts, "ext_interrupts", system.p(IOCellKey), abstractResetAsAsync = true)
|
||||||
(Seq(port), cells)
|
(Seq(port), cells)
|
||||||
} else {
|
} else {
|
||||||
(Nil, Nil)
|
(Nil, Nil)
|
||||||
@@ -205,104 +200,123 @@ class WithExtInterruptIOCells extends OverrideIOBinder({
|
|||||||
})
|
})
|
||||||
|
|
||||||
|
|
||||||
class WithDebugIOCells extends OverrideIOBinder({
|
class WithDebugIOCells extends OverrideLazyIOBinder({
|
||||||
(system: HasPeripheryDebugModuleImp) => {
|
(system: HasPeripheryDebug) => {
|
||||||
system.debug.map({ debug =>
|
implicit val p = GetSystemParameters(system)
|
||||||
val p = system.p
|
val tlbus = system.asInstanceOf[BaseSubsystem].locateTLBusWrapper(p(ExportDebug).slaveWhere)
|
||||||
val tlbus = system.outer.asInstanceOf[BaseSubsystem].locateTLBusWrapper(p(ExportDebug).slaveWhere)
|
val clockSinkNode = system.debugOpt.map(_ => ClockSinkNode(Seq(ClockSinkParameters())))
|
||||||
val debug_clock = Wire(Clock()).suggestName("debug_clock")
|
clockSinkNode.map(_ := tlbus.fixedClockNode)
|
||||||
val debug_reset = Wire(Reset()).suggestName("debug_reset")
|
def clockBundle = clockSinkNode.get.in.head._1
|
||||||
debug_clock := false.B.asClock // must provide default assignment to avoid firrtl unassigned error
|
|
||||||
debug_reset := false.B // must provide default assignment to avoid firrtl unassigned error
|
|
||||||
BoringUtils.bore(tlbus.module.clock, Seq(debug_clock))
|
|
||||||
BoringUtils.bore(tlbus.module.reset, Seq(debug_reset))
|
|
||||||
|
|
||||||
// We never use the PSDIO, so tie it off on-chip
|
|
||||||
system.psd.psd.foreach { _ <> 0.U.asTypeOf(new PSDTestMode) }
|
InModuleBody { system.asInstanceOf[BaseSubsystem].module match { case system: HasPeripheryDebugModuleImp => {
|
||||||
system.resetctrl.map { rcio => rcio.hartIsInReset.map { _ := debug_reset.asBool } }
|
system.debug.map({ debug =>
|
||||||
system.debug.map { d =>
|
// We never use the PSDIO, so tie it off on-chip
|
||||||
// Tie off extTrigger
|
system.psd.psd.foreach { _ <> 0.U.asTypeOf(new PSDTestMode) }
|
||||||
d.extTrigger.foreach { t =>
|
system.resetctrl.map { rcio => rcio.hartIsInReset.map { _ := clockBundle.reset.asBool } }
|
||||||
t.in.req := false.B
|
system.debug.map { d =>
|
||||||
t.out.ack := t.out.req
|
// Tie off extTrigger
|
||||||
|
d.extTrigger.foreach { t =>
|
||||||
|
t.in.req := false.B
|
||||||
|
t.out.ack := t.out.req
|
||||||
|
}
|
||||||
|
// Tie off disableDebug
|
||||||
|
d.disableDebug.foreach { d => d := false.B }
|
||||||
|
// Drive JTAG on-chip IOs
|
||||||
|
d.systemjtag.map { j =>
|
||||||
|
j.reset := clockBundle.reset
|
||||||
|
j.mfr_id := p(JtagDTMKey).idcodeManufId.U(11.W)
|
||||||
|
j.part_number := p(JtagDTMKey).idcodePartNum.U(16.W)
|
||||||
|
j.version := p(JtagDTMKey).idcodeVersion.U(4.W)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
// Tie off disableDebug
|
Debug.connectDebugClockAndReset(Some(debug), clockBundle.clock)
|
||||||
d.disableDebug.foreach { d => d := false.B }
|
|
||||||
// Drive JTAG on-chip IOs
|
// Add IOCells for the DMI/JTAG/APB ports
|
||||||
d.systemjtag.map { j =>
|
val dmiTuple = debug.clockeddmi.map { d =>
|
||||||
j.reset := debug_reset
|
IOCell.generateIOFromSignal(d, "dmi", p(IOCellKey), abstractResetAsAsync = true)
|
||||||
j.mfr_id := system.p(JtagDTMKey).idcodeManufId.U(11.W)
|
|
||||||
j.part_number := system.p(JtagDTMKey).idcodePartNum.U(16.W)
|
|
||||||
j.version := system.p(JtagDTMKey).idcodeVersion.U(4.W)
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
Debug.connectDebugClockAndReset(Some(debug), debug_clock)(system.p)
|
|
||||||
|
|
||||||
// Add IOCells for the DMI/JTAG/APB ports
|
val jtagTuple = debug.systemjtag.map { j =>
|
||||||
val dmiTuple = debug.clockeddmi.map { d =>
|
IOCell.generateIOFromSignal(j.jtag, "jtag", p(IOCellKey), abstractResetAsAsync = true)
|
||||||
IOCell.generateIOFromSignal(d, "dmi", p(IOCellKey), abstractResetAsAsync = p(GlobalResetSchemeKey).pinIsAsync)
|
}
|
||||||
}
|
|
||||||
|
|
||||||
val jtagTuple = debug.systemjtag.map { j =>
|
val apbTuple = debug.apb.map { a =>
|
||||||
IOCell.generateIOFromSignal(j.jtag, "jtag", p(IOCellKey), abstractResetAsAsync = p(GlobalResetSchemeKey).pinIsAsync)
|
IOCell.generateIOFromSignal(a, "apb", p(IOCellKey), abstractResetAsAsync = true)
|
||||||
}
|
}
|
||||||
|
|
||||||
val apbTuple = debug.apb.map { a =>
|
val allTuples = (dmiTuple ++ jtagTuple ++ apbTuple).toSeq
|
||||||
IOCell.generateIOFromSignal(a, "apb", p(IOCellKey), abstractResetAsAsync = p(GlobalResetSchemeKey).pinIsAsync)
|
(allTuples.map(_._1).toSeq, allTuples.flatMap(_._2).toSeq)
|
||||||
}
|
}).getOrElse((Nil, Nil))
|
||||||
|
}}}
|
||||||
val allTuples = (dmiTuple ++ jtagTuple ++ apbTuple).toSeq
|
|
||||||
(allTuples.map(_._1).toSeq, allTuples.flatMap(_._2).toSeq)
|
|
||||||
}).getOrElse((Nil, Nil))
|
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
class WithSerialTLIOCells extends OverrideIOBinder({
|
class WithSerialTLIOCells extends OverrideIOBinder({
|
||||||
(system: CanHavePeripheryTLSerial) => system.serial_tl.map({ s =>
|
(system: CanHavePeripheryTLSerial) => system.serial_tl.map({ s =>
|
||||||
val sys = system.asInstanceOf[BaseSubsystem]
|
val sys = system.asInstanceOf[BaseSubsystem]
|
||||||
val (port, cells) = IOCell.generateIOFromSignal(s.getWrappedValue, "serial_tl", sys.p(IOCellKey))
|
val (port, cells) = IOCell.generateIOFromSignal(s.getWrappedValue, "serial_tl", sys.p(IOCellKey), abstractResetAsAsync = true)
|
||||||
(Seq(port), cells)
|
(Seq(port), cells)
|
||||||
}).getOrElse((Nil, Nil))
|
}).getOrElse((Nil, Nil))
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|
||||||
class WithAXI4MemPunchthrough extends OverrideIOBinder({
|
class WithAXI4MemPunchthrough extends OverrideLazyIOBinder({
|
||||||
(system: CanHaveMasterAXI4MemPort) => {
|
(system: CanHaveMasterAXI4MemPort) => {
|
||||||
val ports: Seq[ClockedAndResetIO[AXI4Bundle]] = system.mem_axi4.zipWithIndex.map({ case (m, i) =>
|
implicit val p: Parameters = GetSystemParameters(system)
|
||||||
val p = IO(new ClockedAndResetIO(DataMirror.internal.chiselTypeClone[AXI4Bundle](m))).suggestName(s"axi4_mem_${i}")
|
val clockSinkNode = p(ExtMem).map(_ => ClockSinkNode(Seq(ClockSinkParameters())))
|
||||||
p.bits <> m
|
clockSinkNode.map(_ := system.asInstanceOf[HasTileLinkLocations].locateTLBusWrapper(MBUS).fixedClockNode)
|
||||||
val mbus = system.asInstanceOf[HasTileLinkLocations].locateTLBusWrapper(MBUS)
|
def clockBundle = clockSinkNode.get.in.head._1
|
||||||
p.clock := BoreHelper("axi4_mem_clock", mbus.module.clock)
|
|
||||||
p.reset := BoreHelper("axi4_mem_reset", mbus.module.reset)
|
InModuleBody {
|
||||||
p
|
val ports: Seq[ClockedAndResetIO[AXI4Bundle]] = system.mem_axi4.zipWithIndex.map({ case (m, i) =>
|
||||||
})
|
val p = IO(new ClockedAndResetIO(DataMirror.internal.chiselTypeClone[AXI4Bundle](m))).suggestName(s"axi4_mem_${i}")
|
||||||
(ports, Nil)
|
p.bits <> m
|
||||||
|
p.clock := clockBundle.clock
|
||||||
|
p.reset := clockBundle.reset
|
||||||
|
p
|
||||||
|
})
|
||||||
|
(ports, Nil)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
class WithAXI4MMIOPunchthrough extends OverrideIOBinder({
|
class WithAXI4MMIOPunchthrough extends OverrideLazyIOBinder({
|
||||||
(system: CanHaveMasterAXI4MMIOPort) => {
|
(system: CanHaveMasterAXI4MMIOPort) => {
|
||||||
val ports: Seq[ClockedAndResetIO[AXI4Bundle]] = system.mmio_axi4.zipWithIndex.map({ case (m, i) =>
|
implicit val p: Parameters = GetSystemParameters(system)
|
||||||
val p = IO(new ClockedAndResetIO(DataMirror.internal.chiselTypeClone[AXI4Bundle](m))).suggestName(s"axi4_mmio_${i}")
|
val clockSinkNode = p(ExtBus).map(_ => ClockSinkNode(Seq(ClockSinkParameters())))
|
||||||
p.bits <> m
|
clockSinkNode.map(_ := system.asInstanceOf[HasTileLinkLocations].locateTLBusWrapper(MBUS).fixedClockNode)
|
||||||
val mbus = system.asInstanceOf[HasTileLinkLocations].locateTLBusWrapper(MBUS)
|
def clockBundle = clockSinkNode.get.in.head._1
|
||||||
p.clock := BoreHelper("axi4_mmio_clock", mbus.module.clock)
|
|
||||||
p.reset := BoreHelper("axi4_mmio_reset", mbus.module.reset)
|
InModuleBody {
|
||||||
p
|
val ports: Seq[ClockedAndResetIO[AXI4Bundle]] = system.mmio_axi4.zipWithIndex.map({ case (m, i) =>
|
||||||
})
|
val p = IO(new ClockedAndResetIO(DataMirror.internal.chiselTypeClone[AXI4Bundle](m))).suggestName(s"axi4_mmio_${i}")
|
||||||
(ports, Nil)
|
p.bits <> m
|
||||||
|
p.clock := clockBundle.clock
|
||||||
|
p.reset := clockBundle.reset
|
||||||
|
p
|
||||||
|
})
|
||||||
|
(ports, Nil)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
class WithL2FBusAXI4Punchthrough extends OverrideIOBinder({
|
class WithL2FBusAXI4Punchthrough extends OverrideLazyIOBinder({
|
||||||
(system: CanHaveSlaveAXI4Port) => {
|
(system: CanHaveSlaveAXI4Port) => {
|
||||||
val ports: Seq[ClockedIO[AXI4Bundle]] = system.l2_frontend_bus_axi4.zipWithIndex.map({ case (m, i) =>
|
implicit val p: Parameters = GetSystemParameters(system)
|
||||||
val p = IO(new ClockedIO(Flipped(DataMirror.internal.chiselTypeClone[AXI4Bundle](m)))).suggestName(s"axi4_fbus_${i}")
|
val clockSinkNode = p(ExtIn).map(_ => ClockSinkNode(Seq(ClockSinkParameters())))
|
||||||
m <> p.bits
|
clockSinkNode.map(_ := system.asInstanceOf[BaseSubsystem].fbus.fixedClockNode)
|
||||||
p.clock := BoreHelper("axi4_fbus_clock", system.asInstanceOf[BaseSubsystem].fbus.module.clock)
|
def clockBundle = clockSinkNode.get.in.head._1
|
||||||
p
|
|
||||||
})
|
InModuleBody {
|
||||||
(ports, Nil)
|
val ports: Seq[ClockedIO[AXI4Bundle]] = system.l2_frontend_bus_axi4.zipWithIndex.map({ case (m, i) =>
|
||||||
|
val p = IO(new ClockedIO(Flipped(DataMirror.internal.chiselTypeClone[AXI4Bundle](m)))).suggestName(s"axi4_fbus_${i}")
|
||||||
|
m <> p.bits
|
||||||
|
p.clock := clockBundle.clock
|
||||||
|
p
|
||||||
|
})
|
||||||
|
(ports, Nil)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|||||||
@@ -56,6 +56,23 @@ class ChipyardSubsystem(implicit p: Parameters) extends BaseSubsystem
|
|||||||
case b: BoomTile => b.module.core.coreMonitorBundle
|
case b: BoomTile => b.module.core.coreMonitorBundle
|
||||||
}.toList
|
}.toList
|
||||||
|
|
||||||
|
|
||||||
|
// Relying on [[TLBusWrapperConnection]].driveClockFromMaster for
|
||||||
|
// bus-couplings that are not asynchronous strips the bus name from the sink
|
||||||
|
// ClockGroup. This makes it impossible to determine which clocks are driven
|
||||||
|
// by which bus based on the member names, which is problematic when there is
|
||||||
|
// a rational crossing between two buses. Instead, provide all bus clocks
|
||||||
|
// directly from the asyncClockGroupsNode in the subsystem to ensure bus
|
||||||
|
// names are always preserved in the top-level clock names.
|
||||||
|
//
|
||||||
|
// For example, using a RationalCrossing between the Sbus and Cbus, and
|
||||||
|
// driveClockFromMaster = Some(true) results in all cbus-attached device and
|
||||||
|
// bus clocks to be given names of the form "subsystem_sbus_[0-9]*".
|
||||||
|
// Conversly, if an async crossing is used, they instead receive names of the
|
||||||
|
// form "subsystem_cbus_[0-9]*". The assignment below provides the latter names in all cases.
|
||||||
|
Seq(PBUS, FBUS, MBUS, CBUS).foreach { loc =>
|
||||||
|
tlBusWrapperLocationMap.lift(loc).foreach { _.clockGroupNode := asyncClockGroupsNode }
|
||||||
|
}
|
||||||
override lazy val module = new ChipyardSubsystemModuleImp(this)
|
override lazy val module = new ChipyardSubsystemModuleImp(this)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ import freechips.rocketchip.diplomacy.{LazyModule}
|
|||||||
import freechips.rocketchip.config.{Field, Parameters}
|
import freechips.rocketchip.config.{Field, Parameters}
|
||||||
|
|
||||||
import chipyard.harness.{ApplyHarnessBinders, HarnessBinders}
|
import chipyard.harness.{ApplyHarnessBinders, HarnessBinders}
|
||||||
|
import chipyard.iobinders.HasIOBinders
|
||||||
|
|
||||||
// -------------------------------
|
// -------------------------------
|
||||||
// Chipyard Test Harness
|
// Chipyard Test Harness
|
||||||
@@ -14,9 +15,7 @@ import chipyard.harness.{ApplyHarnessBinders, HarnessBinders}
|
|||||||
case object BuildTop extends Field[Parameters => LazyModule]((p: Parameters) => new ChipTop()(p))
|
case object BuildTop extends Field[Parameters => LazyModule]((p: Parameters) => new ChipTop()(p))
|
||||||
|
|
||||||
trait HasTestHarnessFunctions {
|
trait HasTestHarnessFunctions {
|
||||||
val lazySystem: LazyModule
|
|
||||||
val harnessFunctions = ArrayBuffer.empty[HasHarnessSignalReferences => Seq[Any]]
|
val harnessFunctions = ArrayBuffer.empty[HasHarnessSignalReferences => Seq[Any]]
|
||||||
val portMap = scala.collection.mutable.Map[String, Seq[Data]]()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
trait HasHarnessSignalReferences {
|
trait HasHarnessSignalReferences {
|
||||||
@@ -39,12 +38,13 @@ class TestHarness(implicit val p: Parameters) extends Module with HasHarnessSign
|
|||||||
val harnessReset = WireInit(reset)
|
val harnessReset = WireInit(reset)
|
||||||
val success = io.success
|
val success = io.success
|
||||||
|
|
||||||
// dutReset assignment can be overridden via a harnessFunction, but by default it is just reset
|
val dutReset = reset.asAsyncReset
|
||||||
val dutReset = WireDefault(if (p(GlobalResetSchemeKey).pinIsAsync) reset.asAsyncReset else reset)
|
|
||||||
|
|
||||||
lazyDut match { case d: HasTestHarnessFunctions =>
|
lazyDut match { case d: HasTestHarnessFunctions =>
|
||||||
d.harnessFunctions.foreach(_(this))
|
d.harnessFunctions.foreach(_(this))
|
||||||
ApplyHarnessBinders(this, d.lazySystem, p(HarnessBinders), d.portMap.toMap)
|
}
|
||||||
|
lazyDut match { case d: HasIOBinders =>
|
||||||
|
ApplyHarnessBinders(this, d.lazySystem, d.portMap)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -7,9 +7,6 @@ import freechips.rocketchip.tile.{XLen, TileParams}
|
|||||||
import freechips.rocketchip.config.{Parameters, Field, Config}
|
import freechips.rocketchip.config.{Parameters, Field, Config}
|
||||||
import freechips.rocketchip.system.{TestGeneration, RegressionTestSuite, RocketTestSuite}
|
import freechips.rocketchip.system.{TestGeneration, RegressionTestSuite, RocketTestSuite}
|
||||||
|
|
||||||
import boom.common.{BoomTileAttachParams}
|
|
||||||
import ariane.{ArianeTileAttachParams}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A set of pre-chosen regression tests
|
* A set of pre-chosen regression tests
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -14,20 +14,65 @@ import scala.collection.immutable.ListMap
|
|||||||
* TODO: figure out how much division is acceptable in our simulators and redefine this.
|
* TODO: figure out how much division is acceptable in our simulators and redefine this.
|
||||||
*/
|
*/
|
||||||
object FrequencyUtils {
|
object FrequencyUtils {
|
||||||
def computeReferenceFrequencyMHz(
|
/**
|
||||||
|
* Adds up the squared error between the generated clocks (refClock / [integer] divider)
|
||||||
|
* and the requested frequencies.
|
||||||
|
*
|
||||||
|
* @param refMHz The candidate reference clock
|
||||||
|
* @param desiredFreqMHz A list of the requested output frequencies
|
||||||
|
*/
|
||||||
|
def squaredError(refMHz: Double, desiredFreqMHz: List[Double], sum: Double = 0.0): Double = desiredFreqMHz match {
|
||||||
|
case Nil => sum
|
||||||
|
case desired :: xs =>
|
||||||
|
val divider = Math.round(refMHz / desired)
|
||||||
|
val termError = ((refMHz / divider) - desired) / desired
|
||||||
|
squaredError(refMHz, xs, sum + termError * termError)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Picks a candidate reference frequency by doing a brute-force search over
|
||||||
|
* multiples of the fastest requested clock. Choose the smallest multiple that
|
||||||
|
* has an RMS error (across all output frequencies) that is:
|
||||||
|
* 1) zero or failing that,
|
||||||
|
* 2) is within the relativeThreshold of the best or is less than the absoluteThreshold
|
||||||
|
*
|
||||||
|
* @param requestedOutputs The desired output frequencies in MHz
|
||||||
|
* @param maximumAllowableFreqMHz The maximum allowable reference in MHz
|
||||||
|
* @param relativeThreshold See above
|
||||||
|
* @param absoluteThreshold See above
|
||||||
|
*/
|
||||||
|
def computeReferenceAsMultipleOfFastestClock(
|
||||||
requestedOutputs: Seq[ClockParameters],
|
requestedOutputs: Seq[ClockParameters],
|
||||||
maximumAllowableDivisor: Int = 0xFFFF): ClockParameters = {
|
maximumAllowableFreqMHz: Double,
|
||||||
|
relativeThreshold: Double = 1.10,
|
||||||
|
absoluteThreshold: Double = 0.01): ClockParameters = {
|
||||||
|
|
||||||
require(requestedOutputs.nonEmpty)
|
require(requestedOutputs.nonEmpty)
|
||||||
require(!requestedOutputs.contains(0.0))
|
require(!requestedOutputs.contains(0.0))
|
||||||
val freqs = requestedOutputs.map(f => BigInt(Math.round(f.freqMHz * 1000 * 1000)))
|
val requestedFreqs = requestedOutputs.map(_.freqMHz)
|
||||||
val refFreq = freqs.reduce((a, b) => a * b / a.gcd(b)).toDouble / (1000 * 1000)
|
val fastestFreq = requestedFreqs.max
|
||||||
assert((refFreq / freqs.min.toDouble) < maximumAllowableDivisor.toDouble)
|
require(fastestFreq < maximumAllowableFreqMHz)
|
||||||
ClockParameters(refFreq)
|
|
||||||
|
val candidateFreqs =
|
||||||
|
Seq.tabulate(Math.ceil(maximumAllowableFreqMHz / fastestFreq).toInt)(i => (i + 1) * fastestFreq)
|
||||||
|
val errorTuples = candidateFreqs.map { f =>
|
||||||
|
f -> Math.sqrt(squaredError(f, requestedFreqs.toList) / requestedFreqs.size)
|
||||||
|
}
|
||||||
|
val minError = errorTuples.map(_._2).min
|
||||||
|
val viableFreqs = errorTuples.collect {
|
||||||
|
case (f, error) if (error <= minError * relativeThreshold) || (minError > 0 && error < absoluteThreshold) => f
|
||||||
|
}
|
||||||
|
ClockParameters(viableFreqs.min)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class SimplePllConfiguration(name: String, val sinks: Seq[ClockSinkParameters]) {
|
class SimplePllConfiguration(
|
||||||
val referenceFreqMHz = FrequencyUtils.computeReferenceFrequencyMHz(sinks.flatMap(_.take)).freqMHz
|
name: String,
|
||||||
|
val sinks: Seq[ClockSinkParameters],
|
||||||
|
maximumAllowableFreqMHz: Double = 16000.0 ) {
|
||||||
|
val referenceFreqMHz = FrequencyUtils.computeReferenceAsMultipleOfFastestClock(
|
||||||
|
sinks.flatMap(_.take),
|
||||||
|
maximumAllowableFreqMHz).freqMHz
|
||||||
val sinkDividerMap = ListMap((sinks.map({s => (s, Math.round(referenceFreqMHz / s.take.get.freqMHz).toInt) })):_*)
|
val sinkDividerMap = ListMap((sinks.map({s => (s, Math.round(referenceFreqMHz / s.take.get.freqMHz).toInt) })):_*)
|
||||||
|
|
||||||
private val preamble = s"""
|
private val preamble = s"""
|
||||||
@@ -40,8 +85,10 @@ class SimplePllConfiguration(name: String, val sinks: Seq[ClockSinkParameters])
|
|||||||
}
|
}
|
||||||
|
|
||||||
val summaryString = preamble + outputSummaries.mkString("\n")
|
val summaryString = preamble + outputSummaries.mkString("\n")
|
||||||
ElaborationArtefacts.add(s"${name}.freq-summary", summaryString)
|
def emitSummaries(): Unit = {
|
||||||
println(summaryString)
|
ElaborationArtefacts.add(s"${name}.freq-summary", summaryString)
|
||||||
|
println(summaryString)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
case class DividerOnlyClockGeneratorNode(pllName: String)(implicit valName: ValName)
|
case class DividerOnlyClockGeneratorNode(pllName: String)(implicit valName: ValName)
|
||||||
@@ -53,7 +100,7 @@ case class DividerOnlyClockGeneratorNode(pllName: String)(implicit valName: ValN
|
|||||||
"All output clocks in group must set their take parameters. Use a ClockGroupDealiaser")
|
"All output clocks in group must set their take parameters. Use a ClockGroupDealiaser")
|
||||||
ClockSinkParameters(
|
ClockSinkParameters(
|
||||||
name = Some(s"${pllName}_reference_input"),
|
name = Some(s"${pllName}_reference_input"),
|
||||||
take = Some(FrequencyUtils.computeReferenceFrequencyMHz(u.head.members.flatMap(_.take)))) }
|
take = Some(ClockParameters(new SimplePllConfiguration(pllName, u.head.members).referenceFreqMHz))) }
|
||||||
)
|
)
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -78,6 +125,7 @@ class DividerOnlyClockGenerator(pllName: String)(implicit p: Parameters, valName
|
|||||||
|
|
||||||
val referenceFreq = refSinkParam.take.get.freqMHz
|
val referenceFreq = refSinkParam.take.get.freqMHz
|
||||||
val pllConfig = new SimplePllConfiguration(pllName, outSinkParams.members)
|
val pllConfig = new SimplePllConfiguration(pllName, outSinkParams.members)
|
||||||
|
pllConfig.emitSummaries()
|
||||||
|
|
||||||
val dividedClocks = mutable.HashMap[Int, Clock]()
|
val dividedClocks = mutable.HashMap[Int, Clock]()
|
||||||
def instantiateDivider(div: Int): Clock = {
|
def instantiateDivider(div: Int): Clock = {
|
||||||
|
|||||||
@@ -12,7 +12,7 @@ import freechips.rocketchip.util.{ResetCatchAndSync}
|
|||||||
* Instantiates a reset synchronizer on all clock-reset pairs in a clock group
|
* Instantiates a reset synchronizer on all clock-reset pairs in a clock group
|
||||||
*/
|
*/
|
||||||
class ClockGroupResetSynchronizer(implicit p: Parameters) extends LazyModule {
|
class ClockGroupResetSynchronizer(implicit p: Parameters) extends LazyModule {
|
||||||
val node = ClockGroupIdentityNode()
|
val node = ClockGroupAdapterNode()
|
||||||
lazy val module = new LazyRawModuleImp(this) {
|
lazy val module = new LazyRawModuleImp(this) {
|
||||||
(node.out zip node.in).map { case ((oG, _), (iG, _)) =>
|
(node.out zip node.in).map { case ((oG, _), (iG, _)) =>
|
||||||
(oG.member.data zip iG.member.data).foreach { case (o, i) =>
|
(oG.member.data zip iG.member.data).foreach { case (o, i) =>
|
||||||
|
|||||||
@@ -43,7 +43,8 @@ class AbstractConfig extends Config(
|
|||||||
new chipyard.config.WithUART ++ // add a UART
|
new chipyard.config.WithUART ++ // add a UART
|
||||||
new chipyard.config.WithL2TLBs(1024) ++ // use L2 TLBs
|
new chipyard.config.WithL2TLBs(1024) ++ // use L2 TLBs
|
||||||
new chipyard.config.WithNoSubsystemDrivenClocks ++ // drive the subsystem diplomatic clocks from ChipTop instead of using implicit clocks
|
new chipyard.config.WithNoSubsystemDrivenClocks ++ // drive the subsystem diplomatic clocks from ChipTop instead of using implicit clocks
|
||||||
new chipyard.config.WithPeripheryBusFrequencyAsDefault ++ // Unspecified clocks will match the frequency specified by the pbus dtsFrequency parameter
|
new chipyard.config.WithInheritBusFrequencyAssignments ++ // Unspecified clocks within a bus will receive the bus frequency if set
|
||||||
|
new chipyard.config.WithPeripheryBusFrequencyAsDefault ++ // Unspecified frequencies with match the pbus frequency (which is always set)
|
||||||
new freechips.rocketchip.subsystem.WithJtagDTM ++ // set the debug module to expose a JTAG port
|
new freechips.rocketchip.subsystem.WithJtagDTM ++ // set the debug module to expose a JTAG port
|
||||||
new freechips.rocketchip.subsystem.WithNoMMIOPort ++ // no top-level MMIO master port (overrides default set in rocketchip)
|
new freechips.rocketchip.subsystem.WithNoMMIOPort ++ // no top-level MMIO master port (overrides default set in rocketchip)
|
||||||
new freechips.rocketchip.subsystem.WithNoSlavePort ++ // no top-level MMIO slave port (overrides default set in rocketchip)
|
new freechips.rocketchip.subsystem.WithNoSlavePort ++ // no top-level MMIO slave port (overrides default set in rocketchip)
|
||||||
|
|||||||
@@ -1,19 +0,0 @@
|
|||||||
package chipyard
|
|
||||||
|
|
||||||
import chisel3._
|
|
||||||
|
|
||||||
import freechips.rocketchip.config.{Config}
|
|
||||||
|
|
||||||
// ---------------------
|
|
||||||
// Ariane Configs
|
|
||||||
// ---------------------
|
|
||||||
|
|
||||||
class ArianeConfig extends Config(
|
|
||||||
new ariane.WithNArianeCores(1) ++ // single Ariane core
|
|
||||||
new chipyard.config.AbstractConfig)
|
|
||||||
|
|
||||||
class dmiArianeConfig extends Config(
|
|
||||||
new chipyard.harness.WithSerialAdapterTiedOff ++ // Tie off the serial port, override default instantiation of SimSerial
|
|
||||||
new chipyard.config.WithDMIDTM ++ // have debug module expose a clocked DMI port
|
|
||||||
new ariane.WithNArianeCores(1) ++ // single Ariane core
|
|
||||||
new chipyard.config.AbstractConfig)
|
|
||||||
19
generators/chipyard/src/main/scala/config/CVA6Configs.scala
Normal file
19
generators/chipyard/src/main/scala/config/CVA6Configs.scala
Normal file
@@ -0,0 +1,19 @@
|
|||||||
|
package chipyard
|
||||||
|
|
||||||
|
import chisel3._
|
||||||
|
|
||||||
|
import freechips.rocketchip.config.{Config}
|
||||||
|
|
||||||
|
// ---------------------
|
||||||
|
// CVA6 Configs
|
||||||
|
// ---------------------
|
||||||
|
|
||||||
|
class CVA6Config extends Config(
|
||||||
|
new cva6.WithNCVA6Cores(1) ++ // single CVA6 core
|
||||||
|
new chipyard.config.AbstractConfig)
|
||||||
|
|
||||||
|
class dmiCVA6Config extends Config(
|
||||||
|
new chipyard.harness.WithSerialAdapterTiedOff ++ // Tie off the serial port, override default instantiation of SimSerial
|
||||||
|
new chipyard.config.WithDMIDTM ++ // have debug module expose a clocked DMI port
|
||||||
|
new cva6.WithNCVA6Cores(1) ++ // single CVA6 core
|
||||||
|
new chipyard.config.AbstractConfig)
|
||||||
@@ -1,6 +1,7 @@
|
|||||||
package chipyard
|
package chipyard
|
||||||
|
|
||||||
import freechips.rocketchip.config.{Config}
|
import freechips.rocketchip.config.{Config}
|
||||||
|
import freechips.rocketchip.diplomacy.{AsynchronousCrossing}
|
||||||
|
|
||||||
// --------------
|
// --------------
|
||||||
// Rocket Configs
|
// Rocket Configs
|
||||||
@@ -175,13 +176,19 @@ class MMIORocketConfig extends Config(
|
|||||||
new freechips.rocketchip.subsystem.WithNBigCores(1) ++
|
new freechips.rocketchip.subsystem.WithNBigCores(1) ++
|
||||||
new chipyard.config.AbstractConfig)
|
new chipyard.config.AbstractConfig)
|
||||||
|
|
||||||
class DividedClockRocketConfig extends Config(
|
class MulticlockRocketConfig extends Config(
|
||||||
new chipyard.config.WithTileFrequency(200.0) ++
|
|
||||||
new freechips.rocketchip.subsystem.WithRationalRocketTiles ++ // Add rational crossings between RocketTile and uncore
|
|
||||||
new freechips.rocketchip.subsystem.WithNBigCores(1) ++
|
new freechips.rocketchip.subsystem.WithNBigCores(1) ++
|
||||||
new chipyard.config.WithMemoryBusFrequency(50.0) ++
|
// Frequency specifications
|
||||||
new chipyard.config.WithAsynchrousMemoryBusCrossing ++
|
new chipyard.config.WithTileFrequency(1600.0) ++ // Matches the maximum frequency of U540
|
||||||
new testchipip.WithAsynchronousSerialSlaveCrossing ++
|
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
|
||||||
|
new chipyard.config.WithSystemBusFrequencyAsDefault ++ // All unspecified clock frequencies, notably the implicit clock, will use the sbus freq (800 MHz)
|
||||||
|
// Crossing specifications
|
||||||
|
new chipyard.config.WithCbusToPbusCrossingType(AsynchronousCrossing()) ++ // Add Async crossing between PBUS and CBUS
|
||||||
|
new chipyard.config.WithSbusToMbusCrossingType(AsynchronousCrossing()) ++ // Add Async crossings between backside of L2 and MBUS
|
||||||
|
new freechips.rocketchip.subsystem.WithRationalRocketTiles ++ // Add rational crossings between RocketTile and uncore
|
||||||
|
new testchipip.WithAsynchronousSerialSlaveCrossing ++ // Add Async crossing between serial and MBUS. Its master-side is tied to the FBUS
|
||||||
new chipyard.config.AbstractConfig)
|
new chipyard.config.AbstractConfig)
|
||||||
|
|
||||||
class LBWIFRocketConfig extends Config(
|
class LBWIFRocketConfig extends Config(
|
||||||
|
|||||||
@@ -9,7 +9,7 @@ class Sodor1StageConfig extends Config(
|
|||||||
new sodor.common.WithNSodorCores(1, internalTile = sodor.common.Stage1Factory) ++
|
new sodor.common.WithNSodorCores(1, internalTile = sodor.common.Stage1Factory) ++
|
||||||
new testchipip.WithSerialPBusMem ++
|
new testchipip.WithSerialPBusMem ++
|
||||||
new freechips.rocketchip.subsystem.WithScratchpadsOnly ++ // use sodor tile-internal scratchpad
|
new freechips.rocketchip.subsystem.WithScratchpadsOnly ++ // use sodor tile-internal scratchpad
|
||||||
new freechips.rocketchip.subsystem.WithNMemoryChannels(0) ++ // use no external memory
|
new freechips.rocketchip.subsystem.WithNoMemPort ++ // use no external memory
|
||||||
new freechips.rocketchip.subsystem.WithNBanks(0) ++
|
new freechips.rocketchip.subsystem.WithNBanks(0) ++
|
||||||
new chipyard.config.AbstractConfig)
|
new chipyard.config.AbstractConfig)
|
||||||
|
|
||||||
@@ -18,7 +18,7 @@ class Sodor2StageConfig extends Config(
|
|||||||
new sodor.common.WithNSodorCores(1, internalTile = sodor.common.Stage2Factory) ++
|
new sodor.common.WithNSodorCores(1, internalTile = sodor.common.Stage2Factory) ++
|
||||||
new testchipip.WithSerialPBusMem ++
|
new testchipip.WithSerialPBusMem ++
|
||||||
new freechips.rocketchip.subsystem.WithScratchpadsOnly ++ // use sodor tile-internal scratchpad
|
new freechips.rocketchip.subsystem.WithScratchpadsOnly ++ // use sodor tile-internal scratchpad
|
||||||
new freechips.rocketchip.subsystem.WithNMemoryChannels(0) ++ // use no external memory
|
new freechips.rocketchip.subsystem.WithNoMemPort ++ // use no external memory
|
||||||
new freechips.rocketchip.subsystem.WithNBanks(0) ++
|
new freechips.rocketchip.subsystem.WithNBanks(0) ++
|
||||||
new chipyard.config.AbstractConfig)
|
new chipyard.config.AbstractConfig)
|
||||||
|
|
||||||
@@ -27,7 +27,7 @@ class Sodor3StageConfig extends Config(
|
|||||||
new sodor.common.WithNSodorCores(1, internalTile = sodor.common.Stage3Factory(ports = 2)) ++
|
new sodor.common.WithNSodorCores(1, internalTile = sodor.common.Stage3Factory(ports = 2)) ++
|
||||||
new testchipip.WithSerialPBusMem ++
|
new testchipip.WithSerialPBusMem ++
|
||||||
new freechips.rocketchip.subsystem.WithScratchpadsOnly ++ // use sodor tile-internal scratchpad
|
new freechips.rocketchip.subsystem.WithScratchpadsOnly ++ // use sodor tile-internal scratchpad
|
||||||
new freechips.rocketchip.subsystem.WithNMemoryChannels(0) ++ // use no external memory
|
new freechips.rocketchip.subsystem.WithNoMemPort ++ // use no external memory
|
||||||
new freechips.rocketchip.subsystem.WithNBanks(0) ++
|
new freechips.rocketchip.subsystem.WithNBanks(0) ++
|
||||||
new chipyard.config.AbstractConfig)
|
new chipyard.config.AbstractConfig)
|
||||||
|
|
||||||
@@ -36,7 +36,7 @@ class Sodor3StageSinglePortConfig extends Config(
|
|||||||
new sodor.common.WithNSodorCores(1, internalTile = sodor.common.Stage3Factory(ports = 1)) ++
|
new sodor.common.WithNSodorCores(1, internalTile = sodor.common.Stage3Factory(ports = 1)) ++
|
||||||
new testchipip.WithSerialPBusMem ++
|
new testchipip.WithSerialPBusMem ++
|
||||||
new freechips.rocketchip.subsystem.WithScratchpadsOnly ++ // use sodor tile-internal scratchpad
|
new freechips.rocketchip.subsystem.WithScratchpadsOnly ++ // use sodor tile-internal scratchpad
|
||||||
new freechips.rocketchip.subsystem.WithNMemoryChannels(0) ++ // use no external memory
|
new freechips.rocketchip.subsystem.WithNoMemPort ++ // use no external memory
|
||||||
new freechips.rocketchip.subsystem.WithNBanks(0) ++
|
new freechips.rocketchip.subsystem.WithNBanks(0) ++
|
||||||
new chipyard.config.AbstractConfig)
|
new chipyard.config.AbstractConfig)
|
||||||
|
|
||||||
@@ -45,7 +45,7 @@ class Sodor5StageConfig extends Config(
|
|||||||
new sodor.common.WithNSodorCores(1, internalTile = sodor.common.Stage5Factory) ++
|
new sodor.common.WithNSodorCores(1, internalTile = sodor.common.Stage5Factory) ++
|
||||||
new testchipip.WithSerialPBusMem ++
|
new testchipip.WithSerialPBusMem ++
|
||||||
new freechips.rocketchip.subsystem.WithScratchpadsOnly ++ // use sodor tile-internal scratchpad
|
new freechips.rocketchip.subsystem.WithScratchpadsOnly ++ // use sodor tile-internal scratchpad
|
||||||
new freechips.rocketchip.subsystem.WithNMemoryChannels(0) ++ // use no external memory
|
new freechips.rocketchip.subsystem.WithNoMemPort ++ // use no external memory
|
||||||
new freechips.rocketchip.subsystem.WithNBanks(0) ++
|
new freechips.rocketchip.subsystem.WithNBanks(0) ++
|
||||||
new chipyard.config.AbstractConfig)
|
new chipyard.config.AbstractConfig)
|
||||||
|
|
||||||
@@ -54,6 +54,6 @@ class SodorUCodeConfig extends Config(
|
|||||||
new sodor.common.WithNSodorCores(1, internalTile = sodor.common.UCodeFactory) ++
|
new sodor.common.WithNSodorCores(1, internalTile = sodor.common.UCodeFactory) ++
|
||||||
new testchipip.WithSerialPBusMem ++
|
new testchipip.WithSerialPBusMem ++
|
||||||
new freechips.rocketchip.subsystem.WithScratchpadsOnly ++ // use sodor tile-internal scratchpad
|
new freechips.rocketchip.subsystem.WithScratchpadsOnly ++ // use sodor tile-internal scratchpad
|
||||||
new freechips.rocketchip.subsystem.WithNMemoryChannels(0) ++ // use no external memory
|
new freechips.rocketchip.subsystem.WithNoMemPort ++ // use no external memory
|
||||||
new freechips.rocketchip.subsystem.WithNBanks(0) ++
|
new freechips.rocketchip.subsystem.WithNBanks(0) ++
|
||||||
new chipyard.config.AbstractConfig)
|
new chipyard.config.AbstractConfig)
|
||||||
|
|||||||
@@ -16,7 +16,7 @@ import freechips.rocketchip.util._
|
|||||||
import freechips.rocketchip.tile._
|
import freechips.rocketchip.tile._
|
||||||
import freechips.rocketchip.amba.axi4._
|
import freechips.rocketchip.amba.axi4._
|
||||||
|
|
||||||
// Example parameter class copied from Ariane, not included in documentation but for compile check only
|
// 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
|
// If you are here for documentation, DO NOT copy MyCoreParams and MyTileParams directly - always figure
|
||||||
// out what parameters you need before you write the parameter class
|
// out what parameters you need before you write the parameter class
|
||||||
case class MyCoreParams(
|
case class MyCoreParams(
|
||||||
@@ -164,7 +164,7 @@ class MyTileModuleImp(outer: MyTile) extends BaseTileModuleImp(outer){
|
|||||||
// val core = Module(new MyCoreBlackbox(params...))
|
// val core = Module(new MyCoreBlackbox(params...))
|
||||||
// (as described in the blackbox tutorial) and connect appropriate signals. See the blackbox tutorial
|
// (as described in the blackbox tutorial) and connect appropriate signals. See the blackbox tutorial
|
||||||
// (link on the top of the page) for more info.
|
// (link on the top of the page) for more info.
|
||||||
// You can look at https://github.com/ucb-bar/ariane-wrapper/blob/master/src/main/scala/ArianeTile.scala
|
// You can look at https://github.com/ucb-bar/cva6-wrapper/blob/master/src/main/scala/CVA6Tile.scala
|
||||||
// for a Verilog example.
|
// for a Verilog example.
|
||||||
|
|
||||||
// If your core is in Chisel, you can simply instantiate the top module here like other Chisel module
|
// If your core is in Chisel, you can simply instantiate the top module here like other Chisel module
|
||||||
|
|||||||
@@ -0,0 +1,29 @@
|
|||||||
|
//See LICENSE for license details.
|
||||||
|
package chipyard.clocking
|
||||||
|
|
||||||
|
import freechips.rocketchip.prci._
|
||||||
|
|
||||||
|
class SimplePllConfigurationSpec extends org.scalatest.FlatSpec {
|
||||||
|
|
||||||
|
def genConf(freqMHz: Iterable[Double]): SimplePllConfiguration = new SimplePllConfiguration(
|
||||||
|
"testPLL",
|
||||||
|
freqMHz.map({ f => ClockSinkParameters(
|
||||||
|
name = Some(s"desiredFreq_$f"),
|
||||||
|
take = Some(ClockParameters(f))) }).toSeq,
|
||||||
|
maximumAllowableFreqMHz = 16000.0)
|
||||||
|
|
||||||
|
def trySuccessfulConf(requestedFreqs: Seq[Double], expected: Double): Unit = {
|
||||||
|
val freqStr = requestedFreqs.mkString(", ")
|
||||||
|
it should s"select a reference of ${expected} MHz for ${freqStr} MHz" in {
|
||||||
|
val conf = genConf(requestedFreqs)
|
||||||
|
conf.emitSummaries
|
||||||
|
assert(expected == conf.referenceFreqMHz)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
trySuccessfulConf(Seq(3200.0, 1600.0, 1000.0, 100.0), 16000.0)
|
||||||
|
trySuccessfulConf(Seq(3200.0, 1600.0), 3200.0)
|
||||||
|
trySuccessfulConf(Seq(3200.0, 1066.7), 3200.0)
|
||||||
|
trySuccessfulConf(Seq(100, 50, 6.67), 100)
|
||||||
|
trySuccessfulConf(Seq(1, 2, 3, 5, 7, 11, 13).map(_ * 10.0), 1560.0)
|
||||||
|
}
|
||||||
1
generators/cva6
Submodule
1
generators/cva6
Submodule
Submodule generators/cva6 added at 8a11e2c976
@@ -22,7 +22,7 @@ import midas.targetutils.{MemModelAnnotation, EnableModelMultiThreadingAnnotatio
|
|||||||
import firesim.bridges._
|
import firesim.bridges._
|
||||||
import firesim.configs.MemModelKey
|
import firesim.configs.MemModelKey
|
||||||
import tracegen.{TraceGenSystemModuleImp}
|
import tracegen.{TraceGenSystemModuleImp}
|
||||||
import ariane.ArianeTile
|
import cva6.CVA6Tile
|
||||||
|
|
||||||
import boom.common.{BoomTile}
|
import boom.common.{BoomTile}
|
||||||
import barstools.iocell.chisel._
|
import barstools.iocell.chisel._
|
||||||
@@ -66,7 +66,7 @@ class WithFireSimIOCellModels extends Config((site, here, up) => {
|
|||||||
})
|
})
|
||||||
|
|
||||||
class WithSerialBridge extends OverrideHarnessBinder({
|
class WithSerialBridge extends OverrideHarnessBinder({
|
||||||
(system: CanHavePeripheryTLSerial, th: HasHarnessSignalReferences, ports: Seq[ClockedIO[SerialIO]]) => {
|
(system: CanHavePeripheryTLSerial, th: FireSim, ports: Seq[ClockedIO[SerialIO]]) => {
|
||||||
ports.map { port =>
|
ports.map { port =>
|
||||||
implicit val p = GetSystemParameters(system)
|
implicit val p = GetSystemParameters(system)
|
||||||
val ram = SerialAdapter.connectHarnessRAM(system.serdesser.get, port, th.harnessReset)
|
val ram = SerialAdapter.connectHarnessRAM(system.serdesser.get, port, th.harnessReset)
|
||||||
@@ -77,7 +77,7 @@ class WithSerialBridge extends OverrideHarnessBinder({
|
|||||||
})
|
})
|
||||||
|
|
||||||
class WithNICBridge extends OverrideHarnessBinder({
|
class WithNICBridge extends OverrideHarnessBinder({
|
||||||
(system: CanHavePeripheryIceNIC, th: HasHarnessSignalReferences, ports: Seq[ClockedIO[NICIOvonly]]) => {
|
(system: CanHavePeripheryIceNIC, th: FireSim, ports: Seq[ClockedIO[NICIOvonly]]) => {
|
||||||
val p: Parameters = GetSystemParameters(system)
|
val p: Parameters = GetSystemParameters(system)
|
||||||
ports.map { n => NICBridge(n.clock, n.bits)(p) }
|
ports.map { n => NICBridge(n.clock, n.bits)(p) }
|
||||||
Nil
|
Nil
|
||||||
@@ -85,12 +85,12 @@ class WithNICBridge extends OverrideHarnessBinder({
|
|||||||
})
|
})
|
||||||
|
|
||||||
class WithUARTBridge extends OverrideHarnessBinder({
|
class WithUARTBridge extends OverrideHarnessBinder({
|
||||||
(system: HasPeripheryUARTModuleImp, th: HasHarnessSignalReferences, ports: Seq[UARTPortIO]) =>
|
(system: HasPeripheryUARTModuleImp, th: FireSim, ports: Seq[UARTPortIO]) =>
|
||||||
ports.map { p => UARTBridge(th.harnessClock, p)(system.p) }; Nil
|
ports.map { p => UARTBridge(th.harnessClock, p)(system.p) }; Nil
|
||||||
})
|
})
|
||||||
|
|
||||||
class WithBlockDeviceBridge extends OverrideHarnessBinder({
|
class WithBlockDeviceBridge extends OverrideHarnessBinder({
|
||||||
(system: CanHavePeripheryBlockDevice, th: HasHarnessSignalReferences, ports: Seq[ClockedIO[BlockDeviceIO]]) => {
|
(system: CanHavePeripheryBlockDevice, th: FireSim, ports: Seq[ClockedIO[BlockDeviceIO]]) => {
|
||||||
implicit val p: Parameters = GetSystemParameters(system)
|
implicit val p: Parameters = GetSystemParameters(system)
|
||||||
ports.map { b => BlockDevBridge(b.clock, b.bits, th.harnessReset.toBool) }
|
ports.map { b => BlockDevBridge(b.clock, b.bits, th.harnessReset.toBool) }
|
||||||
Nil
|
Nil
|
||||||
@@ -98,7 +98,7 @@ class WithBlockDeviceBridge extends OverrideHarnessBinder({
|
|||||||
})
|
})
|
||||||
|
|
||||||
class WithFASEDBridge extends OverrideHarnessBinder({
|
class WithFASEDBridge extends OverrideHarnessBinder({
|
||||||
(system: CanHaveMasterAXI4MemPort, th: HasHarnessSignalReferences, ports: Seq[ClockedAndResetIO[AXI4Bundle]]) => {
|
(system: CanHaveMasterAXI4MemPort, th: FireSim, ports: Seq[ClockedAndResetIO[AXI4Bundle]]) => {
|
||||||
implicit val p: Parameters = GetSystemParameters(system)
|
implicit val p: Parameters = GetSystemParameters(system)
|
||||||
(ports zip system.memAXI4Node.edges.in).map { case (axi4, edge) =>
|
(ports zip system.memAXI4Node.edges.in).map { case (axi4, edge) =>
|
||||||
val nastiKey = NastiParameters(axi4.bits.r.bits.data.getWidth,
|
val nastiKey = NastiParameters(axi4.bits.r.bits.data.getWidth,
|
||||||
@@ -118,20 +118,20 @@ class WithFASEDBridge extends OverrideHarnessBinder({
|
|||||||
})
|
})
|
||||||
|
|
||||||
class WithTracerVBridge extends ComposeHarnessBinder({
|
class WithTracerVBridge extends ComposeHarnessBinder({
|
||||||
(system: CanHaveTraceIOModuleImp, th: HasHarnessSignalReferences, ports: Seq[TraceOutputTop]) => {
|
(system: CanHaveTraceIOModuleImp, th: FireSim, ports: Seq[TraceOutputTop]) => {
|
||||||
ports.map { p => p.traces.map(tileTrace => TracerVBridge(tileTrace)(system.p)) }
|
ports.map { p => p.traces.map(tileTrace => TracerVBridge(tileTrace)(system.p)) }
|
||||||
Nil
|
Nil
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
class WithDromajoBridge extends ComposeHarnessBinder({
|
class WithDromajoBridge extends ComposeHarnessBinder({
|
||||||
(system: CanHaveTraceIOModuleImp, th: HasHarnessSignalReferences, ports: Seq[TraceOutputTop]) =>
|
(system: CanHaveTraceIOModuleImp, th: FireSim, ports: Seq[TraceOutputTop]) =>
|
||||||
ports.map { p => p.traces.map(tileTrace => DromajoBridge(tileTrace)(system.p)) }; Nil
|
ports.map { p => p.traces.map(tileTrace => DromajoBridge(tileTrace)(system.p)) }; Nil
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|
||||||
class WithTraceGenBridge extends OverrideHarnessBinder({
|
class WithTraceGenBridge extends OverrideHarnessBinder({
|
||||||
(system: TraceGenSystemModuleImp, th: HasHarnessSignalReferences, ports: Seq[Bool]) =>
|
(system: TraceGenSystemModuleImp, th: FireSim, ports: Seq[Bool]) =>
|
||||||
ports.map { p => GroundTestBridge(th.harnessClock, p)(system.p) }; Nil
|
ports.map { p => GroundTestBridge(th.harnessClock, p)(system.p) }; Nil
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|||||||
@@ -118,6 +118,7 @@ class WithFireSimSimpleClocks extends Config((site, here, up) => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
val pllConfig = new SimplePllConfiguration("FireSim RationalClockBridge", clockGroupEdge.sink.members)
|
val pllConfig = new SimplePllConfiguration("FireSim RationalClockBridge", clockGroupEdge.sink.members)
|
||||||
|
pllConfig.emitSummaries
|
||||||
val rationalClockSpecs = for ((sinkP, division) <- pllConfig.sinkDividerMap) yield {
|
val rationalClockSpecs = for ((sinkP, division) <- pllConfig.sinkDividerMap) yield {
|
||||||
RationalClock(sinkP.name.get, 1, division)
|
RationalClock(sinkP.name.get, 1, division)
|
||||||
}
|
}
|
||||||
@@ -153,7 +154,9 @@ class FireSim(implicit val p: Parameters) extends RawModule with HasHarnessSigna
|
|||||||
lazyModule match { case d: HasTestHarnessFunctions =>
|
lazyModule match { case d: HasTestHarnessFunctions =>
|
||||||
require(d.harnessFunctions.size == 1, "There should only be 1 harness function to connect clock+reset")
|
require(d.harnessFunctions.size == 1, "There should only be 1 harness function to connect clock+reset")
|
||||||
d.harnessFunctions.foreach(_(this))
|
d.harnessFunctions.foreach(_(this))
|
||||||
ApplyHarnessBinders(this, d.lazySystem, p(HarnessBinders), d.portMap.toMap)
|
}
|
||||||
|
lazyModule match { case d: HasIOBinders =>
|
||||||
|
ApplyHarnessBinders(this, d.lazySystem, d.portMap)
|
||||||
}
|
}
|
||||||
NodeIdx.increment()
|
NodeIdx.increment()
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -188,21 +188,19 @@ class SupernodeFireSimRocketConfig extends Config(
|
|||||||
new FireSimRocketConfig)
|
new FireSimRocketConfig)
|
||||||
|
|
||||||
//**********************************************************************************
|
//**********************************************************************************
|
||||||
//* Ariane Configurations
|
//* CVA6 Configurations
|
||||||
//*********************************************************************************/
|
//*********************************************************************************/
|
||||||
class FireSimArianeConfig extends Config(
|
class FireSimCVA6Config extends Config(
|
||||||
new WithDefaultFireSimBridges ++
|
new WithDefaultFireSimBridges ++
|
||||||
new WithDefaultMemModel ++
|
new WithDefaultMemModel ++
|
||||||
new WithFireSimConfigTweaks ++
|
new WithFireSimConfigTweaks ++
|
||||||
new chipyard.ArianeConfig)
|
new chipyard.CVA6Config)
|
||||||
|
|
||||||
//**********************************************************************************
|
//**********************************************************************************
|
||||||
//* Multiclock Configurations
|
//* Multiclock Configurations
|
||||||
//*********************************************************************************/
|
//*********************************************************************************/
|
||||||
class FireSimMulticlockRocketConfig extends Config(
|
class FireSimMulticlockRocketConfig extends Config(
|
||||||
new chipyard.config.WithTileFrequency(6400.0) ++ //lol
|
new chipyard.config.WithTileFrequency(6400.0) ++ //lol
|
||||||
new WithDefaultFireSimBridges ++
|
new freechips.rocketchip.subsystem.WithRationalRocketTiles ++ // Add rational crossings between RocketTile and uncore
|
||||||
new WithDefaultMemModel ++
|
new FireSimRocketConfig)
|
||||||
new WithFireSimConfigTweaks ++
|
|
||||||
new chipyard.DividedClockRocketConfig)
|
|
||||||
|
|
||||||
|
|||||||
@@ -110,7 +110,7 @@ class RocketMulticlockF1Tests extends FireSimTestSuite(
|
|||||||
"FireSimMulticlockRocketConfig",
|
"FireSimMulticlockRocketConfig",
|
||||||
"WithSynthAsserts_BaseF1Config")
|
"WithSynthAsserts_BaseF1Config")
|
||||||
|
|
||||||
class ArianeF1Tests extends FireSimTestSuite("FireSim", "WithNIC_DDR3FRFCFSLLC4MB_FireSimArianeConfig", "BaseF1Config")
|
class CVA6F1Tests extends FireSimTestSuite("FireSim", "WithNIC_DDR3FRFCFSLLC4MB_FireSimCVA6Config", "BaseF1Config")
|
||||||
|
|
||||||
// This test suite only mirrors what is run in CI. CI invokes each test individually, using a testOnly call.
|
// This test suite only mirrors what is run in CI. CI invokes each test individually, using a testOnly call.
|
||||||
class CITests extends Suites(
|
class CITests extends Suites(
|
||||||
|
|||||||
@@ -20,6 +20,7 @@ usage() {
|
|||||||
echo "Options"
|
echo "Options"
|
||||||
echo " --prefix PREFIX : Install destination. If unset, defaults to $(pwd)/riscv-tools-install"
|
echo " --prefix PREFIX : Install destination. If unset, defaults to $(pwd)/riscv-tools-install"
|
||||||
echo " or $(pwd)/esp-tools-install"
|
echo " or $(pwd)/esp-tools-install"
|
||||||
|
echo " --ignore-qemu : Ignore installing QEMU"
|
||||||
echo " --help -h : Display this message"
|
echo " --help -h : Display this message"
|
||||||
exit "$1"
|
exit "$1"
|
||||||
}
|
}
|
||||||
@@ -34,6 +35,7 @@ die() {
|
|||||||
|
|
||||||
TOOLCHAIN="riscv-tools"
|
TOOLCHAIN="riscv-tools"
|
||||||
EC2FASTINSTALL="false"
|
EC2FASTINSTALL="false"
|
||||||
|
IGNOREQEMU=""
|
||||||
RISCV=""
|
RISCV=""
|
||||||
|
|
||||||
# getopts does not support long options, and is inflexible
|
# getopts does not support long options, and is inflexible
|
||||||
@@ -45,6 +47,9 @@ do
|
|||||||
-p | --prefix )
|
-p | --prefix )
|
||||||
shift
|
shift
|
||||||
RISCV=$(realpath $1) ;;
|
RISCV=$(realpath $1) ;;
|
||||||
|
--ignore-qemu )
|
||||||
|
shift
|
||||||
|
IGNOREQEMU="true" ;;
|
||||||
riscv-tools | esp-tools)
|
riscv-tools | esp-tools)
|
||||||
TOOLCHAIN=$1 ;;
|
TOOLCHAIN=$1 ;;
|
||||||
ec2fast )
|
ec2fast )
|
||||||
@@ -102,12 +107,16 @@ if [ "${EC2FASTINSTALL}" = true ] ; then
|
|||||||
git submodule deinit "${module}" || :
|
git submodule deinit "${module}" || :
|
||||||
|
|
||||||
else
|
else
|
||||||
"${MAKE}" --version | (
|
MAKE_VER=$("${MAKE}" --version) || true
|
||||||
read -r makever
|
case ${MAKE_VER} in
|
||||||
case ${makever} in
|
'GNU Make '[4-9]\.*)
|
||||||
'GNU Make '[4-9]\.*|'GNU Make '[1-9][0-9]) ;;
|
;;
|
||||||
*) false ;;
|
'GNU Make '[1-9][0-9])
|
||||||
esac; ) || die 'obsolete make version; need GNU make 4.x or later'
|
;;
|
||||||
|
*)
|
||||||
|
die 'obsolete make version; need GNU make 4.x or later'
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
|
||||||
module_prepare riscv-gnu-toolchain qemu
|
module_prepare riscv-gnu-toolchain qemu
|
||||||
module_build riscv-gnu-toolchain --prefix="${RISCV}" --with-cmodel=medany
|
module_build riscv-gnu-toolchain --prefix="${RISCV}" --with-cmodel=medany
|
||||||
@@ -128,7 +137,9 @@ module_all riscv-tests --prefix="${RISCV}/riscv64-unknown-elf"
|
|||||||
|
|
||||||
SRCDIR="$(pwd)/toolchains" module_all libgloss --prefix="${RISCV}/riscv64-unknown-elf" --host=riscv64-unknown-elf
|
SRCDIR="$(pwd)/toolchains" module_all libgloss --prefix="${RISCV}/riscv64-unknown-elf" --host=riscv64-unknown-elf
|
||||||
|
|
||||||
|
if [ -z "$IGNOREQEMU" ] ; then
|
||||||
SRCDIR="$(pwd)/toolchains" module_all qemu --prefix="${RISCV}" --target-list=riscv64-softmmu
|
SRCDIR="$(pwd)/toolchains" module_all qemu --prefix="${RISCV}" --target-list=riscv64-softmmu
|
||||||
|
fi
|
||||||
|
|
||||||
# make Dromajo
|
# make Dromajo
|
||||||
git submodule update --init $CHIPYARD_DIR/tools/dromajo/dromajo-src
|
git submodule update --init $CHIPYARD_DIR/tools/dromajo/dromajo-src
|
||||||
|
|||||||
@@ -77,6 +77,6 @@ if [ ! -f ./software/firemarshal/marshal-config.yaml ]; then
|
|||||||
fi
|
fi
|
||||||
|
|
||||||
echo "# line auto-generated by init-submodules-no-riscv-tools.sh" >> env.sh
|
echo "# line auto-generated by init-submodules-no-riscv-tools.sh" >> env.sh
|
||||||
echo '__DIR="$(dirname "$(readlink -f "${BASH_SOURCE[0]}")")"' >> env.sh
|
echo '__DIR="$(dirname "$(readlink -f "${BASH_SOURCE[0]:-${(%):-%x}}")")"' >> env.sh
|
||||||
echo "PATH=\$__DIR/bin:\$PATH" >> env.sh
|
echo "PATH=\$__DIR/bin:\$PATH" >> env.sh
|
||||||
echo "PATH=\$__DIR/software/firemarshal:\$PATH" >> env.sh
|
echo "PATH=\$__DIR/software/firemarshal:\$PATH" >> env.sh
|
||||||
|
|||||||
@@ -9,9 +9,9 @@ index 5d642c1..56f6fda 100644
|
|||||||
- sha3, // On separate line to allow for cleaner tutorial-setup patches
|
- sha3, // On separate line to allow for cleaner tutorial-setup patches
|
||||||
+// sha3, // On separate line to allow for cleaner tutorial-setup patches
|
+// sha3, // On separate line to allow for cleaner tutorial-setup patches
|
||||||
dsptools, `rocket-dsptools`,
|
dsptools, `rocket-dsptools`,
|
||||||
gemmini, icenet, tracegen, ariane, nvdla, sodor)
|
gemmini, icenet, tracegen, cva6, nvdla, sodor)
|
||||||
.settings(commonSettings)
|
.settings(commonSettings)
|
||||||
@@ -158,9 +158,9 @@ lazy val ariane = (project in file("generators/ariane"))
|
@@ -158,9 +158,9 @@ lazy val cva6 = (project in file("generators/cva6"))
|
||||||
.dependsOn(rocketchip)
|
.dependsOn(rocketchip)
|
||||||
.settings(commonSettings)
|
.settings(commonSettings)
|
||||||
|
|
||||||
|
|||||||
Submodule sims/firesim updated: 1c76c446da...37fe89a65f
@@ -91,7 +91,7 @@ VERILATOR_OPT_FLAGS := \
|
|||||||
--output-split 10000 \
|
--output-split 10000 \
|
||||||
--output-split-cfuncs 100
|
--output-split-cfuncs 100
|
||||||
|
|
||||||
# default flags added for external IP (ariane/NVDLA)
|
# default flags added for external IP (cva6/NVDLA)
|
||||||
VERILOG_IP_VERILATOR_FLAGS := \
|
VERILOG_IP_VERILATOR_FLAGS := \
|
||||||
--unroll-count 256 \
|
--unroll-count 256 \
|
||||||
-Wno-PINCONNECTEMPTY \
|
-Wno-PINCONNECTEMPTY \
|
||||||
@@ -103,14 +103,14 @@ VERILOG_IP_VERILATOR_FLAGS := \
|
|||||||
-Wno-style \
|
-Wno-style \
|
||||||
-Wall
|
-Wall
|
||||||
|
|
||||||
# normal flags used for chipyard builds (that are incompatible with vlog ip aka ariane/NVDLA)
|
# normal flags used for chipyard builds (that are incompatible with vlog ip aka cva6/NVDLA)
|
||||||
CHIPYARD_VERILATOR_FLAGS := \
|
CHIPYARD_VERILATOR_FLAGS := \
|
||||||
--assert
|
--assert
|
||||||
|
|
||||||
# options dependent on whether external IP (ariane/NVDLA) or just chipyard is used
|
# options dependent on whether external IP (cva6/NVDLA) or just chipyard is used
|
||||||
# NOTE: defer the evaluation of this until it is used!
|
# NOTE: defer the evaluation of this until it is used!
|
||||||
PLATFORM_OPTS = $(shell \
|
PLATFORM_OPTS = $(shell \
|
||||||
if grep -qiP "module\s+(Ariane|NVDLA)" $(build_dir)/*.*v; \
|
if grep -qiP "module\s+(CVA6|NVDLA)" $(build_dir)/*.*v; \
|
||||||
then echo "$(VERILOG_IP_VERILATOR_FLAGS)"; \
|
then echo "$(VERILOG_IP_VERILATOR_FLAGS)"; \
|
||||||
else echo "$(CHIPYARD_VERILATOR_FLAGS)"; fi)
|
else echo "$(CHIPYARD_VERILATOR_FLAGS)"; fi)
|
||||||
|
|
||||||
|
|||||||
Submodule tools/dromajo/dromajo-src updated: 56e2ff46b7...09fbef4565
Reference in New Issue
Block a user