Decouple Vortex dmem bundle from TL
Previously VortexBundle was being instantiated using the parameters of the TileLink bundle from VortexTile. This results in tight coupling between Vortex interface parameters and downstream TileLink parameters. This change adds a standalone Bundle used by the VortexCore wrapper and is independently instantiated from the TL params, i.e. different source widths. Ideally we want to move away from using TL-like structures for VortexBundle and handling adapter logic completely outside the core blackbox.
This commit is contained in:
@@ -8,7 +8,7 @@ import chisel3.util._
|
|||||||
import chisel3.experimental._
|
import chisel3.experimental._
|
||||||
import org.chipsalliance.cde.config.Parameters
|
import org.chipsalliance.cde.config.Parameters
|
||||||
import freechips.rocketchip.tile._
|
import freechips.rocketchip.tile._
|
||||||
import tile.VortexTile
|
import tile.{VortexTile, VortexBundleA, VortexBundleD}
|
||||||
|
|
||||||
class VortexBundle(tile: VortexTile)(implicit p: Parameters) extends CoreBundle {
|
class VortexBundle(tile: VortexTile)(implicit p: Parameters) extends CoreBundle {
|
||||||
val clock = Input(Clock())
|
val clock = Input(Clock())
|
||||||
@@ -22,9 +22,9 @@ class VortexBundle(tile: VortexTile)(implicit p: Parameters) extends CoreBundle
|
|||||||
val a = tile.imemNodes.head.out.head._1.a.cloneType
|
val a = tile.imemNodes.head.out.head._1.a.cloneType
|
||||||
val d = Flipped(tile.imemNodes.head.out.head._1.d.cloneType)
|
val d = Flipped(tile.imemNodes.head.out.head._1.d.cloneType)
|
||||||
})) else None
|
})) else None
|
||||||
val dmem = if (!tile.vortexParams.useVxCache) Some(Vec(4, new Bundle {
|
val dmem = if (!tile.vortexParams.useVxCache) Some(Vec(tile.numLanes, new Bundle {
|
||||||
val a = tile.dmemNodes.head.out.head._1.a.cloneType
|
val a = Decoupled(new VortexBundleA())
|
||||||
val d = Flipped(tile.dmemNodes.head.out.head._1.d.cloneType)
|
val d = Flipped(Decoupled(new VortexBundleD()))
|
||||||
})) else None
|
})) else None
|
||||||
val mem = if (tile.vortexParams.useVxCache) Some(new Bundle {
|
val mem = if (tile.vortexParams.useVxCache) Some(new Bundle {
|
||||||
val a = tile.memNode.out.head._1.a.cloneType
|
val a = tile.memNode.out.head._1.a.cloneType
|
||||||
|
|||||||
@@ -44,6 +44,22 @@ case class VortexTileParams(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
class VortexBundleA extends Bundle {
|
||||||
|
val opcode = UInt(3.W) // FIXME: hardcoded
|
||||||
|
val size = UInt(4.W) // FIXME: hardcoded
|
||||||
|
val source = UInt(10.W) // FIXME: hardcoded
|
||||||
|
val address = UInt(32.W) // FIXME: hardcoded
|
||||||
|
val mask = UInt(4.W) // FIXME: hardcoded
|
||||||
|
val data = UInt(32.W) // FIXME: hardcoded
|
||||||
|
}
|
||||||
|
|
||||||
|
class VortexBundleD extends Bundle {
|
||||||
|
val opcode = UInt(3.W) // FIXME: hardcoded
|
||||||
|
val size = UInt(4.W) // FIXME: hardcoded
|
||||||
|
val source = UInt(10.W) // FIXME: hardcoded
|
||||||
|
val data = UInt(32.W) // FIXME: hardcoded
|
||||||
|
}
|
||||||
|
|
||||||
class VortexTile private (
|
class VortexTile private (
|
||||||
val vortexParams: VortexTileParams,
|
val vortexParams: VortexTileParams,
|
||||||
crossing: ClockCrossingType,
|
crossing: ClockCrossingType,
|
||||||
@@ -91,6 +107,7 @@ class VortexTile private (
|
|||||||
minLatency = 1)))*/
|
minLatency = 1)))*/
|
||||||
|
|
||||||
val numLanes = 4 // FIXME: hardcoded
|
val numLanes = 4 // FIXME: hardcoded
|
||||||
|
val sourceWidth = 1 // TODO: use Parameters for this
|
||||||
|
|
||||||
val imemNodes = Seq.tabulate(1) { i =>
|
val imemNodes = Seq.tabulate(1) { i =>
|
||||||
TLClientNode(
|
TLClientNode(
|
||||||
@@ -98,7 +115,7 @@ class VortexTile private (
|
|||||||
TLMasterPortParameters.v1(
|
TLMasterPortParameters.v1(
|
||||||
clients = Seq(
|
clients = Seq(
|
||||||
TLMasterParameters.v1(
|
TLMasterParameters.v1(
|
||||||
sourceId = IdRange(0, 1 << 10), // TODO magic number
|
sourceId = IdRange(0, 1 << 10), // TODO: magic numbers
|
||||||
name = s"Vortex Core ${vortexParams.hartId} I-Mem $i",
|
name = s"Vortex Core ${vortexParams.hartId} I-Mem $i",
|
||||||
requestFifo = true,
|
requestFifo = true,
|
||||||
supportsProbe =
|
supportsProbe =
|
||||||
@@ -117,7 +134,7 @@ class VortexTile private (
|
|||||||
TLMasterPortParameters.v1(
|
TLMasterPortParameters.v1(
|
||||||
clients = Seq(
|
clients = Seq(
|
||||||
TLMasterParameters.v1(
|
TLMasterParameters.v1(
|
||||||
sourceId = IdRange(0, 1 << 10), // TODO magic number
|
sourceId = IdRange(0, 1 << sourceWidth),
|
||||||
name = s"Vortex Core ${vortexParams.hartId} D-Mem Lane $i",
|
name = s"Vortex Core ${vortexParams.hartId} D-Mem Lane $i",
|
||||||
requestFifo = true,
|
requestFifo = true,
|
||||||
supportsProbe =
|
supportsProbe =
|
||||||
@@ -316,10 +333,12 @@ class VortexTileModuleImp(outer: VortexTile) extends BaseTileModuleImp(outer) {
|
|||||||
|
|
||||||
// connection: VortexBundle <--> sourceGen <--> dmemNodes
|
// connection: VortexBundle <--> sourceGen <--> dmemNodes
|
||||||
val sourceGens = Seq.tabulate(outer.numLanes) { _ =>
|
val sourceGens = Seq.tabulate(outer.numLanes) { _ =>
|
||||||
Module(new VortexSourceGen(
|
Module(new VortexTLAdapter(
|
||||||
2, // FIXME: hardcoded
|
outer.sourceWidth,
|
||||||
dmemTLBundles.head.a.bits,
|
new VortexBundleA(),
|
||||||
dmemTLBundles.head.d.bits,
|
new VortexBundleD(),
|
||||||
|
chiselTypeOf(dmemTLBundles.head.a.bits),
|
||||||
|
chiselTypeOf(dmemTLBundles.head.d.bits),
|
||||||
))
|
))
|
||||||
}
|
}
|
||||||
(core.io.dmem.get zip sourceGens) foreach { case (coreMem, sourceGen) =>
|
(core.io.dmem.get zip sourceGens) foreach { case (coreMem, sourceGen) =>
|
||||||
@@ -360,21 +379,24 @@ class VortexTileModuleImp(outer: VortexTile) extends BaseTileModuleImp(outer) {
|
|||||||
// sourceWidth; this needs to be more flexible.
|
// sourceWidth; this needs to be more flexible.
|
||||||
//
|
//
|
||||||
// Some @copypaste from CoalescerSourceGen.
|
// Some @copypaste from CoalescerSourceGen.
|
||||||
class VortexSourceGen(
|
class VortexTLAdapter(
|
||||||
newSourceWidth: Int,
|
newSourceWidth: Int,
|
||||||
reqT: TLBundleA,
|
inReqT: VortexBundleA,
|
||||||
respT: TLBundleD
|
inRespT: VortexBundleD,
|
||||||
|
outReqT: TLBundleA,
|
||||||
|
outRespT: TLBundleD
|
||||||
) extends Module {
|
) extends Module {
|
||||||
val io = IO(new Bundle {
|
val io = IO(new Bundle {
|
||||||
// in/out means upstream/downstream
|
// in/out means upstream/downstream
|
||||||
val inReq = Flipped(Decoupled(reqT.cloneType))
|
// TODO: change inReq/inResp to VortexBundle
|
||||||
val outReq = Decoupled(reqT.cloneType)
|
val inReq = Flipped(Decoupled(inReqT))
|
||||||
val inResp = Decoupled(respT.cloneType)
|
val outReq = Decoupled(outReqT)
|
||||||
val outResp = Flipped(Decoupled(respT.cloneType))
|
val inResp = Decoupled(inRespT)
|
||||||
|
val outResp = Flipped(Decoupled(outRespT))
|
||||||
})
|
})
|
||||||
val sourceGen = Module(new SourceGenerator(
|
val sourceGen = Module(new SourceGenerator(
|
||||||
newSourceWidth,
|
newSourceWidth,
|
||||||
Some(chiselTypeOf(reqT.source)),
|
Some(inReqT.source),
|
||||||
ignoreInUse = false
|
ignoreInUse = false
|
||||||
))
|
))
|
||||||
sourceGen.io.gen := io.outReq.fire // use up a source ID only when request is created
|
sourceGen.io.gen := io.outReq.fire // use up a source ID only when request is created
|
||||||
@@ -382,15 +404,32 @@ class VortexSourceGen(
|
|||||||
sourceGen.io.reclaim.bits := io.outResp.bits.source
|
sourceGen.io.reclaim.bits := io.outResp.bits.source
|
||||||
sourceGen.io.meta := io.inReq.bits.source
|
sourceGen.io.meta := io.inReq.bits.source
|
||||||
|
|
||||||
// passthrough logic
|
// io passthrough logic
|
||||||
io.outReq <> io.inReq
|
// TLBundleA <> VortexBundleA
|
||||||
|
io.outReq.valid := io.inReq.valid
|
||||||
|
io.outReq.bits.opcode := io.inReq.bits.opcode
|
||||||
|
io.outReq.bits.param := 0.U
|
||||||
|
io.outReq.bits.size := io.inReq.bits.size
|
||||||
|
io.outReq.bits.source := io.inReq.bits.source
|
||||||
|
io.outReq.bits.address := io.inReq.bits.address
|
||||||
|
io.outReq.bits.mask := io.inReq.bits.mask
|
||||||
|
io.outReq.bits.data := io.inReq.bits.data
|
||||||
|
io.outReq.bits.corrupt := 0.U
|
||||||
|
io.inReq.ready := io.outReq.ready
|
||||||
|
// VortexBundleD <> TLBundleD
|
||||||
|
io.inResp.valid := io.outResp.valid
|
||||||
|
io.inResp.bits.opcode := io.outResp.bits.opcode
|
||||||
|
io.inResp.bits.size := io.outResp.bits.size
|
||||||
|
io.inResp.bits.source := io.outResp.bits.source
|
||||||
|
io.inResp.bits.data := io.outResp.bits.data
|
||||||
|
io.outResp.ready := io.inResp.ready
|
||||||
|
|
||||||
// "man-in-the-middle"
|
// "man-in-the-middle"
|
||||||
io.inReq.ready := io.outReq.ready && sourceGen.io.id.valid
|
io.inReq.ready := io.outReq.ready && sourceGen.io.id.valid
|
||||||
io.outReq.valid := io.inReq.valid && sourceGen.io.id.valid
|
io.outReq.valid := io.inReq.valid && sourceGen.io.id.valid
|
||||||
// FIXME: Fill is a hack; just change downstream to the right sourceWidth
|
// FIXME: Fill is a hack; just change downstream to the right sourceWidth
|
||||||
// io.outReq.bits.source := Fill(newSourceWidth, sourceGen.io.id.bits)
|
// io.outReq.bits.source := Fill(newSourceWidth, sourceGen.io.id.bits)
|
||||||
io.outReq.bits.source := sourceGen.io.id.bits
|
io.outReq.bits.source := sourceGen.io.id.bits
|
||||||
io.inResp <> io.outResp
|
|
||||||
// translate upstream response back to its old sourceId
|
// translate upstream response back to its old sourceId
|
||||||
io.inResp.bits.source := sourceGen.io.peek
|
io.inResp.bits.source := sourceGen.io.peek
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user