Merge branch 'dev' into diplomatic-clocks
This commit is contained in:
@@ -104,7 +104,7 @@ $(TOP_TARGETS) $(HARNESS_TARGETS): firrtl_temp
|
||||
@echo "" > /dev/null
|
||||
|
||||
firrtl_temp: $(FIRRTL_FILE) $(ANNO_FILE) $(VLOG_SOURCES)
|
||||
$(call run_scala_main,tapeout,barstools.tapeout.transforms.GenerateTopAndHarness,-o $(TOP_FILE) -tho $(HARNESS_FILE) -i $(FIRRTL_FILE) --syn-top $(TOP) --harness-top $(VLOG_MODEL) -faf $(ANNO_FILE) -tsaof $(TOP_ANNO) -tdf $(sim_top_blackboxes) -tsf $(TOP_FIR) -thaof $(HARNESS_ANNO) -hdf $(sim_harness_blackboxes) -thf $(HARNESS_FIR) $(REPL_SEQ_MEM) $(HARNESS_CONF_FLAGS) -td $(build_dir)) && touch $(sim_top_blackboxes) $(sim_harness_blackboxes)
|
||||
$(call run_scala_main,tapeout,barstools.tapeout.transforms.GenerateTopAndHarness,-o $(TOP_FILE) -tho $(HARNESS_FILE) -i $(FIRRTL_FILE) --syn-top $(TOP) --harness-top $(VLOG_MODEL) -faf $(ANNO_FILE) -tsaof $(TOP_ANNO) -tdf $(sim_top_blackboxes) -tsf $(TOP_FIR) -thaof $(HARNESS_ANNO) -hdf $(sim_harness_blackboxes) -thf $(HARNESS_FIR) $(REPL_SEQ_MEM) $(HARNESS_CONF_FLAGS) -td $(build_dir) -ll $(FIRRTL_LOGLEVEL)) && touch $(sim_top_blackboxes) $(sim_harness_blackboxes)
|
||||
# DOC include end: FirrtlCompiler
|
||||
|
||||
# This file is for simulation only. VLSI flows should replace this file with one containing hard SRAMs
|
||||
|
||||
301
docs/Customization/Custom-Core.rst
Normal file
301
docs/Customization/Custom-Core.rst
Normal file
@@ -0,0 +1,301 @@
|
||||
.. _custom_core:
|
||||
|
||||
Adding a custom core
|
||||
====================
|
||||
|
||||
You may want to integrate a custom RISC-V core into the Chipyard framework. This documentation page provides step-by-step
|
||||
instructions on how to achieve this.
|
||||
|
||||
.. note::
|
||||
|
||||
RoCC is currently not supported by cores other than Rocket and BOOM. Please use Rocket or BOOM as the RoCC base core if you need to use RoCC.
|
||||
|
||||
.. note::
|
||||
|
||||
This page contains links to the files that contains important definitions in the Rocket chip repository, which is maintained separately
|
||||
from Chipyard. If you find any discrepancy between the code on this page and the code in the source file, please report it through
|
||||
GitHub issues!
|
||||
|
||||
Wrap Verilog Module with Blackbox (Optional)
|
||||
--------------------------------------------
|
||||
|
||||
Since Chipyard uses Scala and Chisel, if the top module of your core is not in Chisel, you will first need to create a Verilog
|
||||
blackbox for it so that it can be processed by Chipyard. See :ref:`incorporating-verilog-blocks` for instructions.
|
||||
|
||||
Create Parameter Case Classes
|
||||
-----------------------------
|
||||
|
||||
Chipyard will generate a core for every ``InstantiableTileParams`` object it discovered in the ``TilesLocated(InSubsystem)`` key.
|
||||
This object is derived from``TileParams``, a trait containing the information needed to create a tile. All cores must have
|
||||
their own implementation of ``InstantiableTileParams``, as well as ``CoreParams`` which is passed as a field in ``TileParams``.
|
||||
|
||||
``TileParams`` holds the parameters for the tile, which include parameters for all components in the tile (e.g.
|
||||
core, cache, MMU, etc.), while ``CoreParams`` contains parameters specific to the core on the tile.
|
||||
They must be implemented as case classes with fields that can be overridden by
|
||||
other config fragments as the constructor parameters. See the appendix at the bottom of the page for a list of
|
||||
variable to be implemented. You can also add custom fields to them, but standard fields should always be preferred.
|
||||
|
||||
``InstantiableTileParams[TileType]`` holds the constructor of ``TileType`` on top of the fields of ``TileParams``,
|
||||
where ``TileType`` is the tile class (see the next section).
|
||||
All custom cores will also need to implement ``instantiate()`` in their tile parameter class to return a new instance
|
||||
of the tile class ``TileType``.
|
||||
|
||||
``TileParams`` (in the file `BaseTile.scala <https://github.com/chipsalliance/rocket-chip/blob/master/src/main/scala/tile/BaseTile.scala>`_) ,
|
||||
``InstantiableTileParams`` (in the file `BaseTile.scala <https://github.com/chipsalliance/rocket-chip/blob/master/src/main/scala/tile/BaseTile.scala>`_),
|
||||
``CoreParams`` (in the file `Core.scala <https://github.com/chipsalliance/rocket-chip/blob/master/src/main/scala/tile/Core.scala>`_),
|
||||
and ``FPUParams`` (in the file `FPU.scala <https://github.com/chipsalliance/rocket-chip/blob/master/src/main/scala/tile/FPU.scala>`_)
|
||||
contains the following fields:
|
||||
|
||||
.. code-block:: scala
|
||||
|
||||
trait TileParams {
|
||||
val core: CoreParams // Core parameters (see below)
|
||||
val icache: Option[ICacheParams] // Rocket specific: I1 cache option
|
||||
val dcache: Option[DCacheParams] // Rocket specific: D1 cache option
|
||||
val btb: Option[BTBParams] // Rocket specific: BTB / branch predictor option
|
||||
val hartId: Int // Hart ID: Must be unique within a design config (This MUST be a case class parameter)
|
||||
val beuAddr: Option[BigInt] // Rocket specific: Bus Error Unit for Rocket Core
|
||||
val blockerCtrlAddr: Option[BigInt] // Rocket specific: Bus Blocker for Rocket Core
|
||||
val name: Option[String] // Name of the core
|
||||
}
|
||||
|
||||
abstract class InstantiableTileParams[TileType <: BaseTile] extends TileParams {
|
||||
def instantiate(crossing: TileCrossingParamsLike, lookup: LookupByHartIdImpl)
|
||||
(implicit p: Parameters): TileType
|
||||
}
|
||||
|
||||
trait CoreParams {
|
||||
val bootFreqHz: BigInt // Frequency
|
||||
val useVM: Boolean // Support virtual memory
|
||||
val useUser: Boolean // Support user mode
|
||||
val useSupervisor: Boolean // Support supervisor mode
|
||||
val useDebug: Boolean // Support RISC-V debug specs
|
||||
val useAtomics: Boolean // Support A extension
|
||||
val useAtomicsOnlyForIO: Boolean // Support A extension for memory-mapped IO (may be true even if useAtomics is false)
|
||||
val useCompressed: Boolean // Support C extension
|
||||
val useVector: Boolean = false // Support V extension
|
||||
val useSCIE: Boolean // Support custom instructions (in custom-0 and custom-1)
|
||||
val useRVE: Boolean // Use E base ISA
|
||||
val mulDiv: Option[MulDivParams] // *Rocket specific: M extension related setting (Use Some(MulDivParams()) to indicate M extension supported)
|
||||
val fpu: Option[FPUParams] // F and D extensions and related setting (see below)
|
||||
val fetchWidth: Int // Max # of insts fetched every cycle
|
||||
val decodeWidth: Int // Max # of insts decoded every cycle
|
||||
val retireWidth: Int // Max # of insts retired every cycle
|
||||
val instBits: Int // Instruction bits (if 32 bit and 64 bit are both supported, use 64)
|
||||
val nLocalInterrupts: Int // # of local interrupts (see SiFive interrupt cookbook)
|
||||
val nPMPs: Int // # of Physical Memory Protection units
|
||||
val pmpGranularity: Int // Size of the smallest unit of region for PMP unit (must be power of 2)
|
||||
val nBreakpoints: Int // # of hardware breakpoints supported (in RISC-V debug specs)
|
||||
val useBPWatch: Boolean // Support hardware breakpoints
|
||||
val nPerfCounters: Int // # of supported performance counters
|
||||
val haveBasicCounters: Boolean // Support basic counters defined in the RISC-V counter extension
|
||||
val haveFSDirty: Boolean // If true, the core will set FS field in mstatus CSR to dirty when appropriate
|
||||
val misaWritable: Boolean // Support writable misa CSR (like variable instruction bits)
|
||||
val haveCFlush: Boolean // Rocket specific: enables Rocket's custom instruction extension to flush the cache
|
||||
val nL2TLBEntries: Int // # of L2 TLB entries
|
||||
val mtvecInit: Option[BigInt] // mtvec CSR (of V extension) initial value
|
||||
val mtvecWritable: Boolean // If mtvec CSR is writable
|
||||
|
||||
// Normally, you don't need to change these values (except lrscCycles)
|
||||
def customCSRs(implicit p: Parameters): CustomCSRs = new CustomCSRs
|
||||
|
||||
def hasSupervisorMode: Boolean = useSupervisor || useVM
|
||||
def instBytes: Int = instBits / 8
|
||||
def fetchBytes: Int = fetchWidth * instBytes
|
||||
// Rocket specific: Longest possible latency of Rocket core D1 cache. Simply set it to the default value 80 if you don't use it.
|
||||
def lrscCycles: Int
|
||||
|
||||
def dcacheReqTagBits: Int = 6
|
||||
|
||||
def minFLen: Int = 32
|
||||
def vLen: Int = 0
|
||||
def sLen: Int = 0
|
||||
def eLen(xLen: Int, fLen: Int): Int = xLen max fLen
|
||||
def vMemDataBits: Int = 0
|
||||
}
|
||||
|
||||
case class FPUParams(
|
||||
minFLen: Int = 32, // Minimum floating point length (no need to change)
|
||||
fLen: Int = 64, // Maximum floating point length, use 32 if only single precision is supported
|
||||
divSqrt: Boolean = true, // Div/Sqrt operation supported
|
||||
sfmaLatency: Int = 3, // Rocket specific: Fused multiply-add pipeline latency (single precision)
|
||||
dfmaLatency: Int = 4 // Rocket specific: Fused multiply-add pipeline latency (double precision)
|
||||
)
|
||||
|
||||
Most of the fields here (marked "Rocket spcific") are originally designed for the Rocket core and thus contain some
|
||||
implementation-specific details, but many of them are general enough to be useful for other cores. You may ignore
|
||||
any fields marked "Rocket specific" and use their default values; however, if you need to store additional information
|
||||
with meaning or usage similar to these "Rocket specific" fields, it is recommended to use these fields instead of
|
||||
creating your own custom fields.
|
||||
|
||||
You will also need a ``CanAttachTile`` class to add the tile config into the config system, with the following format:
|
||||
|
||||
.. literalinclude:: ../../generators/chipyard/src/main/scala/example/TutorialTile.scala
|
||||
:language: scala
|
||||
:start-after: DOC include start: CanAttachTile
|
||||
:end-before: DOC include end: CanAttachTile
|
||||
|
||||
During elaboration, Chipyard will look for subclasses of ``CanAttachTile`` in the config system and instantiate a tile
|
||||
from the parameters in this class for every such class it found.
|
||||
|
||||
.. note::
|
||||
|
||||
Implementations may choose to ignore some fields here or use them in a non-standard way, but using an inaccurate
|
||||
value may break Chipyard components that rely on them (e.g. an inaccurate indication of supported ISA extension will
|
||||
result in an incorrect test suite being generated) as well as any custom modules that use them. ALWAYS document any
|
||||
fields you ignore or with altered usage in your core implementation, and if you are implementing other devices that
|
||||
would look up these config values, also document them. "Rocket specific" values are generally safe to ignore, but
|
||||
you should document them if you use them.
|
||||
|
||||
Create Tile Class
|
||||
-----------------
|
||||
|
||||
In Chipyard, all Tiles are diplomatically instantiated. In the first phase, diplomatic nodes which specify Tile-to-System
|
||||
interconnects are evaluated, while in the second "Module Implementation" phase, hardware is elaborated.
|
||||
See :ref:`tilelink_and_diplomacy` for more details. In this step, you will need to implement a tile class for your core,
|
||||
which specifies the constraints on the core's parameters and the connections with other diplomatic nodes. This class
|
||||
usually contains Diplomacy/TileLink code only, and Chisel RTL code should not go here.
|
||||
|
||||
All tile classes implement ``BaseTile`` and will normally implement ``SinksExternalInterrupts`` and ``SourcesExternalNotifications``,
|
||||
which allow the tile to accept external interrupt. A typical tile has the following form:
|
||||
|
||||
.. literalinclude:: ../../generators/chipyard/src/main/scala/example/TutorialTile.scala
|
||||
:language: scala
|
||||
:start-after: DOC include start: Tile class
|
||||
:end-before: DOC include end: Tile class
|
||||
|
||||
Connect TileLink Buses
|
||||
----------------------
|
||||
|
||||
Chipyard uses TileLink as its onboard bus protocol. If your core doesn't use TileLink, you will need to insert converters
|
||||
between the core's memory protocol and TileLink within the Tile module.
|
||||
in the tile class. Below is an example of how to connect a core using AXI4 to the TileLink bus with converters provided by
|
||||
Rocket chip:
|
||||
|
||||
.. literalinclude:: ../../generators/chipyard/src/main/scala/example/TutorialTile.scala
|
||||
:language: scala
|
||||
:start-after: DOC include start: AXI4 convert
|
||||
:end-before: DOC include end: AXI4 convert
|
||||
|
||||
Remember, you may not need all of these intermediate widgets. See :ref:`diplomatic_widgets` for the meaning of each intermediate
|
||||
widget. If you are using TileLink, then you only need the tap node and the TileLink node used by your components. Chipyard also
|
||||
provides converters for AHB, APB and AXIS, and most of the AXI4 widgets has equivalent widget for these bus protocol; see the
|
||||
source files in ``generators/rocket-chip/src/main/scala/amba`` for more info.
|
||||
|
||||
If you are using some other bus protocol, you may implement your own converters, using the files in ``generators/rocket-chip/src/main/scala/amba``
|
||||
as the template, but it is not recommended unless you are familiar with TileLink.
|
||||
|
||||
``memAXI4Node`` is an AXI4 master node and is defined as following in our example:
|
||||
|
||||
.. literalinclude:: ../../generators/chipyard/src/main/scala/example/TutorialTile.scala
|
||||
:language: scala
|
||||
:start-after: DOC include start: AXI4 node
|
||||
:end-before: DOC include end: AXI4 node
|
||||
|
||||
where ``portName`` and ``idBits`` (number of bits to represent a port ID) are the parameter provides by the tile.
|
||||
Make sure to read :ref:`node_types` to check out what type of nodes Chipyard supports and their parameters!
|
||||
|
||||
Also, by default, there are boundary buffers for both master and slave connections to the bus when they are leaving the tile, and you
|
||||
can override the following two functions to control how to buffer the bus requests/responses:
|
||||
(You can find the definition of these two functions in the class ``BaseTile`` in the file
|
||||
`BaseTile.scala <https://github.com/chipsalliance/rocket-chip/blob/master/src/main/scala/tile/BaseTile.scala>`_)
|
||||
|
||||
.. code-block:: scala
|
||||
|
||||
// By default, their value is "TLBuffer(BufferParams.none)".
|
||||
protected def makeMasterBoundaryBuffers(implicit p: Parameters): TLBuffer
|
||||
protected def makeSlaveBoundaryBuffers(implicit p: Parameters): TLBuffer
|
||||
|
||||
You can find more information on ``TLBuffer`` in :ref:`diplomatic_widgets`.
|
||||
|
||||
Create Implementation Class
|
||||
---------------------------
|
||||
|
||||
The implementation class contains the parameterized, actual hardware that depends on the values resolved by the Diplomacy
|
||||
framework according to the info provided in the Tile class. This class will normally contains Chisel RTL code. If your
|
||||
core is in Verilog, you will need to instantiate the black box class that wraps your Verilog implementation and connect it with the buses
|
||||
and other components. No Diplomacy/TileLink code should be in this class; you should only connect the IO signals in TileLink
|
||||
interfaces or other diplomatically defined components, which are located in the tile class.
|
||||
|
||||
The implementation class for your core is of the following form:
|
||||
|
||||
.. literalinclude:: ../../generators/chipyard/src/main/scala/example/TutorialTile.scala
|
||||
:language: scala
|
||||
:start-after: DOC include start: Implementation class
|
||||
:end-before: DOC include end: Implementation class
|
||||
|
||||
If you create an AXI4 node (or equivalents), you will need to connect them to your core. You can connect a port like this:
|
||||
|
||||
.. literalinclude:: ../../generators/chipyard/src/main/scala/example/TutorialTile.scala
|
||||
:language: scala
|
||||
:start-after: DOC include start: AXI4 connect
|
||||
:end-before: DOC include end: AXI4 connect
|
||||
|
||||
Connect Interrupt
|
||||
-----------------
|
||||
|
||||
Chipyard allows a tile to either receive interrupts from other devices or initiate interrupts to notify other cores/devices.
|
||||
In the tile that inherited ``SinksExternalInterrupts``, one can create a ``TileInterrupts`` object (a Chisel bundle) and
|
||||
call ``decodeCoreInterrupts()`` with the object as the argument. Note that you should call this function in the implementation
|
||||
class since it returns a Chisel bundle used by RTL code. You can then read the interrupt bits from the ``TileInterrupts`` bundle
|
||||
we create above. The definition of ``TileInterrupts``
|
||||
(in the file `Interrupts.scala <https://github.com/chipsalliance/rocket-chip/blob/master/src/main/scala/tile/Interrupts.scala>`_) is
|
||||
|
||||
.. code-block:: scala
|
||||
|
||||
class TileInterrupts(implicit p: Parameters) extends CoreBundle()(p) {
|
||||
val debug = Bool() // debug interrupt
|
||||
val mtip = Bool() // Machine level timer interrupt
|
||||
val msip = Bool() // Machine level software interrupt
|
||||
val meip = Bool() // Machine level external interrupt
|
||||
val seip = usingSupervisor.option(Bool()) // Valid only if supervisor mode is supported
|
||||
val lip = Vec(coreParams.nLocalInterrupts, Bool()) // Local interrupts
|
||||
}
|
||||
|
||||
Here is an example on how to connect these signals in the implementation class:
|
||||
|
||||
.. literalinclude:: ../../generators/chipyard/src/main/scala/example/TutorialTile.scala
|
||||
:language: scala
|
||||
:start-after: DOC include start: connect interrupt
|
||||
:end-before: DOC include end: connect interrupt
|
||||
|
||||
Also, the tile can also notify other cores or devices for some events by calling following functions in ``SourcesExternalNotifications``
|
||||
from the implementation class:
|
||||
(These functions can be found in in the trait ``SourcesExternalNotifications`` in the file
|
||||
`Interrupts.scala <https://github.com/chipsalliance/rocket-chip/blob/master/src/main/scala/tile/Interrupts.scala>`_)
|
||||
|
||||
.. code-block:: scala
|
||||
|
||||
def reportHalt(could_halt: Option[Bool]) // Triggered when there is an unrecoverable hardware error (halt the machine)
|
||||
def reportHalt(errors: Seq[CanHaveErrors]) // Varient for standard error bundle (Rocket specific: used only by cache when there's an ECC error)
|
||||
def reportCease(could_cease: Option[Bool], quiescenceCycles: Int = 8) // Triggered when the core stop retiring instructions (like clock gating)
|
||||
def reportWFI(could_wfi: Option[Bool]) // Triggered when a WFI instruction is executed
|
||||
|
||||
Here is an example on how to use these functions to raise interrupt.
|
||||
|
||||
.. literalinclude:: ../../generators/chipyard/src/main/scala/example/TutorialTile.scala
|
||||
:language: scala
|
||||
:start-after: DOC include start: raise interrupt
|
||||
:end-before: DOC include end: raise interrupt
|
||||
|
||||
Create Config Fragments to Integrate the Core
|
||||
---------------------------------------------
|
||||
|
||||
To use your core in a Chipyard config, you will need a config fragment that will create a ``TileParams`` object of your core in
|
||||
the current config. An example of such config will be like this:
|
||||
|
||||
.. literalinclude:: ../../generators/chipyard/src/main/scala/example/TutorialTile.scala
|
||||
:language: scala
|
||||
:start-after: DOC include start: Config fragment
|
||||
:end-before: DOC include end: Config fragment
|
||||
|
||||
Chipyard looks up the tile parameters in the field ``TilesLocated(InSubsystem)``, whose type is a list of ``InstantiableTileParams``.
|
||||
This config fragment simply appends new tile parameters to the end of this list.
|
||||
|
||||
Now you have finished all the steps to prepare your cores for Chipyard! To generate the custom core, simply follow the instructions
|
||||
in :ref:`custom_chisel` to add your project to the build system, then create a config by following the steps in :ref:`hetero_socs_`.
|
||||
You can now run most desired workflows for the new config just as you would for the built-in cores (depending on the functionality your core supports).
|
||||
|
||||
If you would like to see an example of a complete third-party Verilog core integrated into Chipyard, ``generators/ariane/src/main/scala/ArianeTile.scala``
|
||||
provides a concrete example of the Ariane core. Note that this particular example includes additional nuances with respect to the interaction of the AXI
|
||||
interface with the memory coherency system.
|
||||
@@ -1,3 +1,5 @@
|
||||
.. _hetero_socs_:
|
||||
|
||||
Heterogeneous SoCs
|
||||
===============================
|
||||
|
||||
|
||||
@@ -7,6 +7,8 @@ These guides will walk you through customization of your system-on-chip:
|
||||
|
||||
- How to include your custom Chisel sources in the Chipyard build system
|
||||
|
||||
- Adding custom core
|
||||
|
||||
- Adding custom RoCC accelerators to an existing Chipyard core (BOOM or Rocket)
|
||||
|
||||
- Adding custom MMIO widgets to the Chipyard memory system by Tilelink or AXI4, with custom Top-level IOs
|
||||
@@ -35,6 +37,7 @@ We recommend reading all these pages in order. Hit next to get started!
|
||||
|
||||
Heterogeneous-SoCs
|
||||
Custom-Chisel
|
||||
Custom-Core
|
||||
RoCC-or-MMIO
|
||||
RoCC-Accelerators
|
||||
MMIO-Peripherals
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
.. _node_types:
|
||||
|
||||
TileLink Node Types
|
||||
===================
|
||||
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
.. _diplomatic_widgets:
|
||||
|
||||
Diplomatic Widgets
|
||||
==================
|
||||
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
.. _tilelink_and_diplomacy:
|
||||
|
||||
TileLink and Diplomacy Reference
|
||||
================================
|
||||
|
||||
|
||||
@@ -25,7 +25,7 @@ import sifive.blocks.devices.gpio._
|
||||
import sifive.blocks.devices.uart._
|
||||
import sifive.blocks.devices.spi._
|
||||
|
||||
import chipyard.{BuildTop, BuildSystem, ClockDrivers, ChipyardClockKey}
|
||||
import chipyard.{BuildTop, BuildSystem, ClockDrivers, ChipyardClockKey, TestSuitesKey, TestSuiteHelper}
|
||||
|
||||
|
||||
// -----------------------
|
||||
@@ -44,9 +44,9 @@ class WithGPIO extends Config((site, here, up) => {
|
||||
})
|
||||
// DOC include end: gpio config fragment
|
||||
|
||||
class WithUART extends Config((site, here, up) => {
|
||||
class WithUART(baudrate: BigInt = 115200) extends Config((site, here, up) => {
|
||||
case PeripheryUARTKey => Seq(
|
||||
UARTParams(address = 0x54000000L, nTxEntries = 256, nRxEntries = 256))
|
||||
UARTParams(address = 0x54000000L, nTxEntries = 256, nRxEntries = 256, initBaudRate = baudrate))
|
||||
})
|
||||
|
||||
class WithSPIFlash(size: BigInt = 0x10000000) extends Config((site, here, up) => {
|
||||
@@ -92,17 +92,19 @@ class WithMultiRoCC extends Config((site, here, up) => {
|
||||
*
|
||||
* @param harts harts to specify which will get a Hwacha
|
||||
*/
|
||||
class WithMultiRoCCHwacha(harts: Int*) extends Config((site, here, up) => {
|
||||
case MultiRoCCKey => {
|
||||
up(MultiRoCCKey, site) ++ harts.distinct.map{ i =>
|
||||
(i -> Seq((p: Parameters) => {
|
||||
val hwacha = LazyModule(new Hwacha()(p))
|
||||
hwacha
|
||||
}))
|
||||
class WithMultiRoCCHwacha(harts: Int*) extends Config(
|
||||
new chipyard.config.WithHwachaTest ++
|
||||
new Config((site, here, up) => {
|
||||
case MultiRoCCKey => {
|
||||
up(MultiRoCCKey, site) ++ harts.distinct.map{ i =>
|
||||
(i -> Seq((p: Parameters) => {
|
||||
val hwacha = LazyModule(new Hwacha()(p)).suggestName("hwacha")
|
||||
hwacha
|
||||
}))
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
})
|
||||
)
|
||||
|
||||
class WithTraceIO extends Config((site, here, up) => {
|
||||
case TilesLocated(InSubsystem) => up(TilesLocated(InSubsystem), site) map {
|
||||
@@ -137,6 +139,18 @@ class WithRocketDCacheScratchpad extends Config((site, here, up) => {
|
||||
}
|
||||
})
|
||||
|
||||
class WithHwachaTest extends Config((site, here, up) => {
|
||||
case TestSuitesKey => (tileParams: Seq[TileParams], suiteHelper: TestSuiteHelper, p: Parameters) => {
|
||||
up(TestSuitesKey).apply(tileParams, suiteHelper, p)
|
||||
import hwacha.HwachaTestSuites._
|
||||
suiteHelper.addSuites(rv64uv.map(_("p")))
|
||||
suiteHelper.addSuites(rv64uv.map(_("vp")))
|
||||
suiteHelper.addSuite(rv64sv("p"))
|
||||
suiteHelper.addSuite(hwachaBmarks)
|
||||
"SRC_EXTENSION = $(base_dir)/hwacha/$(src_path)/*.scala" + "\nDISASM_EXTENSION = --extension=hwacha"
|
||||
}
|
||||
})
|
||||
|
||||
// The default RocketChip BaseSubsystem drives its diplomatic clock graph
|
||||
// with the implicit clocks of Subsystem. Don't do that, instead we extend
|
||||
// the diplomacy graph upwards into the ChipTop, where we connect it to
|
||||
|
||||
@@ -3,8 +3,8 @@ package chipyard
|
||||
import scala.collection.mutable.{LinkedHashSet}
|
||||
|
||||
import freechips.rocketchip.subsystem._
|
||||
import freechips.rocketchip.tile.{XLen}
|
||||
import freechips.rocketchip.config.{Parameters}
|
||||
import freechips.rocketchip.tile.{XLen, TileParams}
|
||||
import freechips.rocketchip.config.{Parameters, Field, Config}
|
||||
import freechips.rocketchip.system.{TestGeneration, RegressionTestSuite, RocketTestSuite}
|
||||
|
||||
import boom.common.{BoomTileAttachParams}
|
||||
@@ -64,133 +64,51 @@ class TestSuiteHelper
|
||||
def addSuites(s: Seq[RocketTestSuite]) { s.foreach(addSuite) }
|
||||
|
||||
/**
|
||||
* Add BOOM tests (asm, bmark, regression)
|
||||
* Add generic tests (asm, bmark, regression) for all cores.
|
||||
*/
|
||||
def addBoomTestSuites(implicit p: Parameters) = {
|
||||
def addGenericTestSuites(tiles: Seq[TileParams])(implicit p: Parameters) = {
|
||||
val xlen = p(XLen)
|
||||
p(TilesLocated(InSubsystem)).find(_.tileParams.hartId == 0).map {
|
||||
case tp: BoomTileAttachParams => {
|
||||
val tileParams = tp.tileParams
|
||||
val coreParams = tileParams.core
|
||||
val vm = coreParams.useVM
|
||||
val env = if (vm) List("p","v") else List("p")
|
||||
coreParams.fpu foreach { case cfg =>
|
||||
if (xlen == 32) {
|
||||
addSuites(env.map(rv32uf))
|
||||
if (cfg.fLen >= 64) {
|
||||
addSuites(env.map(rv32ud))
|
||||
}
|
||||
} else if (cfg.fLen >= 64) {
|
||||
tiles.find(_.hartId == 0).map { tileParams =>
|
||||
val coreParams = tileParams.core
|
||||
val vm = coreParams.useVM
|
||||
val env = if (vm) List("p","v") else List("p")
|
||||
coreParams.fpu foreach { case cfg =>
|
||||
if (xlen == 32) {
|
||||
addSuites(env.map(rv32uf))
|
||||
if (cfg.fLen >= 64)
|
||||
addSuites(env.map(rv32ud))
|
||||
} else {
|
||||
addSuite(rv32udBenchmarks)
|
||||
addSuites(env.map(rv64uf))
|
||||
if (cfg.fLen >= 64)
|
||||
addSuites(env.map(rv64ud))
|
||||
addSuites(env.map(rv64uf))
|
||||
addSuite(rv32udBenchmarks)
|
||||
}
|
||||
}
|
||||
if (coreParams.useAtomics) {
|
||||
if (tileParams.dcache.flatMap(_.scratch).isEmpty) {
|
||||
addSuites(env.map(if (xlen == 64) rv64ua else rv32ua))
|
||||
} else {
|
||||
addSuites(env.map(if (xlen == 64) rv64uaSansLRSC else rv32uaSansLRSC))
|
||||
}
|
||||
}
|
||||
if (coreParams.useCompressed) addSuites(env.map(if (xlen == 64) rv64uc else rv32uc))
|
||||
val (rvi, rvu) =
|
||||
if (xlen == 64) ((if (vm) rv64i else rv64pi), rv64u)
|
||||
else ((if (vm) rv32i else rv32pi), rv32u)
|
||||
|
||||
addSuites(rvi.map(_("p")))
|
||||
addSuites(rvu.map(_("p")))
|
||||
addSuites((if (vm) List("v") else List()).flatMap(env => rvu.map(_(env))))
|
||||
addSuite(benchmarks)
|
||||
addSuite(new RegressionTestSuite(if (xlen == 64) rv64RegrTestNames else rv32RegrTestNames))
|
||||
}
|
||||
case _ =>
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Add Rocket tests (asm, bmark, regression)
|
||||
*/
|
||||
def addRocketTestSuites(implicit p: Parameters) = {
|
||||
val xlen = p(XLen)
|
||||
p(TilesLocated(InSubsystem)).find(_.tileParams.hartId == 0).map {
|
||||
case tp: RocketTileAttachParams => {
|
||||
val tileParams = tp.tileParams
|
||||
val coreParams = tileParams.core
|
||||
val vm = coreParams.useVM
|
||||
val env = if (vm) List("p","v") else List("p")
|
||||
coreParams.fpu foreach { case cfg =>
|
||||
if (xlen == 32) {
|
||||
addSuites(env.map(rv32uf))
|
||||
if (cfg.fLen >= 64)
|
||||
addSuites(env.map(rv32ud))
|
||||
} else {
|
||||
addSuite(rv32udBenchmarks)
|
||||
addSuites(env.map(rv64uf))
|
||||
if (cfg.fLen >= 64)
|
||||
addSuites(env.map(rv64ud))
|
||||
}
|
||||
}
|
||||
if (coreParams.useAtomics) {
|
||||
if (tileParams.dcache.flatMap(_.scratch).isEmpty)
|
||||
addSuites(env.map(if (xlen == 64) rv64ua else rv32ua))
|
||||
else
|
||||
addSuites(env.map(if (xlen == 64) rv64uaSansLRSC else rv32uaSansLRSC))
|
||||
}
|
||||
if (coreParams.useCompressed) addSuites(env.map(if (xlen == 64) rv64uc else rv32uc))
|
||||
val (rvi, rvu) =
|
||||
if (xlen == 64) ((if (vm) rv64i else rv64pi), rv64u)
|
||||
else ((if (vm) rv32i else rv32pi), rv32u)
|
||||
|
||||
addSuites(rvi.map(_("p")))
|
||||
addSuites((if (vm) List("v") else List()).flatMap(env => rvu.map(_(env))))
|
||||
addSuite(benchmarks)
|
||||
addSuite(new RegressionTestSuite(if (xlen == 64) rv64RegrTestNames else rv32RegrTestNames))
|
||||
if (coreParams.useAtomics) {
|
||||
if (tileParams.dcache.flatMap(_.scratch).isEmpty)
|
||||
addSuites(env.map(if (xlen == 64) rv64ua else rv32ua))
|
||||
else
|
||||
addSuites(env.map(if (xlen == 64) rv64uaSansLRSC else rv32uaSansLRSC))
|
||||
}
|
||||
case _ =>
|
||||
}
|
||||
}
|
||||
if (coreParams.useCompressed) addSuites(env.map(if (xlen == 64) rv64uc else rv32uc))
|
||||
val (rvi, rvu) =
|
||||
if (xlen == 64) ((if (vm) rv64i else rv64pi), rv64u)
|
||||
else ((if (vm) rv32i else rv32pi), rv32u)
|
||||
|
||||
/**
|
||||
* Add Ariane tests (asm, bmark, regression)
|
||||
*/
|
||||
def addArianeTestSuites(implicit p: Parameters) = {
|
||||
val xlen = p(XLen)
|
||||
p(TilesLocated(InSubsystem)).find(_.tileParams.hartId == 0).map {
|
||||
case tp: ArianeTileAttachParams => {
|
||||
val tileParams = tp.tileParams
|
||||
val coreParams = tileParams.core
|
||||
val vm = coreParams.useVM
|
||||
val env = if (vm) List("p","v") else List("p")
|
||||
coreParams.fpu foreach { case cfg =>
|
||||
if (xlen == 32) {
|
||||
addSuites(env.map(rv32uf))
|
||||
if (cfg.fLen >= 64)
|
||||
addSuites(env.map(rv32ud))
|
||||
} else {
|
||||
addSuite(rv32udBenchmarks)
|
||||
addSuites(env.map(rv64uf))
|
||||
if (cfg.fLen >= 64)
|
||||
addSuites(env.map(rv64ud))
|
||||
}
|
||||
}
|
||||
if (coreParams.useAtomics) {
|
||||
if (tileParams.dcache.flatMap(_.scratch).isEmpty)
|
||||
addSuites(env.map(if (xlen == 64) rv64ua else rv32ua))
|
||||
else
|
||||
addSuites(env.map(if (xlen == 64) rv64uaSansLRSC else rv32uaSansLRSC))
|
||||
}
|
||||
if (coreParams.useCompressed) addSuites(env.map(if (xlen == 64) rv64uc else rv32uc))
|
||||
val (rvi, rvu) =
|
||||
if (xlen == 64) ((if (vm) rv64i else rv64pi), rv64u)
|
||||
else ((if (vm) rv32i else rv32pi), rv32u)
|
||||
|
||||
addSuites(rvi.map(_("p")))
|
||||
addSuites((if (vm) List("v") else List()).flatMap(env => rvu.map(_(env))))
|
||||
addSuite(benchmarks)
|
||||
addSuite(new RegressionTestSuite(if (xlen == 64) rv64RegrTestNames else rv32RegrTestNames))
|
||||
}
|
||||
case _ =>
|
||||
addSuites(rvi.map(_("p")))
|
||||
addSuites(rvu.map(_("p")))
|
||||
addSuites((if (vm) List("v") else List()).flatMap(env => rvu.map(_(env))))
|
||||
addSuite(benchmarks)
|
||||
addSuite(new RegressionTestSuite(if (xlen == 64) rv64RegrTestNames else rv32RegrTestNames))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Config key of custom test suite.
|
||||
*/
|
||||
case object TestSuitesKey extends Field[(Seq[TileParams], TestSuiteHelper, Parameters) => String]((tiles, helper, p) => {
|
||||
helper.addGenericTestSuites(tiles)(p)
|
||||
// Return an empty string as makefile additional snippets
|
||||
""
|
||||
})
|
||||
|
||||
@@ -19,7 +19,6 @@ class LargeBoomConfig extends Config(
|
||||
new chipyard.config.AbstractConfig)
|
||||
|
||||
class MegaBoomConfig extends Config(
|
||||
new boom.common.WithBoomBranchPrintf ++
|
||||
new boom.common.WithNMegaBooms(1) ++ // mega boom config
|
||||
new chipyard.config.AbstractConfig)
|
||||
|
||||
@@ -28,6 +27,7 @@ class DualSmallBoomConfig extends Config(
|
||||
new chipyard.config.AbstractConfig)
|
||||
|
||||
class HwachaLargeBoomConfig extends Config(
|
||||
new chipyard.config.WithHwachaTest ++
|
||||
new hwacha.DefaultHwachaConfig ++ // use Hwacha vector accelerator
|
||||
new boom.common.WithNLargeBooms(1) ++
|
||||
new chipyard.config.AbstractConfig)
|
||||
@@ -43,4 +43,3 @@ class DromajoBoomConfig extends Config(
|
||||
new chipyard.config.WithTraceIO ++ // enable the traceio
|
||||
new boom.common.WithNSmallBooms(1) ++
|
||||
new chipyard.config.AbstractConfig)
|
||||
|
||||
|
||||
@@ -13,6 +13,7 @@ class LargeBoomAndRocketConfig extends Config(
|
||||
|
||||
// DOC include start: BoomAndRocketWithHwacha
|
||||
class HwachaLargeBoomAndHwachaRocketConfig extends Config(
|
||||
new chipyard.config.WithHwachaTest ++
|
||||
new hwacha.DefaultHwachaConfig ++ // add hwacha to all harts
|
||||
new boom.common.WithNLargeBooms(1) ++ // add 1 boom core
|
||||
new freechips.rocketchip.subsystem.WithNBigCores(1) ++ // add 1 rocket core
|
||||
|
||||
@@ -11,6 +11,7 @@ class RocketConfig extends Config(
|
||||
new chipyard.config.AbstractConfig)
|
||||
|
||||
class HwachaRocketConfig extends Config(
|
||||
new chipyard.config.WithHwachaTest ++
|
||||
new hwacha.DefaultHwachaConfig ++ // use Hwacha vector accelerator
|
||||
new freechips.rocketchip.subsystem.WithNBigCores(1) ++
|
||||
new chipyard.config.AbstractConfig)
|
||||
|
||||
236
generators/chipyard/src/main/scala/example/TutorialTile.scala
Normal file
236
generators/chipyard/src/main/scala/example/TutorialTile.scala
Normal file
@@ -0,0 +1,236 @@
|
||||
package chipyard.example
|
||||
|
||||
import chisel3._
|
||||
import chisel3.util._
|
||||
|
||||
import freechips.rocketchip.config._
|
||||
import freechips.rocketchip.subsystem._
|
||||
import freechips.rocketchip.devices.tilelink._
|
||||
import freechips.rocketchip.diplomacy._
|
||||
import freechips.rocketchip.diplomaticobjectmodel.logicaltree.{LogicalTreeNode}
|
||||
import freechips.rocketchip.rocket._
|
||||
import freechips.rocketchip.subsystem.{RocketCrossingParams}
|
||||
import freechips.rocketchip.tilelink._
|
||||
import freechips.rocketchip.interrupts._
|
||||
import freechips.rocketchip.util._
|
||||
import freechips.rocketchip.tile._
|
||||
import freechips.rocketchip.amba.axi4._
|
||||
|
||||
// Example parameter class copied from Ariane, not included in documentation but for compile check only
|
||||
// If you are here for documentation, DO NOT copy MyCoreParams and MyTileParams directly - always figure
|
||||
// out what parameters you need before you write the parameter class
|
||||
case class MyCoreParams(
|
||||
bootFreqHz: BigInt = BigInt(1700000000),
|
||||
rasEntries: Int = 4,
|
||||
btbEntries: Int = 16,
|
||||
bhtEntries: Int = 16,
|
||||
enableToFromHostCaching: Boolean = false,
|
||||
) extends CoreParams {
|
||||
val useVM: Boolean = true
|
||||
val useUser: Boolean = true
|
||||
val useSupervisor: Boolean = false
|
||||
val useDebug: Boolean = true
|
||||
val useAtomics: Boolean = true
|
||||
val useAtomicsOnlyForIO: Boolean = false // copied from Rocket
|
||||
val useCompressed: Boolean = true
|
||||
override val useVector: Boolean = false
|
||||
val useSCIE: Boolean = false
|
||||
val useRVE: Boolean = false
|
||||
val mulDiv: Option[MulDivParams] = Some(MulDivParams()) // copied from Rocket
|
||||
val fpu: Option[FPUParams] = Some(FPUParams()) // copied fma latencies from Rocket
|
||||
val nLocalInterrupts: Int = 0
|
||||
val nPMPs: Int = 0 // TODO: Check
|
||||
val pmpGranularity: Int = 4 // copied from Rocket
|
||||
val nBreakpoints: Int = 0 // TODO: Check
|
||||
val useBPWatch: Boolean = false
|
||||
val nPerfCounters: Int = 29
|
||||
val haveBasicCounters: Boolean = true
|
||||
val haveFSDirty: Boolean = false
|
||||
val misaWritable: Boolean = false
|
||||
val haveCFlush: Boolean = false
|
||||
val nL2TLBEntries: Int = 512 // copied from Rocket
|
||||
val mtvecInit: Option[BigInt] = Some(BigInt(0)) // copied from Rocket
|
||||
val mtvecWritable: Boolean = true // copied from Rocket
|
||||
val instBits: Int = if (useCompressed) 16 else 32
|
||||
val lrscCycles: Int = 80 // copied from Rocket
|
||||
val decodeWidth: Int = 1 // TODO: Check
|
||||
val fetchWidth: Int = 1 // TODO: Check
|
||||
val retireWidth: Int = 2
|
||||
}
|
||||
|
||||
// DOC include start: CanAttachTile
|
||||
case class MyTileAttachParams(
|
||||
tileParams: MyTileParams,
|
||||
crossingParams: RocketCrossingParams
|
||||
) extends CanAttachTile {
|
||||
type TileType = MyTile
|
||||
val lookup = PriorityMuxHartIdFromSeq(Seq(tileParams))
|
||||
}
|
||||
// DOC include end: CanAttachTile
|
||||
|
||||
case class MyTileParams(
|
||||
name: Option[String] = Some("my_tile"),
|
||||
hartId: Int = 0,
|
||||
trace: Boolean = false,
|
||||
val core: MyCoreParams = MyCoreParams()
|
||||
) extends InstantiableTileParams[MyTile]
|
||||
{
|
||||
val beuAddr: Option[BigInt] = None
|
||||
val blockerCtrlAddr: Option[BigInt] = None
|
||||
val btb: Option[BTBParams] = Some(BTBParams())
|
||||
val boundaryBuffers: Boolean = false
|
||||
val dcache: Option[DCacheParams] = Some(DCacheParams())
|
||||
val icache: Option[ICacheParams] = Some(ICacheParams())
|
||||
def instantiate(crossing: TileCrossingParamsLike, lookup: LookupByHartIdImpl)(implicit p: Parameters): MyTile = {
|
||||
new MyTile(this, crossing, lookup)
|
||||
}
|
||||
}
|
||||
|
||||
// DOC include start: Tile class
|
||||
class MyTile(
|
||||
val myParams: MyTileParams,
|
||||
crossing: ClockCrossingType,
|
||||
lookup: LookupByHartIdImpl,
|
||||
q: Parameters)
|
||||
extends BaseTile(myParams, crossing, lookup, q)
|
||||
with SinksExternalInterrupts
|
||||
with SourcesExternalNotifications
|
||||
{
|
||||
|
||||
// Private constructor ensures altered LazyModule.p is used implicitly
|
||||
def this(params: MyTileParams, crossing: TileCrossingParamsLike, lookup: LookupByHartIdImpl)(implicit p: Parameters) =
|
||||
this(params, crossing.crossingType, lookup, p)
|
||||
|
||||
// Require TileLink nodes
|
||||
val intOutwardNode = IntIdentityNode()
|
||||
val masterNode = visibilityNode
|
||||
val slaveNode = TLIdentityNode()
|
||||
|
||||
// Implementation class (See below)
|
||||
override lazy val module = new MyTileModuleImp(this)
|
||||
|
||||
// Required entry of CPU device in the device tree for interrupt purpose
|
||||
val cpuDevice: SimpleDevice = new SimpleDevice("cpu", Seq("my-organization,my-cpu", "riscv")) {
|
||||
override def parent = Some(ResourceAnchors.cpus)
|
||||
override def describe(resources: ResourceBindings): Description = {
|
||||
val Description(name, mapping) = super.describe(resources)
|
||||
Description(name, mapping ++
|
||||
cpuProperties ++
|
||||
nextLevelCacheProperty ++
|
||||
tileProperties)
|
||||
}
|
||||
}
|
||||
|
||||
ResourceBinding {
|
||||
Resource(cpuDevice, "reg").bind(ResourceAddress(hartId))
|
||||
}
|
||||
|
||||
// TODO: Create TileLink nodes and connections here.
|
||||
// DOC include end: Tile class
|
||||
|
||||
// DOC include start: AXI4 node
|
||||
// # of bits used in TileLink ID for master node. 4 bits can support 16 master nodes, but you can have a longer ID if you need more.
|
||||
val idBits = 4
|
||||
val memAXI4Node = AXI4MasterNode(
|
||||
Seq(AXI4MasterPortParameters(
|
||||
masters = Seq(AXI4MasterParameters(
|
||||
name = "myPortName",
|
||||
id = IdRange(0, 1 << idBits))))))
|
||||
val memoryTap = TLIdentityNode() // Every bus connection should have their own tap node
|
||||
// DOC include end: AXI4 node
|
||||
|
||||
// DOC include start: AXI4 convert
|
||||
(tlMasterXbar.node // tlMasterXbar is the bus crossbar to be used when this core / tile is acting as a master; otherwise, use tlSlaveXBar
|
||||
:= memoryTap
|
||||
:= TLBuffer()
|
||||
:= TLFIFOFixer(TLFIFOFixer.all) // fix FIFO ordering
|
||||
:= TLWidthWidget(masterPortBeatBytes) // reduce size of TL
|
||||
:= AXI4ToTL() // convert to TL
|
||||
:= AXI4UserYanker(Some(2)) // remove user field on AXI interface. need but in reality user intf. not needed
|
||||
:= AXI4Fragmenter() // deal with multi-beat xacts
|
||||
:= memAXI4Node) // The custom node, see below
|
||||
// DOC include end: AXI4 convert
|
||||
|
||||
}
|
||||
|
||||
// DOC include start: Implementation class
|
||||
class MyTileModuleImp(outer: MyTile) extends BaseTileModuleImp(outer){
|
||||
// annotate the parameters
|
||||
Annotated.params(this, outer.myParams)
|
||||
|
||||
// TODO: Create the top module of the core and connect it with the ports in "outer"
|
||||
|
||||
// If your core is in Verilog (assume your blackbox is called "MyCoreBlackbox"), instantiate it here like
|
||||
// val core = Module(new MyCoreBlackbox(params...))
|
||||
// (as described in the blackbox tutorial) and connect appropriate signals. See the blackbox tutorial
|
||||
// (link on the top of the page) for more info.
|
||||
// You can look at https://github.com/ucb-bar/ariane-wrapper/blob/master/src/main/scala/ArianeTile.scala
|
||||
// for a Verilog example.
|
||||
|
||||
// If your core is in Chisel, you can simply instantiate the top module here like other Chisel module
|
||||
// and connect appropriate signal. You can even implement this class as your top module.
|
||||
// See https://github.com/riscv-boom/riscv-boom/blob/master/src/main/scala/common/tile.scala and
|
||||
// https://github.com/chipsalliance/rocket-chip/blob/master/src/main/scala/tile/RocketTile.scala for
|
||||
// Chisel example.
|
||||
|
||||
// DOC include end: Implementation class
|
||||
|
||||
// DOC include start: connect interrupt
|
||||
// For example, our core support debug interrupt and machine-level interrupt, and suppose the following two signals
|
||||
// are the interrupt inputs to the core. (DO NOT COPY this code - if your core treat each type of interrupt differently,
|
||||
// you need to connect them to different interrupt ports of your core)
|
||||
val debug_i = Wire(Bool())
|
||||
val mtip_i = Wire(Bool())
|
||||
// We create a bundle here and decode the interrupt.
|
||||
val int_bundle = new TileInterrupts()
|
||||
outer.decodeCoreInterrupts(int_bundle)
|
||||
debug_i := int_bundle.debug
|
||||
mtip_i := int_bundle.meip & int_bundle.msip & int_bundle.mtip
|
||||
// DOC include end: connect interrupt
|
||||
|
||||
// DOC include start: raise interrupt
|
||||
// This is a demo. You should call these function according to your core
|
||||
// Suppose that the following signal is from the decoder indicating a WFI instruction is received.
|
||||
val wfi_o = Wire(Bool())
|
||||
outer.reportWFI(Some(wfi_o))
|
||||
// Suppose that the following signal indicate an unreconverable hardware error.
|
||||
val halt_o = Wire(Bool())
|
||||
outer.reportHalt(Some(halt_o))
|
||||
// Suppose that our core never stall for a long time / stop retiring. Use None to indicate that this interrupt never fires.
|
||||
outer.reportCease(None)
|
||||
// DOC include end: raise interrupt
|
||||
|
||||
// DOC include start: AXI4 connect
|
||||
outer.memAXI4Node.out foreach { case (out, edgeOut) =>
|
||||
// Connect your module IO port to "out"
|
||||
// The type of "out" here is AXI4Bundle, which is defined in generators/rocket-chip/src/main/scala/amba/axi4/Bundles.scala
|
||||
// Please refer to this file for the definition of the ports.
|
||||
// If you are using APB, check APBBundle in generators/rocket-chip/src/main/scala/amba/apb/Bundles.scala
|
||||
// If you are using AHB, check AHBSlaveBundle or AHBMasterBundle in generators/rocket-chip/src/main/scala/amba/ahb/Bundles.scala
|
||||
// (choose one depends on the type of AHB node you create)
|
||||
// If you are using AXIS, check AXISBundle and AXISBundleBits in generators/rocket-chip/src/main/scala/amba/axis/Bundles.scala
|
||||
}
|
||||
// DOC include end: AXI4 connect
|
||||
|
||||
}
|
||||
|
||||
// DOC include start: Config fragment
|
||||
class WithNMyCores(n: Int = 1, overrideIdOffset: Option[Int] = None) extends Config((site, here, up) => {
|
||||
case TilesLocated(InSubsystem) => {
|
||||
// Calculate the next available hart ID (since hart ID cannot be duplicated)
|
||||
val prev = up(TilesLocated(InSubsystem), site)
|
||||
val idOffset = overrideIdOffset.getOrElse(prev.size)
|
||||
// Create TileAttachParams for every core to be instantiated
|
||||
(0 until n).map { i =>
|
||||
MyTileAttachParams(
|
||||
tileParams = MyTileParams(hartId = i + idOffset),
|
||||
crossingParams = RocketCrossingParams()
|
||||
)
|
||||
} ++ prev
|
||||
}
|
||||
// Configurate # of bytes in one memory / IO transaction. For RV64, one load/store instruction can transfer 8 bytes at most.
|
||||
case SystemBusKey => up(SystemBusKey, site).copy(beatBytes = 8)
|
||||
// The # of instruction bits. Use maximum # of bits if your core supports both 32 and 64 bits.
|
||||
case XLen => 64
|
||||
})
|
||||
// DOC include end: Config fragment
|
||||
@@ -15,14 +15,16 @@ import firrtl.options.Viewer.view
|
||||
import freechips.rocketchip.stage.RocketChipOptions
|
||||
import freechips.rocketchip.stage.phases.{RocketTestSuiteAnnotation}
|
||||
import freechips.rocketchip.system.{RocketTestSuite, TestGeneration}
|
||||
import freechips.rocketchip.subsystem.{TilesLocated, InSubsystem}
|
||||
import freechips.rocketchip.util.HasRocketChipStageUtils
|
||||
import freechips.rocketchip.tile.XLen
|
||||
|
||||
import chipyard.TestSuiteHelper
|
||||
import chipyard.TestSuitesKey
|
||||
|
||||
class AddDefaultTests extends Phase with PreservesAll[Phase] with HasRocketChipStageUtils {
|
||||
// Make sure we run both after RocketChip's version of this phase, and Rocket Chip's annotation emission phase
|
||||
// because the RocketTestSuiteAnnotation is not serializable (but is not marked as such).
|
||||
// because the RocketTestSuiteAnnotation is not serializable (but is not marked as such).
|
||||
override val prerequisites = Seq(
|
||||
Dependency[freechips.rocketchip.stage.phases.GenerateFirrtlAnnos],
|
||||
Dependency[freechips.rocketchip.stage.phases.AddDefaultTests])
|
||||
@@ -33,25 +35,11 @@ class AddDefaultTests extends Phase with PreservesAll[Phase] with HasRocketChipS
|
||||
val suiteHelper = new TestSuiteHelper
|
||||
// Use Xlen as a proxy for detecting if we are a processor-like target
|
||||
// The underlying test suites expect this field to be defined
|
||||
if (p.lift(XLen).nonEmpty) {
|
||||
suiteHelper.addRocketTestSuites
|
||||
suiteHelper.addBoomTestSuites
|
||||
suiteHelper.addArianeTestSuites
|
||||
}
|
||||
val tileParams = p(TilesLocated(InSubsystem)) map (tp => tp.tileParams)
|
||||
if (p.lift(XLen).nonEmpty)
|
||||
// If a custom test suite is set up, use the custom test suite
|
||||
annotations += CustomMakefragSnippet(p(TestSuitesKey).apply(tileParams, suiteHelper, p))
|
||||
|
||||
// if hwacha parameter exists then generate its tests
|
||||
// TODO: find a more elegant way to do this. either through
|
||||
// trying to disambiguate BuildRoCC, having a AccelParamsKey,
|
||||
// or having the Accelerator/Tile add its own tests
|
||||
import hwacha.HwachaTestSuites._
|
||||
if (Try(p(hwacha.HwachaNLanes)).getOrElse(0) > 0) {
|
||||
suiteHelper.addSuites(rv64uv.map(_("p")))
|
||||
suiteHelper.addSuites(rv64uv.map(_("vp")))
|
||||
suiteHelper.addSuite(rv64sv("p"))
|
||||
suiteHelper.addSuite(hwachaBmarks)
|
||||
annotations += CustomMakefragSnippet(
|
||||
"SRC_EXTENSION = $(base_dir)/hwacha/$(src_path)/*.scala" + "\nDISASM_EXTENSION = --extension=hwacha")
|
||||
}
|
||||
RocketTestSuiteAnnotation(suiteHelper.suites.values.toSeq) +: annotations
|
||||
}
|
||||
|
||||
|
||||
@@ -70,7 +70,8 @@ class WithFireSimConfigTweaks extends Config(
|
||||
new WithFireSimSimpleClocks ++
|
||||
// Required*: When using FireSim-as-top to provide a correct path to the target bootrom source
|
||||
new WithBootROM ++
|
||||
// Optional*: Removing this will require target-software changes to properly capture UART output
|
||||
// Optional*: Removing this will require adjusting the UART baud rate and
|
||||
// potential target-software changes to properly capture UART output
|
||||
new WithPeripheryBusFrequency(BigInt(3200000000L)) ++
|
||||
// Required: Existing FAME-1 transform cannot handle black-box clock gates
|
||||
new WithoutClockGating ++
|
||||
@@ -86,8 +87,8 @@ class WithFireSimConfigTweaks extends Config(
|
||||
new testchipip.WithTSI ++
|
||||
// Optional: Removing this will require using an initramfs under linux
|
||||
new testchipip.WithBlockDevice ++
|
||||
// Required*:
|
||||
new chipyard.config.WithUART
|
||||
// Required*: Scale default baud rate with periphery bus frequency
|
||||
new chipyard.config.WithUART(BigInt(3686400L))
|
||||
)
|
||||
|
||||
/*******************************************************************************
|
||||
@@ -118,6 +119,21 @@ class FireSimQuadRocketConfig extends Config(
|
||||
new WithFireSimConfigTweaks ++
|
||||
new chipyard.QuadRocketConfig)
|
||||
|
||||
// A stripped down configuration that should fit on all supported hosts.
|
||||
// Flat to avoid having to reorganize the config class hierarchy to remove certain features
|
||||
class FireSimSmallSystemConfig extends Config(
|
||||
new WithDefaultFireSimBridges ++
|
||||
new WithDefaultMemModel ++
|
||||
new WithBootROM ++
|
||||
new WithPeripheryBusFrequency(BigInt(3200000000L)) ++
|
||||
new WithoutClockGating ++
|
||||
new WithoutTLMonitors ++
|
||||
new freechips.rocketchip.subsystem.WithExtMemSize(1 << 28) ++
|
||||
new testchipip.WithTSI ++
|
||||
new testchipip.WithBlockDevice ++
|
||||
new chipyard.config.WithUART ++
|
||||
new freechips.rocketchip.subsystem.WithInclusiveCache(nWays = 2, capacityKB = 64) ++
|
||||
new chipyard.RocketConfig)
|
||||
|
||||
//*****************************************************************
|
||||
// Boom config, base off chipyard's LargeBoomConfig
|
||||
|
||||
Submodule generators/sifive-blocks updated: c1dee8234c...c240e629e2
Submodule generators/testchipip updated: 29eb87c938...8b5c89a5f7
@@ -152,6 +152,8 @@ define run_scala_main
|
||||
endef
|
||||
endif
|
||||
|
||||
FIRRTL_LOGLEVEL ?= error
|
||||
|
||||
#########################################################################################
|
||||
# output directory for tests
|
||||
#########################################################################################
|
||||
|
||||
Reference in New Issue
Block a user