Second revision

This commit is contained in:
Zitao Fang
2020-07-08 16:02:31 -07:00
parent 6cb8a60a80
commit 9ad9d00a23
2 changed files with 62 additions and 26 deletions

View File

@@ -121,7 +121,8 @@ You will also need a ``CanAttachTile`` class to add the tile config into the con
.. literalinclude:: ../../generators/chipyard/src/main/scala/example/TutorialTile.scala
:language: scala
:lines: 61-67
:start-after: DOC include start: CanAttachTile
:end-before: DOC include end: CanAttachTile
.. note::
@@ -137,14 +138,17 @@ 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.
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
:lines: 87-125, 143
:start-after: DOC include start: Tile class
:end-before: DOC include end: Tile class
Connect TileLink Buses
----------------------
@@ -156,7 +160,8 @@ Rocket chip:
.. literalinclude:: ../../generators/chipyard/src/main/scala/example/TutorialTile.scala
:language: scala
:lines: 133-142
: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
@@ -170,7 +175,8 @@ as the template, but it is not recommended unless you are familiar with TileLink
.. literalinclude:: ../../generators/chipyard/src/main/scala/example/TutorialTile.scala
:language: scala
:lines: 126-132
: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!
@@ -185,12 +191,36 @@ can override the following two functions to control how to buffer the bus reques
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 codes, and if your
core is in Verilog, you will need to put the black box class you created in the first step here 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. You can then read the interrupt bits from the object.
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 object.
The definition of ``TileInterrupts`` is
.. code-block:: scala
@@ -204,7 +234,6 @@ The definition of ``TileInterrupts`` is
val lip = Vec(coreParams.nLocalInterrupts, Bool()) // Local interrupts
}
This function should be in the implementation class since it involves hardware generation.
Also, the tile can also notify other cores or devices for some events by calling following functions in ``SourcesExternalNotifications``
from the implementation class:
@@ -215,21 +244,6 @@ from the implementation class:
reportCease(could_cease: Option[Bool], quiescenceCycles: Int = 8) // Triggered when the core stop retiring instructions (like clock gating)
reportWFI(could_wfi: Option[Bool]) // Triggered when a WFI instruction is executed
Create Implementation Class
---------------------------
The implementation class for your core is of the following form:
.. literalinclude:: ../../generators/chipyard/src/main/scala/example/TutorialTile.scala
:language: scala
:lines: 145-149, 160
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
:lines: 151-159
Create Config Fragments to Integrate the Core
---------------------------------------------
@@ -238,7 +252,8 @@ the current config. An example of such config will be like this:
.. literalinclude:: ../../generators/chipyard/src/main/scala/example/TutorialTile.scala
:language: scala
:lines: 162-179
: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.
@@ -247,5 +262,6 @@ Now you have finished all the steps to prepare your cores for Chipyard! To gener
in :ref:`custom_chisel` to add your project to the build system, then create a config by following the steps in :ref:`hetero_socs_`.
You can now run any desired workflow for the new config just as you do for the built-in cores.
If you would like to see how an actual core are integrated into Chipyard, ``generators/ariane/src/main/scala/ArianeTile.scala``
provides a concrete example of integrating a third party Verilog core Ariane.
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.

View File

@@ -58,6 +58,7 @@ case class MyCoreParams(
val retireWidth: Int = 2
}
// DOC include start: CanAttachTile
case class MyTileAttachParams(
tileParams: MyTileParams,
crossingParams: RocketCrossingParams
@@ -65,6 +66,7 @@ case class MyTileAttachParams(
type TileType = MyTile
val lookup = PriorityMuxHartIdFromSeq(Seq(tileParams))
}
// DOC include end: CanAttachTile
case class MyTileParams(
name: Option[String] = Some("my_tile"),
@@ -84,6 +86,7 @@ case class MyTileParams(
}
}
// DOC include start: Tile class
class MyTile(
val myParams: MyTileParams,
crossing: ClockCrossingType,
@@ -123,6 +126,10 @@ class MyTile(
}
// (Connection to bus, interrupt, etc.)
// }
// 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(
@@ -131,6 +138,9 @@ class MyTile(
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()
@@ -140,14 +150,20 @@ class MyTile(
:= 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"
// TODO: Create the top module of the core and connect it with the ports in "outer" }
//}
// DOC include end: Implementation class
// 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
@@ -157,8 +173,11 @@ class MyTileModuleImp(outer: MyTile) extends BaseTileModuleImp(outer){
// (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)
@@ -177,3 +196,4 @@ class WithNMyCores(n: Int = 1, overrideIdOffset: Option[Int] = None) extends Con
// 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