From 13d3ffbcaa129746af2ec349dc437aef71257d8a Mon Sep 17 00:00:00 2001 From: "Wesley W. Terpstra" Date: Mon, 31 Jul 2017 16:00:21 -0700 Subject: [PATCH 1/3] tilelink: Filter now support arbitrary filter functions --- src/main/scala/coreplex/MemoryBus.scala | 2 +- src/main/scala/tilelink/Filter.scala | 95 ++++++++++++++++++------- 2 files changed, 71 insertions(+), 26 deletions(-) diff --git a/src/main/scala/coreplex/MemoryBus.scala b/src/main/scala/coreplex/MemoryBus.scala index db022982..d78cddee 100644 --- a/src/main/scala/coreplex/MemoryBus.scala +++ b/src/main/scala/coreplex/MemoryBus.scala @@ -68,7 +68,7 @@ trait HasMemoryBus extends HasSystemBus with HasPeripheryBus with HasInterruptBu for (bank <- 0 until nBanksPerChannel) { val offset = (bank * nMemoryChannels) + channel in := sbus.toMemoryBus - mbus.fromCoherenceManager := TLFilter(AddressSet(offset * blockBytes, mask))(out) + mbus.fromCoherenceManager := TLFilter(TLFilter.Mmask(AddressSet(offset * blockBytes, mask)))(out) } mbus } diff --git a/src/main/scala/tilelink/Filter.scala b/src/main/scala/tilelink/Filter.scala index 80a4f1c7..28fb6496 100644 --- a/src/main/scala/tilelink/Filter.scala +++ b/src/main/scala/tilelink/Filter.scala @@ -8,31 +8,45 @@ import freechips.rocketchip.config.Parameters import freechips.rocketchip.diplomacy._ import scala.math.{min,max} -class TLFilter(select: AddressSet)(implicit p: Parameters) extends LazyModule +class TLFilter( + Mfilter: TLManagerParameters => Option[TLManagerParameters] = TLFilter.Midentity, + Cfilter: TLClientParameters => Option[TLClientParameters] = TLFilter.Cidentity + )(implicit p: Parameters) extends LazyModule { val node = TLAdapterNode( - clientFn = { cp => cp }, - managerFn = { mp => - mp.copy(managers = mp.managers.map { m => - val filtered = m.address.map(_.intersect(select)).flatten - val alignment = select.alignment /* alignment 0 means 'select' selected everything */ - val maxTransfer = 1 << 30 - val capTransfer = if (alignment == 0 || alignment > maxTransfer) maxTransfer else alignment.toInt - val cap = TransferSizes(1, capTransfer) - if (filtered.isEmpty) { None } else { - Some(m.copy( - address = filtered, - supportsAcquireT = m.supportsAcquireT .intersect(cap), - supportsAcquireB = m.supportsAcquireB .intersect(cap), - supportsArithmetic = m.supportsArithmetic.intersect(cap), - supportsLogical = m.supportsLogical .intersect(cap), - supportsGet = m.supportsGet .intersect(cap), - supportsPutFull = m.supportsPutFull .intersect(cap), - supportsPutPartial = m.supportsPutPartial.intersect(cap), - supportsHint = m.supportsHint .intersect(cap))) - } - }.flatten) - }) + clientFn = { cp => cp.copy(clients = cp.clients.flatMap { c => + val out = Cfilter(c) + out.map { o => // Confirm the filter only REMOVES capability + require (c.sourceId.contains(o.sourceId)) + require (c.supportsProbe.contains(o.supportsProbe)) + require (c.supportsArithmetic.contains(o.supportsArithmetic)) + require (c.supportsLogical.contains(o.supportsLogical)) + require (c.supportsGet.contains(o.supportsGet)) + require (c.supportsPutFull.contains(o.supportsPutFull)) + require (c.supportsPutPartial.contains(o.supportsPutPartial)) + require (c.supportsHint.contains(o.supportsHint)) + require (!c.requestFifo || o.requestFifo) + } + out + })}, + managerFn = { mp => mp.copy(managers = mp.managers.flatMap { m => + val out = Mfilter(m) + out.map { o => // Confirm the filter only REMOVES capability + o.address.foreach { a => require (m.address.map(_.contains(a)).reduce(_||_)) } + require (o.regionType <= m.regionType) + // we allow executable to be changed both ways + require (m.supportsAcquireT.contains(o.supportsAcquireT)) + require (m.supportsAcquireB.contains(o.supportsAcquireB)) + require (m.supportsArithmetic.contains(o.supportsArithmetic)) + require (m.supportsLogical.contains(o.supportsLogical)) + require (m.supportsGet.contains(o.supportsGet)) + require (m.supportsPutFull.contains(o.supportsPutFull)) + require (m.supportsPutPartial.contains(o.supportsPutPartial)) + require (m.supportsHint.contains(o.supportsHint)) + require (m.fifoId == o.fifoId) // could relax this, but hard to validate + } + out + })}) lazy val module = new LazyModuleImp(this) { val io = new Bundle { @@ -45,9 +59,40 @@ class TLFilter(select: AddressSet)(implicit p: Parameters) extends LazyModule object TLFilter { + def Midentity: TLManagerParameters => Option[TLManagerParameters] = { m => Some(m) } + def Cidentity: TLClientParameters => Option[TLClientParameters] = { c => Some(c) } + def Mmask(select: AddressSet): TLManagerParameters => Option[TLManagerParameters] = { m => + val filtered = m.address.map(_.intersect(select)).flatten + val alignment = select.alignment /* alignment 0 means 'select' selected everything */ + val maxTransfer = 1 << 30 + val capTransfer = if (alignment == 0 || alignment > maxTransfer) maxTransfer else alignment.toInt + val cap = TransferSizes(1, capTransfer) + if (filtered.isEmpty) { None } else { + Some(m.copy( + address = filtered, + supportsAcquireT = m.supportsAcquireT .intersect(cap), + supportsAcquireB = m.supportsAcquireB .intersect(cap), + supportsArithmetic = m.supportsArithmetic.intersect(cap), + supportsLogical = m.supportsLogical .intersect(cap), + supportsGet = m.supportsGet .intersect(cap), + supportsPutFull = m.supportsPutFull .intersect(cap), + supportsPutPartial = m.supportsPutPartial.intersect(cap), + supportsHint = m.supportsHint .intersect(cap))) + } + } + def Mnocache: TLManagerParameters => Option[TLManagerParameters] = { m => + if (m.supportsAcquireB) None else Some(m) + } + def Cnocache: TLClientParameters => Option[TLClientParameters] = { c => + if (c.supportsProbe) None else Some(c) + } + // applied to the TL source node; y.node := TLBuffer(x.node) - def apply(select: AddressSet)(x: TLOutwardNode)(implicit p: Parameters, sourceInfo: SourceInfo): TLOutwardNode = { - val filter = LazyModule(new TLFilter(select)) + def apply( + Mfilter: TLManagerParameters => Option[TLManagerParameters] = TLFilter.Midentity, + Cfilter: TLClientParameters => Option[TLClientParameters] = TLFilter.Cidentity + )(x: TLOutwardNode)(implicit p: Parameters, sourceInfo: SourceInfo): TLOutwardNode = { + val filter = LazyModule(new TLFilter(Mfilter, Cfilter)) filter.node := x filter.node } From b12610523095922bc76ee52fa11a01fb12bb9ebd Mon Sep 17 00:00:00 2001 From: "Wesley W. Terpstra" Date: Mon, 31 Jul 2017 16:29:20 -0700 Subject: [PATCH 2/3] tilelink: add TLMap to make it possible to move slaves --- src/main/scala/tilelink/Map.scala | 54 +++++++++++++++++++++++++++++++ 1 file changed, 54 insertions(+) create mode 100644 src/main/scala/tilelink/Map.scala diff --git a/src/main/scala/tilelink/Map.scala b/src/main/scala/tilelink/Map.scala new file mode 100644 index 00000000..95fb2246 --- /dev/null +++ b/src/main/scala/tilelink/Map.scala @@ -0,0 +1,54 @@ +// See LICENSE.SiFive for license details. + +package freechips.rocketchip.tilelink + +import Chisel._ +import chisel3.internal.sourceinfo.SourceInfo +import freechips.rocketchip.config.Parameters +import freechips.rocketchip.diplomacy._ +import scala.math.{min,max} + +// Moves the AddressSets of slave devices around +// Combine with TLFilter to remove slaves or reduce their size +class TLMap(fn: AddressSet => BigInt)(implicit p: Parameters) extends LazyModule +{ + val node = TLAdapterNode( + clientFn = { cp => cp }, + managerFn = { mp => + mp.copy(managers = mp.managers.map(m => + m.copy(address = m.address.map(a => + AddressSet(fn(a), a.mask)))))}) + + lazy val module = new LazyModuleImp(this) { + val io = new Bundle { + val in = node.bundleIn + val out = node.bundleOut + } + + io.out <> io.in + + ((io.in zip io.out) zip (node.edgesIn zip node.edgesOut)) foreach { case ((in, out), (edgeIn, edgeOut)) => + val convert = edgeIn.manager.managers.flatMap(_.address) zip edgeOut.manager.managers.flatMap(_.address) + def forward(x: UInt) = + convert.map { case (i, o) => Mux(i.contains(x), UInt(o.base) | (x & UInt(o.mask)), UInt(0)) }.reduce(_ | _) + def backward(x: UInt) = + convert.map { case (i, o) => Mux(o.contains(x), UInt(i.base) | (x & UInt(i.mask)), UInt(0)) }.reduce(_ | _) + + out.a.bits.address := forward(in.a.bits.address) + if (edgeOut.manager.anySupportAcquireB && edgeOut.client.anySupportProbe) { + out.c.bits.address := forward(in.c.bits.address) + in.b.bits.address := backward(out.b.bits.address) + } + } + } +} + +object TLMap +{ + // applied to the TL source node; y.node := TLMap(fn)(x.node) + def apply(fn: AddressSet => BigInt)(x: TLOutwardNode)(implicit p: Parameters, sourceInfo: SourceInfo): TLOutwardNode = { + val map = LazyModule(new TLMap(fn)) + map.node := x + map.node + } +} From d7fd9d2b82965a3f19ab23e7e998d454b65f1a7f Mon Sep 17 00:00:00 2001 From: "Wesley W. Terpstra" Date: Mon, 31 Jul 2017 16:51:11 -0700 Subject: [PATCH 3/3] tilelink: Filter, add another case --- src/main/scala/tilelink/Filter.scala | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/main/scala/tilelink/Filter.scala b/src/main/scala/tilelink/Filter.scala index 28fb6496..be20dfe4 100644 --- a/src/main/scala/tilelink/Filter.scala +++ b/src/main/scala/tilelink/Filter.scala @@ -83,6 +83,9 @@ object TLFilter def Mnocache: TLManagerParameters => Option[TLManagerParameters] = { m => if (m.supportsAcquireB) None else Some(m) } + def Mcache: TLManagerParameters => Option[TLManagerParameters] = { m => + if (m.supportsAcquireB) Some(m) else None + } def Cnocache: TLClientParameters => Option[TLClientParameters] = { c => if (c.supportsProbe) None else Some(c) }