Merge remote-tracking branch 'origin/dev' into diplomatic-bridges

This commit is contained in:
David Biancolin
2020-04-06 23:59:19 -07:00
40 changed files with 573 additions and 240 deletions

View File

@@ -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:

View File

@@ -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

View File

@@ -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)

View File

@@ -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) </dev/null 2> >(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) </dev/null 2> >(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) </dev/null | tee $(sim_out_name).log)
(set -o pipefail && $(sim) $(PERMISSIVE_ON) $(SIM_FLAGS) $(EXTRA_SIM_FLAGS) $(PERMISSIVE_OFF) $(BINARY) </dev/null | tee $(sim_out_name).log)
#########################################################################################
# helper rules to run simulator with as much debug info as possible
#########################################################################################
run-binary-debug: $(sim_debug)
(set -o pipefail && $(sim_debug) $(PERMISSIVE_ON) +max-cycles=$(timeout_cycles) $(SIM_FLAGS) $(VERBOSE_FLAGS) $(WAVEFORM_FLAG) $(PERMISSIVE_OFF) $(BINARY) </dev/null 2> >(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) </dev/null 2> >(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) $< </dev/null | tee $<.log) && touch $@
(set -o pipefail && $(sim) $(PERMISSIVE_ON) $(SIM_FLAGS) $(EXTRA_SIM_FLAGS) $(PERMISSIVE_OFF) $< </dev/null | tee $<.log) && touch $@
$(output_dir)/%.out: $(output_dir)/% $(sim)
(set -o pipefail && $(sim) $(PERMISSIVE_ON) +dramsim +max-cycles=$(timeout_cycles) $(VERBOSE_FLAGS) $(PERMISSIVE_OFF) $< </dev/null 2> >(spike-dasm > $@) | tee $<.log)
(set -o pipefail && $(sim) $(PERMISSIVE_ON) $(SIM_FLAGS) $(EXTRA_SIM_FLAGS) $(VERBOSE_FLAGS) $(PERMISSIVE_OFF) $< </dev/null 2> >(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 </dev/null 2> $@
$(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 #
#######################################

View File

@@ -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

View File

@@ -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<X>`` 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

View File

@@ -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).

View File

@@ -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

View File

@@ -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
----------------

View File

@@ -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.

View File

@@ -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
-------------------

View File

@@ -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

View File

@@ -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 <https://github.com/ucb-bar/testchipip/blob/master/src/main/scala/Unittests.scala>`_.
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 <https://github.com/ucb-bar/testchipip/blob/master/src/main/scala/Ring.scala>`_,
and may serve as an example of how to implement your own TileLink network with
a different topology.
UART Adapter
------------

View File

@@ -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

View File

@@ -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:**

View File

@@ -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.

View File

@@ -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 <https://hammer-vlsi.readthedocs.io/>`__.
For an example of how to use the VLSI in the context of Chipyard, see :ref:`ASAP7 Tutorial`.

View File

@@ -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

View File

@@ -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"))
})

View File

@@ -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

View File

@@ -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
})
}

View File

@@ -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
}

View File

@@ -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

View File

@@ -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 ++

View File

@@ -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 ++

View File

@@ -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()
}
}

View File

@@ -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 })
}

View File

@@ -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) => {

View File

@@ -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 </dev/null 2> $@
$(output_dir)/tracegen.result: $(output_dir)/tracegen.out $(AXE)
$(base_dir)/scripts/check-tracegen.sh $< > $@
.PHONY: tracegen
tracegen: $(output_dir)/tracegen.result

View File

@@ -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)

View File

@@ -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) $< </dev/null 2> >(spike-dasm > $<.out) | tee $<.log)
(set -o pipefail && $(sim_debug) $(PERMISSIVE_ON) $(SIM_FLAGS) $(EXTRA_SIM_FLAGS) $(VERBOSE_FLAGS) +vcdplusfile=$@ $(PERMISSIVE_OFF) $< </dev/null 2> >(spike-dasm > $<.out) | tee $<.log)
#########################################################################################
# general cleanup rule

View File

@@ -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) $< </dev/null 2> >(spike-dasm > $<.out) | tee $<.log)
(set -o pipefail && $(sim_debug) $(PERMISSIVE_ON) $(SIM_FLAGS) $(EXTRA_SIM_FLAGS) $(VERBOSE_FLAGS) -v$@.vcd $(PERMISSIVE_OFF) $< </dev/null 2> >(spike-dasm > $<.out) | tee $<.log)
#########################################################################################
# general cleanup rule

View File

@@ -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))