Organize Diplomacy node structure of CoalescingUnit
IdentityNode with numThreads edges + master TL node with additional 1 edge for the new coalesced requests.
This commit is contained in:
@@ -6,42 +6,56 @@ import chisel3._
|
||||
import chisel3.util._
|
||||
import freechips.rocketchip.config.Parameters
|
||||
import freechips.rocketchip.diplomacy._
|
||||
import freechips.rocketchip.devices.tilelink.TLTestRAM
|
||||
import freechips.rocketchip.unittest._
|
||||
|
||||
class CoalescingUnit(numThreads: Int = 1)(implicit p: Parameters)
|
||||
extends LazyModule {
|
||||
val beatBytes = 8
|
||||
val seqParam = Seq(
|
||||
TLSlaveParameters.v1(
|
||||
address = Seq(AddressSet(0x0000, 0xffffff)),
|
||||
// resources = device.reg,
|
||||
regionType = RegionType.UNCACHED,
|
||||
executable = true,
|
||||
supportsArithmetic = TransferSizes(1, beatBytes),
|
||||
supportsLogical = TransferSizes(1, beatBytes),
|
||||
supportsGet = TransferSizes(1, beatBytes),
|
||||
supportsPutFull = TransferSizes(1, beatBytes),
|
||||
supportsPutPartial = TransferSizes(1, beatBytes),
|
||||
supportsHint = TransferSizes(1, beatBytes),
|
||||
fifoId = Some(0)
|
||||
// val beatBytes = 8
|
||||
// val seqParam = Seq(
|
||||
// TLSlaveParameters.v1(
|
||||
// address = Seq(AddressSet(0x0000, 0xffffff)),
|
||||
// // resources = device.reg,
|
||||
// regionType = RegionType.UNCACHED,
|
||||
// executable = true,
|
||||
// supportsArithmetic = TransferSizes(1, beatBytes),
|
||||
// supportsLogical = TransferSizes(1, beatBytes),
|
||||
// supportsGet = TransferSizes(1, beatBytes),
|
||||
// supportsPutFull = TransferSizes(1, beatBytes),
|
||||
// supportsPutPartial = TransferSizes(1, beatBytes),
|
||||
// supportsHint = TransferSizes(1, beatBytes),
|
||||
// fifoId = Some(0)
|
||||
// )
|
||||
// )
|
||||
|
||||
// Identity node that captures the incoming TL requests and passes them
|
||||
// through the other end, dropping coalesced requests. This is what the
|
||||
// upstream node will connect to.
|
||||
val node = TLIdentityNode()
|
||||
|
||||
// Master node that actually generates coalesced requests.
|
||||
// This and the IdentityNode will be the two outward-facing nodes that the
|
||||
// downstream, either L1 or the system bus, will connect to.
|
||||
val clientParam = Seq(
|
||||
TLMasterParameters.v1(
|
||||
name = "CoalescerNode",
|
||||
sourceId = IdRange(0, 1),
|
||||
visibility = Seq(AddressSet(0x0000, 0xffffff))
|
||||
)
|
||||
)
|
||||
val entryNodes = Seq.tabulate(numThreads) { _ =>
|
||||
TLManagerNode(Seq(TLSlavePortParameters.v1(seqParam, beatBytes)))
|
||||
}
|
||||
|
||||
val node = TLIdentityNode()
|
||||
entryNodes.foreach { n => n := node }
|
||||
val coalescerNode = TLClientNode(
|
||||
Seq(TLMasterPortParameters.v1(clientParam))
|
||||
)
|
||||
|
||||
lazy val module = new Impl
|
||||
class Impl extends LazyModuleImp(this) {
|
||||
// Example 1: accessing the entire A channel data for Thread 0
|
||||
val (tlIn0, edge0) = entryNodes(0).in(0)
|
||||
dontTouch(tlIn0.a)
|
||||
// // Example 1: accessing the entire A channel data for Thread 0
|
||||
// val (tlIn0, edge0) = threadNodes(0).in(0)
|
||||
// dontTouch(tlIn0.a)
|
||||
|
||||
// Example 2: accssing the entire A channel data for Thread 1
|
||||
val (tlIn1, edge1) = entryNodes(1).in(0)
|
||||
dontTouch(tlIn1.a)
|
||||
// // Example 2: accssing the entire A channel data for Thread 1
|
||||
// val (tlIn1, edge1) = threadNodes(1).in(0)
|
||||
// dontTouch(tlIn1.a)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -49,13 +63,14 @@ class MemTraceDriver(numThreads: Int = 1)(implicit p: Parameters)
|
||||
extends LazyModule {
|
||||
// Create N client nodes together
|
||||
val threadNodes = Seq.tabulate(numThreads) { i =>
|
||||
val clients = Seq(
|
||||
val clientParam = Seq(
|
||||
TLMasterParameters.v1(
|
||||
name = "MemTraceDriver" + i.toString,
|
||||
sourceId = IdRange(0, 4)
|
||||
sourceId = IdRange(0, numThreads),
|
||||
visibility = Seq(AddressSet(0x0000, 0xffffff))
|
||||
)
|
||||
)
|
||||
TLClientNode(Seq(TLMasterPortParameters.v1(clients)))
|
||||
TLClientNode(Seq(TLMasterPortParameters.v1(clientParam)))
|
||||
}
|
||||
|
||||
// Combine N outgoing client node into 1 idenity node for diplomatic
|
||||
@@ -68,15 +83,8 @@ class MemTraceDriver(numThreads: Int = 1)(implicit p: Parameters)
|
||||
lazy val module = new MemTraceDriverImp(this, numThreads)
|
||||
}
|
||||
|
||||
class TraceReq extends Bundle {
|
||||
val valid = Bool()
|
||||
val address = UInt(64.W)
|
||||
}
|
||||
|
||||
class MemTraceDriverImp(
|
||||
outer: MemTraceDriver,
|
||||
numThreads: Int
|
||||
) extends LazyModuleImp(outer)
|
||||
class MemTraceDriverImp(outer: MemTraceDriver, numThreads: Int)
|
||||
extends LazyModuleImp(outer)
|
||||
with UnitTestModule {
|
||||
val sim = Module(
|
||||
new SimMemTrace(filename = "vecadd.core1.thread4.trace", numThreads)
|
||||
@@ -85,7 +93,7 @@ class MemTraceDriverImp(
|
||||
sim.io.reset := reset.asBool
|
||||
sim.io.trace_read.ready := true.B
|
||||
|
||||
// Split output of SimMemTrace, which is flattened across all lanes,
|
||||
// Split output of SimMemTrace, which is flattened across all threads,
|
||||
// back to each thread's.
|
||||
val threadReqs = Wire(Vec(numThreads, new TraceReq))
|
||||
threadReqs.zipWithIndex.foreach { case (req, i) =>
|
||||
@@ -93,7 +101,7 @@ class MemTraceDriverImp(
|
||||
req.address := (sim.io.trace_read.address >> (64 * i))
|
||||
}
|
||||
|
||||
// Connect each sim module to its respective TL connection
|
||||
// Connect each thread to its respective TL node.
|
||||
(outer.threadNodes zip threadReqs).foreach { case (node, req) =>
|
||||
val (tlOut, edge) = node.out(0)
|
||||
tlOut.a.valid := req.valid
|
||||
@@ -116,6 +124,11 @@ class MemTraceDriverImp(
|
||||
io.finished := sim.io.trace_read.finished
|
||||
}
|
||||
|
||||
class TraceReq extends Bundle {
|
||||
val valid = Bool()
|
||||
val address = UInt(64.W)
|
||||
}
|
||||
|
||||
class SimMemTrace(val filename: String, numThreads: Int)
|
||||
extends BlackBox(
|
||||
Map("FILENAME" -> filename, "NUM_THREADS" -> numThreads)
|
||||
@@ -130,6 +143,7 @@ class SimMemTrace(val filename: String, numThreads: Int)
|
||||
val valid = Output(UInt(numThreads.W))
|
||||
// Chisel can't interface with Verilog 2D port, so flatten all lanes into
|
||||
// single wide 1D array.
|
||||
// TODO: assumes 64-bit address.
|
||||
val address = Output(UInt((64 * numThreads).W))
|
||||
val finished = Output(Bool())
|
||||
}
|
||||
@@ -142,11 +156,23 @@ class SimMemTrace(val filename: String, numThreads: Int)
|
||||
|
||||
class CoalConnectTrace(implicit p: Parameters) extends LazyModule {
|
||||
// TODO: use parameters for numThreads
|
||||
val coal = LazyModule(new CoalescingUnit(numThreads = 4))
|
||||
val driver = LazyModule(new MemTraceDriver(numThreads = 4))
|
||||
val numThreads = 4
|
||||
val coal = LazyModule(new CoalescingUnit(numThreads))
|
||||
val driver = LazyModule(new MemTraceDriver(numThreads))
|
||||
|
||||
coal.node :=* driver.node
|
||||
|
||||
// Use TLTestRAM as bogus downstream TL manager nodes
|
||||
// TODO: swap this out with a memtrace logger
|
||||
val rams = Seq.tabulate(numThreads + 1) { _ =>
|
||||
LazyModule(
|
||||
new TLTestRAM(address = AddressSet(0x0000, 0xffffff), beatBytes = 8)
|
||||
)
|
||||
}
|
||||
// Connect all (N+1) outputs of coal to separate TestRAM modules
|
||||
(0 until numThreads).foreach { i => rams(i).node := coal.node }
|
||||
rams(numThreads).node := coal.coalescerNode
|
||||
|
||||
lazy val module = new Impl
|
||||
class Impl extends LazyModuleImp(this) with UnitTestModule {
|
||||
driver.module.io.start := io.start
|
||||
@@ -154,9 +180,8 @@ class CoalConnectTrace(implicit p: Parameters) extends LazyModule {
|
||||
}
|
||||
}
|
||||
|
||||
class CoalescingUnitTest(timeout: Int = 500000)(implicit
|
||||
p: Parameters
|
||||
) extends UnitTest(timeout) {
|
||||
class CoalescingUnitTest(timeout: Int = 500000)(implicit p: Parameters)
|
||||
extends UnitTest(timeout) {
|
||||
val dut = Module(LazyModule(new CoalConnectTrace).module)
|
||||
dut.io.start := io.start
|
||||
io.finished := dut.io.finished
|
||||
|
||||
Reference in New Issue
Block a user