The middle line looks like you defining the implementation of a LazyModuleImp. That’s fine, but you can’t connect diplomatic nodes there. Also, from a stylistic point of view, we don’t generally embed the Fragmenter into the device. It might be that someone wants to use the slave without burst support, so the adapter should not be rolled directly into the implementation.
Take a look in rocket-chip/src/main/scala/devices/tilelink/CLINT.scala.
You’ll see there is a class CLINT which implements a TileLink device using a TLRegisterNode. Then at the bottom is a trait that captures a code snippet that creates the CLINT and a TLFragmenter and attaches them to the cbus.
Generally, you want something like: (myslave.node := TLFragmenter(beatBytes, maxBurstBytes) := xbar.node) when you attach the slave.
Thanks for a prompt response. I’m trying to load/store a non-cached 8kB page to my ROCC module. I was able to connect a TLFragmenter with the code below:
// LazyROCC
val source_min = 0x10
val outstanding = 0x20
val source_max = source_min + outstanding
…
val tmpNode = TLClientNode(Seq(TLClientPortParameters(Seq(TLClientParameters(
sourceId = IdRange (source_min, source_max),
name = s"MyCore0")))))
val frag = TLFragmenter (16,256)
override val atlNode = frag := tmpNode
However, compilation gives a size warning and fails on require fail:
[1, 2] => dut
WARNING: TLMonitor instantiated on a bus with source bits (16) > 14; A=>D transaction flight will not be checked
[error] Caused by: java.lang.IllegalArgumentException: requirement failed
[error] at scala.Predef$.require(Predef.scala:264)
[error] at freechips.rocketchip.tilelink.TLFragmenter$$anon$2.$anonfun$new$4(Fragmenter.scala:73)
The warning can be ignored. The error says that the devices below the TLFragmenter can respond out-of-order, something that it can’t support. Generally, we put the Fragmenter in front of the slaves, where this is not a problem. If you want to but it in front of a master, try altNode = TLFIFOFixer() := TLFragmenter(64, 4096) := tmpNode.
I believe the TileLink spec caps the maximum transfer size at 4kB, so I expect you are going to run into problems with an 8kB burst.
Also, by putting a Fragmenter at the master as you’ve done, the burst is not atomic. It will appear to slaves to be multiple distinct transfers. Furthermore, by using a FIFOFixer like this, performance to any out-of-order memory (which includes main memory) is going to be very slow, with only one request in-flight at a time.
If you don’t care about atomicity, but DO care about performance, probably a better design is to have the master capable of issuing and tracking multiple outstanding requests at once.
This compiled, but I got an “old” error for a 256B burst from the TL Manager:
Assertion failed: ‘A’ channel carries Get type unsupported by manager (connected at CrossingHelper.scala:30:80)
at Monitor.scala:72 assert (edge.manager.supportsGetSafe(edge.address(bundle), bundle.size), “‘A’ channel carries Get type unsupported by manager” + extra)
The error above was my starting point to seek how to increase the burst size for software.
Can I do better than this ? I do have a solution, but this requires to redesign top levels, which I’m willing not to do…