tilelink: FIFOFixer now has a policy parameter
This commit is contained in:
parent
b363a94480
commit
09b9d33a9a
@ -8,11 +8,37 @@ import freechips.rocketchip.config.Parameters
|
|||||||
import freechips.rocketchip.diplomacy._
|
import freechips.rocketchip.diplomacy._
|
||||||
import scala.math.max
|
import scala.math.max
|
||||||
|
|
||||||
class TLFIFOFixer(implicit p: Parameters) extends LazyModule
|
class TLFIFOFixer(policy: TLFIFOFixer.Policy = TLFIFOFixer.all)(implicit p: Parameters) extends LazyModule
|
||||||
{
|
{
|
||||||
|
private def fifoMap(seq: Seq[TLManagerParameters]) = {
|
||||||
|
val (flatManagers, keepManagers) = seq.partition(policy)
|
||||||
|
// We need to be careful if one flatManager and one keepManager share an existing domain
|
||||||
|
// Erring on the side of caution, we will also flatten the keepManager in this case
|
||||||
|
val flatDomains = Set(flatManagers.flatMap(_.fifoId):_*) // => ID 0
|
||||||
|
val keepDomains = Set(keepManagers.flatMap(_.fifoId):_*) -- flatDomains // => IDs compacted
|
||||||
|
// Calculate what the FIFO domains look like after the fixer is applied
|
||||||
|
val flatMap = flatDomains.map { x => (x, 0) }.toMap
|
||||||
|
val keepMap = keepDomains.scanLeft((-1,0)) { case ((_,s),x) => (x, s+1) }.toMap
|
||||||
|
val map = flatMap ++ keepMap
|
||||||
|
val fixMap = seq.map { m => m.fifoId match {
|
||||||
|
case None => if (policy(m)) Some(0) else None
|
||||||
|
case Some(id) => Some(map(id)) // also flattens some who did not ask
|
||||||
|
} }
|
||||||
|
// Compress the FIFO domain space of those we are combining
|
||||||
|
val reMap = flatDomains.scanLeft((-1,-1)) { case ((_,s),x) => (x, s+1) }.toMap
|
||||||
|
val splatMap = seq.map { m => m.fifoId match {
|
||||||
|
case None => None
|
||||||
|
case Some(id) => reMap.lift(id)
|
||||||
|
} }
|
||||||
|
(fixMap, splatMap)
|
||||||
|
}
|
||||||
|
|
||||||
val node = TLAdapterNode(
|
val node = TLAdapterNode(
|
||||||
clientFn = { cp => cp },
|
clientFn = { cp => cp },
|
||||||
managerFn = { mp => mp.copy(managers = mp.managers.map(m => m.copy(fifoId = Some(0)))) })
|
managerFn = { mp =>
|
||||||
|
val (fixMap, _) = fifoMap(mp.managers)
|
||||||
|
mp.copy(managers = (fixMap zip mp.managers) map { case (id, m) => m.copy(fifoId = id) })
|
||||||
|
})
|
||||||
|
|
||||||
lazy val module = new LazyModuleImp(this) {
|
lazy val module = new LazyModuleImp(this) {
|
||||||
val io = new Bundle {
|
val io = new Bundle {
|
||||||
@ -21,33 +47,50 @@ class TLFIFOFixer(implicit p: Parameters) extends LazyModule
|
|||||||
}
|
}
|
||||||
|
|
||||||
((io.in zip io.out) zip (node.edgesIn zip node.edgesOut)) foreach { case ((in, out), (edgeIn, edgeOut)) =>
|
((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 (fixMap, splatMap) = fifoMap(edgeOut.manager.managers)
|
||||||
val a_id = edgeOut.manager.findFifoIdFast(in.a.bits.address)
|
|
||||||
val a_nid = a_id === UInt(0) // no id = not FIFO
|
|
||||||
|
|
||||||
|
// Do we need to serialize the request to this manager?
|
||||||
|
// println(s"make FIFO: ${edgeIn.manager.managers.filter(_.fifoId==Some(0)).map(_.name).mkString(", ")}")
|
||||||
|
// println(s"not FIFO: ${edgeIn.manager.managers.filter(_.fifoId!=Some(0)).map(_.name).mkString(", ")}")
|
||||||
|
val a_notFIFO = edgeIn.manager.fastProperty(in.a.bits.address, _.fifoId != Some(0), (b:Boolean) => Bool(b))
|
||||||
|
// Does this manager have an existing FIFO domain? (don't care about unserialized cases)
|
||||||
|
val hackExist = ((fixMap zip splatMap) zip edgeOut.manager.managers) flatMap {
|
||||||
|
case ((f, s), m) => if (f == Some(0)) Some(m.copy(fifoId = s)) else None
|
||||||
|
}
|
||||||
|
// println(s"has domain: ${hackExist.filter( _.fifoId.isDefined).map(_.name).mkString(", ")}")
|
||||||
|
// println(s"no domain: ${hackExist.filter(!_.fifoId.isDefined).map(_.name).mkString(", ")}")
|
||||||
|
val a_noDomain = edgeOut.manager.copy(managers = hackExist).fastProperty(in.a.bits.address, !_.fifoId.isDefined, (b:Boolean) => Bool(b))
|
||||||
|
// What is that domain? (don't care about noDomain cases)
|
||||||
|
val hackDomain = hackExist.filter(_.fifoId.isDefined)
|
||||||
|
// println(s"domains: ${hackDomain.groupBy(_.name).mapValues(_.map(_.fifoId))}")
|
||||||
|
// println("")
|
||||||
|
val a_id = edgeOut.manager.copy(managers = hackDomain).fastProperty(in.a.bits.address, _.fifoId.get, (id:Int) => UInt(id))
|
||||||
|
val maxId = hackDomain.flatMap(_.fifoId).foldLeft(0)(max)
|
||||||
|
|
||||||
|
// Count beats
|
||||||
val a_first = edgeIn.first(in.a)
|
val a_first = edgeIn.first(in.a)
|
||||||
val d_first = edgeOut.first(out.d) && out.d.bits.opcode =/= TLMessages.ReleaseAck
|
val d_first = edgeOut.first(out.d) && out.d.bits.opcode =/= TLMessages.ReleaseAck
|
||||||
|
|
||||||
|
// Keep one bit for each source recording if there is an outstanding request that must be made FIFO
|
||||||
|
// Sources unused in the stall signal calculation should be pruned by DCE
|
||||||
|
val flight = RegInit(Vec.fill(edgeIn.client.endSourceId) { Bool(false) })
|
||||||
|
when (d_first && in.d.fire()) { flight(in.d.bits.source) := Bool(false) }
|
||||||
|
when (a_first && in.a.fire()) { flight(in.a.bits.source) := !a_notFIFO }
|
||||||
|
|
||||||
val stalls = edgeIn.client.clients.filter(c => c.requestFifo && c.sourceId.size > 1).map { c =>
|
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 a_sel = c.sourceId.contains(in.a.bits.source)
|
||||||
val d_sel = c.sourceId.contains(in.d.bits.source)
|
val id = RegEnable(a_id, in.a.fire() && a_sel && !a_notFIFO)
|
||||||
val id = RegInit(UInt(0, width = log2Up(maxId+1))) // TODO zero-width
|
val track = flight.slice(c.sourceId.start, c.sourceId.end)
|
||||||
val count = RegInit(UInt(0, width = log2Up(c.sourceId.size+1))) // TODO zero-width
|
|
||||||
|
|
||||||
val a_inc = in.a.fire() && a_first && a_sel
|
a_sel && a_first && track.reduce(_ || _) && (a_noDomain || id =/= a_id)
|
||||||
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))(_||_)
|
val stall = stalls.foldLeft(Bool(false))(_||_)
|
||||||
|
|
||||||
out.a <> in.a
|
out.a <> in.a
|
||||||
in.d <> out.d
|
in.d <> out.d
|
||||||
out.a.valid := in.a.valid && !stall
|
out.a.valid := in.a.valid && (a_notFIFO || !stall)
|
||||||
in.a.ready := out.a.ready && !stall
|
in.a.ready := out.a.ready && (a_notFIFO || !stall)
|
||||||
|
|
||||||
if (edgeOut.manager.anySupportAcquireB && edgeOut.client.anySupportProbe) {
|
if (edgeOut.manager.anySupportAcquireB && edgeOut.client.anySupportProbe) {
|
||||||
in .b <> out.b
|
in .b <> out.b
|
||||||
@ -67,11 +110,19 @@ class TLFIFOFixer(implicit p: Parameters) extends LazyModule
|
|||||||
|
|
||||||
object TLFIFOFixer
|
object TLFIFOFixer
|
||||||
{
|
{
|
||||||
|
// Which slaves should have their FIFOness combined?
|
||||||
|
// NOTE: this transformation is still only applied for masters with requestFifo
|
||||||
|
type Policy = TLManagerParameters => Boolean
|
||||||
|
import RegionType._
|
||||||
|
|
||||||
|
val all: Policy = m => true
|
||||||
|
val allFIFO: Policy = m => m.fifoId.isDefined
|
||||||
|
val allUncacheable: Policy = m => m.regionType <= UNCACHEABLE
|
||||||
|
|
||||||
// applied to the TL source node; y.node := TLFIFOFixer()(x.node)
|
// applied to the TL source node; y.node := TLFIFOFixer()(x.node)
|
||||||
def apply()(x: TLOutwardNode)(implicit p: Parameters, sourceInfo: SourceInfo): TLOutwardNode = {
|
def apply(policy: Policy = all)(x: TLOutwardNode)(implicit p: Parameters, sourceInfo: SourceInfo): TLOutwardNode = {
|
||||||
val fixer = LazyModule(new TLFIFOFixer)
|
val fixer = LazyModule(new TLFIFOFixer(policy))
|
||||||
fixer.node := x
|
fixer.node := x
|
||||||
fixer.node
|
fixer.node
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user