HintHandler: rewrite for simpler hardware

This commit is contained in:
Wesley W. Terpstra 2018-10-02 13:23:59 -07:00
parent d898b3662e
commit 79b392377d
2 changed files with 58 additions and 65 deletions

View File

@ -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
}

View File

@ -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)),