This adds an additional layer (ChipTop) between the System module and the TestHarness. The IOBinder API is now changed to take only a single parameter (an Any) and return a 3 things: The IO port(s), the IO cell(s), and a function to call inside the test harness, which is analogous to the old IOBinder function, except that it takes a TestHarness object as an argument instead of (clock, reset, success). * A new Top-level module, ChipTop, has been created. ChipTop instantiates a "system" module specified by BuildSystem. * BuildTop now builds a ChipTop dut module in the TestHarness by default * A new BuildSystem key has been added, which by default builds DigitalTop (previously just called Top) * The IOBinders API has changed. IOBinders are now called inside of ChipTop and return a tuple3 of (IO ports, IO cells, harness functions). The harness functions are now called inside the TestHarness (this is analogous to the previous IOBinder functions). * IO cell models have been included in ChipTop. These can be replaced with real IO cells for tapeout, or used as-is for simulation. * The default for the TOP make variable is now ChipTop (was Top)
42 lines
3.1 KiB
ReStructuredText
42 lines
3.1 KiB
ReStructuredText
IOBinders
|
|
=========
|
|
|
|
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
|
|
:start-after: DOC include start: IOBinders
|
|
:end-before: DOC include end: IOBinders
|
|
|
|
|
|
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.
|
|
|
|
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``.
|
|
|
|
.. 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
|
|
:start-after: DOC include start: WithSimAXIMem
|
|
:end-before: DOC include end: WithSimAXIMem
|
|
|
|
These classes are all ``Config`` objects, which can be mixed into the configs to specify IO connection behaviors.
|
|
|
|
There are two macros for generating these ``Config``s. ``OverrideIOBinder`` overrides any existing behaviors set for a particular IO in the ``Config`` object. This macro is frequently used because typically top-level IOs drive or are driven by only one source, so a composition of ``IOBinders`` does not make sense. The ``ComposeIOBinder`` macro provides the functionality of not overriding existing behaviors.
|