Skip to content

Commit

Permalink
Make TLSerdesser support optional bidirectionality
Browse files Browse the repository at this point in the history
  • Loading branch information
jerryz123 committed May 13, 2023
1 parent 7659e70 commit 862a5db
Show file tree
Hide file tree
Showing 7 changed files with 226 additions and 182 deletions.
70 changes: 49 additions & 21 deletions src/main/scala/Configs.scala
Original file line number Diff line number Diff line change
Expand Up @@ -60,64 +60,92 @@ class WithNBlockDeviceTrackers(n: Int) extends Config((site, here, up) => {

// Default size should be tiny
class WithDefaultSerialTL extends Config((site, here, up) => {
case SerialTLKey => Some(SerialTLParams(
memParams = MasterPortParams(
base = BigInt("10000000", 16),
size = BigInt("00001000", 16),
beatBytes = site(MemoryBusKey).beatBytes,
idBits = 4
),
width = 4
))
case SerialTLKey => Some(SerialTLParams())
})

class WithSerialTLWidth(width: Int) extends Config((site, here, up) => {
case SerialTLKey => up(SerialTLKey).map(k => k.copy(width=width))
})

class WithAXIMemOverSerialTL(axiMemOverSerialTLParams: AXIMemOverSerialTLClockParams) extends Config((site, here, up) => {
case SerialTLKey => up(SerialTLKey).map(k => k.copy(axiMemOverSerialTLParams=Some(axiMemOverSerialTLParams)))
case SerialTLKey => up(SerialTLKey).map(s => s.copy(serialManagerParams=s.serialManagerParams.map(
_.copy(axiMemOverSerialTLParams=Some(axiMemOverSerialTLParams)))))
})

class WithSerialPBusMem extends Config((site, here, up) => {
case SerialTLAttachKey => up(SerialTLAttachKey, site).copy(slaveWhere = PBUS)
class WithSerialTLMasterLocation(masterWhere: TLBusWrapperLocation) extends Config((site, here, up) => {
case SerialTLKey => up(SerialTLKey).map(s => s.copy(attachParams=s.attachParams.copy(masterWhere = masterWhere)))
})

class WithSerialTLSlaveLocation(slaveWhere: TLBusWrapperLocation) extends Config((site, here, up) => {
case SerialTLKey => up(SerialTLKey).map(s => s.copy(attachParams=s.attachParams.copy(slaveWhere = slaveWhere)))
})

class WithSerialTLPBusManager extends WithSerialTLSlaveLocation(PBUS)

class WithSerialSlaveCrossingType(xType: ClockCrossingType) extends Config((site, here, up) => {
case SerialTLAttachKey => up(SerialTLAttachKey, site).copy(slaveCrossingType = xType)
case SerialTLKey => up(SerialTLKey).map(s => s.copy(attachParams=s.attachParams.copy(slaveCrossingType = xType)))
})

class WithAsynchronousSerialSlaveCrossing extends WithSerialSlaveCrossingType(AsynchronousCrossing())

class WithSerialTLMem(
base: BigInt = BigInt("80000000", 16),
size: BigInt = BigInt("10000000", 16),
idBits: Int = 8,
isMainMemory: Boolean = true
) extends Config((site, here, up) => {
case SerialTLKey => up(SerialTLKey, site).map { k => k.copy(
memParams = k.memParams.copy(
case SerialTLKey => {
val masterPortParams = MasterPortParams(
base = base,
size = size,
),
isMemoryDevice = isMainMemory
idBits = idBits,
beatBytes = site(MemoryBusKey).beatBytes
)
up(SerialTLKey, site).map { k => k.copy(
serialManagerParams = Some(k.serialManagerParams.getOrElse(SerialTLManagerParams(memParams = masterPortParams))
.copy(memParams = masterPortParams, isMemoryDevice = isMainMemory)
)
)}
}
})


class WithSerialTLBackingMemory extends Config((site, here, up) => {
case ExtMem => None
case SerialTLKey => up(SerialTLKey, site).map { k => k.copy(
serialManagerParams = Some(k.serialManagerParams.getOrElse(SerialTLManagerParams(memParams = up(ExtMem).get.master))
.copy(memParams = up(ExtMem).get.master, isMemoryDevice = true))
)}
})

class WithSerialTLROM extends Config((site, here, up) => {
case SerialTLKey => up(SerialTLKey, site).map { k => k.copy(
serialManagerParams = k.serialManagerParams.map { s => s.copy(
romParams = Some(SerialTLROMParams())
)}
)}
})

class WithSerialTLROMFile(file: String) extends Config((site, here, up) => {
case SerialTLKey => up(SerialTLKey, site).map { k => k.copy(
romParams = k.romParams.copy(contentFileName = Some(file))
) }
serialManagerParams = k.serialManagerParams.map { s => s.copy(
romParams = s.romParams.map(_.copy(contentFileName = Some(file)))
)}
)}
})

class WithTilesStartInReset(harts: Int*) extends Config((site, here, up) => {
case TileResetCtrlKey => up(TileResetCtrlKey, site).copy(initResetHarts = up(TileResetCtrlKey, site).initResetHarts ++ harts)
class WithSerialTLClockDirection(provideClockFreqMHz: Option[Int] = None) extends Config((site, here, up) => {
case SerialTLKey => up(SerialTLKey).map(_.copy(provideClockFreqMHz = provideClockFreqMHz))
})

class WithNoSerialTL extends Config((site, here, up) => {
case SerialTLKey => None
})

class WithTilesStartInReset(harts: Int*) extends Config((site, here, up) => {
case TileResetCtrlKey => up(TileResetCtrlKey, site).copy(initResetHarts = up(TileResetCtrlKey, site).initResetHarts ++ harts)
})

class WithBootAddrReg(params: BootAddrRegParams = BootAddrRegParams()) extends Config((site, here, up) => {
case BootAddrRegKey => Some(params)
})
Expand Down
101 changes: 55 additions & 46 deletions src/main/scala/PeripheryTLSerial.scala
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ case class AXIMemOverSerialTLClockParams(
case Some(clkParams) => clkParams.clockFreqMHz * (1000 * 1000)
case None => {
// get the freq. from what the serial link masters
system.locateTLBusWrapper(p(SerialTLAttachKey).masterWhere).dtsFrequency.get.toDouble
system.locateTLBusWrapper(p(SerialTLKey).get.attachParams.masterWhere).dtsFrequency.get.toDouble
}
}
}
Expand All @@ -33,79 +33,88 @@ case class SerialTLROMParams(
size: Int = 0x10000,
contentFileName: Option[String] = None) // If unset, generates a JALR to DRAM_BASE

case class SerialTLParams(
case class SerialTLManagerParams(
memParams: MasterPortParams,
romParams: SerialTLROMParams = SerialTLROMParams(),
romParams: Option[SerialTLROMParams] = None,
isMemoryDevice: Boolean = false,
width: Int = 4,
provideClockFreqMHz: Option[Int] = None,
axiMemOverSerialTLParams: Option[AXIMemOverSerialTLClockParams] = Some(AXIMemOverSerialTLClockParams()) // if enabled, expose axi port instead of TL RAM
)
case object SerialTLKey extends Field[Option[SerialTLParams]](None)

case class SerialTLAttachParams(
masterWhere: TLBusWrapperLocation = FBUS,
slaveWhere: TLBusWrapperLocation = MBUS,
slaveCrossingType: ClockCrossingType = SynchronousCrossing()
)
case object SerialTLAttachKey extends Field[SerialTLAttachParams](SerialTLAttachParams())

// The SerialTL can be configured to be bidirectional if serialManagerParams is set
case class SerialTLParams(
clientIdBits: Int = 8,
serialManagerParams: Option[SerialTLManagerParams] = None,
width: Int = 4,
attachParams: SerialTLAttachParams = SerialTLAttachParams(),
provideClockFreqMHz: Option[Int] = None)

case object SerialTLKey extends Field[Option[SerialTLParams]](None)

trait CanHavePeripheryTLSerial { this: BaseSubsystem =>
private val portName = "serial-tl"
val (serdesser, serial_tl) = p(SerialTLKey).map { params =>
val memParams = params.memParams
val romParams = params.romParams
val manager = locateTLBusWrapper(p(SerialTLAttachKey).slaveWhere) // The bus for which this acts as a manager
val client = locateTLBusWrapper(p(SerialTLAttachKey).masterWhere) // The bus for which this acts as a client
val memDevice = if (params.isMemoryDevice) new MemoryDevice else new SimpleDevice("lbwif-ram", Nil)
val romDevice = new SimpleDevice("lbwif-rom", Nil)
val attachParams = params.attachParams
lazy val manager = locateTLBusWrapper(attachParams.slaveWhere) // The bus for which this acts as a manager
lazy val client = locateTLBusWrapper(attachParams.masterWhere) // The bus for which this acts as a client
val clientPortParams = TLMasterPortParameters.v1(
clients = Seq(TLMasterParameters.v1(
name = "serial-tl",
sourceId = IdRange(0, 1)
sourceId = IdRange(0, 1 << params.clientIdBits)
))
)
val managerPortParams = TLSlavePortParameters.v1(
managers = Seq(
TLSlaveParameters.v1(
address = AddressSet.misaligned(memParams.base, memParams.size),
resources = memDevice.reg,
regionType = RegionType.UNCACHED, // cacheable
executable = true,
supportsGet = TransferSizes(1, manager.blockBytes),
supportsPutFull = TransferSizes(1, manager.blockBytes),
supportsPutPartial = TransferSizes(1, manager.blockBytes)
),
TLSlaveParameters.v1(
address = List(AddressSet(romParams.address, romParams.size-1)),
resources = romDevice.reg,
regionType = RegionType.UNCACHED, // cacheable
executable = true,
supportsGet = TransferSizes(1, manager.blockBytes),
fifoId = Some(0)
)
),
beatBytes = memParams.beatBytes
)
require(clientPortParams.clients.size == 1)

val managerPortParams = params.serialManagerParams.map { managerParams =>
val memParams = managerParams.memParams
val romParams = managerParams.romParams
val memDevice = if (managerParams.isMemoryDevice) new MemoryDevice else new SimpleDevice("lbwif-readwrite", Nil)
val romDevice = new SimpleDevice("lbwif-readonly", Nil)
TLSlavePortParameters.v1(
managers = Seq(
TLSlaveParameters.v1(
address = AddressSet.misaligned(memParams.base, memParams.size),
resources = memDevice.reg,
regionType = RegionType.UNCACHED, // cacheable
executable = true,
supportsGet = TransferSizes(1, manager.blockBytes),
supportsPutFull = TransferSizes(1, manager.blockBytes),
supportsPutPartial = TransferSizes(1, manager.blockBytes)
)
) ++ romParams.map { romParams =>
TLSlaveParameters.v1(
address = List(AddressSet(romParams.address, romParams.size-1)),
resources = romDevice.reg,
regionType = RegionType.UNCACHED, // cacheable
executable = true,
supportsGet = TransferSizes(1, manager.blockBytes),
fifoId = Some(0)
)
},
beatBytes = memParams.beatBytes
)
}


val serdesser = client { LazyModule(new TLSerdesser(
w = params.width,
clientPortParams = clientPortParams,
clientPortParams = Some(clientPortParams),
managerPortParams = managerPortParams
)) }
manager.coupleTo(s"port_named_serial_tl_mem") {
((client.crossIn(serdesser.managerNode)(ValName("TLSerialManagerCrossing")))(p(SerialTLAttachKey).slaveCrossingType)
:= TLSourceShrinker(1 << memParams.idBits)
serdesser.managerNode.foreach { managerNode =>
manager.coupleTo(s"port_named_serial_tl_mem") {
((client.crossIn(managerNode)(ValName("TLSerialManagerCrossing")))(attachParams.slaveCrossingType)
:= TLSourceShrinker(1 << params.serialManagerParams.get.memParams.idBits)
:= TLWidthWidget(manager.beatBytes)
:= _ )
}
}
client.coupleFrom(s"port_named_serial_tl_ctrl") {
( _
:= TLBuffer()
:= serdesser.clientNode
)
}
client.coupleFrom(s"port_named_serial_tl_ctrl") { _ := TLBuffer() := serdesser.clientNode.get }

// If we provide a clock, generate a clock domain for the outgoing clock
val serial_tl_clock_node = params.provideClockFreqMHz.map { f =>
Expand Down
35 changes: 18 additions & 17 deletions src/main/scala/Serdes.scala
Original file line number Diff line number Diff line change
Expand Up @@ -345,12 +345,10 @@ object TLMergedBundle {
merged
}

def apply(chan: DecoupledIO[TLChannel], hasCorruptDenied: Boolean)
(implicit edge: TLEdge): DecoupledIO[TLMergedBundle] =
apply(chan, chan.bits.params, hasCorruptDenied)
def apply(chan: DecoupledIO[TLChannel], hasCorruptDenied: Boolean, last: DecoupledIO[TLChannel] => Bool): DecoupledIO[TLMergedBundle] =
apply(chan, chan.bits.params, hasCorruptDenied, last)

def apply(chan: DecoupledIO[TLChannel], params: TLBundleParameters, hasCorruptDenied: Boolean)
(implicit edge: TLEdge): DecoupledIO[TLMergedBundle] = {
def apply(chan: DecoupledIO[TLChannel], params: TLBundleParameters, hasCorruptDenied: Boolean, last: DecoupledIO[TLChannel] => Bool): DecoupledIO[TLMergedBundle] = {
val merged = Wire(Decoupled(new TLMergedBundle(params)))
merged.valid := chan.valid
merged.bits := (chan.bits match {
Expand All @@ -360,7 +358,7 @@ object TLMergedBundle {
case (d: TLBundleD) => apply(d, params, hasCorruptDenied)
case (e: TLBundleE) => apply(e, params, hasCorruptDenied)
})
merged.bits.last := edge.last(chan)
merged.bits.last := last(chan)
chan.ready := merged.ready
merged
}
Expand Down Expand Up @@ -527,7 +525,7 @@ class TLSerdes(w: Int, params: Seq[TLManagerParameters], beatBytes: Int = 8, has
node.in.zip(io.ser).zipWithIndex.foreach { case (((tl, edge), ser), i) =>
val mergeType = new TLMergedBundle(tl.params, hasCorruptDenied)

val outChannels = Seq(tl.e, tl.c, tl.a).map(TLMergedBundle(_, hasCorruptDenied)(edge))
val outChannels = Seq(tl.e, tl.c, tl.a).map(TLMergedBundle(_, hasCorruptDenied, c => edge.last(c)))
val outArb = Module(new HellaPeekingArbiter(
mergeType, outChannels.size, (b: TLMergedBundle) => b.last))
val outSer = Module(new GenericSerializer(mergeType, w))
Expand Down Expand Up @@ -568,7 +566,7 @@ class TLDesser(w: Int, params: Seq[TLClientParameters], hasCorruptDenied: Boolea
node.out.zip(io.ser).zipWithIndex.foreach { case (((tl, edge), ser), i) =>
val mergeType = new TLMergedBundle(tl.params, hasCorruptDenied)

val outChannels = Seq(tl.d, tl.b).map(TLMergedBundle(_, hasCorruptDenied)(edge))
val outChannels = Seq(tl.d, tl.b).map(TLMergedBundle(_, hasCorruptDenied, c => edge.last(c)))
val outArb = Module(new HellaPeekingArbiter(
mergeType, outChannels.size, (b: TLMergedBundle) => b.last))
val outSer = Module(new GenericSerializer(mergeType, w))
Expand Down Expand Up @@ -605,25 +603,28 @@ object TLSerdesser {

class TLSerdesser(
val w: Int,
clientPortParams: TLMasterPortParameters,
managerPortParams: TLSlavePortParameters,
clientPortParams: Option[TLMasterPortParameters],
managerPortParams: Option[TLSlavePortParameters],
bundleParams: TLBundleParameters = TLSerdesser.STANDARD_TLBUNDLE_PARAMS,
hasCorruptDenied: Boolean = true)
(implicit p: Parameters) extends LazyModule {
val clientNode = TLClientNode(Seq(clientPortParams))
val managerNode = TLManagerNode(Seq(managerPortParams))
require (clientPortParams.isDefined || managerPortParams.isDefined)
val clientNode = clientPortParams.map { c => TLClientNode(Seq(c)) }
val managerNode = managerPortParams.map { m => TLManagerNode(Seq(m)) }

lazy val module = new Impl
class Impl extends LazyModuleImp(this) {
val io = IO(new Bundle {
val ser = new SerialIO(w)
})

val (client_tl, client_edge) = clientNode.out(0)
val (manager_tl, manager_edge) = managerNode.in(0)
val client_tl = clientNode.map(_.out(0)._1).getOrElse(0.U.asTypeOf(new TLBundle(bundleParams)))
val client_edge = clientNode.map(_.out(0)._2)
val manager_tl = managerNode.map(_.in(0)._1).getOrElse(0.U.asTypeOf(new TLBundle(bundleParams)))
val manager_edge = managerNode.map(_.in(0)._2)

val clientParams = client_edge.bundle
val managerParams = manager_edge.bundle
val clientParams = client_edge.map(_.bundle).getOrElse(bundleParams)
val managerParams = manager_edge.map(_.bundle).getOrElse(bundleParams)
val mergedParams = clientParams.union(managerParams).union(bundleParams)
require(mergedParams.echoFields.isEmpty, "TLSerdesser does not support TileLink with echo fields")
require(mergedParams.requestFields.isEmpty, "TLSerdesser does not support TileLink with request fields")
Expand All @@ -637,7 +638,7 @@ class TLSerdesser(
val outArb = Module(new HellaPeekingArbiter(
mergeType, outChannels.size, (b: TLMergedBundle) => b.last))
val outSer = Module(new GenericSerializer(mergeType, w))
outArb.io.in <> outChannels.map(TLMergedBundle(_, mergedParams, hasCorruptDenied)(client_edge))
outArb.io.in <> outChannels.map(o => TLMergedBundle(o, mergedParams, hasCorruptDenied, c => client_edge.map(_.last(c)).getOrElse(false.B)))
outSer.io.in <> outArb.io.out
io.ser.out <> outSer.io.out

Expand Down
Loading

0 comments on commit 862a5db

Please sign in to comment.