HintHandler: rewrite for simpler hardware
This commit is contained in:
parent
d898b3662e
commit
79b392377d
|
@ -2,88 +2,80 @@
|
|||
|
||||
package freechips.rocketchip.tilelink
|
||||
|
||||
import Chisel._
|
||||
import chisel3._
|
||||
import chisel3.util._
|
||||
import freechips.rocketchip.config.Parameters
|
||||
import freechips.rocketchip.diplomacy._
|
||||
import freechips.rocketchip.util.Repeater
|
||||
import scala.math.min
|
||||
|
||||
// Acks Hints for managers that don't support them or Acks all Hints if !passthrough
|
||||
class TLHintHandler(supportManagers: Boolean = true, supportClients: Boolean = false, passthrough: Boolean = true)(implicit p: Parameters) extends LazyModule
|
||||
class TLHintHandler(passthrough: Boolean = true)(implicit p: Parameters) extends LazyModule
|
||||
{
|
||||
val node = TLAdapterNode(
|
||||
clientFn = { c => if (!supportClients) c else c.copy(minLatency = min(1, c.minLatency), clients = c.clients .map(_.copy(supportsHint = TransferSizes(1, c.maxTransfer)))) },
|
||||
managerFn = { m => if (!supportManagers) m else m.copy(minLatency = min(1, m.minLatency), managers = m.managers.map(_.copy(supportsHint = TransferSizes(1, m.maxTransfer)))) })
|
||||
clientFn = { cp =>
|
||||
cp.copy(clients = cp.clients.map { c => c.copy(
|
||||
sourceId = IdRange(c.sourceId.start*2, c.sourceId.end*2))})},
|
||||
managerFn = { mp =>
|
||||
mp.copy(managers = mp.managers.map { m => m.copy(
|
||||
supportsHint = if (m.supportsHint && passthrough) m.supportsHint else m.supportsPutPartial)})})
|
||||
|
||||
lazy val module = new LazyModuleImp(this) {
|
||||
(node.in zip node.out) foreach { case ((in, edgeIn), (out, edgeOut)) =>
|
||||
// Don't add support for clients if there is no BCE channel
|
||||
val bce = edgeOut.manager.anySupportAcquireB && edgeIn.client.anySupportProbe
|
||||
require (!supportClients || bce)
|
||||
out <> in
|
||||
|
||||
// Does it even make sense to add the HintHandler?
|
||||
val smartClients = edgeIn.client.clients.map(_.supportsHint.max == edgeIn.client.maxTransfer).reduce(_&&_)
|
||||
val smartManagers = edgeOut.manager.managers.map(_.supportsHint.max == edgeOut.manager.maxTransfer).reduce(_&&_)
|
||||
// Does the HintHandler help with this message?
|
||||
val help = in.a.bits.opcode === TLMessages.Hint && (!passthrough.B ||
|
||||
edgeOut.manager.fastProperty(in.a.bits.address, _.supportsHint.none, (b:Boolean) => b.B))
|
||||
val mapPP = WireInit(help)
|
||||
|
||||
if (supportManagers && !(passthrough && smartManagers)) {
|
||||
val address = edgeIn.address(in.a.bits)
|
||||
val handleA = if (passthrough) !edgeOut.manager.supportsHintFast(address, edgeIn.size(in.a.bits)) else Bool(true)
|
||||
val hintBitsAtA = handleA && in.a.bits.opcode === TLMessages.Hint
|
||||
val hint = Wire(out.d)
|
||||
|
||||
hint.valid := in.a.valid && hintBitsAtA
|
||||
out.a.valid := in.a.valid && !hintBitsAtA
|
||||
in.a.ready := Mux(hintBitsAtA, hint.ready, out.a.ready)
|
||||
|
||||
hint.bits := edgeIn.HintAck(in.a.bits)
|
||||
out.a.bits := in.a.bits
|
||||
|
||||
TLArbiter(TLArbiter.lowestIndexFirst)(in.d, (edgeOut.numBeats1(out.d.bits), out.d), (UInt(0), Queue(hint, 1)))
|
||||
} else {
|
||||
out.a.valid := in.a.valid
|
||||
in.a.ready := out.a.ready
|
||||
out.a.bits := in.a.bits
|
||||
|
||||
in.d.valid := out.d.valid
|
||||
out.d.ready := in.d.ready
|
||||
in.d.bits := out.d.bits
|
||||
// To handle multi-beat Hints, we need to extend the Hint when creating a PutPartial
|
||||
// However, when used between a device (SRAM/RegisterRouter/etc) and a Fragmenter, this is not needed
|
||||
val needRepeater = (edgeIn.manager.managers zip edgeOut.manager.managers) exists { case (in, out) =>
|
||||
!(out.supportsHint && passthrough) && out.supportsPutPartial.max > edgeOut.manager.beatBytes
|
||||
}
|
||||
|
||||
if (supportClients && !(passthrough && smartClients)) {
|
||||
val handleB = if (passthrough) !edgeIn.client.supportsHint(out.b.bits.source, edgeOut.size(out.b.bits)) else Bool(true)
|
||||
val hintBitsAtB = handleB && out.b.bits.opcode === TLMessages.Hint
|
||||
val hint = Wire(in.c)
|
||||
val a = if (!needRepeater) in.a else {
|
||||
val repeater = Module(new Repeater(in.a.bits))
|
||||
val mux = Wire(chiselTypeOf(in.a))
|
||||
|
||||
hint.valid := out.b.valid && hintBitsAtB
|
||||
in.b.valid := out.b.valid && !hintBitsAtB
|
||||
out.b.ready := Mux(hintBitsAtB, hint.ready, in.b.ready)
|
||||
repeater.io.repeat := mapPP && !edgeIn.last(out.a)
|
||||
repeater.io.enq <> in.a
|
||||
// Work-around broken chisel3 <>
|
||||
out.a.bits := mux.bits
|
||||
out.a.valid := mux.valid
|
||||
mux.ready := out.a.ready
|
||||
|
||||
hint.bits := edgeOut.HintAck(out.b.bits)
|
||||
in.b.bits := out.b.bits
|
||||
// Only some signals need to be repeated
|
||||
mux.bits.opcode := in.a.bits.opcode // ignored when full
|
||||
mux.bits.param := in.a.bits.param // ignored when full
|
||||
mux.bits.size := repeater.io.deq.bits.size
|
||||
mux.bits.source := repeater.io.deq.bits.source
|
||||
mux.bits.address := repeater.io.deq.bits.address
|
||||
mux.bits.data := in.a.bits.data // irrelevant when full (mask = 0)
|
||||
mux.bits.mask := in.a.bits.mask // ignored when full
|
||||
mux.bits.corrupt := in.a.bits.corrupt // irrelevant when full (mask = 0)
|
||||
|
||||
TLArbiter(TLArbiter.lowestIndexFirst)(out.c, (edgeIn.numBeats1(in.c.bits), in.c), (UInt(0), Queue(hint, 1)))
|
||||
} else if (bce) {
|
||||
in.b.valid := out.b.valid
|
||||
out.b.ready := in.b.ready
|
||||
in.b.bits := out.b.bits
|
||||
mux.valid := repeater.io.deq.valid
|
||||
repeater.io.deq.ready := mux.ready
|
||||
|
||||
out.c.valid := in.c.valid
|
||||
in.c.ready := out.c.ready
|
||||
out.c.bits := in.c.bits
|
||||
} else {
|
||||
in.b.valid := Bool(false)
|
||||
in.c.ready := Bool(true)
|
||||
out.b.ready := Bool(true)
|
||||
out.c.valid := Bool(false)
|
||||
mapPP := repeater.io.full || help
|
||||
mux
|
||||
}
|
||||
|
||||
if (bce) {
|
||||
// Pass E through unchanged
|
||||
out.e.valid := in.e.valid
|
||||
in.e.ready := out.e.ready
|
||||
out.e.bits := in.e.bits
|
||||
} else {
|
||||
in.e.ready := Bool(true)
|
||||
out.e.valid := Bool(false)
|
||||
// Transform Hint to PutPartialData
|
||||
out.a.bits.opcode := Mux(mapPP, TLMessages.PutPartialData, a.bits.opcode)
|
||||
out.a.bits.param := Mux(mapPP, 0.U, a.bits.param)
|
||||
out.a.bits.mask := Mux(mapPP, 0.U, a.bits.mask)
|
||||
out.a.bits.source := a.bits.source << 1 | mapPP
|
||||
|
||||
// Transform AccessAck to HintAck
|
||||
in.d.bits.source := out.d.bits.source >> 1
|
||||
in.d.bits.opcode := Mux(out.d.bits.source(0), TLMessages.HintAck, out.d.bits.opcode)
|
||||
|
||||
if (edgeOut.manager.anySupportAcquireB && edgeIn.client.anySupportProbe) {
|
||||
in.b.bits.source := out.b.bits.source >> 1
|
||||
out.c.bits.source := in.c.bits.source << 1
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -91,9 +83,9 @@ class TLHintHandler(supportManagers: Boolean = true, supportClients: Boolean = f
|
|||
|
||||
object TLHintHandler
|
||||
{
|
||||
def apply(supportManagers: Boolean = true, supportClients: Boolean = false, passthrough: Boolean = true)(implicit p: Parameters): TLNode =
|
||||
def apply(passthrough: Boolean = true)(implicit p: Parameters): TLNode =
|
||||
{
|
||||
val hints = LazyModule(new TLHintHandler(supportManagers, supportClients, passthrough))
|
||||
val hints = LazyModule(new TLHintHandler(passthrough))
|
||||
hints.node
|
||||
}
|
||||
}
|
||||
|
@ -123,5 +115,5 @@ class TLRAMHintHandler(txns: Int)(implicit p: Parameters) extends LazyModule {
|
|||
|
||||
class TLRAMHintHandlerTest(txns: Int = 5000, timeout: Int = 500000)(implicit p: Parameters) extends UnitTest(timeout) {
|
||||
val dut = Module(LazyModule(new TLRAMHintHandler(txns)).module)
|
||||
io.finished := dut.io.finished
|
||||
io <> dut.io
|
||||
}
|
||||
|
|
|
@ -46,6 +46,7 @@ class WithTLSimpleUnitTests extends Config((site, here, up) => {
|
|||
Module(new TLRAMSimpleTest(4, txns=15*txns, timeout=timeout)),
|
||||
Module(new TLRAMSimpleTest(16, txns=15*txns, timeout=timeout)),
|
||||
Module(new TLRAMZeroDelayTest(4, txns=15*txns, timeout=timeout)),
|
||||
Module(new TLRAMHintHandlerTest( txns=15*txns, timeout=timeout)),
|
||||
Module(new TLFuzzRAMTest( txns= 3*txns, timeout=timeout)),
|
||||
Module(new TLRR0Test( txns= 3*txns, timeout=timeout)),
|
||||
Module(new TLRR1Test( txns= 3*txns, timeout=timeout)),
|
||||
|
|
Loading…
Reference in New Issue