2017-03-21 00:29:03 +01:00
|
|
|
// See LICENSE.SiFive for license details.
|
|
|
|
|
|
|
|
package uncore.tilelink2
|
|
|
|
|
|
|
|
import Chisel._
|
|
|
|
import chisel3.internal.sourceinfo.SourceInfo
|
|
|
|
import config._
|
|
|
|
import diplomacy._
|
|
|
|
import scala.math.max
|
|
|
|
|
|
|
|
class TLFIFOFixer(implicit p: Parameters) extends LazyModule
|
|
|
|
{
|
|
|
|
val node = TLAdapterNode(
|
2017-04-27 01:48:35 +02:00
|
|
|
clientFn = { cp => cp },
|
2017-03-21 00:29:03 +01:00
|
|
|
managerFn = { mp => mp.copy(managers = mp.managers.map(m => m.copy(fifoId = Some(0)))) })
|
|
|
|
|
|
|
|
lazy val module = new LazyModuleImp(this) {
|
|
|
|
val io = new Bundle {
|
|
|
|
val in = node.bundleIn
|
|
|
|
val out = node.bundleOut
|
|
|
|
}
|
|
|
|
|
|
|
|
((io.in zip io.out) zip (node.edgesIn zip node.edgesOut)) foreach { case ((in, out), (edgeIn, edgeOut)) =>
|
|
|
|
val maxId = edgeOut.manager.managers.flatMap(_.fifoId).foldLeft(0)(max)
|
|
|
|
val a_id = edgeOut.manager.findFifoIdFast(in.a.bits.address)
|
|
|
|
val a_nid = a_id === UInt(0) // no id = not FIFO
|
|
|
|
|
|
|
|
val a_first = edgeIn.first(in.a)
|
2017-03-21 22:15:16 +01:00
|
|
|
val d_first = edgeOut.first(out.d) && out.d.bits.opcode =/= TLMessages.ReleaseAck
|
2017-03-21 00:29:03 +01:00
|
|
|
|
|
|
|
val stalls = edgeIn.client.clients.filter(c => c.requestFifo && c.sourceId.size > 1).map { c =>
|
|
|
|
val a_sel = c.sourceId.contains(in.a.bits.source)
|
|
|
|
val d_sel = c.sourceId.contains(in.d.bits.source)
|
2017-04-20 20:28:00 +02:00
|
|
|
val id = RegInit(UInt(0, width = log2Up(maxId+1))) // TODO zero-width
|
|
|
|
val count = RegInit(UInt(0, width = log2Up(c.sourceId.size+1))) // TODO zero-width
|
2017-03-21 00:29:03 +01:00
|
|
|
|
|
|
|
val a_inc = in.a.fire() && a_first && a_sel
|
|
|
|
val d_dec = in.d.fire() && d_first && d_sel
|
|
|
|
count := count + a_inc.asUInt - d_dec.asUInt
|
|
|
|
when (in.a.fire() && a_sel) { id := a_id }
|
|
|
|
|
|
|
|
a_sel && a_first && count =/= UInt(0) && (a_nid || id =/= a_id)
|
|
|
|
}
|
|
|
|
|
|
|
|
val stall = stalls.foldLeft(Bool(false))(_||_)
|
|
|
|
|
|
|
|
out.a <> in.a
|
|
|
|
in.d <> out.d
|
|
|
|
out.a.valid := in.a.valid && !stall
|
|
|
|
in.a.ready := out.a.ready && !stall
|
|
|
|
|
|
|
|
if (edgeOut.manager.anySupportAcquireB && edgeOut.client.anySupportProbe) {
|
|
|
|
in .b <> out.b
|
|
|
|
out.c <> in .c
|
|
|
|
out.e <> in .e
|
|
|
|
} else {
|
|
|
|
in.b.valid := Bool(false)
|
|
|
|
in.c.ready := Bool(true)
|
|
|
|
in.e.ready := Bool(true)
|
|
|
|
out.b.ready := Bool(true)
|
|
|
|
out.c.valid := Bool(false)
|
|
|
|
out.e.valid := Bool(false)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
object TLFIFOFixer
|
|
|
|
{
|
|
|
|
// applied to the TL source node; y.node := TLFIFOFixer()(x.node)
|
|
|
|
def apply()(x: TLOutwardNode)(implicit p: Parameters, sourceInfo: SourceInfo): TLOutwardNode = {
|
|
|
|
val fixer = LazyModule(new TLFIFOFixer)
|
|
|
|
fixer.node := x
|
|
|
|
fixer.node
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|