diff --git a/.circleci/config.yml b/.circleci/config.yml index dfadcba6..dc018859 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -145,6 +145,17 @@ jobs: name: Check that the tutorial-setup patches apply command: | scripts/tutorial-setup.sh + documentation-check: + executor: main-env + steps: + - checkout + - run: + name: Check that documentation builds with no warnings/errors + command: | + sudo apt-get update -y + sudo apt-get install -y python3-pip + sudo pip3 install -r docs/requirements.txt + make -C docs html install-riscv-toolchain: executor: main-env @@ -357,6 +368,9 @@ workflows: # Attempt to apply the tutorial patches - tutorial-setup-check + # Check that documentation builds + - documentation-check + # Build extra tests - build-extra-tests: requires: diff --git a/README.md b/README.md index 0eec2d87..8d4cccc5 100644 --- a/README.md +++ b/README.md @@ -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. 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]), memory systems, and additional peripherals and tooling to help create a full featured SoC. +Chipyard contains processor cores ([Rocket][rocket-chip], [BOOM][boom], [Ariane][ariane]), accelerators ([Hwacha][hwacha], [Gemmini][gemmini]), 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 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]. @@ -64,3 +64,4 @@ These publications cover many of the internal components used in Chipyard. Howev [boom]: https://github.com/ucb-bar/riscv-boom [firemarshal]: https://github.com/firesim/FireMarshal/ [ariane]: https://github.com/pulp-platform/ariane/ +[gemmini]: https://github.com/ucb-bar/gemmini diff --git a/build.sbt b/build.sbt index b0eea0a8..05f05d7b 100644 --- a/build.sbt +++ b/build.sbt @@ -122,8 +122,12 @@ lazy val testchipip = (project in file("generators/testchipip")) .dependsOn(rocketchip, sifive_blocks) .settings(commonSettings) +lazy val iocell = (project in file("./tools/barstools/iocell/")) + .dependsOn(chisel) + .settings(commonSettings) + lazy val chipyard = conditionalDependsOn(project in file("generators/chipyard")) - .dependsOn(boom, hwacha, sifive_blocks, sifive_cache, utilities, + .dependsOn(boom, hwacha, sifive_blocks, sifive_cache, utilities, iocell, sha3, // On separate line to allow for cleaner tutorial-setup patches gemmini, icenet, tracegen, ariane) .settings(commonSettings) diff --git a/common.mk b/common.mk index bf40e602..a98e0e24 100644 --- a/common.mk +++ b/common.mk @@ -3,15 +3,26 @@ ######################################################################################### SHELL=/bin/bash +######################################################################################### +# extra make variables/rules from subprojects +# +# EXTRA_GENERATOR_REQS - requirements needed for the main generator +# EXTRA_SIM_FLAGS - runtime simulation flags +# EXTRA_SIM_CC_FLAGS - cc flags for simulators +# EXTRA_SIM_SOURCES - simulation sources needed for simulator +# EXTRA_SIM_REQS - requirements to build the simulator +######################################################################################### +include $(base_dir)/generators/ariane/ariane.mk +include $(base_dir)/generators/tracegen/tracegen.mk + ######################################################################################### # variables to get all *.scala files ######################################################################################### lookup_srcs = $(shell find -L $(1)/ -name target -prune -o -iname "*.$(2)" -print 2> /dev/null) -SOURCE_DIRS = $(addprefix $(base_dir)/,generators sims/firesim/sim) +SOURCE_DIRS = $(addprefix $(base_dir)/,generators sims/firesim/sim tools/barstools/iocell) SCALA_SOURCES = $(call lookup_srcs,$(SOURCE_DIRS),scala) VLOG_SOURCES = $(call lookup_srcs,$(SOURCE_DIRS),sv) $(call lookup_srcs,$(SOURCE_DIRS),v) -ARIANE_VLOG_SOURCES = $(call lookup_srcs,$(base_dir)/generators/ariane,sv) $(call lookup_srcs,$(base_dir)/generators/ariane,v) ######################################################################################### # rocket and testchipip classes @@ -45,7 +56,7 @@ $(FIRRTL_FILE) $(ANNO_FILE): generator_temp @echo "" > /dev/null # AG: must re-elaborate if ariane sources have changed... otherwise just run firrtl compile -generator_temp: $(SCALA_SOURCES) $(ARIANE_VLOG_SOURCES) $(sim_files) +generator_temp: $(SCALA_SOURCES) $(sim_files) $(EXTRA_GENERATOR_REQS) mkdir -p $(build_dir) cd $(base_dir) && $(SBT) "project $(SBT_PROJECT)" "runMain $(GENERATOR_PACKAGE).Generator $(build_dir) $(MODEL_PACKAGE) $(MODEL) $(CONFIG_PACKAGE) $(CONFIG)" @@ -105,19 +116,19 @@ verilog: $(sim_vsrcs) ######################################################################################### .PHONY: run-binary run-binary-fast run-binary-debug run-fast run-binary: $(sim) - (set -o pipefail && $(sim) $(PERMISSIVE_ON) +max-cycles=$(timeout_cycles) $(SIM_FLAGS) $(VERBOSE_FLAGS) $(PERMISSIVE_OFF) $(BINARY) >(spike-dasm > $(sim_out_name).out) | tee $(sim_out_name).log) + (set -o pipefail && $(sim) $(PERMISSIVE_ON) $(SIM_FLAGS) $(EXTRA_SIM_FLAGS) $(VERBOSE_FLAGS) $(PERMISSIVE_OFF) $(BINARY) >(spike-dasm > $(sim_out_name).out) | tee $(sim_out_name).log) ######################################################################################### # helper rules to run simulator as fast as possible ######################################################################################### run-binary-fast: $(sim) - (set -o pipefail && $(sim) $(PERMISSIVE_ON) +max-cycles=$(timeout_cycles) $(SIM_FLAGS) $(PERMISSIVE_OFF) $(BINARY) >(spike-dasm > $(sim_out_name).out) | tee $(sim_out_name).log) + (set -o pipefail && $(sim_debug) $(PERMISSIVE_ON) $(SIM_FLAGS) $(EXTRA_SIM_FLAGS) $(VERBOSE_FLAGS) $(WAVEFORM_FLAG) $(PERMISSIVE_OFF) $(BINARY) >(spike-dasm > $(sim_out_name).out) | tee $(sim_out_name).log) run-fast: run-asm-tests-fast run-bmark-tests-fast @@ -129,10 +140,10 @@ $(output_dir)/%: $(RISCV)/riscv64-unknown-elf/share/riscv-tests/isa/% ln -sf $< $@ $(output_dir)/%.run: $(output_dir)/% $(sim) - (set -o pipefail && $(sim) $(PERMISSIVE_ON) +max-cycles=$(timeout_cycles) $(SIM_FLAGS) $(PERMISSIVE_OFF) $< >(spike-dasm > $@) | tee $<.log) + (set -o pipefail && $(sim) $(PERMISSIVE_ON) $(SIM_FLAGS) $(EXTRA_SIM_FLAGS) $(VERBOSE_FLAGS) $(PERMISSIVE_OFF) $< >(spike-dasm > $@) | tee $<.log) ######################################################################################### # include build/project specific makefrags made from the generator @@ -141,26 +152,6 @@ ifneq ($(filter run% %.run %.out %.vpd %.vcd,$(MAKECMDGOALS)),) -include $(build_dir)/$(long_name).d endif -################################################# -# Rules for running and checking tracegen tests # -################################################# - -AXE_DIR=$(base_dir)/tools/axe/src -AXE=$(AXE_DIR)/axe - -$(AXE): $(wildcard $(AXE_DIR)/*.[ch]) $(AXE_DIR)/make.sh - cd $(AXE_DIR) && ./make.sh - -$(output_dir)/tracegen.out: $(sim) - mkdir -p $(output_dir) && $(sim) $(PERMISSIVE_ON) +max-cycles=$(timeout_cycles) $(VERBOSE_FLAGS) $(PERMISSIVE_OFF) none $@ - -$(output_dir)/tracegen.result: $(output_dir)/tracegen.out $(AXE) - $(base_dir)/scripts/check-tracegen.sh $< > $@ - -tracegen: $(output_dir)/tracegen.result - -.PHONY: tracegen - ####################################### # Rules for building DRAMSim2 library # ####################################### diff --git a/docs/Advanced-Concepts/Top-Testharness.rst b/docs/Advanced-Concepts/Top-Testharness.rst index 8df37769..ebd5b370 100644 --- a/docs/Advanced-Concepts/Top-Testharness.rst +++ b/docs/Advanced-Concepts/Top-Testharness.rst @@ -2,17 +2,28 @@ Tops, Test-Harnesses, and the Test-Driver =========================================== The three highest levels of hierarchy in a Chipyard -SoC are the Top (DUT), ``TestHarness``, and the ``TestDriver``. -The Top and ``TestHarness`` are both emitted by Chisel generators. +SoC are the ``ChipTop`` (DUT), ``TestHarness``, and the ``TestDriver``. +The ``ChipTop`` and ``TestHarness`` are both emitted by Chisel generators. The ``TestDriver`` serves as our testbench, and is a Verilog file in Rocket Chip. -Top/DUT +ChipTop/DUT ------------------------- -The top-level module of a Rocket Chip SoC is composed via cake-pattern. -Specifically, "Tops" extend a ``System``, which extends a ``Subsystem``, which extends a ``BaseSubsystem``. +``ChipTop`` is the top-level module that instantiates the ``System`` submodule, usually an instance of the concrete class ``DigitalTop``. +The vast majority of the design resides in the ``System``. +Other components that exist inside the ``ChipTop`` layer are generally IO cells, clock receivers and multiplexers, reset synchronizers, and other analog IP that needs to exist outside of the ``System``. +The ``IOBinders`` are responsible for instantiating the IO cells and defining the test harness collateral that connects to the top-level ports. +Most of these types of devices can be instantiated using custom ``IOBinders``, so the provided ``ChipTop`` and ``ChipTopCaughtReset`` classes are sufficient. +However, if needed, the ``BaseChipTop`` abstract class can be extended for building more custom ``ChipTop`` designs. + + +System/DigitalTop +------------------------- + +The system module of a Rocket Chip SoC is composed via cake-pattern. +Specifically, ``DigitalTop`` extends a ``System``, which extends a ``Subsystem``, which extends a ``BaseSubsystem``. BaseSubsystem diff --git a/docs/Chipyard-Basics/Configs-Parameters-Mixins.rst b/docs/Chipyard-Basics/Configs-Parameters-Mixins.rst index 9d7d86d0..94067aa1 100644 --- a/docs/Chipyard-Basics/Configs-Parameters-Mixins.rst +++ b/docs/Chipyard-Basics/Configs-Parameters-Mixins.rst @@ -77,10 +77,10 @@ It is used in the Rocket Chip SoC library and Chipyard framework in merging mult This example shows the Chipyard default top that composes multiple traits together into a fully-featured SoC with many optional components. -.. literalinclude:: ../../generators/chipyard/src/main/scala/Top.scala +.. literalinclude:: ../../generators/chipyard/src/main/scala/DigitalTop.scala :language: scala - :start-after: DOC include start: Top - :end-before: DOC include end: Top + :start-after: DOC include start: DigitalTop + :end-before: DOC include end: DigitalTop There are two "cakes" or mixins here. One for the lazy module (ex. ``CanHavePeripherySerial``) and one for the lazy module @@ -88,8 +88,8 @@ implementation (ex. ``CanHavePeripherySerialModuleImp`` where ``Imp`` refers to all the logical connections between generators and exchanges configuration information among them, while the lazy module implementation performs the actual Chisel RTL elaboration. -In the ``Top`` example class, the "outer" ``Top`` instantiates the "inner" -``TopModule`` as a lazy module implementation. This delays immediate elaboration +In the ``DigitalTop`` example class, the "outer" ``DigitalTop`` instantiates the "inner" +``DigitalTopModule`` as a lazy module implementation. This delays immediate elaboration of the module until all logical connections are determined and all configuration information is exchanged. The ``System`` outer base class, as well as the ``CanHavePeriphery`` outer traits contain code to perform high-level logical @@ -102,8 +102,9 @@ For example, the ``CanHavePeripherySerialModuleImp`` trait optionally physically the ``SerialAdapter`` module, and instantiates queues. In the test harness, the SoC is elaborated with -``val dut = Module(LazyModule(Top))``. -After elaboration, the result will be a ``Top`` module, which contains a +``val dut = p(BuildTop)(p)``. + +After elaboration, the system submodule of ``ChipTop`` will be a ``DigitalTop`` module, which contains a ``SerialAdapter`` module (among others), if the config specified for that block to be instantiated. From a high level, classes which extend ``LazyModule`` *must* reference diff --git a/docs/Customization/DMA-Devices.rst b/docs/Customization/DMA-Devices.rst index 554ff2d4..549a1556 100644 --- a/docs/Customization/DMA-Devices.rst +++ b/docs/Customization/DMA-Devices.rst @@ -15,10 +15,10 @@ that writes zeros to the memory at a configured address. .. literalinclude:: ../../generators/chipyard/src/main/scala/example/InitZero.scala :language: scala -.. literalinclude:: ../../generators/chipyard/src/main/scala/Top.scala +.. literalinclude:: ../../generators/chipyard/src/main/scala/DigitalTop.scala :language: scala - :start-after: DOC include start: Top - :end-before: DOC include end: Top + :start-after: DOC include start: DigitalTop + :end-before: DOC include end: DigitalTop We use ``TLHelper.makeClientNode`` to create a TileLink client node for us. We then connect the client node to the memory system through the front bus (fbus). diff --git a/docs/Customization/IOBinders.rst b/docs/Customization/IOBinders.rst index 59924a0f..6332d07a 100644 --- a/docs/Customization/IOBinders.rst +++ b/docs/Customization/IOBinders.rst @@ -1,7 +1,7 @@ IOBinders ========= -In Chipyard we use a special ``Parameters`` key, ``IOBinders`` to determine what modules to bind to the IOs of a ``Top`` in the ``TestHarness``. +In Chipyard we use a special ``Parameters`` key, ``IOBinders`` to instantiate IO cells in the ``ChipTop`` layer and determine what modules to bind to the IOs of a ``ChipTop`` in the ``TestHarness``. .. literalinclude:: ../../generators/chipyard/src/main/scala/IOBinders.scala :language: scala @@ -9,11 +9,27 @@ In Chipyard we use a special ``Parameters`` key, ``IOBinders`` to determine what :end-before: DOC include end: IOBinders -This special key solves the problem of duplicating test-harnesses for each different ``Top`` type. +This special key solves the problem of duplicating test-harnesses for each different ``System`` type. +You could just as well create a custom harness module that attaches IOs explicitly. +Instead, the ``IOBinders`` key provides a map from Scala traits to attachment behaviors. +Each ``IOBinder`` returns a tuple of three values: the list of ``ChipTop`` ports created by the ``IOBinder``, the list of all IO cell modules instantiated by the ``IOBinder``, and an optional function to be called inside the test harness. +This function is responsible for instantiating logic inside the ``TestHarness`` to appropriately drive the ``ChipTop`` IO ports created by the ``IOBinder``. +Conveniently, because the ``IOBinder`` is generating the port, it may also use the port inside this function, which prevents the ``BaseChipTop`` code from ever needing to access the port ``val``, thus having the ``IOBinder`` house all port specific code. +This scheme prevents the need to have two separate binder functions for each ``System`` trait. +When creating custom ``IOBinders`` it is important to use ``suggestName`` to name ports; otherwise Chisel will raise an exception trying to name the IOs. +The example ``IOBinders`` demonstrate this. -You could just as well create a custom harness module that attaches IOs explicitly. Instead, the IOBinders key provides a map from Scala traits to attachment behaviors. +As an example, the ``WithGPIOTiedOff`` IOBinder creates IO cells for the GPIO module(s) instantiated in the ``System``, then punches out new ``Analog`` ports for each one. +The test harness simply ties these off, but additional logic could be inserted to perform some kind of test in the ``TestHarness``. -For example, the ``WithSimAXIMemTiedOff`` IOBinder specifies that any ``Top`` which matches ``CanHaveMasterAXI4MemPortModuleImp`` will have a ``SimAXIMem`` connected. +.. literalinclude:: ../../generators/chipyard/src/main/scala/IOBinders.scala + :language: scala + :start-after: DOC include start: WithGPIOTiedOff + :end-before: DOC include end: WithGPIOTiedOff + + +``IOBinders`` also do not need to create ports. Some ``IOBinders`` can simply insert circuitry inside the ``ChipTop`` layer. +For example, the ``WithSimAXIMemTiedOff`` IOBinder specifies that any ``System`` which matches ``CanHaveMasterAXI4MemPortModuleImp`` will have a ``SimAXIMem`` connected inside ``ChipTop``. .. literalinclude:: ../../generators/chipyard/src/main/scala/IOBinders.scala :language: scala diff --git a/docs/Customization/Keys-Traits-Configs.rst b/docs/Customization/Keys-Traits-Configs.rst index ffa303b7..f4af3746 100644 --- a/docs/Customization/Keys-Traits-Configs.rst +++ b/docs/Customization/Keys-Traits-Configs.rst @@ -34,25 +34,25 @@ Accessing the value stored in the key is easy in Chisel, as long as the ``implic Traits ------ -Typically, most custom blocks will need to modify the behavior of some pre-existing block. For example, the GCD widget needs the ``Top`` module to instantiate and connect the widget via Tilelink, generate a top-level ``gcd_busy`` port, and connect that to the module as well. Traits let us do this without modifying the existing code for the ``Top``, and enables compartmentalization of code for different custom blocks. +Typically, most custom blocks will need to modify the behavior of some pre-existing block. For example, the GCD widget needs the ``DigitalTop`` module to instantiate and connect the widget via Tilelink, generate a top-level ``gcd_busy`` port, and connect that to the module as well. Traits let us do this without modifying the existing code for the ``DigitalTop``, and enables compartmentalization of code for different custom blocks. -Top-level traits specify that the ``Top`` has been parameterized to read some custom key and optionally instantiate and connect a widget defined by that key. Traits **should not** mandate the instantiation of custom logic. In other words, traits should be written with ``CanHave`` semantics, where the default behavior when the key is unset is a no-op. +Top-level traits specify that the ``DigitalTop`` has been parameterized to read some custom key and optionally instantiate and connect a widget defined by that key. Traits **should not** mandate the instantiation of custom logic. In other words, traits should be written with ``CanHave`` semantics, where the default behavior when the key is unset is a no-op. -Top-level traits should be defined and documented in subprojects, alongside their corresponding keys. The traits should then be added to the ``Top`` being used by Chipyard. +Top-level traits should be defined and documented in subprojects, alongside their corresponding keys. The traits should then be added to the ``DigitalTop`` being used by Chipyard. -Below we see the traits for the GCD example. The Lazy trait connects the GCD module to the Diplomacy graph, while the Implementation trait causes the ``Top`` to instantiate an additional port and concretely connect it to the GCD module. +Below we see the traits for the GCD example. The Lazy trait connects the GCD module to the Diplomacy graph, while the Implementation trait causes the ``DigitalTop`` to instantiate an additional port and concretely connect it to the GCD module. .. literalinclude:: ../../generators/chipyard/src/main/scala/example/GCD.scala :language: scala :start-after: DOC include start: GCD lazy trait :end-before: DOC include end: GCD imp trait -These traits are added to the default ``Top`` in Chipyard. +These traits are added to the default ``DigitalTop`` in Chipyard. -.. literalinclude:: ../../generators/chipyard/src/main/scala/Top.scala +.. literalinclude:: ../../generators/chipyard/src/main/scala/DigitalTop.scala :language: scala - :start-after: DOC include start: Top - :end-before: DOC include end: Top + :start-after: DOC include start: DigitalTop + :end-before: DOC include end: DigitalTop Config Fragments ---------------- diff --git a/docs/Customization/MMIO-Peripherals.rst b/docs/Customization/MMIO-Peripherals.rst index f6b429be..15ed5a00 100644 --- a/docs/Customization/MMIO-Peripherals.rst +++ b/docs/Customization/MMIO-Peripherals.rst @@ -87,21 +87,21 @@ For peripherals which instantiate a concrete module, or which need to be connect :start-after: DOC include start: GCD imp trait :end-before: DOC include end: GCD imp trait -Constructing the Top and Config -------------------------------- +Constructing the DigitalTop and Config +-------------------------------------- Now we want to mix our traits into the system as a whole. -This code is from ``generators/chipyard/src/main/scala/Top.scala``. +This code is from ``generators/chipyard/src/main/scala/DigitalTop.scala``. -.. literalinclude:: ../../generators/chipyard/src/main/scala/Top.scala +.. literalinclude:: ../../generators/chipyard/src/main/scala/DigitalTop.scala :language: scala - :start-after: DOC include start: Top - :end-before: DOC include end: Top + :start-after: DOC include start: DigitalTop + :end-before: DOC include end: DigitalTop Just as we need separate traits for ``LazyModule`` and module implementation, we need two classes to build the system. -The ``Top`` class contains the set of traits which parameterize and define the ``Top``. Typically these traits will optionally add IOs or peripherals to the ``Top``. -The ``Top`` class includes the pre-elaboration code and also a ``lazy val`` to produce the module implementation (hence ``LazyModule``). -The ``TopModule`` class is the actual RTL that gets synthesized. +The ``DigitalTop`` class contains the set of traits which parameterize and define the ``DigitalTop``. Typically these traits will optionally add IOs or peripherals to the ``DigitalTop``. +The ``DigitalTop`` class includes the pre-elaboration code and also a ``lazy val`` to produce the module implementation (hence ``LazyModule``). +The ``DigitalTopModule`` class is the actual RTL that gets synthesized. diff --git a/docs/Customization/Memory-Hierarchy.rst b/docs/Customization/Memory-Hierarchy.rst index 6c924ceb..733e70c6 100644 --- a/docs/Customization/Memory-Hierarchy.rst +++ b/docs/Customization/Memory-Hierarchy.rst @@ -38,6 +38,20 @@ Note that these configurations fully remove the L2 cache and mbus. This configuration fully removes the L2 cache and memory bus by setting the number of channels and number of banks to 0. +The System Bus +-------------- + +The system bus is the TileLink network that sits between the tiles and the L2 +agents and MMIO peripherals. Ordinarily, it is a fully-connected crossbar, +but TestChipIP provides a version that uses a ring network instead. This can +be useful when taping out larger systems. To use the ring network system +bus, simply add the ``WithRingSystemBus`` config fragment to your configuration. + +.. literalinclude:: ../../generators/chipyard/src/main/scala/config/RocketConfigs.scala + :language: scala + :start-after: DOC include start: RingSystemBusRocket + :end-before: DOC include end: RingSystemBusRocket + The SiFive L2 Cache ------------------- diff --git a/docs/Generators/IceNet.rst b/docs/Generators/IceNet.rst index a8595038..f7daa71e 100644 --- a/docs/Generators/IceNet.rst +++ b/docs/Generators/IceNet.rst @@ -78,7 +78,7 @@ Configuration To add IceNIC to your design, add ``HasPeripheryIceNIC`` to your lazy module and ``HasPeripheryIceNICModuleImp`` to the module implementation. If you are confused about the distinction between lazy module and module -implementation, refer to :ref:`Cake Pattern`. +implementation, refer to :ref:`Cake Pattern / Mixin`. Then add the ``WithIceNIC`` config fragment to your configuration. This will define ``NICKey``, which IceNIC uses to determine its parameters. The config fragment diff --git a/docs/Generators/TestChipIP.rst b/docs/Generators/TestChipIP.rst index f85636b1..31f9ce53 100644 --- a/docs/Generators/TestChipIP.rst +++ b/docs/Generators/TestChipIP.rst @@ -3,7 +3,8 @@ Test Chip IP Chipyard includes a Test Chip IP library which provides various hardware widgets that may be useful when designing SoCs. This includes a :ref:`Serial Adapter`, -:ref:`Block Device Controller`, :ref:`TileLink SERDES`, :ref:`TileLink Switcher`, and :ref:`UART Adapter`. +:ref:`Block Device Controller`, :ref:`TileLink SERDES`, :ref:`TileLink Switcher`, +:ref:`TileLink Ring Network`, and :ref:`UART Adapter`. Serial Adapter -------------- @@ -60,6 +61,19 @@ the select signal once TileLink messages have begun sending. For an example of how to use the switcher, take a look at the ``SwitcherTest`` unit test in the `Test Chip IP unit tests `_. +TileLink Ring Network +--------------------- + +TestChipIP provides a TLRingNetwork generator that has a similar interface +to the TLXbar provided by RocketChip, but uses ring networks internally rather +than crossbars. This can be useful for chips with very wide TileLink networks +(many cores and L2 banks) that can sacrifice cross-section bandwidth to relieve +wire routing congestion. Documentation on how to use the ring network can be +found in :ref:`The System Bus`. The implementation itself can be found +`here `_, +and may serve as an example of how to implement your own TileLink network with +a different topology. + UART Adapter ------------ diff --git a/docs/Makefile b/docs/Makefile index fe9f0963..a6e1b4fd 100644 --- a/docs/Makefile +++ b/docs/Makefile @@ -2,8 +2,8 @@ # # You can set these variables from the command line. -SPHINXOPTS = -w warnings.txt -SPHINXBUILD = python -msphinx +SPHINXOPTS = -w warnings.txt -n -W +SPHINXBUILD = python3 -msphinx SPHINXPROJ = Chipyard SOURCEDIR = . BUILDDIR = _build diff --git a/docs/TileLink-Diplomacy-Reference/Widgets.rst b/docs/TileLink-Diplomacy-Reference/Widgets.rst index 41fc033b..7eba871b 100644 --- a/docs/TileLink-Diplomacy-Reference/Widgets.rst +++ b/docs/TileLink-Diplomacy-Reference/Widgets.rst @@ -169,7 +169,7 @@ transactions. - ``minSize: Int`` - Minimum size of transfers supported by all outward managers. - ``maxSize: Int`` - Maximum size of transfers supported after the Fragmenter is applied. - ``alwaysMin: Boolean`` - (optional) Fragment all requests down to minSize (else fragment to maximum supported by manager). (default: false) - - ``earlyAck: EarlyAck.T`` - (optional) Should a multibeat Put be acknowledged on the first beat or last beat? + - ``earlyAck: EarlyAck.T`` - (optional) Should a multibeat Put be acknowledged on the first beat or last beat? Possible values (default: ``EarlyAck.None``): - ``EarlyAck.AllPuts`` - always acknowledge on first beat. @@ -270,7 +270,7 @@ the client to see a particular width. **Example Usage:** -.. code-block:: +.. code-block:: scala // Assume the manager node sets beatBytes to 8 // With WidthWidget, client sees beatBytes of 4 @@ -398,11 +398,11 @@ package, not the ``freechips.rocketchip.tilelink`` package like the others. - ``size: Int`` - The size of the memory in bytes - ``contentsDelayed: => Seq[Byte]`` - A function which, when called generates the byte contents of the ROM. - - ``executable: Boolean`` - (optional) Specify whether the CPU can fetch + - ``executable: Boolean`` - (optional) Specify whether the CPU can fetch instructions from the ROM (default: ``true``). - - ``beatBytes: Int`` - (optional) The width of the interface in bytes. + - ``beatBytes: Int`` - (optional) The width of the interface in bytes. (default: 4). - - ``resources: Seq[Resource]`` - (optional) Sequence of resources to add to + - ``resources: Seq[Resource]`` - (optional) Sequence of resources to add to the device tree. **Example Usage:** @@ -429,13 +429,13 @@ The TLRAM and AXI4RAM widgets provide read-write memories implemented as SRAMs. **Arguments:** - ``address: AddressSet`` - The address range that this RAM will cover. - - ``cacheable: Boolean`` - (optional) Can the contents of this RAM be cached. + - ``cacheable: Boolean`` - (optional) Can the contents of this RAM be cached. (default: ``true``) - - ``executable: Boolean`` - (optional) Can the contents of this RAM be fetched + - ``executable: Boolean`` - (optional) Can the contents of this RAM be fetched as instructions. (default: ``true``) - - ``beatBytes: Int`` - (optional) Width of the TL/AXI4 interface in bytes. + - ``beatBytes: Int`` - (optional) Width of the TL/AXI4 interface in bytes. (default: 4) - - ``atomics: Boolean`` - (optional, TileLink only) Does the RAM support + - ``atomics: Boolean`` - (optional, TileLink only) Does the RAM support atomic operations? (default: ``false``) **Example Usage:** diff --git a/docs/Tools/Barstools.rst b/docs/Tools/Barstools.rst index 34562227..9089c947 100644 --- a/docs/Tools/Barstools.rst +++ b/docs/Tools/Barstools.rst @@ -131,5 +131,5 @@ This, unfortunately, breaks the process-agnostic RTL abstraction, so it is recom The simplest way to do this is to have a config fragment that when included updates instantiates the IO cells and connects them in the test harness. When simulating chip-specific designs, it is important to include the IO cells. The IO cell behavioral models will often assert if they are connected incorrectly, which is a useful runtime check. -They also keep the IO interface at the chip and test harness boundary (see :ref:`Separating the top module from the test harness`) consistent after synthesis and place-and-route, +They also keep the IO interface at the chip and test harness boundary (see :ref:`Separating the Top module from the TestHarness module`) consistent after synthesis and place-and-route, which allows the RTL simulation test harness to be reused. diff --git a/docs/VLSI/Building-A-Chip.rst b/docs/VLSI/Building-A-Chip.rst index b684a07b..9ce283eb 100644 --- a/docs/VLSI/Building-A-Chip.rst +++ b/docs/VLSI/Building-A-Chip.rst @@ -45,8 +45,8 @@ It is possible to write this IR directly, or to generate it using simple python While we certainly look forward to having a more featureful toolkit, we have built many chips to date in this way. -Running the VLSI flow ---------------------- +Running the VLSI tool flow +-------------------------- For the full documentation on how to use the VLSI tool flow, see the `Hammer Documentation `__. For an example of how to use the VLSI in the context of Chipyard, see :ref:`ASAP7 Tutorial`. diff --git a/generators/ariane b/generators/ariane index 145b5ed1..e02436d2 160000 --- a/generators/ariane +++ b/generators/ariane @@ -1 +1 @@ -Subproject commit 145b5ed106efd0b22c2105c20722ab303fa4039b +Subproject commit e02436d2aaf934b6e58d5e11e87276ba0d840f2a diff --git a/generators/chipyard/src/main/scala/ChipTop.scala b/generators/chipyard/src/main/scala/ChipTop.scala new file mode 100644 index 00000000..328891a8 --- /dev/null +++ b/generators/chipyard/src/main/scala/ChipTop.scala @@ -0,0 +1,102 @@ +package chipyard + +import chisel3._ + +import scala.collection.mutable.{ArrayBuffer} + +import freechips.rocketchip.config.{Parameters, Field} +import freechips.rocketchip.diplomacy.{LazyModule} +import freechips.rocketchip.util.{ResetCatchAndSync} +import chipyard.config.ConfigValName._ +import chipyard.iobinders.{IOBinders, TestHarnessFunction, IOBinderTuple} + +import barstools.iocell.chisel._ + +case object BuildSystem extends Field[Parameters => RawModule]((p: Parameters) => Module(LazyModule(new DigitalTop()(p)).suggestName("system").module)) + +/** + * The base class used for building chips. This constructor instantiates a module specified by the BuildSystem parameter, + * named "system", which is an instance of DigitalTop by default. The default clock and reset for "system" are set by two + * wires, "systemClock" and "systemReset", which are intended to be driven by traits mixed-in with this base class. + */ +abstract class BaseChipTop()(implicit val p: Parameters) extends RawModule with HasTestHarnessFunctions { + + // A publicly accessible list of IO cells (useful for a floorplanning tool, for example) + val iocells = ArrayBuffer.empty[IOCell] + // A list of functions to call in the test harness + val harnessFunctions = ArrayBuffer.empty[TestHarnessFunction] + // The system clock + val systemClock = Wire(Input(Clock())) + // The system reset (synchronous to clock) + val systemReset = Wire(Input(Bool())) + + // The system module specified by BuildSystem + val system = withClockAndReset(systemClock, systemReset) { p(BuildSystem)(p) } + + // Call all of the IOBinders and provide them with a default clock and reset + withClockAndReset(systemClock, systemReset) { + val (_ports, _iocells, _harnessFunctions) = p(IOBinders).values.map(_(system)).flatten.unzip3 + // We ignore _ports for now... + iocells ++= _iocells.flatten + harnessFunctions ++= _harnessFunctions.flatten + } + +} + +/** + * A simple clock and reset implementation that punches out clock and reset ports with the same + * names as the implicit clock and reset for standard Module classes. Reset is synchronous to + * clock, which may not be a good idea to use for tapeouts. + */ +trait HasChipTopSimpleClockAndReset { this: BaseChipTop => + + val (clock, systemClockIO) = IOCell.generateIOFromSignal(systemClock, Some("iocell_clock")) + val (reset, systemResetIO) = IOCell.generateIOFromSignal(systemReset, Some("iocell_reset")) + + iocells ++= systemClockIO + iocells ++= systemResetIO + + // Add a TestHarnessFunction that connects clock and reset + harnessFunctions += { (th: TestHarness) => { + // Connect clock; it's not done implicitly with RawModule + clock := th.clock + // Connect reset; it's not done implicitly with RawModule + // Note that we need to use dutReset, not harnessReset + reset := th.dutReset + Nil + } } + +} + +/** + * Variant of HasChipTopSimpleClockAndReset that adds a reset synchronizer so that the top-level reset + * can be asynchronous with clock, which is useful for tapeout configs. + */ +trait HasChipTopSimpleClockAndCaughtReset { this: BaseChipTop => + + val asyncResetCore = Wire(Input(Bool())) + systemReset := ResetCatchAndSync(systemClock, asyncResetCore) + + val (clock, systemClockIO) = IOCell.generateIOFromSignal(systemClock, Some("iocell_clock")) + val (areset, asyncResetIO) = IOCell.generateIOFromSignal(asyncResetCore, Some("iocell_areset")) + + iocells ++= systemClockIO + iocells ++= asyncResetIO + + // Add a TestHarnessFunction that connects clock and areset + harnessFunctions += { (th: TestHarness) => { + // Connect clock; it's not done implicitly with RawModule + clock := th.clock + // Connect reset; it's not done implicitly with RawModule + // Note that we need to use dutReset, not harnessReset + areset := th.dutReset + Nil + } } + +} + +class ChipTop()(implicit p: Parameters) extends BaseChipTop()(p) + with HasChipTopSimpleClockAndReset + +class ChipTopCaughtReset()(implicit p: Parameters) extends BaseChipTop()(p) + with HasChipTopSimpleClockAndCaughtReset diff --git a/generators/chipyard/src/main/scala/ConfigFragments.scala b/generators/chipyard/src/main/scala/ConfigFragments.scala index dae6e055..495c3367 100644 --- a/generators/chipyard/src/main/scala/ConfigFragments.scala +++ b/generators/chipyard/src/main/scala/ConfigFragments.scala @@ -21,7 +21,7 @@ import hwacha.{Hwacha} import sifive.blocks.devices.gpio._ import sifive.blocks.devices.uart._ -import chipyard.{BuildTop} +import chipyard.{BuildTop, BuildSystem, ChipTopCaughtReset} /** * TODO: Why do we need this? @@ -65,8 +65,8 @@ class WithL2TLBs(entries: Int) extends Config((site, here, up) => { )) }) -class WithTracegenTop extends Config((site, here, up) => { - case BuildTop => (p: Parameters) => Module(LazyModule(new tracegen.TraceGenSystem()(p)).suggestName("Top").module) +class WithTracegenSystem extends Config((site, here, up) => { + case BuildSystem => (p: Parameters) => Module(LazyModule(new tracegen.TraceGenSystem()(p)).suggestName("Top").module) }) @@ -150,3 +150,13 @@ class WithControlCore extends Config((site, here, up) => { ) case MaxHartIdBits => log2Up(up(RocketTilesKey, site).size + up(BoomTilesKey, site).size + 1) }) + + +/** + * Config fragment to use ChipTopCaughtReset as the top module, which adds a reset synchronizer to + * the top-level reset, allowing it to be asynchronous with the clock. + * NOTE: You must remember to set TOP=WithChipTopCaughtReset when building with this config + */ +class WithChipTopCaughtReset extends Config((site, here, up) => { + case BuildTop => (p: Parameters) => Module(new ChipTopCaughtReset()(p).suggestName("top")) +}) diff --git a/generators/chipyard/src/main/scala/Top.scala b/generators/chipyard/src/main/scala/DigitalTop.scala similarity index 86% rename from generators/chipyard/src/main/scala/Top.scala rename to generators/chipyard/src/main/scala/DigitalTop.scala index d81d779a..c7b3d497 100644 --- a/generators/chipyard/src/main/scala/Top.scala +++ b/generators/chipyard/src/main/scala/DigitalTop.scala @@ -11,8 +11,8 @@ import freechips.rocketchip.devices.tilelink._ // BOOM and/or Rocket Top Level Systems // ------------------------------------ -// DOC include start: Top -class Top(implicit p: Parameters) extends System +// DOC include start: DigitalTop +class DigitalTop(implicit p: Parameters) extends System with testchipip.CanHaveTraceIO // Enables optionally adding trace IO with testchipip.CanHaveBackingScratchpad // Enables optionally adding a backing scratchpad with testchipip.CanHavePeripheryBlockDevice // Enables optionally adding the block device @@ -23,10 +23,10 @@ class Top(implicit p: Parameters) extends System with chipyard.example.CanHavePeripheryInitZero // Enables optionally adding the initzero example widget with chipyard.example.CanHavePeripheryGCD // Enables optionally adding the GCD example widget { - override lazy val module = new TopModule(this) + override lazy val module = new DigitalTopModule(this) } -class TopModule[+L <: Top](l: L) extends SystemModule(l) +class DigitalTopModule[+L <: DigitalTop](l: L) extends SystemModule(l) with testchipip.CanHaveTraceIOModuleImp with testchipip.CanHavePeripheryBlockDeviceModuleImp with testchipip.CanHavePeripherySerialModuleImp @@ -35,4 +35,4 @@ class TopModule[+L <: Top](l: L) extends SystemModule(l) with icenet.CanHavePeripheryIceNICModuleImp with chipyard.example.CanHavePeripheryGCDModuleImp with freechips.rocketchip.util.DontTouch -// DOC include end: Top +// DOC include end: DigitalTop diff --git a/generators/chipyard/src/main/scala/IOBinders.scala b/generators/chipyard/src/main/scala/IOBinders.scala index 938ecc5f..6388c3db 100644 --- a/generators/chipyard/src/main/scala/IOBinders.scala +++ b/generators/chipyard/src/main/scala/IOBinders.scala @@ -1,19 +1,22 @@ -package chipyard.iobinders +package chipyard +package object iobinders { import chisel3._ +import chisel3.experimental.{Analog, IO} import freechips.rocketchip.config.{Field, Config, Parameters} import freechips.rocketchip.diplomacy.{LazyModule} import freechips.rocketchip.devices.debug._ import freechips.rocketchip.subsystem._ -import freechips.rocketchip.system._ import freechips.rocketchip.util._ import sifive.blocks.devices.gpio._ import sifive.blocks.devices.uart._ +import barstools.iocell.chisel._ + import testchipip._ -import icenet._ +import icenet.{CanHavePeripheryIceNICModuleImp, SimNetwork, NicLoopback, NICKey} import tracegen.{HasTraceGenTilesModuleImp} import scala.reflect.{ClassTag} @@ -26,23 +29,32 @@ import scala.reflect.{ClassTag} // IO connection behavior for tops matching that trait. We use strings to enable // composition and overriding of IOBinders, much like how normal Keys in the config // system are used/ At elaboration, the testharness traverses this set of functions, -// and functions which match the type of the Top are evaluated. +// and functions which match the type of the DigitalTop are evaluated. // You can add your own binder by adding a new (key, fn) pair, typically by using // the OverrideIOBinder or ComposeIOBinder macros + // DOC include start: IOBinders -case object IOBinders extends Field[Map[String, (Clock, Bool, Bool, Any) => Seq[Any]]]( - Map[String, (Clock, Bool, Bool, Any) => Seq[Any]]().withDefaultValue((c: Clock, r: Bool, s: Bool, t: Any) => Nil) +// This type describes a function callable on the TestHarness instance. Its return type is unused. +type TestHarnessFunction = (chipyard.TestHarness) => Seq[Any] +// IOBinders will return a Seq of this tuple, which contains three fields: +// 1. A Seq containing all IO ports created by the IOBinder function +// 2. A Seq containing all IO cell modules created by the IOBinder function +// 3. An optional function to call inside the test harness (e.g. to connect the IOs) +type IOBinderTuple = (Seq[Data], Seq[IOCell], Option[TestHarnessFunction]) + +case object IOBinders extends Field[Map[String, (Any) => Seq[IOBinderTuple]]]( + Map[String, (Any) => Seq[IOBinderTuple]]().withDefaultValue((Any) => Nil) ) // 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](fn: => (Clock, Bool, Bool, T) => Seq[Any])(implicit tag: ClassTag[T]) extends Config((site, here, up) => { +class OverrideIOBinder[T](fn: => (T) => Seq[IOBinderTuple])(implicit tag: ClassTag[T]) extends Config((site, here, up) => { case IOBinders => up(IOBinders, site) + (tag.runtimeClass.toString -> - ((clock: Clock, reset: Bool, success: Bool, t: Any) => { + ((t: Any) => { t match { - case top: T => fn(clock, reset, success, top) + case system: T => fn(system) case _ => Nil } }) @@ -51,12 +63,12 @@ class OverrideIOBinder[T](fn: => (Clock, Bool, Bool, T) => Seq[Any])(implicit ta // This macro composes with previous matches on some Top mixin. This is useful for // annotation-like binders, since those can typically be composed -class ComposeIOBinder[T](fn: => (Clock, Bool, Bool, T) => Seq[Any])(implicit tag: ClassTag[T]) extends Config((site, here, up) => { +class ComposeIOBinder[T](fn: => (T) => Seq[IOBinderTuple])(implicit tag: ClassTag[T]) extends Config((site, here, up) => { case IOBinders => up(IOBinders, site) + (tag.runtimeClass.toString -> - ((clock: Clock, reset: Bool, success: Bool, t: Any) => { + ((t: Any) => { t match { - case top: T => (up(IOBinders, site)(tag.runtimeClass.toString)(clock, reset, success, top) - ++ fn(clock, reset, success, top)) + case system: T => (up(IOBinders, site)(tag.runtimeClass.toString)(system) + ++ fn(system)) case _ => Nil } }) @@ -65,74 +77,146 @@ class ComposeIOBinder[T](fn: => (Clock, Bool, Bool, T) => Seq[Any])(implicit tag // DOC include end: IOBinders +object AddIOCells { + /** + * Add IO cells to a SiFive GPIO devices and name the IO ports. + * @param gpios A Seq of GPIO port bundles + * @param genFn A callable function to generate a DigitalGPIOCell module to use + * @return Returns a tuple of (a 2D Seq of Analog IOs corresponding to individual GPIO pins; a 2D Seq of IOCell module references) + */ + def gpio(gpios: Seq[GPIOPortIO], genFn: () => DigitalGPIOCell = IOCell.genericGPIO): (Seq[Seq[Analog]], Seq[Seq[IOCell]]) = { + gpios.zipWithIndex.map({ case (gpio, i) => + gpio.pins.zipWithIndex.map({ case (pin, j) => + val g = IO(Analog(1.W)) + g.suggestName("gpio_${i}_${j}") + val iocell = genFn() + iocell.suggestName(s"iocell_gpio_${i}_${j}") + iocell.io.o := pin.o.oval + iocell.io.oe := pin.o.oe + iocell.io.ie := pin.o.ie + pin.i.ival := iocell.io.i + iocell.io.pad <> g + (g, iocell) + }).unzip + }).unzip + } + + /** + * Add IO cells to a SiFive UART devices and name the IO ports. + * @param gpios A Seq of UART port bundles + * @return Returns a tuple of (A Seq of top-level UARTPortIO IOs; a 2D Seq of IOCell module references) + */ + def uart(uartPins: Seq[UARTPortIO]): (Seq[UARTPortIO], Seq[Seq[IOCell]]) = { + uartPins.zipWithIndex.map({ case (u, i) => + val (port, ios) = IOCell.generateIOFromSignal(u, Some(s"iocell_uart_${i}")) + port.suggestName(s"uart_${i}") + (port, ios) + }).unzip + } + + /** + * Add IO cells to a debug module and name the IO ports. + * @param gpios A PSDIO bundle + * @param debugOpt An optional DebugIO bundle + * @return Returns a tuple3 of (Top-level PSDIO IO; Optional top-level DebugIO IO; a list of IOCell module references) + */ + def debug(psd: PSDIO, debugOpt: Option[DebugIO]): (PSDIO, Option[DebugIO], Seq[IOCell]) = { + val (psdPort, psdIOs) = IOCell.generateIOFromSignal(psd, Some("iocell_psd")) + val optTuple = debugOpt.map(d => IOCell.generateIOFromSignal(d, Some("iocell_debug"))) + val debugPortOpt: Option[DebugIO] = optTuple.map(_._1) + val debugIOs: Seq[IOCell] = optTuple.map(_._2).toSeq.flatten + debugPortOpt.foreach(_.suggestName("debug")) + psdPort.suggestName("psd") + (psdPort, debugPortOpt, psdIOs ++ debugIOs) + } + + /** + * Add IO cells to a serial module and name the IO ports. + * @param serial A SerialIO bundle + * @return Returns a tuple of (Top-level SerialIO IO; a list of IOCell module references) + */ + def serial(serial: SerialIO): (SerialIO, Seq[IOCell]) = { + val (port, ios) = IOCell.generateIOFromSignal(serial, Some("iocell_serial")) + port.suggestName("serial") + (port, ios) + } +} + +// DOC include start: WithGPIOTiedOff class WithGPIOTiedOff extends OverrideIOBinder({ - (c, r, s, top: HasPeripheryGPIOModuleImp) => top.gpio.map(gpio => gpio.pins.map(p => p.i.ival := false.B)); Nil + (system: HasPeripheryGPIOModuleImp) => { + val (ports2d, ioCells2d) = AddIOCells.gpio(system.gpio) + val harnessFn = (th: chipyard.TestHarness) => { ports2d.flatten.foreach(_ <> AnalogConst(0)); Nil } + Seq((ports2d.flatten, ioCells2d.flatten, Some(harnessFn))) + } +}) +// DOC include end: WithGPIOTiedOff + +class WithUARTAdapter extends OverrideIOBinder({ + (system: HasPeripheryUARTModuleImp) => { + val (ports, ioCells2d) = AddIOCells.uart(system.uart) + val harnessFn = (th: chipyard.TestHarness) => { UARTAdapter.connect(ports)(system.p); Nil } + Seq((ports, ioCells2d.flatten, Some(harnessFn))) + } }) class WithSimBlockDevice extends OverrideIOBinder({ - (c, r, s, top: CanHavePeripheryBlockDeviceModuleImp) => top.connectSimBlockDevice(c, r); Nil + (system: CanHavePeripheryBlockDeviceModuleImp) => system.connectSimBlockDevice(system.clock, system.reset.asBool); Nil }) class WithBlockDeviceModel extends OverrideIOBinder({ - (c, r, s, top: CanHavePeripheryBlockDeviceModuleImp) => top.connectBlockDeviceModel(); Nil + (system: CanHavePeripheryBlockDeviceModuleImp) => system.connectBlockDeviceModel(); Nil }) class WithLoopbackNIC extends OverrideIOBinder({ - (c, r, s, top: CanHavePeripheryIceNICModuleImp) => top.connectNicLoopback(); Nil + (system: CanHavePeripheryIceNICModuleImp) => system.connectNicLoopback(); Nil }) class WithSimNIC extends OverrideIOBinder({ - (c, r, s, top: CanHavePeripheryIceNICModuleImp) => top.connectSimNetwork(c, r); Nil -}) - -class WithUARTAdapter extends OverrideIOBinder({ - (c, r, s, top: HasPeripheryUARTModuleImp) => { - val defaultBaudRate = 115200 // matches sifive-blocks uart baudrate - top.uart.zipWithIndex.foreach{ case (dut_io, i) => - val uart_sim = Module(new UARTAdapter(i, defaultBaudRate)(top.p)) - uart_sim.io.uart.txd := dut_io.txd - dut_io.rxd := uart_sim.io.uart.rxd - } - Nil - } + (system: CanHavePeripheryIceNICModuleImp) => system.connectSimNetwork(system.clock, system.reset.asBool); Nil }) // DOC include start: WithSimAXIMem class WithSimAXIMem extends OverrideIOBinder({ - (c, r, s, top: CanHaveMasterAXI4MemPortModuleImp) => top.connectSimAXIMem(); Nil + (system: CanHaveMasterAXI4MemPortModuleImp) => system.connectSimAXIMem(); Nil }) // DOC include end: WithSimAXIMem class WithBlackBoxSimMem extends OverrideIOBinder({ - (clock, reset, _, top: CanHaveMasterAXI4MemPortModuleImp) => { - (top.mem_axi4 zip top.outer.memAXI4Node).foreach { case (io, node) => - val memSize = top.p(ExtMem).get.master.size - val lineSize = top.p(CacheBlockBytes) + (system: CanHaveMasterAXI4MemPortModuleImp) => { + (system.mem_axi4 zip system.outer.memAXI4Node).foreach { case (io, node) => + val memSize = system.p(ExtMem).get.master.size + val lineSize = system.p(CacheBlockBytes) (io zip node.in).foreach { case (axi4, (_, edge)) => val mem = Module(new SimDRAM(memSize, lineSize, edge.bundle)) mem.io.axi <> axi4 - mem.io.clock := clock - mem.io.reset := reset + mem.io.clock := system.clock + mem.io.reset := system.reset } }; Nil } }) class WithSimAXIMMIO extends OverrideIOBinder({ - (c, r, s, top: CanHaveMasterAXI4MMIOPortModuleImp) => top.connectSimAXIMMIO(); Nil + (system: CanHaveMasterAXI4MMIOPortModuleImp) => system.connectSimAXIMMIO(); Nil }) class WithDontTouchPorts extends OverrideIOBinder({ - (c, r, s, top: DontTouch) => top.dontTouchPorts(); Nil + (system: DontTouch) => system.dontTouchPorts(); Nil }) class WithTieOffInterrupts extends OverrideIOBinder({ - (c, r, s, top: HasExtInterruptsBundle) => top.tieOffInterrupts(); Nil + (system: HasExtInterruptsModuleImp) => { + val (port, ioCells) = IOCell.generateIOFromSignal(system.interrupts, Some("iocell_interrupts")) + port.suggestName("interrupts") + val harnessFn = (th: chipyard.TestHarness) => { port := 0.U; Nil } + Seq((Seq(port), ioCells, Some(harnessFn))) + } }) class WithTieOffL2FBusAXI extends OverrideIOBinder({ - (c, r, s, top: CanHaveSlaveAXI4PortModuleImp) => { - top.l2_frontend_bus_axi4.foreach(axi => { + (system: CanHaveSlaveAXI4PortModuleImp) => { + system.l2_frontend_bus_axi4.foreach(axi => { axi.tieoff() experimental.DataMirror.directionOf(axi.ar.ready) match { case ActualDirection.Input => @@ -142,6 +226,7 @@ class WithTieOffL2FBusAXI extends OverrideIOBinder({ axi.aw.bits := DontCare axi.ar.bits := DontCare axi.w.bits := DontCare + case _ => throw new Exception("Unknown AXI port direction") } }) Nil @@ -149,38 +234,62 @@ class WithTieOffL2FBusAXI extends OverrideIOBinder({ }) class WithTiedOffDebug extends OverrideIOBinder({ - (c, r, s, top: HasPeripheryDebugModuleImp) => { - Debug.tieoffDebug(top.debug, top.psd) - // tieoffDebug doesn't actually tie everything off :/ - top.debug.foreach(_.clockeddmi.foreach({ cdmi => cdmi.dmi.req.bits := DontCare })) - Nil + (system: HasPeripheryDebugModuleImp) => { + val (psdPort, debugPortOpt, ioCells) = AddIOCells.debug(system.psd, system.debug) + val harnessFn = (th: chipyard.TestHarness) => { + Debug.tieoffDebug(debugPortOpt, psdPort) + // tieoffDebug doesn't actually tie everything off :/ + debugPortOpt.foreach(_.clockeddmi.foreach({ cdmi => cdmi.dmi.req.bits := DontCare })) + Nil + } + Seq((Seq(psdPort) ++ debugPortOpt.toSeq, ioCells, Some(harnessFn))) } }) -class WithSimSerial extends OverrideIOBinder({ - (c, r, s, top: CanHavePeripherySerialModuleImp) => { - val ser_success = top.connectSimSerial() - when (ser_success) { s := true.B } - Nil +class WithSimDebug extends OverrideIOBinder({ + (system: HasPeripheryDebugModuleImp) => { + val (psdPort, debugPortOpt, ioCells) = AddIOCells.debug(system.psd, system.debug) + val harnessFn = (th: chipyard.TestHarness) => { + val dtm_success = Wire(Bool()) + Debug.connectDebug(debugPortOpt, psdPort, th.clock, th.harnessReset, dtm_success)(system.p) + when (dtm_success) { th.success := true.B } + th.dutReset := th.harnessReset | debugPortOpt.map { debug => AsyncResetReg(debug.ndreset).asBool }.getOrElse(false.B) + Nil + } + Seq((Seq(psdPort) ++ debugPortOpt.toSeq, ioCells, Some(harnessFn))) } }) class WithTiedOffSerial extends OverrideIOBinder({ - (c, r, s, top: CanHavePeripherySerialModuleImp) => top.tieoffSerial(); Nil + (system: CanHavePeripherySerialModuleImp) => system.serial.map({ serial => + val (port, ioCells) = AddIOCells.serial(serial) + val harnessFn = (th: chipyard.TestHarness) => { + SerialAdapter.tieoff(port) + Nil + } + Seq((Seq(port), ioCells, Some(harnessFn))) + }).getOrElse(Nil) }) +class WithSimSerial extends OverrideIOBinder({ + (system: CanHavePeripherySerialModuleImp) => system.serial.map({ serial => + val (port, ioCells) = AddIOCells.serial(serial) + val harnessFn = (th: chipyard.TestHarness) => { + val ser_success = SerialAdapter.connectSimSerial(port, th.clock, th.harnessReset) + when (ser_success) { th.success := true.B } + Nil + } + Seq((Seq(port), ioCells, Some(harnessFn))) + }).getOrElse(Nil) +}) -class WithSimDebug extends OverrideIOBinder({ - (c, r, s, top: HasPeripheryDebugModuleImp) => { - val dtm_success = Wire(Bool()) - top.reset := r | top.debug.map { debug => AsyncResetReg(debug.ndreset) }.getOrElse(false.B) - Debug.connectDebug(top.debug, top.psd, c, r, dtm_success)(top.p) - when (dtm_success) { s := true.B } - Nil +class WithTraceGenSuccessBinder extends OverrideIOBinder({ + (system: HasTraceGenTilesModuleImp) => { + val (successPort, ioCells) = IOCell.generateIOFromSignal(system.success, Some("iocell_success")) + successPort.suggestName("success") + val harnessFn = (th: chipyard.TestHarness) => { when (successPort) { th.success := true.B }; Nil } + Seq((Seq(successPort), ioCells, Some(harnessFn))) } }) - -class WithTraceGenSuccessBinder extends OverrideIOBinder({ - (c, r, s, top: HasTraceGenTilesModuleImp) => when (top.success) { s := true.B }; Nil -}) +} diff --git a/generators/chipyard/src/main/scala/TestHarness.scala b/generators/chipyard/src/main/scala/TestHarness.scala index ca861288..4aaef747 100644 --- a/generators/chipyard/src/main/scala/TestHarness.scala +++ b/generators/chipyard/src/main/scala/TestHarness.scala @@ -1,23 +1,21 @@ package chipyard import chisel3._ -import chisel3.experimental._ -import firrtl.transforms.{BlackBoxResourceAnno, BlackBoxSourceHelper} - -import freechips.rocketchip.diplomacy.LazyModule +import freechips.rocketchip.diplomacy.{LazyModule} import freechips.rocketchip.config.{Field, Parameters} -import freechips.rocketchip.util.GeneratorApp -import freechips.rocketchip.devices.debug.{Debug} - +import chipyard.iobinders.{TestHarnessFunction} import chipyard.config.ConfigValName._ -import chipyard.iobinders.{IOBinders} // ------------------------------- // BOOM and/or Rocket Test Harness // ------------------------------- -case object BuildTop extends Field[Parameters => Any]((p: Parameters) => Module(LazyModule(new Top()(p)).suggestName("top").module)) +case object BuildTop extends Field[Parameters => HasTestHarnessFunctions]((p: Parameters) => Module(new ChipTop()(p))) + +trait HasTestHarnessFunctions { + val harnessFunctions: Seq[TestHarnessFunction] +} class TestHarness(implicit val p: Parameters) extends Module { val io = IO(new Bundle { @@ -26,5 +24,15 @@ class TestHarness(implicit val p: Parameters) extends Module { val dut = p(BuildTop)(p) io.success := false.B - p(IOBinders).values.map(fn => fn(clock, reset.asBool, io.success, dut)) + + // dutReset can be overridden via a harnessFunction, but by default it is just reset + val dutReset = Wire(Bool()) + dutReset := reset + + dut.harnessFunctions.foreach(_(this)) + + def success = io.success + def harnessReset = this.reset.asBool + } + diff --git a/generators/chipyard/src/main/scala/ArianeConfigs.scala b/generators/chipyard/src/main/scala/config/ArianeConfigs.scala similarity index 100% rename from generators/chipyard/src/main/scala/ArianeConfigs.scala rename to generators/chipyard/src/main/scala/config/ArianeConfigs.scala diff --git a/generators/chipyard/src/main/scala/config/RocketConfigs.scala b/generators/chipyard/src/main/scala/config/RocketConfigs.scala index 954c531b..e25680ca 100644 --- a/generators/chipyard/src/main/scala/config/RocketConfigs.scala +++ b/generators/chipyard/src/main/scala/config/RocketConfigs.scala @@ -364,6 +364,7 @@ class ScratchpadRocketConfig extends Config( new freechips.rocketchip.system.BaseConfig) // DOC include end: scratchpadrocket +// DOC include start: RingSystemBusRocket class RingSystemBusRocketConfig extends Config( new chipyard.iobinders.WithUARTAdapter ++ new chipyard.iobinders.WithTieOffInterrupts ++ @@ -382,3 +383,4 @@ class RingSystemBusRocketConfig extends Config( new freechips.rocketchip.subsystem.WithNExtTopInterrupts(0) ++ new freechips.rocketchip.subsystem.WithNBigCores(1) ++ new freechips.rocketchip.system.BaseConfig) +// DOC include end: RingSystemBusRocket diff --git a/generators/chipyard/src/main/scala/config/TracegenConfigs.scala b/generators/chipyard/src/main/scala/config/TracegenConfigs.scala index ead38869..fefa271d 100644 --- a/generators/chipyard/src/main/scala/config/TracegenConfigs.scala +++ b/generators/chipyard/src/main/scala/config/TracegenConfigs.scala @@ -6,21 +6,21 @@ import freechips.rocketchip.rocket.{DCacheParams} class TraceGenConfig extends Config( new chipyard.iobinders.WithBlackBoxSimMem ++ new chipyard.iobinders.WithTraceGenSuccessBinder ++ - new chipyard.config.WithTracegenTop ++ + new chipyard.config.WithTracegenSystem ++ new tracegen.WithTraceGen(List.fill(2) { DCacheParams(nMSHRs = 0, nSets = 16, nWays = 2) }) ++ new freechips.rocketchip.system.BaseConfig) class NonBlockingTraceGenConfig extends Config( new chipyard.iobinders.WithBlackBoxSimMem ++ new chipyard.iobinders.WithTraceGenSuccessBinder ++ - new chipyard.config.WithTracegenTop ++ + new chipyard.config.WithTracegenSystem ++ new tracegen.WithTraceGen(List.fill(2) { DCacheParams(nMSHRs = 2, nSets = 16, nWays = 2) }) ++ new freechips.rocketchip.system.BaseConfig) class BoomTraceGenConfig extends Config( new chipyard.iobinders.WithBlackBoxSimMem ++ new chipyard.iobinders.WithTraceGenSuccessBinder ++ - new chipyard.config.WithTracegenTop ++ + new chipyard.config.WithTracegenSystem ++ new tracegen.WithBoomTraceGen(List.fill(2) { DCacheParams(nMSHRs = 8, nSets = 16, nWays = 2) }) ++ new freechips.rocketchip.subsystem.WithInclusiveCache ++ new freechips.rocketchip.system.BaseConfig) @@ -28,7 +28,7 @@ class BoomTraceGenConfig extends Config( class NonBlockingTraceGenL2Config extends Config( new chipyard.iobinders.WithBlackBoxSimMem ++ new chipyard.iobinders.WithTraceGenSuccessBinder ++ - new chipyard.config.WithTracegenTop ++ + new chipyard.config.WithTracegenSystem ++ new tracegen.WithL2TraceGen(List.fill(2)(DCacheParams(nMSHRs = 2, nSets = 16, nWays = 4))) ++ new freechips.rocketchip.subsystem.WithInclusiveCache ++ new freechips.rocketchip.system.BaseConfig) @@ -36,7 +36,7 @@ class NonBlockingTraceGenL2Config extends Config( class NonBlockingTraceGenL2RingConfig extends Config( new chipyard.iobinders.WithBlackBoxSimMem ++ new chipyard.iobinders.WithTraceGenSuccessBinder ++ - new chipyard.config.WithTracegenTop ++ + new chipyard.config.WithTracegenSystem ++ new tracegen.WithL2TraceGen(List.fill(2)(DCacheParams(nMSHRs = 2, nSets = 16, nWays = 4))) ++ new testchipip.WithRingSystemBus ++ new freechips.rocketchip.subsystem.WithInclusiveCache ++ diff --git a/generators/firechip/src/main/scala/BridgeBinders.scala b/generators/firechip/src/main/scala/BridgeBinders.scala index 4276890b..bd19ee98 100644 --- a/generators/firechip/src/main/scala/BridgeBinders.scala +++ b/generators/firechip/src/main/scala/BridgeBinders.scala @@ -7,10 +7,11 @@ import chisel3.experimental.annotate import freechips.rocketchip.config.{Field, Config, Parameters} import freechips.rocketchip.diplomacy.{LazyModule} -import freechips.rocketchip.devices.debug.HasPeripheryDebugModuleImp -import freechips.rocketchip.subsystem.{CanHaveMasterAXI4MemPortModuleImp} +import freechips.rocketchip.devices.debug.{Debug, HasPeripheryDebugModuleImp} +import freechips.rocketchip.subsystem.{CanHaveMasterAXI4MemPortModuleImp, HasExtInterruptsModuleImp} import freechips.rocketchip.tile.{RocketTile} import sifive.blocks.devices.uart.HasPeripheryUARTModuleImp +import sifive.blocks.devices.gpio.{HasPeripheryGPIOModuleImp} import testchipip.{CanHavePeripherySerialModuleImp, CanHavePeripheryBlockDeviceModuleImp, CanHaveTraceIOModuleImp} import icenet.CanHavePeripheryIceNICModuleImp @@ -30,75 +31,63 @@ import chipyard.HasChipyardTilesModuleImp object MainMemoryConsts { val regionNamePrefix = "MainMemory" - def globalName(): String = s"${regionNamePrefix}_${NodeIdx()}" + def globalName = s"${regionNamePrefix}_${NodeIdx()}" } class WithSerialBridge extends OverrideIOBinder({ - (c, r, s, target: CanHavePeripherySerialModuleImp) => - target.serial.map(s => SerialBridge(target.clock, s, MainMemoryConsts.globalName)(target.p)).toSeq + (system: CanHavePeripherySerialModuleImp) => + system.serial.foreach(s => SerialBridge(system.clock, s, MainMemoryConsts.globalName)(system.p)); Nil }) class WithNICBridge extends OverrideIOBinder({ - (c, r, s, target: CanHavePeripheryIceNICModuleImp) => - target.net.map(n => NICBridge(target.clock, n)(target.p)).toSeq + (system: CanHavePeripheryIceNICModuleImp) => + system.net.foreach(n => NICBridge(system.clock, n)(system.p)); Nil }) class WithUARTBridge extends OverrideIOBinder({ - (c, r, s, target: HasPeripheryUARTModuleImp) => - target.uart.map(u => UARTBridge(target.clock, u)(target.p)).toSeq + (system: HasPeripheryUARTModuleImp) => + system.uart.foreach(u => UARTBridge(system.clock, u)(system.p)); Nil }) class WithBlockDeviceBridge extends OverrideIOBinder({ - (c, r, s, target: CanHavePeripheryBlockDeviceModuleImp) => - target.bdev.map(b => BlockDevBridge(target.clock, b, target.reset.toBool)(target.p)).toSeq + (system: CanHavePeripheryBlockDeviceModuleImp) => + system.bdev.foreach(b => BlockDevBridge(system.clock, b, system.reset.toBool)(system.p)); Nil }) -// Assign a unique name to each target memory space, consisting of one or more -// memory channels. In the multi-node case, serial widgets can then disambiguate -// each memory region using this string instead of relying on the assumption -// the target has a single memory channel. -object MemoryRegionNames { - var idx = -1 - def getName(): String = { - idx += 1 - s"memory_${idx}" - } -} -class WithFASEDBridge extends OverrideIOBinder ({ - (c, r, s, t: CanHaveMasterAXI4MemPortModuleImp) => { - implicit val p = t.p - (t.mem_axi4 zip t.outer.memAXI4Node).flatMap({ case (io, node) => +class WithFASEDBridge extends OverrideIOBinder({ + (system: CanHaveMasterAXI4MemPortModuleImp) => { + implicit val p = system.p + (system.mem_axi4 zip system.outer.memAXI4Node).flatMap({ case (io, node) => (io zip node.in).map({ case (axi4Bundle, (_, edge)) => val nastiKey = NastiParameters(axi4Bundle.r.bits.data.getWidth, axi4Bundle.ar.bits.addr.getWidth, axi4Bundle.ar.bits.id.getWidth) - FASEDBridge(t.clock, axi4Bundle, t.reset.toBool, + FASEDBridge(system.clock, axi4Bundle, system.reset.toBool, CompleteConfig(p(firesim.configs.MemModelKey), nastiKey, Some(AXI4EdgeSummary(edge)), Some(MainMemoryConsts.globalName))) }) - }).toSeq + }) + Nil } }) class WithTracerVBridge extends OverrideIOBinder({ - (c, r, s, target: CanHaveTraceIOModuleImp) => target.traceIO match { - case Some(t) => t.traces.map(tileTrace => TracerVBridge(tileTrace)(target.p)) - case None => Nil - } + (system: CanHaveTraceIOModuleImp) => + system.traceIO.foreach(_.traces.map(tileTrace => TracerVBridge(tileTrace)(system.p))); Nil }) class WithTraceGenBridge extends OverrideIOBinder({ - (c, r, s, target: HasTraceGenTilesModuleImp) => - Seq(GroundTestBridge(target.clock, target.success)(target.p)) + (system: HasTraceGenTilesModuleImp) => + GroundTestBridge(system.clock, system.success)(system.p); Nil }) class WithFireSimMultiCycleRegfile extends ComposeIOBinder({ - (c, r, s, target: HasChipyardTilesModuleImp) => { - target.outer.tiles.map { + (system: HasChipyardTilesModuleImp) => { + system.outer.tiles.map { case r: RocketTile => { annotate(MemModelAnnotation(r.module.core.rocketImpl.rf.rf)) r.module.fpuOpt.foreach(fpu => annotate(MemModelAnnotation(fpu.fpuImpl.regfile))) @@ -120,13 +109,31 @@ class WithFireSimMultiCycleRegfile extends ComposeIOBinder({ } }) +class WithTiedOffSystemGPIO extends OverrideIOBinder({ + (system: HasPeripheryGPIOModuleImp) => + system.gpio.foreach(_.pins.foreach(_.i.ival := false.B)); Nil +}) + +class WithTiedOffSystemDebug extends OverrideIOBinder({ + (system: HasPeripheryDebugModuleImp) => { + Debug.tieoffDebug(system.debug, system.psd) + // tieoffDebug doesn't actually tie everything off :/ + system.debug.foreach(_.clockeddmi.foreach({ cdmi => cdmi.dmi.req.bits := DontCare })) + Nil + } +}) + +class WithTiedOffSystemInterrupts extends OverrideIOBinder({ + (system: HasExtInterruptsModuleImp) => + system.interrupts := 0.U; Nil +}) // Shorthand to register all of the provided bridges above class WithDefaultFireSimBridges extends Config( - new chipyard.iobinders.WithGPIOTiedOff ++ - new chipyard.iobinders.WithTiedOffDebug ++ - new chipyard.iobinders.WithTieOffInterrupts ++ + new WithTiedOffSystemGPIO ++ + new WithTiedOffSystemDebug ++ + new WithTiedOffSystemInterrupts ++ new WithSerialBridge ++ new WithNICBridge ++ new WithUARTBridge ++ diff --git a/generators/firechip/src/main/scala/FireSim.scala b/generators/firechip/src/main/scala/FireSim.scala index 0cd8f410..fc65f136 100644 --- a/generators/firechip/src/main/scala/FireSim.scala +++ b/generators/firechip/src/main/scala/FireSim.scala @@ -9,7 +9,7 @@ import freechips.rocketchip.diplomacy.{LazyModule} import midas.widgets.{Bridge, PeekPokeBridge, RationalClockBridge} -import chipyard.{BuildTop} +import chipyard.{BuildSystem} import chipyard.iobinders.{IOBinders} // Determines the number of times to instantiate the DUT in the harness. @@ -34,14 +34,14 @@ class FireSim(implicit val p: Parameters) extends RawModule { val reset = WireInit(false.B) withClockAndReset(clock, reset) { // Instantiate multiple instances of the DUT to implement supernode - val targets = Seq.fill(p(NumNodes))(p(BuildTop)(p)) + val targets = Seq.fill(p(NumNodes))(p(BuildSystem)(p)) val peekPokeBridge = PeekPokeBridge(clock, reset) // A Seq of partial functions that will instantiate the right bridge only // if that Mixin trait is present in the target's class instance // // Apply each partial function to each DUT instance - for (target <- targets) { - p(IOBinders).values.map(fn => fn(clock, reset.asBool, false.B, target)) + for ((target) <- targets) { + p(IOBinders).values.map(_(target)) NodeIdx.increment() } } diff --git a/generators/firechip/src/main/scala/FireSimMulticlockPOC.scala b/generators/firechip/src/main/scala/FireSimMulticlockPOC.scala index 318e3547..b16f99c7 100644 --- a/generators/firechip/src/main/scala/FireSimMulticlockPOC.scala +++ b/generators/firechip/src/main/scala/FireSimMulticlockPOC.scala @@ -14,7 +14,7 @@ import boom.common.{BoomTilesKey, BoomCrossingKey} import midas.widgets.{Bridge, PeekPokeBridge, RationalClockBridge, RationalClock} import firesim.configs._ -import chipyard.{BuildTop, Top, TopModule} +import chipyard.{BuildSystem, DigitalTop, DigitalTopModule} import chipyard.config.ConfigValName._ import chipyard.iobinders.{IOBinders} @@ -64,7 +64,7 @@ class WithSingleRationalTileDomain(multiplier: Int, divisor: Int) extends Config class HalfRateUncore extends WithSingleRationalTileDomain(2,1) class WithFiresimMulticlockTop extends Config((site, here, up) => { - case BuildTop => (p: Parameters) => Module(LazyModule(new FiresimMulticlockTop()(p)).suggestName("Top").module) + case BuildSystem => (p: Parameters) => Module(LazyModule(new FiresimMulticlockTop()(p)).suggestName("system").module) }) // Complete Config @@ -74,12 +74,12 @@ class FireSimQuadRocketMulticlockConfig extends Config( new FireSimQuadRocketConfig) // Top Definition -class FiresimMulticlockTop(implicit p: Parameters) extends chipyard.Top +class FiresimMulticlockTop(implicit p: Parameters) extends chipyard.DigitalTop { override lazy val module = new FiresimMulticlockTopModule(this) } -class FiresimMulticlockTopModule[+L <: Top](l: L) extends chipyard.TopModule(l) with HasFireSimClockingImp +class FiresimMulticlockTopModule[+L <: DigitalTop](l: L) extends chipyard.DigitalTopModule(l) with HasFireSimClockingImp // Harness Definition class FireSimMulticlockPOC(implicit val p: Parameters) extends RawModule { @@ -88,14 +88,14 @@ class FireSimMulticlockPOC(implicit val p: Parameters) extends RawModule { val reset = WireInit(false.B) withClockAndReset(refClock, reset) { // Instantiate multiple instances of the DUT to implement supernode - val targets = Seq.fill(p(NumNodes))(p(BuildTop)(p)) + val targets = Seq.fill(p(NumNodes))(p(BuildSystem)(p)) val peekPokeBridge = PeekPokeBridge(refClock, reset) // A Seq of partial functions that will instantiate the right bridge only // if that Mixin trait is present in the target's class instance // // Apply each partial function to each DUT instance for ((target) <- targets) { - p(IOBinders).values.map(fn => fn(refClock, reset.asBool, false.B, target)) + p(IOBinders).values.map(_(target)) } targets.collect({ case t: HasAdditionalClocks => t.clocks := clockBridge.io.clocks }) } diff --git a/generators/firechip/src/main/scala/TargetConfigs.scala b/generators/firechip/src/main/scala/TargetConfigs.scala index 1f9791ee..04d9a8f6 100644 --- a/generators/firechip/src/main/scala/TargetConfigs.scala +++ b/generators/firechip/src/main/scala/TargetConfigs.scala @@ -24,7 +24,6 @@ import testchipip.WithRingSystemBus import firesim.bridges._ import firesim.configs._ -import chipyard.{BuildTop} import chipyard.config.ConfigValName._ class WithBootROM extends Config((site, here, up) => { diff --git a/generators/icenet b/generators/icenet index f2272284..b1f957e6 160000 --- a/generators/icenet +++ b/generators/icenet @@ -1 +1 @@ -Subproject commit f22722847444ecfcd5369f1b33547727d051b834 +Subproject commit b1f957e6eb022c662f0fb33c7ddfbddc686bfde5 diff --git a/generators/testchipip b/generators/testchipip index 30d44252..d06d7c7d 160000 --- a/generators/testchipip +++ b/generators/testchipip @@ -1 +1 @@ -Subproject commit 30d44252e8a990da38f1fed6ac6c810fb42dae28 +Subproject commit d06d7c7dc274420a5fc5600ba8bdb2003cc9b0cd diff --git a/generators/tracegen/tracegen.mk b/generators/tracegen/tracegen.mk new file mode 100644 index 00000000..fc4bd246 --- /dev/null +++ b/generators/tracegen/tracegen.mk @@ -0,0 +1,18 @@ +############################################################## +# extra variables/targets ingested by the chipyard make system +############################################################## + +AXE_DIR=$(base_dir)/tools/axe/src +AXE=$(AXE_DIR)/axe + +$(AXE): $(wildcard $(AXE_DIR)/*.[ch]) $(AXE_DIR)/make.sh + cd $(AXE_DIR) && ./make.sh + +$(output_dir)/tracegen.out: $(sim) + mkdir -p $(output_dir) && $(sim) $(PERMISSIVE_ON) $(SIM_FLAGS) $(EXTRA_SIM_FLAGS) $(VERBOSE_FLAGS) $(PERMISSIVE_OFF) none $@ + +$(output_dir)/tracegen.result: $(output_dir)/tracegen.out $(AXE) + $(base_dir)/scripts/check-tracegen.sh $< > $@ + +.PHONY: tracegen +tracegen: $(output_dir)/tracegen.result diff --git a/scripts/tutorial-patches/build.sbt.patch b/scripts/tutorial-patches/build.sbt.patch index 422c59c8..6f20a3ce 100644 --- a/scripts/tutorial-patches/build.sbt.patch +++ b/scripts/tutorial-patches/build.sbt.patch @@ -5,7 +5,7 @@ index a633066..3df8b74 100644 @@ -124,7 +124,7 @@ lazy val testchipip = (project in file("generators/testchipip")) lazy val chipyard = conditionalDependsOn(project in file("generators/chipyard")) - .dependsOn(boom, hwacha, sifive_blocks, sifive_cache, utilities, + .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 gemmini, icenet, tracegen, ariane) diff --git a/sims/firesim b/sims/firesim index 998eeaea..a4f0a18c 160000 --- a/sims/firesim +++ b/sims/firesim @@ -1 +1 @@ -Subproject commit 998eeaea230884584dd3fe2bd3727c5f30abc3cb +Subproject commit a4f0a18c0aa1690a57dd888be6bc48f52fbc074c diff --git a/sims/vcs/Makefile b/sims/vcs/Makefile index e829047c..659d1fc0 100644 --- a/sims/vcs/Makefile +++ b/sims/vcs/Makefile @@ -50,7 +50,8 @@ VCS_CC_OPTS = \ -CC "-I$(dramsim_dir)" \ -CC "-std=c++11" \ $(dramsim_lib) \ - $(RISCV)/lib/libfesvr.a + $(RISCV)/lib/libfesvr.a \ + -CC "$(EXTRA_SIM_CC_FLAGS)" VCS_NONCC_OPTS = \ +lint=all,noVCDE,noONGS,noUI \ @@ -80,16 +81,16 @@ VCS_DEFINES = \ +define+RANDOMIZE_GARBAGE_ASSIGN \ +define+RANDOMIZE_INVALID_ASSIGN -VCS_OPTS = -notice -line $(VCS_CC_OPTS) $(VCS_NONCC_OPTS) $(VCS_DEFINES) +VCS_OPTS = -notice -line $(VCS_CC_OPTS) $(VCS_NONCC_OPTS) $(VCS_DEFINES) $(EXTRA_SIM_SOURCES) ######################################################################################### # vcs simulator rules ######################################################################################### -$(sim): $(sim_vsrcs) $(sim_common_files) $(dramsim_lib) +$(sim): $(sim_vsrcs) $(sim_common_files) $(dramsim_lib) $(EXTRA_SIM_REQS) rm -rf csrc && $(VCS) $(VCS_OPTS) -o $@ \ -debug_pp -$(sim_debug): $(sim_vsrcs) $(sim_common_files) $(dramsim_lib) +$(sim_debug): $(sim_vsrcs) $(sim_common_files) $(dramsim_lib) $(EXTRA_SIM_REQS) rm -rf csrc && $(VCS) $(VCS_OPTS) -o $@ \ +define+DEBUG \ -debug_pp @@ -99,7 +100,7 @@ $(sim_debug): $(sim_vsrcs) $(sim_common_files) $(dramsim_lib) ######################################################################################### .PRECIOUS: $(output_dir)/%.vpd %.vpd $(output_dir)/%.vpd: $(output_dir)/% $(sim_debug) - (set -o pipefail && $(sim_debug) $(PERMISSIVE_ON) +max-cycles=$(timeout_cycles) $(SIM_FLAGS) $(VERBOSE_FLAGS) +vcdplusfile=$@ $(PERMISSIVE_OFF) $< >(spike-dasm > $<.out) | tee $<.log) + (set -o pipefail && $(sim_debug) $(PERMISSIVE_ON) $(SIM_FLAGS) $(EXTRA_SIM_FLAGS) $(VERBOSE_FLAGS) +vcdplusfile=$@ $(PERMISSIVE_OFF) $< >(spike-dasm > $<.out) | tee $<.log) ######################################################################################### # general cleanup rule diff --git a/sims/verilator/Makefile b/sims/verilator/Makefile index 13e7d201..8bd4cd75 100644 --- a/sims/verilator/Makefile +++ b/sims/verilator/Makefile @@ -47,14 +47,25 @@ include $(base_dir)/common.mk ######################################################################################### VERILATOR := verilator --cc --exe -CXXFLAGS := $(CXXFLAGS) -O1 -std=c++11 -I$(RISCV)/include -I$(dramsim_dir) -D__STDC_FORMAT_MACROS -LDFLAGS := $(LDFLAGS) -L$(RISCV)/lib -Wl,-rpath,$(RISCV)/lib -L$(dramsim_dir) -Wl,-rpath,$(dramsim_dir) -L$(sim_dir) -lfesvr -lpthread -ldramsim +CXXFLAGS := \ + $(CXXFLAGS) -O1 -std=c++11 \ + -I$(RISCV)/include \ + -I$(dramsim_dir) \ + -D__STDC_FORMAT_MACROS \ + $(EXTRA_SIM_CC_FLAGS) + +LDFLAGS := \ + $(LDFLAGS) \ + -L$(sim_dir) \ + -lpthread VERILATOR_CC_OPTS = \ -O3 \ -CFLAGS "$(CXXFLAGS) -DTEST_HARNESS=V$(VLOG_MODEL) -DVERILATOR" \ -CFLAGS "-I$(build_dir) -include $(build_dir)/$(long_name).plusArgs -include $(build_dir)/verilator.h" \ - -LDFLAGS "$(LDFLAGS)" + -LDFLAGS "$(LDFLAGS)" \ + $(RISCV)/lib/libfesvr.a \ + $(dramsim_lib) # default flags added for ariane ARIANE_VERILATOR_FLAGS = \ @@ -87,7 +98,7 @@ VERILATOR_DEFINES = \ +define+PRINTF_COND=\$$c\(\"verbose\",\"\&\&\"\,\"done_reset\"\) \ +define+STOP_COND=\$$c\(\"done_reset\"\) -VERILATOR_OPTS = $(VERILATOR_CC_OPTS) $(VERILATOR_NONCC_OPTS) $(VERILATOR_DEFINES) +VERILATOR_OPTS = $(VERILATOR_CC_OPTS) $(VERILATOR_NONCC_OPTS) $(VERILATOR_DEFINES) $(EXTRA_SIM_SOURCES) ######################################################################################### # verilator build paths and file names @@ -104,13 +115,13 @@ model_mk_debug = $(model_dir_debug)/V$(VLOG_MODEL).mk ######################################################################################### # build makefile fragment that builds the verilator sim rules ######################################################################################### -$(model_mk): $(sim_vsrcs) $(sim_common_files) +$(model_mk): $(sim_vsrcs) $(sim_common_files) $(EXTRA_SIM_REQS) rm -rf $(build_dir)/$(long_name) mkdir -p $(build_dir)/$(long_name) $(VERILATOR) $(VERILATOR_OPTS) -o $(sim) -Mdir $(model_dir) -CFLAGS "-include $(model_header)" touch $@ -$(model_mk_debug): $(sim_vsrcs) $(sim_common_files) +$(model_mk_debug): $(sim_vsrcs) $(sim_common_files) $(EXTRA_SIM_REQS) rm -rf $(build_dir)/$(long_name) mkdir -p $(build_dir)/$(long_name).debug $(VERILATOR) $(VERILATOR_OPTS) -o $(sim_debug) --trace -Mdir $(model_dir_debug) -CFLAGS "-include $(model_header_debug)" @@ -132,7 +143,7 @@ $(sim_debug): $(model_mk_debug) $(dramsim_lib) $(output_dir)/%.vpd: $(output_dir)/% $(sim_debug) rm -f $@.vcd && mkfifo $@.vcd vcd2vpd $@.vcd $@ > /dev/null & - (set -o pipefail && $(sim_debug) $(PERMISSIVE_ON) +max-cycles=$(timeout_cycles) $(SIM_FLAGS) $(VERBOSE_FLAGS) -v$@.vcd $(PERMISSIVE_OFF) $< >(spike-dasm > $<.out) | tee $<.log) + (set -o pipefail && $(sim_debug) $(PERMISSIVE_ON) $(SIM_FLAGS) $(EXTRA_SIM_FLAGS) $(VERBOSE_FLAGS) -v$@.vcd $(PERMISSIVE_OFF) $< >(spike-dasm > $<.out) | tee $<.log) ######################################################################################### # general cleanup rule diff --git a/software/spec2017 b/software/spec2017 index b8643136..a4333f24 160000 --- a/software/spec2017 +++ b/software/spec2017 @@ -1 +1 @@ -Subproject commit b86431364360a9e64487e5dec2962c48bafb67ff +Subproject commit a4333f243cef6bfff08bcbb08f3ec467b4c720d0 diff --git a/tools/barstools b/tools/barstools index 63d74bc1..db677636 160000 --- a/tools/barstools +++ b/tools/barstools @@ -1 +1 @@ -Subproject commit 63d74bc177cb070126eb0e662ff0ea500722a8d7 +Subproject commit db6776367c7a8f4850266d72f81cd4c90561731a diff --git a/variables.mk b/variables.mk index 8a1bb1df..4953c968 100644 --- a/variables.mk +++ b/variables.mk @@ -36,7 +36,7 @@ ifeq ($(SUB_PROJECT),chipyard) CONFIG_PACKAGE ?= $(SBT_PROJECT) GENERATOR_PACKAGE ?= $(SBT_PROJECT) TB ?= TestDriver - TOP ?= Top + TOP ?= ChipTop endif # for Rocket-chip developers ifeq ($(SUB_PROJECT),rocketchip) @@ -143,7 +143,7 @@ output_dir=$(sim_dir)/output/$(long_name) # helper variables to run binaries ######################################################################################### BINARY ?= -SIM_FLAGS ?= +override SIM_FLAGS += +dramsim +max-cycles=$(timeout_cycles) VERBOSE_FLAGS ?= +verbose sim_out_name = $(subst $() $(),_,$(notdir $(basename $(BINARY))).$(long_name))