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 chisel3.util._
|
||||||
import freechips.rocketchip.config.Parameters
|
import freechips.rocketchip.config.Parameters
|
||||||
import freechips.rocketchip.diplomacy._
|
import freechips.rocketchip.diplomacy._
|
||||||
|
import freechips.rocketchip.devices.tilelink.TLTestRAM
|
||||||
import freechips.rocketchip.unittest._
|
import freechips.rocketchip.unittest._
|
||||||
|
|
||||||
class CoalescingUnit(numThreads: Int = 1)(implicit p: Parameters)
|
class CoalescingUnit(numThreads: Int = 1)(implicit p: Parameters)
|
||||||
extends LazyModule {
|
extends LazyModule {
|
||||||
val beatBytes = 8
|
// val beatBytes = 8
|
||||||
val seqParam = Seq(
|
// val seqParam = Seq(
|
||||||
TLSlaveParameters.v1(
|
// TLSlaveParameters.v1(
|
||||||
address = Seq(AddressSet(0x0000, 0xffffff)),
|
// address = Seq(AddressSet(0x0000, 0xffffff)),
|
||||||
// resources = device.reg,
|
// // resources = device.reg,
|
||||||
regionType = RegionType.UNCACHED,
|
// regionType = RegionType.UNCACHED,
|
||||||
executable = true,
|
// executable = true,
|
||||||
supportsArithmetic = TransferSizes(1, beatBytes),
|
// supportsArithmetic = TransferSizes(1, beatBytes),
|
||||||
supportsLogical = TransferSizes(1, beatBytes),
|
// supportsLogical = TransferSizes(1, beatBytes),
|
||||||
supportsGet = TransferSizes(1, beatBytes),
|
// supportsGet = TransferSizes(1, beatBytes),
|
||||||
supportsPutFull = TransferSizes(1, beatBytes),
|
// supportsPutFull = TransferSizes(1, beatBytes),
|
||||||
supportsPutPartial = TransferSizes(1, beatBytes),
|
// supportsPutPartial = TransferSizes(1, beatBytes),
|
||||||
supportsHint = TransferSizes(1, beatBytes),
|
// supportsHint = TransferSizes(1, beatBytes),
|
||||||
fifoId = Some(0)
|
// 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) { _ =>
|
val coalescerNode = TLClientNode(
|
||||||
TLManagerNode(Seq(TLSlavePortParameters.v1(seqParam, beatBytes)))
|
Seq(TLMasterPortParameters.v1(clientParam))
|
||||||
}
|
)
|
||||||
|
|
||||||
val node = TLIdentityNode()
|
|
||||||
entryNodes.foreach { n => n := node }
|
|
||||||
|
|
||||||
lazy val module = new Impl
|
lazy val module = new Impl
|
||||||
class Impl extends LazyModuleImp(this) {
|
class Impl extends LazyModuleImp(this) {
|
||||||
// Example 1: accessing the entire A channel data for Thread 0
|
// // Example 1: accessing the entire A channel data for Thread 0
|
||||||
val (tlIn0, edge0) = entryNodes(0).in(0)
|
// val (tlIn0, edge0) = threadNodes(0).in(0)
|
||||||
dontTouch(tlIn0.a)
|
// dontTouch(tlIn0.a)
|
||||||
|
|
||||||
// Example 2: accssing the entire A channel data for Thread 1
|
// // Example 2: accssing the entire A channel data for Thread 1
|
||||||
val (tlIn1, edge1) = entryNodes(1).in(0)
|
// val (tlIn1, edge1) = threadNodes(1).in(0)
|
||||||
dontTouch(tlIn1.a)
|
// dontTouch(tlIn1.a)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -49,13 +63,14 @@ class MemTraceDriver(numThreads: Int = 1)(implicit p: Parameters)
|
|||||||
extends LazyModule {
|
extends LazyModule {
|
||||||
// Create N client nodes together
|
// Create N client nodes together
|
||||||
val threadNodes = Seq.tabulate(numThreads) { i =>
|
val threadNodes = Seq.tabulate(numThreads) { i =>
|
||||||
val clients = Seq(
|
val clientParam = Seq(
|
||||||
TLMasterParameters.v1(
|
TLMasterParameters.v1(
|
||||||
name = "MemTraceDriver" + i.toString,
|
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
|
// 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)
|
lazy val module = new MemTraceDriverImp(this, numThreads)
|
||||||
}
|
}
|
||||||
|
|
||||||
class TraceReq extends Bundle {
|
class MemTraceDriverImp(outer: MemTraceDriver, numThreads: Int)
|
||||||
val valid = Bool()
|
extends LazyModuleImp(outer)
|
||||||
val address = UInt(64.W)
|
|
||||||
}
|
|
||||||
|
|
||||||
class MemTraceDriverImp(
|
|
||||||
outer: MemTraceDriver,
|
|
||||||
numThreads: Int
|
|
||||||
) extends LazyModuleImp(outer)
|
|
||||||
with UnitTestModule {
|
with UnitTestModule {
|
||||||
val sim = Module(
|
val sim = Module(
|
||||||
new SimMemTrace(filename = "vecadd.core1.thread4.trace", numThreads)
|
new SimMemTrace(filename = "vecadd.core1.thread4.trace", numThreads)
|
||||||
@@ -85,7 +93,7 @@ class MemTraceDriverImp(
|
|||||||
sim.io.reset := reset.asBool
|
sim.io.reset := reset.asBool
|
||||||
sim.io.trace_read.ready := true.B
|
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.
|
// back to each thread's.
|
||||||
val threadReqs = Wire(Vec(numThreads, new TraceReq))
|
val threadReqs = Wire(Vec(numThreads, new TraceReq))
|
||||||
threadReqs.zipWithIndex.foreach { case (req, i) =>
|
threadReqs.zipWithIndex.foreach { case (req, i) =>
|
||||||
@@ -93,7 +101,7 @@ class MemTraceDriverImp(
|
|||||||
req.address := (sim.io.trace_read.address >> (64 * i))
|
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) =>
|
(outer.threadNodes zip threadReqs).foreach { case (node, req) =>
|
||||||
val (tlOut, edge) = node.out(0)
|
val (tlOut, edge) = node.out(0)
|
||||||
tlOut.a.valid := req.valid
|
tlOut.a.valid := req.valid
|
||||||
@@ -116,6 +124,11 @@ class MemTraceDriverImp(
|
|||||||
io.finished := sim.io.trace_read.finished
|
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)
|
class SimMemTrace(val filename: String, numThreads: Int)
|
||||||
extends BlackBox(
|
extends BlackBox(
|
||||||
Map("FILENAME" -> filename, "NUM_THREADS" -> numThreads)
|
Map("FILENAME" -> filename, "NUM_THREADS" -> numThreads)
|
||||||
@@ -130,6 +143,7 @@ class SimMemTrace(val filename: String, numThreads: Int)
|
|||||||
val valid = Output(UInt(numThreads.W))
|
val valid = Output(UInt(numThreads.W))
|
||||||
// Chisel can't interface with Verilog 2D port, so flatten all lanes into
|
// Chisel can't interface with Verilog 2D port, so flatten all lanes into
|
||||||
// single wide 1D array.
|
// single wide 1D array.
|
||||||
|
// TODO: assumes 64-bit address.
|
||||||
val address = Output(UInt((64 * numThreads).W))
|
val address = Output(UInt((64 * numThreads).W))
|
||||||
val finished = Output(Bool())
|
val finished = Output(Bool())
|
||||||
}
|
}
|
||||||
@@ -142,11 +156,23 @@ class SimMemTrace(val filename: String, numThreads: Int)
|
|||||||
|
|
||||||
class CoalConnectTrace(implicit p: Parameters) extends LazyModule {
|
class CoalConnectTrace(implicit p: Parameters) extends LazyModule {
|
||||||
// TODO: use parameters for numThreads
|
// TODO: use parameters for numThreads
|
||||||
val coal = LazyModule(new CoalescingUnit(numThreads = 4))
|
val numThreads = 4
|
||||||
val driver = LazyModule(new MemTraceDriver(numThreads = 4))
|
val coal = LazyModule(new CoalescingUnit(numThreads))
|
||||||
|
val driver = LazyModule(new MemTraceDriver(numThreads))
|
||||||
|
|
||||||
coal.node :=* driver.node
|
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
|
lazy val module = new Impl
|
||||||
class Impl extends LazyModuleImp(this) with UnitTestModule {
|
class Impl extends LazyModuleImp(this) with UnitTestModule {
|
||||||
driver.module.io.start := io.start
|
driver.module.io.start := io.start
|
||||||
@@ -154,9 +180,8 @@ class CoalConnectTrace(implicit p: Parameters) extends LazyModule {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class CoalescingUnitTest(timeout: Int = 500000)(implicit
|
class CoalescingUnitTest(timeout: Int = 500000)(implicit p: Parameters)
|
||||||
p: Parameters
|
extends UnitTest(timeout) {
|
||||||
) extends UnitTest(timeout) {
|
|
||||||
val dut = Module(LazyModule(new CoalConnectTrace).module)
|
val dut = Module(LazyModule(new CoalConnectTrace).module)
|
||||||
dut.io.start := io.start
|
dut.io.start := io.start
|
||||||
io.finished := dut.io.finished
|
io.finished := dut.io.finished
|
||||||
|
|||||||
Reference in New Issue
Block a user